Postfix3.3.1
xsasl_cyrus_server.c
[詳解]
1 /*++
2 /* NAME
3 /* xsasl_cyrus_server 3
4 /* SUMMARY
5 /* Cyrus SASL server-side plug-in
6 /* SYNOPSIS
7 /* #include <xsasl_cyrus_server.h>
8 /*
9 /* XSASL_SERVER_IMPL *xsasl_cyrus_server_init(server_type, path_info)
10 /* const char *server_type;
11 /* const char *path_info;
12 /* DESCRIPTION
13 /* This module implements the Cyrus SASL server-side authentication
14 /* plug-in.
15 /*
16 /* xsasl_cyrus_server_init() initializes the Cyrus SASL library and
17 /* returns an implementation handle that can be used to generate
18 /* SASL server instances.
19 /*
20 /* Arguments:
21 /* .IP server_type
22 /* The server type (cyrus). This argument is ignored, but it
23 /* could be used when one implementation provides multiple
24 /* variants.
25 /* .IP path_info
26 /* The base name of the SASL server configuration file (example:
27 /* smtpd becomes /usr/lib/sasl2/smtpd.conf).
28 /* DIAGNOSTICS
29 /* Fatal: out of memory.
30 /*
31 /* Panic: interface violation.
32 /*
33 /* Other: the routines log a warning and return an error result
34 /* as specified in xsasl_server(3).
35 /* LICENSE
36 /* .ad
37 /* .fi
38 /* The Secure Mailer license must be distributed with this software.
39 /* AUTHOR(S)
40 /* Initial implementation by:
41 /* Till Franke
42 /* SuSE Rhein/Main AG
43 /* 65760 Eschborn, Germany
44 /*
45 /* Adopted by:
46 /* Wietse Venema
47 /* IBM T.J. Watson Research
48 /* P.O. Box 704
49 /* Yorktown Heights, NY 10598, USA
50 /*
51 /* Wietse Venema
52 /* Google, Inc.
53 /* 111 8th Avenue
54 /* New York, NY 10011, USA
55 /*--*/
56 
57 /* System library. */
58 
59 #include <sys_defs.h>
60 #include <sys/socket.h>
61 #include <stdlib.h>
62 #include <string.h>
63 
64 /* Utility library. */
65 
66 #include <msg.h>
67 #include <mymalloc.h>
68 #include <name_mask.h>
69 #include <stringops.h>
70 
71 /* Global library. */
72 
73 #include <mail_params.h>
74 
75 /* Application-specific. */
76 
77 #include <xsasl.h>
78 #include <xsasl_cyrus.h>
79 #include <xsasl_cyrus_common.h>
80 
81 #if defined(USE_SASL_AUTH) && defined(USE_CYRUS_SASL)
82 
83 #include <sasl.h>
84 #include <saslutil.h>
85 
86 /*
87  * Silly little macros.
88  */
89 #define STR(s) vstring_str(s)
90 
91  /*
92  * Macros to handle API differences between SASLv1 and SASLv2. Specifics:
93  *
94  * The SASL_LOG_* constants were renamed in SASLv2.
95  *
96  * SASLv2's sasl_server_new takes two new parameters to specify local and
97  * remote IP addresses for auth mechs that use them.
98  *
99  * SASLv2's sasl_server_start and sasl_server_step no longer have the errstr
100  * parameter.
101  *
102  * SASLv2's sasl_decode64 function takes an extra parameter for the length of
103  * the output buffer.
104  *
105  * The other major change is that SASLv2 now takes more responsibility for
106  * deallocating memory that it allocates internally. Thus, some of the
107  * function parameters are now 'const', to make sure we don't try to free
108  * them too. This is dealt with in the code later on.
109  */
110 
111 #if SASL_VERSION_MAJOR < 2
112 /* SASL version 1.x */
113 #define SASL_SERVER_NEW(srv, fqdn, rlm, lport, rport, cb, secflags, pconn) \
114  sasl_server_new(srv, fqdn, rlm, cb, secflags, pconn)
115 #define SASL_SERVER_START(conn, mech, clin, clinlen, srvout, srvoutlen, err) \
116  sasl_server_start(conn, mech, clin, clinlen, srvout, srvoutlen, err)
117 #define SASL_SERVER_STEP(conn, clin, clinlen, srvout, srvoutlen, err) \
118  sasl_server_step(conn, clin, clinlen, srvout, srvoutlen, err)
119 #define SASL_DECODE64(in, inlen, out, outmaxlen, outlen) \
120  sasl_decode64(in, inlen, out, outlen)
121 typedef char *MECHANISM_TYPE;
122 typedef unsigned MECHANISM_COUNT_TYPE;
123 typedef char *SERVEROUT_TYPE;
124 typedef void *VOID_SERVEROUT_TYPE;
125 
126 #endif
127 
128 #if SASL_VERSION_MAJOR >= 2
129 /* SASL version > 2.x */
130 #define SASL_SERVER_NEW(srv, fqdn, rlm, lport, rport, cb, secflags, pconn) \
131  sasl_server_new(srv, fqdn, rlm, lport, rport, cb, secflags, pconn)
132 #define SASL_SERVER_START(conn, mech, clin, clinlen, srvout, srvoutlen, err) \
133  sasl_server_start(conn, mech, clin, clinlen, srvout, srvoutlen)
134 #define SASL_SERVER_STEP(conn, clin, clinlen, srvout, srvoutlen, err) \
135  sasl_server_step(conn, clin, clinlen, srvout, srvoutlen)
136 #define SASL_DECODE64(in, inlen, out, outmaxlen, outlen) \
137  sasl_decode64(in, inlen, out, outmaxlen, outlen)
138 typedef const char *MECHANISM_TYPE;
139 typedef int MECHANISM_COUNT_TYPE;
140 typedef const char *SERVEROUT_TYPE;
141 typedef const void *VOID_SERVEROUT_TYPE;
142 
143 #endif
144 
145 #ifndef NO_IP_CYRUS_SASL_AUTH
146 #define USE_IP_CYRUS_SASL_AUTH
147 #endif
148 
149  /*
150  * The XSASL_CYRUS_SERVER object is derived from the generic XSASL_SERVER
151  * object.
152  */
153 typedef struct {
154  XSASL_SERVER xsasl; /* generic members, must be first */
155  VSTREAM *stream; /* client-server connection */
156  sasl_conn_t *sasl_conn; /* SASL context */
157  VSTRING *decoded; /* decoded challenge or response */
158  char *username; /* authenticated user */
159  char *mechanism_list; /* applicable mechanisms */
160 } XSASL_CYRUS_SERVER;
161 
162  /*
163  * Forward declarations.
164  */
165 static void xsasl_cyrus_server_done(XSASL_SERVER_IMPL *);
166 static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *,
168 static void xsasl_cyrus_server_free(XSASL_SERVER *);
169 static int xsasl_cyrus_server_first(XSASL_SERVER *, const char *,
170  const char *, VSTRING *);
171 static int xsasl_cyrus_server_next(XSASL_SERVER *, const char *, VSTRING *);
172 static int xsasl_cyrus_server_set_security(XSASL_SERVER *, const char *);
173 static const char *xsasl_cyrus_server_get_mechanism_list(XSASL_SERVER *);
174 static const char *xsasl_cyrus_server_get_username(XSASL_SERVER *);
175 
176  /*
177  * SASL callback interface structure. These call-backs have no per-session
178  * context.
179  */
180 #define NO_CALLBACK_CONTEXT 0
181 
182 static sasl_callback_t callbacks[] = {
183  {SASL_CB_LOG, (XSASL_CYRUS_CB) &xsasl_cyrus_log, NO_CALLBACK_CONTEXT},
184  {SASL_CB_LIST_END, 0, 0}
185 };
186 
187 /* xsasl_cyrus_server_init - create implementation handle */
188 
189 XSASL_SERVER_IMPL *xsasl_cyrus_server_init(const char *unused_server_type,
190  const char *path_info)
191 {
192  const char *myname = "xsasl_cyrus_server_init";
193  XSASL_SERVER_IMPL *xp;
194  int sasl_status;
195 
196 #if SASL_VERSION_MAJOR >= 2 && (SASL_VERSION_MINOR >= 2 \
197  || (SASL_VERSION_MINOR == 1 && SASL_VERSION_STEP >= 19))
198  int sasl_major;
199  int sasl_minor;
200  int sasl_step;
201 
202  /*
203  * DLL hell guard.
204  */
205  sasl_version_info((const char **) 0, (const char **) 0,
206  &sasl_major, &sasl_minor,
207  &sasl_step, (int *) 0);
208  if (sasl_major != SASL_VERSION_MAJOR
209 #if 0
210  || sasl_minor != SASL_VERSION_MINOR
211  || sasl_step != SASL_VERSION_STEP
212 #endif
213  ) {
214  msg_warn("incorrect SASL library version. "
215  "Postfix was built with include files from version %d.%d.%d, "
216  "but the run-time library version is %d.%d.%d",
217  SASL_VERSION_MAJOR, SASL_VERSION_MINOR, SASL_VERSION_STEP,
218  sasl_major, sasl_minor, sasl_step);
219  return (0);
220  }
221 #endif
222 
223  if (*var_cyrus_conf_path) {
224 #ifdef SASL_PATH_TYPE_CONFIG /* Cyrus SASL 2.1.22 */
225  if (sasl_set_path(SASL_PATH_TYPE_CONFIG,
226  var_cyrus_conf_path) != SASL_OK)
227  msg_warn("failed to set Cyrus SASL configuration path: \"%s\"",
229 #else
230  msg_warn("%s is not empty, but setting the Cyrus SASL configuration "
231  "path is not supported with SASL library version %d.%d.%d",
232  VAR_CYRUS_CONF_PATH, SASL_VERSION_MAJOR,
233  SASL_VERSION_MINOR, SASL_VERSION_STEP);
234 #endif
235  }
236 
237  /*
238  * Initialize the library: load SASL plug-in routines, etc.
239  */
240  if (msg_verbose)
241  msg_info("%s: SASL config file is %s.conf", myname, path_info);
242  if ((sasl_status = sasl_server_init(callbacks, path_info)) != SASL_OK) {
243  msg_warn("SASL per-process initialization failed: %s",
244  xsasl_cyrus_strerror(sasl_status));
245  return (0);
246  }
247 
248  /*
249  * Return a generic XSASL_SERVER_IMPL object. We don't need to extend it
250  * with our own methods or data.
251  */
252  xp = (XSASL_SERVER_IMPL *) mymalloc(sizeof(*xp));
253  xp->create = xsasl_cyrus_server_create;
254  xp->done = xsasl_cyrus_server_done;
255  return (xp);
256 }
257 
258 /* xsasl_cyrus_server_done - dispose of implementation */
259 
260 static void xsasl_cyrus_server_done(XSASL_SERVER_IMPL *impl)
261 {
262  myfree((void *) impl);
263  sasl_done();
264 }
265 
266 /* xsasl_cyrus_server_create - create server instance */
267 
268 static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl,
270 {
271  const char *myname = "xsasl_cyrus_server_create";
272  char *server_addr_port = 0;
273  char *client_addr_port = 0;
274  sasl_conn_t *sasl_conn = 0;
275  XSASL_CYRUS_SERVER *server = 0;
276  int sasl_status;
277 
278  if (msg_verbose)
279  msg_info("%s: SASL service=%s, realm=%s",
280  myname, args->service, args->user_realm ?
281  args->user_realm : "(null)");
282 
283  /*
284  * The optimizer will eliminate code duplication and/or dead code.
285  */
286 #define XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(x) \
287  do { \
288  if (server) { \
289  xsasl_cyrus_server_free(&server->xsasl); \
290  } else { \
291  if (sasl_conn) \
292  sasl_dispose(&sasl_conn); \
293  } \
294  XSASL_CYRUS_SERVER_CREATE_RETURN(x); \
295  } while (0)
296 
297 #define XSASL_CYRUS_SERVER_CREATE_RETURN(x) \
298  do { \
299  if (server_addr_port) \
300  myfree(server_addr_port); \
301  if (client_addr_port) \
302  myfree(client_addr_port); \
303  return (x); \
304  } while (0)
305 
306  /*
307  * Set up a new server context.
308  */
309 #define NO_SECURITY_LAYERS (0)
310 #define NO_SESSION_CALLBACKS ((sasl_callback_t *) 0)
311 #define NO_AUTH_REALM ((char *) 0)
312 
313 #if SASL_VERSION_MAJOR >= 2 && defined(USE_IP_CYRUS_SASL_AUTH)
314 
315  /*
316  * Get IP address and port of local and remote endpoints for SASL. Some
317  * implementation supports "[ipv6addr]:port" and "ipv4addr:port" (e.g.,
318  * https://illumos.org/man/3sasl/sasl_server_new), They still support the
319  * historical "address;port" syntax, so we stick with that for now.
320  */
321  server_addr_port = (*args->server_addr && *args->server_port ?
322  concatenate(args->server_addr, ";",
323  args->server_port, (char *) 0) : 0);
324  client_addr_port = (*args->client_addr && *args->client_port ?
325  concatenate(args->client_addr, ";",
326  args->client_port, (char *) 0) : 0);
327 #else
328 
329  /*
330  * Don't give any IP address information to SASL.
331  */
332 #endif
333 
334  if ((sasl_status =
335  SASL_SERVER_NEW(args->service, var_myhostname,
336  args->user_realm ? args->user_realm : NO_AUTH_REALM,
337  server_addr_port, client_addr_port,
338  NO_SESSION_CALLBACKS, NO_SECURITY_LAYERS,
339  &sasl_conn)) != SASL_OK) {
340  msg_warn("SASL per-connection server initialization: %s",
341  xsasl_cyrus_strerror(sasl_status));
342  XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(0);
343  }
344 
345  /*
346  * Extend the XSASL_SERVER object with our own data. We use long-lived
347  * conversion buffers rather than local variables to avoid memory leaks
348  * in case of read/write timeout or I/O error.
349  */
350  server = (XSASL_CYRUS_SERVER *) mymalloc(sizeof(*server));
351  server->xsasl.free = xsasl_cyrus_server_free;
352  server->xsasl.first = xsasl_cyrus_server_first;
353  server->xsasl.next = xsasl_cyrus_server_next;
354  server->xsasl.get_mechanism_list = xsasl_cyrus_server_get_mechanism_list;
355  server->xsasl.get_username = xsasl_cyrus_server_get_username;
356  server->stream = args->stream;
357  server->sasl_conn = sasl_conn;
358  server->decoded = vstring_alloc(20);
359  server->username = 0;
360  server->mechanism_list = 0;
361 
362  if (xsasl_cyrus_server_set_security(&server->xsasl, args->security_options)
363  != XSASL_AUTH_OK)
364  XSASL_CYRUS_SERVER_CREATE_ERROR_RETURN(0);
365 
366  XSASL_CYRUS_SERVER_CREATE_RETURN(&server->xsasl);
367 }
368 
369 /* xsasl_cyrus_server_set_security - set security properties */
370 
371 static int xsasl_cyrus_server_set_security(XSASL_SERVER *xp,
372  const char *sasl_opts_val)
373 {
374  XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
375  sasl_security_properties_t sec_props;
376  int sasl_status;
377 
378  /*
379  * Security options. Some information can be found in the sasl.h include
380  * file.
381  */
382  memset(&sec_props, 0, sizeof(sec_props));
383  sec_props.min_ssf = 0;
384  sec_props.max_ssf = 0; /* don't allow real SASL
385  * security layer */
386  if (*sasl_opts_val == 0) {
387  sec_props.security_flags = 0;
388  } else {
389  sec_props.security_flags =
390  xsasl_cyrus_security_parse_opts(sasl_opts_val);
391  if (sec_props.security_flags == 0) {
392  msg_warn("bad per-session SASL security properties");
393  return (XSASL_AUTH_FAIL);
394  }
395  }
396  sec_props.maxbufsize = 0;
397  sec_props.property_names = 0;
398  sec_props.property_values = 0;
399 
400  if ((sasl_status = sasl_setprop(server->sasl_conn, SASL_SEC_PROPS,
401  &sec_props)) != SASL_OK) {
402  msg_warn("SASL per-connection security setup; %s",
403  xsasl_cyrus_strerror(sasl_status));
404  return (XSASL_AUTH_FAIL);
405  }
406  return (XSASL_AUTH_OK);
407 }
408 
409 /* xsasl_cyrus_server_get_mechanism_list - get available mechanisms */
410 
411 static const char *xsasl_cyrus_server_get_mechanism_list(XSASL_SERVER *xp)
412 {
413  const char *myname = "xsasl_cyrus_server_get_mechanism_list";
414  XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
415  MECHANISM_TYPE mechanism_list;
416  MECHANISM_COUNT_TYPE mechanism_count;
417  int sasl_status;
418 
419  /*
420  * Get the list of authentication mechanisms.
421  */
422 #define UNSUPPORTED_USER ((char *) 0)
423 #define IGNORE_MECHANISM_LEN ((unsigned *) 0)
424 
425  if ((sasl_status = sasl_listmech(server->sasl_conn, UNSUPPORTED_USER,
426  "", " ", "",
427  &mechanism_list,
428  IGNORE_MECHANISM_LEN,
429  &mechanism_count)) != SASL_OK) {
430  msg_warn("%s: %s", myname, xsasl_cyrus_strerror(sasl_status));
431  return (0);
432  }
433  if (mechanism_count <= 0) {
434  msg_warn("%s: no applicable SASL mechanisms", myname);
435  return (0);
436  }
437  server->mechanism_list = mystrdup(mechanism_list);
438 #if SASL_VERSION_MAJOR < 2
439  /* SASL version 1 doesn't free memory that it allocates. */
440  free(mechanism_list);
441 #endif
442  return (server->mechanism_list);
443 }
444 
445 /* xsasl_cyrus_server_free - destroy server instance */
446 
447 static void xsasl_cyrus_server_free(XSASL_SERVER *xp)
448 {
449  XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
450 
451  sasl_dispose(&server->sasl_conn);
452  vstring_free(server->decoded);
453  if (server->username)
454  myfree(server->username);
455  if (server->mechanism_list)
456  myfree(server->mechanism_list);
457  myfree((void *) server);
458 }
459 
460 /* xsasl_cyrus_server_auth_response - encode server first/next response */
461 
462 static int xsasl_cyrus_server_auth_response(int sasl_status,
463  SERVEROUT_TYPE serverout,
464  unsigned serveroutlen,
465  VSTRING *reply)
466 {
467  const char *myname = "xsasl_cyrus_server_auth_response";
468  unsigned enc_length;
469  unsigned enc_length_out;
470 
471  /*
472  * Encode the server first/next non-error response; otherwise return the
473  * unencoded error text that corresponds to the SASL error status.
474  *
475  * Regarding the hairy expression below: output from sasl_encode64() comes
476  * in multiples of four bytes for each triple of input bytes, plus four
477  * bytes for any incomplete last triple, plus one byte for the null
478  * terminator.
479  */
480  if (sasl_status == SASL_OK) {
481  vstring_strcpy(reply, "");
482  return (XSASL_AUTH_DONE);
483  } else if (sasl_status == SASL_CONTINUE) {
484  if (msg_verbose)
485  msg_info("%s: uncoded server challenge: %.*s",
486  myname, (int) serveroutlen, serverout);
487  enc_length = ((serveroutlen + 2) / 3) * 4 + 1;
488  VSTRING_RESET(reply); /* Fix 200512 */
489  VSTRING_SPACE(reply, enc_length);
490  if ((sasl_status = sasl_encode64(serverout, serveroutlen,
491  STR(reply), vstring_avail(reply),
492  &enc_length_out)) != SASL_OK)
493  msg_panic("%s: sasl_encode64 botch: %s",
494  myname, xsasl_cyrus_strerror(sasl_status));
495  return (XSASL_AUTH_MORE);
496  } else {
497  if (sasl_status == SASL_NOUSER) /* privacy */
498  sasl_status = SASL_BADAUTH;
499  vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status));
500  switch (sasl_status) {
501  case SASL_FAIL:
502  case SASL_NOMEM:
503  case SASL_TRYAGAIN:
504  case SASL_UNAVAIL:
505  return XSASL_AUTH_TEMP;
506  default:
507  return (XSASL_AUTH_FAIL);
508  }
509  }
510 }
511 
512 /* xsasl_cyrus_server_first - per-session authentication */
513 
514 int xsasl_cyrus_server_first(XSASL_SERVER *xp, const char *sasl_method,
515  const char *init_response, VSTRING *reply)
516 {
517  const char *myname = "xsasl_cyrus_server_first";
518  XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
519  char *dec_buffer;
520  unsigned dec_length;
521  unsigned reply_len;
522  unsigned serveroutlen;
523  int sasl_status;
524  SERVEROUT_TYPE serverout = 0;
525  int xsasl_status;
526 
527 #if SASL_VERSION_MAJOR < 2
528  const char *errstr = 0;
529 
530 #endif
531 
532 #define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
533 
534  if (msg_verbose)
535  msg_info("%s: sasl_method %s%s%s", myname, sasl_method,
536  IFELSE(init_response, ", init_response ", ""),
537  IFELSE(init_response, init_response, ""));
538 
539  /*
540  * SASL authentication protocol start-up. Process any initial client
541  * response that was sent along in the AUTH command.
542  */
543  if (init_response) {
544  reply_len = strlen(init_response);
545  VSTRING_RESET(server->decoded); /* Fix 200512 */
546  VSTRING_SPACE(server->decoded, reply_len);
547  if ((sasl_status = SASL_DECODE64(init_response, reply_len,
548  dec_buffer = STR(server->decoded),
549  vstring_avail(server->decoded),
550  &dec_length)) != SASL_OK) {
551  vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status));
552  return (XSASL_AUTH_FORM);
553  }
554  if (msg_verbose)
555  msg_info("%s: decoded initial response %s", myname, dec_buffer);
556  } else {
557  dec_buffer = 0;
558  dec_length = 0;
559  }
560  sasl_status = SASL_SERVER_START(server->sasl_conn, sasl_method, dec_buffer,
561  dec_length, &serverout,
562  &serveroutlen, &errstr);
563  xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout,
564  serveroutlen, reply);
565 #if SASL_VERSION_MAJOR < 2
566  /* SASL version 1 doesn't free memory that it allocates. */
567  free(serverout);
568 #endif
569  return (xsasl_status);
570 }
571 
572 /* xsasl_cyrus_server_next - continue authentication */
573 
574 static int xsasl_cyrus_server_next(XSASL_SERVER *xp, const char *request,
575  VSTRING *reply)
576 {
577  const char *myname = "xsasl_cyrus_server_next";
578  XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
579  unsigned dec_length;
580  unsigned request_len;
581  unsigned serveroutlen;
582  int sasl_status;
583  SERVEROUT_TYPE serverout = 0;
584  int xsasl_status;
585 
586 #if SASL_VERSION_MAJOR < 2
587  const char *errstr = 0;
588 
589 #endif
590 
591  request_len = strlen(request);
592  VSTRING_RESET(server->decoded); /* Fix 200512 */
593  VSTRING_SPACE(server->decoded, request_len);
594  if ((sasl_status = SASL_DECODE64(request, request_len,
595  STR(server->decoded),
596  vstring_avail(server->decoded),
597  &dec_length)) != SASL_OK) {
598  vstring_strcpy(reply, xsasl_cyrus_strerror(sasl_status));
599  return (XSASL_AUTH_FORM);
600  }
601  if (msg_verbose)
602  msg_info("%s: decoded response: %.*s",
603  myname, (int) dec_length, STR(server->decoded));
604  sasl_status = SASL_SERVER_STEP(server->sasl_conn, STR(server->decoded),
605  dec_length, &serverout,
606  &serveroutlen, &errstr);
607  xsasl_status = xsasl_cyrus_server_auth_response(sasl_status, serverout,
608  serveroutlen, reply);
609 #if SASL_VERSION_MAJOR < 2
610  /* SASL version 1 doesn't free memory that it allocates. */
611  free(serverout);
612 #endif
613  return (xsasl_status);
614 }
615 
616 /* xsasl_cyrus_server_get_username - get authenticated username */
617 
618 static const char *xsasl_cyrus_server_get_username(XSASL_SERVER *xp)
619 {
620  const char *myname = "xsasl_cyrus_server_get_username";
621  XSASL_CYRUS_SERVER *server = (XSASL_CYRUS_SERVER *) xp;
622  VOID_SERVEROUT_TYPE serverout = 0;
623  int sasl_status;
624 
625  /*
626  * XXX Do not free(serverout).
627  */
628  sasl_status = sasl_getprop(server->sasl_conn, SASL_USERNAME, &serverout);
629  if (sasl_status != SASL_OK || serverout == 0) {
630  msg_warn("%s: sasl_getprop SASL_USERNAME botch: %s",
631  myname, xsasl_cyrus_strerror(sasl_status));
632  return (0);
633  }
634  if (server->username)
635  myfree(server->username);
636  server->username = mystrdup(serverout);
637  printable(server->username, '?');
638  return (server->username);
639 }
640 
641 #endif
const char * server_addr
Definition: xsasl.h:50
int msg_verbose
Definition: msg.c:177
void myfree(void *ptr)
Definition: mymalloc.c:207
#define XSASL_AUTH_FAIL
Definition: xsasl.h:127
char * mystrdup(const char *str)
Definition: mymalloc.c:225
#define VAR_CYRUS_CONF_PATH
Definition: mail_params.h:1631
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
void(* done)(struct XSASL_SERVER_IMPL *)
Definition: xsasl.h:62
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
#define XSASL_AUTH_DONE
Definition: xsasl.h:125
const char * client_addr
Definition: xsasl.h:52
char * var_cyrus_conf_path
Definition: smtp.c:940
#define VSTRING_RESET(vp)
Definition: vstring.h:77
#define STR(x)
Definition: anvil.c:518
const char * client_port
Definition: xsasl.h:53
void msg_warn(const char *fmt,...)
Definition: msg.c:215
const char * user_realm
Definition: xsasl.h:55
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
const char * username(void)
Definition: username.c:38
#define XSASL_AUTH_OK
Definition: xsasl.h:123
#define XSASL_AUTH_TEMP
Definition: xsasl.h:128
VSTREAM * stream
Definition: xsasl.h:48
#define vstring_avail(vp)
Definition: vstring.h:86
const char * server_port
Definition: xsasl.h:51
XSASL_SERVER *(* create)(struct XSASL_SERVER_IMPL *, XSASL_SERVER_CREATE_ARGS *)
Definition: xsasl.h:61
char * concatenate(const char *arg0,...)
Definition: concatenate.c:42
#define XSASL_AUTH_MORE
Definition: xsasl.h:124
const char * security_options
Definition: xsasl.h:56
#define VSTRING_SPACE(vp, len)
Definition: vstring.h:70
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
const char * service
Definition: xsasl.h:54
char * var_myhostname
Definition: mail_params.c:223
char * printable(char *string, int replacement)
Definition: printable.c:49
#define XSASL_AUTH_FORM
Definition: xsasl.h:126
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
void msg_info(const char *fmt,...)
Definition: msg.c:199