~ubuntu-branches/ubuntu/vivid/postfix/vivid-proposed

« back to all changes in this revision

Viewing changes to src/smtpd/smtpd_check.c

Tags: upstream-2.2.6
ImportĀ upstreamĀ versionĀ 2.2.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
/*      int     smtpd_check_addr(address)
13
13
/*      const char *address;
14
14
/*
 
15
/*      char    *smtpd_check_rewrite(state)
 
16
/*      SMTPD_STATE *state;
 
17
/*
15
18
/*      char    *smtpd_check_client(state)
16
19
/*      SMTPD_STATE *state;
17
20
/*
33
36
/*
34
37
/*      char    *smtpd_check_data(state)
35
38
/*      SMTPD_STATE *state;
 
39
/*
 
40
/*      char    *smtpd_check_eod(state)
 
41
/*      SMTPD_STATE *state;
36
42
/* DESCRIPTION
37
43
/*      This module implements additional checks on SMTP client requests.
38
44
/*      A client request is validated in the context of the session state.
45
51
/*      smtpd_check_addr() sanity checks an email address and returns
46
52
/*      non-zero in case of badness.
47
53
/*
 
54
/*      smtpd_check_rewrite() should be called before opening a queue
 
55
/*      file or proxy connection, in order to establish the proper
 
56
/*      header address rewriting context.
 
57
/*
48
58
/*      Each of the following routines scrutinizes the argument passed to
49
59
/*      an SMTP command such as HELO, MAIL FROM, RCPT TO, or scrutinizes
50
60
/*      the initial client connection request.  The administrator can
107
117
/*      smtpd_check_data() enforces generic restrictions after the
108
118
/*      client has sent the DATA command.
109
119
/*
 
120
/*      smtpd_check_eod() enforces generic restrictions after the
 
121
/*      client has sent the END-OF-DATA command.
 
122
/*
110
123
/*      Arguments:
111
124
/* .IP name
112
125
/*      The client hostname, or \fIunknown\fR.
136
149
/*      IBM T.J. Watson Research
137
150
/*      P.O. Box 704
138
151
/*      Yorktown Heights, NY 10598, USA
 
152
/*
 
153
/*      TLS support originally by:
 
154
/*      Lutz Jaenicke
 
155
/*      BTU Cottbus
 
156
/*      Allgemeine Elektrotechnik
 
157
/*      Universitaetsplatz 3-4
 
158
/*      D-03044 Cottbus, Germany
139
159
/*--*/
140
160
 
141
161
/* System library. */
151
171
#include <setjmp.h>
152
172
#include <stdlib.h>
153
173
#include <unistd.h>
 
174
#include <errno.h>
154
175
 
155
176
#ifdef STRCASECMP_IN_STRINGS_H
156
177
#include <strings.h>
157
178
#endif
158
179
 
159
 
#ifndef INADDR_NONE
160
 
#define INADDR_NONE 0xffffffff
161
 
#endif
162
 
 
163
180
/* Utility library. */
164
181
 
165
182
#include <msg.h>
175
192
#include <ctable.h>
176
193
#include <mac_expand.h>
177
194
#include <attr_clnt.h>
 
195
#include <myaddrinfo.h>
 
196
#include <inet_proto.h>
178
197
 
179
198
/* DNS library. */
180
199
 
186
205
#include <namadr_list.h>
187
206
#include <domain_list.h>
188
207
#include <mail_params.h>
189
 
#include <canon_addr.h>
 
208
#include <rewrite_clnt.h>
190
209
#include <resolve_clnt.h>
191
210
#include <mail_error.h>
192
211
#include <resolve_local.h>
205
224
#include <verify_clnt.h>
206
225
#include <input_transp.h>
207
226
#include <is_header.h>
 
227
#include <rewrite_clnt.h>
 
228
#include <valid_mailhost_addr.h>
208
229
 
209
230
/* Application-specific. */
210
231
 
269
290
static DOMAIN_LIST *relay_domains;
270
291
static NAMADR_LIST *mynetworks;
271
292
static NAMADR_LIST *perm_mx_networks;
 
293
#ifdef USE_TLS
 
294
static MAPS *relay_ccerts;
 
295
#endif
272
296
 
273
297
 /*
274
298
  * How to do parent domain wildcard matching, if any.
284
308
static ARGV *rcpt_restrctions;
285
309
static ARGV *etrn_restrctions;
286
310
static ARGV *data_restrctions;
 
311
static ARGV *eod_restrictions;
287
312
 
288
313
static HTABLE *smtpd_rest_classes;
289
314
static HTABLE *policy_clnt_table;
290
315
 
 
316
static ARGV *local_rewrite_clients;
 
317
 
291
318
 /*
292
319
  * Pre-parsed expansion filter.
293
320
  */
309
336
  * Reject context.
310
337
  */
311
338
#define SMTPD_NAME_CLIENT       "Client host"
 
339
#define SMTPD_NAME_CCERT        "Client certificate"
312
340
#define SMTPD_NAME_HELO         "Helo command"
313
341
#define SMTPD_NAME_SENDER       "Sender address"
314
342
#define SMTPD_NAME_RECIPIENT    "Recipient address"
315
343
#define SMTPD_NAME_ETRN         "Etrn command"
316
344
#define SMTPD_NAME_DATA         "Data command"
 
345
#define SMTPD_NAME_EOD          "End-of-data"
317
346
 
318
347
 /*
319
348
  * YASLM.
352
381
    defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2))
353
382
#define DEFER_IF_REJECT3(state, class, fmt, a1, a2, a3) \
354
383
    defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3))
 
384
#define DEFER_IF_REJECT4(state, class, fmt, a1, a2, a3, a4) \
 
385
    defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3), (a4))
355
386
#define DEFER_IF_PERMIT2(state, class, fmt, a1, a2) do { \
356
387
    if ((state)->warn_if_reject == 0) \
357
388
        defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2)); \
415
446
    /*
416
447
     * Resolve the address.
417
448
     */
418
 
    canon_addr_internal(query, addr);
 
449
    rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, addr, query);
419
450
    resolve_clnt_query(STR(query), reply);
420
451
    lowercase(STR(reply->recipient));
421
452
 
452
483
 
453
484
/* smtpd_check_parse - pre-parse restrictions */
454
485
 
455
 
static ARGV *smtpd_check_parse(const char *checks)
 
