[PATCH] SILC prpl fixes
Pekka Riikonen
priikone at iki.fi
Sat Jul 28 05:16:03 EDT 2007
Hello,
The enclosed patch fixes the following:
* Various crashes when SILC Toolkit fails to encode or decode a public key
* The laptop battery draining problem (bug in Red Hat bugzilla) because
the SILC Toolkit is polled every few msecs. Now it is truly event based
and fixes the problem. Old behavior is preserved for Toolkit's that
doesn't support the feature.
Pekka
________________________________________________________________________
Pekka Riikonen priikone at silcnet.org
Secure Internet Live Conferencing (SILC) http://silcnet.org/
-------------- next part --------------
#
# old_revision [56ee47cf16ab80166a40a0a656778f158c6f1c59]
#
# patch "libpurple/protocols/silc/chat.c"
# from [1ae8b183d4f656fe89a006ddd488d46043bc53c6]
# to [469cc7777393ac90437b447a99baf65d5145401d]
#
# patch "libpurple/protocols/silc/ops.c"
# from [464ac0e6768a8f4badeb182e2bfef9b3ebc34e19]
# to [9e7ac0c6b5e26d76032a4e514decd5c659b87678]
#
# patch "libpurple/protocols/silc/pk.c"
# from [a67b620a11231b9b218c27471db5765efed1a124]
# to [d51e1c49b31e88f5a0d34afb6f4cc4b0170c9eb2]
#
# patch "libpurple/protocols/silc/silc.c"
# from [e6875f9a8cec199df09286d63dca544debb3d183]
# to [148f5b3f738db98c9b95f8303c7f2714ad8abfcf]
#
# patch "libpurple/protocols/silc/silcpurple.h"
# from [83a974c5ca39f14d643ad5b512d67742e0ef7e75]
# to [2740ea8368e4ace212817207c2acc3e3a61690d0]
#
# patch "libpurple/protocols/silc/util.c"
# from [dc180615f15f1f5b3128810202d21d5a06061a7b]
# to [dd1c3ee1af03d94f6a285aed1a767a97acc5aee8]
#
============================================================
--- libpurple/protocols/silc/chat.c 1ae8b183d4f656fe89a006ddd488d46043bc53c6
+++ libpurple/protocols/silc/chat.c 469cc7777393ac90437b447a99baf65d5145401d
@@ -160,15 +160,17 @@ silcpurple_chat_getinfo(PurpleConnection
unsigned char *pk;
SilcUInt32 pk_len;
pk = silc_pkcs_public_key_encode(channel->founder_key, &pk_len);
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+ if (pk) {
+ fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+ babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
- g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint);
- g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint);
+ g_string_append_printf(s, _("<br><b>Founder Key Fingerprint:</b><br>%s"), fingerprint);
+ g_string_append_printf(s, _("<br><b>Founder Key Babbleprint:</b><br>%s"), babbleprint);
- silc_free(fingerprint);
- silc_free(babbleprint);
- silc_free(pk);
+ silc_free(fingerprint);
+ silc_free(babbleprint);
+ silc_free(pk);
+ }
}
buf = g_string_free(s, FALSE);
@@ -460,6 +462,8 @@ void silcpurple_chat_chauth_show(SilcPur
silc_dlist_start(channel_pubkeys);
while ((public_key = silc_dlist_get(channel_pubkeys))) {
pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ if (!pk)
+ continue;
fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4);
babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4);
@@ -1013,9 +1017,6 @@ void silcpurple_chat_join(PurpleConnecti
SilcClient client = sg->client;
SilcClientConnection conn = sg->conn;
const char *channel, *passphrase, *parentch;
-#if 0
- PurpleChat *chat;
-#endif
if (!conn)
return;
@@ -1071,22 +1072,6 @@ void silcpurple_chat_join(PurpleConnecti
return;
}
-#if 0
- /* If the channel is not on buddy list, automatically add it there. */
- chat = purple_blist_find_chat(sg->account, channel);
- if (!chat) {
- data = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, g_free);
- g_hash_table_replace(data, g_strdup("channel"),
- g_strdup(channel));
- if (passphrase)
- g_hash_table_replace(data, g_strdup("passphrase"),
- g_strdup(passphrase));
- chat = purple_chat_new(sg->account, NULL, data);
- purple_blist_add_chat(chat, NULL, NULL);
- }
-#endif
-
/* XXX We should have other properties here as well:
1. whether to try to authenticate to the channel
1a. with default key,
============================================================
--- libpurple/protocols/silc/ops.c 464ac0e6768a8f4badeb182e2bfef9b3ebc34e19
+++ libpurple/protocols/silc/ops.c 9e7ac0c6b5e26d76032a4e514decd5c659b87678
@@ -1274,13 +1274,15 @@ silc_command_reply(SilcClient client, Si
unsigned char *pk;
SilcUInt32 pk_len;
pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
- purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
- purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
- silc_free(fingerprint);
- silc_free(babbleprint);
- silc_free(pk);
+ if (pk) {
+ fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+ babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+ purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
+ purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
+ silc_free(fingerprint);
+ silc_free(babbleprint);
+ silc_free(pk);
+ }
}
#if 0 /* XXX for now, let's not show attrs here */
@@ -1346,13 +1348,15 @@ silc_command_reply(SilcClient client, Si
unsigned char *pk;
SilcUInt32 pk_len;
pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len);
- fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
- babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
- purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
- purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
- silc_free(fingerprint);
- silc_free(babbleprint);
- silc_free(pk);
+ if (pk) {
+ fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+ babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+ purple_notify_user_info_add_pair(user_info, _("Public Key Fingerprint"), fingerprint);
+ purple_notify_user_info_add_pair(user_info, _("Public Key Babbleprint"), babbleprint);
+ silc_free(fingerprint);
+ silc_free(babbleprint);
+ silc_free(pk);
+ }
}
purple_notify_userinfo(gc, nickname, user_info, NULL, NULL);
============================================================
--- libpurple/protocols/silc/pk.c a67b620a11231b9b218c27471db5765efed1a124
+++ libpurple/protocols/silc/pk.c d51e1c49b31e88f5a0d34afb6f4cc4b0170c9eb2
@@ -158,6 +158,11 @@ void silcpurple_verify_public_key(SilcCl
NULL, &hostname, &ip, &port);
pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ if (!pk) {
+ if (completion)
+ completion(FALSE, context);
+ return;
+ }
if (conn_type == SILC_CONN_SERVER ||
conn_type == SILC_CONN_ROUTER) {
============================================================
--- libpurple/protocols/silc/silc.c e6875f9a8cec199df09286d63dca544debb3d183
+++ libpurple/protocols/silc/silc.c 148f5b3f738db98c9b95f8303c7f2714ad8abfcf
@@ -128,6 +128,7 @@ silcpurple_keepalive(PurpleConnection *g
NULL, 0);
}
+#if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1)
static gboolean
silcpurple_scheduler(gpointer *context)
{
@@ -135,8 +136,99 @@ silcpurple_scheduler(gpointer *context)
silc_client_run_one(client);
return TRUE;
}
+#else
+typedef struct {
+ guint tag;
+ SilcUInt32 fd;
+} *SilcPurpleFd;
+/* A timeout occurred. Call SILC scheduler. */
+
+static gboolean
+silcpurple_scheduler_timeout(gpointer context)
+{
+ SilcClient client = (SilcClient)context;
+ silc_client_run_one(client);
+ return FALSE;
+}
+
+/* An fd task event occurred. Call SILC scheduler. */
+
static void
+silcpurple_scheduler_fd(gpointer data, gint fd, PurpleInputCondition cond)
+{
+ SilcClient client = (SilcClient)data;
+ silc_client_run_one(client);
+}
+
+/* SILC Scheduler notify callback. This is called whenever task is added to
+ or deleted from SILC scheduler. It's also called when fd task events
+ change. Here we add same tasks to glib's main loop. */
+
+static void
+silcpurple_scheduler(SilcSchedule schedule,
+ SilcBool added, SilcTask task,
+ SilcBool fd_task, SilcUInt32 fd,
+ SilcTaskEvent event,
+ long seconds, long useconds,
+ void *context)
+{
+ SilcClient client = (SilcClient)context;
+ PurpleConnection *gc = client->application;
+ SilcPurple sg = gc->proto_data;
+ SilcPurpleFd fdtask = NULL;
+
+ if (added) {
+ if (fd_task) {
+ /* Add fd or change fd events */
+ PurpleInputCondition e = 0;
+
+ silc_dlist_start(sg->fds);
+ while ((fdtask = silc_dlist_get(sg->fds)))
+ if (fdtask->fd == fd) {
+ purple_input_remove(fdtask->tag);
+ break;
+ }
+
+ if (event & SILC_TASK_READ)
+ e |= PURPLE_INPUT_READ;
+ if (event & SILC_TASK_WRITE)
+ e |= PURPLE_INPUT_WRITE;
+
+ if (e) {
+ if (!fdtask) {
+ fdtask = silc_calloc(1, sizeof(*fdtask));
+ fdtask->fd = fd;
+ silc_dlist_add(sg->fds, fdtask);
+ }
+ fdtask->tag = purple_input_add(fd, e, silcpurple_scheduler_fd,
+ client);
+ } else if (fdtask) {
+ silc_dlist_del(sg->fds, fdtask);
+ silc_free(fdtask);
+ }
+ } else {
+ /* Add timeout */
+ purple_timeout_add((seconds * 1000) + (useconds / 1000),
+ silcpurple_scheduler_timeout, client);
+ }
+ } else {
+ if (fd_task) {
+ /* Remove fd */
+ silc_dlist_start(sg->fds);
+ while ((fdtask = silc_dlist_get(sg->fds)))
+ if (fdtask->fd == fd) {
+ purple_input_remove(fdtask->tag);
+ silc_dlist_del(sg->fds, fdtask);
+ silc_free(fdtask);
+ break;
+ }
+ }
+ }
+}
+#endif /* __SILC_TOOLKIT_VERSION */
+
+static void
silcpurple_connect_cb(SilcClient client, SilcClientConnection conn,
SilcClientConnectionStatus status, SilcStatus error,
const char *message, void *context)
@@ -324,21 +416,11 @@ static void silcpurple_running(SilcClien
static void silcpurple_running(SilcClient client, void *context)
{
- PurpleAccount *account = context;
- PurpleConnection *gc = account->gc;
- SilcPurple sg;
+ SilcPurple sg = context;
+ PurpleConnection *gc = sg->gc;
+ PurpleAccount *account = purple_connection_get_account(gc);
char pkd[256], prd[256];
- sg = silc_calloc(1, sizeof(*sg));
- if (!sg)
- return;
- memset(sg, 0, sizeof(*sg));
- sg->client = client;
- sg->gc = gc;
- sg->account = account;
- sg->scheduler = SILC_PTR_TO_32(gc->proto_data);
- gc->proto_data = sg;
-
/* Progress */
purple_connection_update_progress(gc, _("Connecting to SILC Server"), 1, 5);
@@ -375,10 +457,10 @@ silcpurple_login(PurpleAccount *account)
{
SilcClient client;
PurpleConnection *gc;
+ SilcPurple sg;
SilcClientParams params;
const char *cipher, *hmac;
char *username, *hostname, *realname, **up;
- guint scheduler;
int i;
gc = account->gc;
@@ -431,11 +513,21 @@ silcpurple_login(PurpleAccount *account)
break;
}
+ sg = silc_calloc(1, sizeof(*sg));
+ if (!sg)
+ return;
+ sg->client = client;
+ sg->gc = gc;
+ sg->account = account;
+ gc->proto_data = sg;
+
/* Init SILC client */
if (!silc_client_init(client, username, hostname, realname,
- silcpurple_running, account)) {
+ silcpurple_running, sg)) {
gc->wants_to_die = TRUE;
purple_connection_error(gc, _("Cannot initialize SILC protocol"));
+ gc->proto_data = NULL;
+ silc_free(sg);
return;
}
@@ -443,18 +535,38 @@ silcpurple_login(PurpleAccount *account)
if (!silcpurple_check_silc_dir(gc)) {
gc->wants_to_die = TRUE;
purple_connection_error(gc, _("Error loading SILC key pair"));
+ gc->proto_data = NULL;
+ silc_free(sg);
return;
}
+#if __SILC_TOOLKIT_VERSION < SILC_VERSION(1,1,1)
/* Schedule SILC using Glib's event loop */
- scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client);
- gc->proto_data = SILC_32_TO_PTR(scheduler);
+ sg->scheduler = purple_timeout_add(300, (GSourceFunc)silcpurple_scheduler, client);
+#else
+ /* Run SILC scheduler */
+ sg->fds = silc_dlist_init();
+ silc_schedule_set_notify(client->schedule, silcpurple_scheduler,
+ client);
+ silc_client_run_one(client);
+#endif /* __SILC_TOOLKIT_VERSION */
}
static int
silcpurple_close_final(gpointer *context)
{
SilcPurple sg = (SilcPurple)context;
+#if __SILC_TOOLKIT_VERSION >= SILC_VERSION(1,1,1)
+ SilcPurpleFd task;
+
+ silc_dlist_start(sg->fds);
+ while ((task = silc_dlist_get(sg->fds))) {
+ g_source_remove_by_user_data(SILC_32_TO_PTR(task->fd));
+ silc_free(task);
+ }
+ silc_dlist_uninit(sg->fds);
+#endif /* __SILC_TOOLKIT_VERSION */
+
silc_client_stop(sg->client, NULL, NULL);
silc_client_free(sg->client);
if (sg->mimeass)
============================================================
--- libpurple/protocols/silc/silcpurple.h 83a974c5ca39f14d643ad5b512d67742e0ef7e75
+++ libpurple/protocols/silc/silcpurple.h 2740ea8368e4ace212817207c2acc3e3a61690d0
@@ -35,6 +35,9 @@
#include "server.h"
#include "util.h"
+#undef SILC_VERSION
+#define SILC_VERSION(a, b, c) (((a) << 24) + ((b) << 16) + ((c) << 8))
+
/* Default public and private key file names */
#define SILCPURPLE_PUBLIC_KEY_NAME "public_key.pub"
#define SILCPURPLE_PRIVATE_KEY_NAME "private_key.prv"
@@ -69,6 +72,7 @@ typedef struct SilcPurpleStruct {
SilcPublicKey public_key;
SilcPrivateKey private_key;
+ SilcDList fds;
guint scheduler;
PurpleConnection *gc;
PurpleAccount *account;
============================================================
--- libpurple/protocols/silc/util.c dc180615f15f1f5b3128810202d21d5a06061a7b
+++ libpurple/protocols/silc/util.c dd1c3ee1af03d94f6a285aed1a767a97acc5aee8
@@ -347,8 +347,12 @@ void silcpurple_show_public_key(SilcPurp
key_len = silc_pkcs_public_key_get_len(public_key);
pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+ if (!pk)
+ return;
fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+ if (!fingerprint || !babbleprint)
+ return;
s = g_string_new("");
if (ident->realname)
More information about the Devel
mailing list