コード例 #1
0
ファイル: findkey.c プロジェクト: HoraceWeebler/gnupg
/* Return the secret key as an S-Exp in RESULT after locating it using
   the GRIP.  Stores NULL at RESULT if the operation shall be diverted
   to a token; in this case an allocated S-expression with the
   shadow_info part from the file is stored at SHADOW_INFO.
   CACHE_MODE defines now the cache shall be used.  DESC_TEXT may be
   set to present a custom description for the pinentry.  LOOKUP_TTL
   is an optional function to convey a TTL to the cache manager; we do
   not simply pass the TTL value because the value is only needed if an
   unprotect action was needed and looking up the TTL may have some
   overhead (e.g. scanning the sshcontrol file). */
gpg_error_t
agent_key_from_file (ctrl_t ctrl, const char *desc_text,
                     const unsigned char *grip, unsigned char **shadow_info,
                     cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
                     gcry_sexp_t *result)
{
  int rc;
  unsigned char *buf;
  size_t len, buflen, erroff;
  gcry_sexp_t s_skey;
  int got_shadow_info = 0;

  *result = NULL;
  if (shadow_info)
    *shadow_info = NULL;

  rc = read_key_file (grip, &s_skey);
  if (rc)
    return rc;

  /* For use with the protection functions we also need the key as an
     canonical encoded S-expression in a buffer.  Create this buffer
     now.  */
  rc = make_canon_sexp (s_skey, &buf, &len);
  if (rc)
    return rc;

  switch (agent_private_key_type (buf))
    {
    case PRIVATE_KEY_CLEAR:
      break; /* no unprotection needed */
    case PRIVATE_KEY_PROTECTED:
      {
	char *desc_text_final;
	char *comment = NULL;

        /* Note, that we will take the comment as a C string for
           display purposes; i.e. all stuff beyond a Nul character is
           ignored.  */
        {
          gcry_sexp_t comment_sexp;

          comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
          if (comment_sexp)
            comment = gcry_sexp_nth_string (comment_sexp, 1);
          gcry_sexp_release (comment_sexp);
        }

        desc_text_final = NULL;
	if (desc_text)
          rc = modify_description (desc_text, comment? comment:"", s_skey,
                                   &desc_text_final);
        gcry_free (comment);

	if (!rc)
	  {
	    rc = unprotect (ctrl, desc_text_final, &buf, grip,
                            cache_mode, lookup_ttl);
	    if (rc)
	      log_error ("failed to unprotect the secret key: %s\n",
			 gpg_strerror (rc));
	  }

	xfree (desc_text_final);
      }
      break;
    case PRIVATE_KEY_SHADOWED:
      if (shadow_info)
        {
          const unsigned char *s;
          size_t n;

          rc = agent_get_shadow_info (buf, &s);
          if (!rc)
            {
              n = gcry_sexp_canon_len (s, 0, NULL,NULL);
              assert (n);
              *shadow_info = xtrymalloc (n);
              if (!*shadow_info)
                rc = out_of_core ();
              else
                {
                  memcpy (*shadow_info, s, n);
                  rc = 0;
                  got_shadow_info = 1;
                }
            }
          if (rc)
            log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
        }
      else
        rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
      break;
    default:
      log_error ("invalid private key format\n");
      rc = gpg_error (GPG_ERR_BAD_SECKEY);
      break;
    }
  gcry_sexp_release (s_skey);
  s_skey = NULL;
  if (rc || got_shadow_info)
    {
      xfree (buf);
      return rc;
    }

  buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
  rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
  wipememory (buf, buflen);
  xfree (buf);
  if (rc)
    {
      log_error ("failed to build S-Exp (off=%u): %s\n",
                 (unsigned int)erroff, gpg_strerror (rc));
      return rc;
    }

  *result = s_skey;
  return 0;
}
コード例 #2
0
ファイル: findkey.c プロジェクト: HoraceWeebler/gnupg
/* Return the information about the secret key specified by the binary
   keygrip GRIP.  If the key is a shadowed one the shadow information
   will be stored at the address R_SHADOW_INFO as an allocated
   S-expression.  */
