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:
commit
a52d883fdb
237 changed files with 21268 additions and 4575 deletions
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
67
common/openpgp-s2k.c
Normal 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;
|
||||
}
|
|
@ -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*/
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++ = ':';
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
260
common/ttyio.c
260
common/ttyio.c
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue