common: Rename an odd named function.
[gnupg.git] / g10 / sign.c
index 782b9fc..e5fbd9d 100644 (file)
@@ -23,7 +23,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <assert.h>
 
 #include "gpg.h"
 #include "options.h"
@@ -41,7 +40,7 @@
 #include "pkglue.h"
 #include "sysutils.h"
 #include "call-agent.h"
-
+#include "mbox-util.h"
 
 #ifdef HAVE_DOSISH_SYSTEM
 #define LF "\r\n"
@@ -60,92 +59,121 @@ static void
 mk_notation_policy_etc (PKT_signature *sig,
                        PKT_public_key *pk, PKT_public_key *pksk)
 {
-    const char *string;
-    char *s=NULL;
-    strlist_t pu=NULL;
-    struct notation *nd=NULL;
-    struct expando_args args;
+  const char *string;
+  char *p = NULL;
+  strlist_t pu = NULL;
+  struct notation *nd = NULL;
+  struct expando_args args;
 
-    assert(sig->version>=4);
+  log_assert (sig->version >= 4);
 
-    memset(&args,0,sizeof(args));
-    args.pk=pk;
-    args.pksk=pksk;
+  memset (&args, 0, sizeof(args));
+  args.pk = pk;
+  args.pksk = pksk;
 
-    /* notation data */
-    if(IS_SIG(sig) && opt.sig_notations)
-      nd=opt.sig_notations;
-    else if( IS_CERT(sig) && opt.cert_notations )
-      nd=opt.cert_notations;
+  /* Notation data. */
+  if (IS_SIG(sig) && opt.sig_notations)
+    nd = opt.sig_notations;
+  else if (IS_CERT(sig) && opt.cert_notations)
+    nd = opt.cert_notations;
 
-    if(nd)
-      {
-       struct notation *i;
+  if (nd)
+    {
+      struct notation *item;
 
-       for(i=nd;i;i=i->next)
-         {
-           i->altvalue=pct_expando(i->value,&args);
-           if(!i->altvalue)
-             log_error(_("WARNING: unable to %%-expand notation "
-                         "(too large).  Using unexpanded.\n"));
-         }
+      for (item = nd; item; item = item->next)
+        {
+          item->altvalue = pct_expando (item->value,&args);
+          if (!item->altvalue)
+            log_error (_("WARNING: unable to %%-expand notation "
+                         "(too large).  Using unexpanded.\n"));
+        }
 
-       keygen_add_notations(sig,nd);
+      keygen_add_notations (sig, nd);
 
-       for(i=nd;i;i=i->next)
-         {
-           xfree(i->altvalue);
-           i->altvalue=NULL;
-         }
-      }
+      for (item = nd; item; item = item->next)
+        {
+          xfree (item->altvalue);
+          item->altvalue = NULL;
+        }
+    }
 
-    /* set policy URL */
-    if( IS_SIG(sig) && opt.sig_policy_url )
-      pu=opt.sig_policy_url;
-    else if( IS_CERT(sig) && opt.cert_policy_url )
-      pu=opt.cert_policy_url;
+  /* Set policy URL. */
+  if (IS_SIG(sig) && opt.sig_policy_url)
+    pu = opt.sig_policy_url;
+  else if (IS_CERT(sig) && opt.cert_policy_url)
+    pu = opt.cert_policy_url;
 
-    for(;pu;pu=pu->next)
-      {
-        string = pu->d;
+  for (; pu; pu = pu->next)
+    {
+      string = pu->d;
 
-       s=pct_expando(string,&args);
-       if(!s)
-         {
-           log_error(_("WARNING: unable to %%-expand policy URL "
-                       "(too large).  Using unexpanded.\n"));
-           s=xstrdup(string);
-         }
+      p = pct_expando (string, &args);
+      if (!p)
+        {
+          log_error(_("WARNING: unable to %%-expand policy URL "
+                      "(too large).  Using unexpanded.\n"));
+          p = xstrdup(string);
+        }
 
-       build_sig_subpkt(sig,SIGSUBPKT_POLICY|
-                        ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0),
-                        s,strlen(s));
+      build_sig_subpkt (sig, (SIGSUBPKT_POLICY
+                              | ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0)),
+                        p, strlen (p));
 
-       xfree(s);
-      }
+      xfree (p);
+    }
 
