diff --git a/NEWS b/NEWS index aa3e6d544..bdf2f87d1 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,8 @@ Noteworthy changes in version 2.0.13 * gpgsm --gen-key implements all features of gpgsm-gencert.sh. + * New option --re-import for gpgsm's IMPORT server command. + * Minor bug fixes. diff --git a/TODO b/TODO index e590db886..5182fc8a8 100644 --- a/TODO +++ b/TODO @@ -82,9 +82,6 @@ ** check that we issue NO_SECKEY xxx if a -u key was not found We don't. The messages returned are also wrong (recipient vs. signer). -* jnlib/ -** Try to remove all jnlib_xmalloc. - * g10/ ** issue a NO_SECKEY xxxx if a -u key was not found. diff --git a/agent/command.c b/agent/command.c index e3de085dd..90a7f3437 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1802,7 +1802,7 @@ io_monitor (assuan_context_t ctx, int direction, } -/* Return true if the commznd CMD implements the option OPT. */ +/* Return true if the command CMD implements the option OPT. */ static int command_has_option (const char *cmd, const char *cmdopt) { diff --git a/doc/gpgsm.texi b/doc/gpgsm.texi index e784f71f4..c107bf04d 100644 --- a/doc/gpgsm.texi +++ b/doc/gpgsm.texi @@ -1219,14 +1219,19 @@ in the same way as with the OUTPUT command. To import certificates into the internal key database, the command @example - IMPORT + IMPORT [--re-import] @end example is used. The data is expected on the file descriptor set with the @code{INPUT} command. Certain checks are performend on the -certificate. Note that the code will also handle PKCS\#12 files and +certificate. Note that the code will also handle PKCS#12 files and import private keys; a helper program is used for that. +With the option @option{--re-import} the input data is expected to a be +a linefeed separated list of fingerprints. The command will re-import +the corresponding certificates; that is they are made permanent by +removing their ephemeral flag. + @node GPGSM DELETE @subsection Delete certificates @@ -1259,6 +1264,11 @@ The value of @var{what} specifies the kind of information returned: Return the version of the program. @item pid Return the process id of the process. +@item agent-check +Return success if the agent is running. +@item cmd_has_option @var{cmd} @var{opt} +Return success if the command @var{cmd} implements the option @var{opt}. +The leading two dashes usually used with @var{opt} shall not be given. @end table @mansect see also diff --git a/sm/ChangeLog b/sm/ChangeLog index a2c06753c..954f88ea5 100644 --- a/sm/ChangeLog +++ b/sm/ChangeLog @@ -1,5 +1,11 @@ 2009-07-07 Werner Koch + * server.c (command_has_option): New. + (cmd_getinfo): Add subcommand "cmd_has_option". + (cmd_import): Implement option --re-import. + * import.c (gpgsm_import): Add arg reimport_mode. + (reimport_one): New. + * gpgsm.h: Include session-env.h. (opt): Add field SESSION_ENV. Remove obsolete fields. * server.c (option_handler): Rewrite setting of option fields. diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 900e6dd5e..b6c9a763d 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -333,7 +333,7 @@ gpg_error_t gpgsm_list_keys (ctrl_t ctrl, strlist_t names, estream_t fp, unsigned int mode); /*-- import.c --*/ -int gpgsm_import (ctrl_t ctrl, int in_fd); +int gpgsm_import (ctrl_t ctrl, int in_fd, int reimport_mode); int gpgsm_import_files (ctrl_t ctrl, int nfiles, char **files, int (*of)(const char *fname)); diff --git a/sm/import.c b/sm/import.c index 5e8b42971..5a0eded8f 100644 --- a/sm/import.c +++ b/sm/import.c @@ -1,5 +1,5 @@ /* import.c - Import certificates - * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. + * Copyright (C) 2001, 2003, 2004, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -34,6 +34,8 @@ #include "exechelp.h" #include "i18n.h" #include "sysutils.h" +#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */ + struct stats_s { unsigned long count; @@ -405,14 +407,136 @@ import_one (ctrl_t ctrl, struct stats_s *stats, int in_fd) } + +/* Re-import certifciates. IN_FD is a list of linefeed delimited + fingerprints t re-import. The actual re-import is done by clearing + the ephemeral flag. */ +static int +reimport_one (ctrl_t ctrl, struct stats_s *stats, int in_fd) +{ + gpg_error_t err = 0; + estream_t fp = NULL; + char line[100]; /* Sufficient for a fingerprint. */ + KEYDB_HANDLE kh; + KEYDB_SEARCH_DESC desc; + ksba_cert_t cert = NULL; + unsigned int flags; + + kh = keydb_new (0); + if (!kh) + { + err = gpg_error (GPG_ERR_ENOMEM);; + log_error (_("failed to allocate keyDB handle\n")); + goto leave; + } + keydb_set_ephemeral (kh, 1); + + fp = es_fdopen_nc (in_fd, "r"); + if (!fp) + { + err = gpg_error_from_syserror (); + log_error ("es_fdopen(%d) failed: %s\n", in_fd, gpg_strerror (err)); + goto leave; + } + + while (es_fgets (line, DIM(line)-1, fp) ) + { + if (*line && line[strlen(line)-1] != '\n') + { + err = gpg_error (GPG_ERR_LINE_TOO_LONG); + goto leave; + } + trim_spaces (line); + if (!*line) + continue; + + stats->count++; + + err = keydb_classify_name (line, &desc); + if (err) + { + print_import_problem (ctrl, NULL, 0); + stats->not_imported++; + continue; + } + + keydb_search_reset (kh); + err = keydb_search (kh, &desc, 1); + if (err) + { + print_import_problem (ctrl, NULL, 0); + stats->not_imported++; + continue; + } + + ksba_cert_release (cert); + cert = NULL; + err = keydb_get_cert (kh, &cert); + if (err) + { + log_error ("keydb_get_cert() failed: %s\n", gpg_strerror (err)); + print_import_problem (ctrl, NULL, 1); + stats->not_imported++; + continue; + } + + err = keydb_get_flags (kh, KEYBOX_FLAG_BLOB, 0, &flags); + if (err) + { + log_error (_("error getting stored flags: %s\n"), gpg_strerror (err)); + print_imported_status (ctrl, cert, 0); + stats->not_imported++; + continue; + } + if ( !(flags & KEYBOX_FLAG_BLOB_EPHEMERAL) ) + { + print_imported_status (ctrl, cert, 0); + stats->unchanged++; + continue; + } + + err = keydb_set_cert_flags (cert, 1, KEYBOX_FLAG_BLOB, 0, + KEYBOX_FLAG_BLOB_EPHEMERAL, 0); + if (err) + { + log_error ("clearing ephemeral flag failed: %s\n", + gpg_strerror (err)); + print_import_problem (ctrl, cert, 0); + stats->not_imported++; + continue; + } + + print_imported_status (ctrl, cert, 1); + stats->imported++; + } + err = 0; + if (es_ferror (fp)) + { + err = gpg_error_from_syserror (); + log_error ("error reading fd %d: %s\n", in_fd, gpg_strerror (err)); + goto leave; + } + + leave: + ksba_cert_release (cert); + keydb_release (kh); + es_fclose (fp); + return err; +} + + + int -gpgsm_import (ctrl_t ctrl, int in_fd) +gpgsm_import (ctrl_t ctrl, int in_fd, int reimport_mode) { int rc; struct stats_s stats; memset (&stats, 0, sizeof stats); - rc = import_one (ctrl, &stats, in_fd); + if (reimport_mode) + rc = reimport_one (ctrl, &stats, in_fd); + else + rc = import_one (ctrl, &stats, in_fd); print_imported_summary (ctrl, &stats); /* If we never printed an error message do it now so that a command line invocation will return with an error (log_error keeps a diff --git a/sm/server.c b/sm/server.c index 7ba5b683e..f6c8af99d 100644 --- a/sm/server.c +++ b/sm/server.c @@ -1,6 +1,6 @@ /* server.c - Server mode and main entry point * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, - * 2007, 2008 Free Software Foundation, Inc. + * 2007, 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -68,6 +68,10 @@ static es_cookie_io_functions_t data_line_cookie_functions = }; + +static int command_has_option (const char *cmd, const char *cmdopt); + + /* Note that it is sufficient to allocate the target string D as @@ -638,25 +642,31 @@ cmd_sign (assuan_context_t ctx, char *line) } -/* IMPORT +/* IMPORT [--re-import] - Import the certificates read form the input-fd, return status - message for each imported one. The import checks the validity of - the certificate but not of the entire chain. It is possible to - import expired certificates. */ + Import the certificates read form the input-fd, return status + message for each imported one. The import checks the validity of + the certificate but not of the entire chain. It is possible to + import expired certificates. + + With the option --re-import the input data is expected to a be a LF + separated list of fingerprints. The command will re-import these + certificates, meaning that they are made permanent by removing + their ephemeral flag. */ static int cmd_import (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); int rc; int fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0); + int reimport = has_option (line, "--re-import"); (void)line; if (fd == -1) return set_error (GPG_ERR_ASS_NO_INPUT, NULL); - rc = gpgsm_import (assuan_get_pointer (ctx), fd); + rc = gpgsm_import (assuan_get_pointer (ctx), fd, reimport); /* close and reset the fd */ close_message_fd (ctrl); @@ -1029,12 +1039,14 @@ cmd_getauditlog (assuan_context_t ctx, char *line) version - Return the version of the program. pid - Return the process id of the server. agent-check - Return success if the agent is running. + cmd_has_option CMD OPT + - Returns OK if the command CMD implements the option OPT. */ static int cmd_getinfo (assuan_context_t ctx, char *line) { - int rc; + int rc = 0; if (!strcmp (line, "version")) { @@ -1053,13 +1065,60 @@ cmd_getinfo (assuan_context_t ctx, char *line) ctrl_t ctrl = assuan_get_pointer (ctx); rc = gpgsm_agent_send_nop (ctrl); } + else if (!strncmp (line, "cmd_has_option", 14) + && (line[14] == ' ' || line[14] == '\t' || !line[14])) + { + char *cmd, *cmdopt; + line += 14; + while (*line == ' ' || *line == '\t') + line++; + if (!*line) + rc = gpg_error (GPG_ERR_MISSING_VALUE); + else + { + cmd = line; + while (*line && (*line != ' ' && *line != '\t')) + line++; + if (!*line) + rc = gpg_error (GPG_ERR_MISSING_VALUE); + else + { + *line++ = 0; + while (*line == ' ' || *line == '\t') + line++; + if (!*line) + rc = gpg_error (GPG_ERR_MISSING_VALUE); + else + { + cmdopt = line; + if (!command_has_option (cmd, cmdopt)) + rc = gpg_error (GPG_ERR_GENERAL); + } + } + } + } else rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT"); + return rc; } +/* Return true if the command CMD implements the option OPT. */ +static int +command_has_option (const char *cmd, const char *cmdopt) +{ + if (!strcmp (cmd, "IMPORT")) + { + if (!strcmp (cmdopt, "re-import")) + return 1; + } + + return 0; +} + + /* Tell the assuan library about our commands */ static int register_commands (assuan_context_t ctx)