486
static ARGV *smtpd_check_parse(int flags, const char *checks)
456
487
{
457
488
    char   *saved_checks = mystrdup(checks);
458
489
    ARGV   *argv = argv_alloc(1);
465
496
     * encounter. Dictionaries must be opened before entering the chroot
466
497
     * jail.
467
498
     */
 
499
#define SMTPD_CHECK_PARSE_POLICY        (1<<0)
 
500
#define SMTPD_CHECK_PARSE_MAPS          (1<<1)
 
501
#define SMTPD_CHECK_PARSE_ALL           (~0)
 
502
 
468
503
    while ((name = mystrtok(&bp, RESTRICTION_SEPARATORS)) != 0) {
469
504
        argv_add(argv, name, (char *) 0);
470
 
        if (last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0)
 
505
        if ((flags & SMTPD_CHECK_PARSE_POLICY)
 
506
            && last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0)
471
507
            policy_client_register(name);
472
 
        else if (strchr(name, ':') && dict_handle(name) == 0) {
 
508
        else if ((flags & SMTPD_CHECK_PARSE_MAPS)
 
509
                 && strchr(name, ':') && dict_handle(name) == 0) {
473
510
            dict_register(name, dict_open(name, O_RDONLY, DICT_FLAG_LOCK));
474
511
        }
475
512
        last = name;
563
600
    perm_mx_networks =
564
601
        namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
565
602
                         var_perm_mx_networks);
 
603
#ifdef USE_TLS
 
604
    relay_ccerts = maps_create(VAR_RELAY_CCERTS, var_smtpd_relay_ccerts,
 
605
                               DICT_FLAG_LOCK);
 
606
#endif
566
607
 
567
608
    /*
568
609
     * Pre-parse and pre-open the recipient maps.
623
664
     * Pre-parse the restriction lists. At the same time, pre-open tables
624
665
     * before going to jail.
625
666
     */
626
 
    client_restrctions = smtpd_check_parse(var_client_checks);
627
 
    helo_restrctions = smtpd_check_parse(var_helo_checks);
628
 
    mail_restrctions = smtpd_check_parse(var_mail_checks);
629
 
    rcpt_restrctions = smtpd_check_parse(var_rcpt_checks);
630
 
    etrn_restrctions = smtpd_check_parse(var_etrn_checks);
631
 
    data_restrctions = smtpd_check_parse(var_data_checks);
 
667
    client_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
668
                                           var_client_checks);
 
669
    helo_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
670
                                         var_helo_checks);
 
671
    mail_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
672
                                         var_mail_checks);
 
673
    rcpt_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
674
                                         var_rcpt_checks);
 
675
    etrn_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
676
                                         var_etrn_checks);
 
677
    data_restrctions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
678
                                         var_data_checks);
 
679
    eod_restrictions = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
680
                                         var_eod_checks);
632
681
 
633
682
    /*
634
683
     * Parse the pre-defined restriction classes.
640
689
            if ((value = mail_conf_lookup_eval(name)) == 0 || *value == 0)
641
690
                msg_fatal("restriction class `%s' needs a definition", name);
642
691
            htable_enter(smtpd_rest_classes, name,
643
 
                         (char *) smtpd_check_parse(value));
 
692
                         (char *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
693
                                                    value));
644
694
        }
645
695
        myfree(saved_classes);
646
696
    }
651
701
     */
652
702
#if 0
653
703
    htable_enter(smtpd_rest_classes, "check_relay_domains",
654
 
            smtpd_check_parse("permit_mydomain reject_unauth_destination"));
 
704
                 smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
705
                              "permit_mydomain reject_unauth_destination"));
655
706
#endif
656
707
    htable_enter(smtpd_rest_classes, REJECT_SENDER_LOGIN_MISMATCH,
657
 
                 (char *) smtpd_check_parse(REJECT_AUTH_SENDER_LOGIN_MISMATCH
 
708
                 (char *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL,
 
709
                                            REJECT_AUTH_SENDER_LOGIN_MISMATCH
658
710
                                  " " REJECT_UNAUTH_SENDER_LOGIN_MISMATCH));
659
711
 
660
712
    /*
671
723
     */
672
724
    expand_filter = vstring_alloc(10);
673
725
    unescape(expand_filter, var_smtpd_exp_filter);
 
726
 
 
727
    /*
 
728
     * Local rewrite policy.
 
729
     */
 
730
    local_rewrite_clients = smtpd_check_parse(SMTPD_CHECK_PARSE_MAPS,
 
731
                                              var_local_rwr_clients);
674
732
}
675
733
 
676
734
/* log_whatsup - log as much context as we have */
852
910
    return (SMTPD_CHECK_DUNNO);
853
911
}
854
912
 
 
913
/* permit_inet_interfaces - succeed if client my own address */
 
914
 
 
915
static int permit_inet_interfaces(SMTPD_STATE *state)
 
916
{
 
917
    char   *myname = "permit_inet_interfaces";
 
918
 
 
919
    if (msg_verbose)
 
920
        msg_info("%s: %s %s", myname, state->name, state->addr);
 
921
 
 
922
    if (own_inet_addr((struct sockaddr *) & (state->sockaddr)))
 
923
        return (SMTPD_CHECK_OK);
 
924
    return (SMTPD_CHECK_DUNNO);
 
925
}
 
926
 
855
927
/* permit_mynetworks - succeed if client is in a trusted network */
856
928
 
857
929
static int permit_mynetworks(SMTPD_STATE *state)
903
975
        msg_info("%s: %s", myname, addr);
904
976
 
905
977
    if (addr[0] == '[' && (len = strlen(addr)) > 2 && addr[len - 1] == ']') {
906
 
        test_addr = mystrndup(&addr[1], len - 2);
 
978
        test_addr = mystrndup(addr + 1, len - 2);
907
979
    } else
908
980
        test_addr = addr;
909
981
 
910
982
    /*
911
983
     * Validate the address.
912
984
     */
913
 
    if (!valid_hostaddr(test_addr, DONT_GRIPE))
 
985
    if (!valid_mailhost_addr(test_addr, DONT_GRIPE))
914
986
        stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
915
987
                                  "%d <%s>: %s rejected: invalid ip address",
916
988
                                var_bad_name_code, reply_name, reply_class);
946
1018
    /*
947
1019
     * Validate the hostname.
948
1020
     */
949
 
    if (!valid_hostname(test_name, DONT_GRIPE))
 
1021
    if (!valid_hostname(test_name, DONT_GRIPE)
 
1022
        && !valid_hostaddr(test_name, DONT_GRIPE))      /* XXX back compat */
950
1023
        stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
951
1024
                                  "%d <%s>: %s rejected: Invalid name",
952
1025
                                var_bad_name_code, reply_name, reply_class);
1015
1088
#define RR_ADDR_TYPES   T_A
1016
1089
#endif
1017
1090
 
1018
 
    dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
1019
 
                                  (VSTRING *) 0, RR_ADDR_TYPES, T_MX, 0);
 
1091
    dns_status = dns_lookup_l(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
 
1092
                              (VSTRING *) 0, DNS_REQ_FLAG_ANY,
 
1093
                              RR_ADDR_TYPES, T_MX, 0);
1020
1094
    if (dns_status == DNS_NOTFOUND)
1021
1095
        return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1022
1096
                                   "%d <%s>: %s rejected: Host not found",
1040
1114
    if (msg_verbose)
1041
1115
        msg_info("%s: %s", myname, name);
1042
1116
 
1043
 
    dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
1044
 
                                  (VSTRING *) 0, RR_ADDR_TYPES, T_MX, 0);
 
1117
    dns_status = dns_lookup_l(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
 
1118
                              (VSTRING *) 0, DNS_REQ_FLAG_ANY,
 
1119
                              RR_ADDR_TYPES, T_MX, 0);
1045
1120
    if (dns_status == DNS_NOTFOUND)
1046
1121
        return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1047
1122
                                   "%d <%s>: %s rejected: Domain not found",
1056
1131
 
1057
1132
static int permit_auth_destination(SMTPD_STATE *state, char *recipient);
1058
1133
 
 
1134
/* permit_tls_clientcerts - OK/DUNNO for message relaying */
 
1135
 
 
1136
#ifdef USE_TLS
 
1137
static int permit_tls_clientcerts(SMTPD_STATE *state, int permit_all_certs)
 