-    /* preferred keyserver URL */
-    if( IS_SIG(sig) && opt.sig_keyserver_url )
-      pu=opt.sig_keyserver_url;
+  /* Preferred keyserver URL. */
+  if (IS_SIG(sig) && opt.sig_keyserver_url)
+    pu = opt.sig_keyserver_url;
 
-    for(;pu;pu=pu->next)
-      {
-        string = pu->d;
+  for (; pu; pu = pu->next)
+    {
+      string = pu->d;
 
-       s=pct_expando(string,&args);
-       if(!s)
-         {
-           log_error(_("WARNING: unable to %%-expand preferred keyserver URL"
-                       " (too large).  Using unexpanded.\n"));
-           s=xstrdup(string);
-         }
+      p = pct_expando (string, &args);
+      if (!p)
+        {
+          log_error (_("WARNING: unable to %%-expand preferred keyserver URL"
+                       " (too large).  Using unexpanded.\n"));
+          p = xstrdup (string);
+        }
 
-       build_sig_subpkt(sig,SIGSUBPKT_PREF_KS|
-                        ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0),
-                        s,strlen(s));
+      build_sig_subpkt (sig, (SIGSUBPKT_PREF_KS
+                              | ((pu->flags & 1)?SIGSUBPKT_FLAG_CRITICAL:0)),
+                        p, strlen (p));
+      xfree (p);
+    }
 
-       xfree(s);
-      }
+  /* Set signer's user id.  */
+  if (IS_SIG (sig) && !opt.flags.disable_signer_uid)
+    {
+      char *mbox;
+
+      /* For now we use the uid which was used to locate the key.  */
+      if (pksk->user_id && (mbox = mailbox_from_userid (pksk->user_id->name)))
+        {
+          if (DBG_LOOKUP)
+            log_debug ("setting Signer's UID to '%s'\n", mbox);
+          build_sig_subpkt (sig, SIGSUBPKT_SIGNERS_UID, mbox, strlen (mbox));
+          xfree (mbox);
+        }
+      else if (opt.sender_list)
+        {
+          /* If a list of --sender was given we scan that list and use
+           * the first one matching a user id of the current key.  */
+
+          /* FIXME: We need to get the list of user ids for the PKSK
+           * packet.  That requires either a function to look it up
+           * again or we need to extend the key packet struct to link
+           * to the primary key which in turn could link to the user
+           * ids.  Too much of a change right now.  Let's take just
+           * one from the supplied list and hope that the caller
+           * passed a matching one.  */
+          build_sig_subpkt (sig, SIGSUBPKT_SIGNERS_UID,
+                            opt.sender_list->d, strlen (opt.sender_list->d));
+        }
+    }
 }
 
 
@@ -235,15 +263,15 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
   if (pksk->timestamp > sig->timestamp )
     {
       ulong d = pksk->timestamp - sig->timestamp;
-      log_info (d==1 ? _("key has been created %lu second "
-                         "in future (time warp or clock problem)\n")
-                : _("key has been created %lu seconds "
-                    "in future (time warp or clock problem)\n"), d );
+      log_info (ngettext("key %s was created %lu second"
+                         " in the future (time warp or clock problem)\n",
+                         "key %s was created %lu seconds"
+                         " in the future (time warp or clock problem)\n",
+                         d), keystr_from_pk (pksk), d);
       if (!opt.ignore_time_conflict)
         return gpg_error (GPG_ERR_TIME_CONFLICT);
     }
 
-
   print_pubkey_algo_note (pksk->pubkey_algo);
 
   if (!mdalgo)
