Exemple #1
0
/****************
 * Show the revocation reason as it is stored with the given signature
 */
static void
do_show_revocation_reason( PKT_signature *sig )
{
    size_t n, nn;
    const byte *p, *pp;
    int seq = 0;
    const char *text;

    while( (p = enum_sig_subpkt (sig->hashed, SIGSUBPKT_REVOC_REASON,
				 &n, &seq, NULL )) ) {
	if( !n )
	    continue; /* invalid - just skip it */

	if( *p == 0 )
	    text = _("No reason specified");
	else if( *p == 0x01 )
	    text = _("Key is superseded");
	else if( *p == 0x02 )
	    text = _("Key has been compromised");
	else if( *p == 0x03 )
	    text = _("Key is no longer used");
	else if( *p == 0x20 )
	    text = _("User ID is no longer valid");
	else
	    text = NULL;

	log_info ( _("reason for revocation: "));
	if (text)
          log_printf ("%s\n", text);
	else
          log_printf ("code=%02x\n", *p );
	n--; p++;
	pp = NULL;
	do {
	    /* We don't want any empty lines, so skip them */
	    while( n && *p == '\n' ) {
		p++;
		n--;
	    }
	    if( n ) {
		pp = memchr( p, '\n', n );
		nn = pp? pp - p : n;
		log_info ( _("revocation comment: ") );
		es_write_sanitized (log_get_stream(), p, nn, NULL, NULL);
		log_printf ("\n");
		p += nn; n -= nn;
	    }
	} while( pp );
    }
}
Exemple #2
0
/* This is a variant of gpgsm_print_name sending it output to an estream. */
void
gpgsm_es_print_name2 (estream_t fp, const char *name, int translate)
{
  const unsigned char *s = (const unsigned char *)name;
  int i;

  if (!s)
    {
      es_fputs (_("[Error - No name]"), fp);
    }
  else if (*s == '<')
    {
      const char *s2 = strchr ( (char*)s+1, '>');

      if (s2)
        {
          if (translate)
            es_write_sanitized_utf8_buffer (fp, s + 1, s2 - (char*)s - 1,
                                            NULL, NULL);
          else
            es_write_sanitized (fp, s + 1, s2 - (char*)s - 1, NULL, NULL);
        }
    }
  else if (*s == '(')
    {
      pretty_es_print_sexp (fp, s, gcry_sexp_canon_len (s, 0, NULL, NULL));
    }
  else if (!((*s >= '0' && *s < '9')
             || (*s >= 'A' && *s <= 'Z')
             || (*s >= 'a' && *s <= 'z')))
    es_fputs (_("[Error - invalid encoding]"), fp);
  else
    {
      struct dn_array_s *dn = parse_dn (s);

      if (!dn)
        es_fputs (_("[Error - invalid DN]"), fp);
      else
        {
          print_dn_parts (NULL, fp, dn, translate);
          for (i=0; dn[i].key; i++)
            {
              xfree (dn[i].key);
              xfree (dn[i].value);
            }
          xfree (dn);
        }
    }
}
Exemple #3
0
/* Print a DN part to STREAM or if STREAM is NULL to FP. */
static void
print_dn_part (FILE *fp, estream_t stream,
               struct dn_array_s *dn, const char *key, int translate)
{
  struct dn_array_s *first_dn = dn;

