From d4d61b87f153f5c0657a5f698983a20b5398cfff Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 12 Aug 2010 11:43:46 +0000 Subject: [PATCH] Fix dirmngr problems on CE. Add new dirmngr commands. Minor other fixes. --- agent/ChangeLog | 3 ++ agent/call-pinentry.c | 7 ++++ common/ChangeLog | 4 +++ common/sysutils.c | 4 +-- dirmngr/ChangeLog | 11 +++++- dirmngr/crlcache.c | 6 ++-- dirmngr/dirmngr.c | 23 +++++++++---- dirmngr/dirmngr.h | 1 + dirmngr/server.c | 80 ++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 125 insertions(+), 14 deletions(-) diff --git a/agent/ChangeLog b/agent/ChangeLog index 54e2256ec..a1093389b 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,8 @@ 2010-08-11 Werner Koch + * call-pinentry.c (agent_get_passphrase, agent_askpin): Fix + setting of confidential flag. + * call-scd.c (agent_card_scd): Pass assuan comment lines to the caller. (ASSUAN_CONVEY_COMMENTS): Provide replacement if needed. diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c index 01c9fc5fc..d00fdf6fc 100644 --- a/agent/call-pinentry.c +++ b/agent/call-pinentry.c @@ -705,6 +705,7 @@ agent_askpin (ctrl_t ctrl, struct entry_parm_s parm; const char *errtext = NULL; int is_pin = 0; + int saveflag; if (opt.batch) return 0; /* fixme: we should return BAD PIN */ @@ -782,8 +783,11 @@ agent_askpin (ctrl_t ctrl, errtext = NULL; } + saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL); + assuan_begin_confidential (entry_ctx); rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, inq_quality, entry_ctx, NULL, NULL); + assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag); /* Most pinentries out in the wild return the old Assuan error code for canceled which gets translated to an assuan Cancel error and not to the code for a user cancel. Fix this here. */ @@ -845,6 +849,7 @@ agent_get_passphrase (ctrl_t ctrl, int rc; char line[ASSUAN_LINELENGTH]; struct entry_parm_s parm; + int saveflag; *retpass = NULL; if (opt.batch) @@ -895,9 +900,11 @@ agent_get_passphrase (ctrl_t ctrl, if (!parm.buffer) return unlock_pinentry (out_of_core ()); + saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL); assuan_begin_confidential (entry_ctx); rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, inq_quality, entry_ctx, NULL, NULL); + assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag); /* Most pinentries out in the wild return the old Assuan error code for canceled which gets translated to an assuan Cancel error and not to the code for a user cancel. Fix this here. */ diff --git a/common/ChangeLog b/common/ChangeLog index 9e6956370..b4c79e234 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2010-08-12 Werner Koch + + * sysutils.c (gnupg_remove) [W32CE]: Fix returned error. + 2010-08-09 Werner Koch * logging.c (WITH_IPV6): New macro. diff --git a/common/sysutils.c b/common/sysutils.c index 82d9959d8..b75c5e1e5 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -530,8 +530,8 @@ gnupg_remove (const char *fname) xfree (wfname); } if (!rc) - gpg_err_set_errno (EIO); - return !rc; + return -1; /* ERRNO is automagically provided by gpg-error.h. */ + return 0; #else return remove (fname); #endif diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog index 737ff35fa..8f861c6a0 100644 --- a/dirmngr/ChangeLog +++ b/dirmngr/ChangeLog @@ -1,9 +1,18 @@ +2010-08-12 Werner Koch + + * crlcache.c (update_dir, crl_cache_insert): s/unlink/gnupg_remove/. + + * dirmngr.c (dirmngr_sighup_action): New. + + * server.c (cmd_killdirmngr, cmd_reloaddirmngr): New. + (struct server_local_s): Add field STOPME. + (start_command_handler): Act on STOPME. + 2010-08-06 Werner Koch * dirmngr.c (JNLIB_NEED_AFLOCAL): Define macro. (main): Use SUN_LEN macro. (main) [W32]: Allow EEXIST in addition to EADDRINUSE. - (JNLIB_NEED_AFLOCAL): 2010-08-05 Werner Koch diff --git a/dirmngr/crlcache.c b/dirmngr/crlcache.c index e08741924..14bffe350 100644 --- a/dirmngr/crlcache.c +++ b/dirmngr/crlcache.c @@ -274,7 +274,7 @@ cleanup_cache_dir (int force) if (okay) { log_info (_("removing cache file `%s'\n"), cdbname); - if (unlink (cdbname)) + if (gnupg_remove (cdbname)) { log_error ("failed to remove `%s': %s\n", cdbname, strerror (errno)); @@ -934,7 +934,7 @@ update_dir (crl_cache_t cache) #ifdef HAVE_W32_SYSTEM /* No atomic mv on W32 systems. */ - unlink (fname); + gnupg_remove (fname); #endif if (rename (tmpfname, fname)) { @@ -2166,7 +2166,7 @@ crl_cache_insert (ctrl_t ctrl, const char *url, ksba_reader_t reader) if (opt.verbose) log_info (_("creating cache file `%s'\n"), newfname); #ifdef HAVE_W32_SYSTEM - unlink (newfname); + gnupg_remove (newfname); #endif if (rename (fname, newfname)) { diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index 7aafc48ce..771a58642 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -1578,6 +1578,21 @@ reread_configuration (void) } +/* A global function which allows us to trigger the reload stuff from + other places. */ +void +dirmngr_sighup_action (void) +{ + log_info (_("SIGHUP received - " + "re-reading configuration and flushing caches\n")); + reread_configuration (); + cert_cache_deinit (0); + crl_cache_deinit (); + cert_cache_init (); + crl_cache_init (); +} + + /* The signal handler. */ static void @@ -1587,13 +1602,7 @@ handle_signal (int signo) { #ifndef HAVE_W32_SYSTEM case SIGHUP: - log_info (_("SIGHUP received - " - "re-reading configuration and flushing caches\n")); - reread_configuration (); - cert_cache_deinit (0); - crl_cache_deinit (); - cert_cache_init (); - crl_cache_init (); + dirmngr_sighup_action (); break; case SIGUSR1: diff --git a/dirmngr/dirmngr.h b/dirmngr/dirmngr.h index 67f2122d9..01478a64f 100644 --- a/dirmngr/dirmngr.h +++ b/dirmngr/dirmngr.h @@ -169,6 +169,7 @@ struct server_control_s /*-- dirmngr.c --*/ void dirmngr_exit( int ); /* Wrapper for exit() */ void dirmngr_init_default_ctrl (ctrl_t ctrl); +void dirmngr_sighup_action (void); /*-- server.c --*/ ldap_server_t get_ldapservers_from_ctrl (ctrl_t ctrl); diff --git a/dirmngr/server.c b/dirmngr/server.c index 584cae743..1293dbe77 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -60,6 +60,10 @@ struct server_local_s /* Per-session LDAP serfver. */ ldap_server_t ldapservers; + + /* If this flag is set to true this dirmngr process will be + terminated after the end of this session. */ + int stopme; }; @@ -1218,7 +1222,7 @@ static const char hlp_cachecert[] = "\n" "Put a certificate into the internal cache. This command might be\n" "useful if a client knows in advance certificates required for a\n" - "test and wnats to make sure they get added to the internal cache.\n" + "test and wants to make sure they get added to the internal cache.\n" "It is also helpful for debugging. To get the actual certificate,\n" "this command immediately inquires it using\n" "\n" @@ -1376,6 +1380,75 @@ cmd_getinfo (assuan_context_t ctx, char *line) } + +static const char hlp_killdirmngr[] = + "KILLDIRMNGR\n" + "\n" + "This command allows a user - given sufficient permissions -\n" + "to kill this dirmngr process.\n"; +static gpg_error_t +cmd_killdirmngr (assuan_context_t ctx, char *line) +{ + ctrl_t ctrl = assuan_get_pointer (ctx); + + (void)line; + + if (opt.system_daemon) + { + if (opt.system_service) + return set_error (GPG_ERR_NOT_SUPPORTED, + "can't do that whilst running as system service"); +#ifndef HAVE_W32_SYSTEM + { + gpg_err_code_t ec; + assuan_peercred_t cred; + + ec = gpg_err_code (assuan_get_peercred (ctx, &cred)); + if (!ec && cred.uid) + ec = GPG_ERR_EPERM; /* Only root may terminate. */ + if (ec) + return set_error (ec, "no permission to kill this process"); + } +#endif + } + + ctrl->server_local->stopme = 1; + return gpg_error (GPG_ERR_EOF); +} + + +static const char hlp_reloaddirmngr[] = + "RELOADDIRMNGR\n" + "\n" + "This command is an alternative to SIGHUP\n" + "to reload the configuration."; +static gpg_error_t +cmd_reloaddirmngr (assuan_context_t ctx, char *line) +{ + (void)ctx; + (void)line; + + if (opt.system_daemon) + { +#ifndef HAVE_W32_SYSTEM + { + gpg_err_code_t ec; + assuan_peercred_t cred; + + ec = gpg_err_code (assuan_get_peercred (ctx, &cred)); + if (!ec && cred.uid) + ec = GPG_ERR_EPERM; /* Only root may terminate. */ + if (ec) + return set_error (ec, "no permission to reload this process"); + } +#endif + } + + dirmngr_sighup_action (); + return 0; +} + + /* Tell the assuan library about our commands. */ @@ -1397,6 +1470,8 @@ register_commands (assuan_context_t ctx) { "CACHECERT", cmd_cachecert, hlp_cachecert }, { "VALIDATE", cmd_validate, hlp_validate }, { "GETINFO", cmd_getinfo, hlp_getinfo }, + { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr }, + { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr }, { NULL, NULL } }; int i, j, rc; @@ -1552,6 +1627,9 @@ start_command_handler (assuan_fd_t fd) ctrl->server_local->assuan_ctx = NULL; assuan_release (ctx); + if (ctrl->server_local->stopme) + dirmngr_exit (0); + if (ctrl->refcount) log_error ("oops: connection control structure still referenced (%d)\n", ctrl->refcount);