1 /* 2 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 #pragma ident "%Z%%M% %I% %E% SMI" 6 7 /* common.c - Functions that are common to server and clinet 8 * Rob Siemborski 9 * Tim Martin 10 * $Id: common.c,v 1.92 2003/04/16 19:36:00 rjs3 Exp $ 11 */ 12 /* 13 * Copyright (c) 1998-2003 Carnegie Mellon University. All rights reserved. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in 24 * the documentation and/or other materials provided with the 25 * distribution. 26 * 27 * 3. The name "Carnegie Mellon University" must not be used to 28 * endorse or promote products derived from this software without 29 * prior written permission. For permission or any other legal 30 * details, please contact 31 * Office of Technology Transfer 32 * Carnegie Mellon University 33 * 5000 Forbes Avenue 34 * Pittsburgh, PA 15213-3890 35 * (412) 268-4387, fax: (412) 268-7395 36 * tech-transfer@andrew.cmu.edu 37 * 38 * 4. Redistributions of any form whatsoever must retain the following 39 * acknowledgment: 40 * "This product includes software developed by Computing Services 41 * at Carnegie Mellon University (http://www.cmu.edu/computing/)." 42 * 43 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO 44 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 45 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE 46 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 47 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 48 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 49 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 50 */ 51 52 #include <config.h> 53 #include <stdio.h> 54 #include <string.h> 55 #include <stdlib.h> 56 #include <limits.h> 57 #ifdef HAVE_SYSLOG 58 #include <syslog.h> 59 #endif 60 #include <stdarg.h> 61 #include <ctype.h> 62 63 #include <sasl.h> 64 #include <saslutil.h> 65 #include <saslplug.h> 66 #include "saslint.h" 67 68 #ifdef _SUN_SDK_ 69 #include "md5_private.h" 70 #include "hmac-md5.h" 71 #include "plugin_common.h" 72 #endif 73 74 75 #ifdef WIN32 76 /* need to handle the fact that errno has been defined as a function 77 in a dll, not an extern int */ 78 # ifdef errno 79 # undef errno 80 # endif /* errno */ 81 #endif /* WIN32 */ 82 #ifdef HAVE_UNISTD_H 83 #include <unistd.h> 84 #endif 85 86 static int _sasl_getpath(void *context __attribute__((unused)), const char **path); 87 88 #ifdef _SUN_SDK_ 89 DEFINE_STATIC_MUTEX(global_mutex); 90 DEFINE_STATIC_MUTEX(malloc_global_mutex); 91 static void _sasl_dispose_context(_sasl_global_context_t *ctx); 92 static int _sasl_getconf(void *context, const char **conf); 93 94 #ifdef _INTEGRATED_SOLARIS_ 95 static int init_thread_set_specific = 0; 96 static pthread_key_t errstring_key; 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 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 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 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 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) */ 166 static void *sasl_mutex_alloc(void) 167 { 168 return (void *)0x1; 169 } 170 171 static int sasl_mutex_lock(void *mutex __attribute__((unused))) 172 { 173 return SASL_OK; 174 } 175 176 static int sasl_mutex_unlock(void *mutex __attribute__((unused))) 177 { 178 return SASL_OK; 179 } 180 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 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_ 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_ 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 # */ 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 */ 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 */ 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 */ 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 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 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 */ 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_ 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 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 */ 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 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 */ 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 */ 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 */ 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_ 1110 static void free_err_tsd(void *key) 1111 { 1112 free(key); 1113 1114 pthread_setspecific(errstring_key, NULL); 1115 } 1116 #endif /* _INTEGRATED_SOLARIS_ */ 1117 1118 const char *sasl_errstring(int saslerr, 1119 #ifdef _SUN_SDK_ 1120 const char *langlist, 1121 #else 1122 const char *langlist __attribute__((unused)), 1123 #endif /* _SUN_SDK_ */ 1124 const char **outlang) 1125 { 1126 #ifdef _INTEGRATED_SOLARIS_ 1127 const char *s; 1128 const char *s_locale; 1129 char *s_utf8; 1130 void *tsd; 1131 1132 if (outlang) *outlang="i-default"; 1133 #else 1134 if (outlang) *outlang="en-us"; 1135 #endif /* _INTEGRATED_SOLARIS_ */ 1136 1137 #ifdef _INTEGRATED_SOLARIS_ 1138 switch(saslerr) 1139 { 1140 case SASL_CONTINUE: s = gettext("another step is needed in authentication"); 1141 break; 1142 case SASL_OK: s = gettext("successful result"); 1143 break; 1144 case SASL_FAIL: s = gettext("generic failure"); 1145 break; 1146 case SASL_NOMEM: s = gettext("no memory available"); 1147 break; 1148 case SASL_BUFOVER: s = gettext("overflowed buffer"); 1149 break; 1150 case SASL_NOMECH: s = gettext("no mechanism available"); 1151 break; 1152 case SASL_BADPROT: s = gettext("bad protocol / cancel"); 1153 break; 1154 case SASL_NOTDONE: s = gettext("can't request info until later in exchange"); 1155 break; 1156 case SASL_BADPARAM: s = gettext("invalid parameter supplied"); 1157 break; 1158 case SASL_TRYAGAIN: s = gettext("transient failure (e.g., weak key)"); 1159 break; 1160 case SASL_BADMAC: s = gettext("integrity check failed"); 1161 break; 1162 case SASL_NOTINIT: s = gettext("SASL library not initialized"); 1163 break; 1164 /* -- client only codes -- */ 1165 case SASL_INTERACT: s = gettext("needs user interaction"); 1166 break; 1167 case SASL_BADSERV: s = gettext("server failed mutual authentication step"); 1168 break; 1169 case SASL_WRONGMECH: s = gettext("mechanism doesn't support requested feature"); 1170 break; 1171 /* -- server only codes -- */ 1172 case SASL_BADAUTH: s = gettext("authentication failure"); 1173 break; 1174 case SASL_NOAUTHZ: s = gettext("authorization failure"); 1175 break; 1176 case SASL_TOOWEAK: s = gettext("mechanism too weak for this user"); 1177 break; 1178 case SASL_ENCRYPT: s = gettext("encryption needed to use mechanism"); 1179 break; 1180 case SASL_TRANS: s = gettext("One time use of a plaintext password will enable requested mechanism for user"); 1181 break; 1182 case SASL_EXPIRED: s = gettext("passphrase expired, has to be reset"); 1183 break; 1184 case SASL_DISABLED: s = gettext("account disabled"); 1185 break; 1186 case SASL_NOUSER: s = gettext("user not found"); 1187 break; 1188 case SASL_BADVERS: s = gettext("version mismatch with plug-in"); 1189 break; 1190 case SASL_UNAVAIL: s = gettext("remote authentication server unavailable"); 1191 break; 1192 case SASL_NOVERIFY: s = gettext("user exists, but no verifier for user"); 1193 break; 1194 case SASL_PWLOCK: s = gettext("passphrase locked"); 1195 break; 1196 case SASL_NOCHANGE: s = gettext("requested change was not needed"); 1197 break; 1198 case SASL_WEAKPASS: s = gettext("passphrase is too weak for security policy"); 1199 break; 1200 case SASL_NOUSERPASS: s = gettext("user supplied passwords are not permitted"); 1201 1202 break; 1203 default: s = gettext("undefined error!"); 1204 break; 1205 } 1206 1207 if (use_locale(langlist, 0)) 1208 s_locale = dgettext(TEXT_DOMAIN, s); 1209 else 1210 s_locale = s; 1211 1212 if (s == s_locale) 1213 return s; 1214 1215 s_utf8 = local_to_utf(NULL, s_locale); 1216 if (s_utf8 == NULL) 1217 return s; 1218 1219 if (!init_thread_set_specific) { 1220 LOCK_MUTEX(&global_mutex); 1221 if (!init_thread_set_specific) { 1222 if (pthread_key_create(&errstring_key, free_err_tsd) == 0) 1223 init_thread_set_specific = 1; 1224 } 1225 UNLOCK_MUTEX(&global_mutex); 1226 } 1227 if (!init_thread_set_specific) { 1228 free(s_utf8); 1229 return s; 1230 } 1231 1232 tsd = pthread_getspecific(errstring_key); 1233 if (tsd == NULL) 1234 free(tsd); 1235 pthread_setspecific(errstring_key, s_utf8); 1236 1237 if (outlang) *outlang="*"; 1238 return s_utf8; 1239 #else 1240 switch(saslerr) 1241 { 1242 case SASL_CONTINUE: return "another step is needed in authentication"; 1243 case SASL_OK: return "successful result"; 1244 case SASL_FAIL: return "generic failure"; 1245 case SASL_NOMEM: return "no memory available"; 1246 case SASL_BUFOVER: return "overflowed buffer"; 1247 case SASL_NOMECH: return "no mechanism available"; 1248 case SASL_BADPROT: return "bad protocol / cancel"; 1249 case SASL_NOTDONE: return "can't request info until later in exchange"; 1250 case SASL_BADPARAM: return "invalid parameter supplied"; 1251 case SASL_TRYAGAIN: return "transient failure (e.g., weak key)"; 1252 case SASL_BADMAC: return "integrity check failed"; 1253 case SASL_NOTINIT: return "SASL library not initialized"; 1254 /* -- client only codes -- */ 1255 case SASL_INTERACT: return "needs user interaction"; 1256 case SASL_BADSERV: return "server failed mutual authentication step"; 1257 case SASL_WRONGMECH: return "mechanism doesn't support requested feature"; 1258 /* -- server only codes -- */ 1259 case SASL_BADAUTH: return "authentication failure"; 1260 case SASL_NOAUTHZ: return "authorization failure"; 1261 case SASL_TOOWEAK: return "mechanism too weak for this user"; 1262 case SASL_ENCRYPT: return "encryption needed to use mechanism"; 1263 case SASL_TRANS: return "One time use of a plaintext password will enable requested mechanism for user"; 1264 case SASL_EXPIRED: return "passphrase expired, has to be reset"; 1265 case SASL_DISABLED: return "account disabled"; 1266 case SASL_NOUSER: return "user not found"; 1267 case SASL_BADVERS: return "version mismatch with plug-in"; 1268 case SASL_UNAVAIL: return "remote authentication server unavailable"; 1269 case SASL_NOVERIFY: return "user exists, but no verifier for user"; 1270 case SASL_PWLOCK: return "passphrase locked"; 1271 case SASL_NOCHANGE: return "requested change was not needed"; 1272 case SASL_WEAKPASS: return "passphrase is too weak for security policy"; 1273 case SASL_NOUSERPASS: return "user supplied passwords are not permitted"; 1274 1275 default: return "undefined error!"; 1276 } 1277 #endif /* _INTEGRATED_SOLARIS_ */ 1278 1279 } 1280 1281 /* Return the sanitized error detail about the last error that occured for 1282 * a connection */ 1283 const char *sasl_errdetail(sasl_conn_t *conn) 1284 { 1285 unsigned need_len; 1286 const char *errstr; 1287 char leader[128]; 1288 #ifdef _SUN_SDK_ 1289 int ret; 1290 const _sasl_global_context_t *gctx; 1291 1292 if(!conn) return "invalid parameter supplied"; 1293 1294 gctx = conn->gctx; 1295 #else 1296 if(!conn) return NULL; 1297 #endif /* _SUN_SDK_ */ 1298 1299 errstr = sasl_errstring(conn->error_code, NULL, NULL); 1300 snprintf(leader,128,"SASL(%d): %s: ", 1301 sasl_usererr(conn->error_code), errstr); 1302 1303 need_len = strlen(leader) + strlen(conn->error_buf) + 12; 1304 #ifdef _SUN_SDK_ 1305 ret = _buf_alloc(&conn->errdetail_buf, &conn->errdetail_buf_len, need_len); 1306 if (ret != SASL_OK) 1307 return "no memory available"; 1308 #else 1309 _buf_alloc(&conn->errdetail_buf, &conn->errdetail_buf_len, need_len); 1310 #endif /* _SUN_SDK_ */ 1311 1312 snprintf(conn->errdetail_buf, need_len, "%s%s", leader, conn->error_buf); 1313 1314 return conn->errdetail_buf; 1315 } 1316 1317 /* EXPORT DELETE START */ 1318 /* CRYPT DELETE START */ 1319 #ifdef _INTEGRATED_SOLARIS_ 1320 DEFINE_STATIC_MUTEX(reg_mutex); 1321 typedef struct reg_list { 1322 struct reg_list *next; 1323 void *mech; 1324 } reg_list_t; 1325 1326 static reg_list_t *reg_list_base = NULL; 1327 1328 int _is_sun_reg(void *mech) 1329 { 1330 reg_list_t *r, *prev; 1331 int is_reg = 0; 1332 1333 LOCK_MUTEX(®_mutex); 1334 for (r = reg_list_base; r != NULL; r = r->next) { 1335 if (r->mech != mech) { 1336 prev = r; 1337 continue; 1338 } 1339 is_reg = 1; 1340 if (r == reg_list_base) { 1341 reg_list_base = reg_list_base->next; 1342 } else { 1343 prev->next = r->next; 1344 } 1345 free(r); 1346 break; 1347 } 1348 UNLOCK_MUTEX(®_mutex); 1349 return (is_reg); 1350 } 1351 1352 static void 1353 _register_plugin(void *arg) 1354 { 1355 reg_list_t *r = (reg_list_t *)calloc(1, sizeof (reg_list_t)); 1356 1357 if (r != NULL) { 1358 r->mech = arg; 1359 LOCK_MUTEX(®_mutex); 1360 r->next = reg_list_base; 1361 reg_list_base = r; 1362 UNLOCK_MUTEX(®_mutex); 1363 } 1364 } 1365 #endif /* _INTEGRATED_SOLARIS_ */ 1366 /* CRYPT DELETE END */ 1367 /* EXPORT DELETE END */ 1368 1369 /* Note that this needs the global callbacks, so if you don't give getcallbacks 1370 * a sasl_conn_t, you're going to need to pass it yourself (or else we couldn't 1371 * have client and server at the same time */ 1372 static int _sasl_global_getopt(void *context, 1373 const char *plugin_name, 1374 const char *option, 1375 const char ** result, 1376 unsigned *len) 1377 { 1378 const sasl_global_callbacks_t * global_callbacks; 1379 const sasl_callback_t *callback; 1380 #ifdef _SUN_SDK_ 1381 _sasl_global_context_t *gctx; 1382 #endif /* _SUN_SDK_ */ 1383 1384 global_callbacks = (const sasl_global_callbacks_t *) context; 1385 1386 #ifdef _SUN_SDK_ 1387 /* EXPORT DELETE START */ 1388 /* CRYPT DELETE START */ 1389 #ifdef _INTEGRATED_SOLARIS_ 1390 if (strcmp("reg_sun_plug", option) == 0) { 1391 *result = (const char *)_register_plugin; 1392 *len = 0; 1393 return (SASL_OK); 1394 } 1395 #endif /* _INTEGRATED_SOLARIS_ */ 1396 /* CRYPT DELETE END */ 1397 /* EXPORT DELETE END */ 1398 1399 if (global_callbacks) 1400 gctx = global_callbacks->gctx; 1401 else 1402 gctx = _sasl_gbl_ctx(); 1403 #endif /* _SUN_SDK_ */ 1404 1405 if (global_callbacks && global_callbacks->callbacks) { 1406 for (callback = global_callbacks->callbacks; 1407 callback->id != SASL_CB_LIST_END; 1408 callback++) { 1409 if (callback->id == SASL_CB_GETOPT) { 1410 if (!callback->proc) return SASL_FAIL; 1411 if (((sasl_getopt_t *)(callback->proc))(callback->context, 1412 plugin_name, 1413 option, 1414 result, 1415 len) 1416 == SASL_OK) 1417 return SASL_OK; 1418 } 1419 } 1420 } 1421 1422 /* look it up in our configuration file */ 1423 #ifdef _SUN_SDK_ 1424 *result = sasl_config_getstring(gctx, option, NULL); 1425 #else 1426 *result = sasl_config_getstring(option, NULL); 1427 #endif /* _SUN_SDK_ */ 1428 if (*result != NULL) { 1429 if (len) { *len = strlen(*result); } 1430 return SASL_OK; 1431 } 1432 1433 return SASL_FAIL; 1434 } 1435 1436 static int 1437 _sasl_conn_getopt(void *context, 1438 const char *plugin_name, 1439 const char *option, 1440 const char ** result, 1441 unsigned *len) 1442 { 1443 sasl_conn_t * conn; 1444 const sasl_callback_t *callback; 1445 1446 if (! context) 1447 return SASL_BADPARAM; 1448 1449 conn = (sasl_conn_t *) context; 1450 1451 if (conn->callbacks) 1452 for (callback = conn->callbacks; 1453 callback->id != SASL_CB_LIST_END; 1454 callback++) 1455 if (callback->id == SASL_CB_GETOPT 1456 && (((sasl_getopt_t *)(callback->proc))(callback->context, 1457 plugin_name, 1458 option, 1459 result, 1460 len) 1461 == SASL_OK)) 1462 return SASL_OK; 1463 1464 /* If we made it here, we didn't find an appropriate callback 1465 * in the connection's callback list, or the callback we did 1466 * find didn't return SASL_OK. So we attempt to use the 1467 * global callback for this connection... */ 1468 return _sasl_global_getopt((void *)conn->global_callbacks, 1469 plugin_name, 1470 option, 1471 result, 1472 len); 1473 } 1474 1475 #ifdef HAVE_SYSLOG 1476 /* this is the default logging */ 1477 static int _sasl_syslog(void *context __attribute__((unused)), 1478 int priority, 1479 const char *message) 1480 { 1481 int syslog_priority; 1482 1483 /* set syslog priority */ 1484 switch(priority) { 1485 case SASL_LOG_NONE: 1486 return SASL_OK; 1487 break; 1488 case SASL_LOG_ERR: 1489 syslog_priority = LOG_ERR; 1490 break; 1491 case SASL_LOG_WARN: 1492 syslog_priority = LOG_WARNING; 1493 break; 1494 case SASL_LOG_NOTE: 1495 case SASL_LOG_FAIL: 1496 syslog_priority = LOG_NOTICE; 1497 break; 1498 case SASL_LOG_PASS: 1499 case SASL_LOG_TRACE: 1500 case SASL_LOG_DEBUG: 1501 default: 1502 syslog_priority = LOG_DEBUG; 1503 break; 1504 } 1505 1506 /* do the syslog call. do not need to call openlog */ 1507 syslog(syslog_priority | LOG_AUTH, "%s", message); 1508 1509 return SASL_OK; 1510 } 1511 #endif /* HAVE_SYSLOG */ 1512 1513 static int 1514 _sasl_getsimple(void *context, 1515 int id, 1516 const char ** result, 1517 size_t *len) 1518 { 1519 const char *userid; 1520 #ifndef _SUN_SDK_ 1521 sasl_conn_t *conn; 1522 #endif /* _SUN_SDK_ */ 1523 1524 if (! context || ! result) return SASL_BADPARAM; 1525 1526 #ifndef _SUN_SDK_ 1527 conn = (sasl_conn_t *)context; 1528 #endif /* _SUN_SDK_ */ 1529 1530 switch(id) { 1531 case SASL_CB_AUTHNAME: 1532 #ifdef _INTEGRATED_SOLARIS_ 1533 userid = getenv("LOGNAME"); 1534 if (userid != NULL) { 1535 *result = userid; 1536 if (len) *len = strlen(userid); 1537 return SASL_OK; 1538 } 1539 #else 1540 userid = getenv("USER"); 1541 if (userid != NULL) { 1542 *result = userid; 1543 if (len) *len = strlen(userid); 1544 return SASL_OK; 1545 } 1546 userid = getenv("USERNAME"); 1547 if (userid != NULL) { 1548 *result = userid; 1549 if (len) *len = strlen(userid); 1550 return SASL_OK; 1551 } 1552 #endif /* _INTEGRATED_SOLARIS_ */ 1553 #ifdef WIN32 1554 /* for win32, try using the GetUserName standard call */ 1555 { 1556 DWORD i; 1557 BOOL rval; 1558 static char sender[128]; 1559 1560 i = sizeof(sender); 1561 rval = GetUserName(sender, &i); 1562 if ( rval) { /* got a userid */ 1563 *result = sender; 1564 if (len) *len = strlen(sender); 1565 return SASL_OK; 1566 } 1567 } 1568 #endif /* WIN32 */ 1569 return SASL_FAIL; 1570 default: 1571 return SASL_BADPARAM; 1572 } 1573 } 1574 1575 static int 1576 _sasl_verifyfile(void *context __attribute__((unused)), 1577 char *file __attribute__((unused)), 1578 int type __attribute__((unused))) 1579 { 1580 /* always say ok */ 1581 return SASL_OK; 1582 } 1583 1584 1585 static int 1586 _sasl_proxy_policy(sasl_conn_t *conn, 1587 void *context __attribute__((unused)), 1588 const char *requested_user, unsigned rlen, 1589 const char *auth_identity, unsigned alen, 1590 const char *def_realm __attribute__((unused)), 1591 unsigned urlen __attribute__((unused)), 1592 struct propctx *propctx __attribute__((unused))) 1593 { 1594 if (!conn) 1595 return SASL_BADPARAM; 1596 1597 if (!requested_user || *requested_user == '\0') 1598 return SASL_OK; 1599 1600 if (!auth_identity || !requested_user || rlen != alen || 1601 (memcmp(auth_identity, requested_user, rlen) != 0)) { 1602 #ifdef _INTEGRATED_SOLARIS_ 1603 sasl_seterror(conn, 0, 1604 gettext("Requested identity not authenticated identity")); 1605 #else 1606 sasl_seterror(conn, 0, 1607 "Requested identity not authenticated identity"); 1608 #endif /* _INTEGRATED_SOLARIS_ */ 1609 RETURN(conn, SASL_BADAUTH); 1610 } 1611 1612 return SASL_OK; 1613 } 1614 1615 int _sasl_getcallback(sasl_conn_t * conn, 1616 unsigned long callbackid, 1617 int (**pproc)(), 1618 void **pcontext) 1619 { 1620 const sasl_callback_t *callback; 1621 1622 if (!pproc || !pcontext) 1623 PARAMERROR(conn); 1624 1625 /* Some callbacks are always provided by the library */ 1626 switch (callbackid) { 1627 case SASL_CB_LIST_END: 1628 /* Nothing ever gets to provide this */ 1629 INTERROR(conn, SASL_FAIL); 1630 #ifdef _SUN_SDK_ 1631 break; 1632 #endif /* _SUN_SDK_ */ 1633 case SASL_CB_GETOPT: 1634 if (conn) { 1635 *pproc = &_sasl_conn_getopt; 1636 *pcontext = conn; 1637 } else { 1638 *pproc = &_sasl_global_getopt; 1639 *pcontext = NULL; 1640 } 1641 return SASL_OK; 1642 } 1643 1644 /* If it's not always provided by the library, see if there's 1645 * a version provided by the application for this connection... */ 1646 if (conn && conn->callbacks) { 1647 for (callback = conn->callbacks; callback->id != SASL_CB_LIST_END; 1648 callback++) { 1649 if (callback->id == callbackid) { 1650 *pproc = callback->proc; 1651 *pcontext = callback->context; 1652 if (callback->proc) { 1653 return SASL_OK; 1654 } else { 1655 return SASL_INTERACT; 1656 } 1657 } 1658 } 1659 } 1660 1661 /* And, if not for this connection, see if there's one 1662 * for all {server,client} connections... */ 1663 if (conn && conn->global_callbacks && conn->global_callbacks->callbacks) { 1664 for (callback = conn->global_callbacks->callbacks; 1665 callback->id != SASL_CB_LIST_END; 1666 callback++) { 1667 if (callback->id == callbackid) { 1668 *pproc = callback->proc; 1669 *pcontext = callback->context; 1670 if (callback->proc) { 1671 return SASL_OK; 1672 } else { 1673 return SASL_INTERACT; 1674 } 1675 } 1676 } 1677 } 1678 1679 /* Otherwise, see if the library provides a default callback. */ 1680 switch (callbackid) { 1681 #ifdef HAVE_SYSLOG 1682 case SASL_CB_LOG: 1683 *pproc = (int (*)()) &_sasl_syslog; 1684 *pcontext = NULL; 1685 return SASL_OK; 1686 #endif /* HAVE_SYSLOG */ 1687 case SASL_CB_GETPATH: 1688 *pproc = (int (*)()) &_sasl_getpath; 1689 *pcontext = NULL; 1690 return SASL_OK; 1691 case SASL_CB_AUTHNAME: 1692 *pproc = (int (*)()) &_sasl_getsimple; 1693 *pcontext = conn; 1694 return SASL_OK; 1695 case SASL_CB_VERIFYFILE: 1696 *pproc = & _sasl_verifyfile; 1697 *pcontext = NULL; 1698 return SASL_OK; 1699 case SASL_CB_PROXY_POLICY: 1700 *pproc = (int (*)()) &_sasl_proxy_policy; 1701 *pcontext = NULL; 1702 return SASL_OK; 1703 } 1704 1705 /* Unable to find a callback... */ 1706 *pproc = NULL; 1707 *pcontext = NULL; 1708 #ifdef _SUN_SDK_ 1709 if (callbackid != SASL_CB_LANGUAGE) 1710 _sasl_log(conn, SASL_LOG_NONE, "Unable to find a callback: %d", callbackid); 1711 #else 1712 sasl_seterror(conn, SASL_NOLOG, "Unable to find a callback: %d", callbackid); 1713 #endif /* _SUN_SDK_ */ 1714 RETURN(conn,SASL_FAIL); 1715 } 1716 1717 1718 #ifdef _SUN_SDK_ 1719 static void ___sasl_log (const _sasl_global_context_t *gctx, 1720 sasl_log_t *log_cb, void *log_ctx, 1721 int level, const char *fmt, va_list ap); 1722 #endif /* _SUN_SDK_ */ 1723 /* 1724 * This function is typically called from a plugin. 1725 * It creates a string from the formatting and varargs given 1726 * and calls the logging callback (syslog by default) 1727 * 1728 * %m will parse the value in the next argument as an errno string 1729 * %z will parse the next argument as a SASL error code. 1730 */ 1731 1732 void 1733 _sasl_log (sasl_conn_t *conn, 1734 int level, 1735 const char *fmt, 1736 ...) 1737 #ifdef _SUN_SDK_ 1738 { 1739 _sasl_global_context_t *gctx = conn==NULL ? _sasl_gbl_ctx() : conn->gctx; 1740 sasl_log_t *log_cb; 1741 void *log_ctx; 1742 int result; 1743 va_list ap; 1744 1745 /* See if we have a logging callback... */ 1746 result = _sasl_getcallback(conn, SASL_CB_LOG, &log_cb, &log_ctx); 1747 if (result == SASL_OK && ! log_cb) 1748 return; 1749 1750 va_start(ap, fmt); /* start varargs */ 1751 ___sasl_log(gctx, log_cb, log_ctx, level, fmt, ap); 1752 va_end(ap); 1753 } 1754 1755 void 1756 __sasl_log(const _sasl_global_context_t *gctx, 1757 const sasl_callback_t *callbacks, 1758 int level, 1759 const char *fmt, 1760 ...) 1761 { 1762 sasl_log_t *log_cb = NULL; 1763 void *log_ctx = NULL; 1764 int result; 1765 va_list ap; 1766 1767 if (callbacks) 1768 while (callbacks->id != SASL_CB_LIST_END) { 1769 if (callbacks->id == SASL_CB_LOG) { 1770 log_cb = callbacks->proc; 1771 log_ctx = callbacks->context; 1772 break; 1773 } 1774 ++callbacks; 1775 } 1776 1777 if (log_cb == NULL) { 1778 result = _sasl_getcallback(NULL, SASL_CB_LOG, &log_cb, &log_ctx); 1779 if (result != SASL_OK || ! log_cb) 1780 return; 1781 } 1782 1783 if (gctx == NULL) 1784 gctx = _sasl_gbl_ctx(); 1785 1786 va_start(ap, fmt); /* start varargs */ 1787 ___sasl_log(gctx, log_cb, log_ctx, level, fmt, ap); 1788 va_end(ap); 1789 } 1790 1791 static void 1792 ___sasl_log(const _sasl_global_context_t *gctx, 1793 sasl_log_t *log_cb, 1794 void *log_ctx, 1795 int level, 1796 const char *fmt, 1797 va_list ap) 1798 #endif /* _SUN_SDK_ */ 1799 { 1800 char *out=(char *) sasl_ALLOC(250); 1801 size_t alloclen=100; /* current allocated length */ 1802 size_t outlen=0; /* current length of output buffer */ 1803 size_t formatlen; 1804 size_t pos=0; /* current position in format string */ 1805 int result; 1806 #ifndef _SUN_SDK_ 1807 sasl_log_t *log_cb; 1808 void *log_ctx; 1809 #endif /* !_SUN_SDK_ */ 1810 1811 int ival; 1812 char *cval; 1813 #ifndef _SUN_SDK_ 1814 va_list ap; /* varargs thing */ 1815 #endif /* !_SUN_SDK_ */ 1816 1817 if(!fmt) goto done; 1818 if(!out) return; 1819 1820 formatlen = strlen(fmt); 1821 1822 #ifndef _SUN_SDK_ 1823 /* See if we have a logging callback... */ 1824 result = _sasl_getcallback(conn, SASL_CB_LOG, &log_cb, &log_ctx); 1825 if (result == SASL_OK && ! log_cb) 1826 result = SASL_FAIL; 1827 if (result != SASL_OK) goto done; 1828 1829 va_start(ap, fmt); /* start varargs */ 1830 #endif /* !_SUN_SDK_ */ 1831 1832 while(pos<formatlen) 1833 { 1834 if (fmt[pos]!='%') /* regular character */ 1835 { 1836 result = _buf_alloc(&out, &alloclen, outlen+1); 1837 if (result != SASL_OK) goto done; 1838 out[outlen]=fmt[pos]; 1839 outlen++; 1840 pos++; 1841 1842 } else { /* formating thing */ 1843 int done=0; 1844 char frmt[10]; 1845 int frmtpos=1; 1846 char tempbuf[21]; 1847 frmt[0]='%'; 1848 pos++; 1849 1850 while (done==0) 1851 { 1852 switch(fmt[pos]) 1853 { 1854 case 's': /* need to handle this */ 1855 cval = va_arg(ap, char *); /* get the next arg */ 1856 result = _sasl_add_string(&out, &alloclen, 1857 &outlen, cval); 1858 1859 if (result != SASL_OK) /* add the string */ 1860 goto done; 1861 1862 done=1; 1863 break; 1864 1865 case '%': /* double % output the '%' character */ 1866 result = _buf_alloc(&out,&alloclen,outlen+1); 1867 if (result != SASL_OK) 1868 goto done; 1869 1870 out[outlen]='%'; 1871 outlen++; 1872 done=1; 1873 break; 1874 1875 case 'm': /* insert the errno string */ 1876 result = _sasl_add_string(&out, &alloclen, &outlen, 1877 strerror(va_arg(ap, int))); 1878 if (result != SASL_OK) 1879 goto done; 1880 1881 done=1; 1882 break; 1883 1884 case 'z': /* insert the sasl error string */ 1885 result = _sasl_add_string(&out, &alloclen, &outlen, 1886 (char *) sasl_errstring(va_arg(ap, int),NULL,NULL)); 1887 if (result != SASL_OK) 1888 goto done; 1889 1890 done=1; 1891 break; 1892 1893 case 'c': 1894 #ifndef _SUN_SDK_ 1895 frmt[frmtpos++]=fmt[pos]; 1896 frmt[frmtpos]=0; 1897 #endif /* !_SUN_SDK_ */ 1898 tempbuf[0] = (char) va_arg(ap, int); /* get the next arg */ 1899 tempbuf[1]='\0'; 1900 1901 /* now add the character */ 1902 result = _sasl_add_string(&out, &alloclen, &outlen, tempbuf); 1903 if (result != SASL_OK) 1904 goto done; 1905 1906 done=1; 1907 break; 1908 1909 case 'd': 1910 case 'i': 1911 frmt[frmtpos++]=fmt[pos]; 1912 frmt[frmtpos]=0; 1913 ival = va_arg(ap, int); /* get the next arg */ 1914 1915 snprintf(tempbuf,20,frmt,ival); /* have snprintf do the work */ 1916 /* now add the string */ 1917 result = _sasl_add_string(&out, &alloclen, &outlen, tempbuf); 1918 if (result != SASL_OK) 1919 goto done; 1920 1921 done=1; 1922 1923 break; 1924 default: 1925 frmt[frmtpos++]=fmt[pos]; /* add to the formating */ 1926 frmt[frmtpos]=0; 1927 #ifdef _SUN_SDK_ 1928 if (frmtpos > sizeof (frmt) - 2) 1929 #else 1930 if (frmtpos>9) 1931 #endif /* _SUN_SDK_ */ 1932 done=1; 1933 } 1934 pos++; 1935 if (pos>formatlen) 1936 done=1; 1937 } 1938 1939 } 1940 } 1941 1942 /* put 0 at end */ 1943 result = _buf_alloc(&out, &alloclen, outlen+1); 1944 if (result != SASL_OK) goto done; 1945 out[outlen]=0; 1946 1947 va_end(ap); 1948 1949 /* send log message */ 1950 result = log_cb(log_ctx, level, out); 1951 1952 done: 1953 if(out) sasl_FREE(out); 1954 } 1955 1956 1957 1958 /* Allocate and Init a sasl_utils_t structure */ 1959 #ifdef _SUN_SDK_ 1960 sasl_utils_t * 1961 _sasl_alloc_utils(_sasl_global_context_t *gctx, sasl_conn_t *conn, 1962 sasl_global_callbacks_t *global_callbacks) 1963 #else 1964 sasl_utils_t * 1965 _sasl_alloc_utils(sasl_conn_t *conn, 1966 sasl_global_callbacks_t *global_callbacks) 1967 #endif /* _SUN_SDK_ */ 1968 { 1969 sasl_utils_t *utils; 1970 #ifdef _SUN_SDK_ 1971 sasl_allocation_utils_t alloc; 1972 sasl_mutex_utils_t mutex; 1973 1974 LOCK_MUTEX(&malloc_global_mutex); 1975 alloc = gctx->sasl_allocation_utils; 1976 mutex = gctx->sasl_mutex_utils; 1977 UNLOCK_MUTEX(&malloc_global_mutex); 1978 #endif /* _SUN_SDK_ */ 1979 1980 /* set util functions - need to do rest*/ 1981 #ifdef _SUN_SDK_ 1982 utils=alloc.malloc(sizeof(sasl_utils_t)); 1983 #else 1984 utils=sasl_ALLOC(sizeof(sasl_utils_t)); 1985 #endif /* _SUN_SDK_ */ 1986 if (utils==NULL) 1987 return NULL; 1988 1989 utils->conn = conn; 1990 1991 sasl_randcreate(&utils->rpool); 1992 1993 if (conn) { 1994 utils->getopt = &_sasl_conn_getopt; 1995 utils->getopt_context = conn; 1996 } else { 1997 utils->getopt = &_sasl_global_getopt; 1998 utils->getopt_context = global_callbacks; 1999 } 2000 2001 #ifdef _SUN_SDK_ 2002 utils->malloc=alloc.malloc; 2003 utils->calloc=alloc.calloc; 2004 utils->realloc=alloc.realloc; 2005 utils->free=alloc.free; 2006 2007 utils->mutex_alloc = mutex.alloc; 2008 utils->mutex_lock = mutex.lock; 2009 utils->mutex_unlock = mutex.unlock; 2010 utils->mutex_free = mutex.free; 2011 #else 2012 utils->malloc=_sasl_allocation_utils.malloc; 2013 utils->calloc=_sasl_allocation_utils.calloc; 2014 utils->realloc=_sasl_allocation_utils.realloc; 2015 utils->free=_sasl_allocation_utils.free; 2016 2017 utils->mutex_alloc = _sasl_mutex_utils.alloc; 2018 utils->mutex_lock = _sasl_mutex_utils.lock; 2019 utils->mutex_unlock = _sasl_mutex_utils.unlock; 2020 utils->mutex_free = _sasl_mutex_utils.free; 2021 #endif /* _SUN_SDK_ */ 2022 2023 #ifdef _SUN_SDK_ 2024 utils->MD5Init = (void (*)(MD5_CTX *))&MD5Init; 2025 utils->MD5Update= (void (*) 2026 (MD5_CTX *, const unsigned char *, unsigned int ))&MD5Update; 2027 utils->MD5Final = (void (*)(unsigned char [16], MD5_CTX *))&MD5Final; 2028 #else 2029 utils->MD5Init = &_sasl_MD5Init; 2030 utils->MD5Update= &_sasl_MD5Update; 2031 utils->MD5Final = &_sasl_MD5Final; 2032 #endif /* _SUN_SDK_ */ 2033 utils->hmac_md5 = &_sasl_hmac_md5; 2034 utils->hmac_md5_init = &_sasl_hmac_md5_init; 2035 utils->hmac_md5_final = &_sasl_hmac_md5_final; 2036 utils->hmac_md5_precalc = &_sasl_hmac_md5_precalc; 2037 utils->hmac_md5_import = &_sasl_hmac_md5_import; 2038 utils->mkchal = &sasl_mkchal; 2039 utils->utf8verify = &sasl_utf8verify; 2040 utils->rand=&sasl_rand; 2041 utils->churn=&sasl_churn; 2042 utils->checkpass=NULL; 2043 2044 utils->encode64=&sasl_encode64; 2045 utils->decode64=&sasl_decode64; 2046 2047 utils->erasebuffer=&sasl_erasebuffer; 2048 2049 utils->getprop=&sasl_getprop; 2050 utils->setprop=&sasl_setprop; 2051 2052 utils->getcallback=&_sasl_getcallback; 2053 2054 utils->log=&_sasl_log; 2055 2056 utils->seterror=&sasl_seterror; 2057 2058 #ifndef macintosh 2059 /* Aux Property Utilities */ 2060 utils->prop_new=&prop_new; 2061 utils->prop_dup=&prop_dup; 2062 utils->prop_request=&prop_request; 2063 utils->prop_get=&prop_get; 2064 utils->prop_getnames=&prop_getnames; 2065 utils->prop_clear=&prop_clear; 2066 utils->prop_dispose=&prop_dispose; 2067 utils->prop_format=&prop_format; 2068 utils->prop_set=&prop_set; 2069 utils->prop_setvals=&prop_setvals; 2070 utils->prop_erase=&prop_erase; 2071 #endif 2072 2073 /* Spares */ 2074 utils->spare_fptr = NULL; 2075 utils->spare_fptr1 = utils->spare_fptr2 = 2076 utils->spare_fptr3 = NULL; 2077 2078 return utils; 2079 } 2080 2081 int 2082 _sasl_free_utils(const sasl_utils_t ** utils) 2083 { 2084 sasl_utils_t *nonconst; 2085 #ifdef _SUN_SDK_ 2086 sasl_free_t *free_func; 2087 #endif /* _SUN_SDK_ */ 2088 2089 if(!utils) return SASL_BADPARAM; 2090 if(!*utils) return SASL_OK; 2091 2092 /* I wish we could avoid this cast, it's pretty gratuitous but it 2093 * does make life easier to have it const everywhere else. */ 2094 nonconst = (sasl_utils_t *)(*utils); 2095 2096 sasl_randfree(&(nonconst->rpool)); 2097 #ifdef _SUN_SDK_ 2098 free_func = (*utils)->free; 2099 free_func(nonconst); 2100 #else 2101 sasl_FREE(nonconst); 2102 #endif /* _SUN_SDK_ */ 2103 2104 *utils = NULL; 2105 return SASL_OK; 2106 } 2107 2108 int sasl_idle(sasl_conn_t *conn) 2109 { 2110 if (! conn) { 2111 #ifdef _SUN_SDK_ 2112 _sasl_global_context_t *gctx = _sasl_gbl_ctx(); 2113 2114 if (gctx->sasl_server_idle_hook 2115 && gctx->sasl_server_idle_hook(NULL)) 2116 return 1; 2117 if (gctx->sasl_client_idle_hook 2118 && gctx->sasl_client_idle_hook(NULL)) 2119 return 1; 2120 #else 2121 if (_sasl_server_idle_hook 2122 && _sasl_server_idle_hook(NULL)) 2123 return 1; 2124 if (_sasl_client_idle_hook 2125 && _sasl_client_idle_hook(NULL)) 2126 return 1; 2127 #endif /* _SUN_SDK_ */ 2128 return 0; 2129 } 2130 2131 if (conn->idle_hook) 2132 return conn->idle_hook(conn); 2133 2134 return 0; 2135 } 2136 2137 const sasl_callback_t * 2138 _sasl_find_getpath_callback(const sasl_callback_t *callbacks) 2139 { 2140 static const sasl_callback_t default_getpath_cb = { 2141 SASL_CB_GETPATH, 2142 &_sasl_getpath, 2143 NULL 2144 }; 2145 2146 if (callbacks) 2147 while (callbacks->id != SASL_CB_LIST_END) 2148 { 2149 if (callbacks->id == SASL_CB_GETPATH) 2150 { 2151 return callbacks; 2152 } else { 2153 ++callbacks; 2154 } 2155 } 2156 2157 return &default_getpath_cb; 2158 } 2159 2160 #ifdef _SUN_SDK_ 2161 extern const sasl_callback_t * 2162 _sasl_find_getconf_callback(const sasl_callback_t *callbacks) 2163 { 2164 static const sasl_callback_t default_getconf_cb = { 2165 SASL_CB_GETCONF, 2166 &_sasl_getconf, 2167 NULL 2168 }; 2169 2170 if (callbacks) 2171 while (callbacks->id != SASL_CB_LIST_END) 2172 { 2173 if (callbacks->id == SASL_CB_GETCONF) 2174 { 2175 return callbacks; 2176 } else { 2177 ++callbacks; 2178 } 2179 } 2180 2181 return &default_getconf_cb; 2182 } 2183 #endif /* _SUN_SDK_ */ 2184 2185 const sasl_callback_t * 2186 _sasl_find_verifyfile_callback(const sasl_callback_t *callbacks) 2187 { 2188 static const sasl_callback_t default_verifyfile_cb = { 2189 SASL_CB_VERIFYFILE, 2190 &_sasl_verifyfile, 2191 NULL 2192 }; 2193 2194 if (callbacks) 2195 while (callbacks->id != SASL_CB_LIST_END) 2196 { 2197 if (callbacks->id == SASL_CB_VERIFYFILE) 2198 { 2199 return callbacks; 2200 } else { 2201 ++callbacks; 2202 } 2203 } 2204 2205 return &default_verifyfile_cb; 2206 } 2207 2208 /* Basically a conditional call to realloc(), if we need more */ 2209 #ifdef _SUN_SDK_ 2210 int __buf_alloc(const _sasl_global_context_t *gctx, char **rwbuf, 2211 size_t *curlen, size_t newlen) 2212 #else 2213 int _buf_alloc(char **rwbuf, size_t *curlen, size_t newlen) 2214 #endif /* _SUN_SDK_ */ 2215 { 2216 if(!(*rwbuf)) { 2217 *rwbuf = sasl_ALLOC(newlen); 2218 if (*rwbuf == NULL) { 2219 *curlen = 0; 2220 return SASL_NOMEM; 2221 } 2222 *curlen = newlen; 2223 } else if(*rwbuf && *curlen < newlen) { 2224 size_t needed = 2*(*curlen); 2225 2226 while(needed < newlen) 2227 needed *= 2; 2228 2229 *rwbuf = sasl_REALLOC(*rwbuf, needed); 2230 2231 if (*rwbuf == NULL) { 2232 *curlen = 0; 2233 return SASL_NOMEM; 2234 } 2235 *curlen = needed; 2236 } 2237 2238 return SASL_OK; 2239 } 2240 2241 /* for the mac os x cfm glue: this lets the calling function 2242 get pointers to the error buffer without having to touch the sasl_conn_t struct */ 2243 void _sasl_get_errorbuf(sasl_conn_t *conn, char ***bufhdl, size_t **lenhdl) 2244 { 2245 *bufhdl = &conn->error_buf; 2246 *lenhdl = &conn->error_buf_len; 2247 } 2248 2249 /* convert an iovec to a single buffer */ 2250 #ifdef _SUN_SDK_ 2251 int _iovec_to_buf(const _sasl_global_context_t *gctx, const struct iovec *vec, 2252 unsigned numiov, buffer_info_t **output) 2253 #else 2254 int _iovec_to_buf(const struct iovec *vec, 2255 unsigned numiov, buffer_info_t **output) 2256 #endif /* _SUN_SDK_ */ 2257 { 2258 unsigned i; 2259 int ret; 2260 buffer_info_t *out; 2261 char *pos; 2262 2263 if(!vec || !output) return SASL_BADPARAM; 2264 2265 if(!(*output)) { 2266 *output = sasl_ALLOC(sizeof(buffer_info_t)); 2267 if(!*output) return SASL_NOMEM; 2268 memset(*output,0,sizeof(buffer_info_t)); 2269 } 2270 2271 out = *output; 2272 2273 out->curlen = 0; 2274 for(i=0; i<numiov; i++) 2275 out->curlen += vec[i].iov_len; 2276 2277 ret = _buf_alloc(&out->data, &out->reallen, out->curlen); 2278 2279 if(ret != SASL_OK) return SASL_NOMEM; 2280 2281 memset(out->data, 0, out->reallen); 2282 pos = out->data; 2283 2284 for(i=0; i<numiov; i++) { 2285 memcpy(pos, vec[i].iov_base, vec[i].iov_len); 2286 pos += vec[i].iov_len; 2287 } 2288 2289 return SASL_OK; 2290 } 2291 2292 /* This code might be useful in the future, but it isn't now, so.... */ 2293 #if 0 2294 int _sasl_iptostring(const struct sockaddr *addr, socklen_t addrlen, 2295 char *out, unsigned outlen) { 2296 char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; 2297 2298 if(!addr || !out) return SASL_BADPARAM; 2299 2300 getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), 2301 NI_NUMERICHOST | NI_WITHSCOPEID | NI_NUMERICSERV); 2302 2303 if(outlen < strlen(hbuf) + strlen(pbuf) + 2) 2304 return SASL_BUFOVER; 2305 2306 snprintf(out, outlen, "%s;%s", hbuf, pbuf); 2307 2308 return SASL_OK; 2309 } 2310 #endif 2311 2312 #ifdef _SUN_SDK_ 2313 /* An ipv6 address will contain at least two colons */ 2314 static int can_be_ipv6(const char *addr) 2315 { 2316 const char *p; 2317 2318 if ((p = strchr(addr, ':')) == NULL) 2319 return (0); 2320 2321 p = strchr(p + 1, ':'); 2322 2323 return (p != NULL); 2324 } 2325 #endif /* _SUN_SDK_ */ 2326 2327 int _sasl_ipfromstring(const char *addr, 2328 struct sockaddr *out, socklen_t outlen) 2329 { 2330 int i, j; 2331 struct addrinfo hints, *ai = NULL; 2332 char hbuf[NI_MAXHOST]; 2333 #ifdef _SUN_SDK_ 2334 const char *start, *end, *p; 2335 int addr_only = 1; 2336 #endif /* _SUN_SDK_ */ 2337 2338 /* A NULL out pointer just implies we don't do a copy, just verify it */ 2339 2340 if(!addr) return SASL_BADPARAM; 2341 2342 #ifdef _SUN_SDK_ 2343 end = strchr(addr, ']'); 2344 if (end != NULL) { 2345 /* This an rfc 2732 ipv6 address */ 2346 start = strchr(addr, '['); 2347 if (start >= end || start == NULL) 2348 return SASL_BADPARAM; 2349 for (i = 0, p = start + 1; p < end; p++) { 2350 hbuf[i++] = *p; 2351 if (i >= NI_MAXHOST) 2352 return SASL_BADPARAM; 2353 } 2354 p = strchr(end, ':'); 2355 if (p == NULL) 2356 p = end + 1; 2357 else 2358 p = p + 1; 2359 } else if (can_be_ipv6(addr) != 0) { 2360 /* Parse the address */ 2361 for (i = 0; addr[i] != '\0' && addr[i] != ';'; ) { 2362 hbuf[i] = addr[i]; 2363 if (++i >= NI_MAXHOST) 2364 return SASL_BADPARAM; 2365 } 2366 if (addr[i] == ';') 2367 p = &addr[i+1]; 2368 else 2369 p = &addr[i]; 2370 } else { 2371 for (i = 0; addr[i] != '\0' && addr[i] != ';' && addr[i] != ':'; ) { 2372 hbuf[i] = addr[i]; 2373 if (isalpha(addr[i])) 2374 addr_only = 0; 2375 if (++i >= NI_MAXHOST) 2376 return SASL_BADPARAM; 2377 } 2378 if (addr[i] == ';' || addr[i] == ':') 2379 p = &addr[i+1]; 2380 else 2381 p = &addr[i]; 2382 } 2383 hbuf[i] = '\0'; 2384 for (j = 0; p[j] != '\0'; j++) 2385 if (!isdigit((int)(p[j]))) 2386 return SASL_BADPARAM; 2387 if (atoi(p) == 0) 2388 p = NULL; 2389 #else 2390 /* Parse the address */ 2391 for (i = 0; addr[i] != '\0' && addr[i] != ';'; i++) { 2392 if (i >= NI_MAXHOST) 2393 return SASL_BADPARAM; 2394 hbuf[i] = addr[i]; 2395 } 2396 hbuf[i] = '\0'; 2397 2398 if (addr[i] == ';') 2399 i++; 2400 /* XXX: Do we need this check? */ 2401 for (j = i; addr[j] != '\0'; j++) 2402 if (!isdigit((int)(addr[j]))) 2403 return SASL_BADPARAM; 2404 #endif /* _SUN_SDK_ */ 2405 2406 memset(&hints, 0, sizeof(hints)); 2407 hints.ai_family = PF_UNSPEC; 2408 hints.ai_socktype = SOCK_STREAM; 2409 #ifdef _SUN_SDK_ 2410 hints.ai_flags = addr_only ? AI_PASSIVE | AI_NUMERICHOST : AI_PASSIVE; 2411 if (getaddrinfo(hbuf, p, &hints, &ai) != 0) 2412 #else 2413 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 2414 if (getaddrinfo(hbuf, &addr[i], &hints, &ai) != 0) 2415 #endif /* _SUN_SDK_ */ 2416 return SASL_BADPARAM; 2417 2418 if (out) { 2419 if (outlen < (socklen_t)ai->ai_addrlen) { 2420 freeaddrinfo(ai); 2421 return SASL_BUFOVER; 2422 } 2423 memcpy(out, ai->ai_addr, ai->ai_addrlen); 2424 } 2425 2426 freeaddrinfo(ai); 2427 2428 return SASL_OK; 2429 } 2430 2431 #ifdef _SUN_SDK_ 2432 int _sasl_build_mechlist(_sasl_global_context_t *gctx) 2433 #else 2434 int _sasl_build_mechlist(void) 2435 #endif /* _SUN_SDK_ */ 2436 { 2437 int count = 0; 2438 sasl_string_list_t *clist = NULL, *slist = NULL, *olist = NULL; 2439 sasl_string_list_t *p, *q, **last, *p_next; 2440 2441 #ifdef _SUN_SDK_ 2442 char **global_mech_list; 2443 2444 LOCK_MUTEX(&global_mutex); 2445 2446 clist = _sasl_client_mechs(gctx); 2447 slist = _sasl_server_mechs(gctx); 2448 2449 global_mech_list = gctx->global_mech_list; 2450 #else 2451 clist = _sasl_client_mechs(); 2452 slist = _sasl_server_mechs(); 2453 #endif /* _SUN_SDK_ */ 2454 2455 if(!clist) { 2456 olist = slist; 2457 } else { 2458 int flag; 2459 2460 /* append slist to clist, and set olist to clist */ 2461 for(p = slist; p; p = p_next) { 2462 flag = 0; 2463 p_next = p->next; 2464 2465 last = &clist; 2466 for(q = clist; q; q = q->next) { 2467 if(!strcmp(q->d, p->d)) { 2468 /* They match, set the flag */ 2469 flag = 1; 2470 break; 2471 } 2472 last = &(q->next); 2473 } 2474 2475 if(!flag) { 2476 *last = p; 2477 p->next = NULL; 2478 } else { 2479 sasl_FREE(p); 2480 } 2481 } 2482 2483 olist = clist; 2484 } 2485 2486 if(!olist) { 2487 #ifdef _SUN_SDK_ 2488 UNLOCK_MUTEX(&global_mutex); 2489 #else 2490 printf ("no olist"); 2491 #endif /* _SUN_SDK_ */ 2492 return SASL_FAIL; 2493 } 2494 2495 for (p = olist; p; p = p->next) count++; 2496 2497 if(global_mech_list) { 2498 sasl_FREE(global_mech_list); 2499 #ifdef _SUN_SDK_ 2500 gctx->global_mech_list = NULL; 2501 #else 2502 global_mech_list = NULL; 2503 #endif /* _SUN_SDK_ */ 2504 } 2505 2506 global_mech_list = sasl_ALLOC((count + 1) * sizeof(char *)); 2507 if(!global_mech_list) return SASL_NOMEM; 2508 2509 memset(global_mech_list, 0, (count + 1) * sizeof(char *)); 2510 #ifdef _SUN_SDK_ 2511 gctx->global_mech_list = global_mech_list; 2512 #endif /* _SUN_SDK_ */ 2513 2514 count = 0; 2515 for (p = olist; p; p = p_next) { 2516 p_next = p->next; 2517 2518 global_mech_list[count++] = (char *) p->d; 2519 2520 sasl_FREE(p); 2521 } 2522 2523 #ifdef _SUN_SDK_ 2524 UNLOCK_MUTEX(&global_mutex); 2525 #endif /* _SUN_SDK_ */ 2526 2527 return SASL_OK; 2528 } 2529 2530 const char ** sasl_global_listmech(void) 2531 { 2532 #ifdef _SUN_SDK_ 2533 _sasl_global_context_t *gctx = _sasl_gbl_ctx(); 2534 2535 return (const char **)gctx->global_mech_list; 2536 #else 2537 return (const char **)global_mech_list; 2538 #endif /* _SUN_SDK_ */ 2539 } 2540 2541 int sasl_listmech(sasl_conn_t *conn, 2542 const char *user, 2543 const char *prefix, 2544 const char *sep, 2545 const char *suffix, 2546 const char **result, 2547 unsigned *plen, 2548 int *pcount) 2549 { 2550 if(!conn) { 2551 return SASL_BADPARAM; 2552 } else if(conn->type == SASL_CONN_SERVER) { 2553 RETURN(conn, _sasl_server_listmech(conn, user, prefix, sep, suffix, 2554 result, plen, pcount)); 2555 } else if (conn->type == SASL_CONN_CLIENT) { 2556 RETURN(conn, _sasl_client_listmech(conn, prefix, sep, suffix, 2557 result, plen, pcount)); 2558 } 2559 2560 PARAMERROR(conn); 2561 } 2562 2563 #ifdef _SUN_SDK_ 2564 /* 2565 * Creates a context so that libraries may use libsasl independently 2566 * of applications using libsasl. 2567 * Returns NULL on failure. 2568 * 2569 * sasl_free_context frees the context 2570 * To use libsasl independently of the default context, use 2571 * _sasl_server_init() instead of sasl_server_init() 2572 * _sasl_server_new() instead of sasl_server_new() 2573 * _sasl_client_init() instead of sasl_client_init() 2574 * _sasl_client_new() instead of sasl_client_new() 2575 * _sasl_client_add_plugin() instead of sasl_client_add_plugin() 2576 * _sasl_server_add_plugin() instead of sasl_server_add_plugin() 2577 * _sasl_canonuser_add_plugin() instead of sasl_canonuser_add_plugin() 2578 * _sasl_auxprop_add_plugin() instead of sasl_auxprop_add_plugin() 2579 */ 2580 2581 void *sasl_create_context(void) 2582 { 2583 _sasl_global_context_t *gctx; 2584 2585 gctx = (_sasl_global_context_t *) 2586 sasl_sun_ALLOC(sizeof(_sasl_global_context_t)); 2587 2588 if (gctx != NULL) { 2589 memset(gctx, 0, sizeof(_sasl_global_context_t)); 2590 2591 gctx->server_global_callbacks.gctx = gctx; 2592 gctx->client_global_callbacks.gctx = gctx; 2593 LOCK_MUTEX(&malloc_global_mutex); 2594 gctx->sasl_allocation_utils.malloc = (sasl_malloc_t *)&malloc; 2595 gctx->sasl_allocation_utils.calloc = (sasl_calloc_t *)&calloc; 2596 gctx->sasl_allocation_utils.realloc = (sasl_realloc_t *)&realloc; 2597 gctx->sasl_allocation_utils.free = (sasl_free_t *)&free; 2598 gctx->sasl_mutex_utils.alloc = sasl_mutex_alloc; 2599 gctx->sasl_mutex_utils.lock = sasl_mutex_lock; 2600 gctx->sasl_mutex_utils.unlock = sasl_mutex_unlock; 2601 gctx->sasl_mutex_utils.free = sasl_mutex_free; 2602 UNLOCK_MUTEX(&malloc_global_mutex); 2603 } 2604 return gctx; 2605 } 2606 2607 /* Frees the context created by sasl_create_context() */ 2608 void sasl_free_context(void *context) 2609 { 2610 _sasl_dispose_context(context); 2611 if (context != NULL) { 2612 sasl_sun_FREE(context); 2613 } 2614 } 2615 2616 /* Used by both sasl_done() and sasl_free_context() to free context */ 2617 static void _sasl_dispose_context(_sasl_global_context_t *gctx) 2618 { 2619 if (gctx == NULL) 2620 return; 2621 2622 if (gctx->sasl_server_cleanup_hook && 2623 gctx->sasl_server_cleanup_hook(gctx) == SASL_OK) { 2624 gctx->sasl_server_idle_hook = NULL; 2625 gctx->sasl_server_cleanup_hook = NULL; 2626 } 2627 2628 if (gctx->sasl_client_cleanup_hook && 2629 gctx->sasl_client_cleanup_hook(gctx) == SASL_OK) { 2630 gctx->sasl_client_idle_hook = NULL; 2631 gctx->sasl_client_cleanup_hook = NULL; 2632 } 2633 2634 if(gctx->sasl_server_cleanup_hook || gctx->sasl_client_cleanup_hook) 2635 return; 2636 2637 _sasl_canonuser_free(gctx); 2638 _sasl_done_with_plugins(gctx); 2639 2640 sasl_config_free(gctx); 2641 2642 if (gctx->free_mutex != NULL) 2643 sasl_MUTEX_FREE(gctx->free_mutex); 2644 gctx->free_mutex = NULL; 2645 2646 _sasl_free_utils(&(gctx->sasl_server_global_utils)); 2647 _sasl_free_utils(&(gctx->sasl_canonusr_global_utils)); 2648 2649 LOCK_MUTEX(&global_mutex); 2650 sasl_FREE((void *)gctx->global_mech_list); 2651 gctx->global_mech_list = NULL; 2652 UNLOCK_MUTEX(&global_mutex); 2653 2654 /* in case of another init/done */ 2655 gctx->sasl_server_cleanup_hook = NULL; 2656 gctx->sasl_client_cleanup_hook = NULL; 2657 2658 gctx->sasl_client_idle_hook = NULL; 2659 gctx->sasl_server_idle_hook = NULL; 2660 } 2661 2662 _sasl_global_context_t *_sasl_gbl_ctx(void) 2663 { 2664 static _sasl_global_context_t gbl_ctx = { 2665 0, /* sasl_server_active */ 2666 NULL, /* mechlist */ 2667 NULL, /* splug_path_info */ 2668 {NULL, NULL, &gbl_ctx}, /* server_global_callbacks */ 2669 NULL, /* sasl_server_cleanup_hook */ 2670 NULL, /* sasl_server_idle_hook */ 2671 NULL, /* cmechlist */ 2672 NULL, /* cplug_path_info */ 2673 {NULL, NULL, &gbl_ctx}, /* client_global_callbacks */ 2674 0, /* sasl_client_active */ 2675 NULL, /* sasl_client_cleanup_hook */ 2676 NULL, /* sasl_client_idle_hook */ 2677 NULL, /* sasl_server_global_utils */ 2678 NULL, /* sasl_client_global_utils */ 2679 NULL, /* configlist */ 2680 0, /* nconfiglist */ 2681 NULL, /* config_path */ 2682 0, /* config_last_read */ 2683 NULL, /* auxprop_head */ 2684 NULL, /* canonuser_head */ 2685 NULL, /* global_mech_list */ 2686 NULL, /* free_mutex */ 2687 {(sasl_malloc_t *)&malloc, (sasl_calloc_t *)&calloc, 2688 (sasl_realloc_t *)&realloc, (sasl_free_t *)&free}, 2689 /* sasl_allocation_utils */ 2690 {&sasl_mutex_alloc, &sasl_mutex_lock, &sasl_mutex_unlock, 2691 &sasl_mutex_free}, /* sasl_mutex_utils */ 2692 NULL /* lib_list_head */ 2693 }; 2694 2695 return (&gbl_ctx); 2696 } 2697 2698 static int 2699 _sasl_getconf(void *context __attribute__((unused)), const char **conf) 2700 { 2701 if (! conf) 2702 return SASL_BADPARAM; 2703 2704 *conf = SASL_CONFDIR; 2705 2706 return SASL_OK; 2707 } 2708 2709 /* EXPORT DELETE START */ 2710 /* CRYPT DELETE START */ 2711 #ifdef _INTEGRATED_SOLARIS_ 2712 #pragma fini(sasl_fini) 2713 int 2714 sasl_fini(void) 2715 { 2716 reg_list_t *next; 2717 2718 while (reg_list_base != NULL) { 2719 next = reg_list_base->next; 2720 free(reg_list_base); 2721 reg_list_base = next; 2722 } 2723 return (0); 2724 } 2725 #endif /* _INTEGRATED_SOLARIS_ */ 2726 /* CRYPT DELETE END */ 2727 /* EXPORT DELETE END */ 2728 2729 #endif /* _SUN_SDK_ */ 2730 2731 #ifndef WIN32 2732 static int 2733 _sasl_getpath(void *context __attribute__((unused)), 2734 const char **path) 2735 { 2736 if (! path) 2737 return SASL_BADPARAM; 2738 2739 #ifdef _SUN_SDK_ 2740 /* SASL_PATH is not allowed for SUN SDK */ 2741 #else 2742 *path = getenv(SASL_PATH_ENV_VAR); 2743 if (! *path) 2744 #endif /* _SUN_SDK_ */ 2745 *path = PLUGINDIR; 2746 2747 return SASL_OK; 2748 } 2749 2750 #else 2751 /* Return NULL on failure */ 2752 static int 2753 _sasl_getpath(void *context __attribute__((unused)), const char **path) 2754 { 2755 /* Open registry entry, and find all registered SASL libraries. 2756 * 2757 * Registry location: 2758 * 2759 * SOFTWARE\\Carnegie Mellon\\Project Cyrus\\SASL Library 2760 * 2761 * Key - value: 2762 * 2763 * "SearchPath" - value: PATH like (';' delimited) list 2764 * of directories where to search for plugins 2765 * The list may contain references to environment 2766 * variables (e.g. %PATH%). 2767 * 2768 */ 2769 HKEY hKey; 2770 DWORD ret; 2771 DWORD ValueType; /* value type */ 2772 DWORD cbData; /* value size */ 2773 BYTE * ValueData; /* value */ 2774 DWORD cbExpandedData; /* "expanded" value size */ 2775 BYTE * ExpandedValueData; /* "expanded" value */ 2776 char * return_value; /* function return value */ 2777 char * tmp; 2778 2779 /* Initialization */ 2780 ExpandedValueData = NULL; 2781 ValueData = NULL; 2782 return_value = NULL; 2783 2784 /* Open the registry */ 2785 ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 2786 SASL_ROOT_KEY, 2787 0, 2788 KEY_READ, 2789 &hKey); 2790 2791 if (ret != ERROR_SUCCESS) { 2792 /* no registry entry */ 2793 *path = PLUGINDIR; 2794 return SASL_OK; 2795 } 2796 2797 /* figure out value type and required buffer size */ 2798 /* the size will include space for terminating NUL if required */ 2799 RegQueryValueEx (hKey, 2800 SASL_PATH_SUBKEY, 2801 NULL, /* reserved */ 2802 &ValueType, 2803 NULL, 2804 &cbData); 2805 2806 /* Only accept string related types */ 2807 if (ValueType != REG_EXPAND_SZ && 2808 ValueType != REG_MULTI_SZ && 2809 ValueType != REG_SZ) { 2810 return_value = NULL; 2811 goto CLEANUP; 2812 } 2813 2814 /* Any high water mark? */ 2815 ValueData = sasl_ALLOC(cbData); 2816 if (ValueData == NULL) { 2817 return_value = NULL; 2818 goto CLEANUP; 2819 }; 2820 2821 RegQueryValueEx (hKey, 2822 SASL_PATH_SUBKEY, 2823 NULL, /* reserved */ 2824 &ValueType, 2825 ValueData, 2826 &cbData); 2827 2828 switch (ValueType) { 2829 case REG_EXPAND_SZ: 2830 /* : A random starting guess */ 2831 cbExpandedData = cbData + 1024; 2832 ExpandedValueData = sasl_ALLOC(cbExpandedData); 2833 if (ExpandedValueData == NULL) { 2834 return_value = NULL; 2835 goto CLEANUP; 2836 }; 2837 2838 cbExpandedData = ExpandEnvironmentStrings( 2839 ValueData, 2840 ExpandedValueData, 2841 cbExpandedData); 2842 2843 if (cbExpandedData == 0) { 2844 /* : GetLastError() contains the reason for failure */ 2845 return_value = NULL; 2846 goto CLEANUP; 2847 } 2848 2849 /* : Must retry expansion with the bigger buffer */ 2850 if (cbExpandedData > cbData + 1024) { 2851 /* : Memory leak here if can't realloc */ 2852 ExpandedValueData = sasl_REALLOC(ExpandedValueData, cbExpandedData); 2853 if (ExpandedValueData == NULL) { 2854 return_value = NULL; 2855 goto CLEANUP; 2856 }; 2857 2858 cbExpandedData = ExpandEnvironmentStrings( 2859 ValueData, 2860 ExpandedValueData, 2861 cbExpandedData); 2862 2863 /* : This should not happen */ 2864 if (cbExpandedData == 0) { 2865 /* : GetLastError() contains the reason for failure */ 2866 return_value = NULL; 2867 goto CLEANUP; 2868 } 2869 } 2870 2871 sasl_FREE(ValueData); 2872 ValueData = ExpandedValueData; 2873 /* : This is to prevent automatical freeing of this block on cleanup */ 2874 ExpandedValueData = NULL; 2875 2876 break; 2877 2878 case REG_MULTI_SZ: 2879 tmp = ValueData; 2880 2881 /* : We shouldn't overflow here, as the buffer is guarantied 2882 : to contain at least two consequent NULs */ 2883 while (1) { 2884 if (tmp[0] == '\0') { 2885 /* : Stop the process if we found the end of the string (two consequent NULs) */ 2886 if (tmp[1] == '\0') { 2887 break; 2888 } 2889 2890 /* : Replace delimiting NUL with our delimiter characted */ 2891 tmp[0] = PATHS_DELIMITER; 2892 } 2893 tmp += strlen(tmp); 2894 } 2895 break; 2896 2897 case REG_SZ: 2898 /* Do nothing, it is good as is */ 2899 break; 2900 2901 default: 2902 return_value = NULL; 2903 goto CLEANUP; 2904 } 2905 2906 return_value = ValueData; 2907 2908 CLEANUP: 2909 RegCloseKey(hKey); 2910 if (ExpandedValueData != NULL) sasl_FREE(ExpandedValueData); 2911 if (return_value == NULL) { 2912 if (ValueData != NULL) sasl_FREE(ValueData); 2913 } 2914 *path = return_value; 2915 2916 #ifdef _SUN_SDK_ 2917 /* SASL_PATH is not allowed for SUN SDK */ 2918 if (! *path) 2919 *path = PLUGINDIR; 2920 #endif /* _SUN_SDK_ */ 2921 return SASL_OK; 2922 } 2923 2924 #endif 2925