Postfix3.3.1
smtp_key.c
[詳解]
1 /*++
2 /* NAME
3 /* smtp_key 3
4 /* SUMMARY
5 /* cache/table lookup key management
6 /* SYNOPSIS
7 /* #include "smtp.h"
8 /*
9 /* char *smtp_key_prefix(buffer, delim_na, iterator, context_flags)
10 /* VSTRING *buffer;
11 /* const char *delim_na;
12 /* SMTP_ITERATOR *iterator;
13 /* int context_flags;
14 /* DESCRIPTION
15 /* The Postfix SMTP server accesses caches and lookup tables,
16 /* using lookup keys that contain information from various
17 /* contexts: per-server configuration, per-request envelope,
18 /* and results from DNS queries.
19 /*
20 /* These lookup keys sometimes share the same context information.
21 /* The primary purpose of this API is to ensure that this
22 /* shared context is used consistently, and that its use is
23 /* made explicit (both are needed to verify that there is no
24 /* false cache sharing).
25 /*
26 /* smtp_key_prefix() constructs a lookup key prefix from context
27 /* that may be shared with other lookup keys. The user is free
28 /* to append additional application-specific context. The result
29 /* value is a pointer to the result text.
30 /*
31 /* Arguments:
32 /* .IP buffer
33 /* Storage for the result.
34 /* .IP delim_na
35 /* The field delimiter character, and the optional place holder
36 /* character for a) information that is unavailable, b)
37 /* information that is inapplicable, or c) that would result
38 /* in an empty field. Key fields that contain "delim_na"
39 /* characters will be base64-encoded.
40 /* Do not specify "delim_na" characters that are part of the
41 /* base64 character set.
42 /* .IP iterator
43 /* Information that will be selected by the specified flags.
44 /* .IP context_flags
45 /* Bit-wise OR of one or more of the following.
46 /* .RS
47 /* .IP SMTP_KEY_FLAG_SERVICE
48 /* The global service name. This is a proxy for
49 /* destination-independent and request-independent context.
50 /* .IP SMTP_KEY_FLAG_SENDER
51 /* The envelope sender address. This is a proxy for sender-dependent
52 /* context, such as per-sender SASL authentication.
53 /* .IP SMTP_KEY_FLAG_REQ_NEXTHOP
54 /* The request nexthop destination. This is a proxy for
55 /* destination-dependent, but host-independent context.
56 /* .IP SMTP_KEY_FLAG_NEXTHOP
57 /* The current iterator's nexthop destination (request nexthop
58 /* or fallback nexthop, including optional [] and :port). This
59 /* is the form that users specify in a SASL or TLS lookup
60 /* tables.
61 /* .IP SMTP_KEY_FLAG_HOSTNAME
62 /* The current iterator's remote hostname.
63 /* .IP SMTP_KEY_FLAG_ADDR
64 /* The current iterator's remote address.
65 /* .IP SMTP_KEY_FLAG_PORT
66 /* The current iterator's remote port.
67 /* .RE
68 /* DIAGNOSTICS
69 /* Panic: undefined flag or zero flags. Fatal: out of memory.
70 /* LICENSE
71 /* .ad
72 /* .fi
73 /* The Secure Mailer license must be distributed with this software.
74 /* AUTHOR(S)
75 /* Wietse Venema
76 /* IBM T.J. Watson Research
77 /* P.O. Box 704
78 /* Yorktown Heights, NY 10598, USA
79 /*--*/
80 
81  /*
82  * System library.
83  */
84 #include <sys_defs.h>
85 #include <netinet/in.h> /* ntohs() for Solaris or BSD */
86 #include <arpa/inet.h> /* ntohs() for Linux or BSD */
87 #include <string.h>
88 
89  /*
90  * Utility library.
91  */
92 #include <msg.h>
93 #include <vstring.h>
94 #include <base64_code.h>
95 
96  /*
97  * Global library.
98  */
99 #include <mail_params.h>
100 
101  /*
102  * Application-specific.
103  */
104 #include <smtp.h>
105 
106  /*
107  * We use a configurable field terminator and optional place holder for data
108  * that is unavailable or inapplicable. We base64-encode content that
109  * contains these characters, and content that needs obfuscation.
110  */
111 
112 /* smtp_key_append_na - append place-holder key field */
113 
114 static void smtp_key_append_na(VSTRING *buffer, const char *delim_na)
115 {
116  if (delim_na[1] != 0)
117  VSTRING_ADDCH(buffer, delim_na[1]);
118  VSTRING_ADDCH(buffer, delim_na[0]);
119 }
120 
121 /* smtp_key_append_str - append string-valued key field */
122 
123 static void smtp_key_append_str(VSTRING *buffer, const char *str,
124  const char *delim_na)
125 {
126  if (str == 0 || str[0] == 0) {
127  smtp_key_append_na(buffer, delim_na);
128  } else if (str[strcspn(str, delim_na)] != 0) {
129  base64_encode_opt(buffer, str, strlen(str), BASE64_FLAG_APPEND);
130  VSTRING_ADDCH(buffer, delim_na[0]);
131  } else {
132  vstring_sprintf_append(buffer, "%s%c", str, delim_na[0]);
133  }
134 }
135 
136 /* smtp_key_append_uint - append unsigned-valued key field */
137 
138 static void smtp_key_append_uint(VSTRING *buffer, unsigned num,
139  const char *delim_na)
140 {
141  vstring_sprintf_append(buffer, "%u%c", num, delim_na[0]);
142 }
143 
144 /* smtp_key_prefix - format common elements in lookup key */
145 
146 char *smtp_key_prefix(VSTRING *buffer, const char *delim_na,
147  SMTP_ITERATOR *iter, int flags)
148 {
149  static const char myname[] = "smtp_key_prefix";
150  SMTP_STATE *state = iter->parent; /* private member */
151 
152  /*
153  * Sanity checks.
154  */
155  if (state == 0)
156  msg_panic("%s: no parent state", myname);
157  if (flags & ~SMTP_KEY_MASK_ALL)
158  msg_panic("%s: unknown key flags 0x%x",
159  myname, flags & ~SMTP_KEY_MASK_ALL);
160  if (flags == 0)
161  msg_panic("%s: zero flags", myname);
162 
163  /*
164  * Initialize.
165  */
166  VSTRING_RESET(buffer);
167 
168  /*
169  * Per-service and per-request context.
170  */
171  if (flags & SMTP_KEY_FLAG_SERVICE)
172  smtp_key_append_str(buffer, state->service, delim_na);
173  if (flags & SMTP_KEY_FLAG_SENDER)
174  smtp_key_append_str(buffer, state->request->sender, delim_na);
175 
176  /*
177  * Per-destination context, non-canonicalized form.
178  */
179  if (flags & SMTP_KEY_FLAG_REQ_NEXTHOP)
180  smtp_key_append_str(buffer, STR(iter->request_nexthop), delim_na);
181  if (flags & SMTP_KEY_FLAG_NEXTHOP)
182  smtp_key_append_str(buffer, STR(iter->dest), delim_na);
183 
184  /*
185  * Per-host context, canonicalized form.
186  */
187  if (flags & SMTP_KEY_FLAG_HOSTNAME)
188  smtp_key_append_str(buffer, STR(iter->host), delim_na);
189  if (flags & SMTP_KEY_FLAG_ADDR)
190  smtp_key_append_str(buffer, STR(iter->addr), delim_na);
191  if (flags & SMTP_KEY_FLAG_PORT)
192  smtp_key_append_uint(buffer, ntohs(iter->port), delim_na);
193 
194  /* Similarly, provide unique TLS fingerprint when applicable. */
195 
196  VSTRING_TERMINATE(buffer);
197 
198  return STR(buffer);
199 }
#define SMTP_KEY_FLAG_HOSTNAME
Definition: smtp.h:614
struct SMTP_STATE * parent
Definition: smtp.h:61
#define BASE64_FLAG_APPEND
Definition: base64_code.h:26
unsigned port
Definition: smtp.h:56
VSTRING * request_nexthop
Definition: smtp.h:52
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
VSTRING * base64_encode_opt(VSTRING *result, const char *in, ssize_t len, int flags)
Definition: base64_code.c:95
DELIVER_REQUEST * request
Definition: smtp.h:146
#define SMTP_KEY_FLAG_SERVICE
Definition: smtp.h:610
char * smtp_key_prefix(VSTRING *buffer, const char *delim_na, SMTP_ITERATOR *iter, int flags)
Definition: smtp_key.c:146
VSTRING * dest
Definition: smtp.h:53
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
Definition: vstring.c:624
VSTRING * host
Definition: smtp.h:54
#define SMTP_KEY_FLAG_PORT
Definition: smtp.h:616
#define SMTP_KEY_MASK_ALL
Definition: smtp.h:618
#define VSTRING_RESET(vp)
Definition: vstring.h:77
#define STR(x)
Definition: anvil.c:518
VSTRING * addr
Definition: smtp.h:55
const char * service
Definition: smtp.h:145
#define SMTP_KEY_FLAG_REQ_NEXTHOP
Definition: smtp.h:612
#define SMTP_KEY_FLAG_NEXTHOP
Definition: smtp.h:613
#define SMTP_KEY_FLAG_ADDR
Definition: smtp.h:615
#define SMTP_KEY_FLAG_SENDER
Definition: smtp.h:611