  for (; dn->key; dn++)
    {
      if (!dn->done && !strcmp (dn->key, key))
        {
          /* Forward to the last multi-valued RDN, so that we can
             print them all in reverse in the correct order.  Note
             that this overrides the the standard sequence but that
             seems to a reasonable thing to do with multi-valued
             RDNs. */
          while (dn->multivalued && dn[1].key)
            dn++;
        next:
          if (!dn->done && dn->value && *dn->value)
            {
              if (stream)
                {
                  es_fprintf (stream, "/%s=", dn->key);
                  if (translate)
                    es_write_sanitized_utf8_buffer (stream, dn->value,
                                                    strlen (dn->value),
                                                    "/", NULL);
                  else
                    es_write_sanitized (stream, dn->value, strlen (dn->value),
                                        "/", NULL);
                }
              else
                {
                  fprintf (fp, "/%s=", dn->key);
                  if (translate)
                    print_sanitized_utf8_string (fp, dn->value, '/');
                  else
                    print_sanitized_string (fp, dn->value, '/');
                }
            }
          dn->done = 1;
          if (dn > first_dn && dn[-1].multivalued)
            {
              dn--;
              goto next;
            }
        }
    }
}
Exemple #4
0
void
dump_kbnode (KBNODE node)
{
  for (; node; node = node->next )
    {
      const char *s;
      switch (node->pkt->pkttype)
        {
        case 0:		s="empty"; break;
        case PKT_PUBLIC_KEY:	s="public-key"; break;
        case PKT_SECRET_KEY:	s="secret-key"; break;
        case PKT_SECRET_SUBKEY: s= "secret-subkey"; break;
        case PKT_PUBKEY_ENC:	s="public-enc"; break;
        case PKT_SIGNATURE:	s="signature"; break;
        case PKT_ONEPASS_SIG: s="onepass-sig"; break;
        case PKT_USER_ID:	s="user-id"; break;
        case PKT_PUBLIC_SUBKEY: s="public-subkey"; break;
        case PKT_COMMENT:	s="comment"; break;
        case PKT_RING_TRUST:	s="trust"; break;
        case PKT_PLAINTEXT:	s="plaintext"; break;
        case PKT_COMPRESSED:	s="compressed"; break;
        case PKT_ENCRYPTED:	s="encrypted"; break;
        case PKT_GPG_CONTROL: s="gpg-control"; break;
        default:		s="unknown"; break;
	}
      log_debug ("node %p %02x/%02x type=%s",
                 node, node->flag, node->private_flag, s);
      if (node->pkt->pkttype == PKT_USER_ID)
        {
          PKT_user_id *uid = node->pkt->pkt.user_id;
          log_printf ("  \"");
          es_write_sanitized (log_get_stream (), uid->name, uid->len,
                              NULL, NULL);
          log_printf ("\" %c%c%c%c\n",
                      uid->is_expired? 'e':'.',
                      uid->is_revoked? 'r':'.',
                      uid->created?    'v':'.',
                      uid->is_primary? 'p':'.' );
        }
      else if (node->pkt->pkttype == PKT_SIGNATURE)
        {
          log_printf ("  class=%02x keyid=%08lX ts=%lu\n",
                      node->pkt->pkt.signature->sig_class,
                      (ulong)node->pkt->pkt.signature->keyid[1],
                      (ulong)node->pkt->pkt.signature->timestamp);
        }
      else if (node->pkt->pkttype == PKT_GPG_CONTROL)
        {
          log_printf (" ctrl=%d len=%u\n",
                      node->pkt->pkt.gpg_control->control,
                      (unsigned int)node->pkt->pkt.gpg_control->datalen);
        }
      else if (node->pkt->pkttype == PKT_PUBLIC_KEY
               || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
        {
          PKT_public_key *pk = node->pkt->pkt.public_key;

          log_printf ("  keyid=%08lX a=%d u=%d %c%c%c%c\n",
                      (ulong)keyid_from_pk( pk, NULL ),
                      pk->pubkey_algo, pk->pubkey_usage,
                      pk->has_expired? 'e':'.',
                      pk->flags.revoked? 'r':'.',
                      pk->flags.valid?    'v':'.',
                      pk->flags.mdc?   'm':'.');
        }

      log_flush ();
    }
}
Exemple #5
0
/* Insert the given fpr into our trustdb.  We expect FPR to be an all
   uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'.
   This function does first check whether that key has already been put
   into the trustdb and returns success in this case.  Before a FPR
   actually gets inserted, the user is asked by means of the Pinentry
   whether this is actual want he wants to do.  */
gpg_error_t
agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
{
  gpg_error_t err = 0;
  char *desc;
  char *fname;
  estream_t fp;
  char *fprformatted;
  char *nameformatted;
  int is_disabled;
  int yes_i_trust;

  /* Check whether we are at all allowed to modify the trustlist.
     This is useful so that the trustlist may be a symlink to a global
     trustlist with only admin priviliges to modify it.  Of course
     this is not a secure way of denying access, but it avoids the
     usual clicking on an Okay button most users are used to. */
  fname = make_filename (opt.homedir, "trustlist.txt", NULL);
  if ( access (fname, W_OK) && errno != ENOENT)
    {
      xfree (fname);
      return gpg_error (GPG_ERR_EPERM);
    }
  xfree (fname);

  if (!agent_istrusted (ctrl, fpr, &is_disabled))
    {
      return 0; /* We already got this fingerprint.  Silently return
                   success. */
    }

  /* This feature must explicitly been enabled. */
  if (!opt.allow_mark_trusted)
    return gpg_error (GPG_ERR_NOT_SUPPORTED);

  if (is_disabled)
    {
      /* There is an disabled entry in the trustlist.  Return an error
         so that the user won't be asked again for that one.  Changing
         this flag with the integrated marktrusted feature is and will
         not be made possible.  */
      return gpg_error (GPG_ERR_NOT_TRUSTED);
    }


  /* Insert a new one. */
  nameformatted = reformat_name (name, "%0A   ");
  if (!nameformatted)
    return gpg_error_from_syserror ();

  /* First a general question whether this is trusted.  */
  desc = xtryasprintf (
                /* TRANSLATORS: This prompt is shown by the Pinentry
                   and has one special property: A "%%0A" is used by
                   Pinentry to insert a line break.  The double
                   percent sign is actually needed because it is also
                   a printf format string.  If you need to insert a
                   plain % sign, you need to encode it as "%%25".  The
                   "%s" gets replaced by the name as stored in the
                   certificate. */
                _("Do you ultimately trust%%0A"
                  "  \"%s\"%%0A"
                  "to correctly certify user certificates?"),
                nameformatted);
  if (!desc)
    {
      xfree (nameformatted);
      return out_of_core ();
    }
  err = agent_get_confirmation (ctrl, desc, _("Yes"), _("No"), 1);
  xfree (desc);
  if (!err)
    yes_i_trust = 1;
  else if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
    yes_i_trust = 0;
  else
    {
      xfree (nameformatted);
      return err;
    }


  fprformatted = insert_colons (fpr);
  if (!fprformatted)
    {
      xfree (nameformatted);
      return out_of_core ();
    }

  /* If the user trusts this certificate he has to verify the
     fingerprint of course.  */
  if (yes_i_trust)
    {
      desc = xtryasprintf
        (
         /* TRANSLATORS: This prompt is shown by the Pinentry and has
            one special property: A "%%0A" is used by Pinentry to
            insert a line break.  The double percent sign is actually
            needed because it is also a printf format string.  If you
            need to insert a plain % sign, you need to encode it as
            "%%25".  The second "%s" gets replaced by a hexdecimal
            fingerprint string whereas the first one receives the name
            as stored in the certificate. */
         _("Please verify that the certificate identified as:%%0A"
           "  \"%s\"%%0A"
           "has the fingerprint:%%0A"
           "  %s"), nameformatted, fprformatted);
      if (!desc)
        {
          xfree (fprformatted);
          xfree (nameformatted);
          return out_of_core ();
        }

      /* TRANSLATORS: "Correct" is the label of a button and intended
         to be hit if the fingerprint matches the one of the CA.  The
         other button is "the default "Cancel" of the Pinentry. */
      err = agent_get_confirmation (ctrl, desc, _("Correct"), _("Wrong"), 1);
      xfree (desc);
      if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
        yes_i_trust = 0;
      else if (err)
        {
          xfree (fprformatted);
          xfree (nameformatted);
          return err;
        }
    }


  /* Now check again to avoid duplicates.  We take the lock to make
     sure that nobody else plays with our file and force a reread.  */
  lock_trusttable ();
  agent_reload_trustlist ();
  if (!agent_istrusted (ctrl, fpr, &is_disabled) || is_disabled)
    {
      unlock_trusttable ();
      xfree (fprformatted);
      xfree (nameformatted);
      return is_disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0;
    }

  fname = make_filename (opt.homedir, "trustlist.txt", NULL);
  if ( access (fname, F_OK) && errno == ENOENT)
    {
      fp = es_fopen (fname, "wx,mode=-rw-r");
      if (!fp)
        {
          err = gpg_error_from_syserror ();
          log_error ("can't create `%s': %s\n", fname, gpg_strerror (err));
          xfree (fname);
          unlock_trusttable ();
          xfree (fprformatted);
          xfree (nameformatted);
          return err;
        }
      es_fputs (headerblurb, fp);
      es_fclose (fp);
    }
  fp = es_fopen (fname, "a+,mode=-rw-r");
  if (!fp)
    {
      err = gpg_error_from_syserror ();
      log_error ("can't open `%s': %s\n", fname, gpg_strerror (err));
      xfree (fname);
      unlock_trusttable ();
      xfree (fprformatted);
      xfree (nameformatted);
      return err;
    }

  /* Append the key. */
  es_fputs ("\n# ", fp);
  xfree (nameformatted);
  nameformatted = reformat_name (name, "\n# ");
  if (!nameformatted || strchr (name, '\n'))
    {
      /* Note that there should never be a LF in NAME but we better
         play safe and print a sanitized version in this case.  */
      es_write_sanitized (fp, name, strlen (name), NULL, NULL);
    }
  else
    es_fputs (nameformatted, fp);
  es_fprintf (fp, "\n%s%s %c\n", yes_i_trust?"":"!", fprformatted, flag);
  if (es_ferror (fp))
    err = gpg_error_from_syserror ();

  if (es_fclose (fp))
    err = gpg_error_from_syserror ();

  agent_reload_trustlist ();
  xfree (fname);
  unlock_trusttable ();
  xfree (fprformatted);
  xfree (nameformatted);
  return err;
}