1138
{
 
1139
    char   *low_name;
 
1140
    const char *found;
 
1141
 
 
1142
    if (state->tls_info.peer_verified && permit_all_certs) {
 
1143
        if (msg_verbose)
 
1144
            msg_info("Relaying allowed for all verified client certificates");
 
1145
        return(SMTPD_CHECK_OK);
 
1146
    }
 
1147
 
 
1148
    if (state->tls_info.peer_verified && state->tls_info.peer_fingerprint) {
 
1149
        low_name = lowercase(mystrdup(state->tls_info.peer_fingerprint));
 
1150
        found = maps_find(relay_ccerts, low_name, DICT_FLAG_FIXED);
 
1151
        myfree(low_name);
 
1152
        if (found) {
 
1153
            if (msg_verbose)
 
1154
                msg_info("Relaying allowed for certified client: %s", found);
 
1155
            return (SMTPD_CHECK_OK);
 
1156
        } else if (msg_verbose)
 
1157
            msg_info("relay_clientcerts: No match for fingerprint '%s'",
 
1158
                     state->tls_info.peer_fingerprint);
 
1159
    }
 
1160
    return (SMTPD_CHECK_DUNNO);
 
1161
}
 
1162
#endif
 
1163
 
1059
1164
/* check_relay_domains - OK/FAIL for message relaying */
1060
1165
 
1061
1166
static int check_relay_domains(SMTPD_STATE *state, char *recipient,
1181
1286
 
1182
1287
    if (state->client != 0
1183
1288
        && SMTPD_STAND_ALONE(state) == 0
1184
 
        && vstream_peek(state->client) > 0
 
1289
        && (vstream_peek(state->client) > 0
 
1290
            || peekfd(vstream_fileno(state->client)) > 0)
1185
1291
        && (strcasecmp(state->protocol, MAIL_PROTO_ESMTP) != 0
1186
1292
            || strcasecmp(state->where, "DATA") == 0)) {
1187
1293
        return (smtpd_check_reject(state, MAIL_ERROR_PROTOCOL,
1197
1303
                            const char *reply_name, const char *reply_class)
1198
1304
{
1199
1305
    char   *myname = "all_auth_mx_addr";
1200
 
    struct in_addr addr;
 
1306
    MAI_HOSTADDR_STR hostaddr;
1201
1307
    DNS_RR *rr;
1202
1308
    DNS_RR *addr_list;
1203
1309
    int     dns_status;
1214
1320
    /*
1215
1321
     * Verify that all host addresses are within permit_mx_backup_networks.
1216
1322
     */
1217
 
    dns_status = dns_lookup(host, T_A, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0);
 
1323
    dns_status = dns_lookup_v(host, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0,
 
1324
                              DNS_REQ_FLAG_ALL, inet_proto_info()->dns_atype_list);
1218
1325
    if (dns_status != DNS_OK) {
1219
1326
        DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
1220
1327
        "450 <%s>: %s rejected: Unable to look up host %s as mail exchanger",
1222
1329
        return (NOPE);
1223
1330
    }
1224
1331
    for (rr = addr_list; rr != 0; rr = rr->next) {
1225
 
        if (rr->data_len > sizeof(addr)) {
1226
 
            msg_warn("%s: skipping address length %d for host %s",
1227
 
                     state->queue_id, rr->data_len, host);
 
1332
        if (dns_rr_to_pa(rr, &hostaddr) == 0) {
 
1333
            msg_warn("%s: skipping record type %s for host %s: %m",
 
1334
                     myname, dns_strtype(rr->type), host);
1228
1335
            continue;
1229
1336
        }
1230
 
        memcpy((char *) &addr, rr->data, sizeof(addr));
1231
1337
        if (msg_verbose)
1232
 
            msg_info("%s: checking: %s", myname, inet_ntoa(addr));
 
1338
            msg_info("%s: checking: %s", myname, hostaddr.buf);
1233
1339
 
1234
 
        if (!namadr_list_match(perm_mx_networks, host, inet_ntoa(addr))) {
 
1340
        if (!namadr_list_match(perm_mx_networks, host, hostaddr.buf)) {
1235
1341
 
1236
1342
            /*
1237
1343
             * Reject: at least one IP address is not listed in
1239
1345
             */
1240
1346
            if (msg_verbose)
1241
1347
                msg_info("%s: address %s for %s does not match %s",
1242
 
                       myname, inet_ntoa(addr), host, VAR_PERM_MX_NETWORKS);
 
1348
                         myname, hostaddr.buf, host, VAR_PERM_MX_NETWORKS);
1243
1349
            dns_rr_free(addr_list);
1244
1350
            return (NOPE);
1245
1351
        }
1254
1360
                            const char *reply_name, const char *reply_class)
1255
1361
{
1256
1362
    char   *myname = "has_my_addr";
1257
 
    struct in_addr addr;
1258
 
    char  **cpp;
1259
 
    struct hostent *hp;
 
1363
    struct addrinfo *res;
 
1364
    struct addrinfo *res0;
 
1365
    int     aierr;
 
1366
    MAI_HOSTADDR_STR hostaddr;
 
1367
    INET_PROTO_INFO *proto_info = inet_proto_info();
1260
1368
 
1261
1369
    if (msg_verbose)
1262
1370
        msg_info("%s: host %s", myname, host);
1267
1375
#define YUP     1
1268
1376
#define NOPE    0
1269
1377
 
1270
 
    if ((hp = gethostbyname(host)) == 0) {
1271
 
        DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
1272
 
          "450 <%s>: %s rejected: Unable to look up mail exchanger host %s",
1273
 
                         reply_name, reply_class, host);
1274
 
        return (NOPE);
1275
 
    }
1276
 
    if (hp->h_addrtype != AF_INET || hp->h_length != sizeof(addr)) {
1277
 
        msg_warn("address type %d length %d for %s",
1278
 
                 hp->h_addrtype, hp->h_length, host);
1279
 
        return (NOPE);
1280
 
    }
1281
 
    for (cpp = hp->h_addr_list; *cpp; cpp++) {
1282
 
        memcpy((char *) &addr, *cpp, sizeof(addr));
1283
 
        if (msg_verbose)
1284
 
            msg_info("%s: addr %s", myname, inet_ntoa(addr));
1285
 
        if (own_inet_addr(&addr))
1286
 
            return (YUP);
1287
 
        if (proxy_inet_addr(&addr))
1288
 
            return (YUP);
 
1378
    aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0);
 
1379
    if (aierr) {
 
1380
        DEFER_IF_REJECT4(state, MAIL_ERROR_POLICY,
 
1381
                         "450 <%s>: %s rejected: Unable to look up mail exchanger host %s: %s",
 
1382
                         reply_name, reply_class, host, MAI_STRERROR(aierr));
 
1383
        return (NOPE);
 
1384
    }
 
1385
#define HAS_MY_ADDR_RETURN(x) { freeaddrinfo(res0); return (x); }
 
1386
 
 
1387
    for (res = res0; res != 0; res = res->ai_next) {
 
1388
        if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
 
1389
            if (msg_verbose)
 
1390
                msg_info("skipping address family %d for host %s",
 
1391
                         res->ai_family, host);
 
1392
            continue;
 
1393
        }
 
1394
        if (msg_verbose) {
 
1395
            SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
 
1396
                                 &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
 
1397
            msg_info("%s: addr %s", myname, hostaddr.buf);
 
1398
        }
 
1399
        if (own_inet_addr(res->ai_addr))
 
1400
            HAS_MY_ADDR_RETURN(YUP);
 
1401
        if (proxy_inet_addr(res->ai_addr))
 
1402
            HAS_MY_ADDR_RETURN(YUP);
1289
1403
    }
1290
1404
    if (msg_verbose)
1291
1405
        msg_info("%s: host %s: no match", myname, host);
1292
1406
 
1293
 
    return (NOPE);
 
1407
    HAS_MY_ADDR_RETURN(NOPE);
1294
1408
}
1295
1409
 
1296
1410
/* i_am_mx - is this machine listed as MX relay */
1298
1412
static int i_am_mx(SMTPD_STATE *state, DNS_RR *mx_list,
1299
1413
                           const char *reply_name, const char *reply_class)
1300
1414
{
1301
 
    const char *myname = "permit_mx_backup";
 
1415
    const char *myname = "i_am_mx";
1302
1416
    DNS_RR *mx;
1303
1417
 
1304
1418
    /*
1335
1449
static int permit_mx_primary(SMTPD_STATE *state, DNS_RR *mx_list,
1336
1450
                            const char *reply_name, const char *reply_class)
1337
1451
{
 
1452
    const char *myname = "permit_mx_primary";
1338
1453
    DNS_RR *mx;
1339
1454
    unsigned int best_pref;
1340
1455
 
 
1456
    if (msg_verbose)
 
1457
        msg_info("%s", myname);
 
1458
 
1341
1459
    /*
1342
1460
     * Find the preference of the primary MX hosts.
1343
1461
     */
1630
1748
                 table, VAR_SMTPD_PROXY_FILT, action);
1631
1749
        return (0);
1632
1750
    }
 
1751
 
 
1752
    /*
 
1753
     * ETRN does not receive mail so we can't store queue file records.
 
1754
     */
 
1755
    if (strcmp(state->where, "ETRN") == 0) {
 
1756
        msg_warn("access table %s: action %s is unavailable in %s",
 
1757
                 table, action, VAR_ETRN_CHECKS);
 
1758
        return (0);
 
1759
    }
1633
1760
    return (not_in_client_helo(state, table, action, reply_class));
1634
1761
}
1635
1762
 
1646
1773
     * Thus, if delay_reject=no, client and helo actions such as FILTER or
1647
1774
     * HOLD also should not affect subsequent mail deliveries. Hmm...
1648
1775
     * 
1649
 
     * XXX If the MAIL FROM command is rejected then we have to reset access
1650
 
     * map side effects such as FILTER.
 
1776
     * XXX If the MAIL FROM command is rejected then we have to reset access map
 
1777
     * side effects such as FILTER.
1651
1778
     */
1652
1779
    if (state->sender == 0) {
1653
1780
        msg_warn("access table %s: with %s=%s, "
1837
1964
        if (not_in_client_helo(state, table, "PREPEND", reply_class) == 0)
1838
1965
            return (SMTPD_CHECK_DUNNO);
1839
1966
#endif
 
1967
        if (strcmp(state->where, SMTPD_AFTER_DOT) == 0) {
 
1968
            msg_warn("access table %s: action PREPEND must be used before %s",
 
1969
                     table, VAR_EOD_CHECKS);
 
1970
            return (SMTPD_CHECK_DUNNO);
 
1971
        }
1840
1972
        if (*cmd_text == 0 || is_header(cmd_text) == 0) {
1841
1973
            msg_warn("access map %s entry \"%s\" requires header: text",
1842
1974
                     table, datum);
2029
2161
    char   *addr;
2030
2162
    const char *value;
2031
2163
    DICT   *dict;
 
2164
    int     delim;
2032
2165
 
2033
2166
    if (msg_verbose)
2034
2167
        msg_info("%s: %s", myname, address);
2039
2172
#define CHK_ADDR_RETURN(x,y) { *found = y; return(x); }
2040
2173
 
2041
2174
    addr = STR(vstring_strcpy(error_text, address));
 
2175
#ifdef HAS_IPV6
 
2176
    if (strchr(addr, ':') != 0)
 
2177
        delim = ':';
 
2178
    else
 
2179
#endif
 
2180
        delim = '.';
2042
2181
 
2043
2182
    if ((dict = dict_handle(table)) == 0)
2044
2183
        msg_panic("%s: dictionary not found: %s", myname, table);
2052
2191
                msg_fatal("%s: table lookup problem", table);
2053
2192
        }
2054
2193
        flags = PARTIAL;
2055
 
    } while (split_at_right(addr, '.'));
 
2194
    } while (split_at_right(addr, delim));
2056
2195
 
2057
2196
    CHK_ADDR_RETURN(SMTPD_CHECK_DUNNO, MISSED);
2058
2197
}
2110
2249
    DNS_RR *server_list;
