Changes to let the key listing use estream to help systems without

funopen.
This commit is contained in:
Werner Koch 2007-03-19 14:35:04 +00:00
parent 674530c3fa
commit 12b661166c
15 changed files with 723 additions and 272 deletions

5
NEWS
View File

@ -1,6 +1,9 @@
Noteworthy changes in version 2.0.4
------------------------------------------------
* The Assuan key listing commands are now also working for systems
without the funopen/fopencookie API.
Noteworthy changes in version 2.0.3 (2007-03-08)
------------------------------------------------
@ -10,7 +13,7 @@ Noteworthy changes in version 2.0.3 (2007-03-08)
did not permit this, and were thus not using the plaintext boundary
status tags that GnuPG provides. This change makes GnuPG reject
such messages by default which makes those programs safe again.
--allow-multiple-messages returns to the old behavior.
--allow-multiple-messages returns to the old behavior. [CVE-2007-1263].
* New --verify-option show-primary-uid-only.

15
TODO
View File

@ -76,8 +76,6 @@
** Add a test to check the extkeyusage.
* Windows port
** gpgsm's LISTKEYS does not yet work
Fix is to change everything to libestream
** Signals are not support
This means we can't reread a configuration
** No card status notifications.
@ -85,6 +83,10 @@
* sm/
** check that we issue NO_SECKEY xxx if a -u key was not found
We don't. The messages returned are also wrong (recipient vs. signer).
** cmd_export
Does only work on systems with funopen/fopencookie. Changing is
easy.
* jnlib/
** provide jnlib_malloc and try to remove all jnlib_xmalloc.
@ -124,5 +126,12 @@
* Pinpad Reader
We do not yet support P15 applications. The trivial thing using
ASCII characters will be easy to implement but the otehr cases need
ASCII characters will be easy to implement but the other cases need
some more work.
* Bugs
** After disabling scdaemon and sending a HUP
scdaemon stays as a zombie and gpg-agent does not perform any more
commands.

View File

@ -1,3 +1,10 @@
2007-03-19 Werner Koch <wk@g10code.com>
* estream.c (es_fprintf_unlocked): New.
(es_write_sanitized): New.
(es_write_hexstring): New.
(es_write_sanitized_utf8_buffer) [GNUPG_MAJOR_VERSION]: New.
2007-03-09 David Shaw <dshaw@jabberwocky.com>
From STABLE-BRANCH-1-4

View File

