1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Merge branch 'master' into switch-to-gpgk

--
This commit is contained in:
Werner Koch 2019-03-18 19:41:07 +01:00
commit a52d883fdb
No known key found for this signature in database
GPG key ID: E3FDFF218E45B72B
237 changed files with 21268 additions and 4575 deletions

View file

@ -83,7 +83,7 @@ common_sources = \
localename.c \
session-env.c session-env.h \
userids.c userids.h \
openpgp-oid.c \
openpgp-oid.c openpgp-s2k.c \
ssh-utils.c ssh-utils.h \
agent-opt.c \
helpfile.c \

View file

@ -408,7 +408,7 @@ static void
store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
{
/* TODO: replace this dummy function with a rea one
* and fix the probelms IRIX has with (ALIAS_DEV)arg..
* and fix the problems IRIX has with (ALIAS_DEV)arg..
* used as lvalue
*/
(void)arg;
@ -439,7 +439,7 @@ ignore_invalid_option_p (ARGPARSE_ARGS *arg, const char *keyword)
/* Add the keywords up to the next LF to the list of to be ignored
options. After returning FP will either be at EOF or the next
character read wll be the first of a new line. The function
character read will be the first of a new line. The function
returns 0 on success or true on malloc failure. */
static int
ignore_invalid_option_add (ARGPARSE_ARGS *arg, FILE *fp)
@ -1280,7 +1280,7 @@ long_opt_strlen( ARGPARSE_OPTS *o )
* this option
* - a description,ine which starts with a '@' and is followed by
* any other characters is printed as is; this may be used for examples
* ans such.
* and such.
* - A description which starts with a '|' outputs the string between this
* bar and the next one as arguments of the long option.
*/

View file

@ -185,7 +185,7 @@ typedef enum
if no real recipient has been given. */
AUDIT_SESSION_KEY, /* string */
/* Mark the creation or availibility of the session key. The
/* Mark the creation or availability of the session key. The
parameter is the algorithm ID. */
AUDIT_ENCRYPTED_TO, /* cert, err */

View file

@ -177,7 +177,7 @@ bin2hexcolon (const void *buffer, size_t length, char *stringbuf)
string or a white space character. The function makes sure that
the resulting string in BUFFER is terminated by a Nul byte. Note
that the returned string may include embedded Nul bytes; the extra
Nul byte at the end is used to make sure tha the result can always
Nul byte at the end is used to make sure that the result can always
be used as a C-string.
BUFSIZE is the available length of BUFFER; if the converted result

View file

@ -140,7 +140,7 @@
you pass (0) instead of (-1) the function does not wait in case the
file is already locked but returns -1 and sets ERRNO to EACCES.
Any other positive value for the second parameter is considered a
timeout valuie in milliseconds.
timeout value in milliseconds.
To release the lock you call:

View file

@ -53,6 +53,7 @@ typedef struct
exec_tool_status_cb_t status_cb;
void *status_cb_value;
int cont;
int quiet;
size_t used;
size_t buffer_size;
char *buffer;
@ -110,6 +111,8 @@ read_and_log_stderr (read_and_log_buffer_t *state, es_poll_t *fderr)
state->status_cb (state->status_cb_value,
state->buffer + 9, rest);
}
else if (state->quiet)
;
else if (!state->cont
&& !strncmp (state->buffer, pname, len)
&& strlen (state->buffer) > strlen (pname)
@ -331,10 +334,16 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
int count;
read_and_log_buffer_t fderrstate;
struct copy_buffer *cpbuf_in = NULL, *cpbuf_out = NULL, *cpbuf_extra = NULL;
int quiet = 0;
int dummy_exitcode;
memset (fds, 0, sizeof fds);
memset (&fderrstate, 0, sizeof fderrstate);
/* If the first argument to the program is "--quiet" avoid all extra
* diagnostics. */
quiet = (argv && argv[0] && !strcmp (argv[0], "--quiet"));
cpbuf_in = xtrymalloc (sizeof *cpbuf_in);
if (cpbuf_in == NULL)
{
@ -360,6 +369,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
copy_buffer_init (cpbuf_extra);
fderrstate.pgmname = pgmname;
fderrstate.quiet = quiet;
fderrstate.status_cb = status_cb;
fderrstate.status_cb_value = status_cb_value;
fderrstate.buffer_size = 256;
@ -375,7 +385,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
err = gnupg_create_outbound_pipe (extrapipe, &extrafp, 1);
if (err)
{
log_error ("error running outbound pipe for extra fp: %s\n",
log_error ("error creating outbound pipe for extra fp: %s\n",
gpg_strerror (err));
goto leave;
}
@ -411,7 +421,8 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
argv[argsaveidx] = argsave;
if (err)
{
log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
if (!quiet)
log_error ("error running '%s': %s\n", pgmname, gpg_strerror (err));
goto leave;
}
@ -535,7 +546,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
es_fclose (outfp); outfp = NULL;
es_fclose (errfp); errfp = NULL;
err = gnupg_wait_process (pgmname, pid, 1, NULL);
err = gnupg_wait_process (pgmname, pid, 1, quiet? &dummy_exitcode : NULL);
pid = (pid_t)(-1);
leave:
@ -547,7 +558,7 @@ gnupg_exec_tool_stream (const char *pgmname, const char *argv[],
es_fclose (outfp);
es_fclose (errfp);
if (pid != (pid_t)(-1))
gnupg_wait_process (pgmname, pid, 1, NULL);
gnupg_wait_process (pgmname, pid, 1, quiet? &dummy_exitcode : NULL);
gnupg_release_process (pid);
copy_buffer_shred (cpbuf_in);

View file

@ -68,8 +68,8 @@
/*-- End configurable part. --*/
/* The size of the iobuffers. This can be chnages using the
* iobuf_set_buffer_size fucntion. */
/* The size of the iobuffers. This can be changed using the
* iobuf_set_buffer_size function. */
static unsigned int iobuf_buffer_size = DEFAULT_IOBUF_BUFFER_SIZE;
@ -878,9 +878,9 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
}
else if (c == 255)
{
a->size = (size_t)iobuf_get (chain) << 24;
a->size |= iobuf_get (chain) << 16;
a->size |= iobuf_get (chain) << 8;
a->size = iobuf_get_noeof (chain) << 24;
a->size |= iobuf_get_noeof (chain) << 16;
a->size |= iobuf_get_noeof (chain) << 8;
if ((c = iobuf_get (chain)) == -1)
{
log_error ("block_filter: invalid 4 byte length\n");
@ -2262,6 +2262,7 @@ iobuf_copy (iobuf_t dest, iobuf_t source)
size_t nread;
size_t nwrote = 0;
size_t max_read = 0;
int err;
assert (source->use == IOBUF_INPUT || source->use == IOBUF_INPUT_TEMP);
@ -2278,6 +2279,9 @@ iobuf_copy (iobuf_t dest, iobuf_t source)
/* EOF. */
break;
if (nread > max_read)
max_read = nread;
err = iobuf_write (dest, temp, nread);
if (err)
break;
@ -2285,7 +2289,8 @@ iobuf_copy (iobuf_t dest, iobuf_t source)
}
/* Burn the buffer. */
wipememory (temp, sizeof (temp));
if (max_read)
wipememory (temp, max_read);
xfree (temp);
return nwrote;
@ -2610,12 +2615,50 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
}
p = buffer;
while ((c = iobuf_get (a)) != -1)
while (1)
{
*p++ = c;
nbytes++;
if (c == '\n')
break;
if (!a->nofast && a->d.start < a->d.len && nbytes < length - 1)
/* Fast path for finding '\n' by using standard C library's optimized
memchr. */
{
unsigned size = a->d.len - a->d.start;
byte *newline_pos;
if (size > length - 1 - nbytes)
size = length - 1 - nbytes;
newline_pos = memchr (a->d.buf + a->d.start, '\n', size);
if (newline_pos)
{
/* Found newline, copy buffer and return. */
size = (newline_pos - (a->d.buf + a->d.start)) + 1;
memcpy (p, a->d.buf + a->d.start, size);
p += size;
nbytes += size;
a->d.start += size;
a->nbytes += size;
break;
}
else
{
/* No newline, copy buffer and continue. */
memcpy (p, a->d.buf + a->d.start, size);
p += size;
nbytes += size;
a->d.start += size;
a->nbytes += size;
}
}
else
{
c = iobuf_readbyte (a);
if (c == -1)
break;
*p++ = c;
nbytes++;
if (c == '\n')
break;
}
if (nbytes == length - 1)
/* We don't have enough space to add a \n and a \0. Increase

View file

@ -173,11 +173,12 @@ is_valid_mailbox (const char *name)
/* Return the mailbox (local-part@domain) form a standard user id.
All plain ASCII characters in the result are converted to
lowercase. Caller must free the result. Returns NULL if no valid
mailbox was found (or we are out of memory). */
* All plain ASCII characters in the result are converted to
* lowercase. If SUBADDRESS is 1, '+' denoted sub-addresses are not
* included in the result. Caller must free the result. Returns NULL
* if no valid mailbox was found (or we are out of memory). */
char *
mailbox_from_userid (const char *userid)
mailbox_from_userid (const char *userid, int subaddress)
{
const char *s, *s_end;
size_t len;
@ -226,6 +227,29 @@ mailbox_from_userid (const char *userid)
else
errno = EINVAL;
if (result && subaddress == 1)
{
char *atsign, *plus;
if ((atsign = strchr (result, '@')))
{
/* We consider a subaddress only if there is a single '+'
* in the local part and the '+' is not the first or last
* character. */
*atsign = 0;
if ((plus = strchr (result, '+'))
&& !strchr (plus+1, '+')
&& result != plus
&& plus[1] )
{
*atsign = '@';
memmove (plus, atsign, strlen (atsign)+1);
}
else
*atsign = '@';
}
}
return result? ascii_strlwr (result): NULL;
}

View file

@ -22,7 +22,7 @@
int has_invalid_email_chars (const void *buffer, size_t length);
int is_valid_mailbox (const char *name);
int is_valid_mailbox_mem (const void *buffer, size_t length);
char *mailbox_from_userid (const char *userid);
char *mailbox_from_userid (const char *userid, int subaddress);
int is_valid_user_id (const char *uid);
int is_valid_domain_name (const char *string);

View file

@ -328,6 +328,82 @@ make_printable_string (const void *p, size_t n, int delim )
}
/* Decode the C formatted string SRC and return the result in a newly
* allocated buffer. In error returns NULL and sets ERRNO. */
char *
decode_c_string (const char *src)
{
char *buffer, *dst;
int val;
/* The converted string will never be larger than the original
string. */
buffer = dst = xtrymalloc (strlen (src) + 1);
if (!buffer)
return NULL;
while (*src)
{
if (*src != '\\')
{
*dst++ = *src++;
continue;
}
#define DECODE_ONE(_m,_r) case _m: src += 2; *dst++ = _r; break;
switch (src[1])
{
DECODE_ONE ('n', '\n');
DECODE_ONE ('r', '\r');
DECODE_ONE ('f', '\f');
DECODE_ONE ('v', '\v');
DECODE_ONE ('b', '\b');
DECODE_ONE ('t', '\t');
DECODE_ONE ('\\', '\\');
DECODE_ONE ('\'', '\'');
DECODE_ONE ('\"', '\"');
case 'x':
val = hextobyte (src+2);
if (val == -1) /* Bad coding, keep as is. */
{
*dst++ = *src++;
*dst++ = *src++;
if (*src)
*dst++ = *src++;
if (*src)
*dst++ = *src++;
}
else if (!val)
{
/* A binary zero is not representable in a C string thus
* we keep the C-escaping. Note that this will also
* never be larger than the source string. */
*dst++ = '\\';
*dst++ = '0';
src += 4;
}
else
{
*(unsigned char *)dst++ = val;
src += 4;
}
break;
default: /* Bad coding; keep as is.. */
*dst++ = *src++;
*dst++ = *src++;
break;
}
#undef DECODE_ONE
}
*dst++ = 0;
return buffer;
}
/* Check whether (BUF,LEN) is valid header for an OpenPGP compressed
* packet. LEN should be at least 6. */
static int

View file

@ -49,6 +49,22 @@
#include "mischelp.h"
void
wipememory (void *ptr, size_t len)
{
#if defined(HAVE_W32_SYSTEM) && defined(SecureZeroMemory)
SecureZeroMemory (ptr, len);
#elif defined(HAVE_EXPLICIT_BZERO)
explicit_bzero (ptr, len);
#else
/* Prevent compiler from optimizing away the call to memset by accessing
memset through volatile pointer. */
static void *(*volatile memset_ptr)(void *, int, size_t) = (void *)memset;
memset_ptr (ptr, 0, len);
#endif
}
/* Check whether the files NAME1 and NAME2 are identical. This is for
example achieved by comparing the inode numbers of the files. */
int

View file

@ -47,15 +47,9 @@ time_t timegm (struct tm *tm);
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define DIMof(type,member) DIM(((type *)0)->member)
/* To avoid that a compiler optimizes certain memset calls away, these
macros may be used instead. */
#define wipememory2(_ptr,_set,_len) do { \
volatile char *_vptr=(volatile char *)(_ptr); \
size_t _vlen=(_len); \
while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
} while(0)
#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
/* To avoid that a compiler optimizes certain memset calls away,
wipememory function may be used instead. */
void wipememory(void *ptr, size_t len);
/* Include hacks which are mainly required for Slowaris. */
#ifdef GNUPG_COMMON_NEED_AFLOCAL

View file

@ -30,7 +30,7 @@ cat <<EOF
* gnupg_strerror:
* @err: Error code
*
* This function returns a textual representaion of the given
* This function returns a textual representation of the given
* errorcode. If this is an unknown value, a string with the value
* is returned (Beware: it is hold in a static buffer).
*

View file

@ -26,7 +26,7 @@ cat <<EOF
* gnupg_error_token:
* @err: Error code
*
* This function returns a textual representaion of the given
* This function returns a textual representation of the given
* errorcode. If this is an unknown value, a static string is returned.
* This function differs from gnupg_strerror that it yields the string
* representation of the macro which is never subject to i18n.

View file

@ -184,48 +184,36 @@ openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi)
}
/* Return a malloced string represenation of the OID in the opaque MPI
A. In case of an error NULL is returned and ERRNO is set. */
/* Return a malloced string representation of the OID in the buffer
* (BUF,LEN). In case of an error NULL is returned and ERRNO is set.
* As per OpenPGP spec the first byte of the buffer is the length of
* the rest; the function performs a consistency check. */
char *
openpgp_oid_to_str (gcry_mpi_t a)
openpgp_oidbuf_to_str (const unsigned char *buf, size_t len)
{
const unsigned char *buf;
size_t length;
unsigned int lengthi;
char *string, *p;
int n = 0;
unsigned long val, valmask;
valmask = (unsigned long)0xfe << (8 * (sizeof (valmask) - 1));
if (!a
|| !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)
|| !(buf = gcry_mpi_get_opaque (a, &lengthi)))
{
gpg_err_set_errno (EINVAL);
return NULL;
}
buf = gcry_mpi_get_opaque (a, &lengthi);
length = (lengthi+7)/8;
/* The first bytes gives the length; check consistency. */
if (!length || buf[0] != length -1)
if (!len || buf[0] != len -1)
{
gpg_err_set_errno (EINVAL);
return NULL;
}
/* Skip length byte. */
length--;
len--;
buf++;
/* To calculate the length of the string we can safely assume an
upper limit of 3 decimal characters per byte. Two extra bytes
account for the special first octect */
string = p = xtrymalloc (length*(1+3)+2+1);
account for the special first octet */
string = p = xtrymalloc (len*(1+3)+2+1);
if (!string)
return NULL;
if (!length)
if (!len)
{
*p = 0;
return string;
@ -237,7 +225,7 @@ openpgp_oid_to_str (gcry_mpi_t a)
p += sprintf (p, "1.%d", buf[n]-40);
else {
val = buf[n] & 0x7f;
while ( (buf[n]&0x80) && ++n < length )
while ( (buf[n]&0x80) && ++n < len )
{
if ( (val & valmask) )
goto badoid; /* Overflow. */
@ -250,10 +238,10 @@ openpgp_oid_to_str (gcry_mpi_t a)
sprintf (p, "2.%lu", val);
p += strlen (p);
}
for (n++; n < length; n++)
for (n++; n < len; n++)
{
val = buf[n] & 0x7f;
while ( (buf[n]&0x80) && ++n < length )
while ( (buf[n]&0x80) && ++n < len )
{
if ( (val & valmask) )
goto badoid; /* Overflow. */
@ -278,6 +266,35 @@ openpgp_oid_to_str (gcry_mpi_t a)
}
/* Return a malloced string representation of the OID in the opaque
* MPI A. In case of an error NULL is returned and ERRNO is set. */
char *
openpgp_oid_to_str (gcry_mpi_t a)
{
const unsigned char *buf;
unsigned int lengthi;
if (!a
|| !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)
|| !(buf = gcry_mpi_get_opaque (a, &lengthi)))
{
gpg_err_set_errno (EINVAL);
return NULL;
}
buf = gcry_mpi_get_opaque (a, &lengthi);
return openpgp_oidbuf_to_str (buf, (lengthi+7)/8);
}
/* Return true if (BUF,LEN) represents the OID for Ed25519. */
int
openpgp_oidbuf_is_ed25519 (const void *buf, size_t len)
{
return (buf && len == DIM (oid_ed25519)
&& !memcmp (buf, oid_ed25519, DIM (oid_ed25519)));
}
/* Return true if A represents the OID for Ed25519. */
int
@ -285,32 +302,36 @@ openpgp_oid_is_ed25519 (gcry_mpi_t a)
{
const unsigned char *buf;
unsigned int nbits;
size_t n;
if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
return 0;
buf = gcry_mpi_get_opaque (a, &nbits);
n = (nbits+7)/8;
return (n == DIM (oid_ed25519)
&& !memcmp (buf, oid_ed25519, DIM (oid_ed25519)));
return openpgp_oidbuf_is_ed25519 (buf, (nbits+7)/8);
}
/* Return true if (BUF,LEN) represents the OID for Curve25519. */
int
openpgp_oidbuf_is_cv25519 (const void *buf, size_t len)
{
return (buf && len == DIM (oid_cv25519)
&& !memcmp (buf, oid_cv25519, DIM (oid_cv25519)));
}
/* Return true if the MPI A represents the OID for Curve25519. */
int
openpgp_oid_is_cv25519 (gcry_mpi_t a)
{
const unsigned char *buf;
unsigned int nbits;
size_t n;
if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
return 0;
buf = gcry_mpi_get_opaque (a, &nbits);
n = (nbits+7)/8;
return (n == DIM (oid_cv25519)
&& !memcmp (buf, oid_cv25519, DIM (oid_cv25519)));
return openpgp_oidbuf_is_cv25519 (buf, (nbits+7)/8);
}

67
common/openpgp-s2k.c Normal file
View file

@ -0,0 +1,67 @@
/* openpgp-s2ks.c - OpenPGP S2K helper functions
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
* 2005, 2006 Free Software Foundation, Inc.
* Copyright (C) 2010, 2019 g10 Code GmbH
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - 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.
*
* or both in parallel, as here.
*
* This file 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, see <https://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <assert.h>
#include "util.h"
#include "openpgpdefs.h"
/* Pack an s2k iteration count into the form specified in RFC-48800.
* If we're in between valid values, round up. */
unsigned char
encode_s2k_iterations (int iterations)
{
unsigned char c=0;
unsigned char result;
unsigned int count;
if (iterations <= 1024)
return 0; /* Command line arg compatibility. */
if (iterations >= 65011712)
return 255;
/* Need count to be in the range 16-31 */
for (count=iterations>>6; count>=32; count>>=1)
c++;
result = (c<<4)|(count-16);
if (S2K_DECODE_COUNT(result) < iterations)
result++;
return result;
}

View file

@ -196,5 +196,19 @@ typedef enum
}
compress_algo_t;
/* Limits to be used for static arrays. */
#define OPENPGP_MAX_NPKEY 5 /* Maximum number of public key parameters. */
#define OPENPGP_MAX_NSKEY 7 /* Maximum number of secret key parameters. */
#define OPENPGP_MAX_NSIG 2 /* Maximum number of signature parameters. */
#define OPENPGP_MAX_NENC 2 /* Maximum number of encryption parameters. */
/* Decode an rfc4880 encoded S2K count. */
#define S2K_DECODE_COUNT(_val) ((16ul + ((_val) & 15)) << (((_val) >> 4) + 6))
/*--openpgp-s2k.c --*/
unsigned char encode_s2k_iterations (int iterations);
#endif /*GNUPG_COMMON_OPENPGPDEFS_H*/

View file

@ -37,16 +37,16 @@
/* Create a newly alloced string from STRING with all spaces and
control characters converted to plus signs or %xx sequences. The
function returns the new string or NULL in case of a malloc
failure.
Note that we also escape the quote character to work around a bug
in the mingw32 runtime which does not correcty handle command line
quoting. We correctly double the quote mark when calling a program
(i.e. gpg-protect-tool), but the pre-main code does not notice the
double quote as an escaped quote. We do this also on POSIX systems
for consistency. */
* control characters converted to plus signs or %xx sequences. The
* function returns the new string or NULL in case of a malloc
* failure.
*
* Note that this fucntion also escapes the quote character to work
* around a bug in the mingw32 runtime which does not correctly handle
* command line quoting. We correctly double the quote mark when
* calling a program (i.e. gpg-protect-tool), but the pre-main code
* does not notice the double quote as an escaped quote. We do this
* also on POSIX systems for consistency. */
char *
percent_plus_escape (const char *string)
{
@ -87,19 +87,36 @@ percent_plus_escape (const char *string)
}
/* Create a newly alloced string from (DATA,DATALEN) with embedded
* Nuls quoted as %00. The standard percent unescaping can be
* used to reverse this encoding. */
/* Create a newly malloced string from (DATA,DATALEN) with embedded
* nuls quoted as %00. The standard percent unescaping can be used to
* reverse this encoding. With PLUS_ESCAPE set plus-escaping (spaces
* are replaced by a '+') and escaping of characters with values less
* than 0x20 is used. If PREFIX is not NULL it will be prepended to
* the output in standard escape format; that is PLUS_ESCAPING is
* ignored for PREFIX. */
char *
percent_data_escape (const void *data, size_t datalen)
percent_data_escape (int plus_escape, const char *prefix,
const void *data, size_t datalen)
{
char *buffer, *p;
const char *s;
size_t n, length;
const unsigned char *s;
size_t n;
size_t length = 1;
for (length=1, s=data, n=datalen; n; s++, n--)
if (prefix)
{
if (!*s || *s == '%')
for (s = prefix; *s; s++)
{
if (*s == '%' || *s < 0x20)
length += 3;
else
length++;
}
}
for (s=data, n=datalen; n; s++, n--)
{
if (!*s || *s == '%' || (plus_escape && (*s < ' ' || *s == '+')))
length += 3;
else
length++;
@ -109,6 +126,20 @@ percent_data_escape (const void *data, size_t datalen)
if (!buffer)
return NULL;
if (prefix)
{
for (s = prefix; *s; s++)
{
if (*s == '%' || *s < 0x20)
{
snprintf (p, 4, "%%%02X", *s);
p += 3;
}
else
*p++ = *s;
}
}
for (s=data, n=datalen; n; s++, n--)
{
if (!*s)
@ -121,13 +152,21 @@ percent_data_escape (const void *data, size_t datalen)
memcpy (p, "%25", 3);
p += 3;
}
else if (plus_escape && *s == ' ')
{
*p++ = '+';
}
else if (plus_escape && (*s < ' ' || *s == '+'))
{
snprintf (p, 4, "%%%02X", *s);
p += 3;
}
else
*p++ = *s;
}
*p = 0;
return buffer;
}

View file

@ -30,8 +30,22 @@
#include <config.h>
#include <string.h>
#include "server-help.h"
#include "util.h"
#include "server-help.h"
static GPGRT_INLINE gpg_error_t
my_error (int e)
{
return gpg_err_make (default_errsource, (e));
}
static GPGRT_INLINE gpg_error_t
my_error_from_syserror (void)
{
return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
}
/* Skip over options in LINE.
@ -114,6 +128,40 @@ has_option_name (const char *line, const char *name)
}
/* Parse an option with the format "--NAME=VALUE" which must occur in
* LINE before a double-dash. LINE is written to but not modified by
* this function. If the option is found and has a value the value is
* stored as a malloced string at R_VALUE. If the option was not
* found or an error occurred NULL is stored there. Note that
* currently the value must be a string without any space; we may
* eventually update this function to allow for a quoted value. */
gpg_error_t
get_option_value (char *line, const char *name, char **r_value)
{
char *p, *pend;
int c;
*r_value = NULL;
p = (char*)has_option_name (line, name);
if (!p || p >= skip_options (line))
return 0;
if (*p != '=' || !p[1] || spacep (p+1))
return my_error (GPG_ERR_INV_ARG);
p++;
for (pend = p; *pend && !spacep (pend); pend++)
;
c = *pend;
*pend = 0;
*r_value = xtrystrdup (p);
*pend = c;
if (!p)
return my_error_from_syserror ();
return 0;
}
/* Return a pointer to the argument of the option with NAME. If such
an option is not given, NULL is returned. */
char *

View file

@ -55,6 +55,14 @@ int has_leading_option (const char *line, const char *name);
or a space. */
const char *has_option_name (const char *line, const char *name);
/* Same as has_option_name but ignores all options after a "--" and
* does not return a const char ptr. */
char *has_leading_option_name (char *line, const char *name);
/* Parse an option with the format "--NAME=VALUE" and return the value
* as a malloced string. */
gpg_error_t get_option_value (char *line, const char *name, char **r_value);
/* Return a pointer to the argument of the option with NAME. If such
an option is not given, NULL is returned. */
char *option_value (const char *line, const char *name);

View file

@ -105,7 +105,7 @@ smatch (unsigned char const **buf, size_t buflen, const char *token)
}
/* Format VALUE for use as the length indicatior of an S-expression.
The caller needs to provide a buffer HELP_BUFFER wth a length of
The caller needs to provide a buffer HELP_BUFFER with a length of
HELP_BUFLEN. The return value is a pointer into HELP_BUFFER with
the formatted length string. The colon and a trailing nul are
appended. HELP_BUFLEN must be at least 3 - a more useful value is

View file

@ -303,7 +303,7 @@ make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
for (; n > 1; n -=2, s += 2)
*p++ = xtoi_2 (s);
*p++ = ')';
*p = 0; /* (Not really neaded.) */
*p = 0; /* (Not really needed.) */
return buf;
}
@ -577,3 +577,61 @@ get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen)
gcry_sexp_release (sexp);
return algo;
}
/* Given the public key S_PKEY, return a new buffer with a descriptive
* string for its algorithm. This function may return NULL on memory
* error. */
char *
pubkey_algo_string (gcry_sexp_t s_pkey)
{
const char *prefix;
gcry_sexp_t l1;
char *algoname;
int algo;
char *result;
l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
if (!l1)
return xtrystrdup ("E_no_key");
{
gcry_sexp_t l_tmp = gcry_sexp_cadr (l1);
gcry_sexp_release (l1);
l1 = l_tmp;
}
algoname = gcry_sexp_nth_string (l1, 0);
gcry_sexp_release (l1);
if (!algoname)
return xtrystrdup ("E_no_algo");
algo = gcry_pk_map_name (algoname);
switch (algo)
{
case GCRY_PK_RSA: prefix = "rsa"; break;
case GCRY_PK_ELG: prefix = "elg"; break;
case GCRY_PK_DSA: prefix = "dsa"; break;
case GCRY_PK_ECC: prefix = ""; break;
default: prefix = NULL; break;
}
if (prefix && *prefix)
result = xtryasprintf ("%s%u", prefix, gcry_pk_get_nbits (s_pkey));
else if (prefix)
{
const char *curve = gcry_pk_get_curve (s_pkey, 0, NULL);
const char *name = openpgp_oid_to_curve
(openpgp_curve_to_oid (curve, NULL), 0);
if (name)
result = xtrystrdup (name);
else if (curve)
result = xtryasprintf ("X_%s", curve);
else
result = xtrystrdup ("E_unknown");
}
else
result = xtryasprintf ("X_algo_%d", algo);
xfree (algoname);
return result;
}

