Beispiel #1
0
gboolean sgpgme_has_secret_key(void)
{
	gpgme_error_t err = 0;
	gpgme_ctx_t ctx;
	gpgme_key_t key;

	err = gpgme_new (&ctx);
	if (err) {
		debug_print("err : %s\n", gpgme_strerror(err));
		return TRUE;
	}
check_again:
	err = gpgme_op_keylist_start(ctx, NULL, TRUE);
	if (!err)
		err = gpgme_op_keylist_next(ctx, &key);
	gpgme_op_keylist_end(ctx);
	if (gpg_err_code(err) == GPG_ERR_EOF) {
		if (gpgme_get_protocol(ctx) != GPGME_PROTOCOL_CMS) {
			gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS);
			goto check_again;
		}
		gpgme_release(ctx);
		return FALSE;
	} else {
		gpgme_release(ctx);
		return TRUE;
	}
}
Beispiel #2
0
/* Return a GPGME key object matching PATTERN.  If no key matches or
   the match is ambiguous, return NULL. */
gpgme_key_t 
op_get_one_key (char *pattern)
{
  gpgme_error_t err;
  gpgme_ctx_t ctx;
  gpgme_key_t k, k2;

  err = gpgme_new (&ctx);
  if (err)
    return NULL; /* Error. */
  err = gpgme_op_keylist_start (ctx, pattern, 0);
  if (!err)
    {
      err = gpgme_op_keylist_next (ctx, &k);
      if (!err && !gpgme_op_keylist_next (ctx, &k2))
        {
          /* More than one matching key available.  Return an error
             instead. */
          gpgme_key_release (k);
          gpgme_key_release (k2);
          k = k2 = NULL;
        }
    }
  gpgme_op_keylist_end (ctx);
  gpgme_release (ctx);
  return k;
}
static void
pygpgme_keyiter_dealloc(PyGpgmeKeyIter *self)
{
    if (self->ctx) {
        gpgme_error_t err = gpgme_op_keylist_end(self->ctx->ctx);
        PyObject *exc = pygpgme_error_object(err);

        if (exc != NULL && exc != Py_None) {
            PyErr_WriteUnraisable(exc);
        }
        Py_XDECREF(exc);
        Py_DECREF(self->ctx);
        self->ctx = NULL;
    }
    PyObject_Del(self);
}
Beispiel #4
0
gpgme_key_t GPGWrapper::getKey(const char * identifier, bool isPrivate)
{
    gpgme_key_t result;

    gpgme_error_t error = gpgme_op_keylist_start(context, identifier, isPrivate ? 1 : 0);
    fail_if_err(error, L"Nie uda³o siê zainicjowaæ pobierania klucza.");

    error = gpgme_op_keylist_next(context, &result);
    fail_if_err(error, L"Nie uda³o siê pobraæ klucza.");

    reciversIdToKey[identifier] = result;

    error = gpgme_op_keylist_end(context);
    fail_if_err(error, L"Nie uda³o siê zakoñczyæ pobieranie klucza.");

    return result;
}
Beispiel #5
0
KGpgKeyList KGpgMe::keys(bool privateKeys /* = false */) const
{
	KGpgKeyList keys;
	gpgme_error_t err = 0, err2 = 0;
	gpgme_key_t key = 0;
	gpgme_keylist_result_t result = 0;

	if(m_ctx) {
		err = gpgme_op_keylist_start(m_ctx, NULL, privateKeys);
		if(!err) {
			while(!(err = gpgme_op_keylist_next(m_ctx, &key))) {
				KGpgKey gpgkey;

				if(!key->subkeys)
					continue;
				gpgkey.id = key->subkeys->keyid;
				if(key->uids) {
					gpgkey.name = key->uids->name;
					gpgkey.email = key->uids->email;
				}
				keys.append(gpgkey);
				gpgme_key_unref(key);
			}

			if (gpg_err_code (err) == GPG_ERR_EOF)
				err = 0;
			err2 = gpgme_op_keylist_end(m_ctx);
			if(!err)
				err = err2;
		}
	}

	if(err) {
		KMessageBox::error(kapp->activeWindow(), QString("%1: %2")
			.arg(gpgme_strsource(err)).arg(gpgme_strerror(err)));
	}
	else {
		result = gpgme_op_keylist_result(m_ctx);
		if (result->truncated) {
			KMessageBox::error(kapp->activeWindow(),
				i18n("Key listing unexpectedly truncated."));
		}
	}
	return keys;
}
Beispiel #6
0
int gpg_list_keys(key_entry_t **head) {
    gpgme_ctx_t ctx;
    gpgme_error_t err;
    gpgme_keylist_mode_t mode = 0;

    *head = 0;
    err = gpgme_new(&ctx);
    if (err) {
        return 0;
    }
    gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
    gpgme_set_keylist_mode(ctx, mode);
    err = gpgme_op_keylist_start(ctx, 0, 0);
    if (err) {
        return 0;
    }
    
    int count = 0;
    key_entry_t *key_entry_prev = 0;
    while (1) {
        gpgme_key_t key;
        err = gpgme_op_keylist_next(ctx, &key);
        if (err) {
            break;
        }
        
        key_entry_t *key_entry = g_new(key_entry_t, 1);
        key_entry->next = 0;
        key_entry->key = key;
        
        if (key_entry_prev)
            key_entry_prev->next = key_entry;

        key_entry_prev = key_entry;
        if (!*head) *head = key_entry;
        
        ++count;
    }
    
    gpgme_op_keylist_end(ctx);
    gpgme_release(ctx);
    return count;
}
Beispiel #7
0
/* #############################################################################
 *
 * Description    check if for the given keyname a secret key exists
 * Author         Harry Brueckner
 * Date           2005-04-25
 * Arguments      char* keyname   - the key to check
 * Return         int 1 if there is a secret key, 0 if not and -1 if a gpg
 *                      error occured
 */
int gpgIsSecretKey(char* keyname)
  {
    gpgme_ctx_t         context;
    gpgme_key_t         key;
    gpgme_error_t       error;
    int                 secret = 0;

    TRACE(99, "gpgIsSecretKey()", NULL);

    if (!config -> encryptdata)
      { return 0; }

    /* get a new context */
    error = gpgme_new(&context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return -1;
      }

    /* start cycling through the list of keys */
    error = gpgme_op_keylist_start(context, keyname, LIST_SECRET);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return -1;
      }

    while (!(error = gpgme_op_keylist_next(context, &key)))
      {   /* take the first usable key we find */
        /* TODO: only choose usable secret keys */
        if (key -> can_encrypt &&
            key -> secret &&
            !key -> disabled &&
            !key -> expired &&
            !key -> invalid &&
            !key -> revoked)
          {   /* we just use keys we can encrypt for */
            secret = 1;
          }

        gpgme_key_unref(key);

        if (secret)
          { break; }
      }

    if (error &&
        gpg_err_code(error) != GPG_ERR_EOF)
      {    /* we validate the last value of the 'next' operation */
        gpgme_release(context);
        gpgError(error);
        return -1;
      }

    /* finish the key listing */
    error = gpgme_op_keylist_end(context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return -1;
      }

    gpgme_release(context);

    return secret;
  }
