Home | History | Annotate | Line # | Download | only in xsasl
      1 /*	$NetBSD: xsasl_server.c,v 1.3 2025/02/25 19:15:53 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	xsasl-server 3
      6 /* SUMMARY
      7 /*	Postfix SASL server plug-in interface
      8 /* SYNOPSIS
      9 /*	#include <xsasl.h>
     10 /*
     11 /*	XSASL_SERVER_IMPL *xsasl_server_init(server_type, path_info)
     12 /*	const char *server_type;
     13 /*	const char *path_info;
     14 /*
     15 /*	void	xsasl_server_done(implementation)
     16 /*	XSASL_SERVER_IMPL *implementation;
     17 /*
     18 /*	ARGV	*xsasl_server_types()
     19 /*
     20 /* .in +4
     21 /*	typedef struct XSASL_SERVER_CREATE_ARGS {
     22 /*		VSTREAM *stream;
     23 /*		const char *server_addr;
     24 /*		const char *client_addr;
     25 /*		const char *service;
     26 /*		const char *user_realm;
     27 /*		const char *security_options;
     28 /*		int     tls_flag;
     29 /*	} XSASL_SERVER_CREATE_ARGS;
     30 /* .in -4
     31 /*
     32 /*	XSASL_SERVER *xsasl_server_create(implementation, args)
     33 /*	XSASL_SERVER_IMPL *implementation;
     34 /*	XSASL_SERVER_CREATE_ARGS *args;
     35 /*
     36 /*	XSASL_SERVER *XSASL_SERVER_CREATE(implementation, args,
     37 /*					stream = stream_value,
     38 /*					...,
     39 /*					tls_flag = tls_flag_value)
     40 /*	XSASL_SERVER_IMPL *implementation;
     41 /*	XSASL_SERVER_CREATE_ARGS *args;
     42 /*
     43 /*	void xsasl_server_free(server)
     44 /*	XSASL_SERVER *server;
     45 /*
     46 /*	int	xsasl_server_first(server, auth_method, init_resp, server_reply)
     47 /*	XSASL_SERVER *server;
     48 /*	const char *auth_method;
     49 /*	const char *init_resp;
     50 /*	VSTRING *server_reply;
     51 /*
     52 /*	int	xsasl_server_next(server, client_request, server_reply)
     53 /*	XSASL_SERVER *server;
     54 /*	const char *client_request;
     55 /*	VSTRING *server_reply;
     56 /*
     57 /*	const char *xsasl_server_get_mechanism_list(server)
     58 /*	XSASL_SERVER *server;
     59 /*
     60 /*	const char *xsasl_server_get_username(server)
     61 /*	XSASL_SERVER *server;
     62 /* DESCRIPTION
     63 /*	The XSASL_SERVER abstraction implements a generic interface
     64 /*	to one or more SASL authentication implementations.
     65 /*
     66 /*	xsasl_server_init() is called once during process initialization.
     67 /*	It selects a SASL implementation by name, specifies the
     68 /*	location of a configuration file or rendez-vous point, and
     69 /*	returns an implementation handle that can be used to generate
     70 /*	SASL server instances. This function is typically used to
     71 /*	initialize the underlying implementation.
     72 /*
     73 /*	xsasl_server_done() disposes of an implementation handle,
     74 /*	and allows the underlying implementation to release resources.
     75 /*
     76 /*	xsasl_server_types() lists the available implementation types.
     77 /*	The result should be destroyed by the caller.
     78 /*
     79 /*	xsasl_server_create() is called at the start of an SMTP
     80 /*	session. It generates a Postfix SASL plug-in server instance
     81 /*	for the specified service and authentication realm, and
     82 /*	with the specified security properties. Specify a null
     83 /*	pointer when no realm should be used. The stream handle is
     84 /*	stored so that encryption can be turned on after successful
     85 /*	negotiations. Specify zero-length strings when a client or
     86 /*	server address is unavailable.
     87 /*
     88 /*	XSASL_SERVER_CREATE() is a macro that provides an interface
     89 /*	with named parameters.  Named parameters do not have to
     90 /*	appear in a fixed order. The parameter names correspond to
     91 /*	the member names of the XSASL_SERVER_CREATE_ARGS structure.
     92 /*
     93 /*	xsasl_server_free() is called at the end of an SMTP session.
     94 /*	It destroys a SASL server instance, and disables further
     95 /*	read/write operations if encryption was turned on.
     96 /*
     97 /*	xsasl_server_first() produces the server response for the
     98 /*	client AUTH command. The client input are an authentication
     99 /*	method, and an optional initial response or null pointer.
    100 /*	The initial response and server non-error replies are BASE64
    101 /*	encoded.  Server error replies are 7-bit ASCII text without
    102 /*	control characters, without BASE64 encoding, and without
    103 /*	SMTP reply code or enhanced status code.
    104 /*
    105 /*	The result is one of the following:
    106 /* .IP XSASL_AUTH_MORE
    107 /*	More client input is needed. The server reply specifies
    108 /*	what.
    109 /* .IP XSASL_AUTH_DONE
    110 /*	Authentication completed successfully.
    111 /* .IP XSASL_AUTH_FORM
    112 /*	The client input is incorrectly formatted. The server error
    113 /*	reply explains why.
    114 /* .IP XSASL_AUTH_FAIL
    115 /*	Authentication failed. The server error reply explains why.
    116 /* .PP
    117 /*	xsasl_server_next() supports the subsequent stages of the
    118 /*	client-server AUTH protocol. Both the client input and
    119 /*	server non-error responses are BASE64 encoded.  See
    120 /*	xsasl_server_first() for other details.
    121 /*
    122 /*	xsasl_server_get_mechanism_list() returns the authentication
    123 /*	mechanisms that match the security properties, as a white-space
    124 /*	separated list. This is meant to be used in the SMTP EHLO
    125 /*	reply.
    126 /*
    127 /*	xsasl_server_get_username() returns the stored username
    128 /*	after successful authentication. The username may be null
    129 /*	after authentication failure, depending on the kind of
    130 /*	failure and on authentication backend implementation
    131 /*	details. A non-null result is converted to printable text.
    132 /*
    133 /*	Arguments:
    134 /* .IP addr_family
    135 /*	The network address family: AF_INET6 or AF_INET.
    136 /* .IP auth_method
    137 /*	AUTH command authentication method.
    138 /* .IP client_addr
    139 /*	IPv4 or IPv6 address (no surrounding [] or ipv6: prefix),
    140 /*	or zero-length string if unavailable.
    141 /* .IP client_port
    142 /*	TCP port or zero-length string if unavailable.
    143 /* .IP init_resp
    144 /*	AUTH command initial response or null pointer.
    145 /* .IP implementation
    146 /*	Implementation handle that was obtained with xsasl_server_init().
    147 /* .IP path_info
    148 /*	The value of the smtpd_sasl_path parameter or equivalent.
    149 /*	This specifies the implementation-dependent location of a
    150 /*	configuration file, rendez-vous point, etc., and is passed
    151 /*	unchanged to the plug-in.
    152 /* .IP security_options
    153 /*	The value of the smtpd_security_options parameter or
    154 /*	equivalent. This is passed unchanged to the plug-in.
    155 /* .IP server
    156 /*	SASL plug-in server handle.
    157 /* .IP server_addr
    158 /*	IPv4 or IPv6 address (no surrounding [] or ipv6: prefix),
    159 /*	or zero-length string if unavailable.
    160 /* .IP server_port
    161 /*	TCP port or zero-length string if unavailable.
    162 /* .IP server_reply
    163 /*	BASE64 encoded server non-error reply (without SMTP reply
    164 /*	code or enhanced status code), or ASCII error description.
    165 /* .IP server_type
    166 /*	The name of a Postfix SASL server plug_in implementation.
    167 /* .IP server_types
    168 /*	Null-terminated array of strings with SASL server plug-in
    169 /*	implementation names.
    170 /* .IP service
    171 /*	The service that is implemented by the local server, typically
    172 /*	"smtp" or "lmtp".
    173 /* .IP stream
    174 /*	The connection between client and server.  When SASL
    175 /*	encryption is negotiated, the plug-in will transparently
    176 /*	intercept the socket read/write operations.
    177 /* .IP user_realm
    178 /*	Authentication domain or null pointer.
    179 /* SECURITY
    180 /* .ad
    181 /* .fi
    182 /*	The caller does not sanitize client input. It is the
    183 /*	responsibility of the underlying SASL server implementation
    184 /*	to produce 7-bit ASCII without control characters as server
    185 /*	non-error and error replies, and as the result from
    186 /*	xsasl_server_method() and xsasl_server_username().
    187 /* DIAGNOSTICS
    188 /*	In case of failure, xsasl_server_init(), xsasl_server_create(),
    189 /*	xsasl_server_get_mechanism_list() and xsasl_server_get_username()
    190 /*	log a warning and return a null pointer.
    191 /*
    192 /*	Functions that normally return XSASL_AUTH_OK will log a warning
    193 /*	and return an appropriate result value.
    194 /*
    195 /*	Fatal errors: out of memory.
    196 /*
    197 /*	Panic: interface violations.
    198 /* SEE ALSO
    199 /*	cyrus_security(3) Cyrus SASL security features
    200 /* LICENSE
    201 /* .ad
    202 /* .fi
    203 /*	The Secure Mailer license must be distributed with this
    204 /*	software.
    205 /* AUTHOR(S)
    206 /*	Wietse Venema
    207 /*	IBM T.J. Watson Research
    208 /*	P.O. Box 704
    209 /*	Yorktown Heights, NY 10598, USA
    210 /*
    211 /*	Wietse Venema
    212 /*	Google, Inc.
    213 /*	111 8th Avenue
    214 /*	New York, NY 10011, USA
    215 /*
    216 /*	Wietse Venema
    217 /*	porcupine.org
    218 /*	Amawalk, NY 10501, USA
    219 /*--*/
    220 
    221 /* System library. */
    222 
    223 #include <sys_defs.h>
    224 #include <string.h>
    225 
    226 /* Utility library. */
    227 
    228 #include <msg.h>
    229 #include <mymalloc.h>
    230 
    231 /* SASL implementations. */
    232 
    233 #include <xsasl.h>
    234 #include <xsasl_cyrus.h>
    235 #include <xsasl_dovecot.h>
    236 
    237  /*
    238   * Lookup table for available SASL server implementations.
    239   */
    240 typedef struct {
    241     char   *server_type;
    242     struct XSASL_SERVER_IMPL *(*server_init) (const char *, const char *);
    243 } XSASL_SERVER_IMPL_INFO;
    244 
    245 static const XSASL_SERVER_IMPL_INFO server_impl_info[] = {
    246 #ifdef XSASL_TYPE_CYRUS
    247     {XSASL_TYPE_CYRUS, xsasl_cyrus_server_init},
    248 #endif
    249 #ifdef XSASL_TYPE_DOVECOT
    250     {XSASL_TYPE_DOVECOT, xsasl_dovecot_server_init},
    251 #endif
    252     {0, 0}
    253 };
    254 
    255 /* xsasl_server_init - look up server implementation by name */
    256 
    257 XSASL_SERVER_IMPL *xsasl_server_init(const char *server_type,
    258 				             const char *path_info)
    259 {
    260     const XSASL_SERVER_IMPL_INFO *xp;
    261 
    262     for (xp = server_impl_info; xp->server_type; xp++)
    263 	if (strcmp(server_type, xp->server_type) == 0)
    264 	    return (xp->server_init(server_type, path_info));
    265     msg_warn("unsupported SASL server implementation: %s", server_type);
    266     return (0);
    267 }
    268 
    269 /* xsasl_server_types - report available implementation types */
    270 
    271 ARGV   *xsasl_server_types(void)
    272 {
    273     const XSASL_SERVER_IMPL_INFO *xp;
    274     ARGV   *argv = argv_alloc(1);
    275 
    276     for (xp = server_impl_info; xp->server_type; xp++)
    277 	argv_add(argv, xp->server_type, ARGV_END);
    278     return (argv);
    279 }
    280