int geanypg_sign_selection_dialog(encrypt_data * ed)
{
    GtkWidget * dialog = gtk_dialog_new();
    unsigned long idx;
    int response;
    GtkWidget * contentarea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
    GtkWidget * combobox = geanypg_combobox(
                                geanypg_makelist(ed->skey_array, ed->nskeys, 0));

    gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new(_("Choose a key to sign with:")), FALSE, FALSE, 5);
    gtk_box_pack_start(GTK_BOX(contentarea), combobox, TRUE, TRUE, 0);

    // add ok and cancel buttons
    gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
    gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);

    gtk_widget_show_all(dialog);
    gtk_window_set_title(GTK_WINDOW(dialog), _("Select signer"));
    // make sure dialog is destroyed when user responds
    response = gtk_dialog_run(GTK_DIALOG(dialog));
    if (response == GTK_RESPONSE_CANCEL)
    {
        gtk_widget_destroy(dialog);
        return 0;
    }
    idx = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox));
    gpgme_signers_clear(ed->ctx);
    if (idx < ed->nskeys)
        gpgme_signers_add(ed->ctx, ed->skey_array[idx]);

    gtk_widget_destroy(dialog);
    return 1;
}
Beispiel #2
0
void GPGWrapper::init()
{
    if (initialized)
        return;

    initialized = true;

    gpgme_check_version(NULL);
    setlocale(LC_ALL, "");
    gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
#ifdef LC_MESSAGES
    gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
#endif

    gpgme_error_t error = gpgme_new(&context);
    fail_if_err(error, L"Nie uda³o siê zainicjowaæ kontekstu GPG.");

    gpgme_set_textmode(context, 1);
    gpgme_set_armor(context, 1);

    error = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
    fail_if_err(error, L"Nie zainstalowano OpenPGP.");

    error = gpgme_set_protocol(context, GPGME_PROTOCOL_OpenPGP);
    fail_if_err(error, L"Nie uda³o siê ustawiæ OpenPGP.");

    privateKey = getPrivateKey(privateKeyId.c_str());
    error = gpgme_signers_add(context, privateKey);
    fail_if_err(error, L"Nie uda³o siê ustawiæ klucza prywatnego.");
}
static int
pygpgme_context_set_signers(PyGpgmeContext *self, PyObject *value)
{
    PyObject *signers = NULL;
    int i, length, ret = 0;

    if (value == NULL) {
        PyErr_SetString(PyExc_AttributeError, "Can not delete attribute");
        return -1;
    }

    signers = PySequence_Fast(value, "signers must be a sequence of keys");
    if (!signers) {
        ret = -1;
        goto end;
    }

    gpgme_signers_clear(self->ctx);
    length = PySequence_Fast_GET_SIZE(signers);
    for (i = 0; i < length; i++) {
        PyObject *item = PySequence_Fast_GET_ITEM(signers, i);

        if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) {
            PyErr_SetString(PyExc_TypeError,
                            "signers must be a sequence of keys");
            ret = -1;
            goto end;
        }
        gpgme_signers_add(self->ctx, ((PyGpgmeKey *)item)->key);
    }

 end:
    Py_XDECREF(signers);
    return ret;
}
Beispiel #4
0
/* Created a detached signature for INDATA and write it to OUTDATA.
   On termination of the signing command engine_private_finished() is
   called with FILTER as the first argument.  */
int
op_gpgme_sign (protocol_t protocol, 
               gpgme_data_t indata, gpgme_data_t outdata,
               engine_filter_t filter, void *hwnd)
{
  gpg_error_t err;
  closure_data_t cld;
  gpgme_ctx_t ctx = NULL;
  gpgme_key_t sign_key = NULL;

  (void)hwnd;

  if (signer_dialog_box (&sign_key, NULL, 0) == -1)
    {
      log_debug ("%s:%s: leave (dialog failed)\n", SRCNAME, __func__);
      return gpg_error (GPG_ERR_CANCELED);  
    }

  cld = xcalloc (1, sizeof *cld);
  cld->closure = sign_closure;
  cld->filter = filter;

  err = gpgme_new (&ctx);
  if (err)
    goto leave;
  gpgme_set_progress_cb (ctx, NULL, cld);
  switch (protocol)
    {
    case PROTOCOL_OPENPGP:  /* Gpgme's default.  */
      break;
    case PROTOCOL_SMIME:
      err = gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
      break;
    default:
      err = gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
      break;
    }
  if (err)
    goto leave;

  gpgme_set_armor (ctx, 1);
  gpgme_set_passphrase_cb (ctx, passphrase_callback_box, &cld->pw_cb);
  cld->pw_cb.ctx = ctx;
  cld->pw_cb.ttl = opt.passwd_ttl;
  err = gpgme_signers_add (ctx, sign_key);
  if (!err)
    err = gpgme_op_sign_start (ctx, indata, outdata, GPGME_SIG_MODE_DETACH);

 leave:
  if (err)
    {
      xfree (cld);
      gpgme_release (ctx);
    }
  else
    engine_private_set_cancel (filter, ctx);
  gpgme_key_unref (sign_key);
  return err;
}
/**
 * seahorse_service_crypto_sign_text:
 * @crypto: SeahorseServiceCrypto
 * @signer: the signer keyid
 * @flags: 0 (ignored)
 * @cleartext: the text to sign
 * @crypttext: the clear text signature (out) (GPGME_SIG_MODE_CLEAR)
 * @error: an error to return
 *
 * DBus: SignText
 *
 * Signs the @cleartext and returns the signature in @crypttext
 *
 * Returns: TRUE on success
 */
