1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Upgrade openssl from 1.1.0e to 1.1.1b, with source code. 4.0.78

This commit is contained in:
winlin 2021-03-01 20:47:57 +08:00
parent 8f1c992379
commit 96dbd7bced
1476 changed files with 616554 additions and 4 deletions

View file

@ -0,0 +1,4 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
dso_dl.c dso_dlfcn.c dso_err.c dso_lib.c \
dso_openssl.c dso_win32.c dso_vms.c

View file

@ -0,0 +1,279 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "dso_locl.h"
#ifdef DSO_DL
# include <dl.h>
/* Part of the hack in "dl_load" ... */
# define DSO_MAX_TRANSLATED_SIZE 256
static int dl_load(DSO *dso);
static int dl_unload(DSO *dso);
static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname);
static char *dl_name_converter(DSO *dso, const char *filename);
static char *dl_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static int dl_pathbyaddr(void *addr, char *path, int sz);
static void *dl_globallookup(const char *name);
static DSO_METHOD dso_meth_dl = {
"OpenSSL 'dl' shared library method",
dl_load,
dl_unload,
dl_bind_func,
NULL, /* ctrl */
dl_name_converter,
dl_merger,
NULL, /* init */
NULL, /* finish */
dl_pathbyaddr,
dl_globallookup
};
DSO_METHOD *DSO_METHOD_openssl(void)
{
return &dso_meth_dl;
}
/*
* For this DSO_METHOD, our meth_data STACK will contain; (i) the handle
* (shl_t) returned from shl_load(). NB: I checked on HPUX11 and shl_t is
* itself a pointer type so the cast is safe.
*/
static int dl_load(DSO *dso)
{
shl_t ptr = NULL;
/*
* We don't do any fancy retries or anything, just take the method's (or
* DSO's if it has the callback set) best translation of the
* platform-independent filename and try once with that.
*/
char *filename = DSO_convert_filename(dso, NULL);
if (filename == NULL) {
DSOerr(DSO_F_DL_LOAD, DSO_R_NO_FILENAME);
goto err;
}
ptr = shl_load(filename, BIND_IMMEDIATE |
(dso->flags & DSO_FLAG_NO_NAME_TRANSLATION ? 0 :
DYNAMIC_PATH), 0L);
if (ptr == NULL) {
char errbuf[160];
DSOerr(DSO_F_DL_LOAD, DSO_R_LOAD_FAILED);
if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
ERR_add_error_data(4, "filename(", filename, "): ", errbuf);
goto err;
}
if (!sk_push(dso->meth_data, (char *)ptr)) {
DSOerr(DSO_F_DL_LOAD, DSO_R_STACK_ERROR);
goto err;
}
/*
* Success, stick the converted filename we've loaded under into the DSO
* (it also serves as the indicator that we are currently loaded).
*/
dso->loaded_filename = filename;
return 1;
err:
/* Cleanup! */
OPENSSL_free(filename);
if (ptr != NULL)
shl_unload(ptr);
return 0;
}
static int dl_unload(DSO *dso)
{
shl_t ptr;
if (dso == NULL) {
DSOerr(DSO_F_DL_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (sk_num(dso->meth_data) < 1)
return 1;
/* Is this statement legal? */
ptr = (shl_t) sk_pop(dso->meth_data);
if (ptr == NULL) {
DSOerr(DSO_F_DL_UNLOAD, DSO_R_NULL_HANDLE);
/*
* Should push the value back onto the stack in case of a retry.
*/
sk_push(dso->meth_data, (char *)ptr);
return 0;
}
shl_unload(ptr);
return 1;
}
static DSO_FUNC_TYPE dl_bind_func(DSO *dso, const char *symname)
{
shl_t ptr;
void *sym;
if ((dso == NULL) || (symname == NULL)) {
DSOerr(DSO_F_DL_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (sk_num(dso->meth_data) < 1) {
DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_STACK_ERROR);
return NULL;
}
ptr = (shl_t) sk_value(dso->meth_data, sk_num(dso->meth_data) - 1);
if (ptr == NULL) {
DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_NULL_HANDLE);
return NULL;
}
if (shl_findsym(&ptr, symname, TYPE_UNDEFINED, &sym) < 0) {
char errbuf[160];
DSOerr(DSO_F_DL_BIND_FUNC, DSO_R_SYM_FAILURE);
if (openssl_strerror_r(errno, errbuf, sizeof(errbuf)))
ERR_add_error_data(4, "symname(", symname, "): ", errbuf);
return NULL;
}
return (DSO_FUNC_TYPE)sym;
}
static char *dl_merger(DSO *dso, const char *filespec1, const char *filespec2)
{
char *merged;
if (!filespec1 && !filespec2) {
DSOerr(DSO_F_DL_MERGER, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
/*
* If the first file specification is a rooted path, it rules. same goes
* if the second file specification is missing.
*/
if (!filespec2 || filespec1[0] == '/') {
merged = OPENSSL_strdup(filespec1);
if (merged == NULL) {
DSOerr(DSO_F_DL_MERGER, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
/*
* If the first file specification is missing, the second one rules.
*/
else if (!filespec1) {
merged = OPENSSL_strdup(filespec2);
if (merged == NULL) {
DSOerr(DSO_F_DL_MERGER, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else
/*
* This part isn't as trivial as it looks. It assumes that the
* second file specification really is a directory, and makes no
* checks whatsoever. Therefore, the result becomes the
* concatenation of filespec2 followed by a slash followed by
* filespec1.
*/
{
int spec2len, len;
spec2len = (filespec2 ? strlen(filespec2) : 0);
len = spec2len + (filespec1 ? strlen(filespec1) : 0);
if (spec2len && filespec2[spec2len - 1] == '/') {
spec2len--;
len--;
}
merged = OPENSSL_malloc(len + 2);
if (merged == NULL) {
DSOerr(DSO_F_DL_MERGER, ERR_R_MALLOC_FAILURE);
return NULL;
}
strcpy(merged, filespec2);
merged[spec2len] = '/';
strcpy(&merged[spec2len + 1], filespec1);
}
return merged;
}
/*
* This function is identical to the one in dso_dlfcn.c, but as it is highly
* unlikely that both the "dl" *and* "dlfcn" variants are being compiled at
* the same time, there's no great duplicating the code. Figuring out an
* elegant way to share one copy of the code would be more difficult and
* would not leave the implementations independent.
*/
static char *dl_name_converter(DSO *dso, const char *filename)
{
char *translated;
int len, rsize, transform;
len = strlen(filename);
rsize = len + 1;
transform = (strstr(filename, "/") == NULL);
{
/* We will convert this to "%s.s?" or "lib%s.s?" */
rsize += strlen(DSO_EXTENSION); /* The length of ".s?" */
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
rsize += 3; /* The length of "lib" */
}
translated = OPENSSL_malloc(rsize);
if (translated == NULL) {
DSOerr(DSO_F_DL_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
return NULL;
}
if (transform) {
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
sprintf(translated, "lib%s%s", filename, DSO_EXTENSION);
else
sprintf(translated, "%s%s", filename, DSO_EXTENSION);
} else
sprintf(translated, "%s", filename);
return translated;
}
static int dl_pathbyaddr(void *addr, char *path, int sz)
{
struct shl_descriptor inf;
int i, len;
if (addr == NULL) {
union {
int (*f) (void *, char *, int);
void *p;
} t = {
dl_pathbyaddr
};
addr = t.p;
}
for (i = -1; shl_get_r(i, &inf) == 0; i++) {
if (((size_t)addr >= inf.tstart && (size_t)addr < inf.tend) ||
((size_t)addr >= inf.dstart && (size_t)addr < inf.dend)) {
len = (int)strlen(inf.filename);
if (sz <= 0)
return len + 1;
if (len >= sz)
len = sz - 1;
memcpy(path, inf.filename, len);
path[len++] = 0;
return len;
}
}
return -1;
}
static void *dl_globallookup(const char *name)
{
void *ret;
shl_t h = NULL;
return shl_findsym(&h, name, TYPE_UNDEFINED, &ret) ? NULL : ret;
}
#endif /* DSO_DL */

View file

@ -0,0 +1,457 @@
/*
* Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* We need to do this early, because stdio.h includes the header files that
* handle _GNU_SOURCE and other similar macros. Defining it later is simply
* too late, because those headers are protected from re- inclusion.
*/
#ifndef _GNU_SOURCE
# define _GNU_SOURCE /* make sure dladdr is declared */
#endif
#include "dso_locl.h"
#include "e_os.h"
#ifdef DSO_DLFCN
# ifdef HAVE_DLFCN_H
# ifdef __osf__
# define __EXTENSIONS__
# endif
# include <dlfcn.h>
# define HAVE_DLINFO 1
# if defined(__CYGWIN__) || \
defined(__SCO_VERSION__) || defined(_SCO_ELF) || \
(defined(__osf__) && !defined(RTLD_NEXT)) || \
(defined(__OpenBSD__) && !defined(RTLD_SELF)) || \
defined(__ANDROID__)
# undef HAVE_DLINFO
# endif
# endif
/* Part of the hack in "dlfcn_load" ... */
# define DSO_MAX_TRANSLATED_SIZE 256
static int dlfcn_load(DSO *dso);
static int dlfcn_unload(DSO *dso);
static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname);
static char *dlfcn_name_converter(DSO *dso, const char *filename);
static char *dlfcn_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static int dlfcn_pathbyaddr(void *addr, char *path, int sz);
static void *dlfcn_globallookup(const char *name);
static DSO_METHOD dso_meth_dlfcn = {
"OpenSSL 'dlfcn' shared library method",
dlfcn_load,
dlfcn_unload,
dlfcn_bind_func,
NULL, /* ctrl */
dlfcn_name_converter,
dlfcn_merger,
NULL, /* init */
NULL, /* finish */
dlfcn_pathbyaddr,
dlfcn_globallookup
};
DSO_METHOD *DSO_METHOD_openssl(void)
{
return &dso_meth_dlfcn;
}
/*
* Prior to using the dlopen() function, we should decide on the flag we
* send. There's a few different ways of doing this and it's a messy
* venn-diagram to match up which platforms support what. So as we don't have
* autoconf yet, I'm implementing a hack that could be hacked further
* relatively easily to deal with cases as we find them. Initially this is to
* cope with OpenBSD.
*/
# if defined(__OpenBSD__) || defined(__NetBSD__)
# ifdef DL_LAZY
# define DLOPEN_FLAG DL_LAZY
# else
# ifdef RTLD_NOW
# define DLOPEN_FLAG RTLD_NOW
# else
# define DLOPEN_FLAG 0
# endif
# endif
# else
# define DLOPEN_FLAG RTLD_NOW /* Hope this works everywhere else */
# endif
/*
* For this DSO_METHOD, our meth_data STACK will contain; (i) the handle
* (void*) returned from dlopen().
*/
static int dlfcn_load(DSO *dso)
{
void *ptr = NULL;
/* See applicable comments in dso_dl.c */
char *filename = DSO_convert_filename(dso, NULL);
int flags = DLOPEN_FLAG;
int saveerrno = get_last_sys_error();
if (filename == NULL) {
DSOerr(DSO_F_DLFCN_LOAD, DSO_R_NO_FILENAME);
goto err;
}
# ifdef RTLD_GLOBAL
if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS)
flags |= RTLD_GLOBAL;
# endif
# ifdef _AIX
if (filename[strlen(filename) - 1] == ')')
flags |= RTLD_MEMBER;
# endif
ptr = dlopen(filename, flags);
if (ptr == NULL) {
DSOerr(DSO_F_DLFCN_LOAD, DSO_R_LOAD_FAILED);
ERR_add_error_data(4, "filename(", filename, "): ", dlerror());
goto err;
}
/*
* Some dlopen() implementations (e.g. solaris) do no preserve errno, even
* on a successful call.
*/
set_sys_error(saveerrno);
if (!sk_void_push(dso->meth_data, (char *)ptr)) {
DSOerr(DSO_F_DLFCN_LOAD, DSO_R_STACK_ERROR);
goto err;
}
/* Success */
dso->loaded_filename = filename;
return 1;
err:
/* Cleanup! */
OPENSSL_free(filename);
if (ptr != NULL)
dlclose(ptr);
return 0;
}
static int dlfcn_unload(DSO *dso)
{
void *ptr;
if (dso == NULL) {
DSOerr(DSO_F_DLFCN_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (sk_void_num(dso->meth_data) < 1)
return 1;
ptr = sk_void_pop(dso->meth_data);
if (ptr == NULL) {
DSOerr(DSO_F_DLFCN_UNLOAD, DSO_R_NULL_HANDLE);
/*
* Should push the value back onto the stack in case of a retry.
*/
sk_void_push(dso->meth_data, ptr);
return 0;
}
/* For now I'm not aware of any errors associated with dlclose() */
dlclose(ptr);
return 1;
}
static DSO_FUNC_TYPE dlfcn_bind_func(DSO *dso, const char *symname)
{
void *ptr;
union {
DSO_FUNC_TYPE sym;
void *dlret;
} u;
if ((dso == NULL) || (symname == NULL)) {
DSOerr(DSO_F_DLFCN_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (sk_void_num(dso->meth_data) < 1) {
DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_STACK_ERROR);
return NULL;
}
ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
if (ptr == NULL) {
DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_NULL_HANDLE);
return NULL;
}
u.dlret = dlsym(ptr, symname);
if (u.dlret == NULL) {
DSOerr(DSO_F_DLFCN_BIND_FUNC, DSO_R_SYM_FAILURE);
ERR_add_error_data(4, "symname(", symname, "): ", dlerror());
return NULL;
}
return u.sym;
}
static char *dlfcn_merger(DSO *dso, const char *filespec1,
const char *filespec2)
{
char *merged;
if (!filespec1 && !filespec2) {
DSOerr(DSO_F_DLFCN_MERGER, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
/*
* If the first file specification is a rooted path, it rules. same goes
* if the second file specification is missing.
*/
if (!filespec2 || (filespec1 != NULL && filespec1[0] == '/')) {
merged = OPENSSL_strdup(filespec1);
if (merged == NULL) {
DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
/*
* If the first file specification is missing, the second one rules.
*/
else if (!filespec1) {
merged = OPENSSL_strdup(filespec2);
if (merged == NULL) {
DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
/*
* This part isn't as trivial as it looks. It assumes that the
* second file specification really is a directory, and makes no
* checks whatsoever. Therefore, the result becomes the
* concatenation of filespec2 followed by a slash followed by
* filespec1.
*/
int spec2len, len;
spec2len = strlen(filespec2);
len = spec2len + strlen(filespec1);
if (spec2len && filespec2[spec2len - 1] == '/') {
spec2len--;
len--;
}
merged = OPENSSL_malloc(len + 2);
if (merged == NULL) {
DSOerr(DSO_F_DLFCN_MERGER, ERR_R_MALLOC_FAILURE);
return NULL;
}
strcpy(merged, filespec2);
merged[spec2len] = '/';
strcpy(&merged[spec2len + 1], filespec1);
}
return merged;
}
static char *dlfcn_name_converter(DSO *dso, const char *filename)
{
char *translated;
int len, rsize, transform;
len = strlen(filename);
rsize = len + 1;
transform = (strstr(filename, "/") == NULL);
if (transform) {
/* We will convert this to "%s.so" or "lib%s.so" etc */
rsize += strlen(DSO_EXTENSION); /* The length of ".so" */
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
rsize += 3; /* The length of "lib" */
}
translated = OPENSSL_malloc(rsize);
if (translated == NULL) {
DSOerr(DSO_F_DLFCN_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
return NULL;
}
if (transform) {
if ((DSO_flags(dso) & DSO_FLAG_NAME_TRANSLATION_EXT_ONLY) == 0)
sprintf(translated, "lib%s" DSO_EXTENSION, filename);
else
sprintf(translated, "%s" DSO_EXTENSION, filename);
} else
sprintf(translated, "%s", filename);
return translated;
}
# ifdef __sgi
/*-
This is a quote from IRIX manual for dladdr(3c):
<dlfcn.h> does not contain a prototype for dladdr or definition of
Dl_info. The #include <dlfcn.h> in the SYNOPSIS line is traditional,
but contains no dladdr prototype and no IRIX library contains an
implementation. Write your own declaration based on the code below.
The following code is dependent on internal interfaces that are not
part of the IRIX compatibility guarantee; however, there is no future
intention to change this interface, so on a practical level, the code
below is safe to use on IRIX.
*/
# include <rld_interface.h>
# ifndef _RLD_INTERFACE_DLFCN_H_DLADDR
# define _RLD_INTERFACE_DLFCN_H_DLADDR
typedef struct Dl_info {
const char *dli_fname;
void *dli_fbase;
const char *dli_sname;
void *dli_saddr;
int dli_version;
int dli_reserved1;
long dli_reserved[4];
} Dl_info;
# else
typedef struct Dl_info Dl_info;
# endif
# define _RLD_DLADDR 14
static int dladdr(void *address, Dl_info *dl)
{
void *v;
v = _rld_new_interface(_RLD_DLADDR, address, dl);
return (int)v;
}
# endif /* __sgi */
# ifdef _AIX
/*-
* See IBM's AIX Version 7.2, Technical Reference:
* Base Operating System and Extensions, Volume 1 and 2
* https://www.ibm.com/support/knowledgecenter/ssw_aix_72/com.ibm.aix.base/technicalreferences.htm
*/
# include <sys/ldr.h>
# include <errno.h>
/* ~ 64 * (sizeof(struct ld_info) + _XOPEN_PATH_MAX + _XOPEN_NAME_MAX) */
# define DLFCN_LDINFO_SIZE 86976
typedef struct Dl_info {
const char *dli_fname;
} Dl_info;
/*
* This dladdr()-implementation will also find the ptrgl (Pointer Glue) virtual
* address of a function, which is just located in the DATA segment instead of
* the TEXT segment.
*/
static int dladdr(void *ptr, Dl_info *dl)
{
uintptr_t addr = (uintptr_t)ptr;
unsigned int found = 0;
struct ld_info *ldinfos, *next_ldi, *this_ldi;
if ((ldinfos = OPENSSL_malloc(DLFCN_LDINFO_SIZE)) == NULL) {
errno = ENOMEM;
dl->dli_fname = NULL;
return 0;
}
if ((loadquery(L_GETINFO, (void *)ldinfos, DLFCN_LDINFO_SIZE)) < 0) {
/*-
* Error handling is done through errno and dlerror() reading errno:
* ENOMEM (ldinfos buffer is too small),
* EINVAL (invalid flags),
* EFAULT (invalid ldinfos ptr)
*/
OPENSSL_free((void *)ldinfos);
dl->dli_fname = NULL;
return 0;
}
next_ldi = ldinfos;
do {
this_ldi = next_ldi;
if (((addr >= (uintptr_t)this_ldi->ldinfo_textorg)
&& (addr < ((uintptr_t)this_ldi->ldinfo_textorg +
this_ldi->ldinfo_textsize)))
|| ((addr >= (uintptr_t)this_ldi->ldinfo_dataorg)
&& (addr < ((uintptr_t)this_ldi->ldinfo_dataorg +
this_ldi->ldinfo_datasize)))) {
char *buffer, *member;
size_t buffer_sz, member_len;
buffer_sz = strlen(this_ldi->ldinfo_filename) + 1;
member = this_ldi->ldinfo_filename + buffer_sz;
if ((member_len = strlen(member)) > 0)
buffer_sz += 1 + member_len + 1;
found = 1;
if ((buffer = OPENSSL_malloc(buffer_sz)) != NULL) {
OPENSSL_strlcpy(buffer, this_ldi->ldinfo_filename, buffer_sz);
if (member_len > 0) {
/*
* Need to respect a possible member name and not just
* returning the path name in this case. See docs:
* sys/ldr.h, loadquery() and dlopen()/RTLD_MEMBER.
*/
OPENSSL_strlcat(buffer, "(", buffer_sz);
OPENSSL_strlcat(buffer, member, buffer_sz);
OPENSSL_strlcat(buffer, ")", buffer_sz);
}
dl->dli_fname = buffer;
} else {
errno = ENOMEM;
}
} else {
next_ldi = (struct ld_info *)((uintptr_t)this_ldi +
this_ldi->ldinfo_next);
}
} while (this_ldi->ldinfo_next && !found);
OPENSSL_free((void *)ldinfos);
return (found && dl->dli_fname != NULL);
}
# endif /* _AIX */
static int dlfcn_pathbyaddr(void *addr, char *path, int sz)
{
# ifdef HAVE_DLINFO
Dl_info dli;
int len;
if (addr == NULL) {
union {
int (*f) (void *, char *, int);
void *p;
} t = {
dlfcn_pathbyaddr
};
addr = t.p;
}
if (dladdr(addr, &dli)) {
len = (int)strlen(dli.dli_fname);
if (sz <= 0) {
# ifdef _AIX
OPENSSL_free((void *)dli.dli_fname);
# endif
return len + 1;
}
if (len >= sz)
len = sz - 1;
memcpy(path, dli.dli_fname, len);
path[len++] = 0;
# ifdef _AIX
OPENSSL_free((void *)dli.dli_fname);
# endif
return len;
}
ERR_add_error_data(2, "dlfcn_pathbyaddr(): ", dlerror());
# endif
return -1;
}
static void *dlfcn_globallookup(const char *name)
{
void *ret = NULL, *handle = dlopen(NULL, RTLD_LAZY);
if (handle) {
ret = dlsym(handle, name);
dlclose(handle);
}
return ret;
}
#endif /* DSO_DLFCN */

View file

@ -0,0 +1,100 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/err.h>
#include "internal/dsoerr.h"
#ifndef OPENSSL_NO_ERR
static const ERR_STRING_DATA DSO_str_functs[] = {
{ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_BIND_FUNC, 0), "dlfcn_bind_func"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_LOAD, 0), "dlfcn_load"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_MERGER, 0), "dlfcn_merger"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_NAME_CONVERTER, 0),
"dlfcn_name_converter"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DLFCN_UNLOAD, 0), "dlfcn_unload"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DL_BIND_FUNC, 0), "dl_bind_func"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DL_LOAD, 0), "dl_load"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DL_MERGER, 0), "dl_merger"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DL_NAME_CONVERTER, 0), "dl_name_converter"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DL_UNLOAD, 0), "dl_unload"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_BIND_FUNC, 0), "DSO_bind_func"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_CONVERT_FILENAME, 0),
"DSO_convert_filename"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_CTRL, 0), "DSO_ctrl"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_FREE, 0), "DSO_free"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_GET_FILENAME, 0), "DSO_get_filename"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_GLOBAL_LOOKUP, 0), "DSO_global_lookup"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_LOAD, 0), "DSO_load"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_MERGE, 0), "DSO_merge"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_NEW_METHOD, 0), "DSO_new_method"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_PATHBYADDR, 0), "DSO_pathbyaddr"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_SET_FILENAME, 0), "DSO_set_filename"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_DSO_UP_REF, 0), "DSO_up_ref"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_BIND_SYM, 0), "vms_bind_sym"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_LOAD, 0), "vms_load"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_MERGER, 0), "vms_merger"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_VMS_UNLOAD, 0), "vms_unload"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_BIND_FUNC, 0), "win32_bind_func"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_GLOBALLOOKUP, 0), "win32_globallookup"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_JOINER, 0), "win32_joiner"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_LOAD, 0), "win32_load"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_MERGER, 0), "win32_merger"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_NAME_CONVERTER, 0),
"win32_name_converter"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_PATHBYADDR, 0), ""},
{ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_SPLITTER, 0), "win32_splitter"},
{ERR_PACK(ERR_LIB_DSO, DSO_F_WIN32_UNLOAD, 0), "win32_unload"},
{0, NULL}
};
static const ERR_STRING_DATA DSO_str_reasons[] = {
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_CTRL_FAILED), "control command failed"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_DSO_ALREADY_LOADED), "dso already loaded"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_EMPTY_FILE_STRUCTURE),
"empty file structure"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_FAILURE), "failure"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_FILENAME_TOO_BIG), "filename too big"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_FINISH_FAILED),
"cleanup method function failed"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_INCORRECT_FILE_SYNTAX),
"incorrect file syntax"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_LOAD_FAILED),
"could not load the shared library"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_NAME_TRANSLATION_FAILED),
"name translation failed"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_NO_FILENAME), "no filename"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_NULL_HANDLE),
"a null shared library handle was used"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_SET_FILENAME_FAILED),
"set filename failed"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_STACK_ERROR),
"the meth_data stack is corrupt"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_SYM_FAILURE),
"could not bind to the requested symbol name"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_UNLOAD_FAILED),
"could not unload the shared library"},
{ERR_PACK(ERR_LIB_DSO, 0, DSO_R_UNSUPPORTED),
"functionality not supported"},
{0, NULL}
};
#endif
int ERR_load_DSO_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (ERR_func_error_string(DSO_str_functs[0].error) == NULL) {
ERR_load_strings_const(DSO_str_functs);
ERR_load_strings_const(DSO_str_reasons);
}
#endif
return 1;
}

