1 /* $NetBSD: token.c,v 1.1.1.1 2009/06/23 10:08:49 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* token 3 6 /* SUMMARY 7 /* tokenize alias/include/.forward entries and deliver 8 /* SYNOPSIS 9 /* #include "local.h" 10 /* 11 /* int deliver_token(state, usr_attr, addr) 12 /* LOCAL_STATE state; 13 /* USER_ATTR usr_attr; 14 /* TOK822 *addr; 15 /* 16 /* int deliver_token_string(state, usr_attr, string, addr_count) 17 /* LOCAL_STATE state; 18 /* USER_ATTR usr_attr; 19 /* char *string; 20 /* int *addr_count; 21 /* 22 /* int deliver_token_stream(state, usr_attr, fp, addr_count) 23 /* LOCAL_STATE state; 24 /* USER_ATTR usr_attr; 25 /* VSTREAM *fp; 26 /* int *addr_count; 27 /* DESCRIPTION 28 /* This module delivers to addresses listed in an alias database 29 /* entry, in an include file, or in a .forward file. 30 /* 31 /* deliver_token() delivers to the address in the given token: 32 /* an absolute /path/name, a ~/path/name relative to the recipient's 33 /* home directory, an :include:/path/name request, an external 34 /* "|command", or a mail address. 35 /* 36 /* deliver_token_string() delivers to all addresses listed in 37 /* the specified string. 38 /* 39 /* deliver_token_stream() delivers to all addresses listed in 40 /* the specified stream. Input records > \fIline_length_limit\fR 41 /* are broken up into multiple records, to prevent the mail 42 /* system from using unreasonable amounts of memory. 43 /* 44 /* Arguments: 45 /* .IP state 46 /* The attributes that specify the message, recipient and more. 47 /* Attributes describing alias, include or forward expansion. 48 /* A table with the results from expanding aliases or lists. 49 /* A table with delivered-to: addresses taken from the message. 50 /* .IP usr_attr 51 /* Attributes describing user rights and environment. 52 /* .IP addr 53 /* A parsed address from an include file, alias file or .forward file. 54 /* .IP string 55 /* A null-terminated string. 56 /* .IP fp 57 /* A readable stream. 58 /* .IP addr_count 59 /* Null pointer, or the address of a counter that is incremented 60 /* by the number of destinations found by the tokenizer. 61 /* DIAGNOSTICS 62 /* Fatal errors: out of memory. The result is non-zero when the 63 /* operation should be tried again. Warnings: malformed address. 64 /* SEE ALSO 65 /* list_token(3) tokenize list 66 /* LICENSE 67 /* .ad 68 /* .fi 69 /* The Secure Mailer license must be distributed with this software. 70 /* AUTHOR(S) 71 /* Wietse Venema 72 /* IBM T.J. Watson Research 73 /* P.O. Box 704 74 /* Yorktown Heights, NY 10598, USA 75 /*--*/ 76 77 /* System library. */ 78 79 #include <sys_defs.h> 80 #include <unistd.h> 81 #include <string.h> 82 83 #ifdef STRCASECMP_IN_STRINGS_H 84 #include <strings.h> 85 #endif 86 87 /* Utility library. */ 88 89 #include <msg.h> 90 #include <vstring.h> 91 #include <vstream.h> 92 #include <htable.h> 93 #include <readlline.h> 94 #include <mymalloc.h> 95 #include <vstring_vstream.h> 96 #include <stringops.h> 97 98 /* Global library. */ 99 100 #include <tok822.h> 101 #include <mail_params.h> 102 #include <bounce.h> 103 #include <defer.h> 104 105 /* Application-specific. */ 106 107 #include "local.h" 108 109 /* deliver_token_home - expand ~token */ 110 111 static int deliver_token_home(LOCAL_STATE state, USER_ATTR usr_attr, char *addr) 112 { 113 char *full_path; 114 int status; 115 116 if (addr[1] != '/') { /* disallow ~user */ 117 msg_warn("bad home directory syntax for: %s", addr); 118 dsb_simple(state.msg_attr.why, "5.3.5", 119 "mail system configuration error"); 120 status = bounce_append(BOUNCE_FLAGS(state.request), 121 BOUNCE_ATTR(state.msg_attr)); 122 } else if (usr_attr.home == 0) { /* require user context */ 123 msg_warn("unknown home directory for: %s", addr); 124 dsb_simple(state.msg_attr.why, "5.3.5", 125 "mail system configuration error"); 126 status = bounce_append(BOUNCE_FLAGS(state.request), 127 BOUNCE_ATTR(state.msg_attr)); 128 } else if (usr_attr.home[0] == '/' && usr_attr.home[1] == 0) { 129 status = deliver_file(state, usr_attr, addr + 1); 130 } else { /* expand ~ to home */ 131 full_path = concatenate(usr_attr.home, addr + 1, (char *) 0); 132 status = deliver_file(state, usr_attr, full_path); 133 myfree(full_path); 134 } 135 return (status); 136 } 137 138 /* deliver_token - deliver to expansion of include file or alias */ 139 140 int deliver_token(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr) 141 { 142 VSTRING *addr_buf = vstring_alloc(100); 143 static char include[] = ":include:"; 144 int status; 145 char *path; 146 147 tok822_internalize(addr_buf, addr->head, TOK822_STR_DEFL); 148 if (msg_verbose) 149 msg_info("deliver_token: %s", STR(addr_buf)); 150 151 if (*STR(addr_buf) == '/') { 152 status = deliver_file(state, usr_attr, STR(addr_buf)); 153 } else if (*STR(addr_buf) == '~') { 154 status = deliver_token_home(state, usr_attr, STR(addr_buf)); 155 } else if (*STR(addr_buf) == '|') { 156 if ((local_cmd_deliver_mask & state.msg_attr.exp_type) == 0) { 157 dsb_simple(state.msg_attr.why, "5.7.1", 158 "mail to command is restricted"); 159 status = bounce_append(BOUNCE_FLAGS(state.request), 160 BOUNCE_ATTR(state.msg_attr)); 161 } else 162 status = deliver_command(state, usr_attr, STR(addr_buf) + 1); 163 } else if (strncasecmp(STR(addr_buf), include, sizeof(include) - 1) == 0) { 164 path = STR(addr_buf) + sizeof(include) - 1; 165 status = deliver_include(state, usr_attr, path); 166 } else { 167 status = deliver_resolve_tree(state, usr_attr, addr); 168 } 169 vstring_free(addr_buf); 170 171 return (status); 172 } 173 174 /* deliver_token_string - tokenize string and deliver */ 175 176 int deliver_token_string(LOCAL_STATE state, USER_ATTR usr_attr, 177 char *string, int *addr_count) 178 { 179 TOK822 *tree; 180 TOK822 *addr; 181 int status = 0; 182 183 if (msg_verbose) 184 msg_info("deliver_token_string: %s", string); 185 186 tree = tok822_parse(string); 187 for (addr = tree; addr != 0; addr = addr->next) { 188 if (addr->type == TOK822_ADDR) { 189 if (addr_count) 190 (*addr_count)++; 191 status |= deliver_token(state, usr_attr, addr); 192 } 193 } 194 tok822_free_tree(tree); 195 return (status); 196 } 197 198 /* deliver_token_stream - tokenize stream and deliver */ 199 200 int deliver_token_stream(LOCAL_STATE state, USER_ATTR usr_attr, 201 VSTREAM *fp, int *addr_count) 202 { 203 VSTRING *buf = vstring_alloc(100); 204 int status = 0; 205 206 if (msg_verbose) 207 msg_info("deliver_token_stream: %s", VSTREAM_PATH(fp)); 208 209 while (vstring_fgets_bound(buf, fp, var_line_limit)) { 210 if (*STR(buf) != '#') { 211 status = deliver_token_string(state, usr_attr, STR(buf), addr_count); 212 if (status != 0) 213 break; 214 } 215 } 216 if (vstream_ferror(fp)) { 217 dsb_simple(state.msg_attr.why, "4.3.0", 218 "error reading forwarding file: %m"); 219 status = defer_append(BOUNCE_FLAGS(state.request), 220 BOUNCE_ATTR(state.msg_attr)); 221 } 222 vstring_free(buf); 223 return (status); 224 } 225