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
107 typedef shl_t dll_handle;
108 typedef void * dll_func;
109
110 dll_handle
dlopen(char * fname,int mode)111 dlopen(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
128 int
dlclose(dll_handle h)129 dlclose(dll_handle h)
130 {
131 shl_t hp = *((shl_t *)h);
132 if (hp != NULL) free(hp);
133 return shl_unload(h);
134 }
135
136 dll_func
dlsym(dll_handle h,char * n)137 dlsym(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
dlerror()147 char *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_ */
164 typedef struct lib_list
165 {
166 struct lib_list *next;
167 void *library;
168 } lib_list_t;
169
170 #ifndef _SUN_SDK_
171 static lib_list_t *lib_list_head = NULL;
172 #endif /* !_SUN_SDK_ */
173
174 DEFINE_STATIC_MUTEX(global_mutex);
175
176 #endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
177
_sasl_locate_entry(void * library,const char * entryname,void ** entry_point)178 int _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_
_sasl_plugin_load(_sasl_global_context_t * gctx,char * plugin,void * library,const char * entryname,int (* add_plugin)(_sasl_global_context_t * gctx,const char *,void *))238 static 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
244 static 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
_parse_la(const char * prefix,const char * in,char * out)285 static 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_
_sasl_get_plugin(_sasl_global_context_t * gctx,const char * file,const sasl_callback_t * verifyfile_cb,void ** libraryptr)382 int _sasl_get_plugin(_sasl_global_context_t *gctx,
383 const char *file,
384 const sasl_callback_t *verifyfile_cb,
385 void **libraryptr)
386 #else
387 int _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
release_plugin(_sasl_global_context_t * gctx,void * library)454 static 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_
_sasl_load_plugins(_sasl_global_context_t * gctx,int server,const add_plugin_list_t * entrypoints,const sasl_callback_t * getpath_cb,const sasl_callback_t * verifyfile_cb)489 int _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
495 int _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_
751 int
_sasl_done_with_plugins(_sasl_global_context_t * gctx)752 _sasl_done_with_plugins(_sasl_global_context_t *gctx)
753 #else
754 int
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
796 static HANDLE global_mutex = NULL;
797
798 int 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
823 int win_global_mutex_unlock()
824 {
825 if (global_mutex == NULL)
826 return (-1);
827
828 return (ReleaseMutex(global_mutex) ? 0 : -1);
829 }
830
831 BOOL 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