aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2002-08-09 18:12:22 +0000
committerWerner Koch <[email protected]>2002-08-09 18:12:22 +0000
commit850a4d5214f8179710ab0c9ea7b67973b175e7b2 (patch)
tree10f8aa8340cebda8ac8476475e4d622ba3c3d950
parent* card.c (card_get_serial_and_stamp): Use the tokeinfo serial (diff)
downloadgnupg-850a4d5214f8179710ab0c9ea7b67973b175e7b2.tar.gz
gnupg-850a4d5214f8179710ab0c9ea7b67973b175e7b2.zip
* gpgsm.c (emergency_cleanup): New.
(main): Initialize the signal handler. * sign.c (gpgsm_sign): Reset the hash context for subsequent signers and release it at the end.
Diffstat (limited to '')
-rw-r--r--sm/ChangeLog27
-rw-r--r--sm/certcheck.c34
-rw-r--r--sm/certlist.c27
-rw-r--r--sm/gpgsm.c143
-rw-r--r--sm/gpgsm.h6
-rw-r--r--sm/server.c54
-rw-r--r--sm/sign.c245
-rw-r--r--sm/verify.c10
8 files changed, 321 insertions, 225 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 386538b45..6e9dc0acb 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,30 @@
+2002-08-09 Werner Koch <[email protected]>
+
+ * gpgsm.c (emergency_cleanup): New.
+ (main): Initialize the signal handler.
+
+ * sign.c (gpgsm_sign): Reset the hash context for subsequent
+ signers and release it at the end.
+
+2002-08-05 Werner Koch <[email protected]>
+
+ * server.c (cmd_signer): New command "SIGNER"
+ (register_commands): Register it.
+ (cmd_sign): Pass the signer list to gpgsm_sign.
+ * certlist.c (gpgsm_add_to_certlist): Add SECRET argument, check
+ for secret key if set and changed all callers.
+ * sign.c (gpgsm_sign): New argument SIGNERLIST and implemt
+ multiple signers.
+ * gpgsm.c (main): Support more than one -u.
+
+ * server.c (cmd_recipient): Return reason code 1 for No_Public_Key
+ which is actually what gets returned from add_to_certlist.
+
+2002-07-26 Werner Koch <[email protected]>
+
+ * certcheck.c (gpgsm_check_cert_sig): Implement proper cleanup.
+ (gpgsm_check_cms_signature): Ditto.
+
2002-07-22 Werner Koch <[email protected]>
* keydb.c (keydb_add_resource): Register a lock file.
diff --git a/sm/certcheck.c b/sm/certcheck.c
index 612a3d2d6..4700fe723 100644
--- a/sm/certcheck.c
+++ b/sm/certcheck.c
@@ -138,12 +138,16 @@ gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert)
if (!n)
{
log_error ("libksba did not return a proper S-Exp\n");
+ gcry_md_close (md);
+ ksba_free (p);
return GNUPG_Bug;
}
rc = gcry_sexp_sscan ( &s_sig, NULL, p, n);
+ ksba_free (p);
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
+ gcry_md_close (md);
return map_gcry_err (rc);
}
@@ -152,29 +156,42 @@ gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert)
if (!n)
{
log_error ("libksba did not return a proper S-Exp\n");
+ gcry_md_close (md);
+ ksba_free (p);
+ gcry_sexp_release (s_sig);
return GNUPG_Bug;
}
rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
+ ksba_free (p);
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
+ gcry_md_close (md);
+ gcry_sexp_release (s_sig);
return map_gcry_err (rc);
}
rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame);
if (rc)
{
- /* fixme: clean up some things */
+ gcry_md_close (md);
+ gcry_sexp_release (s_sig);
+ gcry_sexp_release (s_pkey);
return rc;
}
+
/* put hash into the S-Exp s_hash */
if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
BUG ();
-
+ gcry_mpi_release (frame);
rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
if (DBG_CRYPTO)
log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc));
+ gcry_md_close (md);
+ gcry_sexp_release (s_sig);
+ gcry_sexp_release (s_hash);
+ gcry_sexp_release (s_pkey);
return map_gcry_err (rc);
}
@@ -208,15 +225,19 @@ gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval,
if (!n)
{
log_error ("libksba did not return a proper S-Exp\n");
+ ksba_free (p);
+ gcry_sexp_release (s_sig);
return GNUPG_Bug;
}
if (DBG_X509)
log_printhex ("public key: ", p, n);
rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
+ ksba_free (p);
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
+ gcry_sexp_release (s_sig);
return map_gcry_err (rc);
}
@@ -224,17 +245,22 @@ gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval,
rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame);
if (rc)
{
- /* fixme: clean up some things */
+ gcry_sexp_release (s_sig);
+ gcry_sexp_release (s_pkey);
return rc;
}
/* put hash into the S-Exp s_hash */
if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
BUG ();
-
+ gcry_mpi_release (frame);
+
rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
if (DBG_CRYPTO)
log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc));
+ gcry_sexp_release (s_sig);
+ gcry_sexp_release (s_hash);
+ gcry_sexp_release (s_sig);
return map_gcry_err (rc);
}
diff --git a/sm/certlist.c b/sm/certlist.c
index ca61eb0d2..8a8570fdf 100644
--- a/sm/certlist.c
+++ b/sm/certlist.c
@@ -133,10 +133,12 @@ same_subject_issuer (const char *subject, const char *issuer, KsbaCert cert)
-/* add a certificate to a list of certificate and make sure that it is
- a valid certificate */
+/* Add a certificate to a list of certificate and make sure that it is
+ a valid certificate. With SECRET set to true a secret key must be
+ avaibale for the certificate. */
int
-gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr)
+gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
+ CERTLIST *listaddr)
{
int rc;
KEYDB_SEARCH_DESC desc;
@@ -161,7 +163,8 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr)
rc = keydb_get_cert (kh, &cert);
if (!rc)
{
- rc = gpgsm_cert_use_encrypt_p (cert);
+ rc = secret? gpgsm_cert_use_sign_p (cert)
+ : gpgsm_cert_use_encrypt_p (cert);
if (rc == GNUPG_Wrong_Key_Usage)
{
/* There might be another certificate with the
@@ -206,7 +209,8 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr)
if (!keydb_get_cert (kh, &cert2))
{
int tmp = (same_subject_issuer (subject, issuer, cert2)
- && (gpgsm_cert_use_encrypt_p (cert2)
+ && ((secret? gpgsm_cert_use_sign_p (cert2):
+ gpgsm_cert_use_encrypt_p (cert2))
== GNUPG_Wrong_Key_Usage));
ksba_cert_release (cert2);
if (tmp)
@@ -218,6 +222,19 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr)
xfree (subject);
xfree (issuer);
+ if (!rc && secret)
+ {
+ char *p;
+
+ rc = GNUPG_No_Secret_Key;
+ p = gpgsm_get_keygrip_hexstring (cert);
+ if (p)
+ {
+ if (!gpgsm_agent_havekey (p))
+ rc = 0;
+ xfree (p);
+ }
+ }
if (!rc)
rc = gpgsm_validate_path (ctrl, cert, NULL);
if (!rc)
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 9efeca79f..d17f1c66d 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -403,6 +403,7 @@ static char *build_list (const char *text,
static void set_cmd (enum cmd_and_opt_values *ret_cmd,
enum cmd_and_opt_values new_cmd );
+static void emergency_cleanup (void);
static int check_special_filename (const char *fname);
static int open_read (const char *filename);
static FILE *open_fwrite (const char *filename);
@@ -601,6 +602,7 @@ main ( int argc, char **argv)
enum cmd_and_opt_values cmd = 0;
struct server_control_s ctrl;
CERTLIST recplist = NULL;
+ CERTLIST signerlist = NULL;
/* trap_unaligned ();*/
set_strusage (my_strusage);
@@ -626,7 +628,7 @@ main ( int argc, char **argv)
may_coredump = disable_core_dumps ();
- /* Fixme: init_signals();*/
+ gnupg_init_signals (0, emergency_cleanup);
create_dotlock (NULL); /* register locking cleanup */
i18n_init();
@@ -922,9 +924,10 @@ main ( int argc, char **argv)
case oTextmodeShort: /*fixme:opt.textmode = 2;*/ break;
case oTextmode: /*fixme:opt.textmode=1;*/ break;
- case oUser: /* store the local users */
- opt.local_user = pargs.r.ret_str;
- add_to_strlist ( &locusr, pargs.r.ret_str);
+ case oUser: /* store the local users, the first one is the default */
+ if (!opt.local_user)
+ opt.local_user = pargs.r.ret_str;
+ add_to_strlist (&locusr, pargs.r.ret_str);
break;
case oNoSecmemWarn:
@@ -1059,15 +1062,39 @@ main ( int argc, char **argv)
keydb_add_resource (sl->d, 0, 0);
FREE_STRLIST(nrings);
+
+ for (sl = locusr; sl; sl = sl->next)
+ {
+ int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist);
+ if (rc)
+ {
+ log_error (_("can't sign using `%s': %s\n"),
+ sl->d, gnupg_strerror (rc));
+ gpgsm_status2 (&ctrl, STATUS_INV_RECP,
+ rc == -1? "1":
+ rc == GNUPG_No_Public_Key? "1":
+ rc == GNUPG_Ambiguous_Name? "2":
+ rc == GNUPG_Wrong_Key_Usage? "3":
+ rc == GNUPG_Certificate_Revoked? "4":
+ rc == GNUPG_Certificate_Expired? "5":
+ rc == GNUPG_No_CRL_Known? "6":
+ rc == GNUPG_CRL_Too_Old? "7":
+ rc == GNUPG_No_Policy_Match? "8":
+ rc == GNUPG_No_Secret_Key? "9":
+ "0",
+ sl->d, NULL);
+ }
+ }
for (sl = remusr; sl; sl = sl->next)
{
- int rc = gpgsm_add_to_certlist (&ctrl, sl->d, &recplist);
+ int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 0, &recplist);
if (rc)
{
log_error (_("can't encrypt to `%s': %s\n"),
sl->d, gnupg_strerror (rc));
gpgsm_status2 (&ctrl, STATUS_INV_RECP,
rc == -1? "1":
+ rc == GNUPG_No_Public_Key? "1":
rc == GNUPG_Ambiguous_Name? "2":
rc == GNUPG_Wrong_Key_Usage? "3":
rc == GNUPG_Certificate_Revoked? "4":
@@ -1109,69 +1136,25 @@ main ( int argc, char **argv)
break;
case aSign: /* sign the given file */
- /* FIXME: W we don't handle --output yet. We should also allow
+ /* FIXME: We don't handle --output yet. We should also allow
to concatenate multiple files for signing because that is
what gpg does.*/
if (!argc)
- gpgsm_sign (&ctrl, 0, detached_sig, stdout); /* create from stdin */
+ gpgsm_sign (&ctrl, signerlist,
+ 0, detached_sig, stdout); /* create from stdin */
else if (argc == 1)
- gpgsm_sign (&ctrl, open_read (*argv),
- detached_sig, stdout); /* from file */
+ gpgsm_sign (&ctrl, signerlist,
+ open_read (*argv), detached_sig, stdout); /* from file */
else
wrong_args (_("--sign [datafile]"));
break;
-#if 0
- sl = NULL;
- if (detached_sig)
- { /* sign all files */
- for (; argc; argc--, argv++ )
- add_to_strlist ( &sl, *argv );
- }
- else
- {
- if (argc > 1 )
- wrong_args (_("--sign [filename]"));
- if (argc)
- {
- sl = xcalloc (1, sizeof *sl + strlen(fname));
- strcpy(sl->d, fname);
- }
- }
- if ( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) )
- log_error ("signing failed: %s\n", gpg_errstr(rc) );
- free_strlist(sl);
-#endif
- break;
case aSignEncr: /* sign and encrypt the given file */
log_error ("this command has not yet been implemented\n");
-#if 0
- if (argc > 1)
- wrong_args(_("--sign --encrypt [filename]"));
- if (argc)
- {
- sl = xcalloc( 1, sizeof *sl + strlen(fname));
- strcpy(sl->d, fname);
- }
- else
- sl = NULL;
-
- if ( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
- log_error ("%s: sign+encrypt failed: %s\n",
- print_fname_stdin(fname), gpg_errstr(rc) );
- free_strlist(sl);
-#endif
break;
case aClearsign: /* make a clearsig */
log_error ("this command has not yet been implemented\n");
-#if 0
- if (argc > 1)
- wrong_args (_("--clearsign [filename]"));
- if ( (rc = clearsign_file(fname, locusr, NULL)) )
- log_error ("%s: clearsign failed: %s\n",
- print_fname_stdin(fname), gpg_errstr(rc) );
-#endif
break;
case aVerify:
@@ -1199,8 +1182,6 @@ main ( int argc, char **argv)
case aVerifyFiles:
log_error ("this command has not yet been implemented\n");
-/* if ((rc = verify_files( argc, argv ))) */
-/* log_error ("verify files failed: %s\n", gpg_errstr(rc) ); */
break;
case aDecrypt:
@@ -1244,18 +1225,6 @@ main ( int argc, char **argv)
case aKeygen: /* generate a key */
log_error ("this function is not yet available from the commandline\n");
-/* if (opt.batch) */
-/* { */
-/* if (argc > 1) */
-/* wrong_args("--gen-key [parameterfile]"); */
-/* generate_keypair (argc? *argv : NULL); */
-/* } */
-/* else */
-/* { */
-/* if (argc) */
-/* wrong_args ("--gen-key"); */
-/* generate_keypair(NULL); */
-/* } */
break;
case aImport:
@@ -1279,16 +1248,6 @@ main ( int argc, char **argv)
case aSendKeys:
case aRecvKeys:
log_error ("this command has not yet been implemented\n");
-/* sl = NULL; */
-/* for ( ; argc; argc--, argv++ ) */
-/* add_to_strlist (&sl, *argv); */
-/* if ( cmd == aSendKeys ) */
-/* ldap_export (sl); */
-/* else if (cmd == aRecvKeys ) */
-/* ldap_import (sl); */
-/* else */
-/* export_pubkeys (sl, (cmd == aExport)); */
-/* free_strlist (sl); */
break;
@@ -1305,34 +1264,26 @@ main ( int argc, char **argv)
default:
- log_error ("invalid command\n");
-#if 0
- if (argc > 1)
- wrong_args(_("[filename]"));
- /* Issue some output for the unix newbie */
- if ( !fname && !opt.outfile && isatty( fileno(stdin) )
- && isatty (fileno(stdout) ) && isatty (fileno(stderr) ) )
- log_info (_("Go ahead and type your message ...\n"));
-
- if ( !(a = iobuf_open(fname)) )
- log_error (_("can't open `%s'\n"), print_fname_stdin(fname));
- else
- {
- if (!opt.no_armor)
- iobuf_close(a);
- }
-#endif
+ log_error ("invalid command (there is no implicit command)\n");
break;
}
/* cleanup */
gpgsm_release_certlist (recplist);
+ gpgsm_release_certlist (signerlist);
FREE_STRLIST(remusr);
FREE_STRLIST(locusr);
gpgsm_exit(0);
return 8; /*NEVER REACHED*/
}
+/* Note: This function is used by signal handlers!. */
+static void
+emergency_cleanup (void)
+{
+ gcry_control (GCRYCTL_TERM_SECMEM );
+}
+
void
gpgsm_exit (int rc)
@@ -1351,7 +1302,7 @@ gpgsm_exit (int rc)
if (opt.debug)
gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
#endif
- gcry_control (GCRYCTL_TERM_SECMEM );
+ emergency_cleanup ();
rc = rc? rc : log_get_errorcount(0)? 2 : gpgsm_errors_seen? 1 : 0;
exit (rc);
}
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 0d5294b44..3e5205980 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -197,7 +197,8 @@ int gpgsm_cert_use_encrypt_p (KsbaCert cert);
int gpgsm_cert_use_verify_p (KsbaCert cert);
int gpgsm_cert_use_decrypt_p (KsbaCert cert);
int gpgsm_cert_use_cert_p (KsbaCert cert);
-int gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr);
+int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
+ CERTLIST *listaddr);
void gpgsm_release_certlist (CERTLIST list);
int gpgsm_find_cert (const char *name, KsbaCert *r_cert);
@@ -218,7 +219,8 @@ int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp);
/*-- sign.c --*/
int gpgsm_get_default_cert (KsbaCert *r_cert);
-int gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp);
+int gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
+ int data_fd, int detached, FILE *out_fp);
/*-- encrypt.c --*/
int gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int in_fd, FILE *out_fp);
diff --git a/sm/server.c b/sm/server.c
index 0e30ae873..71b6194c7 100644
--- a/sm/server.c
+++ b/sm/server.c
@@ -43,6 +43,7 @@ struct server_local_s {
int list_internal;
int list_external;
CERTLIST recplist;
+ CERTLIST signerlist;
};
@@ -182,7 +183,9 @@ reset_notify (ASSUAN_CONTEXT ctx)
CTRL ctrl = assuan_get_pointer (ctx);
gpgsm_release_certlist (ctrl->server_local->recplist);
+ gpgsm_release_certlist (ctrl->server_local->signerlist);
ctrl->server_local->recplist = NULL;
+ ctrl->server_local->signerlist = NULL;
close_message_fd (ctrl);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
@@ -239,10 +242,11 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
CTRL ctrl = assuan_get_pointer (ctx);
int rc;
- rc = gpgsm_add_to_certlist (ctrl, line, &ctrl->server_local->recplist);
+ rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist);
if (rc)
gpgsm_status2 (ctrl, STATUS_INV_RECP,
rc == -1? "1":
+ rc == GNUPG_No_Public_Key? "1":
rc == GNUPG_Ambiguous_Name? "2":
rc == GNUPG_Wrong_Key_Usage? "3":
rc == GNUPG_Certificate_Revoked? "4":
@@ -256,6 +260,47 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
return map_to_assuan_status (rc);
}
+/* SIGNER <userID>
+
+ Set the signer's keys for the signature creation. <userID> should
+ be the internal representation of the key; the server may accept any
+ other way of specification [we will support this]. If this is a
+ valid and usable signing key the server does respond with OK,
+ otherwise it returns an ERR with the reason why the key can't be
+ used, the signing will then not be done for this key. If the policy
+ is not to sign at all if not all signer keys are valid, the client
+ has to take care of this. All SIGNER commands are cumulative until
+ a RESET but they are *not* reset by an SIGN command becuase it can
+ be expected that set of signers are used for more than one sign
+ operation.
+
+ Note that this command returns an INV_RECP status which is a bit
+ strange, but they are very similar. */
+static int
+cmd_signer (ASSUAN_CONTEXT ctx, char *line)
+{
+ CTRL ctrl = assuan_get_pointer (ctx);
+ int rc;
+
+ rc = gpgsm_add_to_certlist (ctrl, line, 1, &ctrl->server_local->signerlist);
+ if (rc)
+ gpgsm_status2 (ctrl, STATUS_INV_RECP,
+ rc == -1? "1":
+ rc == GNUPG_No_Public_Key? "1":
+ rc == GNUPG_Ambiguous_Name? "2":
+ rc == GNUPG_Wrong_Key_Usage? "3":
+ rc == GNUPG_Certificate_Revoked? "4":
+ rc == GNUPG_Certificate_Expired? "5":
+ rc == GNUPG_No_CRL_Known? "6":
+ rc == GNUPG_CRL_Too_Old? "7":
+ rc == GNUPG_No_Policy_Match? "8":
+ rc == GNUPG_No_Secret_Key? "9":
+ "0",
+ line, NULL);
+
+ return map_to_assuan_status (rc);
+}
+
/* ENCRYPT
@@ -407,7 +452,9 @@ cmd_sign (ASSUAN_CONTEXT ctx, char *line)
out_fp = fdopen ( dup(out_fd), "w");
if (!out_fp)
return set_error (General_Error, "fdopen() failed");
- rc = gpgsm_sign (assuan_get_pointer (ctx), inp_fd, detached, out_fp);
+
+ rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
+ inp_fd, detached, out_fp);
fclose (out_fp);
/* close and reset the fd */
@@ -676,6 +723,7 @@ register_commands (ASSUAN_CONTEXT ctx)
int (*handler)(ASSUAN_CONTEXT, char *line);
} table[] = {
{ "RECIPIENT", 0, cmd_recipient },
+ { "SIGNER", 0, cmd_signer },
{ "ENCRYPT", 0, cmd_encrypt },
{ "DECRYPT", 0, cmd_decrypt },
{ "VERIFY", 0, cmd_verify },
@@ -776,6 +824,8 @@ gpgsm_server (void)
gpgsm_release_certlist (ctrl.server_local->recplist);
ctrl.server_local->recplist = NULL;
+ gpgsm_release_certlist (ctrl.server_local->signerlist);
+ ctrl.server_local->signerlist = NULL;
assuan_deinit_server (ctx);
}
diff --git a/sm/sign.c b/sm/sign.c
index 4cce9f926..061dfeebc 100644
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -1,5 +1,5 @@
/* sign.c - Sign a message
- * Copyright (C) 2001 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -228,8 +228,6 @@ get_default_signer (void)
return cert;
}
-
-
/* Depending on the options in CTRL add the certificate CERT as well as
other certificate up in the chain to the Root-CA to the CMS
object. */
@@ -290,10 +288,11 @@ add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert)
Sign the data received on DATA-FD in embedded mode or in detached
mode when DETACHED is true. Write the signature to OUT_FP. The
- key used to sign is the default one - we will extend the function
- to take a list of fingerprints in the future. */
+ keys used to sign are taken from SIGNERLIST or the default one will
+ be used if the value of this argument is NULL. */
int
-gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
+gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
+ int data_fd, int detached, FILE *out_fp)
{
int i, rc;
KsbaError err;
@@ -301,13 +300,14 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
KsbaWriter writer;
KsbaCMS cms = NULL;
KsbaStopReason stopreason;
- KsbaCert cert = NULL;
KEYDB_HANDLE kh = NULL;
GCRY_MD_HD data_md = NULL;
int signer;
const char *algoid;
int algo;
time_t signed_at;
+ CERTLIST cl;
+ int release_signerlist = 0;
kh = keydb_new (0);
if (!kh)
@@ -353,47 +353,60 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
goto leave;
}
-
- /* gather certificates of signers and store in theCMS object */
- /* fixme: process a list of fingerprints and store the certificate of
- each given fingerprint */
- cert = get_default_signer ();
- if (!cert)
+ /* If no list of signers is given, use a default one. */
+ if (!signerlist)
{
- log_error ("no default signer found\n");
- rc = seterr (General_Error);
- goto leave;
+ KsbaCert cert = get_default_signer ();
+ if (!cert)
+ {
+ log_error ("no default signer found\n");
+ rc = seterr (General_Error);
+ goto leave;
+ }
+ signerlist = xtrycalloc (1, sizeof *signerlist);
+ if (!signerlist)
+ {
+ rc = GNUPG_Out_Of_Core;
+ ksba_cert_release (cert);
+ goto leave;
+ }
+ signerlist->cert = cert;
+ release_signerlist = 1;
}
- rc = gpgsm_cert_use_sign_p (cert);
- if (rc)
- goto leave;
- err = ksba_cms_add_signer (cms, cert);
- if (err)
- {
- log_error ("ksba_cms_add_signer failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
- rc = add_certificate_list (ctrl, cms, cert);
- if (rc)
- {
- log_error ("failed to store list of certificates: %s\n",
- gnupg_strerror(rc));
- goto leave;
- }
- ksba_cert_release (cert); cert = NULL;
-
- /* Set the hash algorithm we are going to use */
- err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/);
- if (err)
+ /* Gather certificates of signers and store them in the CMS object. */
+ for (cl=signerlist; cl; cl = cl->next)
{
- log_debug ("ksba_cms_add_digest_algo failed: %s\n", ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
+ rc = gpgsm_cert_use_sign_p (cl->cert);
+ if (rc)
+ goto leave;
+
+ err = ksba_cms_add_signer (cms, cl->cert);
+ if (err)
+ {
+ log_error ("ksba_cms_add_signer failed: %s\n", ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
+ rc = add_certificate_list (ctrl, cms, cl->cert);
+ if (rc)
+ {
+ log_error ("failed to store list of certificates: %s\n",
+ gnupg_strerror(rc));
+ goto leave;
+ }
+ /* Set the hash algorithm we are going to use */
+ err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/);
+ if (err)
+ {
+ log_debug ("ksba_cms_add_digest_algo failed: %s\n",
+ ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
}
-
+
/* Prepare hashing (actually we are figuring out what we have set above)*/
data_md = gcry_md_open (0, 0);
if (!data_md)
@@ -417,7 +430,6 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
gcry_md_enable (data_md, algo);
}
- signer = 0;
if (detached)
{ /* we hash the data right now so that we can store the message
digest. ksba_cms_build() takes this as an flag that detached
@@ -437,24 +449,30 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
rc = GNUPG_Bug;
goto leave;
}
- err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
- if (err)
+ for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{
- log_error ("ksba_cms_set_message_digest failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
+ err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
+ if (err)
+ {
+ log_error ("ksba_cms_set_message_digest failed: %s\n",
+ ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
}
}
signed_at = gnupg_get_time ();
- err = ksba_cms_set_signing_time (cms, signer, signed_at);
- if (err)
+ for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{
- log_error ("ksba_cms_set_signing_time failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
+ err = ksba_cms_set_signing_time (cms, signer, signed_at);
+ if (err)
+ {
+ log_error ("ksba_cms_set_signing_time failed: %s\n",
+ ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
}
do
@@ -473,10 +491,10 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
size_t digest_len;
assert (!detached);
- /* Fixme do this for all signers and get the algo to use from
- the signer's certificate - does not make mich sense, bu we
- should do this consistent as we have already done it above.
- Code is mostly duplicated above. */
+ /* Fixme: get the algo to use from the signer's certificate
+ - does not make much sense, but we should do this
+ consistent as we have already done it above. Code is
+ mostly duplicated above. */
algo = GCRY_MD_SHA1;
rc = hash_and_copy_data (data_fd, data_md, writer);
@@ -490,13 +508,17 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
rc = GNUPG_Bug;
goto leave;
}
- err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
- if (err)
+ for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{
- log_error ("ksba_cms_set_message_digest failed: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
+ err = ksba_cms_set_message_digest (cms, signer,
+ digest, digest_len);
+ if (err)
+ {
+ log_error ("ksba_cms_set_message_digest failed: %s\n",
+ ksba_strerror (err));
+ rc = map_ksba_err (err);
+ goto leave;
+ }
}
}
else if (stopreason == KSBA_SR_NEED_SIG)
@@ -504,7 +526,6 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
GCRY_MD_HD md;
algo = GCRY_MD_SHA1;
- signer = 0;
md = gcry_md_open (algo, 0);
if (DBG_HASHING)
gcry_md_start_debug (md, "sign.attr");
@@ -515,70 +536,67 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
goto leave;
}
ksba_cms_set_hash_function (cms, HASH_FNC, md);
- rc = ksba_cms_hash_signed_attrs (cms, signer);
- if (rc)
- {
- log_debug ("hashing signed attrs failed: %s\n",
- ksba_strerror (rc));
- gcry_md_close (md);
- goto leave;
- }
-
- { /* This is all an temporary hack */
- char *sigval;
-
- ksba_cert_release (cert);
- cert = get_default_signer ();
- if (!cert)
- {
- log_error ("oops - failed to get cert again\n");
- rc = seterr (General_Error);
- goto leave;
- }
-
- sigval = NULL;
- rc = gpgsm_create_cms_signature (cert, md, algo, &sigval);
- if (rc)
- goto leave;
-
- err = ksba_cms_set_sig_val (cms, signer, sigval);
- xfree (sigval);
- if (err)
- {
- log_error ("failed to store the signature: %s\n",
- ksba_strerror (err));
- rc = map_ksba_err (err);
- goto leave;
- }
-
- /* And write a status message */
+ for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{
+ char *sigval = NULL;
char *buf, *fpr;
-
- fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
+
+ if (signer)
+ gcry_md_reset (md);
+ rc = ksba_cms_hash_signed_attrs (cms, signer);
+ if (rc)
+ {
+ log_debug ("hashing signed attrs failed: %s\n",
+ ksba_strerror (rc));
+ gcry_md_close (md);
+ goto leave;
+ }
+
+ rc = gpgsm_create_cms_signature (cl->cert, md, algo, &sigval);
+ if (rc)
+ {
+ gcry_md_close (md);
+ goto leave;
+ }
+
+ err = ksba_cms_set_sig_val (cms, signer, sigval);
+ xfree (sigval);
+ if (err)
+ {
+ log_error ("failed to store the signature: %s\n",
+ ksba_strerror (err));
+ rc = map_ksba_err (err);
+ gcry_md_close (md);
+ goto leave;
+ }
+
+ /* write a status message */
+ fpr = gpgsm_get_fingerprint_hexstring (cl->cert, GCRY_MD_SHA1);
if (!fpr)
{
rc = seterr (Out_Of_Core);
+ gcry_md_close (md);
goto leave;
}
rc = asprintf (&buf, "%c %d %d 00 %lu %s",
- detached? 'D':'S',
- GCRY_PK_RSA, /* FIXME: get pk algo from cert */
- algo,
- (ulong)signed_at,
- fpr);
+ detached? 'D':'S',
+ GCRY_PK_RSA, /* FIXME: get pk algo from cert */
+ algo,
+ (ulong)signed_at,
+ fpr);
xfree (fpr);
if (rc < 0)
{
rc = seterr (Out_Of_Core);
+ gcry_md_close (md);
goto leave;
}
rc = 0;
- gpgsm_status (ctrl, STATUS_SIG_CREATED, buf );
+ gpgsm_status (ctrl, STATUS_SIG_CREATED, buf);
free (buf); /* yes, we must use the regular free() here */
}
+ gcry_md_close (md);
- }
}
}
while (stopreason != KSBA_SR_READY);
@@ -594,7 +612,8 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
leave:
- ksba_cert_release (cert);
+ if (release_signerlist)
+ gpgsm_release_certlist (signerlist);
ksba_cms_release (cms);
gpgsm_destroy_writer (b64writer);
keydb_release (kh);
diff --git a/sm/verify.c b/sm/verify.c
index f4af56885..3e44897e8 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -1,5 +1,5 @@
/* verify.c - Verify a messages signature
- * Copyright (C) 2001 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -248,7 +248,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
cert = NULL;
err = 0;
- for (signer=0; signer < 1; signer++)
+ for (signer=0; ; signer++)
{
char *issuer = NULL;
KsbaSexp sigval = NULL;
@@ -265,7 +265,11 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
break;
}
if (err)
- break;
+ {
+ if (signer && err == -1)
+ err = 0;
+ break;
+ }
if (DBG_X509)
{
log_debug ("signer %d - issuer: `%s'\n",