diff options
author | Werner Koch <[email protected]> | 2002-01-25 16:41:13 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2002-01-25 16:41:13 +0000 |
commit | 151deac0dfcc712a00844943445cbde7c6b0eb38 (patch) | |
tree | fa0b13b368613ba2ec69d7261377d4e4f54d84a9 | |
parent | * assuan-socket-connect.c (LOGERRORX): and removed typo. (diff) | |
download | gnupg-151deac0dfcc712a00844943445cbde7c6b0eb38.tar.gz gnupg-151deac0dfcc712a00844943445cbde7c6b0eb38.zip |
* gpgsm.c (main): Disable core dumps.
* sign.c (add_certificate_list): New.
(gpgsm_sign): Add the certificates to the CMS object.
* certpath.c (gpgsm_walk_cert_chain): New.
* gpgsm.h (server_control_s): Add included_certs.
* gpgsm.c: Add option --include-certs.
(gpgsm_init_default_ctrl): New.
(main): Call it.
* server.c (gpgsm_server): Ditto.
(option_handler): Support --include-certs.
-rw-r--r-- | sm/ChangeLog | 14 | ||||
-rw-r--r-- | sm/certchain.c | 61 | ||||
-rw-r--r-- | sm/certpath.c | 61 | ||||
-rw-r--r-- | sm/gpgsm.c | 28 | ||||
-rw-r--r-- | sm/gpgsm.h | 11 | ||||
-rw-r--r-- | sm/server.c | 14 | ||||
-rw-r--r-- | sm/sign.c | 56 |
7 files changed, 235 insertions, 10 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog index a893fdff9..561e3a573 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,3 +1,17 @@ +2002-01-25 Werner Koch <[email protected]> + + * gpgsm.c (main): Disable core dumps. + + * sign.c (add_certificate_list): New. + (gpgsm_sign): Add the certificates to the CMS object. + * certpath.c (gpgsm_walk_cert_chain): New. + * gpgsm.h (server_control_s): Add included_certs. + * gpgsm.c: Add option --include-certs. + (gpgsm_init_default_ctrl): New. + (main): Call it. + * server.c (gpgsm_server): Ditto. + (option_handler): Support --include-certs. + 2002-01-23 Werner Koch <[email protected]> * certpath.c (gpgsm_validate_path): Print the DN of a missing issuer. diff --git a/sm/certchain.c b/sm/certchain.c index 9ef862643..842481bfc 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -84,7 +84,68 @@ allowed_ca (KsbaCert cert, int *pathlen) return 0; } +/* Return the next certificate up in the chain starting at START. + Returns -1 when there are no more certificates. */ +int +gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next) +{ + int rc = 0; + char *issuer = NULL; + char *subject = NULL; + KEYDB_HANDLE kh = keydb_new (0); + + *r_next = NULL; + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = GNUPG_General_Error; + goto leave; + } + + issuer = ksba_cert_get_issuer (start, 0); + subject = ksba_cert_get_subject (start, 0); + if (!issuer) + { + log_error ("no issuer found in certificate\n"); + rc = GNUPG_Bad_Certificate; + goto leave; + } + if (!subject) + { + log_error ("no subject found in certificate\n"); + rc = GNUPG_Bad_Certificate; + goto leave; + } + + if (!strcmp (issuer, subject)) + { + rc = -1; /* we are at the root */ + goto leave; + } + + rc = keydb_search_subject (kh, issuer); + if (rc) + { + log_error ("failed to find issuer's certificate: rc=%d\n", rc); + rc = GNUPG_Missing_Certificate; + goto leave; + } + + rc = keydb_get_cert (kh, r_next); + if (rc) + { + log_error ("failed to get cert: rc=%d\n", rc); + rc = GNUPG_General_Error; + } + + leave: + xfree (issuer); + xfree (subject); + keydb_release (kh); + return rc; +} + int gpgsm_validate_path (KsbaCert cert) { diff --git a/sm/certpath.c b/sm/certpath.c index 9ef862643..842481bfc 100644 --- a/sm/certpath.c +++ b/sm/certpath.c @@ -84,7 +84,68 @@ allowed_ca (KsbaCert cert, int *pathlen) return 0; } +/* Return the next certificate up in the chain starting at START. + Returns -1 when there are no more certificates. */ +int +gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next) +{ + int rc = 0; + char *issuer = NULL; + char *subject = NULL; + KEYDB_HANDLE kh = keydb_new (0); + + *r_next = NULL; + if (!kh) + { + log_error (_("failed to allocated keyDB handle\n")); + rc = GNUPG_General_Error; + goto leave; + } + + issuer = ksba_cert_get_issuer (start, 0); + subject = ksba_cert_get_subject (start, 0); + if (!issuer) + { + log_error ("no issuer found in certificate\n"); + rc = GNUPG_Bad_Certificate; + goto leave; + } + if (!subject) + { + log_error ("no subject found in certificate\n"); + rc = GNUPG_Bad_Certificate; + goto leave; + } + + if (!strcmp (issuer, subject)) + { + rc = -1; /* we are at the root */ + goto leave; + } + + rc = keydb_search_subject (kh, issuer); + if (rc) + { + log_error ("failed to find issuer's certificate: rc=%d\n", rc); + rc = GNUPG_Missing_Certificate; + goto leave; + } + + rc = keydb_get_cert (kh, r_next); + if (rc) + { + log_error ("failed to get cert: rc=%d\n", rc); + rc = GNUPG_General_Error; + } + + leave: + xfree (issuer); + xfree (subject); + keydb_release (kh); + return rc; +} + int gpgsm_validate_path (KsbaCert cert) { diff --git a/sm/gpgsm.c b/sm/gpgsm.c index d9b9e27b9..0203c5a2a 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -33,6 +33,7 @@ #include "../kbx/keybox.h" /* malloc hooks */ #include "i18n.h" #include "keydb.h" +#include "sysutils.h" enum cmd_and_opt_values { aNull = 0, @@ -98,6 +99,14 @@ enum cmd_and_opt_values { oDisableCRLChecks, oEnableCRLChecks, + oIncludeCerts, + + + + + + + oTextmode, oFingerprint, oWithFingerprint, @@ -229,6 +238,9 @@ static ARGPARSE_OPTS opts[] = { { oDisableCRLChecks, "disable-crl-checks", 0, N_("never consult a CRL")}, { oEnableCRLChecks, "enable-crl-checks", 0, "@"}, + { oIncludeCerts, "include-certs", 1, + N_("|N|number of certificates to include") }, + #if 0 { oDefRecipient, "default-recipient" ,2, @@ -577,7 +589,7 @@ main ( int argc, char **argv) gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); - may_coredump = 0/* FIXME: disable_core_dumps()*/; + may_coredump = disable_core_dumps (); /* FIXME: init_signals();*/ @@ -631,8 +643,9 @@ main ( int argc, char **argv) assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free); - /* Setup a default control structure */ + /* Setup a default control structure for command line mode */ memset (&ctrl, 0, sizeof ctrl); + gpgsm_init_default_ctrl (&ctrl); ctrl.no_server = 1; ctrl.status_fd = -1; /* not status output */ ctrl.autodetect_encoding = 1; @@ -741,7 +754,8 @@ main ( int argc, char **argv) case oEnableCRLChecks: opt.no_crl_check = 0; break; - + + case oIncludeCerts: ctrl.include_certs = pargs.r.ret_int; break; case oOutput: opt.outfile = pargs.r.ret_str; break; @@ -1198,6 +1212,14 @@ gpgsm_exit (int rc) } +void +gpgsm_init_default_ctrl (struct server_control_s *ctrl) +{ + ctrl->include_certs = 1; +} + + + /* Check whether the filename has the form "-&nnnn", where n is a non-zero number. Returns this number or -1 if it is not the case. */ static int diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 4d7e55880..f8f5ed8b6 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -89,6 +89,8 @@ struct { struct server_local_s; +/* Note that the default values for this are set by + gpgsm_init_default_ctrl() */ struct server_control_s { int no_server; /* we are not running under server control */ int status_fd; /* only for non-server mode */ @@ -102,6 +104,11 @@ struct server_control_s { int create_base64; /* Create base64 encoded output */ int create_pem; /* create PEM output */ const char *pem_name; /* PEM name to use */ + + int include_certs; /* -1 to send all certificates in the chain + along with a signature or the number of + certificates up the chain (0 = none, 1 = only + signer) */ }; typedef struct server_control_s *CTRL; @@ -118,6 +125,7 @@ typedef struct certlist_s *CERTLIST; /*-- gpgsm.c --*/ void gpgsm_exit (int rc); +void gpgsm_init_default_ctrl (struct server_control_s *ctrl); /*-- server.c --*/ void gpgsm_server (void); @@ -158,10 +166,11 @@ int gpgsm_create_cms_signature (KsbaCert cert, GCRY_MD_HD md, int mdalgo, /*-- certpath.c --*/ +int gpgsm_walk_cert_chain (KsbaCert start, KsbaCert *r_next); int gpgsm_validate_path (KsbaCert cert); int gpgsm_basic_cert_check (KsbaCert cert); -/*-- cetlist.c --*/ +/*-- cetrlist.c --*/ int gpgsm_add_to_certlist (const char *name, CERTLIST *listaddr); void gpgsm_release_certlist (CERTLIST list); int gpgsm_find_cert (const char *name, KsbaCert *r_cert); diff --git a/sm/server.c b/sm/server.c index e05f5da0b..616ae9bfe 100644 --- a/sm/server.c +++ b/sm/server.c @@ -57,7 +57,18 @@ close_message_fd (CTRL ctrl) static int option_handler (ASSUAN_CONTEXT ctx, const char *key, const char *value) { - log_debug ("got option key=`%s' value=`%s'\n", key, value); + CTRL ctrl = assuan_get_pointer (ctx); + + if (!strcmp (key, "include-certs")) + { + int i = *value? atoi (value) : -1; + if (ctrl->include_certs < -1) + return ASSUAN_Parameter_Error; + ctrl->include_certs = i; + } + else + return ASSUAN_Invalid_Option; + return 0; } @@ -458,6 +469,7 @@ gpgsm_server (void) struct server_control_s ctrl; memset (&ctrl, 0, sizeof ctrl); + gpgsm_init_default_ctrl (&ctrl); /* For now we use a simple pipe based server so that we can work from scripts. We will later add options to run as a daemon and @@ -103,6 +103,49 @@ get_default_signer (void) } +/* Depending on the options in CTRL add the certifcate CERT as well as + other certificate up in the chain to the Root-CA to the CMS + object. */ +static int +add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert) +{ + KsbaError err; + int rc = 0; + KsbaCert next = NULL; + int n; + + ksba_cert_ref (cert); + + n = ctrl->include_certs; + if (n < 0 || n > 50) + n = 50; /* We better apply an upper bound */ + + if (n) + { + err = ksba_cms_add_cert (cms, cert); + if (err) + goto ksba_failure; + } + while ( n-- && !(rc = gpgsm_walk_cert_chain (cert, &next)) ) + { + err = ksba_cms_add_cert (cms, next); + ksba_cert_release (cert); + cert = next; next = NULL; + if (err) + goto ksba_failure; + } + ksba_cert_release (cert); + + return rc == -1? 0: rc; + + ksba_failure: + ksba_cert_release (cert); + log_error ("ksba_cms_add_cert failed: %s\n", ksba_strerror (err)); + return map_ksba_err (err); +} + + + /* Perform a sign operation. @@ -192,16 +235,19 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp) err = ksba_cms_add_signer (cms, cert); if (err) { - log_debug ("ksba_cms_add_signer failed: %s\n", ksba_strerror (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; - /* fixme: We might want to include a list of certificate which are - put as info into the signed data object - maybe we should add a - flag to ksba_cms_add_signer to decider whether this cert should - be send along with the signature */ /* Set the hash algorithm we are going to use */ err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/); |