Fix use of strncpy, which is actually good to use memcpy.
[gnupg.git] / g10 / pkclist.c
index de8897a..46258bf 100644 (file)
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include "gpg.h"
 #include "options.h"
 #include "packet.h"
-#include "status.h"
+#include "../common/status.h"
 #include "keydb.h"
-#include "util.h"
+#include "../common/util.h"
 #include "main.h"
 #include "trustdb.h"
-#include "ttyio.h"
-#include "status.h"
+#include "../common/ttyio.h"
+#include "../common/status.h"
 #include "photoid.h"
-#include "i18n.h"
+#include "../common/i18n.h"
 #include "tofu.h"
 
 #define CONTROL_D ('D' - 'A' + 1)
@@ -110,10 +110,10 @@ do_show_revocation_reason( PKT_signature *sig )
    subkeys, etc.)  Mode 1: use only the revocation on the main pk */
 
 void
-show_revocation_reason( PKT_public_key *pk, int mode )
+show_revocation_reason (ctrl_t ctrl, PKT_public_key *pk, int mode)
 {
     /* Hmmm, this is not so easy because we have to duplicate the code
-     * used in the trustbd to calculate the keyflags.  We need to find
+     * used in the trustdb to calculate the keyflags.  We need to find
      * a clean way to check revocation certificates on keys and
      * signatures.  And there should be no duplicate code.  Because we
      * enter this function only when the trustdb told us that we have
@@ -127,7 +127,7 @@ show_revocation_reason( PKT_public_key *pk, int mode )
 
     /* get the keyblock */
     fingerprint_from_pk( pk, fingerprint, &fingerlen );
-    rc = get_pubkey_byfprint(NULL, &keyblock, fingerprint, fingerlen);
+    rc = get_pubkey_byfprint (ctrl, NULL, &keyblock, fingerprint, fingerlen);
     if( rc ) { /* that should never happen */
        log_debug( "failed to get the keyblock\n");
        return;
@@ -160,7 +160,7 @@ show_revocation_reason( PKT_public_key *pk, int mode )
 
     /* We didn't find it, so check if the whole key is revoked */
     if(!node && !mode)
-      show_revocation_reason(pk,1);
+      show_revocation_reason (ctrl, pk, 1);
 
     release_kbnode( keyblock );
 }
@@ -178,7 +178,7 @@ show_revocation_reason( PKT_public_key *pk, int mode )
  */
 #ifndef NO_TRUST_MODELS
 static int
-do_edit_ownertrust (PKT_public_key *pk, int mode,
+do_edit_ownertrust (ctrl_t ctrl, PKT_public_key *pk, int mode,
                     unsigned *new_trust, int defer_help )
 {
   char *p;
@@ -188,8 +188,7 @@ do_edit_ownertrust (PKT_public_key *pk, int mode,
   int show=0;
   int min_num;
   int did_help=defer_help;
-  unsigned int minimum = tdb_get_min_ownertrust (pk);
-  char pkstrbuf[PUBKEY_STRING_SIZE];
+  unsigned int minimum = tdb_get_min_ownertrust (ctrl, pk, 0);
 
   switch(minimum)
     {
@@ -222,33 +221,33 @@ do_edit_ownertrust (PKT_public_key *pk, int mode,
           {
             KBNODE keyblock, un;
 
-            tty_printf(_("No trust value assigned to:\n"));
-           tty_printf("%s/%s %s\n",
-                       pubkey_string (pk, pkstrbuf, sizeof pkstrbuf),
-                       keystr(keyid), datestr_from_pk( pk ) );
-           p=get_user_id_native(keyid);
-           tty_printf(_("      \"%s\"\n"),p);
-           xfree(p);
+            tty_printf (_("No trust value assigned to:\n"));
+            print_key_line (ctrl, NULL, pk, 0);
+
+           p = get_user_id_native (ctrl, keyid);
+           tty_printf (_("      \"%s\"\n"),p);
+           xfree (p);
 
-            keyblock = get_pubkeyblock (keyid);
+            keyblock = get_pubkeyblock (ctrl, keyid);
             if (!keyblock)
                 BUG ();
             for (un=keyblock; un; un = un->next)
              {
                 if (un->pkt->pkttype != PKT_USER_ID )
                  continue;
-                if (un->pkt->pkt.user_id->is_revoked )
+                if (un->pkt->pkt.user_id->flags.revoked)
                  continue;
-                if (un->pkt->pkt.user_id->is_expired )
+                if (un->pkt->pkt.user_id->flags.expired)
                  continue;
                /* Only skip textual primaries */
-                if (un->pkt->pkt.user_id->is_primary
+                if (un->pkt->pkt.user_id->flags.primary
                    && !un->pkt->pkt.user_id->attrib_data )
                  continue;
 
                if((opt.verify_options&VERIFY_SHOW_PHOTOS)
                   && un->pkt->pkt.user_id->attrib_data)
-                 show_photos (un->pkt->pkt.user_id->attribs,
+                 show_photos (ctrl,
+                               un->pkt->pkt.user_id->attribs,
                                un->pkt->pkt.user_id->numattribs, pk,
                                un->pkt->pkt.user_id);
 
@@ -258,7 +257,7 @@ do_edit_ownertrust (PKT_public_key *pk, int mode,
                tty_printf(_("  aka \"%s\"\n"),p);
              }
 
-            print_fingerprint (NULL, pk, 2);
+            print_fingerprint (ctrl, NULL, pk, 2);
             tty_printf("\n");
            release_kbnode (keyblock);
           }
@@ -376,14 +375,14 @@ do_edit_ownertrust (PKT_public_key *pk, int mode,
  */
 #ifndef NO_TRUST_MODELS
 int
-edit_ownertrust (PKT_public_key *pk, int mode )
+edit_ownertrust (ctrl_t ctrl, PKT_public_key *pk, int mode )
 {
   unsigned int trust = 0;
   int no_help = 0;
 
   for(;;)
     {
-      switch ( do_edit_ownertrust (pk, mode, &trust, no_help ) )
+      switch ( do_edit_ownertrust (ctrl, pk, mode, &trust, no_help ) )
         {
         case -1: /* quit */
           return -1;
@@ -392,8 +391,8 @@ edit_ownertrust (PKT_public_key *pk, int mode )
           break;
         case 1: /* trust value set */
           trust &= ~TRUST_FLAG_DISABLED;
-          trust |= get_ownertrust (pk) & TRUST_FLAG_DISABLED;
-          update_ownertrust (pk, trust );
+          trust |= get_ownertrust (ctrl, pk) & TRUST_FLAG_DISABLED;
+          update_ownertrust (ctrl, pk, trust );
           return 1;
         default:
           return 0;
@@ -429,7 +428,7 @@ do_we_trust( PKT_public_key *pk, unsigned int trustlevel )
     default:
       log_error ("invalid trustlevel %u returned from validation layer\n",
                 trustlevel);
-      /* fall thru */
+      /* fall through */
     case TRUST_UNKNOWN:
     case TRUST_UNDEFINED:
       log_info(_("%s: There is no assurance this key belongs"
@@ -450,6 +449,13 @@ do_we_trust( PKT_public_key *pk, unsigned int trustlevel )
       if( opt.verbose )
        log_info(_("This key belongs to us\n"));
       return 1; /* yes */
+
+    case TRUST_NEVER:
+      /* This can be returned by TOFU, which can return negative
+         assertions.  */
+      log_info(_("%s: This key is bad!  It has been marked as untrusted!\n"),
+               keystr_from_pk(pk));
+      return 0; /* no */
     }
 
   return 1; /*NOTREACHED*/
@@ -461,7 +467,7 @@ do_we_trust( PKT_public_key *pk, unsigned int trustlevel )
  * key anyway.
  */
 static int
-do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel )
+do_we_trust_pre (ctrl_t ctrl, PKT_public_key *pk, unsigned int trustlevel )
 {
   int rc;
 
@@ -469,14 +475,20 @@ do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel )
 
   if( !opt.batch && !rc )
     {
-      print_pubkey_info(NULL,pk);
-      print_fingerprint (NULL, pk, 2);
+      print_pubkey_info (ctrl, NULL,pk);
+      print_fingerprint (ctrl, NULL, pk, 2);
       tty_printf("\n");
 
-      tty_printf(
-              _("It is NOT certain that the key belongs to the person named\n"
-                "in the user ID.  If you *really* know what you are doing,\n"
-                "you may answer the next question with yes.\n"));
+      if ((trustlevel & TRUST_MASK) == TRUST_NEVER)
+        tty_printf(
+          _("This key is bad!  It has been marked as untrusted!  If you\n"
+            "*really* know what you are doing, you may answer the next\n"
+            "question with yes.\n"));
+      else
+        tty_printf(
+          _("It is NOT certain that the key belongs to the person named\n"
+            "in the user ID.  If you *really* know what you are doing,\n"
+            "you may answer the next question with yes.\n"));
 
       tty_printf("\n");
 
@@ -487,7 +499,7 @@ do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel )
           char *hint_str;
 
           keyid_from_pk (pk, kid);
-          hint_str = get_long_user_id_string ( kid );
+          hint_str = get_long_user_id_string (ctrl, kid);
           write_status_text ( STATUS_USERID_HINT, hint_str );
           xfree (hint_str);
         }
@@ -509,6 +521,9 @@ do_we_trust_pre( PKT_public_key *pk, unsigned int trustlevel )
 static void
 write_trust_status (int statuscode, int trustlevel)
 {
+#ifdef NO_TRUST_MODELS
+  write_status (statuscode);
+#else /* NO_TRUST_MODELS */
   int tm;
 
   /* For the combined tofu+pgp method, we return the trust model which
@@ -518,6 +533,7 @@ write_trust_status (int statuscode, int trustlevel)
   else
     tm = opt.trust_model;
   write_status_strings (statuscode, "0 ", trust_model_string (tm), NULL);
+#endif /* NO_TRUST_MODELS */
 }
 
 
@@ -526,13 +542,13 @@ write_trust_status (int statuscode, int trustlevel)
  * Returns an error code if we should not trust this signature.
  */
 int
-check_signatures_trust( PKT_signature *sig )
+check_signatures_trust (ctrl_t ctrl, PKT_signature *sig)
 {
   PKT_public_key *pk = xmalloc_clear( sizeof *pk );
   unsigned int trustlevel = TRUST_UNKNOWN;
   int rc=0;
 
-  rc = get_pubkey( pk, sig->keyid );
+  rc = get_pubkey_for_sig (ctrl, pk, sig);
   if (rc)
     { /* this should not happen */
       log_error("Ooops; the key vanished  - can't check the trust\n");
@@ -545,7 +561,7 @@ check_signatures_trust( PKT_signature *sig )
       if( !opt.quiet )
         log_info(_("WARNING: Using untrusted key!\n"));
       if (opt.with_fingerprint)
-        print_fingerprint (NULL, pk, 1);
+        print_fingerprint (ctrl, NULL, pk, 1);
       goto leave;
     }
 
@@ -553,7 +569,7 @@ check_signatures_trust( PKT_signature *sig )
     log_info(_("WARNING: this key might be revoked (revocation key"
               " not present)\n"));
 
-  trustlevel = get_validity (pk, NULL, sig, 1);
+  trustlevel = get_validity (ctrl, NULL, pk, NULL, sig, 1);
 
   if ( (trustlevel & TRUST_FLAG_REVOKED) )
     {
@@ -564,13 +580,13 @@ check_signatures_trust( PKT_signature *sig )
       else
        log_info(_("WARNING: This key has been revoked by its owner!\n"));
       log_info(_("         This could mean that the signature is forged.\n"));
-      show_revocation_reason( pk, 0 );
+      show_revocation_reason (ctrl, pk, 0);
     }
   else if ((trustlevel & TRUST_FLAG_SUB_REVOKED) )
     {
       write_status( STATUS_KEYREVOKED );
       log_info(_("WARNING: This subkey has been revoked by its owner!\n"));
-      show_revocation_reason( pk, 0 );
+      show_revocation_reason (ctrl, pk, 0);
     }
 
   if ((trustlevel & TRUST_FLAG_DISABLED))
@@ -586,7 +602,7 @@ check_signatures_trust( PKT_signature *sig )
 
 
       primary_pk = xmalloc_clear (sizeof *primary_pk);
-      get_pubkey (primary_pk, pk->main_keyid);
+      get_pubkey (ctrl, primary_pk, pk->main_keyid);
       fingerprint_from_pk (primary_pk, fpr, &fprlen);
       free_public_key (primary_pk);
 
@@ -616,7 +632,7 @@ check_signatures_trust( PKT_signature *sig )
               log_info (_("trustlevel adjusted to FULL"
                           " due to valid PKA info\n"));
             }
-          /* (fall through) */
+          /* fall through */
         case TRUST_FULLY:
           if (!okay)
             {
@@ -633,13 +649,13 @@ check_signatures_trust( PKT_signature *sig )
     {
     case TRUST_EXPIRED:
       log_info(_("Note: This key has expired!\n"));
-      print_fingerprint (NULL, pk, 1);
+      print_fingerprint (ctrl, NULL, pk, 1);
       break;
 
     default:
       log_error ("invalid trustlevel %u returned from validation layer\n",
                  trustlevel);
-      /* fall thru */
+      /* fall through */
     case TRUST_UNKNOWN:
     case TRUST_UNDEFINED:
       write_trust_status (STATUS_TRUST_UNDEFINED, trustlevel);
@@ -647,16 +663,17 @@ check_signatures_trust( PKT_signature *sig )
                  " a trusted signature!\n"));
       log_info(_("         There is no indication that the "
                  "signature belongs to the owner.\n" ));
-      print_fingerprint (NULL, pk, 1);
+      print_fingerprint (ctrl, NULL, pk, 1);
       break;
 
     case TRUST_NEVER:
-      /* currently we won't get that status */
+      /* This level can be returned by TOFU, which supports negative
+       * assertions.  */
       write_trust_status (STATUS_TRUST_NEVER, trustlevel);
       log_info(_("WARNING: We do NOT trust this key!\n"));
       log_info(_("         The signature is probably a FORGERY.\n"));
       if (opt.with_fingerprint)
-        print_fingerprint (NULL, pk, 1);
+        print_fingerprint (ctrl, NULL, pk, 1);
       rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
       break;
 
@@ -666,19 +683,19 @@ check_signatures_trust( PKT_signature *sig )
                  " sufficiently trusted signatures!\n"));
       log_info(_("         It is not certain that the"
                  " signature belongs to the owner.\n" ));
-      print_fingerprint (NULL, pk, 1);
+      print_fingerprint (ctrl, NULL, pk, 1);
       break;
 
     case TRUST_FULLY:
       write_trust_status (STATUS_TRUST_FULLY, trustlevel);
       if (opt.with_fingerprint)
-        print_fingerprint (NULL, pk, 1);
+        print_fingerprint (ctrl, NULL, pk, 1);
       break;
 
     case TRUST_ULTIMATE:
       write_trust_status (STATUS_TRUST_ULTIMATE, trustlevel);
       if (opt.with_fingerprint)
-        print_fingerprint (NULL, pk, 1);
+        print_fingerprint (ctrl, NULL, pk, 1);
       break;
     }
 
@@ -713,40 +730,35 @@ key_present_in_pk_list(PK_LIST pk_list, PKT_public_key *pk)
 }
 
 
-/****************
+/*
  * Return a malloced string with a default recipient if there is any
+ * Fixme: We don't distinguish between malloc failure and no-default-recipient.
  */
 static char *
-default_recipient(ctrl_t ctrl)
+default_recipient (ctrl_t ctrl)
 {
-    PKT_public_key *pk;
-    byte fpr[MAX_FINGERPRINT_LEN+1];
-    size_t n;
-    char *p;
-    int i;
-
-    if( opt.def_recipient )
-       return xstrdup( opt.def_recipient );
-    if( !opt.def_recipient_self )
-       return NULL;
-    pk = xmalloc_clear( sizeof *pk );
-    i = get_seckey_default (ctrl, pk);
-    if( i ) {
-       free_public_key( pk );
-       return NULL;
+  PKT_public_key *pk;
+  char *result;
+
+  if (opt.def_recipient)
+    return xtrystrdup (opt.def_recipient);
+
+  if (!opt.def_recipient_self)
+    return NULL;
+  pk = xtrycalloc (1, sizeof *pk );
+  if (!pk)
+    return NULL;
+  if (get_seckey_default (ctrl, pk))
+    {
+      free_public_key (pk);
+      return NULL;
     }
-    n = MAX_FINGERPRINT_LEN;
-    fingerprint_from_pk( pk, fpr, &n );
-    free_public_key( pk );
-    p = xmalloc( 2*n+3 );
-    *p++ = '0';
-    *p++ = 'x';
-    for(i=0; i < n; i++ )
-       sprintf( p+2*i, "%02X", fpr[i] );
-    p -= 2;
-    return p;
+  result = hexfingerprint (pk, NULL, 0);
+  free_public_key (pk);
+  return result;
 }
 
+
 static int
 expand_id(const char *id,strlist_t *into,unsigned int flags)
 {
@@ -776,14 +788,16 @@ expand_id(const char *id,strlist_t *into,unsigned int flags)
 }
 
 /* For simplicity, and to avoid potential loops, we only expand once -
  you can't make an alias that points to an alias. */
* you can't make an alias that points to an alias.  */
 static strlist_t
-expand_group(strlist_t input)
+expand_group (strlist_t input)
 {
-  strlist_t sl,output=NULL,rover;
+  strlist_t output = NULL;
+  strlist_t sl, rover;
 
-  for(rover=input;rover;rover=rover->next)
-    if(expand_id(rover->d,&output,rover->flags)==0)
+  for (rover = input; rover; rover = rover->next)
+    if (!(rover->flags & PK_LIST_FROM_FILE)
+        && !expand_id(rover->d,&output,rover->flags))
       {
        /* Didn't find any groups, so use the existing string */
        sl=add_to_strlist(&output,rover->d);
@@ -795,17 +809,19 @@ expand_group(strlist_t input)
 
 
 /* Helper for build_pk_list to find and check one key.  This helper is
-   also used directly in server mode by the RECIPIENTS command.  On
-   success the new key is added to PK_LIST_ADDR.  NAME is the user id
-   of the key. USE the requested usage and a set MARK_HIDDEN will mark
-   the key in the updated list as a hidden recipient. */
+ * also used directly in server mode by the RECIPIENTS command.  On
+ * success the new key is added to PK_LIST_ADDR.  NAME is the user id
+ * of the key.  USE the requested usage and a set MARK_HIDDEN will
+ * mark the key in the updated list as a hidden recipient.  If
+ * FROM_FILE is true, NAME is not a user ID but the name of a file
+ * holding a key. */
 gpg_error_t
 find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
-                    int mark_hidden, pk_list_t *pk_list_addr)
+                    int mark_hidden, int from_file, pk_list_t *pk_list_addr)
 {
   int rc;
   PKT_public_key *pk;
-  int trustlevel;
+  KBNODE keyblock = NULL;
 
   if (!name || !*name)
     return gpg_error (GPG_ERR_INV_USER_ID);
@@ -815,7 +831,10 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
     return gpg_error_from_syserror ();
   pk->req_usage = use;
 
-  rc = get_pubkey_byname (ctrl, NULL, pk, name, NULL, NULL, 0, 0);
+  if (from_file)
+    rc = get_pubkey_fromfile (ctrl, pk, name);
+  else
+    rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0);
   if (rc)
     {
       int code;
@@ -838,6 +857,7 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
   if (rc)
     {
       /* Key found but not usable for us (e.g. sign-only key). */
+      release_kbnode (keyblock);
       send_status_inv_recp (3, name); /* Wrong key usage */
       log_error (_("%s: skipped: %s\n"), name, gpg_strerror (rc) );
       free_public_key (pk);
@@ -845,24 +865,29 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
     }
 
   /* Key found and usable.  Check validity. */
-  trustlevel = get_validity (pk, pk->user_id, NULL, 1);
-  if ( (trustlevel & TRUST_FLAG_DISABLED) )
+  if (!from_file)
     {
-      /* Key has been disabled. */
-      send_status_inv_recp (13, name);
-      log_info (_("%s: skipped: public key is disabled\n"), name);
-      free_public_key (pk);
-      return GPG_ERR_UNUSABLE_PUBKEY;
-    }
+      int trustlevel;
 
-  if ( !do_we_trust_pre (pk, trustlevel) )
-    {
-      /* We don't trust this key.  */
-      send_status_inv_recp (10, name);
-      free_public_key (pk);
-      return GPG_ERR_UNUSABLE_PUBKEY;
+      trustlevel = get_validity (ctrl, keyblock, pk, pk->user_id, NULL, 1);
+      release_kbnode (keyblock);
+      if ( (trustlevel & TRUST_FLAG_DISABLED) )
+        {
+          /* Key has been disabled. */
+          send_status_inv_recp (13, name);
+          log_info (_("%s: skipped: public key is disabled\n"), name);
+          free_public_key (pk);
+          return GPG_ERR_UNUSABLE_PUBKEY;
+        }
+
+      if ( !do_we_trust_pre (ctrl, pk, trustlevel) )
+        {
+          /* We don't trust this key.  */
+          send_status_inv_recp (10, name);
+          free_public_key (pk);
+          return GPG_ERR_UNUSABLE_PUBKEY;
+        }
     }
-  /* Note: do_we_trust may have changed the trustlevel. */
 
   /* Skip the actual key if the key is already present in the
      list.  */
@@ -895,22 +920,24 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
 
 
 /* This is the central function to collect the keys for recipients.
-   It is thus used to prepare a public key encryption. encrypt-to
-   keys, default keys and the keys for the actual recipients are all
-   collected here.  When not in batch mode and no recipient has been
-   passed on the commandline, the function will also ask for
-   recipients.
-
-   RCPTS is a string list with the recipients; NULL is an allowed
-   value but not very useful.  Group expansion is done on these names;
-   they may be in any of the user Id formats we can handle.  The flags
-   bits for each string in the string list are used for:
-     Bit 0 (PK_LIST_ENCRYPT_TO): This is an encrypt-to recipient.
-     Bit 1 (PK_LIST_HIDDEN)    : This is a hidden recipient.
-
-   On success a list of keys is stored at the address RET_PK_LIST; the
-   caller must free this list.  On error the value at this address is
-   not changed.
+ * It is thus used to prepare a public key encryption. encrypt-to
+ * keys, default keys and the keys for the actual recipients are all
+ * collected here.  When not in batch mode and no recipient has been
+ * passed on the commandline, the function will also ask for
+ * recipients.
+ *
+ * RCPTS is a string list with the recipients; NULL is an allowed
+ * value but not very useful.  Group expansion is done on these names;
+ * they may be in any of the user Id formats we can handle.  The flags
+ * bits for each string in the string list are used for:
+ *
+ * - PK_LIST_ENCRYPT_TO :: This is an encrypt-to recipient.
+ * - PK_LIST_HIDDEN     :: This is a hidden recipient.
+ * - PK_LIST_FROM_FILE  :: The argument is a file with a key.
+ *
+ * On success a list of keys is stored at the address RET_PK_LIST; the
+ * caller must free this list.  On error the value at this address is
+ * not changed.
  */
 int
 build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
@@ -995,11 +1022,11 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
 
           /* Hidden recipients are not allowed while in PGP mode,
              issue a warning and switch into GnuPG mode. */
-          if ((rov->flags & PK_LIST_HIDDEN) && (PGP6 || PGP7 || PGP8))
+          if ((rov->flags & PK_LIST_HIDDEN) && (PGP7 || PGP8))
             {
-              log_info(_("you may not use %s while in %s mode\n"),
+              log_info(_("option '%s' may not be used in %s mode\n"),
                        "--hidden-recipient",
-                       compliance_option_string());
+                       gnupg_compliance_option_string (opt.compliance));
 
               compliance_failure();
             }
@@ -1046,11 +1073,11 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
                   /* Hidden encrypt-to recipients are not allowed while
                      in PGP mode, issue a warning and switch into
                      GnuPG mode. */
-                  if ((r->flags&PK_LIST_ENCRYPT_TO) && (PGP6 || PGP7 || PGP8))
+                  if ((r->flags&PK_LIST_ENCRYPT_TO) && (PGP7 || PGP8))
                     {
-                      log_info(_("you may not use %s while in %s mode\n"),
+                      log_info(_("option '%s' may not be used in %s mode\n"),
                                "--hidden-encrypt-to",
-                               compliance_option_string());
+                               gnupg_compliance_option_string (opt.compliance));
 
                       compliance_failure();
                     }
@@ -1122,8 +1149,8 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
                   else
                     {
                       size_t n;
-                      char *p = get_user_id( keyid, &n );
-                      tty_print_utf8_string( p, n );
+                      char *p = get_user_id (ctrl, keyid, &n, NULL);
+                      tty_print_utf8_string ( p, n );
                       xfree(p);
                     }
                   tty_printf("\"\n");
@@ -1183,12 +1210,13 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
                 { /* Check validity of this key. */
                   int trustlevel;
 
-                  trustlevel = get_validity (pk, pk->user_id, NULL, 1);
+                  trustlevel =
+                    get_validity (ctrl, NULL, pk, pk->user_id, NULL, 1);
                   if ( (trustlevel & TRUST_FLAG_DISABLED) )
                     {
                       tty_printf (_("Public key is disabled.\n") );
                     }
-                  else if ( do_we_trust_pre (pk, trustlevel) )
+                  else if ( do_we_trust_pre (ctrl, pk, trustlevel) )
                     {
                       /* Skip the actual key if the key is already
                        * present in the list */
@@ -1270,6 +1298,7 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
 
           rc = find_and_check_key (ctrl, remusr->d, PUBKEY_USAGE_ENC,
                                    !!(remusr->flags&PK_LIST_HIDDEN),
+                                   !!(remusr->flags&PK_LIST_FROM_FILE),
                                    &pk_list);
           if (rc)
             goto fail;
@@ -1284,6 +1313,29 @@ build_pk_list (ctrl_t ctrl, strlist_t rcpts, PK_LIST *ret_pk_list)
       rc = GPG_ERR_NO_USER_ID;
     }
 
+#ifdef USE_TOFU
+  if (! rc && (opt.trust_model == TM_TOFU_PGP || opt.trust_model == TM_TOFU))
+    {
+      PK_LIST iter;
+      for (iter = pk_list; iter; iter = iter->next)
+        {
+          int rc2;
+
+          /* Note: we already resolved any conflict when looking up
+             the key.  Don't annoy the user again if she selected
+             accept once.  */
+          rc2 = tofu_register_encryption (ctrl, iter->pk, NULL, 0);
+          if (rc2)
+            log_info ("WARNING: Failed to register encryption to %s"
+                      " with TOFU engine\n",
+                      keystr (pk_main_keyid (iter->pk)));
+          else if (DBG_TRUST)
+            log_debug ("Registered encryption to %s with TOFU DB.\n",
+                      keystr (pk_main_keyid (iter->pk)));
+        }
+    }
+#endif /*USE_TOFU*/
+
  fail:
 
   if ( rc )
@@ -1318,11 +1370,6 @@ algo_available( preftype_t preftype, int algo, const union pref_hint *hint)
 {
   if( preftype == PREFTYPE_SYM )
     {
-      if(PGP6 && (algo != CIPHER_ALGO_IDEA
-                 && algo != CIPHER_ALGO_3DES
-                 && algo != CIPHER_ALGO_CAST5))
-       return 0;
-
       if(PGP7 && (algo != CIPHER_ALGO_IDEA
                  && algo != CIPHER_ALGO_3DES
                  && algo != CIPHER_ALGO_CAST5
@@ -1353,9 +1400,9 @@ algo_available( preftype_t preftype, int algo, const union pref_hint *hint)
            return 0;
        }
 
-      if((PGP6 || PGP7) && (algo != DIGEST_ALGO_MD5
-                           && algo != DIGEST_ALGO_SHA1
-                           && algo != DIGEST_ALGO_RMD160))
+      if (PGP7 && (algo != DIGEST_ALGO_MD5
+                   && algo != DIGEST_ALGO_SHA1
+                   && algo != DIGEST_ALGO_RMD160))
        return 0;
 
 
@@ -1369,8 +1416,8 @@ algo_available( preftype_t preftype, int algo, const union pref_hint *hint)
     }
   else if( preftype == PREFTYPE_ZIP )
     {
-      if((PGP6 || PGP7) && (algo != COMPRESS_ALGO_NONE
-                           && algo != COMPRESS_ALGO_ZIP))
+      if (PGP7 && (algo != COMPRESS_ALGO_NONE
+                   && algo != COMPRESS_ALGO_ZIP))
        return 0;
 
       /* PGP8 supports all the compression algos we do */
@@ -1416,9 +1463,12 @@ select_algo_from_prefs(PK_LIST pk_list, int preftype,
             support.  All this doesn't mean IDEA is actually
             available, of course. */
           implicit=CIPHER_ALGO_3DES;
-
          break;
 
+       case PREFTYPE_AEAD:
+          /* No implicit algo.  */
+          break;
+
        case PREFTYPE_HASH:
          /* While I am including this code for completeness, note
             that currently --pgp2 mode locks the hash at MD5, so this
@@ -1501,6 +1551,8 @@ select_algo_from_prefs(PK_LIST pk_list, int preftype,
       prefs=NULL;
       if(preftype==PREFTYPE_SYM && opt.personal_cipher_prefs)
        prefs=opt.personal_cipher_prefs;
+      else if(preftype==PREFTYPE_AEAD && opt.personal_aead_prefs)
+       prefs=opt.personal_aead_prefs;
       else if(preftype==PREFTYPE_HASH && opt.personal_digest_prefs)
        prefs=opt.personal_digest_prefs;
       else if(preftype==PREFTYPE_ZIP && opt.personal_compress_prefs)
@@ -1594,9 +1646,36 @@ select_mdc_from_pklist (PK_LIST pk_list)
 }
 
 
-/* Print a warning for all keys in PK_LIST missing the MDC feature. */
+/* Select the AEAD flag from the pk_list.  We can only use AEAD if all
+ * recipients support this feature.  Returns the AEAD to be used or 0
+ * if AEAD shall not be used.  */
+aead_algo_t
+select_aead_from_pklist (PK_LIST pk_list)
+{
+  pk_list_t pkr;
+  int aead;
+
+  if (!pk_list)
+    return 0;
+
+  for (pkr = pk_list; pkr; pkr = pkr->next)
+    {
+      if (pkr->pk->user_id) /* selected by user ID */
+        aead = pkr->pk->user_id->flags.aead;
+      else
+        aead = pkr->pk->flags.aead;
+      if (!aead)
+        return 0;  /* At least one recipient does not support it. */
+    }
+
+  return default_aead_algo (); /* Yes, AEAD can be used. */
+}
+
+
+/* Print a warning for all keys in PK_LIST missing the AEAD feature
+ * flag or AEAD algorithms. */
 void
-warn_missing_mdc_from_pklist (PK_LIST pk_list)
+warn_missing_aead_from_pklist (PK_LIST pk_list)
 {
   PK_LIST pkr;
 
@@ -1605,12 +1684,12 @@ warn_missing_mdc_from_pklist (PK_LIST pk_list)
       int mdc;
 
       if (pkr->pk->user_id) /* selected by user ID */
-        mdc = pkr->pk->user_id->flags.mdc;
+        mdc = pkr->pk->user_id->flags.aead;
       else
-        mdc = pkr->pk->flags.mdc;
+        mdc = pkr->pk->flags.aead;
       if (!mdc)
         log_info (_("Note: key %s has no %s feature\n"),
-                  keystr_from_pk (pkr->pk), "MDC");
+                  keystr_from_pk (pkr->pk), "AEAD");
     }
 }