Home | History | Annotate | Line # | Download | only in postscreen
      1 /*	$NetBSD: postscreen_endpt.c,v 1.6 2026/05/09 18:49:19 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	postscreen_endpt 3
      6 /* SUMMARY
      7 /*	look up connection endpoint information
      8 /* SYNOPSIS
      9 /*	#include <postscreen.h>
     10 /*
     11 /*	void	psc_endpt_lookup(smtp_client_stream, lookup_done)
     12 /*	VSTREAM	*smtp_client_stream;
     13 /*	void	(*lookup_done)(status, smtp_client_stream,
     14 /*				smtp_client_addr, smtp_client_port,
     15 /*				smtp_server_addr, smtp_server_port)
     16 /*	int	status;
     17 /*	MAI_HOSTADDR_STR *smtp_client_addr;
     18 /*	MAI_SERVPORT_STR *smtp_client_port;
     19 /*	MAI_HOSTADDR_STR *smtp_server_addr;
     20 /*	MAI_SERVPORT_STR *smtp_server_port;
     21 /* AUXILIARY METHODS
     22 /*	void	psc_endpt_local_lookup(smtp_client_stream, lookup_done)
     23 /*	VSTREAM	*smtp_client_stream;
     24 /*	void	(*lookup_done)(status, smtp_client_stream,
     25 /*				smtp_client_addr, smtp_client_port,
     26 /*				smtp_server_addr, smtp_server_port)
     27 /*	int	status;
     28 /*	MAI_HOSTADDR_STR *smtp_client_addr;
     29 /*	MAI_SERVPORT_STR *smtp_client_port;
     30 /*	MAI_HOSTADDR_STR *smtp_server_addr;
     31 /*	MAI_SERVPORT_STR *smtp_server_port;
     32 /* DESCRIPTION
     33 /*	psc_endpt_lookup() looks up remote and local connection
     34 /*	endpoint information, either through local system calls,
     35 /*	or through an adapter for an up-stream proxy protocol.
     36 /*
     37 /*	The following summarizes what the postscreen(8) server
     38 /*	expects from a proxy protocol adapter routine.
     39 /* .IP \(bu
     40 /*	Accept the same arguments as psc_endpt_lookup().
     41 /* .IP \(bu
     42 /*	Call psc_endpt_local_lookup() to look up connection info
     43 /*	when the upstream proxy indicates that the connection is
     44 /*	not proxied (e.g., health check probe).
     45 /* .IP \(bu
     46 /*	Validate protocol, address and port syntax. Permit only
     47 /*	protocols that are configured with the main.cf:inet_protocols
     48 /*	setting.
     49 /* .IP \(bu
     50 /*	Convert IPv4-in-IPv6 address syntax to IPv4 syntax when
     51 /*	both IPv6 and IPv4 support are enabled with main.cf:inet_protocols.
     52 /* .IP \(bu
     53 /*	Log a clear warning message that explains why a request
     54 /*	fails.
     55 /* .IP \(bu
     56 /*	Never talk to the remote SMTP client.
     57 /* .PP
     58 /*	Arguments:
     59 /* .IP client_stream
     60 /*	A brand-new stream that is connected to the remote client.
     61 /*	This argument MUST be passed to psc_endpt_local_lookup()
     62 /*	if the up-stream proxy indicates that a connection is not
     63 /*	proxied.
     64 /* .IP lookup
     65 /*	Call-back routine that reports the result status, address
     66 /*	and port information. The result status is -1 in case of
     67 /*	error, 0 in case of success. This MUST NOT be called directly
     68 /*	if the up-stream proxy indicates that a connection is not
     69 /*	proxied; instead this MUST be called indirectly by
     70 /*	psc_endpt_local_lookup().
     71 /* LICENSE
     72 /* .ad
     73 /* .fi
     74 /*	The Secure Mailer license must be distributed with this software.
     75 /* AUTHOR(S)
     76 /*	Wietse Venema
     77 /*	IBM T.J. Watson Research
     78 /*	P.O. Box 704
     79 /*	Yorktown Heights, NY 10598, USA
     80 /*
     81 /*	Wietse Venema
     82 /*	Google, Inc.
     83 /*	111 8th Avenue
     84 /*	New York, NY 10011, USA
     85 /*--*/
     86 
     87 /* System library. */
     88 
     89 #include <sys_defs.h>
     90 #include <string.h>
     91 
     92 #ifdef STRCASECMP_IN_STRINGS_H
     93 #include <strings.h>
     94 #endif
     95 
     96 /* Utility library. */
     97 
     98 #include <msg.h>
     99 #include <myaddrinfo.h>
    100 #include <vstream.h>
    101 #include <inet_proto.h>
    102 
    103 /* Global library. */
    104 
    105 #include <mail_params.h>
    106 #include <haproxy_srvr.h>
    107 
    108 /* Application-specific. */
    109 
    110 #include <postscreen.h>
    111 #include <postscreen_haproxy.h>
    112 
    113 static const INET_PROTO_INFO *proto_info;
    114 
    115 /* psc_endpt_local_lookup - look up local system connection information */
    116 
    117 void    psc_endpt_local_lookup(VSTREAM *smtp_client_stream,
    118 			               PSC_ENDPT_LOOKUP_FN lookup_done)
    119 {
    120     struct sockaddr_storage addr_storage;
    121     SOCKADDR_SIZE addr_storage_len;
    122     int     status;
    123     MAI_HOSTADDR_STR smtp_client_addr;
    124     MAI_SERVPORT_STR smtp_client_port;
    125     MAI_HOSTADDR_STR smtp_server_addr;
    126     MAI_SERVPORT_STR smtp_server_port;
    127     int     aierr;
    128 
    129 #define RESET_ADDR_STORAGE_LEN() (addr_storage_len = sizeof(addr_storage))
    130 
    131     /*
    132      * Look up the remote SMTP client address and port.
    133      */
    134     if (RESET_ADDR_STORAGE_LEN(),
    135 	getpeername(vstream_fileno(smtp_client_stream), (struct sockaddr *)
    136 		    &addr_storage, &addr_storage_len) < 0) {
    137 	msg_warn("getpeername: %m -- dropping this connection");
    138 	status = -1;
    139     }
    140 
    141     /*
    142      * Convert the remote SMTP client address and port to printable form for
    143      * logging and access control. Note: this may change addr_storage and
    144      * addr_storage_len.
    145      */
    146     else if ((aierr = sane_sockaddr_to_hostaddr(
    147 					  (struct sockaddr *) &addr_storage,
    148 				       &addr_storage_len, &smtp_client_addr,
    149 				    &smtp_client_port, SOCK_STREAM)) != 0) {
    150 	msg_warn("cannot convert client address/port to string: %s"
    151 		 " -- dropping this connection",
    152 		 MAI_STRERROR(aierr));
    153 	status = -1;
    154     }
    155 
    156     /*
    157      * Look up the local SMTP server address and port. Be sure to reset the
    158      * addr_storage_len value.
    159      */
    160     else if (RESET_ADDR_STORAGE_LEN(),
    161 	     getsockname(vstream_fileno(smtp_client_stream),
    162 			 (struct sockaddr *) &addr_storage,
    163 			 &addr_storage_len) < 0) {
    164 	msg_warn("getsockname: %m -- dropping this connection");
    165 	status = -1;
    166     }
    167 
    168     /*
    169      * Convert the local SMTP server address and port to printable form for
    170      * logging. This may also change addr_storage and addr_storage_len, but
    171      * those variables are dead.
    172      */
    173     else if ((aierr = sane_sockaddr_to_hostaddr(
    174 					  (struct sockaddr *) &addr_storage,
    175 				       &addr_storage_len, &smtp_server_addr,
    176 				    &smtp_server_port, SOCK_STREAM)) != 0) {
    177 	msg_warn("cannot convert server address/port to string: %s"
    178 		 " -- dropping this connection",
    179 		 MAI_STRERROR(aierr));
    180 	status = -1;
    181     } else {
    182 	status = 0;
    183     }
    184     lookup_done(status, smtp_client_stream,
    185 		&smtp_client_addr, &smtp_client_port,
    186 		&smtp_server_addr, &smtp_server_port);
    187 }
    188 
    189  /*
    190   * Lookup table for available proxy protocols.
    191   */
    192 typedef struct {
    193     const char *name;
    194     void    (*endpt_lookup) (VSTREAM *, PSC_ENDPT_LOOKUP_FN);
    195 } PSC_ENDPT_LOOKUP_INFO;
    196 
    197 static const PSC_ENDPT_LOOKUP_INFO psc_endpt_lookup_info[] = {
    198     NOPROXY_PROTO_NAME, psc_endpt_local_lookup,
    199     HAPROXY_PROTO_NAME, psc_endpt_haproxy_lookup,
    200     0,
    201 };
    202 
    203 /* psc_endpt_lookup - look up connection endpoint information */
    204 
    205 void    psc_endpt_lookup(VSTREAM *smtp_client_stream,
    206 			         PSC_ENDPT_LOOKUP_FN notify)
    207 {
    208     const PSC_ENDPT_LOOKUP_INFO *pp;
    209 
    210     if (proto_info == 0)
    211 	proto_info = inet_proto_info();
    212 
    213     for (pp = psc_endpt_lookup_info; /* see below */ ; pp++) {
    214 	if (pp->name == 0)
    215 	    msg_fatal("unsupported %s value: %s",
    216 		      VAR_PSC_UPROXY_PROTO, var_psc_uproxy_proto);
    217 	if (strcmp(var_psc_uproxy_proto, pp->name) == 0) {
    218 	    pp->endpt_lookup(smtp_client_stream, notify);
    219 	    return;
    220 	}
    221     }
    222 }
    223