summaryrefslogtreecommitdiffstats
path: root/src/xsasl/xsasl_client.c
blob: 0bddd41ef248e08de2c8b319e6c83765fb588b50 (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
/*++
/* NAME
/*	xsasl_client 3
/* SUMMARY
/*	Postfix SASL client plug-in interface
/* SYNOPSIS
/*	#include <xsasl.h>
/*
/*	XSASL_CLIENT_IMPL *xsasl_client_init(client_type, path_info)
/*	const char *client_type;
/*	const char *path_info;
/*
/*	void	xsasl_client_done(implementation)
/*	XSASL_CLIENT_IMPL *implementation;
/*
/*	ARGV	*xsasl_client_types()
/*
/* .in +4
/*	typedef struct XSASL_CLIENT_CREATE_ARGS {
/*		VSTREAM	*stream;
/*		const char *service;
/*		const char *server_name;
/*		const char *security_options;
/*	} XSASL_CLIENT_CREATE_ARGS;
/* .in -4
/*
/*	XSASL_CLIENT *xsasl_client_create(implementation, create_args)
/*	XSASL_CLIENT_IMPL *implementation;
/*	XSASL_CLIENT_CREATE_ARGS *create_args;
/*
/*	XSASL_CLIENT *XSASL_CLIENT_CREATE(implementation, create_args,
/*					stream = stream_val,
/*					...,
/*					security_options = prop_val)
/*	XSASL_CLIENT_IMPL *implementation;
/*	XSASL_CLIENT_CREATE_ARGS *create_args;
/*
/*	void	xsasl_client_free(client)
/*	XSASL_CLIENT *client;
/*
/*	int	xsasl_client_first(client, stream, mech_list, username,
/*					password, auth_method, init_resp)
/*	XSASL_CLIENT *client;
/*	const char *mech_list;
/*	const char *username;
/*	const char *password;
/*	const char **auth_method;
/*	VSTRING *init_resp;
/*
/*	int	xsasl_client_next(client, server_reply, client_reply)
/*	XSASL_CLIENT *client;
/*	const char *server_reply;
/*	VSTRING *client_reply;
/* DESCRIPTION
/*	The XSASL_CLIENT abstraction implements a generic interface
/*	to one or more SASL authentication implementations.
/*
/*	xsasl_client_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 client instances. This function is typically used to
/*	initialize the underlying implementation.
/*
/*	xsasl_client_done() disposes of an implementation handle,
/*	and allows the underlying implementation to release resources.
/*
/*	xsasl_client_types() lists the available implementation types.
/*	The result should be destroyed by the caller.
/*
/*	xsasl_client_create() is called at the start of an SMTP
/*	session. It generates a Postfix SASL plug-in client instance
/*	for the specified service and server name, with the specified
/*	security properties. The stream handle is stored so that
/*	encryption can be turned on after successful negotiations.
/*
/*	XSASL_CLIENT_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_CLIENT_CREATE_ARGS structure.
/*
/*	xsasl_client_free() is called at the end of an SMTP session.
/*	It destroys a SASL client instance, and disables further
/*	read/write operations if encryption was turned on.
/*
/*	xsasl_client_first() produces the client input for the AUTH
/*	command. The input is an authentication method list from
/*	an EHLO response, a username and a password. On return, the
/*	method argument specifies the authentication method; storage
/*	space is owned by the underlying implementation.  The initial
/*	response and client non-error replies are BASE64 encoded.
/*	Client error replies are 7-bit ASCII text without control
/*	characters, and without BASE64 encoding. They are meant for
/*	the local application, not for transmission to the server.
/*	The client may negotiate encryption of the client-server
/*	connection.
/*
/*	The result is one of the following:
/* .IP XSASL_AUTH_OK
/*	Success.
/* .IP XSASL_AUTH_FORM
/*	The server reply is incorrectly formatted. The client error
/*	reply explains why.
/* .IP XSASL_AUTH_FAIL
/*	Other error. The client error reply explains why.
/* .PP
/*	xsasl_client_next() supports the subsequent stages of the
/*	AUTH protocol. Both the client reply and client non-error
/*	responses are BASE64 encoded.  See xsasl_client_first() for
/*	other details.
/*
/*	Arguments:
/* .IP client
/*	SASL plug-in client handle.
/* .IP client_reply
/*	BASE64 encoded non-error client reply, or ASCII error
/*	description for the user.
/* .IP client_type
/*	The name of a Postfix SASL client plug_in implementation.
/* .IP client_types
/*	Null-terminated array of strings with SASL client plug-in
/*	implementation names.
/* .IP init_resp
/*	The AUTH command initial response.
/* .IP implementation
/*	Implementation handle that was obtained with xsasl_client_init().
/* .IP mech_list
/*	List of SASL mechanisms as announced by the server.
/* .IP auth_method
/*	The AUTH command authentication method.
/* .IP password
/*	Information from the Postfix SASL password file or equivalent.
/* .IP path_info
/*	The value of the smtp_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 smtp_sasl_security_options parameter or
/*	equivalent. This is passed unchanged to the plug-in.
/* .IP server_name
/*	The remote server fully qualified hostname.
/* .IP server_reply
/*	BASE64 encoded server reply without SMTP reply code or
/*	enhanced status code.
/* .IP service
/*	The service that is implemented by the local client (typically,
/*	"lmtp" or "smtp").
/* .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 username
/*	Information from the Postfix SASL password file.
/* SECURITY
/* .ad
/* .fi
/*	The caller does not sanitize the server reply. It is the
/*	responsibility of the underlying SASL client implementation
/*	to produce 7-bit ASCII without control characters as client
/*	non-error and error replies.
/* DIAGNOSTICS
/*	In case of error, xsasl_client_init() and xsasl_client_create()
/*	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.
/*
/*	Panic: interface violation.
/*
/*	Fatal errors: out of memory.
/* 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
/*--*/

/* 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>

 /*
  * Lookup table for available SASL client implementations.
  */
typedef struct {
    char   *client_type;
    struct XSASL_CLIENT_IMPL *(*client_init) (const char *, const char *);
} XSASL_CLIENT_IMPL_INFO;

static const XSASL_CLIENT_IMPL_INFO client_impl_info[] = {
#ifdef XSASL_TYPE_CYRUS
    XSASL_TYPE_CYRUS, xsasl_cyrus_client_init,
#endif
    0,
};

/* xsasl_client_init - look up client implementation by name */

XSASL_CLIENT_IMPL *xsasl_client_init(const char *client_type,
				             const char *path_info)
{
    const XSASL_CLIENT_IMPL_INFO *xp;

    for (xp = client_impl_info; xp->client_type; xp++)
	if (strcmp(client_type, xp->client_type) == 0)
	    return (xp->client_init(client_type, path_info));
    msg_warn("unsupported SASL client implementation: %s", client_type);
    return (0);
}

/* xsasl_client_types - report available implementation types */

ARGV   *xsasl_client_types(void)
{
    const XSASL_CLIENT_IMPL_INFO *xp;
    ARGV   *argv = argv_alloc(1);

    for (xp = client_impl_info; xp->client_type; xp++)
	argv_add(argv, xp->client_type, ARGV_END);
    return (argv);
}