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

/* System library. */

#include <sys_defs.h>
#include <string.h>

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>

/* SASL implementations. */

#include <xsasl.h>
#include <xsasl_cyrus.h>
#include <xsasl_dovecot.h>

 /*
  * Lookup table for available SASL server implementations.
  */
typedef struct {
    char   *server_type;
    struct XSASL_SERVER_IMPL *(*server_init) (const char *, const char *);
} XSASL_SERVER_IMPL_INFO;

static const XSASL_SERVER_IMPL_INFO server_impl_info[] = {
#ifdef XSASL_TYPE_CYRUS
    {XSASL_TYPE_CYRUS, xsasl_cyrus_server_init},
#endif
#ifdef XSASL_TYPE_DOVECOT
    {XSASL_TYPE_DOVECOT, xsasl_dovecot_server_init},
#endif
    {0, 0}
};

/* xsasl_server_init - look up server implementation by name */

XSASL_SERVER_IMPL *xsasl_server_init(const char *server_type,
				             const char *path_info)
{
    const XSASL_SERVER_IMPL_INFO *xp;

    for (xp = server_impl_info; xp->server_type; xp++)
	if (strcmp(server_type, xp->server_type) == 0)
	    return (xp->server_init(server_type, path_info));
    msg_warn("unsupported SASL server implementation: %s", server_type);
    return (0);
}

/* xsasl_server_types - report available implementation types */

ARGV   *xsasl_server_types(void)
{
    const XSASL_SERVER_IMPL_INFO *xp;
    ARGV   *argv = argv_alloc(1);

    for (xp = server_impl_info; xp->server_type; xp++)
	argv_add(argv, xp->server_type, ARGV_END);
    return (argv);
}