* ttyio.c (tty_enable_completion, tty_disable_completion): Add checks
[gnupg.git] / cipher / dynload.c
index e227317..05d82f6 100644 (file)
@@ -1,53 +1,45 @@
 /* dynload.c - load cipher extensions
- *     Copyright (C) 1998 Free Software Foundation, Inc.
+ *     Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
  *
- * This file is part of GNUPG.
+ * This file is part of GnuPG.
  *
- * GNUPG is free software; you can redistribute it and/or modify
+ * GnuPG is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * GNUPG is distributed in the hope that it will be useful,
+ * GnuPG is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_DL_DLOPEN
-  #include <dlfcn.h>
-#endif
+#include <unistd.h>
 #include "util.h"
 #include "cipher.h"
-#include "dynload.h"
+#include "algorithms.h"
+
 
 typedef struct ext_list {
     struct ext_list *next;
-    void *handle; /* handle from dlopen() */
-    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;
-} ENUMCONTEXT;
-
-/****************
+/* 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:
@@ -56,312 +48,57 @@ typedef struct {
  * algorithms 20 and 109.  This is only a hint but if it is there the
  * loader may decide to only load a module which claims to have a
  * requested algorithm.
+ *
+ * mainpgm is the path to the program which wants to load a module
+ * it is only used in some environments.
  */
 void
-register_cipher_extension( const char *fname )
+register_cipher_extension( const char *mainpgm, const char *fname )
 {
-    EXTLIST r, el;
+    EXTLIST r, el, intex;
     char *p, *pe;
 
-    if( *fname != '/' ) { /* do tilde expansion etc */
-       char *;
+    if( *fname != DIRSEP_C ) { /* do tilde expansion etc */
+       char *tmp;
 
-       if( strchr(fname, '/') )
-           p = make_filename(fname, NULL);
+       if( strchr(fname, DIRSEP_C) )
+           tmp = make_filename(fname, NULL);
        else
-           p = make_filename(GNUPG_LIBDIR, fname, NULL);
-       el = m_alloc_clear( sizeof *el + strlen(p) );
-       strcpy(el->name, p );
-       m_free(p);
+           tmp = make_filename(GNUPG_LIBDIR, fname, NULL);
+       el = xmalloc_clear( sizeof *el + strlen(tmp) );
+       strcpy(el->name, tmp );
+       xfree(tmp);
     }
     else {
-       el = m_alloc_clear( sizeof *el + strlen(fname) );
+       el = xmalloc_clear( sizeof *el + strlen(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 */
-    for(r = extensions; r; r = r->next )
+    intex = NULL;
+    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);
+           log_info("extension `%s' already registered\n", el->name );
+           xfree(el);
            return;
        }
+    }
     /* and register */
     el->next = extensions;
     extensions = el;
 }
 
-
-static int
-load_extension( EXTLIST el )
-{
-  #ifdef USE_DYNAMIC_LINKING
-    char **name;
-    void *sym;
-    const char *err;
-    int seq = 0;
-    int class, vers;
-
-
-    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, "gnupgext_version");
-    if( (err=dlerror()) ) {
-       log_error("%s: not a gnupg extension: %s\n", el->name, err );
-       goto failure;
-    }
-
-    if( g10_opt_verbose )
-       log_info("%s: %s%s%s%s\n", el->name, *name,
-                 el->hintstr? " (":"",
-                 el->hintstr? el->hintstr:"",
-                 el->hintstr? ")":"");
-
-    sym = dlsym(el->handle, "gnupgext_enum_func");
-    if( (err=dlerror()) ) {
-       log_error("%s: invalid gnupg extension: %s\n", el->name, err );
-       goto failure;
-    }
-    el->enumfunc = (void *(*)(int,int*,int*,int*))sym;
-
-    if( g10_opt_verbose > 1 ) {
-       /* 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;
-           }
-       }
-    }
-    return 0;
-
-  failure:
-    if( el->handle ) {
-       dlclose(el->handle);
-       el->handle = NULL;
-    }
-    el->failed = 1;
-  #endif /*USE_DYNAMIC_LINKING*/
-    return -1;
-}
-
-
-
-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;
-       *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:
-           *r_get_info = ctx->sym;
-           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;
-}
-
-const char *
-enum_gnupgext_ciphers( void **enum_context, int *algo,
-                      size_t *keylen, size_t *blocksize, size_t *contextsize,
-                      void (**setkey)( void *c, byte *key, unsigned keylen ),
-                      void (**encrypt)( void *c, byte *outbuf, byte *inbuf ),
-                      void (**decrypt)( void *c, byte *outbuf, byte *inbuf )
-                    )
-{
-    EXTLIST r;
-    ENUMCONTEXT *ctx;
-    const char * (*finfo)(int, size_t*, size_t*, size_t*,
-                         void (**)( void *, byte *, unsigned),
-                         void (**)( void *, byte *, byte *),
-                         void (**)( void *, byte *, byte *));
-
-    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:
-           finfo = ctx->sym;
-           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,
-                                   setkey, encrypt, decrypt );
-               if( algname ) {
-                   ctx->r = r;
-                   return algname;
-               }
-           }
-           ctx->seq2 = 0;
-       }
-       ctx->seq1 = 0;
-    }
-    ctx->r = r;
-    return NULL;
-}
-
+/* Return the module name with index SEQ, return NULL as as indication
+   for end of list. */
 const char *
-enum_gnupgext_pubkeys( void **enum_context, int *algo,
-    int *npkey, int *nskey, int *nenc, int *nsig, int *usage,
-    int (**generate)( int algo, unsigned nbits, MPI *skey, MPI **retfactors ),
-    int (**check_secret_key)( int algo, MPI *skey ),
-    int (**encrypt)( int algo, MPI *resarr, MPI data, MPI *pkey ),
-    int (**decrypt)( 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 ) )
+dynload_enum_module_names (int seq)
 {
-    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 * ) );
+  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 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:
-           finfo = ctx->sym;
-           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, usage,
-                                   generate, check_secret_key, encrypt,
-                                   decrypt, sign, verify, get_nbits );
-               if( algname ) {
-                   ctx->r = r;
-                   return algname;
-               }
-           }
-           ctx->seq2 = 0;
-       }
-       ctx->seq1 = 0;
-    }
-    ctx->r = r;
-    return NULL;
+  for (; el && el->name && seq; el = el->next, seq--)
+    ;
+  return el? el->name:NULL;
 }
-