aboutsummaryrefslogtreecommitdiffstats
path: root/sm
diff options
context:
space:
mode:
Diffstat (limited to 'sm')
-rw-r--r--sm/ChangeLog32
-rw-r--r--sm/call-agent.c30
-rw-r--r--sm/call-dirmngr.c140
-rw-r--r--sm/certcheck.c3
-rw-r--r--sm/gpgsm.c86
-rw-r--r--sm/gpgsm.h3
-rw-r--r--sm/verify.c30
7 files changed, 314 insertions, 10 deletions
diff --git a/sm/ChangeLog b/sm/ChangeLog
index 8e11e0ddf..0a9150726 100644
--- a/sm/ChangeLog
+++ b/sm/ChangeLog
@@ -1,3 +1,35 @@
+2002-12-03 Werner Koch <[email protected]>
+
+ * call-agent.c (gpgsm_agent_passwd): New.
+ * gpgsm.c (main): New command --passwd and --call-protect-tool
+ (run_protect_tool): New.
+
+2002-11-25 Werner Koch <[email protected]>
+
+ * verify.c (gpgsm_verify): Handle content-type attribute.
+
+2002-11-13 Werner Koch <[email protected]>
+
+ * call-agent.c (start_agent): Try to use $GPG_TTY instead of
+ ttyname. Changed ttyname to test stdin becuase it can be assumed
+ that output redirection is more common that input redirection.
+
+2002-11-12 Werner Koch <[email protected]>
+
+ * gpgsm.c: New command --call-dirmngr.
+ * call-dirmngr.c (gpgsm_dirmngr_run_command)
+ (run_command_inq_cb,run_command_cb)
+ (run_command_status_cb): New.
+
+2002-11-11 Werner Koch <[email protected]>
+
+ * certcheck.c (gpgsm_check_cms_signature): Don't double free
+ s_sig but free s_pkey at leave.
+
+2002-11-10 Werner Koch <[email protected]>
+
+ * gpgsm.c: Removed duplicate --list-secret-key entry.
+
2002-09-19 Werner Koch <[email protected]>
* certcheck.c (gpgsm_check_cert_sig): Add cert hash debugging.
diff --git a/sm/call-agent.c b/sm/call-agent.c
index 6cb2fb505..d518b2bc5 100644
--- a/sm/call-agent.c
+++ b/sm/call-agent.c
@@ -248,8 +248,12 @@ start_agent (void)
if (rc)
return map_assuan_err (rc);
}
- if (!opt.ttyname && ttyname (1))
- dft_ttyname = ttyname (1);
+ if (!opt.ttyname)
+ {
+ dft_ttyname = getenv ("GPG_TTY");
+ if ((!dft_ttyname || !*dft_ttyname) && ttyname (0))
+ dft_ttyname = ttyname (0);
+ }
if (opt.ttyname || dft_ttyname)
{
char *optstr;
@@ -749,3 +753,25 @@ gpgsm_agent_learn ()
return learn_parm.error;
}
+
+/* Ask the agent to change the passphrase of the key identified by HEXKEYGRIP. */
+int
+gpgsm_agent_passwd (const char *hexkeygrip)
+{
+ int rc;
+ char line[ASSUAN_LINELENGTH];
+
+ rc = start_agent ();
+ if (rc)
+ return rc;
+
+ if (!hexkeygrip || strlen (hexkeygrip) != 40)
+ return GNUPG_Invalid_Value;
+
+ snprintf (line, DIM(line)-1, "PASSWD %s", hexkeygrip);
+ line[DIM(line)-1] = 0;
+
+ rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+ return map_assuan_err (rc);
+}
+
diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c
index a1d94e25b..6c1156a83 100644
--- a/sm/call-dirmngr.c
+++ b/sm/call-dirmngr.c
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <time.h>
#include <assert.h>
+#include <ctype.h>
#include <gcrypt.h>
@@ -59,7 +60,9 @@ struct lookup_parm_s {
int error;
};
-
+struct run_command_parm_s {
+ ASSUAN_CONTEXT ctx;
+};
/* A simple implementation of a dynamic buffer. Use init_membuf() to
@@ -452,7 +455,7 @@ lookup_status_cb (void *opaque, const char *line)
}
-/* Run the Directroy Managers lookup command using the apptern
+/* Run the Directroy Managers lookup command using the pattern
compiled from the strings given in NAMES. The caller must provide
the callback CB which will be passed cert by cert. Note that CTRL
is optional. */
@@ -493,3 +496,136 @@ gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
}
+
+/* Run Command helpers*/
+
+/* Fairly simple callback to write all output of dirmngr to stdout. */
+static AssuanError
+run_command_cb (void *opaque, const void *buffer, size_t length)
+{
+ if (buffer)
+ {
+ if ( fwrite (buffer, length, 1, stdout) != 1 )
+ log_error ("error writing to stdout: %s\n", strerror (errno));
+ }
+ return 0;
+}
+
+/* Handle inquiries from the dirmngr COMMAND. */
+static AssuanError
+run_command_inq_cb (void *opaque, const char *line)
+{
+ struct run_command_parm_s *parm = opaque;
+ AssuanError rc = 0;
+
+ if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
+ { /* send the given certificate */
+ int err;
+ KsbaCert cert;
+ const unsigned char *der;
+ size_t derlen;
+
+ line += 8;
+ if (!*line)
+ return ASSUAN_Inquire_Error;
+
+ err = gpgsm_find_cert (line, &cert);
+ if (err)
+ {
+ log_error ("certificate not found: %s\n", gnupg_strerror (err));
+ rc = ASSUAN_Inquire_Error;
+ }
+ else
+ {
+ der = ksba_cert_get_image (cert, &derlen);
+ if (!der)
+ rc = ASSUAN_Inquire_Error;
+ else
+ rc = assuan_send_data (parm->ctx, der, derlen);
+ ksba_cert_release (cert);
+ }
+ }
+ else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
+ { /* Simply show the message given in the argument. */
+ line += 9;
+ log_info ("dirmngr: %s\n", line);
+ }
+ else
+ {
+ log_error ("unsupported inquiry `%s'\n", line);
+ rc = ASSUAN_Inquire_Unknown;
+ }
+
+ return rc;
+}
+
+static AssuanError
+run_command_status_cb (void *opaque, const char *line)
+{
+ if (opt.verbose)
+ {
+ log_info ("dirmngr status: %s\n", line);
+ }
+ return 0;
+}
+
+
+
+/* Pass COMMAND to dirmngr and print all output generated by Dirmngr
+ to stdout. A couple of inquiries are defined (see above). ARGC
+ arguments in ARGV are given to the Dirmngr. Spaces, plus and
+ percent characters within the argument strings are percent escaped
+ so that blanks can act as delimiters. */
+int
+gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
+ int argc, char **argv)
+{
+ int rc;
+ int i;
+ const char *s;
+ char *line, *p;
+ size_t len;
+ struct run_command_parm_s parm;
+
+ rc = start_dirmngr ();
+ if (rc)
+ return rc;
+
+ parm.ctx = dirmngr_ctx;
+
+ len = strlen (command) + 1;
+ for (i=0; i < argc; i++)
+ len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
+ line = xtrymalloc (len);
+ if (!line)
+ return GNUPG_Out_Of_Core;
+
+ p = stpcpy (line, command);
+ for (i=0; i < argc; i++)
+ {
+ *p++ = ' ';
+ for (s=argv[i]; *s; s++)
+ {
+ if (!isascii (*s))
+ *p++ = *s;
+ else if (*s == ' ')
+ *p++ = '+';
+ else if (!isprint (*s) || *s == '+')
+ {
+ sprintf (p, "%%%02X", *s);
+ p += 3;
+ }
+ else
+ *p++ = *s;
+ }
+ }
+ *p = 0;
+
+ rc = assuan_transact (dirmngr_ctx, line,
+ run_command_cb, NULL,
+ run_command_inq_cb, &parm,
+ run_command_status_cb, NULL);
+ xfree (line);
+ log_info ("response of dirmngr: %s\n", rc? assuan_strerror (rc): "okay");
+ return map_assuan_err (rc);
+}
diff --git a/sm/certcheck.c b/sm/certcheck.c
index 37d2b00df..1f9054b13 100644
--- a/sm/certcheck.c
+++ b/sm/certcheck.c
@@ -266,13 +266,12 @@ gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval,
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);
+ gcry_sexp_release (s_pkey);
return map_gcry_err (rc);
}
diff --git a/sm/gpgsm.c b/sm/gpgsm.c
index bfcdeb741..1583787a1 100644
--- a/sm/gpgsm.c
+++ b/sm/gpgsm.c
@@ -77,6 +77,9 @@ enum cmd_and_opt_values {
aCheckKeys, /* nyi */
aServer,
aLearnCard,
+ aCallDirmngr,
+ aCallProtectTool,
+ aPasswd,
oOptions,
oDebug,
@@ -139,7 +142,6 @@ enum cmd_and_opt_values {
oCipherAlgo,
oDigestAlgo,
oCompressAlgo,
- oPasswdFD,
oCommandFD,
oNoVerbose,
oTrustDBName,
@@ -219,7 +221,6 @@ static ARGPARSE_OPTS opts[] = {
{ aListSigs, "list-sigs", 256, N_("list certificate chain")},
{ aListSigs, "check-sigs",256, "@"},
{ oFingerprint, "fingerprint", 256, N_("list keys and fingerprints")},
- { aListSecretKeys, "list-secret-keys", 256, N_("list secret keys")},
{ aKeygen, "gen-key", 256, N_("generate a new key pair")},
{ aDeleteKey, "delete-key",256, N_("remove key from the public keyring")},
{ aSendKeys, "send-keys" , 256, N_("export keys to a key server") },
@@ -228,7 +229,10 @@ static ARGPARSE_OPTS opts[] = {
{ aExport, "export", 256 , N_("export certificates")},
{ aLearnCard, "learn-card", 256 ,N_("register a smartcard")},
{ aServer, "server", 256, N_("run in server mode")},
- { oLogFile, "log-file" ,2, N_("use a log file for the server")},
+ { aCallDirmngr, "call-dirmngr", 256, N_("pass a command to the dirmngr")},
+ { aCallProtectTool, "call-protect-tool", 256,
+ N_("invoke gpg-protect-tool")},
+ { aPasswd, "passwd", 256, N_("change a passphrase")},
{ 301, NULL, 0, N_("@\nOptions:\n ") },
@@ -283,6 +287,7 @@ static ARGPARSE_OPTS opts[] = {
{ oVerbose, "verbose", 0, N_("verbose") },
{ oQuiet, "quiet", 0, N_("be somewhat more quiet") },
{ oNoTTY, "no-tty", 0, N_("don't use the terminal at all") },
+ { oLogFile, "log-file" ,2, N_("use a log file for the server")},
#if 0
{ oForceV3Sigs, "force-v3-sigs", 0, N_("force v3 signatures") },
{ oForceMDC, "force-mdc", 0, N_("always use a MDC for encryption") },
@@ -406,6 +411,7 @@ 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);
+static void run_protect_tool (int argc, char **argv);
static int
@@ -589,6 +595,7 @@ main ( int argc, char **argv)
char *configname = NULL;
unsigned configlineno;
int parse_debug = 0;
+ int no_more_options = 0;
int default_config =1;
int default_keyring = 1;
char *logfile = NULL;
@@ -666,6 +673,9 @@ main ( int argc, char **argv)
default_config = 0; /* --no-options */
else if (pargs.r_opt == oHomedir)
opt.homedir = pargs.r.ret_str;
+ else if (pargs.r_opt == aCallProtectTool)
+ break; /* This break makes sure that --version and --help are
+ passed to the protect-tool. */
}
@@ -724,7 +734,8 @@ main ( int argc, char **argv)
default_config = 0;
}
- while (optfile_parse (configfp, configname, &configlineno, &pargs, opts))
+ while (!no_more_options
+ && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
{
switch (pargs.r_opt)
{
@@ -732,7 +743,17 @@ main ( int argc, char **argv)
opt.batch = 1;
set_cmd (&cmd, aServer);
break;
+ case aCallDirmngr:
+ opt.batch = 1;
+ set_cmd (&cmd, aCallDirmngr);
+ break;
+ case aCallProtectTool:
+ opt.batch = 1;
+ set_cmd (&cmd, aCallProtectTool);
+ no_more_options = 1; /* Stop parsing. */
+ break;
+
case aCheckKeys: set_cmd (&cmd, aCheckKeys); break;
case aImport: set_cmd (&cmd, aImport); break;
case aSendKeys: set_cmd (&cmd, aSendKeys); break;
@@ -744,6 +765,8 @@ main ( int argc, char **argv)
case aListSigs: set_cmd (&cmd, aListSigs); break;
case aLearnCard: set_cmd (&cmd, aLearnCard); break;
+
+ case aPasswd: set_cmd (&cmd, aPasswd); break;
case aDeleteKey:
set_cmd (&cmd, aDeleteKey);
@@ -1128,6 +1151,18 @@ main ( int argc, char **argv)
gpgsm_server ();
break;
+ case aCallDirmngr:
+ if (!argc)
+ wrong_args (_("--call-dirmngr <command> {args}"));
+ else
+ if (gpgsm_dirmngr_run_command (&ctrl, *argv, argc-1, argv+1))
+ gpgsm_exit (1);
+ break;
+
+ case aCallProtectTool:
+ run_protect_tool (argc, argv);
+ break;
+
case aEncr: /* encrypt the given file */
if (!argc)
gpgsm_encrypt (&ctrl, recplist, 0, stdout); /* from stdin */
@@ -1258,6 +1293,28 @@ main ( int argc, char **argv)
}
break;
+ case aPasswd:
+ if (argc != 1)
+ wrong_args ("--passwd <key-Id>");
+ else
+ {
+ int rc;
+ KsbaCert cert = NULL;
+ char *grip = NULL;
+
+ rc = gpgsm_find_cert (*argv, &cert);
+ if (rc)
+ ;
+ else if (!(grip = gpgsm_get_keygrip_hexstring (cert)))
+ rc = GNUPG_Bug;
+ else
+ rc = gpgsm_agent_passwd (grip);
+ if (rc)
+ log_error ("error changing passphrase: %s\n", gnupg_strerror (rc));
+ xfree (grip);
+ ksba_cert_release (cert);
+ }
+ break;
default:
log_error ("invalid command (there is no implicit command)\n");
@@ -1386,3 +1443,24 @@ open_fwrite (const char *filename)
}
return fp;
}
+
+
+static void
+run_protect_tool (int argc, char **argv)
+{
+ char *pgm = GNUPG_PROTECT_TOOL;
+ char **av;
+ int i;
+
+ av = xcalloc (argc+2, sizeof *av);
+ av[0] = strrchr (pgm, '/');
+ if (!av[0])
+ av[0] = pgm;
+ for (i=1; argc; i++, argc--, argv++)
+ av[i] = *argv;
+ av[i] = NULL;
+ execv (pgm, av);
+ log_error ("error executing `%s': %s\n", pgm, strerror (errno));
+ gpgsm_exit (2);
+}
+
diff --git a/sm/gpgsm.h b/sm/gpgsm.h
index 50590206e..dd91e3764 100644
--- a/sm/gpgsm.h
+++ b/sm/gpgsm.h
@@ -248,11 +248,14 @@ int gpgsm_agent_istrusted (KsbaCert cert);
int gpgsm_agent_havekey (const char *hexkeygrip);
int gpgsm_agent_marktrusted (KsbaCert cert);
int gpgsm_agent_learn (void);
+int gpgsm_agent_passwd (const char *hexkeygrip);
/*-- call-dirmngr.c --*/
int gpgsm_dirmngr_isvalid (KsbaCert cert);
int gpgsm_dirmngr_lookup (CTRL ctrl, STRLIST names,
void (*cb)(void*, KsbaCert), void *cb_value);
+int gpgsm_dirmngr_run_command (CTRL ctrl, const char *command,
+ int argc, char **argv);
diff --git a/sm/verify.c b/sm/verify.c
index df7c8bfe8..3461d68af 100644
--- a/sm/verify.c
+++ b/sm/verify.c
@@ -257,6 +257,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
KsbaSexp serial;
char *msgdigest = NULL;
size_t msgdigestlen;
+ char *ctattr;
err = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial);
if (!signer && err == KSBA_No_Data && data_fd == -1 && is_detached)
@@ -313,6 +314,35 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
else /* real error */
break;
+ err = ksba_cms_get_sigattr_oids (cms, signer,
+ "1.2.840.113549.1.9.3",&ctattr);
+ if (!err)
+ {
+ const char *s;
+
+ if (DBG_X509)
+ log_debug ("signer %d - content-type attribute: %s", signer, ctattr);
+ s = ksba_cms_get_content_oid (cms, 1);
+ if (!s || strcmp (ctattr, s))
+ {
+ log_error ("content-type attribute does not match "
+ "actual content-type\n");
+ ksba_free (ctattr);
+ ctattr = NULL;
+ goto next_signer;
+ }
+ ksba_free (ctattr);
+ ctattr = NULL;
+ }
+ else if (err != -1)
+ {
+ log_error ("error getting content-type attribute: %s\n",
+ ksba_strerror (err));
+ goto next_signer;
+ }
+ err = 0;
+
+
sigval = ksba_cms_get_sig_val (cms, signer);
if (!sigval)
{