1 /* $NetBSD: xsasl_client.c,v 1.1.1.1 2009/06/23 10:09:02 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* xsasl_client 3 6 /* SUMMARY 7 /* Postfix SASL client plug-in interface 8 /* SYNOPSIS 9 /* #include <xsasl.h> 10 /* 11 /* XSASL_CLIENT_IMPL *xsasl_client_init(client_type, path_info) 12 /* const char *client_type; 13 /* const char *path_info; 14 /* 15 /* void xsasl_client_done(implementation) 16 /* XSASL_CLIENT_IMPL *implementation; 17 /* 18 /* ARGV *xsasl_client_types() 19 /* 20 /* .in +4 21 /* typedef struct XSASL_CLIENT_CREATE_ARGS { 22 /* VSTREAM *stream; 23 /* const char *service; 24 /* const char *server_name; 25 /* const char *security_options; 26 /* } XSASL_CLIENT_CREATE_ARGS; 27 /* .in -4 28 /* 29 /* XSASL_CLIENT *xsasl_client_create(implementation, create_args) 30 /* XSASL_CLIENT_IMPL *implementation; 31 /* XSASL_CLIENT_CREATE_ARGS *create_args; 32 /* 33 /* XSASL_CLIENT *XSASL_CLIENT_CREATE(implementation, create_args, 34 /* stream = stream_val, 35 /* ..., 36 /* security_options = prop_val) 37 /* XSASL_CLIENT_IMPL *implementation; 38 /* XSASL_CLIENT_CREATE_ARGS *create_args; 39 /* 40 /* void xsasl_client_free(client) 41 /* XSASL_CLIENT *client; 42 /* 43 /* int xsasl_client_first(client, stream, mech_list, username, 44 /* password, auth_method, init_resp) 45 /* XSASL_CLIENT *client; 46 /* const char *mech_list; 47 /* const char *username; 48 /* const char *password; 49 /* const char **auth_method; 50 /* VSTRING *init_resp; 51 /* 52 /* int xsasl_client_next(client, server_reply, client_reply) 53 /* XSASL_CLIENT *client; 54 /* const char *server_reply; 55 /* VSTRING *client_reply; 56 /* DESCRIPTION 57 /* The XSASL_CLIENT abstraction implements a generic interface 58 /* to one or more SASL authentication implementations. 59 /* 60 /* xsasl_client_init() is called once during process initialization. 61 /* It selects a SASL implementation by name, specifies the 62 /* location of a configuration file or rendez-vous point, and 63 /* returns an implementation handle that can be used to generate 64 /* SASL client instances. This function is typically used to 65 /* initialize the underlying implementation. 66 /* 67 /* xsasl_client_done() disposes of an implementation handle, 68 /* and allows the underlying implementation to release resources. 69 /* 70 /* xsasl_client_types() lists the available implementation types. 71 /* The result should be destroyed by the caller. 72 /* 73 /* xsasl_client_create() is called at the start of an SMTP 74 /* session. It generates a Postfix SASL plug-in client instance 75 /* for the specified service and server name, with the specified 76 /* security properties. The stream handle is stored so that 77 /* encryption can be turned on after successful negotiations. 78 /* 79 /* XSASL_CLIENT_CREATE() is a macro that provides an interface 80 /* with named parameters. Named parameters do not have to 81 /* appear in a fixed order. The parameter names correspond to 82 /* the member names of the XSASL_CLIENT_CREATE_ARGS structure. 83 /* 84 /* xsasl_client_free() is called at the end of an SMTP session. 85 /* It destroys a SASL client instance, and disables further 86 /* read/write operations if encryption was turned on. 87 /* 88 /* xsasl_client_first() produces the client input for the AUTH 89 /* command. The input is an authentication method list from 90 /* an EHLO response, a username and a password. On return, the 91 /* method argument specifies the authentication method; storage 92 /* space is owned by the underlying implementation. The initial 93 /* response and client non-error replies are BASE64 encoded. 94 /* Client error replies are 7-bit ASCII text without control 95 /* characters, and without BASE64 encoding. They are meant for 96 /* the local application, not for transmission to the server. 97 /* The client may negotiate encryption of the client-server 98 /* connection. 99 /* 100 /* The result is one of the following: 101 /* .IP XSASL_AUTH_OK 102 /* Success. 103 /* .IP XSASL_AUTH_FORM 104 /* The server reply is incorrectly formatted. The client error 105 /* reply explains why. 106 /* .IP XSASL_AUTH_FAIL 107 /* Other error. The client error reply explains why. 108 /* .PP 109 /* xsasl_client_next() supports the subsequent stages of the 110 /* AUTH protocol. Both the client reply and client non-error 111 /* responses are BASE64 encoded. See xsasl_client_first() for 112 /* other details. 113 /* 114 /* Arguments: 115 /* .IP client 116 /* SASL plug-in client handle. 117 /* .IP client_reply 118 /* BASE64 encoded non-error client reply, or ASCII error 119 /* description for the user. 120 /* .IP client_type 121 /* The name of a Postfix SASL client plug_in implementation. 122 /* .IP client_types 123 /* Null-terminated array of strings with SASL client plug-in 124 /* implementation names. 125 /* .IP init_resp 126 /* The AUTH command initial response. 127 /* .IP implementation 128 /* Implementation handle that was obtained with xsasl_client_init(). 129 /* .IP mech_list 130 /* List of SASL mechanisms as announced by the server. 131 /* .IP auth_method 132 /* The AUTH command authentication method. 133 /* .IP password 134 /* Information from the Postfix SASL password file or equivalent. 135 /* .IP path_info 136 /* The value of the smtp_sasl_path parameter or equivalent. 137 /* This specifies the implementation-dependent location of a 138 /* configuration file, rendez-vous point, etc., and is passed 139 /* unchanged to the plug-in. 140 /* .IP security_options 141 /* The value of the smtp_sasl_security_options parameter or 142 /* equivalent. This is passed unchanged to the plug-in. 143 /* .IP server_name 144 /* The remote server fully qualified hostname. 145 /* .IP server_reply 146 /* BASE64 encoded server reply without SMTP reply code or 147 /* enhanced status code. 148 /* .IP service 149 /* The service that is implemented by the local client (typically, 150 /* "lmtp" or "smtp"). 151 /* .IP stream 152 /* The connection between client and server. 153 /* When SASL encryption is negotiated, the plug-in will 154 /* transparently intercept the socket read/write operations. 155 /* .IP username 156 /* Information from the Postfix SASL password file. 157 /* SECURITY 158 /* .ad 159 /* .fi 160 /* The caller does not sanitize the server reply. It is the 161 /* responsibility of the underlying SASL client implementation 162 /* to produce 7-bit ASCII without control characters as client 163 /* non-error and error replies. 164 /* DIAGNOSTICS 165 /* In case of error, xsasl_client_init() and xsasl_client_create() 166 /* log a warning and return a null pointer. 167 /* 168 /* Functions that normally return XSASL_AUTH_OK will log a warning 169 /* and return an appropriate result value. 170 /* 171 /* Panic: interface violation. 172 /* 173 /* Fatal errors: out of memory. 174 /* SEE ALSO 175 /* cyrus_security(3) Cyrus SASL security features 176 /* LICENSE 177 /* .ad 178 /* .fi 179 /* The Secure Mailer license must be distributed with this 180 /* software. 181 /* AUTHOR(S) 182 /* Wietse Venema 183 /* IBM T.J. Watson Research 184 /* P.O. Box 704 185 /* Yorktown Heights, NY 10598, USA 186 /*--*/ 187 188 /* System library. */ 189 190 #include <sys_defs.h> 191 #include <string.h> 192 193 /* Utility library. */ 194 195 #include <msg.h> 196 #include <mymalloc.h> 197 198 /* SASL implementations. */ 199 200 #include <xsasl.h> 201 #include <xsasl_cyrus.h> 202 203 /* 204 * Lookup table for available SASL client implementations. 205 */ 206 typedef struct { 207 char *client_type; 208 struct XSASL_CLIENT_IMPL *(*client_init) (const char *, const char *); 209 } XSASL_CLIENT_IMPL_INFO; 210 211 static const XSASL_CLIENT_IMPL_INFO client_impl_info[] = { 212 #ifdef XSASL_TYPE_CYRUS 213 XSASL_TYPE_CYRUS, xsasl_cyrus_client_init, 214 #endif 215 0, 216 }; 217 218 /* xsasl_client_init - look up client implementation by name */ 219 220 XSASL_CLIENT_IMPL *xsasl_client_init(const char *client_type, 221 const char *path_info) 222 { 223 const XSASL_CLIENT_IMPL_INFO *xp; 224 225 for (xp = client_impl_info; xp->client_type; xp++) 226 if (strcmp(client_type, xp->client_type) == 0) 227 return (xp->client_init(client_type, path_info)); 228 msg_warn("unsupported SASL client implementation: %s", client_type); 229 return (0); 230 } 231 232 /* xsasl_client_types - report available implementation types */ 233 234 ARGV *xsasl_client_types(void) 235 { 236 const XSASL_CLIENT_IMPL_INFO *xp; 237 ARGV *argv = argv_alloc(1); 238 239 for (xp = client_impl_info; xp->client_type; xp++) 240 argv_add(argv, xp->client_type, ARGV_END); 241 return (argv); 242 } 243