/**
 * 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;
}
/**
 * gpgme_generate_key:
 * @sksrc: the bastile source
 * @name: the user's full name
 * @email: the user's email address
 * @comment: a comment, added to the key
 * @type: key type like DSA_ELGAMAL
 * @bits: the number of bits for the key to generate (2048)
 * @expires: expiry date can be 0
 *
 * Displays a password generation box and creates a key afterwards. For the key
 * data it uses @name @email and @comment ncryption is chosen by @type and @bits
 * @expire sets the expiry date
 *
 */
void bastile_gpgme_generate_key (BastileGpgmeSource *sksrc, const gchar *name, const gchar *email,
                            const gchar *comment, guint type, guint bits, time_t expires)
{
    BastileOperation *op;
    const gchar *pass;
    gpgme_error_t gerr;
    GtkDialog *dialog;



    dialog = bastile_passphrase_prompt_show (_("Passphrase for New PGP Key"),
                                              _("Enter the passphrase for your new key twice."),
                                              NULL, NULL, TRUE);
    if (gtk_dialog_run (dialog) == GTK_RESPONSE_ACCEPT)
    {
        pass = bastile_passphrase_prompt_get (dialog);
        op = bastile_gpgme_key_op_generate (sksrc, name, email, comment,
                                             pass, type, bits, expires, &gerr);

        if (!GPG_IS_OK (gerr)) {
            bastile_gpgme_handle_error (gerr, _("Couldn't generate key"));
        } else {
            bastile_progress_show (op, _("Generating key"), TRUE);
            bastile_operation_watch (op, (BastileDoneFunc)completion_handler, NULL, NULL, NULL);
            g_object_unref (op);
        }
    }
    gtk_widget_destroy (GTK_WIDGET (dialog));
}
void
seahorse_gpgme_add_revoker_new (SeahorseGpgmeKey *pkey, GtkWindow *parent)
{
	SeahorseGpgmeKey *revoker;
	GtkWidget *dialog;
	gint response;
	gpgme_error_t err;
	const gchar *userid1, *userid2;
	
	g_return_if_fail (pkey != NULL && SEAHORSE_IS_GPGME_KEY (pkey));

	revoker = SEAHORSE_GPGME_KEY (seahorse_signer_get (parent));
	if (revoker == NULL)
		return;
	
	userid1 = seahorse_object_get_label (SEAHORSE_OBJECT (revoker));
	userid2 = seahorse_object_get_label (SEAHORSE_OBJECT (pkey));

	dialog = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL,
	                                 GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO,
	                                 _("You are about to add %s as a revoker for %s."
	                                   " This operation cannot be undone! Are you sure you want to continue?"),
	                                   userid1, userid2);
    
	response = gtk_dialog_run (GTK_DIALOG (dialog));
	gtk_widget_destroy (dialog);
	
	if (response != GTK_RESPONSE_YES)
		return;
	
	err = seahorse_gpgme_key_op_add_revoker (pkey, revoker);
	if (!GPG_IS_OK (err))
		seahorse_gpgme_handle_error (err, _("Couldn't add revoker"));
}
G_MODULE_EXPORT void
on_gpgme_revoke_ok_clicked (GtkButton *button,
                            gpointer user_data)
{
	SeahorseWidget *swidget = SEAHORSE_WIDGET (user_data);
	SeahorseRevokeReason reason;
	SeahorseGpgmeSubkey *subkey;
	const gchar *description;
	gpgme_error_t err;
	GtkWidget *widget;
	GtkTreeModel *model;
	GtkTreeIter iter;
	GValue value;
	
	widget = GTK_WIDGET (seahorse_widget_get_widget (swidget, "reason"));
	model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget));
	gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter);
	
	memset (&value, 0, sizeof(value));
	gtk_tree_model_get_value (model, &iter, COLUMN_INT, &value);
	reason = g_value_get_int (&value);
	g_value_unset (&value);
	
	description = gtk_entry_get_text (GTK_ENTRY (seahorse_widget_get_widget (swidget, "description")));
	subkey = g_object_get_data (G_OBJECT (swidget), "subkey");
	g_return_if_fail (SEAHORSE_IS_GPGME_SUBKEY (subkey));
	
	err = seahorse_gpgme_key_op_revoke_subkey (subkey, reason, description);
	if (!GPG_IS_OK (err))
		seahorse_gpgme_handle_error (err, _("Couldn't revoke subkey"));
	seahorse_widget_destroy (swidget);
}
/* Create a data on the given uri, remote uris get gnome-vfs backends,
 * local uris get normal file access. */
