diff options
Diffstat (limited to 'src/local/token.c')
-rw-r--r-- | src/local/token.c | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/local/token.c b/src/local/token.c new file mode 100644 index 0000000..2eb0c28 --- /dev/null +++ b/src/local/token.c @@ -0,0 +1,222 @@ +/*++ +/* NAME +/* token 3 +/* SUMMARY +/* tokenize alias/include/.forward entries and deliver +/* SYNOPSIS +/* #include "local.h" +/* +/* int deliver_token(state, usr_attr, addr) +/* LOCAL_STATE state; +/* USER_ATTR usr_attr; +/* TOK822 *addr; +/* +/* int deliver_token_string(state, usr_attr, string, addr_count) +/* LOCAL_STATE state; +/* USER_ATTR usr_attr; +/* char *string; +/* int *addr_count; +/* +/* int deliver_token_stream(state, usr_attr, fp, addr_count) +/* LOCAL_STATE state; +/* USER_ATTR usr_attr; +/* VSTREAM *fp; +/* int *addr_count; +/* DESCRIPTION +/* This module delivers to addresses listed in an alias database +/* entry, in an include file, or in a .forward file. +/* +/* deliver_token() delivers to the address in the given token: +/* an absolute /path/name, a ~/path/name relative to the recipient's +/* home directory, an :include:/path/name request, an external +/* "|command", or a mail address. +/* +/* deliver_token_string() delivers to all addresses listed in +/* the specified string. +/* +/* deliver_token_stream() delivers to all addresses listed in +/* the specified stream. Input records > \fIline_length_limit\fR +/* are broken up into multiple records, to prevent the mail +/* system from using unreasonable amounts of memory. +/* +/* Arguments: +/* .IP state +/* The attributes that specify the message, recipient and more. +/* Attributes describing alias, include or forward expansion. +/* A table with the results from expanding aliases or lists. +/* A table with delivered-to: addresses taken from the message. +/* .IP usr_attr +/* Attributes describing user rights and environment. +/* .IP addr +/* A parsed address from an include file, alias file or .forward file. +/* .IP string +/* A null-terminated string. +/* .IP fp +/* A readable stream. +/* .IP addr_count +/* Null pointer, or the address of a counter that is incremented +/* by the number of destinations found by the tokenizer. +/* DIAGNOSTICS +/* Fatal errors: out of memory. The result is non-zero when the +/* operation should be tried again. Warnings: malformed address. +/* SEE ALSO +/* list_token(3) tokenize list +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <unistd.h> +#include <string.h> + +#ifdef STRCASECMP_IN_STRINGS_H +#include <strings.h> +#endif + +/* Utility library. */ + +#include <msg.h> +#include <vstring.h> +#include <vstream.h> +#include <htable.h> +#include <readlline.h> +#include <mymalloc.h> +#include <vstring_vstream.h> +#include <stringops.h> + +/* Global library. */ + +#include <tok822.h> +#include <mail_params.h> +#include <bounce.h> +#include <defer.h> + +/* Application-specific. */ + +#include "local.h" + +/* deliver_token_home - expand ~token */ + +static int deliver_token_home(LOCAL_STATE state, USER_ATTR usr_attr, char *addr) +{ + char *full_path; + int status; + + if (addr[1] != '/') { /* disallow ~user */ + msg_warn("bad home directory syntax for: %s", addr); + dsb_simple(state.msg_attr.why, "5.3.5", + "mail system configuration error"); + status = bounce_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr)); + } else if (usr_attr.home == 0) { /* require user context */ + msg_warn("unknown home directory for: %s", addr); + dsb_simple(state.msg_attr.why, "5.3.5", + "mail system configuration error"); + status = bounce_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr)); + } else if (usr_attr.home[0] == '/' && usr_attr.home[1] == 0) { + status = deliver_file(state, usr_attr, addr + 1); + } else { /* expand ~ to home */ + full_path = concatenate(usr_attr.home, addr + 1, (char *) 0); + status = deliver_file(state, usr_attr, full_path); + myfree(full_path); + } + return (status); +} + +/* deliver_token - deliver to expansion of include file or alias */ + +int deliver_token(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr) +{ + VSTRING *addr_buf = vstring_alloc(100); + static char include[] = ":include:"; + int status; + char *path; + + tok822_internalize(addr_buf, addr->head, TOK822_STR_DEFL); + if (msg_verbose) + msg_info("deliver_token: %s", STR(addr_buf)); + + if (*STR(addr_buf) == '/') { + status = deliver_file(state, usr_attr, STR(addr_buf)); + } else if (*STR(addr_buf) == '~') { + status = deliver_token_home(state, usr_attr, STR(addr_buf)); + } else if (*STR(addr_buf) == '|') { + if ((local_cmd_deliver_mask & state.msg_attr.exp_type) == 0) { + dsb_simple(state.msg_attr.why, "5.7.1", + "mail to command is restricted"); + status = bounce_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr)); + } else + status = deliver_command(state, usr_attr, STR(addr_buf) + 1); + } else if (strncasecmp(STR(addr_buf), include, sizeof(include) - 1) == 0) { + path = STR(addr_buf) + sizeof(include) - 1; + status = deliver_include(state, usr_attr, path); + } else { + status = deliver_resolve_tree(state, usr_attr, addr); + } + vstring_free(addr_buf); + + return (status); +} + +/* deliver_token_string - tokenize string and deliver */ + +int deliver_token_string(LOCAL_STATE state, USER_ATTR usr_attr, + char *string, int *addr_count) +{ + TOK822 *tree; + TOK822 *addr; + int status = 0; + + if (msg_verbose) + msg_info("deliver_token_string: %s", string); + + tree = tok822_parse(string); + for (addr = tree; addr != 0; addr = addr->next) { + if (addr->type == TOK822_ADDR) { + if (addr_count) + (*addr_count)++; + status |= deliver_token(state, usr_attr, addr); + } + } + tok822_free_tree(tree); + return (status); +} + +/* deliver_token_stream - tokenize stream and deliver */ + +int deliver_token_stream(LOCAL_STATE state, USER_ATTR usr_attr, + VSTREAM *fp, int *addr_count) +{ + VSTRING *buf = vstring_alloc(100); + int status = 0; + + if (msg_verbose) + msg_info("deliver_token_stream: %s", VSTREAM_PATH(fp)); + + while (vstring_fgets_bound(buf, fp, var_line_limit)) { + if (*STR(buf) != '#') { + status = deliver_token_string(state, usr_attr, STR(buf), addr_count); + if (status != 0) + break; + } + } + if (vstream_ferror(fp)) { + dsb_simple(state.msg_attr.why, "4.3.0", + "error reading forwarding file: %m"); + status = defer_append(BOUNCE_FLAGS(state.request), + BOUNCE_ATTR(state.msg_attr)); + } + vstring_free(buf); + return (status); +} |