GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/dso/dso_lib.c Lines: 0 179 0.0 %
Date: 2017-11-07 Branches: 0 114 0.0 %

Line Branch Exec Source
1
/* $OpenBSD: dso_lib.c,v 1.19 2017/01/29 17:49:23 beck Exp $ */
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
#include <stdio.h>
60
#include <string.h>
61
62
#include <openssl/crypto.h>
63
#include <openssl/dso.h>
64
#include <openssl/err.h>
65
66
static DSO_METHOD *default_DSO_meth = NULL;
67
68
DSO *
69
DSO_new(void)
70
{
71
	return (DSO_new_method(NULL));
72
}
73
74
void
75
DSO_set_default_method(DSO_METHOD *meth)
76
{
77
	default_DSO_meth = meth;
78
}
79
80
DSO_METHOD *
81
DSO_get_default_method(void)
82
{
83
	return (default_DSO_meth);
84
}
85
86
DSO_METHOD *
87
DSO_get_method(DSO *dso)
88
{
89
	return (dso->meth);
90
}
91
92
DSO_METHOD *
93
DSO_set_method(DSO *dso, DSO_METHOD *meth)
94
{
95
	DSO_METHOD *mtmp;
96
97
	mtmp = dso->meth;
98
	dso->meth = meth;
99
	return (mtmp);
100
}
101
102
DSO *
103
DSO_new_method(DSO_METHOD *meth)
104
{
105
	DSO *ret;
106
107
	if (default_DSO_meth == NULL)
108
		/* We default to DSO_METH_openssl() which in turn defaults
109
		 * to stealing the "best available" method. Will fallback
110
		 * to DSO_METH_null() in the worst case. */
111
		default_DSO_meth = DSO_METHOD_openssl();
112
	ret = calloc(1, sizeof(DSO));
113
	if (ret == NULL) {
114
		DSOerror(ERR_R_MALLOC_FAILURE);
115
		return (NULL);
116
	}
117
	ret->meth_data = sk_void_new_null();
118
	if (ret->meth_data == NULL) {
119
		/* sk_new doesn't generate any errors so we do */
120
		DSOerror(ERR_R_MALLOC_FAILURE);
121
		free(ret);
122
		return (NULL);
123
	}
124
	if (meth == NULL)
125
		ret->meth = default_DSO_meth;
126
	else
127
		ret->meth = meth;
128
	ret->references = 1;
129
	if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
130
		free(ret);
131
		ret = NULL;
132
	}
133
	return (ret);
134
}
135
136
int
137
DSO_free(DSO *dso)
138
{
139
	int i;
140
141
	if (dso == NULL) {
142
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
143
		return (0);
144
	}
145
146
	i = CRYPTO_add(&dso->references, -1, CRYPTO_LOCK_DSO);
147
	if (i > 0)
148
		return (1);
149
150
	if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
151
		DSOerror(DSO_R_UNLOAD_FAILED);
152
		return (0);
153
	}
154
155
	if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
156
		DSOerror(DSO_R_FINISH_FAILED);
157
		return (0);
158
	}
159
160
	sk_void_free(dso->meth_data);
161
	free(dso->filename);
162
	free(dso->loaded_filename);
163
	free(dso);
164
	return (1);
165
}
166
167
int
168
DSO_flags(DSO *dso)
169
{
170
	return ((dso == NULL) ? 0 : dso->flags);
171
}
172
173
174
int
175
DSO_up_ref(DSO *dso)
176
{
177
	if (dso == NULL) {
178
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
179
		return (0);
180
	}
181
182
	CRYPTO_add(&dso->references, 1, CRYPTO_LOCK_DSO);
183
	return (1);
184
}
185
186
DSO *
187
DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
188
{
189
	DSO *ret;
190
	int allocated = 0;
191
192
	if (dso == NULL) {
193
		ret = DSO_new_method(meth);
194
		if (ret == NULL) {
195
			DSOerror(ERR_R_MALLOC_FAILURE);
196
			goto err;
197
		}
198
		allocated = 1;
199
		/* Pass the provided flags to the new DSO object */
200
		if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
201
			DSOerror(DSO_R_CTRL_FAILED);
202
			goto err;
203
		}
204
	} else
