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.
sl@0
     1
/* dso_dl.c -*- mode:C; c-file-style: "eay" -*- */
sl@0
     2
/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
sl@0
     3
 * project 2000.
sl@0
     4
 */
sl@0
     5
/* ====================================================================
sl@0
     6
 * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
sl@0
     7
 *
sl@0
     8
 * Redistribution and use in source and binary forms, with or without
sl@0
     9
 * modification, are permitted provided that the following conditions
sl@0
    10
 * are met:
sl@0
    11
 *
sl@0
    12
 * 1. Redistributions of source code must retain the above copyright
sl@0
    13
 *    notice, this list of conditions and the following disclaimer. 
sl@0
    14
 *
sl@0
    15
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    16
 *    notice, this list of conditions and the following disclaimer in
sl@0
    17
 *    the documentation and/or other materials provided with the
sl@0
    18
 *    distribution.
sl@0
    19
 *
sl@0
    20
 * 3. All advertising materials mentioning features or use of this
sl@0
    21
 *    software must display the following acknowledgment:
sl@0
    22
 *    "This product includes software developed by the OpenSSL Project
sl@0
    23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
sl@0
    24
 *
sl@0
    25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
sl@0
    26
 *    endorse or promote products derived from this software without
sl@0
    27
 *    prior written permission. For written permission, please contact
sl@0
    28
 *    licensing@OpenSSL.org.
sl@0
    29
 *
sl@0
    30
 * 5. Products derived from this software may not be called "OpenSSL"
sl@0
    31
 *    nor may "OpenSSL" appear in their names without prior written
sl@0
    32
 *    permission of the OpenSSL Project.
sl@0
    33
 *
sl@0
    34
 * 6. Redistributions of any form whatsoever must retain the following
sl@0
    35
 *    acknowledgment:
sl@0
    36
 *    "This product includes software developed by the OpenSSL Project
sl@0
    37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
sl@0
    38
 *
sl@0
    39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
sl@0
    40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
sl@0
    42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
sl@0
    43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
sl@0
    44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
sl@0
    45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sl@0
    46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sl@0
    48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
sl@0
    49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
sl@0
    50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
sl@0
    51
 * ====================================================================
sl@0
    52
 *
sl@0
    53
 * This product includes cryptographic software written by Eric Young
sl@0
    54
 * (eay@cryptsoft.com).  This product includes software written by Tim
sl@0
    55
 * Hudson (tjh@cryptsoft.com).
sl@0
    56
 *
sl@0
    57
 */
sl@0
    58
/*
sl@0
    59
 © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
sl@0
    60
 */
sl@0
    61
#include <stdio.h>
sl@0
    62
#include "cryptlib.h"
sl@0
    63
#include <openssl/dso.h>
sl@0
    64
#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
sl@0
    65
#include "libcrypto_wsd_macros.h"
sl@0
    66
#include "libcrypto_wsd.h"
sl@0
    67
#endif
sl@0
    68
sl@0
    69
sl@0
    70
#ifndef DSO_DL
sl@0
    71
EXPORT_C DSO_METHOD *DSO_METHOD_dl(void)
sl@0
    72
       {
sl@0
    73
       return NULL;
sl@0
    74
       }
sl@0
    75
#else
sl@0
    76
sl@0
    77
#include <dl.h>
sl@0
    78
sl@0
    79
/* Part of the hack in "dl_load" ... */
sl@0
    80
#define DSO_MAX_TRANSLATED_SIZE 256
sl@0
    81
sl@0
    82
static int dl_load(DSO *dso);
sl@0
    83
static int dl_unload(DSO *dso);
sl@0
    84
static void *dl_bind_var(DSO *dso, const char *symname);
sl@0
    85
static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname);
sl@0
    86
#if 0
sl@0
    87
static int dl_unbind_var(DSO *dso, char *symname, void *symptr);
sl@0
    88
static int dl_unbind_func(DSO *dso, char *symname, DSO_FUNC_TYPE symptr);
sl@0
    89
static int dl_init(DSO *dso);
sl@0
    90
static int dl_finish(DSO *dso);
sl@0
    91
static int dl_ctrl(DSO *dso, int cmd, long larg, void *parg);
sl@0
    92
#endif
sl@0
    93
static char *dl_name_converter(DSO *dso, const char *filename);
sl@0
    94
static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2);
sl@0
    95
sl@0
    96
#ifndef EMULATOR
sl@0
    97
