aboutsummaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
Diffstat (limited to 'sm')
-rw-r--r--sm/call-agent.c37
-rw-r--r--sm/certlist.c60
-rw-r--r--sm/certreqgen-ui.c26
-rw-r--r--sm/decrypt.c14
-rw-r--r--sm/delete.c5
-rw-r--r--sm/gpgsm.c31
-rw-r--r--sm/gpgsm.h21
-rw-r--r--sm/keydb.c328
-rw-r--r--sm/keydb.h6
-rw-r--r--sm/keylist.c2
-rw-r--r--sm/server.c4
-rw-r--r--sm/sign.c124
12 files changed, 517 insertions, 141 deletions
diff --git a/sm/call-agent.c b/sm/call-agent.c
index 4f2b83f56..b37c2e53d 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -409,19 +409,19 @@ gpgsm_scd_pksign (ctrl_t ctrl, const char *keyid, const char *desc,
{
case GCRY_PK_RSA:
rc = gcry_sexp_build (&sig, NULL, "(sig-val(rsa(s%b)))",
- sigbuflen, sigbuf);
+ (int)sigbuflen, sigbuf);
break;
case GCRY_PK_ECC:
rc = gcry_sexp_build (&sig, NULL, "(sig-val(ecdsa(r%b)(s%b)))",
- sigbuflen/2, sigbuf,
- sigbuflen/2, sigbuf + sigbuflen/2);
+ (int)sigbuflen/2, sigbuf,
+ (int)sigbuflen/2, sigbuf + sigbuflen/2);
break;
case GCRY_PK_EDDSA:
rc = gcry_sexp_build (&sig, NULL, "(sig-val(eddsa(r%b)(s%b)))",
- sigbuflen/2, sigbuf,
- sigbuflen/2, sigbuf + sigbuflen/2);
+ (int)sigbuflen/2, sigbuf,
+ (int)sigbuflen/2, sigbuf + sigbuflen/2);
break;
default:
@@ -785,9 +785,9 @@ scd_keypairinfo_status_cb (void *opaque, const char *line)
{
sl = append_to_strlist (listaddr, line);
p = sl->d;
- /* Make sure that we only have two tokes so that future
- extensions of the format won't change the format expected by
- the caller. */
+ /* Make sure that we only have two tokens so that future
+ * extensions of the format won't change the format expected by
+ * the caller. */
while (*p && !spacep (p))
p++;
if (*p)
@@ -796,7 +796,22 @@ scd_keypairinfo_status_cb (void *opaque, const char *line)
p++;
while (*p && !spacep (p))
p++;
- *p = 0;
+ if (*p)
+ {
+ *p++ = 0;
+ while (spacep (p))
+ p++;
+ while (*p && !spacep (p))
+ {
+ switch (*p++)
+ {
+ case 'c': sl->flags |= GCRY_PK_USAGE_CERT; break;
+ case 's': sl->flags |= GCRY_PK_USAGE_SIGN; break;
+ case 'e': sl->flags |= GCRY_PK_USAGE_ENCR; break;
+ case 'a': sl->flags |= GCRY_PK_USAGE_AUTH; break;
+ }
+ }
+ }
}
}
@@ -806,7 +821,7 @@ scd_keypairinfo_status_cb (void *opaque, const char *line)
/* Call the agent to read the keypairinfo lines of the current card.
The list is returned as a string made up of the keygrip, a space
- and the keyid. */
+ and the keyid. The flags of the string carry the usage bits. */
int
gpgsm_agent_scd_keypairinfo (ctrl_t ctrl, strlist_t *r_list)
{
@@ -821,7 +836,7 @@ gpgsm_agent_scd_keypairinfo (ctrl_t ctrl, strlist_t *r_list)
inq_parm.ctrl = ctrl;
inq_parm.ctx = agent_ctx;
- rc = assuan_transact (agent_ctx, "SCD LEARN --force",
+ rc = assuan_transact (agent_ctx, "SCD LEARN --keypairinfo",
NULL, NULL,
default_inq_cb, &inq_parm,
scd_keypairinfo_status_cb, &list);
diff --git a/sm/certlist.c b/sm/certlist.c
index 12a492518..b3d113bfd 100644
--- a/sm/certlist.c
+++ b/sm/certlist.c
@@ -48,7 +48,7 @@ static const char oid_kp_ocspSigning[] = "1.3.6.1.5.5.7.3.9";
debugging). MODE 4 is for certificate signing, MODE for COSP
response signing. */
static int
-cert_usage_p (ksba_cert_t cert, int mode)
+cert_usage_p (ksba_cert_t cert, int mode, int silent)
{
gpg_error_t err;
unsigned int use;
@@ -118,7 +118,7 @@ cert_usage_p (ksba_cert_t cert, int mode)
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
{
err = 0;
- if (opt.verbose && mode < 2)
+ if (opt.verbose && mode < 2 && !silent)
log_info (_("no key usage specified - assuming all usages\n"));
use = ~0;
}
@@ -139,8 +139,9 @@ cert_usage_p (ksba_cert_t cert, int mode)
{
if ((use & (KSBA_KEYUSAGE_KEY_CERT_SIGN)))
return 0;
- log_info (_("certificate should not have "
- "been used for certification\n"));
+ if (!silent)
+ log_info (_("certificate should not have "
+ "been used for certification\n"));
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
}
@@ -151,8 +152,9 @@ cert_usage_p (ksba_cert_t cert, int mode)
|| (use & (KSBA_KEYUSAGE_KEY_CERT_SIGN
|KSBA_KEYUSAGE_CRL_SIGN))))
return 0;
- log_info (_("certificate should not have "
- "been used for OCSP response signing\n"));
+ if (!silent)
+ log_info (_("certificate should not have "
+ "been used for OCSP response signing\n"));
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
}
@@ -162,19 +164,22 @@ cert_usage_p (ksba_cert_t cert, int mode)
)
return 0;
- log_info (mode==3? _("certificate should not have been used for encryption\n"):
- mode==2? _("certificate should not have been used for signing\n"):
- mode==1? _("certificate is not usable for encryption\n"):
- _("certificate is not usable for signing\n"));
+ if (!silent)
+ log_info
+ (mode==3? _("certificate should not have been used for encryption\n"):
+ mode==2? _("certificate should not have been used for signing\n"):
+ mode==1? _("certificate is not usable for encryption\n"):
+ /**/ _("certificate is not usable for signing\n"));
+
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
}
/* Return 0 if the cert is usable for signing */
int
-gpgsm_cert_use_sign_p (ksba_cert_t cert)
+gpgsm_cert_use_sign_p (ksba_cert_t cert, int silent)
{
- return cert_usage_p (cert, 0);
+ return cert_usage_p (cert, 0, silent);
}
@@ -182,31 +187,31 @@ gpgsm_cert_use_sign_p (ksba_cert_t cert)
int
gpgsm_cert_use_encrypt_p (ksba_cert_t cert)
{
- return cert_usage_p (cert, 1);
+ return cert_usage_p (cert, 1, 0);
}
int
gpgsm_cert_use_verify_p (ksba_cert_t cert)
{
- return cert_usage_p (cert, 2);
+ return cert_usage_p (cert, 2, 0);
}
int
gpgsm_cert_use_decrypt_p (ksba_cert_t cert)
{
- return cert_usage_p (cert, 3);
+ return cert_usage_p (cert, 3, 0);
}
int
gpgsm_cert_use_cert_p (ksba_cert_t cert)
{
- return cert_usage_p (cert, 4);
+ return cert_usage_p (cert, 4, 0);
}
int
gpgsm_cert_use_ocsp_p (ksba_cert_t cert)
{
- return cert_usage_p (cert, 5);
+ return cert_usage_p (cert, 5, 0);
}
@@ -341,25 +346,20 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
first_subject = ksba_cert_get_subject (cert, 0);
first_issuer = ksba_cert_get_issuer (cert, 0);
}
- rc = secret? gpgsm_cert_use_sign_p (cert)
+ rc = secret? gpgsm_cert_use_sign_p (cert, 0)
: gpgsm_cert_use_encrypt_p (cert);
if (gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE)
{
/* There might be another certificate with the
correct usage, so we try again */
- if (!wrong_usage)
- { /* save the first match */
- wrong_usage = rc;
- ksba_cert_release (cert);
- cert = NULL;
- goto get_next;
- }
- else if (same_subject_issuer (first_subject, first_issuer,
- cert))
+ if (!wrong_usage
+ || same_subject_issuer (first_subject, first_issuer,cert))
{
- wrong_usage = rc;
+ if (!wrong_usage)
+ wrong_usage = rc; /* save error of the first match */
ksba_cert_release (cert);
cert = NULL;
+ log_info (_("looking for another certificate\n"));
goto get_next;
}
else
@@ -403,8 +403,8 @@ gpgsm_add_to_certlist (ctrl_t ctrl, const char *name, int secret,
first_issuer,
cert2)
&& ((gpg_err_code (
- secret? gpgsm_cert_use_sign_p (cert2)
- : gpgsm_cert_use_encrypt_p (cert2)
+ secret? gpgsm_cert_use_sign_p (cert2,0)
+ : gpgsm_cert_use_encrypt_p (cert2)
)
) == GPG_ERR_WRONG_KEY_USAGE));
if (tmp)
diff --git a/sm/certreqgen-ui.c b/sm/certreqgen-ui.c
index 70e5739e8..ae9ec35d0 100644
--- a/sm/certreqgen-ui.c
+++ b/sm/certreqgen-ui.c
@@ -249,6 +249,7 @@ gpgsm_gencertreq_tty (ctrl_t ctrl, estream_t output_stream)
gcry_sexp_t s_pkey;
char *algostr = NULL;
const char *keyref;
+ int any = 0;
keyref = strchr (sl->d, ' ');
if (keyref)
@@ -257,12 +258,33 @@ gpgsm_gencertreq_tty (ctrl_t ctrl, estream_t output_stream)
if (!gpgsm_agent_readkey (ctrl, 1, keyref, &pkey))
{
if (!gcry_sexp_new (&s_pkey, pkey, 0, 0))
- algostr = pubkey_algo_string (s_pkey);
+ algostr = pubkey_algo_string (s_pkey, NULL);
gcry_sexp_release (s_pkey);
}
xfree (pkey);
}
- tty_printf (" (%d) %s %s\n", count, sl->d, algostr);
+ tty_printf (" (%d) %s %s", count, sl->d, algostr);
+ if ((sl->flags & GCRY_PK_USAGE_CERT))
+ {
+ tty_printf ("%scert", any?",":" (");
+ any = 1;
+ }
+ if ((sl->flags & GCRY_PK_USAGE_SIGN))
+ {
+ tty_printf ("%ssign", any?",":" (");
+ any = 1;
+ }
+ if ((sl->flags & GCRY_PK_USAGE_AUTH))
+ {
+ tty_printf ("%sauth", any?",":" (");
+ any = 1;
+ }
+ if ((sl->flags & GCRY_PK_USAGE_ENCR))
+ {
+ tty_printf ("%sencr", any?",":" (");
+ any = 1;
+ }
+ tty_printf ("%s\n", any?")":"");
xfree (algostr);
}
xfree (answer);
diff --git a/sm/decrypt.c b/sm/decrypt.c
index b0ab63f00..ec9800840 100644
--- a/sm/decrypt.c
+++ b/sm/decrypt.c
@@ -397,16 +397,17 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
char *hexkeygrip = NULL;
char *desc = NULL;
char kidbuf[16+1];
+ int tmp_rc;
*kidbuf = 0;
- rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
- if (rc == -1 && recp)
+ tmp_rc = ksba_cms_get_issuer_serial (cms, recp, &issuer, &serial);
+ if (tmp_rc == -1 && recp)
break; /* no more recipients */
audit_log_i (ctrl->audit, AUDIT_NEW_RECP, recp);
- if (rc)
+ if (tmp_rc)
log_error ("recp %d - error getting info: %s\n",
- recp, gpg_strerror (rc));
+ recp, gpg_strerror (tmp_rc));
else
{
ksba_cert_t cert = NULL;
@@ -569,7 +570,7 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
audit_log_i (ctrl->audit, AUDIT_NEW_RECP, recp);
if (tmp_rc)
log_error ("recp %d - error getting info: %s\n",
- recp, gpg_strerror (rc));
+ recp, gpg_strerror (tmp_rc));
else
{
char *tmpstr = gpgsm_format_sn_issuer (serial, issuer);
@@ -583,7 +584,8 @@ gpgsm_decrypt (ctrl_t ctrl, int in_fd, estream_t out_fp)
if (!any_key)
{
- rc = gpg_error (GPG_ERR_NO_SECKEY);
+ if (!rc)
+ rc = gpg_error (GPG_ERR_NO_SECKEY);
goto leave;
}
}
diff --git a/sm/delete.c b/sm/delete.c
index f359cc595..b370406de 100644
--- a/sm/delete.c
+++ b/sm/delete.c
@@ -113,7 +113,8 @@ delete_one (ctrl_t ctrl, const char *username)
goto leave;
}
- /* We need to search again to get back to the right position. */
+ /* We need to search again to get back to the right position. Neo
+ * that the lock is kept until the KH is released. */
rc = keydb_lock (kh);
if (rc)
{
@@ -132,7 +133,7 @@ delete_one (ctrl_t ctrl, const char *username)
goto leave;
}
- rc = keydb_delete (kh, duplicates ? 0 : 1);
+ rc = keydb_delete (kh);
if (rc)
goto leave;
if (opt.verbose)
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index 2f9e5bfd2..f5837079d 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -192,6 +192,8 @@ enum cmd_and_opt_values {
oNoRandomSeedFile,
oNoCommonCertsImport,
oIgnoreCertExtension,
+ oAuthenticode,
+ oAttribute,
oNoAutostart
};
@@ -402,6 +404,8 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_n (oNoCommonCertsImport, "no-common-certs-import", "@"),
ARGPARSE_s_s (oIgnoreCertExtension, "ignore-cert-extension", "@"),
ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
+ ARGPARSE_s_n (oAuthenticode, "authenticode", "@"),
+ ARGPARSE_s_s (oAttribute, "attribute", "@"),
/* Command aliases. */
ARGPARSE_c (aListKeys, "list-key", "@"),
@@ -426,6 +430,8 @@ static struct debug_flags_s debug_flags [] =
{ DBG_MEMSTAT_VALUE, "memstat" },
{ DBG_HASHING_VALUE, "hashing" },
{ DBG_IPC_VALUE , "ipc" },
+ { DBG_CLOCK_VALUE , "clock" },
+ { DBG_LOOKUP_VALUE , "lookup" },
{ 0, NULL }
};
@@ -1283,8 +1289,12 @@ main ( int argc, char **argv)
case oDebugNoChainValidation: opt.no_chain_validation = 1; break;
case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break;
- case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
- case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
+ case oStatusFD:
+ ctrl.status_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 1);
+ break;
+ case oLoggerFD:
+ log_set_fd (translate_sys2libc_fd_int (pargs.r.ret_int, 1));
+ break;
case oWithMD5Fingerprint:
opt.with_md5_fingerprint=1; /*fall through*/
case oWithFingerprint:
@@ -1456,6 +1466,12 @@ main ( int argc, char **argv)
add_to_strlist (&opt.ignored_cert_extensions, pargs.r.ret_str);
break;
+ case oAuthenticode: opt.authenticode = 1; break;
+
+ case oAttribute:
+ add_to_strlist (&opt.attributes, pargs.r.ret_str);
+ break;
+
case oNoAutostart: opt.autostart = 0; break;
case oCompliance:
@@ -1738,6 +1754,8 @@ main ( int argc, char **argv)
if (!do_not_setup_keys)
{
+ int errcount = log_get_errorcount (0);
+
for (sl = locusr; sl ; sl = sl->next)
{
int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist, 0);
@@ -1766,6 +1784,15 @@ main ( int argc, char **argv)
if ((sl->flags & 1))
do_add_recipient (&ctrl, sl->d, &recplist, 1, recp_required);
}
+
+ /* We do not require a recipient for decryption but because
+ * recipients and signers are always checked and log_error is
+ * sometimes used (for failed signing keys or due to a failed
+ * CRL checking) that would have bumbed up the error counter.
+ * We clear the counter in the decryption case because there is
+ * no reason to force decryption to fail. */
+ if (cmd == aDecrypt && !errcount)
+ log_get_errorcount (1); /* clear counter */
}
if (log_get_errorcount(0))
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 7a5e4917d..65fff853a 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -149,6 +149,21 @@ struct
strlist_t ignored_cert_extensions;
enum gnupg_compliance_mode compliance;
+
+ /* Enable creation of authenticode signatures. */
+ int authenticode;
+
+ /* A list of extra attributes put into a signed data object. For a
+ * signed each attribute each string has the format:
+ * <oid>:s:<hex_or_filename>
+ * and for an unsigned attribute
+ * <oid>:u:<hex_or_filename>
+ * The OID is in the usual dotted decimal for. The HEX_OR_FILENAME
+ * is either a list of hex digits or a filename with the DER encoded
+ * value. A filename is detected by the presence of a slash in the
+ * HEX_OR_FILENAME. The actual value needs to be encoded as a SET OF
+ * attribute values. */
+ strlist_t attributes;
} opt;
/* Debug values and macros. */
@@ -160,6 +175,8 @@ struct
#define DBG_MEMSTAT_VALUE 128 /* show memory statistics */
#define DBG_HASHING_VALUE 512 /* debug hashing operations */
#define DBG_IPC_VALUE 1024 /* debug assuan communication */
+#define DBG_CLOCK_VALUE 4096
+#define DBG_LOOKUP_VALUE 8192 /* debug the key lookup */
#define DBG_X509 (opt.debug & DBG_X509_VALUE)
#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE)
@@ -167,6 +184,8 @@ struct
#define DBG_CACHE (opt.debug & DBG_CACHE_VALUE)
#define DBG_HASHING (opt.debug & DBG_HASHING_VALUE)
#define DBG_IPC (opt.debug & DBG_IPC_VALUE)
+#define DBG_CLOCK (opt.debug & DBG_CLOCK_VALUE)
+#define DBG_LOOKUP (opt.debug & DBG_LOOKUP_VALUE)
/* Forward declaration for an object defined in server.c */
struct server_local_s;
@@ -318,7 +337,7 @@ int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
int gpgsm_basic_cert_check (ctrl_t ctrl, ksba_cert_t cert);
/*-- certlist.c --*/
-int gpgsm_cert_use_sign_p (ksba_cert_t cert);
+int gpgsm_cert_use_sign_p (ksba_cert_t cert, int silent);
int gpgsm_cert_use_encrypt_p (ksba_cert_t cert);
int gpgsm_cert_use_verify_p (ksba_cert_t cert);
int gpgsm_cert_use_decrypt_p (ksba_cert_t cert);
diff --git a/sm/keydb.c b/sm/keydb.c
index f66a5766d..53e3cf887 100644
--- a/sm/keydb.c
+++ b/sm/keydb.c
@@ -23,7 +23,6 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -47,7 +46,6 @@ struct resource_item {
KEYBOX_HANDLE kr;
} u;
void *token;
- dotlock_t lockhandle;
};
static struct resource_item all_resources[MAX_KEYDB_RESOURCES];
@@ -58,7 +56,14 @@ static int any_registered;
struct keydb_handle {
+
+ /* If this flag is set the resources is locked. */
int locked;
+
+ /* If this flag is set a lock will only be released by
+ * keydb_release. */
+ int keep_lock;
+
int found;
int saved_found;
int current;
@@ -346,26 +351,20 @@ keydb_add_resource (ctrl_t ctrl, const char *url, int force, int *auto_created)
err = gpg_error (GPG_ERR_RESOURCE_LIMIT);
else
{
+ KEYBOX_HANDLE kbxhd;
+
all_resources[used_resources].type = rt;
all_resources[used_resources].u.kr = NULL; /* Not used here */
all_resources[used_resources].token = token;
- all_resources[used_resources].lockhandle
- = dotlock_create (filename, 0);
- if (!all_resources[used_resources].lockhandle)
- log_fatal ( _("can't create lock for '%s'\n"), filename);
-
- /* Do a compress run if needed and the file is not locked. */
- if (!dotlock_take (all_resources[used_resources].lockhandle, 0))
+ /* Do a compress run if needed and the keybox is not locked. */
+ kbxhd = keybox_new_x509 (token, 0);
+ if (kbxhd)
{
- KEYBOX_HANDLE kbxhd = keybox_new_x509 (token, 0);
-
- if (kbxhd)
- {
- keybox_compress (kbxhd);
- keybox_release (kbxhd);
- }
- dotlock_release (all_resources[used_resources].lockhandle);
+ if (!keybox_lock (kbxhd, 1, 0))
+ keybox_compress (kbxhd);
+
+ keybox_release (kbxhd);
}
used_resources++;
@@ -401,11 +400,14 @@ keydb_new (void)
KEYDB_HANDLE hd;
int i, j;
+ if (DBG_CLOCK)
+ log_clock ("%s: enter\n", __func__);
+
hd = xcalloc (1, sizeof *hd);
hd->found = -1;
hd->saved_found = -1;
- assert (used_resources <= MAX_KEYDB_RESOURCES);
+ log_assert (used_resources <= MAX_KEYDB_RESOURCES);
for (i=j=0; i < used_resources; i++)
{
switch (all_resources[i].type)
@@ -415,7 +417,6 @@ keydb_new (void)
case KEYDB_RESOURCE_TYPE_KEYBOX:
hd->active[j].type = all_resources[i].type;
hd->active[j].token = all_resources[i].token;
- hd->active[j].lockhandle = all_resources[i].lockhandle;
hd->active[j].u.kr = keybox_new_x509 (all_resources[i].token, 0);
if (!hd->active[j].u.kr)
{
@@ -429,6 +430,8 @@ keydb_new (void)
hd->used = j;
active_handles++;
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (hd=%p)\n", __func__, hd);
return hd;
}
@@ -439,9 +442,14 @@ keydb_release (KEYDB_HANDLE hd)
if (!hd)
return;
- assert (active_handles > 0);
+
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+
+ log_assert (active_handles > 0);
active_handles--;
+ hd->keep_lock = 0;
unlock_all (hd);
for (i=0; i < hd->used; i++)
{
@@ -455,7 +463,9 @@ keydb_release (KEYDB_HANDLE hd)
}
}
- xfree (hd);
+ xfree (hd);
+ if (DBG_CLOCK)
+ log_clock ("%s: leave\n", __func__);
}
@@ -526,17 +536,26 @@ keydb_set_ephemeral (KEYDB_HANDLE hd, int yes)
/* If the keyring has not yet been locked, lock it now. This
- operation is required before any update operation; it is optional
- for an insert operation. The lock is released with
- keydb_released. */
+ * operation is required before any update operation; it is optional
+ * for an insert operation. The lock is kept until a keydb_release so
+ * that internal unlock_all calls have no effect. */
gpg_error_t
keydb_lock (KEYDB_HANDLE hd)
{
+ gpg_error_t err;
+
if (!hd)
return gpg_error (GPG_ERR_INV_HANDLE);
- if (hd->locked)
- return 0; /* Already locked. */
- return lock_all (hd);
+
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+ err = lock_all (hd);
+ if (!err)
+ hd->keep_lock = 1;
+
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (err=%s)\n", __func__, gpg_strerror (err));
+ return err;
}
@@ -556,8 +575,7 @@ lock_all (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (hd->active[i].lockhandle)
- rc = dotlock_take (hd->active[i].lockhandle, -1);
+ rc = keybox_lock (hd->active[i].u.kr, 1, -1);
break;
}
if (rc)
@@ -566,7 +584,7 @@ lock_all (KEYDB_HANDLE hd)
if (rc)
{
- /* revert the already set locks */
+ /* Revert the already set locks. */
for (i--; i >= 0; i--)
{
switch (hd->active[i].type)
@@ -574,8 +592,7 @@ lock_all (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (hd->active[i].lockhandle)
- dotlock_release (hd->active[i].lockhandle);
+ keybox_lock (hd->active[i].u.kr, 0, 0);
break;
}
}
@@ -583,10 +600,7 @@ lock_all (KEYDB_HANDLE hd)
else
hd->locked = 1;
- /* make_dotlock () does not yet guarantee that errno is set, thus
- we can't rely on the error reason and will simply use
- EACCES. */
- return rc? gpg_error (GPG_ERR_EACCES) : 0;
+ return rc;
}
static void
@@ -594,7 +608,7 @@ unlock_all (KEYDB_HANDLE hd)
{
int i;
- if (!hd->locked)
+ if (!hd->locked || hd->keep_lock)
return;
for (i=hd->used-1; i >= 0; i--)
@@ -604,8 +618,7 @@ unlock_all (KEYDB_HANDLE hd)
case KEYDB_RESOURCE_TYPE_NONE:
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
- if (hd->active[i].lockhandle)
- dotlock_release (hd->active[i].lockhandle);
+ keybox_lock (hd->active[i].u.kr, 0, 0);
break;
}
}
@@ -638,6 +651,8 @@ keydb_push_found_state (KEYDB_HANDLE hd)
hd->saved_found = hd->found;
hd->found = -1;
+ if (DBG_CLOCK)
+ log_clock ("%s: done (hd=%p)\n", __func__, hd);
}
@@ -661,6 +676,8 @@ keydb_pop_found_state (KEYDB_HANDLE hd)
keybox_pop_found_state (hd->active[hd->found].u.kr);
break;
}
+ if (DBG_CLOCK)
+ log_clock ("%s: done (hd=%p)\n", __func__, hd);
}
@@ -678,9 +695,16 @@ keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+
if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
+ {
+ rc = -1; /* nothing found */
+ goto leave;
+ }
+ rc = GPG_ERR_BUG;
switch (hd->active[hd->found].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
@@ -691,9 +715,13 @@ keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
break;
}
+ leave:
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (rc=%d)\n", __func__, rc);
return rc;
}
+
/* Return a flag of the last found object. WHICH is the flag requested;
it should be one of the KEYBOX_FLAG_ values. If the operation is
successful, the flag value will be stored at the address given by
@@ -701,14 +729,21 @@ keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert)
gpg_error_t
keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
{
- int err = 0;
+ gpg_error_t err;
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+
if ( hd->found < 0 || hd->found >= hd->used)
- return gpg_error (GPG_ERR_NOTHING_FOUND);
+ {
+ err = gpg_error (GPG_ERR_NOTHING_FOUND);
+ goto leave;
+ }
+ err = gpg_error (GPG_ERR_BUG);
switch (hd->active[hd->found].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
@@ -719,9 +754,13 @@ keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
break;
}
+ leave:
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (err=%s)\n", __func__, gpg_strerror (err));
return err;
}
+
/* Set a flag of the last found object. WHICH is the flag to be set; it
should be one of the KEYBOX_FLAG_ values. If the operation is
successful, the flag value will be stored in the keybox. Note,
@@ -731,16 +770,25 @@ keydb_get_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int *value)
gpg_error_t
keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
{
- int err = 0;
+ gpg_error_t err = 0;
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+
if ( hd->found < 0 || hd->found >= hd->used)
- return gpg_error (GPG_ERR_NOTHING_FOUND);
+ {
+ err = gpg_error (GPG_ERR_NOTHING_FOUND);
+ goto leave;
+ }
if (!hd->locked)
- return gpg_error (GPG_ERR_NOT_LOCKED);
+ {
+ err = gpg_error (GPG_ERR_NOT_LOCKED);
+ goto leave;
+ }
switch (hd->active[hd->found].type)
{
@@ -752,16 +800,19 @@ keydb_set_flags (KEYDB_HANDLE hd, int which, int idx, unsigned int value)
break;
}
+ leave:
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (err=%s)\n", __func__, gpg_strerror (err));
return err;
}
/*
* Insert a new Certificate into one of the resources.
*/
-int
+gpg_error_t
keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
{
- int rc = -1;
+ gpg_error_t err;
int idx;
unsigned char digest[20];
@@ -771,104 +822,136 @@ keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
if (opt.dry_run)
return 0;
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+
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 gpg_error (GPG_ERR_GENERAL);
+ {
+ err = gpg_error (GPG_ERR_GENERAL);
+ goto leave;
+ }
if (!hd->locked)
- return gpg_error (GPG_ERR_NOT_LOCKED);
+ {
+ err = gpg_error (GPG_ERR_NOT_LOCKED);
+ goto leave;
+ }
gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
+ err = gpg_error (GPG_ERR_BUG);
switch (hd->active[idx].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL);
+ err = gpg_error (GPG_ERR_GENERAL);
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
+ err = keybox_insert_cert (hd->active[idx].u.kr, cert, digest);
break;
}
unlock_all (hd);
- return rc;
+
+ leave:
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (err=%s)\n", __func__, gpg_strerror (err));
+ return err;
}
/* Update the current keyblock with KB. */
-int
+/* Note: This function is currently not called. */
+gpg_error_t
keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert)
{
- int rc = 0;
+ gpg_error_t err;
unsigned char digest[20];
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
+ return gpg_error (GPG_ERR_NOT_FOUND);
if (opt.dry_run)
return 0;
- rc = lock_all (hd);
- if (rc)
- return rc;
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+
+ err = lock_all (hd);
+ if (err)
+ goto leave;
gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL); /* kludge*/
+ err = gpg_error (GPG_ERR_BUG);
switch (hd->active[hd->found].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL); /* oops */
+ err = gpg_error (GPG_ERR_GENERAL); /* oops */
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
+ err = keybox_update_cert (hd->active[hd->found].u.kr, cert, digest);
break;
}
unlock_all (hd);
- return rc;
+ leave:
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (err=%s)\n", __func__, gpg_strerror (err));
+ return err;
}
/*
* The current keyblock or cert will be deleted.
*/
-int
-keydb_delete (KEYDB_HANDLE hd, int unlock)
+gpg_error_t
+keydb_delete (KEYDB_HANDLE hd)
{
- int rc = -1;
+ gpg_error_t err;
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
if ( hd->found < 0 || hd->found >= hd->used)
- return -1; /* nothing found */
+ return gpg_error (GPG_ERR_NOT_FOUND);
- if( opt.dry_run )
+ if (opt.dry_run)
return 0;
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+
if (!hd->locked)
- return gpg_error (GPG_ERR_NOT_LOCKED);
+ {
+ err = gpg_error (GPG_ERR_NOT_LOCKED);
+ goto leave;
+ }
+ err = gpg_error (GPG_ERR_BUG);
switch (hd->active[hd->found].type)
{
case KEYDB_RESOURCE_TYPE_NONE:
- rc = gpg_error (GPG_ERR_GENERAL);
+ err = gpg_error (GPG_ERR_GENERAL);
break;
case KEYDB_RESOURCE_TYPE_KEYBOX:
- rc = keybox_delete (hd->active[hd->found].u.kr);
+ err = keybox_delete (hd->active[hd->found].u.kr);
break;
}
- if (unlock)
- unlock_all (hd);
- return rc;
+ unlock_all (hd);
+
+ leave:
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (err=%s)\n", __func__, gpg_strerror (err));
+ return err;
}
@@ -941,29 +1024,92 @@ keydb_rebuild_caches (void)
gpg_error_t
keydb_search_reset (KEYDB_HANDLE hd)
{
+ gpg_error_t err = 0;
int i;
- gpg_error_t rc = 0;
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+
hd->current = 0;
hd->found = -1;
/* and reset all resources */
- for (i=0; !rc && i < hd->used; i++)
+ for (i=0; !err && 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);
+ err = keybox_search_reset (hd->active[i].u.kr);
break;
}
}
- return rc;
+
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (err=%s)\n", __func__, gpg_strerror (err));
+ return err;
}
+
+char *
+keydb_search_desc_dump (struct keydb_search_desc *desc)
+{
+ char *fpr;
+ char *result;
+
+ switch (desc->mode)
+ {
+ case KEYDB_SEARCH_MODE_EXACT:
+ return xasprintf ("EXACT: '%s'", desc->u.name);
+ case KEYDB_SEARCH_MODE_SUBSTR:
+ return xasprintf ("SUBSTR: '%s'", desc->u.name);
+ case KEYDB_SEARCH_MODE_MAIL:
+ return xasprintf ("MAIL: '%s'", desc->u.name);
+ case KEYDB_SEARCH_MODE_MAILSUB:
+ return xasprintf ("MAILSUB: '%s'", desc->u.name);
+ case KEYDB_SEARCH_MODE_MAILEND:
+ return xasprintf ("MAILEND: '%s'", desc->u.name);
+ case KEYDB_SEARCH_MODE_WORDS:
+ return xasprintf ("WORDS: '%s'", desc->u.name);
+ case KEYDB_SEARCH_MODE_SHORT_KID:
+ return xasprintf ("SHORT_KID: '%08lX'", (ulong)desc->u.kid[1]);
+ case KEYDB_SEARCH_MODE_LONG_KID:
+ return xasprintf ("LONG_KID: '%08lX%08lX'",
+ (ulong)desc->u.kid[0], (ulong)desc->u.kid[1]);
+ case KEYDB_SEARCH_MODE_FPR:
+ fpr = bin2hexcolon (desc->u.fpr, desc->fprlen, NULL);
+ result = xasprintf ("FPR%02d: '%s'", desc->fprlen, fpr);
+ xfree (fpr);
+ return result;
+ case KEYDB_SEARCH_MODE_ISSUER:
+ return xasprintf ("ISSUER: '%s'", desc->u.name);
+ case KEYDB_SEARCH_MODE_ISSUER_SN:
+ return xasprintf ("ISSUER_SN: '%*s'",
+ (int) (desc->snlen == -1
+ ? strlen (desc->sn) : desc->snlen),
+ desc->sn);
+ case KEYDB_SEARCH_MODE_SN:
+ return xasprintf ("SN: '%*s'",
+ (int) (desc->snlen == -1
+ ? strlen (desc->sn) : desc->snlen),
+ desc->sn);
+ case KEYDB_SEARCH_MODE_SUBJECT:
+ return xasprintf ("SUBJECT: '%s'", desc->u.name);
+ case KEYDB_SEARCH_MODE_KEYGRIP:
+ return xasprintf ("KEYGRIP: %s", desc->u.grip);
+ case KEYDB_SEARCH_MODE_FIRST:
+ return xasprintf ("FIRST");
+ case KEYDB_SEARCH_MODE_NEXT:
+ return xasprintf ("NEXT");
+ default:
+ return xasprintf ("Bad search mode (%d)", desc->mode);
+ }
+}
+
+
/*
* Search through all keydb resources, starting at the current position,
* for a keyblock which contains one of the keys described in the DESC array.
@@ -974,6 +1120,7 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
{
int rc = -1;
unsigned long skipped;
+ int i;
if (!hd)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -985,7 +1132,22 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
return gpg_error (GPG_ERR_NOT_FOUND);
}
- while (rc == -1 && hd->current >= 0 && hd->current < hd->used)
+ if (DBG_CLOCK)
+ log_clock ("%s: enter (hd=%p)\n", __func__, hd);
+
+ if (DBG_LOOKUP)
+ {
+ log_debug ("%s: %zd search description(s):\n", __func__, ndesc);
+ for (i = 0; i < ndesc; i ++)
+ {
+ char *t = keydb_search_desc_dump (&desc[i]);
+ log_debug ("%s: %d: %s\n", __func__, i, t);
+ xfree (t);
+ }
+ }
+
+ while ((rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
+ && hd->current >= 0 && hd->current < hd->used)
{
switch (hd->active[hd->current].type)
{
@@ -998,6 +1160,15 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
NULL, &skipped);
break;
}
+
+ if (DBG_LOOKUP)
+ log_debug ("%s: searched %s (resource %d of %d) => %s\n",
+ __func__,
+ hd->active[hd->current].type == KEYDB_RESOURCE_TYPE_KEYBOX
+ ? "keybox" : "unknown type",
+ hd->current, hd->used,
+ rc == -1 ? "EOF" : gpg_strerror (rc));
+
if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF)
{ /* EOF -> switch to next resource */
hd->current++;
@@ -1006,6 +1177,9 @@ keydb_search (ctrl_t ctrl, KEYDB_HANDLE hd,
hd->found = hd->current;
}
+
+ if (DBG_CLOCK)
+ log_clock ("%s: leave (rc=%d)\n", __func__, rc);
return rc;
}
diff --git a/sm/keydb.h b/sm/keydb.h
index 623462553..1ab94a2c2 100644
--- a/sm/keydb.h
+++ b/sm/keydb.h
@@ -46,10 +46,10 @@ gpg_error_t keydb_set_flags (KEYDB_HANDLE hd, int which, int idx,
void keydb_push_found_state (KEYDB_HANDLE hd);
void keydb_pop_found_state (KEYDB_HANDLE hd);
int keydb_get_cert (KEYDB_HANDLE hd, ksba_cert_t *r_cert);
-int keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
-int keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
+gpg_error_t keydb_insert_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
+gpg_error_t keydb_update_cert (KEYDB_HANDLE hd, ksba_cert_t cert);
-int keydb_delete (KEYDB_HANDLE hd, int unlock);
+gpg_error_t keydb_delete (KEYDB_HANDLE hd);
int keydb_locate_writable (KEYDB_HANDLE hd, const char *reserved);
void keydb_rebuild_caches (void);
diff --git a/sm/keylist.c b/sm/keylist.c
index e242310be..4eecb8720 100644
--- a/sm/keylist.c
+++ b/sm/keylist.c
@@ -1373,6 +1373,8 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
else
es_fprintf (fp, " [certificate is bad: %s]\n", gpg_strerror (err));
}
+ if (opt.debug)
+ es_fflush (fp);
}
diff --git a/sm/server.c b/sm/server.c
index 98505e26d..77ec07fc0 100644
--- a/sm/server.c
+++ b/sm/server.c
@@ -1162,14 +1162,14 @@ cmd_getinfo (assuan_context_t ctx, char *line)
{
cmdopt = line;
if (!command_has_option (cmd, cmdopt))
- rc = gpg_error (GPG_ERR_GENERAL);
+ rc = gpg_error (GPG_ERR_FALSE);
}
}
}
}
else if (!strcmp (line, "offline"))
{
- rc = ctrl->offline? 0 : gpg_error (GPG_ERR_GENERAL);
+ rc = ctrl->offline? 0 : gpg_error (GPG_ERR_FALSE);
}
else
rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
diff --git a/sm/sign.c b/sm/sign.c
index 24ecad3d7..341d8cf68 100644
--- a/sm/sign.c
+++ b/sm/sign.c
@@ -161,7 +161,7 @@ gpgsm_get_default_cert (ctrl_t ctrl, ksba_cert_t *r_cert)
return rc;
}
- if (!gpgsm_cert_use_sign_p (cert))
+ if (!gpgsm_cert_use_sign_p (cert, 1))
{
p = gpgsm_get_keygrip_hexstring (cert);
if (p)
@@ -302,6 +302,99 @@ add_certificate_list (ctrl_t ctrl, ksba_cms_t cms, ksba_cert_t cert)
}
+#if KSBA_VERSION_NUMBER >= 0x010400 && 0 /* 1.4.0 */
+static gpg_error_t
+add_signed_attribute (ksba_cms_t cms, const char *attrstr)
+{
+ gpg_error_t err;
+ char **fields = NULL;
+ const char *s;
+ int i;
+ unsigned char *der = NULL;
+ size_t derlen;
+
+ fields = strtokenize (attrstr, ":");
+ if (!fields)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("strtokenize failed: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+
+ for (i=0; fields[i]; i++)
+ ;
+ if (i != 3)
+ {
+ err = gpg_error (GPG_ERR_SYNTAX);
+ log_error ("invalid attribute specification '%s': %s\n",
+ attrstr, i < 3 ? "not enough fields":"too many fields");
+ goto leave;
+ }
+ if (!ascii_strcasecmp (fields[1], "u"))
+ {
+ err = 0;
+ goto leave; /* Skip unsigned attruibutes. */
+ }
+ if (ascii_strcasecmp (fields[1], "s"))
+ {
+ err = gpg_error (GPG_ERR_SYNTAX);
+ log_error ("invalid attribute specification '%s': %s\n",
+ attrstr, "type is not 's' or 'u'");
+ goto leave;
+ }
+ /* Check that the OID is valid. */
+ err = ksba_oid_from_str (fields[0], &der, &derlen);
+ if (err)
+ {
+ log_error ("invalid attribute specification '%s': %s\n",
+ attrstr, gpg_strerror (err));
+ goto leave;
+ }
+ xfree (der);
+ der = NULL;
+
+ if (strchr (fields[2], '/'))
+ {
+ /* FIXME: read from file. */
+ }
+ else /* Directly given in hex. */
+ {
+ for (i=0, s = fields[2]; hexdigitp (s); s++, i++)
+ ;
+ if (*s || !i || (i&1))
+ {
+ log_error ("invalid attribute specification '%s': %s\n",
+ attrstr, "invalid hex encoding of the data");
+ err = gpg_error (GPG_ERR_SYNTAX);
+ goto leave;
+ }
+ der = xtrystrdup (fields[2]);
+ if (!der)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("malloc failed: %s\n", gpg_strerror (err));
+ goto leave;
+ }
+ for (s=fields[2], derlen=0; s[0] && s[1]; s += 2)
+ der[derlen++] = xtoi_2 (s);
+ }
+
+ /* Store the data in the CMS object for all signers. */
+ err = ksba_cms_add_attribute (cms, -1, fields[0], 0, der, derlen);
+ if (err)
+ {
+ log_error ("invalid attribute specification '%s': %s\n",
+ attrstr, gpg_strerror (err));
+ goto leave;
+ }
+
+ leave:
+ xfree (der);
+ xfree (fields);
+ return err;
+}
+#endif /*ksba >= 1.4.0 */
+
/* Perform a sign operation.
@@ -377,10 +470,17 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
goto leave;
}
- /* We are going to create signed data with data as encap. content */
+ /* We are going to create signed data with data as encap. content.
+ * In authenticode mode we use spcIndirectDataContext instead. */
err = ksba_cms_set_content_type (cms, 0, KSBA_CT_SIGNED_DATA);
if (!err)
- err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
+ err = ksba_cms_set_content_type
+ (cms, 1,
+#if KSBA_VERSION_NUMBER >= 0x010400 && 0
+ opt.authenticode? KSBA_CT_SPC_IND_DATA_CTX :
+#endif
+ KSBA_CT_DATA
+ );
if (err)
{
log_debug ("ksba_cms_set_content_type failed: %s\n",
@@ -404,7 +504,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
/* Although we don't check for ambiguous specification we will
check that the signer's certificate is usable and valid. */
- rc = gpgsm_cert_use_sign_p (cert);
+ rc = gpgsm_cert_use_sign_p (cert, 0);
if (!rc)
rc = gpgsm_validate_chain (ctrl, cert, "", NULL, 0, NULL, 0, NULL);
if (rc)
@@ -513,7 +613,7 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
/* Gather certificates of signers and store them in the CMS object. */
for (cl=signerlist; cl; cl = cl->next)
{
- rc = gpgsm_cert_use_sign_p (cl->cert);
+ rc = gpgsm_cert_use_sign_p (cl->cert, 0);
if (rc)
goto leave;
@@ -643,6 +743,20 @@ gpgsm_sign (ctrl_t ctrl, certlist_t signerlist,
}
}
+ /* We can add signed attributes only when build against libksba 1.4. */
+#if KSBA_VERSION_NUMBER >= 0x010400 && 0 /* 1.4.0 */
+ {
+ strlist_t sl;
+
+ for (sl = opt.attributes; sl; sl = sl->next)
+ if ((err = add_signed_attribute (cms, sl->d)))
+ goto leave;
+ }
+#else
+ log_info ("Note: option --attribute is ignored by this version\n");
+#endif /*ksba >= 1.4.0 */
+
+
/* We need to write at least a minimal list of our capabilities to
try to convince some MUAs to use 3DES and not the crippled
RC2. Our list is: