X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/ee8b809061baea861fc87c41bcb72a62d76b0047..a713f76692228165883d92875fbad3bfb89c001e:/src/src/verify.c diff --git a/src/src/verify.c b/src/src/verify.c index 236a87c52..fc8cd84ea 100644 --- a/src/src/verify.c +++ b/src/src/verify.c @@ -98,7 +98,7 @@ if (type[0] == 'd' && cache_record->result != ccache_reject) { if (length == sizeof(dbdata_callout_cache_obs)) { - dbdata_callout_cache *new = store_get(sizeof(dbdata_callout_cache)); + dbdata_callout_cache *new = store_get(sizeof(dbdata_callout_cache), FALSE); memcpy(new, cache_record, length); new->postmaster_stamp = new->random_stamp = new->time_stamp; cache_record = new; @@ -140,7 +140,7 @@ if (options & vopt_callout_no_cache) { HDEBUG(D_verify) debug_printf("callout cache: disabled by no_cache\n"); } -else if (!(dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE))) +else if (!(dbm_file = dbfn_open(US"callout", O_RDWR, &dbblock, FALSE, TRUE))) { HDEBUG(D_verify) debug_printf("callout cache: not available\n"); } @@ -313,7 +313,7 @@ implying some kind of I/O error. We don't want to write the cache in that case. Otherwise the value is ccache_accept, ccache_reject, or ccache_reject_mfnull. */ if (dom_rec->result != ccache_unknown) - if (!(dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE))) + if (!(dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE, TRUE))) { HDEBUG(D_verify) debug_printf("callout cache: not available\n"); } @@ -335,7 +335,7 @@ is disabled. */ if (done && addr_rec->result != ccache_unknown) { if (!dbm_file) - dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE); + dbm_file = dbfn_open(US"callout", O_RDWR|O_CREAT, &dbblock, FALSE, TRUE); if (!dbm_file) { HDEBUG(D_verify) debug_printf("no callout cache available\n"); @@ -370,10 +370,9 @@ cutthrough_multi(address_item * addr, host_item * host_list, transport_feedback * tf, int * yield) { BOOL done = FALSE; -host_item * host; if (addr->transport == cutthrough.addr.transport) - for (host = host_list; host; host = host->next) + for (host_item * host = host_list; host; host = host->next) if (Ustrcmp(host->address, cutthrough.host.address) == 0) { int host_af; @@ -421,7 +420,7 @@ if (addr->transport == cutthrough.addr.transport) if (done) { - address_item * na = store_get(sizeof(address_item)); + address_item * na = store_get(sizeof(address_item), FALSE); *na = cutthrough.addr; cutthrough.addr = *addr; cutthrough.addr.host_used = &cutthrough.host; @@ -575,7 +574,6 @@ else { smtp_transport_options_block *ob = (smtp_transport_options_block *)addr->transport->options_block; - host_item * host; /* The information wasn't available in the cache, so we have to do a real callout and save the result in the cache for next time, unless no_cache is set, @@ -623,7 +621,7 @@ coding means skipping this whole loop and doing the append separately. */ /* If we did not use a cached connection, make connections to the hosts and do real callouts. The list of hosts is passed in as an argument. */ - for (host = host_list; host && !done; host = host->next) + for (host_item * host = host_list; host && !done; host = host->next) { int host_af; int port = 25; @@ -689,7 +687,7 @@ tls_retry_connection: if permitted */ yield = smtp_setup_conn(&sx, FALSE); -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS if ( yield == DEFER && addr->basic_errno == ERRNO_TLSFAILURE && ob->tls_tempfail_tryclear @@ -821,7 +819,7 @@ tls_retry_connection: HDEBUG(D_acl|D_v) debug_printf_indent("problem after random/rset/mfrom; reopen conn\n"); random_local_part = NULL; -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS tls_close(sx.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT); #endif HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP(close)>>\n"); @@ -978,8 +976,7 @@ no_conn: { extern int acl_where; /* src/acl.c */ errno = 0; - addr->message = string_sprintf( - "response to \"EHLO\" did not include SMTPUTF8"); + addr->message = US"response to \"EHLO\" did not include SMTPUTF8"; addr->user_message = acl_where == ACL_WHERE_RCPT ? US"533 no support for internationalised mailbox name" : US"550 mailbox unavailable"; @@ -987,13 +984,6 @@ no_conn: done = TRUE; } break; -#endif -#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_REQUIRETLS) - case ERRNO_REQUIRETLS: - addr->user_message = US"530 5.7.4 REQUIRETLS support required"; - yield = FAIL; - done = TRUE; - break; #endif case ECONNREFUSED: sx.send_quit = FALSE; @@ -1011,6 +1001,26 @@ no_conn: string_sprintf("response to \"%s\" was: %s", big_buffer, string_printing(sx.buffer)); + /* RFC 5321 section 4.2: the text portion of the response may have only + HT, SP, Printable US-ASCII. Deal with awkward chars by cutting the + received message off before passing it onward. Newlines are ok; they + just become a multiline response (but wrapped in the error code we + produce). */ + + for (uschar * s = sx.buffer; + *s && s < sx.buffer + sizeof(sx.buffer); + s++) + { + uschar c = *s; + if (c != '\t' && c != '\n' && (c < ' ' || c > '~')) + { + if (s - sx.buffer < sizeof(sx.buffer) - 12) + memcpy(s, "(truncated)", 12); + else + *s = '\0'; + break; + } + } addr->user_message = options & vopt_is_recipient ? string_sprintf("Callout verification failed:\n%s", sx.buffer) : string_sprintf("Called: %s\nSent: %s\nResponse: %s", @@ -1068,8 +1078,6 @@ no_conn: && !sx.lmtp ) { - address_item * parent, * caddr; - HDEBUG(D_acl|D_v) debug_printf_indent("holding verify callout open for %s\n", cutthrough.delivery ? "cutthrough delivery" : "potential further verifies and delivery"); @@ -1097,10 +1105,10 @@ no_conn: cutthrough.addr = *addr; cutthrough.addr.next = NULL; cutthrough.addr.host_used = &cutthrough.host; - for (caddr = &cutthrough.addr, parent = addr->parent; + for (address_item * caddr = &cutthrough.addr, * parent = addr->parent; parent; caddr = caddr->parent, parent = parent->parent) - *(caddr->parent = store_get(sizeof(address_item))) = *parent; + *(caddr->parent = store_get(sizeof(address_item), FALSE)) = *parent; ctctx.outblock.buffer = ctbuffer; ctctx.outblock.buffersize = sizeof(ctbuffer); @@ -1114,16 +1122,13 @@ no_conn: if (options & vopt_callout_recipsender) cancel_cutthrough_connection(TRUE, US"not usable for cutthrough"); if (sx.send_quit) - { - (void) smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n"); - - /* Wait a short time for response, and discard it */ - smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', 1); - } + if (smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n") != -1) + /* Wait a short time for response, and discard it */ + smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', 1); if (sx.cctx.sock >= 0) { -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS if (sx.cctx.tls_ctx) { tls_close(sx.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT); @@ -1187,7 +1192,7 @@ if (!done) /* Come here from within the cache-reading code on fast-track exit. */ END_CALLOUT: -tls_modify_variables(&tls_in); +tls_modify_variables(&tls_in); /* return variables to inbound values */ return yield; } @@ -1229,7 +1234,7 @@ if(cutthrough.cctx.sock < 0) return TRUE; if( -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS cutthrough.is_tls ? tls_write(cutthrough.cctx.tls_ctx, ctctx.outblock.buffer, n, FALSE) : @@ -1430,7 +1435,7 @@ if(fd >= 0) /* Wait a short time for response, and discard it */ cutthrough_response(&tmp_ctx, '2', NULL, 1); -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS if (cutthrough.is_tls) { tls_close(cutthrough.cctx.tls_ctx, TLS_SHUTDOWN_NOWAIT); @@ -1476,7 +1481,6 @@ uschar * cutthrough_finaldot(void) { uschar res; -address_item * addr; HDEBUG(D_transport|D_acl|D_v) debug_printf_indent(" SMTP>> .\n"); /* Assume data finshed with new-line */ @@ -1488,7 +1492,7 @@ if( !cutthrough_puts(US".", 1) res = cutthrough_response(&cutthrough.cctx, '2', &cutthrough.addr.message, CUTTHROUGH_DATA_TIMEOUT); -for (addr = &cutthrough.addr; addr; addr = addr->next) +for (address_item * addr = &cutthrough.addr; addr; addr = addr->next) { addr->message = cutthrough.addr.message; switch(res) @@ -1544,6 +1548,8 @@ if (addr != vaddr) vaddr->basic_errno = addr->basic_errno; vaddr->more_errno = addr->more_errno; vaddr->prop.address_data = addr->prop.address_data; + vaddr->prop.variables = NULL; + tree_dup((tree_node **)&vaddr->prop.variables, addr->prop.variables); copyflag(vaddr, addr, af_pass_message); } return yield; @@ -1710,8 +1716,8 @@ if (global_rewrite_rules) global_rewrite_rules, rewrite_existflags); if (address != old) { - for (i = 0; i < (MAX_NAMED_LIST * 2)/32; i++) vaddr->localpart_cache[i] = 0; - for (i = 0; i < (MAX_NAMED_LIST * 2)/32; i++) vaddr->domain_cache[i] = 0; + for (int i = 0; i < (MAX_NAMED_LIST * 2)/32; i++) vaddr->localpart_cache[i] = 0; + for (int i = 0; i < (MAX_NAMED_LIST * 2)/32; i++) vaddr->domain_cache[i] = 0; if (fp && !expn) fprintf(fp, "Address rewritten as: %s\n", address); } } @@ -1889,7 +1895,6 @@ while (addr_new) else { int flags; - host_item *host, *nexthost; host_build_hostlist(&host_list, s, tf.hosts_randomize); /* Just ignore failures to find a host address. If we don't manage @@ -1902,7 +1907,7 @@ while (addr_new) if (tf.qualify_single) flags |= HOST_FIND_QUALIFY_SINGLE; if (tf.search_parents) flags |= HOST_FIND_SEARCH_PARENTS; - for (host = host_list; host; host = nexthost) + for (host_item * host = host_list, * nexthost; host; host = nexthost) { nexthost = host->next; if (tf.gethostbyname || @@ -1940,12 +1945,12 @@ while (addr_new) } else { -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS deliver_set_expansions(addr); #endif rc = do_callout(addr, host_list, &tf, callout, callout_overall, callout_connect, options, se_mailfrom, pm_mailfrom); -#ifdef SUPPORT_TLS +#ifndef DISABLE_TLS deliver_set_expansions(NULL); #endif } @@ -2105,6 +2110,8 @@ while (addr_new) of $address_data to be that of the child */ vaddr->prop.address_data = addr->prop.address_data; + vaddr->prop.variables = NULL; + tree_dup((tree_node **)&vaddr->prop.variables, addr->prop.variables); /* If stopped because more than one new address, cannot cutthrough */ @@ -2136,7 +2143,6 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++) while (addr_list) { address_item *addr = addr_list; - address_item *p = addr->parent; transport_instance * tp = addr->transport; addr_list = addr->next; @@ -2159,7 +2165,7 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++) /* Now show its parents */ - for (p = addr->parent; p; p = p->parent) + for (address_item * p = addr->parent; p; p = p->parent) fprintf(fp, "\n <-- %s", p->address); fprintf(fp, "\n "); @@ -2173,17 +2179,16 @@ for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++) if (addr->host_list && tp && !tp->overrides_hosts) { - host_item *h; int maxlen = 0; int maxaddlen = 0; - for (h = addr->host_list; h; h = h->next) + for (host_item * h = addr->host_list; h; h = h->next) { /* get max lengths of host names, addrs */ int len = Ustrlen(h->name); if (len > maxlen) maxlen = len; len = h->address ? Ustrlen(h->address) : 7; if (len > maxaddlen) maxaddlen = len; } - for (h = addr->host_list; h; h = h->next) + for (host_item * h = addr->host_list; h; h = h->next) { fprintf(fp, " host %-*s ", maxlen, h->name); @@ -2208,7 +2213,7 @@ the -bv or -bt case). */ out: verify_mode = NULL; -tls_modify_variables(&tls_in); +tls_modify_variables(&tls_in); /* return variables to inbound values */ return yield; } @@ -2233,11 +2238,10 @@ Returns: OK int verify_check_headers(uschar **msgptr) { -header_line *h; uschar *colon, *s; int yield = OK; -for (h = header_list; h && yield == OK; h = h->next) +for (header_line * h = header_list; h && yield == OK; h = h->next) { if (h->type != htype_from && h->type != htype_reply_to && @@ -2356,17 +2360,16 @@ Returns: OK int verify_check_header_names_ascii(uschar **msgptr) { -header_line *h; -uschar *colon, *s; +uschar *colon; -for (h = header_list; h; h = h->next) +for (header_line * h = header_list; h; h = h->next) { colon = Ustrchr(h->text, ':'); - for(s = h->text; s < colon; s++) + for(uschar * s = h->text; s < colon; s++) if ((*s < 33) || (*s > 126)) { *msgptr = string_sprintf("Invalid character in header \"%.*s\" found", - colon - h->text, h->text); + (int)(colon - h->text), h->text); return FAIL; } } @@ -2386,22 +2389,20 @@ The original proposed patch did the former, but I have chosen to do the latter, because (a) it requires no memory and (b) will use fewer resources when there are many addresses in To: and/or Cc: and only one or two envelope recipients. -Arguments: none +Arguments: case_sensitive true if case sensitive matching should be used Returns: OK if there are no blind recipients FAIL if there is at least one blind recipient */ int -verify_check_notblind(void) +verify_check_notblind(BOOL case_sensitive) { -int i; -for (i = 0; i < recipients_count; i++) +for (int i = 0; i < recipients_count; i++) { - header_line *h; BOOL found = FALSE; uschar *address = recipients_list[i].address; - for (h = header_list; !found && h != NULL; h = h->next) + for (header_line * h = header_list; !found && h; h = h->next) { uschar *colon, *s; @@ -2416,10 +2417,10 @@ for (i = 0; i < recipients_count; i++) f.parse_allow_group = TRUE; - while (*s != 0) + while (*s) { - uschar *ss = parse_find_address_end(s, FALSE); - uschar *recipient,*errmess; + uschar * ss = parse_find_address_end(s, FALSE); + uschar * recipient, * errmess; int terminator = *ss; int start, end, domain; @@ -2431,21 +2432,22 @@ for (i = 0; i < recipients_count; i++) *ss = terminator; /* If we found a valid recipient that has a domain, compare it with the - envelope recipient. Local parts are compared case-sensitively, domains - case-insensitively. By comparing from the start with length "domain", we - include the "@" at the end, which ensures that we are comparing the whole - local part of each address. */ - - if (recipient != NULL && domain != 0) - { - found = Ustrncmp(recipient, address, domain) == 0 && - strcmpic(recipient + domain, address + domain) == 0; - if (found) break; - } + envelope recipient. Local parts are compared with case-sensitivity + according to the routine arg, domains case-insensitively. + By comparing from the start with length "domain", we include the "@" at + the end, which ensures that we are comparing the whole local part of each + address. */ + + if (recipient && domain != 0) + if ((found = (case_sensitive + ? Ustrncmp(recipient, address, domain) == 0 + : strncmpic(recipient, address, domain) == 0) + && strcmpic(recipient + domain, address + domain) == 0)) + break; /* Advance to the next address */ - s = ss + (terminator? 1:0); + s = ss + (terminator ? 1:0); while (isspace(*s)) s++; } /* Next address */ @@ -2478,10 +2480,9 @@ Returns: pointer to an address item, or NULL address_item * verify_checked_sender(uschar *sender) { -address_item *addr; -for (addr = sender_verified_list; addr != NULL; addr = addr->next) - if (Ustrcmp(sender, addr->address) == 0) break; -return addr; +for (address_item * addr = sender_verified_list; addr; addr = addr->next) + if (Ustrcmp(sender, addr->address) == 0) return addr; +return NULL; } @@ -2535,12 +2536,9 @@ verify_check_header_address(uschar **user_msgptr, uschar **log_msgptr, static int header_types[] = { htype_sender, htype_reply_to, htype_from }; BOOL done = FALSE; int yield = FAIL; -int i; -for (i = 0; i < 3 && !done; i++) - { - header_line *h; - for (h = header_list; h != NULL && !done; h = h->next) +for (int i = 0; i < 3 && !done; i++) + for (header_line * h = header_list; h != NULL && !done; h = h->next) { int terminator, new_ok; uschar *s, *ss, *endname; @@ -2672,7 +2670,7 @@ for (i = 0; i < 3 && !done; i++) f.parse_allow_group = FALSE; f.parse_found_group = FALSE; } /* Next header, unless done */ - } /* Next header type unless done */ + /* Next header type unless done */ if (yield == FAIL && *log_msgptr == NULL) *log_msgptr = US"there is no valid sender in any header line"; @@ -2770,7 +2768,7 @@ for (;;) int size = sizeof(buffer) - (p - buffer); if (size <= 0) goto END_OFF; /* Buffer filled without seeing \n. */ - count = ip_recv(&ident_conn_ctx, p, size, rfc1413_query_timeout); + count = ip_recv(&ident_conn_ctx, p, size, time(NULL) + rfc1413_query_timeout); if (count <= 0) goto END_OFF; /* Read error or EOF */ /* Scan what we just read, to see if we have reached the terminating \r\n. Be @@ -2912,8 +2910,7 @@ if (*ss == '@') } else if (Ustrcmp(ss, "@[]") == 0) { - ip_address_item *ip; - for (ip = host_find_interfaces(); ip != NULL; ip = ip->next) + for (ip_address_item * ip = host_find_interfaces(); ip; ip = ip->next) if (Ustrcmp(ip->address, cb->host_address) == 0) return OK; return FAIL; } @@ -2936,7 +2933,7 @@ only by digits and dots (a slash at the start indicates a file name and of course slashes may be present in lookups, but not preceded only by digits and dots). */ -for (t = ss; isdigit(*t) || *t == '.'; t++); +for (t = ss; isdigit(*t) || *t == '.'; ) t++; if (*t == 0 || (*t == '/' && t != ss)) { *error = US"malformed IPv4 address or address mask"; @@ -2970,7 +2967,8 @@ if (Ustrncmp(ss, "net", 3) == 0 && semicolon != NULL) if (mlen == 0 && t == ss+3) mlen = -1; /* No mask supplied */ iplookup = (*t++ == '-'); } -else t = ss; +else + t = ss; /* Do the IP address lookup if that is indeed what we have */ @@ -3072,11 +3070,8 @@ if (*t == 0) rc = host_find_byname(&h, NULL, HOST_FIND_QUALIFY_SINGLE, NULL, FALSE); if (rc == HOST_FOUND || rc == HOST_FOUND_LOCAL) { - host_item *hh; - for (hh = &h; hh != NULL; hh = hh->next) - { + for (host_item * hh = &h; hh; hh = hh->next) if (host_is_in_net(hh->address, cb->host_address, 0)) return OK; - } return FAIL; } if (rc == HOST_FIND_AGAIN) return DEFER; @@ -3270,7 +3265,7 @@ int verify_check_host(uschar **listptr) { return verify_check_this_host(CUSS listptr, sender_host_cache, NULL, - (sender_host_address == NULL)? US"" : sender_host_address, NULL); + sender_host_address ? sender_host_address : US"", NULL); } @@ -3305,9 +3300,8 @@ always 1. */ if (host_aton(address, bin) == 1) { - int i; int x = bin[0]; - for (i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { sprintf(CS bptr, "%d.", x & 255); while (*bptr) bptr++; @@ -3321,19 +3315,16 @@ unknown. This is just a guess. */ #if HAVE_IPV6 else - { - int i, j; - for (j = 3; j >= 0; j--) + for (int j = 3; j >= 0; j--) { int x = bin[j]; - for (i = 0; i < 8; i++) + for (int i = 0; i < 8; i++) { sprintf(CS bptr, "%x.", x & 15); while (*bptr) bptr++; x >>= 4; } } - } #endif /* Remove trailing period -- this is needed so that both arbitrary @@ -3380,7 +3371,7 @@ one_check_dnsbl(uschar *domain, uschar *domain_txt, uschar *keydomain, uschar *prepend, uschar *iplist, BOOL bitmask, int match_type, int defer_return) { -dns_answer dnsa; +dns_answer * dnsa = store_get_dns_answer(); dns_scan dnss; tree_node *t; dnsbl_cache_block *cb; @@ -3405,7 +3396,7 @@ if ( (t = tree_search(dnsbl_cache, query)) /* Previous lookup was cached */ { - HDEBUG(D_dnsbl) debug_printf("using result of previous DNS lookup\n"); + HDEBUG(D_dnsbl) debug_printf("dnslists: using result of previous lookup\n"); } /* If not cached from a previous lookup, we must do a DNS lookup, and @@ -3413,7 +3404,7 @@ cache the result in permanent memory. */ else { - uint ttl = 3600; + uint ttl = 3600; /* max TTL for positive cache entries */ store_pool = POOL_PERM; @@ -3424,16 +3415,16 @@ else else { /* Set up a tree entry to cache the lookup */ - t = store_get(sizeof(tree_node) + Ustrlen(query)); + t = store_get(sizeof(tree_node) + Ustrlen(query), is_tainted(query)); Ustrcpy(t->name, query); - t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block)); + t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block), FALSE); (void)tree_insertnode(&dnsbl_cache, t); } /* Do the DNS lookup . */ HDEBUG(D_dnsbl) debug_printf("new DNS lookup for %s\n", query); - cb->rc = dns_basic_lookup(&dnsa, query, T_A); + cb->rc = dns_basic_lookup(dnsa, query, T_A); cb->text_set = FALSE; cb->text = NULL; cb->rhs = NULL; @@ -3448,36 +3439,58 @@ else addresses generated in that way as well. Mark the cache entry with the "now" plus the minimum of the address TTLs, - or some suitably far-future time if none were found. */ + or the RFC 2308 negative-cache value from the SOA if none were found. */ - if (cb->rc == DNS_SUCCEED) + switch (cb->rc) { - dns_record *rr; - dns_address **addrp = &(cb->rhs); - for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); - rr; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) - if (rr->type == T_A) - { - dns_address *da = dns_address_from_rr(&dnsa, rr); - if (da) - { - *addrp = da; - while (da->next) da = da->next; - addrp = &da->next; + case DNS_SUCCEED: + { + dns_address ** addrp = &cb->rhs; + dns_address * da; + for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) + if (rr->type == T_A && (da = dns_address_from_rr(dnsa, rr))) + { + *addrp = da; + while (da->next) da = da->next; + addrp = &da->next; if (ttl > rr->ttl) ttl = rr->ttl; - } - } + } - /* If we didn't find any A records, change the return code. This can - happen when there is a CNAME record but there are no A records for what - it points to. */ + if (cb->rhs) + { + cb->expiry = time(NULL) + ttl; + break; + } - if (!cb->rhs) cb->rc = DNS_NODATA; + /* If we didn't find any A records, change the return code. This can + happen when there is a CNAME record but there are no A records for what + it points to. */ + + cb->rc = DNS_NODATA; + } + /*FALLTHROUGH*/ + + case DNS_NOMATCH: + case DNS_NODATA: + { + /* Although there already is a neg-cache layer maintained by + dns_basic_lookup(), we have a dnslist cache entry allocated and + tree-inserted. So we may as well use it. */ + + time_t soa_negttl = dns_expire_from_soa(dnsa, T_A); + cb->expiry = soa_negttl ? soa_negttl : time(NULL) + ttl; + break; + } + + default: + cb->expiry = time(NULL) + ttl; + break; } - cb->expiry = time(NULL)+ttl; store_pool = old_pool; + HDEBUG(D_dnsbl) debug_printf("dnslists: wrote cache entry, ttl=%d\n", + (int)(cb->expiry - time(NULL))); } /* We now have the result of the DNS lookup, either newly done, or cached @@ -3488,7 +3501,7 @@ list (introduced by "&"), or a negative bitmask list (introduced by "!&").*/ if (cb->rc == DNS_SUCCEED) { - dns_address *da = NULL; + dns_address * da = NULL; uschar *addlist = cb->rhs->address; /* For A and AAAA records, there may be multiple addresses from multiple @@ -3607,22 +3620,18 @@ if (cb->rc == DNS_SUCCEED) if (!cb->text_set) { cb->text_set = TRUE; - if (dns_basic_lookup(&dnsa, query, T_TXT) == DNS_SUCCEED) - { - dns_record *rr; - for (rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); - rr; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) - if (rr->type == T_TXT) break; - if (rr) - { - int len = (rr->data)[0]; - if (len > 511) len = 127; - store_pool = POOL_PERM; - cb->text = string_sprintf("%.*s", len, CUS (rr->data+1)); - store_pool = old_pool; - } - } + if (dns_basic_lookup(dnsa, query, T_TXT) == DNS_SUCCEED) + for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) + if (rr->type == T_TXT) + { + int len = (rr->data)[0]; + if (len > 511) len = 127; + store_pool = POOL_PERM; + cb->text = string_sprintf("%.*s", len, CUS (rr->data+1)); + store_pool = old_pool; + break; + } } dnslist_value = addlist; @@ -3716,7 +3725,6 @@ int sep = 0; int defer_return = FAIL; const uschar *list = *listptr; uschar *domain; -uschar *s; uschar buffer[1024]; uschar revadd[128]; /* Long enough for IPv6 address */ @@ -3730,7 +3738,7 @@ dns_init(FALSE, FALSE, FALSE); /*XXX dnssec? */ /* Loop through all the domains supplied, until something matches */ -while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL) +while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))) { int rc; BOOL bitmask = FALSE; @@ -3740,7 +3748,7 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL uschar *iplist; uschar *key; - HDEBUG(D_dnsbl) debug_printf("DNS list check: %s\n", domain); + HDEBUG(D_dnsbl) debug_printf("dnslists check: %s\n", domain); /* Deal with special values that change the behaviour on defer */ @@ -3794,8 +3802,7 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL set domain_txt == domain. */ domain_txt = domain; - comma = Ustrchr(domain, ','); - if (comma != NULL) + if ((comma = Ustrchr(domain, ','))) { *comma++ = 0; domain = comma; @@ -3807,32 +3814,28 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL actually causing an error here, because that would no doubt hold up incoming mail. Instead, I'll just log it. */ - for (s = domain; *s != 0; s++) - { + for (uschar * s = domain; *s; s++) if (!isalnum(*s) && *s != '-' && *s != '.' && *s != '_') { log_write(0, LOG_MAIN, "dnslists domain \"%s\" contains " "strange characters - is this right?", domain); break; } - } /* Check the alternate domain if present */ - if (domain_txt != domain) for (s = domain_txt; *s != 0; s++) - { + if (domain_txt != domain) for (uschar * s = domain_txt; *s; s++) if (!isalnum(*s) && *s != '-' && *s != '.' && *s != '_') { log_write(0, LOG_MAIN, "dnslists domain \"%s\" contains " "strange characters - is this right?", domain_txt); break; } - } /* If there is no key string, construct the query by adding the domain name onto the inverted host address, and perform a single DNS lookup. */ - if (key == NULL) + if (!key) { if (where == ACL_WHERE_NOTSMTP_START || where == ACL_WHERE_NOTSMTP) { @@ -3841,7 +3844,7 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL acl_wherenames[where]); return ERROR; } - if (sender_host_address == NULL) return FAIL; /* can never match */ + if (!sender_host_address) return FAIL; /* can never match */ if (revadd[0] == 0) invert_address(revadd, sender_host_address); rc = one_check_dnsbl(domain, domain_txt, sender_host_address, revadd, iplist, bitmask, match_type, defer_return); @@ -3863,11 +3866,9 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL int keysep = 0; BOOL defer = FALSE; uschar *keydomain; - uschar keybuffer[256]; uschar keyrevadd[128]; - while ((keydomain = string_nextinlist(CUSS &key, &keysep, keybuffer, - sizeof(keybuffer))) != NULL) + while ((keydomain = string_nextinlist(CUSS &key, &keysep, NULL, 0))) { uschar *prepend = keydomain; @@ -3879,7 +3880,6 @@ while ((domain = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL rc = one_check_dnsbl(domain, domain_txt, keydomain, prepend, iplist, bitmask, match_type, defer_return); - if (rc == OK) { dnslist_domain = string_copy(domain_txt);