Commit 37f3e64d authored by Stefan Walter's avatar Stefan Walter

Add DNS-SD key sharing

    * configure.in:
    * daemon/Makefile.am:
    * daemon/seahorse-daemon.c:
    * daemon/seahorse-daemon.h:
    * daemon/seahorse-hkp-server.c:
    * daemon/seahorse-sharing.c:
    * data/seahorse.schemas.in:
    * libseahorse/Makefile.am:
    * libseahorse/seahorse-context.c:
    * libseahorse/seahorse-context.h:
    * libseahorse/seahorse-dns-sd.c:
    * libseahorse/seahorse-dns-sd.h:
    * libseahorse/seahorse-gconf.h:
    * libseahorse/seahorse-prefs.c:
    * libseahorse/seahorse-prefs.glade:
    * libseahorse/seahorse-server-source.c:
    * libseahorse/seahorse-server-source.h:
    * libseahorse/seahorse-util.c:
    * libseahorse/seahorse-util.h:
    * pixmaps/Makefile.am:
    * pixmaps/seahorse-share-keys.png:
    * pixmaps/seahorse-share-keys.xcf:
    * src/seahorse-keyserver-search.c:
    * src/seahorse-keyserver-search.glade: Add DNS-SD key sharing
parent 424fcb0d
2005-05-20 Nate Nielsen <nielsen@memberwebs.com>
* configure.in:
* daemon/Makefile.am:
* daemon/seahorse-daemon.c:
* daemon/seahorse-daemon.h:
* daemon/seahorse-hkp-server.c:
* daemon/seahorse-sharing.c:
* data/seahorse.schemas.in:
* libseahorse/Makefile.am:
* libseahorse/seahorse-context.c:
* libseahorse/seahorse-context.h:
* libseahorse/seahorse-dns-sd.c:
* libseahorse/seahorse-dns-sd.h:
* libseahorse/seahorse-gconf.h:
* libseahorse/seahorse-prefs.c:
* libseahorse/seahorse-prefs.glade:
* libseahorse/seahorse-server-source.c:
* libseahorse/seahorse-server-source.h:
* libseahorse/seahorse-util.c:
* libseahorse/seahorse-util.h:
* pixmaps/Makefile.am:
* pixmaps/seahorse-share-keys.png:
* pixmaps/seahorse-share-keys.xcf:
* src/seahorse-keyserver-search.c:
* src/seahorse-keyserver-search.glade: Add DNS-SD key sharing
2005-05-19 Nate Nielsen <nielsen@memberwebs.com>
* Merge seahorse-0-8 changes into HEAD
......
......@@ -321,6 +321,41 @@ else
fi
dnl *******************
dnl KEY SHARING
dnl *******************
# Allow sharing to be disabled
AC_ARG_ENABLE(sharing,
AC_HELP_STRING([--disable-sharing],
[Don't compile in key sharing]))
if test "$enable_hkp" != "yes"; then
echo "key sharing requires HKP support"
enable_sharing=no
fi
if test "$enable_sharing" = "no"; then
echo "disabling key sharing"
else
PKG_CHECK_MODULES(HOWL, howl >= 0.9.6)
if test -n "$HOWL_CFLAGS"; then
echo "enabling key sharing"
enable_sharing=yes
fi
SEAHORSE_CFLAGS="$SEAHORSE_CFLAGS $HOWL_CFLAGS"
SEAHORSE_LIBS="$SEAHORSE_LIBS $HOWL_LIBS"
AC_DEFINE_UNQUOTED(WITH_SHARING, 1, [Compile key sharing code])
fi
AM_CONDITIONAL(WITH_SHARING, test "$enable_sharing" != "no")
dnl *******************
# Debug mode
AC_ARG_ENABLE(debug,
AC_HELP_STRING([--enable-debug],
......@@ -388,4 +423,5 @@ Plugins:
GEdit: $enable_gedit
Nautilus (v < 2.8): $with_nautilus
Nautilus (v > 2.10): $with_nautilus_ext
Key Sharing: $enable_sharing
"
......@@ -21,9 +21,16 @@ else
AGENT_LIB =
endif
if WITH_SHARING
SHARING_SRCS = seahorse-hkp-server.c seahorse-sharing.c
else
SHARING_SRCS =
endif
seahorse_daemon_SOURCES = \
seahorse-daemon.c \
seahorse-daemon.h
seahorse-daemon.h \
$(SHARING_SRCS)
seahorse_daemon_LDADD = \
$(top_builddir)/libseahorse/libseahorse-internal.la \
......
......@@ -230,12 +230,20 @@ int main(int argc, char* argv[])
/* We log to the syslog */
prepare_logging ();
/* Initialize the various daemon components */
#ifdef WITH_AGENT
seahorse_agent_init ();
#endif
#ifdef WITH_SHARING
seahorse_sharing_init();
#endif
gtk_main ();
/* And now clean them all up */
#ifdef WITH_SHARING
seahorse_sharing_cleanup();
#endif
#ifdef WITH_AGENT
seahorse_agent_uninit ();
#endif
......
......@@ -22,20 +22,33 @@
#ifndef _SEAHORSE_DAEMON_H_
#define _SEAHORSE_DAEMON_H_
#include "config.h"
/* seahorse-sharing.c ------------------------------------------------------- */
#ifdef WITH_SHARING
void seahorse_sharing_init();
void seahorse_sharing_cleanup();
#endif
/* seahorse-hkp-server.c ---------------------------------------------------- */
gboolean seahorse_hkp_server_start();
#ifdef WITH_HKP
gboolean seahorse_hkp_server_start (GError **err);
void seahorse_hkp_server_stop ();
guint seahorse_hkp_server_get_port ();
void seahorse_hkp_server_stop();
gboolean seahorse_hkp_server_is_running ();
guint seahorse_hkp_server_get_port();
#define HKP_SERVER_ERROR (seahorse_hkp_server_error_domain ())
GQuark seahorse_hkp_server_error_domain ();
gboolean seahorse_hkp_server_is_running();
#endif
#endif /* _SEAHORSE_DAEMON_H_ */
This diff is collapsed.
/*
* Seahorse
*
* Copyright (C) 2005 Nate Nielsen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gnome.h>
#include <howl.h>
/* Workaround broken howl installing config.h */
#undef PACKAGE
#undef VERSION
#undef PACKAGE_STRING
#undef PACKAGE_NAME
#undef PACKAGE_VERSION
#undef PACKAGE_TARNAME
#include "config.h"
#include "eggtrayicon.h"
#include "seahorse-daemon.h"
#include "seahorse-gconf.h"
#include "seahorse-util.h"
/* TODO: Need to be able to advertize in real domains */
static void start_sharing ();
static void stop_sharing ();
/* For the docklet icon */
static EggTrayIcon *tray_icon = NULL;
static guint gconf_notify_id = 0;
/* DNS-SD publishing -------------------------------------------------------- */
static sw_discovery_publish_id published_id = 0;
static sw_discovery howl_session = NULL;
static guint channel_notify_id = 0;
static sw_result
publish_reply (sw_discovery discovery, sw_discovery_publish_status status,
sw_discovery_oid id, sw_opaque extra)
{
return SW_OKAY;
}
static gboolean
howl_input (GIOChannel *io_channel, GIOCondition cond, gpointer callback_data)
{
sw_discovery session = callback_data;
sw_salt salt;
if (sw_discovery_salt (session, &salt) == SW_OKAY) {
sw_salt_lock (salt);
sw_discovery_read_socket (session);
sw_salt_unlock (salt);
}
return TRUE;
}
static void
stop_publishing (void)
{
if (published_id != 0)
sw_discovery_cancel (howl_session, published_id);
published_id = 0;
if (channel_notify_id != 0)
g_source_remove (channel_notify_id);
if (howl_session)
sw_discovery_fina (howl_session);
howl_session = NULL;
}
static gboolean
start_publishing (int port)
{
GIOChannel *channel;
sw_result result;
gchar *user_name;
gchar *share_name;
int fd;
if (sw_discovery_init (&howl_session) != SW_OKAY)
return FALSE;
fd = sw_discovery_socket (howl_session);
channel = g_io_channel_unix_new (fd);
channel_notify_id = g_io_add_watch (channel, G_IO_IN, howl_input, howl_session);
g_io_channel_unref (channel);
user_name = seahorse_util_string_up_first (g_get_user_name ());
/* Translators: The %s will get filled in with the user name
of the user, to form a genitive. If this is difficult to
translate correctly so that it will work correctly in your
language, you may use something equivalent to
"Shared keys of %s", or leave out the %s altogether.
In the latter case, please put "%.0s" somewhere in the string,
which will match the user name string passed by the C code,
but not put the user name in the final string. This is to
avoid the warning that msgfmt might otherwise generate. */
share_name = g_strdup_printf (_("%s's encryption keys"), user_name);
g_free (user_name);
result = sw_discovery_publish (howl_session, 0, share_name, "_hkp._tcp",
NULL, NULL, port, /* text */"", 0,
publish_reply, NULL, &published_id);
g_free (share_name);
if (result != SW_OKAY) {
stop_publishing ();
return FALSE;
}
return TRUE;
}
/* Tray Icon ---------------------------------------------------------------- */
static void
stop_activate (GtkWidget *item, gpointer data)
{
seahorse_gconf_set_boolean (KEYSHARING_KEY, FALSE);
}
static void
prefs_activate (GtkWidget *item, gpointer data)
{
GError *err = NULL;
g_spawn_command_line_async ("seahorse-pgp-preferences --sharing", &err);
if (err != NULL) {
g_warning ("couldn't execute seahorse-pgp-preferences: %s", err->message);
g_error_free (err);
}
}
/* Called when icon destroyed */
static void
tray_destroyed (GtkWidget *widget, void *data)
{
g_object_unref (G_OBJECT (tray_icon));
tray_icon = NULL;
}
/* Called when icon clicked */
static void
tray_clicked (GtkWidget *button, GdkEventButton *event, void *data)
{
GtkWidget *image, *menu;
GtkWidget *item;
if (event->type != GDK_BUTTON_PRESS)
return;
/* Right click, show menu */
if (event->button == 3) {
menu = gtk_menu_new ();
/* Stop Sharing menu item */
item = gtk_image_menu_item_new_with_mnemonic (_("_Stop Sharing My Keys"));
image = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
g_signal_connect (item, "activate", G_CALLBACK (stop_activate), NULL);
gtk_menu_append (menu, item);
/* Sharing Preferences menu item */
item = gtk_image_menu_item_new_from_stock (GTK_STOCK_PREFERENCES, NULL);
g_signal_connect (item, "activate", G_CALLBACK (prefs_activate), NULL);
gtk_menu_append (menu, item);
gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
event->button, gtk_get_current_event_time ());
gtk_widget_show_all (menu);
}
}
static void
show_tray ()
{
GtkWidget *box;
GtkWidget *image;
if (!tray_icon) {
tray_icon = egg_tray_icon_new ("seahorse-daemon-sharing");
box = gtk_event_box_new ();
image = gtk_image_new_from_file (PIXMAPSDIR "seahorse-share-keys.png");
gtk_container_add (GTK_CONTAINER (box), image);
gtk_container_add (GTK_CONTAINER (tray_icon), box);
g_signal_connect (G_OBJECT (tray_icon), "destroy",
G_CALLBACK (tray_destroyed), NULL);
g_signal_connect (G_OBJECT (box), "button-press-event",
G_CALLBACK (tray_clicked), NULL);
if (!gtk_check_version (2, 4, 0))
g_object_set (G_OBJECT (box), "visible-window", FALSE, NULL);
gtk_widget_show_all (GTK_WIDGET (tray_icon));
g_object_ref (G_OBJECT (tray_icon));
}
}
static void
hide_tray ()
{
if (tray_icon) {
g_signal_handlers_disconnect_by_func (G_OBJECT (tray_icon),
G_CALLBACK (tray_destroyed), NULL);
gtk_widget_destroy (GTK_WIDGET (tray_icon));
g_object_unref (G_OBJECT (tray_icon));
tray_icon = NULL;
}
}
/* -------------------------------------------------------------------------- */
static void
start_sharing ()
{
GError *err = NULL;
if (!seahorse_hkp_server_is_running ()) {
if (!seahorse_hkp_server_start (&err)) {
seahorse_util_handle_error (err, _("Couldn't start the key sharing server."));
return;
}
if (!start_publishing (seahorse_hkp_server_get_port ())) {
seahorse_hkp_server_stop ();
/* TODO: Do we need something more descriptive here? */
seahorse_util_show_error (NULL, _("Couldn't publish key sharing information."));
return;
}
}
show_tray ();
}
static void
stop_sharing ()
{
stop_publishing ();
if (seahorse_hkp_server_is_running ())
seahorse_hkp_server_stop ();
hide_tray ();
}
static void
gconf_notify (GConfClient *client, guint id, GConfEntry *entry, gpointer data)
{
if (g_str_equal (KEYSHARING_KEY, gconf_entry_get_key (entry))) {
if (gconf_value_get_bool (gconf_entry_get_value (entry)))
start_sharing ();
else
stop_sharing ();
}
}
void
seahorse_sharing_init ()
{
gconf_notify_id = seahorse_gconf_notify (KEYSHARING_KEY, gconf_notify, NULL);
if (seahorse_gconf_get_boolean (KEYSHARING_KEY))
start_sharing();
}
void
seahorse_sharing_cleanup ()
{
if (gconf_notify_id)
seahorse_gconf_unnotify (gconf_notify_id);
gconf_notify_id = 0;
stop_sharing ();
}
......@@ -49,6 +49,20 @@
</locale>
</schema>
</schemalist>
<schemalist>
<schema>
<key>/schemas/apps/seahorse/sharing/sharing_enabled</key>
<applyto>/apps/seahorse/sharing/sharing_enabled</applyto>
<owner>seahorse</owner>
<type>bool</type>
<default>FALSE</default>
<locale name="C">
<short>Enable DNS-SD sharing</short>
<long>Enables DNS-SD (OpenTalk) sharing of keys. seahorse-daemon
must running and must be built with HKP and DNS-SD support.</long>
</locale>
</schema>
</schemalist>
<schemalist>
<schema>
<key>/schemas/desktop/pgp/ascii_armor</key>
......@@ -205,5 +219,18 @@
<long>The last search pattern searched for against a keyserver.</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/pgp/keyservers/search_keyservers</key>
<applyto>/desktop/pgp/keyservers/search_keyservers</applyto>
<owner>seahorse</owner>
<type>list</type>
<list_type>string</list_type>
<default>[]</default>
<locale name="C">
<short>Last keyservers used</short>
<long>The last keyserver a search was performed against
or empty for all keyservers.</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>
......@@ -68,6 +68,7 @@ libseahorse_internal_la_SOURCES = \
seahorse-operation.c seahorse-operation.h \
seahorse-progress.c seahorse-progress.h \
seahorse-gconf.c seahorse-gconf.h \
seahorse-dns-sd.c seahorse-dns-sd.h \
eggtrayicon.c eggtrayicon.h \
$(BUILT_SOURCES) \
$(AGENT_SRCS) \
......
......@@ -23,6 +23,8 @@
#include <libintl.h>
#include <gnome.h>
#include "config.h"
#include "seahorse-context.h"
#include "seahorse-marshal.h"
#include "seahorse-libdialogs.h"
......@@ -30,9 +32,11 @@
#include "seahorse-util.h"
#include "seahorse-multi-source.h"
#include "seahorse-pgp-source.h"
#include "seahorse-dns-sd.h"
struct _SeahorseContextPrivate {
SeahorseKeySource *source;
SeahorseServiceDiscovery *discovery;
};
static void seahorse_context_class_init (SeahorseContextClass *klass);
......@@ -86,7 +90,9 @@ seahorse_context_init (SeahorseContext *sctx)
/* Our multi source */
sctx->priv->source = SEAHORSE_KEY_SOURCE (seahorse_multi_source_new ());
sctx->priv->discovery = seahorse_service_discovery_new ();
/* The context is explicitly destroyed */
g_object_ref (sctx);
}
......@@ -107,7 +113,11 @@ seahorse_context_dispose (GObject *gobject)
g_object_unref (sctx->priv->source);
sctx->priv->source = NULL;
}
if (sctx->priv->discovery)
g_object_unref (sctx->priv->discovery);
sctx->priv->discovery = NULL;
G_OBJECT_CLASS (parent_class)->dispose (gobject);
}
......@@ -225,3 +235,18 @@ seahorse_context_get_key_source (SeahorseContext *sctx)
g_return_val_if_fail (sctx->priv->source != NULL, NULL);
return sctx->priv->source;
}
/**
* seahorse_context_get_discovery
* @sctx: #SeahorseContext object
*
* Gets the Service Discovery object for this context.
*
* Return: The Service Discovery object.
*/
SeahorseServiceDiscovery*
seahorse_context_get_discovery (SeahorseContext *sctx)
{
g_return_val_if_fail (sctx->priv->discovery != NULL, NULL);
return sctx->priv->discovery;
}
......@@ -29,6 +29,7 @@
#include "seahorse-key.h"
#include "seahorse-key-pair.h"
#include "seahorse-key-source.h"
#include "seahorse-dns-sd.h"
#define SEAHORSE_TYPE_CONTEXT (seahorse_context_get_type ())
#define SEAHORSE_CONTEXT(obj) (GTK_CHECK_CAST ((obj), SEAHORSE_TYPE_CONTEXT, SeahorseContext))
......@@ -71,4 +72,7 @@ SeahorseKeySource* seahorse_context_get_key_source (SeahorseContext *sctx)
void seahorse_context_own_source (SeahorseContext *sctx,
SeahorseKeySource *sksrc);
SeahorseServiceDiscovery*
seahorse_context_get_discovery (SeahorseContext *sctx);
#endif /* __SEAHORSE_CONTEXT_H__ */
/*
* Seahorse
*
* Copyright (C) 2005 Nate Nielsen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gnome.h>
#ifdef WITH_SHARING
/* Workaround broken howl installing config.h */
#undef PACKAGE
#undef VERSION
#undef PACKAGE_STRING
#undef PACKAGE_NAME
#undef PACKAGE_VERSION
#undef PACKAGE_TARNAME
#include <howl.h>
#endif /* WITH_SHARING */
#include "seahorse-dns-sd.h"
#define HKP_SERVICE_TYPE "_hkp._tcp."
/*
* DEBUG: Define if we want to show discoveries from this
* host. Normally these are suppressed
*/
/* #define DISCOVER_THIS_HOST 1 */
struct _SeahorseServiceDiscoveryPriv {
#ifdef WITH_SHARING
sw_discovery session;
sw_discovery_oid oid;
#endif
guint timer;
};
enum {
ADDED,
REMOVED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
static GObjectClass *parent_class = NULL;
/* GObject handlers */
static void class_init (SeahorseServiceDiscoveryClass *ssd);
static void object_init (SeahorseServiceDiscovery *ssd);
static void object_dispose (GObject *gobject);
static void object_finalize (GObject *gobject);
GType
seahorse_service_discovery_get_type (void) {
static GType gtype = 0;
if (!gtype) {
static const GTypeInfo gtinfo = {
sizeof (SeahorseServiceDiscoveryClass), NULL, NULL,
(GClassInitFunc) class_init, NULL, NULL,
sizeof (SeahorseServiceDiscovery), 0, (GInstanceInitFunc) object_init
};
gtype = g_type_register_static (G_TYPE_OBJECT, "SeahorseServiceDiscovery",
&gtinfo, 0);
}
return gtype;
}
static void
class_init (SeahorseServiceDiscoveryClass *klass)
{
GObjectClass *gobject_class;
parent_class = g_type_class_peek_parent (klass);
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = object_dispose;
gobject_class->finalize = object_finalize;
signals[ADDED] = g_signal_new ("added", SEAHORSE_TYPE_SERVICE_DISCOVERY,
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SeahorseServiceDiscoveryClass, added),
NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
signals[REMOVED] = g_signal_new ("removed", SEAHORSE_TYPE_SERVICE_DISCOVERY,
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (SeahorseServiceDiscoveryClass, removed),
NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING);
}
#ifdef WITH_SHARING
static gboolean
salt_timer (SeahorseServiceDiscovery *ssd)
{
sw_salt salt;
sw_ulong timeout = 0;
g_return_val_if_fail (SEAHORSE_IS_SERVICE_DISCOVERY (ssd), FALSE);
g_return_val_if_fail (ssd->priv->session != NULL, FALSE);
sw_discovery_salt (ssd->priv->session, &salt);
sw_salt_step (salt, &timeout);
return TRUE;
}
static sw_result
resolve_callback (sw_discovery discovery, sw_discovery_oid oid, sw_uint32 interface_index,
sw_const_string name, sw_const_string type, sw_const_string domain,
sw_ipv4_address address, sw_port port, sw_octets text_record,
sw_ulong text_record_len, SeahorseServiceDiscovery *ssd)
{
sw_ipv4_address local;
gchar *service_name;
gchar *service_uri;
gchar *ipname;
g_return_val_if_fail (SEAHORSE_IS_SERVICE_DISCOVERY (ssd), SW_DISCOVERY_E_BAD_PARAM);
if (g_strcasecmp (HKP_SERVICE_TYPE, type) != 0)
return SW_OKAY;
/* To prevent warnings */
memset (&local, 0, sizeof (local));
#ifndef DISCOVER_THIS_HOST
/*
* TODO: In the future there needs to be a better way of determining
* which services we see that are from the local host. This can fail
* on multihomed hosts.
*/
sw_ipv4_address_init_from_this_host (&local);
if (sw_ipv4_address_equals (local, address))
return SW_OKAY;
#endif /* DISCOVER_THIS_HOST */
ipname = g_new0(gchar, 16);
sw_ipv4_address_name (address, ipname, 16);
service_uri = g_strdup_printf ("hkp://%s:%d", ipname, 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);
g_print ("DNS-SD added: %s %s\n", service_name, service_uri);