No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / lib / krb5 / plugin.c
blob56ab548fe9c65ea835574d645d65ba17ae66750a
1 /*
2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include "krb5_locl.h"
35 __RCSID("$Heimdal: plugin.c 22033 2007-11-10 10:39:47Z lha $"
36 "$NetBSD$");
37 #ifdef HAVE_DLFCN_H
38 #include <dlfcn.h>
39 #endif
40 #include <dirent.h>
42 struct krb5_plugin {
43 void *symbol;
44 void *dsohandle;
45 struct krb5_plugin *next;
48 struct plugin {
49 enum krb5_plugin_type type;
50 void *name;
51 void *symbol;
52 struct plugin *next;
55 static HEIMDAL_MUTEX plugin_mutex = HEIMDAL_MUTEX_INITIALIZER;
56 static struct plugin *registered = NULL;
58 static const char *plugin_dir = LIBDIR "/plugin/krb5";
64 void *
65 _krb5_plugin_get_symbol(struct krb5_plugin *p)
67 return p->symbol;
70 struct krb5_plugin *
71 _krb5_plugin_get_next(struct krb5_plugin *p)
73 return p->next;
80 #ifdef HAVE_DLOPEN
82 static krb5_error_code
83 loadlib(krb5_context context,
84 enum krb5_plugin_type type,
85 const char *name,
86 const char *lib,
87 struct krb5_plugin **e)
89 *e = calloc(1, sizeof(**e));
90 if (*e == NULL) {
91 krb5_set_error_string(context, "out of memory");
92 return ENOMEM;
95 #ifndef RTLD_LAZY
96 #define RTLD_LAZY 0
97 #endif
99 (*e)->dsohandle = dlopen(lib, RTLD_LAZY);
100 if ((*e)->dsohandle == NULL) {
101 free(*e);
102 *e = NULL;
103 krb5_set_error_string(context, "Failed to load %s: %s",
104 lib, dlerror());
105 return ENOMEM;
108 /* dlsym doesn't care about the type */
109 (*e)->symbol = dlsym((*e)->dsohandle, name);
110 if ((*e)->symbol == NULL) {
111 dlclose((*e)->dsohandle);
112 free(*e);
113 krb5_clear_error_string(context);
114 return ENOMEM;
117 return 0;
119 #endif /* HAVE_DLOPEN */
122 * Register a plugin symbol name of specific type.
123 * @param context a Keberos context
124 * @param type type of plugin symbol
125 * @param name name of plugin symbol
126 * @param symbol a pointer to the named symbol
127 * @return In case of error a non zero error com_err error is returned
128 * and the Kerberos error string is set.
130 * @ingroup krb5_support
133 krb5_error_code
134 krb5_plugin_register(krb5_context context,
135 enum krb5_plugin_type type,
136 const char *name,
137 void *symbol)
139 struct plugin *e;
141 e = calloc(1, sizeof(*e));
142 if (e == NULL) {
143 krb5_set_error_string(context, "out of memory");
144 return ENOMEM;
146 e->type = type;
147 e->name = strdup(name);
148 if (e->name == NULL) {
149 free(e);
150 krb5_set_error_string(context, "out of memory");
151 return ENOMEM;
153 e->symbol = symbol;
155 HEIMDAL_MUTEX_lock(&plugin_mutex);
156 e->next = registered;
157 registered = e;
158 HEIMDAL_MUTEX_unlock(&plugin_mutex);
160 return 0;
163 krb5_error_code
164 _krb5_plugin_find(krb5_context context,
165 enum krb5_plugin_type type,
166 const char *name,
167 struct krb5_plugin **list)
169 struct krb5_plugin *e;
170 struct plugin *p;
171 krb5_error_code ret;
172 char *sysdirs[2] = { NULL, NULL };
173 char **dirs = NULL, **di;
174 struct dirent *entry;
175 char *path;
176 DIR *d = NULL;
178 *list = NULL;
180 HEIMDAL_MUTEX_lock(&plugin_mutex);
182 for (p = registered; p != NULL; p = p->next) {
183 if (p->type != type || strcmp(p->name, name) != 0)
184 continue;
186 e = calloc(1, sizeof(*e));
187 if (e == NULL) {
188 HEIMDAL_MUTEX_unlock(&plugin_mutex);
189 krb5_set_error_string(context, "out of memory");
190 ret = ENOMEM;
191 goto out;
193 e->symbol = p->symbol;
194 e->dsohandle = NULL;
195 e->next = *list;
196 *list = e;
198 HEIMDAL_MUTEX_unlock(&plugin_mutex);
200 #ifdef HAVE_DLOPEN
202 dirs = krb5_config_get_strings(context, NULL, "libdefaults",
203 "plugin_dir", NULL);
204 if (dirs == NULL) {
205 sysdirs[0] = rk_UNCONST(plugin_dir);
206 dirs = sysdirs;
209 for (di = dirs; *di != NULL; di++) {
211 d = opendir(*di);
212 if (d == NULL)
213 continue;
215 while ((entry = readdir(d)) != NULL) {
216 asprintf(&path, "%s/%s", *di, entry->d_name);
217 if (path == NULL) {
218 krb5_set_error_string(context, "out of memory");
219 ret = ENOMEM;
220 goto out;
222 ret = loadlib(context, type, name, path, &e);
223 free(path);
224 if (ret)
225 continue;
227 e->next = *list;
228 *list = e;
230 closedir(d);
232 if (dirs != sysdirs)
233 krb5_config_free_strings(dirs);
234 #endif /* HAVE_DLOPEN */
236 if (*list == NULL) {
237 krb5_set_error_string(context, "Did not find a plugin for %s", name);
238 return ENOENT;
241 return 0;
243 out:
244 if (dirs && dirs != sysdirs)
245 krb5_config_free_strings(dirs);
246 if (d)
247 closedir(d);
248 _krb5_plugin_free(*list);
249 *list = NULL;
251 return ret;
254 void
255 _krb5_plugin_free(struct krb5_plugin *list)
257 struct krb5_plugin *next;
258 while (list) {
259 next = list->next;
260 if (list->dsohandle)
261 dlclose(list->dsohandle);
262 free(list);
263 list = next;