2111
2250
    DNS_RR *server;
2112
2251
    int     found = 0;
2113
 
    struct in_addr addr;
2114
 
    struct hostent *hp;
2115
 
    char   *addr_string;
 
2252
    MAI_HOSTADDR_STR addr_string;
 
2253
    int     aierr;
 
2254
    struct addrinfo *res0;
 
2255
    struct addrinfo *res;
2116
2256
    int     status;
2117
 
    char  **cpp;
2118
 
    static DNS_FIXED fixed;
 
2257
    INET_PROTO_INFO *proto_info;
2119
2258
 
2120
2259
    /*
2121
2260
     * Sanity check.
2136
2275
        domain = name;
2137
2276
 
2138
2277
    /*
 
2278
     * Treat an address literal as its own MX server, just like we treat a
 
2279
     * name without MX record as its own MX server. There is, however, no
 
2280
     * applicable NS server equivalent.
 
2281
     */
 
2282
    if (*domain == '[') {
 
2283
        char   *saved_addr;
 
2284
        const char *bare_addr;
 
2285
        int     len;
 
2286
 
 
2287
        if (type != T_MX)
 
2288
            return (SMTPD_CHECK_DUNNO);
 
2289
        len = strlen(domain);
 
2290
        if (domain[len - 1] != ']')
 
2291
            return (SMTPD_CHECK_DUNNO);
 
2292
        /* Memory leak alert: no early returns after this point. */
 
2293
        saved_addr = mystrndup(domain + 1, len - 2);
 
2294
        if ((bare_addr = valid_mailhost_addr(saved_addr, DONT_GRIPE)) == 0)
 
2295
            status = SMTPD_CHECK_DUNNO;
 
2296
        else
 
2297
            status = check_addr_access(state, table, bare_addr, FULL,
 
2298
                                       &found, reply_name, reply_class,
 
2299
                                       def_acl);
 
2300
        myfree(saved_addr);
 
2301
        return (status);
 
2302
    }
 
2303
 
 
2304
    /*
2139
2305
     * If the domain name does not exist then we apply no restriction.
2140
2306
     * 
2141
2307
     * If the domain name exists but no MX record exists, fabricate an MX record
2148
2314
                            (VSTRING *) 0, (VSTRING *) 0);
2149
2315
    if (dns_status == DNS_NOTFOUND && h_errno == NO_DATA) {
2150
2316
        if (type == T_MX) {
2151
 
            server_list = dns_rr_create(domain, &fixed, 0,
 
2317
            server_list = dns_rr_create(domain, type, C_IN, 0, 0,
2152
2318
                                        domain, strlen(domain) + 1);
2153
2319
            dns_status = DNS_OK;
2154
2320
        } else if (type == T_NS) {
2175
2341
    /*
2176
2342
     * Check the hostnames first, then the addresses.
2177
2343
     */
 
2344
    proto_info = inet_proto_info();
2178
2345
    for (server = server_list; server != 0; server = server->next) {
2179
2346
        if (msg_verbose)
2180
2347
            msg_info("%s: %s hostname check: %s",
2183
2350
                                      FULL, &found, reply_name, reply_class,
2184
2351
                                          def_acl)) != 0 || found)
