partial DSA support
[gnupg.git] / g10 / getkey.c
index eea9b6b..300e33b 100644 (file)
@@ -1,14 +1,14 @@
 /* getkey.c -  Get a key from the database
- *     Copyright (c) 1997 by Werner Koch (dd9jn)
+ *     Copyright (C) 1998 Free Software Foundation, Inc.
  *
- * This file is part of G10.
+ * This file is part of GNUPG.
  *
- * G10 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.
  *
- * G10 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.
@@ -73,7 +73,8 @@ static int scan_keyring( PKT_public_cert *pkc, u32 *keyid,
 static int scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid,
                                const char *name, const char *filename);
 
-
+/* note this function may be called before secure memory is
+ * available */
 void
 add_keyring( const char *name )
 {
@@ -81,19 +82,32 @@ add_keyring( const char *name )
     int rc;
 
     /* FIXME: check wether this one is available etc */
-    /* my be we should do this later */
-    sl = m_alloc( sizeof *sl + strlen(name) );
-    strcpy(sl->d, name );
+    /* maybe we should do this later */
+    if( *name != '/' ) { /* do tilde expansion etc */
+       char *p ;
+
+       if( strchr(name, '/') )
+           p = make_filename(name, NULL);
+       else
+           p = make_filename(opt.homedir, name, NULL);
+       sl = m_alloc( sizeof *sl + strlen(p) );
+       strcpy(sl->d, p );
+       m_free(p);
+    }
+    else {
+       sl = m_alloc( sizeof *sl + strlen(name) );
+       strcpy(sl->d, name );
+    }
     sl->next = keyrings;
     keyrings = sl;
 
-    /* FIXME: We should remove much out of this mpdule and
+    /* FIXME: We should remove much out of this module and
      * combine it with the keyblock stuff from ringedit.c
      * For now we will simple add the filename as keyblock resource
      */
-    rc = add_keyblock_resource( name, 0, 0 );
+    rc = add_keyblock_resource( sl->d, 0, 0 );
     if( rc )
-       log_error("keyblock resource '%s': %s\n", name, g10_errstr(rc) );
+       log_error("keyblock resource '%s': %s\n", sl->d, g10_errstr(rc) );
 }
 
 
@@ -119,8 +133,21 @@ add_secret_keyring( const char *name )
 
     /* FIXME: check wether this one is available etc */
     /* my be we should do this later */
-    sl = m_alloc( sizeof *sl + strlen(name) );
-    strcpy(sl->d, name );
+    if( *name != '/' ) { /* do tilde expansion etc */
+       char *p ;
+
+       if( strchr(name, '/') )
+           p = make_filename(name, NULL);
+       else
+           p = make_filename(opt.homedir, name, NULL);
+       sl = m_alloc( sizeof *sl + strlen(p) );
+       strcpy(sl->d, p );
+       m_free(p);
+    }
+    else {
+       sl = m_alloc( sizeof *sl + strlen(name) );
+       strcpy(sl->d, name );
+    }
     sl->next = secret_keyrings;
     secret_keyrings = sl;
 
@@ -128,9 +155,9 @@ add_secret_keyring( const char *name )
      * combine it with the keyblock stuff from ringedit.c
      * For now we will simple add the filename as keyblock resource
      */
-    rc = add_keyblock_resource( name, 0, 1 );
+    rc = add_keyblock_resource( sl->d, 0, 1 );
     if( rc )
-       log_error("secret keyblock resource '%s': %s\n", name, g10_errstr(rc) );
+       log_error("secret keyblock resource '%s': %s\n", sl->d, g10_errstr(rc));
 }
 
 
@@ -141,6 +168,7 @@ cache_public_cert( PKT_public_cert *pkc )
     u32 keyid[2];
 
     if( pkc->pubkey_algo == PUBKEY_ALGO_ELGAMAL
+       || pkc->pubkey_algo == PUBKEY_ALGO_DSA
        || pkc->pubkey_algo == PUBKEY_ALGO_RSA ) {
        keyid_from_pkc( pkc, keyid );
     }
@@ -296,6 +324,8 @@ get_pubkey_byname( PKT_public_cert *pkc, const char *name )
        int i;
        char buf[9];
 
+       if( *s == '0' && s[1] == 'x' && isxdigit(s[2]) )
+           s += 2; /*kludge to allow 0x034343434 */
        for(i=0; isxdigit(s[i]); i++ )
            ;
        if( s[i] && !isspace(s[i]) ) /* not terminated by EOS or blank*/
