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 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 47 DSO *DSO_new(void) 48 { 49 return DSO_new_method(NULL); 50 } 51 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 87 int DSO_flags(DSO *dso) 88 { 89 return ((dso == NULL) ? 0 : dso->flags); 90 } 91 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 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 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 */ 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 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 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 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 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 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 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 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