1 /*
2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7
8 /* common.c - Functions that are common to server and clinet
9 * Rob Siemborski
10 * Tim Martin
11 * $Id: common.c,v 1.92 2003/04/16 19:36:00 rjs3 Exp $
12 */
13 /*
14 * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 *
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 *
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in
25 * the documentation and/or other materials provided with the
26 * distribution.
27 *
28 * 3. The name "Carnegie Mellon University" must not be used to
29 * endorse or promote products derived from this software without
30 * prior written permission. For permission or any other legal
31 * details, please contact
32 * Office of Technology Transfer
33 * Carnegie Mellon University
34 * 5000 Forbes Avenue
35 * Pittsburgh, PA 15213-3890
36 * (412) 268-4387, fax: (412) 268-7395
37 * tech-transfer@andrew.cmu.edu
38 *
39 * 4. Redistributions of any form whatsoever must retain the following
40 * acknowledgment:
41 * "This product includes software developed by Computing Services
42 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
43 *
44 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
45 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
46 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
47 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
48 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
49 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
50 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51 */
52
53 #include <config.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <stdlib.h>
57 #include <limits.h>
58 #ifdef HAVE_SYSLOG
59 #include <syslog.h>
60 #endif
61 #include <stdarg.h>
62 #include <ctype.h>
63
64 #include <sasl.h>
65 #include <saslutil.h>
66 #include <saslplug.h>
67 #include "saslint.h"
68
69 #ifdef _SUN_SDK_
70 #include "md5_private.h"
71 #include "hmac-md5.h"
72 #include "plugin_common.h"
73 #endif
74
75
76 #ifdef WIN32
77 /* need to handle the fact that errno has been defined as a function
78 in a dll, not an extern int */
79 # ifdef errno
80 # undef errno
81 # endif /* errno */
82 #endif /* WIN32 */
83 #ifdef HAVE_UNISTD_H
84 #include <unistd.h>
85 #endif
86
87 static int _sasl_getpath(void *context __attribute__((unused)), const char **path);
88
89 #ifdef _SUN_SDK_
90 DEFINE_STATIC_MUTEX(global_mutex);
91 DEFINE_STATIC_MUTEX(malloc_global_mutex);
92 static void _sasl_dispose_context(_sasl_global_context_t *ctx);
93 static int _sasl_getconf(void *context, const char **conf);
94
95 #ifdef _INTEGRATED_SOLARIS_
96 static pthread_key_t errstring_key = PTHREAD_ONCE_KEY_NP;
97 #endif /* _INTEGRATED_SOLARIS_ */
98 #else
99 static const char build_ident[] = "$Build: libsasl " PACKAGE "-" VERSION " $";
100
101 /* It turns out to be conveinent to have a shared sasl_utils_t */
102 LIBSASL_VAR const sasl_utils_t *sasl_global_utils = NULL;
103
104 /* Should be a null-terminated array that lists the available mechanisms */
105 static char **global_mech_list = NULL;
106
107 void *free_mutex = NULL;
108
109 int (*_sasl_client_cleanup_hook)(void) = NULL;
110 int (*_sasl_server_cleanup_hook)(void) = NULL;
111 int (*_sasl_client_idle_hook)(sasl_conn_t *conn) = NULL;
112 int (*_sasl_server_idle_hook)(sasl_conn_t *conn) = NULL;
113
114 sasl_allocation_utils_t _sasl_allocation_utils={
115 (sasl_malloc_t *) &malloc,
116 (sasl_calloc_t *) &calloc,
117 (sasl_realloc_t *) &realloc,
118 (sasl_free_t *) &free
119 };
120 #endif /* _SUN_SDK_ */
121
122 #ifdef USE_PTHREADS
sasl_mutex_alloc(void)123 static void *sasl_mutex_alloc(void)
124 {
125 pthread_mutex_t *mutex =
126 (pthread_mutex_t *)malloc(sizeof (pthread_mutex_t));
127
128 if (mutex != NULL) {
129 if (pthread_mutex_init(mutex, NULL) != 0) {
130 free(mutex);
131 mutex = NULL;
132 }
133 }
134 return (mutex);
135 }
136
sasl_mutex_lock(void * mutex)137 static int sasl_mutex_lock(void *mutex)
138 {
139 int ret = SASL_BADPARAM;
140
141 if (mutex != NULL)
142 ret = pthread_mutex_lock((pthread_mutex_t *)mutex);
143
144 return ret;
145 }
146
sasl_mutex_unlock(void * mutex)147 static int sasl_mutex_unlock(void *mutex)
148 {
149 int ret = SASL_BADPARAM;
150
151 if (mutex != NULL)
152 ret = pthread_mutex_unlock((pthread_mutex_t *)mutex);
153
154 return ret;
155 }
156
sasl_mutex_free(void * mutex)157 static void sasl_mutex_free(void *mutex __attribute__((unused)))
158 {
159 if (mutex != NULL) {
160 pthread_mutex_destroy((pthread_mutex_t *)mutex);
161 free(mutex);
162 }
163 }
164 #else
165 /* Intenal mutex functions do as little as possible (no thread protection) */
sasl_mutex_alloc(void)166 static void *sasl_mutex_alloc(void)
167 {
168 return (void *)0x1;
169 }
170
sasl_mutex_lock(void * mutex)171 static int sasl_mutex_lock(void *mutex __attribute__((unused)))
172 {
173 return SASL_OK;
174 }
175
sasl_mutex_unlock(void * mutex)176 static int sasl_mutex_unlock(void *mutex __attribute__((unused)))
177 {
178 return SASL_OK;
179 }
180
sasl_mutex_free(void * mutex)181 static void sasl_mutex_free(void *mutex __attribute__((unused)))
182 {
183 return;
184 }
185 #endif /* USE_PTHREADS */
186
187 #ifndef _SUN_SDK_
188 sasl_mutex_utils_t _sasl_mutex_utils={
189 &sasl_mutex_alloc,
190 &sasl_mutex_lock,
191 &sasl_mutex_unlock,
192 &sasl_mutex_free
193 };
194 #endif /* !_SUN_SDK_ */
195
sasl_set_mutex(sasl_mutex_alloc_t * n,sasl_mutex_lock_t * l,sasl_mutex_unlock_t * u,sasl_mutex_free_t * d)196 void sasl_set_mutex(sasl_mutex_alloc_t *n, sasl_mutex_lock_t *l,
197 sasl_mutex_unlock_t *u, sasl_mutex_free_t *d)
198 {
199 #ifdef _SUN_SDK_
200 _sasl_global_context_t *gctx = _sasl_gbl_ctx();
201
202 gctx->sasl_mutex_utils.alloc=n;
203 gctx->sasl_mutex_utils.lock=l;
204 gctx->sasl_mutex_utils.unlock=u;
205 gctx->sasl_mutex_utils.free=d;
206 #else
207 _sasl_mutex_utils.alloc=n;
208 _sasl_mutex_utils.lock=l;
209 _sasl_mutex_utils.unlock=u;
210 _sasl_mutex_utils.free=d;
211 #endif
212 }
213
214 /* copy a string to malloced memory */
215 #ifdef _SUN_SDK_
__sasl_strdup(const _sasl_global_context_t * gctx,const char * in,char ** out,size_t * outlen)216 int __sasl_strdup(const _sasl_global_context_t *gctx, const char *in,
217 char **out, size_t *outlen)
218 #else
219 int _sasl_strdup(const char *in, char **out, size_t *outlen)
220 #endif /* _SUN_SDK_ */
221 {
222 size_t len = strlen(in);
223 if (outlen) *outlen = len;
224 *out=sasl_ALLOC(len + 1);
225 if (! *out) return SASL_NOMEM;
226 strcpy((char *) *out, in);
227 return SASL_OK;
228 }
229
230 /* adds a string to the buffer; reallocing if need be */
231 #ifdef _SUN_SDK_
__sasl_add_string(const _sasl_global_context_t * gctx,char ** out,size_t * alloclen,size_t * outlen,const char * add)232 int __sasl_add_string(const _sasl_global_context_t *gctx, char **out,
233 size_t *alloclen, size_t *outlen,
234 const char *add)
235 #else
236 int _sasl_add_string(char **out, size_t *alloclen,
237 size_t *outlen, const char *add)
238 #endif /* _SUN_SDK_ */
239 {
240 size_t addlen;
241
242 if (add==NULL) add = "(null)";
243
244 addlen=strlen(add); /* only compute once */
245 if (_buf_alloc(out, alloclen, (*outlen)+addlen)!=SASL_OK)
246 return SASL_NOMEM;
247
248 strncpy(*out + *outlen, add, addlen);
249 *outlen += addlen;
250
251 return SASL_OK;
252 }
253
254 /* return the version of the cyrus sasl library as compiled,
255 * using 32 bits: high byte is major version, second byte is minor version,
256 * low 16 bits are step # */
sasl_version(const char ** implementation,int * version)257 void sasl_version(const char **implementation, int *version)
258 {
259 #ifdef _SUN_SDK_
260 const char *implementation_string = "Sun SASL";
261 #else
262 const char *implementation_string = "Cyrus SASL";
263 #endif /* _SUN_SDK_ */
264 if(implementation) *implementation = implementation_string;
265 if(version) *version = (SASL_VERSION_MAJOR << 24) |
266 (SASL_VERSION_MINOR << 16) |
267 (SASL_VERSION_STEP);
268 }
269
270 /* security-encode a regular string. Mostly a wrapper for sasl_encodev */
271 /* output is only valid until next call to sasl_encode or sasl_encodev */
sasl_encode(sasl_conn_t * conn,const char * input,unsigned inputlen,const char ** output,unsigned * outputlen)272 int sasl_encode(sasl_conn_t *conn, const char *input,
273 unsigned inputlen,
274 const char **output, unsigned *outputlen)
275 {
276 int result;
277 struct iovec tmp;
278
279 if(!conn) return SASL_BADPARAM;
280 if(!input || !inputlen || !output || !outputlen)
281 PARAMERROR(conn);
282
283 /* maxoutbuf checking is done in sasl_encodev */
284
285 /* Note: We are casting a const pointer here, but it's okay
286 * because we believe people downstream of us are well-behaved, and the
287 * alternative is an absolute mess, performance-wise. */
288 tmp.iov_base = (void *)input;
289 tmp.iov_len = inputlen;
290
291 result = sasl_encodev(conn, &tmp, 1, output, outputlen);
292
293 RETURN(conn, result);
294 }
295
296 /* security-encode an iovec */
297 /* output is only valid until next call to sasl_encode or sasl_encodev */
sasl_encodev(sasl_conn_t * conn,const struct iovec * invec,unsigned numiov,const char ** output,unsigned * outputlen)298 int sasl_encodev(sasl_conn_t *conn,
299 const struct iovec *invec, unsigned numiov,
300 const char **output, unsigned *outputlen)
301 {
302 #ifdef _SUN_SDK_
303 int result = SASL_FAIL;
304 #else
305 int result;
306 #endif /* _SUN_SDK_ */
307 unsigned i;
308 size_t total_size = 0;
309
310 /* EXPORT DELETE START */
311 if (!conn) return SASL_BADPARAM;
312 if (! invec || ! output || ! outputlen || numiov < 1)
313 PARAMERROR(conn);
314
315 if(!conn->props.maxbufsize) {
316 #ifdef _SUN_SDK_
317 _sasl_log(conn, SASL_LOG_ERR,
318 "called sasl_encode[v] with application that does not support security layers");
319 #else
320 sasl_seterror(conn, 0,
321 "called sasl_encode[v] with application that does not support security layers");
322 #endif /* _SUN_SDK_ */
323 return SASL_TOOWEAK;
324 }
325
326 /* This might be better to check on a per-plugin basis, but I think
327 * it's cleaner and more effective here. It also encourages plugins
328 * to be honest about what they accept */
329
330 for(i=0; i<numiov;i++) {
331 #ifdef _SUN_SDK_
332 if (invec[i].iov_base == NULL)
333 PARAMERROR(conn);
334 #endif /* _SUN_SDK_ */
335 total_size += invec[i].iov_len;
336 }
337 if(total_size > conn->oparams.maxoutbuf)
338 PARAMERROR(conn);
339
340 if(conn->oparams.encode == NULL) {
341 #ifdef _SUN_SDK_
342 result = _iovec_to_buf(conn->gctx, invec, numiov, &conn->encode_buf);
343 #else
344 result = _iovec_to_buf(invec, numiov, &conn->encode_buf);
345 #endif /* _SUN_SDK_ */
346 if(result != SASL_OK) INTERROR(conn, result);
347
348 *output = conn->encode_buf->data;
349 *outputlen = conn->encode_buf->curlen;
350
351 /* CRYPT DELETE START */
352 #ifdef _INTEGRATED_SOLARIS_
353 } else if (!conn->sun_reg) {
354 INTERROR(conn, SASL_FAIL);
355 #endif /* _INTEGRATED_SOLARIS_ */
356 /* CRYPT DELETE END */
357 } else {
358 result = conn->oparams.encode(conn->context, invec, numiov,
359 output, outputlen);
360 }
361 /* EXPORT DELETE END */
362
363 RETURN(conn, result);
364 }
365
366 /* output is only valid until next call to sasl_decode */
sasl_decode(sasl_conn_t * conn,const char * input,unsigned inputlen,const char ** output,unsigned * outputlen)367 int sasl_decode(sasl_conn_t *conn,
368 const char *input, unsigned inputlen,
369 const char **output, unsigned *outputlen)
370 {
371 int result;
372 /* EXPORT DELETE START */
373 #ifdef _SUN_SDK_
374 const _sasl_global_context_t *gctx;
375 #endif /* _SUN_SDK_ */
376
377 if(!conn) return SASL_BADPARAM;
378 if(!input || !output || !outputlen)
379 PARAMERROR(conn);
380
381 #ifdef _SUN_SDK_
382 gctx = conn->gctx;
383 #endif /* _SUN_SDK_ */
384
385 if(!conn->props.maxbufsize) {
386 #ifdef _SUN_SDK_
387 _sasl_log(conn, SASL_LOG_ERR,
388 "called sasl_decode with application that does not support security layers");
389 #else
390 sasl_seterror(conn, 0,
391 "called sasl_decode with application that does not support security layers");
392 #endif /* _SUN_SDK_ */
393 RETURN(conn, SASL_TOOWEAK);
394 }
395
396 if(conn->oparams.decode == NULL)
397 {
398 /* Since we know how long the output is maximally, we can
399 * just allocate it to begin with, and never need another
400 * allocation! */
401
402 /* However, if they pass us more than they actually can take,
403 * we cannot help them... */
404 if(inputlen > conn->props.maxbufsize) {
405 #ifdef _SUN_SDK_
406 _sasl_log(conn, SASL_LOG_ERR,
407 "input too large for default sasl_decode");
408 #else
409 sasl_seterror(conn, 0,
410 "input too large for default sasl_decode");
411 #endif /* _SUN_SDK_ */
412 RETURN(conn,SASL_BUFOVER);
413 }
414
415 if(!conn->decode_buf)
416 conn->decode_buf = sasl_ALLOC(conn->props.maxbufsize + 1);
417 if(!conn->decode_buf)
418 MEMERROR(conn);
419
420 memcpy(conn->decode_buf, input, inputlen);
421 conn->decode_buf[inputlen] = '\0';
422 *output = conn->decode_buf;
423 *outputlen = inputlen;
424
425 return SASL_OK;
426 /* CRYPT DELETE START */
427 #ifdef _INTEGRATED_SOLARIS_
428 } else if (!conn->sun_reg) {
429 INTERROR(conn, SASL_FAIL);
430 #endif /* _INTEGRATED_SOLARIS_ */
431 /* CRYPT DELETE END */
432 } else {
433 result = conn->oparams.decode(conn->context, input, inputlen,
434 output, outputlen);
435
436 /* NULL an empty buffer (for misbehaved applications) */
437 if (*outputlen == 0) *output = NULL;
438
439 RETURN(conn, result);
440 }
441
442 /* EXPORT DELETE END */
443 #ifdef _SUN_SDK_
444 return SASL_FAIL;
445 #else
446 INTERROR(conn, SASL_FAIL);
447 #endif /* _SUN_SDK_ */
448 }
449
450
451 void
sasl_set_alloc(sasl_malloc_t * m,sasl_calloc_t * c,sasl_realloc_t * r,sasl_free_t * f)452 sasl_set_alloc(sasl_malloc_t *m,
453 sasl_calloc_t *c,
454 sasl_realloc_t *r,
455 sasl_free_t *f)
456 {
457 #ifdef _SUN_SDK_
458 _sasl_global_context_t *gctx = _sasl_gbl_ctx();
459
460 LOCK_MUTEX(&malloc_global_mutex);
461 gctx->sasl_allocation_utils.malloc=m;
462 gctx->sasl_allocation_utils.calloc=c;
463 gctx->sasl_allocation_utils.realloc=r;
464 gctx->sasl_allocation_utils.free=f;
465 UNLOCK_MUTEX(&malloc_global_mutex);
466 #else
467 _sasl_allocation_utils.malloc=m;
468 _sasl_allocation_utils.calloc=c;
469 _sasl_allocation_utils.realloc=r;
470 _sasl_allocation_utils.free=f;
471 #endif /* _SUN_SDK_ */
472 }
473
sasl_done(void)474 void sasl_done(void)
475 {
476 #ifdef _SUN_SDK_
477 _sasl_dispose_context(_sasl_gbl_ctx());
478 #else
479 if (_sasl_server_cleanup_hook && _sasl_server_cleanup_hook() == SASL_OK) {
480 _sasl_server_idle_hook = NULL;
481 _sasl_server_cleanup_hook = NULL;
482 }
483
484 if (_sasl_client_cleanup_hook && _sasl_client_cleanup_hook() == SASL_OK) {
485 _sasl_client_idle_hook = NULL;
486 _sasl_client_cleanup_hook = NULL;
487 }
488
489 if(_sasl_server_cleanup_hook || _sasl_client_cleanup_hook)
490 return;
491
492
493 _sasl_canonuser_free();
494 _sasl_done_with_plugins();
495
496 #ifdef _SUN_SDK_
497 sasl_config_free();
498 #endif /* _SUN_SDK_ */
499
500 sasl_MUTEX_FREE(free_mutex);
501 free_mutex = NULL;
502
503 _sasl_free_utils(&sasl_global_utils);
504
505 if(global_mech_list) sasl_FREE(global_mech_list);
506 global_mech_list = NULL;
507 #endif /* _SUN_SDK_ */
508 }
509
510 /* fills in the base sasl_conn_t info */
_sasl_conn_init(sasl_conn_t * conn,const char * service,unsigned int flags,enum Sasl_conn_type type,int (* idle_hook)(sasl_conn_t * conn),const char * serverFQDN,const char * iplocalport,const char * ipremoteport,const sasl_callback_t * callbacks,const sasl_global_callbacks_t * global_callbacks)511 int _sasl_conn_init(sasl_conn_t *conn,
512 const char *service,
513 unsigned int flags,
514 enum Sasl_conn_type type,
515 int (*idle_hook)(sasl_conn_t *conn),
516 const char *serverFQDN,
517 const char *iplocalport,
518 const char *ipremoteport,
519 const sasl_callback_t *callbacks,
520 const sasl_global_callbacks_t *global_callbacks) {
521 int result = SASL_OK;
522 #ifdef _SUN_SDK_
523 const _sasl_global_context_t *gctx = conn->gctx;
524 #endif /* _SUN_SDK_ */
525
526 conn->type = type;
527
528 result = _sasl_strdup(service, &conn->service, NULL);
529 if (result != SASL_OK)
530 MEMERROR(conn);
531
532 memset(&conn->oparams, 0, sizeof(sasl_out_params_t));
533 memset(&conn->external, 0, sizeof(_sasl_external_properties_t));
534
535 conn->flags = flags;
536
537 result = sasl_setprop(conn, SASL_IPLOCALPORT, iplocalport);
538 if(result != SASL_OK)
539 RETURN(conn, result);
540
541 result = sasl_setprop(conn, SASL_IPREMOTEPORT, ipremoteport);
542 if(result != SASL_OK)
543 RETURN(conn, result);
544
545 conn->encode_buf = NULL;
546 conn->context = NULL;
547 #ifndef _SUN_SDK_
548 conn->secret = NULL;
549 #endif /* !_SUN_SDK_ */
550 conn->idle_hook = idle_hook;
551 conn->callbacks = callbacks;
552 conn->global_callbacks = global_callbacks;
553
554 memset(&conn->props, 0, sizeof(conn->props));
555
556 /* Start this buffer out as an empty string */
557 conn->error_code = SASL_OK;
558 conn->errdetail_buf = conn->error_buf = NULL;
559 conn->errdetail_buf_len = conn->error_buf_len = 150;
560
561 result = _buf_alloc(&conn->error_buf, &conn->error_buf_len, 150);
562 if(result != SASL_OK) MEMERROR(conn);
563 result = _buf_alloc(&conn->errdetail_buf, &conn->errdetail_buf_len, 150);
564 if(result != SASL_OK) MEMERROR(conn);
565
566 conn->error_buf[0] = '\0';
567 conn->errdetail_buf[0] = '\0';
568
569 conn->decode_buf = NULL;
570
571 if(serverFQDN) {
572 result = _sasl_strdup(serverFQDN, &conn->serverFQDN, NULL);
573 } else if (conn->type == SASL_CONN_SERVER) {
574 /* We can fake it because we *are* the server */
575 char name[MAXHOSTNAMELEN];
576 memset(name, 0, sizeof(name));
577 gethostname(name, MAXHOSTNAMELEN);
578
579 result = _sasl_strdup(name, &conn->serverFQDN, NULL);
580 } else {
581 conn->serverFQDN = NULL;
582 }
583
584
585 if(result != SASL_OK) MEMERROR( conn );
586
587 #ifdef _SUN_SDK_
588 return (SASL_OK);
589 #else
590 RETURN(conn, SASL_OK);
591 #endif /* _SUN_SDK_ */
592 }
593
594 #ifdef _SUN_SDK_
_sasl_common_init(_sasl_global_context_t * gctx,sasl_global_callbacks_t * global_callbacks,int server)595 int _sasl_common_init(_sasl_global_context_t *gctx,
596 sasl_global_callbacks_t *global_callbacks,
597 int server)
598 {
599 int result;
600 sasl_utils_t *sasl_global_utils;
601
602 sasl_global_utils = (sasl_utils_t *)gctx->sasl_canonusr_global_utils;
603
604 if(!sasl_global_utils) {
605 sasl_global_utils = _sasl_alloc_utils(gctx, NULL, global_callbacks);
606 if(sasl_global_utils == NULL) return SASL_NOMEM;
607 gctx->sasl_canonusr_global_utils = sasl_global_utils;
608 }
609
610 if (server) {
611 sasl_global_utils = (sasl_utils_t *)gctx->sasl_server_global_utils;
612
613 if(!sasl_global_utils) {
614 sasl_global_utils = _sasl_alloc_utils(gctx, NULL, global_callbacks);
615 if(sasl_global_utils == NULL) return SASL_NOMEM;
616 gctx->sasl_server_global_utils = sasl_global_utils;
617 }
618 }
619
620 /* Init the canon_user plugin */
621 result = _sasl_canonuser_add_plugin(gctx, "INTERNAL",
622 internal_canonuser_init);
623 if(result != SASL_OK) return result;
624
625 if (!gctx->free_mutex)
626 gctx->free_mutex = sasl_MUTEX_ALLOC();
627 if (!gctx->free_mutex) return SASL_FAIL;
628
629 return SASL_OK;
630 }
631 #else
_sasl_common_init(sasl_global_callbacks_t * global_callbacks)632 int _sasl_common_init(sasl_global_callbacks_t *global_callbacks)
633 {
634 int result;
635
636 /* Setup the global utilities */
637 if(!sasl_global_utils) {
638 sasl_global_utils = _sasl_alloc_utils(NULL, global_callbacks);
639 if(sasl_global_utils == NULL) return SASL_NOMEM;
640 }
641
642 /* Init the canon_user plugin */
643 result = sasl_canonuser_add_plugin("INTERNAL", internal_canonuser_init);
644 if(result != SASL_OK) return result;
645
646 if (!free_mutex)
647 free_mutex = sasl_MUTEX_ALLOC();
648 if (!free_mutex) return SASL_FAIL;
649
650 return SASL_OK;
651 }
652 #endif /* _SUN_SDK_ */
653
654 /* dispose connection state, sets it to NULL
655 * checks for pointer to NULL
656 */
sasl_dispose(sasl_conn_t ** pconn)657 void sasl_dispose(sasl_conn_t **pconn)
658 {
659 int result;
660 #ifdef _SUN_SDK_
661 _sasl_global_context_t *gctx;
662 void *free_mutex;
663 #endif /* _SUN_SDK_ */
664
665 if (! pconn) return;
666 if (! *pconn) return;
667
668 /* serialize disposes. this is necessary because we can't
669 dispose of conn->mutex if someone else is locked on it */
670 #ifdef _SUN_SDK_
671 gctx = (*pconn)->gctx;
672 free_mutex = gctx->free_mutex;
673 #endif /* _SUN_SDK_ */
674 result = sasl_MUTEX_LOCK(free_mutex);
675 if (result!=SASL_OK) return;
676
677 /* *pconn might have become NULL by now */
678 #ifdef _SUN_SDK_
679 if (! (*pconn)) {
680 sasl_MUTEX_UNLOCK(free_mutex);
681 return;
682 }
683 #else
684 if (! (*pconn)) return;
685 #endif /* _SUN_SDK_ */
686
687 (*pconn)->destroy_conn(*pconn);
688 sasl_FREE(*pconn);
689 *pconn=NULL;
690
691 sasl_MUTEX_UNLOCK(free_mutex);
692 }
693
_sasl_conn_dispose(sasl_conn_t * conn)694 void _sasl_conn_dispose(sasl_conn_t *conn) {
695 #ifdef _SUN_SDK_
696 const _sasl_global_context_t *gctx = conn->gctx;
697 #endif /* _SUN_SDK_ */
698
699 if (conn->serverFQDN)
700 sasl_FREE(conn->serverFQDN);
701
702 if (conn->external.auth_id)
703 sasl_FREE(conn->external.auth_id);
704
705 if(conn->encode_buf) {
706 if(conn->encode_buf->data) sasl_FREE(conn->encode_buf->data);
707 sasl_FREE(conn->encode_buf);
708 }
709
710 if(conn->error_buf)
711 sasl_FREE(conn->error_buf);
712
713 if(conn->errdetail_buf)
714 sasl_FREE(conn->errdetail_buf);
715
716 if(conn->decode_buf)
717 sasl_FREE(conn->decode_buf);
718
719 if(conn->mechlist_buf)
720 sasl_FREE(conn->mechlist_buf);
721
722 if(conn->service)
723 sasl_FREE(conn->service);
724
725 /* oparams sub-members should be freed by the plugin, in so much
726 * as they were allocated by the plugin */
727 }
728
729
730 /* get property from SASL connection state
731 * propnum -- property number
732 * pvalue -- pointer to value
733 * returns:
734 * SASL_OK -- no error
735 * SASL_NOTDONE -- property not available yet
736 * SASL_BADPARAM -- bad property number
737 */
sasl_getprop(sasl_conn_t * conn,int propnum,const void ** pvalue)738 int sasl_getprop(sasl_conn_t *conn, int propnum, const void **pvalue)
739 {
740 int result = SASL_OK;
741 sasl_getopt_t *getopt;
742 void *context;
743
744 if (! conn) return SASL_BADPARAM;
745 if (! pvalue) PARAMERROR(conn);
746
747 switch(propnum)
748 {
749 case SASL_SSF:
750 /* EXPORT DELETE START */
751 /* CRYPT DELETE START */
752 #ifdef _INTEGRATED_SOLARIS_
753 if (!conn->sun_reg)
754 conn->oparams.mech_ssf = 0;
755 #endif /* _INTEGRATED_SOLARIS_ */
756 /* CRYPT DELETE END */
757 /* EXPORT DELETE END */
758 *(sasl_ssf_t **)pvalue= &conn->oparams.mech_ssf;
759 break;
760 case SASL_MAXOUTBUF:
761 *(unsigned **)pvalue = &conn->oparams.maxoutbuf;
762 break;
763 case SASL_GETOPTCTX:
764 result = _sasl_getcallback(conn, SASL_CB_GETOPT, &getopt, &context);
765 if(result != SASL_OK) break;
766
767 *(void **)pvalue = context;
768 break;
769 case SASL_CALLBACK:
770 *(const sasl_callback_t **)pvalue = conn->callbacks;
771 break;
772 case SASL_IPLOCALPORT:
773 if(conn->got_ip_local)
774 *(const char **)pvalue = conn->iplocalport;
775 else {
776 *(const char **)pvalue = NULL;
777 result = SASL_NOTDONE;
778 }
779 break;
780 case SASL_IPREMOTEPORT:
781 if(conn->got_ip_remote)
782 *(const char **)pvalue = conn->ipremoteport;
783 else {
784 *(const char **)pvalue = NULL;
785 result = SASL_NOTDONE;
786 }
787 break;
788 case SASL_USERNAME:
789 if(! conn->oparams.user)
790 result = SASL_NOTDONE;
791 else
792 *((const char **)pvalue) = conn->oparams.user;
793 break;
794 case SASL_AUTHUSER:
795 if(! conn->oparams.authid)
796 result = SASL_NOTDONE;
797 else
798 *((const char **)pvalue) = conn->oparams.authid;
799 break;
800 case SASL_SERVERFQDN:
801 *((const char **)pvalue) = conn->serverFQDN;
802 break;
803 case SASL_DEFUSERREALM:
804 if(conn->type != SASL_CONN_SERVER) result = SASL_BADPROT;
805 else
806 *((const char **)pvalue) = ((sasl_server_conn_t *)conn)->user_realm;
807 break;
808 case SASL_SERVICE:
809 *((const char **)pvalue) = conn->service;
810 break;
811 case SASL_AUTHSOURCE: /* name of plugin (not name of mech) */
812 if(conn->type == SASL_CONN_CLIENT) {
813 if(!((sasl_client_conn_t *)conn)->mech) {
814 result = SASL_NOTDONE;
815 break;
816 }
817 *((const char **)pvalue) =
818 ((sasl_client_conn_t *)conn)->mech->plugname;
819 } else if (conn->type == SASL_CONN_SERVER) {
820 if(!((sasl_server_conn_t *)conn)->mech) {
821 result = SASL_NOTDONE;
822 break;
823 }
824 *((const char **)pvalue) =
825 ((sasl_server_conn_t *)conn)->mech->plugname;
826 } else {
827 result = SASL_BADPARAM;
828 }
829 break;
830 case SASL_MECHNAME: /* name of mech */
831 if(conn->type == SASL_CONN_CLIENT) {
832 if(!((sasl_client_conn_t *)conn)->mech) {
833 result = SASL_NOTDONE;
834 break;
835 }
836 *((const char **)pvalue) =
837 ((sasl_client_conn_t *)conn)->mech->plug->mech_name;
838 } else if (conn->type == SASL_CONN_SERVER) {
839 if(!((sasl_server_conn_t *)conn)->mech) {
840 result = SASL_NOTDONE;
841 break;
842 }
843 *((const char **)pvalue) =
844 ((sasl_server_conn_t *)conn)->mech->plug->mech_name;
845 } else {
846 result = SASL_BADPARAM;
847 }
848
849 if(!(*pvalue) && result == SASL_OK) result = SASL_NOTDONE;
850 break;
851 case SASL_PLUGERR:
852 *((const char **)pvalue) = conn->error_buf;
853 break;
854 case SASL_SSF_EXTERNAL:
855 *((const sasl_ssf_t **)pvalue) = &conn->external.ssf;
856 break;
857 case SASL_AUTH_EXTERNAL:
858 *((const char **)pvalue) = conn->external.auth_id;
859 break;
860 case SASL_SEC_PROPS:
861 *((const sasl_security_properties_t **)pvalue) = &conn->props;
862 break;
863 default:
864 result = SASL_BADPARAM;
865 }
866
867 if(result == SASL_BADPARAM) {
868 PARAMERROR(conn);
869 } else if(result == SASL_NOTDONE) {
870 #ifdef _SUN_SDK_
871 _sasl_log(conn, SASL_LOG_NONE,
872 "Information that was requested is not yet available.");
873 #else
874 sasl_seterror(conn, SASL_NOLOG,
875 "Information that was requested is not yet available.");
876 #endif /* _SUN_SDK_ */
877 RETURN(conn, result);
878 } else if(result != SASL_OK) {
879 INTERROR(conn, result);
880 } else
881 RETURN(conn, result);
882 #ifdef _SUN_SDK_
883 return SASL_OK;
884 #endif /* _SUN_SDK_ */
885 }
886
887 /* set property in SASL connection state
888 * returns:
889 * SASL_OK -- value set
890 * SASL_BADPARAM -- invalid property or value
891 */
sasl_setprop(sasl_conn_t * conn,int propnum,const void * value)892 int sasl_setprop(sasl_conn_t *conn, int propnum, const void *value)
893 {
894 int result = SASL_OK;
895 char *str;
896 #ifdef _SUN_SDK_
897 const _sasl_global_context_t *gctx;
898 #endif /* _SUN_SDK_ */
899
900 /* make sure the sasl context is valid */
901 if (!conn)
902 return SASL_BADPARAM;
903
904 #ifdef _SUN_SDK_
905 gctx = conn->gctx;
906 #endif /* _SUN_SDK_ */
907
908 switch(propnum)
909 {
910 case SASL_SSF_EXTERNAL:
911 conn->external.ssf = *((sasl_ssf_t *)value);
912 if(conn->type == SASL_CONN_SERVER) {
913 ((sasl_server_conn_t*)conn)->sparams->external_ssf =
914 conn->external.ssf;
915 } else {
916 ((sasl_client_conn_t*)conn)->cparams->external_ssf =
917 conn->external.ssf;
918 }
919 break;
920
921 case SASL_AUTH_EXTERNAL:
922 if(value && strlen(value)) {
923 result = _sasl_strdup(value, &str, NULL);
924 if(result != SASL_OK) MEMERROR(conn);
925 } else {
926 str = NULL;
927 }
928
929 if(conn->external.auth_id)
930 sasl_FREE(conn->external.auth_id);
931
932 conn->external.auth_id = str;
933
934 break;
935
936 case SASL_DEFUSERREALM:
937 if(conn->type != SASL_CONN_SERVER) {
938 #ifdef _SUN_SDK_
939 _sasl_log(conn, SASL_LOG_WARN,
940 "Tried to set realm on non-server connection");
941 #else
942 sasl_seterror(conn, 0, "Tried to set realm on non-server connection");
943 #endif /* _SUN_SDK_ */
944 result = SASL_BADPROT;
945 break;
946 }
947
948 if(value && strlen(value)) {
949 result = _sasl_strdup(value, &str, NULL);
950 if(result != SASL_OK) MEMERROR(conn);
951 } else {
952 PARAMERROR(conn);
953 }
954
955 if(((sasl_server_conn_t *)conn)->user_realm)
956 sasl_FREE(((sasl_server_conn_t *)conn)->user_realm);
957
958 ((sasl_server_conn_t *)conn)->user_realm = str;
959 ((sasl_server_conn_t *)conn)->sparams->user_realm = str;
960
961 break;
962
963 case SASL_SEC_PROPS:
964 {
965 sasl_security_properties_t *props = (sasl_security_properties_t *)value;
966
967 if(props->maxbufsize == 0 && props->min_ssf != 0) {
968 #ifdef _SUN_SDK_
969 _sasl_log(conn, SASL_LOG_ERR,
970 "Attempt to disable security layers (maxoutbuf == 0) with min_ssf > 0");
971 #else
972 sasl_seterror(conn, 0,
973 "Attempt to disable security layers (maxoutbuf == 0) with min_ssf > 0");
974 #endif /* _SUN_SDK_ */
975 RETURN(conn, SASL_TOOWEAK);
976 }
977
978 conn->props = *props;
979
980 if(conn->type == SASL_CONN_SERVER) {
981 ((sasl_server_conn_t*)conn)->sparams->props = *props;
982 } else {
983 ((sasl_client_conn_t*)conn)->cparams->props = *props;
984 }
985
986 break;
987 }
988
989 case SASL_IPREMOTEPORT:
990 {
991 const char *ipremoteport = (const char *)value;
992 if(!value) {
993 conn->got_ip_remote = 0;
994 #ifdef _SUN_SDK_
995 } else if (strlen(ipremoteport) >= sizeof (conn->ipremoteport)) {
996 RETURN(conn, SASL_BADPARAM);
997 #endif /* _SUN_SDK_ */
998 } else if (_sasl_ipfromstring(ipremoteport, NULL, 0)
999 != SASL_OK) {
1000 #ifdef _SUN_SDK_
1001 _sasl_log(conn, SASL_LOG_ERR, "Bad IPREMOTEPORT value");
1002 #else
1003 sasl_seterror(conn, 0, "Bad IPREMOTEPORT value");
1004 #endif /* _SUN_SDK_ */
1005 RETURN(conn, SASL_BADPARAM);
1006 } else {
1007 strcpy(conn->ipremoteport, ipremoteport);
1008 conn->got_ip_remote = 1;
1009 }
1010
1011 if(conn->got_ip_remote) {
1012 if(conn->type == SASL_CONN_CLIENT) {
1013 ((sasl_client_conn_t *)conn)->cparams->ipremoteport
1014 = conn->ipremoteport;
1015 ((sasl_client_conn_t *)conn)->cparams->ipremlen =
1016 strlen(conn->ipremoteport);
1017 } else if (conn->type == SASL_CONN_SERVER) {
1018 ((sasl_server_conn_t *)conn)->sparams->ipremoteport
1019 = conn->ipremoteport;
1020 ((sasl_server_conn_t *)conn)->sparams->ipremlen =
1021 strlen(conn->ipremoteport);
1022 }
1023 } else {
1024 if(conn->type == SASL_CONN_CLIENT) {
1025 ((sasl_client_conn_t *)conn)->cparams->ipremoteport
1026 = NULL;
1027 ((sasl_client_conn_t *)conn)->cparams->ipremlen = 0;
1028 } else if (conn->type == SASL_CONN_SERVER) {
1029 ((sasl_server_conn_t *)conn)->sparams->ipremoteport
1030 = NULL;
1031 ((sasl_server_conn_t *)conn)->sparams->ipremlen = 0;
1032 }
1033 }
1034
1035 break;
1036 }
1037
1038 case SASL_IPLOCALPORT:
1039 {
1040 const char *iplocalport = (const char *)value;
1041 if(!value) {
1042 conn->got_ip_local = 0;
1043 #ifdef _SUN_SDK_
1044 } else if (strlen(iplocalport) >= sizeof (conn->iplocalport)) {
1045 RETURN(conn, SASL_BADPARAM);
1046 #endif /* _SUN_SDK_ */
1047 } else if (_sasl_ipfromstring(iplocalport, NULL, 0)
1048 != SASL_OK) {
1049 #ifdef _SUN_SDK_
1050 _sasl_log(conn, SASL_LOG_ERR, "Bad IPLOCALPORT value");
1051 #else
1052 sasl_seterror(conn, 0, "Bad IPLOCALPORT value");
1053 #endif /* _SUN_SDK_ */
1054 RETURN(conn, SASL_BADPARAM);
1055 } else {
1056 strcpy(conn->iplocalport, iplocalport);
1057 conn->got_ip_local = 1;
1058 }
1059
1060 if(conn->got_ip_local) {
1061 if(conn->type == SASL_CONN_CLIENT) {
1062 ((sasl_client_conn_t *)conn)->cparams->iplocalport
1063 = conn->iplocalport;
1064 ((sasl_client_conn_t *)conn)->cparams->iploclen
1065 = strlen(conn->iplocalport);
1066 } else if (conn->type == SASL_CONN_SERVER) {
1067 ((sasl_server_conn_t *)conn)->sparams->iplocalport
1068 = conn->iplocalport;
1069 ((sasl_server_conn_t *)conn)->sparams->iploclen
1070 = strlen(conn->iplocalport);
1071 }
1072 } else {
1073 if(conn->type == SASL_CONN_CLIENT) {
1074 ((sasl_client_conn_t *)conn)->cparams->iplocalport
1075 = NULL;
1076 ((sasl_client_conn_t *)conn)->cparams->iploclen = 0;
1077 } else if (conn->type == SASL_CONN_SERVER) {
1078 ((sasl_server_conn_t *)conn)->sparams->iplocalport
1079 = NULL;
1080 ((sasl_server_conn_t *)conn)->sparams->iploclen = 0;
1081 }
1082 }
1083 break;
1084 }
1085
1086 default:
1087 #ifdef _SUN_SDK_
1088 _sasl_log(conn, SASL_LOG_WARN, "Unknown parameter type");
1089 #else
1090 sasl_seterror(conn, 0, "Unknown parameter type");
1091 #endif /* _SUN_SDK_ */
1092 result = SASL_BADPARAM;
1093 }
1094
1095 RETURN(conn, result);
1096 }
1097
1098 /* this is apparently no longer a user function */
sasl_usererr(int saslerr)1099 static int sasl_usererr(int saslerr)
1100 {
1101 /* Hide the difference in a username failure and a password failure */
1102 if (saslerr == SASL_NOUSER)
1103 return SASL_BADAUTH;
1104
1105 /* otherwise return the error given; no transform necessary */
1106 return saslerr;
1107 }
1108
1109 #ifdef _INTEGRATED_SOLARIS_
free_err_tsd(void * key)1110 static void free_err_tsd(void *key)
1111 {
1112 free(key);
1113 }
1114 #endif /* _INTEGRATED_SOLARIS_ */
1115
sasl_errstring(int saslerr,const char * langlist,const char ** outlang)1116 const char *sasl_errstring(int saslerr,
1117 #ifdef _SUN_SDK_
1118 const char *langlist,
1119 #else
1120 const char *langlist __attribute__((unused)),
1121 #endif /* _SUN_SDK_ */
1122 const char **outlang)
1123 {
1124 #ifdef _INTEGRATED_SOLARIS_
1125 const char *s;
1126 const char *s_locale;
1127 char *s_utf8;
1128 void *tsd;
1129
1130 if (outlang) *outlang="i-default";
1131 #else
1132 if (outlang) *outlang="en-us";
1133 #endif /* _INTEGRATED_SOLARIS_ */
1134
1135 #ifdef _INTEGRATED_SOLARIS_
1136 switch(saslerr)
1137 {
1138 case SASL_CONTINUE: s = gettext("another step is needed in authentication");
1139 break;
1140 case SASL_OK: s = gettext("successful result");
1141 break;
1142 case SASL_FAIL: s = gettext("generic failure");
1143 break;
1144 case SASL_NOMEM: s = gettext("no memory available");
1145 break;
1146 case SASL_BUFOVER: s = gettext("overflowed buffer");
1147 break;
1148 case SASL_NOMECH: s = gettext("no mechanism available");
1149 break;
1150 case SASL_BADPROT: s = gettext("bad protocol / cancel");
1151 break;
1152 case SASL_NOTDONE: s = gettext("can't request info until later in exchange");
1153 break;
1154 case SASL_BADPARAM: s = gettext("invalid parameter supplied");
1155 break;
1156 case SASL_TRYAGAIN: s = gettext("transient failure (e.g., weak key)");
1157 break;
1158 case SASL_BADMAC: s = gettext("integrity check failed");
1159 break;
1160 case SASL_NOTINIT: s = gettext("SASL library not initialized");
1161 break;
1162 /* -- client only codes -- */
1163 case SASL_INTERACT: s = gettext("needs user interaction");
1164 break;
1165 case SASL_BADSERV: s = gettext("server failed mutual authentication step");
1166 break;
1167 case SASL_WRONGMECH: s = gettext("mechanism doesn't support requested feature");
1168 break;
1169 /* -- server only codes -- */
1170 case SASL_BADAUTH: s = gettext("authentication failure");
1171 break;
1172 case SASL_NOAUTHZ: s = gettext("authorization failure");
1173 break;
1174 case SASL_TOOWEAK: s = gettext("mechanism too weak for this user");
1175 break;
1176 case SASL_ENCRYPT: s = gettext("encryption needed to use mechanism");
1177 break;
1178 case SASL_TRANS: s = gettext("One time use of a plaintext password will enable requested mechanism for user");
1179 break;
1180 case SASL_EXPIRED: s = gettext("passphrase expired, has to be reset");
1181 break;
1182 case SASL_DISABLED: s = gettext("account disabled");
1183 break;
1184 case SASL_NOUSER: s = gettext("user not found");
1185 break;
1186 case SASL_BADVERS: s = gettext("version mismatch with plug-in");
1187 break;
1188 case SASL_UNAVAIL: s = gettext("remote authentication server unavailable");
1189 break;
1190 case SASL_NOVERIFY: s = gettext("user exists, but no verifier for user");
1191 break;
1192 case SASL_PWLOCK: s = gettext("passphrase locked");
1193 break;
1194 case SASL_NOCHANGE: s = gettext("requested change was not needed");
1195 break;
1196 case SASL_WEAKPASS: s = gettext("passphrase is too weak for security policy");
1197 break;
1198 case SASL_NOUSERPASS: s = gettext("user supplied passwords are not permitted");
1199
1200 break;
1201 default: s = gettext("undefined error!");
1202 break;
1203 }
1204
1205 if (use_locale(langlist, 0))
1206 s_locale = dgettext(TEXT_DOMAIN, s);
1207 else
1208 s_locale = s;
1209
1210 if (s == s_locale)
1211 return s;
1212
1213 s_utf8 = local_to_utf(NULL, s_locale);
1214 if (s_utf8 == NULL)
1215 return s;
1216
1217 if (pthread_key_create_once_np(&errstring_key, free_err_tsd) != 0) {
1218 free(s_utf8);
1219 return s;
1220 }
1221
1222 tsd = pthread_getspecific(errstring_key);
1223 if (tsd != NULL)
1224 free(tsd);
1225 pthread_setspecific(errstring_key, s_utf8);
1226
1227 if (outlang) *outlang="*";
1228 return s_utf8;
1229 #else
1230 switch(saslerr)
1231 {
1232 case SASL_CONTINUE: return "another step is needed in authentication";
1233 case SASL_OK: return "successful result";
1234 case SASL_FAIL: return "generic failure";
1235 case SASL_NOMEM: return "no memory available";
1236 case SASL_BUFOVER: return "overflowed buffer";
1237 case SASL_NOMECH: return "no mechanism available";
1238 case SASL_BADPROT: return "bad protocol / cancel";
1239 case SASL_NOTDONE: return "can't request info until later in exchange";
1240 case SASL_BADPARAM: return "invalid parameter supplied";
1241 case SASL_TRYAGAIN: return "transient failure (e.g., weak key)";
1242 case SASL_BADMAC: return "integrity check failed";
1243 case SASL_NOTINIT: return "SASL library not initialized";
1244 /* -- client only codes -- */
1245 case SASL_INTERACT: return "needs user interaction";
1246 case SASL_BADSERV: return "server failed mutual authentication step";
1247 case SASL_WRONGMECH: return "mechanism doesn't support requested feature";
1248 /* -- server only codes -- */
1249 case SASL_BADAUTH: return "authentication failure";
1250 case SASL_NOAUTHZ: return "authorization failure";
1251 case SASL_TOOWEAK: return "mechanism too weak for this user";
1252 case SASL_ENCRYPT: return "encryption needed to use mechanism";
1253 case SASL_TRANS: return "One time use of a plaintext password will enable requested mechanism for user";
1254 case SASL_EXPIRED: return "passphrase expired, has to be reset";
1255 case SASL_DISABLED: return "account disabled";
1256 case SASL_NOUSER: return "user not found";
1257 case SASL_BADVERS: return "version mismatch with plug-in";
1258 case SASL_UNAVAIL: return "remote authentication server unavailable";
1259 case SASL_NOVERIFY: return "user exists, but no verifier for user";
1260 case SASL_PWLOCK: return "passphrase locked";
1261 case SASL_NOCHANGE: return "requested change was not needed";
1262 case SASL_WEAKPASS: return "passphrase is too weak for security policy";
1263 case SASL_NOUSERPASS: return "user supplied passwords are not permitted";
1264
1265 default: return "undefined error!";
1266 }
1267 #endif /* _INTEGRATED_SOLARIS_ */
1268
1269 }
1270
1271 /* Return the sanitized error detail about the last error that occured for
1272 * a connection */
sasl_errdetail(sasl_conn_t * conn)1273 const char *sasl_errdetail(sasl_conn_t *conn)
1274 {
1275 unsigned need_len;
1276 const char *errstr;
1277 char leader[128];
1278 #ifdef _SUN_SDK_
1279 int ret;
1280 const _sasl_global_context_t *gctx;
1281
1282 if(!conn) return "invalid parameter supplied";
1283
1284 gctx = conn->gctx;
1285 #else
1286 if(!conn) return NULL;
1287 #endif /* _SUN_SDK_ */
1288
1289 errstr = sasl_errstring(conn->error_code, NULL, NULL);
1290 snprintf(leader,128,"SASL(%d): %s: ",
1291 sasl_usererr(conn->error_code), errstr);
1292
1293 need_len = strlen(leader) + strlen(conn->error_buf) + 12;
1294 #ifdef _SUN_SDK_
1295 ret = _buf_alloc(&conn->errdetail_buf, &conn->errdetail_buf_len, need_len);
1296 if (ret != SASL_OK)
1297 return "no memory available";
1298 #else
1299 _buf_alloc(&conn->errdetail_buf, &conn->errdetail_buf_len, need_len);
1300 #endif /* _SUN_SDK_ */
1301
1302 snprintf(conn->errdetail_buf, need_len, "%s%s", leader, conn->error_buf);
1303
1304 return conn->errdetail_buf;
1305 }
1306
1307 /* EXPORT DELETE START */
1308 /* CRYPT DELETE START */
1309 #ifdef _INTEGRATED_SOLARIS_
1310 DEFINE_STATIC_MUTEX(reg_mutex);
1311 typedef struct reg_list {
1312 struct reg_list *next;
1313 void *mech;
1314 } reg_list_t;
1315
1316 static reg_list_t *reg_list_base = NULL;
1317
_is_sun_reg(void * mech)1318 int _is_sun_reg(void *mech)
1319 {
1320 reg_list_t *r, *prev;
1321 int is_reg = 0;
1322
1323 LOCK_MUTEX(®_mutex);
1324 for (r = reg_list_base; r != NULL; r = r->next) {
1325 if (r->mech != mech) {
1326 prev = r;
1327 continue;
1328 }
1329 is_reg = 1;
1330 if (r == reg_list_base) {
1331 reg_list_base = reg_list_base->next;
1332 } else {
1333 prev->next = r->next;
1334 }
1335 free(r);
1336 break;
1337 }
1338 UNLOCK_MUTEX(®_mutex);
1339 return (is_reg);
1340 }
1341
1342 static void
_register_plugin(void * arg)1343 _register_plugin(void *arg)
1344 {
1345 reg_list_t *r = (reg_list_t *)calloc(1, sizeof (reg_list_t));
1346
1347 if (r != NULL) {
1348 r->mech = arg;
1349 LOCK_MUTEX(®_mutex);
1350 r->next = reg_list_base;
1351 reg_list_base = r;
1352 UNLOCK_MUTEX(®_mutex);
1353 }
1354 }
1355 #endif /* _INTEGRATED_SOLARIS_ */
1356 /* CRYPT DELETE END */
1357 /* EXPORT DELETE END */
1358
1359 /* Note that this needs the global callbacks, so if you don't give getcallbacks
1360 * a sasl_conn_t, you're going to need to pass it yourself (or else we couldn't
1361 * have client and server at the same time */
_sasl_global_getopt(void * context,const char * plugin_name,const char * option,const char ** result,unsigned * len)1362 static int _sasl_global_getopt(void *context,
1363 const char *plugin_name,
1364 const char *option,
1365 const char ** result,
1366 unsigned *len)
1367 {
1368 const sasl_global_callbacks_t * global_callbacks;
1369 const sasl_callback_t *callback;
1370 #ifdef _SUN_SDK_
1371 _sasl_global_context_t *gctx;
1372 #endif /* _SUN_SDK_ */
1373
1374 global_callbacks = (const sasl_global_callbacks_t *) context;
1375
1376 #ifdef _SUN_SDK_
1377 /* EXPORT DELETE START */
1378 /* CRYPT DELETE START */
1379 #ifdef _INTEGRATED_SOLARIS_
1380 if (strcmp("reg_sun_plug", option) == 0) {
1381 *result = (const char *)_register_plugin;
1382 *len = 0;
1383 return (SASL_OK);
1384 }
1385 #endif /* _INTEGRATED_SOLARIS_ */
1386 /* CRYPT DELETE END */
1387 /* EXPORT DELETE END */
1388
1389 if (global_callbacks)
1390 gctx = global_callbacks->gctx;
1391 else
1392 gctx = _sasl_gbl_ctx();
1393 #endif /* _SUN_SDK_ */
1394
1395 if (global_callbacks && global_callbacks->callbacks) {
1396 for (callback = global_callbacks->callbacks;
1397 callback->id != SASL_CB_LIST_END;
1398 callback++) {
1399 if (callback->id == SASL_CB_GETOPT) {
1400 if (!callback->proc) return SASL_FAIL;
1401 if (((sasl_getopt_t *)(callback->proc))(callback->context,
1402 plugin_name,
1403 option,
1404 result,
1405 len)
1406 == SASL_OK)
1407 return SASL_OK;
1408 }
1409 }
1410 }
1411
1412 /* look it up in our configuration file */
1413 #ifdef _SUN_SDK_
1414 *result = sasl_config_getstring(gctx, option, NULL);
1415 #else
1416 *result = sasl_config_getstring(option, NULL);
1417 #endif /* _SUN_SDK_ */
1418 if (*result != NULL) {
1419 if (len) { *len = strlen(*result); }
1420 return SASL_OK;
1421 }
1422
1423 return SASL_FAIL;
1424 }
1425
1426 static int
_sasl_conn_getopt(void * context,const char * plugin_name,const char * option,const char ** result,unsigned * len)1427 _sasl_conn_getopt(void *context,
1428 const char *plugin_name,
1429 const char *option,
1430 const char ** result,
1431 unsigned *len)
1432 {
1433 sasl_conn_t * conn;
1434 const sasl_callback_t *callback;
1435
1436 if (! context)
1437 return SASL_BADPARAM;
1438
1439 conn = (sasl_conn_t *) context;
1440
1441 if (conn->callbacks)
1442 for (callback = conn->callbacks;
1443 callback->id != SASL_CB_LIST_END;
1444 callback++)
1445 if (callback->id == SASL_CB_GETOPT
1446 && (((sasl_getopt_t *)(callback->proc))(callback->context,
1447 plugin_name,
1448 option,
1449 result,
1450 len)
1451 == SASL_OK))
1452 return SASL_OK;
1453
1454 /* If we made it here, we didn't find an appropriate callback
1455 * in the connection's callback list, or the callback we did
1456 * find didn't return SASL_OK. So we attempt to use the
1457 * global callback for this connection... */
1458 return _sasl_global_getopt((void *)conn->global_callbacks,
1459 plugin_name,
1460 option,
1461 result,
1462 len);
1463 }
1464
1465 #ifdef HAVE_SYSLOG
1466 /* this is the default logging */
_sasl_syslog(void * context,int priority,const char * message)1467 static int _sasl_syslog(void *context __attribute__((unused)),
1468 int priority,
1469 const char *message)
1470 {
1471 int syslog_priority;
1472
1473 /* set syslog priority */
1474 switch(priority) {
1475 case SASL_LOG_NONE:
1476 return SASL_OK;
1477 break;
1478 case SASL_LOG_ERR:
1479 syslog_priority = LOG_ERR;
1480 break;
1481 case SASL_LOG_WARN:
1482 syslog_priority = LOG_WARNING;
1483 break;
1484 case SASL_LOG_NOTE:
1485 case SASL_LOG_FAIL:
1486 syslog_priority = LOG_NOTICE;
1487 break;
1488 case SASL_LOG_PASS:
1489 case SASL_LOG_TRACE:
1490 case SASL_LOG_DEBUG:
1491 default:
1492 syslog_priority = LOG_DEBUG;
1493 break;
1494 }
1495
1496 /* do the syslog call. do not need to call openlog */
1497 syslog(syslog_priority | LOG_AUTH, "%s", message);
1498
1499 return SASL_OK;
1500 }
1501 #endif /* HAVE_SYSLOG */
1502
1503 static int
_sasl_getsimple(void * context,int id,const char ** result,size_t * len)1504 _sasl_getsimple(void *context,
1505 int id,
1506 const char ** result,
1507 size_t *len)
1508 {
1509 const char *userid;
1510 #ifndef _SUN_SDK_
1511 sasl_conn_t *conn;
1512 #endif /* _SUN_SDK_ */
1513
1514 if (! context || ! result) return SASL_BADPARAM;
1515
1516 #ifndef _SUN_SDK_
1517 conn = (sasl_conn_t *)context;
1518 #endif /* _SUN_SDK_ */
1519
1520 switch(id) {
1521 case SASL_CB_AUTHNAME:
1522 #ifdef _INTEGRATED_SOLARIS_
1523 userid = getenv("LOGNAME");
1524 if (userid != NULL) {
1525 *result = userid;
1526 if (len) *len = strlen(userid);
1527 return SASL_OK;
1528 }
1529 #else
1530 userid = getenv("USER");
1531 if (userid != NULL) {
1532 *result = userid;
1533 if (len) *len = strlen(userid);
1534 return SASL_OK;
1535 }
1536 userid = getenv("USERNAME");
1537 if (userid != NULL) {
1538 *result = userid;
1539 if (len) *len = strlen(userid);
1540 return SASL_OK;
1541 }
1542 #endif /* _INTEGRATED_SOLARIS_ */
1543 #ifdef WIN32
1544 /* for win32, try using the GetUserName standard call */
1545 {
1546 DWORD i;
1547 BOOL rval;
1548 static char sender[128];
1549
1550 i = sizeof(sender);
1551 rval = GetUserName(sender, &i);
1552 if ( rval) { /* got a userid */
1553 *result = sender;
1554 if (len) *len = strlen(sender);
1555 return SASL_OK;
1556 }
1557 }
1558 #endif /* WIN32 */
1559 return SASL_FAIL;
1560 default:
1561 return SASL_BADPARAM;
1562 }
1563 }
1564
1565 static int
_sasl_verifyfile(void * context,char * file,int type)1566 _sasl_verifyfile(void *context __attribute__((unused)),
1567 char *file __attribute__((unused)),
1568 int type __attribute__((unused)))
1569 {
1570 /* always say ok */
1571 return SASL_OK;
1572 }
1573
1574
1575 static int
_sasl_proxy_policy(sasl_conn_t * conn,void * context,const char * requested_user,unsigned rlen,const char * auth_identity,unsigned alen,const char * def_realm,unsigned urlen,struct propctx * propctx)1576 _sasl_proxy_policy(sasl_conn_t *conn,
1577 void *context __attribute__((unused)),
1578 const char *requested_user, unsigned rlen,
1579 const char *auth_identity, unsigned alen,
1580 const char *def_realm __attribute__((unused)),
1581 unsigned urlen __attribute__((unused)),
1582 struct propctx *propctx __attribute__((unused)))
1583 {
1584 if (!conn)
1585 return SASL_BADPARAM;
1586
1587 if (!requested_user || *requested_user == '\0')
1588 return SASL_OK;
1589
1590 if (!auth_identity || !requested_user || rlen != alen ||
1591 (memcmp(auth_identity, requested_user, rlen) != 0)) {
1592 #ifdef _INTEGRATED_SOLARIS_
1593 sasl_seterror(conn, 0,
1594 gettext("Requested identity not authenticated identity"));
1595 #else
1596 sasl_seterror(conn, 0,
1597 "Requested identity not authenticated identity");
1598 #endif /* _INTEGRATED_SOLARIS_ */
1599 RETURN(conn, SASL_BADAUTH);
1600 }
1601
1602 return SASL_OK;
1603 }
1604
_sasl_getcallback(sasl_conn_t * conn,unsigned long callbackid,int (** pproc)(),void ** pcontext)1605 int _sasl_getcallback(sasl_conn_t * conn,
1606 unsigned long callbackid,
1607 int (**pproc)(),
1608 void **pcontext)
1609 {
1610 const sasl_callback_t *callback;
1611
1612 if (!pproc || !pcontext)
1613 PARAMERROR(conn);
1614
1615 /* Some callbacks are always provided by the library */
1616 switch (callbackid) {
1617 case SASL_CB_LIST_END:
1618 /* Nothing ever gets to provide this */
1619 INTERROR(conn, SASL_FAIL);
1620 #ifdef _SUN_SDK_
1621 break;
1622 #endif /* _SUN_SDK_ */
1623 case SASL_CB_GETOPT:
1624 if (conn) {
1625 *pproc = &_sasl_conn_getopt;
1626 *pcontext = conn;
1627 } else {
1628 *pproc = &_sasl_global_getopt;
1629 *pcontext = NULL;
1630 }
1631 return SASL_OK;
1632 }
1633
1634 /* If it's not always provided by the library, see if there's
1635 * a version provided by the application for this connection... */
1636 if (conn && conn->callbacks) {
1637 for (callback = conn->callbacks; callback->id != SASL_CB_LIST_END;
1638 callback++) {
1639 if (callback->id == callbackid) {
1640 *pproc = callback->proc;
1641 *pcontext = callback->context;
1642 if (callback->proc) {
1643 return SASL_OK;
1644 } else {
1645 return SASL_INTERACT;
1646 }
1647 }
1648 }
1649 }
1650
1651 /* And, if not for this connection, see if there's one
1652 * for all {server,client} connections... */
1653 if (conn && conn->global_callbacks && conn->global_callbacks->callbacks) {
1654 for (callback = conn->global_callbacks->callbacks;
1655 callback->id != SASL_CB_LIST_END;
1656 callback++) {
1657 if (callback->id == callbackid) {
1658 *pproc = callback->proc;
1659 *pcontext = callback->context;
1660 if (callback->proc) {
1661 return SASL_OK;
1662 } else {
1663 return SASL_INTERACT;
1664 }
1665 }
1666 }
1667 }
1668
1669 /* Otherwise, see if the library provides a default callback. */
1670 switch (callbackid) {
1671 #ifdef HAVE_SYSLOG
1672 case SASL_CB_LOG:
1673 *pproc = (int (*)()) &_sasl_syslog;
1674 *pcontext = NULL;
1675 return SASL_OK;
1676 #endif /* HAVE_SYSLOG */
1677 case SASL_CB_GETPATH:
1678 *pproc = (int (*)()) &_sasl_getpath;
1679 *pcontext = NULL;
1680 return SASL_OK;
1681 case SASL_CB_AUTHNAME:
1682 *pproc = (int (*)()) &_sasl_getsimple;
1683 *pcontext = conn;
1684 return SASL_OK;
1685 case SASL_CB_VERIFYFILE:
1686 *pproc = & _sasl_verifyfile;
1687 *pcontext = NULL;
1688 return SASL_OK;
1689 case SASL_CB_PROXY_POLICY:
1690 *pproc = (int (*)()) &_sasl_proxy_policy;
1691 *pcontext = NULL;
1692 return SASL_OK;
1693 }
1694
1695 /* Unable to find a callback... */
1696 *pproc = NULL;
1697 *pcontext = NULL;
1698 #ifdef _SUN_SDK_
1699 if (callbackid != SASL_CB_LANGUAGE)
1700 _sasl_log(conn, SASL_LOG_NONE, "Unable to find a callback: %d", callbackid);
1701 #else
1702 sasl_seterror(conn, SASL_NOLOG, "Unable to find a callback: %d", callbackid);
1703 #endif /* _SUN_SDK_ */
1704 RETURN(conn,SASL_FAIL);
1705 }
1706
1707
1708 #ifdef _SUN_SDK_
1709 static void ___sasl_log (const _sasl_global_context_t *gctx,
1710 sasl_log_t *log_cb, void *log_ctx,
1711 int level, const char *fmt, va_list ap);
1712 #endif /* _SUN_SDK_ */
1713 /*
1714 * This function is typically called from a plugin.
1715 * It creates a string from the formatting and varargs given
1716 * and calls the logging callback (syslog by default)
1717 *
1718 * %m will parse the value in the next argument as an errno string
1719 * %z will parse the next argument as a SASL error code.
1720 */
1721
1722 void
_sasl_log(sasl_conn_t * conn,int level,const char * fmt,...)1723 _sasl_log (sasl_conn_t *conn,
1724 int level,
1725 const char *fmt,
1726 ...)
1727 #ifdef _SUN_SDK_
1728 {
1729 _sasl_global_context_t *gctx = conn==NULL ? _sasl_gbl_ctx() : conn->gctx;
1730 sasl_log_t *log_cb;
1731 void *log_ctx;
1732 int result;
1733 va_list ap;
1734
1735 /* See if we have a logging callback... */
1736 result = _sasl_getcallback(conn, SASL_CB_LOG, &log_cb, &log_ctx);
1737 if (result == SASL_OK && ! log_cb)
1738 return;
1739
1740 va_start(ap, fmt); /* start varargs */
1741 ___sasl_log(gctx, log_cb, log_ctx, level, fmt, ap);
1742 va_end(ap);
1743 }
1744
1745 void
__sasl_log(const _sasl_global_context_t * gctx,const sasl_callback_t * callbacks,int level,const char * fmt,...)1746 __sasl_log(const _sasl_global_context_t *gctx,
1747 const sasl_callback_t *callbacks,
1748 int level,
1749 const char *fmt,
1750 ...)
1751 {
1752 sasl_log_t *log_cb = NULL;
1753 void *log_ctx = NULL;
1754 int result;
1755 va_list ap;
1756
1757 if (callbacks)
1758 while (callbacks->id != SASL_CB_LIST_END) {
1759 if (callbacks->id == SASL_CB_LOG) {
1760 log_cb = callbacks->proc;
1761 log_ctx = callbacks->context;
1762 break;
1763 }
1764 ++callbacks;
1765 }
1766
1767 if (log_cb == NULL) {
1768 result = _sasl_getcallback(NULL, SASL_CB_LOG, &log_cb, &log_ctx);
1769 if (result != SASL_OK || ! log_cb)
1770 return;
1771 }
1772
1773 if (gctx == NULL)
1774 gctx = _sasl_gbl_ctx();
1775
1776 va_start(ap, fmt); /* start varargs */
1777 ___sasl_log(gctx, log_cb, log_ctx, level, fmt, ap);
1778 va_end(ap);
1779 }
1780
1781 static void
___sasl_log(const _sasl_global_context_t * gctx,sasl_log_t * log_cb,void * log_ctx,int level,const char * fmt,va_list ap)1782 ___sasl_log(const _sasl_global_context_t *gctx,
1783 sasl_log_t *log_cb,
1784 void *log_ctx,
1785 int level,
1786 const char *fmt,
1787 va_list ap)
1788 #endif /* _SUN_SDK_ */
1789 {
1790 char *out=(char *) sasl_ALLOC(250);
1791 size_t alloclen=100; /* current allocated length */
1792 size_t outlen=0; /* current length of output buffer */
1793 size_t formatlen;
1794 size_t pos=0; /* current position in format string */
1795 int result;
1796 #ifndef _SUN_SDK_
1797 sasl_log_t *log_cb;
1798 void *log_ctx;
1799 #endif /* !_SUN_SDK_ */
1800
1801 int ival;
1802 char *cval;
1803 #ifndef _SUN_SDK_
1804 va_list ap; /* varargs thing */
1805 #endif /* !_SUN_SDK_ */
1806
1807 if(!fmt) goto done;
1808 if(!out) return;
1809
1810 formatlen = strlen(fmt);
1811
1812 #ifndef _SUN_SDK_
1813 /* See if we have a logging callback... */
1814 result = _sasl_getcallback(conn, SASL_CB_LOG, &log_cb, &log_ctx);
1815 if (result == SASL_OK && ! log_cb)
1816 result = SASL_FAIL;
1817 if (result != SASL_OK) goto done;
1818
1819 va_start(ap, fmt); /* start varargs */
1820 #endif /* !_SUN_SDK_ */
1821
1822 while(pos<formatlen)
1823 {
1824 if (fmt[pos]!='%') /* regular character */
1825 {
1826 result = _buf_alloc(&out, &alloclen, outlen+1);
1827 if (result != SASL_OK) goto done;
1828 out[outlen]=fmt[pos];
1829 outlen++;
1830 pos++;
1831
1832 } else { /* formating thing */
1833 int done=0;
1834 char frmt[10];
1835 int frmtpos=1;
1836 char tempbuf[21];
1837 frmt[0]='%';
1838 pos++;
1839
1840 while (done==0)
1841 {
1842 switch(fmt[pos])
1843 {
1844 case 's': /* need to handle this */
1845 cval = va_arg(ap, char *); /* get the next arg */
1846 result = _sasl_add_string(&out, &alloclen,
1847 &outlen, cval);
1848
1849 if (result != SASL_OK) /* add the string */
1850 goto done;
1851
1852 done=1;
1853 break;
1854
1855 case '%': /* double % output the '%' character */
1856 result = _buf_alloc(&out,&alloclen,outlen+1);
1857 if (result != SASL_OK)
1858 goto done;
1859
1860 out[outlen]='%';
1861 outlen++;
1862 done=1;
1863 break;
1864
1865 case 'm': /* insert the errno string */
1866 result = _sasl_add_string(&out, &alloclen, &outlen,
1867 strerror(va_arg(ap, int)));
1868 if (result != SASL_OK)
1869 goto done;
1870
1871 done=1;
1872 break;
1873
1874 case 'z': /* insert the sasl error string */
1875 result = _sasl_add_string(&out, &alloclen, &outlen,
1876 (char *) sasl_errstring(va_arg(ap, int),NULL,NULL));
1877 if (result != SASL_OK)
1878 goto done;
1879
1880 done=1;
1881 break;
1882
1883 case 'c':
1884 #ifndef _SUN_SDK_
1885 frmt[frmtpos++]=fmt[pos];
1886 frmt[frmtpos]=0;
1887 #endif /* !_SUN_SDK_ */
1888 tempbuf[0] = (char) va_arg(ap, int); /* get the next arg */
1889 tempbuf[1]='\0';
1890
1891 /* now add the character */
1892 result = _sasl_add_string(&out, &alloclen, &outlen, tempbuf);
1893 if (result != SASL_OK)
1894 goto done;
1895
1896 done=1;
1897 break;
1898
1899 case 'd':
1900 case 'i':
1901 frmt[frmtpos++]=fmt[pos];
1902 frmt[frmtpos]=0;
1903 ival = va_arg(ap, int); /* get the next arg */
1904
1905 snprintf(tempbuf,20,frmt,ival); /* have snprintf do the work */
1906 /* now add the string */
1907 result = _sasl_add_string(&out, &alloclen, &outlen, tempbuf);
1908 if (result != SASL_OK)
1909 goto done;
1910
1911 done=1;
1912
1913 break;
1914 default:
1915 frmt[frmtpos++]=fmt[pos]; /* add to the formating */
1916 frmt[frmtpos]=0;
1917 #ifdef _SUN_SDK_
1918 if (frmtpos > sizeof (frmt) - 2)
1919 #else
1920 if (frmtpos>9)
1921 #endif /* _SUN_SDK_ */
1922 done=1;
1923 }
1924 pos++;
1925 if (pos>formatlen)
1926 done=1;
1927 }
1928
1929 }
1930 }
1931
1932 /* put 0 at end */
1933 result = _buf_alloc(&out, &alloclen, outlen+1);
1934 if (result != SASL_OK) goto done;
1935 out[outlen]=0;
1936
1937 va_end(ap);
1938
1939 /* send log message */
1940 result = log_cb(log_ctx, level, out);
1941
1942 done:
1943 if(out) sasl_FREE(out);
1944 }
1945
1946
1947
1948 /* Allocate and Init a sasl_utils_t structure */
1949 #ifdef _SUN_SDK_
1950 sasl_utils_t *
_sasl_alloc_utils(_sasl_global_context_t * gctx,sasl_conn_t * conn,sasl_global_callbacks_t * global_callbacks)1951 _sasl_alloc_utils(_sasl_global_context_t *gctx, sasl_conn_t *conn,
1952 sasl_global_callbacks_t *global_callbacks)
1953 #else
1954 sasl_utils_t *
1955 _sasl_alloc_utils(sasl_conn_t *conn,
1956 sasl_global_callbacks_t *global_callbacks)
1957 #endif /* _SUN_SDK_ */
1958 {
1959 sasl_utils_t *utils;
1960 #ifdef _SUN_SDK_
1961 sasl_allocation_utils_t alloc;
1962 sasl_mutex_utils_t mutex;
1963
1964 LOCK_MUTEX(&malloc_global_mutex);
1965 alloc = gctx->sasl_allocation_utils;
1966 mutex = gctx->sasl_mutex_utils;
1967 UNLOCK_MUTEX(&malloc_global_mutex);
1968 #endif /* _SUN_SDK_ */
1969
1970 /* set util functions - need to do rest*/
1971 #ifdef _SUN_SDK_
1972 utils=alloc.malloc(sizeof(sasl_utils_t));
1973 #else
1974 utils=sasl_ALLOC(sizeof(sasl_utils_t));
1975 #endif /* _SUN_SDK_ */
1976 if (utils==NULL)
1977 return NULL;
1978
1979 utils->conn = conn;
1980
1981 sasl_randcreate(&utils->rpool);
1982
1983 if (conn) {
1984 utils->getopt = &_sasl_conn_getopt;
1985 utils->getopt_context = conn;
1986 } else {
1987 utils->getopt = &_sasl_global_getopt;
1988 utils->getopt_context = global_callbacks;
1989 }
1990
1991 #ifdef _SUN_SDK_
1992 utils->malloc=alloc.malloc;
1993 utils->calloc=alloc.calloc;
1994 utils->realloc=alloc.realloc;
1995 utils->free=alloc.free;
1996
1997 utils->mutex_alloc = mutex.alloc;
1998 utils->mutex_lock = mutex.lock;
1999 utils->mutex_unlock = mutex.unlock;
2000 utils->mutex_free = mutex.free;
2001 #else
2002 utils->malloc=_sasl_allocation_utils.malloc;
2003 utils->calloc=_sasl_allocation_utils.calloc;
2004 utils->realloc=_sasl_allocation_utils.realloc;
2005 utils->free=_sasl_allocation_utils.free;
2006
2007 utils->mutex_alloc = _sasl_mutex_utils.alloc;
2008 utils->mutex_lock = _sasl_mutex_utils.lock;
2009 utils->mutex_unlock = _sasl_mutex_utils.unlock;
2010 utils->mutex_free = _sasl_mutex_utils.free;
2011 #endif /* _SUN_SDK_ */
2012
2013 #ifdef _SUN_SDK_
2014 utils->MD5Init = (void (*)(MD5_CTX *))&MD5Init;
2015 utils->MD5Update= (void (*)
2016 (MD5_CTX *, const unsigned char *, unsigned int ))&MD5Update;
2017 utils->MD5Final = (void (*)(unsigned char [16], MD5_CTX *))&MD5Final;
2018 #else
2019 utils->MD5Init = &_sasl_MD5Init;
2020 utils->MD5Update= &_sasl_MD5Update;
2021 utils->MD5Final = &_sasl_MD5Final;
2022 #endif /* _SUN_SDK_ */
2023 utils->hmac_md5 = &_sasl_hmac_md5;
2024 utils->hmac_md5_init = &_sasl_hmac_md5_init;
2025 utils->hmac_md5_final = &_sasl_hmac_md5_final;
2026 utils->hmac_md5_precalc = &_sasl_hmac_md5_precalc;
2027 utils->hmac_md5_import = &_sasl_hmac_md5_import;
2028 utils->mkchal = &sasl_mkchal;
2029 utils->utf8verify = &sasl_utf8verify;
2030 utils->rand=&sasl_rand;
2031 utils->churn=&sasl_churn;
2032 utils->checkpass=NULL;
2033
2034 utils->encode64=&sasl_encode64;
2035 utils->decode64=&sasl_decode64;
2036
2037 utils->erasebuffer=&sasl_erasebuffer;
2038
2039 utils->getprop=&sasl_getprop;
2040 utils->setprop=&sasl_setprop;
2041
2042 utils->getcallback=&_sasl_getcallback;
2043
2044 utils->log=&_sasl_log;
2045
2046 utils->seterror=&sasl_seterror;
2047
2048 #ifndef macintosh
2049 /* Aux Property Utilities */
2050 utils->prop_new=&prop_new;
2051 utils->prop_dup=&prop_dup;
2052 utils->prop_request=&prop_request;
2053 utils->prop_get=&prop_get;
2054 utils->prop_getnames=&prop_getnames;
2055 utils->prop_clear=&prop_clear;
2056 utils->prop_dispose=&prop_dispose;
2057 utils->prop_format=&prop_format;
2058 utils->prop_set=&prop_set;
2059 utils->prop_setvals=&prop_setvals;
2060 utils->prop_erase=&prop_erase;
2061 #endif
2062
2063 /* Spares */
2064 utils->spare_fptr = NULL;
2065 utils->spare_fptr1 = utils->spare_fptr2 =
2066 utils->spare_fptr3 = NULL;
2067
2068 return utils;
2069 }
2070
2071 int
_sasl_free_utils(const sasl_utils_t ** utils)2072 _sasl_free_utils(const sasl_utils_t ** utils)
2073 {
2074 sasl_utils_t *nonconst;
2075 #ifdef _SUN_SDK_
2076 sasl_free_t *free_func;
2077 #endif /* _SUN_SDK_ */
2078
2079 if(!utils) return SASL_BADPARAM;
2080 if(!*utils) return SASL_OK;
2081
2082 /* I wish we could avoid this cast, it's pretty gratuitous but it
2083 * does make life easier to have it const everywhere else. */
2084 nonconst = (sasl_utils_t *)(*utils);
2085
2086 sasl_randfree(&(nonconst->rpool));
2087 #ifdef _SUN_SDK_
2088 free_func = (*utils)->free;
2089 free_func(nonconst);
2090 #else
2091 sasl_FREE(nonconst);
2092 #endif /* _SUN_SDK_ */
2093
2094 *utils = NULL;
2095 return SASL_OK;
2096 }
2097
sasl_idle(sasl_conn_t * conn)2098 int sasl_idle(sasl_conn_t *conn)
2099 {
2100 if (! conn) {
2101 #ifdef _SUN_SDK_
2102 _sasl_global_context_t *gctx = _sasl_gbl_ctx();
2103
2104 if (gctx->sasl_server_idle_hook
2105 && gctx->sasl_server_idle_hook(NULL))
2106 return 1;
2107 if (gctx->sasl_client_idle_hook
2108 && gctx->sasl_client_idle_hook(NULL))
2109 return 1;
2110 #else
2111 if (_sasl_server_idle_hook
2112 && _sasl_server_idle_hook(NULL))
2113 return 1;
2114 if (_sasl_client_idle_hook
2115 && _sasl_client_idle_hook(NULL))
2116 return 1;
2117 #endif /* _SUN_SDK_ */
2118 return 0;
2119 }
2120
2121 if (conn->idle_hook)
2122 return conn->idle_hook(conn);
2123
2124 return 0;
2125 }
2126
2127 const sasl_callback_t *
_sasl_find_getpath_callback(const sasl_callback_t * callbacks)2128 _sasl_find_getpath_callback(const sasl_callback_t *callbacks)
2129 {
2130 static const sasl_callback_t default_getpath_cb = {
2131 SASL_CB_GETPATH,
2132 &_sasl_getpath,
2133 NULL
2134 };
2135
2136 if (callbacks)
2137 while (callbacks->id != SASL_CB_LIST_END)
2138 {
2139 if (callbacks->id == SASL_CB_GETPATH)
2140 {
2141 return callbacks;
2142 } else {
2143 ++callbacks;
2144 }
2145 }
2146
2147 return &default_getpath_cb;
2148 }
2149
2150 #ifdef _SUN_SDK_
2151 extern const sasl_callback_t *
_sasl_find_getconf_callback(const sasl_callback_t * callbacks)2152 _sasl_find_getconf_callback(const sasl_callback_t *callbacks)
2153 {
2154 static const sasl_callback_t default_getconf_cb = {
2155 SASL_CB_GETCONF,
2156 &_sasl_getconf,
2157 NULL
2158 };
2159
2160 if (callbacks)
2161 while (callbacks->id != SASL_CB_LIST_END)
2162 {
2163 if (callbacks->id == SASL_CB_GETCONF)
2164 {
2165 return callbacks;
2166 } else {
2167 ++callbacks;
2168 }
2169 }
2170
2171 return &default_getconf_cb;
2172 }
2173 #endif /* _SUN_SDK_ */
2174
2175 const sasl_callback_t *
_sasl_find_verifyfile_callback(const sasl_callback_t * callbacks)2176 _sasl_find_verifyfile_callback(const sasl_callback_t *callbacks)
2177 {
2178 static const sasl_callback_t default_verifyfile_cb = {
2179 SASL_CB_VERIFYFILE,
2180 &_sasl_verifyfile,
2181 NULL
2182 };
2183
2184 if (callbacks)
2185 while (callbacks->id != SASL_CB_LIST_END)
2186 {
2187 if (callbacks->id == SASL_CB_VERIFYFILE)
2188 {
2189 return callbacks;
2190 } else {
2191 ++callbacks;
2192 }
2193 }
2194
2195 return &default_verifyfile_cb;
2196 }
2197
2198 /* Basically a conditional call to realloc(), if we need more */
2199 #ifdef _SUN_SDK_
__buf_alloc(const _sasl_global_context_t * gctx,char ** rwbuf,size_t * curlen,size_t newlen)2200 int __buf_alloc(const _sasl_global_context_t *gctx, char **rwbuf,
2201 size_t *curlen, size_t newlen)
2202 #else
2203 int _buf_alloc(char **rwbuf, size_t *curlen, size_t newlen)
2204 #endif /* _SUN_SDK_ */
2205 {
2206 if(!(*rwbuf)) {
2207 *rwbuf = sasl_ALLOC(newlen);
2208 if (*rwbuf == NULL) {
2209 *curlen = 0;
2210 return SASL_NOMEM;
2211 }
2212 *curlen = newlen;
2213 } else if(*rwbuf && *curlen < newlen) {
2214 size_t needed = 2*(*curlen);
2215
2216 while(needed < newlen)
2217 needed *= 2;
2218
2219 *rwbuf = sasl_REALLOC(*rwbuf, needed);
2220
2221 if (*rwbuf == NULL) {
2222 *curlen = 0;
2223 return SASL_NOMEM;
2224 }
2225 *curlen = needed;
2226 }
2227
2228 return SASL_OK;
2229 }
2230
2231 /* for the mac os x cfm glue: this lets the calling function
2232 get pointers to the error buffer without having to touch the sasl_conn_t struct */
_sasl_get_errorbuf(sasl_conn_t * conn,char *** bufhdl,size_t ** lenhdl)2233 void _sasl_get_errorbuf(sasl_conn_t *conn, char ***bufhdl, size_t **lenhdl)
2234 {
2235 *bufhdl = &conn->error_buf;
2236 *lenhdl = &conn->error_buf_len;
2237 }
2238
2239 /* convert an iovec to a single buffer */
2240 #ifdef _SUN_SDK_
_iovec_to_buf(const _sasl_global_context_t * gctx,const struct iovec * vec,unsigned numiov,buffer_info_t ** output)2241 int _iovec_to_buf(const _sasl_global_context_t *gctx, const struct iovec *vec,
2242 unsigned numiov, buffer_info_t **output)
2243 #else
2244 int _iovec_to_buf(const struct iovec *vec,
2245 unsigned numiov, buffer_info_t **output)
2246 #endif /* _SUN_SDK_ */
2247 {
2248 unsigned i;
2249 int ret;
2250 buffer_info_t *out;
2251 char *pos;
2252
2253 if(!vec || !output) return SASL_BADPARAM;
2254
2255 if(!(*output)) {
2256 *output = sasl_ALLOC(sizeof(buffer_info_t));
2257 if(!*output) return SASL_NOMEM;
2258 memset(*output,0,sizeof(buffer_info_t));
2259 }
2260
2261 out = *output;
2262
2263 out->curlen = 0;
2264 for(i=0; i<numiov; i++)
2265 out->curlen += vec[i].iov_len;
2266
2267 ret = _buf_alloc(&out->data, &out->reallen, out->curlen);
2268
2269 if(ret != SASL_OK) return SASL_NOMEM;
2270
2271 memset(out->data, 0, out->reallen);
2272 pos = out->data;
2273
2274 for(i=0; i<numiov; i++) {
2275 memcpy(pos, vec[i].iov_base, vec[i].iov_len);
2276 pos += vec[i].iov_len;
2277 }
2278
2279 return SASL_OK;
2280 }
2281
2282 /* This code might be useful in the future, but it isn't now, so.... */
2283 #if 0
2284 int _sasl_iptostring(const struct sockaddr *addr, socklen_t addrlen,
2285 char *out, unsigned outlen) {
2286 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
2287
2288 if(!addr || !out) return SASL_BADPARAM;
2289
2290 getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
2291 NI_NUMERICHOST | NI_WITHSCOPEID | NI_NUMERICSERV);
2292
2293 if(outlen < strlen(hbuf) + strlen(pbuf) + 2)
2294 return SASL_BUFOVER;
2295
2296 snprintf(out, outlen, "%s;%s", hbuf, pbuf);
2297
2298 return SASL_OK;
2299 }
2300 #endif
2301
2302 #ifdef _SUN_SDK_
2303 /* An ipv6 address will contain at least two colons */
can_be_ipv6(const char * addr)2304 static int can_be_ipv6(const char *addr)
2305 {
2306 const char *p;
2307
2308 if ((p = strchr(addr, ':')) == NULL)
2309 return (0);
2310
2311 p = strchr(p + 1, ':');
2312
2313 return (p != NULL);
2314 }
2315 #endif /* _SUN_SDK_ */
2316
_sasl_ipfromstring(const char * addr,struct sockaddr * out,socklen_t outlen)2317 int _sasl_ipfromstring(const char *addr,
2318 struct sockaddr *out, socklen_t outlen)
2319 {
2320 int i, j;
2321 struct addrinfo hints, *ai = NULL;
2322 char hbuf[NI_MAXHOST];
2323 #ifdef _SUN_SDK_
2324 const char *start, *end, *p;
2325 int addr_only = 1;
2326 #endif /* _SUN_SDK_ */
2327
2328 /* A NULL out pointer just implies we don't do a copy, just verify it */
2329
2330 if(!addr) return SASL_BADPARAM;
2331
2332 #ifdef _SUN_SDK_
2333 end = strchr(addr, ']');
2334 if (end != NULL) {
2335 /* This an rfc 2732 ipv6 address */
2336 start = strchr(addr, '[');
2337 if (start >= end || start == NULL)
2338 return SASL_BADPARAM;
2339 for (i = 0, p = start + 1; p < end; p++) {
2340 hbuf[i++] = *p;
2341 if (i >= NI_MAXHOST)
2342 return SASL_BADPARAM;
2343 }
2344 p = strchr(end, ':');
2345 if (p == NULL)
2346 p = end + 1;
2347 else
2348 p = p + 1;
2349 } else if (can_be_ipv6(addr) != 0) {
2350 /* Parse the address */
2351 for (i = 0; addr[i] != '\0' && addr[i] != ';'; ) {
2352 hbuf[i] = addr[i];
2353 if (++i >= NI_MAXHOST)
2354 return SASL_BADPARAM;
2355 }
2356 if (addr[i] == ';')
2357 p = &addr[i+1];
2358 else
2359 p = &addr[i];
2360 } else {
2361 for (i = 0; addr[i] != '\0' && addr[i] != ';' && addr[i] != ':'; ) {
2362 hbuf[i] = addr[i];
2363 if (isalpha(addr[i]))
2364 addr_only = 0;
2365 if (++i >= NI_MAXHOST)
2366 return SASL_BADPARAM;
2367 }
2368 if (addr[i] == ';' || addr[i] == ':')
2369 p = &addr[i+1];
2370 else
2371 p = &addr[i];
2372 }
2373 hbuf[i] = '\0';
2374 for (j = 0; p[j] != '\0'; j++)
2375 if (!isdigit((int)(p[j])))
2376 return SASL_BADPARAM;
2377 if (atoi(p) == 0)
2378 p = NULL;
2379 #else
2380 /* Parse the address */
2381 for (i = 0; addr[i] != '\0' && addr[i] != ';'; i++) {
2382 if (i >= NI_MAXHOST)
2383 return SASL_BADPARAM;
2384 hbuf[i] = addr[i];
2385 }
2386 hbuf[i] = '\0';
2387
2388 if (addr[i] == ';')
2389 i++;
2390 /* XXX: Do we need this check? */
2391 for (j = i; addr[j] != '\0'; j++)
2392 if (!isdigit((int)(addr[j])))
2393 return SASL_BADPARAM;
2394 #endif /* _SUN_SDK_ */
2395
2396 memset(&hints, 0, sizeof(hints));
2397 hints.ai_family = PF_UNSPEC;
2398 hints.ai_socktype = SOCK_STREAM;
2399 #ifdef _SUN_SDK_
2400 hints.ai_flags = addr_only ? AI_PASSIVE | AI_NUMERICHOST : AI_PASSIVE;
2401 if (getaddrinfo(hbuf, p, &hints, &ai) != 0)
2402 #else
2403 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
2404 if (getaddrinfo(hbuf, &addr[i], &hints, &ai) != 0)
2405 #endif /* _SUN_SDK_ */
2406 return SASL_BADPARAM;
2407
2408 if (out) {
2409 if (outlen < (socklen_t)ai->ai_addrlen) {
2410 freeaddrinfo(ai);
2411 return SASL_BUFOVER;
2412 }
2413 memcpy(out, ai->ai_addr, ai->ai_addrlen);
2414 }
2415
2416 freeaddrinfo(ai);
2417
2418 return SASL_OK;
2419 }
2420
2421 #ifdef _SUN_SDK_
_sasl_build_mechlist(_sasl_global_context_t * gctx)2422 int _sasl_build_mechlist(_sasl_global_context_t *gctx)
2423 #else
2424 int _sasl_build_mechlist(void)
2425 #endif /* _SUN_SDK_ */
2426 {
2427 int count = 0;
2428 sasl_string_list_t *clist = NULL, *slist = NULL, *olist = NULL;
2429 sasl_string_list_t *p, *q, **last, *p_next;
2430
2431 #ifdef _SUN_SDK_
2432 char **global_mech_list;
2433
2434 LOCK_MUTEX(&global_mutex);
2435
2436 clist = _sasl_client_mechs(gctx);
2437 slist = _sasl_server_mechs(gctx);
2438
2439 global_mech_list = gctx->global_mech_list;
2440 #else
2441 clist = _sasl_client_mechs();
2442 slist = _sasl_server_mechs();
2443 #endif /* _SUN_SDK_ */
2444
2445 if(!clist) {
2446 olist = slist;
2447 } else {
2448 int flag;
2449
2450 /* append slist to clist, and set olist to clist */
2451 for(p = slist; p; p = p_next) {
2452 flag = 0;
2453 p_next = p->next;
2454
2455 last = &clist;
2456 for(q = clist; q; q = q->next) {
2457 if(!strcmp(q->d, p->d)) {
2458 /* They match, set the flag */
2459 flag = 1;
2460 break;
2461 }
2462 last = &(q->next);
2463 }
2464
2465 if(!flag) {
2466 *last = p;
2467 p->next = NULL;
2468 } else {
2469 sasl_FREE(p);
2470 }
2471 }
2472
2473 olist = clist;
2474 }
2475
2476 if(!olist) {
2477 #ifdef _SUN_SDK_
2478 UNLOCK_MUTEX(&global_mutex);
2479 #else
2480 printf ("no olist");
2481 #endif /* _SUN_SDK_ */
2482 return SASL_FAIL;
2483 }
2484
2485 for (p = olist; p; p = p->next) count++;
2486
2487 if(global_mech_list) {
2488 sasl_FREE(global_mech_list);
2489 #ifdef _SUN_SDK_
2490 gctx->global_mech_list = NULL;
2491 #else
2492 global_mech_list = NULL;
2493 #endif /* _SUN_SDK_ */
2494 }
2495
2496 global_mech_list = sasl_ALLOC((count + 1) * sizeof(char *));
2497 if(!global_mech_list) return SASL_NOMEM;
2498
2499 memset(global_mech_list, 0, (count + 1) * sizeof(char *));
2500 #ifdef _SUN_SDK_
2501 gctx->global_mech_list = global_mech_list;
2502 #endif /* _SUN_SDK_ */
2503
2504 count = 0;
2505 for (p = olist; p; p = p_next) {
2506 p_next = p->next;
2507
2508 global_mech_list[count++] = (char *) p->d;
2509
2510 sasl_FREE(p);
2511 }
2512
2513 #ifdef _SUN_SDK_
2514 UNLOCK_MUTEX(&global_mutex);
2515 #endif /* _SUN_SDK_ */
2516
2517 return SASL_OK;
2518 }
2519
sasl_global_listmech(void)2520 const char ** sasl_global_listmech(void)
2521 {
2522 #ifdef _SUN_SDK_
2523 _sasl_global_context_t *gctx = _sasl_gbl_ctx();
2524
2525 return (const char **)gctx->global_mech_list;
2526 #else
2527 return (const char **)global_mech_list;
2528 #endif /* _SUN_SDK_ */
2529 }
2530
sasl_listmech(sasl_conn_t * conn,const char * user,const char * prefix,const char * sep,const char * suffix,const char ** result,unsigned * plen,int * pcount)2531 int sasl_listmech(sasl_conn_t *conn,
2532 const char *user,
2533 const char *prefix,
2534 const char *sep,
2535 const char *suffix,
2536 const char **result,
2537 unsigned *plen,
2538 int *pcount)
2539 {
2540 if(!conn) {
2541 return SASL_BADPARAM;
2542 } else if(conn->type == SASL_CONN_SERVER) {
2543 RETURN(conn, _sasl_server_listmech(conn, user, prefix, sep, suffix,
2544 result, plen, pcount));
2545 } else if (conn->type == SASL_CONN_CLIENT) {
2546 RETURN(conn, _sasl_client_listmech(conn, prefix, sep, suffix,
2547 result, plen, pcount));
2548 }
2549
2550 PARAMERROR(conn);
2551 }
2552
2553 #ifdef _SUN_SDK_
2554 /*
2555 * Creates a context so that libraries may use libsasl independently
2556 * of applications using libsasl.
2557 * Returns NULL on failure.
2558 *
2559 * sasl_free_context frees the context
2560 * To use libsasl independently of the default context, use
2561 * _sasl_server_init() instead of sasl_server_init()
2562 * _sasl_server_new() instead of sasl_server_new()
2563 * _sasl_client_init() instead of sasl_client_init()
2564 * _sasl_client_new() instead of sasl_client_new()
2565 * _sasl_client_add_plugin() instead of sasl_client_add_plugin()
2566 * _sasl_server_add_plugin() instead of sasl_server_add_plugin()
2567 * _sasl_canonuser_add_plugin() instead of sasl_canonuser_add_plugin()
2568 * _sasl_auxprop_add_plugin() instead of sasl_auxprop_add_plugin()
2569 */
2570
sasl_create_context(void)2571 void *sasl_create_context(void)
2572 {
2573 _sasl_global_context_t *gctx;
2574
2575 gctx = (_sasl_global_context_t *)
2576 sasl_sun_ALLOC(sizeof(_sasl_global_context_t));
2577
2578 if (gctx != NULL) {
2579 memset(gctx, 0, sizeof(_sasl_global_context_t));
2580
2581 gctx->server_global_callbacks.gctx = gctx;
2582 gctx->client_global_callbacks.gctx = gctx;
2583 LOCK_MUTEX(&malloc_global_mutex);
2584 gctx->sasl_allocation_utils.malloc = (sasl_malloc_t *)&malloc;
2585 gctx->sasl_allocation_utils.calloc = (sasl_calloc_t *)&calloc;
2586 gctx->sasl_allocation_utils.realloc = (sasl_realloc_t *)&realloc;
2587 gctx->sasl_allocation_utils.free = (sasl_free_t *)&free;
2588 gctx->sasl_mutex_utils.alloc = sasl_mutex_alloc;
2589 gctx->sasl_mutex_utils.lock = sasl_mutex_lock;
2590 gctx->sasl_mutex_utils.unlock = sasl_mutex_unlock;
2591 gctx->sasl_mutex_utils.free = sasl_mutex_free;
2592 UNLOCK_MUTEX(&malloc_global_mutex);
2593 }
2594 return gctx;
2595 }
2596
2597 /* Frees the context created by sasl_create_context() */
sasl_free_context(void * context)2598 void sasl_free_context(void *context)
2599 {
2600 _sasl_dispose_context(context);
2601 if (context != NULL) {
2602 sasl_sun_FREE(context);
2603 }
2604 }
2605
2606 /* Used by both sasl_done() and sasl_free_context() to free context */
_sasl_dispose_context(_sasl_global_context_t * gctx)2607 static void _sasl_dispose_context(_sasl_global_context_t *gctx)
2608 {
2609 if (gctx == NULL)
2610 return;
2611
2612 if (gctx->sasl_server_cleanup_hook &&
2613 gctx->sasl_server_cleanup_hook(gctx) == SASL_OK) {
2614 gctx->sasl_server_idle_hook = NULL;
2615 gctx->sasl_server_cleanup_hook = NULL;
2616 }
2617
2618 if (gctx->sasl_client_cleanup_hook &&
2619 gctx->sasl_client_cleanup_hook(gctx) == SASL_OK) {
2620 gctx->sasl_client_idle_hook = NULL;
2621 gctx->sasl_client_cleanup_hook = NULL;
2622 }
2623
2624 if(gctx->sasl_server_cleanup_hook || gctx->sasl_client_cleanup_hook)
2625 return;
2626
2627 _sasl_canonuser_free(gctx);
2628 _sasl_done_with_plugins(gctx);
2629
2630 sasl_config_free(gctx);
2631
2632 if (gctx->free_mutex != NULL)
2633 sasl_MUTEX_FREE(gctx->free_mutex);
2634 gctx->free_mutex = NULL;
2635
2636 _sasl_free_utils(&(gctx->sasl_server_global_utils));
2637 _sasl_free_utils(&(gctx->sasl_canonusr_global_utils));
2638
2639 LOCK_MUTEX(&global_mutex);
2640 sasl_FREE((void *)gctx->global_mech_list);
2641 gctx->global_mech_list = NULL;
2642 UNLOCK_MUTEX(&global_mutex);
2643
2644 /* in case of another init/done */
2645 gctx->sasl_server_cleanup_hook = NULL;
2646 gctx->sasl_client_cleanup_hook = NULL;
2647
2648 gctx->sasl_client_idle_hook = NULL;
2649 gctx->sasl_server_idle_hook = NULL;
2650 }
2651
_sasl_gbl_ctx(void)2652 _sasl_global_context_t *_sasl_gbl_ctx(void)
2653 {
2654 static _sasl_global_context_t gbl_ctx = {
2655 0, /* sasl_server_active */
2656 NULL, /* mechlist */
2657 NULL, /* splug_path_info */
2658 {NULL, NULL, &gbl_ctx}, /* server_global_callbacks */
2659 NULL, /* sasl_server_cleanup_hook */
2660 NULL, /* sasl_server_idle_hook */
2661 NULL, /* cmechlist */
2662 NULL, /* cplug_path_info */
2663 {NULL, NULL, &gbl_ctx}, /* client_global_callbacks */
2664 0, /* sasl_client_active */
2665 NULL, /* sasl_client_cleanup_hook */
2666 NULL, /* sasl_client_idle_hook */
2667 NULL, /* sasl_server_global_utils */
2668 NULL, /* sasl_client_global_utils */
2669 NULL, /* configlist */
2670 0, /* nconfiglist */
2671 NULL, /* config_path */
2672 0, /* config_last_read */
2673 NULL, /* auxprop_head */
2674 NULL, /* canonuser_head */
2675 NULL, /* global_mech_list */
2676 NULL, /* free_mutex */
2677 {(sasl_malloc_t *)&malloc, (sasl_calloc_t *)&calloc,
2678 (sasl_realloc_t *)&realloc, (sasl_free_t *)&free},
2679 /* sasl_allocation_utils */
2680 {&sasl_mutex_alloc, &sasl_mutex_lock, &sasl_mutex_unlock,
2681 &sasl_mutex_free}, /* sasl_mutex_utils */
2682 NULL /* lib_list_head */
2683 };
2684
2685 return (&gbl_ctx);
2686 }
2687
2688 static int
_sasl_getconf(void * context,const char ** conf)2689 _sasl_getconf(void *context __attribute__((unused)), const char **conf)
2690 {
2691 if (! conf)
2692 return SASL_BADPARAM;
2693
2694 *conf = SASL_CONFDIR;
2695
2696 return SASL_OK;
2697 }
2698
2699 /* EXPORT DELETE START */
2700 /* CRYPT DELETE START */
2701 #ifdef _INTEGRATED_SOLARIS_
2702 #pragma fini(sasl_fini)
2703 int
sasl_fini(void)2704 sasl_fini(void)
2705 {
2706 reg_list_t *next;
2707
2708 while (reg_list_base != NULL) {
2709 next = reg_list_base->next;
2710 free(reg_list_base);
2711 reg_list_base = next;
2712 }
2713 return (0);
2714 }
2715 #endif /* _INTEGRATED_SOLARIS_ */
2716 /* CRYPT DELETE END */
2717 /* EXPORT DELETE END */
2718
2719 #endif /* _SUN_SDK_ */
2720
2721 #ifndef WIN32
2722 static int
_sasl_getpath(void * context,const char ** path)2723 _sasl_getpath(void *context __attribute__((unused)),
2724 const char **path)
2725 {
2726 if (! path)
2727 return SASL_BADPARAM;
2728
2729 #ifdef _SUN_SDK_
2730 /* SASL_PATH is not allowed for SUN SDK */
2731 #else
2732 *path = getenv(SASL_PATH_ENV_VAR);
2733 if (! *path)
2734 #endif /* _SUN_SDK_ */
2735 *path = PLUGINDIR;
2736
2737 return SASL_OK;
2738 }
2739
2740 #else
2741 /* Return NULL on failure */
2742 static int
_sasl_getpath(void * context,const char ** path)2743 _sasl_getpath(void *context __attribute__((unused)), const char **path)
2744 {
2745 /* Open registry entry, and find all registered SASL libraries.
2746 *
2747 * Registry location:
2748 *
2749 * SOFTWARE\\Carnegie Mellon\\Project Cyrus\\SASL Library
2750 *
2751 * Key - value:
2752 *
2753 * "SearchPath" - value: PATH like (';' delimited) list
2754 * of directories where to search for plugins
2755 * The list may contain references to environment
2756 * variables (e.g. %PATH%).
2757 *
2758 */
2759 HKEY hKey;
2760 DWORD ret;
2761 DWORD ValueType; /* value type */
2762 DWORD cbData; /* value size */
2763 BYTE * ValueData; /* value */
2764 DWORD cbExpandedData; /* "expanded" value size */
2765 BYTE * ExpandedValueData; /* "expanded" value */
2766 char * return_value; /* function return value */
2767 char * tmp;
2768
2769 /* Initialization */
2770 ExpandedValueData = NULL;
2771 ValueData = NULL;
2772 return_value = NULL;
2773
2774 /* Open the registry */
2775 ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
2776 SASL_ROOT_KEY,
2777 0,
2778 KEY_READ,
2779 &hKey);
2780
2781 if (ret != ERROR_SUCCESS) {
2782 /* no registry entry */
2783 *path = PLUGINDIR;
2784 return SASL_OK;
2785 }
2786
2787 /* figure out value type and required buffer size */
2788 /* the size will include space for terminating NUL if required */
2789 RegQueryValueEx (hKey,
2790 SASL_PATH_SUBKEY,
2791 NULL, /* reserved */
2792 &ValueType,
2793 NULL,
2794 &cbData);
2795
2796 /* Only accept string related types */
2797 if (ValueType != REG_EXPAND_SZ &&
2798 ValueType != REG_MULTI_SZ &&
2799 ValueType != REG_SZ) {
2800 return_value = NULL;
2801 goto CLEANUP;
2802 }
2803
2804 /* Any high water mark? */
2805 ValueData = sasl_ALLOC(cbData);
2806 if (ValueData == NULL) {
2807 return_value = NULL;
2808 goto CLEANUP;
2809 };
2810
2811 RegQueryValueEx (hKey,
2812 SASL_PATH_SUBKEY,
2813 NULL, /* reserved */
2814 &ValueType,
2815 ValueData,
2816 &cbData);
2817
2818 switch (ValueType) {
2819 case REG_EXPAND_SZ:
2820 /* : A random starting guess */
2821 cbExpandedData = cbData + 1024;
2822 ExpandedValueData = sasl_ALLOC(cbExpandedData);
2823 if (ExpandedValueData == NULL) {
2824 return_value = NULL;
2825 goto CLEANUP;
2826 };
2827
2828 cbExpandedData = ExpandEnvironmentStrings(
2829 ValueData,
2830 ExpandedValueData,
2831 cbExpandedData);
2832
2833 if (cbExpandedData == 0) {
2834 /* : GetLastError() contains the reason for failure */
2835 return_value = NULL;
2836 goto CLEANUP;
2837 }
2838
2839 /* : Must retry expansion with the bigger buffer */
2840 if (cbExpandedData > cbData + 1024) {
2841 /* : Memory leak here if can't realloc */
2842 ExpandedValueData = sasl_REALLOC(ExpandedValueData, cbExpandedData);
2843 if (ExpandedValueData == NULL) {
2844 return_value = NULL;
2845 goto CLEANUP;
2846 };
2847
2848 cbExpandedData = ExpandEnvironmentStrings(
2849 ValueData,
2850 ExpandedValueData,
2851 cbExpandedData);
2852
2853 /* : This should not happen */
2854 if (cbExpandedData == 0) {
2855 /* : GetLastError() contains the reason for failure */
2856 return_value = NULL;
2857 goto CLEANUP;
2858 }
2859 }
2860
2861 sasl_FREE(ValueData);
2862 ValueData = ExpandedValueData;
2863 /* : This is to prevent automatical freeing of this block on cleanup */
2864 ExpandedValueData = NULL;
2865
2866 break;
2867
2868 case REG_MULTI_SZ:
2869 tmp = ValueData;
2870
2871 /* : We shouldn't overflow here, as the buffer is guarantied
2872 : to contain at least two consequent NULs */
2873 while (1) {
2874 if (tmp[0] == '\0') {
2875 /* : Stop the process if we found the end of the string (two consequent NULs) */
2876 if (tmp[1] == '\0') {
2877 break;
2878 }
2879
2880 /* : Replace delimiting NUL with our delimiter characted */
2881 tmp[0] = PATHS_DELIMITER;
2882 }
2883 tmp += strlen(tmp);
2884 }
2885 break;
2886
2887 case REG_SZ:
2888 /* Do nothing, it is good as is */
2889 break;
2890
2891 default:
2892 return_value = NULL;
2893 goto CLEANUP;
2894 }
2895
2896 return_value = ValueData;
2897
2898 CLEANUP:
2899 RegCloseKey(hKey);
2900 if (ExpandedValueData != NULL) sasl_FREE(ExpandedValueData);
2901 if (return_value == NULL) {
2902 if (ValueData != NULL) sasl_FREE(ValueData);
2903 }
2904 *path = return_value;
2905
2906 #ifdef _SUN_SDK_
2907 /* SASL_PATH is not allowed for SUN SDK */
2908 if (! *path)
2909 *path = PLUGINDIR;
2910 #endif /* _SUN_SDK_ */
2911 return SASL_OK;
2912 }
2913
2914 #endif
2915