Home | History | Annotate | Line # | Download | only in xsasl
      1 /*	$NetBSD: xsasl_client.c,v 1.2 2011/02/12 19:07:09 christos 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 #include <xsasl_saslc.h>
    203 
    204  /*
    205   * Lookup table for available SASL client implementations.
    206   */
    207 typedef struct {
    208     char   *client_type;
    209     struct XSASL_CLIENT_IMPL *(*client_init) (const char *, const char *);
    210 } XSASL_CLIENT_IMPL_INFO;
    211 
    212 static const XSASL_CLIENT_IMPL_INFO client_impl_info[] = {
    213 #ifdef XSASL_TYPE_CYRUS
    214     { XSASL_TYPE_CYRUS, xsasl_cyrus_client_init },
    215 #endif
    216 #ifdef XSASL_TYPE_SASLC
    217     { XSASL_TYPE_SASLC, xsasl_saslc_client_init },
    218 #endif
    219     { NULL, NULL }
    220 };
    221 
    222 /* xsasl_client_init - look up client implementation by name */
    223 
    224 XSASL_CLIENT_IMPL *xsasl_client_init(const char *client_type,
    225 				             const char *path_info)
    226 {
    227     const XSASL_CLIENT_IMPL_INFO *xp;
    228 
    229     for (xp = client_impl_info; xp->client_type; xp++)
    230 	if (strcmp(client_type, xp->client_type) == 0)
    231 	    return (xp->client_init(client_type, path_info));
    232     msg_warn("unsupported SASL client implementation: %s", client_type);
    233     return (0);
    234 }
    235 
    236 /* xsasl_client_types - report available implementation types */
    237 
    238 ARGV   *xsasl_client_types(void)
    239 {
    240     const XSASL_CLIENT_IMPL_INFO *xp;
    241     ARGV   *argv = argv_alloc(1);
    242 
    243     for (xp = client_impl_info; xp->client_type; xp++)
    244 	argv_add(argv, xp->client_type, ARGV_END);
    245     return (argv);
    246 }
    247