diff options
Diffstat (limited to 'sm')
-rw-r--r-- | sm/ChangeLog | 15 | ||||
-rw-r--r-- | sm/certchain.c | 16 | ||||
-rw-r--r-- | sm/certcheck.c | 138 | ||||
-rw-r--r-- | sm/gpgsm.c | 8 | ||||
-rw-r--r-- | sm/gpgsm.h | 1 | ||||
-rw-r--r-- | sm/import.c | 39 |
6 files changed, 156 insertions, 61 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog index 51f46c335..951c8db17 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,20 @@ +2004-08-17 Werner Koch <[email protected]> + + * import.c (check_and_store): Do a full validation if + --with-validation is set. + + * certchain.c (gpgsm_basic_cert_check): Print more detailed error + messages. + + * certcheck.c (do_encode_md): Partly support DSA. Add new arg + PKALGO. Changed all callers to pass it. + (pk_algo_from_sexp): New. + 2004-08-16 Werner Koch <[email protected]> + * gpgsm.c: New option --fixed-passphrase. + * import.c (popen_protect_tool): Pass it to the protect-tool. + * server.c (cmd_encrypt): Use DEFAULT_RECPLIST and not recplist for encrypt-to keys. diff --git a/sm/certchain.c b/sm/certchain.c index 8d54767f8..2ce247f65 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -39,9 +39,9 @@ #include "i18n.h" -/* If LISTMODE is true, print FORMAT in liting mode to FP. If +/* If LISTMODE is true, print FORMAT using LISTMODE to FP. If LISTMODE is false, use the string to print an log_info or, if - IS_ERROR is true, an log_error. */ + IS_ERROR is true, and log_error. */ static void do_list (int is_error, int listmode, FILE *fp, const char *format, ...) { @@ -925,9 +925,11 @@ gpgsm_basic_cert_check (ksba_cert_t cert) if (subject && !strcmp (issuer, subject)) { - if (gpgsm_check_cert_sig (cert, cert) ) + rc = gpgsm_check_cert_sig (cert, cert); + if (rc) { - log_error ("selfsigned certificate has a BAD signature\n"); + log_error ("selfsigned certificate has a BAD signature: %s\n", + gpg_strerror (rc)); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } @@ -960,9 +962,11 @@ gpgsm_basic_cert_check (ksba_cert_t cert) goto leave; } - if (gpgsm_check_cert_sig (issuer_cert, cert) ) + rc = gpgsm_check_cert_sig (issuer_cert, cert); + if (rc) { - log_error ("certificate has a BAD signature\n"); + log_error ("certificate has a BAD signature: %s\n", + gpg_strerror (rc)); rc = gpg_error (GPG_ERR_BAD_CERT); goto leave; } diff --git a/sm/certcheck.c b/sm/certcheck.c index b5ed9914a..4f667cbbe 100644 --- a/sm/certcheck.c +++ b/sm/certcheck.c @@ -1,5 +1,5 @@ /* certcheck.c - check one certificate - * Copyright (C) 2001, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -36,51 +36,71 @@ static int -do_encode_md (gcry_md_hd_t md, int algo, unsigned int nbits, +do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits, gcry_mpi_t *r_val) { - int nframe = (nbits+7) / 8; - byte *frame; - int i, n; - byte asn[100]; - size_t asnlen; - size_t len; - - asnlen = DIM(asn); - if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + int n, nframe; + unsigned char *frame; + + if (pkalgo == GCRY_PK_DSA) { - log_error ("no object identifier for algo %d\n", algo); - return gpg_error (GPG_ERR_INTERNAL); + nframe = gcry_md_get_algo_dlen (algo); + if (nframe != 20) + { + log_error (_("DSA requires the use of a 160 bit hash algorithm\n")); + return gpg_error (GPG_ERR_INTERNAL); + } + frame = xtrymalloc (nframe); + if (!frame) + return OUT_OF_CORE (errno); + memcpy (frame, gcry_md_read (md, algo), nframe); + n = nframe; } - - len = gcry_md_get_algo_dlen (algo); - - if ( len + asnlen + 4 > nframe ) + else { - log_error ("can't encode a %d bit MD into a %d bits frame\n", - (int)(len*8), (int)nbits); - return gpg_error (GPG_ERR_INTERNAL); + int i; + unsigned char asn[100]; + size_t asnlen; + size_t len; + + nframe = (nbits+7) / 8; + + asnlen = DIM(asn); + if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + { + log_error ("no object identifier for algo %d\n", algo); + return gpg_error (GPG_ERR_INTERNAL); + } + + len = gcry_md_get_algo_dlen (algo); + + 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 gpg_error (GPG_ERR_INTERNAL); + } + + /* 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 OUT_OF_CORE (errno); + 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 ); } - - /* 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 OUT_OF_CORE (errno); - 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 ); if (DBG_X509) { int j; @@ -95,6 +115,38 @@ do_encode_md (gcry_md_hd_t md, int algo, unsigned int nbits, return 0; } +/* Return the public key algorithm id from the S-expression PKEY. + FIXME: libgcrypt should provide such a function. Note that this + implementation uses the names as used by libksba. */ +static int +pk_algo_from_sexp (gcry_sexp_t pkey) +{ + gcry_sexp_t l1, l2; + const char *name; + size_t n; + int algo; + + l1 = gcry_sexp_find_token (pkey, "public-key", 0); + if (!l1) + return 0; /* Not found. */ + l2 = gcry_sexp_cadr (l1); + gcry_sexp_release (l1); + + name = gcry_sexp_nth_data (l2, 0, &n); + if (!name) + algo = 0; /* Not found. */ + else if (n==3 && !memcmp (name, "rsa", 3)) + algo = GCRY_PK_RSA; + else if (n==3 && !memcmp (name, "dsa", 3)) + algo = GCRY_PK_DSA; + else if (n==13 && !memcmp (name, "ambiguous-rsa", 13)) + algo = GCRY_PK_RSA; + else + algo = 0; + gcry_sexp_release (l2); + return algo; +} + /* Check the signature on CERT using the ISSUER-CERT. This function @@ -182,7 +234,8 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) return rc; } - rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame); + rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey), + gcry_pk_get_nbits (s_pkey), &frame); if (rc) { gcry_md_close (md); @@ -254,7 +307,8 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval, } - rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame); + rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey), + gcry_pk_get_nbits (s_pkey), &frame); if (rc) { gcry_sexp_release (s_sig); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 5fb80a0de..3331537b1 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -95,6 +95,7 @@ enum cmd_and_opt_values { oDebugAllowCoreDump, oDebugNoChainValidation, oDebugIgnoreExpiration, + oFixedPassphrase, oLogFile, oEnableSpecialFilenames, @@ -340,6 +341,7 @@ static ARGPARSE_OPTS opts[] = { { oDebugAllowCoreDump, "debug-allow-core-dump", 0, "@" }, { oDebugNoChainValidation, "debug-no-chain-validation", 0, "@"}, { oDebugIgnoreExpiration, "debug-ignore-expiration", 0, "@"}, + { oFixedPassphrase, "fixed-passphrase", 2, "@"}, { oStatusFD, "status-fd" ,1, N_("|FD|write status info to this FD") }, { aDummy, "no-comment", 0, "@"}, { aDummy, "completes-needed", 1, "@"}, @@ -706,6 +708,7 @@ main ( int argc, char **argv) CERTLIST signerlist = NULL; int do_not_setup_keys = 0; + /* trap_unaligned ();*/ set_strusage (my_strusage); gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); @@ -802,10 +805,10 @@ main ( int argc, char **argv) ctrl.status_fd = -1; /* not status output */ ctrl.autodetect_encoding = 1; - /* set the default option file */ + /* Set the default option file */ if (default_config ) configname = make_filename (opt.homedir, "gpgsm.conf", NULL); - /* cet the default policy file */ + /* Set the default policy file */ opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL); argc = orig_argc; @@ -1019,6 +1022,7 @@ main ( int argc, char **argv) break; case oDebugNoChainValidation: opt.no_chain_validation = 1; break; case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break; + case oFixedPassphrase: opt.fixed_passphrase = pargs.r.ret_str; break; case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break; case oLoggerFD: log_set_fd (pargs.r.ret_int ); break; diff --git a/sm/gpgsm.h b/sm/gpgsm.h index a1813462f..20a3c5ee9 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -100,6 +100,7 @@ struct { int no_policy_check; /* ignore certificate policies */ int no_chain_validation; /* Bypass all cert chain validity tests */ int ignore_expiration; /* Ignore the notAfter validity checks. */ + char *fixed_passphrase; /* Passphrase used by regression tests. */ int auto_issuer_key_retrieve; /* try to retrieve a missing issuer key. */ } opt; diff --git a/sm/import.c b/sm/import.c index c5581eb64..5d3484d92 100644 --- a/sm/import.c +++ b/sm/import.c @@ -172,13 +172,19 @@ check_and_store (CTRL ctrl, struct stats_s *stats, ksba_cert_t cert, int depth) /* Some basic checks, but don't care about missing certificates; this is so that we are able to import entire certificate chains - w/o requirening a special order (i.e. root-CA first). This used + w/o requiring a special order (i.e. root-CA first). This used to be different but because gpgsm_verify even imports certificates without any checks, it doesn't matter much and the code gets much cleaner. A housekeeping function to remove - certificates w/o an anchor would be nice, though. */ + certificates w/o an anchor would be nice, though. + + Optionally we do a full validation in addition to the basic test. + */ rc = gpgsm_basic_cert_check (cert); - if (!rc || gpg_err_code (rc) == GPG_ERR_MISSING_CERT) + if (!rc && ctrl->with_validation) + rc = gpgsm_validate_chain (ctrl, cert, NULL, 0, NULL, 0); + if (!rc || (!ctrl->with-validation + && gpg_err_code (rc) == GPG_ERR_MISSING_CERT) ) { int existed; @@ -527,14 +533,25 @@ popen_protect_tool (const char *pgmname, setup_pinentry_env (); - execlp (pgmname, arg0, - "--homedir", opt.homedir, - "--p12-import", - "--store", - "--no-fail-on-exist", - "--enable-status-msg", - "--", - NULL); + if (opt.fixed_passphrase) + execlp (pgmname, arg0, + "--homedir", opt.homedir, + "--p12-import", + "--store", + "--no-fail-on-exist", + "--enable-status-msg", + "--passphrase", opt.fixed_passphrase, + "--", + NULL); + else + execlp (pgmname, arg0, + "--homedir", opt.homedir, + "--p12-import", + "--store", + "--no-fail-on-exist", + "--enable-status-msg", + "--", + NULL); /* No way to print anything, as we have closed all streams. */ _exit (31); } |