Postfix3.3.1
postscreen_endpt.c
[詳解]
1 /*++
2 /* NAME
3 /* postscreen_endpt 3
4 /* SUMMARY
5 /* look up connection endpoint information
6 /* SYNOPSIS
7 /* #include <postscreen.h>
8 /*
9 /* void psc_endpt_lookup(smtp_client_stream, lookup_done)
10 /* VSTREAM *smtp_client_stream;
11 /* void (*lookup_done)(status, smtp_client_stream,
12 /* smtp_client_addr, smtp_client_port,
13 /* smtp_server_addr, smtp_server_port)
14 /* int status;
15 /* MAI_HOSTADDR_STR *smtp_client_addr;
16 /* MAI_SERVPORT_STR *smtp_client_port;
17 /* MAI_HOSTADDR_STR *smtp_server_addr;
18 /* MAI_SERVPORT_STR *smtp_server_port;
19 /* DESCRIPTION
20 /* psc_endpt_lookup() looks up remote and local connection
21 /* endpoint information, either through local system calls,
22 /* or through an adapter for an up-stream proxy protocol.
23 /*
24 /* The following summarizes what the postscreen(8) server
25 /* expects from a proxy protocol adapter routine.
26 /* .IP \(bu
27 /* Accept the same arguments as psc_endpt_lookup().
28 /* .IP \(bu
29 /* Validate protocol, address and port syntax. Permit only
30 /* protocols that are configured with the main.cf:inet_protocols
31 /* setting.
32 /* .IP \(bu
33 /* Convert IPv4-in-IPv6 address syntax to IPv4 syntax when
34 /* both IPv6 and IPv4 support are enabled with main.cf:inet_protocols.
35 /* .IP \(bu
36 /* Log a clear warning message that explains why a request
37 /* fails.
38 /* .IP \(bu
39 /* Never talk to the remote SMTP client.
40 /* .PP
41 /* Arguments:
42 /* .IP client_stream
43 /* A brand-new stream that is connected to the remote client.
44 /* .IP lookup
45 /* Call-back routine that reports the result status, address
46 /* and port information. The result status is -1 in case of
47 /* error, 0 in case of success.
48 /* LICENSE
49 /* .ad
50 /* .fi
51 /* The Secure Mailer license must be distributed with this software.
52 /* AUTHOR(S)
53 /* Wietse Venema
54 /* IBM T.J. Watson Research
55 /* P.O. Box 704
56 /* Yorktown Heights, NY 10598, USA
57 /*--*/
58 
59 /* System library. */
60 
61 #include <sys_defs.h>
62 #include <string.h>
63 
64 #ifdef STRCASECMP_IN_STRINGS_H
65 #include <strings.h>
66 #endif
67 
68 /* Utility library. */
69 
70 #include <msg.h>
71 #include <myaddrinfo.h>
72 #include <vstream.h>
73 #include <inet_proto.h>
74 
75 /* Global library. */
76 
77 #include <mail_params.h>
78 #include <haproxy_srvr.h>
79 
80 /* Application-specific. */
81 
82 #include <postscreen.h>
83 #include <postscreen_haproxy.h>
84 
85 static INET_PROTO_INFO *proto_info;
86 
87 /* psc_sockaddr_to_hostaddr - transform endpoint address and port to string */
88 
89 static int psc_sockaddr_to_hostaddr(struct sockaddr *addr_storage,
90  SOCKADDR_SIZE addr_storage_len,
91  MAI_HOSTADDR_STR *addr_buf,
92  MAI_SERVPORT_STR *port_buf,
93  int socktype)
94 {
95  int aierr;
96 
97  if ((aierr = sockaddr_to_hostaddr(addr_storage, addr_storage_len,
98  addr_buf, port_buf, socktype)) == 0
99  && strncasecmp("::ffff:", addr_buf->buf, 7) == 0
100  && strchr((char *) proto_info->sa_family_list, AF_INET) != 0)
101  memmove(addr_buf->buf, addr_buf->buf + 7,
102  sizeof(addr_buf->buf) - 7);
103  return (aierr);
104 }
105 
106 /* psc_endpt_local_lookup - look up local system connection information */
107 
108 static void psc_endpt_local_lookup(VSTREAM *smtp_client_stream,
109  PSC_ENDPT_LOOKUP_FN lookup_done)
110 {
111  struct sockaddr_storage addr_storage;
112  SOCKADDR_SIZE addr_storage_len = sizeof(addr_storage);
113  int status;
114  MAI_HOSTADDR_STR smtp_client_addr;
115  MAI_SERVPORT_STR smtp_client_port;
116  MAI_HOSTADDR_STR smtp_server_addr;
117  MAI_SERVPORT_STR smtp_server_port;
118  int aierr;
119 
120  /*
121  * Look up the remote SMTP client address and port.
122  */
123  if (getpeername(vstream_fileno(smtp_client_stream), (struct sockaddr *)
124  &addr_storage, &addr_storage_len) < 0) {
125  msg_warn("getpeername: %m -- dropping this connection");
126  status = -1;
127  }
128 
129  /*
130  * Convert the remote SMTP client address and port to printable form for
131  * logging and access control.
132  */
133  else if ((aierr = psc_sockaddr_to_hostaddr(
134  (struct sockaddr *) &addr_storage,
135  addr_storage_len, &smtp_client_addr,
136  &smtp_client_port, SOCK_STREAM)) != 0) {
137  msg_warn("cannot convert client address/port to string: %s"
138  " -- dropping this connection",
139  MAI_STRERROR(aierr));
140  status = -1;
141  }
142 
143  /*
144  * Look up the local SMTP server address and port.
145  */
146  else if (getsockname(vstream_fileno(smtp_client_stream),
147  (struct sockaddr *) &addr_storage,
148  &addr_storage_len) < 0) {
149  msg_warn("getsockname: %m -- dropping this connection");
150  status = -1;
151  }
152 
153  /*
154  * Convert the local SMTP server address and port to printable form for
155  * logging.
156  */
157  else if ((aierr = psc_sockaddr_to_hostaddr(
158  (struct sockaddr *) &addr_storage,
159  addr_storage_len, &smtp_server_addr,
160  &smtp_server_port, SOCK_STREAM)) != 0) {
161  msg_warn("cannot convert server address/port to string: %s"
162  " -- dropping this connection",
163  MAI_STRERROR(aierr));
164  status = -1;
165  } else {
166  status = 0;
167  }
168  lookup_done(status, smtp_client_stream,
169  &smtp_client_addr, &smtp_client_port,
170  &smtp_server_addr, &smtp_server_port);
171 }
172 
173  /*
174  * Lookup table for available proxy protocols.
175  */
176 typedef struct {
177  const char *name;
178  void (*endpt_lookup) (VSTREAM *, PSC_ENDPT_LOOKUP_FN);
180 
181 static const PSC_ENDPT_LOOKUP_INFO psc_endpt_lookup_info[] = {
182  NOPROXY_PROTO_NAME, psc_endpt_local_lookup,
184  0,
185 };
186 
187 /* psc_endpt_lookup - look up connection endpoint information */
188 
189 void psc_endpt_lookup(VSTREAM *smtp_client_stream,
190  PSC_ENDPT_LOOKUP_FN notify)
191 {
192  const PSC_ENDPT_LOOKUP_INFO *pp;
193 
194  if (proto_info == 0)
195  proto_info = inet_proto_info();
196 
197  for (pp = psc_endpt_lookup_info; /* see below */ ; pp++) {
198  if (pp->name == 0)
199  msg_fatal("unsupported %s value: %s",
201  if (strcmp(var_psc_uproxy_proto, pp->name) == 0) {
202  pp->endpt_lookup(smtp_client_stream, notify);
203  return;
204  }
205  }
206 }
#define HAPROXY_PROTO_NAME
Definition: haproxy_srvr.h:26
#define inet_proto_info()
Definition: inet_proto.h:29
void(* PSC_ENDPT_LOOKUP_FN)(int, VSTREAM *, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *)
Definition: postscreen.h:561
void psc_endpt_lookup(VSTREAM *smtp_client_stream, PSC_ENDPT_LOOKUP_FN notify)
int strncasecmp(const char *s1, const char *s2, size_t n)
Definition: strcasecmp.c:52
int sockaddr_to_hostaddr(const struct sockaddr *sa, SOCKADDR_SIZE salen, MAI_HOSTADDR_STR *hostaddr, MAI_SERVPORT_STR *portnum, int unused_socktype)
Definition: myaddrinfo.c:580
#define SOCKADDR_SIZE
Definition: sys_defs.h:1411
char buf[MAI_HOSTADDR_STRSIZE]
Definition: myaddrinfo.h:146
void psc_endpt_haproxy_lookup(VSTREAM *stream, PSC_ENDPT_LOOKUP_FN notify)
void msg_warn(const char *fmt,...)
Definition: msg.c:215
unsigned char * sa_family_list
Definition: inet_proto.h:21
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define VAR_PSC_UPROXY_PROTO
Definition: mail_params.h:3782
char * var_psc_uproxy_proto
Definition: postscreen.c:521
#define vstream_fileno(vp)
Definition: vstream.h:115
#define MAI_STRERROR(e)
Definition: myaddrinfo.h:169
void(* endpt_lookup)(VSTREAM *, PSC_ENDPT_LOOKUP_FN)
#define NOPROXY_PROTO_NAME
Definition: mail_params.h:3780