예제 #1
0
/**
* resolver: The avahi resolver
* iface: The avahi interface
* proto: The avahi protocol
* event: the avahi event
* name: name of the service
* type: must be HKP_SERVICE_TYPE
* domain: ignored
* host_name: ignored
* address: address of the service
* port: port of the service
* txt: ignored
* flags:
* data: userdata
*
* Resolves the avahi callback (AvahiServiceResolverCallback)
*
**/
static void 
resolve_callback (AvahiServiceResolver *resolver, AvahiIfIndex iface, AvahiProtocol proto, 
                  AvahiResolverEvent event, const char *name, const char *type, const char *domain,
                  const char *host_name, const AvahiAddress *address, uint16_t port, 
                  AvahiStringList *txt, AvahiLookupResultFlags flags, void *data)
{
    BastileServiceDiscovery *ssd = BASTILE_SERVICE_DISCOVERY (data);
    gchar *service_name;
    gchar *service_uri;
    gchar *ipname;
    
    g_assert (BASTILE_IS_SERVICE_DISCOVERY (ssd));


    switch(event) {
    case AVAHI_RESOLVER_FAILURE:
        g_warning ("couldn't resolve service '%s': %s", name, 
                   avahi_strerror (avahi_client_errno (ssd->priv->client)));
        break;
    
    
    case AVAHI_RESOLVER_FOUND:
        
        /* Make sure it's our type ... */
        /* XXX Is the service always guaranteed to be ascii? */
        if (g_ascii_strcasecmp (HKP_SERVICE_TYPE, type) != 0)
            break;
        
#ifndef DISCOVER_THIS_HOST
        /* And that it's local */
        if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
            break;
#endif
        
        ipname = g_new0(gchar, AVAHI_ADDRESS_STR_MAX);
        avahi_address_snprint (ipname, AVAHI_ADDRESS_STR_MAX, address);
        
        service_uri = g_strdup_printf ("hkp://%s:%d", ipname, (int)port);
        service_name = g_strdup (name);
        
        g_hash_table_replace (ssd->services, service_name, service_uri);
        g_signal_emit (ssd, signals[ADDED], 0, service_name);
    
        /* Add it to the context */
        if (!bastile_context_remote_source (SCTX_APP (), service_uri)) {
            BastileServerSource *ssrc = bastile_server_source_new (service_uri);
            g_return_if_fail (ssrc != NULL);
            bastile_context_add_source (SCTX_APP (), BASTILE_SOURCE (ssrc));
        }
    
        DEBUG_DNSSD (("DNS-SD added: %s %s\n", service_name, service_uri));
        break;
        
    default:
        break;
    };

    /* One result is enough for us */
    avahi_service_resolver_free (resolver);
}
예제 #2
0
/**
* browser: The avahi browser
* iface: the interface
* proto: the protocol
* event: the event that happened while browsing (failure, new, remove)
* name: name of the service
* type: HKP_SERVICE_TYPE is expected
* domain: domain of the service
* flags: ignored
* data: userdata, type BastileServiceDiscovery
*
* Called when a service is discovered while browsing.
* It is a AvahiServiceBrowserCallback
*
**/
static void 
browse_callback(AvahiServiceBrowser *browser, AvahiIfIndex iface, AvahiProtocol proto,
                AvahiBrowserEvent event, const char *name, const char *type, 
                const char *domain, AvahiLookupResultFlags flags, void* data) 
{
    BastileServiceDiscovery *ssd = BASTILE_SERVICE_DISCOVERY (data);
    const gchar *uri;
    
    g_assert (BASTILE_IS_SERVICE_DISCOVERY (ssd));
    g_assert (browser == ssd->priv->browser);
    
     /* XXX Is the service always guaranteed to be ascii? */
    if (g_ascii_strcasecmp (HKP_SERVICE_TYPE, type) != 0)
        return;

    switch (event) {
    case AVAHI_BROWSER_FAILURE:
        g_warning ("failure browsing for services: %s", 
                   avahi_strerror (avahi_client_errno (ssd->priv->client)));
        disconnect (ssd);
        break;
    
    
    case AVAHI_BROWSER_NEW:
        if (!avahi_service_resolver_new (ssd->priv->client, iface, proto, name, type, 
                                         domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, ssd))
            g_warning ("couldn't start resolver for service '%s': %s\n", name, 
                       avahi_strerror (avahi_client_errno (ssd->priv->client)));
        break;
        
        
    case AVAHI_BROWSER_REMOVE:
        uri = g_hash_table_lookup (ssd->services, name);
        if (uri != NULL) {
            /* Remove it from the main context */
            BastileSource *sksrc = bastile_context_remote_source (SCTX_APP(), uri);
            bastile_context_remove_source (SCTX_APP(), sksrc);
        }
        
        /* And remove it from our tables */
        g_hash_table_remove (ssd->services, name);
        g_signal_emit (ssd, signals[REMOVED], 0, name);
        DEBUG_DNSSD (("DNS-SD removed: %s\n", name));
        break;
        
    
    default:
        break;
    }
}
예제 #3
0
/**
 * 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;
}
예제 #4
0
static void
add_key (SeahorseHKPSource *ssrc, SeahorsePgpKey *key)
{
	SeahorseObject *prev;
	GQuark keyid;
       
	keyid = seahorse_pgp_key_canonize_id (seahorse_pgp_key_get_keyid (key));
	prev = seahorse_context_get_object (SCTX_APP (), SEAHORSE_SOURCE (ssrc), keyid);
	if (prev != NULL) {
		g_return_if_fail (SEAHORSE_IS_PGP_KEY (prev));
		seahorse_pgp_key_set_uids (SEAHORSE_PGP_KEY (prev), seahorse_pgp_key_get_uids (key));
		seahorse_pgp_key_set_subkeys (SEAHORSE_PGP_KEY (prev), seahorse_pgp_key_get_subkeys (key));
		return;
	}

	/* Add to context */ 
	seahorse_object_set_source (SEAHORSE_OBJECT (key), SEAHORSE_SOURCE (ssrc));
	seahorse_context_add_object (SCTX_APP (), SEAHORSE_OBJECT (key));
}
예제 #5
0
guint
seahorse_pgp_signature_get_sigtype (SeahorsePgpSignature *self)
{
	SeahorseObject *sobj;
	GQuark id;

	g_return_val_if_fail (SEAHORSE_IS_PGP_SIGNATURE (self), 0);
    
	id = seahorse_pgp_key_canonize_id (self->pv->keyid);
	sobj = seahorse_context_find_object (SCTX_APP (), id, SEAHORSE_LOCATION_LOCAL);
    
	if (sobj) {
		if (seahorse_object_get_usage (sobj) == SEAHORSE_USAGE_PRIVATE_KEY) 
			return SKEY_PGPSIG_TRUSTED | SKEY_PGPSIG_PERSONAL;
		if (seahorse_object_get_flags (sobj) & SEAHORSE_FLAG_TRUSTED)
			return SKEY_PGPSIG_TRUSTED;
	}

	return 0;
}
예제 #6
0
/**
 * 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;
}
예제 #7
0
/**
* 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;
}
예제 #8
0
/**
* 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);
}    
예제 #9
0
/**
 * main:
 * @argc: default arguments
 * @argv: default arguments
 *
 * Parses the options, daemonizes, starts HKP, DBus and Avahi
 *
 * Returns: 0 on success
 */
