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