1/* dso_lib.c */ 2/* 3 * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project 4 * 2000. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2000 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing@OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <stdio.h> 61#include <openssl/crypto.h> 62#include "cryptlib.h" 63#include <openssl/dso.h> 64 65static DSO_METHOD *default_DSO_meth = NULL; 66 67DSO *DSO_new(void) 68{ 69 return (DSO_new_method(NULL)); 70} 71 72void DSO_set_default_method(DSO_METHOD *meth) 73{ 74 default_DSO_meth = meth; 75} 76 77DSO_METHOD *DSO_get_default_method(void) 78{ 79 return (default_DSO_meth); 80} 81 82DSO_METHOD *DSO_get_method(DSO *dso) 83{ 84 return (dso->meth); 85} 86 87DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth) 88{ 89 DSO_METHOD *mtmp; 90 mtmp = dso->meth; 91 dso->meth = meth; 92 return (mtmp); 93} 94 95DSO *DSO_new_method(DSO_METHOD *meth) 96{ 97 DSO *ret; 98 99 if (default_DSO_meth == NULL) 100 /* 101 * We default to DSO_METH_openssl() which in turn defaults to 102 * stealing the "best available" method. Will fallback to 103 * DSO_METH_null() in the worst case. 104 */ 105 default_DSO_meth = DSO_METHOD_openssl(); 106 ret = (DSO *)OPENSSL_malloc(sizeof(DSO)); 107 if (ret == NULL) { 108 DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE); 109 return (NULL); 110 } 111 memset(ret, 0, sizeof(DSO)); 112 ret->meth_data = sk_void_new_null(); 113 if (ret->meth_data == NULL) { 114 /* sk_new doesn't generate any errors so we do */ 115 DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE); 116 OPENSSL_free(ret); 117 return (NULL); 118 } 119 if (meth == NULL) 120 ret->meth = default_DSO_meth; 121 else 122 ret->meth = meth; 123 ret->references = 1; 124 if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { 125 sk_void_free(ret->meth_data); 126 OPENSSL_free(ret); 127 ret = NULL; 128 } 129 return (ret); 130} 131 132int DSO_free(DSO *dso) 133{ 134 int i; 135 136 if (dso == NULL) { 137 DSOerr(DSO_F_DSO_FREE, ERR_R_PASSED_NULL_PARAMETER); 138 return (0); 139 } 140 141 i = CRYPTO_add(&dso->references, -1, CRYPTO_LOCK_DSO); 142#ifdef REF_PRINT 143 REF_PRINT("DSO", dso); 144#endif 145 if (i > 0) 146 return (1); 147#ifdef REF_CHECK 148 if (i < 0) { 149 fprintf(stderr, "DSO_free, bad reference count\n"); 150 abort(); 151 } 152#endif 153 154 if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) { 155 DSOerr(DSO_F_DSO_FREE, DSO_R_UNLOAD_FAILED); 156 return (0); 157 } 158 159 if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) { 160 DSOerr(DSO_F_DSO_FREE, DSO_R_FINISH_FAILED); 161 return (0); 162 } 163 164 sk_void_free(dso->meth_data); 165 if (dso->filename != NULL) 166 OPENSSL_free(dso->filename); 167 if (dso->loaded_filename != NULL) 168 OPENSSL_free(dso->loaded_filename); 169 170 OPENSSL_free(dso); 171 return (1); 172} 173 174int DSO_flags(DSO *dso) 175{ 176 return ((dso == NULL) ? 0 : dso->flags); 177} 178 179int DSO_up_ref(DSO *dso) 180{ 181 if (dso == NULL) { 182 DSOerr(DSO_F_DSO_UP_REF, ERR_R_PASSED_NULL_PARAMETER); 183 return (0); 184 } 185 186 CRYPTO_add(&dso->references, 1, CRYPTO_LOCK_DSO); 187 return (1); 188} 189 190DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags) 191{ 192 DSO *ret; 193 int allocated = 0; 194 195 if (dso == NULL) { 196 ret = DSO_new_method(meth); 197 if (ret == NULL) { 198 DSOerr(DSO_F_DSO_LOAD, ERR_R_MALLOC_FAILURE); 199 goto err; 200 } 201 allocated = 1; 202 /* Pass the provided flags to the new DSO object */ 203 if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) { 204 DSOerr(DSO_F_DSO_LOAD, DSO_R_CTRL_FAILED); 205 goto err; 206 } 207 } else 208 ret = dso; 209 /* Don't load if we're currently already loaded */ 210 if (ret->filename != NULL) { 211 DSOerr(DSO_F_DSO_LOAD, DSO_R_DSO_ALREADY_LOADED); 212 goto err; 213 } 214 /* 215 * filename can only be NULL if we were passed a dso that already has one 216 * set. 217 */ 218 if (filename != NULL) 219 if (!DSO_set_filename(ret, filename)) { 220 DSOerr(DSO_F_DSO_LOAD, DSO_R_SET_FILENAME_FAILED); 221 goto err; 222 } 223 filename = ret->filename; 224 if (filename == NULL) { 225 DSOerr(DSO_F_DSO_LOAD, DSO_R_NO_FILENAME); 226 goto err; 227 } 228 if (ret->meth->dso_load == NULL) { 229 DSOerr(DSO_F_DSO_LOAD, DSO_R_UNSUPPORTED); 230 goto err; 231 } 232 if (!ret->meth->dso_load(ret)) { 233 DSOerr(DSO_F_DSO_LOAD, DSO_R_LOAD_FAILED); 234 goto err; 235 } 236 /* Load succeeded */ 237 return (ret); 238 err: 239 if (allocated) 240 DSO_free(ret); 241 return (NULL); 242} 243 244void *DSO_bind_var(DSO *dso, const char *symname) 245{ 246 void *ret = NULL; 247 248 if ((dso == NULL) || (symname == NULL)) { 249 DSOerr(DSO_F_DSO_BIND_VAR, ERR_R_PASSED_NULL_PARAMETER); 250 return (NULL); 251 } 252 if (dso->meth->dso_bind_var == NULL) { 253 DSOerr(DSO_F_DSO_BIND_VAR, DSO_R_UNSUPPORTED); 254 return (NULL); 255 } 256 if ((ret = dso->meth->dso_bind_var(dso, symname)) == NULL) { 257 DSOerr(DSO_F_DSO_BIND_VAR, DSO_R_SYM_FAILURE); 258 return (NULL); 259 } 260 /* Success */ 261 return (ret); 262} 263 264DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname) 265{ 266 DSO_FUNC_TYPE ret = NULL; 267 268 if ((dso == NULL) || (symname == NULL)) { 269 DSOerr(DSO_F_DSO_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER); 270 return (NULL); 271 } 272 if (dso->meth->dso_bind_func == NULL) { 273 DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_UNSUPPORTED); 274 return (NULL); 275 } 276 if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) { 277 DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_SYM_FAILURE); 278 return (NULL); 279 } 280 /* Success */ 281 return (ret); 282} 283 284/* 285 * I don't really like these *_ctrl functions very much to be perfectly 286 * honest. For one thing, I think I have to return a negative value for any 287 * error because possible DSO_ctrl() commands may return values such as 288 * "size"s that can legitimately be zero (making the standard 289 * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd 290 * times. I'd prefer "output" values to be passed by reference and the return 291 * value as success/failure like usual ... but we conform when we must... :-) 292 */ 293long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg) 294{ 295 if (dso == NULL) { 296 DSOerr(DSO_F_DSO_CTRL, ERR_R_PASSED_NULL_PARAMETER); 297 return (-1); 298 } 299 /* 300 * We should intercept certain generic commands and only pass control to 301 * the method-specific ctrl() function if it's something we don't handle. 302 */ 303 switch (cmd) { 304 case DSO_CTRL_GET_FLAGS: 305 return dso->flags; 306 case DSO_CTRL_SET_FLAGS: 307 dso->flags = (int)larg; 308 return (0); 309 case DSO_CTRL_OR_FLAGS: 310 dso->flags |= (int)larg; 311 return (0); 312 default: 313 break; 314 } 315 if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) { 316 DSOerr(DSO_F_DSO_CTRL, DSO_R_UNSUPPORTED); 317 return (-1); 318 } 319 return (dso->meth->dso_ctrl(dso, cmd, larg, parg)); 320} 321 322int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb, 323 DSO_NAME_CONVERTER_FUNC *oldcb) 324{ 325 if (dso == NULL) { 326 DSOerr(DSO_F_DSO_SET_NAME_CONVERTER, ERR_R_PASSED_NULL_PARAMETER); 327 return (0); 328 } 329 if (oldcb) 330 *oldcb = dso->name_converter; 331 dso->name_converter = cb; 332 return (1); 333} 334 335const char *DSO_get_filename(DSO *dso) 336{ 337 if (dso == NULL) { 338 DSOerr(DSO_F_DSO_GET_FILENAME, ERR_R_PASSED_NULL_PARAMETER); 339 return (NULL); 340 } 341 return (dso->filename); 342} 343 344int DSO_set_filename(DSO *dso, const char *filename) 345{ 346 char *copied; 347 348 if ((dso == NULL) || (filename == NULL)) { 349 DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_PASSED_NULL_PARAMETER); 350 return (0); 351 } 352 if (dso->loaded_filename) { 353 DSOerr(DSO_F_DSO_SET_FILENAME, DSO_R_DSO_ALREADY_LOADED); 354 return (0); 355 } 356 /* We'll duplicate filename */ 357 copied = OPENSSL_malloc(strlen(filename) + 1); 358 if (copied == NULL) { 359 DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_MALLOC_FAILURE); 360 return (0); 361 } 362 BUF_strlcpy(copied, filename, strlen(filename) + 1); 363 if (dso->filename) 364 OPENSSL_free(dso->filename); 365 dso->filename = copied; 366 return (1); 367} 368 369char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2) 370{ 371 char *result = NULL; 372 373 if (dso == NULL || filespec1 == NULL) { 374 DSOerr(DSO_F_DSO_MERGE, ERR_R_PASSED_NULL_PARAMETER); 375 return (NULL); 376 } 377 if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) { 378 if (dso->merger != NULL) 379 result = dso->merger(dso, filespec1, filespec2); 380 else if (dso->meth->dso_merger != NULL) 381 result = dso->meth->dso_merger(dso, filespec1, filespec2); 382 } 383 return (result); 384} 385 386char *DSO_convert_filename(DSO *dso, const char *filename) 387{ 388 char *result = NULL; 389 390 if (dso == NULL) { 391 DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_PASSED_NULL_PARAMETER); 392 return (NULL); 393 } 394 if (filename == NULL) 395 filename = dso->filename; 396 if (filename == NULL) { 397 DSOerr(DSO_F_DSO_CONVERT_FILENAME, DSO_R_NO_FILENAME); 398 return (NULL); 399 } 400 if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) { 401 if (dso->name_converter != NULL) 402 result = dso->name_converter(dso, filename); 403 else if (dso->meth->dso_name_converter != NULL) 404 result = dso->meth->dso_name_converter(dso, filename); 405 } 406 if (result == NULL) { 407 result = OPENSSL_malloc(strlen(filename) + 1); 408 if (result == NULL) { 409 DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_MALLOC_FAILURE); 410 return (NULL); 411 } 412 BUF_strlcpy(result, filename, strlen(filename) + 1); 413 } 414 return (result); 415} 416 417const char *DSO_get_loaded_filename(DSO *dso) 418{ 419 if (dso == NULL) { 420 DSOerr(DSO_F_DSO_GET_LOADED_FILENAME, ERR_R_PASSED_NULL_PARAMETER); 421 return (NULL); 422 } 423 return (dso->loaded_filename); 424} 425 426int DSO_pathbyaddr(void *addr, char *path, int sz) 427{ 428 DSO_METHOD *meth = default_DSO_meth; 429 if (meth == NULL) 430 meth = DSO_METHOD_openssl(); 431 if (meth->pathbyaddr == NULL) { 432 DSOerr(DSO_F_DSO_PATHBYADDR, DSO_R_UNSUPPORTED); 433 return -1; 434 } 435 return (*meth->pathbyaddr) (addr, path, sz); 436} 437 438void *DSO_global_lookup(const char *name) 439{ 440 DSO_METHOD *meth = default_DSO_meth; 441 if (meth == NULL) 442 meth = DSO_METHOD_openssl(); 443 if (meth->globallookup == NULL) { 444 DSOerr(DSO_F_DSO_GLOBAL_LOOKUP, DSO_R_UNSUPPORTED); 445 return NULL; 446 } 447 return (*meth->globallookup) (name); 448} 449