a33a8a85bb2124aaa3946e1b774cd9b03c83757d
[openssl.git] / crypto / dso / dso_lib.c
1 /* dso_lib.c -*- mode:C; c-file-style: "eay" -*- */
2 /*
3  * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project
4  * 2000.
5  */
6 /* ====================================================================
7  * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    licensing@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This product includes cryptographic software written by Eric Young
55  * (eay@cryptsoft.com).  This product includes software written by Tim
56  * Hudson (tjh@cryptsoft.com).
57  *
58  */
59
60 #include <stdio.h>
61 #include <openssl/crypto.h>
62 #include "cryptlib.h"
63 #include <openssl/dso.h>
64
65 static DSO_METHOD *default_DSO_meth = NULL;
66
67 DSO *DSO_new(void)
68 {
69     return (DSO_new_method(NULL));
70 }
71
72 void DSO_set_default_method(DSO_METHOD *meth)
73 {
74     default_DSO_meth = meth;
75 }
76
77 DSO_METHOD *DSO_get_default_method(void)
78 {
79     return (default_DSO_meth);
80 }
81
82 DSO_METHOD *DSO_get_method(DSO *dso)
83 {
84     return (dso->meth);
85 }
86
87 DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth)
88 {
89     DSO_METHOD *mtmp;
90     mtmp = dso->meth;
91     dso->meth = meth;
92     return (mtmp);
93 }
94
95 DSO *DSO_new_method(DSO_METHOD *meth)
96 {
97     DSO *ret;
98
99     if (default_DSO_meth == NULL) {
100         /*
101          * We default to DSO_METH_openssl() which in turn defaults to
102          * stealing the "best available" method. Will fallback to
103          * DSO_METH_null() in the worst case.
104          */
105         default_DSO_meth = DSO_METHOD_openssl();
106     }
107     ret = OPENSSL_malloc(sizeof(DSO));
108     if (ret == NULL) {
109         DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
110         return (NULL);
111     }
112     memset(ret, 0, sizeof(DSO));
113     ret->meth_data = sk_void_new_null();
114     if (ret->meth_data == NULL) {
115         /* sk_new doesn't generate any errors so we do */
116         DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
117         OPENSSL_free(ret);
118         return (NULL);
119     }
120     if (meth == NULL)
121         ret->meth = default_DSO_meth;
122     else
123         ret->meth = meth;
124     ret->references = 1;
125     if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
126         OPENSSL_free(ret);
127         ret = NULL;
128     }
129     return (ret);
130 }
131
132 int DSO_free(DSO *dso)
133 {
134     int i;
135
136     if (dso == NULL) {
137         DSOerr(DSO_F_DSO_FREE, ERR_R_PASSED_NULL_PARAMETER);
138         return (0);
139     }
140
141     i = CRYPTO_add(&dso->references, -1, CRYPTO_LOCK_DSO);
142 #ifdef REF_PRINT
143     REF_PRINT("DSO", dso);
144 #endif
145     if (i > 0)
146         return (1);
147 #ifdef REF_CHECK
148     if (i < 0) {
149         fprintf(stderr, "DSO_free, bad reference count\n");
150         abort();
151     }
152 #endif
153
154     if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
155         DSOerr(DSO_F_DSO_FREE, DSO_R_UNLOAD_FAILED);
156         return (0);
157     }
158
159     if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
160         DSOerr(DSO_F_DSO_FREE, DSO_R_FINISH_FAILED);
161         return (0);
162     }
163
164     sk_void_free(dso->meth_data);
165     OPENSSL_free(dso->filename);
166     OPENSSL_free(dso->loaded_filename);
167     OPENSSL_free(dso);
168     return (1);
169 }
170
171 int DSO_flags(DSO *dso)
172 {
173     return ((dso == NULL) ? 0 : dso->flags);
174 }
175
176 int DSO_up_ref(DSO *dso)
177 {
178     if (dso == NULL) {
179         DSOerr(DSO_F_DSO_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
180         return (0);
181     }
182
183     CRYPTO_add(&dso->references, 1, CRYPTO_LOCK_DSO);
184     return (1);
185 }
186
187 DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
188 {
189     DSO *ret;
190     int allocated = 0;
191
192     if (dso == NULL) {
193         ret = DSO_new_method(meth);
194         if (ret == NULL) {
195             DSOerr(DSO_F_DSO_LOAD, ERR_R_MALLOC_FAILURE);
196             goto err;
197         }
198         allocated = 1;
199         /* Pass the provided flags to the new DSO object */
200         if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
201             DSOerr(DSO_F_DSO_LOAD, DSO_R_CTRL_FAILED);
202             goto err;
203         }
204     } else
205         ret = dso;
206     /* Don't load if we're currently already loaded */
207     if (ret->filename != NULL) {
208         DSOerr(DSO_F_DSO_LOAD, DSO_R_DSO_ALREADY_LOADED);
209         goto err;
210     }
211     /*
212      * filename can only be NULL if we were passed a dso that already has one
213      * set.
214      */
215     if (filename != NULL)
216         if (!DSO_set_filename(ret, filename)) {
217             DSOerr(DSO_F_DSO_LOAD, DSO_R_SET_FILENAME_FAILED);
218             goto err;
219         }
220     filename = ret->filename;
221     if (filename == NULL) {
222         DSOerr(DSO_F_DSO_LOAD, DSO_R_NO_FILENAME);
223         goto err;
224     }
225     if (ret->meth->dso_load == NULL) {
226         DSOerr(DSO_F_DSO_LOAD, DSO_R_UNSUPPORTED);
227         goto err;
228     }
229     if (!ret->meth->dso_load(ret)) {
230         DSOerr(DSO_F_DSO_LOAD, DSO_R_LOAD_FAILED);
231         goto err;
232     }
233     /* Load succeeded */
234     return (ret);
235  err:
236     if (allocated)
237         DSO_free(ret);
238     return (NULL);
239 }
240
241 void *DSO_bind_var(DSO *dso, const char *symname)
242 {
243     void *ret = NULL;
244
245     if ((dso == NULL) || (symname == NULL)) {
246         DSOerr(DSO_F_DSO_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER);
247         return (NULL);
248     }
249     if (dso->meth->dso_bind_var == NULL) {
250         DSOerr(DSO_F_DSO_BIND_VAR, DSO_R_UNSUPPORTED);
251         return (NULL);
252     }
253     if ((ret = dso->meth->dso_bind_var(dso, symname)) == NULL) {
254         DSOerr(DSO_F_DSO_BIND_VAR, DSO_R_SYM_FAILURE);
255         return (NULL);
256     }
257     /* Success */
258     return (ret);
259 }
260
261 DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
262 {
263     DSO_FUNC_TYPE ret = NULL;
264
265     if ((dso == NULL) || (symname == NULL)) {
266         DSOerr(DSO_F_DSO_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
267         return (NULL);
268     }
269     if (dso->meth->dso_bind_func == NULL) {
270         DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_UNSUPPORTED);
271         return (NULL);
272     }
273     if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
274         DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_SYM_FAILURE);
275         return (NULL);
276     }
277     /* Success */
278     return (ret);
279 }
280
281 /*
282  * I don't really like these *_ctrl functions very much to be perfectly
283  * honest. For one thing, I think I have to return a negative value for any
284  * error because possible DSO_ctrl() commands may return values such as
285  * "size"s that can legitimately be zero (making the standard
286  * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd
287  * times. I'd prefer "output" values to be passed by reference and the return
288  * value as success/failure like usual ... but we conform when we must... :-)
289  */
290 long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
291 {
292     if (dso == NULL) {
293         DSOerr(DSO_F_DSO_CTRL, ERR_R_PASSED_NULL_PARAMETER);
294         return (-1);
295     }
296     /*
297      * We should intercept certain generic commands and only pass control to
298      * the method-specific ctrl() function if it's something we don't handle.
299      */
300     switch (cmd) {
301     case DSO_CTRL_GET_FLAGS:
302         return dso->flags;
303     case DSO_CTRL_SET_FLAGS:
304         dso->flags = (int)larg;
305         return (0);
306     case DSO_CTRL_OR_FLAGS:
307         dso->flags |= (int)larg;
308         return (0);
309     default:
310         break;
311     }
312     if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
313         DSOerr(DSO_F_DSO_CTRL, DSO_R_UNSUPPORTED);
314         return (-1);
315     }
316     return (dso->meth->dso_ctrl(dso, cmd, larg, parg));
317 }
318
319 int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb,
320                            DSO_NAME_CONVERTER_FUNC *oldcb)
321 {
322     if (dso == NULL) {
323         DSOerr(DSO_F_DSO_SET_NAME_CONVERTER, ERR_R_PASSED_NULL_PARAMETER);
324         return (0);
325     }
326     if (oldcb)
327         *oldcb = dso->name_converter;
328     dso->name_converter = cb;
329     return (1);
330 }
331
332 const char *DSO_get_filename(DSO *dso)
333 {
334     if (dso == NULL) {
335         DSOerr(DSO_F_DSO_GET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
336         return (NULL);
337     }
338     return (dso->filename);
339 }
340
341 int DSO_set_filename(DSO *dso, const char *filename)
342 {
343     char *copied;
344
345     if ((dso == NULL) || (filename == NULL)) {
346         DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
347         return (0);
348     }
349     if (dso->loaded_filename) {
350         DSOerr(DSO_F_DSO_SET_FILENAME, DSO_R_DSO_ALREADY_LOADED);
351         return (0);
352     }
353     /* We'll duplicate filename */
354     copied = OPENSSL_malloc(strlen(filename) + 1);
355     if (copied == NULL) {
356         DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_MALLOC_FAILURE);
357         return (0);
358     }
359     BUF_strlcpy(copied, filename, strlen(filename) + 1);
360     OPENSSL_free(dso->filename);
361     dso->filename = copied;
362     return (1);
363 }
364
365 char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
366 {
367     char *result = NULL;
368
369     if (dso == NULL || filespec1 == NULL) {
370         DSOerr(DSO_F_DSO_MERGE, ERR_R_PASSED_NULL_PARAMETER);
371         return (NULL);
372     }
373     if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
374         if (dso->merger != NULL)
375             result = dso->merger(dso, filespec1, filespec2);
376         else if (dso->meth->dso_merger != NULL)
377             result = dso->meth->dso_merger(dso, filespec1, filespec2);
378     }
379     return (result);
380 }
381
382 char *DSO_convert_filename(DSO *dso, const char *filename)
383 {
384     char *result = NULL;
385
386     if (dso == NULL) {
387         DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
388         return (NULL);
389     }
390     if (filename == NULL)
391         filename = dso->filename;
392     if (filename == NULL) {
393         DSOerr(DSO_F_DSO_CONVERT_FILENAME, DSO_R_NO_FILENAME);
394         return (NULL);
395     }
396     if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
397         if (dso->name_converter != NULL)
398             result = dso->name_converter(dso, filename);
399         else if (dso->meth->dso_name_converter != NULL)
400             result = dso->meth->dso_name_converter(dso, filename);
401     }
402     if (result == NULL) {
403         result = OPENSSL_malloc(strlen(filename) + 1);
404         if (result == NULL) {
405             DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_MALLOC_FAILURE);
406             return (NULL);
407         }
408         BUF_strlcpy(result, filename, strlen(filename) + 1);
409     }
410     return (result);
411 }
412
413 const char *DSO_get_loaded_filename(DSO *dso)
414 {
415     if (dso == NULL) {
416         DSOerr(DSO_F_DSO_GET_LOADED_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
417         return (NULL);
418     }
419     return (dso->loaded_filename);
420 }
421
422 int DSO_pathbyaddr(void *addr, char *path, int sz)
423 {
424     DSO_METHOD *meth = default_DSO_meth;
425     if (meth == NULL)
426         meth = DSO_METHOD_openssl();
427     if (meth->pathbyaddr == NULL) {
428         DSOerr(DSO_F_DSO_PATHBYADDR, DSO_R_UNSUPPORTED);
429         return -1;
430     }
431     return (*meth->pathbyaddr) (addr, path, sz);
432 }
433
434 void *DSO_global_lookup(const char *name)
435 {
436     DSO_METHOD *meth = default_DSO_meth;
437     if (meth == NULL)
438         meth = DSO_METHOD_openssl();
439     if (meth->globallookup == NULL) {
440         DSOerr(DSO_F_DSO_GLOBAL_LOOKUP, DSO_R_UNSUPPORTED);
441         return NULL;
442     }
443     return (*meth->globallookup) (name);
444 }