static DSO_METHOD dso_meth_dl = {
sl@0
    98
	"OpenSSL 'dl' shared library method",
sl@0
    99
	dl_load,
sl@0
   100
	dl_unload,
sl@0
   101
	dl_bind_var,
sl@0
   102
	dl_bind_func,
sl@0
   103
/* For now, "unbind" doesn't exist */
sl@0
   104
#if 0
sl@0
   105
	NULL, /* unbind_var */
sl@0
   106
	NULL, /* unbind_func */
sl@0
   107
#endif
sl@0
   108
	NULL, /* ctrl */
sl@0
   109
	dl_name_converter,
sl@0
   110
	dl_merger,
sl@0
   111
	NULL, /* init */
sl@0
   112
	NULL  /* finish */
sl@0
   113
	};
sl@0
   114
#else
sl@0
   115
GET_STATIC_VAR_FROM_TLS(dso_meth_dl,dso_dl,DSO_METHOD)
sl@0
   116
#define dso_meth_dl (*GET_WSD_VAR_NAME(dso_meth_dl,dso_dl,s)())
sl@0
   117
const DSO_METHOD temp_s_dso_meth_dl = {
sl@0
   118
	"OpenSSL 'dl' shared library method",
sl@0
   119
	dl_load,
sl@0
   120
	dl_unload,
sl@0
   121
	dl_bind_var,
sl@0
   122
	dl_bind_func,
sl@0
   123
/* For now, "unbind" doesn't exist */
sl@0
   124
#if 0
sl@0
   125
	NULL, /* unbind_var */
sl@0
   126
	NULL, /* unbind_func */
sl@0
   127
#endif
sl@0
   128
	NULL, /* ctrl */
sl@0
   129
	dl_name_converter,
sl@0
   130
	dl_merger,
sl@0
   131
	NULL, /* init */
sl@0
   132
	NULL  /* finish */
sl@0
   133
	};
sl@0
   134
#endif
sl@0
   135
DSO_METHOD *DSO_METHOD_dl(void)
sl@0
   136
	{
sl@0
   137
	return(&dso_meth_dl);
sl@0
   138
	}
sl@0
   139
sl@0
   140
/* For this DSO_METHOD, our meth_data STACK will contain;
sl@0
   141
 * (i) the handle (shl_t) returned from shl_load().
sl@0
   142
 * NB: I checked on HPUX11 and shl_t is itself a pointer
sl@0
   143
 * type so the cast is safe.
sl@0
   144
 */
sl@0
   145
sl@0
   146
static int dl_load(DSO *dso)
sl@0
   147
	{
sl@0
   148
	shl_t ptr = NULL;
sl@0
   149
	/* We don't do any fancy retries or anything, just take the method's
sl@0
   150
	 * (or DSO's if it has the callback set) best translation of the
sl@0
   151
	 * platform-independant filename and try once with that. */
sl@0
   152
	char *filename= DSO_convert_filename(dso, NULL);
sl@0
   153
sl@0
   154
	if(filename == NULL)
sl@0
   155
		{
sl@0
   156
		DSOerr(DSO_F_DL_LOAD,DSO_R_NO_FILENAME);
sl@0
   157
		goto err;
sl@0
   158
		}
sl@0
   159
	ptr = shl_load(filename, BIND_IMMEDIATE |
sl@0
   160
		(dso->flags&DSO_FLAG_NO_NAME_TRANSLATION?0:DYNAMIC_PATH), 0L);
sl@0
   161
	if(ptr == NULL)
sl@0
   162
		{
sl@0
   163
		DSOerr(DSO_F_DL_LOAD,DSO_R_LOAD_FAILED);
sl@0
   164
		ERR_add_error_data(4, "filename(", filename, "): ",
sl@0
   165
			strerror(errno));
sl@0
   166
		goto err;
sl@0
   167
		}
sl@0
   168
	if(!sk_push(dso->meth_data, (char *)ptr))
sl@0
   169
		{
sl@0
   170
		DSOerr(DSO_F_DL_LOAD,DSO_R_STACK_ERROR);
sl@0
   171
		goto err;
sl@0
   172
		}
sl@0
   173
	/* Success, stick the converted filename we've loaded under into the DSO
sl@0
   174
	 * (it also serves as the indicator that we are currently loaded). */
sl@0
   175
	dso->loaded_filename = filename;
sl@0
   176
	return(1);
sl@0
   177
err:
sl@0
   178
	/* Cleanup! */
sl@0
   179
	if(filename != NULL)
sl@0
   180
		OPENSSL_free(filename);
sl@0
   181
	if(ptr != NULL)
sl@0
   182
		shl_unload(ptr);
sl@0
   183
	return(0);
sl@0
   184
	}
sl@0
   185
sl@0
   186
