aboutsummaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
Diffstat (limited to 'sm')
-rw-r--r--sm/ChangeLog15
-rw-r--r--sm/certchain.c16
-rw-r--r--sm/certcheck.c138
-rw-r--r--sm/gpgsm.c8
-rw-r--r--sm/gpgsm.h1
-rw-r--r--sm/import.c39
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);
}