aboutsummaryrefslogtreecommitdiffstats
path: root/agent/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/command.c')
-rw-r--r--agent/command.c161
1 files changed, 158 insertions, 3 deletions
diff --git a/agent/command.c b/agent/command.c
index 9ebcd091f..ba0f8fc4c 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -1,6 +1,6 @@
/* command.c - gpg-agent command handler
* Copyright (C) 2001, 2002, 2003, 2004, 2005,
- * 2006, 2008 Free Software Foundation, Inc.
+ * 2006, 2008, 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -30,6 +30,9 @@
#include <ctype.h>
#include <unistd.h>
#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
#include <assuan.h>
@@ -308,8 +311,21 @@ agent_write_status (ctrl_t ctrl, const char *keyword, ...)
*p++ = ' ';
n++;
}
- for ( ; *text && n < DIM (buf)-2; n++)
- *p++ = *text++;
+ for ( ; *text && n < DIM (buf)-3; n++, text++)
+ {
+ if (*text == '\n')
+ {
+ *p++ = '\\';
+ *p++ = 'n';
+ }
+ else if (*text == '\r')
+ {
+ *p++ = '\\';
+ *p++ = 'r';
+ }
+ else
+ *p++ = *text;
+ }
}
*p = 0;
err = assuan_write_status (ctx, keyword, buf);
@@ -806,7 +822,145 @@ cmd_readkey (assuan_context_t ctx, char *line)
}
+
+/* KEYINFO [--list] <keygrip>
+
+ Return information about the key specified by the KEYGRIP. If the
+ key is not available GPG_ERR_NOT_FOUND is returned. If the option
+ --list is given the keygrip is ignored and information about all
+ available keys are returned. The information is returned as a
+ status line with this format:
+
+ KEYINFO <keygrip> <type> <serialno> <idstr>
+
+ KEYGRIP is the keygrip.
+
+ TYPE is describes the type of the key:
+ 'D' - Regular key stored on disk,
+ 'T' - Key is stored on a smartcard (token).
+ '-' - Unknown type.
+
+ SERIALNO is an ASCII string with the serial number of the
+ smartcard. If the serial number is not known a single
+ dash '-' is used instead.
+
+ IDSTR is the IDSTR used to distinguish keys on a smartcard. If it
+ is not known a dash is used instead.
+
+ More information may be added in the future.
+*/
+static gpg_error_t
+do_one_keyinfo (ctrl_t ctrl, const unsigned char *grip)
+{
+ gpg_error_t err;
+ char hexgrip[40+1];
+ int keytype;
+ unsigned char *shadow_info = NULL;
+ char *serialno = NULL;
+ char *idstr = NULL;
+ const char *keytypestr;
+
+ err = agent_key_info_from_file (ctrl, grip, &keytype, &shadow_info);
+ if (err)
+ goto leave;
+
+ /* Reformat the grip so that we use uppercase as good style. */
+ bin2hex (grip, 20, hexgrip);
+
+ if (keytype == PRIVATE_KEY_CLEAR
+ || keytype == PRIVATE_KEY_PROTECTED)
+ keytypestr = "D";
+ else if (keytype == PRIVATE_KEY_SHADOWED)
+ keytypestr = "T";
+ else
+ keytypestr = "-";
+
+ if (shadow_info)
+ {
+ err = parse_shadow_info (shadow_info, &serialno, &idstr);
+ if (err)
+ goto leave;
+ }
+
+ err = agent_write_status (ctrl, "KEYINFO",
+ hexgrip,
+ keytypestr,
+ serialno? serialno : "-",
+ idstr? idstr : "-",
+ NULL);
+ leave:
+ xfree (shadow_info);
+ xfree (serialno);
+ xfree (idstr);
+ return err;
+}
+
+
+static int
+cmd_keyinfo (assuan_context_t ctx, char *line)
+{
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+ int err;
+ unsigned char grip[20];
+ DIR *dir = NULL;
+ int list_mode;
+
+ list_mode = has_option (line, "--list");
+ line = skip_options (line);
+
+ if (list_mode)
+ {
+ char *dirname;
+ struct dirent *dir_entry;
+ char hexgrip[41];
+
+ dirname = make_filename_try (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, NULL);
+ if (!dirname)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ dir = opendir (dirname);
+ if (!dir)
+ {
+ err = gpg_error_from_syserror ();
+ xfree (dirname);
+ goto leave;
+ }
+ xfree (dirname);
+ while ( (dir_entry = readdir (dir)) )
+ {
+ if (strlen (dir_entry->d_name) != 44
+ || strcmp (dir_entry->d_name + 40, ".key"))
+ continue;
+ strncpy (hexgrip, dir_entry->d_name, 40);
+ hexgrip[40] = 0;
+
+ if ( hex2bin (hexgrip, grip, 20) < 0 )
+ continue; /* Bad hex string. */
+
+ err = do_one_keyinfo (ctrl, grip);
+ if (err)
+ goto leave;
+ }
+ err = 0;
+ }
+ else
+ {
+ err = parse_keygrip (ctx, line, grip);
+ if (err)
+ goto leave;
+ err = do_one_keyinfo (ctrl, grip);
+ }
+
+ leave:
+ if (dir)
+ closedir (dir);
+ if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
+ log_error ("command keyinfo failed: %s\n", gpg_strerror (err));
+ return err;
+}
@@ -1574,6 +1728,7 @@ register_commands (assuan_context_t ctx)
{ "GETEVENTCOUNTER",cmd_geteventcounter },
{ "ISTRUSTED", cmd_istrusted },
{ "HAVEKEY", cmd_havekey },
+ { "KEYINFO", cmd_keyinfo },
{ "SIGKEY", cmd_sigkey },
{ "SETKEY", cmd_sigkey },
{ "SETKEYDESC", cmd_setkeydesc },