Home | History | Annotate | Line # | Download | only in local
      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