Implemented the --gen-key command as we can't use the gpgsm-gencert.sh under Windows.

This commit is contained in:
Werner Koch 2007-06-21 18:44:48 +00:00
parent 09cc0ee7be
commit 0b66f30d66
33 changed files with 714 additions and 317 deletions

3
NEWS
View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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
{ {

View File

@ -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,9 +1747,10 @@ 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. */
log_error (_("no gpg-agent running in this session\n")); if (!silent)
log_error (_("no gpg-agent running in this session\n"));
return -1; return -1;
} }
@ -1749,9 +1758,10 @@ 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. */
log_error (_("malformed GPG_AGENT_INFO environment variable\n")); if (!silent)
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);
log_error (_("gpg-agent protocol version %d is not supported\n"), if (!silent)
prot); log_error (_("gpg-agent protocol version %d is not supported\n"),
if (!check_for_running_agent (1)) prot);
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);

View File

@ -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.

View File

@ -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;
}

View File

@ -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*/

View File

@ -593,7 +593,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
cmdline, /* Command line arguments. */ cmdline, /* Command line arguments. */
&sec_attr, /* Process security attributes. */ &sec_attr, /* Process security attributes. */
&sec_attr, /* Thread security attributes. */ &sec_attr, /* Thread security attributes. */
FALSE, /* Inherit handles. */ FALSE, /* Inherit handles. */
cr_flags, /* Creation flags. */ cr_flags, /* Creation flags. */
NULL, /* Environment. */ NULL, /* Environment. */
NULL, /* Use current drive/directory. */ NULL, /* Use current drive/directory. */

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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 )
{ {

View File

@ -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);

View File

@ -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*/

View File

@ -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.

View File

@ -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.

View File

@ -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}

View File

@ -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

View File

@ -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

View File

@ -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]; opt.display, opt.ttyname, opt.ttytype,
int no_close_list[3]; opt.lc_ctype, opt.lc_messages,
int i; opt.verbose, DBG_ASSUAN,
NULL, NULL);
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.lc_ctype, opt.lc_messages);
} }

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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.

View File

@ -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 --*/

View File

@ -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.

View File

@ -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

View File

@ -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,
opt.display, opt.ttyname, opt.ttytype,
opt.lc_ctype, opt.lc_messages,
opt.verbose, DBG_ASSUAN,
gpgsm_status2, ctrl);
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.lc_ctype, opt.lc_messages);
} }
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
View 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);
}

View File

@ -831,17 +831,20 @@ 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;
in_fp = fdopen (dup (in_fd), "rb"); if (in_stream)
in_fp = in_stream;
else
in_fp = fdopen (dup (in_fd), "rb");
if (!in_fp) if (!in_fp)
{ {
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno)); gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
@ -877,7 +880,8 @@ gpgsm_genkey (ctrl_t ctrl, int in_fd, FILE *out_fp)
leave: leave:
gpgsm_destroy_writer (b64writer); gpgsm_destroy_writer (b64writer);
fclose (in_fp); if (!in_stream)
fclose (in_fp);
return rc; return rc;
} }

View File

@ -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;

View File

@ -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,

View File

@ -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 */