View file

@ -75,7 +75,7 @@
/* Name of the socket to be used. This is a kludge to keep on using
the existsing code despite that we only support a standard socket. */
the existing code despite that we only support a standard socket. */
static char *default_gpg_agent_info;
@ -246,6 +246,7 @@ agent_open (assuan_context_t *ctx)
#ifdef SPWQ_USE_LOGGING
log_error (_("no gpg-agent running in this session\n"));
#endif
*ctx = NULL;
return SPWQ_NO_AGENT;
}

View file

@ -247,7 +247,7 @@ get_fingerprint (gcry_sexp_t key, int algo,
goto leave;
}
strncpy (*r_fpr, algo_name, strlen (algo_name));
memcpy (*r_fpr, algo_name, strlen (algo_name));
fpr = (char *) *r_fpr + strlen (algo_name);
*fpr++ = ':';

View file

@ -34,6 +34,10 @@
#include "status.h"
#include "status-codes.h"
/* The stream to output the status information. Output is disabled if
* this is NULL. */
static estream_t statusfp;
/* Return the status string for code NO. */
const char *
@ -47,6 +51,60 @@ get_status_string ( int no )
}
/* Set a global status FD. */
void
gnupg_set_status_fd (int fd)
{
static int last_fd = -1;
if (fd != -1 && last_fd == fd)
return;
if (statusfp && statusfp != es_stdout && statusfp != es_stderr)
es_fclose (statusfp);
statusfp = NULL;
if (fd == -1)
return;
if (fd == 1)
statusfp = es_stdout;
else if (fd == 2)
statusfp = es_stderr;
else
statusfp = es_fdopen (fd, "w");
if (!statusfp)
{
log_fatal ("can't open fd %d for status output: %s\n",
fd, gpg_strerror (gpg_error_from_syserror ()));
}
last_fd = fd;
}
/* Write a status line with code NO followed by the output of the
* printf style FORMAT. The caller needs to make sure that LFs and
* CRs are not printed. */
void
gnupg_status_printf (int no, const char *format, ...)
{
va_list arg_ptr;
if (!statusfp)
return; /* Not enabled. */
es_fputs ("[GNUPG:] ", statusfp);
es_fputs (get_status_string (no), statusfp);
if (format)
{
es_putc (' ', statusfp);
va_start (arg_ptr, format);
es_vfprintf (statusfp, format, arg_ptr);
va_end (arg_ptr);
}
es_putc ('\n', statusfp);
}
const char *
get_inv_recpsgnr_code (gpg_error_t err)
{

View file

@ -163,6 +163,10 @@ enum
const char *get_status_string (int code);
void gnupg_set_status_fd (int fd);
void gnupg_status_printf (int no, const char *format,
...) GPGRT_ATTR_PRINTF(2,3);
const char *get_inv_recpsgnr_code (gpg_error_t err);

View file

@ -810,6 +810,19 @@ ascii_strlwr (char *s)
return s;
}
/* Upcase all ASCII characters in S. */
char *
ascii_strupr (char *s)
{
char *p = s;
for (p=s; *p; p++ )
if (isascii (*p) && *p >= 'a' && *p <= 'z')
*p &= ~0x20;
return s;
}
int
ascii_strcasecmp( const char *a, const char *b )
{
@ -1400,7 +1413,7 @@ parse_version_number (const char *s, int *number)
/* This function breaks up the complete string-representation of the
version number S, which is of the following struture: <major
version number S, which is of the following structure: <major
number>.<minor number>[.<micro number>]<patch level>. The major,
minor, and micro number components will be stored in *MAJOR, *MINOR
and *MICRO. If MICRO is not given 0 is used instead.

View file

@ -76,6 +76,7 @@ int ascii_islower (int c);
int ascii_toupper (int c);
int ascii_tolower (int c);
char *ascii_strlwr (char *s);
char *ascii_strupr (char *s);
int ascii_strcasecmp( const char *a, const char *b );
int ascii_strncasecmp (const char *a, const char *b, size_t n);
int ascii_memcasecmp( const void *a, const void *b, size_t n );

View file

@ -551,14 +551,13 @@ gnupg_tmpfile (void)
void
gnupg_reopen_std (const char *pgmname)
{
#if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
struct stat statbuf;
#ifdef F_GETFD
int did_stdin = 0;
int did_stdout = 0;
int did_stderr = 0;
FILE *complain;
if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
if (fcntl (STDIN_FILENO, F_GETFD) == -1 && errno ==EBADF)
{
if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
did_stdin = 1;
@ -566,7 +565,7 @@ gnupg_reopen_std (const char *pgmname)
did_stdin = 2;
}
if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
if (fcntl (STDOUT_FILENO, F_GETFD) == -1 && errno == EBADF)
{
if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
did_stdout = 1;
@ -574,7 +573,7 @@ gnupg_reopen_std (const char *pgmname)
did_stdout = 2;
}
if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
if (fcntl (STDERR_FILENO, F_GETFD)==-1 && errno==EBADF)
{
if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
did_stderr = 1;
@ -607,7 +606,7 @@ gnupg_reopen_std (const char *pgmname)
if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
exit (3);
#else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
#else /* !F_GETFD */
(void)pgmname;
#endif
}

View file

@ -131,7 +131,7 @@ test_close_all_fds (void)
free (array);
/* Now let's check the realloc we use. We do this and the next
tests only if we are allowed to open enought descriptors. */
tests only if we are allowed to open enough descriptors. */
if (get_max_fds () > 32)
{
int except[] = { 20, 23, 24, -1 };

View file

@ -25,6 +25,9 @@
#include "util.h"
#include "mbox-util.h"
#define PGM "t-mbox-util"
#define pass() do { ; } while(0)
#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\
__FILE__,__LINE__, (a)); \
@ -32,6 +35,10 @@
} while(0)
static int verbose;
static int debug;
static void
run_mbox_test (void)
{
@ -76,7 +83,86 @@ run_mbox_test (void)
for (idx=0; testtbl[idx].userid; idx++)
{
char *mbox = mailbox_from_userid (testtbl[idx].userid);
char *mbox = mailbox_from_userid (testtbl[idx].userid, 0);
if (!testtbl[idx].mbox)
{
if (mbox)
fail (idx);
}
else if (!mbox)
fail (idx);
else if (strcmp (mbox, testtbl[idx].mbox))
fail (idx);
xfree (mbox);
}
}
static void
run_mbox_no_sub_test (void)
{
static struct
{
const char *userid;
const char *mbox;
} testtbl[] =
{
{ "foo+bar@example.org", "foo@example.org" },
{ "Werner Koch <wk@gnupg.org>", "wk@gnupg.org" },
{ "<wk@gnupg.org>", "wk@gnupg.org" },
{ "wk@gnupg.org", "wk@gnupg.org" },
{ "wk@gnupg.org ", NULL },
{ " wk@gnupg.org", NULL },
{ "Werner Koch (test) <wk@gnupg.org>", "wk@gnupg.org" },
{ "Werner Koch <wk@gnupg.org> (test)", "wk@gnupg.org" },
{ "Werner Koch <wk@gnupg.org (test)", NULL },
{ "Werner Koch <wk@gnupg.org >", NULL },
{ "Werner Koch <wk@gnupg.org", NULL },
{ "", NULL },
{ "@", NULL },
{ "bar <>", NULL },
{ "<foo@example.org>", "foo@example.org" },
{ "<foo.@example.org>", "foo.@example.org" },
{ "<.foo.@example.org>", ".foo.@example.org" },
{ "<foo..@example.org>", "foo..@example.org" },
{ "<foo..bar@example.org>", "foo..bar@example.org" },
{ "<foo@example.org.>", NULL },
{ "<foo@example..org>", NULL },
{ "<foo@.>", NULL },
{ "<@example.org>", NULL },
{ "<foo@@example.org>", NULL },
{ "<@foo@example.org>", NULL },
{ "<foo@example.org> ()", "foo@example.org" },
{ "<fo()o@example.org> ()", "fo()o@example.org" },
{ "<fo()o@example.org> ()", "fo()o@example.org" },
{ "fo()o@example.org", NULL},
{ "Mr. Foo <foo@example.org><bar@example.net>", "foo@example.org"},
{ "foo+bar@example.org", "foo@example.org" },
{ "foo++bar@example.org", "foo++bar@example.org" },
{ "foo++@example.org", "foo++@example.org" },
{ "foo+@example.org", "foo+@example.org" },
{ "+foo@example.org", "+foo@example.org" },
{ "++foo@example.org", "++foo@example.org" },
{ "+foo+@example.org", "+foo+@example.org" },
{ "+@example.org", "+@example.org" },
{ "++@example.org", "++@example.org" },
{ "foo+b@example.org", "foo@example.org" },
{ "foo+ba@example.org", "foo@example.org" },
{ "foo+bar@example.org", "foo@example.org" },
{ "foo+barb@example.org", "foo@example.org" },
{ "foo+barba@example.org", "foo@example.org" },
{ "f+b@example.org", "f@example.org" },
{ "fo+b@example.org", "fo@example.org" },
{ NULL, NULL }
};
int idx;
for (idx=0; testtbl[idx].userid; idx++)
{
char *mbox = mailbox_from_userid (testtbl[idx].userid, 1);
if (!testtbl[idx].mbox)
{
@ -143,14 +229,105 @@ run_dns_test (void)
}
static void
run_filter (int no_sub)
{
char buf[4096];
int c;
char *p, *mbox;
unsigned int count1 = 0;
unsigned int count2 = 0;
while (fgets (buf, sizeof buf, stdin))
{
p = strchr (buf, '\n');
if (p)
*p = 0;
else
{
/* Skip to the end of the line. */
while ((c = getc (stdin)) != EOF && c != '\n')
;
}
count1++;
trim_spaces (buf);
mbox = mailbox_from_userid (buf, no_sub);
if (mbox)
{
printf ("%s\n", mbox);
xfree (mbox);
count2++;
}
}
if (verbose)
fprintf (stderr, PGM ": lines=%u mboxes=%u\n", count1, count2);
}
int
main (int argc, char **argv)
{
(void)argc;
(void)argv;
int last_argc = -1;
int opt_filter = 0;
int opt_no_sub = 0;
run_mbox_test ();
run_dns_test ();
if (argc)
{ argc--; argv++; }
while (argc && last_argc != argc )
{
last_argc = argc;
if (!strcmp (*argv, "--"))
{
argc--; argv++;
break;
}
else if (!strcmp (*argv, "--help"))
{
fputs ("usage: " PGM " [FILE]\n"
"Options:\n"
" --verbose Print timings etc.\n"
" --debug Flyswatter\n"
" --filter Filter mboxes from input lines\n"
" --no-sub Ignore '+'-sub-addresses\n"
, stdout);
exit (0);
}
else if (!strcmp (*argv, "--verbose"))
{
verbose++;
argc--; argv++;
}
else if (!strcmp (*argv, "--debug"))
{
verbose += 2;
debug++;
argc--; argv++;
}
else if (!strcmp (*argv, "--filter"))
{
opt_filter = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--no-sub"))
{
opt_no_sub = 1;
argc--; argv++;
}
else if (!strncmp (*argv, "--", 2))
{
fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
exit (1);
}
}
if (opt_filter)
run_filter (opt_no_sub);
else
{
run_mbox_test ();
run_mbox_no_sub_test ();
run_dns_test ();
}
return 0;
}

View file

@ -142,7 +142,15 @@ test_openpgp_oid_to_str (void)
fail (idx, 0);
xfree (string);
gcry_mpi_release (a);
}
/* Again using the buffer variant. */
string = openpgp_oidbuf_to_str (samples[idx].der, samples[idx].der[0]+1);
if (!string)
fail (idx, gpg_error_from_syserror ());
if (strcmp (string, samples[idx].string))
fail (idx, 0);
xfree (string);
}
}

View file

@ -101,6 +101,142 @@ test_percent_plus_escape (void)
static void
test_percent_data_escape (void)
{
static struct {
const char *prefix;
const char *data;
size_t datalen;
const char *expect;
} tbl[] = {
{
NULL,
"", 0,
""
}, {
NULL,
"a", 1,
"a",
}, {
NULL,
"%22", 3,
"%2522"
}, {
NULL,
"%%", 3,
"%25%25%00"
}, {
NULL,
"\n \0BC\t", 6,
"\n %00BC\t"
}, {
"",
"", 0,
""
}, {
"",
"a", 1,
"a",
}, {
"",
"%22", 3,
"%2522"
}, {
"",
"%%", 3,
"%25%25%00"
}, {
"",
"\n \0BC\t", 6,
"\n %00BC\t"
}, {
"a",
"", 0,
"a"
}, {
"a",
"a", 1,
"aa",
}, {
"a",
"%22", 3,
"a%2522"
}, {
"a",
"%%", 3,
"a%25%25%00"
}, {
"a",
"\n \0BC\t", 6,
"a\n %00BC\t"
}, {
" ",
"%%", 3,
" %25%25%00"
}, {
"+",
"%%", 3,
"+%25%25%00"
}, {
"%",
"%%", 3,
"%25%25%25%00"
}, {
"a b",
"%%", 3,
"a b%25%25%00"
}, {
"a%2Bb",
"%%", 3,
"a%252Bb%25%25%00"
}, {
"\n",
"%%", 3,
"%0A%25%25%00"
}, {
NULL,
NULL, 0,
NULL }
};
char *buf;
int i;
size_t len, prefixlen;
for (i=0; tbl[i].data; i++)
{
buf = percent_data_escape (0, tbl[i].prefix, tbl[i].data, tbl[i].datalen);
if (!buf)
{
fprintf (stderr, "out of core: %s\n", strerror (errno));
exit (2);
}
if (strcmp (buf, tbl[i].expect))
{
fail (i);
}
len = percent_plus_unescape_inplace (buf, 0);
prefixlen = tbl[i].prefix? strlen (tbl[i].prefix) : 0;
if (len != tbl[i].datalen + prefixlen)
fail (i);
else if (tbl[i].prefix && memcmp (buf, tbl[i].prefix, prefixlen)
&& !(prefixlen == 1 && *tbl[i].prefix == '+' && *buf == ' '))
{
/* Note extra condition above handles the one test case
* which reverts a plus to a space due to the use of the
* plus-unescape fucntion also for the prefix part. */
fail (i);
}
else if (memcmp (buf+prefixlen, tbl[i].data, tbl[i].datalen))
{
fail (i);
}
xfree (buf);
}
}
static void
test_percent_data_escape_plus (void)
{
static struct {
const char *data;
@ -121,7 +257,28 @@ test_percent_data_escape (void)
"%25%25%00"
}, {
"\n \0BC\t", 6,
"\n %00BC\t"
"%0A+%00BC%09"
}, {
" ", 1,
"+"
}, {
" ", 2,
"++"
}, {
"+ +", 3,
"%2B+%2B"
}, {
"\" \"", 3, /* Note: This function does not escape quotes. */
"\"+\""
}, {
"%22", 3,
"%2522"
}, {
"%% ", 3,
"%25%25+"
}, {
"\n ABC\t", 6,
"%0A+ABC%09"
}, { NULL, 0, NULL }
};
char *buf;
@ -130,14 +287,16 @@ test_percent_data_escape (void)
for (i=0; tbl[i].data; i++)
{
buf = percent_data_escape (tbl[i].data, tbl[i].datalen);
buf = percent_data_escape (1, NULL, tbl[i].data, tbl[i].datalen);
if (!buf)
{
fprintf (stderr, "out of core: %s\n", strerror (errno));
exit (2);
}
if (strcmp (buf, tbl[i].expect))
fail (i);
{
fail (i);
}
len = percent_plus_unescape_inplace (buf, 0);
if (len != tbl[i].datalen)
fail (i);
@ -148,16 +307,15 @@ test_percent_data_escape (void)
}
int
main (int argc, char **argv)
{
(void)argc;
(void)argv;
/* FIXME: We escape_unescape is not tested - only
percent_plus_unescape. */
/* FIXME: escape_unescape is not tested - only percent_plus_unescape. */
test_percent_plus_escape ();
test_percent_data_escape ();
test_percent_data_escape_plus ();
return 0;
}

