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