summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorTizenOpenSource <tizenopensrc@samsung.com>2023-12-07 16:40:38 +0900
committerTizenOpenSource <tizenopensrc@samsung.com>2023-12-07 16:40:38 +0900
commit45ec706a2009b9cc68fff67bb77ccecbb2402c93 (patch)
treee18de3520f0c04b3e37a1889d10b708f9c4ceffd /common
parent0d6c0bc071b2e571c18781271972f6f9ee62dc8a (diff)
downloadgpg2-45ec706a2009b9cc68fff67bb77ccecbb2402c93.tar.gz
gpg2-45ec706a2009b9cc68fff67bb77ccecbb2402c93.tar.bz2
gpg2-45ec706a2009b9cc68fff67bb77ccecbb2402c93.zip
Imported Upstream version 2.4.3upstream/2.4.3
Diffstat (limited to 'common')
-rw-r--r--common/audit.c1
-rw-r--r--common/comopt.c2
-rw-r--r--common/comopt.h8
-rw-r--r--common/compliance.c20
-rw-r--r--common/compliance.h2
-rw-r--r--common/homedir.c51
-rw-r--r--common/init.c19
-rw-r--r--common/iobuf.c251
-rw-r--r--common/iobuf.h12
-rw-r--r--common/ksba-io-support.c205
-rw-r--r--common/ksba-io-support.h11
-rw-r--r--common/miscellaneous.c99
-rw-r--r--common/name-value.c40
-rw-r--r--common/name-value.h6
-rw-r--r--common/openpgp-oid.c47
-rw-r--r--common/recsel.c3
-rw-r--r--common/sexputil.c7
-rw-r--r--common/status-codes.h154
-rw-r--r--common/status.c3
-rw-r--r--common/status.h1
-rw-r--r--common/stringhelp.c44
-rw-r--r--common/stringhelp.h5
-rw-r--r--common/sysutils.c8
-rw-r--r--common/sysutils.h2
-rw-r--r--common/tlv.c6
-rw-r--r--common/util.h3
-rw-r--r--common/w32info-rc.h.in2
27 files changed, 731 insertions, 281 deletions
diff --git a/common/audit.c b/common/audit.c
index 803523c..ae0d452 100644
--- a/common/audit.c
+++ b/common/audit.c
@@ -1109,6 +1109,7 @@ proc_type_verify (audit_ctx_t ctx)
case GPG_ERR_CERT_REVOKED: ok = "bad"; break;
case GPG_ERR_NOT_ENABLED: ok = "disabled"; break;
case GPG_ERR_NO_CRL_KNOWN:
+ case GPG_ERR_INV_CRL_OBJ:
ok = _("no CRL found for certificate");
break;
case GPG_ERR_CRL_TOO_OLD:
diff --git a/common/comopt.c b/common/comopt.c
index 470cdac..1cfd581 100644
--- a/common/comopt.c
+++ b/common/comopt.c
@@ -60,6 +60,8 @@ static gpgrt_opt_t opts[] = {
};
+struct gnupg_comopt_s comopt = {NULL};
+
/* Parse the common options in the homedir and etc. This needs to be
* called after the gpgrt config directories are set. MODULE_ID is one of
diff --git a/common/comopt.h b/common/comopt.h
index 7947f35..9236afc 100644
--- a/common/comopt.h
+++ b/common/comopt.h
@@ -35,14 +35,16 @@
/* Common options for all GnuPG components. */
-EXTERN_UNLESS_MAIN_MODULE
-struct
+struct gnupg_comopt_s
{
char *logfile; /* Socket used by daemons for logging. */
int use_keyboxd; /* Use the keyboxd as storage backend. */
int no_autostart; /* Do not start gpg-agent. */
char *keyboxd_program; /* Use this as keyboxd program. */
-} comopt;
+};
+
+
+extern struct gnupg_comopt_s comopt;
gpg_error_t parse_comopt (int module_id, int verbose);
diff --git a/common/compliance.c b/common/compliance.c
index 33a19fe..59d9403 100644
--- a/common/compliance.c
+++ b/common/compliance.c
@@ -83,7 +83,9 @@ gnupg_initialize_compliance (int gnupg_module_name)
log_assert (! initialized);
/* We accept both OpenPGP-style and gcrypt-style algorithm ids.
- * Assert that they are compatible. */
+ * Assert that they are compatible. At some places gcrypt ids are
+ * used which can't be encoded in an OpenPGP algo octet; we also
+ * assert this. */
log_assert ((int) GCRY_PK_RSA == (int) PUBKEY_ALGO_RSA);
log_assert ((int) GCRY_PK_RSA_E == (int) PUBKEY_ALGO_RSA_E);
log_assert ((int) GCRY_PK_RSA_S == (int) PUBKEY_ALGO_RSA_S);
@@ -91,6 +93,9 @@ gnupg_initialize_compliance (int gnupg_module_name)
log_assert ((int) GCRY_PK_DSA == (int) PUBKEY_ALGO_DSA);
log_assert ((int) GCRY_PK_ECC == (int) PUBKEY_ALGO_ECDH);
log_assert ((int) GCRY_PK_ELG == (int) PUBKEY_ALGO_ELGAMAL);
+ log_assert ((int) GCRY_PK_ECDSA > 255);
+ log_assert ((int) GCRY_PK_ECDH > 255);
+ log_assert ((int) GCRY_PK_EDDSA > 255);
log_assert ((int) GCRY_CIPHER_NONE == (int) CIPHER_ALGO_NONE);
log_assert ((int) GCRY_CIPHER_IDEA == (int) CIPHER_ALGO_IDEA);
log_assert ((int) GCRY_CIPHER_3DES == (int) CIPHER_ALGO_3DES);
@@ -159,6 +164,9 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
case PUBKEY_ALGO_ECDH:
case PUBKEY_ALGO_ECDSA:
case PUBKEY_ALGO_EDDSA:
+ case GCRY_PK_ECDSA:
+ case GCRY_PK_ECDH:
+ case GCRY_PK_EDDSA:
algotype = is_ecc;
break;
@@ -211,7 +219,9 @@ gnupg_pk_is_compliant (enum gnupg_compliance_mode compliance, int algo,
result = (curvename
&& (algo == PUBKEY_ALGO_ECDH
- || algo == PUBKEY_ALGO_ECDSA)
+ || algo == PUBKEY_ALGO_ECDSA
+ || algo == GCRY_PK_ECDH
+ || algo == GCRY_PK_ECDSA)
&& (!strcmp (curvename, "brainpoolP256r1")
|| !strcmp (curvename, "brainpoolP384r1")
|| !strcmp (curvename, "brainpoolP512r1")));
@@ -292,6 +302,7 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
break;
case PUBKEY_ALGO_ECDH:
+ case GCRY_PK_ECDH:
if (use == PK_USE_DECRYPTION)
result = 1;
else if (use == PK_USE_ENCRYPTION)
@@ -316,6 +327,7 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
break;
case PUBKEY_ALGO_ECDSA:
+ case GCRY_PK_ECDSA:
if (use == PK_USE_VERIFICATION)
result = 1;
else
@@ -341,6 +353,10 @@ gnupg_pk_is_allowed (enum gnupg_compliance_mode compliance,
case PUBKEY_ALGO_EDDSA:
+ if (use == PK_USE_VERIFICATION)
+ result = 1;
+ else /* We may not create such signatures in de-vs mode. */
+ result = 0;
break;
default:
diff --git a/common/compliance.h b/common/compliance.h
index 455efa5..ead1147 100644
--- a/common/compliance.h
+++ b/common/compliance.h
@@ -45,7 +45,7 @@ enum gnupg_compliance_mode
enum pk_use_case
{
PK_USE_ENCRYPTION, PK_USE_DECRYPTION,
- PK_USE_SIGNING, PK_USE_VERIFICATION,
+ PK_USE_SIGNING, PK_USE_VERIFICATION
};
/* Flags to distinguish public key algorithm variants. */
diff --git a/common/homedir.c b/common/homedir.c
index 67bbde8..286685f 100644
--- a/common/homedir.c
+++ b/common/homedir.c
@@ -154,6 +154,42 @@ w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d)
}
#endif /*HAVE_W32_SYSTEM*/
+/* Given the directory name DNAME try to create a common.conf and
+ * enable the keyboxd. This should only be called for the standard
+ * home directory and only if that directory has just been created. */
+static void
+create_common_conf (const char *dname)
+{
+#ifdef BUILD_WITH_KEYBOXD
+ estream_t fp;
+ char *fcommon;
+
+ fcommon = make_filename (dname, "common.conf", NULL);
+ fp = es_fopen (fcommon, "wx,mode=-rw-r");
+ if (!fp)
+ {
+ log_info (_("error creating '%s': %s\n"), fcommon,
+ gpg_strerror (gpg_error_from_syserror ()));
+ }
+ else
+ {
+ if (es_fputs ("use-keyboxd\n", fp) == EOF)
+ {
+ log_info (_("error writing to '%s': %s\n"), fcommon,
+ gpg_strerror (es_ferror (fp)
+ ? gpg_error_from_syserror ()
+ : gpg_error (GPG_ERR_EOF)));
+ es_fclose (fp);
+ }
+ else if (es_fclose (fp))
+ {
+ log_info (_("error closing '%s': %s\n"), fcommon,
+ gpg_strerror (gpg_error_from_syserror ()));
+ }
+ }
+#endif /* BUILD_WITH_KEYBOXD */
+}
+
/* Check whether DIR is the default homedir. */
static int
@@ -259,7 +295,9 @@ standard_homedir (void)
/* Try to create the directory if it does not yet exists. */
if (gnupg_access (dir, F_OK))
- gnupg_mkdir (dir, "-rwx");
+ if (!gnupg_mkdir (dir, "-rwx"))
+ create_common_conf (dir);
+
}
else
dir = GNUPG_DEFAULT_HOMEDIR;
@@ -789,8 +827,12 @@ gnupg_maybe_make_homedir (const char *fname, int quiet)
if (gnupg_mkdir (fname, "-rwx"))
log_fatal ( _("can't create directory '%s': %s\n"),
fname, strerror(errno) );
- else if (!quiet )
- log_info ( _("directory '%s' created\n"), fname );
+ else
+ {
+ if (!quiet )
+ log_info ( _("directory '%s' created\n"), fname );
+ create_common_conf (fname);
+ }
}
}
@@ -1623,6 +1665,9 @@ gnupg_module_name (int which)
case GNUPG_MODULE_NAME_CARD:
X(bindir, "tools", "gpg-card");
+ case GNUPG_MODULE_NAME_GPGTAR:
+ X(bindir, "tools", "gpgtar");
+
default:
BUG ();
}
diff --git a/common/init.c b/common/init.c
index 269119f..62a48f8 100644
--- a/common/init.c
+++ b/common/init.c
@@ -30,6 +30,9 @@
#include <config.h>
#ifdef HAVE_W32_SYSTEM
+# if _WIN32_WINNT < 0x0600
+# define _WIN32_WINNT 0x0600 /* Required for SetProcessDEPPolicy. */
+# endif
# ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
# endif
@@ -213,7 +216,21 @@ _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp)
log_set_socket_dir_cb (gnupg_socketdir);
#if HAVE_W32_SYSTEM
- /* For Standard Windows we use our own parser for the command line
+ /* Make sure that Data Execution Prevention is enabled. */
+ if (GetSystemDEPPolicy () >= 2)
+ {
+ DWORD flags;
+ BOOL perm;
+
+ if (!GetProcessDEPPolicy (GetCurrentProcess (), &flags, &perm))
+ log_info ("error getting DEP policy: %s\n",
+ w32_strerror (GetLastError()));
+ else if (!(flags & PROCESS_DEP_ENABLE)
+ && !SetProcessDEPPolicy (PROCESS_DEP_ENABLE))
+ log_info ("Warning: Enabling DEP failed: %s (%d,%d)\n",
+ w32_strerror (GetLastError ()), (int)flags, (int)perm);
+ }
+ /* On Windows we use our own parser for the command line
* so that we can return an array of utf-8 encoded strings. */
prepare_w32_commandline (argcp, argvp);
#else
diff --git a/common/iobuf.c b/common/iobuf.c
index 86bb296..161769a 100644
--- a/common/iobuf.c
+++ b/common/iobuf.c
@@ -1,7 +1,7 @@
/* iobuf.c - File Handling for OpenPGP.
* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2006, 2007, 2008,
* 2009, 2010, 2011 Free Software Foundation, Inc.
- * Copyright (C) 2015 g10 Code GmbH
+ * Copyright (C) 2015, 2023 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -27,6 +27,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-later OR GPL-2.0-or-later)
*/
#include <config.h>
@@ -35,7 +36,6 @@
#include <string.h>
#include <errno.h>
#include <ctype.h>
-#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -95,6 +95,9 @@ typedef struct
int eof_seen;
int delayed_rc;
int print_only_name; /* Flags indicating that fname is not a real file. */
+ char peeked[32]; /* Read ahead buffer. */
+ byte npeeked; /* Number of bytes valid in peeked. */
+ byte upeeked; /* Number of bytes used from peeked. */
char fname[1]; /* Name of the file. */
} file_filter_ctx_t;
@@ -207,7 +210,7 @@ fd_cache_invalidate (const char *fname)
close_cache_t cc;
int rc = 0;
- assert (fname);
+ log_assert (fname);
if (DBG_IOBUF)
log_debug ("fd_cache_invalidate (%s)\n", fname);
@@ -308,6 +311,13 @@ direct_open (const char *fname, const char *mode, int mode700)
{
hfile = CreateFileW (wfname, da, sm, NULL, cd,
FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hfile == INVALID_HANDLE_VALUE)
+ {
+ gnupg_w32_set_errno (-1);
+ if (DBG_IOBUF)
+ log_debug ("iobuf:direct_open '%s' CreateFile failed: %s\n",
+ fname, gpg_strerror (gpg_error_from_syserror()));
+ }
xfree (wfname);
}
else
@@ -370,7 +380,7 @@ fd_cache_close (const char *fname, gnupg_fd_t fp)
{
close_cache_t cc;
- assert (fp);
+ log_assert (fp);
if (!fname || !*fname)
{
#ifdef HAVE_W32_SYSTEM
@@ -411,7 +421,7 @@ fd_cache_open (const char *fname, const char *mode)
{
close_cache_t cc;
- assert (fname);
+ log_assert (fname);
for (cc = close_cache; cc; cc = cc->next)
{
if (cc->fp != GNUPG_INVALID_FD && !fd_cache_strcmp (cc->fname, fname))
@@ -423,8 +433,9 @@ fd_cache_open (const char *fname, const char *mode)
#ifdef HAVE_W32_SYSTEM
if (SetFilePointer (fp, 0, NULL, FILE_BEGIN) == 0xffffffff)
{
- log_error ("rewind file failed on handle %p: ec=%d\n",
- fp, (int) GetLastError ());
+ int ec = (int) GetLastError ();
+ log_error ("rewind file failed on handle %p: ec=%d\n", fp, ec);
+ gnupg_w32_set_errno (ec);
fp = GNUPG_INVALID_FD;
}
#else
@@ -458,7 +469,16 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
if (control == IOBUFCTRL_UNDERFLOW)
{
log_assert (size); /* We need a buffer. */
- if (a->eof_seen)
+ if (a->npeeked > a->upeeked)
+ {
+ nbytes = a->npeeked - a->upeeked;
+ if (nbytes > size)
+ nbytes = size;
+ memcpy (buf, a->peeked + a->upeeked, nbytes);
+ a->upeeked += nbytes;
+ *ret_len = nbytes;
+ }
+ else if (a->eof_seen)
{
rc = -1;
*ret_len = 0;
@@ -483,7 +503,8 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
if (ec != ERROR_BROKEN_PIPE)
{
rc = gpg_error_from_errno (ec);
- log_error ("%s: read error: ec=%d\n", a->fname, ec);
+ log_error ("%s: read error: %s (ec=%d)\n",
+ a->fname, gpg_strerror (rc), ec);
}
}
else if (!nread)
@@ -551,9 +572,10 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
{
if (size && !WriteFile (f, p, nbytes, &n, NULL))
{
- int ec = (int) GetLastError ();
- rc = gpg_error_from_errno (ec);
- log_error ("%s: write error: ec=%d\n", a->fname, ec);
+ int ec = gnupg_w32_set_errno (-1);
+ rc = gpg_error_from_syserror ();
+ log_error ("%s: write error: %s (ec=%d)\n",
+ a->fname, gpg_strerror (rc), ec);
break;
}
p += n;
@@ -596,6 +618,74 @@ file_filter (void *opaque, int control, iobuf_t chain, byte * buf,
a->delayed_rc = 0;
a->keep_open = 0;
a->no_cache = 0;
+ a->npeeked = 0;
+ a->upeeked = 0;
+ }
+ else if (control == IOBUFCTRL_PEEK)
+ {
+ /* Peek on the input. */
+#ifdef HAVE_W32_SYSTEM
+ unsigned long nread;
+
+ nbytes = 0;
+ if (!ReadFile (f, a->peeked, sizeof a->peeked, &nread, NULL))
+ {
+ int ec = (int) GetLastError ();
+ if (ec != ERROR_BROKEN_PIPE)
+ {
+ rc = gpg_error_from_errno (ec);
+ log_error ("%s: read error: %s (ec=%d)\n",
+ a->fname, gpg_strerror (rc), ec);
+ }
+ a->npeeked = 0;
+ }
+ else if (!nread)
+ {
+ a->eof_seen = 1;
+ a->npeeked = 0;
+ }
+ else
+ {
+ a->npeeked = nread;
+ }
+
+#else /* Unix */
+
+ int n;
+
+ peek_more:
+ do
+ {
+ n = read (f, a->peeked + a->npeeked, sizeof a->peeked - a->npeeked);
+ }
+ while (n == -1 && errno == EINTR);
+ if (n > 0)
+ {
+ a->npeeked += n;
+ if (a->npeeked < sizeof a->peeked)
+ goto peek_more;
+ }
+ else if (!n) /* eof */
+ {
+ if (a->npeeked)
+ a->delayed_rc = -1;
+ else
+ a->eof_seen = 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 (a->npeeked)
+ a->delayed_rc = rc;
+ }
+#endif /* Unix */
+
+ size = a->npeeked < size? a->npeeked : size;
+ memcpy (buf, a->peeked, size);
+ *ret_len = size;
+ rc = 0; /* Return success - the user needs to check ret_len. */
}
else if (control == IOBUFCTRL_DESC)
{
@@ -632,7 +722,7 @@ file_es_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;
@@ -751,7 +841,7 @@ sock_filter (void *opaque, int control, iobuf_t chain, byte * buf,
if (control == IOBUFCTRL_UNDERFLOW)
{
- assert (size); /* need a buffer */
+ log_assert (size); /* need a buffer */
if (a->eof_seen)
{
rc = -1;
@@ -794,7 +884,8 @@ sock_filter (void *opaque, int control, iobuf_t chain, byte * buf,
if (n == SOCKET_ERROR)
{
int ec = (int) WSAGetLastError ();
- rc = gpg_error_from_errno (ec);
+ gnupg_w32_set_errno (ec);
+ rc = gpg_error_from_syserror ();
log_error ("socket write error: ec=%d\n", ec);
break;
}
@@ -846,7 +937,7 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
size_t n = 0;
p = buf;
- assert (size); /* need a buffer */
+ log_assert (size); /* need a buffer */
if (a->eof) /* don't read any further */
rc = -1;
while (!rc && size)
@@ -974,7 +1065,7 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
{ /* the complicated openpgp scheme */
size_t blen, n, nbytes = size + a->buflen;
- assert (a->buflen <= OP_MIN_PARTIAL_CHUNK);
+ log_assert (a->buflen <= OP_MIN_PARTIAL_CHUNK);
if (nbytes < OP_MIN_PARTIAL_CHUNK)
{
/* not enough to write a partial block out; so we store it */
@@ -998,12 +1089,12 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
blen /= 2;
c--;
/* write the partial length header */
- assert (c <= 0x1f); /*;-) */
+ log_assert (c <= 0x1f); /*;-) */
c |= 0xe0;
iobuf_put (chain, c);
if ((n = a->buflen))
{ /* write stuff from the buffer */
- assert (n == OP_MIN_PARTIAL_CHUNK);
+ log_assert (n == OP_MIN_PARTIAL_CHUNK);
if (iobuf_write (chain, a->buffer, n))
rc = gpg_error_from_syserror ();
a->buflen = 0;
@@ -1020,8 +1111,8 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
/* store the rest in the buffer */
if (!rc && nbytes)
{
- assert (!a->buflen);
- assert (nbytes < OP_MIN_PARTIAL_CHUNK);
+ log_assert (!a->buflen);
+ log_assert (nbytes < OP_MIN_PARTIAL_CHUNK);
if (!a->buffer)
a->buffer = xmalloc (OP_MIN_PARTIAL_CHUNK);
memcpy (a->buffer, p, nbytes);
@@ -1183,8 +1274,8 @@ iobuf_alloc (int use, size_t bufsize)
iobuf_t a;
static int number = 0;
- assert (use == IOBUF_INPUT || use == IOBUF_INPUT_TEMP
- || use == IOBUF_OUTPUT || use == IOBUF_OUTPUT_TEMP);
+ log_assert (use == IOBUF_INPUT || use == IOBUF_INPUT_TEMP
+ || use == IOBUF_OUTPUT || use == IOBUF_OUTPUT_TEMP);
if (bufsize == 0)
{
log_bug ("iobuf_alloc() passed a bufsize of 0!\n");
@@ -1304,7 +1395,7 @@ iobuf_temp_with_content (const char *buffer, size_t length)
int i;
a = iobuf_alloc (IOBUF_INPUT_TEMP, length);
- assert (length == a->d.size);
+ log_assert (length == a->d.size);
/* memcpy (a->d.buf, buffer, length); */
for (i=0; i < length; i++)
a->d.buf[i] = buffer[i];
@@ -1335,7 +1426,7 @@ do_open (const char *fname, int special_filenames,
int fd;
byte desc[MAX_IOBUF_DESC];
- assert (use == IOBUF_INPUT || use == IOBUF_OUTPUT);
+ log_assert (use == IOBUF_INPUT || use == IOBUF_OUTPUT);
if (special_filenames
/* NULL or '-'. */
@@ -1576,6 +1667,25 @@ iobuf_ioctl (iobuf_t a, iobuf_ioctl_t cmd, int intval, void *ptrval)
return fd_cache_synchronize (ptrval);
}
}
+ else if (cmd == IOBUF_IOCTL_PEEK)
+ {
+ /* Peek at a justed opened file. Use this only directly after a
+ * file has been opened for reading. Don't use it after you did
+ * a seek. This works only if just file filter has been
+ * pushed. Expects a buffer wit size INTVAL at PTRVAL and returns
+ * the number of bytes put into the buffer. */
+ if (DBG_IOBUF)
+ log_debug ("iobuf-%d.%d: ioctl '%s' peek\n",
+ a ? a->no : -1, a ? a->subno : -1, iobuf_desc (a, desc));
+ if (a->filter == file_filter && ptrval && intval)
+ {
+ file_filter_ctx_t *fcx = a->filter_ov;
+ size_t len = intval;
+
+ if (!file_filter (fcx, IOBUFCTRL_PEEK, NULL, ptrval, &len))
+ return (int)len;
+ }
+ }
return -1;
@@ -1755,13 +1865,13 @@ iobuf_pop_filter (iobuf_t a, int (*f) (void *opaque, int control,
if (a->use == IOBUF_INPUT_TEMP || a->use == IOBUF_OUTPUT_TEMP)
{
/* This should be the last filter in the pipeline. */
- assert (! a->chain);
+ log_assert (! a->chain);
return 0;
}
if (!a->filter)
{ /* this is simple */
b = a->chain;
- assert (b);
+ log_assert (b);
xfree (a->d.buf);
xfree (a->real_fname);
memcpy (a, b, sizeof *a);
@@ -1856,14 +1966,14 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
buffer. */
return -1;
- assert (a->use == IOBUF_INPUT);
+ log_assert (a->use == IOBUF_INPUT);
a->e_d.used = 0;
/* If there is still some buffered data, then move it to the start
of the buffer and try to fill the end of the buffer. (This is
useful if we are called from iobuf_peek().) */
- assert (a->d.start <= a->d.len);
+ log_assert (a->d.start <= a->d.len);
a->d.len -= a->d.start;
if (a->d.len)
memmove (a->d.buf, &a->d.buf[a->d.start], a->d.len);
@@ -2027,7 +2137,7 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
}
}
- assert (a->d.start <= a->d.len);
+ log_assert (a->d.start <= a->d.len);
if (a->e_d.used > 0)
return 0;
if (a->d.start < a->d.len)
@@ -2107,7 +2217,7 @@ iobuf_readbyte (iobuf_t a)
return -1;
}
- assert (a->d.start <= a->d.len);
+ log_assert (a->d.start <= a->d.len);
if (a->nlimit && a->nbytes >= a->nlimit)
return -1; /* forced EOF */
@@ -2119,7 +2229,7 @@ iobuf_readbyte (iobuf_t a)
else if ((c = underflow (a, 1)) == -1)
return -1; /* EOF */
- assert (a->d.start <= a->d.len);
+ log_assert (a->d.start <= a->d.len);
/* Note: if underflow doesn't return EOF, then it returns the first
byte that was read and advances a->d.start appropriately. */
@@ -2244,8 +2354,8 @@ iobuf_peek (iobuf_t a, byte * buf, unsigned buflen)
{
int n = 0;
- assert (buflen > 0);
- assert (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP);
+ log_assert (buflen > 0);
+ log_assert (a->use == IOBUF_INPUT || a->use == IOBUF_INPUT_TEMP);
if (buflen > a->d.size)
/* We can't peek more than we can buffer. */
@@ -2261,7 +2371,7 @@ iobuf_peek (iobuf_t a, byte * buf, unsigned buflen)
/* Underflow consumes the first character (it's the return
value). unget() it by resetting the "file position". */
- assert (a->d.start == 1);
+ log_assert (a->d.start == 1);
a->d.start = 0;
}
@@ -2296,7 +2406,7 @@ iobuf_writebyte (iobuf_t a, unsigned int c)
if ((rc=filter_flush (a)))
return rc;
- assert (a->d.len < a->d.size);
+ log_assert (a->d.len < a->d.size);
a->d.buf[a->d.len++] = c;
return 0;
}
@@ -2397,8 +2507,8 @@ iobuf_writestr (iobuf_t a, const char *buf)
int
iobuf_write_temp (iobuf_t dest, iobuf_t source)
{
- assert (source->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP);
- assert (dest->use == IOBUF_OUTPUT || dest->use == IOBUF_OUTPUT_TEMP);
+ log_assert (source->use == IOBUF_OUTPUT || source->use == IOBUF_OUTPUT_TEMP);
+ log_assert (dest->use == IOBUF_OUTPUT || dest->use == IOBUF_OUTPUT_TEMP);
iobuf_flush_temp (source);
return iobuf_write (dest, source->d.buf, source->d.len);
@@ -2499,13 +2609,10 @@ iobuf_set_limit (iobuf_t a, off_t nlimit)
}
-
-off_t
-iobuf_get_filelength (iobuf_t a, int *overflow)
+/* Return the length of the file behind A. If there is no file, return 0. */
+uint64_t
+iobuf_get_filelength (iobuf_t a)
{
- if (overflow)
- *overflow = 0;
-
/* Hmmm: file_filter may have already been removed */
for ( ; a->chain; a = a->chain )
;
@@ -2518,56 +2625,18 @@ iobuf_get_filelength (iobuf_t a, int *overflow)
gnupg_fd_t fp = b->fp;
#if defined(HAVE_W32_SYSTEM)
- ulong size;
- static int (* __stdcall get_file_size_ex) (void *handle,
- LARGE_INTEGER *r_size);
- static int get_file_size_ex_initialized;
-
- if (!get_file_size_ex_initialized)
- {
- void *handle;
+ LARGE_INTEGER exsize;
- handle = dlopen ("kernel32.dll", RTLD_LAZY);
- if (handle)
- {
- get_file_size_ex = dlsym (handle, "GetFileSizeEx");
- if (!get_file_size_ex)
- dlclose (handle);
- }
- get_file_size_ex_initialized = 1;
- }
-
- if (get_file_size_ex)
- {
- /* This is a newer system with GetFileSizeEx; we use this
- then because it seem that GetFileSize won't return a
- proper error in case a file is larger than 4GB. */
- LARGE_INTEGER exsize;
-
- if (get_file_size_ex (fp, &exsize))
- {
- if (!exsize.u.HighPart)
- return exsize.u.LowPart;
- if (overflow)
- *overflow = 1;
- return 0;
- }
- }
- else
- {
- if ((size=GetFileSize (fp, NULL)) != 0xffffffff)
- return size;
- }
+ if (GetFileSizeEx (fp, &exsize))
+ return exsize.QuadPart;
log_error ("GetFileSize for handle %p failed: %s\n",
fp, w32_strerror (-1));
#else /*!HAVE_W32_SYSTEM*/
- {
- struct stat st;
+ struct stat st;
- if ( !fstat (fp, &st) )
- return st.st_size;
- log_error("fstat() failed: %s\n", strerror(errno) );
- }
+ if ( !fstat (fp, &st) )
+ return st.st_size;
+ log_error("fstat() failed: %s\n", strerror(errno) );
#endif /*!HAVE_W32_SYSTEM*/
}
@@ -2782,7 +2851,7 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
NUL character in the buffer. This requires at least 2 bytes. We
don't complicate the code by handling the stupid corner case, but
simply assert that it can't happen. */
- assert (!buffer || length >= 2 || maxlen >= 2);
+ log_assert (!buffer || length >= 2 || maxlen >= 2);
if (!buffer || length <= 1)
/* must allocate a new buffer */
@@ -2853,7 +2922,7 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
/* p is pointing at the last byte in the buffer. We
always terminate the line with "\n\0" so overwrite
the previous byte with a \n. */
- assert (p > buffer);
+ log_assert (p > buffer);
p[-1] = '\n';
/* Indicate truncation. */
diff --git a/common/iobuf.h b/common/iobuf.h
index f527fbf..751ae73 100644
--- a/common/iobuf.h
+++ b/common/iobuf.h
@@ -106,6 +106,7 @@ enum
IOBUFCTRL_FLUSH = 4,
IOBUFCTRL_DESC = 5,
IOBUFCTRL_CANCEL = 6,
+ IOBUFCTRL_PEEK = 7,
IOBUFCTRL_USER = 16
};
@@ -116,7 +117,8 @@ typedef enum
IOBUF_IOCTL_KEEP_OPEN = 1, /* Uses intval. */
IOBUF_IOCTL_INVALIDATE_CACHE = 2, /* Uses ptrval. */
IOBUF_IOCTL_NO_CACHE = 3, /* Uses intval. */
- IOBUF_IOCTL_FSYNC = 4 /* Uses ptrval. */
+ IOBUF_IOCTL_FSYNC = 4, /* Uses ptrval. */
+ IOBUF_IOCTL_PEEK = 5 /* Uses intval and ptrval. */
} iobuf_ioctl_t;
enum iobuf_use
@@ -582,12 +584,8 @@ size_t iobuf_temp_to_buffer (iobuf_t a, byte * buffer, size_t buflen);
size_t iobuf_copy (iobuf_t dest, iobuf_t source);
/* Return the size of any underlying file. This only works with
- file_filter based pipelines.
-
- On Win32, it is sometimes not possible to determine the size of
- files larger than 4GB. In this case, *OVERFLOW (if not NULL) is
- set to 1. Otherwise, *OVERFLOW is set to 0. */
-off_t iobuf_get_filelength (iobuf_t a, int *overflow);
+ file_filter based pipelines. */
+uint64_t iobuf_get_filelength (iobuf_t a);
#define IOBUF_FILELENGTH_LIMIT 0xffffffff
/* Return the file descriptor designating the underlying file. This
diff --git a/common/ksba-io-support.c b/common/ksba-io-support.c
index 2832a4f..352485f 100644
--- a/common/ksba-io-support.c
+++ b/common/ksba-io-support.c
@@ -1,6 +1,6 @@
/* kska-io-support.c - Supporting functions for ksba reader and writer
* Copyright (C) 2001-2005, 2007, 2010-2011, 2017 Werner Koch
- * Copyright (C) 2006 g10 Code GmbH
+ * Copyright (C) 2006, 2023 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-later OR GPL-2.0-or-later)
*/
#include <config.h>
@@ -40,6 +41,7 @@
#include "util.h"
#include "i18n.h"
+#include "tlv.h"
#include "ksba-io-support.h"
@@ -65,6 +67,12 @@ struct reader_cb_parm_s
int autodetect; /* Try to detect the input encoding. */
int assume_pem; /* Assume input encoding is PEM. */
int assume_base64; /* Assume input is base64 encoded. */
+ int strip_zeroes; /* Expect a SEQUENCE followed by zero padding. */
+ /* 1 = check state; 2 = reading; 3 = checking */
+ /* for zeroes. */
+ int use_maxread; /* If true read not more than MAXREAD. */
+ unsigned int maxread; /* # of bytes left to read. */
+ off_t nzeroes; /* Number of padding zeroes red. */
int identified;
int is_pem;
@@ -89,6 +97,15 @@ struct writer_cb_parm_s
char *pem_name; /* Malloced. */
+ struct {
+ gnupg_ksba_progress_cb_t cb;
+ ctrl_t ctrl;
+ u32 last_time; /* last time reported */
+ uint64_t last; /* last amount reported */
+ uint64_t current; /* current amount */
+ uint64_t total; /* total amount */
+ } progress;
+
int wrote_begin;
int did_finish;
@@ -103,6 +120,7 @@ struct writer_cb_parm_s
/* Context for this module's functions. */
struct gnupg_ksba_io_s {
+ int is_writer; /* True if this context refers a writer object. */
union {
struct reader_cb_parm_s rparm;
struct writer_cb_parm_s wparm;
@@ -390,6 +408,55 @@ base64_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
}
+/* Read up to 10 bytes to test whether the data consist of a sequence;
+ * if that is true, set the limited flag and record the length of the
+ * entire sequence in PARM. Unget everything then. Return true if we
+ * have a sequence with a fixed length. */
+static int
+starts_with_sequence (struct reader_cb_parm_s *parm)
+{
+ gpg_error_t err;
+ unsigned char peekbuf[10];
+ int npeeked, c;
+ int found = 0;
+ const unsigned char *p;
+ size_t n, objlen, hdrlen;
+ int class, tag, constructed, ndef;
+
+ for (npeeked=0; npeeked < sizeof peekbuf; npeeked++)
+ {
+ c = es_getc (parm->fp);
+ if (c == EOF)
+ goto leave;
+ peekbuf[npeeked] = c;
+ }
+ /* Enough to check for a sequence. */
+
+ p = peekbuf;
+ n = npeeked;
+ err = parse_ber_header (&p, &n, &class, &tag, &constructed,
+ &ndef, &objlen, &hdrlen);
+ if (err)
+ {
+ log_debug ("%s: error parsing data: %s\n", __func__, gpg_strerror (err));
+ goto leave;
+ }
+
+ if (class == CLASS_UNIVERSAL && constructed && tag == TAG_SEQUENCE && !ndef)
+ {
+ /* We need to add 1 due to the way we implement the limit. */
+ parm->maxread = objlen + hdrlen + 1;
+ if (!(parm->maxread < objlen + hdrlen) && parm->maxread)
+ parm->use_maxread = 1;
+ found = 1;
+ }
+
+ leave:
+ while (npeeked)
+ es_ungetc (peekbuf[--npeeked], parm->fp);
+ return found;
+}
+
static int
simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
@@ -402,9 +469,55 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
if (!buffer)
return -1; /* not supported */
+ restart:
+ if (parm->strip_zeroes)
+ {
+ if (parm->strip_zeroes == 1)
+ {
+ if (starts_with_sequence (parm))
+ parm->strip_zeroes = 2; /* Found fixed length sequence. */
+ else
+ parm->strip_zeroes = 0; /* Disable zero padding check. */
+ }
+ else if (parm->strip_zeroes == 3)
+ {
+ /* Limit reached - check that only zeroes follow. */
+ while (!(c = es_getc (parm->fp)))
+ parm->nzeroes++;
+ if (c == EOF)
+ { /* only zeroes found. Reset zero padding engine and
+ * return EOF. */
+ parm->strip_zeroes = 0;
+ parm->eof_seen = 1;
+ return -1;
+ }
+ /* Not only zeroes. Reset engine and continue. */
+ parm->strip_zeroes = 0;
+ }
+ }
+
for (n=0; n < count; n++)
{
- c = es_getc (parm->fp);
+ if (parm->use_maxread && !--parm->maxread)
+ {
+ parm->use_maxread = 0;
+ if (parm->strip_zeroes)
+ {
+ parm->strip_zeroes = 3;
+ parm->nzeroes = 0;
+ if (n)
+ goto leave; /* Return what we already got. */
+ goto restart; /* Immediately check for trailing zeroes. */
+ }
+ }
+
+ if (parm->nzeroes)
+ {
+ parm->nzeroes--;
+ c = 0;
+ }
+ else
+ c = es_getc (parm->fp);
if (c == EOF)
{
parm->eof_seen = 1;
@@ -417,6 +530,7 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
*(byte *)buffer++ = c;
}
+ leave:
*nread = n;
return 0;
}
@@ -424,6 +538,33 @@ simple_reader_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
+/* Call the progress callback if its time. We do this very 2 seconds
+ * or if FORCE is set. However, we also require that at least 64KiB
+ * have been written to avoid unnecessary progress lines for small
+ * files. */
+static gpg_error_t
+update_write_progress (struct writer_cb_parm_s *parm, size_t count, int force)
+{
+ gpg_error_t err = 0;
+ u32 timestamp;
+
+ parm->progress.current += count;
+ if (parm->progress.current >= (64*1024))
+ {
+ timestamp = make_timestamp ();
+ if (force || (timestamp - parm->progress.last_time > 1))
+ {
+ parm->progress.last = parm->progress.current;
+ parm->progress.last_time = timestamp;
+ err = parm->progress.cb (parm->progress.ctrl,
+ parm->progress.current,
+ parm->progress.total);
+ }
+ }
+ return err;
+}
+
+
static int
base64_writer_cb (void *cb_value, const void *buffer, size_t count)
{
@@ -432,6 +573,8 @@ base64_writer_cb (void *cb_value, const void *buffer, size_t count)
int i, c, idx, quad_count;
const unsigned char *p;
estream_t stream = parm->stream;
+ int rc;
+ size_t nleft;
if (!count)
return 0;
@@ -454,7 +597,7 @@ base64_writer_cb (void *cb_value, const void *buffer, size_t count)
for (i=0; i < idx; i++)
radbuf[i] = parm->base64.radbuf[i];
- for (p=buffer; count; p++, count--)
+ for (p=buffer, nleft = count; nleft; p++, nleft--)
{
radbuf[idx++] = *p;
if (idx > 2)
@@ -480,7 +623,11 @@ base64_writer_cb (void *cb_value, const void *buffer, size_t count)
parm->base64.idx = idx;
parm->base64.quad_count = quad_count;
- return es_ferror (stream)? gpg_error_from_syserror () : 0;
+ rc = es_ferror (stream)? gpg_error_from_syserror () : 0;
+ /* Note that we use the unencoded count for the progress. */
+ if (!rc && parm->progress.cb)
+ rc = update_write_progress (parm, count, 0);
+ return rc;
}
@@ -491,13 +638,16 @@ plain_writer_cb (void *cb_value, const void *buffer, size_t count)
{
struct writer_cb_parm_s *parm = cb_value;
estream_t stream = parm->stream;
+ int rc;
if (!count)
return 0;
es_write (stream, buffer, count, NULL);
-
- return es_ferror (stream)? gpg_error_from_syserror () : 0;
+ rc = es_ferror (stream)? gpg_error_from_syserror () : 0;
+ if (!rc && parm->progress.cb)
+ rc = update_write_progress (parm, count, 0);
+ return rc;
}
@@ -507,6 +657,7 @@ base64_finish_write (struct writer_cb_parm_s *parm)
unsigned char *radbuf;
int c, idx, quad_count;
estream_t stream = parm->stream;
+ int rc;
if (!parm->wrote_begin)
return 0; /* Nothing written or we are not called in base-64 mode. */
@@ -553,7 +704,10 @@ base64_finish_write (struct writer_cb_parm_s *parm)
es_fputs ("-----\n", stream);
}
- return es_ferror (stream)? gpg_error_from_syserror () : 0;
+ rc = es_ferror (stream)? gpg_error_from_syserror () : 0;
+ if (!rc && parm->progress.cb)
+ rc = update_write_progress (parm, 0, 1);
+ return rc;
}
@@ -575,6 +729,7 @@ base64_finish_write (struct writer_cb_parm_s *parm)
* GNUPG_KSBA_IO_MULTIPEM - The reader expects that the caller uses
* ksba_reader_clear after EOF until no more
* objects were found.
+ * GNUPG_KSBA_IO_STRIP - Strip zero padding from some CMS objects.
*
* Note that the PEM flag has a higher priority than the BASE64 flag
* which in turn has a gight priority than the AUTODETECT flag.
@@ -592,6 +747,7 @@ gnupg_ksba_create_reader (gnupg_ksba_io_t *ctx,
if (!*ctx)
return out_of_core ();
(*ctx)->u.rparm.allow_multi_pem = !!(flags & GNUPG_KSBA_IO_MULTIPEM);
+ (*ctx)->u.rparm.strip_zeroes = !!(flags & GNUPG_KSBA_IO_STRIP);
rc = ksba_reader_new (&r);
if (rc)
@@ -683,6 +839,7 @@ gnupg_ksba_create_writer (gnupg_ksba_io_t *ctx, unsigned int flags,
*ctx = xtrycalloc (1, sizeof **ctx);
if (!*ctx)
return gpg_error_from_syserror ();
+ (*ctx)->is_writer = 1;
rc = ksba_writer_new (&w);
if (rc)
@@ -760,3 +917,37 @@ gnupg_ksba_destroy_writer (gnupg_ksba_io_t ctx)
xfree (ctx->u.wparm.pem_name);
xfree (ctx);
}
+
+
+/* Set a callback to the writer object. CTRL will be bassed to the
+ * callback. */
+void
+gnupg_ksba_set_progress_cb (gnupg_ksba_io_t ctx,
+ gnupg_ksba_progress_cb_t cb, ctrl_t ctrl)
+{
+ struct writer_cb_parm_s *parm;
+
+ if (!ctx || !ctx->is_writer)
+ return; /* Currently only supported for writer objects. */
+ parm = &ctx->u.wparm;
+
+ parm->progress.cb = cb;
+ parm->progress.ctrl = ctrl;
+ parm->progress.last_time = 0;
+ parm->progress.last = 0;
+ parm->progress.current = 0;
+ parm->progress.total = 0;
+}
+
+
+/* Update the total count for the progress thingy. */
+void
+gnupg_ksba_set_total (gnupg_ksba_io_t ctx, uint64_t total)
+{
+ struct writer_cb_parm_s *parm;
+
+ if (!ctx || !ctx->is_writer)
+ return; /* Currently only supported for writer objects. */
+ parm = &ctx->u.wparm;
+ parm->progress.total = total;
+}
diff --git a/common/ksba-io-support.h b/common/ksba-io-support.h
index e33e0ed..1dbc303 100644
--- a/common/ksba-io-support.h
+++ b/common/ksba-io-support.h
@@ -25,6 +25,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-later OR GPL-2.0-or-later)
*/
#ifndef GNUPG_KSBA_IO_SUPPORT_H
@@ -36,11 +37,16 @@
#define GNUPG_KSBA_IO_BASE64 2 /* Plain Base64 format. */
#define GNUPG_KSBA_IO_AUTODETECT 4 /* Try to autodetect the format. */
#define GNUPG_KSBA_IO_MULTIPEM 8 /* Allow more than one PEM chunk. */
+#define GNUPG_KSBA_IO_STRIP 16 /* Strip off zero padding. */
/* Context object. */
typedef struct gnupg_ksba_io_s *gnupg_ksba_io_t;
+/* Progress callback type. */
+typedef gpg_error_t (*gnupg_ksba_progress_cb_t)(ctrl_t ctrl,
+ uint64_t current,
+ uint64_t total);
gpg_error_t gnupg_ksba_create_reader (gnupg_ksba_io_t *ctx,
@@ -56,10 +62,13 @@ gpg_error_t gnupg_ksba_create_writer (gnupg_ksba_io_t *ctx,
const char *pem_name,
estream_t stream,
ksba_writer_t *r_writer);
-
gpg_error_t gnupg_ksba_finish_writer (gnupg_ksba_io_t ctx);
void gnupg_ksba_destroy_writer (gnupg_ksba_io_t ctx);
+void gnupg_ksba_set_progress_cb (gnupg_ksba_io_t ctx,
+ gnupg_ksba_progress_cb_t cb, ctrl_t ctrl);
+void gnupg_ksba_set_total (gnupg_ksba_io_t ctx, uint64_t total);
+
diff --git a/common/miscellaneous.c b/common/miscellaneous.c
index df6b687..f19cc53 100644
--- a/common/miscellaneous.c
+++ b/common/miscellaneous.c
@@ -418,7 +418,7 @@ decode_c_string (const char *src)
/* Check whether (BUF,LEN) is valid header for an OpenPGP compressed
* packet. LEN should be at least 6. */
static int
-is_openpgp_compressed_packet (unsigned char *buf, size_t len)
+is_openpgp_compressed_packet (const unsigned char *buf, size_t len)
{
int c, ctb, pkttype;
int lenbytes;
@@ -460,63 +460,64 @@ is_openpgp_compressed_packet (unsigned char *buf, size_t len)
/*
- * Check if the file is compressed.
+ * Check if the file is compressed. You need to pass the first bytes
+ * of the file as (BUF,BUFLEN). Returns true if the buffer seems to
+ * be compressed.
*/
int
-is_file_compressed (const char *s, int *ret_rc)
+is_file_compressed (const byte *buf, unsigned int buflen)
{
- iobuf_t a;
- byte buf[6];
- int i;
- int rc = 0;
- int overflow;
-
- struct magic_compress_s {
- size_t len;
- byte magic[4];
- } magic[] = {
- { 3, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
- { 3, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
- { 4, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
- };
-
- if ( iobuf_is_pipe_filename (s) || !ret_rc )
- return 0; /* We can't check stdin or no file was given */
-
- a = iobuf_open( s );
- if ( a == NULL ) {
- *ret_rc = gpg_error_from_syserror ();
- return 0;
- }
- iobuf_ioctl (a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
-
- if ( iobuf_get_filelength( a, &overflow ) < 6 && !overflow) {
- *ret_rc = 0;
- goto leave;
- }
-
- if ( iobuf_read( a, buf, 6 ) == -1 ) {
- *ret_rc = a->error;
- goto leave;
+ int i;
+
+ struct magic_compress_s
+ {
+ byte len;
+ byte extchk;
+ byte magic[5];
+ } magic[] =
+ {
+ { 3, 0, { 0x42, 0x5a, 0x68, 0x00 } }, /* bzip2 */
+ { 3, 0, { 0x1f, 0x8b, 0x08, 0x00 } }, /* gzip */
+ { 4, 0, { 0x50, 0x4b, 0x03, 0x04 } }, /* (pk)zip */
+ { 5, 0, { '%', 'P', 'D', 'F', '-'} }, /* PDF */
+ { 4, 1, { 0xff, 0xd8, 0xff, 0xe0 } }, /* Maybe JFIF */
+ { 5, 2, { 0x89, 'P','N','G', 0x0d} } /* Likely PNG */
+ };
+
+ if ( buflen < 6 )
+ {
+ return 0; /* Too short to check - assume uncompressed. */
}
- for ( i = 0; i < DIM( magic ); i++ ) {
- if ( !memcmp( buf, magic[i].magic, magic[i].len ) ) {
- *ret_rc = 0;
- rc = 1;
- goto leave;
+ for ( i = 0; i < DIM (magic); i++ )
+ {
+ if (!memcmp( buf, magic[i].magic, magic[i].len))
+ {
+ switch (magic[i].extchk)
+ {
+ case 0:
+ return 1; /* Is compressed. */
+ case 1:
+ if (buflen > 11 && !memcmp (buf + 6, "JFIF", 5))
+ return 1; /* JFIF: this likely a compressed JPEG. */
+ break;
+ case 2:
+ if (buflen > 8
+ && buf[5] == 0x0a && buf[6] == 0x1a && buf[7] == 0x0a)
+ return 1; /* This is a PNG. */
+ break;
+ default:
+ break;
+ }
}
}
- if (is_openpgp_compressed_packet (buf, 6))
- {
- *ret_rc = 0;
- rc = 1;
- }
+ if (buflen >= 6 && is_openpgp_compressed_packet (buf, buflen))
+ {
+ return 1; /* Already compressed. */
+ }
- leave:
- iobuf_close( a );
- return rc;
+ return 0; /* Not detected as compressed. */
}
diff --git a/common/name-value.c b/common/name-value.c
index d1d0a3f..0dffc63 100644
--- a/common/name-value.c
+++ b/common/name-value.c
@@ -497,6 +497,30 @@ nvc_set (nvc_t pk, const char *name, const char *value)
}
+/* Update entry E to VALUE. */
+gpg_error_t
+nve_set (nve_t e, const char *value)
+{
+ char *v;
+
+ if (!e)
+ return GPG_ERR_INV_ARG;
+
+ v = xtrystrdup (value? value:"");
+ if (!v)
+ return my_error_from_syserror ();
+
+ free_strlist_wipe (e->raw_value);
+ e->raw_value = NULL;
+ if (e->value)
+ wipememory (e->value, strlen (e->value));
+ xfree (e->value);
+ e->value = v;
+
+ return 0;
+}
+
+
/* Delete the given entry from PK. */
void
nvc_delete (nvc_t pk, nve_t entry)
@@ -592,7 +616,7 @@ nve_next_value (nve_t entry, const char *name)
/* Return the string for the first entry in NVC with NAME. If an
* entry with NAME is missing in NVC or its value is the empty string
- * NULL is returned. Note that the The returned string is a pointer
+ * NULL is returned. Note that the the returned string is a pointer
* into NVC. */
const char *
nvc_get_string (nvc_t nvc, const char *name)
@@ -608,13 +632,14 @@ nvc_get_string (nvc_t nvc, const char *name)
}
-/* Return true if NAME exists and its value is true; that is either
- * "yes", "true", or a decimal value unequal to 0. */
+/* Return true (ie. a non-zero value) if NAME exists and its value is
+ * true; that is either "yes", "true", or a decimal value unequal to 0. */
int
nvc_get_boolean (nvc_t nvc, const char *name)
{
nve_t item;
const char *s;
+ int n;
if (!nvc)
return 0;
@@ -622,9 +647,12 @@ nvc_get_boolean (nvc_t nvc, const char *name)
if (!item)
return 0;
s = nve_value (item);
- if (s && (atoi (s)
- || !ascii_strcasecmp (s, "yes")
- || !ascii_strcasecmp (s, "true")))
+ if (!s)
+ return 0;
+ n = atoi (s);
+ if (n)
+ return n;
+ if (!ascii_strcasecmp (s, "yes") || !ascii_strcasecmp (s, "true"))
return 1;
return 0;
}
diff --git a/common/name-value.h b/common/name-value.h
index cf854e0..b3fc2f6 100644
--- a/common/name-value.h
+++ b/common/name-value.h
@@ -75,7 +75,8 @@ nve_t nve_next_value (nve_t entry, const char *name);
/* Return the string for the first entry in NVC with NAME or NULL. */
const char *nvc_get_string (nvc_t nvc, const char *name);
-/* Return a boolean value for the first entry in NVC with NAME. */
+/* Return a boolean value (zero or non-zero) for the first entry in
+ * NVC with NAME. */
int nvc_get_boolean (nvc_t nvc, const char *name);
@@ -91,6 +92,9 @@ gpg_error_t nvc_add (nvc_t pk, const char *name, const char *value);
first entry is updated. */
gpg_error_t nvc_set (nvc_t pk, const char *name, const char *value);
+/* Update entry E to VALUE. */
+gpg_error_t nve_set (nve_t e, const char *value);
+
/* Delete the given entry from PK. */
void nvc_delete (nvc_t pk, nve_t pke);
diff --git a/common/openpgp-oid.c b/common/openpgp-oid.c
index f0460b0..4930549 100644
--- a/common/openpgp-oid.c
+++ b/common/openpgp-oid.c
@@ -48,6 +48,8 @@ static struct {
{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519", PUBKEY_ALGO_ECDH },
{ "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519", PUBKEY_ALGO_EDDSA },
+ { "Curve25519", "1.3.101.110", 255, "cv25519", PUBKEY_ALGO_ECDH },
+ { "Ed25519", "1.3.101.112", 255, "ed25519", PUBKEY_ALGO_EDDSA },
{ "X448", "1.3.101.111", 448, "cv448", PUBKEY_ALGO_ECDH },
{ "Ed448", "1.3.101.113", 456, "ed448", PUBKEY_ALGO_EDDSA },
@@ -65,13 +67,17 @@ static struct {
};
-/* The OID for Curve Ed25519 in OpenPGP format. */
+/* The OID for Curve Ed25519 in OpenPGP format. The shorter v5
+ * variant may only be used with v5 keys. */
static const char oid_ed25519[] =
{ 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 };
+static const char oid_ed25519_v5[] = { 0x03, 0x2b, 0x65, 0x70 };
-/* The OID for Curve25519 in OpenPGP format. */
+/* The OID for Curve25519 in OpenPGP format. The shorter v5
+ * variant may only be used with v5 keys. */
static const char oid_cv25519[] =
{ 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 };
+static const char oid_cv25519_v5[] = { 0x03, 0x2b, 0x65, 0x6e };
/* The OID for X448 in OpenPGP format. */
/*
@@ -321,8 +327,12 @@ openpgp_oid_to_str (gcry_mpi_t a)
int
openpgp_oidbuf_is_ed25519 (const void *buf, size_t len)
{
- return (buf && len == DIM (oid_ed25519)
- && !memcmp (buf, oid_ed25519, DIM (oid_ed25519)));
+ if (!buf)
+ return 0;
+ return ((len == DIM (oid_ed25519)
+ && !memcmp (buf, oid_ed25519, DIM (oid_ed25519)))
+ || (len == DIM (oid_ed25519_v5)
+ && !memcmp (buf, oid_ed25519_v5, DIM (oid_ed25519_v5))));
}
@@ -345,8 +355,12 @@ openpgp_oid_is_ed25519 (gcry_mpi_t a)
int
openpgp_oidbuf_is_cv25519 (const void *buf, size_t len)
{
- return (buf && len == DIM (oid_cv25519)
- && !memcmp (buf, oid_cv25519, DIM (oid_cv25519)));
+ if (!buf)
+ return 0;
+ return ((len == DIM (oid_cv25519)
+ && !memcmp (buf, oid_cv25519, DIM (oid_cv25519)))
+ || (len == DIM (oid_cv25519_v5)
+ && !memcmp (buf, oid_cv25519_v5, DIM (oid_cv25519_v5))));
}
@@ -430,8 +444,9 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo)
if (name)
{
for (i=0; oidtable[i].name; i++)
- if (!strcmp (oidtable[i].name, name)
- || (oidtable[i].alias && !strcmp (oidtable[i].alias, name)))
+ if (!ascii_strcasecmp (oidtable[i].name, name)
+ || (oidtable[i].alias
+ && !ascii_strcasecmp (oidtable[i].alias, name)))
{
oidstr = oidtable[i].oidstr;
nbits = oidtable[i].nbits;
@@ -443,7 +458,7 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits, int *r_algo)
/* If not found assume the input is already an OID and check
whether we support it. */
for (i=0; oidtable[i].name; i++)
- if (!strcmp (name, oidtable[i].oidstr))
+ if (!ascii_strcasecmp (name, oidtable[i].oidstr))
{
oidstr = oidtable[i].oidstr;
nbits = oidtable[i].nbits;
@@ -492,9 +507,10 @@ openpgp_oid_or_name_to_curve (const char *oidname, int canon)
return NULL;
for (i=0; oidtable[i].name; i++)
- if (!strcmp (oidtable[i].oidstr, oidname)
- || !strcmp (oidtable[i].name, oidname)
- || (oidtable[i].alias &&!strcmp (oidtable[i].alias, oidname)))
+ if (!ascii_strcasecmp (oidtable[i].oidstr, oidname)
+ || !ascii_strcasecmp (oidtable[i].name, oidname)
+ || (oidtable[i].alias
+ && !ascii_strcasecmp (oidtable[i].alias, oidname)))
return !canon && oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
return NULL;
@@ -556,8 +572,9 @@ openpgp_is_curve_supported (const char *name, int *r_algo,
*r_nbits = 0;
for (idx = 0; idx < DIM (oidtable) && oidtable[idx].name; idx++)
{
- if ((!strcmp (name, oidtable[idx].name)
- || (oidtable[idx].alias && !strcmp (name, (oidtable[idx].alias))))
+ if ((!ascii_strcasecmp (name, oidtable[idx].name)
+ || (oidtable[idx].alias
+ && !ascii_strcasecmp (name, (oidtable[idx].alias))))
&& curve_supported_p (oidtable[idx].name))
{
if (r_algo)
@@ -659,7 +676,7 @@ get_keyalgo_string (enum gcry_pk_algos algo,
{
if (keyalgo_strings[i].algo == algo
&& keyalgo_strings[i].curve && curve
- && !strcmp (keyalgo_strings[i].curve, curve))
+ && !ascii_strcasecmp (keyalgo_strings[i].curve, curve))
return keyalgo_strings[i].name;
}
diff --git a/common/recsel.c b/common/recsel.c
index 60da4d3..ea0858c 100644
--- a/common/recsel.c
+++ b/common/recsel.c
@@ -174,6 +174,7 @@ find_next_lc (char *string)
* -c The string match in this part is done case-sensitive.
* -t Do not trim leading and trailing spaces from VALUE.
* Note that a space after <op> is here required.
+ * -r RFU: String match uses a regular expression
*
* For example four calls to recsel_parse_expr() with these values for
* EXPR
@@ -192,7 +193,7 @@ find_next_lc (char *string)
*
* The caller must pass the address of a selector variable to this
* function and initialize the value of the function to NULL before
- * the first call. recset_release needs to be called to free the
+ * the first call. recsel_release needs to be called to free the
* selector.
*/
gpg_error_t
diff --git a/common/sexputil.c b/common/sexputil.c
index b7ddea8..c7471be 100644
--- a/common/sexputil.c
+++ b/common/sexputil.c
@@ -536,7 +536,8 @@ get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
return err;
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
return err;
- if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
+ if (!tok || !((toklen == 10 && !memcmp ("public-key", tok, toklen))
+ || (toklen == 11 && !memcmp ("private-key", tok, toklen))))
return gpg_error (GPG_ERR_BAD_PUBKEY);
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
return err;
@@ -613,7 +614,7 @@ get_ecc_q_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
size_t buflen, toklen;
int depth, last_depth1, last_depth2;
const unsigned char *ecc_q = NULL;
- size_t ecc_q_len;
+ size_t ecc_q_len = 0;
*r_q = NULL;
*r_qlen = 0;
@@ -1075,6 +1076,8 @@ pubkey_algo_string (gcry_sexp_t s_pkey, enum gcry_pk_algos *r_algoid)
l1 = gcry_sexp_find_token (s_pkey, "public-key", 0);
if (!l1)
+ l1 = gcry_sexp_find_token (s_pkey, "private-key", 0);
+ if (!l1)
return xtrystrdup ("E_no_key");
{
gcry_sexp_t l_tmp = gcry_sexp_cadr (l1);
diff --git a/common/status-codes.h b/common/status-codes.h
index 0d1e6be..c029470 100644
--- a/common/status-codes.h
+++ b/common/status-codes.h
@@ -48,6 +48,7 @@ static const char statusstr_msgstr[] =
"TRUST_ULTIMATE" "\0"
"NEED_PASSPHRASE" "\0"
"VALIDSIG" "\0"
+ "ASSERT_SIGNER" "\0"
"SIG_ID" "\0"
"ENC_TO" "\0"
"NODATA" "\0"
@@ -154,95 +155,96 @@ static const int statusstr_msgidx[] =
136,
152,
161,
- 168,
175,
182,
- 197,
- 207,
- 217,
- 237,
- 252,
- 268,
- 286,
- 302,
- 321,
- 337,
- 345,
- 352,
+ 189,
+ 196,
+ 211,
+ 221,
+ 231,
+ 251,
+ 266,
+ 282,
+ 300,
+ 316,
+ 335,
+ 351,
359,
- 368,
- 378,
- 393,
- 404,
- 417,
- 426,
- 437,
- 448,
- 458,
- 469,
- 486,
- 501,
- 518,
- 533,
+ 366,
+ 373,
+ 382,
+ 392,
+ 407,
+ 418,
+ 431,
+ 440,
+ 451,
+ 462,
+ 472,
+ 483,
+ 500,
+ 515,
+ 532,
547,
- 562,
- 571,
- 580,
- 591,
- 598,
- 607,
- 619,
- 631,
+ 561,
+ 576,
+ 585,
+ 594,
+ 605,
+ 612,
+ 621,
+ 633,
645,
- 660,
+ 659,
674,
- 685,
- 697,
- 709,
- 720,
- 729,
- 738,
- 746,
- 754,
- 769,
- 784,
- 795,
- 806,
- 813,
- 823,
- 833,
- 843,
- 850,
+ 688,
+ 699,
+ 711,
+ 723,
+ 734,
+ 743,
+ 752,
+ 760,
+ 768,
+ 783,
+ 798,
+ 809,
+ 820,
+ 827,
+ 837,
+ 847,
+ 857,
864,
- 874,
- 891,
- 907,
- 927,
- 936,
+ 878,
+ 888,
+ 905,
+ 921,
+ 941,
950,
964,
- 983,
+ 978,
997,
- 1012,
- 1022,
- 1033,
- 1050,
- 1066,
- 1093,
- 1120,
- 1149,
- 1159,
- 1170,
- 1179,
- 1197,
- 1215,
- 1221,
+ 1011,
+ 1026,
+ 1036,
+ 1047,
+ 1064,
+ 1080,
+ 1107,
+ 1134,
+ 1163,
+ 1173,
+ 1184,
+ 1193,
+ 1211,
1229,
- 1237,
- 1245,
+ 1235,
+ 1243,
+ 1251,
+ 1259,
};
#define statusstr_msgidxof(code) (0 ? -1 \
- : ((code >= 0) && (code <= 101)) ? (code - 0) \
+ : ((code >= 0) && (code <= 102)) ? (code - 0) \
: -1)
diff --git a/common/status.c b/common/status.c
index b752c12..b7dc1de 100644
--- a/common/status.c
+++ b/common/status.c
@@ -158,7 +158,8 @@ get_inv_recpsgnr_code (gpg_error_t err)
case GPG_ERR_WRONG_KEY_USAGE: errstr = "3"; break;
case GPG_ERR_CERT_REVOKED: errstr = "4"; break;
case GPG_ERR_CERT_EXPIRED: errstr = "5"; break;
- case GPG_ERR_NO_CRL_KNOWN: errstr = "6"; break;
+ case GPG_ERR_NO_CRL_KNOWN:
+ case GPG_ERR_INV_CRL_OBJ: errstr = "6"; break;
case GPG_ERR_CRL_TOO_OLD: errstr = "7"; break;
case GPG_ERR_NO_POLICY_MATCH: errstr = "8"; break;
diff --git a/common/status.h b/common/status.h
index 0c481d2..e4cf23e 100644
--- a/common/status.h
+++ b/common/status.h
@@ -53,6 +53,7 @@ enum
STATUS_NEED_PASSPHRASE,
STATUS_VALIDSIG,
+ STATUS_ASSERT_SIGNER,
STATUS_SIG_ID,
STATUS_ENC_TO,
STATUS_NODATA,
diff --git a/common/stringhelp.c b/common/stringhelp.c
index 6959299..1049c78 100644
--- a/common/stringhelp.c
+++ b/common/stringhelp.c
@@ -1689,10 +1689,16 @@ format_text (const char *text_in, int target_cols, int max_cols)
}
-/* Substitute environment variables in STRING and return a new string.
- * On error the function returns NULL. */
+/* Substitute variables in STRING and return a new string. GETVAL is
+ * a function which maps NAME to its value; that value is a string
+ * which may not change during the execution time of this function.
+ * If GETVAL returns NULL substitute_vars returns NULL and the caller
+ * may inspect ERRNO for the reason. In all other error cases this
+ * function also returns NULL. Caller must free the returned string. */
char *
-substitute_envvars (const char *string)
+substitute_vars (const char *string,
+ const char *(*getval)(void *cookie, const char *name),
+ void *cookie)
{
char *line, *p, *pend;
const char *value;
@@ -1743,19 +1749,22 @@ substitute_envvars (const char *string)
{
int save = *pend;
*pend = 0;
- value = getenv (p+2);
+ value = getval (cookie, p+2);
*pend++ = save;
}
else
{
int save = *pend;
*pend = 0;
- value = getenv (p+1);
+ value = getval (cookie, p+1);
*pend = save;
}
if (!value)
- value = "";
+ {
+ xfree (result);
+ return NULL;
+ }
valuelen = strlen (value);
if (valuelen <= pend - p)
{
@@ -1791,3 +1800,26 @@ substitute_envvars (const char *string)
leave:
return result;
}
+
+
+/* Helper for substitute_envvars. */
+static const char *
+subst_getenv (void *cookie, const char *name)
+{
+ const char *s;
+
+ (void)cookie;
+
+ s = getenv (name);
+ return s? s : "";
+}
+
+
+/* Substitute environment variables in STRING and return a new string.
+ * On error the function returns NULL. */
+char *
+substitute_envvars (const char *string)
+{
+ return substitute_vars (string, subst_getenv, NULL);
+
+}
diff --git a/common/stringhelp.h b/common/stringhelp.h
index 915b3aa..cd185e4 100644
--- a/common/stringhelp.h
+++ b/common/stringhelp.h
@@ -169,7 +169,10 @@ int compare_version_strings (const char *my_version, const char *req_version);
/* Format a string so that it fits within about TARGET_COLS columns. */
char *format_text (const char *text, int target_cols, int max_cols);
-/* Substitute environmen variabales in STRING. */
+/* Substitute variables in STRING. */
+char *substitute_vars (const char *string,
+ const char *(*getval)(void *cookie, const char *name),
+ void *cookie);
char *substitute_envvars (const char *string);
diff --git a/common/sysutils.c b/common/sysutils.c
index 01510dd..f8e6d86 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -252,6 +252,9 @@ map_w32_to_errno (DWORD w32_err)
case ERROR_ALREADY_EXISTS:
return EEXIST;
+ case ERROR_FILE_INVALID:
+ return EIO;
+
/* This mapping has been taken from reactOS. */
case ERROR_TOO_MANY_OPEN_FILES: return EMFILE;
case ERROR_ARENA_TRASHED: return ENOMEM;
@@ -324,9 +327,10 @@ map_w32_to_errno (DWORD w32_err)
#endif /*HAVE_W32_SYSTEM*/
-/* Set ERRNO from the Windows error. EC may be -1 to use the last error. */
+/* Set ERRNO from the Windows error. EC may be -1 to use the last
+ * error. Returns the Windows error code. */
#ifdef HAVE_W32_SYSTEM
-void
+int
gnupg_w32_set_errno (int ec)
{
/* FIXME: Replace by gpgrt_w32_set_errno. */
diff --git a/common/sysutils.h b/common/sysutils.h
index 7063da0..a78a81c 100644
--- a/common/sysutils.h
+++ b/common/sysutils.h
@@ -110,7 +110,7 @@ int gnupg_inotify_has_name (int fd, const char *name);
#ifdef HAVE_W32_SYSTEM
-void gnupg_w32_set_errno (int ec);
+int gnupg_w32_set_errno (int ec);
void *w32_get_user_sid (void);
#include "../common/w32help.h"
diff --git a/common/tlv.c b/common/tlv.c
index 9618d04..4ba9ef2 100644
--- a/common/tlv.c
+++ b/common/tlv.c
@@ -150,8 +150,10 @@ find_tlv_unchecked (const unsigned char *buffer, size_t length,
/* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag
- and the length part from the TLV triplet. Update BUFFER and SIZE
- on success. */
+ * and the length part from the TLV triplet. Update BUFFER and SIZE
+ * on success. Note that this function does not check that the value
+ * fits into the provided buffer; this allows to work on the TL part
+ * of a TLV. */
gpg_error_t
parse_ber_header (unsigned char const **buffer, size_t *size,
int *r_class, int *r_tag,
diff --git a/common/util.h b/common/util.h
index 6978ab8..aa24e39 100644
--- a/common/util.h
+++ b/common/util.h
@@ -298,6 +298,7 @@ char *_gnupg_socketdir_internal (int skip_checks, unsigned *r_info);
#define GNUPG_MODULE_NAME_KEYBOXD 13
#define GNUPG_MODULE_NAME_TPM2DAEMON 14
#define GNUPG_MODULE_NAME_CARD 15
+#define GNUPG_MODULE_NAME_GPGTAR 16
const char *gnupg_module_name (int which);
void gnupg_module_name_flush_some (void);
void gnupg_set_builddir (const char *newdir);
@@ -359,7 +360,7 @@ 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);
+int is_file_compressed (const byte *buf, unsigned int buflen);
int match_multistr (const char *multistr,const char *match);
diff --git a/common/w32info-rc.h.in b/common/w32info-rc.h.in
index 94f13b0..1e76b58 100644
--- a/common/w32info-rc.h.in
+++ b/common/w32info-rc.h.in
@@ -29,4 +29,4 @@ built on @BUILD_HOSTNAME@ at @BUILD_TIMESTAMP@\0"
#define W32INFO_PRODUCTVERSION "@VERSION@\0"
#define W32INFO_LEGALCOPYRIGHT "Copyright \xa9 \
-2021 g10 Code GmbH\0"
+2023 g10 Code GmbH\0"