diff options
author | Werner Koch <wk@gnupg.org> | 2007-10-02 18:30:58 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2007-10-02 18:30:58 +0200 |
commit | ed7d2d72c64ea23d65d014511a4f0cf74dc144d6 (patch) | |
tree | 70a32592c35e19ed28029bf85a627791b21b0c46 | |
parent | Use Assuan socket wrapper calls. (diff) | |
download | gnupg2-ed7d2d72c64ea23d65d014511a4f0cf74dc144d6.tar.xz gnupg2-ed7d2d72c64ea23d65d014511a4f0cf74dc144d6.zip |
Extended gpg-connect-agent.
New "GETINFO pid" command for scdaemon and gpg-agent.
-rw-r--r-- | agent/ChangeLog | 4 | ||||
-rw-r--r-- | agent/command.c | 8 | ||||
-rw-r--r-- | scd/ChangeLog | 4 | ||||
-rw-r--r-- | scd/command.c | 8 | ||||
-rw-r--r-- | tools/ChangeLog | 10 | ||||
-rw-r--r-- | tools/gpg-connect-agent.c | 439 | ||||
-rw-r--r-- | tools/no-libgcrypt.c | 6 |
7 files changed, 472 insertions, 7 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog index 7b46155fe..28ddb6688 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2007-10-02 Werner Koch <wk@g10code.com> + + * command.c (cmd_getinfo): Add "pid" subcommand. + 2007-10-01 Werner Koch <wk@g10code.com> * agent.h (struct server_control_s): Remove unused CONNECTION_FD. diff --git a/agent/command.c b/agent/command.c index b816fac3e..9be814880 100644 --- a/agent/command.c +++ b/agent/command.c @@ -1344,6 +1344,7 @@ cmd_reloadagent (assuan_context_t ctx, char *line) Supported values for WHAT are: version - Return the version of the program. + pid - Return the process id of the server. socket_name - Return the name of the socket. ssh_socket_name - Return the name of the ssh socket. @@ -1358,6 +1359,13 @@ cmd_getinfo (assuan_context_t ctx, char *line) const char *s = VERSION; rc = assuan_send_data (ctx, s, strlen (s)); } + else if (!strcmp (line, "pid")) + { + char numbuf[50]; + + snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ()); + rc = assuan_send_data (ctx, numbuf, strlen (numbuf)); + } else if (!strcmp (line, "socket_name")) { const char *s = get_agent_socket_name (); diff --git a/scd/ChangeLog b/scd/ChangeLog index 56aca1fb7..382961dbc 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2007-10-02 Werner Koch <wk@g10code.com> + + * command.c (cmd_getinfo): Add "pid" subcommand. + 2007-10-01 Werner Koch <wk@g10code.com> * scdaemon.c (create_server_socket): Use Assuan socket wrappers diff --git a/scd/command.c b/scd/command.c index e65262d06..361b13f51 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1452,6 +1452,7 @@ cmd_unlock (assuan_context_t ctx, char *line) Supported values of WHAT are: version - Return the version of the program. + pid - Return the process id of the server. socket_name - Return the name of the socket. @@ -1476,6 +1477,13 @@ cmd_getinfo (assuan_context_t ctx, char *line) const char *s = VERSION; rc = assuan_send_data (ctx, s, strlen (s)); } + else if (!strcmp (line, "pid")) + { + char numbuf[50]; + + snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ()); + rc = assuan_send_data (ctx, numbuf, strlen (numbuf)); + } else if (!strcmp (line, "socket_name")) { const char *s = scd_get_socket_name (); diff --git a/tools/ChangeLog b/tools/ChangeLog index 1b4bad67c..c8805ea88 100644 --- a/tools/ChangeLog +++ b/tools/ChangeLog @@ -1,3 +1,13 @@ +2007-10-02 Werner Koch <wk@g10code.com> + + * no-libgcrypt.c (gcry_malloc_secure): New. + + * gpg-connect-agent.c (set_var, set_int_var, get_var) + (substitute_line, show_variables, assign_variable) + (do_open, do_close, do_showopen): New. + (main): Add new commands /nosubst, /subst, /let, /showvar, /open, + /close and /showopen. + 2007-10-01 Werner Koch <wk@g10code.com> * gpg-connect-agent.c (do_sendfd): Use INT2FD for assuan_sendfd. diff --git a/tools/gpg-connect-agent.c b/tools/gpg-connect-agent.c index 2300b7f88..2546cbb4f 100644 --- a/tools/gpg-connect-agent.c +++ b/tools/gpg-connect-agent.c @@ -30,7 +30,7 @@ #include "../common/util.h" #include "../common/asshelp.h" #include "../common/sysutils.h" - +#include "../common/membuf.h" /* Constants to identify the commands and options. */ enum cmd_and_opt_values @@ -82,6 +82,7 @@ struct const char *raw_socket; /* Name of socket to connect in raw mode. */ int exec; /* Run the pgm given on the command line. */ unsigned int connect_flags; /* Flags used for connecting. */ + int enable_varsubst; /* Set if variable substitution is enabled. */ } opt; @@ -101,6 +102,30 @@ static definq_t definq_list; static definq_t *definq_list_tail = &definq_list; +/* Variable definitions and glovbal table. */ +struct variable_s +{ + struct variable_s *next; + char *value; /* Malloced value - always a string. */ + char name[1]; /* Name of the variable. */ +}; +typedef struct variable_s *variable_t; + +static variable_t variable_table; + +/* This is used to store the pid of the server. */ +static pid_t server_pid = (pid_t)(-1); + + +/* A list of open file descriptors. */ +static struct +{ + int inuse; +#ifdef HAVE_W32_SYSTEM + HANDLE handle; +#endif +} open_fd_table[256]; + /*-- local prototypes --*/ static int read_and_print_response (assuan_context_t ctx); @@ -139,6 +164,162 @@ my_strusage( int level ) return p; } + +static void +set_var (const char *name, const char *value) +{ + variable_t var; + + for (var = variable_table; var; var = var->next) + if (!strcmp (var->name, name)) + break; + if (!var) + { + var = xmalloc (sizeof *var + strlen (name)); + var->value = NULL; + strcpy (var->name, name); + var->next = variable_table; + variable_table = var; + } + xfree (var->value); + var->value = value? xstrdup (value) : NULL; +} + + +static void +set_int_var (const char *name, int value) +{ + char numbuf[35]; + + snprintf (numbuf, sizeof numbuf, "%d", value); + set_var (name, numbuf); +} + +/* Return the value of a variable. That value is valid until a + variable of the name is changed. Return NULL if not found. */ +static const char * +get_var (const char *name) +{ + variable_t var; + + for (var = variable_table; var; var = var->next) + if (!strcmp (var->name, name)) + break; + if (!var || !var->value) + return NULL; + return var->value; +} + + + +/* Substitute variables in LINE and return a new allocated buffer if + required. The function might modify LINE if the expanded version + fits into it. */ +static char * +substitute_line (char *buffer) +{ + char *line = buffer; + char *p, *pend; + const char *value; + size_t valuelen, n; + char *result = NULL; + + while (*line) + { + p = strchr (line, '$'); + if (!p) + return result; /* No more variables. */ + + if (p[1] == '$') /* Escaped dollar sign. */ + { + memmove (p, p+1, strlen (p+1)+1); + line = p + 1; + continue; + } + for (pend=p+1; *pend && !spacep (pend) && *pend != '$' ; pend++) + ; + if (*pend) + { + int save = *pend; + *pend = 0; + value = get_var (p+1); + *pend = save; + } + else + value = get_var (p+1); + if (!value) + value = ""; + valuelen = strlen (value); + if (valuelen <= pend - p) + { + memcpy (p, value, valuelen); + p += valuelen; + n = pend - p; + if (n) + memmove (p, p+n, strlen (p+n)+1); + line = p; + } + else + { + char *src = result? result : buffer; + char *dst; + + dst = xmalloc (strlen (src) + valuelen + 1); + n = p - src; + memcpy (dst, src, n); + memcpy (dst + n, value, valuelen); + n += valuelen; + strcpy (dst + n, pend); + line = dst + n; + free (result); + result = dst; + } + } + return result; +} + + + +static void +assign_variable (char *line) +{ + char *name, *p, *tmp; + + /* Get the name. */ + name = line; + for (p=name; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + while (spacep (p)) + p++; + + if (!*p) + set_var (name, NULL); /* Remove variable. */ + else + { + tmp = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmp) + { + set_var (name, tmp); + xfree (tmp); + } + else + set_var (name, p); + } +} + + +static void +show_variables (void) +{ + variable_t var; + + for (var = variable_table; var; var = var->next) + if (var->value) + printf ("%-20s %s\n", var->name, var->value); +} + /* Store an inquire response pattern. Note, that this function may change the content of LINE. We assume that leading white spaces @@ -246,7 +427,7 @@ do_sendfd (assuan_context_t ctx, char *line) rc = assuan_sendfd (ctx, INT2FD (fd) ); if (rc) - log_error ("sednig descriptor %d failed: %s\n", fd, gpg_strerror (rc)); + log_error ("sending descriptor %d failed: %s\n", fd, gpg_strerror (rc)); fclose (fp); } @@ -258,6 +439,200 @@ do_recvfd (assuan_context_t ctx, char *line) } +static void +do_open (char *line) +{ + FILE *fp; + char *varname, *name, *mode, *p; + int fd; + +#ifdef HAVE_W32_SYSTEM + if (server_pid == (pid_t)(-1)) + { + log_error ("the pid of the server is unknown\n"); + log_info ("use command \"/serverpid\" first\n"); + return; + } +#endif + + /* Get variable name. */ + varname = line; + for (p=varname; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + while (spacep (p)) + p++; + + /* Get file name. */ + name = p; + for (p=name; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + while (spacep (p)) + p++; + + /* Get mode. */ + mode = p; + if (!*mode) + mode = "r"; + else + { + for (p=mode; *p && !spacep (p); p++) + ; + if (*p) + *p++ = 0; + } + + /* Open and send. */ + fp = fopen (name, mode); + if (!fp) + { + log_error ("can't open `%s' in \"%s\" mode: %s\n", + name, mode, strerror (errno)); + return; + } + fd = fileno (fp); + if (fd >= 0 && fd < DIM (open_fd_table)) + { + open_fd_table[fd].inuse = 1; +#ifdef HAVE_W32_SYSTEM + { + HANDLE prochandle, handle, newhandle; + + handle = (void*)_get_osfhandle (fd); + + prochandle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, server_pid); + if (!prochandle) + { + log_error ("failed to open the server process\n"); + close (fd); + return; + } + + if (!DuplicateHandle (GetCurrentProcess(), handle, + prochandle, &newhandle, 0, + TRUE, DUPLICATE_SAME_ACCESS )) + { + log_error ("failed to duplicate the handle\n"); + close (fd); + CloseHandle (prochandle); + return; + } + CloseHandle (prochandle); + open_fd_table[fd].handle = newhandle; + } + if (opt.verbose) + log_info ("file `%s' opened in \"%s\" mode, fd=%d (libc=%d)\n", + name, mode, (int)open_fd_table[fd].handle, fd); + set_int_var (varname, (int)open_fd_table[fd].handle); +#else + if (opt.verbose) + log_info ("file `%s' opened in \"%s\" mode, fd=%d\n", + name, mode, fd); + set_int_var (varname, fd); +#endif + } + else + { + log_error ("can't put fd %d into table\n", fd); + close (fd); + } +} + + +static void +do_close (char *line) +{ + int fd = atoi (line); + +#ifdef HAVE_W32_SYSTEM + int i; + + for (i=0; i < DIM (open_fd_table); i++) + if ( open_fd_table[i].inuse && open_fd_table[i].handle == (void*)fd) + break; + if (i < DIM (open_fd_table)) + fd = i; + else + { + log_error ("given fd (system handle) has not been opened\n"); + return; + } +#endif + + if (fd < 0 || fd >= DIM (open_fd_table)) + { + log_error ("invalid fd\n"); + return; + } + + if (!open_fd_table[fd].inuse) + { + log_error ("given fd has not been opened\n"); + return; + } +#ifdef HAVE_W32_SYSTEM + CloseHandle (open_fd_table[fd].handle); /* Close duped handle. */ +#endif + close (fd); + open_fd_table[fd].inuse = 0; +} + + +static void +do_showopen (void) +{ + int i; + + for (i=0; i < DIM (open_fd_table); i++) + if (open_fd_table[i].inuse) + { +#ifdef HAVE_W32_SYSTEM + printf ("%-15d (libc=%d)\n", (int)open_fd_table[i].handle, i); +#else + printf ("%-15d\n", i); +#endif + } +} + + + +static int +getinfo_pin_cb (void *opaque, const void *buffer, size_t length) +{ + membuf_t *mb = opaque; + put_membuf (mb, buffer, length); + return 0; +} + +/* Get the pid of the server and store it locally. */ +static void +do_serverpid (assuan_context_t ctx) +{ + int rc; + membuf_t mb; + char *buffer; + + init_membuf (&mb, 100); + rc = assuan_transact (ctx, "GETINFO pid", getinfo_pin_cb, &mb, + NULL, NULL, NULL, NULL); + put_membuf (&mb, "", 1); + buffer = get_membuf (&mb, NULL); + if (rc || !buffer) + log_error ("command \"%s\" failed: %s\n", + "GETINFO pid", gpg_strerror (rc)); + else + { + server_pid = (pid_t)strtoul (buffer, NULL, 10); + if (opt.verbose) + log_info ("server's PID is %lu\n", (unsigned long)server_pid); + } + xfree (buffer); +} + + /* gpg-connect-agent's entry point. */ int main (int argc, char **argv) @@ -266,6 +641,7 @@ main (int argc, char **argv) int no_more_options = 0; assuan_context_t ctx; char *line, *p; + char *tmpline; size_t linesize; int rc; @@ -406,7 +782,15 @@ main (int argc, char **argv) *p++ = 0; while (spacep (p)) p++; - if (!strcmp (cmd, "definqfile")) + if (!strcmp (cmd, "let")) + { + assign_variable (p); + } + else if (!strcmp (cmd, "showvar")) + { + show_variables (); + } + else if (!strcmp (cmd, "definqfile")) { add_definq (p, 0); } @@ -424,7 +808,14 @@ main (int argc, char **argv) } else if (!strcmp (cmd, "echo")) { - puts (p); + tmpline = opt.enable_varsubst? substitute_line (p) : NULL; + if (tmpline) + { + puts (tmpline); + xfree (tmpline); + } + else + puts (p); } else if (!strcmp (cmd, "sendfd")) { @@ -436,6 +827,22 @@ main (int argc, char **argv) do_recvfd (ctx, p); continue; } + else if (!strcmp (cmd, "open")) + { + do_open (p); + } + else if (!strcmp (cmd, "close")) + { + do_close (p); + } + else if (!strcmp (cmd, "showopen")) + { + do_showopen (); + } + else if (!strcmp (cmd, "serverpid")) + { + do_serverpid (ctx); + } else if (!strcmp (cmd, "hex")) opt.hex = 1; else if (!strcmp (cmd, "nohex")) @@ -444,11 +851,17 @@ main (int argc, char **argv) opt.decode = 1; else if (!strcmp (cmd, "nodecode")) opt.decode = 0; + else if (!strcmp (cmd, "subst")) + opt.enable_varsubst = 1; + else if (!strcmp (cmd, "nosubst")) + opt.enable_varsubst = 0; else if (!strcmp (cmd, "help")) { puts ( "Available commands:\n" "/echo ARGS Echo ARGS.\n" +"/let NAME VALUE Set variable NAME to VALUE.\n" +"/showvar Show all variables.\n" "/definqfile NAME FILE\n" " Use content of FILE for inquiries with NAME.\n" " NAME may be \"*\" to match any inquiry.\n" @@ -458,9 +871,14 @@ main (int argc, char **argv) "/showdef Print all definitions.\n" "/cleardef Delete all definitions.\n" "/sendfd FILE MODE Open FILE and pass descriptor to server.\n" -"/recvfd Receive FD from server and print. \n" +"/recvfd Receive FD from server and print.\n" +"/open VAR FILE MODE Open FILE and assign the descrptor to VAR.\n" +"/close FD Close file with descriptor FD.\n" +"/showopen Show descriptors of all open files.\n" +"/serverpid Retrieve the pid of the server.\n" "/[no]hex Enable hex dumping of received data lines.\n" "/[no]decode Enable decoding of received data lines.\n" +"/[no]subst Enable varibale substitution.\n" "/help Print this help."); } else @@ -468,8 +886,15 @@ main (int argc, char **argv) continue; } - - rc = assuan_write_line (ctx, line); + + tmpline = opt.enable_varsubst? substitute_line (line) : NULL; + if (tmpline) + { + rc = assuan_write_line (ctx, tmpline); + xfree (tmpline); + } + else + rc = assuan_write_line (ctx, line); if (rc) { log_info (_("sending line failed: %s\n"), gpg_strerror (rc) ); diff --git a/tools/no-libgcrypt.c b/tools/no-libgcrypt.c index c9122e755..a21ccdb76 100644 --- a/tools/no-libgcrypt.c +++ b/tools/no-libgcrypt.c @@ -38,6 +38,12 @@ gcry_malloc (size_t n) } void * +gcry_malloc_secure (size_t n) +{ + return malloc (n); +} + +void * gcry_xmalloc (size_t n) { void *p = malloc (n); |