Postfix3.3.1
smtpd_expand.c
[詳解]
1 /*++
2 /* NAME
3 /* smtpd_expand 3
4 /* SUMMARY
5 /* SMTP server macro expansion
6 /* SYNOPSIS
7 /* #include <smtpd.h>
8 /* #include <smtpd_expand.h>
9 /*
10 /* void smtpd_expand_init()
11 /*
12 /* int smtpd_expand(state, result, template, flags)
13 /* SMTPD_STATE *state;
14 /* VSTRING *result;
15 /* const char *template;
16 /* int flags;
17 /* LOW_LEVEL INTERFACE
18 /* VSTRING *smtpd_expand_filter;
19 /*
20 /* const char *smtpd_expand_lookup(name, unused_mode, context)
21 /* const char *name;
22 /* int unused_mode;
23 /* void *context;
24 /* const char *template;
25 /* DESCRIPTION
26 /* This module expands session-related macros.
27 /*
28 /* smtpd_expand_init() performs one-time initialization.
29 /*
30 /* smtpd_expand() expands macros in the template, using session
31 /* attributes in the state argument, and writes the result to
32 /* the result argument. The flags and result value are as with
33 /* mac_expand().
34 /*
35 /* smtpd_expand_filter and smtpd_expand_lookup() provide access
36 /* to lower-level interfaces that are used by smtpd_expand().
37 /* smtpd_expand_lookup() returns null when a string is not
38 /* found (or when it is a null pointer).
39 /* DIAGNOSTICS
40 /* Panic: interface violations. Fatal errors: out of memory.
41 /* internal protocol errors. smtpd_expand() returns the binary
42 /* OR of MAC_PARSE_ERROR (syntax error) and MAC_PARSE_UNDEF
43 /* (undefined macro name).
44 /* LICENSE
45 /* .ad
46 /* .fi
47 /* The Secure Mailer license must be distributed with this software.
48 /* AUTHOR(S)
49 /* Wietse Venema
50 /* IBM T.J. Watson Research
51 /* P.O. Box 704
52 /* Yorktown Heights, NY 10598, USA
53 /*--*/
54 
55 /* System library. */
56 
57 #include <sys_defs.h>
58 #include <time.h>
59 
60 /* Utility library. */
61 
62 #include <msg.h>
63 #include <vstring.h>
64 #include <mac_expand.h>
65 #include <stringops.h>
66 
67 /* Global library. */
68 
69 #include <mail_params.h>
70 #include <mail_proto.h>
71 
72 /* Application-specific. */
73 
74 #include <smtpd.h>
75 #include <smtpd_expand.h>
76 
77  /*
78  * Pre-parsed expansion filter.
79  */
81 
82  /*
83  * SLMs.
84  */
85 #define STR vstring_str
86 
87 /* smtpd_expand_init - initialize once during process lifetime */
88 
90 {
91 
92  /*
93  * Expand the expansion filter :-)
94  */
95  smtpd_expand_filter = vstring_alloc(10);
96  unescape(smtpd_expand_filter, var_smtpd_exp_filter);
97 }
98 
99 /* smtpd_expand_unknown - report unknown macro name */
100 
101 static void smtpd_expand_unknown(const char *name)
102 {
103  msg_warn("unknown macro name \"%s\" in expansion request", name);
104 }
105 
106 /* smtpd_expand_addr - return address or substring thereof */
107 
108 static const char *smtpd_expand_addr(VSTRING *buf, const char *addr,
109  const char *name, int prefix_len)
110 {
111  const char *p;
112  const char *suffix;
113 
114  /*
115  * Return NULL only for unknown names in expansion requests.
116  */
117  if (addr == 0)
118  return ("");
119 
120  suffix = name + prefix_len;
121 
122  /*
123  * MAIL_ATTR_SENDER or MAIL_ATTR_RECIP.
124  */
125  if (*suffix == 0) {
126  if (*addr)
127  return (addr);
128  else
129  return ("<>");
130  }
131 
132  /*
133  * "sender_name" or "recipient_name".
134  */
135 #define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
136 
137  else if (STREQ(suffix, MAIL_ATTR_S_NAME)) {
138  if (*addr) {
139  if ((p = strrchr(addr, '@')) != 0) {
140  vstring_strncpy(buf, addr, p - addr);
141  return (STR(buf));
142  } else {
143  return (addr);
144  }
145  } else
146  return ("<>");
147  }
148 
149  /*
150  * "sender_domain" or "recipient_domain".
151  */
152  else if (STREQ(suffix, MAIL_ATTR_S_DOMAIN)) {
153  if (*addr) {
154  if ((p = strrchr(addr, '@')) != 0) {
155  return (p + 1);
156  } else {
157  return ("");
158  }
159  } else
160  return ("");
161  }
162 
163  /*
164  * Unknown. Return NULL to indicate an "unknown name" error.
165  */
166  else {
167  smtpd_expand_unknown(name);
168  return (0);
169  }
170 }
171 
172 /* smtpd_expand_lookup - generic SMTP attribute $name expansion */
173 
174 const char *smtpd_expand_lookup(const char *name, int unused_mode,
175  void *context)
176 {
177  SMTPD_STATE *state = (SMTPD_STATE *) context;
178  time_t now;
179  struct tm *lt;
180 
181  if (state->expand_buf == 0)
182  state->expand_buf = vstring_alloc(10);
183 
184  if (msg_verbose > 1)
185  msg_info("smtpd_expand_lookup: ${%s}", name);
186 
187 #define STREQN(x,y,n) (*(x) == *(y) && strncmp((x), (y), (n)) == 0)
188 #define CONST_LEN(x) (sizeof(x) - 1)
189 
190  /*
191  * Don't query main.cf parameters, as the result of expansion could
192  * reveal system-internal information in server replies.
193  *
194  * XXX: This said, multiple servers may be behind a single client-visible
195  * name or IP address, and each may generate its own logs. Therefore, it
196  * may be useful to expose the replying MTA id (myhostname) in the
197  * contact footer, to identify the right logs. So while we don't expose
198  * the raw configuration dictionary, we do expose "$myhostname" as
199  * expanded in var_myhostname.
200  *
201  * Return NULL only for non-existent names.
202  */
203  if (STREQ(name, MAIL_ATTR_SERVER_NAME)) {
204  return (var_myhostname);
205  } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT)) {
206  return (state->namaddr);
207  } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_PORT)) {
208  return (state->port);
209  } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_ADDR)) {
210  return (state->addr);
211  } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_NAME)) {
212  return (state->name);
213  } else if (STREQ(name, MAIL_ATTR_ACT_REVERSE_CLIENT_NAME)) {
214  return (state->reverse_name);
215  } else if (STREQ(name, MAIL_ATTR_ACT_HELO_NAME)) {
216  return (state->helo_name ? state->helo_name : "");
217  } else if (STREQN(name, MAIL_ATTR_SENDER, CONST_LEN(MAIL_ATTR_SENDER))) {
218  return (smtpd_expand_addr(state->expand_buf, state->sender,
219  name, CONST_LEN(MAIL_ATTR_SENDER)));
220  } else if (STREQN(name, MAIL_ATTR_RECIP, CONST_LEN(MAIL_ATTR_RECIP))) {
221  return (smtpd_expand_addr(state->expand_buf, state->recipient,
222  name, CONST_LEN(MAIL_ATTR_RECIP)));
223  } if (STREQ(name, MAIL_ATTR_LOCALTIME)) {
224  if (time(&now) == (time_t) -1)
225  msg_fatal("time lookup failed: %m");
226  lt = localtime(&now);
227  VSTRING_RESET(state->expand_buf);
228  do {
229  VSTRING_SPACE(state->expand_buf, 100);
230  } while (strftime(STR(state->expand_buf),
231  vstring_avail(state->expand_buf),
232  "%b %d %H:%M:%S", lt) == 0);
233  return (STR(state->expand_buf));
234  } else {
235  smtpd_expand_unknown(name);
236  return (0);
237  }
238 }
239 
240 /* smtpd_expand - expand session attributes in string */
241 
242 int smtpd_expand(SMTPD_STATE *state, VSTRING *result,
243  const char *template, int flags)
244 {
245  return (mac_expand(result, template, flags, STR(smtpd_expand_filter),
246  smtpd_expand_lookup, (void *) state));
247 }
int msg_verbose
Definition: msg.c:177
#define MAIL_ATTR_ACT_HELO_NAME
Definition: mail_proto.h:219
int mac_expand(VSTRING *result, const char *pattern, int flags, const char *filter, MAC_EXP_LOOKUP_FN lookup, void *context)
Definition: mac_expand.c:593
#define MAIL_ATTR_S_NAME
Definition: mail_proto.h:184
void smtpd_expand_init(void)
Definition: smtpd_expand.c:89
const char * smtpd_expand_lookup(const char *name, int unused_mode, void *context)
Definition: smtpd_expand.c:174
#define STREQ(x, y)
char * name
Definition: smtpd.h:75
#define MAIL_ATTR_ACT_CLIENT_ADDR
Definition: mail_proto.h:216
VSTRING * expand_buf
Definition: smtpd.h:148
#define MAIL_ATTR_SERVER_NAME
Definition: mail_proto.h:301
char * helo_name
Definition: smtpd.h:95
#define CONST_LEN(x)
#define MAIL_ATTR_ACT_CLIENT_PORT
Definition: mail_proto.h:217
char * port
Definition: smtpd.h:78
#define VSTRING_RESET(vp)
Definition: vstring.h:77
char * var_smtpd_exp_filter
Definition: postscreen.c:517
void msg_warn(const char *fmt,...)
Definition: msg.c:215
#define MAIL_ATTR_ACT_CLIENT_NAME
Definition: mail_proto.h:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
char * sender
Definition: smtpd.h:103
int smtpd_expand(SMTPD_STATE *state, VSTRING *result, const char *template, int flags)
Definition: smtpd_expand.c:242
#define MAIL_ATTR_ACT_REVERSE_CLIENT_NAME
Definition: mail_proto.h:221
#define STR
Definition: smtpd_expand.c:85
#define vstring_avail(vp)
Definition: vstring.h:86
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define STREQN(x, y, n)
char * reverse_name
Definition: smtpd.h:76
#define MAIL_ATTR_LOCALTIME
Definition: mail_proto.h:143
VSTRING * smtpd_expand_filter
Definition: smtpd_expand.c:80
#define VSTRING_SPACE(vp, len)
Definition: vstring.h:70
#define MAIL_ATTR_RECIP
Definition: mail_proto.h:134
char * addr
Definition: smtpd.h:77
#define MAIL_ATTR_SENDER
Definition: mail_proto.h:131
char * recipient
Definition: smtpd.h:106
#define MAIL_ATTR_ACT_CLIENT
Definition: mail_proto.h:214
char * var_myhostname
Definition: mail_params.c:223
VSTRING * vstring_strncpy(VSTRING *vp, const char *src, ssize_t len)
Definition: vstring.c:445
char * namaddr
Definition: smtpd.h:79
VSTRING * unescape(VSTRING *, const char *)
Definition: unescape.c:69
void msg_info(const char *fmt,...)
Definition: msg.c:199
#define MAIL_ATTR_S_DOMAIN
Definition: mail_proto.h:185