View file

@ -404,166 +404,192 @@ tty_print_utf8_string( const byte *p, size_t n )
static char *
do_get( const char *prompt, int hidden )
{
char *buf;
char *buf;
#ifndef __riscos__
byte cbuf[1];
byte cbuf[1];
#endif
int c, n, i;
int c, n, i;
if( batchmode ) {
log_error("Sorry, we are in batchmode - can't get input\n");
exit(2);
if (batchmode)
{
log_error ("Sorry, we are in batchmode - can't get input\n");
exit (2);
}
if (no_terminal) {
log_error("Sorry, no terminal at all requested - can't get input\n");
exit(2);
if (no_terminal)
{
log_error ("Sorry, no terminal at all requested - can't get input\n");
exit (2);
}
if( !initialized )
init_ttyfp();
if (!initialized)
init_ttyfp ();
last_prompt_len = 0;
tty_printf( "%s", prompt );
buf = xmalloc((n=50));
i = 0;
last_prompt_len = 0;
tty_printf ("%s", prompt);
buf = xmalloc ((n=50));
i = 0;
#ifdef USE_W32_CONSOLE
if( hidden )
SetConsoleMode(con.in, HID_INPMODE );
if (hidden)
SetConsoleMode(con.in, HID_INPMODE );
for(;;) {
DWORD nread;
for (;;)
{
DWORD nread;
if( !ReadConsoleA( con.in, cbuf, 1, &nread, NULL ) )
log_fatal("ReadConsole failed: rc=%d", (int)GetLastError() );
if( !nread )
continue;
if( *cbuf == '\n' )
break;
if (!ReadConsoleA( con.in, cbuf, 1, &nread, NULL))
log_fatal ("ReadConsole failed: rc=%d", (int)GetLastError ());
if (!nread)
continue;
if (*cbuf == '\n')
break;
if( !hidden )
last_prompt_len++;
c = *cbuf;
if( c == '\t' )
c = ' ';
else if( c > 0xa0 )
; /* we don't allow 0xa0, as this is a protected blank which may
* confuse the user */
else if( iscntrl(c) )
continue;
if( !(i < n-1) ) {
n += 50;
buf = xrealloc (buf, n);
}
buf[i++] = c;
if (!hidden)
last_prompt_len++;
c = *cbuf;
if (c == '\t')
c = ' ';
else if ( (c >= 0 && c <= 0x1f) || c == 0x7f)
continue;
if (!(i < n-1))
{
n += 50;
buf = xrealloc (buf, n);
}
buf[i++] = c;
}
if( hidden )
SetConsoleMode(con.in, DEF_INPMODE );
if (hidden)
SetConsoleMode(con.in, DEF_INPMODE );
#elif defined(__riscos__) || defined(HAVE_W32CE_SYSTEM)
do {
do
{
#ifdef HAVE_W32CE_SYSTEM
/* Using getchar is not a correct solution but for now it
doesn't matter because we have no real console at all. We
should rework this as soon as we have switched this entire
module to estream. */
c = getchar();
c = getchar();
#else
c = riscos_getchar();
c = riscos_getchar();
#endif
if (c == 0xa || c == 0xd) { /* Return || Enter */
c = (int) '\n';
} else if (c == 0x8 || c == 0x7f) { /* Backspace || Delete */
if (i>0) {
i--;
if (!hidden) {
last_prompt_len--;
fputc(8, ttyfp);
fputc(32, ttyfp);
fputc(8, ttyfp);
fflush(ttyfp);
if (c == 0xa || c == 0xd) /* Return || Enter */
{
c = (int) '\n';
}
else if (c == 0x8 || c == 0x7f) /* Backspace || Delete */
{
if (i>0)
{
i--;
if (!hidden)
{
last_prompt_len--;
fputc(8, ttyfp);
fputc(32, ttyfp);
fputc(8, ttyfp);
fflush(ttyfp);
}
} else {
fputc(7, ttyfp);
fflush(ttyfp);
}
continue;
} else if (c == (int) '\t') { /* Tab */
c = ' ';
} else if (c > 0xa0) {
; /* we don't allow 0xa0, as this is a protected blank which may
* confuse the user */
} else if (iscntrl(c)) {
continue;
else
{
fputc(7, ttyfp);
fflush(ttyfp);
}
continue;
}
if(!(i < n-1)) {
n += 50;
buf = xrealloc (buf, n);
else if (c == (int) '\t') /* Tab */
{
c = ' ';
}
buf[i++] = c;
if (!hidden) {
last_prompt_len++;
fputc(c, ttyfp);
fflush(ttyfp);
else if (c > 0xa0)
{
; /* we don't allow 0xa0, as this is a protected blank which may
* confuse the user */
}
} while (c != '\n');
i = (i>0) ? i-1 : 0;
#else /* Other systems. */
if( hidden ) {
#ifdef HAVE_TCGETATTR
struct termios term;
else if (iscntrl(c))
{
continue;
}
if (!(i < n-1))
{
n += 50;
buf = xrealloc (buf, n);
}
buf[i++] = c;
if (!hidden)
{
last_prompt_len++;
fputc(c, ttyfp);
fflush(ttyfp);
}
}
while (c != '\n');
i = (i>0) ? i-1 : 0;
if( tcgetattr(fileno(ttyfp), &termsave) )
log_fatal("tcgetattr() failed: %s\n", strerror(errno) );
restore_termios = 1;
term = termsave;
term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
if( tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
log_fatal("tcsetattr() failed: %s\n", strerror(errno) );
#else /* Other systems. */
if (hidden)
{
#ifdef HAVE_TCGETATTR
struct termios term;
if (tcgetattr(fileno(ttyfp), &termsave))
log_fatal("tcgetattr() failed: %s\n", strerror(errno));
restore_termios = 1;
term = termsave;
term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
if (tcsetattr( fileno(ttyfp), TCSAFLUSH, &term ) )
log_fatal("tcsetattr() failed: %s\n", strerror(errno));
#endif
}
/* fixme: How can we avoid that the \n is echoed w/o disabling
* canonical mode - w/o this kill_prompt can't work */
while( read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n' ) {
if( !hidden )
last_prompt_len++;
c = *cbuf;
if( c == CONTROL_D )
log_info("control d found\n");
if( c == '\t' )
c = ' ';
else if( c > 0xa0 )
; /* we don't allow 0xa0, as this is a protected blank which may
* confuse the user */
else if( iscntrl(c) )
continue;
if( !(i < n-1) ) {
n += 50;
buf = xrealloc (buf, n );
}
buf[i++] = c;
/* fixme: How can we avoid that the \n is echoed w/o disabling
* canonical mode - w/o this kill_prompt can't work */
while (read(fileno(ttyfp), cbuf, 1) == 1 && *cbuf != '\n')
{
if (!hidden)
last_prompt_len++;
c = *cbuf;
if (c == CONTROL_D)
log_info ("Control-D detected\n");
if (c == '\t') /* Map tab to a space. */
c = ' ';
else if ( (c >= 0 && c <= 0x1f) || c == 0x7f)
continue; /* Skip all other ASCII control characters. */
if (!(i < n-1))
{
n += 50;
buf = xrealloc (buf, n);
}
buf[i++] = c;
}
if( *cbuf != '\n' ) {
buf[0] = CONTROL_D;
i = 1;
if (*cbuf != '\n')
{
buf[0] = CONTROL_D;
i = 1;
}
if( hidden ) {
if (hidden)
{
#ifdef HAVE_TCGETATTR
if( tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave) )
log_error("tcsetattr() failed: %s\n", strerror(errno) );
restore_termios = 0;
if (tcsetattr(fileno(ttyfp), TCSAFLUSH, &termsave))
log_error ("tcsetattr() failed: %s\n", strerror(errno));
restore_termios = 0;
#endif
}
#endif /* end unix version */
buf[i] = 0;
return buf;
buf[i] = 0;
return buf;
}
/* Note: This function never returns NULL. */
char *
tty_get( const char *prompt )
{

View file

@ -226,14 +226,15 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
goto out;
}
}
if (i != 32 && i != 40)
if (i != 32 && i != 40 && i != 64)
{
rc = gpg_error (GPG_ERR_INV_USER_ID); /* Invalid length of fpr. */
goto out;
}
for (i=0,si=s; si < se; i++, si +=2)
desc->u.fpr[i] = hextobyte(si);
for (; i < 20; i++)
desc->fprlen = i;
for (; i < 32; i++)
desc->u.fpr[i]= 0;
mode = KEYDB_SEARCH_MODE_FPR;
}
@ -326,14 +327,17 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
}
desc->u.fpr[i] = c;
}
mode = KEYDB_SEARCH_MODE_FPR16;
desc->fprlen = 16;
for (; i < 32; i++)
desc->u.fpr[i]= 0;
mode = KEYDB_SEARCH_MODE_FPR;
}
else if ((hexlength == 40
&& (s[hexlength] == 0
|| (s[hexlength] == '!' && s[hexlength + 1] == 0)))
|| (!hexprefix && hexlength == 41 && *s == '0'))
{
/* SHA1/RMD160 fingerprint. */
/* SHA1 fingerprint. */
int i;
if (hexlength == 41)
s++;
@ -347,7 +351,32 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
}
desc->u.fpr[i] = c;
}
mode = KEYDB_SEARCH_MODE_FPR20;
desc->fprlen = 20;
for (; i < 32; i++)
desc->u.fpr[i]= 0;
mode = KEYDB_SEARCH_MODE_FPR;
}
else if ((hexlength == 64
&& (s[hexlength] == 0
|| (s[hexlength] == '!' && s[hexlength + 1] == 0)))
|| (!hexprefix && hexlength == 65 && *s == '0'))
{
/* SHA256 fingerprint. */
int i;
if (hexlength == 65)
s++;
for (i=0; i < 32; i++, s+=2)
{
int c = hextobyte(s);
if (c == -1)
{
rc = gpg_error (GPG_ERR_INV_USER_ID);
goto out;
}
desc->u.fpr[i] = c;
}
desc->fprlen = 32;
mode = KEYDB_SEARCH_MODE_FPR;
}
else if (!hexprefix)
{
@ -367,15 +396,21 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
desc->u.fpr[i] = c;
}
if (i == 20)
mode = KEYDB_SEARCH_MODE_FPR20;
{
desc->fprlen = 20;
mode = KEYDB_SEARCH_MODE_FPR;
}
for (; i < 32; i++)
desc->u.fpr[i]= 0;
}
if (!mode)
{
/* Still not found. Now check for a space separated
OpenPGP v4 fingerprint like:
8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367
or
8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367
* OpenPGP v4 fingerprint like:
* 8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367
* or
* 8061 5870 F5BA D690 3336 86D0 F2AD 85AC 1E42 B367
* FIXME: Support OpenPGP v5 fingerprint
*/
hexlength = strspn (s, " 0123456789abcdefABCDEF");
if (s[hexlength] && s[hexlength] != ' ')
@ -409,7 +444,12 @@ classify_user_id (const char *name, KEYDB_SEARCH_DESC *desc, int openpgp_hack)
s += 2;
}
if (i == 20)
mode = KEYDB_SEARCH_MODE_FPR20;
{
desc->fprlen = 20;
mode = KEYDB_SEARCH_MODE_FPR;
}
for (; i < 32; i++)
desc->u.fpr[i]= 0;
}
}
if (!mode) /* Default to substring search. */

View file

@ -39,7 +39,10 @@
* libgpg-error version. Define them here.
* Example: (#if GPG_ERROR_VERSION_NUMBER < 0x011500 // 1.21)
*/
#if GPG_ERROR_VERSION_NUMBER < 0x012400 /* 1.36 */
#define GPG_ERR_NO_AUTH 314
#define GPG_ERR_BAD_AUTH 315
#endif /*GPG_ERROR_VERSION_NUMBER*/
/* Hash function used with libksba. */
#define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write)
@ -189,6 +192,7 @@ gpg_error_t get_rsa_pk_from_canon_sexp (const unsigned char *keydata,
int get_pk_algo_from_key (gcry_sexp_t key);
int get_pk_algo_from_canon_sexp (const unsigned char *keydata,
size_t keydatalen);
char *pubkey_algo_string (gcry_sexp_t s_pkey);
/*-- convert.c --*/
int hex2bin (const char *string, void *buffer, size_t length);
@ -201,7 +205,8 @@ char *hex2str_alloc (const char *hexstring, size_t *r_count);
/*-- percent.c --*/
char *percent_plus_escape (const char *string);
char *percent_data_escape (const void *data, size_t datalen);
char *percent_data_escape (int plus, const char *prefix,
const void *data, size_t datalen);
char *percent_plus_unescape (const char *string, int nulrepl);
char *percent_unescape (const char *string, int nulrepl);
@ -210,8 +215,11 @@ size_t percent_unescape_inplace (char *string, int nulrepl);
/*-- openpgp-oid.c --*/
gpg_error_t openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi);
char *openpgp_oidbuf_to_str (const unsigned char *buf, size_t len);
char *openpgp_oid_to_str (gcry_mpi_t a);
int openpgp_oidbuf_is_ed25519 (const void *buf, size_t len);
int openpgp_oid_is_ed25519 (gcry_mpi_t a);
int openpgp_oidbuf_is_cv25519 (const void *buf, size_t len);
int openpgp_oid_is_cv25519 (gcry_mpi_t a);
const char *openpgp_curve_to_oid (const char *name, unsigned int *r_nbits);
const char *openpgp_oid_to_curve (const char *oid, int canon);
@ -258,6 +266,13 @@ void gnupg_module_name_flush_some (void);
void gnupg_set_builddir (const char *newdir);
/* A list of constants to identify protocols. This is used by tools
* which need to distinguish between the different protocols
* implemented by GnuPG. May be used as bit flags. */
#define GNUPG_PROTOCOL_OPENPGP 1 /* The one and only (gpg). */
#define GNUPG_PROTOCOL_CMS 2 /* The core of S/MIME (gpgsm) */
#define GNUPG_PROTOCOL_SSH_AGENT 4 /* Out ssh-agent implementation */
/*-- gpgrlhelp.c --*/
void gnupg_rl_initialize (void);
@ -299,6 +314,7 @@ void print_hexstring (FILE *fp, const void *buffer, size_t length,
int reserved);
char *try_make_printable_string (const void *p, size_t n, int delim);
char *make_printable_string (const void *p, size_t n, int delim);
char *decode_c_string (const char *src);
int is_file_compressed (const char *s, int *ret_rc);