mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Merge branch 'STABLE-BRANCH-2-2'
This commit is contained in:
commit
20539ea5ca
10
AUTHORS
10
AUTHORS
@ -15,9 +15,9 @@ copyrightable year that would otherwise be listed individually.
|
|||||||
List of Copyright holders
|
List of Copyright holders
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
Copyright (C) 1997-2017 Werner Koch
|
Copyright (C) 1997-2018 Werner Koch
|
||||||
Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
Copyright (C) 1994-2018 Free Software Foundation, Inc.
|
||||||
Copyright (C) 2003-2013,2015-2017 g10 Code GmbH
|
Copyright (C) 2003-2013,2015-2018 g10 Code GmbH
|
||||||
Copyright (C) 2002 Klarälvdalens Datakonsult AB
|
Copyright (C) 2002 Klarälvdalens Datakonsult AB
|
||||||
Copyright (C) 1995-1997, 2000-2007 Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
Copyright (C) 1995-1997, 2000-2007 Ulrich Drepper <drepper@gnu.ai.mit.edu>
|
||||||
Copyright (C) 1994 X Consortium
|
Copyright (C) 1994 X Consortium
|
||||||
@ -264,8 +264,8 @@ domain.
|
|||||||
|
|
||||||
=========
|
=========
|
||||||
|
|
||||||
Copyright 1998-2017 Free Software Foundation, Inc.
|
Copyright 1998-2018 Free Software Foundation, Inc.
|
||||||
Copyright 1997-2017 Werner Koch
|
Copyright 1997-2018 Werner Koch
|
||||||
|
|
||||||
This file is free software; as a special exception the author gives
|
This file is free software; as a special exception the author gives
|
||||||
unlimited permission to copy and/or distribute it, with or without
|
unlimited permission to copy and/or distribute it, with or without
|
||||||
|
4
README
4
README
@ -2,8 +2,8 @@
|
|||||||
=========================
|
=========================
|
||||||
Version 2.2
|
Version 2.2
|
||||||
|
|
||||||
Copyright 1997-2017 Werner Koch
|
Copyright 1997-2018 Werner Koch
|
||||||
Copyright 1998-2017 Free Software Foundation, Inc.
|
Copyright 1998-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
|
||||||
* INTRODUCTION
|
* INTRODUCTION
|
||||||
|
@ -293,50 +293,19 @@ parse_keygrip (assuan_context_t ctx, const char *string, unsigned char *buf)
|
|||||||
|
|
||||||
|
|
||||||
/* Write an Assuan status line. KEYWORD is the first item on the
|
/* Write an Assuan status line. KEYWORD is the first item on the
|
||||||
status line. The following arguments are all separated by a space
|
* status line. The following arguments are all separated by a space
|
||||||
in the output. The last argument must be a NULL. Linefeeds and
|
* in the output. The last argument must be a NULL. Linefeeds and
|
||||||
carriage returns characters (which are not allowed in an Assuan
|
* carriage returns characters (which are not allowed in an Assuan
|
||||||
status line) are silently quoted in C-style. */
|
* status line) are silently quoted in C-style. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
agent_write_status (ctrl_t ctrl, const char *keyword, ...)
|
agent_write_status (ctrl_t ctrl, const char *keyword, ...)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err;
|
||||||
va_list arg_ptr;
|
va_list arg_ptr;
|
||||||
const char *text;
|
|
||||||
assuan_context_t ctx = ctrl->server_local->assuan_ctx;
|
assuan_context_t ctx = ctrl->server_local->assuan_ctx;
|
||||||
char buf[950], *p;
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
va_start (arg_ptr, keyword);
|
va_start (arg_ptr, keyword);
|
||||||
|
err = vprint_assuan_status_strings (ctx, keyword, arg_ptr);
|
||||||
p = buf;
|
|
||||||
n = 0;
|
|
||||||
while ( (text = va_arg (arg_ptr, const char *)) )
|
|
||||||
{
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
*p++ = ' ';
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
for ( ; *text && n < DIM (buf)-3; n++, text++)
|
|
||||||
{
|
|
||||||
if (*text == '\n')
|
|
||||||
{
|
|
||||||
*p++ = '\\';
|
|
||||||
*p++ = 'n';
|
|
||||||
}
|
|
||||||
else if (*text == '\r')
|
|
||||||
{
|
|
||||||
*p++ = '\\';
|
|
||||||
*p++ = 'r';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*p++ = *text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*p = 0;
|
|
||||||
err = assuan_write_status (ctx, keyword, buf);
|
|
||||||
|
|
||||||
va_end (arg_ptr);
|
va_end (arg_ptr);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -1062,7 +1031,8 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
|||||||
rc = gpg_error_from_syserror ();
|
rc = gpg_error_from_syserror ();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, pkbuf, pkbuflen);
|
pkbuflen = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON,
|
||||||
|
pkbuf, pkbuflen);
|
||||||
rc = assuan_send_data (ctx, pkbuf, pkbuflen);
|
rc = assuan_send_data (ctx, pkbuf, pkbuflen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ help:
|
|||||||
@echo 'You may append INSTALL_PREFIX=<dir> for native builds.'
|
@echo 'You may append INSTALL_PREFIX=<dir> for native builds.'
|
||||||
@echo 'Prepend TARGET with "git-" to build from GIT repos.'
|
@echo 'Prepend TARGET with "git-" to build from GIT repos.'
|
||||||
@echo 'Prepend TARGET with "this-" to build from the source tarball.'
|
@echo 'Prepend TARGET with "this-" to build from the source tarball.'
|
||||||
|
@echo 'Use STATIC=1 to build with statically linked libraries.'
|
||||||
@echo 'Use SELFCHECK=0 for a non-released version.'
|
@echo 'Use SELFCHECK=0 for a non-released version.'
|
||||||
@echo 'Use CUSTOM_SWDB=1 for an already downloaded swdb.lst.'
|
@echo 'Use CUSTOM_SWDB=1 for an already downloaded swdb.lst.'
|
||||||
|
|
||||||
@ -140,6 +141,9 @@ UPD_SWDB=0
|
|||||||
# Set to 0 to skip the GnuPG version self-check
|
# Set to 0 to skip the GnuPG version self-check
|
||||||
SELFCHECK=1
|
SELFCHECK=1
|
||||||
|
|
||||||
|
# Set to 1 to build with statically linked libraries.
|
||||||
|
STATIC=0
|
||||||
|
|
||||||
# Set to the location of the directory with tarballs of
|
# Set to the location of the directory with tarballs of
|
||||||
# external packages.
|
# external packages.
|
||||||
TARBALLS=$(shell pwd)/../tarballs
|
TARBALLS=$(shell pwd)/../tarballs
|
||||||
@ -208,8 +212,10 @@ speedo_spkgs += \
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(STATIC),0)
|
||||||
speedo_spkgs += \
|
speedo_spkgs += \
|
||||||
gpgme
|
gpgme
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(TARGETOS),w32)
|
ifeq ($(TARGETOS),w32)
|
||||||
ifeq ($(WITH_GUI),1)
|
ifeq ($(WITH_GUI),1)
|
||||||
@ -461,6 +467,8 @@ speedo_pkg_gtk__tar = $(pkg2rep)/gtk+-$(gtk__ver).tar.xz
|
|||||||
# Package build options
|
# Package build options
|
||||||
#
|
#
|
||||||
|
|
||||||
|
speedo_pkg_npth_configure = --enable-static
|
||||||
|
|
||||||
speedo_pkg_libgpg_error_configure = --enable-static
|
speedo_pkg_libgpg_error_configure = --enable-static
|
||||||
speedo_pkg_w64_libgpg_error_configure = --enable-static
|
speedo_pkg_w64_libgpg_error_configure = --enable-static
|
||||||
|
|
||||||
@ -471,15 +479,30 @@ speedo_pkg_libgcrypt_configure = --disable-static
|
|||||||
|
|
||||||
speedo_pkg_libksba_configure = --disable-static
|
speedo_pkg_libksba_configure = --disable-static
|
||||||
|
|
||||||
|
speedo_pkg_ntbtls_configure = --enable-static
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($(STATIC),1)
|
||||||
|
speedo_pkg_npth_configure += --disable-shared
|
||||||
|
|
||||||
|
speedo_pkg_libgpg_error_configure += --disable-shared
|
||||||
|
|
||||||
|
speedo_pkg_libassuan_configure += --disable-shared
|
||||||
|
|
||||||
|
speedo_pkg_libgcrypt_configure += --disable-shared
|
||||||
|
|
||||||
|
speedo_pkg_libksba_configure += --disable-shared
|
||||||
|
endif
|
||||||
|
|
||||||
# For now we build ntbtls only static
|
# For now we build ntbtls only static
|
||||||
speedo_pkg_ntbtls_configure = --enable-static --disable-shared
|
speedo_pkg_ntbtls_configure = --disable-shared
|
||||||
|
|
||||||
ifeq ($(TARGETOS),w32)
|
ifeq ($(TARGETOS),w32)
|
||||||
speedo_pkg_gnupg_configure = \
|
speedo_pkg_gnupg_configure = \
|
||||||
--disable-g13 --enable-ntbtls \
|
--disable-g13 --enable-ntbtls \
|
||||||
--enable-build-timestamp
|
--enable-build-timestamp
|
||||||
else
|
else
|
||||||
speedo_pkg_gnupg_configure = --disable-g13
|
speedo_pkg_gnupg_configure = --disable-g13 --enable-wks-tools
|
||||||
endif
|
endif
|
||||||
speedo_pkg_gnupg_extracflags = -g
|
speedo_pkg_gnupg_extracflags = -g
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
#else /* Used by GnuPG */
|
#else /* Used by GnuPG */
|
||||||
|
|
||||||
# define ARGPARSE_GPL_VERSION 3
|
# define ARGPARSE_GPL_VERSION 3
|
||||||
# define ARGPARSE_CRIGHT_STR "Copyright (C) 2017 Free Software Foundation, Inc."
|
# define ARGPARSE_CRIGHT_STR "Copyright (C) 2018 Free Software Foundation, Inc."
|
||||||
|
|
||||||
#endif /*GNUPG_MAJOR_VERSION*/
|
#endif /*GNUPG_MAJOR_VERSION*/
|
||||||
|
|
||||||
|
@ -93,5 +93,12 @@ gpg_error_t vprint_assuan_status (assuan_context_t ctx,
|
|||||||
const char *format,
|
const char *format,
|
||||||
va_list arg_ptr) GPGRT_ATTR_PRINTF(3,0);
|
va_list arg_ptr) GPGRT_ATTR_PRINTF(3,0);
|
||||||
|
|
||||||
|
gpg_error_t vprint_assuan_status_strings (assuan_context_t ctx,
|
||||||
|
const char *keyword,
|
||||||
|
va_list arg_ptr);
|
||||||
|
gpg_error_t print_assuan_status_strings (assuan_context_t ctx,
|
||||||
|
const char *keyword,
|
||||||
|
...) GPGRT_ATTR_SENTINEL(1);
|
||||||
|
|
||||||
|
|
||||||
#endif /*GNUPG_COMMON_ASSHELP_H*/
|
#endif /*GNUPG_COMMON_ASSHELP_H*/
|
||||||
|
@ -71,3 +71,66 @@ print_assuan_status (assuan_context_t ctx,
|
|||||||
va_end (arg_ptr);
|
va_end (arg_ptr);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper function to print a list of strings as an assuan status
|
||||||
|
* line. KEYWORD is the first item on the status line. ARG_PTR is a
|
||||||
|
* list of strings which are all separated by a space in the output.
|
||||||
|
* The last argument must be a NULL. Linefeeds and carriage returns
|
||||||
|
* characters (which are not allowed in an Assuan status line) are
|
||||||
|
* silently quoted in C-style. */
|
||||||
|
gpg_error_t
|
||||||
|
vprint_assuan_status_strings (assuan_context_t ctx,
|
||||||
|
const char *keyword, va_list arg_ptr)
|
||||||
|
{
|
||||||
|
gpg_error_t err = 0;
|
||||||
|
const char *text;
|
||||||
|
char buf[950], *p;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
n = 0;
|
||||||
|
while ((text = va_arg (arg_ptr, const char *)) && n < DIM (buf)-3 )
|
||||||
|
{
|
||||||
|
if (n)
|
||||||
|
{
|
||||||
|
*p++ = ' ';
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
for ( ; *text && n < DIM (buf)-3; n++, text++)
|
||||||
|
{
|
||||||
|
if (*text == '\n')
|
||||||
|
{
|
||||||
|
*p++ = '\\';
|
||||||
|
*p++ = 'n';
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
else if (*text == '\r')
|
||||||
|
{
|
||||||
|
*p++ = '\\';
|
||||||
|
*p++ = 'r';
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*p++ = *text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p = 0;
|
||||||
|
err = assuan_write_status (ctx, keyword, buf);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* See vprint_assuan_status_strings. */
|
||||||
|
gpg_error_t
|
||||||
|
print_assuan_status_strings (assuan_context_t ctx, const char *keyword, ...)
|
||||||
|
{
|
||||||
|
va_list arg_ptr;
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
|
va_start (arg_ptr, keyword);
|
||||||
|
err = vprint_assuan_status_strings (ctx, keyword, arg_ptr);
|
||||||
|
va_end (arg_ptr);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
@ -29,4 +29,4 @@ built on @BUILD_HOSTNAME@ at @BUILD_TIMESTAMP@\0"
|
|||||||
#define W32INFO_PRODUCTVERSION "@VERSION@\0"
|
#define W32INFO_PRODUCTVERSION "@VERSION@\0"
|
||||||
|
|
||||||
#define W32INFO_LEGALCOPYRIGHT "Copyright \xa9 \
|
#define W32INFO_LEGALCOPYRIGHT "Copyright \xa9 \
|
||||||
2017 Free Software Foundation, Inc.\0"
|
2018 Free Software Foundation, Inc.\0"
|
||||||
|
18
configure.ac
18
configure.ac
@ -1,6 +1,6 @@
|
|||||||
# configure.ac - for GnuPG 2.1
|
# configure.ac - for GnuPG 2.1
|
||||||
# Copyright (C) 1998-2017 Free Software Foundation, Inc.
|
# Copyright (C) 1998-2018 Free Software Foundation, Inc.
|
||||||
# Copyright (C) 1998-2017 Werner Koch
|
# Copyright (C) 1998-2018 Werner Koch
|
||||||
#
|
#
|
||||||
# This file is part of GnuPG.
|
# This file is part of GnuPG.
|
||||||
#
|
#
|
||||||
@ -650,6 +650,7 @@ have_android_system=no
|
|||||||
use_simple_gettext=no
|
use_simple_gettext=no
|
||||||
use_ldapwrapper=yes
|
use_ldapwrapper=yes
|
||||||
mmap_needed=yes
|
mmap_needed=yes
|
||||||
|
require_pipe_to_unblock_pselect=no
|
||||||
case "${host}" in
|
case "${host}" in
|
||||||
*-mingw32*)
|
*-mingw32*)
|
||||||
# special stuff for Windoze NT
|
# special stuff for Windoze NT
|
||||||
@ -726,10 +727,20 @@ case "${host}" in
|
|||||||
AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
|
AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
|
||||||
Expose all libc features (__DARWIN_C_FULL).)
|
Expose all libc features (__DARWIN_C_FULL).)
|
||||||
;;
|
;;
|
||||||
|
*-*-netbsd*)
|
||||||
|
require_pipe_to_unblock_pselect=yes
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if test "$require_pipe_to_unblock_pselect" = yes; then
|
||||||
|
AC_DEFINE(HAVE_PSELECT_NO_EINTR, 1,
|
||||||
|
[Defined if we run on systems like NetBSD, where
|
||||||
|
pselect cannot be unblocked by signal from a thread
|
||||||
|
within the same process. We use pipe in this case, instead.])
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$have_dosish_system" = yes; then
|
if test "$have_dosish_system" = yes; then
|
||||||
AC_DEFINE(HAVE_DOSISH_SYSTEM,1,
|
AC_DEFINE(HAVE_DOSISH_SYSTEM,1,
|
||||||
[Defined if we run on some of the PCDOS like systems
|
[Defined if we run on some of the PCDOS like systems
|
||||||
@ -831,7 +842,8 @@ if test x"$LIBUSB_NAME" != x ; then
|
|||||||
have_libusb=yes ])
|
have_libusb=yes ])
|
||||||
AC_MSG_CHECKING([libusb include dir])
|
AC_MSG_CHECKING([libusb include dir])
|
||||||
usb_incdir_found="no"
|
usb_incdir_found="no"
|
||||||
for _incdir in "" "/usr/include/libusb-1.0" "/usr/local/include/libusb-1.0"; do
|
for _incdir in "" "/usr/include/libusb-1.0" \
|
||||||
|
"/usr/local/include/libusb-1.0" "/usr/pkg/include/libusb-1.0"; do
|
||||||
_libusb_save_cppflags=$CPPFLAGS
|
_libusb_save_cppflags=$CPPFLAGS
|
||||||
if test -n "${_incdir}"; then
|
if test -n "${_incdir}"; then
|
||||||
CPPFLAGS="-I${_incdir} ${CPPFLAGS}"
|
CPPFLAGS="-I${_incdir} ${CPPFLAGS}"
|
||||||
|
@ -2134,7 +2134,12 @@ cmd_keyserver (assuan_context_t ctx, char *line)
|
|||||||
if (resolve_flag)
|
if (resolve_flag)
|
||||||
{
|
{
|
||||||
err = ensure_keyserver (ctrl);
|
err = ensure_keyserver (ctrl);
|
||||||
if (!err)
|
if (err)
|
||||||
|
{
|
||||||
|
assuan_set_error (ctx, err,
|
||||||
|
"Bad keyserver configuration in dirmngr.conf");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
err = ks_action_resolve (ctrl, ctrl->server_local->keyservers);
|
err = ks_action_resolve (ctrl, ctrl->server_local->keyservers);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -2829,30 +2834,13 @@ dirmngr_status (ctrl_t ctrl, const char *keyword, ...)
|
|||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
va_list arg_ptr;
|
va_list arg_ptr;
|
||||||
const char *text;
|
|
||||||
assuan_context_t ctx;
|
assuan_context_t ctx;
|
||||||
|
|
||||||
va_start (arg_ptr, keyword);
|
va_start (arg_ptr, keyword);
|
||||||
|
|
||||||
if (ctrl->server_local && (ctx = ctrl->server_local->assuan_ctx))
|
if (ctrl->server_local && (ctx = ctrl->server_local->assuan_ctx))
|
||||||
{
|
{
|
||||||
char buf[950], *p;
|
err = vprint_assuan_status_strings (ctx, keyword, arg_ptr);
|
||||||
size_t n;
|
|
||||||
|
|
||||||
p = buf;
|
|
||||||
n = 0;
|
|
||||||
while ( (text = va_arg (arg_ptr, const char *)) )
|
|
||||||
{
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
*p++ = ' ';
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
for ( ; *text && n < DIM (buf)-2; n++)
|
|
||||||
*p++ = *text++;
|
|
||||||
}
|
|
||||||
*p = 0;
|
|
||||||
err = assuan_write_status (ctx, keyword, buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end (arg_ptr);
|
va_end (arg_ptr);
|
||||||
|
@ -6,6 +6,7 @@ default-new-key-algo rsa3072/cert,sign+rsa3072/encr
|
|||||||
|
|
||||||
[gpgsm]
|
[gpgsm]
|
||||||
enable-crl-checks
|
enable-crl-checks
|
||||||
|
compliance de-vs
|
||||||
|
|
||||||
[gpg-agent]
|
[gpg-agent]
|
||||||
enable-extended-key-format
|
enable-extended-key-format
|
||||||
|
13
doc/gpg.texi
13
doc/gpg.texi
@ -3829,6 +3829,19 @@ If you are going to verify detached signatures, make sure that the
|
|||||||
program knows about it; either give both filenames on the command line
|
program knows about it; either give both filenames on the command line
|
||||||
or use @samp{-} to specify STDIN.
|
or use @samp{-} to specify STDIN.
|
||||||
|
|
||||||
|
For scripted or other unattended use of @command{gpg} make sure to use
|
||||||
|
the machine-parseable interface and not the default interface which is
|
||||||
|
intended for direct use by humans. The machine-parseable interface
|
||||||
|
provides a stable and well documented API independent of the locale or
|
||||||
|
future changes of @command{gpg}. To enable this interface use the
|
||||||
|
options @option{--with-colons} and @option{--status-fd}. For certain
|
||||||
|
operations the option @option{--command-fd} may come handy too. See
|
||||||
|
this man page and the file @file{DETAILS} for the specification of the
|
||||||
|
interface. Note that the GnuPG ``info'' pages as well as the PDF
|
||||||
|
version of the GnuPG manual features a chapter on unattended use of
|
||||||
|
GnuPG. As an alternative the library @command{GPGME} can be used as a
|
||||||
|
high-level abstraction on top of that interface.
|
||||||
|
|
||||||
@mansect interoperability
|
@mansect interoperability
|
||||||
@chapheading INTEROPERABILITY WITH OTHER OPENPGP PROGRAMS
|
@chapheading INTEROPERABILITY WITH OTHER OPENPGP PROGRAMS
|
||||||
|
|
||||||
|
@ -257,10 +257,10 @@ fingerprints or keygrips.
|
|||||||
@item --export-secret-key-p12 @var{key-id}
|
@item --export-secret-key-p12 @var{key-id}
|
||||||
@opindex export-secret-key-p12
|
@opindex export-secret-key-p12
|
||||||
Export the private key and the certificate identified by @var{key-id} in
|
Export the private key and the certificate identified by @var{key-id} in
|
||||||
a PKCS#12 format. When used with the @code{--armor} option a few
|
using the PKCS#12 format. When used with the @code{--armor} option a few
|
||||||
informational lines are prepended to the output. Note, that the PKCS#12
|
informational lines are prepended to the output. Note, that the PKCS#12
|
||||||
format is not very secure and this command is only provided if there is
|
format is not very secure and proper transport security should be used
|
||||||
no other way to exchange the private key. (@xref{option --p12-charset}.)
|
to convey the exported key. (@xref{option --p12-charset}.)
|
||||||
|
|
||||||
@item --export-secret-key-p8 @var{key-id}
|
@item --export-secret-key-p8 @var{key-id}
|
||||||
@itemx --export-secret-key-raw @var{key-id}
|
@itemx --export-secret-key-raw @var{key-id}
|
||||||
|
26
doc/wks.texi
26
doc/wks.texi
@ -181,6 +181,7 @@ Display a brief help page and exit.
|
|||||||
.RI [ options ]
|
.RI [ options ]
|
||||||
.B \-\-install-key
|
.B \-\-install-key
|
||||||
.I file
|
.I file
|
||||||
|
.I user-id
|
||||||
.br
|
.br
|
||||||
.B gpg-wks-server
|
.B gpg-wks-server
|
||||||
.RI [ options ]
|
.RI [ options ]
|
||||||
@ -221,14 +222,19 @@ the process returns failure; to suppress the diagnostic, use option
|
|||||||
@option{-q}. More than one user-id can be given; see also option
|
@option{-q}. More than one user-id can be given; see also option
|
||||||
@option{with-file}.
|
@option{with-file}.
|
||||||
|
|
||||||
|
The command @option{--install-key} manually installs a key into the
|
||||||
|
WKD. The arguments are a file with the keyblock and the user-id to
|
||||||
|
install. If the first argument resembles a fingerprint the key is
|
||||||
|
taken from the current keyring; to force the use of a file, prefix the
|
||||||
|
first argument with "./".
|
||||||
|
|
||||||
The command @option{--remove-key} uninstalls a key from the WKD. The
|
The command @option{--remove-key} uninstalls a key from the WKD. The
|
||||||
process return success in this case; to also print a diagnostic, use
|
process returns success in this case; to also print a diagnostic, use
|
||||||
option @option{-v}. If the key is not installed a diagnostics is
|
option @option{-v}. If the key is not installed a diagnostic is
|
||||||
printed and the process returns failure; to suppress the diagnostic,
|
printed and the process returns failure; to suppress the diagnostic,
|
||||||
use option @option{-q}.
|
use option @option{-q}.
|
||||||
|
|
||||||
The commands @option{--install-key} and @option{--revoke-key} are not
|
The command @option{--revoke-key} is not yet functional.
|
||||||
yet functional.
|
|
||||||
|
|
||||||
|
|
||||||
@mansect options
|
@mansect options
|
||||||
@ -326,7 +332,7 @@ the submission address:
|
|||||||
|
|
||||||
@example
|
@example
|
||||||
$ gpg --batch --passphrase '' --quick-gen-key key-submission@@example.net
|
$ gpg --batch --passphrase '' --quick-gen-key key-submission@@example.net
|
||||||
$ gpg --with-wkd-hash -K key-submission@@example.net
|
$ gpg -K key-submission@@example.net
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
The output of the last command looks similar to this:
|
The output of the last command looks similar to this:
|
||||||
@ -339,17 +345,13 @@ The output of the last command looks similar to this:
|
|||||||
ssb rsa3072 2016-08-30 [E]
|
ssb rsa3072 2016-08-30 [E]
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Take the hash of the string "key-submission", which is
|
Take the fingerprint from that output and manually publish the key:
|
||||||
"bxzcxpxk8h87z1k7bzk86xn5aj47intu" and manually publish that key:
|
|
||||||
|
|
||||||
@example
|
@example
|
||||||
$ gpg --export-options export-minimal --export \
|
$ gpg-wks-server --install-key C0FCF8642D830C53246211400346653590B3795B \
|
||||||
> -o /var/lib/gnupg/wks/example.net/hu/bxzcxpxk8h87z1k7bzk86xn5aj47intu \
|
> key-submission@@example.net
|
||||||
> key-submission@@example.new
|
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Make sure that the created file is world readable.
|
|
||||||
|
|
||||||
Finally that submission address needs to be redirected to a script
|
Finally that submission address needs to be redirected to a script
|
||||||
running @command{gpg-wks-server}. The @command{procmail} command can
|
running @command{gpg-wks-server}. The @command{procmail} command can
|
||||||
be used for this: Redirect the submission address to the user "webkey"
|
be used for this: Redirect the submission address to the user "webkey"
|
||||||
|
@ -1269,10 +1269,7 @@ parse_keyblock_image (iobuf_t iobuf, int pk_no, int uid_no,
|
|||||||
break; /* Allowed per RFC. */
|
break; /* Allowed per RFC. */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Note that can't allow ring trust packets here and some of
|
log_info ("skipped packet of type %d in keybox\n", (int)pkt->pkttype);
|
||||||
the other GPG specific packets don't make sense either. */
|
|
||||||
log_error ("skipped packet of type %d in keybox\n",
|
|
||||||
(int)pkt->pkttype);
|
|
||||||
free_packet(pkt, &parsectx);
|
free_packet(pkt, &parsectx);
|
||||||
init_packet(pkt);
|
init_packet(pkt);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1664,11 +1664,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
|
|||||||
if (opt.only_sign_text_ids)
|
if (opt.only_sign_text_ids)
|
||||||
result = cpr_get_answer_is_yes
|
result = cpr_get_answer_is_yes
|
||||||
("keyedit.sign_all.okay",
|
("keyedit.sign_all.okay",
|
||||||
_("Really sign all user IDs? (y/N) "));
|
_("Really sign all text user IDs? (y/N) "));
|
||||||
else
|
else
|
||||||
result = cpr_get_answer_is_yes
|
result = cpr_get_answer_is_yes
|
||||||
("keyedit.sign_all.okay",
|
("keyedit.sign_all.okay",
|
||||||
_("Really sign all text user IDs? (y/N) "));
|
_("Really sign all user IDs? (y/N) "));
|
||||||
|
|
||||||
if (! result)
|
if (! result)
|
||||||
{
|
{
|
||||||
|
@ -459,7 +459,7 @@ keyring_get_keyblock (KEYRING_HANDLE hd, KBNODE *ret_kb)
|
|||||||
break; /* Allowed by us. */
|
break; /* Allowed by us. */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_error ("skipped packet of type %d in keyring\n",
|
log_info ("skipped packet of type %d in keyring\n",
|
||||||
(int)pkt->pkttype);
|
(int)pkt->pkttype);
|
||||||
free_packet(pkt, &parsectx);
|
free_packet(pkt, &parsectx);
|
||||||
init_packet(pkt);
|
init_packet(pkt);
|
||||||
|
21
g13/server.c
21
g13/server.c
@ -34,6 +34,7 @@
|
|||||||
#include "mount.h"
|
#include "mount.h"
|
||||||
#include "suspend.h"
|
#include "suspend.h"
|
||||||
#include "../common/server-help.h"
|
#include "../common/server-help.h"
|
||||||
|
#include "../common/asshelp.h"
|
||||||
#include "../common/call-gpg.h"
|
#include "../common/call-gpg.h"
|
||||||
|
|
||||||
|
|
||||||
@ -737,24 +738,8 @@ g13_status (ctrl_t ctrl, int no, ...)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assuan_context_t ctx = ctrl->server_local->assuan_ctx;
|
err = vprint_assuan_status_strings (ctrl->server_local->assuan_ctx,
|
||||||
char buf[950], *p;
|
get_status_string (no), arg_ptr);
|
||||||
size_t n;
|
|
||||||
|
|
||||||
p = buf;
|
|
||||||
n = 0;
|
|
||||||
while ( (text = va_arg (arg_ptr, const char *)) )
|
|
||||||
{
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
*p++ = ' ';
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
for ( ; *text && n < DIM (buf)-2; n++)
|
|
||||||
*p++ = *text++;
|
|
||||||
}
|
|
||||||
*p = 0;
|
|
||||||
err = assuan_write_status (ctx, get_status_string (no), buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end (arg_ptr);
|
va_end (arg_ptr);
|
||||||
|
28
g13/sh-cmd.c
28
g13/sh-cmd.c
@ -28,6 +28,7 @@
|
|||||||
#include "g13-syshelp.h"
|
#include "g13-syshelp.h"
|
||||||
#include <assuan.h>
|
#include <assuan.h>
|
||||||
#include "../common/i18n.h"
|
#include "../common/i18n.h"
|
||||||
|
#include "../common/asshelp.h"
|
||||||
#include "keyblob.h"
|
#include "keyblob.h"
|
||||||
|
|
||||||
|
|
||||||
@ -904,34 +905,13 @@ sh_encrypt_keyblob (ctrl_t ctrl, const void *keyblob, size_t keybloblen,
|
|||||||
gpg_error_t
|
gpg_error_t
|
||||||
g13_status (ctrl_t ctrl, int no, ...)
|
g13_status (ctrl_t ctrl, int no, ...)
|
||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err;
|
||||||
va_list arg_ptr;
|
va_list arg_ptr;
|
||||||
const char *text;
|
|
||||||
|
|
||||||
va_start (arg_ptr, no);
|
va_start (arg_ptr, no);
|
||||||
|
|
||||||
if (1)
|
err = vprint_assuan_status_strings (ctrl->server_local->assuan_ctx,
|
||||||
{
|
get_status_string (no), arg_ptr);
|
||||||
assuan_context_t ctx = ctrl->server_local->assuan_ctx;
|
|
||||||
char buf[950], *p;
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
p = buf;
|
|
||||||
n = 0;
|
|
||||||
while ( (text = va_arg (arg_ptr, const char *)) )
|
|
||||||
{
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
*p++ = ' ';
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
for ( ; *text && n < DIM (buf)-2; n++)
|
|
||||||
*p++ = *text++;
|
|
||||||
}
|
|
||||||
*p = 0;
|
|
||||||
err = assuan_write_status (ctx, get_status_string (no), buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end (arg_ptr);
|
va_end (arg_ptr);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ blob_cmp_fpr (KEYBOXBLOB blob, const unsigned char *fpr)
|
|||||||
if (keyinfolen < 28)
|
if (keyinfolen < 28)
|
||||||
return 0; /* invalid blob */
|
return 0; /* invalid blob */
|
||||||
pos = 20;
|
pos = 20;
|
||||||
if (pos + keyinfolen*nkeys > length)
|
if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
|
||||||
return 0; /* out of bounds */
|
return 0; /* out of bounds */
|
||||||
|
|
||||||
for (idx=0; idx < nkeys; idx++)
|
for (idx=0; idx < nkeys; idx++)
|
||||||
@ -279,7 +279,7 @@ blob_cmp_fpr_part (KEYBOXBLOB blob, const unsigned char *fpr,
|
|||||||
if (keyinfolen < 28)
|
if (keyinfolen < 28)
|
||||||
return 0; /* invalid blob */
|
return 0; /* invalid blob */
|
||||||
pos = 20;
|
pos = 20;
|
||||||
if (pos + keyinfolen*nkeys > length)
|
if (pos + (uint64_t)keyinfolen*nkeys > (uint64_t)length)
|
||||||
return 0; /* out of bounds */
|
return 0; /* out of bounds */
|
||||||
|
|
||||||
for (idx=0; idx < nkeys; idx++)
|
for (idx=0; idx < nkeys; idx++)
|
||||||
@ -313,7 +313,7 @@ blob_cmp_name (KEYBOXBLOB blob, int idx,
|
|||||||
if (keyinfolen < 28)
|
if (keyinfolen < 28)
|
||||||
return 0; /* invalid blob */
|
return 0; /* invalid blob */
|
||||||
pos = 20 + keyinfolen*nkeys;
|
pos = 20 + keyinfolen*nkeys;
|
||||||
if (pos+2 > length)
|
if ((uint64_t)pos+2 > (uint64_t)length)
|
||||||
return 0; /* out of bounds */
|
return 0; /* out of bounds */
|
||||||
|
|
||||||
/*serial*/
|
/*serial*/
|
||||||
@ -340,7 +340,7 @@ blob_cmp_name (KEYBOXBLOB blob, int idx,
|
|||||||
mypos += idx*uidinfolen;
|
mypos += idx*uidinfolen;
|
||||||
off = get32 (buffer+mypos);
|
off = get32 (buffer+mypos);
|
||||||
len = get32 (buffer+mypos+4);
|
len = get32 (buffer+mypos+4);
|
||||||
if (off+len > length)
|
if ((uint64_t)off+(uint64_t)len > (uint64_t)length)
|
||||||
return 0; /* error: better stop here out of bounds */
|
return 0; /* error: better stop here out of bounds */
|
||||||
if (len < 1)
|
if (len < 1)
|
||||||
continue; /* empty name */
|
continue; /* empty name */
|
||||||
@ -439,7 +439,7 @@ blob_cmp_mail (KEYBOXBLOB blob, const char *name, size_t namelen, int substr,
|
|||||||
mypos += idx*uidinfolen;
|
mypos += idx*uidinfolen;
|
||||||
off = get32 (buffer+mypos);
|
off = get32 (buffer+mypos);
|
||||||
len = get32 (buffer+mypos+4);
|
len = get32 (buffer+mypos+4);
|
||||||
if (off+len > length)
|
if ((uint64_t)off+(uint64_t)len > (uint64_t)length)
|
||||||
return 0; /* error: better stop here - out of bounds */
|
return 0; /* error: better stop here - out of bounds */
|
||||||
if (x509)
|
if (x509)
|
||||||
{
|
{
|
||||||
@ -522,7 +522,7 @@ blob_x509_has_grip (KEYBOXBLOB blob, const unsigned char *grip)
|
|||||||
return 0; /* Too short. */
|
return 0; /* Too short. */
|
||||||
cert_off = get32 (buffer+8);
|
cert_off = get32 (buffer+8);
|
||||||
cert_len = get32 (buffer+12);
|
cert_len = get32 (buffer+12);
|
||||||
if (cert_off+cert_len > length)
|
if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
|
||||||
return 0; /* Too short. */
|
return 0; /* Too short. */
|
||||||
|
|
||||||
rc = ksba_reader_new (&reader);
|
rc = ksba_reader_new (&reader);
|
||||||
@ -1097,7 +1097,7 @@ keybox_get_keyblock (KEYBOX_HANDLE hd, iobuf_t *r_iobuf,
|
|||||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
return gpg_error (GPG_ERR_TOO_SHORT);
|
||||||
image_off = get32 (buffer+8);
|
image_off = get32 (buffer+8);
|
||||||
image_len = get32 (buffer+12);
|
image_len = get32 (buffer+12);
|
||||||
if (image_off+image_len > length)
|
if ((uint64_t)image_off+(uint64_t)image_len > (uint64_t)length)
|
||||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
return gpg_error (GPG_ERR_TOO_SHORT);
|
||||||
|
|
||||||
err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
|
err = _keybox_get_flag_location (buffer, length, KEYBOX_FLAG_SIG_INFO,
|
||||||
@ -1139,7 +1139,7 @@ keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *r_cert)
|
|||||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
return gpg_error (GPG_ERR_TOO_SHORT);
|
||||||
cert_off = get32 (buffer+8);
|
cert_off = get32 (buffer+8);
|
||||||
cert_len = get32 (buffer+12);
|
cert_len = get32 (buffer+12);
|
||||||
if (cert_off+cert_len > length)
|
if ((uint64_t)cert_off+(uint64_t)cert_len > (uint64_t)length)
|
||||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
return gpg_error (GPG_ERR_TOO_SHORT);
|
||||||
|
|
||||||
rc = ksba_reader_new (&reader);
|
rc = ksba_reader_new (&reader);
|
||||||
|
@ -348,6 +348,7 @@ get_cached_data (app_t app, int tag,
|
|||||||
err = iso7816_get_data (app->slot, exmode, tag, &p, &len);
|
err = iso7816_get_data (app->slot, exmode, tag, &p, &len);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
if (len)
|
||||||
*result = p;
|
*result = p;
|
||||||
*resultlen = len;
|
*resultlen = len;
|
||||||
|
|
||||||
@ -370,7 +371,10 @@ get_cached_data (app_t app, int tag,
|
|||||||
c = xtrymalloc (sizeof *c + len);
|
c = xtrymalloc (sizeof *c + len);
|
||||||
if (c)
|
if (c)
|
||||||
{
|
{
|
||||||
|
if (len)
|
||||||
memcpy (c->data, p, len);
|
memcpy (c->data, p, len);
|
||||||
|
else
|
||||||
|
xfree (p);
|
||||||
c->length = len;
|
c->length = len;
|
||||||
c->tag = tag;
|
c->tag = tag;
|
||||||
c->next = app->app_local->cache;
|
c->next = app->app_local->cache;
|
||||||
@ -2068,7 +2072,8 @@ pin2hash_if_kdf (app_t app, int chvno, char *pinvalue, int *r_pinlen)
|
|||||||
size_t buflen;
|
size_t buflen;
|
||||||
|
|
||||||
if (app->app_local->extcap.kdf_do
|
if (app->app_local->extcap.kdf_do
|
||||||
&& (relptr = get_one_do (app, 0x00F9, &buffer, &buflen, NULL)))
|
&& (relptr = get_one_do (app, 0x00F9, &buffer, &buflen, NULL))
|
||||||
|
&& buflen == 110 && (buffer[2] == 0x03))
|
||||||
{
|
{
|
||||||
char *salt;
|
char *salt;
|
||||||
unsigned long s2k_count;
|
unsigned long s2k_count;
|
||||||
|
@ -1848,7 +1848,8 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...)
|
|||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
n = 0;
|
n = 0;
|
||||||
while ( (value = va_arg (arg_ptr, const unsigned char *)) )
|
while ( (value = va_arg (arg_ptr, const unsigned char *))
|
||||||
|
&& n < DIM (buf)-2 )
|
||||||
{
|
{
|
||||||
valuelen = va_arg (arg_ptr, size_t);
|
valuelen = va_arg (arg_ptr, size_t);
|
||||||
if (!valuelen)
|
if (!valuelen)
|
||||||
@ -1865,6 +1866,7 @@ send_status_info (ctrl_t ctrl, const char *keyword, ...)
|
|||||||
{
|
{
|
||||||
sprintf (p, "%%%02X", *value);
|
sprintf (p, "%%%02X", *value);
|
||||||
p += 3;
|
p += 3;
|
||||||
|
n += 2;
|
||||||
}
|
}
|
||||||
else if (*value == ' ')
|
else if (*value == ' ')
|
||||||
*p++ = '+';
|
*p++ = '+';
|
||||||
|
@ -236,6 +236,10 @@ static HANDLE the_event;
|
|||||||
/* PID to notify update of usb devices. */
|
/* PID to notify update of usb devices. */
|
||||||
static pid_t main_thread_pid;
|
static pid_t main_thread_pid;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
/* FD to notify changes. */
|
||||||
|
static int notify_fd;
|
||||||
|
#endif
|
||||||
|
|
||||||
static char *create_socket_name (char *standard_name);
|
static char *create_socket_name (char *standard_name);
|
||||||
static gnupg_fd_t create_server_socket (const char *name,
|
static gnupg_fd_t create_server_socket (const char *name,
|
||||||
@ -1210,6 +1214,8 @@ scd_kick_the_loop (void)
|
|||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
log_error ("SetEvent for scd_kick_the_loop failed: %s\n",
|
log_error ("SetEvent for scd_kick_the_loop failed: %s\n",
|
||||||
w32_strerror (-1));
|
w32_strerror (-1));
|
||||||
|
#elif defined(HAVE_PSELECT_NO_EINTR)
|
||||||
|
write (notify_fd, "", 1);
|
||||||
#else
|
#else
|
||||||
ret = kill (main_thread_pid, SIGCONT);
|
ret = kill (main_thread_pid, SIGCONT);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -1241,6 +1247,17 @@ handle_connections (int listen_fd)
|
|||||||
#else
|
#else
|
||||||
int signo;
|
int signo;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
int pipe_fd[2];
|
||||||
|
|
||||||
|
ret = gnupg_create_pipe (pipe_fd);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
log_error ("pipe creation failed: %s\n", gpg_strerror (ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
notify_fd = pipe_fd[1];
|
||||||
|
#endif
|
||||||
|
|
||||||
ret = npth_attr_init(&tattr);
|
ret = npth_attr_init(&tattr);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -1298,6 +1315,7 @@ handle_connections (int listen_fd)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int periodical_check;
|
int periodical_check;
|
||||||
|
int max_fd = nfd;
|
||||||
|
|
||||||
if (shutdown_pending)
|
if (shutdown_pending)
|
||||||
{
|
{
|
||||||
@ -1326,8 +1344,14 @@ handle_connections (int listen_fd)
|
|||||||
thus a simple assignment is fine to copy the entire set. */
|
thus a simple assignment is fine to copy the entire set. */
|
||||||
read_fdset = fdset;
|
read_fdset = fdset;
|
||||||
|
|
||||||
|
#ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
FD_SET (pipe_fd[0], &read_fdset);
|
||||||
|
if (max_fd < pipe_fd[0])
|
||||||
|
max_fd = pipe_fd[0];
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_W32_SYSTEM
|
#ifndef HAVE_W32_SYSTEM
|
||||||
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, t,
|
ret = npth_pselect (max_fd+1, &read_fdset, NULL, NULL, t,
|
||||||
npth_sigev_sigmask ());
|
npth_sigev_sigmask ());
|
||||||
saved_errno = errno;
|
saved_errno = errno;
|
||||||
|
|
||||||
@ -1353,6 +1377,15 @@ handle_connections (int listen_fd)
|
|||||||
/* Timeout. Will be handled when calculating the next timeout. */
|
/* Timeout. Will be handled when calculating the next timeout. */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
if (FD_ISSET (pipe_fd[0], &read_fdset))
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
read (pipe_fd[0], buf, sizeof buf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset))
|
if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset))
|
||||||
{
|
{
|
||||||
ctrl_t ctrl;
|
ctrl_t ctrl;
|
||||||
@ -1393,6 +1426,10 @@ handle_connections (int listen_fd)
|
|||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
if (the_event != INVALID_HANDLE_VALUE)
|
if (the_event != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle (the_event);
|
CloseHandle (the_event);
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_PSELECT_NO_EINTR
|
||||||
|
close (pipe_fd[0]);
|
||||||
|
close (pipe_fd[1]);
|
||||||
#endif
|
#endif
|
||||||
cleanup ();
|
cleanup ();
|
||||||
log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
|
log_info (_("%s %s stopped\n"), strusage(11), strusage(13));
|
||||||
|
@ -479,6 +479,7 @@ gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream, int rawmode)
|
|||||||
leave:
|
leave:
|
||||||
gnupg_ksba_destroy_writer (b64writer);
|
gnupg_ksba_destroy_writer (b64writer);
|
||||||
ksba_cert_release (cert);
|
ksba_cert_release (cert);
|
||||||
|
xfree (keygrip);
|
||||||
xfree (desc);
|
xfree (desc);
|
||||||
keydb_release (hd);
|
keydb_release (hd);
|
||||||
}
|
}
|
||||||
@ -603,7 +604,7 @@ sexp_to_kparms (gcry_sexp_t sexp)
|
|||||||
|
|
||||||
array[6] = gcry_mpi_snew (0); /* compute d mod (p-1) */
|
array[6] = gcry_mpi_snew (0); /* compute d mod (p-1) */
|
||||||
gcry_mpi_sub_ui (array[6], array[4], 1);
|
gcry_mpi_sub_ui (array[6], array[4], 1);
|
||||||
gcry_mpi_mod (array[6], array[3], array[6]);
|
gcry_mpi_mod (array[6], array[2], array[6]);
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
21
sm/server.c
21
sm/server.c
@ -31,6 +31,7 @@
|
|||||||
#include <assuan.h>
|
#include <assuan.h>
|
||||||
#include "../common/sysutils.h"
|
#include "../common/sysutils.h"
|
||||||
#include "../common/server-help.h"
|
#include "../common/server-help.h"
|
||||||
|
#include "../common/asshelp.h"
|
||||||
|
|
||||||
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
|
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
|
||||||
|
|
||||||
@ -1426,24 +1427,8 @@ gpgsm_status2 (ctrl_t ctrl, int no, ...)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assuan_context_t ctx = ctrl->server_local->assuan_ctx;
|
err = vprint_assuan_status_strings (ctrl->server_local->assuan_ctx,
|
||||||
char buf[950], *p;
|
get_status_string (no), arg_ptr);
|
||||||
size_t n;
|
|
||||||
|
|
||||||
p = buf;
|
|
||||||
n = 0;
|
|
||||||
while ( (text = va_arg (arg_ptr, const char *)) )
|
|
||||||
{
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
*p++ = ' ';
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
for ( ; *text && n < DIM (buf)-2; n++)
|
|
||||||
*p++ = *text++;
|
|
||||||
}
|
|
||||||
*p = 0;
|
|
||||||
err = assuan_write_status (ctx, get_status_string (no), buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end (arg_ptr);
|
va_end (arg_ptr);
|
||||||
|
@ -116,7 +116,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __STDC_VERSION__ < 199901L
|
#if __STDC_VERSION__ < 199901L
|
||||||
# if __GNUC__ >= 2
|
# if __GNUC__ >= 2 && !defined (__func__)
|
||||||
# define __func__ __FUNCTION__
|
# define __func__ __FUNCTION__
|
||||||
# else
|
# else
|
||||||
/* Let's try our luck here. Some systems may provide __func__ without
|
/* Let's try our luck here. Some systems may provide __func__ without
|
||||||
|
@ -325,119 +325,6 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct get_key_status_parm_s
|
|
||||||
{
|
|
||||||
const char *fpr;
|
|
||||||
int found;
|
|
||||||
int count;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
get_key_status_cb (void *opaque, const char *keyword, char *args)
|
|
||||||
{
|
|
||||||
struct get_key_status_parm_s *parm = opaque;
|
|
||||||
|
|
||||||
/*log_debug ("%s: %s\n", keyword, args);*/
|
|
||||||
if (!strcmp (keyword, "EXPORTED"))
|
|
||||||
{
|
|
||||||
parm->count++;
|
|
||||||
if (!ascii_strcasecmp (args, parm->fpr))
|
|
||||||
parm->found = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Get a key by fingerprint from gpg's keyring and make sure that the
|
|
||||||
* mail address ADDRSPEC is included in the key. If EXACT is set the
|
|
||||||
* returned user id must match Addrspec exactly and not just in the
|
|
||||||
* addr-spec (mailbox) part. The key is returned as a new memory
|
|
||||||
* stream at R_KEY. */
|
|
||||||
static gpg_error_t
|
|
||||||
get_key (estream_t *r_key, const char *fingerprint, const char *addrspec,
|
|
||||||
int exact)
|
|
||||||
{
|
|
||||||
gpg_error_t err;
|
|
||||||
ccparray_t ccp;
|
|
||||||
const char **argv = NULL;
|
|
||||||
estream_t key = NULL;
|
|
||||||
struct get_key_status_parm_s parm;
|
|
||||||
char *filterexp = NULL;
|
|
||||||
|
|
||||||
memset (&parm, 0, sizeof parm);
|
|
||||||
|
|
||||||
*r_key = NULL;
|
|
||||||
|
|
||||||
key = es_fopenmem (0, "w+b");
|
|
||||||
if (!key)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prefix the key with the MIME content type. */
|
|
||||||
es_fputs ("Content-Type: application/pgp-keys\n"
|
|
||||||
"\n", key);
|
|
||||||
|
|
||||||
filterexp = es_bsprintf ("keep-uid=%s=%s", exact? "uid":"mbox", addrspec);
|
|
||||||
if (!filterexp)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
ccparray_init (&ccp, 0);
|
|
||||||
|
|
||||||
ccparray_put (&ccp, "--no-options");
|
|
||||||
if (!opt.verbose)
|
|
||||||
ccparray_put (&ccp, "--quiet");
|
|
||||||
else if (opt.verbose > 1)
|
|
||||||
ccparray_put (&ccp, "--verbose");
|
|
||||||
ccparray_put (&ccp, "--batch");
|
|
||||||
ccparray_put (&ccp, "--status-fd=2");
|
|
||||||
ccparray_put (&ccp, "--always-trust");
|
|
||||||
ccparray_put (&ccp, "--armor");
|
|
||||||
ccparray_put (&ccp, "--export-options=export-minimal");
|
|
||||||
ccparray_put (&ccp, "--export-filter");
|
|
||||||
ccparray_put (&ccp, filterexp);
|
|
||||||
ccparray_put (&ccp, "--export");
|
|
||||||
ccparray_put (&ccp, "--");
|
|
||||||
ccparray_put (&ccp, fingerprint);
|
|
||||||
|
|
||||||
ccparray_put (&ccp, NULL);
|
|
||||||
argv = ccparray_get (&ccp, NULL);
|
|
||||||
if (!argv)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
parm.fpr = fingerprint;
|
|
||||||
err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
|
|
||||||
NULL, key,
|
|
||||||
get_key_status_cb, &parm);
|
|
||||||
if (!err && parm.count > 1)
|
|
||||||
err = gpg_error (GPG_ERR_TOO_MANY);
|
|
||||||
else if (!err && !parm.found)
|
|
||||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
log_error ("export failed: %s\n", gpg_strerror (err));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
es_rewind (key);
|
|
||||||
*r_key = key;
|
|
||||||
key = NULL;
|
|
||||||
|
|
||||||
leave:
|
|
||||||
es_fclose (key);
|
|
||||||
xfree (argv);
|
|
||||||
xfree (filterexp);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Add the user id UID to the key identified by FINGERPRINT. */
|
/* Add the user id UID to the key identified by FINGERPRINT. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
add_user_id (const char *fingerprint, const char *uid)
|
add_user_id (const char *fingerprint, const char *uid)
|
||||||
@ -767,7 +654,7 @@ command_send (const char *fingerprint, const char *userid)
|
|||||||
err = gpg_error (GPG_ERR_INV_USER_ID);
|
err = gpg_error (GPG_ERR_INV_USER_ID);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
err = get_key (&key, fingerprint, addrspec, 0);
|
err = wks_get_key (&key, fingerprint, addrspec, 0);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
@ -782,27 +669,19 @@ command_send (const char *fingerprint, const char *userid)
|
|||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
err = wkd_get_submission_address (addrspec, &submission_to);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
log_error (_("error looking up submission address for domain '%s': %s\n"),
|
|
||||||
domain, gpg_strerror (err));
|
|
||||||
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
|
||||||
log_error (_("this domain probably doesn't support WKS.\n"));
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
log_info ("submitting request to '%s'\n", submission_to);
|
|
||||||
|
|
||||||
/* Get the policy flags. */
|
|
||||||
if (!fake_submission_addr)
|
|
||||||
{
|
{
|
||||||
|
/* We first try to get the submission address from the policy
|
||||||
|
* file (this is the new method). If both are available we
|
||||||
|
* check that they match and print a warning if not. In the
|
||||||
|
* latter case we keep on using the one from the
|
||||||
|
* submission-address file. */
|
||||||
estream_t mbuf;
|
estream_t mbuf;
|
||||||
|
|
||||||
err = wkd_get_policy_flags (addrspec, &mbuf);
|
err = wkd_get_policy_flags (addrspec, &mbuf);
|
||||||
if (err && gpg_err_code (err) != GPG_ERR_NO_DATA)
|
if (err && gpg_err_code (err) != GPG_ERR_NO_DATA)
|
||||||
{
|
{
|
||||||
log_error ("error reading policy flags for '%s': %s\n",
|
log_error ("error reading policy flags for '%s': %s\n",
|
||||||
submission_to, gpg_strerror (err));
|
domain, gpg_strerror (err));
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
if (mbuf)
|
if (mbuf)
|
||||||
@ -812,8 +691,35 @@ command_send (const char *fingerprint, const char *userid)
|
|||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = wkd_get_submission_address (addrspec, &submission_to);
|
||||||
|
if (err && !policy.submission_address)
|
||||||
|
{
|
||||||
|
log_error (_("error looking up submission address for domain '%s'"
|
||||||
|
": %s\n"), domain, gpg_strerror (err));
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
||||||
|
log_error (_("this domain probably doesn't support WKS.\n"));
|
||||||
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (submission_to && policy.submission_address
|
||||||
|
&& ascii_strcasecmp (submission_to, policy.submission_address))
|
||||||
|
log_info ("Warning: different submission addresses (sa=%s, po=%s)\n",
|
||||||
|
submission_to, policy.submission_address);
|
||||||
|
|
||||||
|
if (!submission_to)
|
||||||
|
{
|
||||||
|
submission_to = xtrystrdup (policy.submission_address);
|
||||||
|
if (!submission_to)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info ("submitting request to '%s'\n", submission_to);
|
||||||
|
|
||||||
if (policy.auth_submit)
|
if (policy.auth_submit)
|
||||||
log_info ("no confirmation required for '%s'\n", addrspec);
|
log_info ("no confirmation required for '%s'\n", addrspec);
|
||||||
|
|
||||||
@ -853,7 +759,7 @@ command_send (const char *fingerprint, const char *userid)
|
|||||||
estream_t newkey;
|
estream_t newkey;
|
||||||
|
|
||||||
es_rewind (key);
|
es_rewind (key);
|
||||||
err = wks_filter_uid (&newkey, key, thisuid->uid);
|
err = wks_filter_uid (&newkey, key, thisuid->uid, 0);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error ("error filtering key: %s\n", gpg_strerror (err));
|
log_error ("error filtering key: %s\n", gpg_strerror (err));
|
||||||
@ -878,7 +784,7 @@ command_send (const char *fingerprint, const char *userid)
|
|||||||
* the key again. */
|
* the key again. */
|
||||||
es_fclose (key);
|
es_fclose (key);
|
||||||
key = NULL;
|
key = NULL;
|
||||||
err = get_key (&key, fingerprint, addrspec, 1);
|
err = wks_get_key (&key, fingerprint, addrspec, 1);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -1002,6 +908,7 @@ command_send (const char *fingerprint, const char *userid)
|
|||||||
free_uidinfo_list (uidlist);
|
free_uidinfo_list (uidlist);
|
||||||
es_fclose (keyenc);
|
es_fclose (keyenc);
|
||||||
es_fclose (key);
|
es_fclose (key);
|
||||||
|
wks_free_policy (&policy);
|
||||||
xfree (addrspec);
|
xfree (addrspec);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* gpg-wks-server.c - A server for the Web Key Service protocols.
|
/* gpg-wks-server.c - A server for the Web Key Service protocols.
|
||||||
* Copyright (C) 2016 Werner Koch
|
* Copyright (C) 2016, 2018 Werner Koch
|
||||||
* Copyright (C) 2016 Bundesamt für Sicherheit in der Informationstechnik
|
* Copyright (C) 2016 Bundesamt für Sicherheit in der Informationstechnik
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
/* The Web Key Service I-D defines an update protocol to store a
|
/* The Web Key Service I-D defines an update protocol to store a
|
||||||
* public key in the Web Key Directory. The current specification is
|
* public key in the Web Key Directory. The current specification is
|
||||||
* draft-koch-openpgp-webkey-service-01.txt.
|
* draft-koch-openpgp-webkey-service-05.txt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -35,6 +35,7 @@
|
|||||||
#include "../common/util.h"
|
#include "../common/util.h"
|
||||||
#include "../common/init.h"
|
#include "../common/init.h"
|
||||||
#include "../common/sysutils.h"
|
#include "../common/sysutils.h"
|
||||||
|
#include "../common/userids.h"
|
||||||
#include "../common/ccparray.h"
|
#include "../common/ccparray.h"
|
||||||
#include "../common/exectool.h"
|
#include "../common/exectool.h"
|
||||||
#include "../common/zb32.h"
|
#include "../common/zb32.h"
|
||||||
@ -154,7 +155,7 @@ static gpg_error_t command_receive_cb (void *opaque,
|
|||||||
const char *mediatype, estream_t fp,
|
const char *mediatype, estream_t fp,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
static gpg_error_t command_list_domains (void);
|
static gpg_error_t command_list_domains (void);
|
||||||
static gpg_error_t command_install_key (const char *fname);
|
static gpg_error_t command_install_key (const char *fname, const char *userid);
|
||||||
static gpg_error_t command_remove_key (const char *mailaddr);
|
static gpg_error_t command_remove_key (const char *mailaddr);
|
||||||
static gpg_error_t command_revoke_key (const char *mailaddr);
|
static gpg_error_t command_revoke_key (const char *mailaddr);
|
||||||
static gpg_error_t command_check_key (const char *mailaddr);
|
static gpg_error_t command_check_key (const char *mailaddr);
|
||||||
@ -376,9 +377,9 @@ main (int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case aInstallKey:
|
case aInstallKey:
|
||||||
if (argc != 1)
|
if (argc != 2)
|
||||||
wrong_args ("--install-key FILE");
|
wrong_args ("--install-key FILE USER-ID");
|
||||||
err = command_install_key (*argv);
|
err = command_install_key (*argv, argv[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case aRemoveKey:
|
case aRemoveKey:
|
||||||
@ -1135,6 +1136,8 @@ process_new_key (server_ctx_t ctx, estream_t key)
|
|||||||
char *fname = NULL;
|
char *fname = NULL;
|
||||||
struct policy_flags_s policybuf;
|
struct policy_flags_s policybuf;
|
||||||
|
|
||||||
|
memset (&policybuf, 0, sizeof policybuf);
|
||||||
|
|
||||||
/* First figure out the user id from the key. */
|
/* First figure out the user id from the key. */
|
||||||
xfree (ctx->fpr);
|
xfree (ctx->fpr);
|
||||||
free_uidinfo_list (ctx->mboxes);
|
free_uidinfo_list (ctx->mboxes);
|
||||||
@ -1206,6 +1209,7 @@ process_new_key (server_ctx_t ctx, estream_t key)
|
|||||||
xfree (nonce);
|
xfree (nonce);
|
||||||
xfree (fname);
|
xfree (fname);
|
||||||
xfree (dname);
|
xfree (dname);
|
||||||
|
wks_free_policy (&policybuf);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1336,6 +1340,81 @@ send_congratulation_message (const char *mbox, const char *keyfile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Write the content of SRC to the new file FNAME. */
|
||||||
|
static gpg_error_t
|
||||||
|
write_to_file (estream_t src, const char *fname)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
estream_t dst;
|
||||||
|
char buffer[4096];
|
||||||
|
size_t nread, written;
|
||||||
|
|
||||||
|
dst = es_fopen (fname, "wb");
|
||||||
|
if (!dst)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
nread = es_fread (buffer, 1, sizeof buffer, src);
|
||||||
|
if (!nread)
|
||||||
|
break;
|
||||||
|
written = es_fwrite (buffer, 1, nread, dst);
|
||||||
|
if (written != nread)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (!es_feof (src) && !es_ferror (src) && !es_ferror (dst));
|
||||||
|
if (!es_feof (src) || es_ferror (src) || es_ferror (dst))
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
es_fclose (dst);
|
||||||
|
gnupg_remove (fname);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (es_fclose (dst))
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_error ("error closing '%s': %s\n", fname, gpg_strerror (err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Compute the the full file name for the key with ADDRSPEC and return
|
||||||
|
* it at R_FNAME. */
|
||||||
|
static gpg_error_t
|
||||||
|
compute_hu_fname (char **r_fname, const char *addrspec)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char *hash;
|
||||||
|
const char *domain;
|
||||||
|
char sha1buf[20];
|
||||||
|
|
||||||
|
*r_fname = NULL;
|
||||||
|
|
||||||
|
domain = strchr (addrspec, '@');
|
||||||
|
if (!domain || !domain[1] || domain == addrspec)
|
||||||
|
return gpg_error (GPG_ERR_INV_ARG);
|
||||||
|
domain++;
|
||||||
|
|
||||||
|
gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, addrspec, domain - addrspec - 1);
|
||||||
|
hash = zb32_encode (sha1buf, 8*20);
|
||||||
|
if (!hash)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
*r_fname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
|
||||||
|
if (!*r_fname)
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
xfree (hash);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check that we have send a request with NONCE and publish the key. */
|
/* Check that we have send a request with NONCE and publish the key. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
|
check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
|
||||||
@ -1409,24 +1488,10 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Hash user ID and create filename. */
|
/* Hash user ID and create filename. */
|
||||||
s = strchr (address, '@');
|
err = compute_hu_fname (&fnewname, address);
|
||||||
log_assert (s);
|
if (err)
|
||||||
gcry_md_hash_buffer (GCRY_MD_SHA1, shaxbuf, address, s - address);
|
|
||||||
hash = zb32_encode (shaxbuf, 8*20);
|
|
||||||
if (!hash)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
|
||||||
|
|
||||||
fnewname = make_filename_try (opt.directory, domain, "hu", hash, NULL);
|
|
||||||
if (!fnewname)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Publish. */
|
/* Publish. */
|
||||||
err = copy_key_as_binary (fname, fnewname, address);
|
err = copy_key_as_binary (fname, fnewname, address);
|
||||||
@ -1897,6 +1962,7 @@ command_list_domains (void)
|
|||||||
if (!memcmp (&empty_policy, &policy, sizeof policy))
|
if (!memcmp (&empty_policy, &policy, sizeof policy))
|
||||||
log_error ("domain %s: empty policy file\n", domain);
|
log_error ("domain %s: empty policy file\n", domain);
|
||||||
}
|
}
|
||||||
|
wks_free_policy (&policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1931,16 +1997,140 @@ command_cron (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Install a single key into the WKD by reading FNAME. */
|
/* Install a single key into the WKD by reading FNAME and extracting
|
||||||
|
* USERID. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
command_install_key (const char *fname)
|
command_install_key (const char *fname, const char *userid)
|
||||||
{
|
{
|
||||||
(void)fname;
|
gpg_error_t err;
|
||||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
KEYDB_SEARCH_DESC desc;
|
||||||
|
estream_t fp = NULL;
|
||||||
|
char *addrspec = NULL;
|
||||||
|
char *fpr = NULL;
|
||||||
|
uidinfo_list_t uidlist = NULL;
|
||||||
|
uidinfo_list_t uid, thisuid;
|
||||||
|
time_t thistime;
|
||||||
|
char *huname = NULL;
|
||||||
|
int any;
|
||||||
|
|
||||||
|
addrspec = mailbox_from_userid (userid);
|
||||||
|
if (!addrspec)
|
||||||
|
{
|
||||||
|
log_error ("\"%s\" is not a proper mail address\n", userid);
|
||||||
|
err = gpg_error (GPG_ERR_INV_USER_ID);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!classify_user_id (fname, &desc, 1)
|
||||||
|
&& (desc.mode == KEYDB_SEARCH_MODE_FPR
|
||||||
|
|| desc.mode == KEYDB_SEARCH_MODE_FPR20))
|
||||||
|
{
|
||||||
|
/* FNAME looks like a fingerprint. Get the key from the
|
||||||
|
* standard keyring. */
|
||||||
|
err = wks_get_key (&fp, fname, addrspec, 0);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("error getting key '%s' (uid='%s'): %s\n",
|
||||||
|
fname, addrspec, gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* Take it from the file */
|
||||||
|
{
|
||||||
|
fp = es_fopen (fname, "rb");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_error ("error reading '%s': %s\n", fname, gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List the key so that we can figure out the newest UID with the
|
||||||
|
* requested addrspec. */
|
||||||
|
err = wks_list_key (fp, &fpr, &uidlist);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("error parsing key: %s\n", gpg_strerror (err));
|
||||||
|
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
thistime = 0;
|
||||||
|
thisuid = NULL;
|
||||||
|
any = 0;
|
||||||
|
for (uid = uidlist; uid; uid = uid->next)
|
||||||
|
{
|
||||||
|
if (!uid->mbox)
|
||||||
|
continue; /* Should not happen anyway. */
|
||||||
|
if (ascii_strcasecmp (uid->mbox, addrspec))
|
||||||
|
continue; /* Not the requested addrspec. */
|
||||||
|
any = 1;
|
||||||
|
if (uid->created > thistime)
|
||||||
|
{
|
||||||
|
thistime = uid->created;
|
||||||
|
thisuid = uid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!thisuid)
|
||||||
|
thisuid = uidlist; /* This is the case for a missing timestamp. */
|
||||||
|
if (!any)
|
||||||
|
{
|
||||||
|
log_error ("public key in '%s' has no mail address '%s'\n",
|
||||||
|
fname, addrspec);
|
||||||
|
err = gpg_error (GPG_ERR_INV_USER_ID);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("using key with user id '%s'\n", thisuid->uid);
|
||||||
|
|
||||||
|
{
|
||||||
|
estream_t fp2;
|
||||||
|
|
||||||
|
es_rewind (fp);
|
||||||
|
err = wks_filter_uid (&fp2, fp, thisuid->uid, 1);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("error filtering key: %s\n", gpg_strerror (err));
|
||||||
|
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
es_fclose (fp);
|
||||||
|
fp = fp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hash user ID and create filename. */
|
||||||
|
err = compute_hu_fname (&huname, addrspec);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
/* Publish. */
|
||||||
|
err = write_to_file (fp, huname);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("copying key to '%s' failed: %s\n", huname,gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure it is world readable. */
|
||||||
|
if (gnupg_chmod (huname, "-rwxr--r--"))
|
||||||
|
log_error ("can't set permissions of '%s': %s\n",
|
||||||
|
huname, gpg_strerror (gpg_err_code_from_syserror()));
|
||||||
|
|
||||||
|
if (!opt.quiet)
|
||||||
|
log_info ("key %s published for '%s'\n", fpr, addrspec);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
xfree (huname);
|
||||||
|
free_uidinfo_list (uidlist);
|
||||||
|
xfree (fpr);
|
||||||
|
xfree (addrspec);
|
||||||
|
es_fclose (fp);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return the filename and optioanlly the addrspec for USERID at
|
/* Return the filename and optionally the addrspec for USERID at
|
||||||
* R_FNAME and R_ADDRSPEC. R_ADDRSPEC might also be set on error. */
|
* R_FNAME and R_ADDRSPEC. R_ADDRSPEC might also be set on error. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
|
fname_from_userid (const char *userid, char **r_fname, char **r_addrspec)
|
||||||
|
@ -60,6 +60,7 @@ struct
|
|||||||
/* The parsed policy flags. */
|
/* The parsed policy flags. */
|
||||||
struct policy_flags_s
|
struct policy_flags_s
|
||||||
{
|
{
|
||||||
|
char *submission_address;
|
||||||
unsigned int mailbox_only : 1;
|
unsigned int mailbox_only : 1;
|
||||||
unsigned int dane_only : 1;
|
unsigned int dane_only : 1;
|
||||||
unsigned int auth_submit : 1;
|
unsigned int auth_submit : 1;
|
||||||
@ -85,13 +86,16 @@ typedef struct uidinfo_list_s *uidinfo_list_t;
|
|||||||
void wks_set_status_fd (int fd);
|
void wks_set_status_fd (int fd);
|
||||||
void wks_write_status (int no, const char *format, ...) GPGRT_ATTR_PRINTF(2,3);
|
void wks_write_status (int no, const char *format, ...) GPGRT_ATTR_PRINTF(2,3);
|
||||||
void free_uidinfo_list (uidinfo_list_t list);
|
void free_uidinfo_list (uidinfo_list_t list);
|
||||||
|
gpg_error_t wks_get_key (estream_t *r_key, const char *fingerprint,
|
||||||
|
const char *addrspec, int exact);
|
||||||
gpg_error_t wks_list_key (estream_t key, char **r_fpr,
|
gpg_error_t wks_list_key (estream_t key, char **r_fpr,
|
||||||
uidinfo_list_t *r_mboxes);
|
uidinfo_list_t *r_mboxes);
|
||||||
gpg_error_t wks_filter_uid (estream_t *r_newkey, estream_t key,
|
gpg_error_t wks_filter_uid (estream_t *r_newkey, estream_t key,
|
||||||
const char *uid);
|
const char *uid, int binary);
|
||||||
gpg_error_t wks_send_mime (mime_maker_t mime);
|
gpg_error_t wks_send_mime (mime_maker_t mime);
|
||||||
gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream,
|
gpg_error_t wks_parse_policy (policy_flags_t flags, estream_t stream,
|
||||||
int ignore_unknown);
|
int ignore_unknown);
|
||||||
|
void wks_free_policy (policy_flags_t policy);
|
||||||
|
|
||||||
/*-- wks-receive.c --*/
|
/*-- wks-receive.c --*/
|
||||||
|
|
||||||
|
152
tools/wks-util.c
152
tools/wks-util.c
@ -132,6 +132,120 @@ free_uidinfo_list (uidinfo_list_t list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct get_key_status_parm_s
|
||||||
|
{
|
||||||
|
const char *fpr;
|
||||||
|
int found;
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_key_status_cb (void *opaque, const char *keyword, char *args)
|
||||||
|
{
|
||||||
|
struct get_key_status_parm_s *parm = opaque;
|
||||||
|
|
||||||
|
/*log_debug ("%s: %s\n", keyword, args);*/
|
||||||
|
if (!strcmp (keyword, "EXPORTED"))
|
||||||
|
{
|
||||||
|
parm->count++;
|
||||||
|
if (!ascii_strcasecmp (args, parm->fpr))
|
||||||
|
parm->found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a key by fingerprint from gpg's keyring and make sure that the
|
||||||
|
* mail address ADDRSPEC is included in the key. If EXACT is set the
|
||||||
|
* returned user id must match Addrspec exactly and not just in the
|
||||||
|
* addr-spec (mailbox) part. The key is returned as a new memory
|
||||||
|
* stream at R_KEY. */
|
||||||
|
gpg_error_t
|
||||||
|
wks_get_key (estream_t *r_key, const char *fingerprint, const char *addrspec,
|
||||||
|
int exact)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
ccparray_t ccp;
|
||||||
|
const char **argv = NULL;
|
||||||
|
estream_t key = NULL;
|
||||||
|
struct get_key_status_parm_s parm;
|
||||||
|
char *filterexp = NULL;
|
||||||
|
|
||||||
|
memset (&parm, 0, sizeof parm);
|
||||||
|
|
||||||
|
*r_key = NULL;
|
||||||
|
|
||||||
|
key = es_fopenmem (0, "w+b");
|
||||||
|
if (!key)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prefix the key with the MIME content type. */
|
||||||
|
es_fputs ("Content-Type: application/pgp-keys\n"
|
||||||
|
"\n", key);
|
||||||
|
|
||||||
|
filterexp = es_bsprintf ("keep-uid=%s=%s", exact? "uid":"mbox", addrspec);
|
||||||
|
if (!filterexp)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
ccparray_init (&ccp, 0);
|
||||||
|
|
||||||
|
ccparray_put (&ccp, "--no-options");
|
||||||
|
if (!opt.verbose)
|
||||||
|
ccparray_put (&ccp, "--quiet");
|
||||||
|
else if (opt.verbose > 1)
|
||||||
|
ccparray_put (&ccp, "--verbose");
|
||||||
|
ccparray_put (&ccp, "--batch");
|
||||||
|
ccparray_put (&ccp, "--status-fd=2");
|
||||||
|
ccparray_put (&ccp, "--always-trust");
|
||||||
|
ccparray_put (&ccp, "--armor");
|
||||||
|
ccparray_put (&ccp, "--export-options=export-minimal");
|
||||||
|
ccparray_put (&ccp, "--export-filter");
|
||||||
|
ccparray_put (&ccp, filterexp);
|
||||||
|
ccparray_put (&ccp, "--export");
|
||||||
|
ccparray_put (&ccp, "--");
|
||||||
|
ccparray_put (&ccp, fingerprint);
|
||||||
|
|
||||||
|
ccparray_put (&ccp, NULL);
|
||||||
|
argv = ccparray_get (&ccp, NULL);
|
||||||
|
if (!argv)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
parm.fpr = fingerprint;
|
||||||
|
err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
|
||||||
|
NULL, key,
|
||||||
|
get_key_status_cb, &parm);
|
||||||
|
if (!err && parm.count > 1)
|
||||||
|
err = gpg_error (GPG_ERR_TOO_MANY);
|
||||||
|
else if (!err && !parm.found)
|
||||||
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("export failed: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
es_rewind (key);
|
||||||
|
*r_key = key;
|
||||||
|
key = NULL;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
es_fclose (key);
|
||||||
|
xfree (argv);
|
||||||
|
xfree (filterexp);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper for wks_list_key and wks_filter_uid. */
|
/* Helper for wks_list_key and wks_filter_uid. */
|
||||||
static void
|
static void
|
||||||
@ -317,10 +431,13 @@ wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes)
|
|||||||
|
|
||||||
|
|
||||||
/* Run gpg as a filter on KEY and write the output to a new stream
|
/* Run gpg as a filter on KEY and write the output to a new stream
|
||||||
* stored at R_NEWKEY. The new key will containn only the user id
|
* stored at R_NEWKEY. The new key will contain only the user id UID.
|
||||||
* UID. Returns 0 on success. Only one key is expected in KEY. */
|
* Returns 0 on success. Only one key is expected in KEY. If BINARY
|
||||||
|
* is set the resulting key is returned as a binary (non-armored)
|
||||||
|
* keyblock. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid)
|
wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid,
|
||||||
|
int binary)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
ccparray_t ccp;
|
ccparray_t ccp;
|
||||||
@ -340,6 +457,7 @@ wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Prefix the key with the MIME content type. */
|
/* Prefix the key with the MIME content type. */
|
||||||
|
if (!binary)
|
||||||
es_fputs ("Content-Type: application/pgp-keys\n"
|
es_fputs ("Content-Type: application/pgp-keys\n"
|
||||||
"\n", newkey);
|
"\n", newkey);
|
||||||
|
|
||||||
@ -361,6 +479,7 @@ wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid)
|
|||||||
ccparray_put (&ccp, "--batch");
|
ccparray_put (&ccp, "--batch");
|
||||||
ccparray_put (&ccp, "--status-fd=2");
|
ccparray_put (&ccp, "--status-fd=2");
|
||||||
ccparray_put (&ccp, "--always-trust");
|
ccparray_put (&ccp, "--always-trust");
|
||||||
|
if (!binary)
|
||||||
ccparray_put (&ccp, "--armor");
|
ccparray_put (&ccp, "--armor");
|
||||||
ccparray_put (&ccp, "--import-options=import-export");
|
ccparray_put (&ccp, "--import-options=import-export");
|
||||||
ccparray_put (&ccp, "--import-filter");
|
ccparray_put (&ccp, "--import-filter");
|
||||||
@ -443,6 +562,7 @@ gpg_error_t
|
|||||||
wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
||||||
{
|
{
|
||||||
enum tokens {
|
enum tokens {
|
||||||
|
TOK_SUBMISSION_ADDRESS,
|
||||||
TOK_MAILBOX_ONLY,
|
TOK_MAILBOX_ONLY,
|
||||||
TOK_DANE_ONLY,
|
TOK_DANE_ONLY,
|
||||||
TOK_AUTH_SUBMIT,
|
TOK_AUTH_SUBMIT,
|
||||||
@ -453,6 +573,7 @@ wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
|||||||
const char *name;
|
const char *name;
|
||||||
enum tokens token;
|
enum tokens token;
|
||||||
} keywords[] = {
|
} keywords[] = {
|
||||||
|
{ "submission-address", TOK_SUBMISSION_ADDRESS },
|
||||||
{ "mailbox-only", TOK_MAILBOX_ONLY },
|
{ "mailbox-only", TOK_MAILBOX_ONLY },
|
||||||
{ "dane-only", TOK_DANE_ONLY },
|
{ "dane-only", TOK_DANE_ONLY },
|
||||||
{ "auth-submit", TOK_AUTH_SUBMIT },
|
{ "auth-submit", TOK_AUTH_SUBMIT },
|
||||||
@ -519,6 +640,20 @@ wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
|||||||
|
|
||||||
switch (keywords[i].token)
|
switch (keywords[i].token)
|
||||||
{
|
{
|
||||||
|
case TOK_SUBMISSION_ADDRESS:
|
||||||
|
if (!value || !*value)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_SYNTAX);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
xfree (flags->submission_address);
|
||||||
|
flags->submission_address = xtrystrdup (value);
|
||||||
|
if (!flags->submission_address)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case TOK_MAILBOX_ONLY: flags->mailbox_only = 1; break;
|
case TOK_MAILBOX_ONLY: flags->mailbox_only = 1; break;
|
||||||
case TOK_DANE_ONLY: flags->dane_only = 1; break;
|
case TOK_DANE_ONLY: flags->dane_only = 1; break;
|
||||||
case TOK_AUTH_SUBMIT: flags->auth_submit = 1; break;
|
case TOK_AUTH_SUBMIT: flags->auth_submit = 1; break;
|
||||||
@ -553,3 +688,14 @@ wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
|||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
wks_free_policy (policy_flags_t policy)
|
||||||
|
{
|
||||||
|
if (policy)
|
||||||
|
{
|
||||||
|
xfree (policy->submission_address);
|
||||||
|
memset (policy, 0, sizeof *policy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user