1 /*
2 * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (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
8 */
9
10 #include "dso_local.h"
11 #include "internal/refcount.h"
12
DSO_new_method(DSO_METHOD * meth)13 static DSO *DSO_new_method(DSO_METHOD *meth)
14 {
15 DSO *ret;
16
17 ret = OPENSSL_zalloc(sizeof(*ret));
18 if (ret == NULL) {
19 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
20 return NULL;
21 }
22 ret->meth_data = sk_void_new_null();
23 if (ret->meth_data == NULL) {
24 /* sk_new doesn't generate any errors so we do */
25 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
26 OPENSSL_free(ret);
27 return NULL;
28 }
29 ret->meth = DSO_METHOD_openssl();
30 ret->references = 1;
31 ret->lock = CRYPTO_THREAD_lock_new();
32 if (ret->lock == NULL) {
33 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
34 sk_void_free(ret->meth_data);
35 OPENSSL_free(ret);
36 return NULL;
37 }
38
39 if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
40 DSO_free(ret);
41 ret = NULL;
42 }
43
44 return ret;
45 }
46
DSO_new(void)47 DSO *DSO_new(void)
48 {
49 return DSO_new_method(NULL);
50 }
51
DSO_free(DSO * dso)52 int DSO_free(DSO *dso)
53 {
54 int i;
55
56 if (dso == NULL)
57 return 1;
58
59 if (CRYPTO_DOWN_REF(&dso->references, &i, dso->lock) <= 0)
60 return 0;
61
62 REF_PRINT_COUNT("DSO", dso);
63 if (i > 0)
64 return 1;
65 REF_ASSERT_ISNT(i < 0);
66
67 if ((dso->flags & DSO_FLAG_NO_UNLOAD_ON_FREE) == 0) {
68 if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
69 ERR_raise(ERR_LIB_DSO, DSO_R_UNLOAD_FAILED);
70 return 0;
71 }
72 }
73
74 if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
75 ERR_raise(ERR_LIB_DSO, DSO_R_FINISH_FAILED);
76 return 0;
77 }
78
79 sk_void_free(dso->meth_data);
80 OPENSSL_free(dso->filename);
81 OPENSSL_free(dso->loaded_filename);
82 CRYPTO_THREAD_lock_free(dso->lock);
83 OPENSSL_free(dso);
84 return 1;
85 }
86
DSO_flags(DSO * dso)87 int DSO_flags(DSO *dso)
88 {
89 return ((dso == NULL) ? 0 : dso->flags);
90 }
91
DSO_up_ref(DSO * dso)92 int DSO_up_ref(DSO *dso)
93 {
94 int i;
95
96 if (dso == NULL) {
97 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
98 return 0;
99 }
100
101 if (CRYPTO_UP_REF(&dso->references, &i, dso->lock) <= 0)
102 return 0;
103
104 REF_PRINT_COUNT("DSO", dso);
105 REF_ASSERT_ISNT(i < 2);
106 return ((i > 1) ? 1 : 0);
107 }
108
DSO_load(DSO * dso,const char * filename,DSO_METHOD * meth,int flags)109 DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
110 {
111 DSO *ret;
112 int allocated = 0;
113
114 if (dso == NULL) {
115 ret = DSO_new_method(meth);
116 if (ret == NULL) {
117 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
118 goto err;
119 }
120 allocated = 1;
121 /* Pass the provided flags to the new DSO object */
122 if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
123 ERR_raise(ERR_LIB_DSO, DSO_R_CTRL_FAILED);
124 goto err;
125 }
126 } else
127 ret = dso;
128 /* Don't load if we're currently already loaded */
129 if (ret->filename != NULL) {
130 ERR_raise(ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED);
131 goto err;
132 }
133 /*
134 * filename can only be NULL if we were passed a dso that already has one
135 * set.
136 */
137 if (filename != NULL)
138 if (!DSO_set_filename(ret, filename)) {
139 ERR_raise(ERR_LIB_DSO, DSO_R_SET_FILENAME_FAILED);
140 goto err;
141 }
142 filename = ret->filename;
143 if (filename == NULL) {
144 ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
145 goto err;
146 }
147 if (ret->meth->dso_load == NULL) {
148 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
149 goto err;
150 }
151 if (!ret->meth->dso_load(ret)) {
152 ERR_raise(ERR_LIB_DSO, DSO_R_LOAD_FAILED);
153 goto err;
154 }
155 /* Load succeeded */
156 return ret;
157 err:
158 if (allocated)
159 DSO_free(ret);
160 return NULL;
161 }
162
DSO_bind_func(DSO * dso,const char * symname)163 DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
164 {
165 DSO_FUNC_TYPE ret = NULL;
166
167 if ((dso == NULL) || (symname == NULL)) {
168 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
169 return NULL;
170 }
171 if (dso->meth->dso_bind_func == NULL) {
172 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
173 return NULL;
174 }
175 if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
176 ERR_raise(ERR_LIB_DSO, DSO_R_SYM_FAILURE);
177 return NULL;
178 }
179 /* Success */
180 return ret;
181 }
182
183 /*
184 * I don't really like these *_ctrl functions very much to be perfectly
185 * honest. For one thing, I think I have to return a negative value for any
186 * error because possible DSO_ctrl() commands may return values such as
187 * "size"s that can legitimately be zero (making the standard
188 * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd
189 * times. I'd prefer "output" values to be passed by reference and the return
190 * value as success/failure like usual ... but we conform when we must... :-)
191 */
DSO_ctrl(DSO * dso,int cmd,long larg,void * parg)192 long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
193 {
194 if (dso == NULL) {
195 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
196 return -1;
197 }
198 /*
199 * We should intercept certain generic commands and only pass control to
200 * the method-specific ctrl() function if it's something we don't handle.
201 */
202 switch (cmd) {
203 case DSO_CTRL_GET_FLAGS:
204 return dso->flags;
205 case DSO_CTRL_SET_FLAGS:
206 dso->flags = (int)larg;
207 return 0;
208 case DSO_CTRL_OR_FLAGS:
209 dso->flags |= (int)larg;
210 return 0;
211 default:
212 break;
213 }
214 if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
215 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
216 return -1;
217 }
218 return dso->meth->dso_ctrl(dso, cmd, larg, parg);
219 }
220
DSO_get_filename(DSO * dso)221 const char *DSO_get_filename(DSO *dso)
222 {
223 if (dso == NULL) {
224 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
225 return NULL;
226 }
227 return dso->filename;
228 }
229
DSO_set_filename(DSO * dso,const char * filename)230 int DSO_set_filename(DSO *dso, const char *filename)
231 {
232 char *copied;
233
234 if ((dso == NULL) || (filename == NULL)) {
235 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
236 return 0;
237 }
238 if (dso->loaded_filename) {
239 ERR_raise(ERR_LIB_DSO, DSO_R_DSO_ALREADY_LOADED);
240 return 0;
241 }
242 /* We'll duplicate filename */
243 copied = OPENSSL_strdup(filename);
244 if (copied == NULL) {
245 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
246 return 0;
247 }
248 OPENSSL_free(dso->filename);
249 dso->filename = copied;
250 return 1;
251 }
252
DSO_merge(DSO * dso,const char * filespec1,const char * filespec2)253 char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
254 {
255 char *result = NULL;
256
257 if (dso == NULL || filespec1 == NULL) {
258 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
259 return NULL;
260 }
261 if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
262 if (dso->merger != NULL)
263 result = dso->merger(dso, filespec1, filespec2);
264 else if (dso->meth->dso_merger != NULL)
265 result = dso->meth->dso_merger(dso, filespec1, filespec2);
266 }
267 return result;
268 }
269
DSO_convert_filename(DSO * dso,const char * filename)270 char *DSO_convert_filename(DSO *dso, const char *filename)
271 {
272 char *result = NULL;
273
274 if (dso == NULL) {
275 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
276 return NULL;
277 }
278 if (filename == NULL)
279 filename = dso->filename;
280 if (filename == NULL) {
281 ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
282 return NULL;
283 }
284 if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
285 if (dso->name_converter != NULL)
286 result = dso->name_converter(dso, filename);
287 else if (dso->meth->dso_name_converter != NULL)
288 result = dso->meth->dso_name_converter(dso, filename);
289 }
290 if (result == NULL) {
291 result = OPENSSL_strdup(filename);
292 if (result == NULL) {
293 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
294 return NULL;
295 }
296 }
297 return result;
298 }
299
DSO_pathbyaddr(void * addr,char * path,int sz)300 int DSO_pathbyaddr(void *addr, char *path, int sz)
301 {
302 DSO_METHOD *meth = DSO_METHOD_openssl();
303
304 if (meth->pathbyaddr == NULL) {
305 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
306 return -1;
307 }
308 return (*meth->pathbyaddr) (addr, path, sz);
309 }
310
DSO_dsobyaddr(void * addr,int flags)311 DSO *DSO_dsobyaddr(void *addr, int flags)
312 {
313 DSO *ret = NULL;
314 char *filename = NULL;
315 int len = DSO_pathbyaddr(addr, NULL, 0);
316
317 if (len < 0)
318 return NULL;
319
320 filename = OPENSSL_malloc(len);
321 if (filename != NULL
322 && DSO_pathbyaddr(addr, filename, len) == len)
323 ret = DSO_load(NULL, filename, NULL, flags);
324
325 OPENSSL_free(filename);
326 return ret;
327 }
328
DSO_global_lookup(const char * name)329 void *DSO_global_lookup(const char *name)
330 {
331 DSO_METHOD *meth = DSO_METHOD_openssl();
332
333 if (meth->globallookup == NULL) {
334 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
335 return NULL;
336 }
337 return (*meth->globallookup) (name);
338 }
339