diff options
author | Werner Koch <[email protected]> | 2001-11-13 12:50:14 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2001-11-13 12:50:14 +0000 |
commit | 90d060c1997c6c0b9f26c9088020d62f91d450da (patch) | |
tree | b2e7720d625699a49729b36286fb66a774c5faed /sm | |
parent | A Makefile is a pretty useful thing (diff) | |
download | gnupg-90d060c1997c6c0b9f26c9088020d62f91d450da.tar.gz gnupg-90d060c1997c6c0b9f26c9088020d62f91d450da.zip |
We have reached a state where we are able to import certs and
check the certification path.
Diffstat (limited to 'sm')
-rw-r--r-- | sm/Makefile.am | 7 | ||||
-rw-r--r-- | sm/certchain.c | 131 | ||||
-rw-r--r-- | sm/certcheck.c | 156 | ||||
-rw-r--r-- | sm/certdump.c | 131 | ||||
-rw-r--r-- | sm/certpath.c | 131 | ||||
-rw-r--r-- | sm/fingerprint.c | 104 | ||||
-rw-r--r-- | sm/gpgsm.c | 15 | ||||
-rw-r--r-- | sm/gpgsm.h | 35 | ||||
-rw-r--r-- | sm/import.c | 200 | ||||
-rw-r--r-- | sm/keydb.c | 557 | ||||
-rw-r--r-- | sm/keydb.h | 46 | ||||
-rw-r--r-- | sm/misc.c | 54 | ||||
-rw-r--r-- | sm/util.h | 8 |
13 files changed, 1149 insertions, 426 deletions
diff --git a/sm/Makefile.am b/sm/Makefile.am index ec2c1b247..ab34f10b6 100644 --- a/sm/Makefile.am +++ b/sm/Makefile.am @@ -28,10 +28,15 @@ BUILT_SOURCES = errors.c gpgsm_SOURCES = \ gpgsm.c gpgsm.h \ util.h misc.c errors.c \ + keydb.c keydb.h \ server.c \ + fingerprint.c \ + certdump.c \ + certcheck.c \ + certpath.c \ import.c -gpgsm_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \ +gpgsm_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a ../kbx/libkeybox.a \ ../../libksba/src/.libs/libksba.a \ ../../libgcrypt/src/.libs/libgcrypt.so.1 diff --git a/sm/certchain.c b/sm/certchain.c new file mode 100644 index 000000000..aef1612cc --- /dev/null +++ b/sm/certchain.c @@ -0,0 +1,131 @@ +/* certpath.c - path validation + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * 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, + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include <gcrypt.h> +#include <ksba.h> + +#include "gpgsm.h" +#include "keydb.h" +#include "i18n.h" + +int +gpgsm_validate_path (KsbaCert cert) +{ + int rc = 0, depth = 0; + char *issuer = NULL; + char *subject = NULL; + KEYDB_HANDLE kh = keydb_new (0); + KsbaCert subject_cert = NULL, issuer_cert = NULL; + + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = GPGSM_General_Error; + goto leave; + } + + log_debug ("validate path for certificate:\n"); + gpgsm_dump_cert (cert); + + subject_cert = cert; + + for (;;) + { + xfree (issuer); + xfree (subject); + issuer = ksba_cert_get_issuer (subject_cert); + subject = ksba_cert_get_subject (subject_cert); + + if (!issuer) + { + if (DBG_X509) + log_debug ("ERROR: issuer missing\n"); + rc = GPGSM_Bad_Certificate; + goto leave; + } + + if (subject && !strcmp (issuer, subject)) + { + if (gpgsm_check_cert_sig (subject_cert, subject_cert) ) + { + log_debug ("selfsigned certificate has a BAD signatures\n"); + rc = depth? GPGSM_Bad_Certificate_Path : GPGSM_Bad_Certificate; + goto leave; + } + log_debug ("selfsigned certificate is good\n"); + break; /* okay, a self-signed certicate is an end-point */ + } + + depth++; + /* fixme: check against a maximum path length */ + + /* find the next cert up the tree */ + keydb_search_reset (kh); + rc = keydb_search_issuer (kh, issuer); + if (rc) + { + log_debug ("failed to find issuer's certificate: rc=%d\n", rc); + rc = GPGSM_Missing_Certificate; + goto leave; + } + + ksba_cert_release (issuer_cert); issuer_cert = NULL; + rc = keydb_get_cert (kh, &issuer_cert); + if (rc) + { + log_debug ("failed to get cert: rc=%d\n", rc); + rc = GPGSM_General_Error; + goto leave; + } + + log_debug ("got issuer's certificate:\n"); + gpgsm_dump_cert (issuer_cert); + + if (gpgsm_check_cert_sig (issuer_cert, subject_cert) ) + { + log_debug ("certificate has a BAD signatures\n"); + rc = GPGSM_Bad_Certificate_Path; + goto leave; + } + log_debug ("certificate is good\n"); + + keydb_search_reset (kh); + subject_cert = issuer_cert; + issuer_cert = NULL; + } + + leave: + xfree (issuer); + keydb_release (kh); + ksba_cert_release (issuer_cert); + if (subject_cert != cert) + ksba_cert_release (subject_cert); + return rc; +} + diff --git a/sm/certcheck.c b/sm/certcheck.c new file mode 100644 index 000000000..a86aa2d9e --- /dev/null +++ b/sm/certcheck.c @@ -0,0 +1,156 @@ +/* certcheck.c - check one certificate + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * 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, + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include <gcrypt.h> +#include <ksba.h> + +#include "gpgsm.h" +#include "keydb.h" +#include "i18n.h" + +static int +do_encode_md (GCRY_MD_HD md, int algo, size_t len, unsigned nbits, + const byte *asn, size_t asnlen, GCRY_MPI *r_val) +{ + int nframe = (nbits+7) / 8; + byte *frame; + int i, n; + + if ( len + asnlen + 4 > nframe ) + { + log_error ("can't encode a %d bit MD into a %d bits frame\n", + (int)(len*8), (int)nbits); + return GPGSM_Internal_Error; + } + + /* We encode the MD in this way: + * + * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) + * + * PAD consists of FF bytes. + */ + frame = xtrymalloc (nframe); + if (!frame) + return GPGSM_Out_Of_Core; + n = 0; + frame[n++] = 0; + frame[n++] = 1; /* block type */ + i = nframe - len - asnlen -3 ; + assert ( i > 1 ); + memset ( frame+n, 0xff, i ); n += i; + frame[n++] = 0; + memcpy ( frame+n, asn, asnlen ); n += asnlen; + memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len; + assert ( n == nframe ); + gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, &nframe); + xfree (frame); + return 0; +} + + +/* + Check the signature on CERT using the ISSUER-CERT. This function + does only test the cryptographic signature and nothing else. It is + assumed that the ISSUER_CERT is valid. */ +int +gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert) +{ + /* OID for MD5 as defined in PKCS#1 (rfc2313) */ + static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 (md5) */ + { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 + }; + + GCRY_MD_HD md; + int rc, algo; + GCRY_MPI frame; + char *p; + GCRY_SEXP s_sig, s_hash, s_pkey; + + algo = ksba_cert_get_digest_algo (cert); + md = gcry_md_open (algo, 0); + if (!md) + { + log_error ("md_open failed: %s\n", gcry_strerror (-1)); + return GPGSM_General_Error; + } + + rc = ksba_cert_hash (cert, 1, HASH_FNC, md); + if (rc) + { + log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc)); + gcry_md_close (md); + return map_ksba_err (rc); + } + gcry_md_final (md); + + p = ksba_cert_get_sig_val (cert); /* fixme: check p*/ + if (DBG_X509) + log_debug ("signature: %s\n", p); + + rc = gcry_sexp_sscan ( &s_sig, NULL, p, strlen(p)); + if (rc) + { + log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); + return map_gcry_err (rc); + } + /*gcry_sexp_dump (s_sig);*/ + + + /* FIXME: need to map the algo to the ASN OID - we assume a fixed + one for now */ + rc = do_encode_md (md, algo, 16, 2048, asn, DIM(asn), &frame); + if (rc) + { + /* fixme: clean up some things */ + return rc; + } + /* put hash into the S-Exp s_hash */ + if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) + BUG (); + /*fputs ("hash:\n", stderr); gcry_sexp_dump (s_hash);*/ + + p = ksba_cert_get_public_key (issuer_cert); + if (DBG_X509) + log_debug ("issuer public key: %s\n", p); + + rc = gcry_sexp_sscan ( &s_pkey, NULL, p, strlen(p)); + if (rc) + { + log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); + return map_gcry_err (rc); + } + /*gcry_sexp_dump (s_pkey);*/ + + rc = gcry_pk_verify (s_sig, s_hash, s_pkey); + if (DBG_CRYPTO) + log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc)); + return map_gcry_err (rc); +} + diff --git a/sm/certdump.c b/sm/certdump.c new file mode 100644 index 000000000..5dfce2a02 --- /dev/null +++ b/sm/certdump.c @@ -0,0 +1,131 @@ +/* certdump.c - Dump a certificate for debugging + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * 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, + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include <gcrypt.h> +#include <ksba.h> + +#include "gpgsm.h" +#include "keydb.h" + +static void +print_integer (unsigned char *p) +{ + unsigned long len; + + if (!p) + fputs ("none", stdout); + else + { + len = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + for (p+=4; len; len--, p++) + printf ("%02X", *p); + } +} + +static void +print_time (time_t t) +{ + + if (!t) + fputs ("none", stdout); + else if ( t == (time_t)(-1) ) + fputs ("error", stdout); + else + { + struct tm *tp; + + tp = gmtime (&t); + printf ("%04d-%02d-%02d %02d:%02d:%02d", + 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, + tp->tm_hour, tp->tm_min, tp->tm_sec); + assert (!tp->tm_isdst); + } +} + +static void +print_dn (char *p) +{ + + if (!p) + fputs ("error", stdout); + else + printf ("`%s'", p); +} + + +void +gpgsm_dump_cert (KsbaCert cert) +{ + unsigned char *p; + char *dn; + time_t t; + + if (!cert) + { + fputs ("[no certificate]\n", stdout); + return; + } + + p = ksba_cert_get_serial (cert); + fputs ("serial: ", stdout); + print_integer (p); + ksba_free (p); + putchar ('\n'); + + t = ksba_cert_get_validity (cert, 0); + fputs ("notBefore: ", stdout); + print_time (t); + putchar ('\n'); + t = ksba_cert_get_validity (cert, 1); + fputs ("notAfter: ", stdout); + print_time (t); + putchar ('\n'); + + dn = ksba_cert_get_issuer (cert); + fputs ("issuer: ", stdout); + print_dn (dn); + ksba_free (dn); + putchar ('\n'); + + dn = ksba_cert_get_subject (cert); + fputs ("subject: ", stdout); + print_dn (dn); + ksba_free (dn); + putchar ('\n'); + + printf ("hash algo: %d\n", ksba_cert_get_digest_algo (cert)); + + p = gpgsm_get_fingerprint_string (cert, 0); + printf ("SHA1 Fingerprint=%s\n", p); + xfree (p); +} + + + + diff --git a/sm/certpath.c b/sm/certpath.c new file mode 100644 index 000000000..aef1612cc --- /dev/null +++ b/sm/certpath.c @@ -0,0 +1,131 @@ +/* certpath.c - path validation + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * 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, + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include <gcrypt.h> +#include <ksba.h> + +#include "gpgsm.h" +#include "keydb.h" +#include "i18n.h" + +int +gpgsm_validate_path (KsbaCert cert) +{ + int rc = 0, depth = 0; + char *issuer = NULL; + char *subject = NULL; + KEYDB_HANDLE kh = keydb_new (0); + KsbaCert subject_cert = NULL, issuer_cert = NULL; + + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = GPGSM_General_Error; + goto leave; + } + + log_debug ("validate path for certificate:\n"); + gpgsm_dump_cert (cert); + + subject_cert = cert; + + for (;;) + { + xfree (issuer); + xfree (subject); + issuer = ksba_cert_get_issuer (subject_cert); + subject = ksba_cert_get_subject (subject_cert); + + if (!issuer) + { + if (DBG_X509) + log_debug ("ERROR: issuer missing\n"); + rc = GPGSM_Bad_Certificate; + goto leave; + } + + if (subject && !strcmp (issuer, subject)) + { + if (gpgsm_check_cert_sig (subject_cert, subject_cert) ) + { + log_debug ("selfsigned certificate has a BAD signatures\n"); + rc = depth? GPGSM_Bad_Certificate_Path : GPGSM_Bad_Certificate; + goto leave; + } + log_debug ("selfsigned certificate is good\n"); + break; /* okay, a self-signed certicate is an end-point */ + } + + depth++; + /* fixme: check against a maximum path length */ + + /* find the next cert up the tree */ + keydb_search_reset (kh); + rc = keydb_search_issuer (kh, issuer); + if (rc) + { + log_debug ("failed to find issuer's certificate: rc=%d\n", rc); + rc = GPGSM_Missing_Certificate; + goto leave; + } + + ksba_cert_release (issuer_cert); issuer_cert = NULL; + rc = keydb_get_cert (kh, &issuer_cert); + if (rc) + { + log_debug ("failed to get cert: rc=%d\n", rc); + rc = GPGSM_General_Error; + goto leave; + } + + log_debug ("got issuer's certificate:\n"); + gpgsm_dump_cert (issuer_cert); + + if (gpgsm_check_cert_sig (issuer_cert, subject_cert) ) + { + log_debug ("certificate has a BAD signatures\n"); + rc = GPGSM_Bad_Certificate_Path; + goto leave; + } + log_debug ("certificate is good\n"); + + keydb_search_reset (kh); + subject_cert = issuer_cert; + issuer_cert = NULL; + } + + leave: + xfree (issuer); + keydb_release (kh); + ksba_cert_release (issuer_cert); + if (subject_cert != cert) + ksba_cert_release (subject_cert); + return rc; +} + diff --git a/sm/fingerprint.c b/sm/fingerprint.c new file mode 100644 index 000000000..9453a6eab --- /dev/null +++ b/sm/fingerprint.c @@ -0,0 +1,104 @@ +/* fingerprint.c - Get the fingerprint + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * 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, + * 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 + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <time.h> +#include <assert.h> + +#include <gcrypt.h> +#include <ksba.h> + +#include "gpgsm.h" + +/* Return the fingerprint of the certificate (we can't put this into + libksba becuase we need libgcrypt support). The caller must + provide an array of sufficient length or NULL so that the function + allocates the array. If r_len is not NULL, the length of the + digest is return, well, this can also be done by using + gcry_md_get_algo_dlen(). If algo is 0, a SHA-1 will be used. + + If there is a problem , the function does never return NULL but a + digest of all 0xff. + */ +char * +gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len) +{ + GCRY_MD_HD md; + int rc, len; + + if (!algo) + algo = GCRY_MD_SHA1; + + len = gcry_md_get_algo_dlen (algo); + assert (len); + if (!array) + array = xmalloc (len); + + if (r_len) + *r_len = len; + + md = gcry_md_open (algo, 0); + if (!md) + { + log_error ("md_open failed: %s\n", gcry_strerror (-1)); + memset (array, 0xff, len); /* better return an invalid fpr than NULL */ + return array; + } + + rc = ksba_cert_hash (cert, 0, HASH_FNC, md); + if (rc) + { + log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc)); + gcry_md_close (md); + memset (array, 0xff, len); /* better return an invalid fpr than NULL */ + return array; + } + gcry_md_final (md); + memcpy (array, gcry_md_read(md, algo), len ); + return array; +} + + +/* Return an allocated buffer with the formatted fungerprint */ +char * +gpgsm_get_fingerprint_string (KsbaCert cert, int algo) +{ + unsigned char digest[MAX_DIGEST_LEN]; + char *buf; + int len, i; + + if (!algo) + algo = GCRY_MD_SHA1; + + len = gcry_md_get_algo_dlen (algo); + assert (len <= MAX_DIGEST_LEN ); + gpgsm_get_fingerprint (cert, algo, digest, NULL); + buf = xmalloc (len*3+1); + *buf = 0; + for (i=0; i < len; i++ ) + sprintf (buf+strlen(buf), i? ":%02X":"%02X", digest[i]); + return buf; +} + diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 3ca58d3c8..39db2433e 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -29,7 +29,9 @@ #include <gcrypt.h> #include "gpgsm.h" #include "../assuan/assuan.h" /* malloc hooks */ +#include "../kbx/keybox.h" /* malloc hooks */ #include "i18n.h" +#include "keydb.h" enum cmd_and_opt_values { aNull = 0, @@ -441,7 +443,7 @@ set_debug(void) { if (opt.debug & DBG_MPI_VALUE) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); - if (opt.debug & DBG_CIPHER_VALUE ) + if (opt.debug & DBG_CRYPTO_VALUE ) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); } @@ -562,8 +564,9 @@ main ( int argc, char **argv) Now we are now working under our real uid */ + ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free ); assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); - /* ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );*/ + keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); if (default_config ) configname = make_filename (opt.homedir, "gpgsm.conf", NULL); @@ -831,12 +834,10 @@ main ( int argc, char **argv) if (!cmd && opt.fingerprint && !with_fpr) set_cmd (&cmd, aListKeys); -#if 0 /* fixme */ - if (!nrings && default_keyring) /* add default ring */ - add_keyblock_resource ("pubcerts.gpg", 0, 0); + if (!nrings && default_keyring) /* add default keybox */ + keydb_add_resource ("pubcerts.kbx", 0, 0); for (sl = nrings; sl; sl = sl->next) - add_keyblock_resource( sl->d, 0, 0 ); -#endif + keydb_add_resource (sl->d, 0, 0); FREE_STRLIST(nrings); fname = argc? *argv : NULL; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 1c66e1032..a4361dc1c 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -21,6 +21,7 @@ #ifndef GPGSM_H #define GPGSM_H +#include <ksba.h> #include "util.h" /* Error numbers */ @@ -31,10 +32,15 @@ enum { GPGSM_Out_Of_Core = 2, GPGSM_Invalid_Value = 3, GPGSM_IO_Error = 4, - + GPGSM_Resource_Limit = 5, + GPGSM_Internal_Error = 6, + GPGSM_Bad_Certificate = 7, + GPGSM_Bad_Certificate_Path = 8, + GPGSM_Missing_Certificate = 9, }; +#define MAX_DIGEST_LEN 24 /* A large struct name "opt" to keep global flags */ struct { @@ -77,14 +83,14 @@ struct { #define DBG_X509_VALUE 1 /* debug x.509 data reading/writing */ #define DBG_MPI_VALUE 2 /* debug mpi details */ -#define DBG_CIPHER_VALUE 4 /* debug cipher handling */ +#define DBG_CRYPTO_VALUE 4 /* debug low level crypto */ #define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ #define DBG_CACHE_VALUE 64 /* debug the caching */ #define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ #define DBG_HASHING_VALUE 512 /* debug hashing operations */ #define DBG_X509 (opt.debug & DBG_X509_VALUE) -#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE) +#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE) #define DBG_MEMORY (opt.debug & DBG_MEMORY_VALUE) #define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) #define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) @@ -95,8 +101,31 @@ void gpgsm_exit (int rc); /*-- server.c --*/ void gpgsm_server (void); +/*-- fingerprint --*/ +char *gpgsm_get_fingerprint (KsbaCert cert, int algo, char *array, int *r_len); +char *gpgsm_get_fingerprint_string (KsbaCert cert, int algo); + +/*-- certdump.c --*/ +void gpgsm_dump_cert (KsbaCert cert); + +/*-- certcheck.c --*/ +int gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert); + + +/*-- certpath.c --*/ +int gpgsm_validate_path (KsbaCert cert); + + + /*-- import.c --*/ int gpgsm_import (int in_fd); + + + +/*-- errors.c (built) --*/ +const char *gpgsm_strerror (int err); + + #endif /*GPGSM_H*/ diff --git a/sm/import.c b/sm/import.c index 7fde82327..8dc36c1ad 100644 --- a/sm/import.c +++ b/sm/import.c @@ -31,6 +31,8 @@ #include <ksba.h> #include "gpgsm.h" +#include "keydb.h" +#include "i18n.h" struct reader_cb_parm_s { FILE *fp; @@ -68,199 +70,31 @@ reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread) static void -print_integer (unsigned char *p) +store_cert (KsbaCert cert) { - unsigned long len; - - if (!p) - fputs ("none", stdout); - else - { - len = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - for (p+=4; len; len--, p++) - printf ("%02X", *p); - } -} - -static void -print_time (time_t t) -{ - - if (!t) - fputs ("none", stdout); - else if ( t == (time_t)(-1) ) - fputs ("error", stdout); - else - { - struct tm *tp; - - tp = gmtime (&t); - printf ("%04d-%02d-%02d %02d:%02d:%02d", - 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday, - tp->tm_hour, tp->tm_min, tp->tm_sec); - assert (!tp->tm_isdst); - } -} - -static void -print_dn (char *p) -{ - - if (!p) - fputs ("error", stdout); - else - printf ("`%s'", p); -} - -static void -print_cert (KsbaCert cert) -{ - unsigned char *p; - char *dn; - time_t t; - - p = ksba_cert_get_serial (cert); - fputs ("serial: ", stdout); - print_integer (p); - ksba_free (p); - putchar ('\n'); - - t = ksba_cert_get_validity (cert, 0); - fputs ("notBefore: ", stdout); - print_time (t); - putchar ('\n'); - t = ksba_cert_get_validity (cert, 1); - fputs ("notAfter: ", stdout); - print_time (t); - putchar ('\n'); - - dn = ksba_cert_get_issuer (cert); - fputs ("issuer: ", stdout); - print_dn (dn); - ksba_free (dn); - putchar ('\n'); - - dn = ksba_cert_get_subject (cert); - fputs ("subject: ", stdout); - print_dn (dn); - ksba_free (dn); - putchar ('\n'); - - printf ("hash algo: %d\n", ksba_cert_get_digest_algo (cert)); -} - - - -static MPI -do_encode_md (GCRY_MD_HD md, int algo, size_t len, unsigned nbits, - const byte *asn, size_t asnlen) -{ - int nframe = (nbits+7) / 8; - byte *frame; - int i,n; - MPI a; - - if( len + asnlen + 4 > nframe ) - log_bug("can't encode a %d bit MD into a %d bits frame\n", - (int)(len*8), (int)nbits); - - /* We encode the MD in this way: - * - * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) - * - * PAD consists of FF bytes. - */ - frame = xmalloc (nframe); - n = 0; - frame[n++] = 0; - frame[n++] = 1; /* block type */ - i = nframe - len - asnlen -3 ; - assert( i > 1 ); - memset( frame+n, 0xff, i ); n += i; - frame[n++] = 0; - memcpy( frame+n, asn, asnlen ); n += asnlen; - memcpy( frame+n, gcry_md_read(md, algo), len ); n += len; - assert( n == nframe ); - gcry_mpi_scan ( &a, GCRYMPI_FMT_USG, frame, &nframe); - xfree(frame); - return a; -} - - - - -static void -check_selfsigned_cert (KsbaCert cert) -{ - /* OID for MD5 as defined in PKCS#1 (rfc2313) */ - static byte asn[18] = /* Object ID is 1.2.840.113549.2.5 (md5) */ - { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 - }; - - GCRY_MD_HD md; - int rc, algo; - GCRY_MPI frame; - char *p; - GCRY_SEXP s_sig, s_hash, s_pkey; - - algo = ksba_cert_get_digest_algo (cert); - md = gcry_md_open (algo, 0); - if (!md) - { - log_error ("md_open failed: %s\n", gcry_strerror (-1)); - return; - } + KEYDB_HANDLE kh; + int rc; - gcry_md_start_debug (md, "cert"); - rc = ksba_cert_hash (cert, gcry_md_write, md); - if (rc) + kh = keydb_new (0); + if (!kh) { - log_error ("ksba_cert_hash failed: %s\n", ksba_strerror (rc)); - gcry_md_close (md); + log_error (_("failed to allocated keyDB handle\n")); return; } - gcry_md_final (md); - - p = ksba_cert_get_sig_val (cert); - printf ("signature: %s\n", p); - - rc = gcry_sexp_sscan ( &s_sig, NULL, p, strlen(p)); + rc = keydb_locate_writable (kh, 0); if (rc) - { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - return; - } - /*gcry_sexp_dump (s_sig);*/ - - - /* FIXME: need to map the algo to the ASN OID - we assume a fixed - one for now */ - frame = do_encode_md (md, algo, 16, 2048, asn, DIM(asn)); + log_error (_("error finding writable keyDB: %s\n"), gpgsm_strerror (rc)); - /* put hash into the S-Exp s_hash */ - if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) - BUG (); - /*fputs ("hash:\n", stderr); gcry_sexp_dump (s_hash);*/ - _gcry_log_mpidump ("hash", frame); - - p = ksba_cert_get_public_key (cert); - printf ("public key: %s\n", p); - - rc = gcry_sexp_sscan ( &s_pkey, NULL, p, strlen(p)); + rc = keydb_insert_cert (kh, cert); if (rc) { - log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc)); - return; + log_error (_("error storing certificate: %s\n"), gpgsm_strerror (rc)); } - /*gcry_sexp_dump (s_pkey);*/ - - rc = gcry_pk_verify (s_sig, s_hash, s_pkey); - log_error ("gcry_pk_verify: %s\n", gcry_strerror (rc)); - + keydb_release (kh); } + int gpgsm_import (int in_fd) @@ -311,9 +145,8 @@ gpgsm_import (int in_fd) goto leave; } - print_cert (cert); - check_selfsigned_cert (cert); - + if ( !gpgsm_validate_path (cert) ) + store_cert (cert); leave: ksba_cert_release (cert); @@ -323,3 +156,4 @@ gpgsm_import (int in_fd) return rc; } + diff --git a/sm/keydb.c b/sm/keydb.c index b12ba1df3..ef839edfb 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -28,19 +28,12 @@ #include <sys/stat.h> #include <unistd.h> -#include "util.h" -#include "options.h" -#include "keybox.h" +#include "gpgsm.h" +#include "../kbx/keybox.h" #include "keydb.h" #include "i18n.h" -static struct { - const char *homedir; - int dry_run; - int quiet; - int verbose; - int preserve_permissions; -} keydbopt; +#define DIRSEP_C '/' static int active_handles; @@ -87,25 +80,24 @@ keydb_add_resource (const char *url, int force, int secret) { static int any_secret, any_public; const char *resname = url; - IOBUF iobuf = NULL; char *filename = NULL; - int rc = 0; + int rc = 0; KeydbResourceType rt = KEYDB_RESOURCE_TYPE_NONE; - const char *created_fname = NULL; +/* const char *created_fname = NULL; */ /* Do we have an URL? * gnupg-ring:filename := this is a plain keybox * filename := See what is is, but create as plain keybox. */ if (strlen (resname) > 11) { - if (!strncmp( resname, "gnupg-ring:", 11) ) { + if (!strncmp( resname, "gnupg-kbx:", 10) ) { rt = KEYDB_RESOURCE_TYPE_KEYBOX; resname += 11; } #if !defined(HAVE_DRIVE_LETTERS) && !defined(__riscos__) else if (strchr (resname, ':')) { log_error ("invalid key resource URL `%s'\n", url ); - rc = G10ERR_GENERAL; + rc = GPGSM_General_Error; goto leave; } #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */ @@ -115,59 +107,62 @@ keydb_add_resource (const char *url, int force, int secret) if (strchr(resname, DIRSEP_C) ) filename = make_filename (resname, NULL); else - filename = make_filename (keydbopt.homedir, resname, NULL); + filename = make_filename (opt.homedir, resname, NULL); } else - filename = m_strdup (resname); + filename = xstrdup (resname); if (!force) force = secret? !any_secret : !any_public; /* see whether we can determine the filetype */ if (rt == KEYDB_RESOURCE_TYPE_NONE) { - FILE *fp = fopen( filename, "rb" ); + FILE *fp2 = fopen( filename, "rb" ); - if (fp) { + if (fp2) { u32 magic; - if (fread( &magic, 4, 1, fp) == 1 ) { + /* FIXME: check for the keybox magic */ + if (fread( &magic, 4, 1, fp2) == 1 ) + { if (magic == 0x13579ace || magic == 0xce9a5713) - ; /* GDBM magic - no more support */ + ; /* GDBM magic - no more support */ else - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - } + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + } else /* maybe empty: assume ring */ - rt = KEYDB_RESOURCE_TYPE_KEYBOX; - fclose( fp ); + rt = KEYDB_RESOURCE_TYPE_KEYBOX; + fclose (fp2); } else /* no file yet: create ring */ - rt = KEYDB_RESOURCE_TYPE_KEYBOX; + rt = KEYDB_RESOURCE_TYPE_KEYBOX; } switch (rt) { case KEYDB_RESOURCE_TYPE_NONE: log_error ("unknown type of key resource `%s'\n", url ); - rc = G10ERR_GENERAL; + rc = GPGSM_General_Error; goto leave; case KEYDB_RESOURCE_TYPE_KEYBOX: - iobuf = iobuf_open (filename); +#if 0 + fp = fopen (filename); if (!iobuf && !force) { rc = G10ERR_OPEN_FILE; goto leave; } - if (!iobuf) { + if (!fp) { char *last_slash_in_filename; last_slash_in_filename = strrchr (filename, DIRSEP_C); *last_slash_in_filename = 0; if (access(filename, F_OK)) { - /* on the first time we try to create the default homedir and - * in this case the process will be terminated, so that on the - * next invocation it can read the options file in on startup - */ + /* on the first time we try to create the default + homedir and in this case the process will be + terminated, so that on the next invocation it can + read the options file in on startup */ try_make_homedir (filename); rc = G10ERR_OPEN_FILE; *last_slash_in_filename = DIRSEP_C; @@ -185,7 +180,7 @@ keydb_add_resource (const char *url, int force, int secret) } else { #ifndef HAVE_DOSISH_SYSTEM - if (secret && !keydbopt.preserve_permissionws) { + if (secret && !opt.preserve_permissionws) { if (chmod (filename, S_IRUSR | S_IWUSR) ) { log_error (_("changing permission of " " `%s' failed: %s\n"), @@ -195,7 +190,7 @@ keydb_add_resource (const char *url, int force, int secret) } } #endif - if (!keydbopt.quiet) + if (!opt.quiet) log_info (_("keybox `%s' created\n"), filename); created_fname = filename; } @@ -204,12 +199,13 @@ keydb_add_resource (const char *url, int force, int secret) iobuf = NULL; if (created_fname) /* must invalidate that ugly cache */ iobuf_ioctl (NULL, 2, 0, (char*)created_fname); +#endif { - void *token = keybox_register_filename (filename, secret); + void *token = keybox_register_file (filename, secret); if (!token) ; /* already registered - ignore it */ else if (used_resources >= MAX_KEYDB_RESOURCES) - rc = G10ERR_RESOURCE_LIMIT; + rc = GPGSM_Resource_Limit; else { all_resources[used_resources].type = rt; @@ -223,7 +219,7 @@ keydb_add_resource (const char *url, int force, int secret) default: log_error ("resource type of `%s' not supported\n", url); - rc = G10ERR_GENERAL; + rc = GPGSM_General_Error; goto leave; } @@ -231,12 +227,12 @@ keydb_add_resource (const char *url, int force, int secret) leave: if (rc) - log_error ("keyblock resource `%s': %s\n", filename, g10_errstr(rc)); + log_error ("keyblock resource `%s': %s\n", filename, gpgsm_strerror(rc)); else if (secret) any_secret = 1; else any_public = 1; - m_free (filename); + xfree (filename); return rc; } @@ -249,7 +245,7 @@ keydb_new (int secret) KEYDB_HANDLE hd; int i, j; - hd = m_alloc_clear (sizeof *hd); + hd = xcalloc (1, sizeof *hd); hd->found = -1; assert (used_resources <= MAX_KEYDB_RESOURCES); @@ -267,7 +263,7 @@ keydb_new (int secret) hd->active[j].secret = all_resources[i].secret; hd->active[j].u.kr = keybox_new (all_resources[i].token, secret); if (!hd->active[j].u.kr) { - m_free (hd); + xfree (hd); return NULL; /* fixme: release all previously allocated handles*/ } j++; @@ -283,95 +279,101 @@ keydb_new (int secret) void keydb_release (KEYDB_HANDLE hd) { - int i; - - if (!hd) - return; - assert (active_handles > 0); - active_handles--; + int i; + + if (!hd) + return; + assert (active_handles > 0); + active_handles--; - unlock_all (hd); - for (i=0; i < hd->used; i++) { - switch (hd->active[i].type) { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - keybox_release (hd->active[i].u.kr); - break; + unlock_all (hd); + for (i=0; i < hd->used; i++) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + keybox_release (hd->active[i].u.kr); + break; } } - m_free (hd); + xfree (hd); } -/* - * Return the name of the current resource. This is function first - * looks for the last found found, then for the current search - * position, and last returns the first available resource. The - * returned string is only valid as long as the handle exists. This - * function does only return NULL if no handle is specified, in all - * other error cases an empty string is returned. - */ +/* Return the name of the current resource. This is function first + looks for the last found found, then for the current search + position, and last returns the first available resource. The + returned string is only valid as long as the handle exists. This + function does only return NULL if no handle is specified, in all + other error cases an empty string is returned. */ const char * keydb_get_resource_name (KEYDB_HANDLE hd) { - int idx; - const char *s = NULL; - - if (!hd) - return NULL; + int idx; + const char *s = NULL; + + if (!hd) + return NULL; - if ( hd->found >= 0 && hd->found < hd->used) - idx = hd->found; - else if ( hd->current >= 0 && hd->current < hd->used) - idx = hd->current; - else - idx = 0; + if ( hd->found >= 0 && hd->found < hd->used) + idx = hd->found; + else if ( hd->current >= 0 && hd->current < hd->used) + idx = hd->current; + else + idx = 0; - switch (hd->active[idx].type) { - case KEYDB_RESOURCE_TYPE_NONE: - s = NULL; - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - s = keybox_get_resource_name (hd->active[idx].u.kr); - break; + switch (hd->active[idx].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + s = NULL; + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + s = keybox_get_resource_name (hd->active[idx].u.kr); + break; } - - return s? s: ""; + + return s? s: ""; } - + static int lock_all (KEYDB_HANDLE hd) { - int i, rc = 0; - - for (i=0; !rc && i < hd->used; i++) { - switch (hd->active[i].type) { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_lock (hd->active[i].u.kr, 1); - break; + int i, rc = 0; + + for (i=0; !rc && i < hd->used; i++) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + /* FIXME rc = keybox_lock (hd->active[i].u.kr, 1);*/ + break; } } - if (rc) { + if (rc) + { /* revert the already set locks */ - for (i--; i >= 0; i--) { - switch (hd->active[i].type) { + for (i--; i >= 0; i--) + { + switch (hd->active[i].type) + { case KEYDB_RESOURCE_TYPE_NONE: break; case KEYDB_RESOURCE_TYPE_KEYBOX: - keybox_lock (hd->active[i].u.kr, 0); + /* Fixme: keybox_lock (hd->active[i].u.kr, 0);*/ break; - } - } - } + } + } + } else - hd->locked = 1; + hd->locked = 1; return rc; } @@ -379,24 +381,27 @@ lock_all (KEYDB_HANDLE hd) static void unlock_all (KEYDB_HANDLE hd) { - int i; - - if (!hd->locked) - return; - - for (i=hd->used-1; i >= 0; i--) { - switch (hd->active[i].type) { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - keybox_lock (hd->active[i].u.kr, 0); - break; + int i; + + if (!hd->locked) + return; + + for (i=hd->used-1; i >= 0; i--) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + /* fixme: keybox_lock (hd->active[i].u.kr, 0);*/ + break; } } - hd->locked = 0; + hd->locked = 0; } - + +#if 0 /* * Return the last found keybox. Caller must free it. * The returned keyblock has the kbode flag bit 0 set for the node with @@ -440,7 +445,7 @@ keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb) if ( hd->found < 0 || hd->found >= hd->used) return -1; /* nothing found */ - if( keydbopt.dry_run ) + if( opt.dry_run ) return 0; rc = lock_all (hd); @@ -473,7 +478,7 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) if (!hd) return G10ERR_INV_ARG; - if( keydbopt.dry_run ) + if( opt.dry_run ) return 0; if ( hd->found >= 0 && hd->found < hd->used) @@ -500,41 +505,157 @@ keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb) return rc; } +#endif /*disabled code*/ + + + +/* + Return the last found keybox. Caller must free it. The returned + keyblock has the kbode flag bit 0 set for the node with the public + key used to locate the keyblock or flag bit 1 set for the user ID + node. */ +int +keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert) +{ + int rc = 0; + + if (!hd) + return GPGSM_Invalid_Value; + + if ( hd->found < 0 || hd->found >= hd->used) + return -1; /* nothing found */ + + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = GPGSM_General_Error; /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_get_cert (hd->active[hd->found].u.kr, r_cert); + break; + } + + return rc; +} /* - * The current keyblock will be deleted. + * Insert a new Certificate into one of the resources. */ int -keydb_delete_keyblock (KEYDB_HANDLE hd) +keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert) { - int rc = -1; + int rc = -1; + int idx; + char digest[20]; + + if (!hd) + return GPGSM_Invalid_Value; - if (!hd) - return G10ERR_INV_ARG; + if (opt.dry_run) + return 0; + + if ( hd->found >= 0 && hd->found < hd->used) + idx = hd->found; + else if ( hd->current >= 0 && hd->current < hd->used) + idx = hd->current; + else + return GPGSM_General_Error; + + rc = lock_all (hd); + if (rc) + return rc; - if ( hd->found < 0 || hd->found >= hd->used) - return -1; /* nothing found */ + gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ - if( keydbopt.dry_run ) - return 0; + switch (hd->active[idx].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = GPGSM_General_Error; + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest); + break; + } + + unlock_all (hd); + return rc; +} - rc = lock_all (hd); - if (rc) - return rc; - switch (hd->active[hd->found].type) { - case KEYDB_RESOURCE_TYPE_NONE: - rc = G10ERR_GENERAL; /* oops */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_delete_keyblock (hd->active[hd->found].u.kr); - break; + +/* update the current keyblock with KB */ +int +keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert) +{ + int rc = 0; + char digest[20]; + + if (!hd) + return GPGSM_Invalid_Value; + + if ( hd->found < 0 || hd->found >= hd->used) + return -1; /* nothing found */ + + if (opt.dry_run) + return 0; + + rc = lock_all (hd); + if (rc) + return rc; + + gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/ + + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = GPGSM_General_Error; /* oops */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest); + break; } - unlock_all (hd); + unlock_all (hd); + return rc; +} + + +/* + * The current keyblock or cert will be deleted. + */ +int +keydb_delete (KEYDB_HANDLE hd) +{ + int rc = -1; + + if (!hd) + return GPGSM_Invalid_Value; + + if ( hd->found < 0 || hd->found >= hd->used) + return -1; /* nothing found */ + + if( opt.dry_run ) + return 0; + + rc = lock_all (hd); + if (rc) return rc; + + switch (hd->active[hd->found].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + rc = GPGSM_General_Error; + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_delete (hd->active[hd->found].u.kr); + break; + } + + unlock_all (hd); + return rc; } + /* * Locate the default writable key resource, so that the next @@ -547,12 +668,12 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) int rc; if (!hd) - return G10ERR_INV_ARG; + return GPGSM_Invalid_Value; rc = keydb_search_reset (hd); /* this does reset hd->current */ if (rc) return rc; - + for ( ; hd->current >= 0 && hd->current < hd->used; hd->current++) { switch (hd->active[hd->current].type) @@ -576,7 +697,7 @@ keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved) void keydb_rebuild_caches (void) { - int i, rc; + int i; for (i=0; i < used_resources; i++) { @@ -587,10 +708,10 @@ keydb_rebuild_caches (void) case KEYDB_RESOURCE_TYPE_NONE: /* ignore */ break; case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_rebuild_cache (all_resources[i].token); - if (rc) - log_error (_("failed to rebuild keybox cache: %s\n"), - g10_errstr (rc)); +/* rc = keybox_rebuild_cache (all_resources[i].token); */ +/* if (rc) */ +/* log_error (_("failed to rebuild keybox cache: %s\n"), */ +/* g10_errstr (rc)); */ break; } } @@ -604,27 +725,29 @@ keydb_rebuild_caches (void) int keydb_search_reset (KEYDB_HANDLE hd) { - int i, rc = 0; - - if (!hd) - return G10ERR_INV_ARG; + int i, rc = 0; + + if (!hd) + return GPGSM_Invalid_Value; - hd->current = 0; - hd->found = -1; - /* and reset all resources */ - for (i=0; !rc && i < hd->used; i++) { - switch (hd->active[i].type) { - case KEYDB_RESOURCE_TYPE_NONE: - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_search_reset (hd->active[i].u.kr); - break; + hd->current = 0; + hd->found = -1; + /* and reset all resources */ + for (i=0; !rc && i < hd->used; i++) + { + switch (hd->active[i].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_search_reset (hd->active[i].u.kr); + break; } } - return rc; + return rc; /* fixme: we need to map error codes or share them with + all modules*/ } - /* * Search through all keydb resources, starting at the current position, * for a keyblock which contains one of the keys described in the DESC array. @@ -632,71 +755,101 @@ keydb_search_reset (KEYDB_HANDLE hd) int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) { - int rc = -1; - - if (!hd) - return G10ERR_INV_ARG; + int rc = -1; + + if (!hd) + return GPGSM_Invalid_Value; - while (rc == -1 && hd->current >= 0 && hd->current < hd->used) { - switch (hd->active[hd->current].type) { - case KEYDB_RESOURCE_TYPE_NONE: - BUG(); /* we should never see it here */ - break; - case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc); - break; + while (rc == -1 && hd->current >= 0 && hd->current < hd->used) + { + switch (hd->active[hd->current].type) + { + case KEYDB_RESOURCE_TYPE_NONE: + BUG(); /* we should never see it here */ + break; + case KEYDB_RESOURCE_TYPE_KEYBOX: + rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc); + break; } - if (rc == -1) /* EOF -> switch to next resource */ - hd->current++; - else if (!rc) - hd->found = hd->current; + if (rc == -1) /* EOF -> switch to next resource */ + hd->current++; + else if (!rc) + hd->found = hd->current; } - - return rc; + + return rc; } int keydb_search_first (KEYDB_HANDLE hd) { - KEYDB_SEARCH_DESC desc; - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_FIRST; - return keydb_search (hd, &desc, 1); + KEYDB_SEARCH_DESC desc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_FIRST; + return keydb_search (hd, &desc, 1); } int keydb_search_next (KEYDB_HANDLE hd) { - KEYDB_SEARCH_DESC desc; - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_NEXT; - return keydb_search (hd, &desc, 1); + KEYDB_SEARCH_DESC desc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_NEXT; + return keydb_search (hd, &desc, 1); } int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid) { - KEYDB_SEARCH_DESC desc; - - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_LONG_KID; - desc.u.kid[0] = kid[0]; - desc.u.kid[1] = kid[1]; - return keydb_search (hd, &desc, 1); + KEYDB_SEARCH_DESC desc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_LONG_KID; +/* desc.u.kid[0] = kid[0]; */ +/* desc.u.kid[1] = kid[1]; */ + return keydb_search (hd, &desc, 1); } int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr) { - KEYDB_SEARCH_DESC desc; + KEYDB_SEARCH_DESC desc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_FPR; + memcpy (desc.u.fpr, fpr, 20); + return keydb_search (hd, &desc, 1); +} - memset (&desc, 0, sizeof desc); - desc.mode = KEYDB_SEARCH_MODE_FPR; - memcpy (desc.u.fpr, fpr, MAX_FINGERPRINT_LEN); - return keydb_search (hd, &desc, 1); +int +keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer) +{ + KEYDB_SEARCH_DESC desc; + int rc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_ISSUER; + desc.u.name = issuer; + rc = keydb_search (hd, &desc, 1); + return rc; +} + +int +keydb_search_issuer_sn (KEYDB_HANDLE hd, + const char *issuer, const unsigned char *serial) +{ + KEYDB_SEARCH_DESC desc; + int rc; + + memset (&desc, 0, sizeof desc); + desc.mode = KEYDB_SEARCH_MODE_ISSUER_SN; + desc.sn = serial; + desc.u.name = issuer; + rc = keydb_search (hd, &desc, 1); + return rc; } diff --git a/sm/keydb.h b/sm/keydb.h index f67f7362e..71f457fef 100644 --- a/sm/keydb.h +++ b/sm/keydb.h @@ -21,53 +21,43 @@ #ifndef GNUPG_KEYDB_H #define GNUPG_KEYDB_H +#include <ksba.h> + +#include "../kbx/keybox-search-desc.h" + typedef struct keydb_handle *KEYDB_HANDLE; -typedef enum { - KEYDB_SEARCH_MODE_NONE, - KEYDB_SEARCH_MODE_EXACT, - KEYDB_SEARCH_MODE_SUBSTR, - KEYDB_SEARCH_MODE_MAIL, - KEYDB_SEARCH_MODE_MAILSUB, - KEYDB_SEARCH_MODE_MAILEND, - KEYDB_SEARCH_MODE_WORDS, - KEYDB_SEARCH_MODE_SHORT_KID, - KEYDB_SEARCH_MODE_LONG_KID, - KEYDB_SEARCH_MODE_FPR16, - KEYDB_SEARCH_MODE_FPR20, - KEYDB_SEARCH_MODE_FPR, - KEYDB_SEARCH_MODE_FIRST, - KEYDB_SEARCH_MODE_NEXT -} KeydbSearchMode; - -struct keydb_search_desc { - KeydbSearchMode mode; - int (*skipfnc)(void *,u32*); - void *skipfncvalue; - union { - const char *name; - char fpr[MAX_FINGERPRINT_LEN]; - u32 kid[2]; - } u; -}; /*-- keydb.c --*/ int keydb_add_resource (const char *url, int force, int secret); KEYDB_HANDLE keydb_new (int secret); void keydb_release (KEYDB_HANDLE hd); const char *keydb_get_resource_name (KEYDB_HANDLE hd); + +#if 0 /* pgp stuff */ int keydb_get_keyblock (KEYDB_HANDLE hd, KBNODE *ret_kb); int keydb_update_keyblock (KEYDB_HANDLE hd, KBNODE kb); int keydb_insert_keyblock (KEYDB_HANDLE hd, KBNODE kb); -int keydb_delete_keyblock (KEYDB_HANDLE hd); +#endif + +int keydb_get_cert (KEYDB_HANDLE hd, KsbaCert *r_cert); +int keydb_insert_cert (KEYDB_HANDLE hd, KsbaCert cert); +int keydb_update_cert (KEYDB_HANDLE hd, KsbaCert cert); + +int keydb_delete (KEYDB_HANDLE hd); + int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved); void keydb_rebuild_caches (void); + int keydb_search_reset (KEYDB_HANDLE hd); int keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc); int keydb_search_first (KEYDB_HANDLE hd); int keydb_search_next (KEYDB_HANDLE hd); int keydb_search_kid (KEYDB_HANDLE hd, u32 *kid); int keydb_search_fpr (KEYDB_HANDLE hd, const byte *fpr); +int keydb_search_issuer (KEYDB_HANDLE hd, const char *issuer); +int keydb_search_issuer_sn (KEYDB_HANDLE hd, + const char *issuer, const unsigned char *serial); #endif /*GNUPG_KEYDB_H*/ @@ -29,13 +29,63 @@ #include <ksba.h> #include "util.h" +#include "gpgsm.h" /* Note: we might want to wrap this in a macro to get our hands on - the line and file wehre the error occired */ + the line and file where the error occired */ int map_ksba_err (int err) { - return -1; + switch (err) + { + case -1: + case 0: + break; + + default: + err = GPGSM_General_Error; + break; + } + return err; } + +int +map_gcry_err (int err) +{ + switch (err) + { + case -1: + case 0: + break; + + default: + err = GPGSM_General_Error; + break; + } + return err; +} + +int +map_kbx_err (int err) +{ + switch (err) + { + case -1: + case 0: + break; + + default: + err = GPGSM_General_Error; + break; + } + return err; +} + + + + + + + @@ -23,6 +23,10 @@ #include <gcrypt.h> /* we need this for the memory function protos */ +/* to pass the fucntion to libksba we need to cast it */ +#define HASH_FNC ((void (*)(void *, const byte*,size_t))gcry_md_write) + + #include "../jnlib/logging.h" #include "../jnlib/argparse.h" #include "../jnlib/stringhelp.h" @@ -46,5 +50,9 @@ /*-- misc.c --*/ int map_ksba_err (int err); +int map_gcry_err (int err); +int map_kbx_err (int err); #endif /*UTIL_H*/ + + |