gpg_error_t
agent_key_info_from_file (ctrl_t ctrl, const unsigned char *grip,
                          int *r_keytype, unsigned char **r_shadow_info)
{
  gpg_error_t err;
  unsigned char *buf;
  size_t len;
  int keytype;

  (void)ctrl;

  if (r_keytype)
    *r_keytype = PRIVATE_KEY_UNKNOWN;
  if (r_shadow_info)
    *r_shadow_info = NULL;

  {
    gcry_sexp_t sexp;

    err = read_key_file (grip, &sexp);
    if (err)
      {
        if (gpg_err_code (err) == GPG_ERR_ENOENT)
          return gpg_error (GPG_ERR_NOT_FOUND);
        else
          return err;
      }
    err = make_canon_sexp (sexp, &buf, &len);
    gcry_sexp_release (sexp);
    if (err)
      return err;
  }

  keytype = agent_private_key_type (buf);
  switch (keytype)
    {
    case PRIVATE_KEY_CLEAR:
      break;
    case PRIVATE_KEY_PROTECTED:
      /* If we ever require it we could retrieve the comment fields
         from such a key. */
      break;
    case PRIVATE_KEY_SHADOWED:
      if (r_shadow_info)
        {
          const unsigned char *s;
          size_t n;

          err = agent_get_shadow_info (buf, &s);
          if (!err)
            {
              n = gcry_sexp_canon_len (s, 0, NULL, NULL);
              assert (n);
              *r_shadow_info = xtrymalloc (n);
              if (!*r_shadow_info)
                err = gpg_error_from_syserror ();
              else
                memcpy (*r_shadow_info, s, n);
            }
        }
      break;
    default:
      err = gpg_error (GPG_ERR_BAD_SECKEY);
      break;
    }

  if (!err && r_keytype)
    *r_keytype = keytype;

  xfree (buf);
  return err;
}
コード例 #3
0
ファイル: findkey.c プロジェクト: cuidi/gnupg
/* Delete the key with GRIP from the disk after having asked for
   confirmation using DESC_TEXT.  If FORCE is set the function won't
   require a confirmation via Pinentry or warns if the key is also
   used by ssh.

   Common error codes are:
     GPG_ERR_NO_SECKEY
     GPG_ERR_KEY_ON_CARD
     GPG_ERR_NOT_CONFIRMED
*/
gpg_error_t
agent_delete_key (ctrl_t ctrl, const char *desc_text,
                  const unsigned char *grip, int force)
{
  gpg_error_t err;
  gcry_sexp_t s_skey = NULL;
  unsigned char *buf = NULL;
  size_t len;
  char *desc_text_final = NULL;
  char *comment = NULL;
  ssh_control_file_t cf = NULL;
  char hexgrip[40+4+1];
  char *default_desc = NULL;

  err = read_key_file (grip, &s_skey);
  if (gpg_err_code (err) == GPG_ERR_ENOENT)
    err = gpg_error (GPG_ERR_NO_SECKEY);
  if (err)
    goto leave;

  err = make_canon_sexp (s_skey, &buf, &len);
  if (err)
    goto leave;

  switch (agent_private_key_type (buf))
    {
    case PRIVATE_KEY_CLEAR:
    case PRIVATE_KEY_OPENPGP_NONE:
    case PRIVATE_KEY_PROTECTED:
      bin2hex (grip, 20, hexgrip);
      if (!force)
        {
          if (!desc_text)
            {
              default_desc = xtryasprintf
          (L_("Do you really want to delete the key identified by keygrip%%0A"
              "  %s%%0A  %%C%%0A?"), hexgrip);
              desc_text = default_desc;
            }

          /* Note, that we will take the comment as a C string for
             display purposes; i.e. all stuff beyond a Nul character is
             ignored.  */
          {
            gcry_sexp_t comment_sexp;

            comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
            if (comment_sexp)
              comment = gcry_sexp_nth_string (comment_sexp, 1);
            gcry_sexp_release (comment_sexp);
          }

          if (desc_text)
            err = modify_description (desc_text, comment? comment:"", s_skey,
                                      &desc_text_final);
          if (err)
            goto leave;

          err = agent_get_confirmation (ctrl, desc_text_final,
                                        L_("Delete key"), L_("No"), 0);
          if (err)
            goto leave;

          cf = ssh_open_control_file ();
          if (cf)
            {
              if (!ssh_search_control_file (cf, hexgrip, NULL, NULL, NULL))
                {
                  err = agent_get_confirmation
                    (ctrl,
                     L_("Warning: This key is also listed for use with SSH!\n"
                        "Deleting the key might remove your ability to "
                        "access remote machines."),
                     L_("Delete key"), L_("No"), 0);
                  if (err)
                    goto leave;
                }
            }
        }
      err = remove_key_file (grip);
      break;

    case PRIVATE_KEY_SHADOWED:
      err = remove_key_file (grip);
      break;

    default:
      log_error ("invalid private key format\n");
      err = gpg_error (GPG_ERR_BAD_SECKEY);
      break;
    }

 leave:
  ssh_close_control_file (cf);
  gcry_free (comment);
  xfree (desc_text_final);
  xfree (default_desc);
  xfree (buf);
  gcry_sexp_release (s_skey);
  return err;
}