gboolean
seahorse_service_crypto_sign_text (SeahorseServiceCrypto *crypto, const char *signer, 
                                   int flags, const char *cleartext, char **crypttext,
                                   GError **error)
{
    SeahorseObject *signkey = NULL;
    gpgme_error_t gerr;
    SeahorseGpgmeOperation *pop; 
    gpgme_data_t plain, cipher;
    gboolean ret = TRUE;
    
    /* 
     * TODO: Once we support different kinds of keys that support encryption
     * then all this logic will need to change. 
     */
    
    /* The signer */
    if (!signer || !signer[0]) 
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                     _("No signer specified"));
    
    signkey = seahorse_context_object_from_dbus (SCTX_APP (), signer);
    if (!signkey) {
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, 
                     _("Invalid or unrecognized signer: %s"), signer);
        return FALSE;
    }
        
    if (!SEAHORSE_IS_GPGME_KEY (signkey) || 
        !(seahorse_object_get_flags (signkey) & SEAHORSE_FLAG_CAN_SIGN)) {
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                     _("Key is not valid for signing: %s"), signer);
        return FALSE;
    }
    
    pop = seahorse_gpgme_operation_new (NULL);
    
    /* new data from text */
    gerr = gpgme_data_new_from_mem (&plain, cleartext, strlen (cleartext), FALSE);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
    gerr = gpgme_data_new (&cipher);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
   
    /* encrypt with armor */
    gpgme_set_textmode (pop->gctx, TRUE);
    gpgme_set_armor (pop->gctx, TRUE);

    /* Do the signage */
    gpgme_signers_add (pop->gctx, seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (signkey)));
    gerr = gpgme_op_sign_start (pop->gctx, plain, cipher, GPGME_SIG_MODE_CLEAR);

    /* Frees cipher */
    ret = process_crypto_result (pop, gerr, cipher, crypttext, NULL, error);
    
    g_object_unref (pop);
    gpgme_data_release (plain);
    return ret;
}
Beispiel #6
0
static gboolean
pkcs7_add_signer (Pkcs7Ctx *pkcs7, const char *signer, GError **err)
{
	gpgme_key_t key = NULL;
	
	if (!(key = pkcs7_get_key_by_name (pkcs7, signer, TRUE, err)))
		return FALSE;
	
	/* set the key (the previous operation guaranteed that it exists, no need
	 * 2 check return values...) */
	gpgme_signers_add (pkcs7->ctx, key);
	gpgme_key_unref (key);
	
	return TRUE;
}
Beispiel #7
0
    void crypto_asym::set_signatories(const std::vector<std::string> & signatories)
    {
#if GPGME_SUPPORT
	gpgme_key_t *signatories_key = NULL;

	if(signatories.empty())
	{
	    gpgme_signers_clear(context);
	    has_signatories = false;
	}
	else
	{
	    build_key_list(signatories, signatories_key, true);
	    try
	    {
		gpgme_signers_clear(context);
		gpgme_key_t *ptr = signatories_key;
		gpgme_error_t err;

		if(ptr == NULL)
		    throw SRC_BUG;  // build_key_list failed
		while(*ptr != NULL)
		{
		    err = gpgme_signers_add(context, *ptr);
		    switch(gpgme_err_code(err))
		    {
		    case GPG_ERR_NO_ERROR:
			break;
		    default:
			throw Erange("crypto_asym::encrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err));
		    }
		    ++ptr;
		}
	    }
	    catch(...)
	    {
		release_key_list(signatories_key);
		gpgme_signers_clear(context);
		has_signatories = false;
		throw;
	    }
	    release_key_list(signatories_key);
	    has_signatories = true;
	}
#else
	throw Efeature("Asymetric Strong encryption algorithms using GPGME");
#endif
    }
Beispiel #8
0
/*
 * Setting the signers and the protocol for the context. The protocol
 * to use is derived from the keys.  An errro will be displayed if the
 * selected keys are not all of one protocol.
 */
static gboolean
set_signers (GpaFileSignOperation *op, GList *signers)
{
    GList *cur;
    gpg_error_t err;
    gpgme_protocol_t protocol = GPGME_PROTOCOL_UNKNOWN;

    gpgme_signers_clear (GPA_OPERATION (op)->context->ctx);
    if (!signers)
    {
        /* Can't happen */
        gpa_window_error (_("You didn't select any key for signing"),
                          GPA_OPERATION (op)->window);
        return FALSE;
    }
    for (cur = signers; cur; cur = g_list_next (cur))
    {
        gpgme_key_t key = cur->data;
        if (protocol == GPGME_PROTOCOL_UNKNOWN)
            protocol = key->protocol;
        else if (key->protocol != protocol)
        {
            /* Should not happen because the selection dialog should
               have not allowed to select different key types.  */
            gpa_window_error
            (_("The selected certificates are not all of the same type."
               " That is, you mixed OpenPGP and X.509 certificates."
               " Please make sure to select only certificates of the"
               " same type."),
             GPA_OPERATION (op)->window);
            return FALSE;
        }
    }

    gpgme_set_protocol (GPA_OPERATION (op)->context->ctx, protocol);

    for (cur = signers; cur; cur = g_list_next (cur))
    {
        gpgme_key_t key = cur->data;
        err = gpgme_signers_add (GPA_OPERATION (op)->context->ctx, key);
        if (err)
            gpa_gpgme_error (err);
    }

    return TRUE;
}
static gboolean
encrypt_sign_start (SeahorseToolMode *mode, const gchar *uri, gpgme_data_t uridata,
                    SeahorsePGPOperation *pop, GError **err)
{
    gpgme_data_t cipher;
    gpgme_error_t gerr;
    gchar *touri;

    g_assert (mode->recipients && mode->recipients[0]);

    /* File to encrypt to */
    touri = seahorse_util_add_suffix (uri, SEAHORSE_CRYPT_SUFFIX,
                                      _("Choose Encrypted File Name for '%s'"));
    if (!touri)
        return FALSE;

    /* Open necessary files, release these with the operation */
    cipher = seahorse_vfs_data_create (touri, SEAHORSE_VFS_WRITE | SEAHORSE_VFS_DELAY, err);
    g_free (touri);
    if (!cipher)
        return FALSE;
    g_object_set_data_full (G_OBJECT (pop), "cipher-data", cipher,
                            (GDestroyNotify)gpgme_data_release);

    gpgme_set_armor (pop->gctx, seahorse_gconf_get_boolean (ARMOR_KEY));
    gpgme_set_textmode (pop->gctx, FALSE);

    /* Start actual encryption */
    gpgme_signers_clear (pop->gctx);
    if (mode->signer) {
        gpgme_signers_add (pop->gctx, mode->signer);
        gerr = gpgme_op_encrypt_sign_start (pop->gctx, mode->recipients,
                                            GPGME_ENCRYPT_ALWAYS_TRUST, uridata, cipher);

    } else {
        gerr = gpgme_op_encrypt_start (pop->gctx, mode->recipients,
                                       GPGME_ENCRYPT_ALWAYS_TRUST, uridata, cipher);
    }

    if (gerr != 0) {
        seahorse_util_gpgme_to_error (gerr, err);
        return FALSE;
    }

    return TRUE;
}
Beispiel #10
0
/*
 * Add signer to ctx's list of signers and return TRUE on success or FALSE
 * on error.
 */
static gboolean
gpgme_add_signer(gpgme_ctx_t ctx, const gchar * signer, GtkWindow * parent,
		 GError ** error)
{
    gpgme_key_t key = NULL;

    /* note: private (secret) key has never low trust... */
    if (!
	(key = get_key_from_name(ctx, signer, TRUE, FALSE, parent, error)))
	return FALSE;

    /* set the key (the previous operation guaranteed that it exists, no
     * need 2 check return values...) */
    gpgme_signers_add(ctx, key);
    gpgme_key_unref(key);

    return TRUE;
}
Beispiel #11
0
/* Sign this key with the given private key.  */
gpg_error_t
gpa_gpgme_edit_sign_start (GpaContext *ctx, gpgme_key_t key,
                           gpgme_key_t secret_key, gboolean local)
{
  struct edit_parms_s *parms = NULL;
  gpg_error_t err = gpg_error (GPG_ERR_NO_ERROR);
  gpgme_data_t out;

  err = gpgme_data_new (&out);
  if (gpg_err_code (err) != GPG_ERR_NO_ERROR)
    {
      return err;
    }
  gpgme_signers_clear (ctx->ctx);
  err = gpgme_signers_add (ctx->ctx, secret_key);
  if (gpg_err_code (err) != GPG_ERR_NO_ERROR)
    {
      return err;
    }
  parms = gpa_gpgme_edit_sign_parms_new (ctx, "0", local, out);
  err = gpgme_op_edit_start (ctx->ctx, key, edit_fnc, parms, out);

  return err;
}
Beispiel #12
0
/* The main GPG encryption routine for libfko.
*/
int
gpgme_encrypt(fko_ctx_t fko_ctx, unsigned char *indata, size_t in_len,
        const char *pw, unsigned char **out, size_t *out_len)
{
    char               *tmp_buf;
    int                 res;

    gpgme_ctx_t         gpg_ctx     = NULL;
    gpgme_data_t        cipher      = NULL;
    gpgme_data_t        plaintext   = NULL;
    gpgme_key_t         key[2]      = { NULL, NULL };
    gpgme_error_t       err;

    /* Initialize gpgme
    */
    res = init_gpgme(fko_ctx);
    if(res != FKO_SUCCESS)
        return(res);

    gpg_ctx = fko_ctx->gpg_ctx;

    /* Initialize the plaintext data (place into gpgme_data object)
    */
    err = gpgme_data_new_from_mem(&plaintext, (char*)indata, in_len, 1);
    if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
    {
        gpgme_release(gpg_ctx);
        fko_ctx->gpg_ctx = NULL;
        fko_ctx->gpg_err = err;

        return(FKO_ERROR_GPGME_PLAINTEXT_DATA_OBJ);
    }

    /* Set protocol
    */
    err = gpgme_set_protocol(gpg_ctx, GPGME_PROTOCOL_OpenPGP);
    if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
    {
        gpgme_data_release(plaintext);
        gpgme_release(gpg_ctx);
        fko_ctx->gpg_ctx = NULL;

        fko_ctx->gpg_err = err;

        return(FKO_ERROR_GPGME_SET_PROTOCOL);
    }

    /* Set ascii-armor off (we will be base64-encoding the encrypted data
     * ourselves.
    */
    gpgme_set_armor(gpg_ctx, 0);

    /* The gpgme_encrypt.... functions take a recipient key array, so we add
     * our single key here.
    */
    key[0] = fko_ctx->recipient_key;

    /* Create the buffer for our encrypted data.
    */
    err = gpgme_data_new(&cipher);
    if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
    {
        gpgme_data_release(plaintext);
        gpgme_release(gpg_ctx);
        fko_ctx->gpg_ctx = NULL;

        fko_ctx->gpg_err = err;

        return(FKO_ERROR_GPGME_CIPHER_DATA_OBJ);
    }

    /* Here we add the signer to the gpgme context if there is one.
    */
    if(fko_ctx->gpg_signer != NULL) {
        gpgme_signers_clear(gpg_ctx);
        err = gpgme_signers_add(gpg_ctx, fko_ctx->signer_key);
        if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
        {
            gpgme_data_release(plaintext);
            gpgme_data_release(cipher);
            gpgme_release(gpg_ctx);
            fko_ctx->gpg_ctx = NULL;

            fko_ctx->gpg_err = err;

            return(FKO_ERROR_GPGME_ADD_SIGNER);
        }
    }

    /* Set the passphrase callback.
    */
    gpgme_set_passphrase_cb(gpg_ctx, my_passphrase_cb, (void*)pw);

    /* Encrypt and sign (if a sig was provided) the SPA data.
    */
    if(fko_ctx->gpg_signer == NULL)
        err = gpgme_op_encrypt(
            gpg_ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, cipher
        );
    else
        err = gpgme_op_encrypt_sign(
            gpg_ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, cipher
        );

    if(gpg_err_code(err) != GPG_ERR_NO_ERROR)
    {
        gpgme_data_release(plaintext);
        gpgme_data_release(cipher);
        gpgme_release(gpg_ctx);
        fko_ctx->gpg_ctx = NULL;

        fko_ctx->gpg_err = err;

        if(gpgme_err_code(err) == GPG_ERR_CANCELED)
            return(FKO_ERROR_GPGME_BAD_PASSPHRASE);

        return(FKO_ERROR_GPGME_ENCRYPT_SIGN);
    }

    /* Done with the plaintext.
    */
    gpgme_data_release(plaintext);

    /* Get the encrypted data and its length from the gpgme data object.
     * BTW, this does free the memory used by cipher.
    */
    tmp_buf = gpgme_data_release_and_get_mem(cipher, out_len);

    *out = malloc(*out_len); /* This is freed upon fko_ctx destruction. */
    if(*out == NULL)
        res = FKO_ERROR_MEMORY_ALLOCATION;
    else
    {
        memcpy(*out, tmp_buf, *out_len);
        res = FKO_SUCCESS;
    }

    gpgme_free(tmp_buf);

    return(res);
}
QString QalfCrypto::sign(QString &message, QString &key) {
	gpgme_key_t gpgkey ;
	gpgme_data_t signature ;
	gpgme_data_t msg ;
	gpgme_verify_result_t verification ;
	gpgme_signature_t signatures ;
 	gpgme_error_t result  ;
	char  * buffer ;
		
	gpgme_set_passphrase_cb(context,&passphrase_callback,NULL) ;
	result = gpgme_set_protocol(context,GPGME_PROTOCOL_OpenPGP) ;
	Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR) ;
	gpgme_set_armor(context,1) ;
	gpgme_set_textmode(context,1) ;

	gpgme_signers_clear(context) ;
	result = gpgme_set_keylist_mode(context,GPGME_KEYLIST_MODE_LOCAL) ;

	// retrieving key
	result = gpgme_get_key(context, key.toAscii().data(),&gpgkey,1) ;
	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;
	Q_ASSERT(gpgkey != 0) ;

	// signing
	result = gpgme_signers_add(context,gpgkey) ;
	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;
	
	result = gpgme_data_new(&signature);
	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;

	int message_length = message.toAscii().size() ;
	char * message_char = (char *) calloc(message_length+1,sizeof(char)) ;
	memcpy(message_char,message.toAscii().data(),message_length) ;
// 	printf("memcmp : %d\n",memcmp(message_char,"1fc36e1d41a93c1d79f6872198f426129320d287",message_length+1)) ;
	result = gpgme_data_new_from_mem(&msg,message_char,message_length,0) ;
	
	gpgme_data_seek(signature,0,SEEK_SET) ;
	gpgme_data_seek(msg,0,SEEK_SET) ;
	
	result = gpgme_op_sign(context, msg,signature, GPGME_SIG_MODE_DETACH) ;
	Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR || gpgme_err_code(result) == GPG_ERR_BAD_PASSPHRASE || gpgme_err_code(result) == GPG_ERR_CANCELED) ;
	
