Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / xsasl / xsasl_dovecot_server.c
blob1e7fface2aa3e4e34ae1b34873904a19004b991a
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* xsasl_dovecot_server 3
6 /* SUMMARY
7 /* Dovecot SASL server-side plug-in
8 /* SYNOPSIS
9 /* XSASL_SERVER_IMPL *xsasl_dovecot_server_init(server_type, appl_name)
10 /* const char *server_type;
11 /* const char *appl_name;
12 /* DESCRIPTION
13 /* This module implements the Dovecot SASL server-side authentication
14 /* plug-in.
16 /* .IP server_type
17 /* The plug-in type that was specified to xsasl_server_init().
18 /* The argument is ignored, because the Dovecot plug-in
19 /* implements only one plug-in type.
20 /* .IP path_info
21 /* The location of the Dovecot authentication server's UNIX-domain
22 /* socket. Note: the Dovecot plug-in uses late binding, therefore
23 /* all connect operations are done with Postfix privileges.
24 /* DIAGNOSTICS
25 /* Fatal: out of memory.
27 /* Panic: interface violation.
29 /* Other: the routines log a warning and return an error result
30 /* as specified in xsasl_server(3).
31 /* LICENSE
32 /* .ad
33 /* .fi
34 /* The Secure Mailer license must be distributed with this software.
35 /* AUTHOR(S)
36 /* Initial implementation by:
37 /* Timo Sirainen
38 /* Procontrol
39 /* Finland
41 /* Adopted by:
42 /* Wietse Venema
43 /* IBM T.J. Watson Research
44 /* P.O. Box 704
45 /* Yorktown Heights, NY 10598, USA
46 /*--*/
48 /* System library. */
50 #include <sys_defs.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
55 #ifdef STRCASECMP_IN_STRINGS_H
56 #include <strings.h>
57 #endif
59 /* Utility library. */
61 #include <msg.h>
62 #include <mymalloc.h>
63 #include <connect.h>
64 #include <split_at.h>
65 #include <stringops.h>
66 #include <vstream.h>
67 #include <vstring_vstream.h>
68 #include <name_mask.h>
69 #include <argv.h>
70 #include <myaddrinfo.h>
72 /* Global library. */
74 #include <mail_params.h>
76 /* Application-specific. */
78 #include <xsasl.h>
79 #include <xsasl_dovecot.h>
81 #ifdef USE_SASL_AUTH
83 /* Major version changes are not backwards compatible,
84 minor version numbers can be ignored. */
85 #define AUTH_PROTOCOL_MAJOR_VERSION 1
86 #define AUTH_PROTOCOL_MINOR_VERSION 0
89 * Encorce read/write time limits, so that we can produce accurate
90 * diagnostics instead of getting killed by the watchdog timer.
92 #define AUTH_TIMEOUT 10
95 * Security property bitmasks.
97 #define SEC_PROPS_NOPLAINTEXT (1 << 0)
98 #define SEC_PROPS_NOACTIVE (1 << 1)
99 #define SEC_PROPS_NODICTIONARY (1 << 2)
100 #define SEC_PROPS_NOANONYMOUS (1 << 3)
101 #define SEC_PROPS_FWD_SECRECY (1 << 4)
102 #define SEC_PROPS_MUTUAL_AUTH (1 << 5)
103 #define SEC_PROPS_PRIVATE (1 << 6)
105 #define SEC_PROPS_POS_MASK (SEC_PROPS_MUTUAL_AUTH | SEC_PROPS_FWD_SECRECY)
106 #define SEC_PROPS_NEG_MASK (SEC_PROPS_NOPLAINTEXT | SEC_PROPS_NOACTIVE | \
107 SEC_PROPS_NODICTIONARY | SEC_PROPS_NOANONYMOUS)
110 * Security properties as specified in the Postfix main.cf file.
112 static const NAME_MASK xsasl_dovecot_conf_sec_props[] = {
113 "noplaintext", SEC_PROPS_NOPLAINTEXT,
114 "noactive", SEC_PROPS_NOACTIVE,
115 "nodictionary", SEC_PROPS_NODICTIONARY,
116 "noanonymous", SEC_PROPS_NOANONYMOUS,
117 "forward_secrecy", SEC_PROPS_FWD_SECRECY,
118 "mutual_auth", SEC_PROPS_MUTUAL_AUTH,
119 0, 0,
123 * Security properties as specified in the Dovecot protocol. See
124 * http://wiki.dovecot.org/Authentication_Protocol.
126 static const NAME_MASK xsasl_dovecot_serv_sec_props[] = {
127 "plaintext", SEC_PROPS_NOPLAINTEXT,
128 "active", SEC_PROPS_NOACTIVE,
129 "dictionary", SEC_PROPS_NODICTIONARY,
130 "anonymous", SEC_PROPS_NOANONYMOUS,
131 "forward-secrecy", SEC_PROPS_FWD_SECRECY,
132 "mutual-auth", SEC_PROPS_MUTUAL_AUTH,
133 "private", SEC_PROPS_PRIVATE,
134 0, 0,
138 * Class variables.
140 typedef struct XSASL_DCSRV_MECH {
141 char *mech_name; /* mechanism name */
142 int sec_props; /* mechanism properties */
143 struct XSASL_DCSRV_MECH *next;
144 } XSASL_DCSRV_MECH;
146 typedef struct {
147 XSASL_SERVER_IMPL xsasl;
148 VSTREAM *sasl_stream;
149 char *socket_path;
150 XSASL_DCSRV_MECH *mechanism_list; /* unfiltered mechanism list */
151 unsigned int request_id_counter;
152 } XSASL_DOVECOT_SERVER_IMPL;
155 * The XSASL_DOVECOT_SERVER object is derived from the generic XSASL_SERVER
156 * object.
158 typedef struct {
159 XSASL_SERVER xsasl; /* generic members, must be first */
160 XSASL_DOVECOT_SERVER_IMPL *impl;
161 unsigned int last_request_id;
162 char *service;
163 char *username; /* authenticated user */
164 VSTRING *sasl_line;
165 unsigned int sec_props; /* Postfix mechanism filter */
166 int tls_flag; /* TLS enabled in this session */
167 char *mechanism_list; /* filtered mechanism list */
168 ARGV *mechanism_argv; /* ditto */
169 char *client_addr; /* remote IP address */
170 char *server_addr; /* remote IP address */
171 } XSASL_DOVECOT_SERVER;
174 * Forward declarations.
176 static void xsasl_dovecot_server_done(XSASL_SERVER_IMPL *);
177 static XSASL_SERVER *xsasl_dovecot_server_create(XSASL_SERVER_IMPL *,
178 XSASL_SERVER_CREATE_ARGS *);
179 static void xsasl_dovecot_server_free(XSASL_SERVER *);
180 static int xsasl_dovecot_server_first(XSASL_SERVER *, const char *,
181 const char *, VSTRING *);
182 static int xsasl_dovecot_server_next(XSASL_SERVER *, const char *, VSTRING *);
183 static const char *xsasl_dovecot_server_get_mechanism_list(XSASL_SERVER *);
184 static const char *xsasl_dovecot_server_get_username(XSASL_SERVER *);
186 /* xsasl_dovecot_server_mech_append - append server mechanism entry */
188 static void xsasl_dovecot_server_mech_append(XSASL_DCSRV_MECH **mech_list,
189 const char *mech_name, int sec_props)
191 XSASL_DCSRV_MECH **mpp;
192 XSASL_DCSRV_MECH *mp;
194 for (mpp = mech_list; *mpp != 0; mpp = &mpp[0]->next)
195 /* void */ ;
197 mp = (XSASL_DCSRV_MECH *) mymalloc(sizeof(*mp));
198 mp->mech_name = mystrdup(mech_name);
199 mp->sec_props = sec_props;
200 mp->next = 0;
201 *mpp = mp;
204 /* xsasl_dovecot_server_mech_free - destroy server mechanism list */
206 static void xsasl_dovecot_server_mech_free(XSASL_DCSRV_MECH *mech_list)
208 XSASL_DCSRV_MECH *mp;
209 XSASL_DCSRV_MECH *next;
211 for (mp = mech_list; mp != 0; mp = next) {
212 myfree(mp->mech_name);
213 next = mp->next;
214 myfree((char *) mp);
218 /* xsasl_dovecot_server_mech_filter - filter server mechanism list */
220 static char *xsasl_dovecot_server_mech_filter(ARGV *mechanism_argv,
221 XSASL_DCSRV_MECH *mechanism_list,
222 unsigned int conf_props)
224 const char *myname = "xsasl_dovecot_server_mech_filter";
225 unsigned int pos_conf_props = (conf_props & SEC_PROPS_POS_MASK);
226 unsigned int neg_conf_props = (conf_props & SEC_PROPS_NEG_MASK);
227 VSTRING *mechanisms_str = vstring_alloc(10);
228 XSASL_DCSRV_MECH *mp;
231 * Match Postfix properties against Dovecot server properties.
233 for (mp = mechanism_list; mp != 0; mp = mp->next) {
234 if ((mp->sec_props & pos_conf_props) == pos_conf_props
235 && (mp->sec_props & neg_conf_props) == 0) {
236 if (VSTRING_LEN(mechanisms_str) > 0)
237 VSTRING_ADDCH(mechanisms_str, ' ');
238 vstring_strcat(mechanisms_str, mp->mech_name);
239 argv_add(mechanism_argv, mp->mech_name, (char *) 0);
240 if (msg_verbose)
241 msg_info("%s: keep mechanism: %s", myname, mp->mech_name);
242 } else {
243 if (msg_verbose)
244 msg_info("%s: skip mechanism: %s", myname, mp->mech_name);
247 return (vstring_export(mechanisms_str));
250 /* xsasl_dovecot_server_connect - initial auth server handshake */
252 static int xsasl_dovecot_server_connect(XSASL_DOVECOT_SERVER_IMPL *xp)
254 const char *myname = "xsasl_dovecot_server_connect";
255 VSTRING *line_str;
256 VSTREAM *sasl_stream;
257 char *line, *cmd, *mech_name;
258 unsigned int major_version, minor_version;
259 int fd, success;
260 int sec_props;
261 const char *path;
263 if (msg_verbose)
264 msg_info("%s: Connecting", myname);
267 * Not documented, but necessary for testing.
269 path = xp->socket_path;
270 if (strncmp(path, "inet:", 5) == 0) {
271 fd = inet_connect(path + 5, BLOCKING, AUTH_TIMEOUT);
272 } else {
273 if (strncmp(path, "unix:", 5) == 0)
274 path += 5;
275 fd = unix_connect(path, BLOCKING, AUTH_TIMEOUT);
277 if (fd < 0) {
278 msg_warn("SASL: Connect to %s failed: %m", xp->socket_path);
279 return (-1);
281 sasl_stream = vstream_fdopen(fd, O_RDWR);
282 vstream_control(sasl_stream,
283 VSTREAM_CTL_PATH, xp->socket_path,
284 VSTREAM_CTL_TIMEOUT, AUTH_TIMEOUT,
285 VSTREAM_CTL_END);
287 /* XXX Encapsulate for logging. */
288 vstream_fprintf(sasl_stream,
289 "VERSION\t%u\t%u\n"
290 "CPID\t%u\n",
291 AUTH_PROTOCOL_MAJOR_VERSION,
292 AUTH_PROTOCOL_MINOR_VERSION,
293 (unsigned int) getpid());
294 if (vstream_fflush(sasl_stream) == VSTREAM_EOF) {
295 msg_warn("SASL: Couldn't send handshake: %m");
296 return (-1);
298 success = 0;
299 line_str = vstring_alloc(256);
300 /* XXX Encapsulate for logging. */
301 while (vstring_get_nonl(line_str, sasl_stream) != VSTREAM_EOF) {
302 line = vstring_str(line_str);
304 if (msg_verbose)
305 msg_info("%s: auth reply: %s", myname, line);
307 cmd = line;
308 line = split_at(line, '\t');
310 if (strcmp(cmd, "VERSION") == 0) {
311 if (sscanf(line, "%u\t%u", &major_version, &minor_version) != 2) {
312 msg_warn("SASL: Protocol version error");
313 break;
315 if (major_version != AUTH_PROTOCOL_MAJOR_VERSION) {
316 /* Major version is different from ours. */
317 msg_warn("SASL: Protocol version mismatch (%d vs. %d)",
318 major_version, AUTH_PROTOCOL_MAJOR_VERSION);
319 break;
321 } else if (strcmp(cmd, "MECH") == 0 && line != NULL) {
322 mech_name = line;
323 line = split_at(line, '\t');
324 if (line != 0) {
325 sec_props =
326 name_mask_delim_opt(myname,
327 xsasl_dovecot_serv_sec_props,
328 line, "\t", NAME_MASK_ANY_CASE);
329 if ((sec_props & SEC_PROPS_PRIVATE) != 0)
330 continue;
331 } else
332 sec_props = 0;
333 xsasl_dovecot_server_mech_append(&xp->mechanism_list, mech_name,
334 sec_props);
335 } else if (strcmp(cmd, "DONE") == 0) {
336 /* Handshake finished. */
337 success = 1;
338 break;
339 } else {
340 /* ignore any unknown commands */
343 vstring_free(line_str);
345 if (!success) {
346 /* handshake failed */
347 (void) vstream_fclose(sasl_stream);
348 return (-1);
350 xp->sasl_stream = sasl_stream;
351 return (0);
354 /* xsasl_dovecot_server_disconnect - dispose of server connection state */
356 static void xsasl_dovecot_server_disconnect(XSASL_DOVECOT_SERVER_IMPL *xp)
358 if (xp->sasl_stream) {
359 (void) vstream_fclose(xp->sasl_stream);
360 xp->sasl_stream = 0;
362 if (xp->mechanism_list) {
363 xsasl_dovecot_server_mech_free(xp->mechanism_list);
364 xp->mechanism_list = 0;
368 /* xsasl_dovecot_server_init - create implementation handle */
370 XSASL_SERVER_IMPL *xsasl_dovecot_server_init(const char *unused_server_type,
371 const char *path_info)
373 XSASL_DOVECOT_SERVER_IMPL *xp;
375 xp = (XSASL_DOVECOT_SERVER_IMPL *) mymalloc(sizeof(*xp));
376 xp->xsasl.create = xsasl_dovecot_server_create;
377 xp->xsasl.done = xsasl_dovecot_server_done;
378 xp->socket_path = mystrdup(path_info);
379 xp->sasl_stream = 0;
380 xp->mechanism_list = 0;
381 xp->request_id_counter = 0;
382 return (&xp->xsasl);
385 /* xsasl_dovecot_server_done - dispose of implementation */
387 static void xsasl_dovecot_server_done(XSASL_SERVER_IMPL *impl)
389 XSASL_DOVECOT_SERVER_IMPL *xp = (XSASL_DOVECOT_SERVER_IMPL *) impl;
391 xsasl_dovecot_server_disconnect(xp);
392 myfree(xp->socket_path);
393 myfree((char *) impl);
396 /* xsasl_dovecot_server_create - create server instance */
398 static XSASL_SERVER *xsasl_dovecot_server_create(XSASL_SERVER_IMPL *impl,
399 XSASL_SERVER_CREATE_ARGS *args)
401 const char *myname = "xsasl_dovecot_server_create";
402 XSASL_DOVECOT_SERVER *server;
403 struct sockaddr_storage ss;
404 struct sockaddr *sa = (struct sockaddr *) & ss;
405 SOCKADDR_SIZE salen;
406 MAI_HOSTADDR_STR server_addr;
408 if (msg_verbose)
409 msg_info("%s: SASL service=%s, realm=%s",
410 myname, args->service, args->user_realm ?
411 args->user_realm : "(null)");
414 * Extend the XSASL_SERVER_IMPL object with our own data. We use
415 * long-lived conversion buffers rather than local variables to avoid
416 * memory leaks in case of read/write timeout or I/O error.
418 server = (XSASL_DOVECOT_SERVER *) mymalloc(sizeof(*server));
419 server->xsasl.free = xsasl_dovecot_server_free;
420 server->xsasl.first = xsasl_dovecot_server_first;
421 server->xsasl.next = xsasl_dovecot_server_next;
422 server->xsasl.get_mechanism_list = xsasl_dovecot_server_get_mechanism_list;
423 server->xsasl.get_username = xsasl_dovecot_server_get_username;
424 server->impl = (XSASL_DOVECOT_SERVER_IMPL *) impl;
425 server->sasl_line = vstring_alloc(256);
426 server->username = 0;
427 server->service = mystrdup(args->service);
428 server->last_request_id = 0;
429 server->mechanism_list = 0;
430 server->mechanism_argv = 0;
431 server->tls_flag = args->tls_flag;
432 server->sec_props =
433 name_mask_opt(myname, xsasl_dovecot_conf_sec_props,
434 args->security_options,
435 NAME_MASK_ANY_CASE | NAME_MASK_FATAL);
436 server->client_addr = mystrdup(args->client_addr);
439 * XXX Temporary code until smtpd_peer.c is updated.
441 if (args->server_addr && *args->server_addr) {
442 server->server_addr = mystrdup(args->server_addr);
443 } else {
444 salen = sizeof(ss);
445 if (getsockname(vstream_fileno(args->stream), sa, &salen) < 0
446 || sockaddr_to_hostaddr(sa, salen, &server_addr, 0, 0) != 0)
447 server_addr.buf[0] = 0;
448 server->server_addr = mystrdup(server_addr.buf);
451 return (&server->xsasl);
454 /* xsasl_dovecot_server_get_mechanism_list - get available mechanisms */
456 static const char *xsasl_dovecot_server_get_mechanism_list(XSASL_SERVER *xp)
458 XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
460 if (!server->impl->sasl_stream) {
461 if (xsasl_dovecot_server_connect(server->impl) < 0)
462 return (0);
464 if (server->mechanism_list == 0) {
465 server->mechanism_argv = argv_alloc(2);
466 server->mechanism_list =
467 xsasl_dovecot_server_mech_filter(server->mechanism_argv,
468 server->impl->mechanism_list,
469 server->sec_props);
471 return (server->mechanism_list[0] ? server->mechanism_list : 0);
474 /* xsasl_dovecot_server_free - destroy server instance */
476 static void xsasl_dovecot_server_free(XSASL_SERVER *xp)
478 XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
480 vstring_free(server->sasl_line);
481 if (server->username)
482 myfree(server->username);
483 if (server->mechanism_list) {
484 myfree(server->mechanism_list);
485 argv_free(server->mechanism_argv);
487 myfree(server->service);
488 myfree(server->server_addr);
489 myfree(server->client_addr);
490 myfree((char *) server);
493 /* xsasl_dovecot_server_auth_response - encode server first/next response */
495 static int xsasl_dovecot_parse_reply(XSASL_DOVECOT_SERVER *server, char **line)
497 char *id;
499 if (*line == NULL) {
500 msg_warn("SASL: Protocol error");
501 return -1;
503 id = *line;
504 *line = split_at(*line, '\t');
506 if (strtoul(id, NULL, 0) != server->last_request_id) {
507 /* reply to another request, shouldn't really happen.. */
508 return -1;
510 return 0;
513 static void xsasl_dovecot_parse_reply_args(XSASL_DOVECOT_SERVER *server,
514 char *line, VSTRING *reply,
515 int success)
517 char *next;
519 if (server->username) {
520 myfree(server->username);
521 server->username = 0;
525 * Note: TAB is part of the Dovecot protocol and must not appear in
526 * legitimate Dovecot usernames, otherwise the protocol would break.
528 for (; line != NULL; line = next) {
529 next = split_at(line, '\t');
530 if (strncmp(line, "user=", 5) == 0) {
531 server->username = mystrdup(line + 5);
532 printable(server->username, '?');
533 } else if (strncmp(line, "reason=", 7) == 0) {
534 if (!success) {
535 printable(line + 7, '?');
536 vstring_strcpy(reply, line + 7);
542 /* xsasl_dovecot_handle_reply - receive and process auth reply */
544 static int xsasl_dovecot_handle_reply(XSASL_DOVECOT_SERVER *server,
545 VSTRING *reply)
547 const char *myname = "xsasl_dovecot_handle_reply";
548 char *line, *cmd;
550 /* XXX Encapsulate for logging. */
551 while (vstring_get_nonl(server->sasl_line,
552 server->impl->sasl_stream) != VSTREAM_EOF) {
553 line = vstring_str(server->sasl_line);
555 if (msg_verbose)
556 msg_info("%s: auth reply: %s", myname, line);
558 cmd = line;
559 line = split_at(line, '\t');
561 if (strcmp(cmd, "OK") == 0) {
562 if (xsasl_dovecot_parse_reply(server, &line) == 0) {
563 /* authentication successful */
564 xsasl_dovecot_parse_reply_args(server, line, reply, 1);
565 return XSASL_AUTH_DONE;
567 } else if (strcmp(cmd, "CONT") == 0) {
568 if (xsasl_dovecot_parse_reply(server, &line) == 0) {
569 vstring_strcpy(reply, line);
570 return XSASL_AUTH_MORE;
572 } else if (strcmp(cmd, "FAIL") == 0) {
573 if (xsasl_dovecot_parse_reply(server, &line) == 0) {
574 /* authentication failure */
575 xsasl_dovecot_parse_reply_args(server, line, reply, 0);
576 return XSASL_AUTH_FAIL;
578 } else {
579 /* ignore */
583 vstring_strcpy(reply, "Connection lost to authentication server");
584 return XSASL_AUTH_FAIL;
587 /* is_valid_base64 - input sanitized */
589 static int is_valid_base64(const char *data)
593 * XXX Maybe use ISALNUM() (isascii && isalnum, i.e. locale independent).
595 for (; *data != '\0'; data++) {
596 if (!((*data >= '0' && *data <= '9') ||
597 (*data >= 'a' && *data <= 'z') ||
598 (*data >= 'A' && *data <= 'Z') ||
599 *data == '+' || *data == '/' || *data == '='))
600 return 0;
602 return 1;
605 /* xsasl_dovecot_server_first - per-session authentication */
607 int xsasl_dovecot_server_first(XSASL_SERVER *xp, const char *sasl_method,
608 const char *init_response, VSTRING *reply)
610 const char *myname = "xsasl_dovecot_server_first";
611 XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
612 int i;
613 char **cpp;
615 #define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
617 if (msg_verbose)
618 msg_info("%s: sasl_method %s%s%s", myname, sasl_method,
619 IFELSE(init_response, ", init_response ", ""),
620 IFELSE(init_response, init_response, ""));
622 if (server->mechanism_argv == 0)
623 msg_panic("%s: no mechanism list", myname);
625 for (cpp = server->mechanism_argv->argv; /* see below */ ; cpp++) {
626 if (*cpp == 0) {
627 vstring_strcpy(reply, "Invalid authentication mechanism");
628 return XSASL_AUTH_FAIL;
630 if (strcasecmp(sasl_method, *cpp) == 0)
631 break;
633 if (init_response)
634 if (!is_valid_base64(init_response)) {
635 vstring_strcpy(reply, "Invalid base64 data in initial response");
636 return XSASL_AUTH_FAIL;
638 for (i = 0; i < 2; i++) {
639 if (!server->impl->sasl_stream) {
640 if (xsasl_dovecot_server_connect(server->impl) < 0)
641 return (0);
643 /* send the request */
644 server->last_request_id = ++server->impl->request_id_counter;
645 /* XXX Encapsulate for logging. */
646 vstream_fprintf(server->impl->sasl_stream,
647 "AUTH\t%u\t%s\tservice=%s\tnologin\tlip=%s\trip=%s",
648 server->last_request_id, sasl_method,
649 server->service, server->server_addr,
650 server->client_addr);
651 if (server->tls_flag)
652 /* XXX Encapsulate for logging. */
653 vstream_fputs("\tsecured", server->impl->sasl_stream);
654 if (init_response) {
657 * initial response is already base64 encoded, so we can send it
658 * directly.
660 /* XXX Encapsulate for logging. */
661 vstream_fprintf(server->impl->sasl_stream,
662 "\tresp=%s", init_response);
664 /* XXX Encapsulate for logging. */
665 VSTREAM_PUTC('\n', server->impl->sasl_stream);
667 if (vstream_fflush(server->impl->sasl_stream) != VSTREAM_EOF)
668 break;
670 if (i == 1) {
671 vstring_strcpy(reply, "Can't connect to authentication server");
672 return XSASL_AUTH_FAIL;
676 * Reconnect and try again.
678 xsasl_dovecot_server_disconnect(server->impl);
681 return xsasl_dovecot_handle_reply(server, reply);
684 /* xsasl_dovecot_server_next - continue authentication */
686 static int xsasl_dovecot_server_next(XSASL_SERVER *xp, const char *request,
687 VSTRING *reply)
689 XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
691 if (!is_valid_base64(request)) {
692 vstring_strcpy(reply, "Invalid base64 data in continued response");
693 return XSASL_AUTH_FAIL;
695 /* XXX Encapsulate for logging. */
696 vstream_fprintf(server->impl->sasl_stream,
697 "CONT\t%u\t%s\n", server->last_request_id, request);
698 if (vstream_fflush(server->impl->sasl_stream) == VSTREAM_EOF) {
699 vstring_strcpy(reply, "Connection lost to authentication server");
700 return XSASL_AUTH_FAIL;
702 return xsasl_dovecot_handle_reply(server, reply);
705 /* xsasl_dovecot_server_get_username - get authenticated username */
707 static const char *xsasl_dovecot_server_get_username(XSASL_SERVER *xp)
709 XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
711 return (server->username);
714 #endif