os/ossrv/ssl/libcrypto/src/crypto/dso/dso_dl.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* dso_dl.c -*- mode:C; c-file-style: "eay" -*- */
     2 /* Written by Richard Levitte (richard@levitte.org) 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 #include <stdio.h>
    62 #include "cryptlib.h"
    63 #include <openssl/dso.h>
    64 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
    65 #include "libcrypto_wsd_macros.h"
    66 #include "libcrypto_wsd.h"
    67 #endif
    68 
    69 
    70 #ifndef DSO_DL
    71 EXPORT_C DSO_METHOD *DSO_METHOD_dl(void)
    72        {
    73        return NULL;
    74        }
    75 #else
    76 
    77 #include <dl.h>
    78 
    79 /* Part of the hack in "dl_load" ... */
    80 #define DSO_MAX_TRANSLATED_SIZE 256
    81 
    82 static int dl_load(DSO *dso);
    83 static int dl_unload(DSO *dso);
    84 static void *dl_bind_var(DSO *dso, const char *symname);
    85 static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname);
    86 #if 0
    87 static int dl_unbind_var(DSO *dso, char *symname, void *symptr);
    88 static int dl_unbind_func(DSO *dso, char *symname, DSO_FUNC_TYPE symptr);
    89 static int dl_init(DSO *dso);
    90 static int dl_finish(DSO *dso);
    91 static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg);
    92 #endif
    93 static char *dl_name_converter(DSO *dso, const char *filename);
    94 static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2);
    95 
    96 #ifndef EMULATOR
    97 static DSO_METHOD dso_meth_dl = {
    98 	"OpenSSL 'dl' shared library method",
    99 	dl_load,
   100 	dl_unload,
   101 	dl_bind_var,
   102 	dl_bind_func,
   103 /* For now, "unbind" doesn't exist */
   104 #if 0
   105 	NULL, /* unbind_var */
   106 	NULL, /* unbind_func */
   107 #endif
   108 	NULL, /* ctrl */
   109 	dl_name_converter,
   110 	dl_merger,
   111 	NULL, /* init */
   112 	NULL  /* finish */
   113 	};
   114 #else
   115 GET_STATIC_VAR_FROM_TLS(dso_meth_dl,dso_dl,DSO_METHOD)
   116 #define dso_meth_dl (*GET_WSD_VAR_NAME(dso_meth_dl,dso_dl,s)())
   117 const DSO_METHOD temp_s_dso_meth_dl = {
   118 	"OpenSSL 'dl' shared library method",
   119 	dl_load,
   120 	dl_unload,
   121 	dl_bind_var,
   122 	dl_bind_func,
   123 /* For now, "unbind" doesn't exist */
   124 #if 0
   125 	NULL, /* unbind_var */
   126 	NULL, /* unbind_func */
   127 #endif
   128 	NULL, /* ctrl */
   129 	dl_name_converter,
   130 	dl_merger,
   131 	NULL, /* init */
   132 	NULL  /* finish */
   133 	};
   134 #endif
   135 DSO_METHOD *DSO_METHOD_dl(void)
   136 	{
   137 	return(&dso_meth_dl);
   138 	}
   139 
   140 /* For this DSO_METHOD, our meth_data STACK will contain;
   141  * (i) the handle (shl_t) returned from shl_load().
   142  * NB: I checked on HPUX11 and shl_t is itself a pointer
   143  * type so the cast is safe.
   144  */
   145 
   146 static int dl_load(DSO *dso)
   147 	{
   148 	shl_t ptr = NULL;
   149 	/* We don't do any fancy retries or anything, just take the method's
   150 	 * (or DSO's if it has the callback set) best translation of the
   151 	 * platform-independant filename and try once with that. */
   152 	char *filename= DSO_convert_filename(dso, NULL);
   153 
   154 	if(filename == NULL)
   155 		{
   156 		DSOerr(DSO_F_DL_LOAD,DSO_R_NO_FILENAME);
   157 		goto err;
   158 		}
   159 	ptr = shl_load(filename, BIND_IMMEDIATE |
   160 		(dso->flags&DSO_FLAG_NO_NAME_TRANSLATION?0:DYNAMIC_PATH), 0L);
   161 	if(ptr == NULL)
   162 		{
   163 		DSOerr(DSO_F_DL_LOAD,DSO_R_LOAD_FAILED);
   164 		ERR_add_error_data(4, "filename(", filename, "): ",
   165 			strerror(errno));
   166 		goto err;
   167 		}
   168 	if(!sk_push(dso->meth_data, (char *)ptr))
   169 		{
   170 		DSOerr(DSO_F_DL_LOAD,DSO_R_STACK_ERROR);
   171 		goto err;
   172 		}
   173 	/* Success, stick the converted filename we've loaded under into the DSO
   174 	 * (it also serves as the indicator that we are currently loaded). */
   175 	dso->loaded_filename = filename;
   176 	return(1);
   177 err:
   178 	/* Cleanup! */
   179 	if(filename != NULL)
   180 		OPENSSL_free(filename);
   181 	if(ptr != NULL)
   182 		shl_unload(ptr);
   183 	return(0);
   184 	}
   185 
   186 static int dl_unload(DSO *dso)
   187 	{
   188 	shl_t ptr;
   189 	if(dso == NULL)
   190 		{
   191 		DSOerr(DSO_F_DL_UNLOAD,ERR_R_PASSED_NULL_PARAMETER);
   192 		return(0);
   193 		}
   194 	if(sk_num(dso->meth_data) < 1)
   195 		return(1);
   196 	/* Is this statement legal? */
   197 	ptr = (shl_t)sk_pop(dso->meth_data);
   198 	if(ptr == NULL)
   199 		{
   200 		DSOerr(DSO_F_DL_UNLOAD,DSO_R_NULL_HANDLE);
   201 		/* Should push the value back onto the stack in
   202 		 * case of a retry. */
   203 		sk_push(dso->meth_data, (char *)ptr);
   204 		return(0);
   205 		}
   206 	shl_unload(ptr);
   207 	return(1);
   208 	}
   209 
   210 static void *dl_bind_var(DSO *dso, const char *symname)
   211 	{
   212 	shl_t ptr;
   213 	void *sym;
   214 
   215 	if((dso == NULL) || (symname == NULL))
   216 		{
   217 		DSOerr(DSO_F_DL_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER);
   218 		return(NULL);
   219 		}
   220 	if(sk_num(dso->meth_data) < 1)
   221 		{
   222 		DSOerr(DSO_F_DL_BIND_VAR,DSO_R_STACK_ERROR);
   223 		return(NULL);
   224 		}
   225 	ptr = (shl_t)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
   226 	if(ptr == NULL)
   227 		{
   228 		DSOerr(DSO_F_DL_BIND_VAR,DSO_R_NULL_HANDLE);
   229 		return(NULL);
   230 		}
   231 	if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0)
   232 		{
   233 		DSOerr(DSO_F_DL_BIND_VAR,DSO_R_SYM_FAILURE);
   234 		ERR_add_error_data(4, "symname(", symname, "): ",
   235 			strerror(errno));
   236 		return(NULL);
   237 		}
   238 	return(sym);
   239 	}
   240 
   241 static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname)
   242 	{
   243 	shl_t ptr;
   244 	void *sym;
   245 
   246 	if((dso == NULL) || (symname == NULL))
   247 		{
   248 		DSOerr(DSO_F_DL_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER);
   249 		return(NULL);
   250 		}
   251 	if(sk_num(dso->meth_data) < 1)
   252 		{
   253 		DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_STACK_ERROR);
   254 		return(NULL);
   255 		}
   256 	ptr = (shl_t)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
   257 	if(ptr == NULL)
   258 		{
   259 		DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_NULL_HANDLE);
   260 		return(NULL);
   261 		}
   262 	if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0)
   263 		{
   264 		DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_SYM_FAILURE);
   265 		ERR_add_error_data(4, "symname(", symname, "): ",
   266 			strerror(errno));
   267 		return(NULL);
   268 		}
   269 	return((DSO_FUNC_TYPE)sym);
   270 	}
   271 
   272 static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2)
   273 	{
   274 	char *merged;
   275 
   276 	if(!filespec1 && !filespec2)
   277 		{
   278 		DSOerr(DSO_F_DL_MERGER,
   279 				ERR_R_PASSED_NULL_PARAMETER);
   280 		return(NULL);
   281 		}
   282 	/* If the first file specification is a rooted path, it rules.
   283 	   same goes if the second file specification is missing. */
   284 	if (!filespec2 || filespec1[0] == '/')
   285 		{
   286 		merged = OPENSSL_malloc(strlen(filespec1) + 1);
   287 		if(!merged)
   288 			{
   289 			DSOerr(DSO_F_DL_MERGER,
   290 				ERR_R_MALLOC_FAILURE);
   291 			return(NULL);
   292 			}
   293 		strcpy(merged, filespec1);
   294 		}
   295 	/* If the first file specification is missing, the second one rules. */
   296 	else if (!filespec1)
   297 		{
   298 		merged = OPENSSL_malloc(strlen(filespec2) + 1);
   299 		if(!merged)
   300 			{
   301 			DSOerr(DSO_F_DL_MERGER,
   302 				ERR_R_MALLOC_FAILURE);
   303 			return(NULL);
   304 			}
   305 		strcpy(merged, filespec2);
   306 		}
   307 	else
   308 		/* This part isn't as trivial as it looks.  It assumes that
   309 		   the second file specification really is a directory, and
   310 		   makes no checks whatsoever.  Therefore, the result becomes
   311 		   the concatenation of filespec2 followed by a slash followed
   312 		   by filespec1. */
   313 		{
   314 		int spec2len, len;
   315 
   316 		spec2len = (filespec2 ? strlen(filespec2) : 0);
   317 		len = spec2len + (filespec1 ? strlen(filespec1) : 0);
   318 
   319 		if(filespec2 && filespec2[spec2len - 1] == '/')
   320 			{
   321 			spec2len--;
   322 			len--;
   323 			}
   324 		merged = OPENSSL_malloc(len + 2);
   325 		if(!merged)
   326 			{
   327 			DSOerr(DSO_F_DL_MERGER,
   328 				ERR_R_MALLOC_FAILURE);
   329 			return(NULL);
   330 			}
   331 		strcpy(merged, filespec2);
   332 		merged[spec2len] = '/';
   333 		strcpy(&merged[spec2len + 1], filespec1);
   334 		}
   335 	return(merged);
   336 	}
   337 
   338 /* This function is identical to the one in dso_dlfcn.c, but as it is highly
   339  * unlikely that both the "dl" *and* "dlfcn" variants are being compiled at the
   340  * same time, there's no great duplicating the code. Figuring out an elegant 
   341  * way to share one copy of the code would be more difficult and would not
   342  * leave the implementations independant. */
   343 #if defined(__hpux)
   344 static const char extension[] = ".sl";
   345 #else
   346 static const char extension[] = ".so";
   347 #endif
   348 static char *dl_name_converter(DSO *dso, const char *filename)
   349 	{
   350 	char *translated;
   351 	int len, rsize, transform;
   352 
   353 	len = strlen(filename);
   354 	rsize = len + 1;
   355 	transform = (strstr(filename, "/") == NULL);
   356 		{
   357 		/* We will convert this to "%s.s?" or "lib%s.s?" */
   358 		rsize += strlen(extension);/* The length of ".s?" */
   359 		if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
   360 			rsize += 3; /* The length of "lib" */
   361 		}
   362 	translated = OPENSSL_malloc(rsize);
   363 	if(translated == NULL)
   364 		{
   365 		DSOerr(DSO_F_DL_NAME_CONVERTER,
   366 				DSO_R_NAME_TRANSLATION_FAILED); 
   367 		return(NULL);   
   368 		}
   369 	if(transform)
   370 		{
   371 		if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
   372 			sprintf(translated, "lib%s%s", filename, extension);
   373 		else
   374 			sprintf(translated, "%s%s", filename, extension);
   375 		}
   376 	else
   377 		sprintf(translated, "%s", filename);
   378 	return(translated);
   379 	}
   380 
   381 #endif /* DSO_DL */