// 	gpgme_data_seek(signature,0,SEEK_SET) ;
// 	gpgme_data_seek(msg,0,SEEK_SET) ;
// 	
// 	result = gpgme_op_verify (context, signature, msg , 0) ;
// 	Q_ASSERT(gpgme_err_code(result) != GPG_ERR_INV_VALUE) ;
// 	Q_ASSERT(gpgme_err_code(result) != GPG_ERR_NO_DATA) ;
// 	Q_ASSERT(result == GPG_ERR_NO_ERROR) ;
// 	
// 	verification = gpgme_op_verify_result(context) ;
// 	Q_ASSERT(verification != 0) ;
// 	
// 	signatures = verification->signatures ;
// 	Q_ASSERT(verification->signatures != 0) ;
// 	result = signatures->status ;
// 	printf("status : %d\n",gpgme_err_code(result)) ;
// 	printf("signature summary : %d\n",signatures->summary) ;
// 	Q_ASSERT(signatures->summary == GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN) ;
// 	
	QString signatureStr ;
	buffer = (char *) calloc(2048,sizeof(char)) ;
	gpgme_data_seek(signature,0,SEEK_SET) ;
	gpgme_data_read(signature,buffer,2048) ;

	signatureStr += buffer ;

	qDebug() << "signature" << signatureStr ;
	
	gpgme_data_release(signature) ;
	gpgme_key_unref(gpgkey) ;
	gpgme_data_release(msg) ;
	return signatureStr ;
}
/**
* crypto: the crypto service (#SeahorseServiceCrypto)
* recipients: A list of recipients (keyids "openpgp:B8098FB063E2C811")
*             Must be empty when symmetric encryption is used.
* signer: optional, the keyid of the signer
* flags: FLAG_SYMMETRIC to perform symmetric encryption
* cleartext: the text to encrypt
* clearlength: Length of the cleartext
* crypttext: the encrypted text (out)
* cryptlength: the length of this text (out)
* textmode: TRUE if gpgme should use textmode
* ascii_armor: TRUE if GPGME should use ascii armor
* error: The Error
*
* Handles encryption in a generic way. Can be used by several DBus APIs
*
* Returns TRUE on success
**/
static gboolean
crypto_encrypt_generic (SeahorseServiceCrypto *crypto,
                        const char **recipients, const char *signer,
                        int flags, const char *cleartext, gsize clearlength,
                        char **crypttext, gsize *cryptlength, gboolean textmode,
                        gboolean ascii_armor, GError **error)
{
	GList *recipkeys = NULL;
	SeahorseGpgmeOperation *pop;
	SeahorseObject *signkey = NULL;
	SeahorseObject *skey;
	gpgme_key_t *recips;
	gboolean symmetric = FALSE;
	gpgme_data_t plain, cipher;
	gpgme_error_t gerr;
	gboolean ret = TRUE;
	GSettings *settings;
	gchar *keyid;

	if ((flags & FLAG_SYMMETRIC) == FLAG_SYMMETRIC)
		symmetric = TRUE;

	if (symmetric && recipients[0] != NULL) {
		g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
		             _("Recipients specified for symmetric encryption"));
		return FALSE;
	}

	/* The signer */
	if (signer && signer[0]) {
		signkey = seahorse_context_object_from_dbus (SCTX_APP (), signer);
		if (!signkey) {
			g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
			             _("Invalid or unrecognized signer: %s"), signer);
			return FALSE;
		}

		if (!SEAHORSE_IS_GPGME_KEY (signkey) ||
			!(seahorse_object_get_flags (signkey) & SEAHORSE_FLAG_CAN_SIGN)) {
			g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
			             _("Key is not valid for signing: %s"), signer);
			return FALSE;
		}
	}

	if (!symmetric) {
		/* The recipients */
		for( ; recipients[0]; recipients++)
		{
			skey = seahorse_context_object_from_dbus (SCTX_APP (), recipients[0]);
			if (!skey) {
				g_list_free (recipkeys);
				g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
					     _("Invalid or unrecognized recipient: %s"), recipients[0]);
				return FALSE;
			}

			if (!SEAHORSE_IS_GPGME_KEY (skey) ||
				!(seahorse_object_get_flags (skey) & SEAHORSE_FLAG_CAN_ENCRYPT)) {
				g_list_free (recipkeys);
				g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
					     _("Key is not a valid recipient for encryption: %s"), recipients[0]);
				return FALSE;
			}

			recipkeys = g_list_prepend (recipkeys, SEAHORSE_PGP_KEY (skey));
		}

		if (!recipkeys) {
			g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
				     _("No recipients specified"));
			return FALSE;
		}
	}

	pop = seahorse_gpgme_operation_new (NULL);

	/* new data form text */
	gerr = gpgme_data_new_from_mem (&plain, cleartext, clearlength, FALSE);
	g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
	gerr = gpgme_data_new (&cipher);
	g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);

	/* encrypt with armor */
	gpgme_set_textmode (pop->gctx, textmode);
	gpgme_set_armor (pop->gctx, ascii_armor);

	if (symmetric) {
		/* gpgme_op_encrypt{_sign,}_start() will perform symmetric encryption
		 * when no recipients are specified. */
		recips = NULL;
	} else {
		/* Add the default key if set and necessary */
		settings = g_settings_new ("org.gnome.crypto.pgp");
		if (g_settings_get_boolean (settings, "encrypt-to-self")) {
			keyid = g_settings_get_string (settings, "default-key");
			if (keyid && keyid[0]) {
				skey = seahorse_context_find_object (NULL, g_quark_from_string (keyid),
								     SEAHORSE_LOCATION_LOCAL);
				if (SEAHORSE_IS_PGP_KEY (skey))
					recipkeys = g_list_append (recipkeys, skey);
			}
			g_free (keyid);
		}
		g_object_unref (settings);

		/* Make keys into the right format for GPGME */
		recips = keylist_to_keys (recipkeys);
		g_list_free (recipkeys);
	}

	/* Do the encryption */
	if (signkey) {
		gpgme_signers_add (pop->gctx, seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (signkey)));
		gerr = gpgme_op_encrypt_sign_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST,
		                                    plain, cipher);
	} else {
		gerr = gpgme_op_encrypt_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST,
		                               plain, cipher);
	}
	free_keys (recips);

	/* Frees cipher */
	ret = process_crypto_result (pop, gerr, cipher, crypttext, cryptlength, error);
	g_object_unref (pop);
	gpgme_data_release (plain);
	return ret;
}
/**
* crypto: the crypto service (#SeahorseServiceCrypto)
* recipients: A list of recipients (keyids "openpgp:B8098FB063E2C811")
* signer: optional, the keyid of the signer
* flags: 0, not used
* cleartext: the text to encrypt
* clearlength: Length of the cleartext
* crypttext: the encrypted text (out)
* cryptlength: the length of this text (out)
* textmode: TRUE if gpgme should use textmode
* ascii_armor: TRUE if GPGME should use ascii armor
* error: The Error
*
* Handles encryption in a generic way. Can be used by several DBus APIs
*
* Returns TRUE on success
**/
static gboolean
crypto_encrypt_generic (SeahorseServiceCrypto *crypto,
                        const char **recipients, const char *signer,
                        int flags, const char *cleartext, gsize clearlength,
                        char **crypttext, gsize *cryptlength, gboolean textmode,
                        gboolean ascii_armor, GError **error)
{
    GList *recipkeys = NULL;
    SeahorseGpgmeOperation *pop; 
    SeahorseObject *signkey = NULL;
    SeahorseObject *skey;
    gpgme_key_t *recips;
    gpgme_data_t plain, cipher;
    gpgme_error_t gerr;
    gboolean ret = TRUE;
    
    /* 
     * TODO: Once we support different kinds of keys that support encryption
     * then all this logic will need to change. 
     */
    /* The signer */
    if (signer && signer[0]) {
        signkey = seahorse_context_object_from_dbus (SCTX_APP (), signer);
        if (!signkey) {
            g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, 
                         _("Invalid or unrecognized signer: %s"), signer);
            return FALSE;
        }
        
        if (!SEAHORSE_IS_GPGME_KEY (signkey) || 
            !(seahorse_object_get_flags (signkey) & SEAHORSE_FLAG_CAN_SIGN)) {
            g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                         _("Key is not valid for signing: %s"), signer);
            return FALSE;
        }
    }
    /* The recipients */
    for( ; recipients[0]; recipients++)
    {
        skey = seahorse_context_object_from_dbus (SCTX_APP (), recipients[0]);
        if (!skey) {
            g_list_free (recipkeys);
            g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID, 
                         _("Invalid or unrecognized recipient: %s"), recipients[0]);
            return FALSE;
        }
        
        if (!SEAHORSE_IS_GPGME_KEY (skey) ||
            !(seahorse_object_get_flags (skey) & SEAHORSE_FLAG_CAN_ENCRYPT)) {
            g_list_free (recipkeys);
            g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                         _("Key is not a valid recipient for encryption: %s"), recipients[0]);
            return FALSE;
        }
        
        recipkeys = g_list_prepend (recipkeys, SEAHORSE_PGP_KEY (skey));
    }
    
    if (!recipkeys) {
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                     _("No recipients specified"));
        return FALSE;
    }
    pop = seahorse_gpgme_operation_new (NULL);
    
    /* new data form text */
    gerr = gpgme_data_new_from_mem (&plain, cleartext, clearlength, FALSE);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
    gerr = gpgme_data_new (&cipher);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
   
    /* encrypt with armor */
    gpgme_set_textmode (pop->gctx, textmode);
    gpgme_set_armor (pop->gctx, ascii_armor);

    /* Add the default key if set and necessary */
    if (seahorse_gconf_get_boolean (ENCRYPTSELF_KEY)) {
        skey = SEAHORSE_OBJECT (seahorse_context_get_default_key (SCTX_APP ()));
        if (SEAHORSE_IS_PGP_KEY (skey))
            recipkeys = g_list_append (recipkeys, skey);
    }

    /* Make keys into the right format for GPGME */
    recips = keylist_to_keys (recipkeys);
    g_list_free (recipkeys);
    
    /* Do the encryption */
    if (signkey) {
        gpgme_signers_add (pop->gctx, seahorse_gpgme_key_get_private (SEAHORSE_GPGME_KEY (signkey)));
        gerr = gpgme_op_encrypt_sign_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST, 
                                            plain, cipher);
    } else {
        gerr = gpgme_op_encrypt_start (pop->gctx, recips, GPGME_ENCRYPT_ALWAYS_TRUST, 
                                       plain, cipher);
    }
    free_keys (recips);

    /* Frees cipher */
    ret = process_crypto_result (pop, gerr, cipher, crypttext, cryptlength, error);
    g_object_unref (pop);
    gpgme_data_release (plain);
    return ret;
}
int geanypg_encrypt_selection_dialog(encrypt_data * ed, gpgme_key_t ** selected, int * sign)
{
    GtkWidget * dialog = gtk_dialog_new();
    unsigned long idx, sidx, capacity;
    int response;
    GtkWidget * contentarea, * listview, * scrollwin, * combobox;
    GtkTreeIter iter;
    listdata data;
    gboolean active;

    *sign = 0;

    GtkListStore * list = geanypg_makelist(ed->key_array, ed->nkeys, 0);
    listview = geanypg_listview(list, &data);
    scrollwin = gtk_scrolled_window_new(NULL, NULL);
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollwin),
                        listview);
    gtk_widget_set_size_request(scrollwin, 500, 160);
    combobox = geanypg_combobox(geanypg_makelist(ed->skey_array, ed->nskeys, 1));


    contentarea = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
    gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new(_("Please select any recipients")), FALSE, FALSE, 5);
    gtk_box_pack_start(GTK_BOX(contentarea), scrollwin, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new(_("Sign the message as:")), FALSE, FALSE, 5);
    gtk_box_pack_start(GTK_BOX(contentarea), combobox, FALSE, FALSE, 0);


    // add ok and cancel buttons
    gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
    gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);

    gtk_window_set_title(GTK_WINDOW(dialog), _("Select recipients"));
    gtk_widget_show_all(dialog);
    // make sure dialog is destroyed when user responds
    response = gtk_dialog_run(GTK_DIALOG(dialog));
    if (response == GTK_RESPONSE_CANCEL)
    {
        gtk_widget_destroy(dialog);
        return 0;
    }
    idx = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox));
    if (idx && idx <= ed->nskeys)
    {
        *sign = 1;
        gpgme_signers_add(ed->ctx, ed->skey_array[idx - 1]); // -1 because the first option is `None'
    }
    // try to loop all the keys in the list
    // if they are active (the user checked the checkbox in front of the key)
    // add it to the selected array, finaly make sure that the array
    // is NULL terminated
    if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(list), &iter))
    {
        capacity = SIZE;
        *selected = (gpgme_key_t*) malloc(SIZE * sizeof(gpgme_key_t));
        idx = 0;
        sidx = 0;
        gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, TOGGLE_COLUMN, &active, -1);
        if (active)
                (*selected)[sidx++] = ed->key_array[idx];

        while (gtk_tree_model_iter_next(GTK_TREE_MODEL(list), &iter))
        {
            ++idx;
            gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, TOGGLE_COLUMN, &active, -1);
            if (active)
                (*selected)[sidx++] = ed->key_array[idx];
            if (sidx >= capacity - 1)
            {
                capacity += SIZE;
                *selected = (gpgme_key_t*) realloc(*selected, capacity * sizeof(gpgme_key_t));
            }
        }
        (*selected)[sidx] = NULL;
    }
    else
    {
        gtk_widget_destroy(dialog);
        return 0;
    }

    gtk_widget_destroy(dialog);
    return 1;
}
Beispiel #17
0
/* ------------------
 * sign a plain string with the key found with fingerprint fpr
 * FREE MEMORY AFTER USAGE OF RETURN VALUE!
 * ------------------ */
