os/ossrv/ssl/libcrypto/src/crypto/dso/dso_lib.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* dso_lib.c -*- mode:C; c-file-style: "eay" -*- */
     2 /* Written by Geoff Thorpe (geoff@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@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@cryptsoft.com).  This product includes software written by Tim
    55  * Hudson (tjh@cryptsoft.com).
    56  *
    57  */
    58  /*
    59  © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
    60  */
    61 
    62 #include <stdio.h>
    63 #include <openssl/crypto.h>
    64 #include "cryptlib.h"
    65 #include <openssl/dso.h>
    66 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
    67 #include "libcrypto_wsd_macros.h"
    68 #include "libcrypto_wsd.h"
    69 #endif
    70 #ifndef EMULATOR
    71 static DSO_METHOD *default_DSO_meth = NULL;
    72 #else
    73 GET_STATIC_VAR_FROM_TLS(default_DSO_meth,dso_lib,DSO_METHOD *)
    74 #define default_DSO_meth (*GET_WSD_VAR_NAME(default_DSO_meth,dso_lib, s)())
    75 #endif
    76 
    77 EXPORT_C DSO *DSO_new(void)
    78 	{
    79 	return(DSO_new_method(NULL));
    80 	}
    81 
    82 EXPORT_C void DSO_set_default_method(DSO_METHOD *meth)
    83 	{
    84 	default_DSO_meth = meth;
    85 	}
    86 
    87 EXPORT_C DSO_METHOD *DSO_get_default_method(void)
    88 	{
    89 	return(default_DSO_meth);
    90 	}
    91 
    92 EXPORT_C DSO_METHOD *DSO_get_method(DSO *dso)
    93 	{
    94 	return(dso->meth);
    95 	}
    96 
    97 EXPORT_C DSO_METHOD *DSO_set_method(DSO *dso, DSO_METHOD *meth)
    98 	{
    99 	DSO_METHOD *mtmp;
   100 	mtmp = dso->meth;
   101 	dso->meth = meth;
   102 	return(mtmp);
   103 	}
   104 
   105 EXPORT_C DSO *DSO_new_method(DSO_METHOD *meth)
   106 	{
   107 	DSO *ret;
   108 
   109 	if(default_DSO_meth == NULL)
   110 		/* We default to DSO_METH_openssl() which in turn defaults
   111 		 * to stealing the "best available" method. Will fallback
   112 		 * to DSO_METH_null() in the worst case. */
   113 		default_DSO_meth = DSO_METHOD_openssl();
   114 	ret = (DSO *)OPENSSL_malloc(sizeof(DSO));
   115 	if(ret == NULL)
   116 		{
   117 		DSOerr(DSO_F_DSO_NEW_METHOD,ERR_R_MALLOC_FAILURE);
   118 		return(NULL);
   119 		}
   120 	memset(ret, 0, sizeof(DSO));
   121 	ret->meth_data = sk_new_null();
   122 	if(ret->meth_data == NULL)
   123 		{
   124 		/* sk_new doesn't generate any errors so we do */
   125 		DSOerr(DSO_F_DSO_NEW_METHOD,ERR_R_MALLOC_FAILURE);
   126 		OPENSSL_free(ret);
   127 		return(NULL);
   128 		}
   129 	if(meth == NULL)
   130 		ret->meth = default_DSO_meth;
   131 	else
   132 		ret->meth = meth;
   133 	ret->references = 1;
   134 	if((ret->meth->init != NULL) && !ret->meth->init(ret))
   135 		{
   136 		OPENSSL_free(ret);
   137 		ret=NULL;
   138 		}
   139 	return(ret);
   140 	}
   141 
   142 EXPORT_C int DSO_free(DSO *dso)
   143 	{
   144         int i;
   145  
   146 	if(dso == NULL)
   147 		{
   148 		DSOerr(DSO_F_DSO_FREE,ERR_R_PASSED_NULL_PARAMETER);
   149 		return(0);
   150 		}
   151  
   152 	i=CRYPTO_add(&dso->references,-1,CRYPTO_LOCK_DSO);
   153 #ifdef REF_PRINT
   154 	REF_PRINT("DSO",dso);
   155 #endif
   156 	if(i > 0) return(1);
   157 #ifdef REF_CHECK
   158 	if(i < 0)
   159 		{
   160 		fprintf(stderr,"DSO_free, bad reference count\n");
   161 		abort();
   162 		}
   163 #endif
   164 
   165 	if((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso))
   166 		{
   167 		DSOerr(DSO_F_DSO_FREE,DSO_R_UNLOAD_FAILED);
   168 		return(0);
   169 		}
   170  
   171 	if((dso->meth->finish != NULL) && !dso->meth->finish(dso))
   172 		{
   173 		DSOerr(DSO_F_DSO_FREE,DSO_R_FINISH_FAILED);
   174 		return(0);
   175 		}
   176 	
   177 	sk_free(dso->meth_data);
   178 	if(dso->filename != NULL)
   179 		OPENSSL_free(dso->filename);
   180 	if(dso->loaded_filename != NULL)
   181 		OPENSSL_free(dso->loaded_filename);
   182  
   183 	OPENSSL_free(dso);
   184 	return(1);
   185 	}
   186 
   187 EXPORT_C int DSO_flags(DSO *dso)
   188 	{
   189 	return((dso == NULL) ? 0 : dso->flags);
   190 	}
   191 
   192 
   193 EXPORT_C int DSO_up_ref(DSO *dso)
   194 	{
   195 	if (dso == NULL)
   196 		{
   197 		DSOerr(DSO_F_DSO_UP_REF,ERR_R_PASSED_NULL_PARAMETER);
   198 		return(0);
   199 		}
   200 
   201 	CRYPTO_add(&dso->references,1,CRYPTO_LOCK_DSO);
   202 	return(1);
   203 	}
   204 
   205 EXPORT_C DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
   206 	{
   207 	DSO *ret;
   208 	int allocated = 0;
   209 
   210 	if(dso == NULL)
   211 		{
   212 		ret = DSO_new_method(meth);
   213 		if(ret == NULL)
   214 			{
   215 			DSOerr(DSO_F_DSO_LOAD,ERR_R_MALLOC_FAILURE);
   216 			goto err;
   217 			}
   218 		allocated = 1;
   219 		/* Pass the provided flags to the new DSO object */
   220 		if(DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0)
   221 			{
   222 			DSOerr(DSO_F_DSO_LOAD,DSO_R_CTRL_FAILED);
   223 			goto err;
   224 			}
   225 		}
   226 	else
   227 		ret = dso;
   228 	/* Don't load if we're currently already loaded */
   229 	if(ret->filename != NULL)
   230 		{
   231 		DSOerr(DSO_F_DSO_LOAD,DSO_R_DSO_ALREADY_LOADED);
   232 		goto err;
   233 		}
   234 	/* filename can only be NULL if we were passed a dso that already has
   235 	 * one set. */
   236 	if(filename != NULL)
   237 		if(!DSO_set_filename(ret, filename))
   238 			{
   239 			DSOerr(DSO_F_DSO_LOAD,DSO_R_SET_FILENAME_FAILED);
   240 			goto err;
   241 			}
   242 	filename = ret->filename;
   243 	if(filename == NULL)
   244 		{
   245 		DSOerr(DSO_F_DSO_LOAD,DSO_R_NO_FILENAME);
   246 		goto err;
   247 		}
   248 	if(ret->meth->dso_load == NULL)
   249 		{
   250 		DSOerr(DSO_F_DSO_LOAD,DSO_R_UNSUPPORTED);
   251 		goto err;
   252 		}
   253 	if(!ret->meth->dso_load(ret))
   254 		{
   255 		DSOerr(DSO_F_DSO_LOAD,DSO_R_LOAD_FAILED);
   256 		goto err;
   257 		}
   258 	/* Load succeeded */
   259 	return(ret);
   260 err:
   261 	if(allocated)
   262 		DSO_free(ret);
   263 	return(NULL);
   264 	}
   265 
   266 EXPORT_C void *DSO_bind_var(DSO *dso, const char *symname)
   267 	{
   268 	void *ret = NULL;
   269 
   270 	if((dso == NULL) || (symname == NULL))
   271 		{
   272 		DSOerr(DSO_F_DSO_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER);
   273 		return(NULL);
   274 		}
   275 	if(dso->meth->dso_bind_var == NULL)
   276 		{
   277 		DSOerr(DSO_F_DSO_BIND_VAR,DSO_R_UNSUPPORTED);
   278 		return(NULL);
   279 		}
   280 	if((ret = dso->meth->dso_bind_var(dso, symname)) == NULL)
   281 		{
   282 		DSOerr(DSO_F_DSO_BIND_VAR,DSO_R_SYM_FAILURE);
   283 		return(NULL);
   284 		}
   285 	/* Success */
   286 	return(ret);
   287 	}
   288 
   289 EXPORT_C DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
   290 	{
   291 	DSO_FUNC_TYPE ret = NULL;
   292 
   293 	if((dso == NULL) || (symname == NULL))
   294 		{
   295 		DSOerr(DSO_F_DSO_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER);
   296 		return(NULL);
   297 		}
   298 	if(dso->meth->dso_bind_func == NULL)
   299 		{
   300 		DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_UNSUPPORTED);
   301 		return(NULL);
   302 		}
   303 	if((ret = dso->meth->dso_bind_func(dso, symname)) == NULL)
   304 		{
   305 		DSOerr(DSO_F_DSO_BIND_FUNC,DSO_R_SYM_FAILURE);
   306 		return(NULL);
   307 		}
   308 	/* Success */
   309 	return(ret);
   310 	}
   311 
   312 /* I don't really like these *_ctrl functions very much to be perfectly
   313  * honest. For one thing, I think I have to return a negative value for
   314  * any error because possible DSO_ctrl() commands may return values
   315  * such as "size"s that can legitimately be zero (making the standard
   316  * "if(DSO_cmd(...))" form that works almost everywhere else fail at
   317  * odd times. I'd prefer "output" values to be passed by reference and
   318  * the return value as success/failure like usual ... but we conform
   319  * when we must... :-) */
   320 EXPORT_C long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
   321 	{
   322 	if(dso == NULL)
   323 		{
   324 		DSOerr(DSO_F_DSO_CTRL,ERR_R_PASSED_NULL_PARAMETER);
   325 		return(-1);
   326 		}
   327 	/* We should intercept certain generic commands and only pass control
   328 	 * to the method-specific ctrl() function if it's something we don't
   329 	 * handle. */
   330 	switch(cmd)
   331 		{
   332 	case DSO_CTRL_GET_FLAGS:
   333 		return dso->flags;
   334 	case DSO_CTRL_SET_FLAGS:
   335 		dso->flags = (int)larg;
   336 		return(0);
   337 	case DSO_CTRL_OR_FLAGS:
   338 		dso->flags |= (int)larg;
   339 		return(0);
   340 	default:
   341 		break;
   342 		}
   343 	if((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL))
   344 		{
   345 		DSOerr(DSO_F_DSO_CTRL,DSO_R_UNSUPPORTED);
   346 		return(-1);
   347 		}
   348 	return(dso->meth->dso_ctrl(dso,cmd,larg,parg));
   349 	}
   350 
   351 EXPORT_C int DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb,
   352 			DSO_NAME_CONVERTER_FUNC *oldcb)
   353 	{
   354 	if(dso == NULL)
   355 		{
   356 		DSOerr(DSO_F_DSO_SET_NAME_CONVERTER,
   357 				ERR_R_PASSED_NULL_PARAMETER);
   358 		return(0);
   359 		}
   360 	if(oldcb)
   361 		*oldcb = dso->name_converter;
   362 	dso->name_converter = cb;
   363 	return(1);
   364 	}
   365 
   366 EXPORT_C const char *DSO_get_filename(DSO *dso)
   367 	{
   368 	if(dso == NULL)
   369 		{
   370 		DSOerr(DSO_F_DSO_GET_FILENAME,ERR_R_PASSED_NULL_PARAMETER);
   371 		return(NULL);
   372 		}
   373 	return(dso->filename);
   374 	}
   375 
   376 EXPORT_C int DSO_set_filename(DSO *dso, const char *filename)
   377 	{
   378 	char *copied;
   379 
   380 	if((dso == NULL) || (filename == NULL))
   381 		{
   382 		DSOerr(DSO_F_DSO_SET_FILENAME,ERR_R_PASSED_NULL_PARAMETER);
   383 		return(0);
   384 		}
   385 	if(dso->loaded_filename)
   386 		{
   387 		DSOerr(DSO_F_DSO_SET_FILENAME,DSO_R_DSO_ALREADY_LOADED);
   388 		return(0);
   389 		}
   390 	/* We'll duplicate filename */
   391 	copied = OPENSSL_malloc(strlen(filename) + 1);
   392 	if(copied == NULL)
   393 		{
   394 		DSOerr(DSO_F_DSO_SET_FILENAME,ERR_R_MALLOC_FAILURE);
   395 		return(0);
   396 		}
   397 	BUF_strlcpy(copied, filename, strlen(filename) + 1);
   398 	if(dso->filename)
   399 		OPENSSL_free(dso->filename);
   400 	dso->filename = copied;
   401 	return(1);
   402 	}
   403 
   404 EXPORT_C char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
   405 	{
   406 	char *result = NULL;
   407 
   408 	if(dso == NULL || filespec1 == NULL)
   409 		{
   410 		DSOerr(DSO_F_DSO_MERGE,ERR_R_PASSED_NULL_PARAMETER);
   411 		return(NULL);
   412 		}
   413 	if(filespec1 == NULL)
   414 		filespec1 = dso->filename;
   415 	if(filespec1 == NULL)
   416 		{
   417 		DSOerr(DSO_F_DSO_MERGE,DSO_R_NO_FILE_SPECIFICATION);
   418 		return(NULL);
   419 		}
   420 	if((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0)
   421 		{
   422 		if(dso->merger != NULL)
   423 			result = dso->merger(dso, filespec1, filespec2);
   424 		else if(dso->meth->dso_merger != NULL)
   425 			result = dso->meth->dso_merger(dso,
   426 				filespec1, filespec2);
   427 		}
   428 	return(result);
   429 	}
   430 
   431 EXPORT_C char *DSO_convert_filename(DSO *dso, const char *filename)
   432 	{
   433 	char *result = NULL;
   434 
   435 	if(dso == NULL)
   436 		{
   437 		DSOerr(DSO_F_DSO_CONVERT_FILENAME,ERR_R_PASSED_NULL_PARAMETER);
   438 		return(NULL);
   439 		}
   440 	if(filename == NULL)
   441 		filename = dso->filename;
   442 	if(filename == NULL)
   443 		{
   444 		DSOerr(DSO_F_DSO_CONVERT_FILENAME,DSO_R_NO_FILENAME);
   445 		return(NULL);
   446 		}
   447 	if((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0)
   448 		{
   449 		if(dso->name_converter != NULL)
   450 			result = dso->name_converter(dso, filename);
   451 		else if(dso->meth->dso_name_converter != NULL)
   452 			result = dso->meth->dso_name_converter(dso, filename);
   453 		}
   454 	if(result == NULL)
   455 		{
   456 		result = OPENSSL_malloc(strlen(filename) + 1);
   457 		if(result == NULL)
   458 			{
   459 			DSOerr(DSO_F_DSO_CONVERT_FILENAME,
   460 					ERR_R_MALLOC_FAILURE);
   461 			return(NULL);
   462 			}
   463 		BUF_strlcpy(result, filename, strlen(filename) + 1);
   464 		}
   465 	return(result);
   466 	}
   467 
   468 EXPORT_C const char *DSO_get_loaded_filename(DSO *dso)
   469 	{
   470 	if(dso == NULL)
   471 		{
   472 		DSOerr(DSO_F_DSO_GET_LOADED_FILENAME,
   473 				ERR_R_PASSED_NULL_PARAMETER);
   474 		return(NULL);
   475 		}
   476 	return(dso->loaded_filename);
   477 	}