@@ -347,7 +375,7 @@ openpgp_card_v1_p (PKT_public_key *pk)
         }
 
       xfree (pk->serialno);
-      agent_get_keyinfo (NULL, hexgrip, &pk->serialno);
+      agent_get_keyinfo (NULL, hexgrip, &pk->serialno, NULL);
       xfree (hexgrip);
       pk->flags.serialno_valid = 1;
     }
@@ -592,7 +620,7 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
          * data, it is not possible to know the used length
          * without a double read of the file - to avoid that
          * we simple use partial length packets. */
-        if ( ptmode == 't' )
+        if ( ptmode == 't' || ptmode == 'u' || ptmode == 'm')
          filesize = 0;
       }
     else
@@ -601,6 +629,7 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
     if (!opt.no_literal) {
         PACKET pkt;
 
+        /* Note that PT has been initialized above in no_literal mode.  */
         pt->timestamp = make_timestamp ();
         pt->mode = ptmode;
         pt->len = filesize;
@@ -614,6 +643,7 @@ write_plaintext_packet (IOBUF out, IOBUF inp, const char *fname, int ptmode)
             log_error ("build_packet(PLAINTEXT) failed: %s\n",
                        gpg_strerror (rc) );
         pt->buf = NULL;
+        free_packet (&pkt);
     }
     else {
         byte copy_buffer[4096];
@@ -677,7 +707,7 @@ write_signature_packets (SK_LIST sk_list, IOBUF out, gcry_md_hd_t hash,
 
       if (sig->version >= 4)
         {
-          build_sig_subpkt_from_sig (sig);
+          build_sig_subpkt_from_sig (sig, pk);
           mk_notation_policy_etc (sig, NULL, pk);
         }
 
@@ -769,11 +799,11 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
 
     /* Note: In the old non-agent version the following call used to
        unprotect the secret key.  This is now done on demand by the agent.  */
-    if( (rc = build_sk_list (locusr, &sk_list, PUBKEY_USAGE_SIG )) )
+    if( (rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG )) )
        goto leave;
 
     if (encryptflag
-        && (rc=build_pk_list (ctrl, remusr, &pk_list, PUBKEY_USAGE_ENC)))
+        && (rc=build_pk_list (ctrl, remusr, &pk_list)))
       goto leave;
 
     /* prepare iobufs */
@@ -1018,7 +1048,8 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
     }
     else {
         rc = write_plaintext_packet (out, inp, fname,
-                                     opt.textmode && !outfile ? 't':'b');
+                                     opt.textmode && !outfile ?
+                                     (opt.mimemode? 'm':'t'):'b');
     }
 
     /* catch errors from above */
@@ -1057,7 +1088,8 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr,
  * make a clear signature. note that opt.armor is not needed
  */
 int
-clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
+clearsign_file (ctrl_t ctrl,
+                const char *fname, strlist_t locusr, const char *outfile )
 {
     armor_filter_context_t *afx;
     progress_filter_context_t *pfx;
@@ -1080,7 +1112,7 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
 
     /* Note: In the old non-agent version the following call used to
        unprotect the secret key.  This is now done on demand by the agent.  */
-    if( (rc=build_sk_list( locusr, &sk_list, PUBKEY_USAGE_SIG )) )
+    if( (rc=build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG )) )
        goto leave;
 
     /* prepare iobufs */
@@ -1141,7 +1173,7 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
                }
            }
        }
-       assert(any);
+       log_assert(any);
        iobuf_writestr(out, LF );
     }
 
@@ -1191,7 +1223,7 @@ clearsign_file( const char *fname, strlist_t locusr, const char *outfile )
  * FIXME: Far too much code is duplicated - revamp the whole file.
  */
 int