static char* sign(const char* plain_str,const char* fpr)
{
	gpgme_error_t error;
	gpgme_ctx_t ctx;
	gpgme_key_t key;
	gpgme_data_t plain,sig;
	const int MAX_LEN = 10000;
	char *sig_str = NULL;
	char *sig_str_dup = NULL;
	size_t len = 0;

	// connect to gpgme
	gpgme_check_version (NULL);
	error = gpgme_new(&ctx);
	if (error)
	{
		purple_debug_error(PLUGIN_ID,"gpgme_new failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error));
		return NULL;
	}

	// get key by fingerprint
	error = gpgme_get_key(ctx,fpr,&key,1);
	if (error || !key)
	{
		purple_debug_error(PLUGIN_ID,"gpgme_get_key failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error));
		gpgme_release (ctx);
		return NULL;
	}

	// select signers
	gpgme_signers_clear(ctx);
	error = gpgme_signers_add (ctx,key);
	if (error)
	{
		purple_debug_error(PLUGIN_ID,"gpgme_signers_add failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error));
		gpgme_release (ctx);
		return NULL;
	}

	// create data containers
	gpgme_data_new_from_mem (&plain, plain_str,strlen(plain_str),1);
	gpgme_data_new(&sig);

	// sign message, ascii armored
	gpgme_set_armor(ctx,1);
	error = gpgme_op_sign(ctx,plain,sig,GPGME_SIG_MODE_DETACH);
	if (error)
	{
		purple_debug_error(PLUGIN_ID,"gpgme_op_sign failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error));
		gpgme_release (ctx);
		return NULL;
	}

	// release memory for data containers
	gpgme_data_release(plain);
	sig_str = gpgme_data_release_and_get_mem(sig,&len);
	if (sig_str != NULL)
	{
		sig_str[len] = 0;
		sig_str_dup = str_unarmor(sig_str);
	}
	gpgme_free(sig_str);
	
	// close gpgme connection
	gpgme_release (ctx);

	return sig_str_dup;
}
Beispiel #18
0
gpointer
sign_file (const gchar *input_file_path, const gchar *fpr)
{
    gpgme_error_t error;
    gpgme_ctx_t context;
    gpgme_key_t signing_key;
    gpgme_data_t clear_text, signed_text;
    gpgme_sign_result_t result;
    gchar *buffer;
    gssize nbytes;

    error = gpgme_new (&context);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        return GPGME_ERROR;
    }

    gpgme_set_armor (context, 0);

    error = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        gpgme_release (context);
        return GPGME_ERROR;
    }

    const char *keyring_dir = gpgme_get_dirinfo ("homedir");
    error = gpgme_ctx_set_engine_info (context, GPGME_PROTOCOL_OpenPGP, NULL, keyring_dir);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        gpgme_release (context);
        return GPGME_ERROR;
    }

    error = gpgme_get_key (context, fpr, &signing_key, 1);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        gpgme_release (context);
        return GPGME_ERROR;
    }

    error = gpgme_signers_add (context, signing_key);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        cleanup (NULL, NULL, NULL, NULL, &signing_key, &context);
        return GPGME_ERROR;
    }

    FILE *infp = g_fopen (input_file_path, "r");
    if (infp == NULL) {
        g_printerr ("Couldn't open input file\n");
        cleanup (NULL, NULL, NULL, NULL, &signing_key, &context);
        return FILE_OPEN_ERROR;
    }

    error = gpgme_data_new_from_stream (&clear_text, infp);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        cleanup (infp, NULL, NULL, NULL, &signing_key, &context);
        return GPGME_ERROR;
    }

    error = gpgme_data_new (&signed_text);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        cleanup (infp, NULL, NULL, NULL, &signing_key, &context);
        return GPGME_ERROR;
    }

    error = gpgme_op_sign (context, clear_text, signed_text, GPGME_SIG_MODE_DETACH);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        cleanup (infp, NULL, NULL, NULL, &signing_key, &context);
        return GPGME_ERROR;
    }

    result = gpgme_op_sign_result (context);
    if (result->invalid_signers) {
        g_printerr ("Invalid signer found: %s\n", result->invalid_signers->fpr);
        cleanup (infp, NULL, NULL, NULL, &signing_key, &context);
        return GPGME_ERROR;
    }
    if (!result->signatures || result->signatures->next) {
        g_printerr ("Unexpected number of signatures created\n");
        cleanup (infp, NULL, NULL, NULL, &signing_key, &context);
        return GPGME_ERROR;
    }

    error = gpgme_data_seek (signed_text, 0, SEEK_SET);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        cleanup (infp, NULL, NULL, NULL, &signing_key, &context);
        return GPGME_ERROR;
    }

    buffer = g_try_malloc0 (SIG_MAXLEN);
    if (buffer == NULL) {
        g_printerr ("Couldn't allocate memory\n");
        cleanup (infp, NULL, NULL, NULL, &signing_key, &context);
        return MEMORY_ALLOCATION_ERROR;
    }

    nbytes = gpgme_data_read (signed_text, buffer, SIG_MAXLEN);
    if (nbytes == -1) {
        g_printerr ("Error while reading data\n");
        cleanup (infp, NULL, NULL, NULL, &signing_key, &context);
        return GPGME_ERROR;
    }

    GError *gerr = NULL;
    gchar *output_file_path = g_strconcat (input_file_path, ".sig", NULL);
    GFile *fpout = g_file_new_for_path (output_file_path);
    GFileOutputStream *ostream = g_file_append_to (fpout, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &gerr);
    if (gerr != NULL) {
        g_printerr ("Couldn't open output file for writing\n");
        cleanup (infp, fpout, NULL, output_file_path, &signing_key, &context);
        return FILE_OPEN_ERROR;
    }

    gssize wbytes = g_output_stream_write (G_OUTPUT_STREAM (ostream), buffer, nbytes, NULL, &gerr);
    if (wbytes == -1) {
        g_printerr ("Couldn't write the request number of bytes (%s)\n", gerr->message);
        cleanup (infp, fpout, ostream, output_file_path, &signing_key, &context);
        return FILE_WRITE_ERROR;
    }

    cleanup (infp, fpout, ostream, output_file_path, &signing_key, &context);

    return SIGN_OK;
}
Beispiel #19
0
int
main (int argc, char **argv)
{
  int last_argc = -1;
  gpgme_error_t err;
  gpgme_ctx_t ctx;
  const char *key_string = NULL;
  gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
  gpgme_sig_mode_t sigmode = GPGME_SIG_MODE_CLEAR;
  gpgme_data_t in, out;

  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, "--key"))
        {
          argc--; argv++;
          if (!argc)
            show_usage (1);
          key_string = *argv;
          argc--; argv++;
        }
      else if (!strncmp (*argv, "--", 2))
        show_usage (1);

    }

  if (argc != 1)
    show_usage (1);

  init_gpgme (protocol);

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

  if (key_string)
    {
      gpgme_key_t akey;

      err = gpgme_get_key (ctx, key_string, &akey, 1);
      if (err)
        {
          exit (1);
        }
      err = gpgme_signers_add (ctx, akey);
      fail_if_err (err);
      gpgme_key_unref (akey);
    }

  err = gpgme_data_new_from_file (&in, *argv, 1);
  if (err)
    {
      fprintf (stderr, PGM ": error reading `%s': %s\n",
               *argv, gpg_strerror (err));
      exit (1);
    }

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

  err = gpgme_op_sign (ctx, in, out, sigmode);
  if (err)
    {
      fprintf (stderr, PGM ": signing failed: %s\n", gpg_strerror (err));
      exit (1);
    }

  print_data (out);
  gpgme_data_release (out);

  gpgme_data_release (in);

  gpgme_release (ctx);
  return 0;
}
Beispiel #20
0
/* #############################################################################
 *
 * Description    encrypt the given buffer and return the encrypted data with
 *                an updated size information
 * Author         Harry Brueckner
 * Date           2005-03-31
 * Arguments      char* buffer      - buffer to encrypt
 *                int size          - size of the buffer
 *                char** newbuffer  - pointer to the new buffer which holds the
 *                                    encrypted data
 *                int* newsize      - size of the returned buffer
 *                PASSPHRASE_FN password_cb   - callback function pointer used
 *                                              to get the current passphrase
 *                SHOWERROR_FN showerror_cb   - callback function pointer used
 *                                              to display errors
 * Return         0 if ok, otherwise 1
 */
