Pin::Pin() { gpg_error_t res; pid_t pid; int flags; const char *argv[2]; gpg_err_init(); res = assuan_new (&ctx); if(res) throw runtime_error(strprintf("pinentry initialisation: %s", gpg_strerror(res))); assuan_set_assuan_log_prefix("Pin: "); // needed esp. for ncurses lang = strprintf("OPTION lc-ctype=%s",getenv("LANG")); tty = strprintf("OPTION ttyname=%s",getenv("TTY")); flags = 0x0; argv[0] = "bitcoind"; // fake argv argv[1] = NULL; res = assuan_pipe_connect (ctx, SECURE_EXEC_PATH"/pinentry", argv, NULL, NULL, NULL, flags); if(res) throw runtime_error(strprintf("pinentry pipe forking: %s", gpg_strerror(res))); pid = assuan_get_pid(ctx); if(pid == ASSUAN_INVALID_PID) throw runtime_error(strprintf("pinentry not running: %s", gpg_strerror(res))); cmd(tty.c_str()); cmd(lang.c_str()); }
/* This function may be called to print infromation pertaining to the current state of this module to the log. */ void agent_query_dump_state (void) { log_info ("agent_query_dump_state: entry_lock="); dump_mutex_state (&entry_lock); log_printf ("\n"); log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%p\n", entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid); }
/* Close a popup window. */ void agent_popup_message_stop (ctrl_t ctrl) { int rc; pid_t pid; (void)ctrl; if (!popup_tid || !entry_ctx) { log_debug ("agent_popup_message_stop called with no active popup\n"); return; } pid = assuan_get_pid (entry_ctx); if (pid == (pid_t)(-1)) ; /* No pid available can't send a kill. */ else if (popup_finished) ; /* Already finished and ready for joining. */ #ifdef HAVE_W32_SYSTEM /* Older versions of assuan set PID to 0 on Windows to indicate an invalid value. */ else if (pid != (pid_t) INVALID_HANDLE_VALUE && pid != 0) { HANDLE process = (HANDLE) pid; /* Arbitrary error code. */ TerminateProcess (process, 1); } #else else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) { /* The daemon already died. No need to send a kill. However because we already waited for the process, we need to tell assuan that it should not wait again (done by unlock_pinentry). */ if (rc == pid) assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1); } else if (pid > 0) kill (pid, SIGINT); #endif /* Now wait for the thread to terminate. */ rc = npth_join (popup_tid, NULL); if (rc) log_debug ("agent_popup_message_stop: pth_join failed: %s\n", strerror (rc)); /* Thread IDs are opaque, but we try our best here by resetting it to the same content that a static global variable has. */ memset (&popup_tid, '\0', sizeof (popup_tid)); entry_owner = NULL; /* Now we can close the connection. */ unlock_pinentry (0); }
/* This function may be called to print infromation pertaining to the current state of this module to the log. */ void agent_scd_dump_state (void) { log_info ("agent_scd_dump_state: primary_scd_ctx=%p pid=%ld reusable=%d\n", primary_scd_ctx, (long)assuan_get_pid (primary_scd_ctx), primary_scd_ctx_reusable); if (socket_name) log_info ("agent_scd_dump_state: socket='%s'\n", socket_name); }
/* Client main. If true is returned, a disconnect has not been done. */ static int client (assuan_context_t ctx, const char *fname) { int rc; FILE *fp; int i; log_info ("client started. Servers's pid is %ld\n", (long)assuan_get_pid (ctx)); for (i=0; i < 6; i++) { fp = fopen (fname, "r"); if (!fp) { log_error ("failed to open `%s': %s\n", fname, strerror (errno)); return -1; } rc = assuan_sendfd (ctx, fileno (fp)); if (rc) { log_error ("assuan_sendfd failed: %s\n", gpg_strerror (rc)); return -1; } fclose (fp); rc = assuan_transact (ctx, "INPUT FD", NULL, NULL, NULL, NULL, NULL, NULL); if (rc) { log_error ("sending INPUT FD failed: %s\n", gpg_strerror (rc)); return -1; } rc = assuan_transact (ctx, "ECHO", NULL, NULL, NULL, NULL, NULL, NULL); if (rc) { log_error ("sending ECHO failed: %s\n", gpg_strerror (rc)); return -1; } } /* Give us some time to check with lsof that all descriptors are closed. */ /* sleep (10); */ assuan_release (ctx); return 0; }
static void server (void) { int rc; assuan_context_t ctx; log_info ("server started\n"); rc = assuan_new (&ctx); if (rc) log_fatal ("assuan_new failed: %s\n", gpg_strerror (rc)); rc = assuan_init_pipe_server (ctx, NULL); if (rc) log_fatal ("assuan_init_pipe_server failed: %s\n", gpg_strerror (rc)); rc = register_commands (ctx); if (rc) log_fatal ("register_commands failed: %s\n", gpg_strerror(rc)); assuan_set_log_stream (ctx, stderr); for (;;) { rc = assuan_accept (ctx); if (rc) { if (rc != -1) log_error ("assuan_accept failed: %s\n", gpg_strerror (rc)); break; } log_info ("client connected. Client's pid is %ld\n", (long)assuan_get_pid (ctx)); rc = assuan_process (ctx); if (rc) log_error ("assuan_process failed: %s\n", gpg_strerror (rc)); } assuan_release (ctx); }
/* This function may be called to print infromation pertaining to the current state of this module to the log. */ void agent_query_dump_state (void) { log_info ("agent_query_dump_state: entry_ctx=%p pid=%ld popup_tid=%lx\n", entry_ctx, (long)assuan_get_pid (entry_ctx), popup_tid); }
/* Check whether the Scdaemon is still alive and clean it up if not. */ void agent_scd_check_aliveness (void) { pid_t pid; #ifdef HAVE_W32_SYSTEM DWORD rc; #else int rc; #endif struct timespec abstime; int err; if (!primary_scd_ctx) return; /* No scdaemon running. */ /* This is not a critical function so we use a short timeout while acquiring the lock. */ npth_clock_gettime (&abstime); abstime.tv_sec += 1; err = npth_mutex_timedlock (&start_scd_lock, &abstime); if (err) { if (err == ETIMEDOUT) { if (opt.verbose > 1) log_info ("failed to acquire the start_scd lock while" " doing an aliveness check: %s\n", strerror (err)); } else log_error ("failed to acquire the start_scd lock while" " doing an aliveness check: %s\n", strerror (err)); return; } if (primary_scd_ctx) { pid = assuan_get_pid (primary_scd_ctx); #ifdef HAVE_W32_SYSTEM /* If we have a PID we disconnect if either GetExitProcessCode fails or if ir returns the exit code of the scdaemon. 259 is the error code for STILL_ALIVE. */ if (pid != (pid_t)(void*)(-1) && pid && (!GetExitCodeProcess ((HANDLE)pid, &rc) || rc != 259)) #else if (pid != (pid_t)(-1) && pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) ) #endif { /* Okay, scdaemon died. Disconnect the primary connection now but take care that it won't do another wait. Also cleanup all other connections and release their resources. The next use will start a new daemon then. Due to the use of the START_SCD_LOCAL we are sure that none of these context are actually in use. */ struct scd_local_s *sl; assuan_set_flag (primary_scd_ctx, ASSUAN_NO_WAITPID, 1); assuan_release (primary_scd_ctx); for (sl=scd_local_list; sl; sl = sl->next_local) { if (sl->ctx) { if (sl->ctx != primary_scd_ctx) assuan_release (sl->ctx); sl->ctx = NULL; } } primary_scd_ctx = NULL; primary_scd_ctx_reusable = 0; xfree (socket_name); socket_name = NULL; } } err = npth_mutex_unlock (&start_scd_lock); if (err) log_error ("failed to release the start_scd lock while" " doing the aliveness check: %s\n", strerror (err)); }