2185
2352
            CHECK_SERVER_RETURN(status);
2186
 
        SET_H_ERRNO(0);                         /* XXX */
2187
 
        if ((hp = gethostbyname((char *) server->data)) == 0) {
 
2353
        if ((aierr = hostname_to_sockaddr((char *) server->data,
 
2354
                                          (char *) 0, 0, &res0)) != 0) {
2188
2355
            msg_warn("Unable to look up %s host %s for %s %s: %s",
2189
2356
                     dns_strtype(type), (char *) server->data,
2190
 
                     reply_class, reply_name, dns_strerror(h_errno));
 
2357
                     reply_class, reply_name, MAI_STRERROR(aierr));
2191
2358
            continue;
2192
2359
        }
2193
 
        if (hp->h_addrtype != AF_INET || hp->h_length != sizeof(addr)) {
2194
 
            if (msg_verbose)
2195
 
                msg_warn("address type %d length %d for %s",
2196
 
                       hp->h_addrtype, hp->h_length, (char *) server->data);
2197
 
            continue;                           /* XXX */
2198
 
        }
 
2360
        /* Now we must also free the addrinfo result. */
2199
2361
        if (msg_verbose)
2200
2362
            msg_info("%s: %s host address check: %s",
2201
2363
                     myname, dns_strtype(type), (char *) server->data);
2202
 
        for (cpp = hp->h_addr_list; *cpp; cpp++) {
2203
 
            memcpy((char *) &addr, *cpp, sizeof(addr));
2204
 
            addr_string = mystrdup(inet_ntoa(addr));
2205
 
            status = check_addr_access(state, table, addr_string, FULL,
 
2364
        for (res = res0; res != 0; res = res->ai_next) {
 
2365
            if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
 
2366
                if (msg_verbose)
 
2367
                    msg_info("skipping address family %d for host %s",
 
2368
                             res->ai_family, server->data);
 
2369
                continue;
 
2370
            }
 
2371
            SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
 
2372
                                 &addr_string, (MAI_SERVPORT_STR *) 0, 0);
 
2373
            status = check_addr_access(state, table, addr_string.buf, FULL,
2206
2374
                                       &found, reply_name, reply_class,
2207
2375
                                       def_acl);
2208
 
            myfree(addr_string);
2209
 
            if (status != 0 || found)
 
2376
            if (status != 0 || found) {
 
2377
                freeaddrinfo(res0);             /* 200412 */
2210
2378
                CHECK_SERVER_RETURN(status);
 
2379
            }
2211
2380
        }
 
2381
        freeaddrinfo(res0);                     /* 200412 */
2212
2382
    }
2213
2383
    CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
2214
2384
}
2215
2385
 
 
2386
/* check_ccert_access - access for TLS clients by certificate fingerprint */
 
2387
 
 
2388
#ifdef USE_TLS
 
2389
 
 
2390
static int check_ccert_access(SMTPD_STATE *state, const char *table,
 
2391
                                      const char *def_acl)
 
2392
{
 
2393
    char   *myname = "check_ccert_access";
 
2394
    int     found;
 
2395
 
 
2396
    if (state->tls_info.peer_verified && state->tls_info.peer_fingerprint) {
 
2397
        if (msg_verbose)
 
2398
            msg_info("%s: %s", myname, state->tls_info.peer_fingerprint);
 
2399
 
 
2400
        /*
 
2401
         * Regexp tables don't make sense for certificate fingerprints. That
 
2402
         * may be so, but we can't ignore the entire check_ccert_access
 
2403
         * request without logging a warning.
 
2404
         * 
 
2405
         * Log the peer CommonName when access is denied. Non-printable
 
2406
         * characters will be neutered by smtpd_check_reject(). The SMTP
 
2407
         * client name and address are always syslogged as part of a "reject"
 
2408
         * event.
 
2409
         */
 
2410
        return (check_access(state, table, state->tls_info.peer_fingerprint,
 
2411
                             DICT_FLAG_NONE, &found, state->tls_info.peer_CN,
 
2412
                             SMTPD_NAME_CCERT, def_acl));
 
2413
    }
 
2414
    return (SMTPD_CHECK_DUNNO);
 
2415
}
 
2416
 
 
2417
#endif
 
2418
 
2216
2419
/* check_mail_access - OK/FAIL based on mail address lookup */
2217
2420
 