int main(int argc, char* argv[])
{
    GOptionContext *octx = NULL;
    GError *error = NULL;

    seahorse_secure_memory_init ();
    
    octx = g_option_context_new ("");
    g_option_context_add_main_entries (octx, options, GETTEXT_PACKAGE);
    g_option_context_add_group (octx, egg_sm_client_get_option_group ());

    if (!gtk_init_with_args (&argc, &argv, _("Encryption Daemon (Seahorse)"), 
                             (GOptionEntry *)options, GETTEXT_PACKAGE, &error)) {
	    g_printerr ("seahorse-daemon: %s\n", error->message);
	    g_error_free (error);
	    exit (1);
    }
     	 
	g_signal_connect (egg_sm_client_get (), "quit", G_CALLBACK (smclient_quit), NULL);

    /*
     * All functions after this point have to print messages
     * nicely and not just called exit()
     */
    daemonize ();

    /* Handle some signals */
    seahorse_unix_signal_register (SIGINT, unix_signal);
    seahorse_unix_signal_register (SIGTERM, unix_signal);

    /* We log to the syslog */
    prepare_logging ();

    /* Insert Icons into Stock */
    seahorse_gtkstock_init ();
   
    /* Make the default SeahorseContext */
    seahorse_context_new (SEAHORSE_CONTEXT_APP | SEAHORSE_CONTEXT_DAEMON);

    /* Load the various components */
    seahorse_pgp_module_init ();

    seahorse_context_refresh_auto (NULL);

    /* Initialize the various daemon components */
    seahorse_dbus_server_init ();

    /* Sometimes we've already gotten a quit signal */
    if(!daemon_quit) {
        daemon_running = TRUE;
        gtk_main ();
        g_message ("left gtk_main\n");
    }

    seahorse_dbus_server_cleanup ();

    g_option_context_free (octx);
    seahorse_context_destroy (SCTX_APP ());

    return 0;
}
예제 #10
0
/**
* 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;
}
예제 #11
0
void
bastile_keyserver_sync (GList *keys)
{
    BastileSource *sksrc;
    BastileSource *lsksrc;
    BastileMultiOperation *mop;
    BastileOperation *op;
    gchar *keyserver;
    GSList *ks, *l;
    GList *k;
    GSList *keyids = NULL;
    
    if (!keys)
        return;
    
    g_assert (BASTILE_IS_OBJECT (keys->data));
    
    /* Build a keyid list */
    for (k = keys; k; k = g_list_next (k)) 
        keyids = g_slist_prepend (keyids, 
                    GUINT_TO_POINTER (bastile_object_get_id (BASTILE_OBJECT (k->data))));

    mop = bastile_multi_operation_new ();

    /* And now synchronizing keys from the servers */
    ks = bastile_servers_get_uris ();
    
    for (l = ks; l; l = g_slist_next (l)) {
        
        sksrc = bastile_context_remote_source (SCTX_APP (), (const gchar*)(l->data));

        /* This can happen if the URI scheme is not supported */
        if (sksrc == NULL)
            continue;
        
        lsksrc = bastile_context_find_source (SCTX_APP (), 
                        bastile_source_get_tag (sksrc), BASTILE_LOCATION_LOCAL);
        
        if (lsksrc) {
            op = bastile_transfer_operation_new (_("Synchronizing keys"), sksrc, lsksrc, keyids);
            g_return_if_fail (op != NULL);

            bastile_multi_operation_take (mop, op);
            bastile_operation_watch (op, (BastileDoneFunc) sync_export_complete, sksrc, NULL, NULL);
        }
    }
    
    bastile_util_string_slist_free (ks);
    
    /* Publishing keys online */    
    keyserver = bastile_mateconf_get_string (PUBLISH_TO_KEY);
    if (keyserver && keyserver[0]) {
        
        sksrc = bastile_context_remote_source (SCTX_APP (), keyserver);

        /* This can happen if the URI scheme is not supported */
        if (sksrc != NULL) {

            op = bastile_context_transfer_objects (SCTX_APP (), keys, sksrc);
            g_return_if_fail (sksrc != NULL);

            bastile_multi_operation_take (mop, op);
            bastile_operation_watch (op, (BastileDoneFunc) sync_import_complete, sksrc, NULL, NULL);

        }
    }

    g_slist_free (keyids);
    g_free (keyserver);
    
    /* Show the progress window if necessary */
    bastile_progress_show (BASTILE_OPERATION (mop), _("Synchronizing keys..."), FALSE);
    g_object_unref (mop);
}
예제 #12
0
/* Initializes context and preferences, then loads key manager */
int
main (int argc, char **argv)
{
    static GOptionEntry options[] = {
        { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL },
        { NULL, 0, 0, 0, NULL, NULL, NULL }
    };
    GError *error = NULL;
    int ret = 0;

    g_thread_init (NULL);

    bastile_secure_memory_init ();
    
#ifdef ENABLE_NLS
    bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
    bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
    textdomain (GETTEXT_PACKAGE);
#endif

    if (!gtk_init_with_args (&argc, &argv, _("Encryption Key Manager"), options, GETTEXT_PACKAGE, &error)) {
        g_printerr ("bastile: %s\n", error->message);
        g_error_free (error);
        exit (1);
    }

    if (show_version) {
        g_print ("%s\n", PACKAGE_STRING);
        g_print ("GNUPG: %s (%d.%d.%d)\n", GNUPG, GPG_MAJOR, GPG_MINOR, GPG_MICRO);
        exit (1);
    }

    /* Insert Icons into Stock */ 
    bastile_gtkstock_init ();
    
    /* Make the default BastileContext */
    bastile_context_new (BASTILE_CONTEXT_APP);

    /* Initialize the various components */
#ifdef WITH_PGP
    bastile_pgp_module_init ();
#endif
#ifdef WITH_SSH
    bastile_ssh_module_init ();
#endif
#ifdef WITH_PKCS11
    bastile_pkcs11_module_init ();
#endif
    bastile_gkr_module_init ();

    bastile_key_manager_show ();

    /* Start the refreshing of the keys */
    bastile_context_refresh_auto (NULL);

    g_signal_connect_after (SCTX_APP (), "destroy", gtk_main_quit, NULL);
    
    gtk_main ();


    bastile_cleanup_perform ();
    return ret;
}