X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/db3f7b6972f3b003c0413b78afcfbe295ffe0b97..f5bf7636988febc332349f2a1deb2a4329ff3243:/src/src/rda.c diff --git a/src/src/rda.c b/src/src/rda.c index 078f4fe4b..5fa3d09b4 100644 --- a/src/src/rda.c +++ b/src/src/rda.c @@ -96,37 +96,37 @@ static int rda_exists(uschar *filename, uschar **error) { int rc, saved_errno; -uschar *slash; struct stat statbuf; +uschar * s; if ((rc = Ustat(filename, &statbuf)) >= 0) return FILE_EXIST; saved_errno = errno; -Ustrncpy(big_buffer, filename, big_buffer_size - 3); +s = string_copy(filename); sigalrm_seen = FALSE; if (saved_errno == ENOENT) { - slash = Ustrrchr(big_buffer, '/'); - Ustrcpy(slash+1, "."); + uschar * slash = Ustrrchr(s, '/'); + Ustrcpy(slash+1, US"."); ALARM(30); - rc = Ustat(big_buffer, &statbuf); + rc = Ustat(s, &statbuf); if (rc != 0 && errno == EACCES && !sigalrm_seen) { *slash = 0; - rc = Ustat(big_buffer, &statbuf); + rc = Ustat(s, &statbuf); } saved_errno = errno; ALARM_CLR(0); - DEBUG(D_route) debug_printf("stat(%s)=%d\n", big_buffer, rc); + DEBUG(D_route) debug_printf("stat(%s)=%d\n", s, rc); } if (sigalrm_seen || rc != 0) { - *error = string_sprintf("failed to stat %s (%s)", big_buffer, - sigalrm_seen? "timeout" : strerror(saved_errno)); + *error = string_sprintf("failed to stat %s (%s)", s, + sigalrm_seen? "timeout" : strerror(saved_errno)); return FILE_EXIST_UNCLEAR; } @@ -184,40 +184,35 @@ However, if the ignore_enotdir option is set (to ignore "something on the path is not a directory" errors), the right behaviour seems to be not to do the directory test. */ -fwd = Ufopen(filename, "rb"); -if (fwd == NULL) +if (!(fwd = Ufopen(filename, "rb"))) switch(errno) { - switch(errno) - { - case ENOENT: /* File does not exist */ + case ENOENT: /* File does not exist */ DEBUG(D_route) debug_printf("%s does not exist\n%schecking parent directory\n", - filename, - ((options & RDO_ENOTDIR) != 0)? "ignore_enotdir set => skip " : ""); - *yield = (((options & RDO_ENOTDIR) != 0) || - rda_exists(filename, error) == FILE_NOT_EXIST)? - FF_NONEXIST : FF_ERROR; + filename, options & RDO_ENOTDIR ? "ignore_enotdir set => skip " : ""); + *yield = + options & RDO_ENOTDIR || rda_exists(filename, error) == FILE_NOT_EXIST + ? FF_NONEXIST : FF_ERROR; return NULL; - case ENOTDIR: /* Something on the path isn't a directory */ + case ENOTDIR: /* Something on the path isn't a directory */ if ((options & RDO_ENOTDIR) == 0) goto DEFAULT_ERROR; DEBUG(D_route) debug_printf("non-directory on path %s: file assumed not to " "exist\n", filename); *yield = FF_NONEXIST; return NULL; - case EACCES: /* Permission denied */ + case EACCES: /* Permission denied */ if ((options & RDO_EACCES) == 0) goto DEFAULT_ERROR; DEBUG(D_route) debug_printf("permission denied for %s: file assumed not to " "exist\n", filename); *yield = FF_NONEXIST; return NULL; - DEFAULT_ERROR: - default: + DEFAULT_ERROR: + default: *error = string_open_failed(errno, "%s", filename); *yield = FF_ERROR; return NULL; - } } /* Check that we have a regular file. */ @@ -246,22 +241,18 @@ if ((statbuf.st_mode & rdata->modemask) != 0) /* Check the file owner and file group if required to do so. */ if (!uid_ok) - { - if (rdata->pw != NULL && statbuf.st_uid == rdata->pw->pw_uid) + if (rdata->pw && statbuf.st_uid == rdata->pw->pw_uid) uid_ok = TRUE; - else if (rdata->owners != NULL) + else if (rdata->owners) for (int i = 1; i <= (int)(rdata->owners[0]); i++) if (rdata->owners[i] == statbuf.st_uid) { uid_ok = TRUE; break; } - } if (!gid_ok) - { - if (rdata->pw != NULL && statbuf.st_gid == rdata->pw->pw_gid) + if (rdata->pw && statbuf.st_gid == rdata->pw->pw_gid) gid_ok = TRUE; - else if (rdata->owngroups != NULL) + else if (rdata->owngroups) for (int i = 1; i <= (int)(rdata->owngroups[0]); i++) if (rdata->owngroups[i] == statbuf.st_gid) { gid_ok = TRUE; break; } - } if (!uid_ok || !gid_ok) { @@ -281,7 +272,7 @@ if (statbuf.st_size > MAX_FILTER_SIZE) /* Read the file in one go in order to minimize the time we have it open. */ -filebuf = store_get(statbuf.st_size + 1); +filebuf = store_get(statbuf.st_size + 1, is_tainted(filename)); if (fread(filebuf, 1, statbuf.st_size, fwd) != statbuf.st_size) { @@ -291,8 +282,8 @@ if (fread(filebuf, 1, statbuf.st_size, fwd) != statbuf.st_size) } filebuf[statbuf.st_size] = 0; -DEBUG(D_route) - debug_printf(OFF_T_FMT " bytes read from %s\n", statbuf.st_size, filename); +DEBUG(D_route) debug_printf(OFF_T_FMT " %sbytes read from %s\n", + statbuf.st_size, is_tainted(filename) ? "(tainted) " : "", filename); (void)fclose(fwd); return filebuf; @@ -347,8 +338,8 @@ uschar *data; if (rdata->isfile) { int yield = 0; - data = rda_get_file_contents(rdata, options, error, &yield); - if (data == NULL) return yield; + if (!(data = rda_get_file_contents(rdata, options, error, &yield))) + return yield; } else data = rdata->string; @@ -366,7 +357,7 @@ if (*filtertype != FILTER_FORWARD) int old_expand_forbid = expand_forbid; DEBUG(D_route) debug_printf("data is %s filter program\n", - (*filtertype == FILTER_EXIM)? "an Exim" : "a Sieve"); + *filtertype == FILTER_EXIM ? "an Exim" : "a Sieve"); /* RDO_FILTER is an "allow" bit */ @@ -377,8 +368,7 @@ if (*filtertype != FILTER_FORWARD) } expand_forbid = - (expand_forbid & ~RDO_FILTER_EXPANSIONS) | - (options & RDO_FILTER_EXPANSIONS); + expand_forbid & ~RDO_FILTER_EXPANSIONS | options & RDO_FILTER_EXPANSIONS; /* RDO_{EXIM,SIEVE}_FILTER are forbid bits */ @@ -473,7 +463,8 @@ if (len == 0) 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; + /* We trust the data source, so untainted */ + if (read(fd, *sp = store_get(len, FALSE), len) != len) return FALSE; return TRUE; } @@ -486,7 +477,7 @@ return TRUE; /* This function is passed a forward list string (unexpanded) or the name of a file (unexpanded) whose contents are the forwarding list. The list may in fact be a filter program if it starts with "#Exim filter" or "#Sieve filter". Other -types of filter, with different inital tag strings, may be introduced in due +types of filter, with different initial tag strings, may be introduced in due course. The job of the function is to process the forwarding list or filter. It is @@ -552,13 +543,12 @@ uschar *data; uschar *readerror = US""; void (*oldsignal)(int); -DEBUG(D_route) debug_printf("rda_interpret (%s): %s\n", - (rdata->isfile)? "file" : "string", rdata->string); +DEBUG(D_route) debug_printf("rda_interpret (%s): '%s'\n", + rdata->isfile ? "file" : "string", string_printing(rdata->string)); /* Do the expansions of the file name or data first, while still privileged. */ -data = expand_string(rdata->string); -if (data == NULL) +if (!(data = expand_string(rdata->string))) { if (f.expand_string_forcedfail) return FF_NOTDELIVERED; *error = string_sprintf("failed to expand \"%s\": %s", rdata->string, @@ -567,7 +557,7 @@ if (data == NULL) } rdata->string = data; -DEBUG(D_route) debug_printf("expanded: %s\n", data); +DEBUG(D_route) debug_printf("expanded: '%s'\n", data); if (rdata->isfile && data[0] != '/') { @@ -767,7 +757,7 @@ if ((pid = fork()) == 0) out: (void)close(fd); search_tidyup(); - _exit(0); + exim_underbar_exit(0); bad: DEBUG(D_rewrite) debug_printf("rda_interpret: failed write to pipe\n"); @@ -802,7 +792,7 @@ if (eblockp) uschar *s; if (!rda_read_string(fd, &s)) goto DISASTER; if (!s) break; - e = store_get(sizeof(error_block)); + e = store_get(sizeof(error_block), FALSE); e->next = NULL; e->text1 = s; if (!rda_read_string(fd, &s)) goto DISASTER; @@ -866,7 +856,7 @@ if (yield == FF_DELIVERED || yield == FF_NOTDELIVERED || /* First string is the address; NULL => end of addresses */ if (!rda_read_string(fd, &recipient)) goto DISASTER; - if (recipient == NULL) break; + if (!recipient) break; /* Hang on the end of the chain */ @@ -901,7 +891,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 *), FALSE); addr->pipe_expandn[i] = NULL; while (--i >= 0) addr->pipe_expandn[i] = expandn[i]; } @@ -911,7 +901,7 @@ if (yield == FF_DELIVERED || yield == FF_NOTDELIVERED || if (read(fd, &reply_options, sizeof(int)) != sizeof(int)) goto DISASTER; if ((reply_options & REPLY_EXISTS) != 0) { - addr->reply = store_get(sizeof(reply_item)); + addr->reply = store_get(sizeof(reply_item), FALSE); addr->reply->file_expand = (reply_options & REPLY_EXPAND) != 0; addr->reply->return_message = (reply_options & REPLY_RETURN) != 0;