@ -1,5 +1,5 @@
/* estream.c - Extended Stream I/O Library
* Copyright (C) 2004, 2006 g10 Code GmbH
* Copyright (C) 2004, 2006, 2007 g10 Code GmbH
*
* This file is part of Libestream.
*
@ -49,6 +49,10 @@
# include <pth.h>
#endif
#ifdef GNUPG_MAJOR_VERSION
#include "../common/util.h"
#endif
#ifndef HAVE_MKSTEMP
int mkstemp (char *template);
#endif
@ -205,7 +209,9 @@ static estream_mutex_t estream_list_lock = ESTREAM_MUTEX_INITIALIZER;
/* Macros. */
/* Calculate array dimension. */
#ifndef DIM
#define DIM(array) (sizeof (array) / sizeof (*array))
#endif
/* Evaluate EXPRESSION, setting VARIABLE to the return code, if
VARIABLE is zero. */
@ -740,6 +746,14 @@ static es_cookie_io_functions_t estream_functions_file =
static int
es_convert_mode (const char *mode, unsigned int *flags)
{
/* FIXME: We need to allow all combinations for mode flags and for
binary we need to do a
#ifdef HAVE_DOSISH_SYSTEM
setmode (fd, O_BINARY);
#endif
*/
struct
{
const char *mode;
@ -2702,6 +2716,21 @@ es_vfprintf (estream_t ES__RESTRICT stream, const char *ES__RESTRICT format,
}
static int
es_fprintf_unlocked (estream_t ES__RESTRICT stream,
const char *ES__RESTRICT format, ...)
{
int ret;
va_list ap;
va_start (ap, format);
ret = es_print (stream, format, ap);
va_end (ap);
return ret;
}
int
es_fprintf (estream_t ES__RESTRICT stream,
const char *ES__RESTRICT format, ...)
@ -2839,3 +2868,163 @@ es_opaque_get (estream_t stream)
return opaque;
}
/* Print a BUFFER to STREAM while replacing all control characters and
the characters in DELIMITERS by standard C escape sequences.
Returns 0 on success or -1 on error. If BYTES_WRITTEN is not NULL
the number of bytes actually written are stored at this
address. */
int
es_write_sanitized (estream_t ES__RESTRICT stream,
const void * ES__RESTRICT buffer, size_t length,
const char * delimiters,
size_t * ES__RESTRICT bytes_written)
{
const unsigned char *p = buffer;
size_t count = 0;
int ret;
ESTREAM_LOCK (stream);
for (; length; length--, p++, count++)
{
if (*p < 0x20
|| (*p >= 0x7f && *p < 0xa0)
|| (delimiters
&& (strchr (delimiters, *p) || *p == '\\')))
{
es_putc_unlocked ('\\', stream);
count++;
if (*p == '\n')
{
es_putc_unlocked ('n', stream);
count++;
}
else if (*p == '\r')
{
es_putc_unlocked ('r', stream);
count++;
}
else if (*p == '\f')
{
es_putc_unlocked ('f', stream);
count++;
}
else if (*p == '\v')
{
es_putc_unlocked ('v', stream);
count++;
}
else if (*p == '\b')
{
es_putc_unlocked ('b', stream);
count++;
}
else if (!*p)
{
es_putc_unlocked('0', stream);
count++;
}
else
{
es_fprintf_unlocked (stream, "x%02x", *p);
count += 3;
}
}
else
{
es_putc_unlocked (*p, stream);
count++;
}
}
if (bytes_written)
*bytes_written = count;
ret = es_ferror_unlocked (stream)? -1 : 0;
ESTREAM_UNLOCK (stream);
return ret;
}
/* Write LENGTH bytes of BUFFER to STREAM as a hex encoded string.
RESERVED must be 0. Returns 0 on success or -1 on error. If
BYTES_WRITTEN is not NULL the number of bytes actually written are
stored at this address. */
int
es_write_hexstring (estream_t ES__RESTRICT stream,
const void *ES__RESTRICT buffer, size_t length,
int reserved, size_t *ES__RESTRICT bytes_written )
{
int ret;
const unsigned char *s;
size_t count = 0;
#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
if (!length)
return 0;
ESTREAM_LOCK (stream);
for (s = buffer; length; s++, length--)
{
es_putc_unlocked ( tohex ((*s>>4)&15), stream);
es_putc_unlocked ( tohex (*s&15), stream);
count += 2;
}
if (bytes_written)
*bytes_written = count;
ret = es_ferror_unlocked (stream)? -1 : 0;
ESTREAM_UNLOCK (stream);
return ret;
#undef tohex
}
#ifdef GNUPG_MAJOR_VERSION
/* Special estream function to print an UTF8 string in the native
encoding. The interface is the same as es_write_sanitized, however
only one delimiter may be supported.
THIS IS NOT A STANDARD ESTREAM FUNCTION AND ONLY USED BY GNUPG. */
int
es_write_sanitized_utf8_buffer (estream_t stream,
const void *buffer, size_t length,
const char *delimiters, size_t *bytes_written)
{
const char *p = buffer;
size_t i;
/* We can handle plain ascii simpler, so check for it first. */
for (i=0; i < length; i++ )
{
if ( (p[i] & 0x80) )
break;
}
if (i < length)
{
int delim = delimiters? *delimiters : 0;
char *buf;
int ret;
/*(utf8 conversion already does the control character quoting). */
buf = utf8_to_native (p, length, delim);
if (bytes_written)
*bytes_written = strlen (buf);
ret = es_fputs (buf, stream);
xfree (buf);
return i;
}
else
return es_write_sanitized (stream, p, length, delimiters, bytes_written);
}
#endif /*GNUPG_MAJOR_VERSION*/

View File

@ -172,6 +172,13 @@ int es_read (estream_t ES__RESTRICT stream,
int es_write (estream_t ES__RESTRICT stream,
const void *ES__RESTRICT buffer, size_t bytes_to_write,
size_t *ES__RESTRICT bytes_written);
int es_write_sanitized (estream_t ES__RESTRICT stream,
const void *ES__RESTRICT buffer, size_t length,
const char *delimiters,
size_t *ES__RESTRICT bytes_written);
int es_write_hexstring (estream_t ES__RESTRICT stream,
const void *ES__RESTRICT buffer, size_t length,
int reserved, size_t *ES__RESTRICT bytes_written);
size_t es_fread (void *ES__RESTRICT ptr, size_t size, size_t nitems,
estream_t ES__RESTRICT stream);
@ -203,5 +210,15 @@ estream_t es_tmpfile (void);
void es_opaque_set (estream_t ES__RESTRICT stream, void *ES__RESTRICT opaque);
void *es_opaque_get (estream_t stream);
#ifdef GNUPG_MAJOR_VERSION
int es_write_sanitized_utf8_buffer (estream_t stream,
const void *buffer, size_t length,
const char *delimiters,
size_t *bytes_written);
#endif /*GNUPG_MAJOR_VERSION*/
#endif /*ESTREAM_H*/

View File

@ -74,6 +74,7 @@ make_printable_string (const void *p, size_t n, int delim )
}
/*
* Check if the file is compressed.
*/

View File

@ -43,7 +43,6 @@
#include "../jnlib/dotlock.h"
#include "../jnlib/utf8conv.h"
#if __GNUC__ >= 4
# define GNUPG_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a)))
#else

View File

@ -1,6 +1,6 @@
Multiple Messages Problem in GnuPG and GPGME
==============================================
2007-03-05
2007-03-05 [CVE-2007-1263]
Summary

View File

@ -1,3 +1,25 @@
2007-03-19 Werner Koch <wk@g10code.com>
Change to let the key listing use estream to help systems without
funopen.
* keylist.c: Use estream in place of stdio functions.
* gpgsm.c (open_es_fwrite): New.
(main): Use it for the list commands.
* server.c (data_line_cookie_functions): New.
(data_line_cookie_write, data_line_cookie_close): New.
(do_listkeys): Use estream.
* certdump.c (gpgsm_print_serial): Changed to use estream.
(gpgsm_print_time): Ditto.
(pretty_es_print_sexp): New.
(gpgsm_es_print_name): New.
(print_dn_part): New arg STREAM. Changed all callers.
(print_dn_parts): Ditto.
* certchain.c (gpgsm_validate_chain): Changed FP to type
estream_t.
(do_list, unknown_criticals, allowed_ca, check_cert_policy)
(is_cert_still_valid): Ditto.
2007-01-31 Werner Koch <wk@g10code.com>
* gpgsm.c (main): Let --gen-key print a more informative error

View File

@ -93,7 +93,7 @@ set_already_asked_marktrusted (ksba_cert_t cert)
LISTMODE is false, use the string to print an log_info or, if
IS_ERROR is true, and log_error. */
static void
do_list (int is_error, int listmode, FILE *fp, const char *format, ...)
do_list (int is_error, int listmode, estream_t fp, const char *format, ...)
{
va_list arg_ptr;
@ -102,9 +102,9 @@ do_list (int is_error, int listmode, FILE *fp, const char *format, ...)
{
if (fp)
{
fputs (" [", fp);
vfprintf (fp, format, arg_ptr);
fputs ("]\n", fp);
es_fputs (" [", fp);
es_vfprintf (fp, format, arg_ptr);
es_fputs ("]\n", fp);
}
}
else
@ -133,7 +133,7 @@ compare_certs (ksba_cert_t a, ksba_cert_t b)
static int
unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp)
unknown_criticals (ksba_cert_t cert, int listmode, estream_t fp)
{
static const char *known[] = {
"2.5.29.15", /* keyUsage */
@ -183,7 +183,7 @@ unknown_criticals (ksba_cert_t cert, int listmode, FILE *fp)
BasicConstraints extension. The function returns 0 on success and
the awlloed length of the chain at CHAINLEN. */
static int
allowed_ca (ksba_cert_t cert, int *chainlen, int listmode, FILE *fp)
allowed_ca (ksba_cert_t cert, int *chainlen, int listmode, estream_t fp)
{
gpg_error_t err;
int flag;
@ -208,7 +208,7 @@ allowed_ca (ksba_cert_t cert, int *chainlen, int listmode, FILE *fp)
static int
check_cert_policy (ksba_cert_t cert, int listmode, FILE *fplist)
check_cert_policy (ksba_cert_t cert, int listmode, estream_t fplist)
{
gpg_error_t err;
char *policies;
@ -645,7 +645,7 @@ gpgsm_is_root_cert (ksba_cert_t cert)
/* This is a helper for gpgsm_validate_chain. */
static gpg_error_t
is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp,
is_cert_still_valid (ctrl_t ctrl, int lm, estream_t fp,
ksba_cert_t subject_cert, ksba_cert_t issuer_cert,
int *any_revoked, int *any_no_crl, int *any_crl_too_old)
{
@ -704,7 +704,7 @@ is_cert_still_valid (ctrl_t ctrl, int lm, FILE *fp,
*/
int
gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t r_exptime,
int listmode, FILE *fp, unsigned int flags)
int listmode, estream_t fp, unsigned int flags)
{
int rc = 0, depth = 0, maxdepth;
char *issuer = NULL;

View File

@ -1,5 +1,5 @@
/* certdump.c - Dump a certificate for debugging
* Copyright (C) 2001, 2004 Free Software Foundation, Inc.
* Copyright (C) 2001, 2004, 2007 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -56,30 +56,27 @@ struct dn_array_s {
};
/* print the first element of an S-Expression */
/* Print the first element of an S-Expression. */
void
gpgsm_print_serial (FILE *fp, ksba_const_sexp_t sn)
gpgsm_print_serial (estream_t fp, ksba_const_sexp_t sn)
{
const char *p = (const char *)sn;
unsigned long n;
char *endp;
if (!p)
fputs (_("none"), fp);
es_fputs (_("none"), fp);
else if (*p != '(')
fputs ("[Internal error - not an S-expression]", fp);
es_fputs ("[Internal error - not an S-expression]", fp);
else
{
p++;
n = strtoul (p, &endp, 10);
p = endp;
if (*p!=':')
fputs ("[Internal Error - invalid S-expression]", fp);
es_fputs ("[Internal Error - invalid S-expression]", fp);
else
{
for (p++; n; n--, p++)
fprintf (fp, "%02X", *(const unsigned char*)p);
}
es_write_hexstring (fp, p, strlen (p), 0, NULL);
}
}
@ -148,14 +145,16 @@ gpgsm_format_serial (ksba_const_sexp_t sn)
void
gpgsm_print_time (FILE *fp, ksba_isotime_t t)
gpgsm_print_time (estream_t fp, ksba_isotime_t t)
{
if (!t || !*t)
fputs (_("none"), fp);
es_fputs (_("none"), fp);
else
fprintf (fp, "%.4s-%.2s-%.2s %.2s:%.2s:%s", t, t+4, t+6, t+9, t+11, t+13);
es_fprintf (fp, "%.4s-%.2s-%.2s %.2s:%.2s:%s",
t, t+4, t+6, t+9, t+11, t+13);
}
void
gpgsm_dump_time (ksba_isotime_t t)
{
@ -468,8 +467,10 @@ parse_dn (const unsigned char *string)
}
/* Print a DN part to STREAM or if STREAM is NULL to FP. */
static void
print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key, int translate)
print_dn_part (FILE *fp, estream_t stream,
struct dn_array_s *dn, const char *key, int translate)
{
struct dn_array_s *first_dn = dn;
@ -487,11 +488,25 @@ print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key, int translate)
next:
if (!dn->done && dn->value && *dn->value)
{
fprintf (fp, "/%s=", dn->key);
if (translate)
print_sanitized_utf8_string (fp, dn->value, '/');
if (stream)
{
es_fprintf (stream, "/%s=", dn->key);
if (translate)
es_write_sanitized_utf8_buffer (stream, dn->value,
strlen (dn->value),
"/", NULL);
else
es_write_sanitized (stream, dn->value, strlen (dn->value),
"/", NULL);
}
else
print_sanitized_string (fp, dn->value, '/');
{
fprintf (fp, "/%s=", dn->key);
if (translate)
print_sanitized_utf8_string (fp, dn->value, '/');
else
print_sanitized_string (fp, dn->value, '/');
}
}
dn->done = 1;
if (dn > first_dn && dn[-1].multivalued)
@ -506,7 +521,8 @@ print_dn_part (FILE *fp, struct dn_array_s *dn, const char *key, int translate)
/* Print all parts of a DN in a "standard" sequence. We first print
all the known parts, followed by the uncommon ones */
static void
print_dn_parts (FILE *fp, struct dn_array_s *dn, int translate)
print_dn_parts (FILE *fp, estream_t stream,
struct dn_array_s *dn, int translate)
{
const char *stdpart[] = {
"CN", "OU", "O", "STREET", "L", "ST", "C", "EMail", NULL
@ -514,11 +530,11 @@ print_dn_parts (FILE *fp, struct dn_array_s *dn, int translate)
int i;
for (i=0; stdpart[i]; i++)
print_dn_part (fp, dn, stdpart[i], translate);
print_dn_part (fp, stream, dn, stdpart[i], translate);
/* Now print the rest without any specific ordering */
for (; dn->key; dn++)
print_dn_part (fp, dn, dn->key, translate);
print_dn_part (fp, stream, dn, dn->key, translate);
}
@ -567,6 +583,53 @@ pretty_print_sexp (FILE *fp, const unsigned char *buf, size_t buflen)
gcry_sexp_release (sexp);
}
/* Print the S-Expression in BUF to extended STREAM, which has a valid
length of BUFLEN, as a human readable string in one line to FP. */
static void
pretty_es_print_sexp (estream_t fp, const unsigned char *buf, size_t buflen)
{
size_t len;
gcry_sexp_t sexp;
char *result, *p;
if ( gcry_sexp_sscan (&sexp, NULL, (const char*)buf, buflen) )
{
es_fputs (_("[Error - invalid encoding]"), fp);
return;
}
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
assert (len);
result = xtrymalloc (len);
if (!result)
{
es_fputs (_("[Error - out of core]"), fp);
gcry_sexp_release (sexp);
return;
}
len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, len);
assert (len);
for (p = result; len; len--, p++)
{
if (*p == '\n')
{
if (len > 1) /* Avoid printing the trailing LF. */
es_fputs ("\\n", fp);
}
else if (*p == '\r')
es_fputs ("\\r", fp);
else if (*p == '\v')
es_fputs ("\\v", fp);
else if (*p == '\t')
es_fputs ("\\t", fp);
else
es_putc (*p, fp);
}
xfree (result);
gcry_sexp_release (sexp);
}
void
gpgsm_print_name2 (FILE *fp, const char *name, int translate)
@ -604,7 +667,7 @@ gpgsm_print_name2 (FILE *fp, const char *name, int translate)
fputs (_("[Error - invalid DN]"), fp);
else
{
print_dn_parts (fp, dn, translate);
print_dn_parts (fp, NULL, dn, translate);
for (i=0; dn[i].key; i++)
{
xfree (dn[i].key);
@ -623,6 +686,55 @@ gpgsm_print_name (FILE *fp, const char *name)
}
/* This is avariant of gpgsm_print_name sending it output to an estream. */
void
gpgsm_es_print_name (estream_t fp, const char *name)
{
const unsigned char *s = (const unsigned char *)name;
int i;
if (!s)
{
es_fputs (_("[Error - No name]"), fp);
}
else if (*s == '<')
{
const char *s2 = strchr ( (char*)s+1, '>');
if (s2)
es_write_sanitized_utf8_buffer (fp, s + 1, s2 - (char*)s - 1,
NULL, NULL);
}
else if (*s == '(')
{
pretty_es_print_sexp (fp, s, gcry_sexp_canon_len (s, 0, NULL, NULL));
}
else if (!((*s >= '0' && *s < '9')
|| (*s >= 'A' && *s <= 'Z')
|| (*s >= 'a' && *s <= 'z')))
es_fputs (_("[Error - invalid encoding]"), fp);
else
{
struct dn_array_s *dn = parse_dn (s);
if (!dn)
es_fputs (_("[Error - invalid DN]"), fp);
else
{
print_dn_parts (NULL, fp, dn, 1);
for (i=0; dn[i].key; i++)
{
xfree (dn[i].key);
xfree (dn[i].value);
}
xfree (dn);
}
}
}
/* A cookie structure used for the memory stream. */
struct format_name_cookie
{

View File

@ -481,6 +481,7 @@ static void emergency_cleanup (void);
static int check_special_filename (const char *fname);
static int open_read (const char *filename);
static FILE *open_fwrite (const char *filename);
static estream_t open_es_fwrite (const char *filename);
static void run_protect_tool (int argc, char **argv);
@ -1570,7 +1571,7 @@ main ( int argc, char **argv)
case aDumpSecretKeys:
{
unsigned int mode;
FILE *fp;
estream_t fp;
switch (cmd)
{
@ -1585,13 +1586,12 @@ main ( int argc, char **argv)
default: BUG();
}
fp = open_fwrite (opt.outfile?opt.outfile:"-");
fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
for (sl=NULL; argc; argc--, argv++)
add_to_strlist (&sl, *argv);
gpgsm_list_keys (&ctrl, sl, fp, mode);
free_strlist(sl);
if (fp != stdout)
fclose (fp);
es_fclose (fp);
}
break;
@ -1816,6 +1816,44 @@ open_fwrite (const char *filename)
}
/* Open FILENAME for fwrite and return an extended stream. Stop with
an error message in case of problems. "-" denotes stdout and if
special filenames are allowed the given fd is opened instead.
Caller must close the returned stream. */
static estream_t
open_es_fwrite (const char *filename)
{
int fd;
estream_t fp;
if (filename[0] == '-' && !filename[1])
{
fflush (stdout);
fp = es_fdopen (dup (fileno(stdout)), "wb");
return fp;
}
fd = check_special_filename (filename);
if (fd != -1)
{
fp = es_fdopen (dup (fd), "wb");
if (!fp)
{
log_error ("es_fdopen(%d) failed: %s\n", fd, strerror (errno));
gpgsm_exit (2);
}
return fp;
}
fp = es_fopen (filename, "wb");
if (!fp)
{
log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
gpgsm_exit (2);
}
return fp;
}
static void
run_protect_tool (int argc, char **argv)
{

View File

@ -32,6 +32,7 @@
#include <ksba.h>
#include "../common/util.h"
#include "../common/errors.h"
#include "../common/estream.h"
#define MAX_DIGEST_LEN 24
@ -225,10 +226,11 @@ void gpgsm_destroy_writer (Base64Context ctx);
/*-- certdump.c --*/
void gpgsm_print_serial (FILE *fp, ksba_const_sexp_t p);
void gpgsm_print_time (FILE *fp, ksba_isotime_t t);
void gpgsm_print_serial (estream_t fp, ksba_const_sexp_t p);
void gpgsm_print_time (estream_t fp, ksba_isotime_t t);
void gpgsm_print_name2 (FILE *fp, const char *string, int translate);
void gpgsm_print_name (FILE *fp, const char *string);
void gpgsm_es_print_name (estream_t fp, const char *string);
void gpgsm_cert_log_name (const char *text, ksba_cert_t cert);
@ -261,7 +263,7 @@ int gpgsm_walk_cert_chain (ksba_cert_t start, ksba_cert_t *r_next);
int gpgsm_is_root_cert (ksba_cert_t cert);
int gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert,
ksba_isotime_t r_exptime,
int listmode, FILE *listfp,
int listmode, estream_t listfp,
unsigned int flags);
int gpgsm_basic_cert_check (ksba_cert_t cert);
@ -281,7 +283,7 @@ int gpgsm_find_cert (const char *name, ksba_sexp_t keyid, ksba_cert_t *r_cert);
/*-- keylist.c --*/
gpg_error_t gpgsm_list_keys (ctrl_t ctrl, strlist_t names,
FILE *fp, unsigned int mode);
estream_t fp, unsigned int mode);
/*-- import.c --*/
int gpgsm_import (ctrl_t ctrl, int in_fd);

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,21 @@ struct server_local_s {
};
/* Cookie definition for assuan data line output. */
static ssize_t data_line_cookie_write (void *cookie,
const void *buffer, size_t size);
static int data_line_cookie_close (void *cookie);
static es_cookie_io_functions_t data_line_cookie_functions =
{
NULL,
data_line_cookie_write,
NULL,
data_line_cookie_close
};
/* Note that it is sufficient to allocate the target string D as
long as the source string S, i.e.: strlen(s)+1; */
static void
@ -106,6 +120,37 @@ has_option (const char *line, const char *name)
}
/* A write handler used by es_fopencookie to write assuan data
lines. */
static ssize_t
data_line_cookie_write (void *cookie, const void *buffer, size_t size)
{
assuan_context_t ctx = cookie;
if (assuan_send_data (ctx, buffer, size))
{
errno = EIO;
return -1;
}
return size;
}
static int
data_line_cookie_close (void *cookie)
{
assuan_context_t ctx = cookie;
if (assuan_send_data (ctx, NULL, 0))
{
errno = EIO;
return -1;
}
return 0;
}
static void
close_message_fd (ctrl_t ctrl)
{
@ -706,7 +751,7 @@ static int
do_listkeys (assuan_context_t ctx, char *line, int mode)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
FILE *fp;
estream_t fp;
char *p;
strlist_t list, sl;
unsigned int listmode;
@ -737,17 +782,20 @@ do_listkeys (assuan_context_t ctx, char *line, int mode)
if (ctrl->server_local->list_to_output)
{
if ( assuan_get_output_fd (ctx) == -1 )
int outfd = assuan_get_output_fd (ctx);
if ( outfd == -1 )
return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
fp = fdopen (assuan_get_output_fd (ctx), "w");
fp = es_fdopen ( dup (outfd), "w");
if (!fp)
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
return set_error (GPG_ERR_ASS_GENERAL, "es_fdopen() failed");
}
else
{
fp = assuan_get_data_fp (ctx);
fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
if (!fp)
return set_error (GPG_ERR_ASS_GENERAL, "no data stream");
return set_error (GPG_ERR_ASS_GENERAL,
"error setting up a data stream");
}
ctrl->with_colons = 1;
@ -758,11 +806,9 @@ do_listkeys (assuan_context_t ctx, char *line, int mode)
listmode |= (1<<7);
err = gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode);
free_strlist (list);
es_fclose (fp);
if (ctrl->server_local->list_to_output)
{
fclose (fp);
assuan_close_output_fd (ctx);
}
assuan_close_output_fd (ctx);
return err;
}