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