Beispiel #8
0
int 
main (int argc, char **argv)
{
  gpgme_error_t err;
  gpgme_ctx_t ctx;
  gpgme_key_t key;
  gpgme_keylist_result_t result;
  int i = 0;

  init_gpgme (GPGME_PROTOCOL_CMS);

  err = gpgme_new (&ctx);
  fail_if_err (err);
  gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);

  err = gpgme_op_keylist_start (ctx, NULL, 0);
  fail_if_err (err);
    
  while (!(err = gpgme_op_keylist_next (ctx, &key)))
    {
      if (!keys[i].fpr)
	{
	  fprintf (stderr, "More keys returned than expected\n");
	  exit (1);
	}

      if (strcmp (key->subkeys->fpr, keys[i].fpr))
	{
	  fprintf (stderr, "Warning: Skipping unknown key %s\n",
		   key->subkeys->fpr);
	  continue;
	}
      else
	printf ("Checking key %s\n", key->subkeys->fpr);

      /* Global key flags.  */
      if (key->revoked)
	{
	  fprintf (stderr, "Key unexpectedly revoked\n");
	  exit (1);
	}
      if (key->expired)
	{
	  fprintf (stderr, "Key unexpectedly expired\n");
	  exit (1);
	}
      if (key->disabled)
	{
	  fprintf (stderr, "Key unexpectedly disabled\n");
	  exit (1);
	}
      if (key->invalid)
	{
	  fprintf (stderr, "Key unexpectedly invalid\n");
	  exit (1);
	}
      if (key->can_encrypt != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s usable for encryption\n",
		   key->can_encrypt ? "" : " not");
	  exit (1);
	}
      if (key->can_sign != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s usable for signing\n",
		   key->can_sign ? "" : " not");
	  exit (1);
	}
      if (!key->can_certify)
	{
	  fprintf (stderr, "Key unexpectedly unusable for certifications\n");
	  exit (1);
	}
      if (key->secret != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s secret\n",
		   key->secret ? "" : " not");
	  exit (1);
	}
      if (key->protocol != GPGME_PROTOCOL_CMS)
	{
	  fprintf (stderr, "Key has unexpected protocol: %s\n",
		   gpgme_get_protocol_name (key->protocol));
	  exit (1);
	}
      if (!key->issuer_serial)
	{
	  fprintf (stderr, "Key unexpectedly misses issuer serial\n");
	  exit (1);
	}
      if (strcmp (key->issuer_serial, keys[i].issuer_serial))
	{
	  fprintf (stderr, "Key has unexpected issuer serial: %s\n",
		   key->issuer_serial);
	  exit (1);
	}
      if (!key->issuer_name)
	{
	  fprintf (stderr, "Key unexpectedly misses issuer name\n");
	  exit (1);
	}
      if (strcmp (key->issuer_name, keys[i].issuer_name))
	{
	  fprintf (stderr, "Key has unexpected issuer name: %s\n",
		   key->issuer_name);
	  exit (1);
	}
      if (key->chain_id && !keys[i].chain_id)
	{
	  fprintf (stderr, "Key unexpectedly carries chain ID: %s\n",
		   key->chain_id);
	  exit (1);
	}
      if (!key->chain_id && keys[i].chain_id)
	{
	  fprintf (stderr, "Key unexpectedly carries no chain ID\n");
	  exit (1);
	}
      if (key->chain_id && strcmp (key->chain_id, keys[i].chain_id))
	{
	  fprintf (stderr, "Key carries unexpected chain ID: %s\n",
		   key->chain_id);
	  exit (1);
	}
      if (key->owner_trust != GPGME_VALIDITY_UNKNOWN)
	{
	  fprintf (stderr, "Key has unexpected owner trust: %i\n",
		   key->owner_trust);
	  exit (1);
	}
      if (!key->subkeys || key->subkeys->next)
	{
	  fprintf (stderr, "Key has unexpected number of subkeys\n");
	  exit (1);
	}

      /* Primary key.  */
      if (key->subkeys->revoked)
	{
	  fprintf (stderr, "Primary key unexpectedly revoked\n");
	  exit (1);
	}
      if (key->subkeys->expired)
	{
	  fprintf (stderr, "Primary key unexpectedly expired\n");
	  exit (1);
	}
      if (key->subkeys->disabled)
	{
	  fprintf (stderr, "Primary key unexpectedly disabled\n");
	  exit (1);
	}
      if (key->subkeys->invalid)
	{
	  fprintf (stderr, "Primary key unexpectedly invalid\n");
	  exit (1);
	}
      if (key->subkeys->can_encrypt != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s usable for encryption\n",
		   key->subkeys->can_encrypt ? "" : " not");
	  exit (1);
	}
      if (key->subkeys->can_sign != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s usable for signing\n",
		   key->subkeys->can_sign ? "" : " not");
	  exit (1);
	}
      if (!key->subkeys->can_certify)
	{
	  fprintf (stderr, "Primary key unexpectedly unusable for certifications\n");
	  exit (1);
	}
      if (key->subkeys->secret != keys[i].secret)
	{
	  fprintf (stderr, "Primary Key unexpectedly%s secret\n",
		   key->secret ? "" : " not");
	  exit (1);
	}
      if (key->subkeys->pubkey_algo != GPGME_PK_RSA)
	{
	  fprintf (stderr, "Primary key has unexpected public key algo: %s\n",
		   gpgme_pubkey_algo_name (key->subkeys->pubkey_algo));
	  exit (1);
	}
      if (key->subkeys->length != keys[i].key_length)
	{
	  fprintf (stderr, "Primary key has unexpected length: %i\n",
		   key->subkeys->length);
	  exit (1);
	}
      if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16]))
	{
	  fprintf (stderr, "Primary key has unexpected key ID: %s\n",
		   key->subkeys->keyid);
	  exit (1);
	}
      if (strcmp (key->subkeys->fpr, keys[i].fpr))
	{
	  fprintf (stderr, "Primary key has unexpected fingerprint: %s\n",
		   key->subkeys->fpr);
	  exit (1);
	}
      if (key->subkeys->timestamp != keys[i].timestamp)
	{
	  fprintf (stderr, "Primary key unexpected timestamp: %lu\n",
		   key->subkeys->timestamp);
	  exit (1);
	}
      if (key->subkeys->expires != keys[i].expires)
	{
	  fprintf (stderr, "Primary key unexpectedly expires: %lu\n",
		   key->subkeys->expires);
	  exit (1);
	}

      /* Be tolerant against a missing email (ie, older gpgsm versions).  */
      if (!key->uids || (key->uids->next && !keys[i].email))
	{
	  fprintf (stderr, "Key has unexpected number of user IDs\n");
	  exit (1);
	}
      if (key->uids->revoked)
	{
	  fprintf (stderr, "User ID unexpectedly revoked\n");
	  exit (1);
	}
      if (key->uids->invalid)
	{
	  fprintf (stderr, "User ID unexpectedly invalid\n");
	  exit (1);
	}
      if (key->uids->validity != keys[i].validity)
	{
	  fprintf (stderr, "User ID unexpectedly validity: %i\n",
		   key->uids->validity);
	  exit (1);
	}
      if (key->uids->signatures)
	{
	  fprintf (stderr, "User ID unexpectedly signed\n");
	  exit (1);
	}
      if (!key->uids->name || key->uids->name[0])
	{
	  fprintf (stderr, "Unexpected name in user ID: %s\n",
		   key->uids->name);
	  exit (1);
	}
      if (!key->uids->comment || key->uids->comment[0])
	{
	  fprintf (stderr, "Unexpected comment in user ID: %s\n",
		   key->uids->comment);
	  exit (1);
	}
      if (!key->uids->email || key->uids->email[0])
	{
	  fprintf (stderr, "Unexpected email in user ID: %s\n",
		   key->uids->email);
	  exit (1);
	}
      if (!key->uids->uid || strcmp (key->uids->uid, keys[i].uid))
	{
	  fprintf (stderr, "Unexpected uid in user ID: %s\n",
		   key->uids->uid);
	  exit (1);
	}
      if (key->uids->next && strcmp (key->uids->next->uid, keys[i].email))
	{
	  fprintf (stderr, "Unexpected email in user ID: %s\n",
		   key->uids->next->uid);
	  exit (1);
	}
      if (key->uids->next && strcmp (key->uids->next->uid, keys[i].email))
	{
	  fprintf (stderr, "Unexpected email in user ID: %s\n",
		   key->uids->next->uid);
	  exit (1);
	}



      gpgme_key_unref (key);
      i++;
    }
  if (gpg_err_code (err) != GPG_ERR_EOF)
    fail_if_err (err);
  err = gpgme_op_keylist_end (ctx);
  fail_if_err (err);

  result = gpgme_op_keylist_result (ctx);
  if (result->truncated)
    {
      fprintf (stderr, "Key listing unexpectedly truncated\n");
      exit (1);
    }

  if (keys[i].fpr)
    {
      fprintf (stderr, "Less keys returned than expected\n");
      exit (1);
    }

  gpgme_release (ctx);
  return 0;
}
Beispiel #9
0
/* Get the GPG key for the given name or ID.
*/
int
get_gpg_key(fko_ctx_t fko_ctx, gpgme_key_t *mykey, const int signer)
{
    int             res;
    const char     *name;

    gpgme_ctx_t     list_ctx    = NULL;
    gpgme_key_t     key         = NULL;
    gpgme_key_t     key2        = NULL;
    gpgme_error_t   err;

    /* Create a gpgme context for the list
    */
    /* Initialize gpgme
    */
    res = init_gpgme(fko_ctx);
    if(res != FKO_SUCCESS)
    {
        if(signer)
            return(FKO_ERROR_GPGME_CONTEXT_SIGNER_KEY);
        else
            return(FKO_ERROR_GPGME_CONTEXT_RECIPIENT_KEY);
    }

    list_ctx = fko_ctx->gpg_ctx;

    if(signer)
        name = fko_ctx->gpg_signer;
    else
        name = fko_ctx->gpg_recipient;

    err = gpgme_op_keylist_start(list_ctx, name, signer);
    if (err)
    {
        gpgme_release(list_ctx);

        fko_ctx->gpg_err = err;

        if(signer)
            return(FKO_ERROR_GPGME_SIGNER_KEYLIST_START);
        else
            return(FKO_ERROR_GPGME_RECIPIENT_KEYLIST_START);
    }

    /* Grab the first key in the list (we hope it is the only one).
    */
    err = gpgme_op_keylist_next(list_ctx, &key);
    if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
    {
        /* Key not found
        */
        fko_ctx->gpg_err = err;

        if(signer)
            return(FKO_ERROR_GPGME_SIGNER_KEY_NOT_FOUND);
        else
            return(FKO_ERROR_GPGME_RECIPIENT_KEY_NOT_FOUND);
    }

    /* We try to get the next key match. If we do, then the name is
     * ambiguous, so we return an error.
    */
    err = gpgme_op_keylist_next(list_ctx, &key2);
    if(gpg_err_code(err) == GPG_ERR_NO_ERROR) /* Note: look for NO error */
    {
        /* Ambiguous specfication of key
        */
        gpgme_key_unref(key);
        gpgme_key_unref(key2);

        fko_ctx->gpg_err = err;

        if(signer)
            return(FKO_ERROR_GPGME_SIGNER_KEY_AMBIGUOUS);
        else
            return(FKO_ERROR_GPGME_RECIPIENT_KEY_AMBIGUOUS);
    }

    gpgme_op_keylist_end(list_ctx);

    gpgme_key_unref(key2);

    *mykey = key;

    return(FKO_SUCCESS);
}
Beispiel #10
0
static gpgme_key_t
pkcs7_get_key_by_name (Pkcs7Ctx *pkcs7, const char *name, gboolean secret, GError **err)
{
	time_t now = time (NULL);
	gpgme_key_t key = NULL;
	gpgme_subkey_t subkey;
	gboolean bad = FALSE;
	gpgme_error_t error;
	int errval = 0;
	
	if ((error = gpgme_op_keylist_start (pkcs7->ctx, name, secret)) != GPG_ERR_NO_ERROR) {
		if (secret)
			g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not list secret keys for \"%s\""), name);
		else
			g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not list keys for \"%s\""), name);
		return NULL;
	}
	
	while ((error = gpgme_op_keylist_next (pkcs7->ctx, &key)) == GPG_ERR_NO_ERROR) {
		/* check if this key and the relevant subkey are usable */
		if (KEY_IS_OK (key)) {
			subkey = key->subkeys;
			
			while (subkey && ((secret && !subkey->can_sign) ||
					  (!secret && !subkey->can_encrypt)))
				subkey = subkey->next;
			
			if (subkey && KEY_IS_OK (subkey) && 
			    (subkey->expires == 0 || subkey->expires > now))
				break;
			
			if (subkey->expired)
				errval = GPG_ERR_KEY_EXPIRED;
			else
				errval = GPG_ERR_BAD_KEY;
		} else {
			if (key->expired)
				errval = GPG_ERR_KEY_EXPIRED;
			else
				errval = GPG_ERR_BAD_KEY;
		}
		
		gpgme_key_unref (key);
		bad = TRUE;
		key = NULL;
	}
	
	gpgme_op_keylist_end (pkcs7->ctx);
	
	if (error != GPG_ERR_NO_ERROR && error != GPG_ERR_EOF) {
		if (secret)
			g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not list secret keys for \"%s\""), name);
		else
			g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not list keys for \"%s\""), name);
		
		return NULL;
	}
	
	if (!key) {
		if (strchr (name, '@')) {
			if (bad)
				g_set_error (err, GMIME_GPGME_ERROR, errval,
					     _("A key for %s is present, but it is expired, disabled, revoked or invalid"),
					     name);
			else
				g_set_error (err, GMIME_GPGME_ERROR, GPG_ERR_NOT_FOUND,
					     _("Could not find a key for %s"), name);
		} else {
			if (bad)
				g_set_error (err, GMIME_GPGME_ERROR, errval,
					     _("A key with id %s is present, but it is expired, disabled, revoked or invalid"),
					     name);
			else
				g_set_error (err, GMIME_GPGME_ERROR, GPG_ERR_NOT_FOUND,
					     _("Could not find a key with id %s"), name);
		}
		
		return NULL;
	}
	
	return key;
}
Beispiel #11
0
    void crypto_asym::build_key_list(const vector<string> & recipients_email, gpgme_key_t * & ciphering_keys, bool signatories)
    {
	U_I size = recipients_email.size() + 1;

	ciphering_keys = new (nothrow) gpgme_key_t[size];
	if(ciphering_keys == NULL)
	    throw Ememory("crypto_asym::build_key_list");

	    // clearing all fields in order to be able to know which
	    // index has been allocated and need to be restored in case of error
	for(U_I i = 0; i < size ; ++i)
	    ciphering_keys[i] = NULL;

	try
	{
	    gpgme_error_t err = GPG_ERR_NO_ERROR;
	    gpgme_user_id_t id = NULL;
	    bool found = false;
	    bool eof = false;
	    bool loop = false;
	    U_I offset = 0;

		// for each recipient, listing all keys to find a match

	    for(U_I i = 0; i < recipients_email.size(); ++i)
	    {
		err = gpgme_op_keylist_start(context, NULL, 0);
		switch(gpgme_err_code(err))
		{
		case GPG_ERR_NO_ERROR:
		    break;
		case GPG_ERR_INV_VALUE:
		    throw SRC_BUG;
		default:
		    throw Erange("crypto_asym::decrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err));
		}

		found = false;
		eof = false;
		do
		{
			// getting the next key

		    err = gpgme_op_keylist_next(context, &(ciphering_keys[i - offset]));
		    switch(gpgme_err_code(err))
		    {
		    case GPG_ERR_EOF:
			eof = true;
			break;
		    case GPG_ERR_NO_ERROR:
			id = ciphering_keys[i - offset]->uids;
			loop = true;

			    // for each key, listing all identies associated with it to find a match
			do
			{
			    found = (strncmp(recipients_email[i].c_str(), id->email, recipients_email[i].size()) == 0);

			    if(found)
			    {
				if(ciphering_keys[i - offset]->revoked
				   || ciphering_keys[i - offset]->expired
				   || ciphering_keys[i - offset]->disabled
				   || ciphering_keys[i - offset]->invalid)
				    found = false;
				if(signatories)
				{
				    if(!ciphering_keys[i - offset]->can_sign)
					found = false;
				}
				else
				{
				    if(!ciphering_keys[i - offset]->can_encrypt)
					found = false;
				}
			    }

			    if(!found && id->next != NULL)
				id = id->next;
			    else
				loop = false;
			}
			while(loop);

			    // if not identity match found for that key deleting the key

			if(!found)
			{
			    gpgme_key_unref(ciphering_keys[i - offset]);
			    ciphering_keys[i - offset] = NULL;
			}
			break;
		    default:
			throw Erange("crypto_asym::decrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err));
		    }
		}
		while(!found && !eof);

		    // if we exit before gpgme_op_keylist_next() return GPG_ERR_EOF
		    // we must update the state of the context to end the key listing operation

		if(!eof)
		    (void)gpgme_op_keylist_end(context);

		if(!found)
		{
		    if(signatories)
			get_ui().printf(gettext("No valid signing key could be find for %S"), &(recipients_email[i]));
		    else
			get_ui().printf(gettext("No valid encryption key could be find for %S"), &(recipients_email[i]));
		    get_ui().pause("Do you want to continue without this recipient?");
		    ++offset;
		}
	    }

		// if no recipient could be found at all aborting the operation

	    if(offset + 1 >= size)
	    {
		if(signatories)
		    throw Erange("crypto_asym::build_key_list", gettext("No signatory remain with a valid key, signing is impossible, aborting"));
		else
		    throw Erange("crypto_asym::build_key_list", gettext("No recipient remain with a valid key, encryption is impossible, aborting"));
	    }

		// the key list must end wth a NULL entry

	    if(ciphering_keys[size - 1 - offset] != NULL)
		throw SRC_BUG;
	}
	catch(...)
	{
	    release_key_list(ciphering_keys);
	    throw;
	}
    }
Beispiel #12
0
/* Try to find a key for each item in array NAMES. Items not found are
   stored as malloced strings in the newly allocated array UNKNOWN.
   Found keys are stored in the newly allocated array KEYS.  Both
   arrays are terminated by a NULL entry.  Caller needs to release
   KEYS and UNKNOWN.

   Returns: 0 on success. However success may also be that one or all
   keys are unknown.
*/
int 
op_lookup_keys (char **names, gpgme_key_t **keys, char ***unknown)
{
  gpgme_error_t err;
  gpgme_ctx_t ctx;
  size_t n;
  int i, kpos, upos;
  gpgme_key_t k, k2;

  *keys = NULL;
  *unknown = NULL;

  err = gpgme_new (&ctx);
  if (err)
    return -1; /* Error. */

  for (n=0; names[n]; n++)
    ;

  *keys =  xcalloc (n+1, sizeof *keys);
  *unknown = xcalloc (n+1, sizeof *unknown);

  for (i=kpos=upos=0; names[i]; i++)
    {
      k = NULL;
      err = gpgme_op_keylist_start (ctx, names[i], 0);
      if (!err)
        {
          err = gpgme_op_keylist_next (ctx, &k);
          if (!err && !gpgme_op_keylist_next (ctx, &k2))
            {
              /* More than one matching key available.  Take this one
                 as unknown. */
              gpgme_key_release (k);
              gpgme_key_release (k2);
              k = k2 = NULL;
            }
        }
      gpgme_op_keylist_end (ctx);

      
      /* only useable keys will be added otherwise they will be stored
         in unknown (marked with their status). */
      if (k && !k->revoked && !k->disabled && !k->expired)
        (*keys)[kpos++] = k;
      else if (k)
	{
	  char *p, *fmt = "%s (%s)";
	  char *warn = k->revoked? "revoked" : k->expired? "expired" : "disabled";
	  
	  p = xcalloc (1, strlen (names[i]) + strlen (warn) + strlen (fmt) +1);
	  sprintf (p, fmt, names[i], warn);
	  (*unknown)[upos++] = p;
	  gpgme_key_release (k);
	}
      else if (!k)
        (*unknown)[upos++] = xstrdup (names[i]);
    }

  gpgme_release (ctx);
  return 0;
}
Beispiel #13
0
void GPGME::encryptBytesToFile(const QByteArray & data, const QString & filename, const QString & keyId)
{
    setError(GPG_ERR_NO_ERROR); // clear error
    qDebug() << "Encrypt data to file" << filename;
    gpgme_error_t err;

    // check data size
    if (data.size() > FILESIZE_HARD_LIMIT) {
        setError(GPGME_WRAPPER_ERR_DATA_TOO_LARGE, true);
        return;
    }

    // list all available keys and find the appropriate
    err = gpgme_op_keylist_start(p->context, keyId.toLatin1().data(), 0);
    gpgme_key_t key = 0;
    gpgme_key_t loop_key = 0;
    int foundCount = 0;

    while (1) {
        err = gpgme_op_keylist_next(p->context, &loop_key);
        if (err != GPG_ERR_NO_ERROR) {
            break;
        }
        qDebug() << "KEY FOUND";
        if (loop_key != 0) {
            key = loop_key;
        }
        foundCount++;
    }
    gpgme_op_keylist_end(p->context);

    if (foundCount > 1) {
        setError(GPGME_WRAPPER_ERR_MORE_THAN_ONE_KEY_FOUND);
        return;
    }

    if (key == 0) {
        // key not found
        setError(GPGME_WRAPPER_ERR_CANNOT_FIND_KEY, true);
        return;
    }

    // if filename ends with ".asc" then use armored output, otherwise use binary
    if (filename.toLower().endsWith(".asc")) {
        // use armored output
        gpgme_set_armor(p->context, 1);
        qDebug() << "Encode: use armored output";
    }

    gpgme_data_t cipher;
    gpgme_data_t plain;

    gpgme_data_new_from_mem(&plain, data.data(), data.size(), 0); // do not copy data
    
    // backup file contents
    QFile file(filename);
    if (!file.open(QIODevice::ReadOnly)) {
        setError(GPGME_WRAPPER_ERR_CANNOT_OPEN_FILE, true);
        return;
    }
    if (file.size() > FILESIZE_HARD_LIMIT) {
        setError(GPGME_WRAPPER_ERR_FILE_TOO_LARGE, true);
        return;
    }
    QByteArray cipherBackup = file.readAll();
    file.close();
    
    // prepare file for writing
    if (!file.open(QIODevice::WriteOnly)) {
        setError(GPGME_WRAPPER_ERR_CANNOT_OPEN_FILE, true);
        return;
    }

    err = gpgme_data_new_from_fd(&cipher, file.handle());
    if (err != GPG_ERR_NO_ERROR) {
        setError(err);
        return;
    }

    gpgme_key_t keys[2];
    keys[0] = key;
    keys[1] = 0;

    err = gpgme_op_encrypt(p->context, keys, static_cast<gpgme_encrypt_flags_t>(GPGME_ENCRYPT_ALWAYS_TRUST), plain, cipher);
    if (err != GPG_ERR_NO_ERROR) {
        // revert file contents in case of error
        file.resize(0);
        file.write(cipherBackup);
        setError(err);
    }
    file.close();
}
Beispiel #14
0
/* #############################################################################
 *
 * Description    validate the given encryption key
 * Author         Harry Brueckner
 * Date           2005-03-31
 * Arguments      char* key   - the key to validate
 * Return         char* NULL on error, otherwise the name and mail address
 */
char* gpgValidateEncryptionKey(char* keyname)
  {
    gpgme_ctx_t         context;
    gpgme_key_t         key;
    gpgme_error_t       error;
    int                 secret,
                        size;
    char*               identifier = NULL;
    char*               tcomment;
    char*               tname;

    TRACE(99, "gpgValidateEncryptionKey()", NULL);

    if (!config -> encryptdata)
      { return NULL; }

    /* get a new context */
    error = gpgme_new(&context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    for (secret = 1; secret >= 0 && !identifier; secret--)
      {
        /* start cycling through the list of keys */
        error = gpgme_op_keylist_start(context, keyname,
            (secret == 1) ? LIST_SECRET : LIST_ALL);
        if (error)
          {
            gpgme_release(context);
            gpgError(error);
            return NULL;
          }

        while (!(error = gpgme_op_keylist_next(context, &key)))
          {   /* take the first key we find */
#ifdef TEST_OPTION
  #ifdef KEY_DEBUG
            gpgDebugKey(key);
  #endif
#endif
            if (key -> can_encrypt &&
                !key -> disabled &&
                !key -> expired &&
                !key -> invalid &&
                !key -> revoked)
              {   /* we just use keys we can encrypt for and sign with */
                tname = convert2terminal((unsigned char*)key -> uids -> name);
                if (key -> uids -> comment)
                  { tcomment = key -> uids -> comment; }
                else
                  { tcomment = NULL; }

                if (tcomment && strlen(tcomment))
                  {   /* a comment exists for this key */
                    size = strlen(key -> subkeys -> keyid) + 1 +
                        strlen(tname) + 1 +
                        strlen(tcomment) + 2 + 1 +
                        strlen(key -> uids -> email) + 2 + 1;
                    identifier = memAlloc(__FILE__, __LINE__, size);
                    snprintf(identifier, size, "%s %s (%s) <%s>",
                        key -> subkeys -> keyid,
                        tname,
                        tcomment,
                        key -> uids -> email);
                  }
                else
                  {   /* no comment exists */
                    size = strlen(key -> subkeys -> keyid) + 1 +
                        strlen(tname) + 1 +
                        strlen(key -> uids -> email) + 2 + 1;
                    identifier = memAlloc(__FILE__, __LINE__, size);
                    snprintf(identifier, size, "%s %s <%s>",
                        key -> subkeys -> keyid,
                        tname,
                        key -> uids -> email);
                  }
              }

            gpgme_key_unref(key);

            if (identifier)
              { break; }
          }

        if (error &&
            gpg_err_code(error) != GPG_ERR_EOF)
          {    /* we validate the last value of the 'next' operation */
            gpgme_release(context);
            gpgError(error);
            return NULL;
          }
      }

    /* finish the key listing */
    error = gpgme_op_keylist_end(context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    gpgme_release(context);

    return identifier;
  }
Beispiel #15
0
gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account,
			      const gchar *from_addr)
{
	GPGAccountConfig *config;
	const gchar *signer_addr = account->address;

	gpgme_signers_clear(ctx);

	if (from_addr)
		signer_addr = from_addr;
	config = prefs_gpg_account_get_config(account);

	switch(config->sign_key) {
	case SIGN_KEY_DEFAULT:
		debug_print("using default gnupg key\n");
		break;
	case SIGN_KEY_BY_FROM:
		debug_print("using key for %s\n", signer_addr);
		break;
	case SIGN_KEY_CUSTOM:
		debug_print("using key for %s\n", config->sign_key_id);
		break;
	}

	if (config->sign_key != SIGN_KEY_DEFAULT) {
		const gchar *keyid;
		gpgme_key_t key, key2;
		gpgme_error_t err;

		if (config->sign_key == SIGN_KEY_BY_FROM)
			keyid = signer_addr;
		else if (config->sign_key == SIGN_KEY_CUSTOM)
			keyid = config->sign_key_id;
		else
			goto bail;

		err = gpgme_op_keylist_start(ctx, keyid, 1);
		if (!err) {
			do {
				err = gpgme_op_keylist_next(ctx, &key);
				if (!err && key && key->protocol == gpgme_get_protocol(ctx) &&
				    !key->expired && !key->revoked && !key->disabled)
					break;
				if (!err && key && key->protocol != gpgme_get_protocol(ctx)) {
					debug_print("skipping a key (wrong protocol %d)\n", key->protocol);
					gpgme_key_release(key);
				}
				if (!err && key && (key->expired || key->revoked || key->disabled)) {
					
					debug_print("skipping a key");
					if (key->expired) 
						debug_print(" expired");
					if (key->revoked) 
						debug_print(" revoked");
					if (key->disabled) 
						debug_print(" disabled");
					debug_print("\n");
					gpgme_key_release(key);
				}
			} while (!err);
		}
		if (err) {
			g_warning("setup_signers start: %s", gpgme_strerror(err));
			privacy_set_error(_("Secret key not found (%s)"), gpgme_strerror(err));
			goto bail;
		}
		
		do {
			err = gpgme_op_keylist_next(ctx, &key2);
			if (!err && key2 && key2->protocol == gpgme_get_protocol(ctx) &&
			    !key2->expired && !key2->revoked && !key2->disabled)
				break;
			if (!err && key2 && key2->protocol != gpgme_get_protocol(ctx)) {
				debug_print("skipping a key (wrong protocol %d)\n", key2->protocol);
				gpgme_key_release(key2);
			}
			if (!err && key2 && (key2->expired || key2->revoked || key2->disabled)) {
					debug_print("skipping a key");
					if (key2->expired) 
						debug_print(" expired");
					if (key2->revoked) 
						debug_print(" revoked");
					if (key2->disabled) 
						debug_print(" disabled");
					debug_print("\n");
				gpgme_key_release(key2);
			}
		} while (!err);
		if (!err) {
			gpgme_key_release(key2);
			g_warning("ambiguous specification of secret key '%s'\n",
				keyid);
			privacy_set_error(_("Secret key specification is ambiguous"));
			goto bail;
		}
		
		gpgme_op_keylist_end(ctx);
		err = gpgme_signers_add(ctx, key);
		debug_print("got key (proto %d (pgp %d, smime %d).\n", key->protocol,
				GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_CMS);
		gpgme_key_release(key);
		
		if (err) {
			g_warning("error adding secret key: %s\n", gpgme_strerror(err));
			privacy_set_error(_("Error setting secret key: %s"), gpgme_strerror(err));
			goto bail;
		}
	}

	prefs_gpg_account_free_config(config);

	return TRUE;
bail:
	prefs_gpg_account_free_config(config);
	return FALSE;
}
Beispiel #16
0
/* #############################################################################
 *
 * Description    find a fingerprint for the given key
 * Author         Harry Brueckner
 * Date           2005-04-07
 * Arguments      keyname       - description string
 *                secret_only   - if set to 1, only secret keys are listed
 * Return         char* with the found fingerprint; the string must be freed
 *                by the caller
 */
char* gpgGetFingerprint(char* keyname, int secret_only)
  {
    gpgme_ctx_t         context;
    gpgme_key_t         key;
    gpgme_error_t       error;
    char*               identifier = NULL;

    TRACE(99, "gpgGetFingerprint()", NULL);

    if (!config -> encryptdata)
      { return NULL; }

    /* get a new context */
    error = gpgme_new(&context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    /* start cycling through the list of keys */
    error = gpgme_op_keylist_start(context, keyname, secret_only);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    /* first we look for secret keys */
    while (!identifier &&
        !(error = gpgme_op_keylist_next(context, &key)))
      {   /* take the first key we find */
        if (!identifier &&
            !key -> disabled &&
            !key -> expired &&
            !key -> invalid &&
            !key -> revoked)
          {   /* we just use keys we can encrypt for */
            identifier = memAlloc(__FILE__, __LINE__,
                strlen(key -> subkeys -> fpr) + 1);
            strStrncpy(identifier, key -> subkeys -> fpr,
                strlen(key -> subkeys -> fpr) + 1);
          }

        gpgme_key_unref(key);
      }

    if (error &&
        gpg_err_code(error) != GPG_ERR_EOF)
      {    /* we validate the last value of the 'next' operation */
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    /* finish the key listing */
    error = gpgme_op_keylist_end(context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    gpgme_release(context);

    return identifier;
  }
Beispiel #17
0
int
main (int argc, char **argv)
{
  int last_argc = -1;
  gpgme_error_t err;
  gpgme_ctx_t ctx;
  gpgme_key_t key;
  gpgme_keylist_result_t result;
  gpgme_key_t keyarray[100];
  int keyidx = 0;
  gpgme_data_t out;
  gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
  gpgme_export_mode_t mode = 0;

  if (argc)
    { argc--; argv++; }

  while (argc && last_argc != argc )
    {
      last_argc = argc;
      if (!strcmp (*argv, "--"))
        {
          argc--; argv++;
          break;
        }
      else if (!strcmp (*argv, "--help"))
        show_usage (0);
      else if (!strcmp (*argv, "--verbose"))
        {
          verbose = 1;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--openpgp"))
        {
          protocol = GPGME_PROTOCOL_OpenPGP;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--cms"))
        {
          protocol = GPGME_PROTOCOL_CMS;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--extern"))
        {
          mode |= GPGME_EXPORT_MODE_EXTERN;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--secret"))
        {
          mode |= GPGME_EXPORT_MODE_SECRET;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--raw"))
        {
          mode |= GPGME_EXPORT_MODE_RAW;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--pkcs12"))
        {
          mode |= GPGME_EXPORT_MODE_PKCS12;
          argc--; argv++;
        }
      else if (!strncmp (*argv, "--", 2))
        show_usage (1);

    }

  if (!argc)
    show_usage (1);

  init_gpgme (protocol);

  err = gpgme_new (&ctx);
  fail_if_err (err);
  gpgme_set_protocol (ctx, protocol);

  /* Lookup the keys.  */
  err = gpgme_op_keylist_ext_start (ctx, (const char**)argv, 0, 0);
  fail_if_err (err);

  while (!(err = gpgme_op_keylist_next (ctx, &key)))
    {
      printf ("keyid: %s  (fpr: %s)\n",
              key->subkeys?nonnull (key->subkeys->keyid):"?",
              key->subkeys?nonnull (key->subkeys->fpr):"?");

      if (keyidx < DIM (keyarray)-1)
        keyarray[keyidx++] = key;
      else
        {
          fprintf (stderr, PGM": too many keys"
                   "- skipping this key\n");
          gpgme_key_unref (key);
        }
    }
  if (gpgme_err_code (err) != GPG_ERR_EOF)
    fail_if_err (err);
  err = gpgme_op_keylist_end (ctx);
  fail_if_err (err);
  keyarray[keyidx] = NULL;

  result = gpgme_op_keylist_result (ctx);
  if (result->truncated)
    {
      fprintf (stderr, PGM ": key listing unexpectedly truncated\n");
      exit (1);
    }

  /* Now for the actual export.  */
  if ((mode & GPGME_EXPORT_MODE_EXTERN))
    printf ("sending keys to keyserver\n");
  if ((mode & GPGME_EXPORT_MODE_SECRET))
    printf ("exporting secret keys!\n");

  err = gpgme_data_new (&out);
  fail_if_err (err);

  gpgme_set_armor (ctx, 1);
  err = gpgme_op_export_keys (ctx, keyarray, mode,
                              (mode & GPGME_KEYLIST_MODE_EXTERN)? NULL:out);
  fail_if_err (err);

  fflush (NULL);
  if (!(mode & GPGME_KEYLIST_MODE_EXTERN))
    {
      fputs ("Begin Result:\n", stdout);
      print_data (out);
      fputs ("End Result.\n", stdout);
    }

  /* Cleanup.  */
  gpgme_data_release (out);

  for (keyidx=0; keyarray[keyidx]; keyidx++)
    gpgme_key_unref (keyarray[keyidx]);

  gpgme_release (ctx);
  return 0;
}
Beispiel #18
0
gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account,
			      const gchar *from_addr)
{
	GPGAccountConfig *config;
	const gchar *signer_addr = account->address;

	gpgme_signers_clear(ctx);

	if (from_addr)
		signer_addr = from_addr;
	config = prefs_gpg_account_get_config(account);

	switch(config->sign_key) {
	case SIGN_KEY_DEFAULT:
		debug_print("using default gnupg key\n");
		break;
	case SIGN_KEY_BY_FROM:
		debug_print("using key for %s\n", signer_addr);
		break;
	case SIGN_KEY_CUSTOM:
		debug_print("using key for %s\n", config->sign_key_id);
		break;
	}

	if (config->sign_key != SIGN_KEY_DEFAULT) {
		const gchar *keyid;
		gpgme_key_t key, found_key;
		gpgme_error_t err;

		if (config->sign_key == SIGN_KEY_BY_FROM)
			keyid = signer_addr;
		else if (config->sign_key == SIGN_KEY_CUSTOM)
			keyid = config->sign_key_id;
		else
			goto bail;

                found_key = NULL;
		/* Look for any key, not just private ones, or GPGMe doesn't
		 * correctly set the revoked flag. */
		err = gpgme_op_keylist_start(ctx, keyid, 0);
		while ((err = gpgme_op_keylist_next(ctx, &key)) == 0) {
			if (key == NULL)
				continue;

			if (!key->can_sign)
				continue;

			if (key->protocol != gpgme_get_protocol(ctx)) {
				debug_print("skipping a key (wrong protocol %d)\n", key->protocol);
				gpgme_key_release(key);
				continue;
			}

			if (key->expired) {
				debug_print("skipping a key, expired");
				gpgme_key_release(key);
				continue;
			}
			if (key->revoked) {
				debug_print("skipping a key, revoked");
				gpgme_key_release(key);
				continue;
			}
			if (key->disabled) {
				debug_print("skipping a key, disabled");
				gpgme_key_release(key);
				continue;
			}

			if (found_key != NULL) {
				gpgme_key_release(key);
				gpgme_op_keylist_end(ctx);
				g_warning("ambiguous specification of secret key '%s'\n", keyid);
				privacy_set_error(_("Secret key specification is ambiguous"));
				goto bail;
			}

			found_key = key;
                }
		gpgme_op_keylist_end(ctx);

		if (found_key == NULL) {
			g_warning("setup_signers start: %s", gpgme_strerror(err));
			privacy_set_error(_("Secret key not found (%s)"), gpgme_strerror(err));
			goto bail;
                }

		err = gpgme_signers_add(ctx, found_key);
		debug_print("got key (proto %d (pgp %d, smime %d).\n",
			    found_key->protocol, GPGME_PROTOCOL_OpenPGP,
			    GPGME_PROTOCOL_CMS);
		gpgme_key_release(found_key);

		if (err) {
			g_warning("error adding secret key: %s\n",
				  gpgme_strerror(err));
			privacy_set_error(_("Error setting secret key: %s"),
					  gpgme_strerror(err));
			goto bail;
		}
        }

	prefs_gpg_account_free_config(config);

	return TRUE;
bail:
	prefs_gpg_account_free_config(config);
	return FALSE;
}
Beispiel #19
0
static gpgme_key_t
get_key_from_name(gpgme_ctx_t ctx, const gchar * name, gboolean secret,
		  gboolean accept_all, GtkWindow * parent, GError ** error)
{
    GList *keys = NULL;
    gpgme_key_t key;
    gpgme_error_t err;
    gboolean found_bad;
    time_t now = time(NULL);

    /* let gpgme list keys */
    if ((err =
	 gpgme_op_keylist_start(ctx, name, secret)) != GPG_ERR_NO_ERROR) {
	gchar *msg =
	    g_strdup_printf(_("could not list keys for \"%s\""), name);

	g_set_error_from_gpgme(error, err, msg);
	g_free(msg);
	return NULL;
    }

    found_bad = FALSE;
    while ((err = gpgme_op_keylist_next(ctx, &key)) == GPG_ERR_NO_ERROR) {
	/* check if this key and the relevant subkey are usable */
	if (KEY_IS_OK(key)) {
	    gpgme_subkey_t subkey = key->subkeys;

	    while (subkey && ((secret && !subkey->can_sign) ||
			      (!secret && !subkey->can_encrypt)))
		subkey = subkey->next;

	    if (subkey && KEY_IS_OK(subkey) &&
		(subkey->expires == 0 || subkey->expires > now))
		keys = g_list_append(keys, key);
	    else
		found_bad = TRUE;
	} else
	    found_bad = TRUE;
    }

    if (gpg_err_code(err) != GPG_ERR_EOF) {
	gchar *msg =
	    g_strdup_printf(_("could not list keys for \"%s\""), name);

	g_set_error_from_gpgme(error, err, msg);
	g_free(msg);
	gpgme_op_keylist_end(ctx);
	g_list_foreach(keys, (GFunc) gpgme_key_unref, NULL);
	g_list_free(keys);
	return NULL;
    }
    gpgme_op_keylist_end(ctx);

    if (!keys) {
	if (error) {
	    if (strchr(name, '@')) {
		if (found_bad)
		    g_set_error(error, GPGME_ERROR_QUARK,
				GPG_ERR_KEY_SELECTION,
				_
				("%s: a key for %s is present, but it is expired, disabled, revoked or invalid"),
				"gmime-gpgme", name);
		else
		    g_set_error(error, GPGME_ERROR_QUARK,
				GPG_ERR_KEY_SELECTION,
				_("%s: could not find a key for %s"),
				"gmime-gpgme", name);
	    } else {
		if (found_bad)
		    g_set_error(error, GPGME_ERROR_QUARK,
				GPG_ERR_KEY_SELECTION,
				_
				("%s: a key with id %s is present, but it is expired, disabled, revoked or invalid"),
				"gmime-gpgme", name);
		else
		    g_set_error(error, GPGME_ERROR_QUARK,
				GPG_ERR_KEY_SELECTION,
				_("%s: could not find a key with id %s"),
				"gmime-gpgme", name);
	    }
	}
	return NULL;
    }

    /* let the user select a key from the list if there is more than one */
    if (g_list_length(keys) > 1) {
	if (select_key_cb)
	    key =
		select_key_cb(name, secret, keys, gpgme_get_protocol(ctx),
			      parent);
	else {
	    if (error)
		g_set_error(error, GPGME_ERROR_QUARK,
			    GPG_ERR_KEY_SELECTION,
			    _("%s: multiple keys for %s"), "gmime-gpgme",
			    name);
	    key = NULL;
	}
	if (key)
	    gpgme_key_ref(key);
	g_list_foreach(keys, (GFunc) gpgme_key_unref, NULL);
    } else
	key = (gpgme_key_t) keys->data;
    g_list_free(keys);

    /* OpenPGP: ask the user if a low-validity key should be trusted for
     * encryption */
    // FIXME - shouldn't we do the same for S/MIME?
    if (key && !secret && !accept_all
	&& gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) {
	gpgme_user_id_t uid = key->uids;
	gchar *upcase_name = g_ascii_strup(name, -1);
	gboolean found = FALSE;

	while (!found && uid) {
	    /* check the email field which may or may not be present */
	    if (uid->email && !g_ascii_strcasecmp(uid->email, name))
		found = TRUE;
	    else {
		/* no email or no match, check the uid */
		gchar *upcase_uid = g_ascii_strup(uid->uid, -1);

		if (strstr(upcase_uid, upcase_name))
		    found = TRUE;
		else
		    uid = uid->next;
		g_free(upcase_uid);
	    }
	}
	g_free(upcase_name);

	/* ask the user if a low-validity key shall be used */
	if (uid && uid->validity < GPGME_VALIDITY_FULL) {
	    if (!accept_low_trust_cb
		|| !accept_low_trust_cb(name, uid, parent)) {
		gpgme_key_unref(key);
		key = NULL;
		if (error)
		    g_set_error(error, GPGME_ERROR_QUARK,
				GPG_ERR_KEY_SELECTION,
				_("%s: insufficient validity for uid %s"),
				"gmime-gpgme", name);
	    }
	}
    }

    return key;
}
Beispiel #20
0
static gpgme_key_t 
fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t proto)
{
    GtkCMCList *clist;
    gpgme_ctx_t ctx;
    gpgme_error_t err;
    gpgme_key_t key;
    int running=0;
    int num_results = 0;
    gboolean exact_match = FALSE;
    gpgme_key_t last_key = NULL;
    gpgme_user_id_t last_uid = NULL;
    cm_return_val_if_fail (sk, NULL);
    clist = sk->clist;
    cm_return_val_if_fail (clist, NULL);

    debug_print ("select_keys:fill_clist:  pattern '%s' proto %d\n", pattern, proto);

    /*gtk_cmclist_freeze (select_keys.clist);*/
    err = gpgme_new (&ctx);
    g_assert (!err);

    gpgme_set_protocol(ctx, proto);
    sk->select_ctx = ctx;

    update_progress (sk, ++running, pattern);
    while (gtk_events_pending ())
        gtk_main_iteration ();

    err = gpgme_op_keylist_start (ctx, pattern, 0);
    if (err) {
        debug_print ("** gpgme_op_keylist_start(%s) failed: %s",
                     pattern, gpgme_strerror (err));
        sk->select_ctx = NULL;
        gpgme_release(ctx);
        return NULL;
    }
    update_progress (sk, ++running, pattern);
    while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) {
	gpgme_user_id_t uid = key->uids;
	if (!key->can_encrypt || key->revoked || key->expired || key->disabled)
		continue;
        debug_print ("%% %s:%d:  insert\n", __FILE__ ,__LINE__ );
        set_row (clist, key, proto ); 
	for (; uid; uid = uid->next) {
		gchar *raw_mail = NULL;

		if (!uid->email)
			continue;
		if (uid->revoked || uid->invalid)
			continue;
		raw_mail = g_strdup(uid->email);
		extract_address(raw_mail);
		if (!strcasecmp(pattern, raw_mail)) {
			exact_match = TRUE;
			last_uid = uid;
			g_free(raw_mail);
			break;
		}
		g_free(raw_mail);
	}
	num_results++;
	last_key = key;
	key = NULL;
        update_progress (sk, ++running, pattern);
        while (gtk_events_pending ())
            gtk_main_iteration ();
    }
 
    if (exact_match == TRUE && num_results == 1) {
	    if (last_key->uids->validity < GPGME_VALIDITY_FULL && 
		!use_untrusted(last_key, last_uid, proto))
		    exact_match = FALSE;
    }

    debug_print ("%% %s:%d:  ready\n", __FILE__ ,__LINE__ );
    if (gpgme_err_code(err) != GPG_ERR_EOF) {
        debug_print ("** gpgme_op_keylist_next failed: %s",
                     gpgme_strerror (err));
        gpgme_op_keylist_end(ctx);
    }
    if (!exact_match || num_results != 1) {
	    sk->select_ctx = NULL;
	    gpgme_release (ctx);
    }
    /*gtk_cmclist_thaw (select_keys.clist);*/
    return (exact_match == TRUE && num_results == 1 ? last_key:NULL);
}
static gpgme_key_t*
prompt_recipients (gpgme_key_t *signkey)
{
    gpgme_error_t gerr = 0;
    CryptUIKeyset *keyset;
    gpgme_ctx_t ctx;
    gpgme_key_t key;
    GArray *keys;
    gchar **recips;
    gchar *signer;

    *signkey = NULL;

    keyset = cryptui_keyset_new ("openpgp", TRUE);

    if (cryptui_keyset_get_count (keyset) == 0) {
        cryptui_need_to_get_keys ();
    } else {
        recips = cryptui_prompt_recipients (keyset, _("Choose Recipients"), &signer);

        if (recips) {
            gpgme_check_version (NULL);
            gerr = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
            g_return_val_if_fail (gerr == 0, NULL);

            gerr = gpgme_new (&ctx);
            g_return_val_if_fail (gerr == 0, NULL);

            if (signer) {
                /* Load up the GPGME secret key */
                gchar *id = cryptui_keyset_key_raw_keyid (keyset, signer);
                gerr = gpgme_get_key (ctx, id, signkey, 1);
                g_free (id);

                /* A more descriptive error message */
                if (GPG_ERR_EOF == gpgme_err_code (gerr))
                    gerr = gpgme_error (GPG_ERR_NOT_FOUND);
            }

            if (gerr == 0) {
                gchar **ids;
                guint num;

                /* Load up the GPGME keys */
                ids = cryptui_keyset_keys_raw_keyids (keyset, (const gchar**)recips);
                num = g_strv_length (ids);
                keys = g_array_new (TRUE, TRUE, sizeof (gpgme_key_t));
                gerr = gpgme_op_keylist_ext_start (ctx, (const gchar**)ids, 0, 0);
                g_free (ids);

                if (gerr == 0) {
                    while ((gerr = gpgme_op_keylist_next (ctx, &key)) == 0)
                        g_array_append_val (keys, key);
                    gpgme_op_keylist_end (ctx);
                }

                /* Ignore EOF error */
                if (GPG_ERR_EOF == gpgme_err_code (gerr))
                    gerr = 0;

                if (gerr == 0 && num != keys->len)
                    g_warning ("couldn't load all the keys (%d/%d) from GPGME", keys->len, num);
            }

            gpgme_release (ctx);
        }

        g_object_unref (keyset);

        if (!recips)
            return NULL;

        g_strfreev (recips);
        g_free (signer);

        if (gerr == 0 && keys->len)
            return (gpgme_key_t*)g_array_free (keys, FALSE);

        /* When failure, free all our return values */
        seahorse_util_free_keys ((gpgme_key_t*)g_array_free (keys, FALSE));
        if (*signkey)
            gpgme_key_unref (*signkey);

        seahorse_util_handle_gpgme (gerr, _("Couldn't load keys"));
    }

    return NULL;
}