diff options
author | Werner Koch <wk@gnupg.org> | 2007-06-21 20:44:48 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2007-06-21 20:44:48 +0200 |
commit | 0b66f30d66fadbfd1a949edbe765043b06c5931b (patch) | |
tree | e2e33a51151de2deac0d4e43cd7bc38429fe2965 /common | |
parent | [w32] gpg-agent is now started automagically by gpgsm. (diff) | |
download | gnupg2-0b66f30d66fadbfd1a949edbe765043b06c5931b.tar.xz gnupg2-0b66f30d66fadbfd1a949edbe765043b06c5931b.zip |
Implemented the --gen-key command as we can't use the gpgsm-gencert.sh under Windows.
Diffstat (limited to 'common')
-rw-r--r-- | common/ChangeLog | 14 | ||||
-rw-r--r-- | common/asshelp.c | 184 | ||||
-rw-r--r-- | common/asshelp.h | 16 | ||||
-rw-r--r-- | common/exechelp.c | 2 | ||||
-rw-r--r-- | common/membuf.c | 9 | ||||
-rw-r--r-- | common/membuf.h | 3 | ||||
-rw-r--r-- | common/ttyio.c | 23 | ||||
-rw-r--r-- | common/ttyio.h | 3 | ||||
-rw-r--r-- | common/util.h | 6 |
9 files changed, 255 insertions, 5 deletions
diff --git a/common/ChangeLog b/common/ChangeLog index 3f8fa41c4..e80e70359 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,17 @@ +2007-06-21 Werner Koch <wk@g10code.com> + + * membuf.h (get_membuf_len): New. + + * membuf.c (init_membuf_secure): Really allocate in secure memory. + (put_membuf_str): New. + + * ttyio.c (tty_getf): New. + + * util.h (ctrl_t): Declare it here. + + * asshelp.c (start_new_gpg_agent): New. Based on code from + ../sm/call-agent.c + 2007-06-20 Werner Koch <wk@g10code.com> * sysutils.c (gnupg_sleep): New. diff --git a/common/asshelp.c b/common/asshelp.c index 54d7224d8..024128042 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -29,8 +29,11 @@ #include <locale.h> #endif +#include "i18n.h" #include "util.h" - +#include "exechelp.h" +#include "sysutils.h" +#include "errors.h" /* FIXME: This one conatisn only status code - rename it*/ #include "asshelp.h" @@ -164,3 +167,182 @@ send_pinentry_environment (assuan_context_t ctx, return 0; } + +/* Try to connect to the agent via socket or fork it off and work by + pipes. Handle the server's initial greeting. Returns a new assuan + context at R_CTX or an error code. */ +gpg_error_t +start_new_gpg_agent (assuan_context_t *r_ctx, + gpg_err_source_t errsource, + const char *homedir, + const char *agent_program, + const char *opt_display, + const char *opt_ttyname, + const char *opt_ttytype, + const char *opt_lc_ctype, + const char *opt_lc_messages, + int verbose, int debug, + gpg_error_t (*status_cb)(ctrl_t, int, ...), + ctrl_t status_cb_arg) +{ + /* If we ever failed to connect via a socket we will force the use + of the pipe based server for the lifetime of the process. */ + static int force_pipe_server = 0; + + gpg_error_t rc = 0; + char *infostr, *p; + assuan_context_t ctx; + + *r_ctx = NULL; + + restart: + infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO"); + if (!infostr || !*infostr) + { + char *sockname; + + /* First check whether we can connect at the standard + socket. */ + sockname = make_filename (homedir, "S.gpg-agent", NULL); + rc = assuan_socket_connect (&ctx, sockname, 0); + + if (rc) + { + /* With no success start a new server. */ + if (verbose) + log_info (_("no running gpg-agent - starting one\n")); + + if (status_cb) + status_cb (status_cb_arg, STATUS_PROGRESS, + "starting_agent ? 0 0", NULL); + + if (fflush (NULL)) + { + gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); + log_error ("error flushing pending output: %s\n", + strerror (errno)); + xfree (sockname); + return tmperr; + } + + if (!agent_program || !*agent_program) + agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT); + +#ifdef HAVE_W32_SYSTEM + { + /* Under Windows we start the server in daemon mode. This + is because the default is to use the standard socket + and thus there is no need for the GPG_AGENT_INFO + envvar. This is possible as we don't have a real unix + domain socket but use a plain file and thus there is no + need to care about non-local file systems. */ + const char *argv[3]; + + argv[0] = "--daemon"; + argv[1] = "--use-standard-socket"; + argv[2] = NULL; + + rc = gnupg_spawn_process_detached (agent_program, argv, NULL); + if (rc) + log_debug ("failed to start agent `%s': %s\n", + agent_program, gpg_strerror (rc)); + else + { + /* Give the agent some time to prepare itself. */ + gnupg_sleep (3); + /* Now try again to connect the agent. */ + rc = assuan_socket_connect (&ctx, sockname, 0); + } + } +#else /*!HAVE_W32_SYSTEM*/ + { + const char *pgmname; + const char *argv[3]; + int no_close_list[3]; + int i; + + if ( !(pgmname = strrchr (agent_program, '/'))) + pgmname = agent_program; + else + pgmname++; + + argv[0] = pgmname; + argv[1] = "--server"; + argv[2] = NULL; + + i=0; + if (log_get_fd () != -1) + no_close_list[i++] = log_get_fd (); + no_close_list[i++] = fileno (stderr); + no_close_list[i] = -1; + + /* Connect to the agent and perform initial handshaking. */ + rc = assuan_pipe_connect (&ctx, agent_program, argv, + no_close_list); + } +#endif /*!HAVE_W32_SYSTEM*/ + } + xfree (sockname); + } + else + { + int prot; + int pid; + + infostr = xstrdup (infostr); + if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr) + { + log_error (_("malformed GPG_AGENT_INFO environment variable\n")); + xfree (infostr); + force_pipe_server = 1; + goto restart; + } + *p++ = 0; + pid = atoi (p); + while (*p && *p != PATHSEP_C) + p++; + prot = *p? atoi (p+1) : 0; + if (prot != 1) + { + log_error (_("gpg-agent protocol version %d is not supported\n"), + prot); + xfree (infostr); + force_pipe_server = 1; + goto restart; + } + + rc = assuan_socket_connect (&ctx, infostr, pid); + xfree (infostr); + if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED) + { + log_info (_("can't connect to the agent - trying fall back\n")); + force_pipe_server = 1; + goto restart; + } + } + + if (rc) + { + log_error ("can't connect to the agent: %s\n", gpg_strerror (rc)); + return gpg_error (GPG_ERR_NO_AGENT); + } + + if (debug) + log_debug ("connection to agent established\n"); + + rc = assuan_transact (ctx, "RESET", + NULL, NULL, NULL, NULL, NULL, NULL); + if (!rc) + rc = send_pinentry_environment (ctx, errsource, + opt_display, opt_ttyname, opt_ttytype, + opt_lc_ctype, opt_lc_messages); + if (rc) + { + assuan_disconnect (ctx); + return rc; + } + + *r_ctx = ctx; + return 0; +} + diff --git a/common/asshelp.h b/common/asshelp.h index 9f4b5806b..adf81f9b7 100644 --- a/common/asshelp.h +++ b/common/asshelp.h @@ -34,5 +34,21 @@ send_pinentry_environment (assuan_context_t ctx, const char *opt_lc_ctype, const char *opt_lc_messages); +/* This fucntion is used by the call-agent.c modules to fire up a new + agent. What a parameter list ;-). */ +gpg_error_t +start_new_gpg_agent (assuan_context_t *r_ctx, + gpg_err_source_t errsource, + const char *homedir, + const char *agent_program, + const char *opt_display, + const char *opt_ttyname, + const char *opt_ttytype, + const char *opt_lc_ctype, + const char *opt_lc_messages, + int verbose, int debug, + gpg_error_t (*status_cb)(ctrl_t, int, ...), + ctrl_t status_cb_arg); + #endif /*GNUPG_COMMON_ASSHELP_H*/ diff --git a/common/exechelp.c b/common/exechelp.c index d0be84047..c488e291a 100644 --- a/common/exechelp.c +++ b/common/exechelp.c @@ -593,7 +593,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], cmdline, /* Command line arguments. */ &sec_attr, /* Process security attributes. */ &sec_attr, /* Thread security attributes. */ - FALSE, /* Inherit handles. */ + FALSE, /* Inherit handles. */ cr_flags, /* Creation flags. */ NULL, /* Environment. */ NULL, /* Use current drive/directory. */ diff --git a/common/membuf.c b/common/membuf.c index 51014592b..eb436c466 100644 --- a/common/membuf.c +++ b/common/membuf.c @@ -52,7 +52,7 @@ init_membuf_secure (membuf_t *mb, int initiallen) mb->len = 0; mb->size = initiallen; mb->out_of_core = 0; - mb->buf = xtrymalloc (initiallen); + mb->buf = xtrymalloc_secure (initiallen); if (!mb->buf) mb->out_of_core = errno; } @@ -87,6 +87,13 @@ put_membuf (membuf_t *mb, const void *buf, size_t len) } +void +put_membuf_str (membuf_t *mb, const char *string) +{ + put_membuf (mb, string, strlen (string)); +} + + void * get_membuf (membuf_t *mb, size_t *len) { diff --git a/common/membuf.h b/common/membuf.h index f9c08a400..906ae156c 100644 --- a/common/membuf.h +++ b/common/membuf.h @@ -34,10 +34,13 @@ struct private_membuf_s typedef struct private_membuf_s membuf_t; +/* Return the current length of the membuf. */ +#define get_membuf_len(a) ((a)->len) void init_membuf (membuf_t *mb, int initiallen); void init_membuf_secure (membuf_t *mb, int initiallen); void put_membuf (membuf_t *mb, const void *buf, size_t len); +void put_membuf_str (membuf_t *mb, const char *string); void *get_membuf (membuf_t *mb, size_t *len); diff --git a/common/ttyio.c b/common/ttyio.c index 831ad9048..98a4614fe 100644 --- a/common/ttyio.c +++ b/common/ttyio.c @@ -50,6 +50,7 @@ #include "util.h" #include "ttyio.h" +#include "estream-printf.h" #include "common-defs.h" #define CONTROL_D ('D' - 'A' + 1) @@ -243,7 +244,7 @@ tty_printf( const char *fmt, ... ) } -/* Same as tty_printf but if FP is not NULL, behave like a regualr +/* Same as tty_printf but if FP is not NULL, behave like a regular fprintf. */ void tty_fprintf (FILE *fp, const char *fmt, ... ) @@ -563,6 +564,26 @@ tty_get( const char *prompt ) return do_get ( prompt, 0 ); } +/* Variable argument version of tty_get. The prompt is is actually a + format string with arguments. */ +char * +tty_getf (const char *promptfmt, ... ) +{ + va_list arg_ptr; + char *prompt; + char *answer; + + va_start (arg_ptr, promptfmt); + if (estream_vasprintf (&prompt, promptfmt, arg_ptr) < 0) + log_fatal ("estream_vasprintf failed: %s\n", strerror (errno)); + va_end (arg_ptr); + answer = tty_get (prompt); + xfree (prompt); + return answer; +} + + + char * tty_get_hidden( const char *prompt ) { diff --git a/common/ttyio.h b/common/ttyio.h index d93906eab..eed6b0910 100644 --- a/common/ttyio.h +++ b/common/ttyio.h @@ -31,9 +31,12 @@ void tty_printf (const char *fmt, ... ) __attribute__ ((format (printf,1,2))); void tty_fprintf (FILE *fp, const char *fmt, ... ) __attribute__ ((format (printf,2,3))); +char *tty_getf (const char *promptfmt, ... ) + __attribute__ ((format (printf,1,2))); #else void tty_printf (const char *fmt, ... ); void tty_fprintf (FILE *fp, const char *fmt, ... ); +char *tty_getf (const char *promptfmt, ... ); #endif void tty_print_string (const unsigned char *p, size_t n); void tty_print_utf8_string (const unsigned char *p, size_t n); diff --git a/common/util.h b/common/util.h index 42df1274f..39858216f 100644 --- a/common/util.h +++ b/common/util.h @@ -46,7 +46,6 @@ #define asprintf estream_asprintf #define vasprintf estream_vasprintf - /* GCC attributes. */ #if __GNUC__ >= 4 # define GNUPG_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a))) @@ -246,5 +245,10 @@ ttyname (int fd) #define xtoi_4(p) ((xtoi_2(p) * 256) + xtoi_2((p)+2)) +/*-- Forward declaration of the commonly used server control structure. */ +/* (We need it here as it is used by some callback prototypes.) */ +struct server_control_s; +typedef struct server_control_s *ctrl_t; + #endif /*GNUPG_COMMON_UTIL_H*/ |