static int dl_unload(DSO *dso)
sl@0
   187
	{
sl@0
   188
	shl_t ptr;
sl@0
   189
	if(dso == NULL)
sl@0
   190
		{
sl@0
   191
		DSOerr(DSO_F_DL_UNLOAD,ERR_R_PASSED_NULL_PARAMETER);
sl@0
   192
		return(0);
sl@0
   193
		}
sl@0
   194
	if(sk_num(dso->meth_data) < 1)
sl@0
   195
		return(1);
sl@0
   196
	/* Is this statement legal? */
sl@0
   197
	ptr = (shl_t)sk_pop(dso->meth_data);
sl@0
   198
	if(ptr == NULL)
sl@0
   199
		{
sl@0
   200
		DSOerr(DSO_F_DL_UNLOAD,DSO_R_NULL_HANDLE);
sl@0
   201
		/* Should push the value back onto the stack in
sl@0
   202
		 * case of a retry. */
sl@0
   203
		sk_push(dso->meth_data, (char *)ptr);
sl@0
   204
		return(0);
sl@0
   205
		}
sl@0
   206
	shl_unload(ptr);
sl@0
   207
	return(1);
sl@0
   208
	}
sl@0
   209
sl@0
   210
static void *dl_bind_var(DSO *dso, const char *symname)
sl@0
   211
	{
sl@0
   212
	shl_t ptr;
sl@0
   213
	void *sym;
sl@0
   214
sl@0
   215
	if((dso == NULL) || (symname == NULL))
sl@0
   216
		{
sl@0
   217
		DSOerr(DSO_F_DL_BIND_VAR,ERR_R_PASSED_NULL_PARAMETER);
sl@0
   218
		return(NULL);
sl@0
   219
		}
sl@0
   220
	if(sk_num(dso->meth_data) < 1)
sl@0
   221
		{
sl@0
   222
		DSOerr(DSO_F_DL_BIND_VAR,DSO_R_STACK_ERROR);
sl@0
   223
		return(NULL);
sl@0
   224
		}
sl@0
   225
	ptr = (shl_t)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
sl@0
   226
	if(ptr == NULL)
sl@0
   227
		{
sl@0
   228
		DSOerr(DSO_F_DL_BIND_VAR,DSO_R_NULL_HANDLE);
sl@0
   229
		return(NULL);
sl@0
   230
		}
sl@0
   231
	if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0)
sl@0
   232
		{
sl@0
   233
		DSOerr(DSO_F_DL_BIND_VAR,DSO_R_SYM_FAILURE);
sl@0
   234
		ERR_add_error_data(4, "symname(", symname, "): ",
sl@0
   235
			strerror(errno));
sl@0
   236
		return(NULL);
sl@0
   237
		}
sl@0
   238
	return(sym);
sl@0
   239
	}
sl@0
   240
sl@0
   241
static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname)
sl@0
   242
	{
sl@0
   243
	shl_t ptr;
sl@0
   244
	void *sym;
sl@0
   245
sl@0
   246
	if((dso == NULL) || (symname == NULL))
sl@0
   247
		{
sl@0
   248
		DSOerr(DSO_F_DL_BIND_FUNC,ERR_R_PASSED_NULL_PARAMETER);
sl@0
   249
		return(NULL);
sl@0
   250
		}
sl@0
   251
	if(sk_num(dso->meth_data) < 1)
sl@0
   252
		{
sl@0
   253
		DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_STACK_ERROR);
sl@0
   254
		return(NULL);
sl@0
   255
		}
sl@0
   256
	ptr = (shl_t)sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
sl@0
   257
	if(ptr == NULL)
sl@0
   258
		{
sl@0
   259
		DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_NULL_HANDLE);
sl@0
   260
		return(NULL);
sl@0
   261
		}
sl@0
   262
	if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0)
sl@0
   263
		{
sl@0
   264
		DSOerr(DSO_F_DL_BIND_FUNC,DSO_R_SYM_FAILURE);
sl@0
   265
		ERR_add_error_data(4, "symname(", symname, "): ",
sl@0
   266
			strerror(errno));
sl@0
   267
		return(NULL);
sl@0
   268
		}
sl@0
   269
	return((DSO_FUNC_TYPE)sym);
sl@0
   270
	}
sl@0
   271
sl@0
   272
