X-Git-Url: https://vcs.fsf.org/?p=exim.git;a=blobdiff_plain;f=src%2Fsrc%2Frda.c;h=ee7c1fe96376fcc853e5c64bd270ae7418e8f238;hp=2af9fbfaadc23e9384be1a7e64354df0355c9f25;hb=8768d5483a5894400ae1f70cda1beb44ed9b087c;hpb=efd9a4221230676150af3f26d08432c5567c3a07 diff --git a/src/src/rda.c b/src/src/rda.c index 2af9fbfaa..ee7c1fe96 100644 --- a/src/src/rda.c +++ b/src/src/rda.c @@ -1,10 +1,8 @@ -/* $Cambridge: exim/src/src/rda.c,v 1.15 2008/12/18 13:13:54 michael Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2007 */ +/* Copyright (c) University of Cambridge 1995 - 2018 */ /* See the file NOTICE for conditions of use and distribution. */ /* This module contains code for extracting addresses from a forwarding list @@ -360,7 +358,7 @@ if (rdata->isfile) } else data = rdata->string; -*filtertype = system_filtering? FILTER_EXIM : rda_is_filter(data); +*filtertype = f.system_filtering ? FILTER_EXIM : rda_is_filter(data); /* Filter interpretation is done by a general function that is also called from the filter testing option (-bf). There are two versions: one for Exim filtering @@ -435,22 +433,24 @@ return parse_forward_list(data, * Write string down pipe * *************************************************/ -/* This function is used for tranferring a string down a pipe between +/* This function is used for transferring a string down a pipe between processes. If the pointer is NULL, a length of zero is written. Arguments: fd the pipe s the string -Returns: nothing +Returns: -1 on error, else 0 */ -static void -rda_write_string(int fd, uschar *s) +static int +rda_write_string(int fd, const uschar *s) { int len = (s == NULL)? 0 : Ustrlen(s) + 1; -(void)write(fd, &len, sizeof(int)); -if (s != NULL) (void)write(fd, s, len); +return ( write(fd, &len, sizeof(int)) != sizeof(int) + || (s != NULL && write(fd, s, len) != len) + ) + ? -1 : 0; } @@ -474,11 +474,12 @@ rda_read_string(int fd, uschar **sp) int len; if (read(fd, &len, sizeof(int)) != sizeof(int)) return FALSE; -if (len == 0) *sp = NULL; else - { - *sp = store_get(len); - if (read(fd, *sp, len) != len) return FALSE; - } +if (len == 0) + *sp = NULL; +else + /* We know we have enough memory so disable the error on "len" */ + /* coverity[tainted_data] */ + if (read(fd, *sp = store_get(len), len) != len) return FALSE; return TRUE; } @@ -565,7 +566,7 @@ DEBUG(D_route) debug_printf("rda_interpret (%s): %s\n", data = expand_string(rdata->string); if (data == NULL) { - if (expand_string_forcedfail) return FF_NOTDELIVERED; + if (f.expand_string_forcedfail) return FF_NOTDELIVERED; *error = string_sprintf("failed to expand \"%s\": %s", rdata->string, expand_string_message); return FF_ERROR; @@ -635,7 +636,7 @@ if ((pid = fork()) == 0) { DEBUG(D_rewrite) debug_printf("turned off address rewrite logging (not " "root or exim in this process)\n"); - log_write_selector &= ~L_address_rewrite; + BIT_CLEAR(log_selector, log_selector_size, Li_address_rewrite); } /* Now do the business */ @@ -647,9 +648,11 @@ if ((pid = fork()) == 0) /* Pass back whether it was a filter, and the return code and any overall error text via the pipe. */ - (void)write(fd, filtertype, sizeof(int)); - (void)write(fd, &yield, sizeof(int)); - rda_write_string(fd, *error); + if ( write(fd, filtertype, sizeof(int)) != sizeof(int) + || write(fd, &yield, sizeof(int)) != sizeof(int) + || rda_write_string(fd, *error) != 0 + ) + goto bad; /* Pass back the contents of any syntax error blocks if we have a pointer */ @@ -657,43 +660,50 @@ if ((pid = fork()) == 0) { error_block *ep; for (ep = *eblockp; ep != NULL; ep = ep->next) - { - rda_write_string(fd, ep->text1); - rda_write_string(fd, ep->text2); - } - rda_write_string(fd, NULL); /* Indicates end of eblocks */ + if ( rda_write_string(fd, ep->text1) != 0 + || rda_write_string(fd, ep->text2) != 0 + ) + goto bad; + if (rda_write_string(fd, NULL) != 0) /* Indicates end of eblocks */ + goto bad; } /* If this is a system filter, we have to pass back the numbers of any original header lines that were removed, and then any header lines that were added but not subsequently removed. */ - if (system_filtering) + if (f.system_filtering) { int i = 0; header_line *h; for (h = header_list; h != waslast->next; i++, h = h->next) - { - if (h->type == htype_old) (void)write(fd, &i, sizeof(i)); - } + if ( h->type == htype_old + && write(fd, &i, sizeof(i)) != sizeof(i) + ) + goto bad; + i = -1; - (void)write(fd, &i, sizeof(i)); + if (write(fd, &i, sizeof(i)) != sizeof(i)) + goto bad; while (waslast != header_last) { waslast = waslast->next; if (waslast->type != htype_old) - { - rda_write_string(fd, waslast->text); - (void)write(fd, &(waslast->type), sizeof(waslast->type)); - } + if ( rda_write_string(fd, waslast->text) != 0 + || write(fd, &(waslast->type), sizeof(waslast->type)) + != sizeof(waslast->type) + ) + goto bad; } - rda_write_string(fd, NULL); /* Indicates end of added headers */ + if (rda_write_string(fd, NULL) != 0) /* Indicates end of added headers */ + goto bad; } /* Write the contents of the $n variables */ - (void)write(fd, filter_n, sizeof(filter_n)); + if (write(fd, filter_n, sizeof(filter_n)) != sizeof(filter_n)) + goto bad; /* If the result was DELIVERED or NOTDELIVERED, we pass back the generated addresses, and their associated information, through the pipe. This is @@ -705,56 +715,73 @@ if ((pid = fork()) == 0) yield == FF_FAIL || yield == FF_FREEZE) { address_item *addr; - for (addr = *generated; addr != NULL; addr = addr->next) + for (addr = *generated; addr; addr = addr->next) { int reply_options = 0; - rda_write_string(fd, addr->address); - (void)write(fd, &(addr->mode), sizeof(addr->mode)); - (void)write(fd, &(addr->flags), sizeof(addr->flags)); - rda_write_string(fd, addr->p.errors_address); + if ( rda_write_string(fd, addr->address) != 0 + || write(fd, &addr->mode, sizeof(addr->mode)) != sizeof(addr->mode) + || write(fd, &addr->flags, sizeof(addr->flags)) != sizeof(addr->flags) + || rda_write_string(fd, addr->prop.errors_address) != 0 + ) + goto bad; - if (addr->pipe_expandn != NULL) + if (addr->pipe_expandn) { uschar **pp; - for (pp = addr->pipe_expandn; *pp != NULL; pp++) - rda_write_string(fd, *pp); + for (pp = addr->pipe_expandn; *pp; pp++) + if (rda_write_string(fd, *pp) != 0) + goto bad; } - rda_write_string(fd, NULL); - - if (addr->reply == NULL) - (void)write(fd, &reply_options, sizeof(int)); /* 0 means no reply */ + if (rda_write_string(fd, NULL) != 0) + goto bad; + + if (!addr->reply) + { + if (write(fd, &reply_options, sizeof(int)) != sizeof(int)) /* 0 means no reply */ + goto bad; + } else { reply_options |= REPLY_EXISTS; if (addr->reply->file_expand) reply_options |= REPLY_EXPAND; if (addr->reply->return_message) reply_options |= REPLY_RETURN; - (void)write(fd, &reply_options, sizeof(int)); - (void)write(fd, &(addr->reply->expand_forbid), sizeof(int)); - (void)write(fd, &(addr->reply->once_repeat), sizeof(time_t)); - rda_write_string(fd, addr->reply->to); - rda_write_string(fd, addr->reply->cc); - rda_write_string(fd, addr->reply->bcc); - rda_write_string(fd, addr->reply->from); - rda_write_string(fd, addr->reply->reply_to); - rda_write_string(fd, addr->reply->subject); - rda_write_string(fd, addr->reply->headers); - rda_write_string(fd, addr->reply->text); - rda_write_string(fd, addr->reply->file); - rda_write_string(fd, addr->reply->logfile); - rda_write_string(fd, addr->reply->oncelog); + if ( write(fd, &reply_options, sizeof(int)) != sizeof(int) + || write(fd, &(addr->reply->expand_forbid), sizeof(int)) + != sizeof(int) + || write(fd, &(addr->reply->once_repeat), sizeof(time_t)) + != sizeof(time_t) + || rda_write_string(fd, addr->reply->to) != 0 + || rda_write_string(fd, addr->reply->cc) != 0 + || rda_write_string(fd, addr->reply->bcc) != 0 + || rda_write_string(fd, addr->reply->from) != 0 + || rda_write_string(fd, addr->reply->reply_to) != 0 + || rda_write_string(fd, addr->reply->subject) != 0 + || rda_write_string(fd, addr->reply->headers) != 0 + || rda_write_string(fd, addr->reply->text) != 0 + || rda_write_string(fd, addr->reply->file) != 0 + || rda_write_string(fd, addr->reply->logfile) != 0 + || rda_write_string(fd, addr->reply->oncelog) != 0 + ) + goto bad; } } - rda_write_string(fd, NULL); /* Marks end of addresses */ + if (rda_write_string(fd, NULL) != 0) /* Marks end of addresses */ + goto bad; } /* OK, this process is now done. Free any cached resources. Must use _exit() and not exit() !! */ +out: (void)close(fd); search_tidyup(); _exit(0); + +bad: + DEBUG(D_rewrite) debug_printf("rda_interpret: failed write to pipe\n"); + goto out; } /* Back in the main process: panic if the fork did not succeed. */ @@ -777,29 +804,28 @@ if (read(fd, filtertype, sizeof(int)) != sizeof(int) || /* Read the contents of any syntax error blocks if we have a pointer */ -if (eblockp != NULL) +if (eblockp) { - uschar *s; error_block *e; - error_block **p = eblockp; - for (;;) + error_block **p; + for (p = eblockp; ; p = &e->next) { + uschar *s; if (!rda_read_string(fd, &s)) goto DISASTER; - if (s == NULL) break; + if (!s) break; e = store_get(sizeof(error_block)); e->next = NULL; e->text1 = s; if (!rda_read_string(fd, &s)) goto DISASTER; e->text2 = s; *p = e; - p = &(e->next); } } /* If this is a system filter, read the identify of any original header lines that were removed, and then read data for any new ones that were added. */ -if (system_filtering) +if (f.system_filtering) { int hn = 0; header_line *h = header_list; @@ -812,8 +838,7 @@ if (system_filtering) while (hn < n) { hn++; - h = h->next; - if (h == NULL) goto DISASTER_NO_HEADER; + if (!(h = h->next)) goto DISASTER_NO_HEADER; } h->type = htype_old; } @@ -823,7 +848,7 @@ if (system_filtering) uschar *s; int type; if (!rda_read_string(fd, &s)) goto DISASTER; - if (s == NULL) break; + if (!s) break; if (read(fd, &type, sizeof(type)) != sizeof(type)) goto DISASTER; header_add(type, "%s", s); } @@ -862,9 +887,9 @@ if (yield == FF_DELIVERED || yield == FF_NOTDELIVERED || /* Next comes the mode and the flags fields */ - if (read(fd, &(addr->mode), sizeof(addr->mode)) != sizeof(addr->mode) || - read(fd, &(addr->flags), sizeof(addr->flags)) != sizeof(addr->flags) || - !rda_read_string(fd, &(addr->p.errors_address))) goto DISASTER; + if (read(fd, &addr->mode, sizeof(addr->mode)) != sizeof(addr->mode) || + read(fd, &addr->flags, sizeof(addr->flags)) != sizeof(addr->flags) || + !rda_read_string(fd, &addr->prop.errors_address)) goto DISASTER; /* Next comes a possible setting for $thisaddress and any numerical variables for pipe expansion, terminated by a NULL string. The maximum @@ -883,7 +908,7 @@ if (yield == FF_DELIVERED || yield == FF_NOTDELIVERED || if (i > 0) { - addr->pipe_expandn = store_get((i+1) * sizeof(uschar **)); + addr->pipe_expandn = store_get((i+1) * sizeof(uschar *)); addr->pipe_expandn[i] = NULL; while (--i >= 0) addr->pipe_expandn[i] = expandn[i]; }