2218
2421
static int check_mail_access(SMTPD_STATE *state, const char *table,
2240
2443
        reject_dict_retry(state, addr);
2241
2444
 
2242
2445
    /*
2243
 
     * Garbage in, garbage out. Every address from canon_addr_internal() and
2244
 
     * from resolve_clnt_query() must be fully qualified.
 
2446
     * Garbage in, garbage out. Every address from rewrite_clnt_internal()
 
2447
     * and from resolve_clnt_query() must be fully qualified.
2245
2448
     */
2246
2449
    if ((domain = strrchr(CONST_STR(reply->recipient), '@')) == 0) {
2247
2450
        msg_warn("%s: no @domain in address: %s", myname,
2460
2663
 
2461
2664
static void *rbl_pagein(const char *query, void *unused_context)
2462
2665
{
 
2666
    const char *myname = "rbl_pagein";
2463
2667
    DNS_RR *txt_list;
2464
2668
    VSTRING *why;
2465
2669
    int     dns_status;
2466
2670
    SMTPD_RBL_STATE *rbl;
2467
2671
    DNS_RR *addr_list;
2468
 
    struct in_addr addr;
 
2672
    MAI_HOSTADDR_STR hostaddr;
2469
2673
    DNS_RR *rr;
2470
2674
    DNS_RR *next;
2471
2675
    VSTRING *buf;
2475
2679
     * Do the query. If the DNS lookup produces no definitive reply, give the
2476
2680
     * requestor the benefit of the doubt. We can't block all email simply
2477
2681
     * because an RBL server is unavailable.
 
2682
     * 
 
2683
     * Don't do this for AAAA records. Yet.
2478
2684
     */
2479
2685
    why = vstring_alloc(10);
2480
2686
    dns_status = dns_lookup(query, T_A, 0, &addr_list, (VSTRING *) 0, why);
2511
2717
        rbl->txt = 0;
2512
2718
    rbl->a = argv_alloc(1);
2513
2719
    for (rr = addr_list; rr != 0; rr = rr->next) {
2514
 
        memcpy((char *) &addr.s_addr, addr_list->data, sizeof(addr.s_addr));
2515
 
        argv_add(rbl->a, inet_ntoa(addr), ARGV_END);
 
2720
        if (dns_rr_to_pa(rr, &hostaddr) == 0)
 
2721
            msg_warn("%s: skipping record type %s for query %s: %m",
 
2722
                     myname, dns_strtype(rr->type), query);
 
2723
        else
 
2724
            argv_add(rbl->a, hostaddr.buf, ARGV_END);
2516
2725
    }
2517
2726
    dns_rr_free(addr_list);
2518
2727
    return ((void *) rbl);
2649
2858
        msg_info("%s: %s %s", myname, reply_class, addr);
2650
2859
 
2651
2860
    /*
2652
 
     * IPv4 only for now
 
2861
     * IPv4 / IPv6-mapped IPv4 (if supported) only for now
2653
2862
     */
2654
 
#ifdef INET6
2655
 
    if (inet_pton(AF_INET, addr, &a) != 1)
 
2863
    if (valid_ipv6_hostaddr(addr, DONT_GRIPE))
2656
2864
        return SMTPD_CHECK_DUNNO;
2657
 
#endif
2658
2865
 
2659
2866
    /*
2660
2867
     * Reverse the client IPV4 address, tack on the RBL domain name and query
2867
3074
                          ATTR_TYPE_STR, MAIL_ATTR_INSTANCE,
2868
3075
                          STR(state->instance),
2869
3076
                          ATTR_TYPE_LONG, MAIL_ATTR_SIZE,
2870
 
                          (unsigned long) state->msg_size,
 
3077
                          (unsigned long) (state->act_size > 0 ?
 
3078
                                         state->act_size : state->msg_size),
2871
3079
#ifdef USE_SASL_AUTH
2872
3080
                          ATTR_TYPE_STR, MAIL_ATTR_SASL_METHOD,
2873
3081
                          var_smtpd_sasl_enable && state->sasl_method ?
2879
3087
                          var_smtpd_sasl_enable && state->sasl_sender ?
2880
3088
                          state->sasl_sender : "",
2881
3089
#endif
 
3090
#ifdef USE_TLS
 
3091
                          ATTR_TYPE_STR, MAIL_ATTR_CCERT_SUBJECT,
 
3092
                          state->tls_info.peer_verified ?
 
3093
                          state->tls_info.peer_CN : "",
 
3094
                          ATTR_TYPE_STR, MAIL_ATTR_CCERT_ISSSUER,
 
3095
                          state->tls_info.peer_verified ?
 
3096
                          state->tls_info.issuer_CN : "",
 
3097
                          ATTR_TYPE_STR, MAIL_ATTR_CCERT_FINGERPRINT,
 
3098
                          state->tls_info.peer_verified ?
 
3099
                          state->tls_info.peer_fingerprint : "",
 
3100
#endif
2882
3101
                          ATTR_TYPE_END,
2883
3102
                          ATTR_FLAG_MISSING,    /* Reply attributes. */
2884
3103
                          ATTR_TYPE_STR, MAIL_ATTR_ACTION, action,
3014
3233
        } else if (strcasecmp(name, REJECT_UNAUTH_PIPE) == 0) {
3015
3234
            status = reject_unauth_pipelining(state, reply_name, reply_class);
3016
3235
        } else if (strcasecmp(name, CHECK_POLICY_SERVICE) == 0) {
3017
 
            if (cpp[1] == 0)
 
3236
            if (cpp[1] == 0 || strchr(cpp[1], ':') == 0) {
3018
3237
                msg_warn("restriction %s must be followed by transport:server",
3019
3238
                         CHECK_POLICY_SERVICE);
3020
 
            else
 
3239
                longjmp(smtpd_check_buf, smtpd_check_reject(state,
 
3240
                    MAIL_ERROR_SOFTWARE, "451 Server configuration error"));
 
3241
            } else
3021
3242
                status = check_policy_service(state, *++cpp, reply_name,
3022
3243
                                              reply_class, def_acl);
3023
3244
        } else if (strcasecmp(name, DEFER_IF_PERMIT) == 0) {
3028
3249
            DEFER_IF_REJECT2(state, MAIL_ERROR_POLICY,
3029
3250
                         "450 <%s>: %s rejected: defer_if_reject requested",
3030
3251
                             reply_name, reply_class);
 
3252
#ifdef SNAPSHOT
 
3253
        } else if (strcasecmp(name, SLEEP) == 0) {
 
3254
            if (cpp[1] == 0 || alldig(cpp[1]) == 0) {
 
3255
                msg_warn("restriction %s must be followed by number", SLEEP);
 
3256
                longjmp(smtpd_check_buf, smtpd_check_reject(state,
 
3257
                    MAIL_ERROR_SOFTWARE, "451 Server configuration error"));
 
3258
            } else
 
3259
                sleep(atoi(*++cpp));
 
3260
#endif
3031
3261
        }
3032
3262
 
3033
3263
        /*
3035
3265
         */
3036
3266
        else if (strcasecmp(name, REJECT_UNKNOWN_CLIENT) == 0) {
3037
3267
            status = reject_unknown_client(state);
 
3268
        } else if (strcasecmp(name, PERMIT_INET_INTERFACES) == 0) {
 
3269
            status = permit_inet_interfaces(state);
3038
3270
        } else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
3039
3271
            status = permit_mynetworks(state);
3040
3272
        } else if (is_map_command(state, name, CHECK_CLIENT_ACL, &cpp)) {
3060
3292
                    status = reject_rbl_domain(state, *cpp, state->name,
3061
3293
                                               SMTPD_NAME_CLIENT);
3062
3294
            }
 
3295
#ifdef USE_TLS
 
3296
        } else if (is_map_command(state, name, CHECK_CCERT_ACL, &cpp)) {
 
3297
            status = check_ccert_access(state, *cpp, def_acl);
 
3298
#endif
3063
3299
        }
3064
3300
 
3065
3301
        /*
3092
3328
            msg_warn("restriction %s is deprecated. Use %s instead",
3093
3329
                     PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS);
3094
3330
            if (state->helo_name) {
3095
 
                if (state->helo_name[strspn(state->helo_name, "0123456789.")] == 0
 
3331
                if (state->helo_name[strspn(state->helo_name, "0123456789.:")] == 0
3096
3332
                && (status = reject_invalid_hostaddr(state, state->helo_name,
3097
3333
                                   state->helo_name, SMTPD_NAME_HELO)) == 0)
3098
3334
                    status = SMTPD_CHECK_OK;
3238
3474
#else
3239
3475
                msg_warn("restriction `%s' ignored: no SASL support", name);
3240
3476
#endif
 
3477
#ifdef USE_TLS
 
3478
        } else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) {
 
3479
          status = permit_tls_clientcerts(state, 1);
 
3480
        } else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) {
 
3481
          status = permit_tls_clientcerts(state, 0);
 
3482
#endif
3241
3483
        } else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
3242
3484
            if (state->recipient)
3243
3485
                status = reject_unknown_address(state, state->recipient,
3356
3598
    return (0);
3357
3599
}
3358
3600
 
 
3601
/* smtpd_check_rewrite - choose address qualification context */
 
3602
 
 
3603
void    smtpd_check_rewrite(SMTPD_STATE *state)
 
3604
{
 
3605
    const char *myname = "smtpd_check_rewrite";
 
3606
    int     status;
 
3607
    char  **cpp;
 
3608
    DICT   *dict;
 
3609
    char   *name;
 
3610
 
 
3611
    /*
 
3612
     * We don't use generic_checks() because it produces results that aren't
 
3613
     * applicable such as DEFER or REJECT.
 
3614
     */
 
3615
    for (cpp = local_rewrite_clients->argv; *cpp != 0; cpp++) {
 
3616
        if (msg_verbose)
 
3617
            msg_info("%s: trying: %s", myname, *cpp);
 
3618
        status = SMTPD_CHECK_DUNNO;
 
3619
        if (strchr(name = *cpp, ':') != 0) {
 
3620
            name = CHECK_ADDR_MAP;
 
3621
            cpp -= 1;
 
3622
        }
 
3623
        if (strcasecmp(name, PERMIT_INET_INTERFACES) == 0) {
 
3624
            status = permit_inet_interfaces(state);
 
3625
        } else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
 
3626
            status = permit_mynetworks(state);
 
3627
        } else if (is_map_command(state, name, CHECK_ADDR_MAP, &cpp)) {
 
3628
            if ((dict = dict_handle(*cpp)) == 0)
 
3629
                msg_panic("%s: dictionary not found: %s", myname, *cpp);
 
3630
            if (dict_get(dict, state->addr) != 0)
 
3631
                status = SMTPD_CHECK_OK;
 
3632
        } else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) {
 
3633
#ifdef USE_SASL_AUTH
 
3634
            status = permit_sasl_auth(state, SMTPD_CHECK_OK,
 
3635
                                      SMTPD_CHECK_DUNNO);
 
3636
#else
 
3637
            status = SMTPD_CHECK_DUNNO;
 
3638
#endif
 
3639
#ifdef USE_TLS
 
3640
        } else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) {
 
3641
            status = permit_tls_clientcerts(state, 1);
 
3642
        } else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) {
 
3643
            status = permit_tls_clientcerts(state, 0);
 
3644
#endif
 
3645
        } else {
 
3646
            msg_warn("parameter %s: invalid request: %s",
 
3647
                     VAR_LOC_RWR_CLIENTS, name);
 
3648
            continue;
 
3649
        }
 