int gpgEncrypt(char* buffer, int size, char** newbuffer, int* newsize,
    PASSPHRASE_FN password_cb, SHOWERROR_FN showerror_cb)
  {
    gpgme_ctx_t         context;
    gpgme_data_t        input,
                        output;
    gpgme_encrypt_result_t  result;
    gpgme_error_t       error;
    gpgme_key_t*        key = NULL;
    gpgme_key_t         tkey = NULL;
    gpgme_sign_result_t sign_result;
    int                 i,
                        keys = 0,
                        showerror = 1;
    char*               agent;
    char*               fpr;
    char*               tmpbuffer = NULL;

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

    /* we set our passphrase callback function */
    passphrase_callback = password_cb;

    /* we initialize the external size data */
    newsize[0] = 0;

    error = gpgme_new(&context);

    if (!error)
      {
        gpgme_set_textmode(context, 1);
        gpgme_set_armor(context, 1);

        /* Flawfinder: ignore */
        agent = getenv("GPG_AGENT_INFO");
        if (!(agent && strchr(agent, ':')))
          {
            retries = 0;
            gpgme_set_passphrase_cb(context, gpgRequestPassphrase, NULL);
          }
      }

    if (!error)
      { error = gpgme_data_new_from_mem(&input, buffer, size, 0); }

    if (!error)
      { error = gpgme_data_new(&output); }

    if (!error)
      { gpgme_signers_clear(context); }

    if (!error)
      {
        /* allocate the keys */
        keys = keyCount();
        key = memAlloc(__FILE__, __LINE__, sizeof(gpgme_key_t) * (keys + 1));
        key[keys] = NULL;
        signers = 0;
        for (i = 0; i < keys && !error; i++)
          {   /* add all keys */
            fpr = gpgGetFingerprint(keyGet(i), LIST_SECRET);
            if (fpr)
              {
                error = gpgme_get_key(context, fpr, &tkey, LIST_SECRET);
                if (tkey -> secret);
                  {
                    error = gpgme_signers_add(context, tkey);
                    signers++;
                  }

                memFreeString(__FILE__, __LINE__, fpr);
              }

            fpr = gpgGetFingerprint(keyGet(i), LIST_ALL);
            if (fpr)
              {
                error = gpgme_get_key(context, fpr, &key[i], LIST_ALL);
                memFreeString(__FILE__, __LINE__, fpr);
              }
          }
      }

    if (signers > 1)
      {   /* as soon as we get two signers, we must no longer cache anything */
        config -> keeppassphrase = 0;
        clearPassphrase(1);
      }

    /* encrypt and sign the data */
    if (!error)
      {
        error = gpgme_op_encrypt_sign(context, key, GPGME_ENCRYPT_ALWAYS_TRUST,
            input, output);
      }

    /* we don't need the passphrase any longer */
    clearPassphrase(0);

    if (!error)
      { result = gpgme_op_encrypt_result(context); }
    if (!error &&
        result -> invalid_recipients)
      {
        tmpbuffer = memAlloc(__FILE__, __LINE__, STDBUFFERLENGTH);
        snprintf(tmpbuffer, STDBUFFERLENGTH,
            _("Invalid recipient encountered: %s"),
            result -> invalid_recipients -> fpr);
        (showerror_cb)(_("GpgMe error"), tmpbuffer);
        memFree(__FILE__, __LINE__, tmpbuffer, STDBUFFERLENGTH);

        showerror = 0;
        error = 1;
      }

    if (!error)
      {
        sign_result = gpgme_op_sign_result(context);
        error = gpgCheckSignResult(showerror_cb, sign_result,
            GPGME_SIG_MODE_NORMAL);
        showerror = !error;
      }

    if (!error)
      { tmpbuffer = gpgData2Char(output, newsize); }

    /* free the keys again */
    i = 0;
    while (key && keys && key[i])
      { gpgme_key_unref(key[i++]); }
    memFree(__FILE__, __LINE__, key, sizeof(gpgme_key_t) * (keys + 1));

    gpgme_data_release(input);
    gpgme_data_release(output);
    gpgme_release(context);

    *newbuffer = tmpbuffer;

    if (error)
      {
        if (showerror)
          { (showerror_cb)(_("GpgMe encrypt error"), gpgme_strerror(error)); }
        return 1;
      }
    else
        return 0;
  }
