X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Fexpand.c;h=739f5e8545a61d3a139ebadad2368b4b4854a61e;hb=9a799bc0748201e80ca3b4f7ffaaa588315626b7;hp=5432b98121a10d43299840b15b8dcc4462f6682e;hpb=9a26b6b229299c6106f5ab917220f39277b21713;p=exim.git diff --git a/src/src/expand.c b/src/src/expand.c index 5432b9812..739f5e854 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/expand.c,v 1.33 2005/06/20 13:58:22 ph10 Exp $ */ +/* $Cambridge: exim/src/src/expand.c,v 1.43 2005/09/28 10:46:48 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -195,6 +195,7 @@ static uschar *cond_table[] = { US"match", US"match_address", US"match_domain", + US"match_ip", US"match_local_part", US"or", US"pam", @@ -233,6 +234,7 @@ enum { ECOND_MATCH, ECOND_MATCH_ADDRESS, ECOND_MATCH_DOMAIN, + ECOND_MATCH_IP, ECOND_MATCH_LOCAL_PART, ECOND_OR, ECOND_PAM, @@ -397,6 +399,7 @@ static var_entry var_table[] = { { "message_body", vtype_msgbody, &message_body }, { "message_body_end", vtype_msgbody_end, &message_body_end }, { "message_body_size", vtype_int, &message_body_size }, + { "message_exim_id", vtype_stringptr, &message_id }, { "message_headers", vtype_msgheaders, NULL }, { "message_id", vtype_stringptr, &message_id }, { "message_linecount", vtype_int, &message_linecount }, @@ -479,7 +482,8 @@ static var_entry var_table[] = { { "sender_rcvhost", vtype_stringptr, &sender_rcvhost }, { "sender_verify_failure",vtype_stringptr, &sender_verify_failure }, { "smtp_active_hostname", vtype_stringptr, &smtp_active_hostname }, - { "smtp_command_argument", vtype_stringptr, &smtp_command_argument }, + { "smtp_command", vtype_stringptr, &smtp_cmd_buffer }, + { "smtp_command_argument", vtype_stringptr, &smtp_cmd_argument }, { "sn0", vtype_filter_int, &filter_sn[0] }, { "sn1", vtype_filter_int, &filter_sn[1] }, { "sn2", vtype_filter_int, &filter_sn[2] }, @@ -1424,7 +1428,10 @@ while (last > first) s = find_header(US"reply-to:", exists_only, newsize, FALSE, headers_charset); if (s == NULL || *s == 0) + { + *newsize = 0; /* For the *s==0 case */ s = find_header(US"from:", exists_only, newsize, FALSE, headers_charset); + } return (s == NULL)? US"" : s; /* A recipients list is available only during system message filtering, @@ -1801,6 +1808,7 @@ switch(cond_type) variables if it succeeds match_address: matches in an address list match_domain: matches in a domain list + match_ip: matches a host list that is restricted to IP addresses match_local_part: matches in a local part list crypteq: encrypts plaintext and compares against an encrypted text, using crypt(), crypt16(), MD5 or SHA-1 @@ -1809,6 +1817,7 @@ switch(cond_type) case ECOND_MATCH: case ECOND_MATCH_ADDRESS: case ECOND_MATCH_DOMAIN: + case ECOND_MATCH_IP: case ECOND_MATCH_LOCAL_PART: case ECOND_CRYPTEQ: @@ -1962,6 +1971,41 @@ switch(cond_type) MCL_DOMAIN + MCL_NOEXPAND, TRUE, NULL); goto MATCHED_SOMETHING; + case ECOND_MATCH_IP: /* Match IP address in a host list */ + if (sub[0][0] != 0 && string_is_ip_address(sub[0], NULL) <= 0) + { + expand_string_message = string_sprintf("\"%s\" is not an IP address", + sub[0]); + return NULL; + } + else + { + unsigned int *nullcache = NULL; + check_host_block cb; + + cb.host_name = US""; + cb.host_address = sub[0]; + + /* If the host address starts off ::ffff: it is an IPv6 address in + IPv4-compatible mode. Find the IPv4 part for checking against IPv4 + addresses. */ + + cb.host_ipv4 = (Ustrncmp(cb.host_address, "::ffff:", 7) == 0)? + cb.host_address + 7 : cb.host_address; + + rc = match_check_list( + &sub[1], /* the list */ + 0, /* separator character */ + &hostlist_anchor, /* anchor pointer */ + &nullcache, /* cache pointer */ + check_host, /* function for testing */ + &cb, /* argument for function */ + MCL_HOST, /* type of check */ + sub[0], /* text for debugging */ + NULL); /* where to pass back data */ + } + goto MATCHED_SOMETHING; + case ECOND_MATCH_LOCAL_PART: rc = match_isinlist(sub[0], &(sub[1]), 0, &localpartlist_anchor, NULL, MCL_LOCALPART + MCL_NOEXPAND, TRUE, NULL); @@ -2706,12 +2750,14 @@ uschar *s = *sptr; int x = eval_term(&s, decimal, error); if (*error == NULL) { - while (*s == '*' || *s == '/') + while (*s == '*' || *s == '/' || *s == '%') { int op = *s++; int y = eval_term(&s, decimal, error); if (*error != NULL) break; - if (op == '*') x *= y; else x /= y; + if (op == '*') x *= y; + else if (op == '/') x /= y; + else x %= y; } } *sptr = s; @@ -3086,7 +3132,7 @@ while (*s != 0) /* Check that a key was provided for those lookup types that need it, and was not supplied for those that use the query style. */ - if (!mac_islookup(stype, lookup_querystyle)) + if (!mac_islookup(stype, lookup_querystyle|lookup_absfilequery)) { if (key == NULL) { @@ -3106,7 +3152,9 @@ while (*s != 0) } /* Get the next string in brackets and expand it. It is the file name for - single-key+file lookups, and the whole query otherwise. */ + single-key+file lookups, and the whole query otherwise. In the case of + queries that also require a file name (e.g. sqlite), the file name comes + first. */ if (*s != '{') goto EXPAND_FAILED_CURLY; filename = expand_string_internal(s+1, TRUE, &s, skipping); @@ -3115,12 +3163,30 @@ while (*s != 0) while (isspace(*s)) s++; /* If this isn't a single-key+file lookup, re-arrange the variables - to be appropriate for the search_ functions. */ + to be appropriate for the search_ functions. For query-style lookups, + there is just a "key", and no file name. For the special query-style + + file types, the query (i.e. "key") starts with a file name. */ if (key == NULL) { + while (isspace(*filename)) filename++; key = filename; - filename = NULL; + + if (mac_islookup(stype, lookup_querystyle)) + { + filename = NULL; + } + else + { + if (*filename != '/') + { + expand_string_message = string_sprintf( + "absolute file name expected for \"%s\" lookup", name); + goto EXPAND_FAILED; + } + while (*key != 0 && !isspace(*key)) key++; + if (*key != 0) *key++ = 0; + } } /* If skipping, don't do the next bit - just lookup_value == NULL, as if @@ -3399,8 +3465,8 @@ while (*s != 0) uschar *now = prvs_daystamp(0); unsigned int inow = 0,iexpire = 1; - sscanf(CS now,"%u",&inow); - sscanf(CS daystamp,"%u",&iexpire); + (void)sscanf(CS now,"%u",&inow); + (void)sscanf(CS daystamp,"%u",&iexpire); /* When "iexpire" is < 7, a "flip" has occured. Adjust "inow" accordingly. */ @@ -3472,7 +3538,7 @@ while (*s != 0) } yield = cat_file(f, yield, &size, &ptr, sub_arg[1]); - fclose(f); + (void)fclose(f); continue; } @@ -3565,7 +3631,7 @@ while (*s != 0) alarm(timeout); yield = cat_file(f, yield, &size, &ptr, sub_arg[3]); alarm(0); - fclose(f); + (void)fclose(f); /* After a timeout, we restore the pointer in the result, that is, make sure we add nothing from the socket. */ @@ -3662,7 +3728,7 @@ while (*s != 0) /* Nothing is written to the standard input. */ - close(fd_in); + (void)close(fd_in); /* Wait for the process to finish, applying the timeout, and inspect its return code for serious disasters. Simple non-zero returns are passed on. @@ -3693,7 +3759,7 @@ while (*s != 0) f = fdopen(fd_out, "rb"); lookup_value = NULL; lookup_value = cat_file(f, lookup_value, &lsize, &lptr, NULL); - fclose(f); + (void)fclose(f); } /* Process the yes/no strings; $value may be useful in both cases */ @@ -4292,6 +4358,8 @@ while (*s != 0) continue; } + /* Note that for Darwin and Cygwin, BASE_62 actually has the value 36 */ + case EOP_BASE62D: { uschar buf[16]; @@ -4303,10 +4371,11 @@ while (*s != 0) if (t == NULL) { expand_string_message = string_sprintf("argument for base62d " - "operator is \"%s\", which is not a base 62 number", sub); + "operator is \"%s\", which is not a base %d number", sub, + BASE_62); goto EXPAND_FAILED; } - n = n * 62 + (t - base62_chars); + n = n * BASE_62 + (t - base62_chars); } (void)sprintf(CS buf, "%ld", n); yield = string_cat(yield, &size, &ptr, buf, Ustrlen(buf)); @@ -4786,6 +4855,12 @@ while (*s != 0) mode_t mode; struct stat st; + if ((expand_forbid & RDO_EXISTS) != 0) + { + expand_string_message = US"Use of the stat() expansion is not permitted"; + goto EXPAND_FAILED; + } + if (stat(CS sub, &st) < 0) { expand_string_message = string_sprintf("stat(%s) failed: %s",