diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/Makefile.am | 3 | ||||
-rw-r--r-- | g10/build-packet.c | 29 | ||||
-rw-r--r-- | g10/call-agent.c | 11 | ||||
-rw-r--r-- | g10/call-agent.h | 2 | ||||
-rw-r--r-- | g10/call-dirmngr.c | 206 | ||||
-rw-r--r-- | g10/card-util.c | 6 | ||||
-rw-r--r-- | g10/ecdh.c | 24 | ||||
-rw-r--r-- | g10/encrypt.c | 14 | ||||
-rw-r--r-- | g10/getkey.c | 179 | ||||
-rw-r--r-- | g10/gpg.c | 133 | ||||
-rw-r--r-- | g10/keydb.c | 12 | ||||
-rw-r--r-- | g10/keyedit.c | 41 | ||||
-rw-r--r-- | g10/keygen.c | 5 | ||||
-rw-r--r-- | g10/keyid.c | 21 | ||||
-rw-r--r-- | g10/keylist.c | 231 | ||||
-rw-r--r-- | g10/keyserver.c | 10 | ||||
-rw-r--r-- | g10/main.h | 7 | ||||
-rw-r--r-- | g10/mainproc.c | 14 | ||||
-rw-r--r-- | g10/misc.c | 94 | ||||
-rw-r--r-- | g10/options.h | 22 | ||||
-rw-r--r-- | g10/parse-packet.c | 56 | ||||
-rw-r--r-- | g10/pkglue.c | 2 | ||||
-rw-r--r-- | g10/pubkey-enc.c | 4 | ||||
-rw-r--r-- | g10/seskey.c | 4 | ||||
-rw-r--r-- | g10/sig-check.c | 2 | ||||
-rw-r--r-- | g10/sign.c | 4 | ||||
-rw-r--r-- | g10/tdbdump.c | 60 | ||||
-rw-r--r-- | g10/tdbio.c | 65 | ||||
-rw-r--r-- | g10/tdbio.h | 2 | ||||
-rw-r--r-- | g10/trustdb.c | 26 |
30 files changed, 833 insertions, 456 deletions
diff --git a/g10/Makefile.am b/g10/Makefile.am index 0a02119..b66abb8 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -21,8 +21,7 @@ EXTRA_DIST = options.skel distsigkey.gpg ChangeLog-2011 gpg-w32info.rc \ gpg.w32-manifest.in -AM_CPPFLAGS = -I$(top_srcdir)/gl -I$(top_srcdir)/common \ - -I$(top_srcdir)/include -I$(top_srcdir)/intl +AM_CPPFLAGS = -I$(top_srcdir)/common include $(top_srcdir)/am/cmacros.am diff --git a/g10/build-packet.c b/g10/build-packet.c index e44350e..269c63c 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -164,14 +164,32 @@ gpg_mpi_write (iobuf_t out, gcry_mpi_t a) if (gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) { unsigned int nbits; - const void *p; - unsigned int lenhdr[2]; + const unsigned char *p; + unsigned char lenhdr[2]; + /* gcry_log_debugmpi ("a", a); */ p = gcry_mpi_get_opaque (a, &nbits); + if (p) + { + /* Strip leading zero bits. */ + for (; nbits >= 8 && !*p; p++, nbits -= 8) + ; + if (nbits >= 8 && !(*p & 0x80)) + if (--nbits >= 7 && !(*p & 0x40)) + if (--nbits >= 6 && !(*p & 0x20)) + if (--nbits >= 5 && !(*p & 0x10)) + if (--nbits >= 4 && !(*p & 0x08)) + if (--nbits >= 3 && !(*p & 0x04)) + if (--nbits >= 2 && !(*p & 0x02)) + if (--nbits >= 1 && !(*p & 0x01)) + --nbits; + } + /* gcry_log_debug (" [%u bit]\n", nbits); */ + /* gcry_log_debughex (" ", p, (nbits+7)/8); */ lenhdr[0] = nbits >> 8; lenhdr[1] = nbits; rc = iobuf_write (out, lenhdr, 2); - if (!rc) + if (!rc && p) rc = iobuf_write (out, p, (nbits+7)/8); } else @@ -209,7 +227,7 @@ gpg_mpi_write_nohdr (iobuf_t out, gcry_mpi_t a) const void *p; p = gcry_mpi_get_opaque (a, &nbits); - rc = iobuf_write (out, p, (nbits+7)/8); + rc = p ? iobuf_write (out, p, (nbits+7)/8) : 0; } else rc = gpg_error (GPG_ERR_BAD_MPI); @@ -393,7 +411,8 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) assert (gcry_mpi_get_flag (pk->pkey[npkey], GCRYMPI_FLAG_OPAQUE)); p = gcry_mpi_get_opaque (pk->pkey[npkey], &ndatabits); - iobuf_write (a, p, (ndatabits+7)/8 ); + if (p) + iobuf_write (a, p, (ndatabits+7)/8 ); } else { diff --git a/g10/call-agent.c b/g10/call-agent.c index 4bac8a0..017e916 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -43,10 +43,6 @@ #include "../common/shareddefs.h" #include "host2net.h" -#ifndef DBG_ASSUAN -# define DBG_ASSUAN 1 -#endif - #define CONTROL_D ('D' - 'A' + 1) @@ -286,7 +282,7 @@ start_agent (ctrl_t ctrl, int for_card) opt.agent_program, opt.lc_ctype, opt.lc_messages, opt.session_env, - opt.autostart, opt.verbose, DBG_ASSUAN, + opt.autostart, opt.verbose, DBG_IPC, NULL, NULL); if (!opt.autostart && gpg_err_code (rc) == GPG_ERR_NO_AGENT) { @@ -673,7 +669,7 @@ learn_status_cb (void *opaque, const char *line) /* Call the scdaemon to learn about a smartcard */ int -agent_scd_learn (struct agent_card_info_s *info) +agent_scd_learn (struct agent_card_info_s *info, int force) { int rc; struct default_inq_parm_s parm; @@ -701,7 +697,8 @@ agent_scd_learn (struct agent_card_info_s *info) return rc; parm.ctx = agent_ctx; - rc = assuan_transact (agent_ctx, "LEARN --sendinfo", + rc = assuan_transact (agent_ctx, + force ? "LEARN --sendinfo --force" : "LEARN --sendinfo", dummy_data_cb, NULL, default_inq_cb, &parm, learn_status_cb, info); /* Also try to get the key attributes. */ diff --git a/g10/call-agent.h b/g10/call-agent.h index 9c104e8..df570a4 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -77,7 +77,7 @@ struct agent_card_genkey_s { void agent_release_card_info (struct agent_card_info_s *info); /* Return card info. */ -int agent_scd_learn (struct agent_card_info_s *info); +int agent_scd_learn (struct agent_card_info_s *info, int force); /* Send an APDU to the card. */ gpg_error_t agent_scd_apdu (const char *hexapdu, unsigned int *r_sw); diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c index b802f81..ef4ca76 100644 --- a/g10/call-dirmngr.c +++ b/g10/call-dirmngr.c @@ -1,5 +1,6 @@ /* call-dirmngr.c - GPG operations to the Dirmngr. * Copyright (C) 2011 Free Software Foundation, Inc. + * Copyright (C) 2015 g10 Code GmbH * * This file is part of GnuPG. * @@ -130,7 +131,7 @@ create_context (ctrl_t ctrl, assuan_context_t *r_ctx) GPG_ERR_SOURCE_DEFAULT, opt.homedir, opt.dirmngr_program, - opt.autostart, opt.verbose, DBG_ASSUAN, + opt.autostart, opt.verbose, DBG_IPC, NULL /*gpg_status2*/, ctrl); if (!opt.autostart && gpg_err_code (err) == GPG_ERR_NO_DIRMNGR) { @@ -585,6 +586,117 @@ gpg_dirmngr_ks_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp) +static void +record_output (estream_t output, + pkttype_t type, + const char *validity, + /* The public key length or -1. */ + int pub_key_length, + /* The public key algo or -1. */ + int pub_key_algo, + /* 2 ulongs or NULL. */ + const u32 *keyid, + /* The creation / expiration date or 0. */ + u32 creation_date, + u32 expiration_date, + const char *userid) +{ + const char *type_str = NULL; + char *pub_key_length_str = NULL; + char *pub_key_algo_str = NULL; + char *keyid_str = NULL; + char *creation_date_str = NULL; + char *expiration_date_str = NULL; + char *userid_escaped = NULL; + + switch (type) + { + case PKT_PUBLIC_KEY: + type_str = "pub"; + break; + case PKT_PUBLIC_SUBKEY: + type_str = "sub"; + break; + case PKT_USER_ID: + type_str = "uid"; + break; + case PKT_SIGNATURE: + type_str = "sig"; + break; + default: + assert (! "Unhandled type."); + } + + if (pub_key_length > 0) + pub_key_length_str = xasprintf ("%d", pub_key_length); + + if (pub_key_algo != -1) + pub_key_algo_str = xasprintf ("%d", pub_key_algo); + + if (keyid) + keyid_str = xasprintf ("%08lX%08lX", (ulong) keyid[0], (ulong) keyid[1]); + + if (creation_date) + creation_date_str = xstrdup (colon_strtime (creation_date)); + + if (expiration_date) + expiration_date_str = xstrdup (colon_strtime (expiration_date)); + + /* Quote ':', '%', and any 8-bit characters. */ + if (userid) + { + int r; + int w = 0; + + int len = strlen (userid); + /* A 100k character limit on the uid should be way more than + enough. */ + if (len > 100 * 1024) + len = 100 * 1024; + + /* The minimum amount of space that we need. */ + userid_escaped = xmalloc (len * 3 + 1); + + for (r = 0; r < len; r++) + { + if (userid[r] == ':' || userid[r]== '%' || (userid[r] & 0x80)) + { + sprintf (&userid_escaped[w], "%%%02X", (byte) userid[r]); + w += 3; + } + else + userid_escaped[w ++] = userid[r]; + } + userid_escaped[w] = '\0'; + } + + es_fprintf (output, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n", + type_str, + validity ?: "", + pub_key_length_str ?: "", + pub_key_algo_str ?: "", + keyid_str ?: "", + creation_date_str ?: "", + expiration_date_str ?: "", + "" /* Certificate S/N */, + "" /* Ownertrust. */, + userid_escaped ?: "", + "" /* Signature class. */, + "" /* Key capabilities. */, + "" /* Issuer certificate fingerprint. */, + "" /* Flag field. */, + "" /* S/N of a token. */, + "" /* Hash algo. */, + "" /* Curve name. */); + + xfree (userid_escaped); + xfree (expiration_date_str); + xfree (creation_date_str); + xfree (keyid_str); + xfree (pub_key_algo_str); + xfree (pub_key_length_str); +} + /* Handle the KS_PUT inquiries. */ static gpg_error_t ks_put_inq_cb (void *opaque, const char *line) @@ -607,53 +719,80 @@ ks_put_inq_cb (void *opaque, const char *line) if (!fp) err = gpg_error_from_syserror (); + /* Note: the output format for the INFO block follows the colon + format as described in doc/DETAILS. We don't actually reuse + the functionality from g10/keylist.c to produce the output, + because we don't need all of it and some of it is quite + expensive to generate. + + The fields are (the starred fields are the ones we need): + + * Field 1 - Type of record + * Field 2 - Validity + * Field 3 - Key length + * Field 4 - Public key algorithm + * Field 5 - KeyID + * Field 6 - Creation date + * Field 7 - Expiration date + Field 8 - Certificate S/N, UID hash, trust signature info + Field 9 - Ownertrust + * Field 10 - User-ID + Field 11 - Signature class + Field 12 - Key capabilities + Field 13 - Issuer certificate fingerprint or other info + Field 14 - Flag field + Field 15 - S/N of a token + Field 16 - Hash algorithm + Field 17 - Curve name + */ for (node = parm->keyblock; !err && node; node=node->next) { - switch(node->pkt->pkttype) + switch (node->pkt->pkttype) { case PKT_PUBLIC_KEY: case PKT_PUBLIC_SUBKEY: { PKT_public_key *pk = node->pkt->pkt.public_key; + char validity[3]; + int i; + + i = 0; + if (pk->flags.revoked) + validity[i ++] = 'r'; + if (pk->has_expired) + validity[i ++] = 'e'; + validity[i] = '\0'; + keyid_from_pk (pk, NULL); - es_fprintf (fp, "%s:%08lX%08lX:%u:%u:%u:%u:%s%s:\n", - node->pkt->pkttype==PKT_PUBLIC_KEY? "pub" : "sub", - (ulong)pk->keyid[0], (ulong)pk->keyid[1], - pk->pubkey_algo, - nbits_from_pk (pk), - pk->timestamp, - pk->expiredate, - pk->flags.revoked? "r":"", - pk->has_expired? "e":""); + record_output (fp, node->pkt->pkttype, validity, + nbits_from_pk (pk), pk->pubkey_algo, + pk->keyid, pk->timestamp, pk->expiredate, + NULL); } break; case PKT_USER_ID: { PKT_user_id *uid = node->pkt->pkt.user_id; - int r; if (!uid->attrib_data) { - es_fprintf (fp, "uid:"); - - /* Quote ':', '%', and any 8-bit characters. */ - for (r=0; r < uid->len; r++) - { - if (uid->name[r] == ':' - || uid->name[r]== '%' - || (uid->name[r]&0x80)) - es_fprintf (fp, "%%%02X", (byte)uid->name[r]); - else - es_putc (uid->name[r], fp); - } - - es_fprintf (fp, ":%u:%u:%s%s:\n", - uid->created,uid->expiredate, - uid->is_revoked? "r":"", - uid->is_expired? "e":""); + char validity[3]; + int i; + + i = 0; + if (uid->is_revoked) + validity[i ++] = 'r'; + if (uid->is_expired) + validity[i ++] = 'e'; + validity[i] = '\0'; + + record_output (fp, node->pkt->pkttype, validity, + -1, -1, NULL, + uid->created, uid->expiredate, + uid->name); } } break; @@ -667,12 +806,9 @@ ks_put_inq_cb (void *opaque, const char *line) PKT_signature *sig = node->pkt->pkt.signature; if (IS_UID_SIG (sig)) - { - es_fprintf (fp, "sig:%08lX%08lX:%X:%u:%u:\n", - (ulong)sig->keyid[0],(ulong)sig->keyid[1], - sig->sig_class, sig->timestamp, - sig->expiredate); - } + record_output (fp, node->pkt->pkttype, NULL, + -1, -1, sig->keyid, + sig->timestamp, sig->expiredate, NULL); } break; diff --git a/g10/card-util.c b/g10/card-util.c index 4b584bf..a291a07 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -81,7 +81,7 @@ change_pin (int unblock_v2, int allow_admin) struct agent_card_info_s info; int rc; - rc = agent_scd_learn (&info); + rc = agent_scd_learn (&info, 0); if (rc) { log_error (_("OpenPGP card not available: %s\n"), @@ -374,7 +374,7 @@ card_status (estream_t fp, char *serialno, size_t serialnobuflen) if (serialno && serialnobuflen) *serialno = 0; - rc = agent_scd_learn (&info); + rc = agent_scd_learn (&info, 0); if (rc) { if (opt.with_colons) @@ -1702,7 +1702,7 @@ factory_reset (void) but tries to find out something about the card first. */ - err = agent_scd_learn (&info); + err = agent_scd_learn (&info, 0); if (gpg_err_code (err) == GPG_ERR_OBJ_TERM_STATE && gpg_err_source (err) == GPG_ERR_SOURCE_SCD) termstate = 1; @@ -76,7 +76,7 @@ pk_ecdh_default_params (unsigned int qbits) } } assert (i < DIM (kek_params_table)); - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("ECDH KEK params are", kek_params, sizeof(kek_params) ); return gcry_mpi_set_opaque (NULL, kek_params, 4 * 8); @@ -138,7 +138,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, memmove (secret_x, secret_x+1, secret_x_size); memset (secret_x+secret_x_size, 0, nbytes-secret_x_size); - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size ); } @@ -158,7 +158,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, kek_params = gcry_mpi_get_opaque (pkey[2], &nbits); kek_params_size = (nbits+7)/8; - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("ecdh KDF params:", kek_params, kek_params_size); /* Expect 4 bytes 03 01 hash_alg symm_alg. */ @@ -171,7 +171,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, kdf_hash_algo = kek_params[2]; kdf_encr_algo = kek_params[3]; - if (DBG_CIPHER) + if (DBG_CRYPTO) log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n", openpgp_md_algo_name (kdf_hash_algo), openpgp_cipher_algo_name (kdf_encr_algo)); @@ -215,7 +215,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, return err; } - if(DBG_CIPHER) + if(DBG_CRYPTO) log_printhex ("ecdh KDF message params are:", message, message_size); } @@ -251,7 +251,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, /* We could have allocated more, so clean the tail before returning. */ memset (secret_x+secret_x_size, 0, old_size - secret_x_size); - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("ecdh KEK is:", secret_x, secret_x_size ); } @@ -317,7 +317,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, return err; } - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("ecdh encrypting :", in, data_buf_size ); err = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8, @@ -333,7 +333,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, } data_buf[0] = data_buf_size+8; - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] ); result = gcry_mpi_set_opaque (NULL, data_buf, 8 * (1+data_buf[0])); @@ -370,7 +370,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, in = data_buf+data_buf_size; data_buf_size = data_buf[0]; - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size); err = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1, @@ -386,7 +386,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, data_buf_size -= 8; - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("ecdh decrypted to :", in, data_buf_size); /* Padding is removed later. */ @@ -420,12 +420,12 @@ gen_k (unsigned nbits) gcry_mpi_t k; k = gcry_mpi_snew (nbits); - if (DBG_CIPHER) + if (DBG_CRYPTO) log_debug ("choosing a random k of %u bits\n", nbits); gcry_mpi_randomize (k, nbits-1, GCRY_STRONG_RANDOM); - if (DBG_CIPHER) + if (DBG_CRYPTO) { unsigned char *buffer; if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, k)) diff --git a/g10/encrypt.c b/g10/encrypt.c index 8d2b325..d5835d4 100644 --- a/g10/encrypt.c +++ b/g10/encrypt.c @@ -453,6 +453,9 @@ write_symkey_enc (STRING2KEY *symkey_s2k, DEK *symkey_dek, DEK *dek, * supplied). Either FILENAME or FILEFD must be given, but not both. * The caller may provide a checked list of public keys in * PROVIDED_PKS; if not the function builds a list of keys on its own. + * + * Note that FILEFD is currently only used by cmd_encrypt in the the + * not yet finished server.c. */ int encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename, @@ -476,7 +479,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename, int do_compress; if (filefd != -1 && filename) - return gpg_error (GPG_ERR_INV_ARG); + return gpg_error (GPG_ERR_INV_ARG); /* Both given. */ do_compress = !!opt.compress_algo; @@ -618,7 +621,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename, } make_session_key (cfx.dek); - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("DEK is: ", cfx.dek->key, cfx.dek->keylen ); rc = write_pubkey_enc_from_list (pk_list, cfx.dek, out); @@ -635,8 +638,9 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename, if (!opt.no_literal) pt = setup_plaintext_name (filename, inp); - if (filefd != -1 - && !iobuf_is_pipe_filename (filename) && *filename && !opt.textmode ) + /* Get the size of the file if possible, i.e., if it is a real file. */ + if (filename && *filename + && !iobuf_is_pipe_filename (filename) && !opt.textmode ) { off_t tmpsize; int overflow; @@ -811,7 +815,7 @@ encrypt_filter (void *opaque, int control, efx->cfx.dek->use_mdc = use_mdc (efx->pk_list,efx->cfx.dek->algo); make_session_key ( efx->cfx.dek ); - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("DEK is: ", efx->cfx.dek->key, efx->cfx.dek->keylen); rc = write_pubkey_enc_from_list (efx->pk_list, efx->cfx.dek, a); diff --git a/g10/getkey.c b/g10/getkey.c index 30c454b..20b37d8 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -37,7 +37,7 @@ #include "keyserver-internal.h" #include "call-agent.h" #include "host2net.h" - +#include "mbox-util.h" #define MAX_PK_CACHE_ENTRIES PK_UID_CACHE_SIZE #define MAX_UID_CACHE_ENTRIES PK_UID_CACHE_SIZE @@ -116,7 +116,7 @@ print_stats () for (i = 0; i < DIM (lkup_stats); i++) { if (lkup_stats[i].any) - fprintf (stderr, + es_fprintf (es_stderr, "lookup stats: mode=%-2d ok=%-6d nokey=%-6d err=%-6d\n", i, lkup_stats[i].okay_count, @@ -2373,7 +2373,7 @@ finish_lookup (GETKEY_CTX ctx) } } - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("finish_lookup: checking key %08lX (%s)(req_usage=%x)\n", (ulong) keyid_from_pk (keyblock->pkt->pkt.public_key, NULL), foundk ? "one" : "all", req_usage); @@ -2400,43 +2400,43 @@ finish_lookup (GETKEY_CTX ctx) if (foundk) nextk = NULL; /* what a hack */ pk = k->pkt->pkt.public_key; - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tchecking subkey %08lX\n", (ulong) keyid_from_pk (pk, NULL)); if (!pk->flags.valid) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tsubkey not valid\n"); continue; } if (pk->flags.revoked) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tsubkey has been revoked\n"); continue; } if (pk->has_expired) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tsubkey has expired\n"); continue; } if (pk->timestamp > curtime && !opt.ignore_valid_from) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tsubkey not yet valid\n"); continue; } if (!((pk->pubkey_usage & USAGE_MASK) & req_usage)) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tusage does not match: want=%x have=%x\n", req_usage, pk->pubkey_usage); continue; } - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tsubkey might be fine\n"); /* In case a key has a timestamp of 0 set, we make sure that it is used. A better change would be to compare @@ -2455,33 +2455,33 @@ finish_lookup (GETKEY_CTX ctx) if ((!latest_key && !(ctx->exact && foundk != keyblock)) || req_prim) { PKT_public_key *pk; - if (DBG_CACHE && !foundk && !req_prim) + if (DBG_LOOKUP && !foundk && !req_prim) log_debug ("\tno suitable subkeys found - trying primary\n"); pk = keyblock->pkt->pkt.public_key; if (!pk->flags.valid) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tprimary key not valid\n"); } else if (pk->flags.revoked) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tprimary key has been revoked\n"); } else if (pk->has_expired) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tprimary key has expired\n"); } else if (!((pk->pubkey_usage & USAGE_MASK) & req_usage)) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tprimary key usage does not match: " "want=%x have=%x\n", req_usage, pk->pubkey_usage); } else /* Okay. */ { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tprimary key may be used\n"); latest_key = keyblock; latest_date = pk->timestamp; @@ -2490,13 +2490,13 @@ finish_lookup (GETKEY_CTX ctx) if (!latest_key) { - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tno suitable key found - giving up\n"); return 0; /* Not found. */ } found: - if (DBG_CACHE) + if (DBG_LOOKUP) log_debug ("\tusing key %08lX\n", (ulong) keyid_from_pk (latest_key->pkt->pkt.public_key, NULL)); @@ -2525,6 +2525,29 @@ found: } +/* Return true if all the search modes are fingerprints. */ +static int +search_modes_are_fingerprint (getkey_ctx_t ctx) +{ + size_t n, found; + + for (n=found=0; n < ctx->nitems; n++) + { + switch (ctx->items[n].mode) + { + case KEYDB_SEARCH_MODE_FPR16: + case KEYDB_SEARCH_MODE_FPR20: + case KEYDB_SEARCH_MODE_FPR: + found++; + break; + default: + break; + } + } + return found && found == ctx->nitems; +} + + /* The main function to lookup a key. On success the found keyblock is stored at RET_KEYBLOCK and also in CTX. If WANT_SECRET is true a corresponding secret key is required. */ @@ -2534,9 +2557,21 @@ lookup (getkey_ctx_t ctx, kbnode_t *ret_keyblock, int want_secret) int rc; int no_suitable_key = 0; - rc = 0; - while (!(rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems, NULL))) + for (;;) { + rc = keydb_search (ctx->kr_handle, ctx->items, ctx->nitems, NULL); + /* Skip over all legacy keys but only if they are not requested + by fingerprints. + Fixme: The lower level keydb code should actually do that but + then it would be harder to report the number of skipped + legacy keys during import. */ + if (gpg_err_code (rc) == GPG_ERR_LEGACY_KEY + && !(ctx->nitems && ctx->items->mode == KEYDB_SEARCH_MODE_FIRST) + && !search_modes_are_fingerprint (ctx)) + continue; + if (rc) + break; + /* If we are searching for the first key we have to make sure that the next iteration does not do an implicit reset. This can be triggered by an empty key ring. */ @@ -2719,34 +2754,69 @@ enum_secret_keys (void **context, PKT_public_key *sk) /* Return a string with a printable representation of the user_id. * this string must be freed by xfree. */ static char * -get_user_id_string (u32 * keyid) +get_user_id_string (u32 * keyid, int mode, size_t *r_len) { user_id_db_t r; + keyid_list_t a; int pass = 0; + char *p; + /* Try it two times; second pass reads from key resources. */ do { for (r = user_id_db; r; r = r->next) { - keyid_list_t a; for (a = r->keyids; a; a = a->next) { if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1]) { - return xasprintf ("%s %.*s", keystr (keyid), r->len, r->name); + if (mode == 2) + { + /* An empty string as user id is possible. Make + sure that the malloc allocates one byte and + does not bail out. */ + p = xmalloc (r->len? r->len : 1); + memcpy (p, r->name, r->len); + if (r_len) + *r_len = r->len; + } + else + { + if (mode) + p = xasprintf ("%08lX%08lX %.*s", + (ulong) keyid[0], (ulong) keyid[1], + r->len, r->name); + else + p = xasprintf ("%s %.*s", keystr (keyid), + r->len, r->name); + if (r_len) + *r_len = strlen (p); + } + + return p; } } } } while (++pass < 2 && !get_pubkey (NULL, keyid)); - return xasprintf ("%s [?]", keystr (keyid)); + + if (mode == 2) + p = xstrdup (user_id_not_found_utf8 ()); + else if (mode) + p = xasprintf ("%08lX%08lX [?]", (ulong) keyid[0], (ulong) keyid[1]); + else + p = xasprintf ("%s [?]", keystr (keyid)); + + if (r_len) + *r_len = strlen (p); + return p; } char * get_user_id_string_native (u32 * keyid) { - char *p = get_user_id_string (keyid); + char *p = get_user_id_string (keyid, 0, NULL); char *p2 = utf8_to_native (p, strlen (p), 0); xfree (p); return p2; @@ -2756,65 +2826,18 @@ get_user_id_string_native (u32 * keyid) char * get_long_user_id_string (u32 * keyid) { - user_id_db_t r; - keyid_list_t a; - int pass = 0; - /* Try it two times; second pass reads from key resources. */ - do - { - for (r = user_id_db; r; r = r->next) - { - for (a = r->keyids; a; a = a->next) - { - if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1]) - { - return xasprintf ("%08lX%08lX %.*s", - (ulong) keyid[0], (ulong) keyid[1], - r->len, r->name); - } - } - } - } - while (++pass < 2 && !get_pubkey (NULL, keyid)); - return xasprintf ("%08lX%08lX [?]", (ulong) keyid[0], (ulong) keyid[1]); + return get_user_id_string (keyid, 1, NULL); } -/* Please try to use get_user_id_native instead of this one. */ +/* Please try to use get_user_byfpr instead of this one. */ char * get_user_id (u32 * keyid, size_t * rn) { - user_id_db_t r; - char *p; - int pass = 0; - - /* Try it two times; second pass reads from key resources. */ - do - { - for (r = user_id_db; r; r = r->next) - { - keyid_list_t a; - for (a = r->keyids; a; a = a->next) - { - if (a->keyid[0] == keyid[0] && a->keyid[1] == keyid[1]) - { - /* An empty string as user id is possible. Make - sure that the malloc allocates one byte and does - not bail out. */ - p = xmalloc (r->len? r->len : 1); - memcpy (p, r->name, r->len); - *rn = r->len; - return p; - } - } - } - } - while (++pass < 2 && !get_pubkey (NULL, keyid)); - p = xstrdup (user_id_not_found_utf8 ()); - *rn = strlen (p); - return p; + return get_user_id_string (keyid, 2, rn); } + /* Please try to use get_user_id_byfpr_native instead of this one. */ char * get_user_id_native (u32 * keyid) @@ -2828,7 +2851,7 @@ get_user_id_native (u32 * keyid) /* Return a user id from the caching by looking it up using the FPR - which mustbe of size MAX_FINGERPRINT_LEN. */ + which must be of size MAX_FINGERPRINT_LEN. */ char * get_user_id_byfpr (const byte *fpr, size_t *rn) { @@ -2936,10 +2959,8 @@ parse_auto_key_locate (char *options) else if (ascii_strcasecmp (tok, "cert") == 0) akl->type = AKL_CERT; #endif -#ifdef USE_DNS_PKA else if (ascii_strcasecmp (tok, "pka") == 0) akl->type = AKL_PKA; -#endif else if ((akl->spec = parse_keyserver_uri (tok, 1))) akl->type = AKL_SPEC; else @@ -1,6 +1,7 @@ /* gpg.c - The GnuPG utility (main for gpg) * Copyright (C) 1998-2011 Free Software Foundation, Inc. * Copyright (C) 1997-2014 Werner Koch + * Copyright (C) 2015 g10 Code GmbH * * This file is part of GnuPG. * @@ -116,6 +117,7 @@ enum cmd_and_opt_values aQuickSignKey, aQuickLSignKey, aListConfig, + aListGcryptConfig, aGPGConfList, aGPGConfTest, aListPackets, @@ -176,6 +178,7 @@ enum cmd_and_opt_values oNoAskCertLevel, oFingerprint, oWithFingerprint, + oWithICAOSpelling, oWithKeygrip, oWithSecret, oAnswerYes, @@ -193,7 +196,7 @@ enum cmd_and_opt_values oDebug, oDebugLevel, oDebugAll, - oDebugCCIDDriver, + oDebugIOLBF, oStatusFD, oStatusFile, oAttributeFD, @@ -380,6 +383,7 @@ enum cmd_and_opt_values oAllowWeakDigestAlgos, oFakedSystemTime, oNoAutostart, + oPrintPKARecords, oNoop }; @@ -446,6 +450,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_c (aChangePIN, "change-pin", N_("change a card's PIN")), #endif ARGPARSE_c (aListConfig, "list-config", "@"), + ARGPARSE_c (aListGcryptConfig, "list-gcrypt-config", "@"), ARGPARSE_c (aGPGConfList, "gpgconf-list", "@" ), ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@" ), ARGPARSE_c (aListPackets, "list-packets","@"), @@ -552,6 +557,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_p_u (oDebug, "debug", "@"), ARGPARSE_s_s (oDebugLevel, "debug-level", "@"), ARGPARSE_s_n (oDebugAll, "debug-all", "@"), + ARGPARSE_s_n (oDebugIOLBF, "debug-iolbf", "@"), ARGPARSE_s_i (oStatusFD, "status-fd", "@"), ARGPARSE_s_s (oStatusFile, "status-file", "@"), ARGPARSE_s_i (oAttributeFD, "attribute-fd", "@"), @@ -692,6 +698,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oUtf8Strings, "utf8-strings", "@"), ARGPARSE_s_n (oNoUtf8Strings, "no-utf8-strings", "@"), ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"), + ARGPARSE_s_n (oWithICAOSpelling, "with-icao-spelling", "@"), ARGPARSE_s_n (oWithKeygrip, "with-keygrip", "@"), ARGPARSE_s_n (oWithSecret, "with-secret", "@"), ARGPARSE_s_s (oDisableCipherAlgo, "disable-cipher-algo", "@"), @@ -706,6 +713,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oFixedListMode, "fixed-list-mode", "@"), ARGPARSE_s_n (oLegacyListMode, "legacy-list-mode", "@"), ARGPARSE_s_n (oListOnly, "list-only", "@"), + ARGPARSE_s_n (oPrintPKARecords, "print-pka-records", "@"), ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"), ARGPARSE_s_n (oIgnoreValidFrom, "ignore-valid-from", "@"), ARGPARSE_s_n (oIgnoreCrcError, "ignore-crc-error", "@"), @@ -1038,7 +1046,7 @@ build_list (const char *text, char letter, static void wrong_args( const char *text) { - fprintf (stderr, _("usage: %s [options] %s\n"), GPG_NAME, text); + es_fprintf (es_stderr, _("usage: %s [options] %s\n"), GPG_NAME, text); g10_exit(2); } @@ -1086,7 +1094,7 @@ set_debug (const char *level) opt.debug = DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE; else if (!strcmp (level, "expert") || (numok && numlvl <= 8)) opt.debug = (DBG_MEMSTAT_VALUE|DBG_TRUST_VALUE|DBG_EXTPROG_VALUE - |DBG_CACHE_VALUE|DBG_FILTER_VALUE|DBG_PACKET_VALUE); + |DBG_CACHE_VALUE|DBG_LOOKUP|DBG_FILTER_VALUE|DBG_PACKET_VALUE); else if (!strcmp (level, "guru") || numok) { opt.debug = ~0; @@ -1109,17 +1117,17 @@ set_debug (const char *level) memory_stat_debug_mode = 1; if (opt.debug & DBG_MPI_VALUE) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 2); - if (opt.debug & DBG_CIPHER_VALUE ) + if (opt.debug & DBG_CRYPTO_VALUE ) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); if (opt.debug & DBG_IOBUF_VALUE ) iobuf_debug_mode = 1; gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose); if (opt.debug) - log_info ("enabled debug flags:%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + log_info ("enabled debug flags:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", (opt.debug & DBG_PACKET_VALUE )? " packet":"", (opt.debug & DBG_MPI_VALUE )? " mpi":"", - (opt.debug & DBG_CIPHER_VALUE )? " cipher":"", + (opt.debug & DBG_CRYPTO_VALUE )? " crypto":"", (opt.debug & DBG_FILTER_VALUE )? " filter":"", (opt.debug & DBG_IOBUF_VALUE )? " iobuf":"", (opt.debug & DBG_MEMORY_VALUE )? " memory":"", @@ -1129,8 +1137,9 @@ set_debug (const char *level) (opt.debug & DBG_HASHING_VALUE)? " hashing":"", (opt.debug & DBG_EXTPROG_VALUE)? " extprog":"", (opt.debug & DBG_CARD_IO_VALUE)? " cardio":"", - (opt.debug & DBG_ASSUAN_VALUE )? " assuan":"", - (opt.debug & DBG_CLOCK_VALUE )? " clock":""); + (opt.debug & DBG_IPC_VALUE )? " ipc":"", + (opt.debug & DBG_CLOCK_VALUE )? " clock":"", + (opt.debug & DBG_LOOKUP_VALUE )? " lookup":""); } @@ -1574,8 +1583,11 @@ print_algo_names(int (*checker)(int),const char *(*mapper)(int)) static void list_config(char *items) { - int show_all=(items==NULL); - char *name=NULL; + int show_all = !items; + char *name = NULL; + const char *s; + struct groupitem *giter; + int first, iter; if(!opt.with_colons) return; @@ -1586,18 +1598,16 @@ list_config(char *items) if(show_all || ascii_strcasecmp(name,"group")==0) { - struct groupitem *iter; - - for(iter=opt.grouplist;iter;iter=iter->next) + for (giter = opt.grouplist; giter; giter = giter->next) { strlist_t sl; es_fprintf (es_stdout, "cfg:group:"); - es_write_sanitized (es_stdout, iter->name, strlen(iter->name), + es_write_sanitized (es_stdout, giter->name, strlen(giter->name), ":", NULL); es_putc (':', es_stdout); - for(sl=iter->values;sl;sl=sl->next) + for(sl=giter->values; sl; sl=sl->next) { es_write_sanitized (es_stdout, sl->d, strlen (sl->d), ":;", NULL); @@ -1682,20 +1692,31 @@ list_config(char *items) any=1; } - if(show_all || ascii_strcasecmp(name,"ccid-reader-id")==0) + if (show_all || !ascii_strcasecmp(name,"ccid-reader-id")) { -#if defined(ENABLE_CARD_SUPPORT) && defined(HAVE_LIBUSB) \ - && GNUPG_MAJOR_VERSION == 1 + /* We ignore this for GnuPG 1.4 backward compatibility. */ + any=1; + } - char *p, *p2, *list = ccid_get_reader_list (); + if (show_all || !ascii_strcasecmp (name,"curve")) + { + es_printf ("cfg:curve:"); + for (iter=0, first=1; (s = openpgp_enum_curves (&iter)); first=0) + es_printf ("%s%s", first?"":";", s); + es_printf ("\n"); + any=1; + } - for (p=list; p && (p2 = strchr (p, '\n')); p = p2+1) + /* Curve OIDs are rarely useful and thus only printed if requested. */ + if (name && !ascii_strcasecmp (name,"curveoid")) + { + es_printf ("cfg:curveoid:"); + for (iter=0, first=1; (s = openpgp_enum_curves (&iter)); first = 0) { - *p2 = 0; - es_printf ("cfg:ccid-reader-id:%s\n", p); + s = openpgp_curve_to_oid (s, NULL); + es_printf ("%s%s", first?"":";", s? s:"[?]"); } - free (list); -#endif + es_printf ("\n"); any=1; } @@ -2138,6 +2159,8 @@ main (int argc, char **argv) while( arg_parse( &pargs, opts) ) { if( pargs.r_opt == oDebug || pargs.r_opt == oDebugAll ) parse_debug++; + else if (pargs.r_opt == oDebugIOLBF) + es_setvbuf (es_stdout, NULL, _IOLBF, 0); else if( pargs.r_opt == oOptions ) { /* yes there is one, so we do not try the default one, but * read the option file when it is encountered at the commandline @@ -2261,6 +2284,7 @@ main (int argc, char **argv) { case aCheckKeys: case aListConfig: + case aListGcryptConfig: case aGPGConfList: case aGPGConfTest: case aListPackets: @@ -2398,6 +2422,8 @@ main (int argc, char **argv) case oDebugAll: opt.debug = ~0; break; case oDebugLevel: debug_level = pargs.r.ret_str; break; + case oDebugIOLBF: break; /* Already set in pre-parse step. */ + case oStatusFD: set_status_fd ( translate_sys2libc_fd_int (pargs.r.ret_int, 1) ); break; @@ -2421,6 +2447,9 @@ main (int argc, char **argv) opt.with_fingerprint = 1; opt.fingerprint++; break; + case oWithICAOSpelling: + opt.with_icao_spelling = 1; + break; case oFingerprint: opt.fingerprint++; fpr_maybe_cmd = 1; @@ -2807,7 +2836,13 @@ main (int argc, char **argv) log_error (_("could not parse keyserver URL\n")); else { - keyserver->next = opt.keyserver; + /* We only support a single keyserver. Later ones + override earlier ones. (Since we parse the + config file first and then the command line + arguments, the command line takes + precedence.) */ + if (opt.keyserver) + free_keyserver_spec (opt.keyserver); opt.keyserver = keyserver; } } @@ -2947,6 +2982,7 @@ main (int argc, char **argv) case oFastListMode: opt.fast_list_mode = 1; break; case oFixedListMode: /* Dummy */ break; case oLegacyListMode: opt.legacy_list_mode = 1; break; + case oPrintPKARecords: opt.print_pka_records = 1; break; case oListOnly: opt.list_only=1; break; case oIgnoreTimeConflict: opt.ignore_time_conflict = 1; break; case oIgnoreValidFrom: opt.ignore_valid_from = 1; break; @@ -4021,7 +4057,7 @@ main (int argc, char **argv) mpi_print (es_stdout, generate_elg_prime( 1, atoi(argv[1]), atoi(argv[2]), NULL,&factors ), 1); - putchar('\n'); + es_putc ('\n', es_stdout); mpi_print (es_stdout, factors[0], 1 ); /* print q */ } else if( mode == 4 && argc == 3 ) { @@ -4029,13 +4065,13 @@ main (int argc, char **argv) mpi_print (es_stdout, generate_elg_prime( 0, atoi(argv[1]), atoi(argv[2]), g, NULL ), 1); - putchar('\n'); + es_putc ('\n', es_stdout); mpi_print (es_stdout, g, 1 ); mpi_free (g); } else wrong_args("--gen-prime mode bits [qbits] "); - putchar('\n'); + es_putc ('\n', es_stdout); } #endif wrong_args("--gen-prime not yet supported "); @@ -4064,21 +4100,21 @@ main (int argc, char **argv) #endif if (opt.armor) { char *tmp = make_radix64_string (p, n); - fputs (tmp, stdout); + es_fputs (tmp, es_stdout); xfree (tmp); if (n%3 == 1) - putchar ('='); + es_putc ('=', es_stdout); if (n%3) - putchar ('='); + es_putc ('=', es_stdout); } else { - fwrite( p, n, 1, stdout ); + es_fwrite( p, n, 1, es_stdout ); } xfree(p); if( !endless ) count -= n; } if (opt.armor) - putchar ('\n'); + es_putc ('\n', es_stdout); } break; @@ -4203,6 +4239,13 @@ main (int argc, char **argv) } break; + case aListGcryptConfig: + /* Fixme: It would be nice to integrate that with + --list-config but unfortunately there is no way yet to have + libgcrypt print it to an estream for further parsing. */ + gcry_control (GCRYCTL_PRINT_CONFIG, stdout); + break; + case aListPackets: opt.list_packets=2; default: @@ -4298,7 +4341,7 @@ print_hex (gcry_md_hd_t md, int algo, const char *fname) if (indent>40) { - printf("\n"); + es_printf ("\n"); indent=0; } @@ -4396,24 +4439,22 @@ print_hashline( gcry_md_hd_t md, int algo, const char *fname ) static void print_mds( const char *fname, int algo ) { - FILE *fp; + estream_t fp; char buf[1024]; size_t n; gcry_md_hd_t md; if (!fname) { - fp = stdin; -#ifdef HAVE_DOSISH_SYSTEM - setmode ( fileno(fp) , O_BINARY ); -#endif + fp = es_stdin; + es_set_binary (fp); } else { - fp = fopen (fname, "rb" ); - if (fp && is_secured_file (fileno (fp))) + fp = es_fopen (fname, "rb" ); + if (fp && is_secured_file (es_fileno (fp))) { - fclose (fp); + es_fclose (fp); fp = NULL; gpg_err_set_errno (EPERM); } @@ -4444,10 +4485,10 @@ print_mds( const char *fname, int algo ) gcry_md_enable (md, GCRY_MD_SHA512); } - while ((n=fread (buf, 1, DIM(buf), fp))) + while ((n=es_fread (buf, 1, DIM(buf), fp))) gcry_md_write (md, buf, n); - if (ferror(fp)) + if (es_ferror(fp)) log_error ("%s: %s\n", fname?fname:"[stdin]", strerror(errno)); else { @@ -4497,8 +4538,8 @@ print_mds( const char *fname, int algo ) } gcry_md_close (md); - if (fp != stdin) - fclose (fp); + if (fp != es_stdin) + es_fclose (fp); } diff --git a/g10/keydb.c b/g10/keydb.c index cf422a8..040ca65 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -369,10 +369,18 @@ keydb_add_resource (const char *url, unsigned int flags) } #endif /* !HAVE_DRIVE_LETTERS && !__riscos__ */ - if (*resname != DIRSEP_C ) + if (*resname != DIRSEP_C +#ifdef HAVE_W32_SYSTEM + && *resname != '/' /* Fixme: does not handle drive letters. */ +#endif + ) { /* Do tilde expansion etc. */ - if (strchr(resname, DIRSEP_C) ) + if (strchr (resname, DIRSEP_C) +#ifdef HAVE_W32_SYSTEM + || strchr (resname, '/') /* Windows also accepts this. */ +#endif + ) filename = make_filename (resname, NULL); else filename = make_filename (opt.homedir, resname, NULL); diff --git a/g10/keyedit.c b/g10/keyedit.c index f283e55..2f9469f 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -158,23 +158,23 @@ print_and_check_one_sig_colon (KBNODE keyblock, KBNODE node, if (sigrc != '?' || print_without_key) { - printf ("sig:%c::%d:%08lX%08lX:%lu:%lu:", - sigrc, sig->pubkey_algo, (ulong) sig->keyid[0], - (ulong) sig->keyid[1], (ulong) sig->timestamp, - (ulong) sig->expiredate); + es_printf ("sig:%c::%d:%08lX%08lX:%lu:%lu:", + sigrc, sig->pubkey_algo, (ulong) sig->keyid[0], + (ulong) sig->keyid[1], (ulong) sig->timestamp, + (ulong) sig->expiredate); if (sig->trust_depth || sig->trust_value) - printf ("%d %d", sig->trust_depth, sig->trust_value); + es_printf ("%d %d", sig->trust_depth, sig->trust_value); - printf (":"); + es_printf (":"); if (sig->trust_regexp) es_write_sanitized (es_stdout, sig->trust_regexp, strlen (sig->trust_regexp), ":", NULL); - printf ("::%02x%c\n", sig->sig_class, - sig->flags.exportable ? 'x' : 'l'); + es_printf ("::%02x%c\n", sig->sig_class, + sig->flags.exportable ? 'x' : 'l'); if (opt.show_subpackets) print_subpackets_colon (sig); @@ -1450,6 +1450,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, char *answer = NULL; int redisplay = 1; int modified = 0; + int sec_shadowing = 0; int run_subkey_warnings = 0; int toggle; int have_commands = !!commands; @@ -1836,8 +1837,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, if (card_store_subkey (node, xxpk ? xxpk->pubkey_usage : 0)) { redisplay = 1; - /* Only the secret key has been modified; thus - there is no need to set the modified flag. */ + sec_shadowing = 1; } } } @@ -1923,7 +1923,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, if (card_store_subkey (node, 0)) { redisplay = 1; - /* FIXME:sec_modified = 1;*/ + sec_shadowing = 1; } } release_kbnode (node); @@ -2182,7 +2182,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, case cmdQUIT: if (have_commands) goto leave; - if (!modified) + if (!modified && !sec_shadowing) goto leave; if (!cpr_get_answer_is_yes ("keyedit.save.okay", _("Save changes? (y/N) "))) @@ -2204,7 +2204,18 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, break; } } - else + + if (sec_shadowing) + { + err = agent_scd_learn (NULL, 1); + if (err) + { + log_error (_("update failed: %s\n"), gpg_strerror (err)); + break; + } + } + + if (!modified && !sec_shadowing) tty_printf (_("Key not changed so no update needed.\n")); if (update_trust) @@ -4735,11 +4746,11 @@ ask_revoke_sig (KBNODE keyblock, KBNODE node) printf ("uat:::::::::%u %lu", uid->numattribs, uid->attrib_len); else { - printf ("uid:::::::::"); + es_printf ("uid:::::::::"); es_write_sanitized (es_stdout, uid->name, uid->len, ":", NULL); } - printf ("\n"); + es_printf ("\n"); print_and_check_one_sig_colon (keyblock, node, NULL, NULL, NULL, NULL, 1); diff --git a/g10/keygen.c b/g10/keygen.c index 11bfbd4..ccd01f9 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -44,6 +44,7 @@ #include "pkglue.h" #include "../common/shareddefs.h" #include "host2net.h" +#include "mbox-util.h" /* The default algorithms. If you change them remember to change them @@ -4151,7 +4152,7 @@ do_generate_keypair (struct para_data_s *para, { tty_printf (_("public and secret key created and signed.\n") ); tty_printf ("\n"); - list_keyblock (pub_root, 0, 1, 1, NULL); + list_keyblock_direct (pub_root, 0, 1, 1); } @@ -4486,7 +4487,7 @@ gen_card_key (int algo, int keyno, int is_primary, kbnode_t pub_root, /* Send the learn command so that the agent creates a shadow key for card key. We need to do that now so that we are able to create the self-signatures. */ - err = agent_scd_learn (NULL); + err = agent_scd_learn (NULL, 0); if (err) { /* Oops: Card removed during generation. */ diff --git a/g10/keyid.c b/g10/keyid.c index 9f7b70f..a0571b0 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -179,7 +179,10 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) p = gcry_mpi_get_opaque (pk->pkey[i], &nbits); pp[i] = xmalloc ((nbits+7)/8); - memcpy (pp[i], p, (nbits+7)/8); + if (p) + memcpy (pp[i], p, (nbits+7)/8); + else + pp[i] = NULL; nn[i] = (nbits+7)/8; n += nn[i]; } @@ -214,14 +217,18 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) if(npkey==0 && pk->pkey[0] && gcry_mpi_get_flag (pk->pkey[0], GCRYMPI_FLAG_OPAQUE)) { - gcry_md_write (md, pp[0], nn[0]); + if (pp[0]) + gcry_md_write (md, pp[0], nn[0]); } else - for(i=0; i < npkey; i++ ) - { - gcry_md_write ( md, pp[i], nn[i] ); - xfree(pp[i]); - } + { + for(i=0; i < npkey; i++ ) + { + if (pp[i]) + gcry_md_write ( md, pp[i], nn[i] ); + xfree(pp[i]); + } + } } diff --git a/g10/keylist.c b/g10/keylist.c index 5fd9eb8..d62bc20 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -42,23 +42,39 @@ #include "i18n.h" #include "status.h" #include "call-agent.h" +#include "mbox-util.h" + static void list_all (int, int); static void list_one (strlist_t names, int secret, int mark_secret); static void locate_one (ctrl_t ctrl, strlist_t names); static void print_card_serialno (const char *serialno); -struct sig_stats +struct keylist_context { - int inv_sigs; - int no_key; - int oth_err; + int check_sigs; /* If set signatures shall be verified. */ + int inv_sigs; /* Counter used if CHECK_SIGS is set. */ + int no_key; /* Counter used if CHECK_SIGS is set. */ + int oth_err; /* Counter used if CHECK_SIGS is set. */ }; + +static void list_keyblock (kbnode_t keyblock, int secret, int has_secret, + int fpr, struct keylist_context *listctx); + + /* The stream used to write attribute packets to. */ static estream_t attrib_fp; +/* Release resources from a keylist context. */ +static void +keylist_context_release (struct keylist_context *listctx) +{ + (void)listctx; /* Nothing to release. */ +} + + /* List the keys. If list is NULL, all available keys are listed. With LOCATE_MODE set the locate algorithm is used to find a key. */ @@ -414,9 +430,13 @@ show_notation (PKT_signature * sig, int indent, int mode, int which) free_notation (notations); } + static void -print_signature_stats (struct sig_stats *s) +print_signature_stats (struct keylist_context *s) { + if (!s->check_sigs) + return; /* Signature checking was not requested. */ + if (s->inv_sigs == 1) tty_printf (_("1 bad signature\n")); else if (s->inv_sigs) @@ -444,9 +464,11 @@ list_all (int secret, int mark_secret) int rc = 0; int any_secret; const char *lastresname, *resname; - struct sig_stats stats; + struct keylist_context listctx; - memset (&stats, 0, sizeof (stats)); + memset (&listctx, 0, sizeof (listctx)); + if (opt.check_sigs) + listctx.check_sigs = 1; hd = keydb_new (); if (!hd) @@ -497,7 +519,7 @@ list_all (int secret, int mark_secret) } merge_keys_and_selfsig (keyblock); list_keyblock (keyblock, secret, any_secret, opt.fingerprint, - opt.check_sigs ? &stats : NULL); + &listctx); } release_kbnode (keyblock); keyblock = NULL; @@ -511,9 +533,10 @@ list_all (int secret, int mark_secret) keydb_get_skipped_counter (hd)); if (opt.check_sigs && !opt.with_colons) - print_signature_stats (&stats); + print_signature_stats (&listctx); -leave: + leave: + keylist_context_release (&listctx); release_kbnode (keyblock); keydb_release (hd); } @@ -528,9 +551,11 @@ list_one (strlist_t names, int secret, int mark_secret) const char *resname; const char *keyring_str = _("Keyring"); int i; - struct sig_stats stats; + struct keylist_context listctx; - memset (&stats, 0, sizeof (stats)); + memset (&listctx, 0, sizeof (listctx)); + if (!secret && opt.check_sigs) + listctx.check_sigs = 1; /* fixme: using the bynames function has the disadvantage that we * don't know wether one of the names given was not found. OTOH, @@ -559,15 +584,16 @@ list_one (strlist_t names, int secret, int mark_secret) es_putc ('-', es_stdout); es_putc ('\n', es_stdout); } - list_keyblock (keyblock, secret, mark_secret, opt.fingerprint, - (!secret && opt.check_sigs)? &stats : NULL); + list_keyblock (keyblock, secret, mark_secret, opt.fingerprint, &listctx); release_kbnode (keyblock); } while (!getkey_next (ctx, NULL, &keyblock)); getkey_end (ctx); if (opt.check_sigs && !opt.with_colons) - print_signature_stats (&stats); + print_signature_stats (&listctx); + + keylist_context_release (&listctx); } @@ -578,9 +604,11 @@ locate_one (ctrl_t ctrl, strlist_t names) strlist_t sl; GETKEY_CTX ctx = NULL; KBNODE keyblock = NULL; - struct sig_stats stats; + struct keylist_context listctx; - memset (&stats, 0, sizeof (stats)); + memset (&listctx, 0, sizeof (listctx)); + if (opt.check_sigs) + listctx.check_sigs = 1; for (sl = names; sl; sl = sl->next) { @@ -594,8 +622,7 @@ locate_one (ctrl_t ctrl, strlist_t names) { do { - list_keyblock (keyblock, 0, 0, opt.fingerprint, - opt.check_sigs ? &stats : NULL); + list_keyblock (keyblock, 0, 0, opt.fingerprint, &listctx); release_kbnode (keyblock); } while (ctx && !get_pubkey_next (ctx, NULL, &keyblock)); @@ -605,7 +632,9 @@ locate_one (ctrl_t ctrl, strlist_t names) } if (opt.check_sigs && !opt.with_colons) - print_signature_stats (&stats); + print_signature_stats (&listctx); + + keylist_context_release (&listctx); } @@ -794,14 +823,86 @@ dump_attribs (const PKT_user_id *uid, PKT_public_key *pk) } +/* Print IPGP cert records instead of a standard key listing. */ static void -list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) +list_keyblock_pka (kbnode_t keyblock) +{ + kbnode_t kbctx; + kbnode_t node; + PKT_public_key *pk; + char pkstrbuf[PUBKEY_STRING_SIZE]; + char *hexfpr; + + /* Get the keyid from the keyblock. */ + node = find_kbnode (keyblock, PKT_PUBLIC_KEY); + if (!node) + { + log_error ("Oops; key lost!\n"); + dump_kbnode (keyblock); + return; + } + + pk = node->pkt->pkt.public_key; + + es_fprintf (es_stdout, ";; pub %s/%s %s\n;; ", + pubkey_string (pk, pkstrbuf, sizeof pkstrbuf), + keystr_from_pk (pk), datestr_from_pk (pk)); + print_fingerprint (NULL, pk, 10); + hexfpr = hexfingerprint (pk); + + for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));) + { + if (node->pkt->pkttype == PKT_USER_ID) + { + PKT_user_id *uid = node->pkt->pkt.user_id; + char *mbox; + char *p; + + if (pk && (uid->is_expired || uid->is_revoked) + && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS)) + continue; + + es_fputs (";; uid ", es_stdout); + print_utf8_buffer (es_stdout, uid->name, uid->len); + es_putc ('\n', es_stdout); + mbox = mailbox_from_userid (uid->name); + if (mbox && (p = strchr (mbox, '@'))) + { + char hashbuf[20]; + char *hash; + unsigned int len; + + *p++ = 0; + es_fprintf (es_stdout, "$ORIGIN _pka.%s.\n", p); + gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, mbox, strlen (mbox)); + hash = zb32_encode (hashbuf, 8*20); + if (hash) + { + len = strlen (hexfpr)/2; + es_fprintf (es_stdout, + "%s TYPE37 \\# %u 0006 0000 00 %02X %s\n", + hash, 6 + len, len, hexfpr); + xfree (hash); + } + } + xfree (mbox); + } + + } + es_putc ('\n', es_stdout); + + xfree (hexfpr); +} + + +static void +list_keyblock_print (KBNODE keyblock, int secret, int fpr, + struct keylist_context *listctx) { int rc; KBNODE kbctx; KBNODE node; PKT_public_key *pk; - struct sig_stats *stats = opaque; int skip_sigs = 0; int s2k_char; char *hexgrip = NULL; @@ -897,11 +998,11 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));) { - if (node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode) + if (node->pkt->pkttype == PKT_USER_ID) { PKT_user_id *uid = node->pkt->pkt.user_id; - if (pk && (uid->is_expired || uid->is_revoked) + if ((uid->is_expired || uid->is_revoked) && !(opt.list_options & LIST_SHOW_UNUSABLE_UIDS)) { skip_sigs = 1; @@ -914,7 +1015,7 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) dump_attribs (uid, pk); if ((uid->is_revoked || uid->is_expired) - || ((opt.list_options & LIST_SHOW_UID_VALIDITY) && pk)) + || (opt.list_options & LIST_SHOW_UID_VALIDITY)) { const char *validity; int indent; @@ -1029,7 +1130,7 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) int sigrc; char *sigstr; - if (stats) + if (listctx->check_sigs) { rc = check_key_signature (keyblock, node, NULL); switch (gpg_err_code (rc)) @@ -1038,15 +1139,15 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) sigrc = '!'; break; case GPG_ERR_BAD_SIGNATURE: - stats->inv_sigs++; + listctx->inv_sigs++; sigrc = '-'; break; case GPG_ERR_NO_PUBKEY: case GPG_ERR_UNUSABLE_PUBKEY: - stats->no_key++; + listctx->no_key++; continue; default: - stats->oth_err++; + listctx->oth_err++; sigrc = '%'; break; } @@ -1269,7 +1370,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int has_secret, int fpr) for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));) { - if (node->pkt->pkttype == PKT_USER_ID && !opt.fast_list_mode) + if (node->pkt->pkttype == PKT_USER_ID) { char *str; PKT_user_id *uid = node->pkt->pkt.user_id; @@ -1290,7 +1391,7 @@ list_keyblock_colon (KBNODE keyblock, int secret, int has_secret, int fpr) { int uid_validity; - if (pk && !ulti_hack) + if (!ulti_hack) uid_validity = get_validity_info (pk, uid); else uid_validity = 'u'; @@ -1567,25 +1668,54 @@ reorder_keyblock (KBNODE keyblock) do_reorder_keyblock (keyblock, 0); } -void +static void list_keyblock (KBNODE keyblock, int secret, int has_secret, int fpr, - void *opaque) + struct keylist_context *listctx) { reorder_keyblock (keyblock); - if (opt.with_colons) + if (opt.print_pka_records) + list_keyblock_pka (keyblock); + else if (opt.with_colons) list_keyblock_colon (keyblock, secret, has_secret, fpr); else - list_keyblock_print (keyblock, secret, fpr, opaque); + list_keyblock_print (keyblock, secret, fpr, listctx); if (secret) es_fflush (es_stdout); } + +/* Public function used by keygen to list a keyblock. */ +void +list_keyblock_direct (kbnode_t keyblock, int secret, int has_secret, int fpr) +{ + struct keylist_context listctx; + + memset (&listctx, 0, sizeof (listctx)); + list_keyblock (keyblock, secret, has_secret, fpr, &listctx); + keylist_context_release (&listctx); +} + + +/* Print an hex digit in ICAO spelling. */ +static void +print_icao_hexdigit (estream_t fp, int c) +{ + static const char *list[16] = { + "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", + "Eight", "Niner", "Alfa", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot" + }; + + tty_fprintf (fp, "%s", list[c&15]); +} + + /* * Function to print the finperprint. * mode 0: as used in key listings, opt.with_colons is honored * 1: print using log_info () * 2: direct use of tty * 3: direct use of tty but only primary key. + * 10: Same as 0 but with_colons etc is ignored. * * Modes 1 and 2 will try and print both subkey and primary key * fingerprints. A MODE with bit 7 set is used internally. If @@ -1600,6 +1730,15 @@ print_fingerprint (estream_t override_fp, PKT_public_key *pk, int mode) estream_t fp; const char *text; int primary = 0; + int with_colons = opt.with_colons; + int with_icao = opt.with_icao_spelling; + + if (mode == 10) + { + mode = 0; + with_colons = 0; + with_icao = 0; + } if (pk->main_keyid[0] == pk->keyid[0] && pk->main_keyid[1] == pk->keyid[1]) @@ -1653,7 +1792,7 @@ print_fingerprint (estream_t override_fp, PKT_public_key *pk, int mode) fingerprint_from_pk (pk, array, &n); p = array; - if (opt.with_colons && !mode) + if (with_colons && !mode) { es_fprintf (fp, "fpr:::::::::"); for (i = 0; i < n; i++, p++) @@ -1675,6 +1814,26 @@ print_fingerprint (estream_t override_fp, PKT_public_key *pk, int mode) } } tty_fprintf (fp, "\n"); + if (!with_colons && with_icao) + { + p = array; + tty_fprintf (fp, "%*s\"", (int)strlen(text)+1, ""); + for (i = 0; i < n; i++, p++) + { + if (!i) + ; + else if (!(i%4)) + tty_fprintf (fp, "\n%*s ", (int)strlen(text)+1, ""); + else if (!(i%2)) + tty_fprintf (fp, " "); + else + tty_fprintf (fp, " "); + print_icao_hexdigit (fp, *p >> 4); + tty_fprintf (fp, " "); + print_icao_hexdigit (fp, *p & 15); + } + tty_fprintf (fp, "\"\n"); + } } /* Print the serial number of an OpenPGP card if available. */ diff --git a/g10/keyserver.c b/g10/keyserver.c index 035cd03..7cac55e 100644 --- a/g10/keyserver.c +++ b/g10/keyserver.c @@ -1488,12 +1488,12 @@ keyserver_search (ctrl_t ctrl, strlist_t tokens) /* Write global options */ /* for(temp=opt.keyserver_options.other;temp;temp=temp->next) */ - /* fprintf(spawn->tochild,"OPTION %s\n",temp->d); */ + /* es_fprintf(spawn->tochild,"OPTION %s\n",temp->d); */ /* Write per-keyserver options */ /* for(temp=keyserver->options;temp;temp=temp->next) */ - /* fprintf(spawn->tochild,"OPTION %s\n",temp->d); */ + /* es_fprintf(spawn->tochild,"OPTION %s\n",temp->d); */ { membuf_t mb; @@ -1910,7 +1910,7 @@ keyserver_import_cert (ctrl_t ctrl, if(domain) *domain='.'; - err = get_dns_cert (look, &key, fpr, fpr_len, &url); + err = get_dns_cert (look, DNS_CERTTYPE_ANY, &key, fpr, fpr_len, &url); if (err) ; else if (key) @@ -1980,7 +1980,7 @@ keyserver_import_pka (ctrl_t ctrl, *fpr = xmalloc (20); *fpr_len = 20; - uri = get_pka_info (name, *fpr); + uri = get_pka_info (name, *fpr, 20); if (uri && *uri) { /* An URI is available. Lookup the key. */ @@ -1991,8 +1991,8 @@ keyserver_import_pka (ctrl_t ctrl, rc = keyserver_import_fprint (ctrl, *fpr, 20, spec); free_keyserver_spec (spec); } - xfree (uri); } + xfree (uri); if (rc) { @@ -162,9 +162,6 @@ char *optsep(char **stringp); char *argsplit(char *string); int parse_options(char *str,unsigned int *options, struct parse_options *opts,int noisy); -int has_invalid_email_chars (const char *s); -int is_valid_mailbox (const char *name); -int is_valid_user_id (const char *uid); const char *get_libexecdir (void); int path_access(const char *file,int mode); @@ -349,8 +346,8 @@ void public_key_list (ctrl_t ctrl, strlist_t list, int locate_mode ); void secret_key_list (ctrl_t ctrl, strlist_t list ); void print_subpackets_colon(PKT_signature *sig); void reorder_keyblock (KBNODE keyblock); -void list_keyblock (kbnode_t keyblock, int secret, int has_secret, - int fpr, void *opaque); +void list_keyblock_direct (kbnode_t keyblock, int secret, int has_secret, + int fpr); void print_fingerprint (estream_t fp, PKT_public_key *pk, int mode); void print_revokers (estream_t fp, PKT_public_key *pk); void show_policy_url(PKT_signature *sig,int indent,int mode); diff --git a/g10/mainproc.c b/g10/mainproc.c index 8ff84b7..0f6ba2b 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -39,6 +39,7 @@ #include "keyserver-internal.h" #include "photoid.h" #include "pka.h" +#include "mbox-util.h" /* Put an upper limit on nested packets. The 32 is an arbitrary @@ -930,15 +931,15 @@ print_userid (PACKET *pkt) if (pkt->pkttype != PKT_USER_ID) { - printf ("ERROR: unexpected packet type %d", pkt->pkttype ); + es_printf ("ERROR: unexpected packet type %d", pkt->pkttype ); return; } if (opt.with_colons) { if (pkt->pkt.user_id->attrib_data) - printf("%u %lu", - pkt->pkt.user_id->numattribs, - pkt->pkt.user_id->attrib_len); + es_printf("%u %lu", + pkt->pkt.user_id->numattribs, + pkt->pkt.user_id->attrib_len); else es_write_sanitized (es_stdout, pkt->pkt.user_id->name, pkt->pkt.user_id->len, ":", NULL); @@ -1497,7 +1498,8 @@ pka_uri_from_sig (PKT_signature *sig) { char *uri; - uri = get_pka_info (sig->pka_info->email, sig->pka_info->fpr); + uri = get_pka_info (sig->pka_info->email, + sig->pka_info->fpr, sizeof sig->pka_info->fpr); if (uri) { sig->pka_info->valid = 1; @@ -1668,6 +1670,8 @@ check_sig_and_print (CTX c, kbnode_t node) } } + write_status_text (STATUS_NEWSIG, NULL); + astr = openpgp_pk_algo_name ( sig->pubkey_algo ); if (keystrlen () > 8) { @@ -70,18 +70,6 @@ #include <assert.h> -static int -string_count_chr (const char *string, int c) -{ - int count; - - for (count=0; *string; string++ ) - if ( *string == c ) - count++; - return count; -} - - #ifdef ENABLE_SELINUX_HACKS /* A object and a global variable to keep track of files marked as @@ -1394,8 +1382,8 @@ parse_options(char *str,unsigned int *options, for(i=0;opts[i].name;i++) if(opts[i].help) - printf("%s%*s%s\n",opts[i].name, - maxlen+2-(int)strlen(opts[i].name),"",_(opts[i].help)); + es_printf("%s%*s%s\n",opts[i].name, + maxlen+2-(int)strlen(opts[i].name),"",_(opts[i].help)); g10_exit(0); } @@ -1464,69 +1452,6 @@ parse_options(char *str,unsigned int *options, } -/* Check whether the string has characters not valid in an RFC-822 - address. To cope with OpenPGP we ignore non-ascii characters - so that for example umlauts are legal in an email address. An - OpenPGP user ID must be utf-8 encoded but there is no strict - requirement for RFC-822. Thus to avoid IDNA encoding we put the - address verbatim as utf-8 into the user ID under the assumption - that mail programs handle IDNA at a lower level and take OpenPGP - user IDs as utf-8. Note that we can't do an utf-8 encoding - checking here because in keygen.c this function is called with the - native encoding and native to utf-8 encoding is only done later. */ -int -has_invalid_email_chars (const char *s) -{ - int at_seen=0; - const char *valid_chars= - "01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - for ( ; *s; s++ ) - { - if ( (*s & 0x80) ) - continue; /* We only care about ASCII. */ - if ( *s == '@' ) - at_seen=1; - else if ( !at_seen && !(strchr (valid_chars, *s) - || strchr ("!#$%&'*+/=?^`{|}~", *s))) - return 1; - else if ( at_seen && !strchr( valid_chars, *s ) ) - return 1; - } - return 0; -} - - -/* Check whether NAME represents a valid mailbox according to - RFC822. Returns true if so. */ -int -is_valid_mailbox (const char *name) -{ - return !( !name - || !*name - || has_invalid_email_chars (name) - || string_count_chr (name,'@') != 1 - || *name == '@' - || name[strlen(name)-1] == '@' - || name[strlen(name)-1] == '.' - || strstr (name, "..") ); -} - - -/* Check whether UID is a valid standard user id of the form - "Heinrich Heine <heinrichh@duesseldorf.de>" - and return true if this is the case. */ -int -is_valid_user_id (const char *uid) -{ - if (!uid || !*uid) - return 0; - - return 1; -} - - - /* Similar to access(2), but uses PATH to find the file. */ int path_access(const char *file,int mode) @@ -1711,7 +1636,8 @@ pubkey_nbits( int algo, gcry_mpi_t *key ) int mpi_print (estream_t fp, gcry_mpi_t a, int mode) { - int n=0; + int n = 0; + size_t nwritten; if (!a) return es_fprintf (fp, "[MPI_NULL]"); @@ -1729,19 +1655,19 @@ mpi_print (estream_t fp, gcry_mpi_t a, int mode) n += es_fprintf (fp, "[invalid opaque value]"); else { - nbits = (nbits + 7)/8; - for (; nbits; nbits--, p++) - n += es_fprintf (fp, "%02X", *p); + if (!es_write_hexstring (fp, p, (nbits + 7)/8, 0, &nwritten)) + n += nwritten; } } else { unsigned char *buffer; + size_t buflen; - if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, a)) + if (gcry_mpi_aprint (GCRYMPI_FMT_USG, &buffer, &buflen, a)) BUG (); - es_fputs (buffer, fp); - n += strlen (buffer); + if (!es_write_hexstring (fp, buffer, buflen, 0, &nwritten)) + n += nwritten; gcry_free (buffer); } return n; diff --git a/g10/options.h b/g10/options.h index 7b9f366..6c96d18 100644 --- a/g10/options.h +++ b/g10/options.h @@ -67,11 +67,13 @@ struct int check_sigs; /* check key signatures */ int with_colons; int with_key_data; + int with_icao_spelling; /* Print ICAO spelling with fingerprints. */ int with_fingerprint; /* Option --with-fingerprint active. */ int with_keygrip; /* Option --with-keygrip active. */ int with_secret; /* Option --with-secret active. */ int fingerprint; /* list fingerprints */ int list_sigs; /* list signatures */ + int print_pka_records; int no_armor; int list_packets; /* list-packets mode: 1=normal, 2=invoked by command*/ int def_cipher_algo; @@ -266,34 +268,34 @@ struct { #define DBG_PACKET_VALUE 1 /* debug packet reading/writing */ #define DBG_MPI_VALUE 2 /* debug mpi details */ -#define DBG_CIPHER_VALUE 4 /* debug cipher handling */ +#define DBG_CRYPTO_VALUE 4 /* debug crypto handling */ /* (may reveal sensitive data) */ #define DBG_FILTER_VALUE 8 /* debug internal filter handling */ #define DBG_IOBUF_VALUE 16 /* debug iobuf stuff */ #define DBG_MEMORY_VALUE 32 /* debug memory allocation stuff */ -#define DBG_CACHE_VALUE 64 /* debug the cacheing */ +#define DBG_CACHE_VALUE 64 /* debug the caching */ #define DBG_MEMSTAT_VALUE 128 /* show memory statistics */ #define DBG_TRUST_VALUE 256 /* debug the trustdb */ #define DBG_HASHING_VALUE 512 /* debug hashing operations */ -#define DBG_EXTPROG_VALUE 1024 /* debug external program calls */ +#define DBG_IPC_VALUE 1024 /* debug assuan communication */ #define DBG_CARD_IO_VALUE 2048 /* debug smart card I/O. */ #define DBG_CLOCK_VALUE 4096 - -/* Fixme: For now alias this value. */ -#define DBG_ASSUAN_VALUE DBG_EXTPROG_VALUE - +#define DBG_LOOKUP_VALUE 8192 /* debug the kety lookup */ +#define DBG_EXTPROG_VALUE 16384 /* debug external program calls */ /* Tests for the debugging flags. */ #define DBG_PACKET (opt.debug & DBG_PACKET_VALUE) -#define DBG_CIPHER (opt.debug & DBG_CIPHER_VALUE) +#define DBG_CRYPTO (opt.debug & DBG_CRYPTO_VALUE) #define DBG_FILTER (opt.debug & DBG_FILTER_VALUE) #define DBG_CACHE (opt.debug & DBG_CACHE_VALUE) #define DBG_TRUST (opt.debug & DBG_TRUST_VALUE) #define DBG_HASHING (opt.debug & DBG_HASHING_VALUE) -#define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE) +#define DBG_IPC (opt.debug & DBG_IPC_VALUE) #define DBG_CARD_IO (opt.debug & DBG_CARD_IO_VALUE) -#define DBG_ASSUAN (opt.debug & DBG_ASSUAN_VALUE) +#define DBG_IPC (opt.debug & DBG_IPC_VALUE) #define DBG_CLOCK (opt.debug & DBG_CLOCK_VALUE) +#define DBG_LOOKUP (opt.debug & DBG_LOOKUP_VALUE) +#define DBG_EXTPROG (opt.debug & DBG_EXTPROG_VALUE) /* FIXME: We need to check whey we did not put this into opt. */ #define DBG_MEMORY memory_debug_mode diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 6232086..c80b7df 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -112,7 +112,7 @@ read_32 (IOBUF inp) /* Read an external representation of an mpi and return the MPI. The * external format is a 16 bit unsigned value stored in network byte * order, giving the number of bits for the following integer. The - * integer is stored with MSB first (left padded with zeroes to align + * integer is stored with MSB first (left padded with zero bits to align * on a byte boundary). */ static gcry_mpi_t mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure) @@ -177,24 +177,38 @@ set_packet_list_mode (int mode) { int old = list_mode; list_mode = mode; - /* FIXME(gcrypt) mpi_print_mode = DBG_MPI; */ - /* We use stdout print only if invoked by the --list-packets command + + /* We use stdout only if invoked by the --list-packets command but switch to stderr in all other cases. This breaks the previous behaviour but that seems to be more of a bug than intentional. I don't believe that any application makes use of this long standing annoying way of printing to stdout except when doing a --list-packets. If this assumption fails, it will be easy to add an option for the listing stream. Note that we initialize - it only once; mainly because some code may switch the option - value later back to 1 and we want to have all output to the same - stream. + it only once; mainly because there is code which switches + opt.list_mode back to 1 and we want to have all output to the + same stream. The MPI_PRINT_MODE will be enabled if the + corresponding debug flag is set or if we are in --list-packets + and --verbose is given. Using stderr is not actually very clean because it bypasses the logging code but it is a special thing anyway. I am not sure whether using log_stream() would be better. Perhaps we should - enable the list mdoe only with a special option. */ + enable the list mode only with a special option. */ if (!listfp) - listfp = opt.list_packets == 2 ? es_stdout : es_stderr; + { + if (opt.list_packets == 2) + { + listfp = es_stdout; + if (opt.verbose) + mpi_print_mode = 1; + } + else + listfp = es_stderr; + + if (opt.debug && DBG_MPI_VALUE) + mpi_print_mode = 1; + } return old; } @@ -2089,6 +2103,12 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, byte temp[16]; size_t snlen = 0; + if (pktlen < 1) + { + err = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + pk->seckey_info = ski = xtrycalloc (1, sizeof *ski); if (!pk->seckey_info) { @@ -2289,6 +2309,12 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, } else if (ski->is_protected) { + if (pktlen < 2) /* At least two bytes for the length. */ + { + err = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + /* Ugly: The length is encrypted too, so we read all stuff * up to the end of the packet into the first SKEY * element. */ @@ -2309,7 +2335,14 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, /* Not encrypted. */ for (i = npkey; i < nskey; i++) { - unsigned int n = pktlen; + unsigned int n; + + if (pktlen < 2) /* At least two bytes for the length. */ + { + err = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + n = pktlen; pk->pkey[i] = mpi_read (inp, &n, 0); pktlen -= n; if (list_mode) @@ -2325,6 +2358,11 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, if (err) goto leave; + if (pktlen < 2) + { + err = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } ski->csum = read_16 (inp); pktlen -= 2; if (list_mode) diff --git a/g10/pkglue.c b/g10/pkglue.c index 684ce8a..d72275b 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -263,7 +263,7 @@ pk_encrypt (pubkey_algo_t algo, gcry_mpi_t *resarr, gcry_mpi_t data, public = get_mpi_from_sexp (s_ciph, "e", GCRYMPI_FMT_USG); gcry_sexp_release (s_ciph); s_ciph = NULL; - if (DBG_CIPHER) + if (DBG_CRYPTO) { log_debug ("ECDH ephemeral key:"); gcry_mpi_dump (public); diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 9574769..cb834af 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -227,7 +227,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) * DEK is the encryption key (session key) with length k * CSUM */ - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("DEK frame:", frame, nframe); n = 0; @@ -333,7 +333,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) } if (DBG_CLOCK) log_clock ("decryption ready"); - if (DBG_CIPHER) + if (DBG_CRYPTO) log_printhex ("DEK is:", dek->key, dek->keylen); /* Check that the algo is in the preferences and whether it has expired. */ diff --git a/g10/seskey.c b/g10/seskey.c index 410f0bf..e79faf8 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -82,7 +82,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits) u16 csum; gcry_mpi_t a; - if (DBG_CIPHER) + if (DBG_CRYPTO) log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen); csum = 0; @@ -116,7 +116,7 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits) memset (frame+n, i, i); /* Use it as the value of each padded byte. */ assert (n+i == nframe); - if (DBG_CIPHER) + if (DBG_CRYPTO) log_debug ("encode_session_key: " "[%d] %02x %02x %02x ... %02x %02x %02x\n", (int) nframe, frame[0], frame[1], frame[2], diff --git a/g10/sig-check.c b/g10/sig-check.c index 27c51fd..f8ba98b 100644 --- a/g10/sig-check.c +++ b/g10/sig-check.c @@ -427,7 +427,7 @@ check_revocation_keys(PKT_public_key *pk,PKT_signature *sig) busy=1; - /* printf("looking at %08lX with a sig from %08lX\n",(ulong)pk->keyid[1], + /* es_printf("looking at %08lX with a sig from %08lX\n",(ulong)pk->keyid[1], (ulong)sig->keyid[1]); */ /* is the issuer of the sig one of our revokers? */ @@ -1021,7 +1021,7 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr, } handle_progress (pfx, inp, sl->d); if( opt.verbose ) - fprintf(stderr, " '%s'", sl->d ); + log_printf (" '%s'", sl->d ); if(opt.textmode) { memset( &tfx, 0, sizeof tfx); @@ -1033,7 +1033,7 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr, iobuf_close(inp); inp = NULL; } if( opt.verbose ) - putc( '\n', stderr ); + log_printf ("\n"); } else { /* read, so that the filter can calculate the digest */ diff --git a/g10/tdbdump.c b/g10/tdbdump.c index c12e9b7..bf9f387 100644 --- a/g10/tdbdump.c +++ b/g10/tdbdump.c @@ -78,12 +78,12 @@ list_trustdb( const char *username ) ulong recnum; int i; - printf("TrustDB: %s\n", tdbio_get_dbname() ); + es_printf ("TrustDB: %s\n", tdbio_get_dbname() ); for(i=9+strlen(tdbio_get_dbname()); i > 0; i-- ) - putchar('-'); - putchar('\n'); + es_putc ('-', es_stdout); + es_putc ('\n', es_stdout); for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) - tdbio_dump_record( &rec, stdout ); + tdbio_dump_record (&rec, es_stdout); } } @@ -97,23 +97,25 @@ list_trustdb( const char *username ) void export_ownertrust() { - TRUSTREC rec; - ulong recnum; - int i; - byte *p; + TRUSTREC rec; + ulong recnum; + int i; + byte *p; - init_trustdb(); - printf(_("# List of assigned trustvalues, created %s\n" - "# (Use \"gpg --import-ownertrust\" to restore them)\n"), - asctimestamp( make_timestamp() ) ); - for(recnum=0; !tdbio_read_record( recnum, &rec, 0); recnum++ ) { - if( rec.rectype == RECTYPE_TRUST ) { - if( !rec.r.trust.ownertrust ) - continue; - p = rec.r.trust.fingerprint; - for(i=0; i < 20; i++, p++ ) - printf("%02X", *p ); - printf(":%u:\n", (unsigned int)rec.r.trust.ownertrust ); + init_trustdb(); + es_printf (_("# List of assigned trustvalues, created %s\n" + "# (Use \"gpg --import-ownertrust\" to restore them)\n"), + asctimestamp( make_timestamp() ) ); + for (recnum=0; !tdbio_read_record (recnum, &rec, 0); recnum++ ) + { + if (rec.rectype == RECTYPE_TRUST) + { + if (!rec.r.trust.ownertrust) + continue; + p = rec.r.trust.fingerprint; + for (i=0; i < 20; i++, p++ ) + es_printf("%02X", *p ); + es_printf (":%u:\n", (unsigned int)rec.r.trust.ownertrust ); } } } @@ -122,7 +124,7 @@ export_ownertrust() void import_ownertrust( const char *fname ) { - FILE *fp; + estream_t fp; int is_stdin=0; char line[256]; char *p; @@ -134,24 +136,24 @@ import_ownertrust( const char *fname ) init_trustdb(); if( iobuf_is_pipe_filename (fname) ) { - fp = stdin; + fp = es_stdin; fname = "[stdin]"; is_stdin = 1; } - else if( !(fp = fopen( fname, "r" )) ) { + else if( !(fp = es_fopen( fname, "r" )) ) { log_error ( _("can't open '%s': %s\n"), fname, strerror(errno) ); return; } - if (is_secured_file (fileno (fp))) + if (is_secured_file (es_fileno (fp))) { - fclose (fp); + es_fclose (fp); gpg_err_set_errno (EPERM); log_error (_("can't open '%s': %s\n"), fname, strerror(errno) ); return; } - while( fgets( line, DIM(line)-1, fp ) ) { + while (es_fgets (line, DIM(line)-1, fp)) { TRUSTREC rec; if( !*line || *line == '#' ) @@ -216,10 +218,10 @@ import_ownertrust( const char *fname ) log_error (_("error finding trust record in '%s': %s\n"), fname, gpg_strerror (rc)); } - if( ferror(fp) ) + if (es_ferror (fp)) log_error ( _("read error in '%s': %s\n"), fname, strerror(errno) ); - if( !is_stdin ) - fclose(fp); + if (!is_stdin) + es_fclose (fp); if (any) { diff --git a/g10/tdbio.c b/g10/tdbio.c index 91ee3ab..69438b4 100644 --- a/g10/tdbio.c +++ b/g10/tdbio.c @@ -1141,59 +1141,62 @@ update_trusthashtbl( TRUSTREC *tr ) void -tdbio_dump_record( TRUSTREC *rec, FILE *fp ) +tdbio_dump_record (TRUSTREC *rec, estream_t fp) { int i; ulong rnum = rec->recnum; - fprintf(fp, "rec %5lu, ", rnum ); + es_fprintf ( fp, "rec %5lu, ", rnum ); switch( rec->rectype ) { - case 0: fprintf(fp, "blank\n"); + case 0: + es_fprintf (fp, "blank\n"); break; - case RECTYPE_VER: fprintf(fp, - "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d mcl=%d nc=%lu (%s)\n", - rec->r.ver.trusthashtbl, - rec->r.ver.firstfree, - rec->r.ver.marginals, - rec->r.ver.completes, - rec->r.ver.cert_depth, - rec->r.ver.trust_model, - rec->r.ver.min_cert_level, - rec->r.ver.nextcheck, - strtimestamp(rec->r.ver.nextcheck) - ); + case RECTYPE_VER: + es_fprintf (fp, + "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d mcl=%d nc=%lu (%s)\n", + rec->r.ver.trusthashtbl, + rec->r.ver.firstfree, + rec->r.ver.marginals, + rec->r.ver.completes, + rec->r.ver.cert_depth, + rec->r.ver.trust_model, + rec->r.ver.min_cert_level, + rec->r.ver.nextcheck, + strtimestamp(rec->r.ver.nextcheck) + ); break; - case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next ); + case RECTYPE_FREE: + es_fprintf (fp, "free, next=%lu\n", rec->r.free.next ); break; case RECTYPE_HTBL: - fprintf(fp, "htbl,"); + es_fprintf (fp, "htbl,"); for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) - fprintf(fp, " %lu", rec->r.htbl.item[i] ); - putc('\n', fp); + es_fprintf (fp, " %lu", rec->r.htbl.item[i] ); + es_putc ('\n', fp); break; case RECTYPE_HLST: - fprintf(fp, "hlst, next=%lu,", rec->r.hlst.next ); + es_fprintf (fp, "hlst, next=%lu,", rec->r.hlst.next ); for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) - fprintf(fp, " %lu", rec->r.hlst.rnum[i] ); - putc('\n', fp); + es_fprintf (fp, " %lu", rec->r.hlst.rnum[i] ); + es_putc ('\n', fp); break; case RECTYPE_TRUST: - fprintf(fp, "trust "); + es_fprintf (fp, "trust "); for(i=0; i < 20; i++ ) - fprintf(fp, "%02X", rec->r.trust.fingerprint[i] ); - fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust, - rec->r.trust.depth, rec->r.trust.validlist); + es_fprintf (fp, "%02X", rec->r.trust.fingerprint[i] ); + es_fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust, + rec->r.trust.depth, rec->r.trust.validlist); break; case RECTYPE_VALID: - fprintf(fp, "valid "); + es_fprintf (fp, "valid "); for(i=0; i < 20; i++ ) - fprintf(fp, "%02X", rec->r.valid.namehash[i] ); - fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity, - rec->r.valid.next); + es_fprintf(fp, "%02X", rec->r.valid.namehash[i] ); + es_fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity, + rec->r.valid.next); break; default: - fprintf(fp, "unknown type %d\n", rec->rectype ); + es_fprintf (fp, "unknown type %d\n", rec->rectype ); break; } } diff --git a/g10/tdbio.h b/g10/tdbio.h index 4f37de4..d259518 100644 --- a/g10/tdbio.h +++ b/g10/tdbio.h @@ -95,7 +95,7 @@ typedef struct trust_record TRUSTREC; int tdbio_update_version_record(void); int tdbio_set_dbname( const char *new_dbname, int create, int *r_nofile); const char *tdbio_get_dbname(void); -void tdbio_dump_record( TRUSTREC *rec, FILE *fp ); +void tdbio_dump_record( TRUSTREC *rec, estream_t fp ); int tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected ); int tdbio_write_record( TRUSTREC *rec ); int tdbio_db_matches_options(void); diff --git a/g10/trustdb.c b/g10/trustdb.c index 08f6cf4..6145cf0 100644 --- a/g10/trustdb.c +++ b/g10/trustdb.c @@ -938,11 +938,13 @@ tdb_check_trustdb_stale (void) if (opt.no_auto_check_trustdb) { pending_check_trustdb = 1; - log_info (_("please do a --check-trustdb\n")); + if (!opt.quiet) + log_info (_("please do a --check-trustdb\n")); } else { - log_info (_("checking the trustdb\n")); + if (!opt.quiet) + log_info (_("checking the trustdb\n")); validate_keys (0); } } @@ -1068,7 +1070,7 @@ get_validity_counts (PKT_public_key *pk, PKT_user_id *uid) { uid->help_marginal_count=vrec.r.valid.marginal_count; uid->help_full_count=vrec.r.valid.full_count; - /* printf("Fetched marginal %d, full %d\n",uid->help_marginal_count,uid->help_full_count); */ + /* es_printf("Fetched marginal %d, full %d\n",uid->help_marginal_count,uid->help_full_count); */ break; } @@ -1197,8 +1199,8 @@ dump_key_array (int depth, struct key_array *keys) u32 kid[2]; keyid_from_pk(node->pkt->pkt.public_key, kid); - printf ("%d:%08lX%08lX:K::%c::::\n", - depth, (ulong)kid[0], (ulong)kid[1], '?'); + es_printf ("%d:%08lX%08lX:K::%c::::\n", + depth, (ulong)kid[0], (ulong)kid[1], '?'); for (; node; node = node->next) { @@ -1208,15 +1210,15 @@ dump_key_array (int depth, struct key_array *keys) if (len > 30) len = 30; - printf ("%d:%08lX%08lX:U:::%c:::", - depth, (ulong)kid[0], (ulong)kid[1], - (node->flag & 4)? 'f': - (node->flag & 2)? 'm': - (node->flag & 1)? 'q':'-'); + es_printf ("%d:%08lX%08lX:U:::%c:::", + depth, (ulong)kid[0], (ulong)kid[1], + (node->flag & 4)? 'f': + (node->flag & 2)? 'm': + (node->flag & 1)? 'q':'-'); es_write_sanitized (es_stdout, node->pkt->pkt.user_id->name, len, ":", NULL); - putchar (':'); - putchar ('\n'); + es_putc (':', es_stdout); + es_putc ('\n', es_stdout); } } } |