static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2)
sl@0
   273
	{
sl@0
   274
	char *merged;
sl@0
   275
sl@0
   276
	if(!filespec1 && !filespec2)
sl@0
   277
		{
sl@0
   278
		DSOerr(DSO_F_DL_MERGER,
sl@0
   279
				ERR_R_PASSED_NULL_PARAMETER);
sl@0
   280
		return(NULL);
sl@0
   281
		}
sl@0
   282
	/* If the first file specification is a rooted path, it rules.
sl@0
   283
	   same goes if the second file specification is missing. */
sl@0
   284
	if (!filespec2 || filespec1[0] == '/')
sl@0
   285
		{
sl@0
   286
		merged = OPENSSL_malloc(strlen(filespec1) + 1);
sl@0
   287
		if(!merged)
sl@0
   288
			{
sl@0
   289
			DSOerr(DSO_F_DL_MERGER,
sl@0
   290
				ERR_R_MALLOC_FAILURE);
sl@0
   291
			return(NULL);
sl@0
   292
			}
sl@0
   293
		strcpy(merged, filespec1);
sl@0
   294
		}
sl@0
   295
	/* If the first file specification is missing, the second one rules. */
sl@0
   296
	else if (!filespec1)
sl@0
   297
		{
sl@0
   298
		merged = OPENSSL_malloc(strlen(filespec2) + 1);
sl@0
   299
		if(!merged)
sl@0
   300
			{
sl@0
   301
			DSOerr(DSO_F_DL_MERGER,
sl@0
   302
				ERR_R_MALLOC_FAILURE);
sl@0
   303
			return(NULL);
sl@0
   304
			}
sl@0
   305
		strcpy(merged, filespec2);
sl@0
   306
		}
sl@0
   307
	else
sl@0
   308
		/* This part isn't as trivial as it looks.  It assumes that
sl@0
   309
		   the second file specification really is a directory, and
sl@0
   310
		   makes no checks whatsoever.  Therefore, the result becomes
sl@0
   311
		   the concatenation of filespec2 followed by a slash followed
sl@0
   312
		   by filespec1. */
sl@0
   313
		{
sl@0
   314
		int spec2len, len;
sl@0
   315
sl@0
   316
		spec2len = (filespec2 ? strlen(filespec2) : 0);
sl@0
   317
		len = spec2len + (filespec1 ? strlen(filespec1) : 0);
sl@0
   318
sl@0
   319
		if(filespec2 && filespec2[spec2len - 1] == '/')
sl@0
   320
			{
sl@0
   321
			spec2len--;
sl@0
   322
			len--;
sl@0
   323
			}
sl@0
   324
		merged = OPENSSL_malloc(len + 2);
sl@0
   325
		if(!merged)
sl@0
   326
			{
sl@0
   327
			DSOerr(DSO_F_DL_MERGER,
sl@0
   328
				ERR_R_MALLOC_FAILURE);
sl@0
   329
			return(NULL);
sl@0
   330
			}
sl@0
   331
		strcpy(merged, filespec2);
sl@0
   332
		merged[spec2len] = '/';
sl@0
   333
		strcpy(&merged[spec2len + 1], filespec1);
sl@0
   334
		}
sl@0
   335
	return(merged);
sl@0
   336
	}
sl@0
   337
sl@0
   338
/* This function is identical to the one in dso_dlfcn.c, but as it is highly
sl@0
   339
 * unlikely that both the "dl" *and* "dlfcn" variants are being compiled at the
sl@0
   340
 * same time, there's no great duplicating the code. Figuring out an elegant 
sl@0
   341
 * way to share one copy of the code would be more difficult and would not
sl@0
   342
 * leave the implementations independant. */
sl@0
   343
#if defined(__hpux)
sl@0
   344
static const char extension[] = ".sl";
sl@0
   345
#else
sl@0
   346
static const char extension[] = ".so";
sl@0
   347
#endif
sl@0
   348
static char *dl_name_converter(DSO *dso, const char *filename)
sl@0
   349
	{
sl@0
   350
	char *translated;
sl@0
   351
	int len, rsize, transform;
sl@0
   352
sl@0
   353
	len = strlen(filename);
sl@0
   354
	rsize = len + 1;
sl@0
   355
	transform = (strstr(filename, "/") == NULL);
sl@0
   356
		{
sl@0
   357
		/* We will convert this to "%s.s?" or "lib%s.s?" */
sl@0
   358
		rsize += strlen(extension);/* The length of ".s?" */
sl@0
   359
		if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
sl@0
   360
			rsize += 3; /* The length of "lib" */
sl@0
   361
		}
sl@0
   362
	translated = OPENSSL_malloc(rsize);
sl@0
   363
	if(translated == NULL)
sl@0
   364
		{
sl@0
   365
		DSOerr(DSO_F_DL_NAME_CONVERTER,
sl@0
   366
				DSO_R_NAME_TRANSLATION_FAILED); 
sl@0
   367
		return(NULL);   
sl@0
   368
		}
sl@0
   369
	if(transform)
sl@0
   370
		{
sl@0
   371
		if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
sl@0
   372
			sprintf(translated, "lib%s%s", filename, extension);
sl@0
   373
		else
sl@0
   374
			sprintf(translated, "%s%s", filename, extension);
sl@0
   375
		}
sl@0
   376
	else
sl@0
   377
		sprintf(translated, "%s", filename);
sl@0
   378
	return(translated);
sl@0
   379
	}
sl@0
   380
sl@0
   381
#endif /* DSO_DL */