static gpgme_data_t
create_vfs_data (GFile *file, guint mode, SeahorseVfsProgressCb progcb,
                 gpointer userdata, gpg_error_t* err) 
{
    gpgme_error_t gerr;
    gpgme_data_t ret = NULL;
    VfsAsyncHandle* handle = NULL;
    
    if (!err)
        err = &gerr;
    
    handle = vfs_data_open (file, mode & SEAHORSE_VFS_WRITE, 
                                  mode & SEAHORSE_VFS_DELAY);
    if (handle) {
        
        *err = gpgme_data_new_from_cbs (&ret, &vfs_data_cbs, handle);
        if (!GPG_IS_OK (*err)) {
            vfs_data_cbs.release (handle);
            ret = NULL;
        }
        
        handle->progcb = progcb;
        handle->userdata = userdata;
        handle->gdata = ret;
    }

    return ret;
}
Exemple #6
0
/**
 * seahorse_gpgme_get_keytype_table:
 *
 * @table: The requested keytype table
 *
 * Based on the gpg version in use, sets @table
 * to contain the numbers that gpg uses in its CLI
 * for adding new subkeys. This tends to get broken
 * at random by new versions of gpg, but there's no good
 * API for this.
 *
 * Returns GPG_ERR_USER_2 if gpg is too old.
 *
 * Returns: gpgme_error_t
 **/
