remove malloc casts
[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     if (dso->filename != NULL)
166         OPENSSL_free(dso->filename);
167     if (dso->loaded_filename != NULL)
168         OPENSSL_free(dso->loaded_filename);
169
170     OPENSSL_free(dso);
171     return (1);
172 }
173
174 int DSO_flags(DSO *dso)
175 {
176     return ((dso == NULL) ? 0 : dso->flags);
177 }
178
179 int DSO_up_ref(DSO *dso)
180 {
181     if (dso == NULL) {
182         DSOerr(DSO_F_DSO_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
183         return (0);
184     }
185
186     CRYPTO_add(&dso->references, 1, CRYPTO_LOCK_DSO);
187     return (1);
188 }
189
190 DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
191 {
192     DSO *ret;
193     int allocated = 0;
194
195     if (dso == NULL) {
196         ret = DSO_new_method(meth);
197         if (ret == NULL) {
198             DSOerr(DSO_F_DSO_LOAD, ERR_R_MALLOC_FAILURE);
199             goto err;
200         }
201         allocated = 1;
202         /* Pass the provided flags to the new DSO object */
203         if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
204             DSOerr(DSO_F_DSO_LOAD, DSO_R_CTRL_FAILED);
205             goto err;
206         }
207     } else
208         ret = dso;
209     /* Don't load if we're currently already loaded */
210     if (ret->filename != NULL) {
211         DSOerr(DSO_F_DSO_LOAD, DSO_R_DSO_ALREADY_LOADED);
212         goto err;
213     }
214     /*
215      * filename can only be NULL if we were passed a dso that already has one
216      * set.
217      */
218     if (filename != NULL)
219         if (!DSO_set_filename(ret, filename)) {
220             DSOerr(DSO_F_DSO_LOAD, DSO_R_SET_FILENAME_FAILED);
221             goto err;
222         }
223     filename = ret->filename;
224     if (filename == NULL) {
225         DSOerr(DSO_F_DSO_LOAD, DSO_R_NO_FILENAME);
226         goto err;
227     }
228     if (ret->meth->dso_load == NULL) {
229         DSOerr(DSO_F_DSO_LOAD, DSO_R_UNSUPPORTED);
230         goto err;
231     }
232     if (!ret->meth->dso_load(ret)) {
233         DSOerr(DSO_F_DSO_LOAD, DSO_R_LOAD_FAILED);
234         goto err;
235     }
236     /* Load succeeded */
237     return (ret);
238  err:
239     if (allocated)
240         DSO_free(ret);
241     return (NULL);
242 }
243
244 void *DSO_bind_var(DSO *dso, const char *symname)
245 {
246     void *ret = NULL;
247
248     if ((dso == NULL) || (symname == NULL)) {
249         DSOerr(DSO_F_DSO_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER);
250         return (NULL);
251     }
252     if (dso->meth->dso_bind_var == NULL) {
253         DSOerr(DSO_F_DSO_BIND_VAR, DSO_R_UNSUPPORTED);
254         return (NULL);
255     }
256     if ((ret = dso->meth->dso_bind_var(dso, symname)) == NULL) {
257         DSOerr(DSO_F_DSO_BIND_VAR, DSO_R_SYM_FAILURE);
258         return (NULL);
259     }
260     /* Success */
261     return (ret);
262 }
263
264 DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
265 {
266     DSO_FUNC_TYPE ret = NULL;
267
268     if ((dso == NULL) || (symname == NULL)) {
269         DSOerr(DSO_F_DSO_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
270         return (NULL);
271     }
272     if (dso->meth->dso_bind_func == NULL) {
273         DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_UNSUPPORTED);
274         return (NULL);
275     }
276     if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
277         DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_SYM_FAILURE);
278         return (NULL);
279     }
280     /* Success */
281     return (ret);
282 }
283
284 /*
285  * I don't really like these *_ctrl functions very much to be perfectly
286  * honest. For one thing, I think I have to return a negative value for any
287  * error because possible DSO_ctrl() commands may return values such as
288  * "size"s that can legitimately be zero (making the standard
289  * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd
290  * times. I'd prefer "output" values to be passed by reference and the return
291  * value as success/failure like usual ... but we conform when we must... :-)
292  */
293 long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
294 {
295     if (dso == NULL) {
296         DSOerr(DSO_F_DSO_CTRL, ERR_R_PASSED_NULL_PARAMETER);
297         return (-1);
298     }
299     /*
300      * We should intercept certain generic commands and only pass control to
301      * the method-specific ctrl() function if it's something we don't handle.
302      */
303     switch (cmd) {
304     case DSO_CTRL_GET_FLAGS:
305         return dso->flags;
306     case DSO_CTRL_SET_FLAGS:
307         dso->flags = (int)larg;
308         return (0);
309     case DSO_CTRL_OR_FLAGS:
310         dso->flags |= (int)larg;
311         return (0);
312     default:
313         break;
314     }
315     if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
316         DSOerr(DSO_F_DSO_CTRL, DSO_R_UNSUPPORTED);
317         return (-1);
318     }
319     return (dso->meth->dso_ctrl(dso, cmd, larg, parg));
320 }
321
322 int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb,
323                            DSO_NAME_CONVERTER_FUNC *oldcb)
324 {
325     if (dso == NULL) {
326         DSOerr(DSO_F_DSO_SET_NAME_CONVERTER, ERR_R_PASSED_NULL_PARAMETER);
327         return (0);
328     }
329     if (oldcb)
330         *oldcb = dso->name_converter;
331     dso->name_converter = cb;
332     return (1);
333 }
334
335 const char *DSO_get_filename(DSO *dso)
336 {
337     if (dso == NULL) {
338         DSOerr(DSO_F_DSO_GET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
339         return (NULL);
340     }
341     return (dso->filename);
342 }
343
344 int DSO_set_filename(DSO *dso, const char *filename)
345 {
346     char *copied;
347
348     if ((dso == NULL) || (filename == NULL)) {
349         DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
350         return (0);
351     }
352     if (dso->loaded_filename) {
353         DSOerr(DSO_F_DSO_SET_FILENAME, DSO_R_DSO_ALREADY_LOADED);
354         return (0);
355     }
356     /* We'll duplicate filename */
357     copied = OPENSSL_malloc(strlen(filename) + 1);
358     if (copied == NULL) {
359         DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_MALLOC_FAILURE);
360         return (0);
361     }
362     BUF_strlcpy(copied, filename, strlen(filename) + 1);
363     if (dso->filename)
364         OPENSSL_free(dso->filename);
365     dso->filename = copied;
366     return (1);
367 }
368
369 char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
370 {
371     char *result = NULL;
372
373     if (dso == NULL || filespec1 == NULL) {
374         DSOerr(DSO_F_DSO_MERGE, ERR_R_PASSED_NULL_PARAMETER);
375         return (NULL);
376     }
377     if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
378         if (dso->merger != NULL)
379             result = dso->merger(dso, filespec1, filespec2);
380         else if (dso->meth->dso_merger != NULL)
381             result = dso->meth->dso_merger(dso, filespec1, filespec2);
382     }
383     return (result);
384 }
385
386 char *DSO_convert_filename(DSO *dso, const char *filename)
387 {
388     char *result = NULL;
389
390     if (dso == NULL) {
391         DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
392         return (NULL);
393     }
394     if (filename == NULL)
395         filename = dso->filename;
396     if (filename == NULL) {
397         DSOerr(DSO_F_DSO_CONVERT_FILENAME, DSO_R_NO_FILENAME);
398         return (NULL);
399     }
400     if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
401         if (dso->name_converter != NULL)
402             result = dso->name_converter(dso, filename);
403         else if (dso->meth->dso_name_converter != NULL)
404             result = dso->meth->dso_name_converter(dso, filename);
405     }
406     if (result == NULL) {
407         result = OPENSSL_malloc(strlen(filename) + 1);
408         if (result == NULL) {
409             DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_MALLOC_FAILURE);
410             return (NULL);
411         }
412         BUF_strlcpy(result, filename, strlen(filename) + 1);
413     }
414     return (result);
415 }
416
417 const char *DSO_get_loaded_filename(DSO *dso)
418 {
419     if (dso == NULL) {
420         DSOerr(DSO_F_DSO_GET_LOADED_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
421         return (NULL);
422     }
423     return (dso->loaded_filename);
424 }
425
426 int DSO_pathbyaddr(void *addr, char *path, int sz)
427 {
428     DSO_METHOD *meth = default_DSO_meth;
429     if (meth == NULL)
430         meth = DSO_METHOD_openssl();
431     if (meth->pathbyaddr == NULL) {
432         DSOerr(DSO_F_DSO_PATHBYADDR, DSO_R_UNSUPPORTED);
433         return -1;
434     }
435     return (*meth->pathbyaddr) (addr, path, sz);
436 }
437
438 void *DSO_global_lookup(const char *name)
439 {
440     DSO_METHOD *meth = default_DSO_meth;
441     if (meth == NULL)
442         meth = DSO_METHOD_openssl();
443     if (meth->globallookup == NULL) {
444         DSOerr(DSO_F_DSO_GLOBAL_LOOKUP, DSO_R_UNSUPPORTED);
445         return NULL;
446     }
447     return (*meth->globallookup) (name);
448 }