aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Makefile.am3
-rw-r--r--common/argparse.c37
-rw-r--r--common/argparse.h36
-rw-r--r--common/asshelp.c119
-rw-r--r--common/exechelp-posix.c55
-rw-r--r--common/exechelp-w32.c5
-rw-r--r--common/exechelp-w32ce.c5
-rw-r--r--common/exechelp.h2
-rw-r--r--common/iobuf.c122
-rw-r--r--common/iobuf.h6
-rw-r--r--common/logging.c40
-rw-r--r--common/logging.h51
-rw-r--r--common/miscellaneous.c16
-rw-r--r--common/openpgpdefs.h14
-rw-r--r--common/pkscreening.c159
-rw-r--r--common/pkscreening.h26
-rw-r--r--common/sysutils.c7
-rw-r--r--common/util.h5
18 files changed, 518 insertions, 190 deletions
diff --git a/common/Makefile.am b/common/Makefile.am
index fcbe7ea66..94318dae4 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -94,7 +94,8 @@ common_sources = \
name-value.c name-value.h \
recsel.c recsel.h \
ksba-io-support.c ksba-io-support.h \
- compliance.c compliance.h
+ compliance.c compliance.h \
+ pkscreening.c pkscreening.h
if HAVE_W32_SYSTEM
diff --git a/common/argparse.c b/common/argparse.c
index 90d0ff7f3..331998bb2 100644
--- a/common/argparse.c
+++ b/common/argparse.c
@@ -1,32 +1,23 @@
-/* [argparse.c wk 17.06.97] Argument Parser for option handling
- * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
+/* argparse.c - Argument Parser for option handling
* Copyright (C) 1997-2001, 2006-2008, 2013-2017 Werner Koch
+ * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
+ * Copyright (C) 2015-2017 g10 Code GmbH
*
* This file is part of GnuPG.
*
- * GnuPG is free software; you can redistribute and/or modify this
- * part of GnuPG 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 free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
*
- * GnuPG is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
+ * 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 copies of the GNU General Public License
- * and the GNU Lesser General Public License along with this program;
- * if not, see <https://gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1+
*/
/* This file may be used as part of GnuPG or standalone. A GnuPG
diff --git a/common/argparse.h b/common/argparse.h
index cdd18d9a2..4167d667a 100644
--- a/common/argparse.h
+++ b/common/argparse.h
@@ -1,31 +1,23 @@
/* argparse.h - Argument parser for option handling.
- * Copyright (C) 1998,1999,2000,2001,2006 Free Software Foundation, Inc.
+ * Copyright (C) 1997-2001, 2006-2008, 2013-2017 Werner Koch
+ * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
+ * Copyright (C) 2015-2017 g10 Code GmbH
*
* This file is part of GnuPG.
*
- * GnuPG is free software; you can redistribute and/or modify this
- * part of GnuPG under the terms of either
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
*
- * - 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.
+ * 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.
*
- * 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.
- *
- * GnuPG is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copies of the GNU General Public License
- * and the GNU Lesser General Public License along with this program;
- * if not, see <https://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1+
*/
#ifndef GNUPG_COMMON_ARGPARSE_H
diff --git a/common/asshelp.c b/common/asshelp.c
index f3a92f9e5..5209ea6cf 100644
--- a/common/asshelp.c
+++ b/common/asshelp.c
@@ -93,7 +93,7 @@ my_libassuan_log_handler (assuan_context_t ctx, void *hook,
return 0; /* Temporary disabled. */
if (msg)
- log_string (GPGRT_LOG_DEBUG, msg);
+ log_string (GPGRT_LOGLVL_DEBUG, msg);
return 1;
}
@@ -307,6 +307,71 @@ unlock_spawning (lock_spawn_t *lock, const char *name)
}
}
+
+/* Helper for start_new_gpg_agent and start_new_dirmngr.
+ * Values for WHICH are:
+ * 0 - Start gpg-agent
+ * 1 - Start dirmngr
+ * SECS give the number of seconds to wait. SOCKNAME is the name of
+ * the socket to connect. VERBOSE is the usual verbose flag. CTX is
+ * the assuan context. DID_SUCCESS_MSG will be set to 1 if a success
+ * messages has been printed.
+ */
+static gpg_error_t
+wait_for_sock (int secs, int which, const char *sockname,
+ int verbose, assuan_context_t ctx, int *did_success_msg)
+{
+ gpg_error_t err = 0;
+ int target_us = secs * 1000000;
+ int elapsed_us = 0;
+ /*
+ * 977us * 1024 = just a little more than 1s.
+ * so we will double this timeout 10 times in the first
+ * second, and then switch over to 1s checkins.
+ */
+ int next_sleep_us = 977;
+ int lastalert = secs+1;
+ int secsleft;
+
+ while (elapsed_us < target_us)
+ {
+ if (verbose)
+ {
+ secsleft = (target_us - elapsed_us + 999999)/1000000;
+ /* log_clock ("left=%d last=%d targ=%d elap=%d next=%d\n", */
+ /* secsleft, lastalert, target_us, elapsed_us, */
+ /* next_sleep_us); */
+ if (secsleft < lastalert)
+ {
+ log_info (which == 1?
+ _("waiting for the dirmngr to come up ... (%ds)\n"):
+ _("waiting for the agent to come up ... (%ds)\n"),
+ secsleft);
+ lastalert = secsleft;
+ }
+ }
+ gnupg_usleep (next_sleep_us);
+ elapsed_us += next_sleep_us;
+ err = assuan_socket_connect (ctx, sockname, 0, 0);
+ if (!err)
+ {
+ if (verbose)
+ {
+ log_info (which == 1?
+ _("connection to the dirmngr established\n"):
+ _("connection to the agent established\n"));
+ *did_success_msg = 1;
+ }
+ break;
+ }
+ next_sleep_us *= 2;
+ if (next_sleep_us > 1000000)
+ next_sleep_us = 1000000;
+ }
+ return err;
+}
+
+
/* Try to connect to the agent via socket or start it if it is not
running and AUTOSTART is set. Handle the server's initial
greeting. Returns a new assuan context at R_CTX or an error
@@ -433,25 +498,8 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
log_error ("failed to start agent '%s': %s\n",
agent_program, gpg_strerror (err));
else
- {
- for (i=0; i < SECS_TO_WAIT_FOR_AGENT; i++)
- {
- if (verbose)
- log_info (_("waiting for the agent to come up ... (%ds)\n"),
- SECS_TO_WAIT_FOR_AGENT - i);
- gnupg_sleep (1);
- err = assuan_socket_connect (ctx, sockname, 0, 0);
- if (!err)
- {
- if (verbose)
- {
- log_info (_("connection to agent established\n"));
- did_success_msg = 1;
- }
- break;
- }
- }
- }
+ err = wait_for_sock (SECS_TO_WAIT_FOR_AGENT, 0,
+ sockname, verbose, ctx, &did_success_msg);
}
unlock_spawning (&lock, "agent");
@@ -468,7 +516,7 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
}
if (debug && !did_success_msg)
- log_debug ("connection to agent established\n");
+ log_debug ("connection to the agent established\n");
err = assuan_transact (ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL);
@@ -485,7 +533,7 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
NULL, NULL, NULL, NULL, NULL, NULL))
{
if (verbose)
- log_info (_("connection to agent is in restricted mode\n"));
+ log_info (_("connection to the agent is in restricted mode\n"));
err = 0;
}
}
@@ -542,7 +590,7 @@ start_new_dirmngr (assuan_context_t *r_ctx,
dirmngr_program = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR);
if (verbose)
- log_info (_("no running Dirmngr - starting '%s'\n"),
+ log_info (_("no running dirmngr - starting '%s'\n"),
dirmngr_program);
if (status_cb)
@@ -584,29 +632,8 @@ start_new_dirmngr (assuan_context_t *r_ctx,
log_error ("failed to start the dirmngr '%s': %s\n",
dirmngr_program, gpg_strerror (err));
else
- {
- int i;
-
- for (i=0; i < SECS_TO_WAIT_FOR_DIRMNGR; i++)
- {
- if (verbose)
- log_info (_("waiting for the dirmngr "
- "to come up ... (%ds)\n"),
- SECS_TO_WAIT_FOR_DIRMNGR - i);
- gnupg_sleep (1);
- err = assuan_socket_connect (ctx, sockname, 0, 0);
- if (!err)
- {
- if (verbose)
- {
- log_info (_("connection to the dirmngr"
- " established\n"));
- did_success_msg = 1;
- }
- break;
- }
- }
- }
+ err = wait_for_sock (SECS_TO_WAIT_FOR_DIRMNGR, 1,
+ sockname, verbose, ctx, &did_success_msg);
}
unlock_spawning (&lock, "dirmngr");
diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c
index 7237993a2..425f2b4d5 100644
--- a/common/exechelp-posix.c
+++ b/common/exechelp-posix.c
@@ -1,6 +1,6 @@
/* exechelp.c - Fork and exec helpers for POSIX
- * Copyright (C) 2004, 2007, 2008, 2009,
- * 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2007-2009, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2006-2012, 2014-2017 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -26,6 +26,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: (LGPL-3.0+ OR GPL-2.0+)
*/
#include <config.h>
@@ -784,30 +785,32 @@ gnupg_wait_processes (const char **pgmnames, pid_t *pids, size_t count,
}
}
- if (ec == 0)
- for (i = 0; i < count; i++)
- {
- if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127)
- {
- log_error (_("error running '%s': probably not installed\n"),
- pgmnames[i]);
- ec = GPG_ERR_CONFIGURATION;
- }
- else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]))
- {
- if (dummy)
- log_error (_("error running '%s': exit status %d\n"),
- pgmnames[i], WEXITSTATUS (r_exitcodes[i]));
- else
- r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]);
- ec = GPG_ERR_GENERAL;
- }
- else if (!WIFEXITED (r_exitcodes[i]))
- {
- log_error (_("error running '%s': terminated\n"), pgmnames[i]);
- ec = GPG_ERR_GENERAL;
- }
- }
+ for (i = 0; i < count; i++)
+ {
+ if (r_exitcodes[i] == -1)
+ continue;
+
+ if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]) == 127)
+ {
+ log_error (_("error running '%s': probably not installed\n"),
+ pgmnames[i]);
+ ec = GPG_ERR_CONFIGURATION;
+ }
+ else if (WIFEXITED (r_exitcodes[i]) && WEXITSTATUS (r_exitcodes[i]))
+ {
+ if (dummy)
+ log_error (_("error running '%s': exit status %d\n"),
+ pgmnames[i], WEXITSTATUS (r_exitcodes[i]));
+ else
+ r_exitcodes[i] = WEXITSTATUS (r_exitcodes[i]);
+ ec = GPG_ERR_GENERAL;
+ }
+ else if (!WIFEXITED (r_exitcodes[i]))
+ {
+ log_error (_("error running '%s': terminated\n"), pgmnames[i]);
+ ec = GPG_ERR_GENERAL;
+ }
+ }
xfree (dummy);
return gpg_err_make (GPG_ERR_SOURCE_DEFAULT, ec);
diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c
index da174508e..86b1d6869 100644
--- a/common/exechelp-w32.c
+++ b/common/exechelp-w32.c
@@ -1,6 +1,6 @@
/* exechelp-w32.c - Fork and exec helpers for W32.
- * Copyright (C) 2004, 2007, 2008, 2009,
- * 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2007-2009, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2006-2012, 2014-2017 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -26,6 +26,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: (LGPL-3.0+ OR GPL-2.0+)
*/
#include <config.h>
diff --git a/common/exechelp-w32ce.c b/common/exechelp-w32ce.c
index ec9f01441..3d68a01d1 100644
--- a/common/exechelp-w32ce.c
+++ b/common/exechelp-w32ce.c
@@ -1,6 +1,6 @@
/* exechelp-w32.c - Fork and exec helpers for W32CE.
- * Copyright (C) 2004, 2007, 2008, 2009,
- * 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2007-2009, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2010-2012, 2014-2016 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -26,6 +26,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: (LGPL-3.0+ OR GPL-2.0+)
*/
#include <config.h>
diff --git a/common/exechelp.h b/common/exechelp.h
index 2b40ba098..9e1f56f70 100644
--- a/common/exechelp.h
+++ b/common/exechelp.h
@@ -1,5 +1,6 @@
/* exechelp.h - Definitions for the fork and exec helpers
* Copyright (C) 2004, 2009, 2010 Free Software Foundation, Inc.
+ * Copyright (C) 2004, 2006-2012, 2014-2017 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -25,6 +26,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: (LGPL-3.0+ OR GPL-2.0+)
*/
#ifndef GNUPG_COMMON_EXECHELP_H
diff --git a/common/iobuf.c b/common/iobuf.c
index 5a9fd7caf..02c9b491c 100644
--- a/common/iobuf.c
+++ b/common/iobuf.c
@@ -59,10 +59,8 @@
/*-- Begin configurable part. --*/
-/* The size of the internal buffers.
- NOTE: If you change this value you MUST also adjust the regression
- test "armored_key_8192" in armor.test! */
-#define IOBUF_BUFFER_SIZE 8192
+/* The standard size of the internal buffers. */
+#define DEFAULT_IOBUF_BUFFER_SIZE (64*1024)
/* To avoid a potential DoS with compression packets we better limit
the number of filters in a chain. */
@@ -70,6 +68,10 @@
/*-- End configurable part. --*/
+/* The size of the iobuffers. This can be chnages using the
+ * iobuf_set_buffer_size fucntion. */
+static unsigned int iobuf_buffer_size = DEFAULT_IOBUF_BUFFER_SIZE;
+
#ifdef HAVE_W32_SYSTEM
# ifdef HAVE_W32CE_SYSTEM
@@ -92,6 +94,7 @@ typedef struct
int keep_open;
int no_cache;
int eof_seen;
+ int delayed_rc;
int print_only_name; /* Flags indicating that fname is not a real file. */
char fname[1]; /* Name of the file. */
} file_filter_ctx_t;
@@ -167,7 +170,7 @@ static int translate_file_handle (int fd, int for_write);
to be sent to A's filter function.
If A is a IOBUF_OUTPUT_TEMP filter, then this also enlarges the
- buffer by IOBUF_BUFFER_SIZE.
+ buffer by iobuf_buffer_size.
May only be called on an IOBUF_OUTPUT or IOBUF_OUTPUT_TEMP filters. */
static int filter_flush (iobuf_t a);
@@ -451,12 +454,20 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
if (control == IOBUFCTRL_UNDERFLOW)
{
- assert (size); /* We need a buffer. */
+ log_assert (size); /* We need a buffer. */
if (a->eof_seen)
{
rc = -1;
*ret_len = 0;
}
+ else if (a->delayed_rc)
+ {
+ rc = a->delayed_rc;
+ a->delayed_rc = 0;
+ if (rc == -1)
+ a->eof_seen = -1;
+ *ret_len = 0;
+ }
else
{
#ifdef HAVE_W32_SYSTEM
@@ -487,29 +498,39 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
int n;
nbytes = 0;
- do
- {
- n = read (f, buf, size);
- }
- while (n == -1 && errno == EINTR);
- if (n == -1)
- { /* error */
- if (errno != EPIPE)
- {
- rc = gpg_error_from_syserror ();
- log_error ("%s: read error: %s\n",
- a->fname, strerror (errno));
- }
- }
- else if (!n)
- { /* eof */
- a->eof_seen = 1;
- rc = -1;
- }
- else
- {
- nbytes = n;
- }
+ read_more:
+ do
+ {
+ n = read (f, buf + nbytes, size - nbytes);
+ }
+ while (n == -1 && errno == EINTR);
+ if (n > 0)
+ {
+ nbytes += n;
+ if (nbytes < size)
+ goto read_more;
+ }
+ else if (!n) /* eof */
+ {
+ if (nbytes)
+ a->delayed_rc = -1;
+ else
+ {
+ a->eof_seen = 1;
+ rc = -1;
+ }
+ }
+ else /* error */
+ {
+ rc = gpg_error_from_syserror ();
+ if (gpg_err_code (rc) != GPG_ERR_EPIPE)
+ log_error ("%s: read error: %s\n", a->fname, gpg_strerror (rc));
+ if (nbytes)
+ {
+ a->delayed_rc = rc;
+ rc = 0;
+ }
+ }
#endif
*ret_len = nbytes;
}
@@ -569,6 +590,7 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
else if (control == IOBUFCTRL_INIT)
{
a->eof_seen = 0;
+ a->delayed_rc = 0;
a->keep_open = 0;
a->no_cache = 0;
}
@@ -1053,6 +1075,30 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
return rc;
}
+
+/* Change the default size for all IOBUFs to KILOBYTE. This needs to
+ * be called before any iobufs are used and can only be used once.
+ * Returns the current value. Using 0 has no effect except for
+ * returning the current value. */
+unsigned int
+iobuf_set_buffer_size (unsigned int kilobyte)
+{
+ static int used;
+
+ if (!used && kilobyte)
+ {
+ if (kilobyte < 4)
+ kilobyte = 4;
+ else if (kilobyte > 16*1024)
+ kilobyte = 16*1024;
+
+ iobuf_buffer_size = kilobyte * 1024;
+ used = 1;
+ }
+ return iobuf_buffer_size / 1024;
+}
+
+
#define MAX_IOBUF_DESC 32
/*
* Fill the buffer by the description of iobuf A.
@@ -1105,7 +1151,7 @@ iobuf_alloc (int use, size_t bufsize)
if (bufsize == 0)
{
log_bug ("iobuf_alloc() passed a bufsize of 0!\n");
- bufsize = IOBUF_BUFFER_SIZE;
+ bufsize = iobuf_buffer_size;
}
a = xcalloc (1, sizeof *a);
@@ -1213,7 +1259,7 @@ iobuf_cancel (iobuf_t a)
iobuf_t
iobuf_temp (void)
{
- return iobuf_alloc (IOBUF_OUTPUT_TEMP, IOBUF_BUFFER_SIZE);
+ return iobuf_alloc (IOBUF_OUTPUT_TEMP, iobuf_buffer_size);
}
iobuf_t
@@ -1288,7 +1334,7 @@ do_open (const char *fname, int special_filenames,
return NULL;
}
- a = iobuf_alloc (use, IOBUF_BUFFER_SIZE);
+ a = iobuf_alloc (use, iobuf_buffer_size);
fcx = xmalloc (sizeof *fcx + strlen (fname));
fcx->fp = fp;
fcx->print_only_name = print_only;
@@ -1335,7 +1381,7 @@ do_iobuf_fdopen (int fd, const char *mode, int keep_open)
fp = INT2FD (fd);
a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
- IOBUF_BUFFER_SIZE);
+ iobuf_buffer_size);
fcx = xmalloc (sizeof *fcx + 20);
fcx->fp = fp;
fcx->print_only_name = 1;
@@ -1373,7 +1419,7 @@ iobuf_esopen (estream_t estream, const char *mode, int keep_open)
size_t len = 0;
a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
- IOBUF_BUFFER_SIZE);
+ iobuf_buffer_size);
fcx = xtrymalloc (sizeof *fcx + 30);
fcx->fp = estream;
fcx->print_only_name = 1;
@@ -1398,7 +1444,7 @@ iobuf_sockopen (int fd, const char *mode)
size_t len;
a = iobuf_alloc (strchr (mode, 'w') ? IOBUF_OUTPUT : IOBUF_INPUT,
- IOBUF_BUFFER_SIZE);
+ iobuf_buffer_size);
scx = xmalloc (sizeof *scx + 25);
scx->sock = fd;
scx->print_only_name = 1;
@@ -1599,13 +1645,13 @@ iobuf_push_filter2 (iobuf_t a,
increased accordingly. We don't need to allocate a 10 MB
buffer for a non-terminal filter. Just use the default
size. */
- a->d.size = IOBUF_BUFFER_SIZE;
+ a->d.size = iobuf_buffer_size;
}
else if (a->use == IOBUF_INPUT_TEMP)
/* Same idea as above. */
{
a->use = IOBUF_INPUT;
- a->d.size = IOBUF_BUFFER_SIZE;
+ a->d.size = iobuf_buffer_size;
}
/* The new filter (A) gets a new buffer.
@@ -1922,7 +1968,7 @@ filter_flush (iobuf_t a)
if (a->use == IOBUF_OUTPUT_TEMP)
{ /* increase the temp buffer */
- size_t newsize = a->d.size + IOBUF_BUFFER_SIZE;
+ size_t newsize = a->d.size + iobuf_buffer_size;
if (DBG_IOBUF)
log_debug ("increasing temp iobuf from %lu to %lu\n",
diff --git a/common/iobuf.h b/common/iobuf.h
index 22e02daad..16156383c 100644
--- a/common/iobuf.h
+++ b/common/iobuf.h
@@ -259,6 +259,12 @@ struct iobuf_struct
EXTERN_UNLESS_MAIN_MODULE int iobuf_debug_mode;
+/* Change the default size for all IOBUFs to KILOBYTE. This needs to
+ * be called before any iobufs are used and can only be used once.
+ * Returns the current value. Using 0 has no effect except for
+ * returning the current value. */
+unsigned int iobuf_set_buffer_size (unsigned int kilobyte);
+
/* Returns whether the specified filename corresponds to a pipe. In
particular, this function checks if FNAME is "-" and, if special
filenames are enabled (see check_special_filename), whether
diff --git a/common/logging.c b/common/logging.c
index c4eaca411..88860e715 100644
--- a/common/logging.c
+++ b/common/logging.c
@@ -63,6 +63,10 @@
#include "logging.h"
#include "sysutils.h"
+#if defined(GPGRT_ENABLE_LOG_MACROS) && defined(log_debug_string)
+ /* Nothing to do; the libgpgrt functions are used. */
+#else /* Use our own logging functions. */
+
#ifdef HAVE_W32_SYSTEM
# ifndef S_IRWXG
# define S_IRGRP S_IRUSR
@@ -885,7 +889,7 @@ log_logv (int level, const char *fmt, va_list arg_ptr)
* Note that PREFIX is an additional string and independent of the
* prefix set by log_set_prefix. */
void
-log_logv_with_prefix (int level, const char *prefix,
+log_logv_prefix (int level, const char *prefix,
const char *fmt, va_list arg_ptr)
{
do_logv (level, 0, NULL, prefix, fmt, arg_ptr);
@@ -977,7 +981,7 @@ log_debug (const char *fmt, ...)
* printed with LFs expanded to include the prefix and a final --end--
* marker. */
void
-log_debug_with_string (const char *string, const char *fmt, ...)
+log_debug_string (const char *string, const char *fmt, ...)
{
va_list arg_ptr ;
@@ -1011,7 +1015,7 @@ log_flush (void)
dump, with TEXT just an empty string, print a trailing linefeed,
otherwise print an entire debug line. */
void
-log_printhex (const char *text, const void *buffer, size_t length)
+log_printhex (const void *buffer, size_t length, const char *text)
{
if (text && *text)
log_debug ("%s ", text);
@@ -1039,14 +1043,16 @@ log_printsexp () {}
is found in sexputils.c
*/
-
+/* Print a microsecond timestamp followed by a FORMAT. */
void
-log_clock (const char *string)
+log_clock (const char *fmt, ...)
{
-#if 0
+#if ENABLE_LOG_CLOCK
static unsigned long long initial;
struct timespec tv;
unsigned long long now;
+ char clockbuf[50];
+ va_list arg_ptr;
if (clock_gettime (CLOCK_REALTIME, &tv))
{
@@ -1059,11 +1065,21 @@ log_clock (const char *string)
if (!initial)
initial = now;
- log_debug ("[%6llu] %s", (now - initial)/1000, string);
-#else
- /* You need to link with -ltr to enable the above code. */
- log_debug ("[not enabled in the source] %s", string);
-#endif
+ snprintf (clockbuf, sizeof clockbuf, "[%6llu] ", (now - initial)/1000);
+ va_start (arg_ptr, fmt);
+ do_logv (GPGRT_LOG_DEBUG, 0, NULL, clockbuf, fmt, arg_ptr);
+ va_end (arg_ptr);
+
+#else /*!ENABLE_LOG_CLOCK*/
+
+ /* You may need to link with -ltr to use the above code. */
+ va_list arg_ptr;
+
+ va_start (arg_ptr, fmt);
+ do_logv (GPGRT_LOG_DEBUG, 0, NULL, "[no clock] ", fmt, arg_ptr);
+ va_end (arg_ptr);
+
+#endif /*!ENABLE_LOG_CLOCK*/
}
@@ -1101,3 +1117,5 @@ _log_assert (const char *expr, const char *file, int line)
abort (); /* Never called; just to make the compiler happy. */
}
#endif /*!GPGRT_HAVE_MACRO_FUNCTION*/
+
+#endif /* Use our own logging functions. */
diff --git a/common/logging.h b/common/logging.h
index 2225100cb..a20b8f895 100644
--- a/common/logging.h
+++ b/common/logging.h
@@ -38,6 +38,35 @@
#include "mischelp.h"
#include "w32help.h"
+#if defined(GPGRT_ENABLE_LOG_MACROS) && defined(log_debug_string)
+ /* We use the libgpg-error provided log functions. but we need one
+ * more function: */
+# ifdef GPGRT_HAVE_MACRO_FUNCTION
+# define BUG() bug_at ( __FILE__, __LINE__, __FUNCTION__)
+static inline void bug_at (const char *file, int line, const char *func)
+ GPGRT_ATTR_NORETURN;
+static inline void
+bug_at (const char *file, int line, const char *func)
+{
+ gpgrt_log (GPGRT_LOGLVL_BUG, "there is a bug at %s:%d:%s\n",
+ file, line, func);
+ abort ();
+}
+# else
+# define BUG() bug_at ( __FILE__, __LINE__)
+static inline void bug_at (const char *file, int line)
+ GPGRT_ATTR_NORETURN;
+static inline void
+bug_at (const char *file, int line)
+{
+ gpgrt_log (GPGRT_LOGLVL_BUG, "there is a bug at %s:%d\n", file, line);
+ abort ();
+}
+# endif /*!GPGRT_HAVE_MACRO_FUNCTION*/
+
+
+#else /* Use gnupg internal logging functions. */
+
int log_get_errorcount (int clear);
void log_inc_errorcount (void);
void log_set_file( const char *name );
@@ -88,18 +117,27 @@ enum jnlib_log_levels {
GPGRT_LOG_BUG,
GPGRT_LOG_DEBUG
};
+#define GPGRT_LOGLVL_BEGIN GPGRT_LOG_BEGIN
+#define GPGRT_LOGLVL_CONT GPGRT_LOG_CONT
+#define GPGRT_LOGLVL_INFO GPGRT_LOG_INFO
+#define GPGRT_LOGLVL_WARN GPGRT_LOG_WARN
+#define GPGRT_LOGLVL_ERROR GPGRT_LOG_ERROR
+#define GPGRT_LOGLVL_FATAL GPGRT_LOG_FATAL
+#define GPGRT_LOGLVL_BUG GPGRT_LOG_BUG
+#define GPGRT_LOGLVL_DEBUG GPGRT_LOG_DEBUG
+
void log_log (int level, const char *fmt, ...) GPGRT_ATTR_PRINTF(2,3);
void log_logv (int level, const char *fmt, va_list arg_ptr);
-void log_logv_with_prefix (int level, const char *prefix,
- const char *fmt, va_list arg_ptr);
+void log_logv_prefix (int level, const char *prefix,
+ const char *fmt, va_list arg_ptr);
void log_string (int level, const char *string);
void log_bug (const char *fmt, ...) GPGRT_ATTR_NR_PRINTF(1,2);
void log_fatal (const char *fmt, ...) GPGRT_ATTR_NR_PRINTF(1,2);
void log_error (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2);
void log_info (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2);
void log_debug (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2);
-void log_debug_with_string (const char *string, const char *fmt,
- ...) GPGRT_ATTR_PRINTF(2,3);
+void log_debug_string (const char *string, const char *fmt,
+ ...) GPGRT_ATTR_PRINTF(2,3);
void log_printf (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2);
void log_flush (void);
@@ -107,10 +145,11 @@ void log_flush (void);
raw dump, with TEXT being an empty string, print a trailing
linefeed, otherwise print an entire debug line with TEXT followed
by the hexdump and a final LF. */
-void log_printhex (const char *text, const void *buffer, size_t length);
+void log_printhex (const void *buffer, size_t length, const char *text);
-void log_clock (const char *string);
+void log_clock (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2);
+#endif /* Use gnupg internal logging functions. */
/* Some handy assertion macros which don't abort. */
diff --git a/common/miscellaneous.c b/common/miscellaneous.c
index 62ac05a84..0b374e6c8 100644
--- a/common/miscellaneous.c
+++ b/common/miscellaneous.c
@@ -45,14 +45,14 @@ my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
/* Map the log levels. */
switch (level)
{
- case GCRY_LOG_CONT: level = GPGRT_LOG_CONT; break;
- case GCRY_LOG_INFO: level = GPGRT_LOG_INFO; break;
- case GCRY_LOG_WARN: level = GPGRT_LOG_WARN; break;
- case GCRY_LOG_ERROR:level = GPGRT_LOG_ERROR; break;
- case GCRY_LOG_FATAL:level = GPGRT_LOG_FATAL; break;
- case GCRY_LOG_BUG: level = GPGRT_LOG_BUG; break;
- case GCRY_LOG_DEBUG:level = GPGRT_LOG_DEBUG; break;
- default: level = GPGRT_LOG_ERROR; break;
+ case GCRY_LOG_CONT: level = GPGRT_LOGLVL_CONT; break;
+ case GCRY_LOG_INFO: level = GPGRT_LOGLVL_INFO; break;
+ case GCRY_LOG_WARN: level = GPGRT_LOGLVL_WARN; break;
+ case GCRY_LOG_ERROR:level = GPGRT_LOGLVL_ERROR; break;
+ case GCRY_LOG_FATAL:level = GPGRT_LOGLVL_FATAL; break;
+ case GCRY_LOG_BUG: level = GPGRT_LOGLVL_BUG; break;
+ case GCRY_LOG_DEBUG:level = GPGRT_LOGLVL_DEBUG; break;
+ default: level = GPGRT_LOGLVL_ERROR; break;
}
log_logv (level, fmt, arg_ptr);
}
diff --git a/common/openpgpdefs.h b/common/openpgpdefs.h
index 85a4251de..8699a178d 100644
--- a/common/openpgpdefs.h
+++ b/common/openpgpdefs.h
@@ -51,6 +51,7 @@ typedef enum
PKT_ATTRIBUTE = 17, /* PGP's attribute packet. */
PKT_ENCRYPTED_MDC = 18, /* Integrity protected encrypted data. */
PKT_MDC = 19, /* Manipulation detection code packet. */
+ PKT_ENCRYPTED_AEAD= 20, /* AEAD encrypted data packet. */
PKT_COMMENT = 61, /* new comment packet (GnuPG specific). */
PKT_GPG_CONTROL = 63 /* internal control packet (GnuPG specific). */
}
@@ -115,7 +116,8 @@ typedef enum
SIGSUBPKT_FEATURES = 30, /* Feature flags. */
SIGSUBPKT_SIGNATURE = 32, /* Embedded signature. */
- SIGSUBPKT_ISSUER_FPR = 33, /* EXPERIMENTAL: Issuer fingerprint. */
+ SIGSUBPKT_ISSUER_FPR = 33, /* Issuer fingerprint. */
+ SIGSUBPKT_PREF_AEAD = 34, /* Preferred AEAD algorithms. */
SIGSUBPKT_FLAG_CRITICAL = 128
}
@@ -142,6 +144,16 @@ typedef enum
cipher_algo_t;
+/* Note that we encode the AEAD algo in a 3 bit field at some places. */
+typedef enum
+ {
+ AEAD_ALGO_NONE = 0,
+ AEAD_ALGO_EAX = 1,
+ AEAD_ALGO_OCB = 2
+ }
+aead_algo_t;
+
+
typedef enum
{
PUBKEY_ALGO_RSA = 1,
diff --git a/common/pkscreening.c b/common/pkscreening.c
new file mode 100644
index 000000000..a3bfb474e
--- /dev/null
+++ b/common/pkscreening.c
@@ -0,0 +1,159 @@
+/* pkscreening.c - Screen public keys for vulnerabilities
+ * Copyright (C) 2017 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 Lesser General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "pkscreening.h"
+
+
+/* Helper */
+static inline gpg_error_t
+my_error (gpg_err_code_t ec)
+{
+ return gpg_err_make (default_errsource, ec);
+}
+
+
+/* Emulation of the new gcry_mpi_get_ui function. */
+static gpg_error_t
+my_mpi_get_ui (unsigned int *v, gcry_mpi_t a)
+{
+ gpg_error_t err;
+ unsigned char buf[8];
+ size_t n;
+ int i, mul;
+
+ if (gcry_mpi_cmp_ui (a, 16384) > 0)
+ return my_error (GPG_ERR_ERANGE); /* Clearly too large for our purpose. */
+
+ err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, sizeof buf, &n, a);
+ if (err)
+ return err;
+
+ *v = 0;
+ for (i = n - 1, mul = 1; i >= 0; i--, mul *= 256)
+ *v += mul * buf[i];
+
+ return 0;
+}
+
+
+/* Detect whether the MODULUS of a public RSA key is affected by the
+ * ROCA vulnerability as found in the Infinion RSA library
+ * (CVE-2017-15361). Returns 0 if not affected, GPG_ERR_TRUE if
+ * affected, GPG_ERR_BAD_MPI if an opaque RSA was passed, or other
+ * error codes if something weird happened */
+gpg_error_t
+screen_key_for_roca (gcry_mpi_t modulus)
+{
+ static struct {
+ unsigned int prime_ui;
+ const char *print_hex;
+ gcry_mpi_t prime;
+ gcry_mpi_t print;
+ } table[] = {
+ { 3, "0x6" },
+ { 5, "0x1E" },
+ { 7, "0x7E" },
+ { 11, "0x402" },
+ { 13, "0x161A" },
+ { 17, "0x1A316" },
+ { 19, "0x30AF2" },
+ { 23, "0x7FFFFE" },
+ { 29, "0x1FFFFFFE" },
+ { 31, "0x7FFFFFFE" },
+ { 37, "0x4000402" },
+ { 41, "0x1FFFFFFFFFE" },
+ { 43, "0x7FFFFFFFFFE" },
+ { 47, "0x7FFFFFFFFFFE" },
+ { 53, "0x12DD703303AED2" },
+ { 59, "0x7FFFFFFFFFFFFFE" },
+ { 61, "0x1434026619900B0A" },
+ { 67, "0x7FFFFFFFFFFFFFFFE" },
+ { 71, "0x1164729716B1D977E" },
+ { 73, "0x147811A48004962078A" },
+ { 79, "0xB4010404000640502" },
+ { 83, "0x7FFFFFFFFFFFFFFFFFFFE" },
+ { 89, "0x1FFFFFFFFFFFFFFFFFFFFFE" },
+ { 97, "0x1000000006000001800000002" },
+ { 101, "0x1FFFFFFFFFFFFFFFFFFFFFFFFE" },
+ { 103, "0x16380E9115BD964257768FE396" },
+ { 107, "0x27816EA9821633397BE6A897E1A" },
+ { 109, "0x1752639F4E85B003685CBE7192BA" },
+ { 113, "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFE" },
+ { 127, "0x6CA09850C2813205A04C81430A190536" },
+ { 131, "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" },
+ { 137, "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" },
+ { 139, "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" },
+ { 149, "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" },
+ { 151, "0x50C018BC00482458DAC35B1A2412003D18030A" },
+ { 157, "0x161FB414D76AF63826461899071BD5BACA0B7E1A" },
+ { 163, "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" },
+ { 167, "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" }
+ };
+ gpg_error_t err;
+ int i;
+ gcry_mpi_t rem;
+ unsigned int bitno;
+
+ /* Initialize on the first call. */
+ if (!table[0].prime)
+ {
+ /* We pass primes[i] to the call so that in case of a concurrent
+ * second thread the already allocated space is reused. */
+ for (i = 0; i < DIM (table); i++)
+ {
+ table[i].prime = gcry_mpi_set_ui (table[i].prime, table[i].prime_ui);
+ if (gcry_mpi_scan (&table[i].print, GCRYMPI_FMT_HEX,
+ table[i].print_hex, 0, NULL))
+ BUG ();
+ }
+ }
+
+ /* Check that it is not NULL or an opaque MPI. */
+ if (!modulus || gcry_mpi_get_flag (modulus, GCRYMPI_FLAG_OPAQUE))
+ return my_error (GPG_ERR_BAD_MPI);
+
+ /* We divide the modulus of an RSA public key by a set of small
+ * PRIMEs and examine all the remainders. If all the bits at the
+ * index given by the remainder are set in the corresponding PRINT
+ * masks the key is very likely vulnerable. If any of the tested
+ * bits is zero, the key is not vulnerable. */
+ rem = gcry_mpi_new (0);
+ for (i = 0; i < DIM (table); i++)
+ {
+ gcry_mpi_mod (rem, modulus, table[i].prime);
+ err = my_mpi_get_ui (&bitno, rem);
+ if (gpg_err_code (err) == GPG_ERR_ERANGE)
+ continue;
+ if (err)
+ goto leave;
+ if (!gcry_mpi_test_bit (table[i].print, bitno))
+ goto leave; /* Not vulnerable. */
+ }
+
+ /* Very likely vulnerable */
+ err = my_error (GPG_ERR_TRUE);
+
+ leave:
+ gcry_mpi_release (rem);
+ return err;
+}
diff --git a/common/pkscreening.h b/common/pkscreening.h
new file mode 100644
index 000000000..a64758924
--- /dev/null
+++ b/common/pkscreening.h
@@ -0,0 +1,26 @@
+/* pkscreening.c - Screen public keys for vulnerabilities
+ * Copyright (C) 2017 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * 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 Lesser General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GNUPG_COMMON_PKSCREENING_H
+#define GNUPG_COMMON_PKSCREENING_H
+
+gpg_error_t screen_key_for_roca (gcry_mpi_t modulus);
+
+
+#endif /*GNUPG_COMMON_PKSCREENING_H*/
diff --git a/common/sysutils.c b/common/sysutils.c
index e90010c44..55a7ee9ec 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -340,11 +340,10 @@ gnupg_usleep (unsigned int usecs)
struct timespec req;
struct timespec rem;
- req.tv_sec = 0;
- req.tv_nsec = usecs * 1000;
-
+ req.tv_sec = usecs / 1000000;
+ req.tv_nsec = (usecs % 1000000) * 1000;
while (nanosleep (&req, &rem) < 0 && errno == EINTR)
- req = rem;
+ req = rem;
}
#else /*Standard Unix*/
diff --git a/common/util.h b/common/util.h
index c6d19c64b..f3722812d 100644
--- a/common/util.h
+++ b/common/util.h
@@ -59,6 +59,11 @@
/* Hash function used with libksba. */
#define HASH_FNC ((void (*)(void *, const void*,size_t))gcry_md_write)
+/* The length of the keygrip. This is a SHA-1 hash of the key
+ * parameters as generated by gcry_pk_get_keygrip. */
+#define KEYGRIP_LEN 20
+
+
/* Get all the stuff from jnlib. */
#include "../common/logging.h"
#include "../common/argparse.h"