gpgme_error_t
seahorse_gpgme_get_keytype_table (SeahorseKeyTypeTable *table)
{
	gpgme_error_t gerr;
	gpgme_engine_info_t engine;
	SeahorseVersion ver;
	
	gerr = gpgme_get_engine_info (&engine);
	g_return_val_if_fail (GPG_IS_OK (gerr), gerr);
	
	while (engine && engine->protocol != GPGME_PROTOCOL_OpenPGP)
		engine = engine->next;
	g_return_val_if_fail (engine != NULL, GPG_E (GPG_ERR_GENERAL));
	
	ver = seahorse_util_parse_version (engine->version);
	
	if (ver >= VER_2012 || (ver >= VER_1410 && ver < VER_190))
		*table = &KEYTYPES_2012;
	else if (ver >= VER_140 || ver >= VER_190)
		*table = &KEYTYPES_140;
	else if (ver >= VER_124)
		*table = &KEYTYPES_124;
	else if (ver >= VER_120)
		*table = &KEYTYPES_120;
	else	// older versions not supported
		gerr = GPG_E (GPG_ERR_USER_2);
	
	return gerr;
}
/* Initializes the gpg-options static info */
static gboolean
gpg_options_init (GError **err)
{
    if (!gpg_options_inited) {
        gpgme_error_t gerr;
        gpgme_engine_info_t engine;

        gerr = gpgme_get_engine_info (&engine);
        g_return_val_if_fail (GPG_IS_OK (gerr),
                              (bastile_gpgme_to_error (gerr, err), FALSE));

        /* Look for the OpenPGP engine */
        while (engine && engine->protocol != GPGME_PROTOCOL_OpenPGP)
            engine = engine->next;

        /* 
         * Make sure it's the right version for us to be messing 
         * around with the configuration file.
         */
        g_return_val_if_fail (engine && engine->version && engine->file_name &&
                              (g_str_has_prefix (engine->version, GPG_VERSION_PREFIX1) ||
                               g_str_has_prefix (engine->version, GPG_VERSION_PREFIX2)),
                              (bastile_gpgme_to_error (GPG_E (GPG_ERR_INV_ENGINE), err), FALSE));

        /* Now run the binary and read in the home directory */
        if (!parse_home_directory (engine, err))
            return FALSE;

        gpg_options_inited = TRUE;
    }

    return TRUE;
}
gpgme_data_t
seahorse_vfs_data_read_multi (const gchar **uris, GError **err)
{
    gpgme_error_t gerr;
    gpgme_data_t data;
    GList *datas = NULL;
    const gchar **u;
    
    for (u = uris; *u; u++) {
        if(!(*u)[0])
            continue;
        data = seahorse_vfs_data_create (*u, SEAHORSE_VFS_READ, err);
        if (!data)
            break;
        datas = g_list_prepend (datas, data);
    }
    
    /* Failed somewhere */
    if (!data) {
        multi_data_release (datas);
        return NULL;
    }
    
    datas = g_list_reverse (datas);
    gerr = gpgme_data_new_from_cbs (&data, &multi_data_cbs, datas);
    if (!GPG_IS_OK (gerr)) {
        seahorse_util_gpgme_to_error (gerr, err);
        multi_data_release (datas);
        return NULL;
    }

    return data;
}
Exemple #9
0
gboolean
seahorse_gpgme_photo_delete (SeahorseGpgmePhoto *photo, GtkWindow *parent)
{
    gpgme_error_t gerr;
    GtkWidget *dlg;
    gint response; 

    g_return_val_if_fail (SEAHORSE_IS_GPGME_PHOTO (photo), FALSE);
    
    dlg = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL,
                                  GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
                                  _("Are you sure you want to remove the current photo from your key?"));

    gtk_dialog_add_button (GTK_DIALOG (dlg), GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT);
    gtk_dialog_add_button (GTK_DIALOG (dlg), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
       
    response = gtk_dialog_run (GTK_DIALOG (dlg));
    gtk_widget_destroy (dlg);
    
    if (response != GTK_RESPONSE_ACCEPT)
        return FALSE;
    
    gerr = seahorse_gpgme_key_op_photo_delete (photo);
    if (!GPG_IS_OK (gerr)) {
	    seahorse_gpgme_handle_error (gerr, _("Couldn’t delete photo"));
        return FALSE;
    }
    
    return TRUE;
}
gpgme_data_t
seahorse_gpgme_data_input (GInputStream* input)
{
	gpgme_error_t gerr;
	gpgme_data_t ret = NULL;
	
	g_return_val_if_fail (G_IS_INPUT_STREAM (input), NULL);
	
	gerr = gpgme_data_new_from_cbs (&ret, &input_cbs, input);
	if (!GPG_IS_OK (gerr))
		return NULL;
	
	g_object_ref (input);
	return ret;
}
gpgme_data_t
seahorse_gpgme_data_output (GOutputStream* output)
{
	gpgme_error_t gerr;
	gpgme_data_t ret = NULL;

	g_return_val_if_fail (G_IS_OUTPUT_STREAM (output), NULL);
	
	gerr = gpgme_data_new_from_cbs (&ret, &output_cbs, output);
	if (!GPG_IS_OK (gerr))
		return NULL;
	
	g_object_ref (output);
	return ret;
}
G_MODULE_EXPORT void
on_gpgme_expire_ok_clicked (GtkButton *button,
                            gpointer user_data)
{
	SeahorseWidget *swidget = SEAHORSE_WIDGET (user_data);
	GtkWidget *widget; 
	SeahorseGpgmeSubkey *subkey;
	gpgme_error_t err;
	time_t expiry = 0;
	struct tm when;
	
	subkey = SEAHORSE_GPGME_SUBKEY (g_object_get_data (G_OBJECT (swidget), "subkey"));
	
	widget = GTK_WIDGET (seahorse_widget_get_widget (swidget, "expire"));
	if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) {
		
		memset (&when, 0, sizeof (when));            
		widget = GTK_WIDGET (seahorse_widget_get_widget (swidget, "calendar"));
		gtk_calendar_get_date (GTK_CALENDAR (widget), (guint*)&(when.tm_year), 
		                       (guint*)&(when.tm_mon), (guint*)&(when.tm_mday));
		when.tm_year -= 1900;
		expiry = mktime (&when);

		if (expiry <= time (NULL)) {
			seahorse_util_show_error (widget, _("Invalid expiry date"), 
			                          _("The expiry date must be in the future"));
			return;
		}
	}
	
	widget = seahorse_widget_get_widget (swidget, "all-controls");
	gtk_widget_set_sensitive (widget, FALSE);
	g_object_ref (swidget);
	g_object_ref (subkey);
	
	if (expiry != (time_t)seahorse_pgp_subkey_get_expires (SEAHORSE_PGP_SUBKEY (subkey))) {
		err = seahorse_gpgme_key_op_set_expires (subkey, expiry);
		if (!GPG_IS_OK (err))
			seahorse_gpgme_handle_error (err, _("Couldn't change expiry date"));
	}
    
	g_object_unref (subkey);
	g_object_unref (swidget);
	seahorse_widget_destroy (swidget);
}
/**
* pop: a seahorse operation
* gstarterr: the gpgme error that could have occured earlier
* cryptdata: gpgme cryptdata
* result: the result of the gpgme operation (out)
* resultlength: length of the created buffer (out) (can be NULL)
* error: will be set on error
*
* Finishes the gpgme processing and returns the result
*
* returns: TRUE on successful operation, FALSE else
*/
static gboolean
process_crypto_result (SeahorseGpgmeOperation *pop, gpgme_error_t gstarterr, 
                       gpgme_data_t cryptdata, gchar **result, gsize *resultlength, GError **error)
{
    size_t len;
    char *data;
    
    /* Starting the operation failed? */
    if (!GPG_IS_OK (gstarterr)) {
        gpgme_data_release (cryptdata);
        
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_CRYPTO,
                     "%s", gpgme_strerror (gstarterr));
        return FALSE;
    }
    
    /* Wait for it to finish (can run main loop stuff) */
    seahorse_operation_wait (SEAHORSE_OPERATION (pop));
    
    if (seahorse_operation_is_cancelled (SEAHORSE_OPERATION (pop))) {
	    
	    g_set_error (error, SEAHORSE_DBUS_CANCELLED, 0, "%s", "");
	    return FALSE;
    
    } else if (seahorse_operation_is_successful (SEAHORSE_OPERATION (pop))) {
        
        data = gpgme_data_release_and_get_mem (cryptdata, &len);
        *result = g_strndup (data, len);
        if (resultlength != NULL)
            *resultlength = (gsize)len;
        g_free (data);
        return TRUE;
        
    } else {
        
        /* A failed operation always has an error */
        g_assert (seahorse_operation_get_error (SEAHORSE_OPERATION (pop)));
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_CRYPTO, 
                     "%s", seahorse_operation_get_error (SEAHORSE_OPERATION (pop))->message);
        
        gpgme_data_release (cryptdata);
        return FALSE;
    }
}
gpgme_data_t
seahorse_gpgme_data_new_from_mem (const char *buffer, size_t size, gboolean copy)
{
	gpgme_data_t data;
	gpgme_error_t gerr;
    
	gerr = gpgme_data_new_from_mem (&data, buffer, size, copy ? 1 : 0);
	if (!GPG_IS_OK (gerr)) {
		if (gpgme_err_code_to_errno (gerr) == ENOMEM || 
		    gpgme_err_code (gerr) == GPG_ERR_ENOMEM) {
                
			g_error ("%s: failed to allocate gpgme_data_t", G_STRLOC);
                
		} else {
			/* The only reason this should fail is above */
			g_assert_not_reached ();
            
			/* Just in case */
			abort ();
		}
	}
    
	return data;
}
gpgme_data_t 
seahorse_gpgme_data_new ()
{
	gpgme_error_t gerr;
	gpgme_data_t data;
    
	gerr = gpgme_data_new (&data);
	if (!GPG_IS_OK (gerr)) {
		if (gpgme_err_code_to_errno (gerr) == ENOMEM || 
		    gpgme_err_code (gerr) == GPG_ERR_ENOMEM) {
                
			g_error ("%s: failed to allocate gpgme_data_t", G_STRLOC);
                
		} else {
			/* The only reason this should fail is above */
			g_assert_not_reached ();
            
			/* Just in case */
			abort ();
		}
	}
    
	return data;
}
/**
* 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;
}
/**
* data: optional, will be added to the title, can be NULL
* status: the gpgme status
*
* Basing on the status a notification is created an displayed
*
*/
static void
notify_signatures (const gchar* data, gpgme_verify_result_t status)
{
	const gchar *icon = NULL;
	SeahorseObject *object;
	gchar *title, *body, *unesc_data;
	gboolean sig = FALSE;
	GSList *rawids;
	GList *keys;

	/* Discover the key in question */
	rawids = g_slist_append (NULL, status->signatures->fpr);
	keys = seahorse_context_discover_objects (SCTX_APP (), SEAHORSE_PGP, rawids);
	g_slist_free (rawids);

	g_return_if_fail (keys != NULL);
	object = SEAHORSE_OBJECT (keys->data);
	g_list_free (keys);

	/* Figure out what to display */
	switch (gpgme_err_code (status->signatures->status)) {
	case GPG_ERR_KEY_EXPIRED:
		/* TRANSLATORS: <key id='xxx'> is a custom markup tag, do not translate. */
		body = _("Signed by <i><key id='%s'/> <b>expired</b></i> on %s.");
		title = _("Invalid Signature");
		icon = ICON_PREFIX "seahorse-sign-bad.png";
		sig = TRUE;
		break;
		/* TRANSLATORS: <key id='xxx'> is a custom markup tag, do not translate. */
	case GPG_ERR_SIG_EXPIRED:
		body  = _("Signed by <i><key id='%s'/></i> on %s <b>Expired</b>.");
		title = _("Expired Signature");
		icon = ICON_PREFIX "seahorse-sign-bad.png";
		sig = TRUE;
		break;
		/* TRANSLATORS: <key id='xxx'> is a custom markup tag, do not translate. */
	case GPG_ERR_CERT_REVOKED:
		body = _("Signed by <i><key id='%s'/> <b>Revoked</b></i> on %s.");
		title = _("Revoked Signature");
		icon = ICON_PREFIX "seahorse-sign-bad.png";
		sig = TRUE;
		break;
	case GPG_ERR_NO_ERROR:
		/* TRANSLATORS: <key id='xxx'> is a custom markup tag, do not translate. */
		body = _("Signed by <i><key id='%s'/></i> on %s.");
		title = _("Good Signature");
		icon = ICON_PREFIX "seahorse-sign-ok.png";
		sig = TRUE;
		break;
	case GPG_ERR_NO_PUBKEY:
		body = _("Signing key not in keyring.");
		title = _("Unknown Signature");
		icon = ICON_PREFIX "seahorse-sign-unknown.png";
		break;
	case GPG_ERR_BAD_SIGNATURE:
		body = _("Bad or forged signature. The signed data was modified.");
		title = _("Bad Signature");
		icon = ICON_PREFIX "seahorse-sign-bad.png";
		break;
	case GPG_ERR_NO_DATA:
		return;
	default:
		if (!GPG_IS_OK (status->signatures->status))
			seahorse_gpgme_handle_error (status->signatures->status, 
			                             _("Couldn't verify signature."));
		return;
	};

	if (sig) {
		gchar *date = seahorse_util_get_display_date_string (status->signatures->timestamp);
		gchar *id = seahorse_context_id_to_dbus (SCTX_APP (), seahorse_object_get_id (object));
		body = g_markup_printf_escaped (body, id, date);
		g_free (date);
		g_free (id);
	} else {
		body = g_strdup (body);
	}

	if (data) {
		data = seahorse_util_uri_get_last (data);
	    unesc_data = g_uri_unescape_string (data, NULL);
		title = g_strdup_printf ("%s: %s", unesc_data, title);
		g_free (unesc_data);
	} else {
		title = g_strdup (title);
	}

	seahorse_notification_display (title, body, !sig, icon, NULL);

	g_free(title);
	g_free(body);
}    
G_MODULE_EXPORT void
on_gpgme_add_subkey_ok_clicked (GtkButton *button,
                                gpointer user_data)
{
	SeahorseWidget *swidget = SEAHORSE_WIDGET (user_data);
	SeahorseObjectWidget *skwidget;
	SeahorseKeyEncType real_type;
	gint type;
	guint length;
	time_t expires;
	gpgme_error_t err;
	GtkWidget *widget;
	GtkComboBox *combo;
	GtkTreeModel *model;
    GtkTreeIter iter;
	
	skwidget = SEAHORSE_OBJECT_WIDGET (swidget);
	
	combo = GTK_COMBO_BOX (seahorse_widget_get_widget (swidget, "type"));
	gtk_combo_box_get_active_iter (combo, &iter);
	model = gtk_combo_box_get_model (combo);
	gtk_tree_model_get (model, &iter,
                        COMBO_INT, &type,
                        -1);	
		
	length = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (
		seahorse_widget_get_widget (swidget, LENGTH)));
	
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
	seahorse_widget_get_widget (swidget, "never_expires"))))
		expires = 0;
	else {
        widget = GTK_WIDGET (g_object_get_data (G_OBJECT (swidget), "expires-datetime"));
        g_return_if_fail (widget);

        egg_datetime_get_as_time_t (EGG_DATETIME (widget), &expires);
   }
	
	switch (type) {
		case 0:
			real_type = DSA;
			break;
		case 1:
			real_type = ELGAMAL;
			break;
		case 2:
			real_type = RSA_SIGN;
			break;
		default:
			real_type = RSA_ENCRYPT;
			break;
	}
	
	widget = GTK_WIDGET (seahorse_widget_get_widget (swidget, swidget->name));
	gtk_widget_set_sensitive (widget, FALSE);
	err = seahorse_gpgme_key_op_add_subkey (SEAHORSE_GPGME_KEY (skwidget->object), 
	                                        real_type, length, expires);
	gtk_widget_set_sensitive (widget, TRUE);
	
	if (!GPG_IS_OK (err))
		seahorse_gpgme_handle_error (err, _("Couldn't add subkey"));

	seahorse_widget_destroy (swidget);
}
/**
 * seahorse_service_crypto_verify_text:
 * @crypto: #SeahorseServiceCrypto context
 * @ktype: "openpgp"
 * @flags: FLAG_QUIET for no notification
 * @crypttext: the text to decrypt
 * @cleartext: the plaintext after verification (out)
 * @signer: the signer if the text is signed (out)
 * @error: a potential error (out)
 *
 * DBus: VerifyText
 *
 * Decrypts the @crypttext and returns it in @cleartext. If the text
 * was signed, the signed is returned.
 *
 * Returns: TRUE on success
 */
gboolean
seahorse_service_crypto_verify_text (SeahorseServiceCrypto *crypto, 
                                     const gchar *ktype, int flags, 
                                     const gchar *crypttext, gchar **cleartext,
                                     char **signer, GError **error)
{
    gpgme_verify_result_t status;
    gpgme_error_t gerr;
    SeahorseGpgmeOperation *pop; 
    gpgme_data_t plain, cipher;
    gboolean ret = TRUE;
    GQuark keyid;
    
    if (!g_str_equal (ktype, g_quark_to_string (SEAHORSE_PGP))) {
        g_set_error (error, SEAHORSE_DBUS_ERROR, SEAHORSE_DBUS_ERROR_INVALID,
                     _("Invalid key type for verifying: %s"), ktype);
        return FALSE;        
    }

    /* 
     * TODO: Once we support different kinds of keys that support encryption
     * then all this logic will need to change. 
     */

    pop = seahorse_gpgme_operation_new (NULL);
    
    /* new data from text */
    gerr = gpgme_data_new_from_mem (&cipher, crypttext, strlen (crypttext), FALSE);
    g_return_val_if_fail (GPG_IS_OK (gerr), FALSE);
    gerr = gpgme_data_new (&plain);
    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 decryption */
    gerr = gpgme_op_verify_start (pop->gctx, cipher, NULL, plain);

    /* Frees plain */
    ret = process_crypto_result (pop, gerr, plain, cleartext, NULL, error);
    
    if (ret) {
        *signer = NULL;
        status = gpgme_op_verify_result (pop->gctx);
    
        if (status->signatures) {
            if (!(flags & FLAG_QUIET))
                notify_signatures (NULL, status);
            if (status->signatures->summary & GPGME_SIGSUM_GREEN ||
                status->signatures->summary & GPGME_SIGSUM_VALID ||
                status->signatures->summary & GPGME_SIGSUM_KEY_MISSING) {
                keyid = seahorse_pgp_key_canonize_id (status->signatures->fpr);
                *signer = seahorse_context_id_to_dbus (SCTX_APP (), keyid);
            }
        }
    }
    
    g_object_unref (pop);
    gpgme_data_release (cipher);
    return TRUE;
}
/**
* 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;
}
G_MODULE_EXPORT gboolean
on_gpgme_sign_ok_clicked (BastileWidget *swidget, GtkWindow *parent)
{
    BastileSignCheck check;
    BastileSignOptions options = 0;
    BastileObject *signer;
    GtkWidget *w;
    gpgme_error_t err;
    BastileObject *to_sign;

    /* Figure out choice */
    check = SIGN_CHECK_NO_ANSWER;
    w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-choice-not"));
    g_return_val_if_fail (w != NULL, FALSE);
    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)))
        check = SIGN_CHECK_NONE;
    else {
        w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-choice-casual"));
        g_return_val_if_fail (w != NULL, FALSE);
        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)))
            check = SIGN_CHECK_CASUAL;
        else {
            w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-choice-careful"));
            g_return_val_if_fail (w != NULL, FALSE);
            if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)))
                check = SIGN_CHECK_CAREFUL;
        }
    }

    /* Local signature */
    w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-option-local"));
    g_return_val_if_fail (w != NULL, FALSE);
    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)))
        options |= SIGN_LOCAL;

    /* Revocable signature */
    w = GTK_WIDGET (bastile_widget_get_widget (swidget, "sign-option-revocable"));
    g_return_val_if_fail (w != NULL, FALSE);
    if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)))
        options |= SIGN_NO_REVOKE;

    /* Signer */
    w = GTK_WIDGET (bastile_widget_get_widget (swidget, "signer-select"));
    g_return_val_if_fail (w != NULL, FALSE);
    signer = bastile_combo_keys_get_active (GTK_COMBO_BOX (w));

    g_assert (!signer || (BASTILE_IS_GPGME_KEY (signer) &&
                          bastile_object_get_usage (BASTILE_OBJECT (signer)) == BASTILE_USAGE_PRIVATE_KEY));

    to_sign = g_object_get_data (G_OBJECT (swidget), "to-sign");
    if (BASTILE_IS_GPGME_UID (to_sign))
        err = bastile_gpgme_key_op_sign_uid (BASTILE_GPGME_UID (to_sign), BASTILE_GPGME_KEY (signer), check, options);
    else if (BASTILE_IS_GPGME_KEY (to_sign))
        err = bastile_gpgme_key_op_sign (BASTILE_GPGME_KEY (to_sign), BASTILE_GPGME_KEY (signer), check, options);
    else
        g_assert (FALSE);


    if (!GPG_IS_OK (err)) {
        if (gpgme_err_code (err) == GPG_ERR_EALREADY) {
            w = gtk_message_dialog_new (parent, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
                                        _("This key was already signed by\n\"%s\""), bastile_object_get_label (signer));
            gtk_dialog_run (GTK_DIALOG (w));
            gtk_widget_destroy (w);
        } else
            bastile_gpgme_handle_error (err, _("Couldn't sign key"));
    }

    bastile_widget_destroy (swidget);

    return TRUE;
}
Exemple #22
0
gboolean
seahorse_gpgme_photo_add (SeahorseGpgmeKey *pkey,
                          GtkWindow *parent,
                          const gchar *path)
{
	gchar *filename = NULL;
	gchar *tempfile = NULL;
	GError *error = NULL;
	gpgme_error_t gerr;
	GtkWidget *chooser;
	gboolean res = TRUE;

	g_return_val_if_fail (SEAHORSE_IS_GPGME_KEY (pkey), FALSE);

	if (NULL == path) {
		chooser = gtk_file_chooser_dialog_new (_("Choose Photo to Add to Key"), parent,
		                                      GTK_FILE_CHOOSER_ACTION_OPEN,
		                                      GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
		                                      GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
		                                      NULL);

		gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
		gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE);
		add_image_files (chooser);

		if (gtk_dialog_run (GTK_DIALOG (chooser)) == GTK_RESPONSE_ACCEPT)
			filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));

		gtk_widget_destroy (chooser);

		if (!filename)
			return FALSE;
	} else {
		filename = g_strdup (path);
	}

	if (!prepare_photo_id (parent, filename, &tempfile, &error)) {
		seahorse_util_handle_error (&error, NULL, _("Couldn’t prepare photo"));
		return FALSE;
	}

	gerr = seahorse_gpgme_key_op_photo_add (pkey, tempfile ? tempfile : filename);
	if (!GPG_IS_OK (gerr)) {

		/* A special error value set by seahorse_key_op_photoid_add to
		   denote an invalid format file */
		if (gerr == GPG_E (GPG_ERR_USER_1))
			seahorse_util_show_error (NULL, _("Couldn’t add photo"),
			                          _("The file could not be loaded. It may be in an invalid format"));
		else
			seahorse_gpgme_handle_error (gerr, _("Couldn’t add photo"));
		res = FALSE;
	}

	g_free (filename);
	if (tempfile) {
		unlink (tempfile);
		g_free (tempfile);
	}

	return res;
}