1/* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5#pragma ident "%Z%%M% %I% %E% SMI" 6 7/* dlopen.c--Unix dlopen() dynamic loader interface 8 * Rob Siemborski 9 * Rob Earhart 10 * $Id: dlopen.c,v 1.45 2003/07/14 20:08:50 rbraun 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#ifdef HAVE_DLFCN_H 54#include <dlfcn.h> 55#endif 56 57#include <stdlib.h> 58#include <errno.h> 59#include <stdio.h> 60#include <limits.h> 61 62#include <sasl.h> 63#include "saslint.h" 64 65#ifndef PIC 66#include <saslplug.h> 67#include "staticopen.h" 68#endif 69 70#ifdef _SUN_SDK_ 71#include <sys/stat.h> 72#endif /* _SUN_SDK_ */ 73 74#ifdef DO_DLOPEN 75#if HAVE_DIRENT_H 76# include <dirent.h> 77# define NAMLEN(dirent) strlen((dirent)->d_name) 78#else /* HAVE_DIRENT_H */ 79# define dirent direct 80# define NAMLEN(dirent) (dirent)->d_namlen 81# if HAVE_SYS_NDIR_H 82# include <sys/ndir.h> 83# endif 84# if HAVE_SYS_DIR_H 85# include <sys/dir.h> 86# endif 87# if HAVE_NDIR_H 88# include <ndir.h> 89# endif 90#endif /* ! HAVE_DIRENT_H */ 91 92#ifndef NAME_MAX 93# ifdef _POSIX_NAME_MAX 94# define NAME_MAX _POSIX_NAME_MAX 95# else 96# define NAME_MAX 16 97# endif 98#endif 99 100#if NAME_MAX < 8 101# define NAME_MAX 8 102#endif 103 104#ifdef __hpux 105#include <dl.h> 106 107typedef shl_t dll_handle; 108typedef void * dll_func; 109 110dll_handle 111dlopen(char *fname, int mode) 112{ 113 shl_t h = shl_load(fname, BIND_DEFERRED, 0L); 114 shl_t *hp = NULL; 115 116 if (h) { 117 hp = (shl_t *)malloc(sizeof (shl_t)); 118 if (!hp) { 119 shl_unload(h); 120 } else { 121 *hp = h; 122 } 123 } 124 125 return (dll_handle)hp; 126} 127 128int 129dlclose(dll_handle h) 130{ 131 shl_t hp = *((shl_t *)h); 132 if (hp != NULL) free(hp); 133 return shl_unload(h); 134} 135 136dll_func 137dlsym(dll_handle h, char *n) 138{ 139 dll_func handle; 140 141 if (shl_findsym ((shl_t *)h, n, TYPE_PROCEDURE, &handle)) 142 return NULL; 143 144 return (dll_func)handle; 145} 146 147char *dlerror() 148{ 149 if (errno != 0) { 150 return strerror(errno); 151 } 152 return "Generic shared library error"; 153} 154 155#define SO_SUFFIX ".sl" 156#else /* __hpux */ 157#define SO_SUFFIX ".so" 158#endif /* __hpux */ 159 160#define LA_SUFFIX ".la" 161#endif /* DO_DLOPEN */ 162 163#if defined DO_DLOPEN || defined WIN_PLUG /* _SUN_SDK_ */ 164typedef struct lib_list 165{ 166 struct lib_list *next; 167 void *library; 168} lib_list_t; 169 170#ifndef _SUN_SDK_ 171static lib_list_t *lib_list_head = NULL; 172#endif /* !_SUN_SDK_ */ 173 174DEFINE_STATIC_MUTEX(global_mutex); 175 176#endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */ 177 178int _sasl_locate_entry(void *library, const char *entryname, 179 void **entry_point) 180{ 181#ifdef DO_DLOPEN 182/* note that we still check for known problem systems in 183 * case we are cross-compiling */ 184#if defined(DLSYM_NEEDS_UNDERSCORE) || defined(__OpenBSD__) 185 char adj_entryname[1024]; 186#else 187#define adj_entryname entryname 188#endif 189 190 if(!entryname) { 191#ifndef _SUN_SDK_ 192 _sasl_log(NULL, SASL_LOG_ERR, 193 "no entryname in _sasl_locate_entry"); 194#endif /* _SUN_SDK_ */ 195 return SASL_BADPARAM; 196 } 197 198 if(!library) { 199#ifndef _SUN_SDK_ 200 _sasl_log(NULL, SASL_LOG_ERR, 201 "no library in _sasl_locate_entry"); 202#endif /* _SUN_SDK_ */ 203 return SASL_BADPARAM; 204 } 205 206 if(!entry_point) { 207#ifndef _SUN_SDK_ 208 _sasl_log(NULL, SASL_LOG_ERR, 209 "no entrypoint output pointer in _sasl_locate_entry"); 210#endif /* _SUN_SDK_ */ 211 return SASL_BADPARAM; 212 } 213 214#if defined(DLSYM_NEEDS_UNDERSCORE) || defined(__OpenBSD__) 215 snprintf(adj_entryname, sizeof adj_entryname, "_%s", entryname); 216#endif 217 218 *entry_point = NULL; 219 *entry_point = dlsym(library, adj_entryname); 220 if (*entry_point == NULL) { 221#if 0 /* This message appears to confuse people */ 222 _sasl_log(NULL, SASL_LOG_DEBUG, 223 "unable to get entry point %s: %s", adj_entryname, 224 dlerror()); 225#endif 226 return SASL_FAIL; 227 } 228 229 return SASL_OK; 230#else 231 return SASL_FAIL; 232#endif /* DO_DLOPEN */ 233} 234 235#ifdef DO_DLOPEN 236 237#ifdef _SUN_SDK_ 238static int _sasl_plugin_load(_sasl_global_context_t *gctx, 239 char *plugin, void *library, 240 const char *entryname, 241 int (*add_plugin)(_sasl_global_context_t *gctx, 242 const char *, void *)) 243#else 244static int _sasl_plugin_load(char *plugin, void *library, 245 const char *entryname, 246 int (*add_plugin)(const char *, void *)) 247#endif /* _SUN_SDK_ */ 248{ 249 void *entry_point; 250 int result; 251 252 result = _sasl_locate_entry(library, entryname, &entry_point); 253 if(result == SASL_OK) { 254#ifdef _SUN_SDK_ 255 result = add_plugin(gctx, plugin, entry_point); 256#else 257 result = add_plugin(plugin, entry_point); 258#endif /* _SUN_SDK_ */ 259 if(result != SASL_OK) 260#ifdef _SUN_SDK_ 261 __sasl_log(gctx, gctx->server_global_callbacks.callbacks == NULL ? 262 gctx->client_global_callbacks.callbacks : 263 gctx->server_global_callbacks.callbacks, 264 SASL_LOG_DEBUG, 265 "_sasl_plugin_load failed on %s for plugin: %s\n", 266 entryname, plugin); 267#else 268 _sasl_log(NULL, SASL_LOG_DEBUG, 269 "_sasl_plugin_load failed on %s for plugin: %s\n", 270 entryname, plugin); 271#endif /* _SUN_SDK_ */ 272 } 273 274 return result; 275} 276 277#ifndef _SUN_SDK_ 278/* this returns the file to actually open. 279 * out should be a buffer of size PATH_MAX 280 * and may be the same as in. */ 281 282/* We'll use a static buffer for speed unless someone complains */ 283#define MAX_LINE 2048 284 285static int _parse_la(const char *prefix, const char *in, char *out) 286{ 287 FILE *file; 288 size_t length; 289 char line[MAX_LINE]; 290 char *ntmp = NULL; 291 292 if(!in || !out || !prefix || out == in) return SASL_BADPARAM; 293 294 /* Set this so we can detect failure */ 295 *out = '\0'; 296 297 length = strlen(in); 298 299 if (strcmp(in + (length - strlen(LA_SUFFIX)), LA_SUFFIX)) { 300 if(!strcmp(in + (length - strlen(SO_SUFFIX)),SO_SUFFIX)) { 301 /* check for a .la file */ 302 strcpy(line, prefix); 303 strcat(line, in); 304 length = strlen(line); 305 *(line + (length - strlen(SO_SUFFIX))) = '\0'; 306 strcat(line, LA_SUFFIX); 307 file = fopen(line, "rF"); 308 if(file) { 309 /* We'll get it on the .la open */ 310 fclose(file); 311 return SASL_FAIL; 312 } 313 } 314 strcpy(out, prefix); 315 strcat(out, in); 316 return SASL_OK; 317 } 318 319 strcpy(line, prefix); 320 strcat(line, in); 321 322 file = fopen(line, "rF"); 323 if(!file) { 324 _sasl_log(NULL, SASL_LOG_WARN, 325 "unable to open LA file: %s", line); 326 return SASL_FAIL; 327 } 328 329 while(!feof(file)) { 330 if(!fgets(line, MAX_LINE, file)) break; 331 if(line[strlen(line) - 1] != '\n') { 332 _sasl_log(NULL, SASL_LOG_WARN, 333 "LA file has too long of a line: %s", in); 334 return SASL_BUFOVER; 335 } 336 if(line[0] == '\n' || line[0] == '#') continue; 337 if(!strncmp(line, "dlname=", sizeof("dlname=") - 1)) { 338 /* We found the line with the name in it */ 339 char *end; 340 char *start; 341 size_t len; 342 end = strrchr(line, '\''); 343 if(!end) continue; 344 start = &line[sizeof("dlname=")-1]; 345 len = strlen(start); 346 if(len > 3 && start[0] == '\'') { 347 ntmp=&start[1]; 348 *end='\0'; 349 /* Do we have dlname="" ? */ 350 if(ntmp == end) { 351 _sasl_log(NULL, SASL_LOG_DEBUG, 352 "dlname is empty in .la file: %s", in); 353 return SASL_FAIL; 354 } 355 strcpy(out, prefix); 356 strcat(out, ntmp); 357 } 358 break; 359 } 360 } 361 if(ferror(file) || feof(file)) { 362 _sasl_log(NULL, SASL_LOG_WARN, 363 "Error reading .la: %s\n", in); 364 fclose(file); 365 return SASL_FAIL; 366 } 367 fclose(file); 368 369 if(!(*out)) { 370 _sasl_log(NULL, SASL_LOG_WARN, 371 "Could not find a dlname line in .la file: %s", in); 372 return SASL_FAIL; 373 } 374 375 return SASL_OK; 376} 377#endif /* !_SUN_SDK_ */ 378#endif /* DO_DLOPEN */ 379 380/* loads a plugin library */ 381#ifdef _SUN_SDK_ 382int _sasl_get_plugin(_sasl_global_context_t *gctx, 383 const char *file, 384 const sasl_callback_t *verifyfile_cb, 385 void **libraryptr) 386#else 387int _sasl_get_plugin(const char *file, 388 const sasl_callback_t *verifyfile_cb, 389 void **libraryptr) 390#endif /* _SUN_SDK_ */ 391{ 392#ifdef DO_DLOPEN 393 int r = 0; 394 int flag; 395 void *library; 396 lib_list_t *newhead; 397 398 r = ((sasl_verifyfile_t *)(verifyfile_cb->proc)) 399 (verifyfile_cb->context, file, SASL_VRFY_PLUGIN); 400 if (r != SASL_OK) return r; 401 402#ifdef RTLD_NOW 403 flag = RTLD_NOW; 404#else 405 flag = 0; 406#endif 407 408 newhead = sasl_ALLOC(sizeof(lib_list_t)); 409 if(!newhead) return SASL_NOMEM; 410 411 if (!(library = dlopen(file, flag))) { 412#ifdef _SUN_SDK_ 413 __sasl_log(gctx, gctx->server_global_callbacks.callbacks == NULL ? 414 gctx->client_global_callbacks.callbacks : 415 gctx->server_global_callbacks.callbacks, 416 SASL_LOG_ERR, 417 "unable to dlopen %s: %s", file, dlerror()); 418#else 419 _sasl_log(NULL, SASL_LOG_ERR, 420 "unable to dlopen %s: %s", file, dlerror()); 421#endif /* _SUN_SDK_ */ 422 sasl_FREE(newhead); 423 return SASL_FAIL; 424 } 425 426#ifdef _SUN_SDK_ 427 if (LOCK_MUTEX(&global_mutex) < 0) { 428 sasl_FREE(newhead); 429 dlclose(library); 430 return (SASL_FAIL); 431 } 432#endif /* _SUN_SDK_ */ 433 434 newhead->library = library; 435#ifdef _SUN_SDK_ 436 newhead->next = gctx->lib_list_head; 437 gctx->lib_list_head = newhead; 438 UNLOCK_MUTEX(&global_mutex); 439#else 440 newhead->next = lib_list_head; 441 lib_list_head = newhead; 442#endif /* _SUN_SDK_ */ 443 444 *libraryptr = library; 445 return SASL_OK; 446#else 447 return SASL_FAIL; 448#endif /* DO_DLOPEN */ 449} 450 451#ifdef _SUN_SDK_ 452#if defined DO_DLOPEN || defined WIN_PLUG /* _SUN_SDK_ */ 453 454static void release_plugin(_sasl_global_context_t *gctx, void *library) 455{ 456 lib_list_t *libptr, *libptr_next = NULL, *libptr_prev = NULL; 457 int r; 458 459 r = LOCK_MUTEX(&global_mutex); 460 if (r < 0) 461 return; 462 463 for(libptr = gctx->lib_list_head; libptr; libptr = libptr_next) { 464 libptr_next = libptr->next; 465 if (library == libptr->library) { 466 if(libptr->library) 467#if defined DO_DLOPEN /* _SUN_SDK_ */ 468 dlclose(libptr->library); 469#else 470 FreeLibrary(libptr->library); 471#endif /* DO_DLOPEN */ /* _SUN_SDK_ */ 472 sasl_FREE(libptr); 473 break; 474 } 475 libptr_prev = libptr; 476 } 477 if (libptr_prev == NULL) 478 gctx->lib_list_head = libptr_next; 479 else 480 libptr_prev->next = libptr_next; 481 482 UNLOCK_MUTEX(&global_mutex); 483} 484#endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */ 485#endif /* _SUN_SDK_ */ 486 487/* gets the list of mechanisms */ 488#ifdef _SUN_SDK_ 489int _sasl_load_plugins(_sasl_global_context_t *gctx, 490 int server, 491 const add_plugin_list_t *entrypoints, 492 const sasl_callback_t *getpath_cb, 493 const sasl_callback_t *verifyfile_cb) 494#else 495int _sasl_load_plugins(const add_plugin_list_t *entrypoints, 496 const sasl_callback_t *getpath_cb, 497 const sasl_callback_t *verifyfile_cb) 498#endif /* _SUN_SDK_ */ 499{ 500 int result; 501 const add_plugin_list_t *cur_ep; 502#ifdef _SUN_SDK_ 503 _sasl_path_info_t *path_info, *p_info; 504#endif /* _SUN_SDK_ */ 505#ifdef DO_DLOPEN 506 char str[PATH_MAX], tmp[PATH_MAX+2], prefix[PATH_MAX+2]; 507 /* 1 for '/' 1 for trailing '\0' */ 508 char c; 509 int pos; 510 const char *path=NULL; 511 int position; 512 DIR *dp; 513 struct dirent *dir; 514#ifdef _SUN_SDK_ 515 int plugin_loaded; 516 struct stat b; 517#endif /* _SUN_SDK_ */ 518#endif 519#ifndef PIC 520 add_plugin_t *add_plugin; 521 _sasl_plug_type type; 522 _sasl_plug_rec *p; 523#endif 524 525 if (! entrypoints 526 || ! getpath_cb 527 || getpath_cb->id != SASL_CB_GETPATH 528 || ! getpath_cb->proc 529 || ! verifyfile_cb 530 || verifyfile_cb->id != SASL_CB_VERIFYFILE 531 || ! verifyfile_cb->proc) 532 return SASL_BADPARAM; 533 534#ifndef PIC 535 /* do all the static plugins first */ 536 537 for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) { 538 539 /* What type of plugin are we looking for? */ 540 if(!strcmp(cur_ep->entryname, "sasl_server_plug_init")) { 541 type = SERVER; 542#ifdef _SUN_SDK_ 543 add_plugin = (add_plugin_t *)_sasl_server_add_plugin; 544#else 545 add_plugin = (add_plugin_t *)sasl_server_add_plugin; 546#endif /* _SUN_SDK_ */ 547 } else if (!strcmp(cur_ep->entryname, "sasl_client_plug_init")) { 548 type = CLIENT; 549#ifdef _SUN_SDK_ 550 add_plugin = (add_plugin_t *)_sasl_client_add_plugin; 551#else 552 add_plugin = (add_plugin_t *)sasl_client_add_plugin; 553#endif /* _SUN_SDK_ */ 554 } else if (!strcmp(cur_ep->entryname, "sasl_auxprop_plug_init")) { 555 type = AUXPROP; 556#ifdef _SUN_SDK_ 557 add_plugin = (add_plugin_t *)_sasl_auxprop_add_plugin; 558#else 559 add_plugin = (add_plugin_t *)sasl_auxprop_add_plugin; 560#endif /* _SUN_SDK_ */ 561 } else if (!strcmp(cur_ep->entryname, "sasl_canonuser_init")) { 562 type = CANONUSER; 563#ifdef _SUN_SDK_ 564 add_plugin = (add_plugin_t *)_sasl_canonuser_add_plugin; 565#else 566 add_plugin = (add_plugin_t *)sasl_canonuser_add_plugin; 567#endif /* _SUN_SDK_ */ 568 } else { 569 /* What are we looking for then? */ 570 return SASL_FAIL; 571 } 572 for (p=_sasl_static_plugins; p->type; p++) { 573 if(type == p->type) 574#ifdef _SUN_SDK_ 575 result = add_plugin(gctx, p->name, (void *)p->plug); 576#else 577 result = add_plugin(p->name, p->plug); 578#endif /* _SUN_SDK_ */ 579 } 580 } 581#endif /* !PIC */ 582 583/* only do the following if: 584 * 585 * we support dlopen() 586 * AND we are not staticly compiled 587 * OR we are staticly compiled and TRY_DLOPEN_WHEN_STATIC is defined 588 */ 589#if defined(DO_DLOPEN) && (defined(PIC) || (!defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC))) 590 /* get the path to the plugins */ 591 result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context, 592 &path); 593 if (result != SASL_OK) return result; 594 if (! path) return SASL_FAIL; 595 596 if (strlen(path) >= PATH_MAX) { /* no you can't buffer overrun */ 597 return SASL_FAIL; 598 } 599 600 position=0; 601 do { 602 pos=0; 603 do { 604 c=path[position]; 605 position++; 606 str[pos]=c; 607 pos++; 608 } while ((c!=':') && (c!='=') && (c!=0)); 609 str[pos-1]='\0'; 610 611 strcpy(prefix,str); 612 strcat(prefix,"/"); 613#ifdef _SUN_SDK_ 614 path_info = server ? gctx->splug_path_info : gctx->cplug_path_info; 615 while (path_info != NULL) { 616 if (strcmp(path_info->path, prefix) == 0) 617 break; 618 path_info = path_info->next; 619 } 620 if (stat(prefix, &b) != 0) { 621 continue; 622 } 623 if ( path_info == NULL) { 624 p_info = (_sasl_path_info_t *) 625 sasl_ALLOC(sizeof (_sasl_path_info_t)); 626 if (p_info == NULL) { 627 return SASL_NOMEM; 628 } 629 if(_sasl_strdup(prefix, &p_info->path, NULL) != SASL_OK) { 630 sasl_FREE(p_info); 631 return SASL_NOMEM; 632 } 633 p_info->last_changed = b.st_mtime; 634 if (server) { 635 p_info->next = gctx->splug_path_info; 636 gctx->splug_path_info = p_info; 637 } else { 638 p_info->next = gctx->cplug_path_info; 639 gctx->cplug_path_info = p_info; 640 } 641 } else { 642 if (b.st_mtime <= path_info->last_changed) { 643 continue; 644 } 645 } 646#endif /* _SUN_SDK_ */ 647 648 if ((dp=opendir(str)) !=NULL) /* ignore errors */ 649 { 650 while ((dir=readdir(dp)) != NULL) 651 { 652 size_t length; 653 void *library; 654#ifndef _SUN_SDK_ 655 char *c; 656#endif /* !_SUN_SDK_ */ 657 char plugname[PATH_MAX]; 658 char name[PATH_MAX]; 659 660 length = NAMLEN(dir); 661#ifndef _SUN_SDK_ 662 if (length < 4) 663 continue; /* can not possibly be what we're looking for */ 664#endif /* !_SUN_SDK_ */ 665 666 if (length + pos>=PATH_MAX) continue; /* too big */ 667 668#ifdef _SUN_SDK_ 669 if (dir->d_name[0] == '.') 670 continue; 671#else 672 if (strcmp(dir->d_name + (length - strlen(SO_SUFFIX)), 673 SO_SUFFIX) 674 && strcmp(dir->d_name + (length - strlen(LA_SUFFIX)), 675 LA_SUFFIX)) 676 continue; 677#endif /* _SUN_SDK_ */ 678 679 memcpy(name,dir->d_name,length); 680 name[length]='\0'; 681 682#ifdef _SUN_SDK_ 683 snprintf(tmp, sizeof (tmp), "%s%s", prefix, name); 684#else 685 result = _parse_la(prefix, name, tmp); 686 if(result != SASL_OK) 687 continue; 688#endif /* _SUN_SDK_ */ 689 690#ifdef _SUN_SDK_ 691 if (stat(tmp, &b)) 692 continue; /* Can't stat it */ 693 if (!S_ISREG(b.st_mode)) 694 continue; 695 /* Sun plugins don't have lib prefix */ 696 strcpy(plugname, name); 697#else 698 /* skip "lib" and cut off suffix -- 699 this only need be approximate */ 700 strcpy(plugname, name + 3); 701 c = strchr(plugname, (int)'.'); 702 if(c) *c = '\0'; 703#endif /* _SUN_SDK_ */ 704 705#ifdef _SUN_SDK_ 706 result = _sasl_get_plugin(gctx, tmp, verifyfile_cb, 707 &library); 708#else 709 result = _sasl_get_plugin(tmp, verifyfile_cb, &library); 710#endif /* _SUN_SDK_ */ 711 712 if(result != SASL_OK) 713 continue; 714 715#ifdef _SUN_SDK_ 716 plugin_loaded = 0; 717 for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) { 718 /* If this fails, it's not the end of the world */ 719 if (_sasl_plugin_load(gctx, plugname, library, 720 cur_ep->entryname, 721 cur_ep->add_plugin) == SASL_OK) { 722 plugin_loaded = 1; 723 } 724 } 725 if (!plugin_loaded) 726 release_plugin(gctx, library); 727#else 728 for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) { 729 _sasl_plugin_load(plugname, library, cur_ep->entryname, 730 cur_ep->add_plugin); 731 /* If this fails, it's not the end of the world */ 732 } 733#endif /* _SUN_SDK_ */ 734 } 735 736 closedir(dp); 737 } 738 739 } while ((c!='=') && (c!=0)); 740#elif defined _SUN_SDK_ && defined WIN_PLUG 741 result = 742 _sasl_load_win_plugins(gctx, entrypoints, getpath_cb, verifyfile_cb); 743 if (result != SASL_OK) 744 return (result); 745#endif /* defined(DO_DLOPEN) && (!defined(PIC) || (defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC))) */ 746 747 return SASL_OK; 748} 749 750#ifdef _SUN_SDK_ 751int 752_sasl_done_with_plugins(_sasl_global_context_t *gctx) 753#else 754int 755_sasl_done_with_plugins(void) 756#endif /* _SUN_SDK_ */ 757{ 758#if defined DO_DLOPEN || defined WIN_PLUG /* _SUN_SDK_ */ 759 lib_list_t *libptr, *libptr_next; 760 761#ifdef _SUN_SDK_ 762 if (LOCK_MUTEX(&global_mutex) < 0) 763 return (SASL_FAIL); 764#endif /* _SUN_SDK_ */ 765 766#ifdef _SUN_SDK_ 767 for(libptr = gctx->lib_list_head; libptr; libptr = libptr_next) { 768#else 769 for(libptr = lib_list_head; libptr; libptr = libptr_next) { 770#endif /* _SUN_SDK_ */ 771 libptr_next = libptr->next; 772 if(libptr->library) 773#ifdef DO_DLOPEN /* _SUN_SDK_ */ 774 dlclose(libptr->library); 775#else 776 FreeLibrary(libptr->library); 777#endif /* DO_DLOPEN */ /* _SUN_SDK_ */ 778 sasl_FREE(libptr); 779 } 780 781#ifdef _SUN_SDK_ 782 gctx->lib_list_head = NULL; 783#else 784 lib_list_head = NULL; 785#endif /* _SUN_SDK_ */ 786 787#ifdef _SUN_SDK_ 788 UNLOCK_MUTEX(&global_mutex); 789#endif /* _SUN_SDK_ */ 790#endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */ 791 return SASL_OK; 792} 793 794#ifdef WIN_MUTEX 795 796static HANDLE global_mutex = NULL; 797 798int win_global_mutex_lock() 799{ 800 DWORD dwWaitResult; 801 802 if (global_mutex == NULL) { 803 global_mutex = CreateMutex(NULL, FALSE, NULL); 804 if (global_mutex == NULL) 805 return (-1); 806 } 807 808 dwWaitResult = WaitForSingleObject(global_mutex, INFINITE); 809 810 switch (dwWaitResult) { 811 case WAIT_OBJECT_0: 812 return (0); 813 814 case WAIT_TIMEOUT: 815 return (-1); /* Shouldn't happen */ 816 817 case WAIT_ABANDONED: 818 return (-1); /* Shouldn't happen */ 819 } 820 return (-1); /* Unexpected result */ 821} 822 823int win_global_mutex_unlock() 824{ 825 if (global_mutex == NULL) 826 return (-1); 827 828 return (ReleaseMutex(global_mutex) ? 0 : -1); 829} 830 831BOOL APIENTRY DllMain(HANDLE hModule, 832 DWORD ul_reason_for_call, 833 LPVOID lpReserved) 834{ 835 switch( ul_reason_for_call ) { 836 case DLL_PROCESS_ATTACH: 837 global_mutex = CreateMutex(NULL, FALSE, NULL); 838 if (global_mutex == NULL) 839 return (FALSE); 840 break; 841 case DLL_THREAD_ATTACH: 842 case DLL_THREAD_DETACH: 843 case DLL_PROCESS_DETACH: 844 break; 845 } 846 return TRUE; 847} 848#endif 849