aboutsummaryrefslogtreecommitdiffstats
path: root/cipher/dynload.c
diff options
context:
space:
mode:
Diffstat (limited to 'cipher/dynload.c')
-rw-r--r--cipher/dynload.c606
1 files changed, 14 insertions, 592 deletions
diff --git a/cipher/dynload.c b/cipher/dynload.c
index 09cd1366a..38c6a0c35 100644
--- a/cipher/dynload.c
+++ b/cipher/dynload.c
@@ -1,5 +1,5 @@
/* dynload.c - load cipher extensions
- * Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -23,139 +23,22 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#ifdef HAVE_DL_DLOPEN
- #include <dlfcn.h>
-#elif defined(HAVE_DLD_DLD_LINK)
- #include <dld.h>
-#elif defined(HAVE_DL_SHL_LOAD)
- #include <dl.h>
- #include <errno.h>
-#endif
-#ifdef __MINGW32__
- #include <windows.h>
-#endif
#include "util.h"
#include "cipher.h"
-#include "dynload.h"
-
-#ifdef WITH_SYMBOL_UNDERSCORE
- #define SYMBOL_VERSION "_gnupgext_version"
- #define SYMBOL_ENUM "_gnupgext_enum_func"
-#else
- #define SYMBOL_VERSION "gnupgext_version"
- #define SYMBOL_ENUM "gnupgext_enum_func"
-#endif
-
-
-#ifndef RTLD_NOW
- #define RTLD_NOW 1
-#endif
-
-#ifdef HAVE_DL_SHL_LOAD /* HPUX has shl_load instead of dlopen */
-#define HAVE_DL_DLOPEN
-#define dlopen(PATHNAME,MODE) \
- ((void *) shl_load(PATHNAME, DYNAMIC_PATH | \
- (((MODE) & RTLD_NOW) ? BIND_IMMEDIATE : BIND_DEFERRED), 0L))
-#define dlclose(HANDLE) shl_unload((shl_t) (HANDLE))
-#define dlerror() (errno == 0 ? NULL : strerror(errno))
-
-static void *
-dlsym(void *handle, char *name)
-{
- void *addr;
- if (shl_findsym((shl_t *)&handle,name,(short)TYPE_UNDEFINED,&addr) != 0) {
- return NULL;
- }
- return addr;
-}
-#endif /*HAVE_DL_SHL_LOAD*/
-
-#ifdef __MINGW32__
-#define HAVE_DL_DLOPEN
-#define USE_DYNAMIC_LINKING
-
-static int last_error = 0;
-
-void*
-dlopen(const char *pathname, int mode)
-{
- void *h = LoadLibrary( pathname );
- if (!h) {
- log_error( "LoadLibrary failed ec=%d\n", (int)GetLastError() );
- last_error = 1;
- return NULL;
- }
- return h;
-}
-
-int
-dlclose( void *handle )
-{
- last_error = 0;
- return FreeLibrary( handle );
-}
-
-char*
-dlerror(void)
-{
- static char dlerrstr[10];
- if (last_error) {
- sprintf(dlerrstr, "%d", (int)GetLastError() );
- return dlerrstr;
- }
- return NULL;
-}
-
-void*
-dlsym( void *handle, const char *name )
-{
- void *h = GetProcAddress( handle, name );
- if (!h) {
- log_error( "GetProcAddress failed ec=%d\n", (int)GetLastError() );
- last_error = 1;
- return NULL;
- }
- return h;
-}
-#endif /*__MINGW32__*/
-
-
-
+#include "algorithms.h"
typedef struct ext_list {
struct ext_list *next;
- int internal;
- #ifdef HAVE_DL_DLOPEN
- void *handle; /* handle from dlopen() */
- #else
- int handle; /* if the function has been loaded, this is true */
- #endif
- int failed; /* already tried but failed */
- void * (*enumfunc)(int, int*, int*, int*);
- char *hintstr; /* pointer into name */
char name[1];
} *EXTLIST;
static EXTLIST extensions;
-typedef struct {
- EXTLIST r;
- int seq1;
- int seq2;
- void *sym;
- int reqalgo;
-} ENUMCONTEXT;
-
-
-#ifdef HAVE_DLD_DLD_LINK
-static char *mainpgm_path;
-static int did_dld_init;
-static int dld_available;
-#endif
-
-
-/****************
+/* This is actually not used anymore but we keep a list of already
+ * set extensions modules here.
+ *
+ * Here is the ancient comment:
* Register an extension module. The last registered module will
* be loaded first. A name may have a list of classes
* appended; e.g:
@@ -174,10 +57,6 @@ register_cipher_extension( const char *mainpgm, const char *fname )
EXTLIST r, el, intex;
char *p, *pe;
- #ifdef HAVE_DLD_DLD_LINK
- if( !mainpgm_path && mainpgm && *mainpgm )
- mainpgm_path = m_strdup(mainpgm);
- #endif
if( *fname != DIRSEP_C ) { /* do tilde expansion etc */
char *tmp;
@@ -194,12 +73,8 @@ register_cipher_extension( const char *mainpgm, const char *fname )
strcpy(el->name, fname );
}
/* check whether we have a class hint */
- if( (p=strchr(el->name,'(')) && (pe=strchr(p+1,')')) && !pe[1] ) {
+ if( (p=strchr(el->name,'(')) && (pe=strchr(p+1,')')) && !pe[1] )
*p = *pe = 0;
- el->hintstr = p+1;
- }
- else
- el->hintstr = NULL;
/* check that it is not already registered */
intex = NULL;
@@ -209,473 +84,20 @@ register_cipher_extension( const char *mainpgm, const char *fname )
m_free(el);
return;
}
- else if( r->internal )
- intex = r;
- }
- /* and register */
- /* we put them after the internal extension modules */
- /* this is so that the external modules do not get loaded */
- /* as soon as the internal modules are requested */
- if( intex ) {
- el->next = intex->next;
- intex->next = el;
- }
- else {
- el->next = extensions;
- extensions = el;
- }
-}
-
-void
-register_internal_cipher_extension(
- const char *module_id,
- void * (*enumfunc)(int, int*, int*, int*)
- )
-{
- EXTLIST r, el;
-
- el = m_alloc_clear( sizeof *el + strlen(module_id) );
- strcpy(el->name, module_id );
- el->internal = 1;
-
- /* check that it is not already registered */
- for(r = extensions; r; r = r->next ) {
- if( !compare_filenames(r->name, el->name) ) {
- log_info("extension `%s' already registered\n", el->name );
- m_free(el);
- return;
- }
}
/* and register */
- el->enumfunc = enumfunc;
- #ifdef HAVE_DL_DLOPEN
- el->handle = (void*)1;
- #else
- el->handle = 1;
- #endif
el->next = extensions;
extensions = el;
}
-
-static int
-load_extension( EXTLIST el )
-{
- #ifdef USE_DYNAMIC_LINKING
- char **name;
- #ifdef HAVE_DL_DLOPEN
- const char *err;
- int seq = 0;
- int class, vers;
- void *sym;
- #else
- unsigned long addr;
- int rc;
- #endif
-
- #ifndef __MINGW32__
- /* make sure we are not setuid */
- if( getuid() != geteuid() )
- log_bug("trying to load an extension while still setuid\n");
- #endif
-
- /* now that we are not setuid anymore, we can safely load modules */
- #ifdef HAVE_DL_DLOPEN
- el->handle = dlopen(el->name, RTLD_NOW);
- if( !el->handle ) {
- log_error("%s: error loading extension: %s\n", el->name, dlerror() );
- goto failure;
- }
- name = (char**)dlsym(el->handle, SYMBOL_VERSION);
- if( (err=dlerror()) ) {
- log_error("%s: not a gnupg extension: %s\n", el->name, err );
- goto failure;
- }
- #else /* have dld */
- if( !did_dld_init ) {
- did_dld_init = 1;
- if( !mainpgm_path )
- log_error("DLD is not correctly initialized\n");
- else {
- rc = dld_init( dld_find_executable(mainpgm_path) );
- if( rc )
- log_error("DLD init failed: %s\n", dld_strerror(rc) );
- else
- dld_available = 1;
- }
- }
- if( !dld_available ) {
- log_error("%s: DLD not available\n", el->name );
- goto failure;
- }
-
- rc = dld_link( el->name );
- if( rc ) {
- log_error("%s: error loading extension: %s\n",
- el->name, dld_strerror(rc) );
- goto failure;
- }
- addr = dld_get_symbol(SYMBOL_VERSION);
- if( !addr ) {
- log_error("%s: not a gnupg extension: %s\n",
- el->name, dld_strerror(dld_errno) );
- goto failure;
- }
- name = (char**)addr;
- #endif
-
- if( g10_opt_verbose > 1 )
- log_info("%s: %s%s%s%s\n", el->name, *name,
- el->hintstr? " (":"",
- el->hintstr? el->hintstr:"",
- el->hintstr? ")":"");
-
- #ifdef HAVE_DL_DLOPEN
- sym = dlsym(el->handle, SYMBOL_ENUM);
- if( (err=dlerror()) ) {
- log_error("%s: invalid gnupg extension: %s\n", el->name, err );
- goto failure;
- }
- el->enumfunc = (void *(*)(int,int*,int*,int*))sym;
- #else /* dld */
- addr = dld_get_func(SYMBOL_ENUM);
- if( !addr ) {
- log_error("%s: invalid gnupg extension: %s\n",
- el->name, dld_strerror(dld_errno) );
- goto failure;
- }
- rc = dld_function_executable_p(SYMBOL_ENUM);
- if( rc ) {
- log_error("%s: extension function is not executable: %s\n",
- el->name, dld_strerror(rc) );
- goto failure;
- }
- el->enumfunc = (void *(*)(int,int*,int*,int*))addr;
- el->handle = 1; /* mark as usable */
- #endif
-
- #ifdef HAVE_DL_DLOPEN
- if( g10_opt_verbose > 2 ) {
- /* list the contents of the module */
- while( (sym = (*el->enumfunc)(0, &seq, &class, &vers)) ) {
- if( vers != 1 ) {
- log_info("%s: ignoring func with version %d\n",el->name,vers);
- continue;
- }
- switch( class ) {
- case 11:
- case 21:
- case 31:
- log_info("%s: provides %s algorithm %d\n", el->name,
- class == 11? "md" :
- class == 21? "cipher" : "pubkey",
- *(int*)sym);
- break;
- default:
- /*log_debug("%s: skipping class %d\n", el->name, class);*/
- break;
- }
- }
- }
- #endif
- return 0;
-
- failure:
- #ifdef HAVE_DL_DLOPEN
- if( el->handle ) {
- dlclose(el->handle);
- el->handle = NULL;
- }
- #endif
- el->failed = 1;
- #endif /*USE_DYNAMIC_LINKING*/
- return -1;
-}
-
-#ifdef __riscos__
-typedef
-const char *(*DIGESTS_CAST)(int, size_t*,byte**, int*, int*,
- void (**)(void*),
- void (**)(void*,byte*,size_t),
- void (**)(void*),byte *(**)(void*));
-#endif /* __riscos__ */
-
-int
-enum_gnupgext_digests( void **enum_context,
- int *algo,
- const char *(**r_get_info)( int, size_t*,byte**, int*, int*,
- void (**)(void*),
- void (**)(void*,byte*,size_t),
- void (**)(void*),byte *(**)(void*)) )
-{
- EXTLIST r;
- ENUMCONTEXT *ctx;
-
- if( !*enum_context ) { /* init context */
- ctx = m_alloc_clear( sizeof( *ctx ) );
- ctx->r = extensions;
- ctx->reqalgo = *algo;
- *enum_context = ctx;
- }
- else if( !algo ) { /* release the context */
- m_free(*enum_context);
- *enum_context = NULL;
- return 0;
- }
- else
- ctx = *enum_context;
-
- for( r = ctx->r; r; r = r->next ) {
- int class, vers;
-
- if( r->failed )
- continue;
- if( !r->handle && load_extension(r) )
- continue;
- /* get a digest info function */
- if( ctx->sym )
- goto inner_loop;
- while( (ctx->sym = (*r->enumfunc)(10, &ctx->seq1, &class, &vers)) ) {
- void *sym;
- /* must check class because enumfunc may be wrong coded */
- if( vers != 1 || class != 10 )
- continue;
- inner_loop:
-#ifndef __riscos__
- *r_get_info = ctx->sym;
-#else /* __riscos__ */
- *r_get_info = (DIGESTS_CAST) ctx->sym;
-#endif /* __riscos__ */
- while( (sym = (*r->enumfunc)(11, &ctx->seq2, &class, &vers)) ) {
- if( vers != 1 || class != 11 )
- continue;
- *algo = *(int*)sym;
- ctx->r = r;
- return 1;
- }
- ctx->seq2 = 0;
- }
- ctx->seq1 = 0;
- }
- ctx->r = r;
- return 0;
-}
-
-#ifdef __riscos__
-typedef
-const char *(*CIPHERS_CAST)(int, size_t*, size_t*, size_t*,
- int (**)( void *, byte *, unsigned),
- void (**)( void *, byte *, byte *),
- void (**)( void *, byte *, byte *));
-#endif /* __riscos__ */
-
+/* Return the module name with index SEQ, return NULL as as indication
+ for end of list. */
const char *
-enum_gnupgext_ciphers( void **enum_context, int *algo,
- size_t *keylen, size_t *blocksize, size_t *contextsize,
- int (**setkeyf)( void *c, byte *key, unsigned keylen ),
- void (**encryptf)( void *c, byte *outbuf, byte *inbuf ),
- void (**decryptf)( void *c, byte *outbuf, byte *inbuf )
- )
+dynload_enum_module_names (int seq)
{
- EXTLIST r;
- ENUMCONTEXT *ctx;
- const char * (*finfo)(int, size_t*, size_t*, size_t*,
- int (**)( void *, byte *, unsigned),
- void (**)( void *, byte *, byte *),
- void (**)( void *, byte *, byte *));
+ EXTLIST el = extensions;
- if( !*enum_context ) { /* init context */
- ctx = m_alloc_clear( sizeof( *ctx ) );
- ctx->r = extensions;
- *enum_context = ctx;
- }
- else if( !algo ) { /* release the context */
- m_free(*enum_context);
- *enum_context = NULL;
- return NULL;
- }
- else
- ctx = *enum_context;
-
- for( r = ctx->r; r; r = r->next ) {
- int class, vers;
-
- if( r->failed )
- continue;
- if( !r->handle && load_extension(r) )
- continue;
- /* get a cipher info function */
- if( ctx->sym )
- goto inner_loop;
- while( (ctx->sym = (*r->enumfunc)(20, &ctx->seq1, &class, &vers)) ) {
- void *sym;
- /* must check class because enumfunc may be wrong coded */
- if( vers != 1 || class != 20 )
- continue;
- inner_loop:
-#ifndef __riscos__
- finfo = ctx->sym;
-#else /* __riscos__ */
- finfo = (CIPHERS_CAST) ctx->sym;
-#endif /* __riscos__ */
- while( (sym = (*r->enumfunc)(21, &ctx->seq2, &class, &vers)) ) {
- const char *algname;
- if( vers != 1 || class != 21 )
- continue;
- *algo = *(int*)sym;
- algname = (*finfo)( *algo, keylen, blocksize, contextsize,
- setkeyf, encryptf, decryptf );
- if( algname ) {
- ctx->r = r;
- return algname;
- }
- }
- ctx->seq2 = 0;
- }
- ctx->seq1 = 0;
- }
- ctx->r = r;
- return NULL;
-}
-
-#ifdef __riscos__
-typedef
-const char *(*PUBKEYS_CAST)(int, int *, int *, int *, int *, int *,
- int (**)(int, unsigned, MPI *, MPI **),
- int (**)(int, MPI *),
- int (**)(int, MPI *, MPI , MPI *),
- int (**)(int, MPI *, MPI *, MPI *),
- int (**)(int, MPI *, MPI , MPI *),
- int (**)(int, MPI , MPI *, MPI *,
- int (*)(void*,MPI), void *),
- unsigned (**)( int , MPI *));
-#endif /* __riscos__ */
-
-const char *
-enum_gnupgext_pubkeys( void **enum_context, int *algo,
- int *npkey, int *nskey, int *nenc, int *nsig, int *use,
- int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ),
- int (**check_secret_key)( int algo, MPI *skey ),
- int (**encryptf)( int algo, MPI *resarr, MPI data, MPI *pkey ),
- int (**decryptf)( int algo, MPI *result, MPI *data, MPI *skey ),
- int (**sign)( int algo, MPI *resarr, MPI data, MPI *skey ),
- int (**verify)( int algo, MPI hash, MPI *data, MPI *pkey,
- int (*cmp)(void *, MPI), void *opaquev ),
- unsigned (**get_nbits)( int algo, MPI *pkey ) )
-{
- EXTLIST r;
- ENUMCONTEXT *ctx;
- const char * (*finfo)( int, int *, int *, int *, int *, int *,
- int (**)( int, unsigned, MPI *, MPI **),
- int (**)( int, MPI * ),
- int (**)( int, MPI *, MPI , MPI * ),
- int (**)( int, MPI *, MPI *, MPI * ),
- int (**)( int, MPI *, MPI , MPI * ),
- int (**)( int, MPI , MPI *, MPI *,
- int (*)(void*,MPI), void *),
- unsigned (**)( int , MPI * ) );
-
- if( !*enum_context ) { /* init context */
- ctx = m_alloc_clear( sizeof( *ctx ) );
- ctx->r = extensions;
- *enum_context = ctx;
- }
- else if( !algo ) { /* release the context */
- m_free(*enum_context);
- *enum_context = NULL;
- return NULL;
- }
- else
- ctx = *enum_context;
-
- for( r = ctx->r; r; r = r->next ) {
- int class, vers;
-
- if( r->failed )
- continue;
- if( !r->handle && load_extension(r) )
- continue;
- /* get a pubkey info function */
- if( ctx->sym )
- goto inner_loop;
- while( (ctx->sym = (*r->enumfunc)(30, &ctx->seq1, &class, &vers)) ) {
- void *sym;
- if( vers != 1 || class != 30 )
- continue;
- inner_loop:
-#ifndef __riscos__
- finfo = ctx->sym;
-#else /* __riscos__ */
- finfo = (PUBKEYS_CAST) ctx->sym;
-#endif /* __riscos__ */
- while( (sym = (*r->enumfunc)(31, &ctx->seq2, &class, &vers)) ) {
- const char *algname;
- if( vers != 1 || class != 31 )
- continue;
- *algo = *(int*)sym;
- algname = (*finfo)( *algo, npkey, nskey, nenc, nsig, use,
- generate, check_secret_key, encryptf,
- decryptf, sign, verify, get_nbits );
- if( algname ) {
- ctx->r = r;
- return algname;
- }
- }
- ctx->seq2 = 0;
- }
- ctx->seq1 = 0;
- }
- ctx->r = r;
- return NULL;
-}
-
-
-int (*
-dynload_getfnc_gather_random())(void (*)(const void*, size_t, int), int,
- size_t, int)
-{
- EXTLIST r;
- void *sym;
-
- for( r = extensions; r; r = r->next ) {
- int seq, class, vers;
-
- if( r->failed )
- continue;
- if( !r->handle && load_extension(r) )
- continue;
- seq = 0;
- while( (sym = (*r->enumfunc)(40, &seq, &class, &vers)) ) {
- if( vers != 1 || class != 40 )
- continue;
- return (int (*)(void (*)(const void*, size_t, int), int,
- size_t, int))sym;
- }
- }
- return NULL;
+ for (; el && el->name && seq; el = el->next, seq--)
+ ;
+ return el? el->name:NULL;
}
-
-
-void (*
-dynload_getfnc_fast_random_poll())( void (*)(const void*, size_t, int), int)
-{
- EXTLIST r;
- void *sym;
-
- for( r = extensions; r; r = r->next ) {
- int seq, class, vers;
-
- if( r->failed )
- continue;
- if( !r->handle && load_extension(r) )
- continue;
- seq = 0;
- while( (sym = (*r->enumfunc)(41, &seq, &class, &vers)) ) {
- if( vers != 1 || class != 41 )
- continue;
- return (void (*)( void (*)(const void*, size_t, int), int))sym;
- }
- }
- return NULL;
-}
-