зеркало из https://github.com/mozilla/gecko-dev.git
779 строки
20 KiB
C
779 строки
20 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* Allow freebl and softoken to be loaded without util or NSPR.
|
|
*
|
|
* These symbols are overridden once real NSPR, and libutil are attached.
|
|
*/
|
|
#define _GNU_SOURCE 1
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <sys/time.h>
|
|
#include <dlfcn.h>
|
|
#include <prio.h>
|
|
#include <prlink.h>
|
|
#include <prlog.h>
|
|
#include <prthread.h>
|
|
#include <plstr.h>
|
|
#include <prinit.h>
|
|
#include <prlock.h>
|
|
#include <prmem.h>
|
|
#include <prerror.h>
|
|
#include <prmon.h>
|
|
#include <pratom.h>
|
|
#include <prsystem.h>
|
|
#include <prinrval.h>
|
|
#include <prtime.h>
|
|
#include <prcvar.h>
|
|
#include <secasn1.h>
|
|
#include <secdig.h>
|
|
#include <secport.h>
|
|
#include <secitem.h>
|
|
#include <blapi.h>
|
|
#include <private/pprio.h>
|
|
|
|
/* Android API < 21 doesn't define RTLD_NOLOAD */
|
|
#ifndef RTLD_NOLOAD
|
|
#define RTLD_NOLOAD 0
|
|
#endif
|
|
|
|
#define FREEBL_NO_WEAK 1
|
|
|
|
#define WEAK __attribute__((weak))
|
|
|
|
#ifdef FREEBL_NO_WEAK
|
|
|
|
/*
|
|
* This uses function pointers.
|
|
*
|
|
* CONS: A separate function is needed to
|
|
* fill in the function pointers.
|
|
*
|
|
* PROS: it works on all platforms.
|
|
* it allows for dynamically finding nspr and libutil, even once
|
|
* softoken is loaded and running. (NOTE: this may be a problem if
|
|
* we switch between the stubs and real NSPR on the fly. NSPR will
|
|
* do bad things if passed an _FakeArena to free or allocate from).
|
|
*/
|
|
#define STUB_DECLARE(ret, fn, args) \
|
|
typedef ret(*type_##fn) args; \
|
|
static type_##fn ptr_##fn = NULL
|
|
|
|
#define STUB_SAFE_CALL0(fn) \
|
|
if (ptr_##fn) { \
|
|
return ptr_##fn(); \
|
|
}
|
|
#define STUB_SAFE_CALL1(fn, a1) \
|
|
if (ptr_##fn) { \
|
|
return ptr_##fn(a1); \
|
|
}
|
|
#define STUB_SAFE_CALL2(fn, a1, a2) \
|
|
if (ptr_##fn) { \
|
|
return ptr_##fn(a1, a2); \
|
|
}
|
|
#define STUB_SAFE_CALL3(fn, a1, a2, a3) \
|
|
if (ptr_##fn) { \
|
|
return ptr_##fn(a1, a2, a3); \
|
|
}
|
|
#define STUB_SAFE_CALL4(fn, a1, a2, a3, a4) \
|
|
if (ptr_##fn) { \
|
|
return ptr_##fn(a1, a2, a3, a4); \
|
|
}
|
|
#define STUB_SAFE_CALL6(fn, a1, a2, a3, a4, a5, a6) \
|
|
if (ptr_##fn) { \
|
|
return ptr_##fn(a1, a2, a3, a4, a5, a6); \
|
|
}
|
|
|
|
#define STUB_FETCH_FUNCTION(fn) \
|
|
ptr_##fn = (type_##fn)dlsym(lib, #fn); \
|
|
if (ptr_##fn == NULL) { \
|
|
return SECFailure; \
|
|
}
|
|
|
|
#else
|
|
/*
|
|
* this uses the loader weak attribute. it works automatically, but once
|
|
* freebl is loaded, the symbols are 'fixed' (later loading of NSPR or
|
|
* libutil will not resolve these symbols).
|
|
*/
|
|
|
|
#define STUB_DECLARE(ret, fn, args) \
|
|
WEAK extern ret fn args
|
|
|
|
#define STUB_SAFE_CALL0(fn) \
|
|
if (fn) { \
|
|
return fn(); \
|
|
}
|
|
#define STUB_SAFE_CALL1(fn, a1) \
|
|
if (fn) { \
|
|
return fn(a1); \
|
|
}
|
|
#define STUB_SAFE_CALL2(fn, a1, a2) \
|
|
if (fn) { \
|
|
return fn(a1, a2); \
|
|
}
|
|
#define STUB_SAFE_CALL3(fn, a1, a2, a3) \
|
|
if (fn) { \
|
|
return fn(a1, a2, a3); \
|
|
}
|
|
#define STUB_SAFE_CALL4(fn, a1, a2, a3, a4) \
|
|
if (fn) { \
|
|
return fn(a1, a2, a3, a4); \
|
|
}
|
|
#define STUB_SAFE_CALL6(fn, a1, a2, a3, a4, a5, a6) \
|
|
if (fn) { \
|
|
return fn(a1, a2, a3, a4, a5, a6); \
|
|
}
|
|
#endif
|
|
|
|
STUB_DECLARE(void *, PORT_Alloc_Util, (size_t len));
|
|
STUB_DECLARE(void *, PORT_ArenaAlloc_Util, (PLArenaPool * arena, size_t size));
|
|
STUB_DECLARE(void *, PORT_ArenaZAlloc_Util, (PLArenaPool * arena, size_t size));
|
|
STUB_DECLARE(void, PORT_Free_Util, (void *ptr));
|
|
STUB_DECLARE(void, PORT_FreeArena_Util, (PLArenaPool * arena, PRBool zero));
|
|
STUB_DECLARE(int, PORT_GetError_Util, (void));
|
|
STUB_DECLARE(PLArenaPool *, PORT_NewArena_Util, (unsigned long chunksize));
|
|
STUB_DECLARE(void, PORT_SetError_Util, (int value));
|
|
STUB_DECLARE(void *, PORT_ZAlloc_Util, (size_t len));
|
|
STUB_DECLARE(void *, PORT_ZAllocAligned_Util, (size_t bytes, size_t alignment,
|
|
void **mem));
|
|
STUB_DECLARE(void *, PORT_ZAllocAlignedOffset_Util, (size_t bytes,
|
|
size_t alignment,
|
|
size_t offset));
|
|
STUB_DECLARE(void, PORT_ZFree_Util, (void *ptr, size_t len));
|
|
|
|
STUB_DECLARE(void, PR_Assert, (const char *s, const char *file, PRIntn ln));
|
|
STUB_DECLARE(PRStatus, PR_Access, (const char *name, PRAccessHow how));
|
|
STUB_DECLARE(PRStatus, PR_CallOnce, (PRCallOnceType * once, PRCallOnceFN func));
|
|
STUB_DECLARE(PRStatus, PR_Close, (PRFileDesc * fd));
|
|
STUB_DECLARE(void, PR_DestroyLock, (PRLock * lock));
|
|
STUB_DECLARE(void, PR_DestroyCondVar, (PRCondVar * cvar));
|
|
STUB_DECLARE(void, PR_Free, (void *ptr));
|
|
STUB_DECLARE(char *, PR_GetLibraryFilePathname, (const char *name,
|
|
PRFuncPtr addr));
|
|
STUB_DECLARE(PRFileDesc *, PR_ImportPipe, (PROsfd osfd));
|
|
STUB_DECLARE(void, PR_Lock, (PRLock * lock));
|
|
STUB_DECLARE(PRCondVar *, PR_NewCondVar, (PRLock * lock));
|
|
STUB_DECLARE(PRLock *, PR_NewLock, (void));
|
|
STUB_DECLARE(PRStatus, PR_NotifyCondVar, (PRCondVar * cvar));
|
|
STUB_DECLARE(PRStatus, PR_NotifyAllCondVar, (PRCondVar * cvar));
|
|
STUB_DECLARE(PRFileDesc *, PR_Open, (const char *name, PRIntn flags,
|
|
PRIntn mode));
|
|
STUB_DECLARE(PRInt32, PR_Read, (PRFileDesc * fd, void *buf, PRInt32 amount));
|
|
STUB_DECLARE(PROffset32, PR_Seek, (PRFileDesc * fd, PROffset32 offset,
|
|
PRSeekWhence whence));
|
|
STUB_DECLARE(PRStatus, PR_Sleep, (PRIntervalTime ticks));
|
|
STUB_DECLARE(PRStatus, PR_Unlock, (PRLock * lock));
|
|
STUB_DECLARE(PRStatus, PR_WaitCondVar, (PRCondVar * cvar,
|
|
PRIntervalTime timeout));
|
|
STUB_DECLARE(char *, PR_GetEnvSecure, (const char *));
|
|
|
|
STUB_DECLARE(SECItem *, SECITEM_AllocItem_Util, (PLArenaPool * arena,
|
|
SECItem *item, unsigned int len));
|
|
STUB_DECLARE(SECComparison, SECITEM_CompareItem_Util, (const SECItem *a,
|
|
const SECItem *b));
|
|
STUB_DECLARE(SECStatus, SECITEM_CopyItem_Util, (PLArenaPool * arena,
|
|
SECItem *to, const SECItem *from));
|
|
STUB_DECLARE(void, SECITEM_FreeItem_Util, (SECItem * zap, PRBool freeit));
|
|
STUB_DECLARE(void, SECITEM_ZfreeItem_Util, (SECItem * zap, PRBool freeit));
|
|
STUB_DECLARE(SECOidTag, SECOID_FindOIDTag_Util, (const SECItem *oid));
|
|
STUB_DECLARE(int, NSS_SecureMemcmp, (const void *a, const void *b, size_t n));
|
|
STUB_DECLARE(unsigned int, NSS_SecureMemcmpZero, (const void *mem, size_t n));
|
|
|
|
#define PORT_ZNew_stub(type) (type *)PORT_ZAlloc_stub(sizeof(type))
|
|
#define PORT_New_stub(type) (type *)PORT_Alloc_stub(sizeof(type))
|
|
#define PORT_ZNewArray_stub(type, num) \
|
|
(type *)PORT_ZAlloc_stub(sizeof(type) * (num))
|
|
#define PORT_ZNewAligned_stub(type, alignment, mem) \
|
|
(type *)PORT_ZAllocAlignedOffset_stub(sizeof(type), alignment, offsetof(type, mem))
|
|
|
|
/*
|
|
* NOTE: in order to support hashing only the memory allocation stubs,
|
|
* the get library name stubs, and the file io stubs are needed (the latter
|
|
* two are for the library verification). The remaining stubs are simply to
|
|
* compile. Attempts to use the library for other operations without NSPR
|
|
* will most likely fail.
|
|
*/
|
|
|
|
/* memory */
|
|
extern void *
|
|
PORT_Alloc_stub(size_t len)
|
|
{
|
|
STUB_SAFE_CALL1(PORT_Alloc_Util, len);
|
|
return malloc(len);
|
|
}
|
|
|
|
extern void
|
|
PORT_Free_stub(void *ptr)
|
|
{
|
|
STUB_SAFE_CALL1(PORT_Free_Util, ptr);
|
|
return free(ptr);
|
|
}
|
|
|
|
extern void *
|
|
PORT_ZAlloc_stub(size_t len)
|
|
{
|
|
STUB_SAFE_CALL1(PORT_ZAlloc_Util, len);
|
|
void *ptr = malloc(len);
|
|
if (ptr) {
|
|
memset(ptr, 0, len);
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
/* aligned_alloc is C11. This is an alternative to get aligned memory. */
|
|
extern void *
|
|
PORT_ZAllocAligned_stub(size_t bytes, size_t alignment, void **mem)
|
|
{
|
|
STUB_SAFE_CALL3(PORT_ZAllocAligned_Util, bytes, alignment, mem);
|
|
|
|
/* This only works if alignement is a power of 2. */
|
|
if ((alignment == 0) || (alignment & (alignment - 1))) {
|
|
return NULL;
|
|
}
|
|
|
|
size_t x = alignment - 1;
|
|
size_t len = (bytes ? bytes : 1) + x;
|
|
|
|
if (!mem) {
|
|
return NULL;
|
|
}
|
|
|
|
/* Always allocate a non-zero amount of bytes */
|
|
*mem = malloc(len);
|
|
if (!*mem) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(*mem, 0, len);
|
|
return (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x);
|
|
}
|
|
|
|
extern void *
|
|
PORT_ZAllocAlignedOffset_stub(size_t size, size_t alignment, size_t offset)
|
|
{
|
|
STUB_SAFE_CALL3(PORT_ZAllocAlignedOffset_Util, size, alignment, offset);
|
|
if (offset > size) {
|
|
return NULL;
|
|
}
|
|
|
|
void *mem = NULL;
|
|
void *v = PORT_ZAllocAligned_stub(size, alignment, &mem);
|
|
if (!v) {
|
|
return NULL;
|
|
}
|
|
|
|
*((void **)((uintptr_t)v + offset)) = mem;
|
|
return v;
|
|
}
|
|
|
|
extern void
|
|
PORT_ZFree_stub(void *ptr, size_t len)
|
|
{
|
|
STUB_SAFE_CALL2(PORT_ZFree_Util, ptr, len);
|
|
memset(ptr, 0, len);
|
|
return free(ptr);
|
|
}
|
|
|
|
extern void
|
|
PR_Free_stub(void *ptr)
|
|
{
|
|
STUB_SAFE_CALL1(PR_Free, ptr);
|
|
return free(ptr);
|
|
}
|
|
|
|
/*
|
|
* arenas
|
|
*
|
|
*/
|
|
extern PLArenaPool *
|
|
PORT_NewArena_stub(unsigned long chunksize)
|
|
{
|
|
STUB_SAFE_CALL1(PORT_NewArena_Util, chunksize);
|
|
abort();
|
|
return NULL;
|
|
}
|
|
|
|
extern void *
|
|
PORT_ArenaAlloc_stub(PLArenaPool *arena, size_t size)
|
|
{
|
|
|
|
STUB_SAFE_CALL2(PORT_ArenaZAlloc_Util, arena, size);
|
|
abort();
|
|
return NULL;
|
|
}
|
|
|
|
extern void *
|
|
PORT_ArenaZAlloc_stub(PLArenaPool *arena, size_t size)
|
|
{
|
|
|
|
STUB_SAFE_CALL2(PORT_ArenaZAlloc_Util, arena, size);
|
|
abort();
|
|
return NULL;
|
|
}
|
|
|
|
extern void
|
|
PORT_FreeArena_stub(PLArenaPool *arena, PRBool zero)
|
|
{
|
|
|
|
STUB_SAFE_CALL2(PORT_FreeArena_Util, arena, zero);
|
|
abort();
|
|
}
|
|
|
|
/* io */
|
|
extern PRFileDesc *
|
|
PR_Open_stub(const char *name, PRIntn flags, PRIntn mode)
|
|
{
|
|
int *lfd = NULL;
|
|
int fd;
|
|
int lflags = 0;
|
|
|
|
STUB_SAFE_CALL3(PR_Open, name, flags, mode);
|
|
|
|
if (flags & PR_RDWR) {
|
|
lflags = O_RDWR;
|
|
} else if (flags & PR_WRONLY) {
|
|
lflags = O_WRONLY;
|
|
} else {
|
|
lflags = O_RDONLY;
|
|
}
|
|
|
|
if (flags & PR_EXCL)
|
|
lflags |= O_EXCL;
|
|
if (flags & PR_APPEND)
|
|
lflags |= O_APPEND;
|
|
if (flags & PR_TRUNCATE)
|
|
lflags |= O_TRUNC;
|
|
|
|
fd = open(name, lflags, mode);
|
|
if (fd >= 0) {
|
|
lfd = PORT_New_stub(int);
|
|
if (lfd != NULL) {
|
|
*lfd = fd;
|
|
} else {
|
|
close(fd);
|
|
}
|
|
}
|
|
return (PRFileDesc *)lfd;
|
|
}
|
|
|
|
extern PRFileDesc *
|
|
PR_ImportPipe_stub(PROsfd fd)
|
|
{
|
|
int *lfd = NULL;
|
|
|
|
STUB_SAFE_CALL1(PR_ImportPipe, fd);
|
|
|
|
lfd = PORT_New_stub(int);
|
|
if (lfd != NULL) {
|
|
*lfd = fd;
|
|
}
|
|
return (PRFileDesc *)lfd;
|
|
}
|
|
|
|
extern PRStatus
|
|
PR_Close_stub(PRFileDesc *fd)
|
|
{
|
|
int *lfd;
|
|
STUB_SAFE_CALL1(PR_Close, fd);
|
|
|
|
lfd = (int *)fd;
|
|
close(*lfd);
|
|
PORT_Free_stub(lfd);
|
|
|
|
return PR_SUCCESS;
|
|
}
|
|
|
|
extern PRInt32
|
|
PR_Read_stub(PRFileDesc *fd, void *buf, PRInt32 amount)
|
|
{
|
|
int *lfd;
|
|
STUB_SAFE_CALL3(PR_Read, fd, buf, amount);
|
|
|
|
lfd = (int *)fd;
|
|
return read(*lfd, buf, amount);
|
|
}
|
|
|
|
extern PROffset32
|
|
PR_Seek_stub(PRFileDesc *fd, PROffset32 offset, PRSeekWhence whence)
|
|
{
|
|
int *lfd;
|
|
int lwhence = SEEK_SET;
|
|
STUB_SAFE_CALL3(PR_Seek, fd, offset, whence);
|
|
lfd = (int *)fd;
|
|
switch (whence) {
|
|
case PR_SEEK_CUR:
|
|
lwhence = SEEK_CUR;
|
|
break;
|
|
case PR_SEEK_END:
|
|
lwhence = SEEK_END;
|
|
break;
|
|
case PR_SEEK_SET:
|
|
break;
|
|
}
|
|
|
|
return lseek(*lfd, offset, lwhence);
|
|
}
|
|
|
|
PRStatus
|
|
PR_Access_stub(const char *name, PRAccessHow how)
|
|
{
|
|
int mode = F_OK;
|
|
int rv;
|
|
STUB_SAFE_CALL2(PR_Access, name, how);
|
|
switch (how) {
|
|
case PR_ACCESS_WRITE_OK:
|
|
mode = W_OK;
|
|
break;
|
|
case PR_ACCESS_READ_OK:
|
|
mode = R_OK;
|
|
break;
|
|
/* assume F_OK for all others */
|
|
default:
|
|
break;
|
|
}
|
|
rv = access(name, mode);
|
|
if (rv == 0) {
|
|
return PR_SUCCESS;
|
|
}
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* library
|
|
*/
|
|
extern char *
|
|
PR_GetLibraryFilePathname_stub(const char *name, PRFuncPtr addr)
|
|
{
|
|
Dl_info dli;
|
|
char *result;
|
|
|
|
STUB_SAFE_CALL2(PR_GetLibraryFilePathname, name, addr);
|
|
|
|
if (dladdr((void *)addr, &dli) == 0) {
|
|
return NULL;
|
|
}
|
|
result = PORT_Alloc_stub(strlen(dli.dli_fname) + 1);
|
|
if (result != NULL) {
|
|
strcpy(result, dli.dli_fname);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#include <errno.h>
|
|
|
|
/* errors */
|
|
extern int
|
|
PORT_GetError_stub(void)
|
|
{
|
|
STUB_SAFE_CALL0(PORT_GetError_Util);
|
|
return errno;
|
|
}
|
|
|
|
extern void
|
|
PORT_SetError_stub(int value)
|
|
{
|
|
STUB_SAFE_CALL1(PORT_SetError_Util, value);
|
|
errno = value;
|
|
}
|
|
|
|
/* misc */
|
|
extern void
|
|
PR_Assert_stub(const char *s, const char *file, PRIntn ln)
|
|
{
|
|
STUB_SAFE_CALL3(PR_Assert, s, file, ln);
|
|
fprintf(stderr, "%s line %d: %s\n", file, ln, s);
|
|
abort();
|
|
}
|
|
|
|
/* time */
|
|
extern PRStatus
|
|
PR_Sleep_stub(PRIntervalTime ticks)
|
|
{
|
|
STUB_SAFE_CALL1(PR_Sleep, ticks);
|
|
usleep(ticks * 1000);
|
|
return PR_SUCCESS;
|
|
}
|
|
|
|
/* locking */
|
|
extern PRLock *
|
|
PR_NewLock_stub(void)
|
|
{
|
|
STUB_SAFE_CALL0(PR_NewLock);
|
|
abort();
|
|
return NULL;
|
|
}
|
|
|
|
extern PRStatus
|
|
PR_Unlock_stub(PRLock *lock)
|
|
{
|
|
STUB_SAFE_CALL1(PR_Unlock, lock);
|
|
abort();
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
extern void
|
|
PR_Lock_stub(PRLock *lock)
|
|
{
|
|
STUB_SAFE_CALL1(PR_Lock, lock);
|
|
abort();
|
|
return;
|
|
}
|
|
|
|
extern void
|
|
PR_DestroyLock_stub(PRLock *lock)
|
|
{
|
|
STUB_SAFE_CALL1(PR_DestroyLock, lock);
|
|
abort();
|
|
return;
|
|
}
|
|
|
|
extern PRCondVar *
|
|
PR_NewCondVar_stub(PRLock *lock)
|
|
{
|
|
STUB_SAFE_CALL1(PR_NewCondVar, lock);
|
|
abort();
|
|
return NULL;
|
|
}
|
|
|
|
extern PRStatus
|
|
PR_NotifyCondVar_stub(PRCondVar *cvar)
|
|
{
|
|
STUB_SAFE_CALL1(PR_NotifyCondVar, cvar);
|
|
abort();
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
extern PRStatus
|
|
PR_NotifyAllCondVar_stub(PRCondVar *cvar)
|
|
{
|
|
STUB_SAFE_CALL1(PR_NotifyAllCondVar, cvar);
|
|
abort();
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
extern PRStatus
|
|
PR_WaitCondVar_stub(PRCondVar *cvar, PRIntervalTime timeout)
|
|
{
|
|
STUB_SAFE_CALL2(PR_WaitCondVar, cvar, timeout);
|
|
abort();
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
extern char *
|
|
PR_GetEnvSecure_stub(const char *var)
|
|
{
|
|
STUB_SAFE_CALL1(PR_GetEnvSecure, var);
|
|
abort();
|
|
return NULL;
|
|
}
|
|
|
|
extern void
|
|
PR_DestroyCondVar_stub(PRCondVar *cvar)
|
|
{
|
|
STUB_SAFE_CALL1(PR_DestroyCondVar, cvar);
|
|
abort();
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* NOTE: this presupposes GCC 4.1
|
|
*/
|
|
extern PRStatus
|
|
PR_CallOnce_stub(PRCallOnceType *once, PRCallOnceFN func)
|
|
{
|
|
STUB_SAFE_CALL2(PR_CallOnce, once, func);
|
|
abort();
|
|
return PR_FAILURE;
|
|
}
|
|
|
|
/*
|
|
* SECITEMS implement Item Utilities
|
|
*/
|
|
extern void
|
|
SECITEM_FreeItem_stub(SECItem *zap, PRBool freeit)
|
|
{
|
|
STUB_SAFE_CALL2(SECITEM_FreeItem_Util, zap, freeit);
|
|
abort();
|
|
}
|
|
|
|
extern SECItem *
|
|
SECITEM_AllocItem_stub(PLArenaPool *arena, SECItem *item, unsigned int len)
|
|
{
|
|
STUB_SAFE_CALL3(SECITEM_AllocItem_Util, arena, item, len);
|
|
abort();
|
|
return NULL;
|
|
}
|
|
|
|
extern SECComparison
|
|
SECITEM_CompareItem_stub(const SECItem *a, const SECItem *b)
|
|
{
|
|
STUB_SAFE_CALL2(SECITEM_CompareItem_Util, a, b);
|
|
abort();
|
|
return SECEqual;
|
|
}
|
|
|
|
extern SECStatus
|
|
SECITEM_CopyItem_stub(PLArenaPool *arena, SECItem *to, const SECItem *from)
|
|
{
|
|
STUB_SAFE_CALL3(SECITEM_CopyItem_Util, arena, to, from);
|
|
abort();
|
|
return SECFailure;
|
|
}
|
|
|
|
extern SECOidTag
|
|
SECOID_FindOIDTag_stub(const SECItem *oid)
|
|
{
|
|
STUB_SAFE_CALL1(SECOID_FindOIDTag_Util, oid);
|
|
abort();
|
|
return SEC_OID_UNKNOWN;
|
|
}
|
|
|
|
extern void
|
|
SECITEM_ZfreeItem_stub(SECItem *zap, PRBool freeit)
|
|
{
|
|
STUB_SAFE_CALL2(SECITEM_ZfreeItem_Util, zap, freeit);
|
|
abort();
|
|
}
|
|
|
|
extern int
|
|
NSS_SecureMemcmp_stub(const void *a, const void *b, size_t n)
|
|
{
|
|
STUB_SAFE_CALL3(NSS_SecureMemcmp, a, b, n);
|
|
abort();
|
|
}
|
|
|
|
extern unsigned int
|
|
NSS_SecureMemcmpZero_stub(const void *mem, size_t n)
|
|
{
|
|
STUB_SAFE_CALL2(NSS_SecureMemcmpZero, mem, n);
|
|
abort();
|
|
}
|
|
|
|
#ifdef FREEBL_NO_WEAK
|
|
|
|
static const char *nsprLibName = SHLIB_PREFIX "nspr4." SHLIB_SUFFIX;
|
|
static const char *nssutilLibName = SHLIB_PREFIX "nssutil3." SHLIB_SUFFIX;
|
|
|
|
static SECStatus
|
|
freebl_InitNSPR(void *lib)
|
|
{
|
|
STUB_FETCH_FUNCTION(PR_Free);
|
|
STUB_FETCH_FUNCTION(PR_Open);
|
|
STUB_FETCH_FUNCTION(PR_ImportPipe);
|
|
STUB_FETCH_FUNCTION(PR_Close);
|
|
STUB_FETCH_FUNCTION(PR_Read);
|
|
STUB_FETCH_FUNCTION(PR_Seek);
|
|
STUB_FETCH_FUNCTION(PR_GetLibraryFilePathname);
|
|
STUB_FETCH_FUNCTION(PR_Assert);
|
|
STUB_FETCH_FUNCTION(PR_Access);
|
|
STUB_FETCH_FUNCTION(PR_Sleep);
|
|
STUB_FETCH_FUNCTION(PR_CallOnce);
|
|
STUB_FETCH_FUNCTION(PR_NewCondVar);
|
|
STUB_FETCH_FUNCTION(PR_NotifyCondVar);
|
|
STUB_FETCH_FUNCTION(PR_NotifyAllCondVar);
|
|
STUB_FETCH_FUNCTION(PR_WaitCondVar);
|
|
STUB_FETCH_FUNCTION(PR_DestroyCondVar);
|
|
STUB_FETCH_FUNCTION(PR_NewLock);
|
|
STUB_FETCH_FUNCTION(PR_Unlock);
|
|
STUB_FETCH_FUNCTION(PR_Lock);
|
|
STUB_FETCH_FUNCTION(PR_DestroyLock);
|
|
STUB_FETCH_FUNCTION(PR_GetEnvSecure);
|
|
return SECSuccess;
|
|
}
|
|
|
|
static SECStatus
|
|
freebl_InitNSSUtil(void *lib)
|
|
{
|
|
STUB_FETCH_FUNCTION(PORT_Alloc_Util);
|
|
STUB_FETCH_FUNCTION(PORT_Free_Util);
|
|
STUB_FETCH_FUNCTION(PORT_ZAlloc_Util);
|
|
STUB_FETCH_FUNCTION(PORT_ZFree_Util);
|
|
STUB_FETCH_FUNCTION(PORT_NewArena_Util);
|
|
STUB_FETCH_FUNCTION(PORT_ArenaAlloc_Util);
|
|
STUB_FETCH_FUNCTION(PORT_ArenaZAlloc_Util);
|
|
STUB_FETCH_FUNCTION(PORT_FreeArena_Util);
|
|
STUB_FETCH_FUNCTION(PORT_GetError_Util);
|
|
STUB_FETCH_FUNCTION(PORT_SetError_Util);
|
|
STUB_FETCH_FUNCTION(SECITEM_FreeItem_Util);
|
|
STUB_FETCH_FUNCTION(SECITEM_AllocItem_Util);
|
|
STUB_FETCH_FUNCTION(SECITEM_CompareItem_Util);
|
|
STUB_FETCH_FUNCTION(SECITEM_CopyItem_Util);
|
|
STUB_FETCH_FUNCTION(SECITEM_ZfreeItem_Util);
|
|
STUB_FETCH_FUNCTION(SECOID_FindOIDTag_Util);
|
|
STUB_FETCH_FUNCTION(NSS_SecureMemcmp);
|
|
STUB_FETCH_FUNCTION(NSS_SecureMemcmpZero);
|
|
return SECSuccess;
|
|
}
|
|
|
|
/*
|
|
* fetch the library if it's loaded. For NSS it should already be loaded
|
|
*/
|
|
#define freebl_getLibrary(libName) \
|
|
dlopen(libName, RTLD_LAZY | RTLD_NOLOAD)
|
|
|
|
#define freebl_releaseLibrary(lib) \
|
|
if (lib) \
|
|
dlclose(lib)
|
|
|
|
static void *FREEBLnsprGlobalLib = NULL;
|
|
static void *FREEBLnssutilGlobalLib = NULL;
|
|
|
|
void __attribute((destructor)) FREEBL_unload()
|
|
{
|
|
freebl_releaseLibrary(FREEBLnsprGlobalLib);
|
|
freebl_releaseLibrary(FREEBLnssutilGlobalLib);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* load the symbols from the real libraries if available.
|
|
*
|
|
* if force is set, explicitly load the libraries if they are not already
|
|
* loaded. If we could not use the real libraries, return failure.
|
|
*/
|
|
extern SECStatus
|
|
FREEBL_InitStubs()
|
|
{
|
|
SECStatus rv = SECSuccess;
|
|
#ifdef FREEBL_NO_WEAK
|
|
void *nspr = NULL;
|
|
void *nssutil = NULL;
|
|
|
|
/* NSPR should be first */
|
|
if (!FREEBLnsprGlobalLib) {
|
|
nspr = freebl_getLibrary(nsprLibName);
|
|
if (!nspr) {
|
|
return SECFailure;
|
|
}
|
|
rv = freebl_InitNSPR(nspr);
|
|
if (rv != SECSuccess) {
|
|
freebl_releaseLibrary(nspr);
|
|
return rv;
|
|
}
|
|
FREEBLnsprGlobalLib = nspr; /* adopt */
|
|
}
|
|
/* now load NSSUTIL */
|
|
if (!FREEBLnssutilGlobalLib) {
|
|
nssutil = freebl_getLibrary(nssutilLibName);
|
|
if (!nssutil) {
|
|
return SECFailure;
|
|
}
|
|
rv = freebl_InitNSSUtil(nssutil);
|
|
if (rv != SECSuccess) {
|
|
freebl_releaseLibrary(nssutil);
|
|
return rv;
|
|
}
|
|
FREEBLnssutilGlobalLib = nssutil; /* adopt */
|
|
}
|
|
#endif
|
|
|
|
return rv;
|
|
}
|