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