View file

@ -0,0 +1,350 @@
/*
* Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "dso_locl.h"
#include "internal/refcount.h"
static DSO_METHOD *default_DSO_meth = NULL;
static DSO *DSO_new_method(DSO_METHOD *meth)
{
DSO *ret;
if (default_DSO_meth == NULL) {
/*
* We default to DSO_METH_openssl() which in turn defaults to
* stealing the "best available" method. Will fallback to
* DSO_METH_null() in the worst case.
*/
default_DSO_meth = DSO_METHOD_openssl();
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->meth_data = sk_void_new_null();
if (ret->meth_data == NULL) {
/* sk_new doesn't generate any errors so we do */
DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
ret->meth = default_DSO_meth;
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
DSOerr(DSO_F_DSO_NEW_METHOD, ERR_R_MALLOC_FAILURE);
sk_void_free(ret->meth_data);
OPENSSL_free(ret);
return NULL;
}
if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
DSO_free(ret);
ret = NULL;
}
return ret;
}
DSO *DSO_new(void)
{
return DSO_new_method(NULL);
}
int DSO_free(DSO *dso)
{
int i;
if (dso == NULL)
return 1;
if (CRYPTO_DOWN_REF(&dso->references, &i, dso->lock) <= 0)
return 0;
REF_PRINT_COUNT("DSO", dso);
if (i > 0)
return 1;
REF_ASSERT_ISNT(i < 0);
if ((dso->flags & DSO_FLAG_NO_UNLOAD_ON_FREE) == 0) {
if ((dso->meth->dso_unload != NULL) && !dso->meth->dso_unload(dso)) {
DSOerr(DSO_F_DSO_FREE, DSO_R_UNLOAD_FAILED);
return 0;
}
}
if ((dso->meth->finish != NULL) && !dso->meth->finish(dso)) {
DSOerr(DSO_F_DSO_FREE, DSO_R_FINISH_FAILED);
return 0;
}
sk_void_free(dso->meth_data);
OPENSSL_free(dso->filename);
OPENSSL_free(dso->loaded_filename);
CRYPTO_THREAD_lock_free(dso->lock);
OPENSSL_free(dso);
return 1;
}
int DSO_flags(DSO *dso)
{
return ((dso == NULL) ? 0 : dso->flags);
}
int DSO_up_ref(DSO *dso)
{
int i;
if (dso == NULL) {
DSOerr(DSO_F_DSO_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (CRYPTO_UP_REF(&dso->references, &i, dso->lock) <= 0)
return 0;
REF_PRINT_COUNT("DSO", r);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
DSO *DSO_load(DSO *dso, const char *filename, DSO_METHOD *meth, int flags)
{
DSO *ret;
int allocated = 0;
if (dso == NULL) {
ret = DSO_new_method(meth);
if (ret == NULL) {
DSOerr(DSO_F_DSO_LOAD, ERR_R_MALLOC_FAILURE);
goto err;
}
allocated = 1;
/* Pass the provided flags to the new DSO object */
if (DSO_ctrl(ret, DSO_CTRL_SET_FLAGS, flags, NULL) < 0) {
DSOerr(DSO_F_DSO_LOAD, DSO_R_CTRL_FAILED);
goto err;
}
} else
ret = dso;
/* Don't load if we're currently already loaded */
if (ret->filename != NULL) {
DSOerr(DSO_F_DSO_LOAD, DSO_R_DSO_ALREADY_LOADED);
goto err;
}
/*
* filename can only be NULL if we were passed a dso that already has one
* set.
*/
if (filename != NULL)
if (!DSO_set_filename(ret, filename)) {
DSOerr(DSO_F_DSO_LOAD, DSO_R_SET_FILENAME_FAILED);
goto err;
}
filename = ret->filename;
if (filename == NULL) {
DSOerr(DSO_F_DSO_LOAD, DSO_R_NO_FILENAME);
goto err;
}
if (ret->meth->dso_load == NULL) {
DSOerr(DSO_F_DSO_LOAD, DSO_R_UNSUPPORTED);
goto err;
}
if (!ret->meth->dso_load(ret)) {
DSOerr(DSO_F_DSO_LOAD, DSO_R_LOAD_FAILED);
goto err;
}
/* Load succeeded */
return ret;
err:
if (allocated)
DSO_free(ret);
return NULL;
}
DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname)
{
DSO_FUNC_TYPE ret = NULL;
if ((dso == NULL) || (symname == NULL)) {
DSOerr(DSO_F_DSO_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (dso->meth->dso_bind_func == NULL) {
DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_UNSUPPORTED);
return NULL;
}
if ((ret = dso->meth->dso_bind_func(dso, symname)) == NULL) {
DSOerr(DSO_F_DSO_BIND_FUNC, DSO_R_SYM_FAILURE);
return NULL;
}
/* Success */
return ret;
}
/*
* I don't really like these *_ctrl functions very much to be perfectly
* honest. For one thing, I think I have to return a negative value for any
* error because possible DSO_ctrl() commands may return values such as
* "size"s that can legitimately be zero (making the standard
* "if (DSO_cmd(...))" form that works almost everywhere else fail at odd
* times. I'd prefer "output" values to be passed by reference and the return
* value as success/failure like usual ... but we conform when we must... :-)
*/
long DSO_ctrl(DSO *dso, int cmd, long larg, void *parg)
{
if (dso == NULL) {
DSOerr(DSO_F_DSO_CTRL, ERR_R_PASSED_NULL_PARAMETER);
return -1;
}
/*
* We should intercept certain generic commands and only pass control to
* the method-specific ctrl() function if it's something we don't handle.
*/
switch (cmd) {
case DSO_CTRL_GET_FLAGS:
return dso->flags;
case DSO_CTRL_SET_FLAGS:
dso->flags = (int)larg;
return 0;
case DSO_CTRL_OR_FLAGS:
dso->flags |= (int)larg;
return 0;
default:
break;
}
if ((dso->meth == NULL) || (dso->meth->dso_ctrl == NULL)) {
DSOerr(DSO_F_DSO_CTRL, DSO_R_UNSUPPORTED);
return -1;
}
return dso->meth->dso_ctrl(dso, cmd, larg, parg);
}
const char *DSO_get_filename(DSO *dso)
{
if (dso == NULL) {
DSOerr(DSO_F_DSO_GET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
return dso->filename;
}
int DSO_set_filename(DSO *dso, const char *filename)
{
char *copied;
if ((dso == NULL) || (filename == NULL)) {
DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (dso->loaded_filename) {
DSOerr(DSO_F_DSO_SET_FILENAME, DSO_R_DSO_ALREADY_LOADED);
return 0;
}
/* We'll duplicate filename */
copied = OPENSSL_strdup(filename);
if (copied == NULL) {
DSOerr(DSO_F_DSO_SET_FILENAME, ERR_R_MALLOC_FAILURE);
return 0;
}
OPENSSL_free(dso->filename);
dso->filename = copied;
return 1;
}
char *DSO_merge(DSO *dso, const char *filespec1, const char *filespec2)
{
char *result = NULL;
if (dso == NULL || filespec1 == NULL) {
DSOerr(DSO_F_DSO_MERGE, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
if (dso->merger != NULL)
result = dso->merger(dso, filespec1, filespec2);
else if (dso->meth->dso_merger != NULL)
result = dso->meth->dso_merger(dso, filespec1, filespec2);
}
return result;
}
char *DSO_convert_filename(DSO *dso, const char *filename)
{
char *result = NULL;
if (dso == NULL) {
DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (filename == NULL)
filename = dso->filename;
if (filename == NULL) {
DSOerr(DSO_F_DSO_CONVERT_FILENAME, DSO_R_NO_FILENAME);
return NULL;
}
if ((dso->flags & DSO_FLAG_NO_NAME_TRANSLATION) == 0) {
if (dso->name_converter != NULL)
result = dso->name_converter(dso, filename);
else if (dso->meth->dso_name_converter != NULL)
result = dso->meth->dso_name_converter(dso, filename);
}
if (result == NULL) {
result = OPENSSL_strdup(filename);
if (result == NULL) {
DSOerr(DSO_F_DSO_CONVERT_FILENAME, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
return result;
}
int DSO_pathbyaddr(void *addr, char *path, int sz)
{
DSO_METHOD *meth = default_DSO_meth;
if (meth == NULL)
meth = DSO_METHOD_openssl();
if (meth->pathbyaddr == NULL) {
DSOerr(DSO_F_DSO_PATHBYADDR, DSO_R_UNSUPPORTED);
return -1;
}
return (*meth->pathbyaddr) (addr, path, sz);
}
DSO *DSO_dsobyaddr(void *addr, int flags)
{
DSO *ret = NULL;
char *filename = NULL;
int len = DSO_pathbyaddr(addr, NULL, 0);
if (len < 0)
return NULL;
filename = OPENSSL_malloc(len);
if (filename != NULL
&& DSO_pathbyaddr(addr, filename, len) == len)
ret = DSO_load(NULL, filename, NULL, flags);
OPENSSL_free(filename);
return ret;
}
void *DSO_global_lookup(const char *name)
{
DSO_METHOD *meth = default_DSO_meth;
if (meth == NULL)
meth = DSO_METHOD_openssl();
if (meth->globallookup == NULL) {
DSOerr(DSO_F_DSO_GLOBAL_LOOKUP, DSO_R_UNSUPPORTED);
return NULL;
}
return (*meth->globallookup) (name);
}

View file

@ -0,0 +1,107 @@
/*
* Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/dso.h"
#include "internal/dso_conf.h"
#include "internal/refcount.h"
/**********************************************************************/
/* The low-level handle type used to refer to a loaded shared library */
struct dso_st {
DSO_METHOD *meth;
/*
* Standard dlopen uses a (void *). Win32 uses a HANDLE. VMS doesn't use
* anything but will need to cache the filename for use in the dso_bind
* handler. All in all, let each method control its own destiny.
* "Handles" and such go in a STACK.
*/
STACK_OF(void) *meth_data;
CRYPTO_REF_COUNT references;
int flags;
/*
* For use by applications etc ... use this for your bits'n'pieces, don't
* touch meth_data!
*/
CRYPTO_EX_DATA ex_data;
/*
* If this callback function pointer is set to non-NULL, then it will be
* used in DSO_load() in place of meth->dso_name_converter. NB: This
* should normally set using DSO_set_name_converter().
*/
DSO_NAME_CONVERTER_FUNC name_converter;
/*
* If this callback function pointer is set to non-NULL, then it will be
* used in DSO_load() in place of meth->dso_merger. NB: This should
* normally set using DSO_set_merger().
*/
DSO_MERGER_FUNC merger;
/*
* This is populated with (a copy of) the platform-independent filename
* used for this DSO.
*/
char *filename;
/*
* This is populated with (a copy of) the translated filename by which
* the DSO was actually loaded. It is NULL iff the DSO is not currently
* loaded. NB: This is here because the filename translation process may
* involve a callback being invoked more than once not only to convert to
* a platform-specific form, but also to try different filenames in the
* process of trying to perform a load. As such, this variable can be
* used to indicate (a) whether this DSO structure corresponds to a
* loaded library or not, and (b) the filename with which it was actually
* loaded.
*/
char *loaded_filename;
CRYPTO_RWLOCK *lock;
};
struct dso_meth_st {
const char *name;
/*
* Loads a shared library, NB: new DSO_METHODs must ensure that a
* successful load populates the loaded_filename field, and likewise a
* successful unload OPENSSL_frees and NULLs it out.
*/
int (*dso_load) (DSO *dso);
/* Unloads a shared library */
int (*dso_unload) (DSO *dso);
/*
* Binds a function - assumes a return type of DSO_FUNC_TYPE. This should
* be cast to the real function prototype by the caller. Platforms that
* don't have compatible representations for different prototypes (this
* is possible within ANSI C) are highly unlikely to have shared
* libraries at all, let alone a DSO_METHOD implemented for them.
*/
DSO_FUNC_TYPE (*dso_bind_func) (DSO *dso, const char *symname);
/*
* The generic (yuck) "ctrl()" function. NB: Negative return values
* (rather than zero) indicate errors.
*/
long (*dso_ctrl) (DSO *dso, int cmd, long larg, void *parg);
/*
* The default DSO_METHOD-specific function for converting filenames to a
* canonical native form.
*/
DSO_NAME_CONVERTER_FUNC dso_name_converter;
/*
* The default DSO_METHOD-specific function for converting filenames to a
* canonical native form.
*/
DSO_MERGER_FUNC dso_merger;
/* [De]Initialisation handlers. */
int (*init) (DSO *dso);
int (*finish) (DSO *dso);
/* Return pathname of the module containing location */
int (*pathbyaddr) (void *addr, char *path, int sz);
/* Perform global symbol lookup, i.e. among *all* modules */
void *(*globallookup) (const char *symname);
};

View file

@ -0,0 +1,22 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "dso_locl.h"
#if !defined(DSO_VMS) && !defined(DSO_DLCFN) && !defined(DSO_DL) && !defined(DSO_WIN32) && !defined(DSO_DLFCN)
static DSO_METHOD dso_meth_null = {
"NULL shared library method"
};
DSO_METHOD *DSO_METHOD_openssl(void)
{
return &dso_meth_null;
}
#endif

View file

@ -0,0 +1,466 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "dso_locl.h"
#ifdef OPENSSL_SYS_VMS
# pragma message disable DOLLARID
# include <errno.h>
# include <rms.h>
# include <lib$routines.h>
# include <libfisdef.h>
# include <stsdef.h>
# include <descrip.h>
# include <starlet.h>
# include "../vms_rms.h"
/* Some compiler options may mask the declaration of "_malloc32". */
# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE
# if __INITIAL_POINTER_SIZE == 64
# pragma pointer_size save
# pragma pointer_size 32
void *_malloc32(__size_t);
# pragma pointer_size restore
# endif /* __INITIAL_POINTER_SIZE == 64 */
# endif /* __INITIAL_POINTER_SIZE && defined
* _ANSI_C_SOURCE */
# pragma message disable DOLLARID
static int vms_load(DSO *dso);
static int vms_unload(DSO *dso);
static DSO_FUNC_TYPE vms_bind_func(DSO *dso, const char *symname);
static char *vms_name_converter(DSO *dso, const char *filename);
static char *vms_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static DSO_METHOD dso_meth_vms = {
"OpenSSL 'VMS' shared library method",
vms_load,
NULL, /* unload */
vms_bind_func,
NULL, /* ctrl */
vms_name_converter,
vms_merger,
NULL, /* init */
NULL, /* finish */
NULL, /* pathbyaddr */
NULL /* globallookup */
};
/*
* On VMS, the only "handle" is the file name. LIB$FIND_IMAGE_SYMBOL depends
* on the reference to the file name being the same for all calls regarding
* one shared image, so we'll just store it in an instance of the following
* structure and put a pointer to that instance in the meth_data stack.
*/
typedef struct dso_internal_st {
/*
* This should contain the name only, no directory, no extension, nothing
* but a name.
*/
struct dsc$descriptor_s filename_dsc;
char filename[NAMX_MAXRSS + 1];
/*
* This contains whatever is not in filename, if needed. Normally not
* defined.
*/
struct dsc$descriptor_s imagename_dsc;
char imagename[NAMX_MAXRSS + 1];
} DSO_VMS_INTERNAL;
DSO_METHOD *DSO_METHOD_openssl(void)
{
return &dso_meth_vms;
}
static int vms_load(DSO *dso)
{
void *ptr = NULL;
/* See applicable comments in dso_dl.c */
char *filename = DSO_convert_filename(dso, NULL);
/* Ensure 32-bit pointer for "p", and appropriate malloc() function. */
# if __INITIAL_POINTER_SIZE == 64
# define DSO_MALLOC _malloc32
# pragma pointer_size save
# pragma pointer_size 32
# else /* __INITIAL_POINTER_SIZE == 64 */
# define DSO_MALLOC OPENSSL_malloc
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
DSO_VMS_INTERNAL *p = NULL;
# if __INITIAL_POINTER_SIZE == 64
# pragma pointer_size restore
# endif /* __INITIAL_POINTER_SIZE == 64 */
const char *sp1, *sp2; /* Search result */
const char *ext = NULL; /* possible extension to add */
if (filename == NULL) {
DSOerr(DSO_F_VMS_LOAD, DSO_R_NO_FILENAME);
goto err;
}
/*-
* A file specification may look like this:
*
* node::dev:[dir-spec]name.type;ver
*
* or (for compatibility with TOPS-20):
*
* node::dev:<dir-spec>name.type;ver
*
* and the dir-spec uses '.' as separator. Also, a dir-spec
* may consist of several parts, with mixed use of [] and <>:
*
* [dir1.]<dir2>
*
* We need to split the file specification into the name and
* the rest (both before and after the name itself).
*/
/*
* Start with trying to find the end of a dir-spec, and save the position
* of the byte after in sp1
*/
sp1 = strrchr(filename, ']');
sp2 = strrchr(filename, '>');
if (sp1 == NULL)
sp1 = sp2;
if (sp2 != NULL && sp2 > sp1)
sp1 = sp2;
if (sp1 == NULL)
sp1 = strrchr(filename, ':');
if (sp1 == NULL)
sp1 = filename;
else
sp1++; /* The byte after the found character */
/* Now, let's see if there's a type, and save the position in sp2 */
sp2 = strchr(sp1, '.');
/*
* If there is a period and the next character is a semi-colon,
* we need to add an extension
*/
if (sp2 != NULL && sp2[1] == ';')
ext = ".EXE";
/*
* If we found it, that's where we'll cut. Otherwise, look for a version
* number and save the position in sp2
*/
if (sp2 == NULL) {
sp2 = strchr(sp1, ';');
ext = ".EXE";
}
/*
* If there was still nothing to find, set sp2 to point at the end of the
* string
*/
if (sp2 == NULL)
sp2 = sp1 + strlen(sp1);
/* Check that we won't get buffer overflows */
if (sp2 - sp1 > FILENAME_MAX
|| (sp1 - filename) + strlen(sp2) > FILENAME_MAX) {
DSOerr(DSO_F_VMS_LOAD, DSO_R_FILENAME_TOO_BIG);
goto err;
}
p = DSO_MALLOC(sizeof(*p));
if (p == NULL) {
DSOerr(DSO_F_VMS_LOAD, ERR_R_MALLOC_FAILURE);
goto err;
}
strncpy(p->filename, sp1, sp2 - sp1);
p->filename[sp2 - sp1] = '\0';
strncpy(p->imagename, filename, sp1 - filename);
p->imagename[sp1 - filename] = '\0';
if (ext) {
strcat(p->imagename, ext);
if (*sp2 == '.')
sp2++;
}
strcat(p->imagename, sp2);
p->filename_dsc.dsc$w_length = strlen(p->filename);
p->filename_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
p->filename_dsc.dsc$b_class = DSC$K_CLASS_S;
p->filename_dsc.dsc$a_pointer = p->filename;
p->imagename_dsc.dsc$w_length = strlen(p->imagename);
p->imagename_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
p->imagename_dsc.dsc$b_class = DSC$K_CLASS_S;
p->imagename_dsc.dsc$a_pointer = p->imagename;
if (!sk_void_push(dso->meth_data, (char *)p)) {
DSOerr(DSO_F_VMS_LOAD, DSO_R_STACK_ERROR);
goto err;
}
/* Success (for now, we lie. We actually do not know...) */
dso->loaded_filename = filename;
return 1;
err:
/* Cleanup! */
OPENSSL_free(p);
OPENSSL_free(filename);
return 0;
}
/*
* Note that this doesn't actually unload the shared image, as there is no
* such thing in VMS. Next time it get loaded again, a new copy will
* actually be loaded.
*/
static int vms_unload(DSO *dso)
{
DSO_VMS_INTERNAL *p;
if (dso == NULL) {
DSOerr(DSO_F_VMS_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (sk_void_num(dso->meth_data) < 1)
return 1;
p = (DSO_VMS_INTERNAL *)sk_void_pop(dso->meth_data);
if (p == NULL) {
DSOerr(DSO_F_VMS_UNLOAD, DSO_R_NULL_HANDLE);
return 0;
}
/* Cleanup */
OPENSSL_free(p);
return 1;
}
/*
* We must do this in a separate function because of the way the exception
* handler works (it makes this function return
*/
static int do_find_symbol(DSO_VMS_INTERNAL *ptr,
struct dsc$descriptor_s *symname_dsc, void **sym,
unsigned long flags)
{
/*
* Make sure that signals are caught and returned instead of aborting the
* program. The exception handler gets unestablished automatically on
* return from this function.
*/
lib$establish(lib$sig_to_ret);
if (ptr->imagename_dsc.dsc$w_length)
return lib$find_image_symbol(&ptr->filename_dsc,
symname_dsc, sym,
&ptr->imagename_dsc, flags);
else
return lib$find_image_symbol(&ptr->filename_dsc,
symname_dsc, sym, 0, flags);
}
# ifndef LIB$M_FIS_MIXEDCASE
# define LIB$M_FIS_MIXEDCASE (1 << 4);
# endif
void vms_bind_sym(DSO *dso, const char *symname, void **sym)
{
DSO_VMS_INTERNAL *ptr;
int status = 0;
struct dsc$descriptor_s symname_dsc;
/* Arrange 32-bit pointer to (copied) string storage, if needed. */
# if __INITIAL_POINTER_SIZE == 64
# define SYMNAME symname_32p
# pragma pointer_size save
# pragma pointer_size 32
char *symname_32p;
# pragma pointer_size restore
char symname_32[NAMX_MAXRSS + 1];
# else /* __INITIAL_POINTER_SIZE == 64 */
# define SYMNAME ((char *) symname)
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
*sym = NULL;
if ((dso == NULL) || (symname == NULL)) {
DSOerr(DSO_F_VMS_BIND_SYM, ERR_R_PASSED_NULL_PARAMETER);
return;
}
# if __INITIAL_POINTER_SIZE == 64
/* Copy the symbol name to storage with a 32-bit pointer. */
symname_32p = symname_32;
strcpy(symname_32p, symname);
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
symname_dsc.dsc$w_length = strlen(SYMNAME);
symname_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
symname_dsc.dsc$b_class = DSC$K_CLASS_S;
symname_dsc.dsc$a_pointer = SYMNAME;
if (sk_void_num(dso->meth_data) < 1) {
DSOerr(DSO_F_VMS_BIND_SYM, DSO_R_STACK_ERROR);
return;
}
ptr = (DSO_VMS_INTERNAL *)sk_void_value(dso->meth_data,
sk_void_num(dso->meth_data) - 1);
if (ptr == NULL) {
DSOerr(DSO_F_VMS_BIND_SYM, DSO_R_NULL_HANDLE);
return;
}
status = do_find_symbol(ptr, &symname_dsc, sym, LIB$M_FIS_MIXEDCASE);
if (!$VMS_STATUS_SUCCESS(status))
status = do_find_symbol(ptr, &symname_dsc, sym, 0);
if (!$VMS_STATUS_SUCCESS(status)) {
unsigned short length;
char errstring[257];
struct dsc$descriptor_s errstring_dsc;
errstring_dsc.dsc$w_length = sizeof(errstring);
errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
errstring_dsc.dsc$b_class = DSC$K_CLASS_S;
errstring_dsc.dsc$a_pointer = errstring;
*sym = NULL;
status = sys$getmsg(status, &length, &errstring_dsc, 1, 0);
if (!$VMS_STATUS_SUCCESS(status))
lib$signal(status); /* This is really bad. Abort! */
else {
errstring[length] = '\0';
DSOerr(DSO_F_VMS_BIND_SYM, DSO_R_SYM_FAILURE);
if (ptr->imagename_dsc.dsc$w_length)
ERR_add_error_data(9,
"Symbol ", symname,
" in ", ptr->filename,
" (", ptr->imagename, ")",
": ", errstring);
else
ERR_add_error_data(6,
"Symbol ", symname,
" in ", ptr->filename, ": ", errstring);
}
return;
}
return;
}
static DSO_FUNC_TYPE vms_bind_func(DSO *dso, const char *symname)
{
DSO_FUNC_TYPE sym = 0;
vms_bind_sym(dso, symname, (void **)&sym);
return sym;
}
static char *vms_merger(DSO *dso, const char *filespec1,
const char *filespec2)
{
int status;
int filespec1len, filespec2len;
struct FAB fab;
struct NAMX_STRUCT nam;
char esa[NAMX_MAXRSS + 1];
char *merged;
/* Arrange 32-bit pointer to (copied) string storage, if needed. */
# if __INITIAL_POINTER_SIZE == 64
# define FILESPEC1 filespec1_32p;
# define FILESPEC2 filespec2_32p;
# pragma pointer_size save
# pragma pointer_size 32
char *filespec1_32p;
char *filespec2_32p;
# pragma pointer_size restore
char filespec1_32[NAMX_MAXRSS + 1];
char filespec2_32[NAMX_MAXRSS + 1];
# else /* __INITIAL_POINTER_SIZE == 64 */
# define FILESPEC1 ((char *) filespec1)
# define FILESPEC2 ((char *) filespec2)
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
if (!filespec1)
filespec1 = "";
if (!filespec2)
filespec2 = "";
filespec1len = strlen(filespec1);
filespec2len = strlen(filespec2);
# if __INITIAL_POINTER_SIZE == 64
/* Copy the file names to storage with a 32-bit pointer. */
filespec1_32p = filespec1_32;
filespec2_32p = filespec2_32;
strcpy(filespec1_32p, filespec1);
strcpy(filespec2_32p, filespec2);
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
fab = cc$rms_fab;
nam = CC_RMS_NAMX;
FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = FILESPEC1;
FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = filespec1len;
FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNA = FILESPEC2;
FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNS = filespec2len;
NAMX_DNA_FNA_SET(fab)
nam.NAMX_ESA = esa;
nam.NAMX_ESS = NAMX_MAXRSS;
nam.NAMX_NOP = NAM$M_SYNCHK | NAM$M_PWD;
SET_NAMX_NO_SHORT_UPCASE(nam);
fab.FAB_NAMX = &nam;
status = sys$parse(&fab, 0, 0);
if (!$VMS_STATUS_SUCCESS(status)) {
unsigned short length;
char errstring[257];
struct dsc$descriptor_s errstring_dsc;
errstring_dsc.dsc$w_length = sizeof(errstring);
errstring_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
errstring_dsc.dsc$b_class = DSC$K_CLASS_S;
errstring_dsc.dsc$a_pointer = errstring;
status = sys$getmsg(status, &length, &errstring_dsc, 1, 0);
if (!$VMS_STATUS_SUCCESS(status))
lib$signal(status); /* This is really bad. Abort! */
else {
errstring[length] = '\0';
DSOerr(DSO_F_VMS_MERGER, DSO_R_FAILURE);
ERR_add_error_data(7,
"filespec \"", filespec1, "\", ",
"defaults \"", filespec2, "\": ", errstring);
}
return NULL;
}
merged = OPENSSL_malloc(nam.NAMX_ESL + 1);
if (merged == NULL)
goto malloc_err;
strncpy(merged, nam.NAMX_ESA, nam.NAMX_ESL);
merged[nam.NAMX_ESL] = '\0';
return merged;
malloc_err:
DSOerr(DSO_F_VMS_MERGER, ERR_R_MALLOC_FAILURE);
}
static char *vms_name_converter(DSO *dso, const char *filename)
{
int len = strlen(filename);
char *not_translated = OPENSSL_malloc(len + 1);
if (not_translated != NULL)
strcpy(not_translated, filename);
return not_translated;
}
#endif /* OPENSSL_SYS_VMS */

View file

@ -0,0 +1,566 @@
/*
* Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "e_os.h"
#include "dso_locl.h"
#if defined(DSO_WIN32)
# ifdef _WIN32_WCE
# if _WIN32_WCE < 300
static FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName)
{
WCHAR lpProcNameW[64];
int i;
for (i = 0; lpProcName[i] && i < 64; i++)
lpProcNameW[i] = (WCHAR)lpProcName[i];
if (i == 64)
return NULL;
lpProcNameW[i] = 0;
return GetProcAddressW(hModule, lpProcNameW);
}
# endif
# undef GetProcAddress
# define GetProcAddress GetProcAddressA
static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName)
{
WCHAR *fnamw;
size_t len_0 = strlen(lpLibFileName) + 1, i;
# ifdef _MSC_VER
fnamw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR));
# else
fnamw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
# endif
if (fnamw == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
# if defined(_WIN32_WCE) && _WIN32_WCE>=101
if (!MultiByteToWideChar(CP_ACP, 0, lpLibFileName, len_0, fnamw, len_0))
# endif
for (i = 0; i < len_0; i++)
fnamw[i] = (WCHAR)lpLibFileName[i];
return LoadLibraryW(fnamw);
}
# endif
/* Part of the hack in "win32_load" ... */
# define DSO_MAX_TRANSLATED_SIZE 256
static int win32_load(DSO *dso);
static int win32_unload(DSO *dso);
static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname);
static char *win32_name_converter(DSO *dso, const char *filename);
static char *win32_merger(DSO *dso, const char *filespec1,
const char *filespec2);
static void *win32_globallookup(const char *name);
static const char *openssl_strnchr(const char *string, int c, size_t len);
static DSO_METHOD dso_meth_win32 = {
"OpenSSL 'win32' shared library method",
win32_load,
win32_unload,
win32_bind_func,
NULL, /* ctrl */
win32_name_converter,
win32_merger,
NULL, /* init */
NULL, /* finish */
NULL, /* pathbyaddr */
win32_globallookup
};
DSO_METHOD *DSO_METHOD_openssl(void)
{
return &dso_meth_win32;
}
/*
* For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to
* the handle (HINSTANCE) returned from LoadLibrary(), and copied.
*/
static int win32_load(DSO *dso)
{
HINSTANCE h = NULL, *p = NULL;
/* See applicable comments from dso_dl.c */
char *filename = DSO_convert_filename(dso, NULL);
if (filename == NULL) {
DSOerr(DSO_F_WIN32_LOAD, DSO_R_NO_FILENAME);
goto err;
}
h = LoadLibraryA(filename);
if (h == NULL) {
DSOerr(DSO_F_WIN32_LOAD, DSO_R_LOAD_FAILED);
ERR_add_error_data(3, "filename(", filename, ")");
goto err;
}
p = OPENSSL_malloc(sizeof(*p));
if (p == NULL) {
DSOerr(DSO_F_WIN32_LOAD, ERR_R_MALLOC_FAILURE);
goto err;
}
*p = h;
if (!sk_void_push(dso->meth_data, p)) {
DSOerr(DSO_F_WIN32_LOAD, DSO_R_STACK_ERROR);
goto err;
}
/* Success */
dso->loaded_filename = filename;
return 1;
err:
/* Cleanup ! */
OPENSSL_free(filename);
OPENSSL_free(p);
if (h != NULL)
FreeLibrary(h);
return 0;
}
static int win32_unload(DSO *dso)
{
HINSTANCE *p;
if (dso == NULL) {
DSOerr(DSO_F_WIN32_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (sk_void_num(dso->meth_data) < 1)
return 1;
p = sk_void_pop(dso->meth_data);
if (p == NULL) {
DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_NULL_HANDLE);
return 0;
}
if (!FreeLibrary(*p)) {
DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_UNLOAD_FAILED);
/*
* We should push the value back onto the stack in case of a retry.
*/
sk_void_push(dso->meth_data, p);
return 0;
}
/* Cleanup */
OPENSSL_free(p);
return 1;
}
static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname)
{
HINSTANCE *ptr;
union {
void *p;
FARPROC f;
} sym;
if ((dso == NULL) || (symname == NULL)) {
DSOerr(DSO_F_WIN32_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (sk_void_num(dso->meth_data) < 1) {
DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_STACK_ERROR);
return NULL;
}
ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
if (ptr == NULL) {
DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_NULL_HANDLE);
return NULL;
}
sym.f = GetProcAddress(*ptr, symname);
if (sym.p == NULL) {
DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_SYM_FAILURE);
ERR_add_error_data(3, "symname(", symname, ")");
return NULL;
}
return (DSO_FUNC_TYPE)sym.f;
}
struct file_st {
const char *node;
int nodelen;
const char *device;
int devicelen;
const char *predir;
int predirlen;
const char *dir;
int dirlen;
const char *file;
int filelen;
};
static struct file_st *win32_splitter(DSO *dso, const char *filename,
int assume_last_is_dir)
{
struct file_st *result = NULL;
enum { IN_NODE, IN_DEVICE, IN_FILE } position;
const char *start = filename;
char last;
if (!filename) {
DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_NO_FILENAME);
return NULL;
}
result = OPENSSL_zalloc(sizeof(*result));
if (result == NULL) {
DSOerr(DSO_F_WIN32_SPLITTER, ERR_R_MALLOC_FAILURE);
return NULL;
}
position = IN_DEVICE;
if ((filename[0] == '\\' && filename[1] == '\\')
|| (filename[0] == '/' && filename[1] == '/')) {
position = IN_NODE;
filename += 2;
start = filename;
result->node = start;
}
do {
last = filename[0];
switch (last) {
case ':':
if (position != IN_DEVICE) {
DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_INCORRECT_FILE_SYNTAX);
OPENSSL_free(result);
return NULL;
}
result->device = start;
result->devicelen = (int)(filename - start);
position = IN_FILE;
start = ++filename;
result->dir = start;
break;
case '\\':
case '/':
if (position == IN_NODE) {
result->nodelen = (int)(filename - start);
position = IN_FILE;
start = ++filename;
result->dir = start;
} else if (position == IN_DEVICE) {
position = IN_FILE;
filename++;
result->dir = start;
result->dirlen = (int)(filename - start);
start = filename;
} else {
filename++;
result->dirlen += (int)(filename - start);
start = filename;
}
break;
case '\0':
if (position == IN_NODE) {
result->nodelen = (int)(filename - start);
} else {
if (filename - start > 0) {
if (assume_last_is_dir) {
if (position == IN_DEVICE) {
result->dir = start;
result->dirlen = 0;
}
result->dirlen += (int)(filename - start);
} else {
result->file = start;
result->filelen = (int)(filename - start);
}
}
}
break;
default:
filename++;
break;
}
}
while (last);
if (!result->nodelen)
result->node = NULL;
if (!result->devicelen)
result->device = NULL;
if (!result->dirlen)
result->dir = NULL;
if (!result->filelen)
result->file = NULL;
return result;
}
static char *win32_joiner(DSO *dso, const struct file_st *file_split)
{
int len = 0, offset = 0;
char *result = NULL;
const char *start;
if (!file_split) {
DSOerr(DSO_F_WIN32_JOINER, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (file_split->node) {
len += 2 + file_split->nodelen; /* 2 for starting \\ */
if (file_split->predir || file_split->dir || file_split->file)
len++; /* 1 for ending \ */
} else if (file_split->device) {
len += file_split->devicelen + 1; /* 1 for ending : */
}
len += file_split->predirlen;
if (file_split->predir && (file_split->dir || file_split->file)) {
len++; /* 1 for ending \ */
}
len += file_split->dirlen;
if (file_split->dir && file_split->file) {
len++; /* 1 for ending \ */
}
len += file_split->filelen;
if (!len) {
DSOerr(DSO_F_WIN32_JOINER, DSO_R_EMPTY_FILE_STRUCTURE);
return NULL;
}
result = OPENSSL_malloc(len + 1);
if (result == NULL) {
DSOerr(DSO_F_WIN32_JOINER, ERR_R_MALLOC_FAILURE);
return NULL;
}
if (file_split->node) {
strcpy(&result[offset], "\\\\");
offset += 2;
strncpy(&result[offset], file_split->node, file_split->nodelen);
offset += file_split->nodelen;
if (file_split->predir || file_split->dir || file_split->file) {
result[offset] = '\\';
offset++;
}
} else if (file_split->device) {
strncpy(&result[offset], file_split->device, file_split->devicelen);
offset += file_split->devicelen;
result[offset] = ':';
offset++;
}
start = file_split->predir;
while (file_split->predirlen > (start - file_split->predir)) {
const char *end = openssl_strnchr(start, '/',
file_split->predirlen - (start -
file_split->predir));
if (!end)
end = start
+ file_split->predirlen - (start - file_split->predir);
strncpy(&result[offset], start, end - start);
offset += (int)(end - start);
result[offset] = '\\';
offset++;
start = end + 1;
}
start = file_split->dir;
while (file_split->dirlen > (start - file_split->dir)) {
const char *end = openssl_strnchr(start, '/',
file_split->dirlen - (start -
file_split->dir));
if (!end)
end = start + file_split->dirlen - (start - file_split->dir);
strncpy(&result[offset], start, end - start);
offset += (int)(end - start);
result[offset] = '\\';
offset++;
start = end + 1;
}
strncpy(&result[offset], file_split->file, file_split->filelen);
offset += file_split->filelen;
result[offset] = '\0';
return result;
}
static char *win32_merger(DSO *dso, const char *filespec1,
const char *filespec2)
{
char *merged = NULL;
struct file_st *filespec1_split = NULL;
struct file_st *filespec2_split = NULL;
if (!filespec1 && !filespec2) {
DSOerr(DSO_F_WIN32_MERGER, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (!filespec2) {
merged = OPENSSL_strdup(filespec1);
if (merged == NULL) {
DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else if (!filespec1) {
merged = OPENSSL_strdup(filespec2);
if (merged == NULL) {
DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
return NULL;
}
} else {
filespec1_split = win32_splitter(dso, filespec1, 0);
if (!filespec1_split) {
DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
return NULL;
}
filespec2_split = win32_splitter(dso, filespec2, 1);
if (!filespec2_split) {
DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
OPENSSL_free(filespec1_split);
return NULL;
}
/* Fill in into filespec1_split */
if (!filespec1_split->node && !filespec1_split->device) {
filespec1_split->node = filespec2_split->node;
filespec1_split->nodelen = filespec2_split->nodelen;
filespec1_split->device = filespec2_split->device;
filespec1_split->devicelen = filespec2_split->devicelen;
}
if (!filespec1_split->dir) {
filespec1_split->dir = filespec2_split->dir;
filespec1_split->dirlen = filespec2_split->dirlen;
} else if (filespec1_split->dir[0] != '\\'
&& filespec1_split->dir[0] != '/') {
filespec1_split->predir = filespec2_split->dir;
filespec1_split->predirlen = filespec2_split->dirlen;
}
if (!filespec1_split->file) {
filespec1_split->file = filespec2_split->file;
filespec1_split->filelen = filespec2_split->filelen;
}
merged = win32_joiner(dso, filespec1_split);
}
OPENSSL_free(filespec1_split);
OPENSSL_free(filespec2_split);
return merged;
}
static char *win32_name_converter(DSO *dso, const char *filename)
{
char *translated;
int len, transform;
len = strlen(filename);
transform = ((strstr(filename, "/") == NULL) &&
(strstr(filename, "\\") == NULL) &&
(strstr(filename, ":") == NULL));
if (transform)
/* We will convert this to "%s.dll" */
translated = OPENSSL_malloc(len + 5);
else
/* We will simply duplicate filename */
translated = OPENSSL_malloc(len + 1);
if (translated == NULL) {
DSOerr(DSO_F_WIN32_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
return NULL;
}
if (transform)
sprintf(translated, "%s.dll", filename);
else
sprintf(translated, "%s", filename);
return translated;
}
static const char *openssl_strnchr(const char *string, int c, size_t len)
{
size_t i;
const char *p;
for (i = 0, p = string; i < len && *p; i++, p++) {
if (*p == c)
return p;
}
return NULL;
}
# include <tlhelp32.h>
# ifdef _WIN32_WCE
# define DLLNAME "TOOLHELP.DLL"
# else
# ifdef MODULEENTRY32
# undef MODULEENTRY32 /* unmask the ASCII version! */
# endif
# define DLLNAME "KERNEL32.DLL"
# endif
typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *);
static void *win32_globallookup(const char *name)
{
HMODULE dll;
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
CREATETOOLHELP32SNAPSHOT create_snap;
CLOSETOOLHELP32SNAPSHOT close_snap;
MODULE32 module_first, module_next;
union {
void *p;
FARPROC f;
} ret = { NULL };
dll = LoadLibrary(TEXT(DLLNAME));
if (dll == NULL) {
DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
return NULL;
}
create_snap = (CREATETOOLHELP32SNAPSHOT)
GetProcAddress(dll, "CreateToolhelp32Snapshot");
if (create_snap == NULL) {
FreeLibrary(dll);
DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
return NULL;
}
/* We take the rest for granted... */
# ifdef _WIN32_WCE
close_snap = (CLOSETOOLHELP32SNAPSHOT)
GetProcAddress(dll, "CloseToolhelp32Snapshot");
# else
close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
# endif
module_first = (MODULE32) GetProcAddress(dll, "Module32First");
module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
if (hModuleSnap == INVALID_HANDLE_VALUE) {
FreeLibrary(dll);
DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
return NULL;
}
me32.dwSize = sizeof(me32);
if (!(*module_first) (hModuleSnap, &me32)) {
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
return NULL;
}
do {
if ((ret.f = GetProcAddress(me32.hModule, name))) {
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
return ret.p;
}
} while ((*module_next) (hModuleSnap, &me32));
(*close_snap) (hModuleSnap);
FreeLibrary(dll);
return NULL;
}
#endif /* DSO_WIN32 */