summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2007-06-21 20:44:48 +0200
committerWerner Koch <wk@gnupg.org>2007-06-21 20:44:48 +0200
commit0b66f30d66fadbfd1a949edbe765043b06c5931b (patch)
treee2e33a51151de2deac0d4e43cd7bc38429fe2965 /common
parent[w32] gpg-agent is now started automagically by gpgsm. (diff)
downloadgnupg2-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/ChangeLog14
-rw-r--r--common/asshelp.c184
-rw-r--r--common/asshelp.h16
-rw-r--r--common/exechelp.c2
-rw-r--r--common/membuf.c9
-rw-r--r--common/membuf.h3
-rw-r--r--common/ttyio.c23
-rw-r--r--common/ttyio.h3
-rw-r--r--common/util.h6
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*/