X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Ftransports%2Fautoreply.c;h=90a5aa4be6f3aa58d6d082247e9ea4a4bda06f48;hb=46d2a5e6f6e7709d172903b13945d23fc0a2c888;hp=68f8d1f583da8d878bd689cbc6f2700ceb9ce850;hpb=1d717e1c110562fd6bf28478c79f180cafeba776;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/transports/autoreply.c b/src/src/transports/autoreply.c index 68f8d1f58..90a5aa4be 100644 --- a/src/src/transports/autoreply.c +++ b/src/src/transports/autoreply.c @@ -16,44 +16,27 @@ order (note that "_" comes before the lower case letters). Those starting with "*" are not settable by the user but are used by the option-reading software for alternative value types. Some options are publicly visible and so are stored in the driver instance block. These are flagged with opt_public. */ +#define LOFF(field) OPT_OFF(autoreply_transport_options_block, field) optionlist autoreply_transport_options[] = { - { "bcc", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, bcc) }, - { "cc", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, cc) }, - { "file", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, file) }, - { "file_expand", opt_bool, - (void *)offsetof(autoreply_transport_options_block, file_expand) }, - { "file_optional", opt_bool, - (void *)offsetof(autoreply_transport_options_block, file_optional) }, - { "from", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, from) }, - { "headers", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, headers) }, - { "log", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, logfile) }, - { "mode", opt_octint, - (void *)offsetof(autoreply_transport_options_block, mode) }, - { "never_mail", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, never_mail) }, - { "once", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, oncelog) }, - { "once_file_size", opt_int, - (void *)offsetof(autoreply_transport_options_block, once_file_size) }, - { "once_repeat", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, once_repeat) }, - { "reply_to", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, reply_to) }, - { "return_message", opt_bool, - (void *)offsetof(autoreply_transport_options_block, return_message) }, - { "subject", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, subject) }, - { "text", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, text) }, - { "to", opt_stringptr, - (void *)offsetof(autoreply_transport_options_block, to) }, + { "bcc", opt_stringptr, LOFF(bcc) }, + { "cc", opt_stringptr, LOFF(cc) }, + { "file", opt_stringptr, LOFF(file) }, + { "file_expand", opt_bool, LOFF(file_expand) }, + { "file_optional", opt_bool, LOFF(file_optional) }, + { "from", opt_stringptr, LOFF(from) }, + { "headers", opt_stringptr, LOFF(headers) }, + { "log", opt_stringptr, LOFF(logfile) }, + { "mode", opt_octint, LOFF(mode) }, + { "never_mail", opt_stringptr, LOFF(never_mail) }, + { "once", opt_stringptr, LOFF(oncelog) }, + { "once_file_size", opt_int, LOFF(once_file_size) }, + { "once_repeat", opt_stringptr, LOFF(once_repeat) }, + { "reply_to", opt_stringptr, LOFF(reply_to) }, + { "return_message", opt_bool, LOFF(return_message) }, + { "subject", opt_stringptr, LOFF(subject) }, + { "text", opt_stringptr, LOFF(text) }, + { "to", opt_stringptr, LOFF(to) }, }; /* Size of the options list. An extern variable has to be used so that its @@ -156,7 +139,7 @@ checkexpand(uschar *s, address_item *addr, uschar *name, int type) { uschar *ss = expand_string(s); -if (ss == NULL) +if (!ss) { addr->transport_return = FAIL; addr->message = string_sprintf("Expansion of \"%s\" failed in %s transport: " @@ -219,7 +202,7 @@ while (*s != 0) /* If there is some kind of syntax error, just give up on this header line. */ - if (next == NULL) break; + if (!next) break; /* See if the address is on the never_mail list */ @@ -307,7 +290,7 @@ from that block. It has typically been set up by a mail filter processing router. Otherwise, the data must be supplied by this transport, and it has to be expanded here. */ -if (addr->reply != NULL) +if (addr->reply) { DEBUG(D_transport) debug_printf("taking data from address\n"); from = addr->reply->from; @@ -418,18 +401,27 @@ recipient, the effect might not be quite as envisaged. If once_file_size is set, instead of a dbm file, we use a regular file containing a circular buffer recipient cache. */ -if (oncelog && *oncelog != 0 && to) +if (oncelog && *oncelog && to) { time_t then = 0; + if (is_tainted(oncelog)) + { + addr->transport_return = DEFER; + addr->basic_errno = EACCES; + addr->message = string_sprintf("Tainted '%s' (once file for %s transport)" + " not permitted", oncelog, tblock->name); + goto END_OFF; + } + /* Handle fixed-size cache file. */ if (ob->once_file_size > 0) { uschar * nextp; struct stat statbuf; - cache_fd = Uopen(oncelog, O_CREAT|O_RDWR, ob->mode); + cache_fd = Uopen(oncelog, O_CREAT|O_RDWR, ob->mode); if (cache_fd < 0 || fstat(cache_fd, &statbuf) != 0) { addr->transport_return = DEFER; @@ -523,6 +515,15 @@ if (oncelog && *oncelog != 0 && to) if (then != 0 && (once_repeat_sec <= 0 || now - then < once_repeat_sec)) { int log_fd; + if (is_tainted(logfile)) + { + addr->transport_return = DEFER; + addr->basic_errno = EACCES; + addr->message = string_sprintf("Tainted '%s' (logfile for %s transport)" + " not permitted", logfile, tblock->name); + goto END_OFF; + } + DEBUG(D_transport) debug_printf("message previously sent to %s%s\n", to, (once_repeat_sec > 0)? " and repeat time not reached" : ""); log_fd = logfile ? Uopen(logfile, O_WRONLY|O_APPEND|O_CREAT, ob->mode) : -1; @@ -544,24 +545,32 @@ if (oncelog && *oncelog != 0 && to) } /* We are going to send a message. Ensure any requested file is available. */ - -if (file && !(ff = Ufopen(file, "rb")) && !ob->file_optional) +if (file) { - addr->transport_return = DEFER; - addr->basic_errno = errno; - addr->message = string_sprintf("Failed to open file %s when sending " - "message from %s transport: %s", file, tblock->name, strerror(errno)); - return FALSE; + if (is_tainted(file)) + { + addr->transport_return = DEFER; + addr->basic_errno = EACCES; + addr->message = string_sprintf("Tainted '%s' (file for %s transport)" + " not permitted", file, tblock->name); + return FALSE; + } + if (!(ff = Ufopen(file, "rb")) && !ob->file_optional) + { + addr->transport_return = DEFER; + addr->basic_errno = errno; + addr->message = string_sprintf("Failed to open file %s when sending " + "message from %s transport: %s", file, tblock->name, strerror(errno)); + return FALSE; + } } /* Make a subprocess to send the message */ -pid = child_open_exim(&fd); - -/* Creation of child failed; defer this delivery. */ - -if (pid < 0) +if ((pid = child_open_exim(&fd, US"autoreply")) < 0) { + /* Creation of child failed; defer this delivery. */ + addr->transport_return = DEFER; addr->basic_errno = errno; addr->message = string_sprintf("Failed to create child process to send "