xref: /illumos-gate/usr/src/lib/libsasl/lib/dlopen.c (revision 004388eb)
17c478bd9Sstevel@tonic-gate /*
2*004388ebScasper  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /* dlopen.c--Unix dlopen() dynamic loader interface
87c478bd9Sstevel@tonic-gate  * Rob Siemborski
97c478bd9Sstevel@tonic-gate  * Rob Earhart
107c478bd9Sstevel@tonic-gate  * $Id: dlopen.c,v 1.45 2003/07/14 20:08:50 rbraun Exp $
117c478bd9Sstevel@tonic-gate  */
127c478bd9Sstevel@tonic-gate /*
137c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
147c478bd9Sstevel@tonic-gate  *
157c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
167c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
177c478bd9Sstevel@tonic-gate  * are met:
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
207c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
217c478bd9Sstevel@tonic-gate  *
227c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
237c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
247c478bd9Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
257c478bd9Sstevel@tonic-gate  *    distribution.
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * 3. The name "Carnegie Mellon University" must not be used to
287c478bd9Sstevel@tonic-gate  *    endorse or promote products derived from this software without
297c478bd9Sstevel@tonic-gate  *    prior written permission. For permission or any other legal
307c478bd9Sstevel@tonic-gate  *    details, please contact
317c478bd9Sstevel@tonic-gate  *      Office of Technology Transfer
327c478bd9Sstevel@tonic-gate  *      Carnegie Mellon University
337c478bd9Sstevel@tonic-gate  *      5000 Forbes Avenue
347c478bd9Sstevel@tonic-gate  *      Pittsburgh, PA  15213-3890
357c478bd9Sstevel@tonic-gate  *      (412) 268-4387, fax: (412) 268-7395
367c478bd9Sstevel@tonic-gate  *      tech-transfer@andrew.cmu.edu
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  * 4. Redistributions of any form whatsoever must retain the following
397c478bd9Sstevel@tonic-gate  *    acknowledgment:
407c478bd9Sstevel@tonic-gate  *    "This product includes software developed by Computing Services
417c478bd9Sstevel@tonic-gate  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
427c478bd9Sstevel@tonic-gate  *
437c478bd9Sstevel@tonic-gate  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
447c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
457c478bd9Sstevel@tonic-gate  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
467c478bd9Sstevel@tonic-gate  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
477c478bd9Sstevel@tonic-gate  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
487c478bd9Sstevel@tonic-gate  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
497c478bd9Sstevel@tonic-gate  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #include <config.h>
537c478bd9Sstevel@tonic-gate #ifdef HAVE_DLFCN_H
547c478bd9Sstevel@tonic-gate #include <dlfcn.h>
557c478bd9Sstevel@tonic-gate #endif
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #include <stdlib.h>
587c478bd9Sstevel@tonic-gate #include <errno.h>
597c478bd9Sstevel@tonic-gate #include <stdio.h>
607c478bd9Sstevel@tonic-gate #include <limits.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #include <sasl.h>
637c478bd9Sstevel@tonic-gate #include "saslint.h"
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate #ifndef PIC
667c478bd9Sstevel@tonic-gate #include <saslplug.h>
677c478bd9Sstevel@tonic-gate #include "staticopen.h"
687c478bd9Sstevel@tonic-gate #endif
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
717c478bd9Sstevel@tonic-gate #include <sys/stat.h>
727c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate #ifdef DO_DLOPEN
757c478bd9Sstevel@tonic-gate #if HAVE_DIRENT_H
767c478bd9Sstevel@tonic-gate # include <dirent.h>
777c478bd9Sstevel@tonic-gate # define NAMLEN(dirent) strlen((dirent)->d_name)
787c478bd9Sstevel@tonic-gate #else /* HAVE_DIRENT_H */
797c478bd9Sstevel@tonic-gate # define dirent direct
807c478bd9Sstevel@tonic-gate # define NAMLEN(dirent) (dirent)->d_namlen
817c478bd9Sstevel@tonic-gate # if HAVE_SYS_NDIR_H
827c478bd9Sstevel@tonic-gate #  include <sys/ndir.h>
837c478bd9Sstevel@tonic-gate # endif
847c478bd9Sstevel@tonic-gate # if HAVE_SYS_DIR_H
857c478bd9Sstevel@tonic-gate #  include <sys/dir.h>
867c478bd9Sstevel@tonic-gate # endif
877c478bd9Sstevel@tonic-gate # if HAVE_NDIR_H
887c478bd9Sstevel@tonic-gate #  include <ndir.h>
897c478bd9Sstevel@tonic-gate # endif
907c478bd9Sstevel@tonic-gate #endif /* ! HAVE_DIRENT_H */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate #ifndef NAME_MAX
937c478bd9Sstevel@tonic-gate # ifdef _POSIX_NAME_MAX
947c478bd9Sstevel@tonic-gate #  define NAME_MAX _POSIX_NAME_MAX
957c478bd9Sstevel@tonic-gate # else
967c478bd9Sstevel@tonic-gate #  define NAME_MAX 16
977c478bd9Sstevel@tonic-gate # endif
987c478bd9Sstevel@tonic-gate #endif
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate #if NAME_MAX < 8
1017c478bd9Sstevel@tonic-gate #  define NAME_MAX 8
1027c478bd9Sstevel@tonic-gate #endif
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate #ifdef __hpux
1057c478bd9Sstevel@tonic-gate #include <dl.h>
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate typedef shl_t dll_handle;
1087c478bd9Sstevel@tonic-gate typedef void * dll_func;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate dll_handle
dlopen(char * fname,int mode)1117c478bd9Sstevel@tonic-gate dlopen(char *fname, int mode)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate     shl_t h = shl_load(fname, BIND_DEFERRED, 0L);
1147c478bd9Sstevel@tonic-gate     shl_t *hp = NULL;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate     if (h) {
1177c478bd9Sstevel@tonic-gate 	hp = (shl_t *)malloc(sizeof (shl_t));
1187c478bd9Sstevel@tonic-gate 	if (!hp) {
1197c478bd9Sstevel@tonic-gate 	    shl_unload(h);
1207c478bd9Sstevel@tonic-gate 	} else {
1217c478bd9Sstevel@tonic-gate 	    *hp = h;
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate     }
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate     return (dll_handle)hp;
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate int
dlclose(dll_handle h)1297c478bd9Sstevel@tonic-gate dlclose(dll_handle h)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate     shl_t hp = *((shl_t *)h);
1327c478bd9Sstevel@tonic-gate     if (hp != NULL) free(hp);
1337c478bd9Sstevel@tonic-gate     return shl_unload(h);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate dll_func
dlsym(dll_handle h,char * n)1377c478bd9Sstevel@tonic-gate dlsym(dll_handle h, char *n)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate     dll_func handle;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate     if (shl_findsym ((shl_t *)h, n, TYPE_PROCEDURE, &handle))
1427c478bd9Sstevel@tonic-gate 	return NULL;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate     return (dll_func)handle;
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate 
dlerror()1477c478bd9Sstevel@tonic-gate char *dlerror()
1487c478bd9Sstevel@tonic-gate {
1497c478bd9Sstevel@tonic-gate     if (errno != 0) {
1507c478bd9Sstevel@tonic-gate 	return strerror(errno);
1517c478bd9Sstevel@tonic-gate     }
1527c478bd9Sstevel@tonic-gate     return "Generic shared library error";
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate #define SO_SUFFIX	".sl"
1567c478bd9Sstevel@tonic-gate #else /* __hpux */
1577c478bd9Sstevel@tonic-gate #define SO_SUFFIX	".so"
1587c478bd9Sstevel@tonic-gate #endif /* __hpux */
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate #define LA_SUFFIX       ".la"
1617c478bd9Sstevel@tonic-gate #endif /* DO_DLOPEN */
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate #if defined DO_DLOPEN || defined WIN_PLUG /* _SUN_SDK_ */
1647c478bd9Sstevel@tonic-gate typedef struct lib_list
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate     struct lib_list *next;
1677c478bd9Sstevel@tonic-gate     void *library;
1687c478bd9Sstevel@tonic-gate } lib_list_t;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1717c478bd9Sstevel@tonic-gate static lib_list_t *lib_list_head = NULL;
1727c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate DEFINE_STATIC_MUTEX(global_mutex);
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate #endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
1777c478bd9Sstevel@tonic-gate 
_sasl_locate_entry(void * library,const char * entryname,void ** entry_point)1787c478bd9Sstevel@tonic-gate int _sasl_locate_entry(void *library, const char *entryname,
1797c478bd9Sstevel@tonic-gate 		       void **entry_point)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate #ifdef DO_DLOPEN
1827c478bd9Sstevel@tonic-gate /* note that we still check for known problem systems in
1837c478bd9Sstevel@tonic-gate  * case we are cross-compiling */
1847c478bd9Sstevel@tonic-gate #if defined(DLSYM_NEEDS_UNDERSCORE) || defined(__OpenBSD__)
1857c478bd9Sstevel@tonic-gate     char adj_entryname[1024];
1867c478bd9Sstevel@tonic-gate #else
1877c478bd9Sstevel@tonic-gate #define adj_entryname entryname
1887c478bd9Sstevel@tonic-gate #endif
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate     if(!entryname) {
1917c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
1927c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR,
1937c478bd9Sstevel@tonic-gate 		  "no entryname in _sasl_locate_entry");
1947c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
1957c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
1967c478bd9Sstevel@tonic-gate     }
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate     if(!library) {
1997c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
2007c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR,
2017c478bd9Sstevel@tonic-gate 		  "no library in _sasl_locate_entry");
2027c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2037c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
2047c478bd9Sstevel@tonic-gate     }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate     if(!entry_point) {
2077c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
2087c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR,
2097c478bd9Sstevel@tonic-gate 		  "no entrypoint output pointer in _sasl_locate_entry");
2107c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2117c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
2127c478bd9Sstevel@tonic-gate     }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate #if defined(DLSYM_NEEDS_UNDERSCORE) || defined(__OpenBSD__)
2157c478bd9Sstevel@tonic-gate     snprintf(adj_entryname, sizeof adj_entryname, "_%s", entryname);
2167c478bd9Sstevel@tonic-gate #endif
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate     *entry_point = NULL;
2197c478bd9Sstevel@tonic-gate     *entry_point = dlsym(library, adj_entryname);
2207c478bd9Sstevel@tonic-gate     if (*entry_point == NULL) {
2217c478bd9Sstevel@tonic-gate #if 0 /* This message appears to confuse people */
2227c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_DEBUG,
2237c478bd9Sstevel@tonic-gate 		  "unable to get entry point %s: %s", adj_entryname,
2247c478bd9Sstevel@tonic-gate 		  dlerror());
2257c478bd9Sstevel@tonic-gate #endif
2267c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
2277c478bd9Sstevel@tonic-gate     }
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate     return SASL_OK;
2307c478bd9Sstevel@tonic-gate #else
2317c478bd9Sstevel@tonic-gate     return SASL_FAIL;
2327c478bd9Sstevel@tonic-gate #endif /* DO_DLOPEN */
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate #ifdef DO_DLOPEN
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate #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 *))2387c478bd9Sstevel@tonic-gate static int _sasl_plugin_load(_sasl_global_context_t *gctx,
2397c478bd9Sstevel@tonic-gate 			     char *plugin, void *library,
2407c478bd9Sstevel@tonic-gate 			     const char *entryname,
2417c478bd9Sstevel@tonic-gate 			     int (*add_plugin)(_sasl_global_context_t *gctx,
2427c478bd9Sstevel@tonic-gate 					       const char *, void *))
2437c478bd9Sstevel@tonic-gate #else
2447c478bd9Sstevel@tonic-gate static int _sasl_plugin_load(char *plugin, void *library,
2457c478bd9Sstevel@tonic-gate 			     const char *entryname,
2467c478bd9Sstevel@tonic-gate 			     int (*add_plugin)(const char *, void *))
2477c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2487c478bd9Sstevel@tonic-gate {
2497c478bd9Sstevel@tonic-gate     void *entry_point;
2507c478bd9Sstevel@tonic-gate     int result;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate     result = _sasl_locate_entry(library, entryname, &entry_point);
2537c478bd9Sstevel@tonic-gate     if(result == SASL_OK) {
2547c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2557c478bd9Sstevel@tonic-gate 	result = add_plugin(gctx, plugin, entry_point);
2567c478bd9Sstevel@tonic-gate #else
2577c478bd9Sstevel@tonic-gate 	result = add_plugin(plugin, entry_point);
2587c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2597c478bd9Sstevel@tonic-gate 	if(result != SASL_OK)
2607c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
2617c478bd9Sstevel@tonic-gate 	    __sasl_log(gctx, gctx->server_global_callbacks.callbacks == NULL ?
2627c478bd9Sstevel@tonic-gate 	    	       gctx->client_global_callbacks.callbacks :
2637c478bd9Sstevel@tonic-gate 	    	       gctx->server_global_callbacks.callbacks,
2647c478bd9Sstevel@tonic-gate 	    	       SASL_LOG_DEBUG,
2657c478bd9Sstevel@tonic-gate 		       "_sasl_plugin_load failed on %s for plugin: %s\n",
2667c478bd9Sstevel@tonic-gate 		       entryname, plugin);
2677c478bd9Sstevel@tonic-gate #else
2687c478bd9Sstevel@tonic-gate 	    _sasl_log(NULL, SASL_LOG_DEBUG,
2697c478bd9Sstevel@tonic-gate 		      "_sasl_plugin_load failed on %s for plugin: %s\n",
2707c478bd9Sstevel@tonic-gate 		      entryname, plugin);
2717c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
2727c478bd9Sstevel@tonic-gate     }
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate     return result;
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
2787c478bd9Sstevel@tonic-gate /* this returns the file to actually open.
2797c478bd9Sstevel@tonic-gate  *  out should be a buffer of size PATH_MAX
2807c478bd9Sstevel@tonic-gate  *  and may be the same as in. */
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate /* We'll use a static buffer for speed unless someone complains */
2837c478bd9Sstevel@tonic-gate #define MAX_LINE 2048
2847c478bd9Sstevel@tonic-gate 
_parse_la(const char * prefix,const char * in,char * out)2857c478bd9Sstevel@tonic-gate static int _parse_la(const char *prefix, const char *in, char *out)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate     FILE *file;
2887c478bd9Sstevel@tonic-gate     size_t length;
2897c478bd9Sstevel@tonic-gate     char line[MAX_LINE];
2907c478bd9Sstevel@tonic-gate     char *ntmp = NULL;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate     if(!in || !out || !prefix || out == in) return SASL_BADPARAM;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate     /* Set this so we can detect failure */
2957c478bd9Sstevel@tonic-gate     *out = '\0';
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate     length = strlen(in);
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate     if (strcmp(in + (length - strlen(LA_SUFFIX)), LA_SUFFIX)) {
3007c478bd9Sstevel@tonic-gate 	if(!strcmp(in + (length - strlen(SO_SUFFIX)),SO_SUFFIX)) {
3017c478bd9Sstevel@tonic-gate 	    /* check for a .la file */
3027c478bd9Sstevel@tonic-gate 	    strcpy(line, prefix);
3037c478bd9Sstevel@tonic-gate 	    strcat(line, in);
3047c478bd9Sstevel@tonic-gate 	    length = strlen(line);
3057c478bd9Sstevel@tonic-gate 	    *(line + (length - strlen(SO_SUFFIX))) = '\0';
3067c478bd9Sstevel@tonic-gate 	    strcat(line, LA_SUFFIX);
307*004388ebScasper 	    file = fopen(line, "rF");
3087c478bd9Sstevel@tonic-gate 	    if(file) {
3097c478bd9Sstevel@tonic-gate 		/* We'll get it on the .la open */
3107c478bd9Sstevel@tonic-gate 		fclose(file);
3117c478bd9Sstevel@tonic-gate 		return SASL_FAIL;
3127c478bd9Sstevel@tonic-gate 	    }
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 	strcpy(out, prefix);
3157c478bd9Sstevel@tonic-gate 	strcat(out, in);
3167c478bd9Sstevel@tonic-gate 	return SASL_OK;
3177c478bd9Sstevel@tonic-gate     }
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate     strcpy(line, prefix);
3207c478bd9Sstevel@tonic-gate     strcat(line, in);
3217c478bd9Sstevel@tonic-gate 
322*004388ebScasper     file = fopen(line, "rF");
3237c478bd9Sstevel@tonic-gate     if(!file) {
3247c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_WARN,
3257c478bd9Sstevel@tonic-gate 		  "unable to open LA file: %s", line);
3267c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
3277c478bd9Sstevel@tonic-gate     }
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate     while(!feof(file)) {
3307c478bd9Sstevel@tonic-gate 	if(!fgets(line, MAX_LINE, file)) break;
3317c478bd9Sstevel@tonic-gate 	if(line[strlen(line) - 1] != '\n') {
3327c478bd9Sstevel@tonic-gate 	    _sasl_log(NULL, SASL_LOG_WARN,
3337c478bd9Sstevel@tonic-gate 		      "LA file has too long of a line: %s", in);
3347c478bd9Sstevel@tonic-gate 	    return SASL_BUFOVER;
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 	if(line[0] == '\n' || line[0] == '#') continue;
3377c478bd9Sstevel@tonic-gate 	if(!strncmp(line, "dlname=", sizeof("dlname=") - 1)) {
3387c478bd9Sstevel@tonic-gate 	    /* We found the line with the name in it */
3397c478bd9Sstevel@tonic-gate 	    char *end;
3407c478bd9Sstevel@tonic-gate 	    char *start;
3417c478bd9Sstevel@tonic-gate 	    size_t len;
3427c478bd9Sstevel@tonic-gate 	    end = strrchr(line, '\'');
3437c478bd9Sstevel@tonic-gate 	    if(!end) continue;
3447c478bd9Sstevel@tonic-gate 	    start = &line[sizeof("dlname=")-1];
3457c478bd9Sstevel@tonic-gate 	    len = strlen(start);
3467c478bd9Sstevel@tonic-gate 	    if(len > 3 && start[0] == '\'') {
3477c478bd9Sstevel@tonic-gate 		ntmp=&start[1];
3487c478bd9Sstevel@tonic-gate 		*end='\0';
3497c478bd9Sstevel@tonic-gate 		/* Do we have dlname="" ? */
3507c478bd9Sstevel@tonic-gate 		if(ntmp == end) {
3517c478bd9Sstevel@tonic-gate 		    _sasl_log(NULL, SASL_LOG_DEBUG,
3527c478bd9Sstevel@tonic-gate 			      "dlname is empty in .la file: %s", in);
3537c478bd9Sstevel@tonic-gate 		    return SASL_FAIL;
3547c478bd9Sstevel@tonic-gate 		}
3557c478bd9Sstevel@tonic-gate 		strcpy(out, prefix);
3567c478bd9Sstevel@tonic-gate 		strcat(out, ntmp);
3577c478bd9Sstevel@tonic-gate 	    }
3587c478bd9Sstevel@tonic-gate 	    break;
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate     }
3617c478bd9Sstevel@tonic-gate     if(ferror(file) || feof(file)) {
3627c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_WARN,
3637c478bd9Sstevel@tonic-gate 		  "Error reading .la: %s\n", in);
3647c478bd9Sstevel@tonic-gate 	fclose(file);
3657c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
3667c478bd9Sstevel@tonic-gate     }
3677c478bd9Sstevel@tonic-gate     fclose(file);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate     if(!(*out)) {
3707c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_WARN,
3717c478bd9Sstevel@tonic-gate 		  "Could not find a dlname line in .la file: %s", in);
3727c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
3737c478bd9Sstevel@tonic-gate     }
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate     return SASL_OK;
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
3787c478bd9Sstevel@tonic-gate #endif /* DO_DLOPEN */
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate /* loads a plugin library */
3817c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
_sasl_get_plugin(_sasl_global_context_t * gctx,const char * file,const sasl_callback_t * verifyfile_cb,void ** libraryptr)3827c478bd9Sstevel@tonic-gate int _sasl_get_plugin(_sasl_global_context_t *gctx,
3837c478bd9Sstevel@tonic-gate 		     const char *file,
3847c478bd9Sstevel@tonic-gate 		     const sasl_callback_t *verifyfile_cb,
3857c478bd9Sstevel@tonic-gate 		     void **libraryptr)
3867c478bd9Sstevel@tonic-gate #else
3877c478bd9Sstevel@tonic-gate int _sasl_get_plugin(const char *file,
3887c478bd9Sstevel@tonic-gate 		     const sasl_callback_t *verifyfile_cb,
3897c478bd9Sstevel@tonic-gate 		     void **libraryptr)
3907c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
3917c478bd9Sstevel@tonic-gate {
3927c478bd9Sstevel@tonic-gate #ifdef DO_DLOPEN
3937c478bd9Sstevel@tonic-gate     int r = 0;
3947c478bd9Sstevel@tonic-gate     int flag;
3957c478bd9Sstevel@tonic-gate     void *library;
3967c478bd9Sstevel@tonic-gate     lib_list_t *newhead;
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate     r = ((sasl_verifyfile_t *)(verifyfile_cb->proc))
3997c478bd9Sstevel@tonic-gate 		    (verifyfile_cb->context, file, SASL_VRFY_PLUGIN);
4007c478bd9Sstevel@tonic-gate     if (r != SASL_OK) return r;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate #ifdef RTLD_NOW
4037c478bd9Sstevel@tonic-gate     flag = RTLD_NOW;
4047c478bd9Sstevel@tonic-gate #else
4057c478bd9Sstevel@tonic-gate     flag = 0;
4067c478bd9Sstevel@tonic-gate #endif
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate     newhead = sasl_ALLOC(sizeof(lib_list_t));
4097c478bd9Sstevel@tonic-gate     if(!newhead) return SASL_NOMEM;
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate     if (!(library = dlopen(file, flag))) {
4127c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4137c478bd9Sstevel@tonic-gate 	__sasl_log(gctx, gctx->server_global_callbacks.callbacks == NULL ?
4147c478bd9Sstevel@tonic-gate 	    	   gctx->client_global_callbacks.callbacks :
4157c478bd9Sstevel@tonic-gate 	    	   gctx->server_global_callbacks.callbacks,
4167c478bd9Sstevel@tonic-gate 		   SASL_LOG_ERR,
4177c478bd9Sstevel@tonic-gate 		   "unable to dlopen %s: %s", file, dlerror());
4187c478bd9Sstevel@tonic-gate #else
4197c478bd9Sstevel@tonic-gate 	_sasl_log(NULL, SASL_LOG_ERR,
4207c478bd9Sstevel@tonic-gate 		  "unable to dlopen %s: %s", file, dlerror());
4217c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4227c478bd9Sstevel@tonic-gate 	sasl_FREE(newhead);
4237c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
4247c478bd9Sstevel@tonic-gate     }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4277c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&global_mutex) < 0) {
4287c478bd9Sstevel@tonic-gate 	sasl_FREE(newhead);
4297c478bd9Sstevel@tonic-gate 	dlclose(library);
4307c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
4317c478bd9Sstevel@tonic-gate     }
4327c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate     newhead->library = library;
4357c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4367c478bd9Sstevel@tonic-gate     newhead->next = gctx->lib_list_head;
4377c478bd9Sstevel@tonic-gate     gctx->lib_list_head = newhead;
4387c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&global_mutex);
4397c478bd9Sstevel@tonic-gate #else
4407c478bd9Sstevel@tonic-gate     newhead->next = lib_list_head;
4417c478bd9Sstevel@tonic-gate     lib_list_head = newhead;
4427c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate     *libraryptr = library;
4457c478bd9Sstevel@tonic-gate     return SASL_OK;
4467c478bd9Sstevel@tonic-gate #else
4477c478bd9Sstevel@tonic-gate     return SASL_FAIL;
4487c478bd9Sstevel@tonic-gate #endif /* DO_DLOPEN */
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
4527c478bd9Sstevel@tonic-gate #if defined DO_DLOPEN || defined WIN_PLUG /* _SUN_SDK_ */
4537c478bd9Sstevel@tonic-gate 
release_plugin(_sasl_global_context_t * gctx,void * library)4547c478bd9Sstevel@tonic-gate static void release_plugin(_sasl_global_context_t *gctx, void *library)
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate     lib_list_t *libptr, *libptr_next = NULL, *libptr_prev = NULL;
4577c478bd9Sstevel@tonic-gate     int r;
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate     r = LOCK_MUTEX(&global_mutex);
4607c478bd9Sstevel@tonic-gate     if (r < 0)
4617c478bd9Sstevel@tonic-gate 	return;
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate     for(libptr = gctx->lib_list_head; libptr; libptr = libptr_next) {
4647c478bd9Sstevel@tonic-gate 	libptr_next = libptr->next;
4657c478bd9Sstevel@tonic-gate 	if (library == libptr->library) {
4667c478bd9Sstevel@tonic-gate 	    if(libptr->library)
4677c478bd9Sstevel@tonic-gate #if defined DO_DLOPEN /* _SUN_SDK_ */
4687c478bd9Sstevel@tonic-gate 		dlclose(libptr->library);
4697c478bd9Sstevel@tonic-gate #else
4707c478bd9Sstevel@tonic-gate 		FreeLibrary(libptr->library);
4717c478bd9Sstevel@tonic-gate #endif /* DO_DLOPEN */ /* _SUN_SDK_ */
4727c478bd9Sstevel@tonic-gate 	    sasl_FREE(libptr);
4737c478bd9Sstevel@tonic-gate 	    break;
4747c478bd9Sstevel@tonic-gate 	}
4757c478bd9Sstevel@tonic-gate 	libptr_prev = libptr;
4767c478bd9Sstevel@tonic-gate     }
4777c478bd9Sstevel@tonic-gate     if (libptr_prev == NULL)
4787c478bd9Sstevel@tonic-gate 	gctx->lib_list_head = libptr_next;
4797c478bd9Sstevel@tonic-gate     else
4807c478bd9Sstevel@tonic-gate 	libptr_prev->next = libptr_next;
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&global_mutex);
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate #endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
4857c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate /* gets the list of mechanisms */
4887c478bd9Sstevel@tonic-gate #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)4897c478bd9Sstevel@tonic-gate int _sasl_load_plugins(_sasl_global_context_t *gctx,
4907c478bd9Sstevel@tonic-gate 		       int server,
4917c478bd9Sstevel@tonic-gate 		       const add_plugin_list_t *entrypoints,
4927c478bd9Sstevel@tonic-gate 		       const sasl_callback_t *getpath_cb,
4937c478bd9Sstevel@tonic-gate 		       const sasl_callback_t *verifyfile_cb)
4947c478bd9Sstevel@tonic-gate #else
4957c478bd9Sstevel@tonic-gate int _sasl_load_plugins(const add_plugin_list_t *entrypoints,
4967c478bd9Sstevel@tonic-gate 		       const sasl_callback_t *getpath_cb,
4977c478bd9Sstevel@tonic-gate 		       const sasl_callback_t *verifyfile_cb)
4987c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
4997c478bd9Sstevel@tonic-gate {
5007c478bd9Sstevel@tonic-gate     int result;
5017c478bd9Sstevel@tonic-gate     const add_plugin_list_t *cur_ep;
5027c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5037c478bd9Sstevel@tonic-gate     _sasl_path_info_t *path_info, *p_info;
5047c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5057c478bd9Sstevel@tonic-gate #ifdef DO_DLOPEN
5067c478bd9Sstevel@tonic-gate     char str[PATH_MAX], tmp[PATH_MAX+2], prefix[PATH_MAX+2];
5077c478bd9Sstevel@tonic-gate 				/* 1 for '/' 1 for trailing '\0' */
5087c478bd9Sstevel@tonic-gate     char c;
5097c478bd9Sstevel@tonic-gate     int pos;
5107c478bd9Sstevel@tonic-gate     const char *path=NULL;
5117c478bd9Sstevel@tonic-gate     int position;
5127c478bd9Sstevel@tonic-gate     DIR *dp;
5137c478bd9Sstevel@tonic-gate     struct dirent *dir;
5147c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5157c478bd9Sstevel@tonic-gate     int plugin_loaded;
5167c478bd9Sstevel@tonic-gate     struct stat b;
5177c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5187c478bd9Sstevel@tonic-gate #endif
5197c478bd9Sstevel@tonic-gate #ifndef PIC
5207c478bd9Sstevel@tonic-gate     add_plugin_t *add_plugin;
5217c478bd9Sstevel@tonic-gate     _sasl_plug_type type;
5227c478bd9Sstevel@tonic-gate     _sasl_plug_rec *p;
5237c478bd9Sstevel@tonic-gate #endif
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate     if (! entrypoints
5267c478bd9Sstevel@tonic-gate 	|| ! getpath_cb
5277c478bd9Sstevel@tonic-gate 	|| getpath_cb->id != SASL_CB_GETPATH
5287c478bd9Sstevel@tonic-gate 	|| ! getpath_cb->proc
5297c478bd9Sstevel@tonic-gate 	|| ! verifyfile_cb
5307c478bd9Sstevel@tonic-gate 	|| verifyfile_cb->id != SASL_CB_VERIFYFILE
5317c478bd9Sstevel@tonic-gate 	|| ! verifyfile_cb->proc)
5327c478bd9Sstevel@tonic-gate 	return SASL_BADPARAM;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate #ifndef PIC
5357c478bd9Sstevel@tonic-gate     /* do all the static plugins first */
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate     for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) {
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	/* What type of plugin are we looking for? */
5407c478bd9Sstevel@tonic-gate 	if(!strcmp(cur_ep->entryname, "sasl_server_plug_init")) {
5417c478bd9Sstevel@tonic-gate 	    type = SERVER;
5427c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5437c478bd9Sstevel@tonic-gate 	    add_plugin = (add_plugin_t *)_sasl_server_add_plugin;
5447c478bd9Sstevel@tonic-gate #else
5457c478bd9Sstevel@tonic-gate 	    add_plugin = (add_plugin_t *)sasl_server_add_plugin;
5467c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5477c478bd9Sstevel@tonic-gate 	} else if (!strcmp(cur_ep->entryname, "sasl_client_plug_init")) {
5487c478bd9Sstevel@tonic-gate 	    type = CLIENT;
5497c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5507c478bd9Sstevel@tonic-gate 	    add_plugin = (add_plugin_t *)_sasl_client_add_plugin;
5517c478bd9Sstevel@tonic-gate #else
5527c478bd9Sstevel@tonic-gate 	    add_plugin = (add_plugin_t *)sasl_client_add_plugin;
5537c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5547c478bd9Sstevel@tonic-gate 	} else if (!strcmp(cur_ep->entryname, "sasl_auxprop_plug_init")) {
5557c478bd9Sstevel@tonic-gate 	    type = AUXPROP;
5567c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5577c478bd9Sstevel@tonic-gate 	    add_plugin = (add_plugin_t *)_sasl_auxprop_add_plugin;
5587c478bd9Sstevel@tonic-gate #else
5597c478bd9Sstevel@tonic-gate 	    add_plugin = (add_plugin_t *)sasl_auxprop_add_plugin;
5607c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5617c478bd9Sstevel@tonic-gate 	} else if (!strcmp(cur_ep->entryname, "sasl_canonuser_init")) {
5627c478bd9Sstevel@tonic-gate 	    type = CANONUSER;
5637c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5647c478bd9Sstevel@tonic-gate 	    add_plugin = (add_plugin_t *)_sasl_canonuser_add_plugin;
5657c478bd9Sstevel@tonic-gate #else
5667c478bd9Sstevel@tonic-gate 	    add_plugin = (add_plugin_t *)sasl_canonuser_add_plugin;
5677c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5687c478bd9Sstevel@tonic-gate 	} else {
5697c478bd9Sstevel@tonic-gate 	    /* What are we looking for then? */
5707c478bd9Sstevel@tonic-gate 	    return SASL_FAIL;
5717c478bd9Sstevel@tonic-gate 	}
5727c478bd9Sstevel@tonic-gate 	for (p=_sasl_static_plugins; p->type; p++) {
5737c478bd9Sstevel@tonic-gate 	    if(type == p->type)
5747c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
5757c478bd9Sstevel@tonic-gate 	    	result = add_plugin(gctx, p->name, (void *)p->plug);
5767c478bd9Sstevel@tonic-gate #else
5777c478bd9Sstevel@tonic-gate 	    	result = add_plugin(p->name, p->plug);
5787c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
5797c478bd9Sstevel@tonic-gate 	}
5807c478bd9Sstevel@tonic-gate     }
5817c478bd9Sstevel@tonic-gate #endif /* !PIC */
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate /* only do the following if:
5847c478bd9Sstevel@tonic-gate  *
5857c478bd9Sstevel@tonic-gate  * we support dlopen()
5867c478bd9Sstevel@tonic-gate  *  AND we are not staticly compiled
5877c478bd9Sstevel@tonic-gate  *      OR we are staticly compiled and TRY_DLOPEN_WHEN_STATIC is defined
5887c478bd9Sstevel@tonic-gate  */
5897c478bd9Sstevel@tonic-gate #if defined(DO_DLOPEN) && (defined(PIC) || (!defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC)))
5907c478bd9Sstevel@tonic-gate     /* get the path to the plugins */
5917c478bd9Sstevel@tonic-gate     result = ((sasl_getpath_t *)(getpath_cb->proc))(getpath_cb->context,
5927c478bd9Sstevel@tonic-gate 						    &path);
5937c478bd9Sstevel@tonic-gate     if (result != SASL_OK) return result;
5947c478bd9Sstevel@tonic-gate     if (! path) return SASL_FAIL;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate     if (strlen(path) >= PATH_MAX) { /* no you can't buffer overrun */
5977c478bd9Sstevel@tonic-gate 	return SASL_FAIL;
5987c478bd9Sstevel@tonic-gate     }
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate     position=0;
6017c478bd9Sstevel@tonic-gate     do {
6027c478bd9Sstevel@tonic-gate 	pos=0;
6037c478bd9Sstevel@tonic-gate 	do {
6047c478bd9Sstevel@tonic-gate 	    c=path[position];
6057c478bd9Sstevel@tonic-gate 	    position++;
6067c478bd9Sstevel@tonic-gate 	    str[pos]=c;
6077c478bd9Sstevel@tonic-gate 	    pos++;
6087c478bd9Sstevel@tonic-gate 	} while ((c!=':') && (c!='=') && (c!=0));
6097c478bd9Sstevel@tonic-gate 	str[pos-1]='\0';
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	strcpy(prefix,str);
6127c478bd9Sstevel@tonic-gate 	strcat(prefix,"/");
6137c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6147c478bd9Sstevel@tonic-gate 	path_info = server ? gctx->splug_path_info : gctx->cplug_path_info;
6157c478bd9Sstevel@tonic-gate 	while (path_info != NULL) {
6167c478bd9Sstevel@tonic-gate 	    if (strcmp(path_info->path, prefix) == 0)
6177c478bd9Sstevel@tonic-gate 		break;
6187c478bd9Sstevel@tonic-gate 	    path_info = path_info->next;
6197c478bd9Sstevel@tonic-gate 	}
6207c478bd9Sstevel@tonic-gate 	if (stat(prefix, &b) != 0) {
6217c478bd9Sstevel@tonic-gate 	    continue;
6227c478bd9Sstevel@tonic-gate 	}
6237c478bd9Sstevel@tonic-gate 	if ( path_info == NULL) {
6247c478bd9Sstevel@tonic-gate 	    p_info = (_sasl_path_info_t *)
6257c478bd9Sstevel@tonic-gate 		sasl_ALLOC(sizeof (_sasl_path_info_t));
6267c478bd9Sstevel@tonic-gate 	    if (p_info == NULL) {
6277c478bd9Sstevel@tonic-gate 		return SASL_NOMEM;
6287c478bd9Sstevel@tonic-gate 	    }
6297c478bd9Sstevel@tonic-gate 	    if(_sasl_strdup(prefix, &p_info->path, NULL) != SASL_OK) {
6307c478bd9Sstevel@tonic-gate 		sasl_FREE(p_info);
6317c478bd9Sstevel@tonic-gate 		return SASL_NOMEM;
6327c478bd9Sstevel@tonic-gate 	    }
6337c478bd9Sstevel@tonic-gate 	    p_info->last_changed = b.st_mtime;
6347c478bd9Sstevel@tonic-gate 	    if (server) {
6357c478bd9Sstevel@tonic-gate 		p_info->next = gctx->splug_path_info;
6367c478bd9Sstevel@tonic-gate 		gctx->splug_path_info = p_info;
6377c478bd9Sstevel@tonic-gate 	    } else {
6387c478bd9Sstevel@tonic-gate 		p_info->next = gctx->cplug_path_info;
6397c478bd9Sstevel@tonic-gate 		gctx->cplug_path_info = p_info;
6407c478bd9Sstevel@tonic-gate 	    }
6417c478bd9Sstevel@tonic-gate 	} else {
6427c478bd9Sstevel@tonic-gate 	    if (b.st_mtime <= path_info->last_changed) {
6437c478bd9Sstevel@tonic-gate 		continue;
6447c478bd9Sstevel@tonic-gate 	    }
6457c478bd9Sstevel@tonic-gate 	}
6467c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	if ((dp=opendir(str)) !=NULL) /* ignore errors */
6497c478bd9Sstevel@tonic-gate 	{
6507c478bd9Sstevel@tonic-gate 	    while ((dir=readdir(dp)) != NULL)
6517c478bd9Sstevel@tonic-gate 	    {
6527c478bd9Sstevel@tonic-gate 		size_t length;
6537c478bd9Sstevel@tonic-gate 		void *library;
6547c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
6557c478bd9Sstevel@tonic-gate 		char *c;
6567c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
6577c478bd9Sstevel@tonic-gate 		char plugname[PATH_MAX];
6587c478bd9Sstevel@tonic-gate 		char name[PATH_MAX];
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 		length = NAMLEN(dir);
6617c478bd9Sstevel@tonic-gate #ifndef _SUN_SDK_
6627c478bd9Sstevel@tonic-gate 		if (length < 4)
6637c478bd9Sstevel@tonic-gate 		    continue; /* can not possibly be what we're looking for */
6647c478bd9Sstevel@tonic-gate #endif /* !_SUN_SDK_ */
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 		if (length + pos>=PATH_MAX) continue; /* too big */
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6697c478bd9Sstevel@tonic-gate 		if (dir->d_name[0] == '.')
6707c478bd9Sstevel@tonic-gate 		    continue;
6717c478bd9Sstevel@tonic-gate #else
6727c478bd9Sstevel@tonic-gate 		if (strcmp(dir->d_name + (length - strlen(SO_SUFFIX)),
6737c478bd9Sstevel@tonic-gate 			   SO_SUFFIX)
6747c478bd9Sstevel@tonic-gate 		    && strcmp(dir->d_name + (length - strlen(LA_SUFFIX)),
6757c478bd9Sstevel@tonic-gate 			   LA_SUFFIX))
6767c478bd9Sstevel@tonic-gate 		    continue;
6777c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 		memcpy(name,dir->d_name,length);
6807c478bd9Sstevel@tonic-gate 		name[length]='\0';
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6837c478bd9Sstevel@tonic-gate 		snprintf(tmp, sizeof (tmp), "%s%s", prefix, name);
6847c478bd9Sstevel@tonic-gate #else
6857c478bd9Sstevel@tonic-gate 		result = _parse_la(prefix, name, tmp);
6867c478bd9Sstevel@tonic-gate 		if(result != SASL_OK)
6877c478bd9Sstevel@tonic-gate 		    continue;
6887c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
6917c478bd9Sstevel@tonic-gate 		if (stat(tmp, &b))
6927c478bd9Sstevel@tonic-gate 			continue;	/* Can't stat it */
6937c478bd9Sstevel@tonic-gate 		if (!S_ISREG(b.st_mode))
6947c478bd9Sstevel@tonic-gate 			continue;
6957c478bd9Sstevel@tonic-gate 		/* Sun plugins don't have lib prefix */
6967c478bd9Sstevel@tonic-gate 		strcpy(plugname, name);
6977c478bd9Sstevel@tonic-gate #else
6987c478bd9Sstevel@tonic-gate 		/* skip "lib" and cut off suffix --
6997c478bd9Sstevel@tonic-gate 		   this only need be approximate */
7007c478bd9Sstevel@tonic-gate 		strcpy(plugname, name + 3);
7017c478bd9Sstevel@tonic-gate 		c = strchr(plugname, (int)'.');
7027c478bd9Sstevel@tonic-gate 		if(c) *c = '\0';
7037c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
7067c478bd9Sstevel@tonic-gate 		result = _sasl_get_plugin(gctx, tmp, verifyfile_cb,
7077c478bd9Sstevel@tonic-gate                         &library);
7087c478bd9Sstevel@tonic-gate #else
7097c478bd9Sstevel@tonic-gate 		result = _sasl_get_plugin(tmp, verifyfile_cb, &library);
7107c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 		if(result != SASL_OK)
7137c478bd9Sstevel@tonic-gate 		    continue;
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
7167c478bd9Sstevel@tonic-gate 		plugin_loaded = 0;
7177c478bd9Sstevel@tonic-gate 		for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) {
7187c478bd9Sstevel@tonic-gate 			/* If this fails, it's not the end of the world */
7197c478bd9Sstevel@tonic-gate 			if (_sasl_plugin_load(gctx, plugname, library,
7207c478bd9Sstevel@tonic-gate 					cur_ep->entryname,
7217c478bd9Sstevel@tonic-gate 					cur_ep->add_plugin) == SASL_OK) {
7227c478bd9Sstevel@tonic-gate 			    plugin_loaded = 1;
7237c478bd9Sstevel@tonic-gate 			}
7247c478bd9Sstevel@tonic-gate 		}
7257c478bd9Sstevel@tonic-gate 		if (!plugin_loaded)
7267c478bd9Sstevel@tonic-gate 			release_plugin(gctx, library);
7277c478bd9Sstevel@tonic-gate #else
7287c478bd9Sstevel@tonic-gate 		for(cur_ep = entrypoints; cur_ep->entryname; cur_ep++) {
7297c478bd9Sstevel@tonic-gate 			_sasl_plugin_load(plugname, library, cur_ep->entryname,
7307c478bd9Sstevel@tonic-gate 					  cur_ep->add_plugin);
7317c478bd9Sstevel@tonic-gate 			/* If this fails, it's not the end of the world */
7327c478bd9Sstevel@tonic-gate 		}
7337c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7347c478bd9Sstevel@tonic-gate 	    }
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	    closedir(dp);
7377c478bd9Sstevel@tonic-gate 	}
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate     } while ((c!='=') && (c!=0));
7407c478bd9Sstevel@tonic-gate #elif defined _SUN_SDK_ && defined WIN_PLUG
7417c478bd9Sstevel@tonic-gate     result =
7427c478bd9Sstevel@tonic-gate 	_sasl_load_win_plugins(gctx, entrypoints, getpath_cb, verifyfile_cb);
7437c478bd9Sstevel@tonic-gate     if (result != SASL_OK)
7447c478bd9Sstevel@tonic-gate 	return (result);
7457c478bd9Sstevel@tonic-gate #endif /* defined(DO_DLOPEN) && (!defined(PIC) || (defined(PIC) && defined(TRY_DLOPEN_WHEN_STATIC))) */
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate     return SASL_OK;
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
7517c478bd9Sstevel@tonic-gate int
_sasl_done_with_plugins(_sasl_global_context_t * gctx)7527c478bd9Sstevel@tonic-gate _sasl_done_with_plugins(_sasl_global_context_t *gctx)
7537c478bd9Sstevel@tonic-gate #else
7547c478bd9Sstevel@tonic-gate int
7557c478bd9Sstevel@tonic-gate _sasl_done_with_plugins(void)
7567c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7577c478bd9Sstevel@tonic-gate {
7587c478bd9Sstevel@tonic-gate #if defined DO_DLOPEN || defined WIN_PLUG /* _SUN_SDK_ */
7597c478bd9Sstevel@tonic-gate     lib_list_t *libptr, *libptr_next;
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
7627c478bd9Sstevel@tonic-gate     if (LOCK_MUTEX(&global_mutex) < 0)
7637c478bd9Sstevel@tonic-gate 	return (SASL_FAIL);
7647c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
7677c478bd9Sstevel@tonic-gate     for(libptr = gctx->lib_list_head; libptr; libptr = libptr_next) {
7687c478bd9Sstevel@tonic-gate #else
7697c478bd9Sstevel@tonic-gate     for(libptr = lib_list_head; libptr; libptr = libptr_next) {
7707c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7717c478bd9Sstevel@tonic-gate 	libptr_next = libptr->next;
7727c478bd9Sstevel@tonic-gate 	if(libptr->library)
7737c478bd9Sstevel@tonic-gate #ifdef DO_DLOPEN /* _SUN_SDK_ */
7747c478bd9Sstevel@tonic-gate 	    dlclose(libptr->library);
7757c478bd9Sstevel@tonic-gate #else
7767c478bd9Sstevel@tonic-gate 	    FreeLibrary(libptr->library);
7777c478bd9Sstevel@tonic-gate #endif /* DO_DLOPEN */ /* _SUN_SDK_ */
7787c478bd9Sstevel@tonic-gate 	sasl_FREE(libptr);
7797c478bd9Sstevel@tonic-gate     }
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
7827c478bd9Sstevel@tonic-gate     gctx->lib_list_head = NULL;
7837c478bd9Sstevel@tonic-gate #else
7847c478bd9Sstevel@tonic-gate     lib_list_head = NULL;
7857c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7867c478bd9Sstevel@tonic-gate 
7877c478bd9Sstevel@tonic-gate #ifdef _SUN_SDK_
7887c478bd9Sstevel@tonic-gate     UNLOCK_MUTEX(&global_mutex);
7897c478bd9Sstevel@tonic-gate #endif /* _SUN_SDK_ */
7907c478bd9Sstevel@tonic-gate #endif /* DO_DLOPEN || WIN_PLUG */ /* _SUN_SDK_ */
7917c478bd9Sstevel@tonic-gate     return SASL_OK;
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate #ifdef WIN_MUTEX
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate static HANDLE global_mutex = NULL;
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate int win_global_mutex_lock()
7997c478bd9Sstevel@tonic-gate {
8007c478bd9Sstevel@tonic-gate     DWORD dwWaitResult;
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate     if (global_mutex == NULL) {
8037c478bd9Sstevel@tonic-gate 	global_mutex = CreateMutex(NULL, FALSE, NULL);
8047c478bd9Sstevel@tonic-gate 	if (global_mutex == NULL)
8057c478bd9Sstevel@tonic-gate 	    return (-1);
8067c478bd9Sstevel@tonic-gate     }
8077c478bd9Sstevel@tonic-gate 
8087c478bd9Sstevel@tonic-gate     dwWaitResult = WaitForSingleObject(global_mutex, INFINITE);
8097c478bd9Sstevel@tonic-gate 
8107c478bd9Sstevel@tonic-gate     switch (dwWaitResult) {
8117c478bd9Sstevel@tonic-gate 	case WAIT_OBJECT_0:
8127c478bd9Sstevel@tonic-gate 		return (0);
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate            case WAIT_TIMEOUT:
8157c478bd9Sstevel@tonic-gate                return (-1); /* Shouldn't happen */
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate            case WAIT_ABANDONED:
8187c478bd9Sstevel@tonic-gate                return (-1); /* Shouldn't happen */
8197c478bd9Sstevel@tonic-gate     }
8207c478bd9Sstevel@tonic-gate     return (-1); /* Unexpected result */
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate int win_global_mutex_unlock()
8247c478bd9Sstevel@tonic-gate {
8257c478bd9Sstevel@tonic-gate     if (global_mutex == NULL)
8267c478bd9Sstevel@tonic-gate 	return (-1);
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate     return (ReleaseMutex(global_mutex) ? 0 : -1);
8297c478bd9Sstevel@tonic-gate }
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate BOOL APIENTRY DllMain(HANDLE hModule,
8327c478bd9Sstevel@tonic-gate                          DWORD  ul_reason_for_call,
8337c478bd9Sstevel@tonic-gate                          LPVOID lpReserved)
8347c478bd9Sstevel@tonic-gate {
8357c478bd9Sstevel@tonic-gate     switch( ul_reason_for_call ) {
8367c478bd9Sstevel@tonic-gate 	case DLL_PROCESS_ATTACH:
8377c478bd9Sstevel@tonic-gate 	    global_mutex = CreateMutex(NULL, FALSE, NULL);
8387c478bd9Sstevel@tonic-gate 	    if (global_mutex == NULL)
8397c478bd9Sstevel@tonic-gate 		return (FALSE);
8407c478bd9Sstevel@tonic-gate 	    break;
8417c478bd9Sstevel@tonic-gate 	case DLL_THREAD_ATTACH:
8427c478bd9Sstevel@tonic-gate 	case DLL_THREAD_DETACH:
8437c478bd9Sstevel@tonic-gate 	case DLL_PROCESS_DETACH:
8447c478bd9Sstevel@tonic-gate 	    break;
8457c478bd9Sstevel@tonic-gate     }
8467c478bd9Sstevel@tonic-gate     return TRUE;
8477c478bd9Sstevel@tonic-gate }
8487c478bd9Sstevel@tonic-gate #endif
849