@@ -392,6 +422,33 @@ get_seckey( PKT_secret_cert *skc, u32 *keyid )
 }
 
 /****************
+ * Check wether the secret key is available
+ * Returns: 0 := key is available
+ *         G10ERR_NO_SECKEY := not availabe
+ */
+int
+seckey_available( u32 *keyid )
+{
+    PKT_secret_cert *skc;
+    STRLIST sl;
+    int rc=0;
+
+    skc = m_alloc_clear( sizeof *skc );
+    for(sl = secret_keyrings; sl; sl = sl->next )
+       if( !(rc=scan_secret_keyring( skc, keyid, NULL, sl->d )) )
+           goto found;
+    /* fixme: look at other places */
+    goto leave;
+
+  found:
+  leave:
+    free_secret_cert( skc );
+    return rc;
+}
+
+
+
+/****************
  * Get a secret key by name and store it into skc
  * If NAME is NULL use the default certificate
  */
@@ -433,6 +490,7 @@ static int
 scan_keyring( PKT_public_cert *pkc, u32 *keyid,
              const char *name, const char *filename )
 {
+    compress_filter_context_t cfx;
     int rc=0;
     int found = 0;
     IOBUF a;
@@ -454,12 +512,12 @@ scan_keyring( PKT_public_cert *pkc, u32 *keyid,
     if( !DBG_CACHE )
        ;
     else if( shortkeyid )
-       log_debug("scan_keyring %s for %08lx\n",  filename, keyid[1] );
+       log_debug("scan_keyring %s for %08lx\n",  filename, (ulong)keyid[1] );
     else if( name )
        log_debug("scan_keyring %s for '%s'\n",  filename, name );
     else if( keyid )
        log_debug("scan_keyring %s for %08lx %08lx\n",  filename,
-                                               keyid[0], keyid[1] );
+                                            (ulong)keyid[0], (ulong)keyid[1] );
     else
        log_debug("scan_keyring %s (all)\n",  filename );
 
@@ -472,9 +530,23 @@ scan_keyring( PKT_public_cert *pkc, u32 *keyid,
            log_error("Hmmm, pubkey without an user id in '%s'\n", filename);
            goto leave;
        }
+       else if( pkt.pkttype == PKT_COMPRESSED ) {
+           memset( &cfx, 0, sizeof cfx );
+           if( pkt.pkt.compressed->algorithm == 1 )
+               cfx.pgpmode = 1;
+           else if( pkt.pkt.compressed->algorithm != 2  ){
+               rc = G10ERR_COMPR_ALGO;
+               log_error("compressed keyring: %s\n", g10_errstr(rc) );
+               break;
+           }
+
+           pkt.pkt.compressed->buf = NULL;
+           iobuf_push_filter( a, compress_filter, &cfx );
+       }
        else if( keyid && pkt.pkttype == PKT_PUBLIC_CERT ) {
            switch( pkt.pkt.public_cert->pubkey_algo ) {
              case PUBKEY_ALGO_ELGAMAL:
+             case PUBKEY_ALGO_DSA:
              case PUBKEY_ALGO_RSA:
                keyid_from_pkc( pkt.pkt.public_cert, akeyid );
                if( (shortkeyid || akeyid[0] == keyid[0])
@@ -526,6 +598,7 @@ scan_keyring( PKT_public_cert *pkc, u32 *keyid,
                            pkt.pkt.user_id->len, pkt.pkt.user_id->name);
            else {
                if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
+                   || last_pk->pubkey_algo == PUBKEY_ALGO_DSA
                    || last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
                     keyid_from_pkc( last_pk, akeyid );
                     cache_user_id( pkt.pkt.user_id, akeyid );
@@ -587,6 +660,7 @@ scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid,
        else if( keyid && pkt.pkttype == PKT_SECRET_CERT ) {
            switch( pkt.pkt.secret_cert->pubkey_algo ) {
              case PUBKEY_ALGO_ELGAMAL:
+             case PUBKEY_ALGO_DSA:
              case PUBKEY_ALGO_RSA:
                if( get_first ) {
                    copy_secret_cert( skc, pkt.pkt.secret_cert );
@@ -642,6 +716,7 @@ scan_secret_keyring( PKT_secret_cert *skc, u32 *keyid,
                            pkt.pkt.user_id->len, pkt.pkt.user_id->name);
            else {
                if( last_pk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
+                  || last_pk->pubkey_algo == PUBKEY_ALGO_DSA
                   || last_pk->pubkey_algo == PUBKEY_ALGO_RSA ) {
                    keyid_from_skc( last_pk, akeyid );
                    cache_user_id( pkt.pkt.user_id, akeyid );
@@ -740,12 +815,12 @@ get_user_id_string( u32 *keyid )
        for(r=user_id_db; r; r = r->next )
            if( r->keyid[0] == keyid[0] && r->keyid[1] == keyid[1] ) {
                p = m_alloc( r->len + 10 );
-               sprintf(p, "%08lX %.*s", keyid[1], r->len, r->name );
+               sprintf(p, "%08lX %.*s", (ulong)keyid[1], r->len, r->name );
                return p;
            }
     } while( ++pass < 2 && !get_pubkey( NULL, keyid ) );
     p = m_alloc( 15 );
-    sprintf(p, "%08lX [?]", keyid[1] );
+    sprintf(p, "%08lX [?]", (ulong)keyid[1] );
     return p;
 }