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#include <xsasl_saslc.h>
203
204 /*
205  * Lookup table for available SASL client implementations.
206  */
207typedef struct {
208    char   *client_type;
209    struct XSASL_CLIENT_IMPL *(*client_init) (const char *, const char *);
210} XSASL_CLIENT_IMPL_INFO;
211
212static 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
224XSASL_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
238ARGV   *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