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