205
		ret = dso;
206
	/* Don't load if we're currently already loaded */
207
	if (ret->filename != NULL) {
208
		DSOerror(DSO_R_DSO_ALREADY_LOADED);
209
		goto err;
210
	}
211
	/* filename can only be NULL if we were passed a dso that already has
212
	 * one set. */
213
	if (filename != NULL)
214
		if (!DSO_set_filename(ret, filename)) {
215
		DSOerror(DSO_R_SET_FILENAME_FAILED);
216
		goto err;
217
	}
218
	filename = ret->filename;
219
	if (filename == NULL) {
220
		DSOerror(DSO_R_NO_FILENAME);
221
		goto err;
222
	}
223
	if (ret->meth->dso_load == NULL) {
224
		DSOerror(DSO_R_UNSUPPORTED);
225
		goto err;
226
	}
227
	if (!ret->meth->dso_load(ret)) {
228
		DSOerror(DSO_R_LOAD_FAILED);
229
		goto err;
230
	}
231
	/* Load succeeded */
232
	return (ret);
233
234
err:
235
	if (allocated)
236
		DSO_free(ret);
237
	return (NULL);
238
}
239
240
void *
241
DSO_bind_var(DSO *dso, const char *symname)
242
{
243
	void *ret = NULL;
244
245
	if ((dso == NULL) || (symname == NULL)) {
246
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
247
		return (NULL);
248
	}
249
	if (dso->meth->dso_bind_var == NULL) {
250
		DSOerror(DSO_R_UNSUPPORTED);
251
		return (NULL);
252
	}
253
	if ((ret = dso->meth->dso_bind_var(dso, symname)) == NULL) {
254
		DSOerror(DSO_R_SYM_FAILURE);
255
		return (NULL);
256
	}
257
	/* Success */
258
	return (ret);
259
}
260
261
DSO_FUNC_TYPE
262
DSO_bind_func(DSO *dso, const char *symname)
263
{
264
	DSO_FUNC_TYPE ret = NULL;
265
266
	if ((dso == NULL) || (symname == NULL)) {
267
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
268
		return (NULL);
269
	}
270
	if (dso->meth->dso_bind_func == NULL) {
271
		DSOerror(DSO_R_UNSUPPORTED);
272
		return (NULL);
273
	}
274
	if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
275
		DSOerror(DSO_R_SYM_FAILURE);
276
		return (NULL);
277
	}
278
	/* Success */
279
	return (ret);
280
}
281
282
/* I don't really like these *_ctrl functions very much to be perfectly
283
 * honest. For one thing, I think I have to return a negative value for
284
 * any error because possible DSO_ctrl() commands may return values
285
 * such as "size"s that can legitimately be zero (making the standard
286
 * "if(DSO_cmd(...))" form that works almost everywhere else fail at
287
 * odd times. I'd prefer "output" values to be passed by reference and
288
 * the return value as success/failure like usual ... but we conform
289
 * when we must... :-) */
290
long
291
DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
292
{
293
	if (dso == NULL) {
294
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
295
		return (-1);
296
	}
297
	/* We should intercept certain generic commands and only pass control
298
	 * to the method-specific ctrl() function if it's something we don't
299
	 * handle. */
300
	switch (cmd) {
301
	case DSO_CTRL_GET_FLAGS:
302
		return dso->flags;
303
	case DSO_CTRL_SET_FLAGS:
304
		dso->flags = (int)larg;
305
		return (0);
306
	case DSO_CTRL_OR_FLAGS:
307
		dso->flags |= (int)larg;
308
		return (0);
309
	default:
310
		break;
311
	}
312
	if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
313
		DSOerror(DSO_R_UNSUPPORTED);
314
		return (-1);
315
	}
