mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
Merge branch 'STABLE-BRANCH-2-2' into master
-- Signed-off-by: Werner Koch <wk@gnupg.org> Conflicts: NEWS - include release info from 2.2.1 configure.ac - keep master.
This commit is contained in:
commit
cd2d758f3f
27
NEWS
27
NEWS
@ -1,10 +1,29 @@
|
|||||||
Noteworthy changes in version 2.3.0 (unreleased)
|
Noteworthy changes in version 2.3.0 (unreleased)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
Changes also found in 2.2.1:
|
||||||
|
|
||||||
* Release dates of 2.2.x versions:
|
* gpg: Fix formatting of the user id in batch mode key generation
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
if only "name-email" is given.
|
||||||
Version 2.2.1 (unreleased)
|
|
||||||
|
* gpgv: Fix annoying "not suitable for" warnings.
|
||||||
|
|
||||||
|
* wks: Convey only the newest user id to the provider. This is the
|
||||||
|
case if different names are used with the same addr-spec.
|
||||||
|
|
||||||
|
* wks: Create a complying user id for provider policy mailbox-only.
|
||||||
|
|
||||||
|
* wks: Add workaround for posteo.de.
|
||||||
|
|
||||||
|
* scd: Fix the use of large ECC keys with an OpenPGP card.
|
||||||
|
|
||||||
|
* dirmngr: Use system provided root certificates if no specific HKP
|
||||||
|
certificates are configured. If build with GNUTLS, this was
|
||||||
|
already the case.
|
||||||
|
|
||||||
|
Release dates of 2.2.x versions:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Version 2.2.1 (2017-09-19)
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.2.0 (2017-08-28)
|
Noteworthy changes in version 2.2.0 (2017-08-28)
|
||||||
@ -18,6 +37,8 @@ Noteworthy changes in version 2.2.0 (2017-08-28)
|
|||||||
|
|
||||||
* Fixed a few minor bugs.
|
* Fixed a few minor bugs.
|
||||||
|
|
||||||
|
See-also: gnupg-announce/2017q3/000413.html
|
||||||
|
|
||||||
|
|
||||||
Noteworthy changes in version 2.1.23 (2017-08-09)
|
Noteworthy changes in version 2.1.23 (2017-08-09)
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
@ -94,6 +94,10 @@ static int initialization_done;
|
|||||||
/* Total number of non-permanent certificates. */
|
/* Total number of non-permanent certificates. */
|
||||||
static unsigned int total_nonperm_certificates;
|
static unsigned int total_nonperm_certificates;
|
||||||
|
|
||||||
|
/* For each cert class the corresponding bit is set if at least one
|
||||||
|
* certificate of that class is loaded permanetly. */
|
||||||
|
static unsigned int any_cert_of_class;
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_W32_SYSTEM
|
#ifdef HAVE_W32_SYSTEM
|
||||||
/* We load some functions dynamically. Provide typedefs for tehse
|
/* We load some functions dynamically. Provide typedefs for tehse
|
||||||
@ -343,7 +347,9 @@ put_cert (ksba_cert_t cert, int permanent, unsigned int trustclass,
|
|||||||
ci->permanent = !!permanent;
|
ci->permanent = !!permanent;
|
||||||
ci->trustclasses = trustclass;
|
ci->trustclasses = trustclass;
|
||||||
|
|
||||||
if (!permanent)
|
if (permanent)
|
||||||
|
any_cert_of_class |= trustclass;
|
||||||
|
else
|
||||||
total_nonperm_certificates++;
|
total_nonperm_certificates++;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -758,6 +764,7 @@ cert_cache_deinit (int full)
|
|||||||
}
|
}
|
||||||
|
|
||||||
total_nonperm_certificates = 0;
|
total_nonperm_certificates = 0;
|
||||||
|
any_cert_of_class = 0;
|
||||||
initialization_done = 0;
|
initialization_done = 0;
|
||||||
release_cache_lock ();
|
release_cache_lock ();
|
||||||
}
|
}
|
||||||
@ -814,6 +821,15 @@ cert_cache_print_stats (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return true if any cert of a class in MASK is permanently
|
||||||
|
* loaded. */
|
||||||
|
int
|
||||||
|
cert_cache_any_in_class (unsigned int mask)
|
||||||
|
{
|
||||||
|
return !!(any_cert_of_class & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Put CERT into the certificate cache. */
|
/* Put CERT into the certificate cache. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
cache_cert (ksba_cert_t cert)
|
cache_cert (ksba_cert_t cert)
|
||||||
|
@ -39,6 +39,9 @@ void cert_cache_deinit (int full);
|
|||||||
/* Print some statistics to the log file. */
|
/* Print some statistics to the log file. */
|
||||||
void cert_cache_print_stats (void);
|
void cert_cache_print_stats (void);
|
||||||
|
|
||||||
|
/* Return true if any cert of a class in MASK is permanently loaded. */
|
||||||
|
int cert_cache_any_in_class (unsigned int mask);
|
||||||
|
|
||||||
/* Compute the fingerprint of the certificate CERT and put it into
|
/* Compute the fingerprint of the certificate CERT and put it into
|
||||||
the 20 bytes large buffer DIGEST. Return address of this buffer. */
|
the 20 bytes large buffer DIGEST. Return address of this buffer. */
|
||||||
unsigned char *cert_compute_fpr (ksba_cert_t cert, unsigned char *digest);
|
unsigned char *cert_compute_fpr (ksba_cert_t cert, unsigned char *digest);
|
||||||
|
@ -91,6 +91,12 @@ gnupg_http_tls_verify_cb (void *opaque,
|
|||||||
validate_flags |= VALIDATE_FLAG_TRUST_HKP;
|
validate_flags |= VALIDATE_FLAG_TRUST_HKP;
|
||||||
if ((http_flags & HTTP_FLAG_TRUST_SYS))
|
if ((http_flags & HTTP_FLAG_TRUST_SYS))
|
||||||
validate_flags |= VALIDATE_FLAG_TRUST_SYSTEM;
|
validate_flags |= VALIDATE_FLAG_TRUST_SYSTEM;
|
||||||
|
|
||||||
|
/* If HKP trust is requested and there are no HKP certificates
|
||||||
|
* configured, also try thye standard system certificates. */
|
||||||
|
if ((validate_flags & VALIDATE_FLAG_TRUST_HKP)
|
||||||
|
&& !cert_cache_any_in_class (CERTTRUST_CLASS_HKP))
|
||||||
|
validate_flags |= VALIDATE_FLAG_TRUST_SYSTEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((http_flags & HTTP_FLAG_NO_CRL))
|
if ((http_flags & HTTP_FLAG_NO_CRL))
|
||||||
|
@ -78,7 +78,9 @@ the command is a properly formatted mail with all standard headers.
|
|||||||
This mail can be fed to @command{sendmail(8)} or any other tool to
|
This mail can be fed to @command{sendmail(8)} or any other tool to
|
||||||
actually send that mail. If @command{sendmail(8)} is installed the
|
actually send that mail. If @command{sendmail(8)} is installed the
|
||||||
option @option{--send} can be used to directly send the created
|
option @option{--send} can be used to directly send the created
|
||||||
request.
|
request. If the provider request a 'mailbox-only' user id and no such
|
||||||
|
user id is found, @command{gpg-wks-client} will try an additional user
|
||||||
|
id.
|
||||||
|
|
||||||
The @option{--receive} and @option{--read} commands are used to
|
The @option{--receive} and @option{--read} commands are used to
|
||||||
process confirmation mails as send from the service provider. The
|
process confirmation mails as send from the service provider. The
|
||||||
|
@ -202,6 +202,7 @@ main( int argc, char **argv )
|
|||||||
dotlock_disable ();
|
dotlock_disable ();
|
||||||
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
|
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||||
additional_weak_digest("MD5");
|
additional_weak_digest("MD5");
|
||||||
|
gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG);
|
||||||
|
|
||||||
pargs.argc = &argc;
|
pargs.argc = &argc;
|
||||||
pargs.argv = &argv;
|
pargs.argv = &argv;
|
||||||
|
@ -3529,7 +3529,14 @@ proc_parameter_file (ctrl_t ctrl, struct para_data_s *para, const char *fname,
|
|||||||
if( s2 )
|
if( s2 )
|
||||||
p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")");
|
p = stpcpy(stpcpy(stpcpy(p," ("), s2 ),")");
|
||||||
if( s3 )
|
if( s3 )
|
||||||
p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">");
|
{
|
||||||
|
/* If we have only the email part, do not add the space
|
||||||
|
* and the angle brackets. */
|
||||||
|
if (*r->u.value)
|
||||||
|
p = stpcpy(stpcpy(stpcpy(p," <"), s3 ),">");
|
||||||
|
else
|
||||||
|
p = stpcpy (p, s3);
|
||||||
|
}
|
||||||
append_to_parameter (para, r);
|
append_to_parameter (para, r);
|
||||||
have_user_id=1;
|
have_user_id=1;
|
||||||
}
|
}
|
||||||
|
4
po/de.po
4
po/de.po
@ -9,7 +9,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnupg-2.1.0\n"
|
"Project-Id-Version: gnupg-2.1.0\n"
|
||||||
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
|
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
|
||||||
"PO-Revision-Date: 2017-08-09 12:49+0200\n"
|
"PO-Revision-Date: 2017-09-26 11:51+0200\n"
|
||||||
"Last-Translator: Werner Koch <wk@gnupg.org>\n"
|
"Last-Translator: Werner Koch <wk@gnupg.org>\n"
|
||||||
"Language-Team: German <de@li.org>\n"
|
"Language-Team: German <de@li.org>\n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
@ -194,7 +194,7 @@ msgid "failed to create stream from socket: %s\n"
|
|||||||
msgstr "Das Erzeugen eines Datenstroms aus dem Socket schlug fehl: %s\n"
|
msgstr "Das Erzeugen eines Datenstroms aus dem Socket schlug fehl: %s\n"
|
||||||
|
|
||||||
msgid "Please insert the card with serial number"
|
msgid "Please insert the card with serial number"
|
||||||
msgstr "Die legen Sie die Karte mit der folgenden Seriennummer ein:"
|
msgstr "Bitte legen Sie die Karte mit der folgenden Seriennummer ein"
|
||||||
|
|
||||||
msgid "Please remove the current card and insert the one with serial number"
|
msgid "Please remove the current card and insert the one with serial number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
15
po/el.po
15
po/el.po
@ -1,20 +1,21 @@
|
|||||||
# Greek Translation of GnuPG.
|
# Greek Translation of GnuPG.
|
||||||
# Copyright (C) 2002 Free Software Foundation, Inc.
|
# Copyright (C) 2002 Free Software Foundation, Inc.
|
||||||
# Dokianakis Theofanis <madf@hellug.gr>, 2002.
|
# Dokianakis Theofanis <madf@hellug.gr>, 2002.
|
||||||
# !-- psbl.surriel.com rejected (2011-01-11)
|
# !-- psbl.surriel.com rejected (2011-01-11)
|
||||||
# Designated-Translator: none
|
# Designated-Translator: none
|
||||||
#
|
# Dimitris Maroulidis <dmaroulidis@dimitrismaroulidis.com>, 2017.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: gnupg-1.1.92\n"
|
"Project-Id-Version: gnupg-1.1.92\n"
|
||||||
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
|
"Report-Msgid-Bugs-To: translations@gnupg.org\n"
|
||||||
"PO-Revision-Date: 2003-06-27 12:00+0200\n"
|
"PO-Revision-Date: 2017-09-14 21:14+0300\n"
|
||||||
"Last-Translator: Dokianakis Theofanis <madf@hellug.gr>\n"
|
"Last-Translator: Dimitris Maroulidis <dmaroulidis@dimitrismaroulidis.com>\n"
|
||||||
"Language-Team: Greek <nls@tux.hellug.gr>\n"
|
"Language-Team: team@gnome.gr\n"
|
||||||
"Language: el\n"
|
"Language: el\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid "failed to acquire the pinentry lock: %s\n"
|
msgid "failed to acquire the pinentry lock: %s\n"
|
||||||
@ -4423,7 +4424,7 @@ msgid "Keyring"
|
|||||||
msgstr "Κλειδοθήκη"
|
msgstr "Κλειδοθήκη"
|
||||||
|
|
||||||
msgid "Primary key fingerprint:"
|
msgid "Primary key fingerprint:"
|
||||||
msgstr "Αποτύπωμα πρωτεύων κλειδιού:"
|
msgstr "Αποτύπωμα πρωτεύοντος κλειδιού:"
|
||||||
|
|
||||||
msgid " Subkey fingerprint:"
|
msgid " Subkey fingerprint:"
|
||||||
msgstr " Αποτύπωμα υποκλειδιού:"
|
msgstr " Αποτύπωμα υποκλειδιού:"
|
||||||
@ -4431,7 +4432,7 @@ msgstr " Αποτύπωμα υποκλειδιού:"
|
|||||||
#. TRANSLATORS: this should fit into 24 bytes so that the
|
#. TRANSLATORS: this should fit into 24 bytes so that the
|
||||||
#. * fingerprint data is properly aligned with the user ID
|
#. * fingerprint data is properly aligned with the user ID
|
||||||
msgid " Primary key fingerprint:"
|
msgid " Primary key fingerprint:"
|
||||||
msgstr " Αποτύπωμα πρωτεύων κλειδιού:"
|
msgstr " Αποτύπωμα πρωτ. κλειδιού:"
|
||||||
|
|
||||||
msgid " Subkey fingerprint:"
|
msgid " Subkey fingerprint:"
|
||||||
msgstr " Αποτύπωμα υποκλειδιού:"
|
msgstr " Αποτύπωμα υποκλειδιού:"
|
||||||
|
@ -119,7 +119,7 @@ const char *fake_submission_addr;
|
|||||||
static void wrong_args (const char *text) GPGRT_ATTR_NORETURN;
|
static void wrong_args (const char *text) GPGRT_ATTR_NORETURN;
|
||||||
static gpg_error_t command_supported (char *userid);
|
static gpg_error_t command_supported (char *userid);
|
||||||
static gpg_error_t command_check (char *userid);
|
static gpg_error_t command_check (char *userid);
|
||||||
static gpg_error_t command_send (const char *fingerprint, char *userid);
|
static gpg_error_t command_send (const char *fingerprint, const char *userid);
|
||||||
static gpg_error_t encrypt_response (estream_t *r_output, estream_t input,
|
static gpg_error_t encrypt_response (estream_t *r_output, estream_t input,
|
||||||
const char *addrspec,
|
const char *addrspec,
|
||||||
const char *fingerprint);
|
const char *fingerprint);
|
||||||
@ -348,13 +348,13 @@ get_key_status_cb (void *opaque, const char *keyword, char *args)
|
|||||||
|
|
||||||
|
|
||||||
/* Get a key by fingerprint from gpg's keyring and make sure that the
|
/* Get a key by fingerprint from gpg's keyring and make sure that the
|
||||||
* mail address ADDRSPEC is included in the key. The key is returned
|
* mail address ADDRSPEC is included in the key. If EXACT is set the
|
||||||
* as a new memory stream at R_KEY.
|
* returned user id must match Addrspec exactly and not just in the
|
||||||
*
|
* addr-spec (mailbox) part. The key is returned as a new memory
|
||||||
* Fixme: After we have implemented import and export filters for gpg
|
* stream at R_KEY. */
|
||||||
* this function shall only return a key with just this user id. */
|
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
get_key (estream_t *r_key, const char *fingerprint, const char *addrspec)
|
get_key (estream_t *r_key, const char *fingerprint, const char *addrspec,
|
||||||
|
int exact)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
ccparray_t ccp;
|
ccparray_t ccp;
|
||||||
@ -379,7 +379,7 @@ get_key (estream_t *r_key, const char *fingerprint, const char *addrspec)
|
|||||||
es_fputs ("Content-Type: application/pgp-keys\n"
|
es_fputs ("Content-Type: application/pgp-keys\n"
|
||||||
"\n", key);
|
"\n", key);
|
||||||
|
|
||||||
filterexp = es_bsprintf ("keep-uid=mbox = %s", addrspec);
|
filterexp = es_bsprintf ("keep-uid=%s=%s", exact? "uid":"mbox", addrspec);
|
||||||
if (!filterexp)
|
if (!filterexp)
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
@ -438,6 +438,49 @@ get_key (estream_t *r_key, const char *fingerprint, const char *addrspec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Add the user id UID to the key identified by FINGERPRINT. */
|
||||||
|
static gpg_error_t
|
||||||
|
add_user_id (const char *fingerprint, const char *uid)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
ccparray_t ccp;
|
||||||
|
const char **argv = NULL;
|
||||||
|
|
||||||
|
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, "--always-trust");
|
||||||
|
ccparray_put (&ccp, "--quick-add-uid");
|
||||||
|
ccparray_put (&ccp, fingerprint);
|
||||||
|
ccparray_put (&ccp, uid);
|
||||||
|
|
||||||
|
ccparray_put (&ccp, NULL);
|
||||||
|
argv = ccparray_get (&ccp, NULL);
|
||||||
|
if (!argv)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
err = gnupg_exec_tool_stream (opt.gpg_program, argv, NULL,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("adding user id failed: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
xfree (argv);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct decrypt_stream_parm_s
|
struct decrypt_stream_parm_s
|
||||||
{
|
{
|
||||||
@ -600,8 +643,8 @@ command_check (char *userid)
|
|||||||
char *addrspec = NULL;
|
char *addrspec = NULL;
|
||||||
estream_t key = NULL;
|
estream_t key = NULL;
|
||||||
char *fpr = NULL;
|
char *fpr = NULL;
|
||||||
strlist_t mboxes = NULL;
|
uidinfo_list_t mboxes = NULL;
|
||||||
strlist_t sl;
|
uidinfo_list_t sl;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
|
||||||
addrspec = mailbox_from_userid (userid);
|
addrspec = mailbox_from_userid (userid);
|
||||||
@ -647,10 +690,9 @@ command_check (char *userid)
|
|||||||
|
|
||||||
/* Look closer at the key. */
|
/* Look closer at the key. */
|
||||||
err = wks_list_key (key, &fpr, &mboxes);
|
err = wks_list_key (key, &fpr, &mboxes);
|
||||||
if (err || !fpr)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error ("error parsing key: %s\n",
|
log_error ("error parsing key: %s\n", gpg_strerror (err));
|
||||||
err? gpg_strerror (err) : "no fingerprint found");
|
|
||||||
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -660,10 +702,15 @@ command_check (char *userid)
|
|||||||
|
|
||||||
for (sl = mboxes; sl; sl = sl->next)
|
for (sl = mboxes; sl; sl = sl->next)
|
||||||
{
|
{
|
||||||
if (!strcmp (sl->d, addrspec))
|
if (sl->mbox && !strcmp (sl->mbox, addrspec))
|
||||||
found = 1;
|
found = 1;
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
log_info (" addr-spec: %s\n", sl->d);
|
{
|
||||||
|
log_info (" user-id: %s\n", sl->uid);
|
||||||
|
log_info (" created: %s\n", asctimestamp (sl->created));
|
||||||
|
if (sl->mbox)
|
||||||
|
log_info (" addr-spec: %s\n", sl->mbox);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
@ -674,7 +721,7 @@ command_check (char *userid)
|
|||||||
|
|
||||||
leave:
|
leave:
|
||||||
xfree (fpr);
|
xfree (fpr);
|
||||||
free_strlist (mboxes);
|
free_uidinfo_list (mboxes);
|
||||||
es_fclose (key);
|
es_fclose (key);
|
||||||
xfree (addrspec);
|
xfree (addrspec);
|
||||||
return err;
|
return err;
|
||||||
@ -685,7 +732,7 @@ command_check (char *userid)
|
|||||||
/* Locate the key by fingerprint and userid and send a publication
|
/* Locate the key by fingerprint and userid and send a publication
|
||||||
* request. */
|
* request. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
command_send (const char *fingerprint, char *userid)
|
command_send (const char *fingerprint, const char *userid)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
KEYDB_SEARCH_DESC desc;
|
KEYDB_SEARCH_DESC desc;
|
||||||
@ -695,6 +742,12 @@ command_send (const char *fingerprint, char *userid)
|
|||||||
char *submission_to = NULL;
|
char *submission_to = NULL;
|
||||||
mime_maker_t mime = NULL;
|
mime_maker_t mime = NULL;
|
||||||
struct policy_flags_s policy;
|
struct policy_flags_s policy;
|
||||||
|
int no_encrypt = 0;
|
||||||
|
int posteo_hack = 0;
|
||||||
|
const char *domain;
|
||||||
|
uidinfo_list_t uidlist = NULL;
|
||||||
|
uidinfo_list_t uid, thisuid;
|
||||||
|
time_t thistime;
|
||||||
|
|
||||||
memset (&policy, 0, sizeof policy);
|
memset (&policy, 0, sizeof policy);
|
||||||
|
|
||||||
@ -706,6 +759,7 @@ command_send (const char *fingerprint, char *userid)
|
|||||||
err = gpg_error (GPG_ERR_INV_NAME);
|
err = gpg_error (GPG_ERR_INV_NAME);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
addrspec = mailbox_from_userid (userid);
|
addrspec = mailbox_from_userid (userid);
|
||||||
if (!addrspec)
|
if (!addrspec)
|
||||||
{
|
{
|
||||||
@ -713,10 +767,14 @@ command_send (const char *fingerprint, 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);
|
err = get_key (&key, fingerprint, addrspec, 0);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
|
domain = strchr (addrspec, '@');
|
||||||
|
log_assert (domain);
|
||||||
|
domain++;
|
||||||
|
|
||||||
/* Get the submission address. */
|
/* Get the submission address. */
|
||||||
if (fake_submission_addr)
|
if (fake_submission_addr)
|
||||||
{
|
{
|
||||||
@ -727,11 +785,8 @@ command_send (const char *fingerprint, char *userid)
|
|||||||
err = wkd_get_submission_address (addrspec, &submission_to);
|
err = wkd_get_submission_address (addrspec, &submission_to);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
char *domain = strchr (addrspec, '@');
|
log_error (_("error looking up submission address for domain '%s': %s\n"),
|
||||||
if (domain)
|
domain, gpg_strerror (err));
|
||||||
domain = domain + 1;
|
|
||||||
log_error (_("looking up WKS submission address for %s: %s\n"),
|
|
||||||
domain ? domain : addrspec, gpg_strerror (err));
|
|
||||||
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
if (gpg_err_code (err) == GPG_ERR_NO_DATA)
|
||||||
log_error (_("this domain probably doesn't support WKS.\n"));
|
log_error (_("this domain probably doesn't support WKS.\n"));
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -762,14 +817,92 @@ command_send (const char *fingerprint, char *userid)
|
|||||||
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);
|
||||||
|
|
||||||
/* Encrypt the key part. */
|
/* In case the key has several uids with the same addr-spec we will
|
||||||
es_rewind (key);
|
* use the newest one. */
|
||||||
err = encrypt_response (&keyenc, key, submission_to, fingerprint);
|
err = wks_list_key (key, NULL, &uidlist);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
{
|
||||||
es_fclose (key);
|
log_error ("error parsing key: %s\n",gpg_strerror (err));
|
||||||
key = NULL;
|
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
thistime = 0;
|
||||||
|
thisuid = NULL;
|
||||||
|
for (uid = uidlist; uid; uid = uid->next)
|
||||||
|
{
|
||||||
|
if (!uid->mbox)
|
||||||
|
continue; /* Should not happen anyway. */
|
||||||
|
if (policy.mailbox_only
|
||||||
|
&& ascii_strcasecmp (uid->uid, uid->mbox))
|
||||||
|
continue; /* UID has more than just the mailbox. */
|
||||||
|
if (uid->created > thistime)
|
||||||
|
{
|
||||||
|
thistime = uid->created;
|
||||||
|
thisuid = uid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!thisuid)
|
||||||
|
thisuid = uidlist; /* This is the case for a missing timestamp. */
|
||||||
|
if (opt.verbose)
|
||||||
|
log_info ("submitting key with user id '%s'\n", thisuid->uid);
|
||||||
|
|
||||||
|
/* If we have more than one user id we need to filter the key to
|
||||||
|
* include only THISUID. */
|
||||||
|
if (uidlist->next)
|
||||||
|
{
|
||||||
|
estream_t newkey;
|
||||||
|
|
||||||
|
es_rewind (key);
|
||||||
|
err = wks_filter_uid (&newkey, key, thisuid->uid);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("error filtering key: %s\n", gpg_strerror (err));
|
||||||
|
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
es_fclose (key);
|
||||||
|
key = newkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (policy.mailbox_only
|
||||||
|
&& (!thisuid->mbox || ascii_strcasecmp (thisuid->uid, thisuid->mbox)))
|
||||||
|
{
|
||||||
|
log_info ("Warning: policy requires 'mailbox-only'"
|
||||||
|
" - adding user id '%s'\n", addrspec);
|
||||||
|
err = add_user_id (fingerprint, addrspec);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
/* Need to get the key again. This time we request filtering
|
||||||
|
* for the full user id, so that we do not need check and filter
|
||||||
|
* the key again. */
|
||||||
|
es_fclose (key);
|
||||||
|
key = NULL;
|
||||||
|
err = get_key (&key, fingerprint, addrspec, 1);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hack to support posteo but let them disable this by setting the
|
||||||
|
* new policy-version flag. */
|
||||||
|
if (policy.protocol_version < 3
|
||||||
|
&& !ascii_strcasecmp (domain, "posteo.de"))
|
||||||
|
{
|
||||||
|
log_info ("Warning: Using draft-1 method for domain '%s'\n", domain);
|
||||||
|
no_encrypt = 1;
|
||||||
|
posteo_hack = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encrypt the key part. */
|
||||||
|
if (!no_encrypt)
|
||||||
|
{
|
||||||
|
es_rewind (key);
|
||||||
|
err = encrypt_response (&keyenc, key, submission_to, fingerprint);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
es_fclose (key);
|
||||||
|
key = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send the key. */
|
/* Send the key. */
|
||||||
err = mime_maker_new (&mime, NULL);
|
err = mime_maker_new (&mime, NULL);
|
||||||
@ -787,40 +920,86 @@ command_send (const char *fingerprint, char *userid)
|
|||||||
|
|
||||||
/* Tell server which draft we support. */
|
/* Tell server which draft we support. */
|
||||||
err = mime_maker_add_header (mime, "Wks-Draft-Version",
|
err = mime_maker_add_header (mime, "Wks-Draft-Version",
|
||||||
STR2(WKS_DRAFT_VERSION));
|
STR2(WKS_DRAFT_VERSION));
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
err = mime_maker_add_header (mime, "Content-Type",
|
if (no_encrypt)
|
||||||
"multipart/encrypted; "
|
{
|
||||||
"protocol=\"application/pgp-encrypted\"");
|
void *data;
|
||||||
if (err)
|
size_t datalen, n;
|
||||||
goto leave;
|
|
||||||
err = mime_maker_add_container (mime);
|
|
||||||
if (err)
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
err = mime_maker_add_header (mime, "Content-Type",
|
if (posteo_hack)
|
||||||
"application/pgp-encrypted");
|
{
|
||||||
if (err)
|
/* Needs a multipart/mixed with one(!) attachment. It does
|
||||||
goto leave;
|
* not grok a non-multipart mail. */
|
||||||
err = mime_maker_add_body (mime, "Version: 1\n");
|
err = mime_maker_add_header (mime, "Content-Type", "multipart/mixed");
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
err = mime_maker_add_header (mime, "Content-Type",
|
err = mime_maker_add_container (mime);
|
||||||
"application/octet-stream");
|
if (err)
|
||||||
if (err)
|
goto leave;
|
||||||
goto leave;
|
}
|
||||||
|
|
||||||
err = mime_maker_add_stream (mime, &keyenc);
|
err = mime_maker_add_header (mime, "Content-type",
|
||||||
if (err)
|
"application/pgp-keys");
|
||||||
goto leave;
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
if (es_fclose_snatch (key, &data, &datalen))
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
key = NULL;
|
||||||
|
/* We need to skip over the first line which has a content-type
|
||||||
|
* header not needed here. */
|
||||||
|
for (n=0; n < datalen ; n++)
|
||||||
|
if (((const char *)data)[n] == '\n')
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = mime_maker_add_body_data (mime, (char*)data + n, datalen - n);
|
||||||
|
xfree (data);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = mime_maker_add_header (mime, "Content-Type",
|
||||||
|
"multipart/encrypted; "
|
||||||
|
"protocol=\"application/pgp-encrypted\"");
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
err = mime_maker_add_container (mime);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = mime_maker_add_header (mime, "Content-Type",
|
||||||
|
"application/pgp-encrypted");
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
err = mime_maker_add_body (mime, "Version: 1\n");
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
err = mime_maker_add_header (mime, "Content-Type",
|
||||||
|
"application/octet-stream");
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = mime_maker_add_stream (mime, &keyenc);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
err = wks_send_mime (mime);
|
err = wks_send_mime (mime);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
mime_maker_release (mime);
|
mime_maker_release (mime);
|
||||||
xfree (submission_to);
|
xfree (submission_to);
|
||||||
|
free_uidinfo_list (uidlist);
|
||||||
es_fclose (keyenc);
|
es_fclose (keyenc);
|
||||||
es_fclose (key);
|
es_fclose (key);
|
||||||
xfree (addrspec);
|
xfree (addrspec);
|
||||||
|
@ -127,7 +127,7 @@ static struct debug_flags_s debug_flags [] =
|
|||||||
struct server_ctx_s
|
struct server_ctx_s
|
||||||
{
|
{
|
||||||
char *fpr;
|
char *fpr;
|
||||||
strlist_t mboxes; /* List of addr-specs taken from the UIDs. */
|
uidinfo_list_t mboxes; /* List with addr-specs taken from the UIDs. */
|
||||||
unsigned int draft_version_2:1; /* Client supports the draft 2. */
|
unsigned int draft_version_2:1; /* Client supports the draft 2. */
|
||||||
};
|
};
|
||||||
typedef struct server_ctx_s *server_ctx_t;
|
typedef struct server_ctx_s *server_ctx_t;
|
||||||
@ -1092,7 +1092,7 @@ static gpg_error_t
|
|||||||
process_new_key (server_ctx_t ctx, estream_t key)
|
process_new_key (server_ctx_t ctx, estream_t key)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
strlist_t sl;
|
uidinfo_list_t sl;
|
||||||
const char *s;
|
const char *s;
|
||||||
char *dname = NULL;
|
char *dname = NULL;
|
||||||
char *nonce = NULL;
|
char *nonce = NULL;
|
||||||
@ -1101,27 +1101,25 @@ process_new_key (server_ctx_t ctx, estream_t key)
|
|||||||
|
|
||||||
/* 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_strlist (ctx->mboxes);
|
free_uidinfo_list (ctx->mboxes);
|
||||||
err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
|
err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
if (!ctx->fpr)
|
log_assert (ctx->fpr);
|
||||||
{
|
|
||||||
log_error ("error parsing key (no fingerprint)\n");
|
|
||||||
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
log_info ("fingerprint: %s\n", ctx->fpr);
|
log_info ("fingerprint: %s\n", ctx->fpr);
|
||||||
for (sl = ctx->mboxes; sl; sl = sl->next)
|
for (sl = ctx->mboxes; sl; sl = sl->next)
|
||||||
{
|
{
|
||||||
log_info (" addr-spec: %s\n", sl->d);
|
if (sl->mbox)
|
||||||
|
log_info (" addr-spec: %s\n", sl->mbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Walk over all user ids and send confirmation requests for those
|
/* Walk over all user ids and send confirmation requests for those
|
||||||
* we support. */
|
* we support. */
|
||||||
for (sl = ctx->mboxes; sl; sl = sl->next)
|
for (sl = ctx->mboxes; sl; sl = sl->next)
|
||||||
{
|
{
|
||||||
s = strchr (sl->d, '@');
|
if (!sl->mbox)
|
||||||
|
continue;
|
||||||
|
s = strchr (sl->mbox, '@');
|
||||||
log_assert (s && s[1]);
|
log_assert (s && s[1]);
|
||||||
xfree (dname);
|
xfree (dname);
|
||||||
dname = make_filename_try (opt.directory, s+1, NULL);
|
dname = make_filename_try (opt.directory, s+1, NULL);
|
||||||
@ -1133,26 +1131,26 @@ process_new_key (server_ctx_t ctx, estream_t key)
|
|||||||
|
|
||||||
if (access (dname, W_OK))
|
if (access (dname, W_OK))
|
||||||
{
|
{
|
||||||
log_info ("skipping address '%s': Domain not configured\n", sl->d);
|
log_info ("skipping address '%s': Domain not configured\n", sl->mbox);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (get_policy_flags (&policybuf, sl->d))
|
if (get_policy_flags (&policybuf, sl->mbox))
|
||||||
{
|
{
|
||||||
log_info ("skipping address '%s': Bad policy flags\n", sl->d);
|
log_info ("skipping address '%s': Bad policy flags\n", sl->mbox);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (policybuf.auth_submit)
|
if (policybuf.auth_submit)
|
||||||
{
|
{
|
||||||
/* Bypass the confirmation stuff and publish the key as is. */
|
/* Bypass the confirmation stuff and publish the key as is. */
|
||||||
log_info ("publishing address '%s'\n", sl->d);
|
log_info ("publishing address '%s'\n", sl->mbox);
|
||||||
/* FIXME: We need to make sure that we do this only for the
|
/* FIXME: We need to make sure that we do this only for the
|
||||||
* address in the mail. */
|
* address in the mail. */
|
||||||
log_debug ("auth-submit not yet working!\n");
|
log_debug ("auth-submit not yet working!\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_info ("storing address '%s'\n", sl->d);
|
log_info ("storing address '%s'\n", sl->mbox);
|
||||||
|
|
||||||
xfree (nonce);
|
xfree (nonce);
|
||||||
xfree (fname);
|
xfree (fname);
|
||||||
@ -1160,7 +1158,7 @@ process_new_key (server_ctx_t ctx, estream_t key)
|
|||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
err = send_confirmation_request (ctx, sl->d, nonce, fname);
|
err = send_confirmation_request (ctx, sl->mbox, nonce, fname);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
@ -1313,7 +1311,7 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
|
|||||||
char *hash = NULL;
|
char *hash = NULL;
|
||||||
const char *domain;
|
const char *domain;
|
||||||
const char *s;
|
const char *s;
|
||||||
strlist_t sl;
|
uidinfo_list_t sl;
|
||||||
char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
|
char shaxbuf[32]; /* Used for SHA-1 and SHA-256 */
|
||||||
|
|
||||||
/* FIXME: There is a bug in name-value.c which adds white space for
|
/* FIXME: There is a bug in name-value.c which adds white space for
|
||||||
@ -1351,25 +1349,21 @@ check_and_publish (server_ctx_t ctx, const char *address, const char *nonce)
|
|||||||
|
|
||||||
/* We need to get the fingerprint from the key. */
|
/* We need to get the fingerprint from the key. */
|
||||||
xfree (ctx->fpr);
|
xfree (ctx->fpr);
|
||||||
free_strlist (ctx->mboxes);
|
free_uidinfo_list (ctx->mboxes);
|
||||||
err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
|
err = wks_list_key (key, &ctx->fpr, &ctx->mboxes);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
if (!ctx->fpr)
|
log_assert (ctx->fpr);
|
||||||
{
|
|
||||||
log_error ("error parsing key (no fingerprint)\n");
|
|
||||||
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
log_info ("fingerprint: %s\n", ctx->fpr);
|
log_info ("fingerprint: %s\n", ctx->fpr);
|
||||||
for (sl = ctx->mboxes; sl; sl = sl->next)
|
for (sl = ctx->mboxes; sl; sl = sl->next)
|
||||||
log_info (" addr-spec: %s\n", sl->d);
|
if (sl->mbox)
|
||||||
|
log_info (" addr-spec: %s\n", sl->mbox);
|
||||||
|
|
||||||
/* Check that the key has 'address' as a user id. We use
|
/* Check that the key has 'address' as a user id. We use
|
||||||
* case-insensitive matching because the client is expected to
|
* case-insensitive matching because the client is expected to
|
||||||
* return the address verbatim. */
|
* return the address verbatim. */
|
||||||
for (sl = ctx->mboxes; sl; sl = sl->next)
|
for (sl = ctx->mboxes; sl; sl = sl->next)
|
||||||
if (!strcmp (sl->d, address))
|
if (sl->mbox && !strcmp (sl->mbox, address))
|
||||||
break;
|
break;
|
||||||
if (!sl)
|
if (!sl)
|
||||||
{
|
{
|
||||||
@ -1565,7 +1559,7 @@ command_receive_cb (void *opaque, const char *mediatype,
|
|||||||
}
|
}
|
||||||
|
|
||||||
xfree (ctx.fpr);
|
xfree (ctx.fpr);
|
||||||
free_strlist (ctx.mboxes);
|
free_uidinfo_list (ctx.mboxes);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -63,16 +63,32 @@ struct policy_flags_s
|
|||||||
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;
|
||||||
|
unsigned int protocol_version; /* The supported WKS_DRAFT_VERION or 0 */
|
||||||
unsigned int max_pending; /* Seconds to wait for a confirmation. */
|
unsigned int max_pending; /* Seconds to wait for a confirmation. */
|
||||||
};
|
};
|
||||||
typedef struct policy_flags_s *policy_flags_t;
|
typedef struct policy_flags_s *policy_flags_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* An object to convey user ids of a key. */
|
||||||
|
struct uidinfo_list_s
|
||||||
|
{
|
||||||
|
struct uidinfo_list_s *next;
|
||||||
|
time_t created; /* Time the userid was created. */
|
||||||
|
char *mbox; /* NULL or the malloced mailbox from UID. */
|
||||||
|
char uid[1];
|
||||||
|
};
|
||||||
|
typedef struct uidinfo_list_s *uidinfo_list_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-- wks-util.c --*/
|
/*-- wks-util.c --*/
|
||||||
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);
|
||||||
gpg_error_t wks_list_key (estream_t key, char **r_fpr, strlist_t *r_mboxes);
|
void free_uidinfo_list (uidinfo_list_t list);
|
||||||
|
gpg_error_t wks_list_key (estream_t key, char **r_fpr,
|
||||||
|
uidinfo_list_t *r_mboxes);
|
||||||
|
gpg_error_t wks_filter_uid (estream_t *r_newkey, estream_t key,
|
||||||
|
const char *uid);
|
||||||
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);
|
||||||
|
@ -478,7 +478,8 @@ add_body (mime_maker_t ctx, const void *data, size_t datalen)
|
|||||||
|
|
||||||
|
|
||||||
/* Add STRING as body to the mail or the current MIME container. A
|
/* Add STRING as body to the mail or the current MIME container. A
|
||||||
* second call to this function is not allowed.
|
* second call to this function or mime_make_add_body_data is not
|
||||||
|
* allowed.
|
||||||
*
|
*
|
||||||
* FIXME: We may want to have an append_body to add more data to a body.
|
* FIXME: We may want to have an append_body to add more data to a body.
|
||||||
*/
|
*/
|
||||||
@ -489,6 +490,16 @@ mime_maker_add_body (mime_maker_t ctx, const char *string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Add (DATA,DATALEN) as body to the mail or the current MIME
|
||||||
|
* container. Note that a second call to this function or to
|
||||||
|
* mime_make_add_body is not allowed. */
|
||||||
|
gpg_error_t
|
||||||
|
mime_maker_add_body_data (mime_maker_t ctx, const void *data, size_t datalen)
|
||||||
|
{
|
||||||
|
return add_body (ctx, data, datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This is the same as mime_maker_add_body but takes a stream as
|
/* This is the same as mime_maker_add_body but takes a stream as
|
||||||
* argument. As of now the stream is copied to the MIME object but
|
* argument. As of now the stream is copied to the MIME object but
|
||||||
* eventually we may delay that and read the stream only at the time
|
* eventually we may delay that and read the stream only at the time
|
||||||
|
@ -34,6 +34,8 @@ void mime_maker_dump_tree (mime_maker_t ctx);
|
|||||||
gpg_error_t mime_maker_add_header (mime_maker_t ctx,
|
gpg_error_t mime_maker_add_header (mime_maker_t ctx,
|
||||||
const char *name, const char *value);
|
const char *name, const char *value);
|
||||||
gpg_error_t mime_maker_add_body (mime_maker_t ctx, const char *string);
|
gpg_error_t mime_maker_add_body (mime_maker_t ctx, const char *string);
|
||||||
|
gpg_error_t mime_maker_add_body_data (mime_maker_t ctx,
|
||||||
|
const void *data, size_t datalen);
|
||||||
gpg_error_t mime_maker_add_stream (mime_maker_t ctx, estream_t *stream_addr);
|
gpg_error_t mime_maker_add_stream (mime_maker_t ctx, estream_t *stream_addr);
|
||||||
gpg_error_t mime_maker_add_container (mime_maker_t ctx);
|
gpg_error_t mime_maker_add_container (mime_maker_t ctx);
|
||||||
gpg_error_t mime_maker_end_container (mime_maker_t ctx);
|
gpg_error_t mime_maker_end_container (mime_maker_t ctx);
|
||||||
|
174
tools/wks-util.c
174
tools/wks-util.c
@ -90,9 +90,52 @@ wks_write_status (int no, const char *format, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper for wks_list_key. */
|
|
||||||
|
/* Append UID to LIST and return the new item. On success LIST is
|
||||||
|
* updated. On error ERRNO is set and NULL returned. */
|
||||||
|
static uidinfo_list_t
|
||||||
|
append_to_uidinfo_list (uidinfo_list_t *list, const char *uid, time_t created)
|
||||||
|
{
|
||||||
|
uidinfo_list_t r, sl;
|
||||||
|
|
||||||
|
sl = xtrymalloc (sizeof *sl + strlen (uid));
|
||||||
|
if (!sl)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
strcpy (sl->uid, uid);
|
||||||
|
sl->created = created;
|
||||||
|
sl->mbox = mailbox_from_userid (uid);
|
||||||
|
sl->next = NULL;
|
||||||
|
if (!*list)
|
||||||
|
*list = sl;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (r = *list; r->next; r = r->next )
|
||||||
|
;
|
||||||
|
r->next = sl;
|
||||||
|
}
|
||||||
|
return sl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Free the list of uid infos at LIST. */
|
||||||
|
void
|
||||||
|
free_uidinfo_list (uidinfo_list_t list)
|
||||||
|
{
|
||||||
|
while (list)
|
||||||
|
{
|
||||||
|
uidinfo_list_t tmp = list->next;
|
||||||
|
xfree (list->mbox);
|
||||||
|
xfree (list);
|
||||||
|
list = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper for wks_list_key and wks_filter_uid. */
|
||||||
static void
|
static void
|
||||||
list_key_status_cb (void *opaque, const char *keyword, char *args)
|
key_status_cb (void *opaque, const char *keyword, char *args)
|
||||||
{
|
{
|
||||||
(void)opaque;
|
(void)opaque;
|
||||||
|
|
||||||
@ -103,9 +146,10 @@ list_key_status_cb (void *opaque, const char *keyword, char *args)
|
|||||||
|
|
||||||
/* Run gpg on KEY and store the primary fingerprint at R_FPR and the
|
/* Run gpg on KEY and store the primary fingerprint at R_FPR and the
|
||||||
* list of mailboxes at R_MBOXES. Returns 0 on success; on error NULL
|
* list of mailboxes at R_MBOXES. Returns 0 on success; on error NULL
|
||||||
* is stored at R_FPR and R_MBOXES and an error code is returned. */
|
* is stored at R_FPR and R_MBOXES and an error code is returned.
|
||||||
|
* R_FPR may be NULL if the fingerprint is not needed. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
wks_list_key (estream_t key, char **r_fpr, strlist_t *r_mboxes)
|
wks_list_key (estream_t key, char **r_fpr, uidinfo_list_t *r_mboxes)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
ccparray_t ccp;
|
ccparray_t ccp;
|
||||||
@ -118,11 +162,11 @@ wks_list_key (estream_t key, char **r_fpr, strlist_t *r_mboxes)
|
|||||||
char **fields = NULL;
|
char **fields = NULL;
|
||||||
int nfields;
|
int nfields;
|
||||||
int lnr;
|
int lnr;
|
||||||
char *mbox = NULL;
|
|
||||||
char *fpr = NULL;
|
char *fpr = NULL;
|
||||||
strlist_t mboxes = NULL;
|
uidinfo_list_t mboxes = NULL;
|
||||||
|
|
||||||
*r_fpr = NULL;
|
if (r_fpr)
|
||||||
|
*r_fpr = NULL;
|
||||||
*r_mboxes = NULL;
|
*r_mboxes = NULL;
|
||||||
|
|
||||||
/* Open a memory stream. */
|
/* Open a memory stream. */
|
||||||
@ -158,7 +202,7 @@ wks_list_key (estream_t key, char **r_fpr, strlist_t *r_mboxes)
|
|||||||
}
|
}
|
||||||
err = gnupg_exec_tool_stream (opt.gpg_program, argv, key,
|
err = gnupg_exec_tool_stream (opt.gpg_program, argv, key,
|
||||||
NULL, listing,
|
NULL, listing,
|
||||||
list_key_status_cb, NULL);
|
key_status_cb, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error ("import failed: %s\n", gpg_strerror (err));
|
log_error ("import failed: %s\n", gpg_strerror (err));
|
||||||
@ -232,9 +276,8 @@ wks_list_key (estream_t key, char **r_fpr, strlist_t *r_mboxes)
|
|||||||
else if (!strcmp (fields[0], "uid") && nfields > 9)
|
else if (!strcmp (fields[0], "uid") && nfields > 9)
|
||||||
{
|
{
|
||||||
/* Fixme: Unescape fields[9] */
|
/* Fixme: Unescape fields[9] */
|
||||||
xfree (mbox);
|
if (!append_to_uidinfo_list (&mboxes, fields[9],
|
||||||
mbox = mailbox_from_userid (fields[9]);
|
parse_timestamp (fields[5], NULL)))
|
||||||
if (mbox && !append_to_strlist_try (&mboxes, mbox))
|
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
goto leave;
|
goto leave;
|
||||||
@ -248,15 +291,23 @@ wks_list_key (estream_t key, char **r_fpr, strlist_t *r_mboxes)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
*r_fpr = fpr;
|
if (!fpr)
|
||||||
fpr = NULL;
|
{
|
||||||
|
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r_fpr)
|
||||||
|
{
|
||||||
|
*r_fpr = fpr;
|
||||||
|
fpr = NULL;
|
||||||
|
}
|
||||||
*r_mboxes = mboxes;
|
*r_mboxes = mboxes;
|
||||||
mboxes = NULL;
|
mboxes = NULL;
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
xfree (fpr);
|
xfree (fpr);
|
||||||
xfree (mboxes);
|
free_uidinfo_list (mboxes);
|
||||||
xfree (mbox);
|
|
||||||
xfree (fields);
|
xfree (fields);
|
||||||
es_free (line);
|
es_free (line);
|
||||||
xfree (argv);
|
xfree (argv);
|
||||||
@ -265,6 +316,85 @@ wks_list_key (estream_t key, char **r_fpr, strlist_t *r_mboxes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* UID. Returns 0 on success. Only one key is expected in KEY. */
|
||||||
|
gpg_error_t
|
||||||
|
wks_filter_uid (estream_t *r_newkey, estream_t key, const char *uid)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
ccparray_t ccp;
|
||||||
|
const char **argv = NULL;
|
||||||
|
estream_t newkey;
|
||||||
|
char *filterexp = NULL;
|
||||||
|
|
||||||
|
*r_newkey = NULL;
|
||||||
|
|
||||||
|
/* Open a memory stream. */
|
||||||
|
newkey = es_fopenmem (0, "w+b");
|
||||||
|
if (!newkey)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
log_error ("error allocating memory buffer: %s\n", gpg_strerror (err));
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prefix the key with the MIME content type. */
|
||||||
|
es_fputs ("Content-Type: application/pgp-keys\n"
|
||||||
|
"\n", newkey);
|
||||||
|
|
||||||
|
filterexp = es_bsprintf ("keep-uid=uid=%s", uid);
|
||||||
|
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, "--import-options=import-export");
|
||||||
|
ccparray_put (&ccp, "--import-filter");
|
||||||
|
ccparray_put (&ccp, filterexp);
|
||||||
|
ccparray_put (&ccp, "--import");
|
||||||
|
|
||||||
|
ccparray_put (&ccp, NULL);
|
||||||
|
argv = ccparray_get (&ccp, NULL);
|
||||||
|
if (!argv)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
err = gnupg_exec_tool_stream (opt.gpg_program, argv, key,
|
||||||
|
NULL, newkey,
|
||||||
|
key_status_cb, NULL);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("import/export failed: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
es_rewind (newkey);
|
||||||
|
*r_newkey = newkey;
|
||||||
|
newkey = NULL;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
xfree (filterexp);
|
||||||
|
xfree (argv);
|
||||||
|
es_fclose (newkey);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Helper to write mail to the output(s). */
|
/* Helper to write mail to the output(s). */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
wks_send_mime (mime_maker_t mime)
|
wks_send_mime (mime_maker_t mime)
|
||||||
@ -316,7 +446,8 @@ wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
|||||||
TOK_MAILBOX_ONLY,
|
TOK_MAILBOX_ONLY,
|
||||||
TOK_DANE_ONLY,
|
TOK_DANE_ONLY,
|
||||||
TOK_AUTH_SUBMIT,
|
TOK_AUTH_SUBMIT,
|
||||||
TOK_MAX_PENDING
|
TOK_MAX_PENDING,
|
||||||
|
TOK_PROTOCOL_VERSION
|
||||||
};
|
};
|
||||||
static struct {
|
static struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -325,7 +456,8 @@ wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
|||||||
{ "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 },
|
||||||
{ "max-pending", TOK_MAX_PENDING }
|
{ "max-pending", TOK_MAX_PENDING },
|
||||||
|
{ "protocol-version", TOK_PROTOCOL_VERSION }
|
||||||
};
|
};
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
int lnr = 0;
|
int lnr = 0;
|
||||||
@ -400,6 +532,14 @@ wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
|
|||||||
* and decide whether to allow other units. */
|
* and decide whether to allow other units. */
|
||||||
flags->max_pending = atoi (value);
|
flags->max_pending = atoi (value);
|
||||||
break;
|
break;
|
||||||
|
case TOK_PROTOCOL_VERSION:
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_SYNTAX);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
flags->protocol_version = atoi (value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user