3650
        if (status == SMTPD_CHECK_OK) {
 
3651
            state->rewrite_context = MAIL_ATTR_RWR_LOCAL;
 
3652
            return;
 
3653
        }
 
3654
    }
 
3655
    state->rewrite_context = MAIL_ATTR_RWR_REMOTE;
 
3656
}
 
3657
 
3359
3658
/* smtpd_check_client - validate client name or address */
3360
3659
 
3361
3660
char   *smtpd_check_client(SMTPD_STATE *state)
3532
3831
    if (*recipient) {
3533
3832
        if (canon_verify_sender == 0) {
3534
3833
            canon_verify_sender = vstring_alloc(10);
3535
 
            canon_addr_internal(canon_verify_sender, var_verify_sender);
 
3834
            rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL,
 
3835
                                  var_verify_sender,
 
3836
                                  canon_verify_sender);
3536
3837
        }
3537
3838
        if (strcasecmp(STR(canon_verify_sender), recipient) == 0)
3538
3839
            return (0);
3875
4176
char   *smtpd_check_data(SMTPD_STATE *state)
3876
4177
{
3877
4178
    int     status;
3878
 
    char *NOCLOBBER saved_recipient;
 
4179
    char   *NOCLOBBER saved_recipient;
3879
4180
 
3880
4181
    /*
3881
4182
     * Minor kluge so that we can delegate work to the generic routine. We
3919
4220
    return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
3920
4221
}
3921
4222
 
 
4223
/* smtpd_check_eod - check end-of-data command */
 
4224
 
 
4225
char   *smtpd_check_eod(SMTPD_STATE *state)
 
4226
{
 
4227
    int     status;
 
4228
    char   *NOCLOBBER saved_recipient;
 
4229
 
 
4230
    /*
 
4231
     * Minor kluge so that we can delegate work to the generic routine. We
 
4232
     * provide no recipient information in the case of multiple recipients,
 
4233
     * This restriction applies to all recipients alike, and logging only one
 
4234
     * of them would be misleading.
 
4235
     */
 
4236
    if (state->rcpt_count > 1) {
 
4237
        saved_recipient = state->recipient;
 
4238
        state->recipient = 0;
 
4239
    }
 
4240
 
 
4241
    /*
 
4242
     * Reset the defer_if_permit flag. This is necessary when some recipients
 
4243
     * were accepted but the last one was rejected.
 
4244
     */
 
4245
    state->defer_if_permit.active = 0;
 
4246
 
 
4247
    /*
 
4248
     * Apply restrictions in the order as specified.
 
4249
     * 
 
4250
     * XXX We cannot specify a default target for a bare access map.
 
4251
     */
 
4252
    SMTPD_CHECK_RESET();
 
4253
    status = setjmp(smtpd_check_buf);
 
4254
    if (status == 0 && eod_restrictions->argc)
 
4255
        status = generic_checks(state, eod_restrictions,
 
4256
                                "END-OF-DATA", SMTPD_NAME_EOD, NO_DEF_ACL);
 
4257
 
 
4258
    /*
 
4259
     * Force permission into deferral when some earlier temporary error may
 
4260
     * have prevented us from rejecting mail, and report the earlier problem.
 
4261
     */
 
4262
    if (status != SMTPD_CHECK_REJECT && state->defer_if_permit.active)
 
4263
        status = smtpd_check_reject(state, state->defer_if_permit.class,
 
4264
                                  "%s", STR(state->defer_if_permit.reason));
 
4265
 
 
4266
    if (state->rcpt_count > 1)
 
4267
        state->recipient = saved_recipient;
 
4268
 
 
4269
    return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
 
4270
}
 
4271
 
3922
4272
#ifdef TEST
3923
4273
 
3924
4274
 /*
3947
4297
char   *var_rcpt_checks = "";
3948
4298
char   *var_etrn_checks = "";
3949
4299
char   *var_data_checks = "";
 
4300
char   *var_eod_checks = "";
3950
4301
char   *var_relay_domains = "";
 
4302
 
 
4303
#ifdef USE_TLS
 
4304
char   *var_relay_ccerts = "";
 
4305
 
 
4306
#endif
3951
4307
char   *var_mynetworks = "";
3952
4308
char   *var_notify_classes = "";
3953
4309
 
3958
4314
char   *var_myorigin;
3959
4315
char   *var_mydest;
3960
4316
char   *var_inet_interfaces;
 
4317
char   *var_proxy_interfaces;
3961
4318
char   *var_rcpt_delim;
3962
4319
char   *var_rest_classes;
3963
4320
char   *var_alias_maps;
3979
4336
char   *var_relay_rcpt_maps;
3980
4337
char   *var_verify_sender;
3981
4338
char   *var_smtpd_sasl_opts;
 
4339
char   *var_local_rwr_clients;
3982
4340
 
3983
4341
typedef struct {
3984
4342
    char   *name;
3997
4355
    VAR_MYORIGIN, DEF_MYORIGIN, &var_myorigin,
3998
4356
    VAR_MYDEST, DEF_MYDEST, &var_mydest,
3999
4357
    VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces,
 
4358
    VAR_PROXY_INTERFACES, DEF_PROXY_INTERFACES, &var_proxy_interfaces,
4000
4359
    VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim,
4001
4360
    VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes,
4002
4361
    VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps,
4019
4378
    VAR_VERIFY_SENDER, DEF_VERIFY_SENDER, &var_verify_sender,
4020
4379
    VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name,
4021
4380
    VAR_SMTPD_SASL_OPTS, DEF_SMTPD_SASL_OPTS, &var_smtpd_sasl_opts,
 
4381
    VAR_LOC_RWR_CLIENTS, DEF_LOC_RWR_CLIENTS, &var_local_rwr_clients,
4022
4382
    0,
4023
4383
};
4024
4384
 
4083
4443
int     var_smtpd_policy_tmout;
4084
4444
int     var_smtpd_policy_idle;
4085
4445
int     var_smtpd_policy_ttl;
 
4446
int     var_smtpd_rej_unl_from;
 
4447
int     var_smtpd_rej_unl_rcpt;
4086
4448
 
4087
4449
static INT_TABLE int_table[] = {
4088
4450
    "msg_verbose", 0, &msg_verbose,
4107
4469
    VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code,
4108
4470
    VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table,
4109
4471
    VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT, &var_verify_poll_count,
 
4472
    VAR_SMTPD_REJ_UNL_FROM, DEF_SMTPD_REJ_UNL_FROM, &var_smtpd_rej_unl_from,
 
4473
    VAR_SMTPD_REJ_UNL_RCPT, DEF_SMTPD_REJ_UNL_RCPT, &var_smtpd_rej_unl_rcpt,
4110
4474
    0,
4111
4475
};
4112
4476
 
4163
4527
    for (rp = rest_table; rp->name; rp++) {
4164
4528
        if (strcasecmp(rp->name, argv[0]) == 0) {
4165
4529
            argv_free(rp->target[0]);
4166
 
            rp->target[0] = smtpd_check_parse(argv[1]);
 
4530
            rp->target[0] = smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, argv[1]);
4167
4531
            return (1);
4168
4532
        }
4169
4533
    }
4187
4551
        argv_free((ARGV *) entry->value);
4188
4552
    else
4189
4553
        entry = htable_enter(smtpd_rest_classes, name, (char *) 0);
4190
 
    entry->value = (char *) smtpd_check_parse(cp);
 
4554
    entry->value = (char *) smtpd_check_parse(SMTPD_CHECK_PARSE_ALL, cp);
4191
4555
}
4192
4556
 
4193
4557
/* resolve_clnt_init - initialize reply */
4243
4607
    return (VRFY_STAT_OK);
4244
4608
}
4245
4609
 