-sign_symencrypt_file (const char *fname, strlist_t locusr)
+sign_symencrypt_file (ctrl_t ctrl, const char *fname, strlist_t locusr)
 {
     armor_filter_context_t *afx;
     progress_filter_context_t *pfx;
@@ -1224,7 +1256,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
 
     /* Note: In the old non-agent version the following call used to
        unprotect the secret key.  This is now done on demand by the agent.  */
-    rc = build_sk_list (locusr, &sk_list, PUBKEY_USAGE_SIG);
+    rc = build_sk_list (ctrl, locusr, &sk_list, PUBKEY_USAGE_SIG);
     if (rc)
        goto leave;
 
@@ -1253,7 +1285,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
     if (!opt.quiet || !opt.batch)
         log_info (_("%s encryption will be used\n"),
                   openpgp_cipher_algo_name (algo) );
-    cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, &canceled);
+    cfx.dek = passphrase_to_dek (algo, s2k, 1, 1, NULL, &canceled);
 
     if (!cfx.dek || !cfx.dek->keylen) {
         rc = gpg_error (canceled?GPG_ERR_CANCELED:GPG_ERR_BAD_PASSPHRASE);
@@ -1261,12 +1293,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
         goto leave;
     }
 
-    /* We have no way to tell if the recipient can handle messages
-       with an MDC, so this defaults to no.  Perhaps in a few years,
-       this can be defaulted to yes.  Note that like regular
-       encrypting, --force-mdc overrides --disable-mdc. */
-    if(opt.force_mdc)
-      cfx.dek->use_mdc=1;
+    cfx.dek->use_mdc = use_mdc (NULL, cfx.dek->algo);
 
     /* now create the outfile */
     rc = open_outfile (-1, fname, opt.armor? 1:0, 0, &out);
@@ -1309,7 +1336,11 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
 
     /* Push the compress filter */
     if (default_compress_algo())
-      push_compress_filter(out,&zfx,default_compress_algo());
+      {
+        if (cfx.dek && cfx.dek->use_mdc)
+          zfx.new_ctb = 1;
+        push_compress_filter (out, &zfx,default_compress_algo() );
+      }
 
     /* Write the one-pass signature packets */
     /*(current filters: zip - encrypt - armor)*/
@@ -1322,7 +1353,8 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
 
     /* Pipe data through all filters; i.e. write the signed stuff */
     /*(current filters: zip - encrypt - armor)*/
-    rc = write_plaintext_packet (out, inp, fname, opt.textmode ? 't':'b');
+    rc = write_plaintext_packet (out, inp, fname,
+                                 opt.textmode ? (opt.mimemode?'m':'t'):'b');
     if (rc)
        goto leave;
 
@@ -1376,9 +1408,9 @@ make_keysig_packet (PKT_signature **ret_sig, PKT_public_key *pk,
     int sigversion;
     gcry_md_hd_t md;
 
-    assert( (sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F
-           || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19
-           || sigclass == 0x30 || sigclass == 0x28 );
+    log_assert ((sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F
+                || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19
+                || sigclass == 0x30 || sigclass == 0x28 );
 
     sigversion = 4;
     if (sigversion < pksk->version)
@@ -1443,7 +1475,7 @@ make_keysig_packet (PKT_signature **ret_sig, PKT_public_key *pk,
       sig->expiredate=sig->timestamp+duration;
     sig->sig_class = sigclass;
 
-    build_sig_subpkt_from_sig( sig );
+    build_sig_subpkt_from_sig (sig, pksk);
     mk_notation_policy_etc (sig, pk, pksk);
 
     /* Crucial that the call to mksubpkt comes LAST before the calls
@@ -1546,7 +1578,7 @@ update_keysig_packet( PKT_signature **ret_sig,
        automagically lower any sig expiration dates to correctly
        correspond to the differences in the timestamps (i.e. the
        duration will shrink).  */
-    build_sig_subpkt_from_sig( sig );
+    build_sig_subpkt_from_sig (sig, pksk);
 
     if (mksubpkt)
       rc = (*mksubpkt)(sig, opaque);