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