4246
 
/* canon_addr_internal - stub */
 
4610
/* rewrite_clnt_internal - stub */
4247
4611
 
4248
 
VSTRING *canon_addr_internal(VSTRING *result, const char *addr)
 
4612
VSTRING *rewrite_clnt_internal(const char *context, const char *addr,
 
4613
                                       VSTRING *result)
4249
4614
{
4250
4615
    if (addr == STR(result))
4251
 
        msg_panic("canon_addr_internal: result clobbers input");
 
4616
        msg_panic("rewrite_clnt_internal: result clobbers input");
4252
4617
    if (*addr && strchr(addr, '@') == 0)
4253
4618
        msg_fatal("%s: address rewriting is disabled", addr);
4254
4619
    vstring_strcpy(result, addr);
4312
4677
    char   *bp;
4313
4678
    char   *resp;
4314
4679
    char   *addr;
 
4680
    INET_PROTO_INFO *proto_info;
4315
4681
 
4316
4682
    /*
4317
4683
     * Initialization. Use dummies for client information.
4322
4688
    string_init();
4323
4689
    int_init();
4324
4690
    smtpd_check_init();
4325
 
    smtpd_state_init(&state, VSTREAM_IN);
 
4691
    smtpd_state_init(&state, VSTREAM_IN, "smtpd");
4326
4692
    state.queue_id = "<queue id>";
4327
4693
 
 
4694
    proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
 
4695
 
4328
4696
    /*
4329
4697
     * Main loop: update config parameters or test the client, helo, sender
4330
4698
     * and recipient restrictions.
4412
4780
                resp = 0;
4413
4781
                break;
4414
4782
            }
4415
 
            if (strcasecmp(args->argv[0], "local_recipient_maps") == 0) {
 
4783
            if (strcasecmp(args->argv[0], VAR_LOCAL_RCPT_MAPS) == 0) {
4416
4784
                UPDATE_STRING(var_local_rcpt_maps, args->argv[1]);
4417
4785
                UPDATE_MAPS(local_rcpt_maps, VAR_LOCAL_RCPT_MAPS,
4418
4786
                            var_local_rcpt_maps, DICT_FLAG_LOCK);
4419
4787
                resp = 0;
4420
4788
                break;
4421
4789
            }
4422
 
            if (strcasecmp(args->argv[0], "relay_recipient_maps") == 0) {
 
4790
            if (strcasecmp(args->argv[0], VAR_RELAY_RCPT_MAPS) == 0) {
4423
4791
                UPDATE_STRING(var_relay_rcpt_maps, args->argv[1]);
4424
4792
                UPDATE_MAPS(relay_rcpt_maps, VAR_RELAY_RCPT_MAPS,
4425
4793
                            var_relay_rcpt_maps, DICT_FLAG_LOCK);
4426
4794
                resp = 0;
4427
4795
                break;
4428
4796
            }
4429
 
            if (strcasecmp(args->argv[0], "canonical_maps") == 0) {
 
4797
            if (strcasecmp(args->argv[0], VAR_CANONICAL_MAPS) == 0) {
4430
4798
                UPDATE_STRING(var_canonical_maps, args->argv[1]);
4431
4799
                UPDATE_MAPS(canonical_maps, VAR_CANONICAL_MAPS,
4432
4800
                            var_canonical_maps, DICT_FLAG_LOCK);
4433
4801
                resp = 0;
4434
4802
                break;
4435
4803
            }
4436
 
            if (strcasecmp(args->argv[0], "rbl_reply_maps") == 0) {
 
4804
            if (strcasecmp(args->argv[0], VAR_RBL_REPLY_MAPS) == 0) {
4437
4805
                UPDATE_STRING(var_rbl_reply_maps, args->argv[1]);
4438
4806
                UPDATE_MAPS(rbl_reply_maps, VAR_RBL_REPLY_MAPS,
4439
4807
                            var_rbl_reply_maps, DICT_FLAG_LOCK);
4440
4808
                resp = 0;
4441
4809
                break;
4442
4810
            }
4443
 
            if (strcasecmp(args->argv[0], "mynetworks") == 0) {
 
4811
            if (strcasecmp(args->argv[0], VAR_MYNETWORKS) == 0) {
 
4812
                /* NOT: UPDATE_STRING */
4444
4813
                namadr_list_free(mynetworks);
4445
4814
                mynetworks =
4446
4815
                    namadr_list_init(match_parent_style(VAR_MYNETWORKS),
4448
4817
                resp = 0;
4449
4818
                break;
4450
4819
            }
4451
 
            if (strcasecmp(args->argv[0], "relay_domains") == 0) {
 
4820
            if (strcasecmp(args->argv[0], VAR_RELAY_DOMAINS) == 0) {
 
4821
                /* NOT: UPDATE_STRING */
4452
4822
                domain_list_free(relay_domains);
4453
4823
                relay_domains =
4454
4824
                    domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
4456
4826
                resp = 0;
4457
4827
                break;
4458
4828
            }
 
4829
            if (strcasecmp(args->argv[0], VAR_PERM_MX_NETWORKS) == 0) {
 
4830
                UPDATE_STRING(var_perm_mx_networks, args->argv[1]);
 
4831
                domain_list_free(perm_mx_networks);
 
4832
                perm_mx_networks =
 
4833
                    namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
 
4834
                                     args->argv[1]);
 
4835
                resp = 0;
 
4836
                break;
 
4837
            }
4459
4838
            if (strcasecmp(args->argv[0], "restriction_class") == 0) {
4460
4839
                rest_class(args->argv[1]);
4461
4840
                resp = 0;
4500
4879
             * Show commands.
4501
4880
             */
4502
4881
        default:
 
4882
            if (strcasecmp(args->argv[0], "check_rewrite") == 0) {
 
4883
                smtpd_check_rewrite(&state);
 
4884
                resp = state.rewrite_context;
 
4885
                break;
 
4886
            }
4503
4887
            resp = "Commands...\n\
4504
4888
                client <name> <address> [<code>]\n\
4505
4889
                helo <hostname>\n\
4506
4890
                sender <address>\n\
4507
4891
                recipient <address>\n\
 
4892
                check_rewrite\n\
4508
4893
                msg_verbose <level>\n\
4509
4894
                client_restrictions <restrictions>\n\
4510
4895
                helo_restrictions <restrictions>\n\