mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-17 14:07:03 +01:00
Implemented the --gen-key command as we can't use the gpgsm-gencert.sh under Windows.
This commit is contained in:
parent
09cc0ee7be
commit
0b66f30d66
3
NEWS
3
NEWS
@ -5,6 +5,9 @@ Noteworthy changes in version 2.0.5
|
|||||||
|
|
||||||
* Changes required for a port to Windows.
|
* Changes required for a port to Windows.
|
||||||
|
|
||||||
|
* The command --gen-key may now be used instead of the
|
||||||
|
gpgsm-gencert.sh script.
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.0.4 (2007-05-09)
|
Noteworthy changes in version 2.0.4 (2007-05-09)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
2
TODO
2
TODO
@ -95,7 +95,7 @@
|
|||||||
|
|
||||||
* When requiring libksba 1.0.1
|
* When requiring libksba 1.0.1
|
||||||
** Remove the extra GPG_ERR_NO_VALUE tests
|
** Remove the extra GPG_ERR_NO_VALUE tests
|
||||||
They have need added on 2006-10-18 to fix a libksba problem.
|
They have been added on 2006-10-18 to fix a libksba problem.
|
||||||
|
|
||||||
* When switching to libgcrypt 1.3
|
* When switching to libgcrypt 1.3
|
||||||
** scd#encode_md_for_card, g10#encode_md_value, sm@do_encode_md
|
** scd#encode_md_for_card, g10#encode_md_value, sm@do_encode_md
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
2007-06-21 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* agent.h (ctrl_t): Remove. It is now declared in ../common/util.h.
|
||||||
|
|
||||||
|
* gpg-agent.c (check_for_running_agent): New arg SILENT. Changed
|
||||||
|
all callers.
|
||||||
|
(create_server_socket): If the standard socket is in use check
|
||||||
|
whether a agent is running and avoid starting another one.
|
||||||
|
|
||||||
2007-06-18 Marcus Brinkmann <marcus@g10code.de>
|
2007-06-18 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* gpg-agent.c (main): Percent escape pathname in --gpgconf-list
|
* gpg-agent.c (main): Percent escape pathname in --gpgconf-list
|
||||||
|
@ -150,8 +150,6 @@ struct server_control_s
|
|||||||
PKSIGN command to the scdaemon. */
|
PKSIGN command to the scdaemon. */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct server_control_s *ctrl_t;
|
|
||||||
|
|
||||||
|
|
||||||
struct pin_entry_info_s
|
struct pin_entry_info_s
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* gpg-agent.c - The GnuPG Agent
|
/* gpg-agent.c - The GnuPG Agent
|
||||||
* Copyright (C) 2000, 2001, 2002, 2003, 2004,
|
* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005,
|
||||||
* 2005 Free Software Foundation, Inc.
|
* 2006, 2007 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
@ -93,7 +93,6 @@ enum cmd_and_opt_values
|
|||||||
oMinPassphraseLen,
|
oMinPassphraseLen,
|
||||||
oUseStandardSocket,
|
oUseStandardSocket,
|
||||||
oNoUseStandardSocket,
|
oNoUseStandardSocket,
|
||||||
oNoReuseStandardSocket,
|
|
||||||
|
|
||||||
oIgnoreCacheForSigning,
|
oIgnoreCacheForSigning,
|
||||||
oAllowMarkTrusted,
|
oAllowMarkTrusted,
|
||||||
@ -131,8 +130,6 @@ static ARGPARSE_OPTS opts[] = {
|
|||||||
{ oUseStandardSocket, "use-standard-socket", 0,
|
{ oUseStandardSocket, "use-standard-socket", 0,
|
||||||
N_("use a standard location for the socket")},
|
N_("use a standard location for the socket")},
|
||||||
{ oNoUseStandardSocket, "no-use-standard-socket", 0, "@"},
|
{ oNoUseStandardSocket, "no-use-standard-socket", 0, "@"},
|
||||||
{ oNoReuseStandardSocket, "no-reuse-standard-socket", 0, "@"},
|
|
||||||
|
|
||||||
{ oPinentryProgram, "pinentry-program", 2 ,
|
{ oPinentryProgram, "pinentry-program", 2 ,
|
||||||
N_("|PGM|use PGM as the PIN-Entry program") },
|
N_("|PGM|use PGM as the PIN-Entry program") },
|
||||||
{ oPinentryTouchFile, "pinentry-touch-file", 2 , "@" },
|
{ oPinentryTouchFile, "pinentry-touch-file", 2 , "@" },
|
||||||
@ -188,10 +185,6 @@ static char *socket_name;
|
|||||||
/* Name of the communication socket used for ssh-agent-emulation. */
|
/* Name of the communication socket used for ssh-agent-emulation. */
|
||||||
static char *socket_name_ssh;
|
static char *socket_name_ssh;
|
||||||
|
|
||||||
/* If set to true and a standard socket is requested, we won't try to
|
|
||||||
bind to a socket which is already in use. */
|
|
||||||
static int no_reuse_standard_socket;
|
|
||||||
|
|
||||||
/* Default values for options passed to the pinentry. */
|
/* Default values for options passed to the pinentry. */
|
||||||
static char *default_display;
|
static char *default_display;
|
||||||
static char *default_ttyname;
|
static char *default_ttyname;
|
||||||
@ -228,7 +221,7 @@ static void agent_init_default_ctrl (ctrl_t ctrl);
|
|||||||
static void agent_deinit_default_ctrl (ctrl_t ctrl);
|
static void agent_deinit_default_ctrl (ctrl_t ctrl);
|
||||||
|
|
||||||
static void handle_connections (int listen_fd, int listen_fd_ssh);
|
static void handle_connections (int listen_fd, int listen_fd_ssh);
|
||||||
static int check_for_running_agent (int);
|
static int check_for_running_agent (int silent, int mode);
|
||||||
|
|
||||||
/* Pth wrapper function definitions. */
|
/* Pth wrapper function definitions. */
|
||||||
GCRY_THREAD_OPTION_PTH_IMPL;
|
GCRY_THREAD_OPTION_PTH_IMPL;
|
||||||
@ -627,7 +620,6 @@ main (int argc, char **argv )
|
|||||||
|
|
||||||
case oUseStandardSocket: standard_socket = 1; break;
|
case oUseStandardSocket: standard_socket = 1; break;
|
||||||
case oNoUseStandardSocket: standard_socket = 0; break;
|
case oNoUseStandardSocket: standard_socket = 0; break;
|
||||||
case oNoReuseStandardSocket: no_reuse_standard_socket = 1; break;
|
|
||||||
|
|
||||||
case oKeepTTY: opt.keep_tty = 1; break;
|
case oKeepTTY: opt.keep_tty = 1; break;
|
||||||
case oKeepDISPLAY: opt.keep_display = 1; break;
|
case oKeepDISPLAY: opt.keep_display = 1; break;
|
||||||
@ -765,7 +757,7 @@ main (int argc, char **argv )
|
|||||||
if (!pipe_server && !is_daemon)
|
if (!pipe_server && !is_daemon)
|
||||||
{
|
{
|
||||||
log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX);
|
log_set_prefix (NULL, JNLIB_LOG_WITH_PREFIX);
|
||||||
check_for_running_agent (0);
|
check_for_running_agent (0, 0);
|
||||||
agent_exit (0);
|
agent_exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1264,17 +1256,32 @@ create_server_socket (int is_standard_name, char *name)
|
|||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
|
rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
|
||||||
if (is_standard_name && rc == -1 && errno == WSAEADDRINUSE
|
if (is_standard_name && rc == -1 && errno == WSAEADDRINUSE)
|
||||||
&& !no_reuse_standard_socket)
|
|
||||||
{
|
{
|
||||||
|
if (!check_for_running_agent (1, 1))
|
||||||
|
{
|
||||||
|
log_error (_("a gpg-agent is already running - "
|
||||||
|
"not starting a new one\n"));
|
||||||
|
*name = 0; /* Inhibit removal of the socket by cleanup(). */
|
||||||
|
close (fd);
|
||||||
|
agent_exit (2);
|
||||||
|
}
|
||||||
|
|
||||||
remove (name);
|
remove (name);
|
||||||
rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
|
rc = _w32_sock_bind (fd, (struct sockaddr*) serv_addr, len);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
rc = bind (fd, (struct sockaddr*) serv_addr, len);
|
rc = bind (fd, (struct sockaddr*) serv_addr, len);
|
||||||
if (is_standard_name && rc == -1 && errno == EADDRINUSE
|
if (is_standard_name && rc == -1 && errno == EADDRINUSE)
|
||||||
&& !no_reuse_standard_socket)
|
|
||||||
{
|
{
|
||||||
|
if (!check_for_running_agent (1, 1))
|
||||||
|
{
|
||||||
|
log_error (_("a gpg-agent is already running - "
|
||||||
|
"not starting a new one\n"));
|
||||||
|
*name = 0; /* Inhibit removal of the socket by cleanup(). */
|
||||||
|
close (fd);
|
||||||
|
agent_exit (2);
|
||||||
|
}
|
||||||
remove (name);
|
remove (name);
|
||||||
rc = bind (fd, (struct sockaddr*) serv_addr, len);
|
rc = bind (fd, (struct sockaddr*) serv_addr, len);
|
||||||
}
|
}
|
||||||
@ -1288,7 +1295,7 @@ create_server_socket (int is_standard_name, char *name)
|
|||||||
gpg_strerror (gpg_error_from_errno (errno)));
|
gpg_strerror (gpg_error_from_errno (errno)));
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
if (is_standard_name && no_reuse_standard_socket)
|
if (is_standard_name)
|
||||||
*name = 0; /* Inhibit removal of the socket by cleanup(). */
|
*name = 0; /* Inhibit removal of the socket by cleanup(). */
|
||||||
agent_exit (2);
|
agent_exit (2);
|
||||||
}
|
}
|
||||||
@ -1725,9 +1732,10 @@ handle_connections (int listen_fd, int listen_fd_ssh)
|
|||||||
|
|
||||||
|
|
||||||
/* Figure out whether an agent is available and running. Prints an
|
/* Figure out whether an agent is available and running. Prints an
|
||||||
error if not. Usually started with MODE 0. */
|
error if not. If SILENT is true, no mesdsages are printed. Usually
|
||||||
|
started with MODE 0. Returns 0 if the agent is running. */
|
||||||
static int
|
static int
|
||||||
check_for_running_agent (int mode)
|
check_for_running_agent (int silent, int mode)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char *infostr, *p;
|
char *infostr, *p;
|
||||||
@ -1739,8 +1747,9 @@ check_for_running_agent (int mode)
|
|||||||
infostr = getenv ("GPG_AGENT_INFO");
|
infostr = getenv ("GPG_AGENT_INFO");
|
||||||
if (!infostr || !*infostr)
|
if (!infostr || !*infostr)
|
||||||
{
|
{
|
||||||
if (!check_for_running_agent (1))
|
if (!check_for_running_agent (silent, 1))
|
||||||
return 0; /* Okay, its running on the standard socket. */
|
return 0; /* Okay, its running on the standard socket. */
|
||||||
|
if (!silent)
|
||||||
log_error (_("no gpg-agent running in this session\n"));
|
log_error (_("no gpg-agent running in this session\n"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1749,8 +1758,9 @@ check_for_running_agent (int mode)
|
|||||||
if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
|
if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
|
||||||
{
|
{
|
||||||
xfree (infostr);
|
xfree (infostr);
|
||||||
if (!check_for_running_agent (1))
|
if (!check_for_running_agent (silent, 1))
|
||||||
return 0; /* Okay, its running on the standard socket. */
|
return 0; /* Okay, its running on the standard socket. */
|
||||||
|
if (!silent)
|
||||||
log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
|
log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1763,9 +1773,10 @@ check_for_running_agent (int mode)
|
|||||||
if (prot != 1)
|
if (prot != 1)
|
||||||
{
|
{
|
||||||
xfree (infostr);
|
xfree (infostr);
|
||||||
|
if (!silent)
|
||||||
log_error (_("gpg-agent protocol version %d is not supported\n"),
|
log_error (_("gpg-agent protocol version %d is not supported\n"),
|
||||||
prot);
|
prot);
|
||||||
if (!check_for_running_agent (1))
|
if (!check_for_running_agent (silent, 1))
|
||||||
return 0; /* Okay, its running on the standard socket. */
|
return 0; /* Okay, its running on the standard socket. */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1781,15 +1792,15 @@ check_for_running_agent (int mode)
|
|||||||
xfree (infostr);
|
xfree (infostr);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
if (!mode && !check_for_running_agent (1))
|
if (!mode && !check_for_running_agent (silent, 1))
|
||||||
return 0; /* Okay, its running on the standard socket. */
|
return 0; /* Okay, its running on the standard socket. */
|
||||||
|
|
||||||
if (!mode)
|
if (!mode && !silent)
|
||||||
log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
|
log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opt.quiet)
|
if (!opt.quiet && !silent)
|
||||||
log_info ("gpg-agent running and available\n");
|
log_info ("gpg-agent running and available\n");
|
||||||
|
|
||||||
assuan_disconnect (ctx);
|
assuan_disconnect (ctx);
|
||||||
|
@ -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>
|
2007-06-20 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* sysutils.c (gnupg_sleep): New.
|
* sysutils.c (gnupg_sleep): New.
|
||||||
|
184
common/asshelp.c
184
common/asshelp.c
@ -29,8 +29,11 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
#include "util.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"
|
#include "asshelp.h"
|
||||||
|
|
||||||
|
|
||||||
@ -164,3 +167,182 @@ send_pinentry_environment (assuan_context_t ctx,
|
|||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -34,5 +34,21 @@ send_pinentry_environment (assuan_context_t ctx,
|
|||||||
const char *opt_lc_ctype,
|
const char *opt_lc_ctype,
|
||||||
const char *opt_lc_messages);
|
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*/
|
#endif /*GNUPG_COMMON_ASSHELP_H*/
|
||||||
|
@ -52,7 +52,7 @@ init_membuf_secure (membuf_t *mb, int initiallen)
|
|||||||
mb->len = 0;
|
mb->len = 0;
|
||||||
mb->size = initiallen;
|
mb->size = initiallen;
|
||||||
mb->out_of_core = 0;
|
mb->out_of_core = 0;
|
||||||
mb->buf = xtrymalloc (initiallen);
|
mb->buf = xtrymalloc_secure (initiallen);
|
||||||
if (!mb->buf)
|
if (!mb->buf)
|
||||||
mb->out_of_core = errno;
|
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 *
|
void *
|
||||||
get_membuf (membuf_t *mb, size_t *len)
|
get_membuf (membuf_t *mb, size_t *len)
|
||||||
{
|
{
|
||||||
|
@ -34,10 +34,13 @@ struct private_membuf_s
|
|||||||
|
|
||||||
typedef struct private_membuf_s membuf_t;
|
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 (membuf_t *mb, int initiallen);
|
||||||
void init_membuf_secure (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 (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);
|
void *get_membuf (membuf_t *mb, size_t *len);
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "ttyio.h"
|
#include "ttyio.h"
|
||||||
|
#include "estream-printf.h"
|
||||||
#include "common-defs.h"
|
#include "common-defs.h"
|
||||||
|
|
||||||
#define CONTROL_D ('D' - 'A' + 1)
|
#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. */
|
fprintf. */
|
||||||
void
|
void
|
||||||
tty_fprintf (FILE *fp, const char *fmt, ... )
|
tty_fprintf (FILE *fp, const char *fmt, ... )
|
||||||
@ -563,6 +564,26 @@ tty_get( const char *prompt )
|
|||||||
return do_get ( prompt, 0 );
|
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 *
|
char *
|
||||||
tty_get_hidden( const char *prompt )
|
tty_get_hidden( const char *prompt )
|
||||||
{
|
{
|
||||||
|
@ -31,9 +31,12 @@ void tty_printf (const char *fmt, ... )
|
|||||||
__attribute__ ((format (printf,1,2)));
|
__attribute__ ((format (printf,1,2)));
|
||||||
void tty_fprintf (FILE *fp, const char *fmt, ... )
|
void tty_fprintf (FILE *fp, const char *fmt, ... )
|
||||||
__attribute__ ((format (printf,2,3)));
|
__attribute__ ((format (printf,2,3)));
|
||||||
|
char *tty_getf (const char *promptfmt, ... )
|
||||||
|
__attribute__ ((format (printf,1,2)));
|
||||||
#else
|
#else
|
||||||
void tty_printf (const char *fmt, ... );
|
void tty_printf (const char *fmt, ... );
|
||||||
void tty_fprintf (FILE *fp, const char *fmt, ... );
|
void tty_fprintf (FILE *fp, const char *fmt, ... );
|
||||||
|
char *tty_getf (const char *promptfmt, ... );
|
||||||
#endif
|
#endif
|
||||||
void tty_print_string (const unsigned char *p, size_t n);
|
void tty_print_string (const unsigned char *p, size_t n);
|
||||||
void tty_print_utf8_string (const unsigned char *p, size_t n);
|
void tty_print_utf8_string (const unsigned char *p, size_t n);
|
||||||
|
@ -46,7 +46,6 @@
|
|||||||
#define asprintf estream_asprintf
|
#define asprintf estream_asprintf
|
||||||
#define vasprintf estream_vasprintf
|
#define vasprintf estream_vasprintf
|
||||||
|
|
||||||
|
|
||||||
/* GCC attributes. */
|
/* GCC attributes. */
|
||||||
#if __GNUC__ >= 4
|
#if __GNUC__ >= 4
|
||||||
# define GNUPG_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a)))
|
# 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))
|
#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*/
|
#endif /*GNUPG_COMMON_UTIL_H*/
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2007-06-21 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* gpgsm.texi (Certificate Management): Changed description of
|
||||||
|
--gen-key.
|
||||||
|
|
||||||
2007-06-19 Werner Koch <wk@g10code.com>
|
2007-06-19 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* glossary.texi (Glossary): Describe PSE.
|
* glossary.texi (Glossary): Describe PSE.
|
||||||
|
@ -16,6 +16,11 @@ certificates.
|
|||||||
The @emph{Certificate Revocation List} is a list containing
|
The @emph{Certificate Revocation List} is a list containing
|
||||||
certificates revoked by the issuer.
|
certificates revoked by the issuer.
|
||||||
|
|
||||||
|
@item CSR
|
||||||
|
The @emph{Certificate Signing Request} is a message send to a CA to
|
||||||
|
ask them to issue a new certificate. The data format of such a signing
|
||||||
|
request is called PCKS#10.
|
||||||
|
|
||||||
@item Keygrip
|
@item Keygrip
|
||||||
This term is used by GnuPG to describe a 20 byte hash value used
|
This term is used by GnuPG to describe a 20 byte hash value used
|
||||||
to identify a certain key without referencing to a concrete protocol.
|
to identify a certain key without referencing to a concrete protocol.
|
||||||
|
@ -369,20 +369,16 @@ this option at runtime does not kill an already forked scdaemon.
|
|||||||
|
|
||||||
@item --use-standard-socket
|
@item --use-standard-socket
|
||||||
@itemx --no-use-standard-socket
|
@itemx --no-use-standard-socket
|
||||||
@itemx --no-reuse-standard-socket
|
|
||||||
@opindex use-standard-socket
|
@opindex use-standard-socket
|
||||||
@opindex no-use-standard-socket
|
@opindex no-use-standard-socket
|
||||||
@opindex no-reuse-standard-socket
|
|
||||||
By enabling this option @command{gpg-agent} will listen on the socket
|
By enabling this option @command{gpg-agent} will listen on the socket
|
||||||
named @file{S.gpg-agent}, located in the home directory, and not create
|
named @file{S.gpg-agent}, located in the home directory, and not create
|
||||||
a random socket below a temporary directory. Tools connecting to
|
a random socket below a temporary directory. Tools connecting to
|
||||||
@command{gpg-agent} should first try to connect to the socket given in
|
@command{gpg-agent} should first try to connect to the socket given in
|
||||||
environment variable @var{GPG_AGENT_INFO} and the fall back to this
|
environment variable @var{GPG_AGENT_INFO} and the fall back to this
|
||||||
socket. This option may not be used if the home directory is mounted as
|
socket. This option may not be used if the home directory is mounted as
|
||||||
a remote file system. If @option{--no-reuse-standard-socket} is used,
|
a remote file system. Note, that @option{--use-standard-socket} is the
|
||||||
@command{gpg-agent} will not try to reuse a socket which is already in
|
default on Windows systems.
|
||||||
use. Note, that @option{--use-standard-socket} is the default on
|
|
||||||
Windows systems.
|
|
||||||
|
|
||||||
|
|
||||||
@item --display @var{string}
|
@item --display @var{string}
|
||||||
|
@ -164,8 +164,9 @@ use @samp{--help} to get a list of supported operations.
|
|||||||
@table @gnupgtabopt
|
@table @gnupgtabopt
|
||||||
@item --gen-key
|
@item --gen-key
|
||||||
@opindex gen-key
|
@opindex gen-key
|
||||||
This command will only print an error message and direct the user to the
|
This command allows the interactive creation of a certifcate signing
|
||||||
@command{gpgsm-gencert.sh} script.
|
request. It is commonly used along with the @option{--output} option to
|
||||||
|
save the created CSR into a file.
|
||||||
|
|
||||||
@item --list-keys
|
@item --list-keys
|
||||||
@itemx -k
|
@itemx -k
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
2007-06-21 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* main.h: Include util.h.
|
||||||
|
|
||||||
|
* call-agent.c (start_agent): Factored almost all code out to
|
||||||
|
../common/asshelp.c.
|
||||||
|
|
||||||
|
* gpg.h (ctrl_t): Remove. It is now declared in ../common/util.h.
|
||||||
|
|
||||||
2007-06-20 Werner Koch <wk@g10code.com>
|
2007-06-20 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* misc.c (setsysinfo, trap_unaligned): Remove. It is also in
|
* misc.c (setsysinfo, trap_unaligned): Remove. It is also in
|
||||||
|
110
g10/call-agent.c
110
g10/call-agent.c
@ -19,10 +19,6 @@
|
|||||||
* USA.
|
* USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0 /* let Emacs display a red warning */
|
|
||||||
#error fixme: this shares a lot of code with the file in ../sm
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -49,7 +45,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static assuan_context_t agent_ctx = NULL;
|
static assuan_context_t agent_ctx = NULL;
|
||||||
static int force_pipe_server;
|
|
||||||
|
|
||||||
struct cipher_parm_s
|
struct cipher_parm_s
|
||||||
{
|
{
|
||||||
@ -79,107 +74,18 @@ struct genkey_parm_s
|
|||||||
static int
|
static int
|
||||||
start_agent (void)
|
start_agent (void)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
|
||||||
char *infostr, *p;
|
|
||||||
assuan_context_t ctx;
|
|
||||||
|
|
||||||
if (agent_ctx)
|
if (agent_ctx)
|
||||||
return 0; /* fixme: We need a context for each thread or serialize
|
return 0; /* Fixme: We need a context for each thread or serialize
|
||||||
the access to the agent. */
|
the access to the agent. */
|
||||||
|
|
||||||
infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
|
return start_new_gpg_agent (&agent_ctx,
|
||||||
if (!infostr || !*infostr)
|
GPG_ERR_SOURCE_DEFAULT,
|
||||||
{
|
opt.homedir,
|
||||||
const char *pgmname;
|
opt.agent_program,
|
||||||
const char *argv[3];
|
|
||||||
int no_close_list[3];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (opt.verbose)
|
|
||||||
log_info (_("no running gpg-agent - starting one\n"));
|
|
||||||
|
|
||||||
if (fflush (NULL))
|
|
||||||
{
|
|
||||||
gpg_error_t tmperr = gpg_error_from_syserror ();
|
|
||||||
log_error ("error flushing pending output: %s\n", strerror (errno));
|
|
||||||
return tmperr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt.agent_program || !*opt.agent_program)
|
|
||||||
opt.agent_program = gnupg_module_name (GNUPG_MODULE_NAME_AGENT);
|
|
||||||
if ( !(pgmname = strrchr (opt.agent_program, '/')))
|
|
||||||
pgmname = opt.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, opt.agent_program, argv,
|
|
||||||
no_close_list);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int prot;
|
|
||||||
int pid;
|
|
||||||
|
|
||||||
infostr = xstrdup (infostr);
|
|
||||||
if ( !(p = strchr (infostr, ':')) || p == infostr)
|
|
||||||
{
|
|
||||||
log_error (_("malformed GPG_AGENT_INFO environment variable\n"));
|
|
||||||
xfree (infostr);
|
|
||||||
force_pipe_server = 1;
|
|
||||||
return start_agent ();
|
|
||||||
}
|
|
||||||
*p++ = 0;
|
|
||||||
pid = atoi (p);
|
|
||||||
while (*p && *p != ':')
|
|
||||||
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;
|
|
||||||
return start_agent ();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
return start_agent ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
|
|
||||||
return gpg_error (GPG_ERR_NO_AGENT);
|
|
||||||
}
|
|
||||||
agent_ctx = ctx;
|
|
||||||
|
|
||||||
if (DBG_ASSUAN)
|
|
||||||
log_debug ("connection to agent established\n");
|
|
||||||
|
|
||||||
rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL,NULL);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return send_pinentry_environment (agent_ctx, GPG_ERR_SOURCE_DEFAULT,
|
|
||||||
opt.display, opt.ttyname, opt.ttytype,
|
opt.display, opt.ttyname, opt.ttytype,
|
||||||
opt.lc_ctype, opt.lc_messages);
|
opt.lc_ctype, opt.lc_messages,
|
||||||
|
opt.verbose, DBG_ASSUAN,
|
||||||
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,14 +64,6 @@ struct server_control_s
|
|||||||
{
|
{
|
||||||
struct server_local_s *server_local;
|
struct server_local_s *server_local;
|
||||||
};
|
};
|
||||||
typedef struct server_control_s *ctrl_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-- server.c --*/
|
|
||||||
int gpg_server (ctrl_t);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,9 +23,11 @@
|
|||||||
#define G10_MAIN_H
|
#define G10_MAIN_H
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "../common/iobuf.h"
|
#include "iobuf.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
/* It could be argued that the default cipher should be 3DES rather
|
/* It could be argued that the default cipher should be 3DES rather
|
||||||
than CAST5, and the default compression should be 0
|
than CAST5, and the default compression should be 0
|
||||||
@ -300,6 +302,9 @@ void block_all_signals(void);
|
|||||||
void unblock_all_signals(void);
|
void unblock_all_signals(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*-- server.c --*/
|
||||||
|
int gpg_server (ctrl_t);
|
||||||
|
|
||||||
#ifdef ENABLE_CARD_SUPPORT
|
#ifdef ENABLE_CARD_SUPPORT
|
||||||
/*-- card-util.c --*/
|
/*-- card-util.c --*/
|
||||||
void change_pin (int no, int allow_admin);
|
void change_pin (int no, int allow_admin);
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
#include "pkglue.h"
|
#include "pkglue.h"
|
||||||
|
#include "sysutils.h"
|
||||||
#include "call-agent.h"
|
#include "call-agent.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2007-06-21 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* scdaemon.h (ctrl_t): Remove. It is now declared in ../common/util.h.
|
||||||
|
|
||||||
2007-06-18 Marcus Brinkmann <marcus@g10code.de>
|
2007-06-18 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* scdaemon.c (main): Percent escape output of --gpgconf-list.
|
* scdaemon.c (main): Percent escape output of --gpgconf-list.
|
||||||
|
@ -116,7 +116,6 @@ struct server_control_s
|
|||||||
} in_data;
|
} in_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct server_control_s *ctrl_t;
|
|
||||||
typedef struct app_ctx_s *app_t;
|
typedef struct app_ctx_s *app_t;
|
||||||
|
|
||||||
/*-- scdaemon.c --*/
|
/*-- scdaemon.c --*/
|
||||||
|
12
sm/ChangeLog
12
sm/ChangeLog
@ -1,3 +1,15 @@
|
|||||||
|
2007-06-21 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* certreqgen-ui.c: New.
|
||||||
|
* gpgsm.c (main): Let --gen-key call it.
|
||||||
|
* certreqgen.c (gpgsm_genkey): Add optional IN_STREAM arg and
|
||||||
|
adjusted caller.
|
||||||
|
|
||||||
|
* gpgsm.h (ctrl_t): Remove. It is now declared in ../common/util.h.
|
||||||
|
|
||||||
|
* call-agent.c (start_agent): Factored almost all code out to
|
||||||
|
../common/asshelp.c.
|
||||||
|
|
||||||
2007-06-20 Werner Koch <wk@g10code.com>
|
2007-06-20 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* call-agent.c (start_agent) [W32]: Start the agent on the fly.
|
* call-agent.c (start_agent) [W32]: Start the agent on the fly.
|
||||||
|
@ -50,6 +50,7 @@ gpgsm_SOURCES = \
|
|||||||
export.c \
|
export.c \
|
||||||
delete.c \
|
delete.c \
|
||||||
certreqgen.c \
|
certreqgen.c \
|
||||||
|
certreqgen-ui.c \
|
||||||
qualified.c
|
qualified.c
|
||||||
|
|
||||||
|
|
||||||
|
157
sm/call-agent.c
157
sm/call-agent.c
@ -38,11 +38,10 @@
|
|||||||
#include "asshelp.h"
|
#include "asshelp.h"
|
||||||
#include "keydb.h" /* fixme: Move this to import.c */
|
#include "keydb.h" /* fixme: Move this to import.c */
|
||||||
#include "membuf.h"
|
#include "membuf.h"
|
||||||
#include "exechelp.h"
|
|
||||||
|
|
||||||
|
|
||||||
static assuan_context_t agent_ctx = NULL;
|
static assuan_context_t agent_ctx = NULL;
|
||||||
static int force_pipe_server = 0;
|
|
||||||
|
|
||||||
struct cipher_parm_s
|
struct cipher_parm_s
|
||||||
{
|
{
|
||||||
@ -72,161 +71,25 @@ struct learn_parm_s
|
|||||||
static int
|
static int
|
||||||
start_agent (ctrl_t ctrl)
|
start_agent (ctrl_t ctrl)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
|
||||||
char *infostr, *p;
|
|
||||||
assuan_context_t ctx;
|
|
||||||
|
|
||||||
if (agent_ctx)
|
if (agent_ctx)
|
||||||
return 0; /* fixme: We need a context for each thread or serialize
|
return 0; /* fixme: We need a context for each thread or serialize
|
||||||
the access to the agent (which is suitable given that
|
the access to the agent (which is suitable given that
|
||||||
the agent is not MT. */
|
the agent is not MT. */
|
||||||
|
|
||||||
infostr = force_pipe_server? NULL : getenv ("GPG_AGENT_INFO");
|
|
||||||
if (!infostr || !*infostr)
|
|
||||||
{
|
|
||||||
char *sockname;
|
|
||||||
|
|
||||||
/* First check whether we can connect at the standard
|
return start_new_gpg_agent (&agent_ctx,
|
||||||
socket. */
|
GPG_ERR_SOURCE_DEFAULT,
|
||||||
sockname = make_filename (opt.homedir, "S.gpg-agent", NULL);
|
opt.homedir,
|
||||||
rc = assuan_socket_connect (&ctx, sockname, 0);
|
opt.agent_program,
|
||||||
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
/* With no success start a new server. */
|
|
||||||
if (opt.verbose)
|
|
||||||
log_info (_("no running gpg-agent - starting one\n"));
|
|
||||||
|
|
||||||
gpgsm_status (ctrl, STATUS_PROGRESS, "starting_agent ? 0 0");
|
|
||||||
|
|
||||||
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 (!opt.agent_program || !*opt.agent_program)
|
|
||||||
opt.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];
|
|
||||||
|
|
||||||
/* The --no-reuse-standard option makes sure that we don't
|
|
||||||
start a second instance of a agent in case another
|
|
||||||
process has started one in the meantime. */
|
|
||||||
argv[0] = "--daemon";
|
|
||||||
argv[1] = "--no-reuse-standard-socket";
|
|
||||||
argv[2] = NULL;
|
|
||||||
|
|
||||||
rc = gnupg_spawn_process_detached (opt.agent_program, argv, NULL);
|
|
||||||
if (rc)
|
|
||||||
log_debug ("failed to start agent `%s': %s\n",
|
|
||||||
opt.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 (opt.agent_program, '/')))
|
|
||||||
pgmname = opt.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, opt.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;
|
|
||||||
return start_agent (ctrl);
|
|
||||||
}
|
|
||||||
*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;
|
|
||||||
return start_agent (ctrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
return start_agent (ctrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
{
|
|
||||||
log_error ("can't connect to the agent: %s\n", gpg_strerror (rc));
|
|
||||||
return gpg_error (GPG_ERR_NO_AGENT);
|
|
||||||
}
|
|
||||||
agent_ctx = ctx;
|
|
||||||
|
|
||||||
if (DBG_ASSUAN)
|
|
||||||
log_debug ("connection to agent established\n");
|
|
||||||
|
|
||||||
rc = assuan_transact (agent_ctx, "RESET", NULL, NULL, NULL, NULL, NULL, NULL);
|
|
||||||
if (rc)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return send_pinentry_environment (agent_ctx, GPG_ERR_SOURCE_DEFAULT,
|
|
||||||
opt.display, opt.ttyname, opt.ttytype,
|
opt.display, opt.ttyname, opt.ttytype,
|
||||||
opt.lc_ctype, opt.lc_messages);
|
opt.lc_ctype, opt.lc_messages,
|
||||||
|
opt.verbose, DBG_ASSUAN,
|
||||||
|
gpgsm_status2, ctrl);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
membuf_data_cb (void *opaque, const void *buffer, size_t length)
|
membuf_data_cb (void *opaque, const void *buffer, size_t length)
|
||||||
{
|
{
|
||||||
|
317
sm/certreqgen-ui.c
Normal file
317
sm/certreqgen-ui.c
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
/* certreqgen-ui.c - Simple user interface for certreqgen.c
|
||||||
|
* Copyright (C) 2007 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GnuPG.
|
||||||
|
*
|
||||||
|
* GnuPG is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GnuPG is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||||
|
* USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "gpgsm.h"
|
||||||
|
#include <gcrypt.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
#include "ttyio.h"
|
||||||
|
#include "membuf.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Prompt for lines and append them to MB. */
|
||||||
|
static void
|
||||||
|
ask_mb_lines (membuf_t *mb, const char *prefix)
|
||||||
|
{
|
||||||
|
char *answer = NULL;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
xfree (answer);
|
||||||
|
answer = tty_get ("> ");
|
||||||
|
tty_kill_prompt ();
|
||||||
|
trim_spaces (answer);
|
||||||
|
if (*answer)
|
||||||
|
{
|
||||||
|
put_membuf_str (mb, prefix);
|
||||||
|
put_membuf_str (mb, answer);
|
||||||
|
put_membuf (mb, "\n", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (*answer);
|
||||||
|
xfree (answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper to store stuff in a membuf. */
|
||||||
|
void
|
||||||
|
store_key_value_lf (membuf_t *mb, const char *key, const char *value)
|
||||||
|
{
|
||||||
|
put_membuf_str (mb, key);
|
||||||
|
put_membuf_str (mb, value);
|
||||||
|
put_membuf (mb, "\n", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper tp store a membuf create by mb_ask_lines into MB. Returns
|
||||||
|
-1 on error. */
|
||||||
|
int
|
||||||
|
store_mb_lines (membuf_t *mb, membuf_t *lines)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (get_membuf_len (lines))
|
||||||
|
{
|
||||||
|
put_membuf (lines, "", 1);
|
||||||
|
p = get_membuf (lines, NULL);
|
||||||
|
if (!p)
|
||||||
|
return -1;
|
||||||
|
put_membuf_str (mb, p);
|
||||||
|
xfree (p);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This function is used to create a certificate request from the
|
||||||
|
command line. In the past the similar gpgsm-gencert.sh script has
|
||||||
|
been used for it; however that scripts requires a full Unix shell
|
||||||
|
and thus is not suitable for the Windows port. So here is the
|
||||||
|
re-implementation. */
|
||||||
|
void
|
||||||
|
gpgsm_gencertreq_tty (ctrl_t ctrl, FILE *output_fp)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char *answer;
|
||||||
|
int selection;
|
||||||
|
FILE *fp = NULL;
|
||||||
|
int method;
|
||||||
|
char *keytype;
|
||||||
|
char *keygrip = NULL;
|
||||||
|
unsigned int nbits;
|
||||||
|
int minbits = 1024;
|
||||||
|
int maxbits = 4096;
|
||||||
|
int defbits = 2048;
|
||||||
|
const char *keyusage;
|
||||||
|
char *subject_name;
|
||||||
|
membuf_t mb_email, mb_dns, mb_uri, mb_result;
|
||||||
|
char *result = NULL;
|
||||||
|
int i;
|
||||||
|
const char *s, *s2;
|
||||||
|
|
||||||
|
init_membuf (&mb_email, 100);
|
||||||
|
init_membuf (&mb_dns, 100);
|
||||||
|
init_membuf (&mb_uri, 100);
|
||||||
|
init_membuf (&mb_result, 512);
|
||||||
|
|
||||||
|
/* Get the type of the key. */
|
||||||
|
tty_printf (_("Please select what kind of key you want:\n"));
|
||||||
|
tty_printf (_(" (%d) RSA\n"), 1 );
|
||||||
|
tty_printf (_(" (%d) Existing key\n"), 2 );
|
||||||
|
tty_printf (_(" (%d) Existing key from card\n"), 3 );
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
answer = tty_get (_("Your selection? "));
|
||||||
|
tty_kill_prompt ();
|
||||||
|
selection = *answer? atoi (answer): 1;
|
||||||
|
xfree (answer);
|
||||||
|
}
|
||||||
|
while (!(selection >= 1 && selection <= 3));
|
||||||
|
method = selection;
|
||||||
|
|
||||||
|
/* Get size of the key. */
|
||||||
|
if (method == 1)
|
||||||
|
{
|
||||||
|
keytype = xstrdup ("RSA");
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
answer = tty_getf (_("What keysize do you want? (%u) "), defbits);
|
||||||
|
tty_kill_prompt ();
|
||||||
|
nbits = *answer? atoi (answer): defbits;
|
||||||
|
xfree (answer);
|
||||||
|
if (nbits < minbits || nbits > maxbits)
|
||||||
|
tty_printf(_("%s keysizes must be in the range %u-%u\n"),
|
||||||
|
"RSA", minbits, maxbits);
|
||||||
|
else
|
||||||
|
break; /* Okay. */
|
||||||
|
}
|
||||||
|
tty_printf (_("Requested keysize is %u bits\n"), nbits);
|
||||||
|
/* We round it up so that it better matches the word size. */
|
||||||
|
if (( nbits % 64))
|
||||||
|
{
|
||||||
|
nbits = ((nbits + 63) / 64) * 64;
|
||||||
|
tty_printf (_("rounded up to %u bits\n"), nbits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (method == 2)
|
||||||
|
{
|
||||||
|
tty_printf ("Not yet supported; "
|
||||||
|
"use the gpgsm-gencert.sh script instead\n");
|
||||||
|
keytype = xstrdup ("RSA");
|
||||||
|
nbits = defbits; /* We need a dummy value. */
|
||||||
|
}
|
||||||
|
else /* method == 3 */
|
||||||
|
{
|
||||||
|
tty_printf ("Not yet supported; "
|
||||||
|
"use the gpgsm-gencert.sh script instead\n");
|
||||||
|
keytype = xstrdup ("card:foobar");
|
||||||
|
nbits = defbits; /* We need a dummy value. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ask for the key usage. */
|
||||||
|
tty_printf (_("Possible actions for a %s key:\n"), "RSA");
|
||||||
|
tty_printf (_(" (%d) sign, encrypt\n"), 1 );
|
||||||
|
tty_printf (_(" (%d) sign\n"), 2 );
|
||||||
|
tty_printf (_(" (%d) encrypt\n"), 3 );
|
||||||
|
do
|
||||||
|
{
|
||||||
|
answer = tty_get (_("Your selection? "));
|
||||||
|
tty_kill_prompt ();
|
||||||
|
selection = *answer? atoi (answer): 1;
|
||||||
|
xfree (answer);
|
||||||
|
switch (selection)
|
||||||
|
{
|
||||||
|
case 1: keyusage = "sign, encrypt"; break;
|
||||||
|
case 2: keyusage = "sign"; break;
|
||||||
|
case 3: keyusage = "encrypt"; break;
|
||||||
|
default: keyusage = NULL; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!keyusage);
|
||||||
|
|
||||||
|
/* Get the subject name. */
|
||||||
|
answer = NULL;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
size_t erroff, errlen;
|
||||||
|
|
||||||
|
xfree (answer);
|
||||||
|
answer = tty_get (_("Enter the X.509 subject name: "));
|
||||||
|
tty_kill_prompt ();
|
||||||
|
trim_spaces (answer);
|
||||||
|
if (!*answer)
|
||||||
|
tty_printf (_("No subject name given\n"));
|
||||||
|
else if ( (err = ksba_dn_teststr (answer, 0, &erroff, &errlen)) )
|
||||||
|
{
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_NAME)
|
||||||
|
tty_printf (_("Invalid subject name label `%.*s'\n"),
|
||||||
|
(int)errlen, answer+erroff);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* TRANSLATORS: The 22 in the second string is the
|
||||||
|
length of the first string up to the "%s". Please
|
||||||
|
adjust it do the length of your translation. The
|
||||||
|
second string is merely passed to atoi so you can
|
||||||
|
drop everything after the number. */
|
||||||
|
tty_printf (_("Invalid subject name `%s'\n"), answer);
|
||||||
|
tty_printf ("%*s^\n",
|
||||||
|
atoi (_("22 translator: see "
|
||||||
|
"certreg-ui.c:gpgsm_gencertreq_tty"))
|
||||||
|
+ (int)erroff, "");
|
||||||
|
}
|
||||||
|
*answer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!*answer);
|
||||||
|
subject_name = answer;
|
||||||
|
answer = NULL;
|
||||||
|
|
||||||
|
/* Get the email addresses. */
|
||||||
|
tty_printf (_("Enter email addresses"));
|
||||||
|
tty_printf (_(" (end with an empty line):\n"));
|
||||||
|
ask_mb_lines (&mb_email, "Name-Email: ");
|
||||||
|
|
||||||
|
/* DNS names. */
|
||||||
|
tty_printf (_("Enter DNS names"));
|
||||||
|
tty_printf (_(" (optional; end with an empty line):\n"));
|
||||||
|
ask_mb_lines (&mb_email, "Name-DNS: ");
|
||||||
|
|
||||||
|
/* URIs. */
|
||||||
|
tty_printf (_("Enter URIs"));
|
||||||
|
tty_printf (_(" (optional; end with an empty line):\n"));
|
||||||
|
ask_mb_lines (&mb_email, "Name-URI: ");
|
||||||
|
|
||||||
|
|
||||||
|
/* Put it all together. */
|
||||||
|
store_key_value_lf (&mb_result, "Key-Type: ", keytype);
|
||||||
|
{
|
||||||
|
char numbuf[30];
|
||||||
|
snprintf (numbuf, sizeof numbuf, "%u", nbits);
|
||||||
|
store_key_value_lf (&mb_result, "Key-Length: ", numbuf);
|
||||||
|
}
|
||||||
|
store_key_value_lf (&mb_result, "Key-Usage: ", keyusage);
|
||||||
|
store_key_value_lf (&mb_result, "Name-DN: ", subject_name);
|
||||||
|
if (keygrip)
|
||||||
|
store_key_value_lf (&mb_result, "Key-Grip: ", keygrip);
|
||||||
|
if (store_mb_lines (&mb_result, &mb_email))
|
||||||
|
goto mem_error;
|
||||||
|
if (store_mb_lines (&mb_result, &mb_dns))
|
||||||
|
goto mem_error;
|
||||||
|
if (store_mb_lines (&mb_result, &mb_uri))
|
||||||
|
goto mem_error;
|
||||||
|
put_membuf (&mb_result, "", 1);
|
||||||
|
result = get_membuf (&mb_result, NULL);
|
||||||
|
if (!result)
|
||||||
|
goto mem_error;
|
||||||
|
|
||||||
|
tty_printf (_("Parameters to be used for the certificate request:\n"));
|
||||||
|
for (s=result; (s2 = strchr (s, '\n')); s = s2+1, i++)
|
||||||
|
tty_printf (" %.*s\n", (int)(s2-s), s);
|
||||||
|
tty_printf ("\n");
|
||||||
|
|
||||||
|
|
||||||
|
if (!tty_get_answer_is_yes ("Really create request? (y/N) "))
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
/* Now create a parameter file and generate the key. */
|
||||||
|
fp = tmpfile ();
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
log_error (_("error creating temporary file: %s\n"), strerror (errno));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
fputs (result, fp);
|
||||||
|
rewind (fp);
|
||||||
|
tty_printf (_("Now creating certificate request. "
|
||||||
|
"This may take a while ...\n"));
|
||||||
|
{
|
||||||
|
int save_pem = ctrl->create_pem;
|
||||||
|
ctrl->create_pem = 1; /* Force creation of PEM. */
|
||||||
|
err = gpgsm_genkey (ctrl, -1, fp, output_fp);
|
||||||
|
ctrl->create_pem = save_pem;
|
||||||
|
}
|
||||||
|
if (!err)
|
||||||
|
tty_printf (_("Ready. You should now send this request to your CA.\n"));
|
||||||
|
|
||||||
|
|
||||||
|
goto leave;
|
||||||
|
mem_error:
|
||||||
|
log_error (_("resource problem: out or core\n"));
|
||||||
|
leave:
|
||||||
|
if (fp)
|
||||||
|
fclose (fp);
|
||||||
|
xfree (keytype);
|
||||||
|
xfree (subject_name);
|
||||||
|
xfree (keygrip);
|
||||||
|
xfree (get_membuf (&mb_email, NULL));
|
||||||
|
xfree (get_membuf (&mb_dns, NULL));
|
||||||
|
xfree (get_membuf (&mb_uri, NULL));
|
||||||
|
xfree (get_membuf (&mb_result, NULL));
|
||||||
|
xfree (result);
|
||||||
|
}
|
@ -831,16 +831,19 @@ create_request (ctrl_t ctrl,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Create a new key by reading the parameters from in_fd. Multiple
|
/* Create a new key by reading the parameters from in_fd or in_stream.
|
||||||
keys may be created */
|
Multiple keys may be created */
|
||||||
int
|
int
|
||||||
gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp)
|
gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *in_stream, FILE *out_fp)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
FILE *in_fp;
|
FILE *in_fp;
|
||||||
Base64Context b64writer = NULL;
|
Base64Context b64writer = NULL;
|
||||||
ksba_writer_t writer;
|
ksba_writer_t writer;
|
||||||
|
|
||||||
|
if (in_stream)
|
||||||
|
in_fp = in_stream;
|
||||||
|
else
|
||||||
in_fp = fdopen (dup (in_fd), "rb");
|
in_fp = fdopen (dup (in_fd), "rb");
|
||||||
if (!in_fp)
|
if (!in_fp)
|
||||||
{
|
{
|
||||||
@ -877,6 +880,7 @@ gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp)
|
|||||||
|
|
||||||
leave:
|
leave:
|
||||||
gpgsm_destroy_writer (b64writer);
|
gpgsm_destroy_writer (b64writer);
|
||||||
|
if (!in_stream)
|
||||||
fclose (in_fp);
|
fclose (in_fp);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
11
sm/gpgsm.c
11
sm/gpgsm.c
@ -1590,12 +1590,15 @@ main ( int argc, char **argv)
|
|||||||
|
|
||||||
|
|
||||||
case aKeygen: /* Generate a key; well kind of. */
|
case aKeygen: /* Generate a key; well kind of. */
|
||||||
log_error
|
{
|
||||||
(_("key generation is not available from the commandline\n"));
|
FILE *fp = open_fwrite (opt.outfile?opt.outfile:"-");
|
||||||
log_info (_("please use the script \"%s\" to generate a new key\n"),
|
gpgsm_gencertreq_tty (&ctrl, fp);
|
||||||
"gpgsm-gencert.sh");
|
if (fp != stdout)
|
||||||
|
fclose (fp);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case aImport:
|
case aImport:
|
||||||
gpgsm_import_files (&ctrl, argc, argv, open_read);
|
gpgsm_import_files (&ctrl, argc, argv, open_read);
|
||||||
break;
|
break;
|
||||||
|
@ -167,7 +167,6 @@ struct server_control_s
|
|||||||
signer) */
|
signer) */
|
||||||
int use_ocsp; /* Set to true if OCSP should be used. */
|
int use_ocsp; /* Set to true if OCSP should be used. */
|
||||||
};
|
};
|
||||||
typedef struct server_control_s *ctrl_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* Data structure used in base64.c. */
|
/* Data structure used in base64.c. */
|
||||||
@ -317,7 +316,11 @@ int gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int in_fd, FILE *out_fp);
|
|||||||
int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp);
|
int gpgsm_decrypt (ctrl_t ctrl, int in_fd, FILE *out_fp);
|
||||||
|
|
||||||
/*-- certreqgen.c --*/
|
/*-- certreqgen.c --*/
|
||||||
int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp);
|
int gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *in_stream, FILE *out_fp);
|
||||||
|
|
||||||
|
/*-- certreqgen-ui.c --*/
|
||||||
|
void gpgsm_gencertreq_tty (ctrl_t ctrl, FILE *out_fp);
|
||||||
|
|
||||||
|
|
||||||
/*-- qualified.c --*/
|
/*-- qualified.c --*/
|
||||||
gpg_error_t gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert,
|
gpg_error_t gpgsm_is_in_qualified_list (ctrl_t ctrl, ksba_cert_t cert,
|
||||||
|
@ -865,7 +865,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
|
|||||||
out_fp = fdopen ( dup(out_fd), "w");
|
out_fp = fdopen ( dup(out_fd), "w");
|
||||||
if (!out_fp)
|
if (!out_fp)
|
||||||
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
|
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
|
||||||
rc = gpgsm_genkey (ctrl, inp_fd, out_fp);
|
rc = gpgsm_genkey (ctrl, inp_fd, NULL, out_fp);
|
||||||
fclose (out_fp);
|
fclose (out_fp);
|
||||||
|
|
||||||
/* close and reset the fds */
|
/* close and reset the fds */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user