Beispiel #21
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 #22
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 #23
0
char*
p_gpg_sign(const char *const str, const char *const fp)
{
    gpgme_ctx_t ctx;
    gpgme_error_t error = gpgme_new(&ctx);
    if (error) {
        log_error("GPG: Failed to create gpgme context. %s %s", gpgme_strsource(error), gpgme_strerror(error));
        return NULL;
    }

    gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t)_p_gpg_passphrase_cb, NULL);

    gpgme_key_t key = NULL;
    error = gpgme_get_key(ctx, fp, &key, 1);

    if (error || key == NULL) {
        log_error("GPG: Failed to get key. %s %s", gpgme_strsource(error), gpgme_strerror(error));
        gpgme_release(ctx);
        return NULL;
    }

    gpgme_signers_clear(ctx);
    error = gpgme_signers_add(ctx, key);
    gpgme_key_unref(key);

    if (error) {
        log_error("GPG: Failed to load signer. %s %s", gpgme_strsource(error), gpgme_strerror(error));
        gpgme_release(ctx);
        return NULL;
    }

    char *str_or_empty = NULL;
    if (str) {
        str_or_empty = strdup(str);
    } else {
        str_or_empty = strdup("");
    }
    gpgme_data_t str_data;
    gpgme_data_new_from_mem(&str_data, str_or_empty, strlen(str_or_empty), 1);
    free(str_or_empty);

    gpgme_data_t signed_data;
    gpgme_data_new(&signed_data);

    gpgme_set_armor(ctx,1);
    error = gpgme_op_sign(ctx, str_data, signed_data, GPGME_SIG_MODE_DETACH);
    gpgme_data_release(str_data);
    gpgme_release(ctx);

    if (error) {
        log_error("GPG: Failed to sign string. %s %s", gpgme_strsource(error), gpgme_strerror(error));
        gpgme_data_release(signed_data);
        return NULL;
    }

    char *result = NULL;

    size_t len = 0;
    char *signed_str = gpgme_data_release_and_get_mem(signed_data, &len);
    if (signed_str) {
        GString *signed_gstr = g_string_new("");
        g_string_append_len(signed_gstr, signed_str, len);
        result = _remove_header_footer(signed_gstr->str, PGP_SIGNATURE_FOOTER);
        g_string_free(signed_gstr, TRUE);
        gpgme_free(signed_str);
    }

    if (passphrase_attempt) {
        passphrase = strdup(passphrase_attempt);
    }

    return result;
}