316
	return (dso->meth->dso_ctrl(dso, cmd, larg, parg));
317
}
318
319
int
320
DSO_set_name_converter(DSO *dso, DSO_NAME_CONVERTER_FUNC cb,
321
    DSO_NAME_CONVERTER_FUNC *oldcb)
322
{
323
	if (dso == NULL) {
324
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
325
		return (0);
326
	}
327
	if (oldcb)
328
		*oldcb = dso->name_converter;
329
	dso->name_converter = cb;
330
	return (1);
331
}
332
333
const char *
334
DSO_get_filename(DSO *dso)
335
{
336
	if (dso == NULL) {
337
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
338
		return (NULL);
339
	}
340
	return (dso->filename);
341
}
342
343
int
344
DSO_set_filename(DSO *dso, const char *filename)
345
{
346
	char *copied;
347
348
	if ((dso == NULL) || (filename == NULL)) {
349
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
350
		return (0);
351
	}
352
	if (dso->loaded_filename) {
353
		DSOerror(DSO_R_DSO_ALREADY_LOADED);
354
		return (0);
355
	}
356
	/* We'll duplicate filename */
357
	copied = strdup(filename);
358
	if (copied == NULL) {
359
		DSOerror(ERR_R_MALLOC_FAILURE);
360
		return (0);
361
	}
362
	free(dso->filename);
363
	dso->filename = copied;
364
	return (1);
365
}
366
367
char *
368
DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
369
{
370
	char *result = NULL;
371
372
	if (dso == NULL || filespec1 == NULL) {
373
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
374
		return (NULL);
375
	}
376
	if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
377
		if (dso->merger != NULL)
378
			result = dso->merger(dso, filespec1, filespec2);
379
		else if (dso->meth->dso_merger != NULL)
380
			result = dso->meth->dso_merger(dso,
381
			    filespec1, filespec2);
382
	}
383
	return (result);
384
}
385
386
char *
387
DSO_convert_filename(DSO *dso, const char *filename)
388
{
389
	char *result = NULL;
390
391
	if (dso == NULL) {
392
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
393
		return (NULL);
394
	}
395
	if (filename == NULL)
396
		filename = dso->filename;
397
	if (filename == NULL) {
398
		DSOerror(DSO_R_NO_FILENAME);
399
		return (NULL);
400
	}
401
	if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
402
		if (dso->name_converter != NULL)
403
			result = dso->name_converter(dso, filename);
404
		else if (dso->meth->dso_name_converter != NULL)
405
			result = dso->meth->dso_name_converter(dso, filename);
406
	}
407
	if (result == NULL) {
408
		result = strdup(filename);
409
		if (result == NULL) {
410
			DSOerror(ERR_R_MALLOC_FAILURE);
411
			return (NULL);
412
		}
413
	}
414
	return (result);
415
}
416
417
const char *
418
DSO_get_loaded_filename(DSO *dso)
419
{
420
	if (dso == NULL) {
421
		DSOerror(ERR_R_PASSED_NULL_PARAMETER);
422
		return (NULL);
423
	}
424
	return (dso->loaded_filename);
425
}
426
427
int
428
DSO_pathbyaddr(void *addr, char *path, int sz)
429
{
430
	DSO_METHOD *meth = default_DSO_meth;
431
	if (meth == NULL)
432
		meth = DSO_METHOD_openssl();
433
	if (meth->pathbyaddr == NULL) {
434
		DSOerror(DSO_R_UNSUPPORTED);
435
		return -1;
436
	}
437
	return (*meth->pathbyaddr)(addr, path, sz);
438
}
439
440
void *
441
DSO_global_lookup(const char *name)
442
{
443
	DSO_METHOD *meth = default_DSO_meth;
444
	if (meth == NULL)
445
		meth = DSO_METHOD_openssl();
446
	if (meth->globallookup == NULL) {
447
		DSOerror(DSO_R_UNSUPPORTED);
448
		return NULL;
449
	}
450
	return (*meth->globallookup)(name);
451
}