blob: bea8776d71b83bc2afd8b559ea1a464ddf9c2fbb [file] [log] [blame]
Matt Caswell0f113f32015-01-22 03:40:55 +00001/*
Rich Salzd2e9e322016-05-17 14:51:26 -04002 * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
Geoff Thorpe8f4fac72000-04-04 21:57:11 +00003 *
Rich Salzd2e9e322016-05-17 14:51:26 -04004 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
Geoff Thorpe8f4fac72000-04-04 21:57:11 +00008 */
9
Rich Salz73decf52016-03-22 13:16:54 -040010#include "dso_locl.h"
Geoff Thorpe8f4fac72000-04-04 21:57:11 +000011
12static DSO_METHOD *default_DSO_meth = NULL;
13
Rich Salz3d8b2ec2016-03-22 14:33:00 -040014static DSO *DSO_new_method(DSO_METHOD *meth)
Matt Caswell0f113f32015-01-22 03:40:55 +000015{
16 DSO *ret;
Geoff Thorpe8f4fac72000-04-04 21:57:11 +000017
Rich Salzb196e7d2015-04-28 15:28:14 -040018 if (default_DSO_meth == NULL) {
Matt Caswell0f113f32015-01-22 03:40:55 +000019 /*
20 * We default to DSO_METH_openssl() which in turn defaults to
21 * stealing the "best available" method. Will fallback to
22 * DSO_METH_null() in the worst case.
23 */
24 default_DSO_meth = DSO_METHOD_openssl();
Rich Salzb196e7d2015-04-28 15:28:14 -040025 }
Rich Salzb51bce92015-08-25 13:25:58 -040026 ret = OPENSSL_zalloc(sizeof(*ret));
Matt Caswell0f113f32015-01-22 03:40:55 +000027 if (ret == NULL) {
28 DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
29 return (NULL);
30 }
Matt Caswell0f113f32015-01-22 03:40:55 +000031 ret->meth_data = sk_void_new_null();
32 if (ret->meth_data == NULL) {
33 /* sk_new doesn't generate any errors so we do */
34 DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
35 OPENSSL_free(ret);
36 return (NULL);
37 }
Rich Salz3d8b2ec2016-03-22 14:33:00 -040038 ret->meth = default_DSO_meth;
Matt Caswell0f113f32015-01-22 03:40:55 +000039 ret->references = 1;
Alessandro Ghedinic74471d2016-03-04 16:04:37 +000040 ret->lock = CRYPTO_THREAD_lock_new();
41 if (ret->lock == NULL) {
FdaSilvaYYb2b361f2016-04-30 16:23:33 +020042 DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
FdaSilvaYY98637bd2016-01-21 23:10:29 +010043 sk_void_free(ret->meth_data);
Matt Caswell0f113f32015-01-22 03:40:55 +000044 OPENSSL_free(ret);
Alessandro Ghedinic74471d2016-03-04 16:04:37 +000045 return NULL;
46 }
47
48 if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
49 DSO_free(ret);
Matt Caswell0f113f32015-01-22 03:40:55 +000050 ret = NULL;
51 }
Alessandro Ghedinic74471d2016-03-04 16:04:37 +000052
53 return ret;
Matt Caswell0f113f32015-01-22 03:40:55 +000054}
Geoff Thorpe8f4fac72000-04-04 21:57:11 +000055
Rich Salz3d8b2ec2016-03-22 14:33:00 -040056DSO *DSO_new(void)
57{
58 return DSO_new_method(NULL);
59}
60
Geoff Thorpe8f4fac72000-04-04 21:57:11 +000061int DSO_free(DSO *dso)
Matt Caswell0f113f32015-01-22 03:40:55 +000062{
63 int i;
64
Rich Salzefa7dd62015-05-01 10:15:18 -040065 if (dso == NULL)
66 return (1);
Matt Caswell0f113f32015-01-22 03:40:55 +000067
Alessandro Ghedinic74471d2016-03-04 16:04:37 +000068 if (CRYPTO_atomic_add(&dso->references, -1, &i, dso->lock) <= 0)
69 return 0;
70
Rich Salzf3f1cf82016-01-30 12:04:25 -050071 REF_PRINT_COUNT("DSO", dso);
Matt Caswell0f113f32015-01-22 03:40:55 +000072 if (i > 0)
Alessandro Ghedinic74471d2016-03-04 16:04:37 +000073 return 1;
Rich Salzf3f1cf82016-01-30 12:04:25 -050074 REF_ASSERT_ISNT(i < 0);
Geoff Thorpe8f4fac72000-04-04 21:57:11 +000075
Matt Caswell0f113f32015-01-22 03:40:55 +000076 if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
77 DSOerr(DSO_F_DSO_FREE, DSO_R_UNLOAD_FAILED);
Alessandro Ghedinic74471d2016-03-04 16:04:37 +000078 return 0;
Matt Caswell0f113f32015-01-22 03:40:55 +000079 }
80
81 if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
82 DSOerr(DSO_F_DSO_FREE, DSO_R_FINISH_FAILED);
Alessandro Ghedinic74471d2016-03-04 16:04:37 +000083 return 0;
Matt Caswell0f113f32015-01-22 03:40:55 +000084 }
85
86 sk_void_free(dso->meth_data);
Rich Salzb548a1f2015-05-01 10:02:07 -040087 OPENSSL_free(dso->filename);
88 OPENSSL_free(dso->loaded_filename);
Alessandro Ghedinic74471d2016-03-04 16:04:37 +000089 CRYPTO_THREAD_lock_free(dso->lock);
Matt Caswell0f113f32015-01-22 03:40:55 +000090 OPENSSL_free(dso);
Alessandro Ghedinic74471d2016-03-04 16:04:37 +000091 return 1;
Matt Caswell0f113f32015-01-22 03:40:55 +000092}
Geoff Thorpe8f4fac72000-04-04 21:57:11 +000093
94int DSO_flags(DSO *dso)
Matt Caswell0f113f32015-01-22 03:40:55 +000095{
96 return ((dso == NULL) ? 0 : dso->flags);
97}
Geoff Thorpe8f4fac72000-04-04 21:57:11 +000098
Geoff Thorped9ff8892001-09-04 20:40:41 +000099int DSO_up_ref(DSO *dso)
Matt Caswell0f113f32015-01-22 03:40:55 +0000100{
Alessandro Ghedinic74471d2016-03-04 16:04:37 +0000101 int i;
102
Matt Caswell0f113f32015-01-22 03:40:55 +0000103 if (dso == NULL) {
104 DSOerr(DSO_F_DSO_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
Alessandro Ghedinic74471d2016-03-04 16:04:37 +0000105 return 0;
Matt Caswell0f113f32015-01-22 03:40:55 +0000106 }
Geoff Thorpe8f4fac72000-04-04 21:57:11 +0000107
Alessandro Ghedinic74471d2016-03-04 16:04:37 +0000108 if (CRYPTO_atomic_add(&dso->references, 1, &i, dso->lock) <= 0)
109 return 0;
110
111 REF_PRINT_COUNT("DSO", r);
112 REF_ASSERT_ISNT(i < 2);
113 return ((i > 1) ? 1 : 0);
Matt Caswell0f113f32015-01-22 03:40:55 +0000114}
Geoff Thorpe8f4fac72000-04-04 21:57:11 +0000115
Geoff Thorpeb9e63912000-04-19 21:45:17 +0000116DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
Matt Caswell0f113f32015-01-22 03:40:55 +0000117{
118 DSO *ret;
119 int allocated = 0;
Geoff Thorpe8f4fac72000-04-04 21:57:11 +0000120
Matt Caswell0f113f32015-01-22 03:40:55 +0000121 if (dso == NULL) {
122 ret = DSO_new_method(meth);
123 if (ret == NULL) {
124 DSOerr(DSO_F_DSO_LOAD, ERR_R_MALLOC_FAILURE);
125 goto err;
126 }
127 allocated = 1;
128 /* Pass the provided flags to the new DSO object */
129 if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
130 DSOerr(DSO_F_DSO_LOAD, DSO_R_CTRL_FAILED);
131 goto err;
132 }
133 } else
134 ret = dso;
135 /* Don't load if we're currently already loaded */
136 if (ret->filename != NULL) {
137 DSOerr(DSO_F_DSO_LOAD, DSO_R_DSO_ALREADY_LOADED);
138 goto err;
139 }
140 /*
141 * filename can only be NULL if we were passed a dso that already has one
142 * set.
143 */
144 if (filename != NULL)
145 if (!DSO_set_filename(ret, filename)) {
146 DSOerr(DSO_F_DSO_LOAD, DSO_R_SET_FILENAME_FAILED);
147 goto err;
148 }
149 filename = ret->filename;
150 if (filename == NULL) {
151 DSOerr(DSO_F_DSO_LOAD, DSO_R_NO_FILENAME);
152 goto err;
153 }
154 if (ret->meth->dso_load == NULL) {
155 DSOerr(DSO_F_DSO_LOAD, DSO_R_UNSUPPORTED);
156 goto err;
157 }
158 if (!ret->meth->dso_load(ret)) {
159 DSOerr(DSO_F_DSO_LOAD, DSO_R_LOAD_FAILED);
160 goto err;
161 }
162 /* Load succeeded */
163 return (ret);
164 err:
165 if (allocated)
166 DSO_free(ret);
167 return (NULL);
168}
Geoff Thorpe8f4fac72000-04-04 21:57:11 +0000169
Geoff Thorpee9a68cf2000-06-16 10:45:36 +0000170DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
Matt Caswell0f113f32015-01-22 03:40:55 +0000171{
172 DSO_FUNC_TYPE ret = NULL;
Geoff Thorpee9a68cf2000-06-16 10:45:36 +0000173
Matt Caswell0f113f32015-01-22 03:40:55 +0000174 if ((dso == NULL) || (symname == NULL)) {
175 DSOerr(DSO_F_DSO_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
176 return (NULL);
177 }
178 if (dso->meth->dso_bind_func == NULL) {
179 DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_UNSUPPORTED);
180 return (NULL);
181 }
182 if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
183 DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_SYM_FAILURE);
184 return (NULL);
185 }
186 /* Success */
187 return (ret);
188}
Geoff Thorpeb9e63912000-04-19 21:45:17 +0000189
Matt Caswell0f113f32015-01-22 03:40:55 +0000190/*
191 * I don't really like these *_ctrl functions very much to be perfectly
192 * honest. For one thing, I think I have to return a negative value for any
193 * error because possible DSO_ctrl() commands may return values such as
194 * "size"s that can legitimately be zero (making the standard
Viktor Dukhovni61986d32015-04-16 01:50:03 -0400195 * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd
Matt Caswell0f113f32015-01-22 03:40:55 +0000196 * times. I'd prefer "output" values to be passed by reference and the return
197 * value as success/failure like usual ... but we conform when we must... :-)
198 */
Geoff Thorpeb9e63912000-04-19 21:45:17 +0000199long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
Matt Caswell0f113f32015-01-22 03:40:55 +0000200{
201 if (dso == NULL) {
202 DSOerr(DSO_F_DSO_CTRL, ERR_R_PASSED_NULL_PARAMETER);
203 return (-1);
204 }
205 /*
206 * We should intercept certain generic commands and only pass control to
207 * the method-specific ctrl() function if it's something we don't handle.
208 */
209 switch (cmd) {
210 case DSO_CTRL_GET_FLAGS:
211 return dso->flags;
212 case DSO_CTRL_SET_FLAGS:
213 dso->flags = (int)larg;
214 return (0);
215 case DSO_CTRL_OR_FLAGS:
216 dso->flags |= (int)larg;
217 return (0);
218 default:
219 break;
220 }
221 if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
222 DSOerr(DSO_F_DSO_CTRL, DSO_R_UNSUPPORTED);
223 return (-1);
224 }
225 return (dso->meth->dso_ctrl(dso, cmd, larg, parg));
226}
Geoff Thorpe51c8dc32000-10-26 17:38:59 +0000227
Geoff Thorpe51c8dc32000-10-26 17:38:59 +0000228const char *DSO_get_filename(DSO *dso)
Matt Caswell0f113f32015-01-22 03:40:55 +0000229{
230 if (dso == NULL) {
231 DSOerr(DSO_F_DSO_GET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
232 return (NULL);
233 }
234 return (dso->filename);
235}
Geoff Thorpe51c8dc32000-10-26 17:38:59 +0000236
237int DSO_set_filename(DSO *dso, const char *filename)
Matt Caswell0f113f32015-01-22 03:40:55 +0000238{
239 char *copied;
Geoff Thorpe51c8dc32000-10-26 17:38:59 +0000240
Matt Caswell0f113f32015-01-22 03:40:55 +0000241 if ((dso == NULL) || (filename == NULL)) {
242 DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
243 return (0);
244 }
245 if (dso->loaded_filename) {
246 DSOerr(DSO_F_DSO_SET_FILENAME, DSO_R_DSO_ALREADY_LOADED);
247 return (0);
248 }
249 /* We'll duplicate filename */
Dmitry-Meedae9832016-02-29 11:55:13 +0300250 copied = OPENSSL_strdup(filename);
Matt Caswell0f113f32015-01-22 03:40:55 +0000251 if (copied == NULL) {
252 DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_MALLOC_FAILURE);
253 return (0);
254 }
Rich Salzb548a1f2015-05-01 10:02:07 -0400255 OPENSSL_free(dso->filename);
Matt Caswell0f113f32015-01-22 03:40:55 +0000256 dso->filename = copied;
257 return (1);
258}
Geoff Thorpe51c8dc32000-10-26 17:38:59 +0000259
Richard Levittecbecb3a2002-07-15 15:35:40 +0000260char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
Matt Caswell0f113f32015-01-22 03:40:55 +0000261{
262 char *result = NULL;
Richard Levittecbecb3a2002-07-15 15:35:40 +0000263
Matt Caswell0f113f32015-01-22 03:40:55 +0000264 if (dso == NULL || filespec1 == NULL) {
265 DSOerr(DSO_F_DSO_MERGE, ERR_R_PASSED_NULL_PARAMETER);
266 return (NULL);
267 }
268 if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
269 if (dso->merger != NULL)
270 result = dso->merger(dso, filespec1, filespec2);
271 else if (dso->meth->dso_merger != NULL)
272 result = dso->meth->dso_merger(dso, filespec1, filespec2);
273 }
274 return (result);
275}
Richard Levittecbecb3a2002-07-15 15:35:40 +0000276
Geoff Thorpe51c8dc32000-10-26 17:38:59 +0000277char *DSO_convert_filename(DSO *dso, const char *filename)
Matt Caswell0f113f32015-01-22 03:40:55 +0000278{
279 char *result = NULL;
Geoff Thorpe51c8dc32000-10-26 17:38:59 +0000280
Matt Caswell0f113f32015-01-22 03:40:55 +0000281 if (dso == NULL) {
282 DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
283 return (NULL);
284 }
285 if (filename == NULL)
286 filename = dso->filename;
287 if (filename == NULL) {
288 DSOerr(DSO_F_DSO_CONVERT_FILENAME, DSO_R_NO_FILENAME);
289 return (NULL);
290 }
291 if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
292 if (dso->name_converter != NULL)
293 result = dso->name_converter(dso, filename);
294 else if (dso->meth->dso_name_converter != NULL)
295 result = dso->meth->dso_name_converter(dso, filename);
296 }
297 if (result == NULL) {
Dmitry-Meedae9832016-02-29 11:55:13 +0300298 result = OPENSSL_strdup(filename);
Matt Caswell0f113f32015-01-22 03:40:55 +0000299 if (result == NULL) {
300 DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_MALLOC_FAILURE);
301 return (NULL);
302 }
Matt Caswell0f113f32015-01-22 03:40:55 +0000303 }
304 return (result);
305}
Geoff Thorpe51c8dc32000-10-26 17:38:59 +0000306
Andy Polyakovc6cb42e2006-01-02 08:59:20 +0000307void *DSO_global_lookup(const char *name)
Matt Caswell0f113f32015-01-22 03:40:55 +0000308{
309 DSO_METHOD *meth = default_DSO_meth;
310 if (meth == NULL)
311 meth = DSO_METHOD_openssl();
312 if (meth->globallookup == NULL) {
313 DSOerr(DSO_F_DSO_GLOBAL_LOOKUP, DSO_R_UNSUPPORTED);
314 return NULL;
315 }
316 return (*meth->globallookup) (name);
317}