cpw.darkrain42.oscar.ssl: c2ffc4d3: First pass at adding SSL connections to ...
paul at darkrain42.org
paul at darkrain42.org
Wed Jan 14 01:56:54 EST 2009
-----------------------------------------------------------------
Revision: c2ffc4d3ef01a72a347f4310b92502b9d06c5eb4
Ancestor: 2d203a89c855916b5c37a95cc1869c15b24f812c
Author: paul at darkrain42.org
Date: 2008-12-10T23:41:28
Branch: im.pidgin.cpw.darkrain42.oscar.ssl
URL: http://d.pidgin.im/viewmtn/revision/info/c2ffc4d3ef01a72a347f4310b92502b9d06c5eb4
Modified files:
libpurple/protocols/oscar/family_chat.c
libpurple/protocols/oscar/flap_connection.c
libpurple/protocols/oscar/oscar.c
libpurple/protocols/oscar/oscar.h
libpurple/protocols/oscar/oscarcommon.h
libpurple/protocols/oscar/peer.c
libpurple/protocols/oscar/snactypes.h
ChangeLog:
First pass at adding SSL connections to OSCAR.
Both AIM and ICQ can connect.
Three FLAP servers seem to dislike SSL:
(15:39:46) nss: Handshake failed (-5961)
(15:39:46) oscar: unable to connect to FLAP server of type 0x0018
(15:39:46) nss: Handshake failed (-5961)
(15:39:46) oscar: unable to connect to FLAP server of type 0x000d
(15:39:46) nss: Handshake failed (-5961)
(15:39:46) oscar: unable to connect to FLAP server of type 0x0010
As a consequence, neither buddy icons nor chats work currently.
-------------- next part --------------
============================================================
--- libpurple/protocols/oscar/family_chat.c 867a0df9b217ce2a7766466cccc3a6ac78dc2038
+++ libpurple/protocols/oscar/family_chat.c 3355e969a7f551d8d1462e7ddd2e6edb8ecfeddd
@@ -79,13 +79,15 @@ aim_chat_getconn(OscarData *od, const ch
if (conn->type != SNAC_FAMILY_CHAT)
continue;
- if (!conn->internal) {
- purple_debug_misc("oscar", "faim: chat: chat connection with no name! (fd = %d)\n", conn->fd);
+ if (!conn->internal)
+ {
+ purple_debug_misc("oscar", "%sfaim: chat: chat connection with no name! (fd = %d)\n",
+ conn->gsc ? "(ssl) " : "", conn->gsc ? conn->gsc->fd : conn->fd);
continue;
}
if (strcmp(ccp->name, name) == 0)
- return conn;;
+ return conn;
}
return NULL;
============================================================
--- libpurple/protocols/oscar/flap_connection.c cc074ef8462f48258443ecf77a6d66c08a7dafb1
+++ libpurple/protocols/oscar/flap_connection.c 5d38f70256e58416a2a5a2ac3af23bbb5a4bc876
@@ -364,6 +364,15 @@ flap_connection_close(OscarData *od, Fla
conn->fd = -1;
}
+ if (conn->gsc != NULL)
+ {
+ if (conn->type == SNAC_FAMILY_LOCATE)
+ flap_connection_send_close(od, conn);
+
+ purple_ssl_close(conn->gsc);
+ conn->gsc = NULL;
+ }
+
if (conn->watcher_incoming != 0)
{
purple_input_remove(conn->watcher_incoming);
@@ -844,24 +853,31 @@ parse_flap(OscarData *od, FlapConnection
* All complete FLAPs handled immedate after they're received.
* Incomplete FLAP data is stored locally and appended to the next
* time this callback is triggered.
+ *
+ * This is called by flap_connection_recv_cb and
+ * flap_connection_recv_cb_ssl for unencrypted/encrypted connections.
*/
-void
-flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
+static void
+flap_connection_recv(FlapConnection *conn)
{
- FlapConnection *conn;
+ gpointer buf;
+ gsize buflen;
gssize read;
- conn = data;
-
/* Read data until we run out of data and break out of the loop */
while (TRUE)
{
/* Start reading a new FLAP */
if (conn->buffer_incoming.data.data == NULL)
{
+ buf = conn->header + conn->header_received;
+ buflen = 6 - conn->header_received;
+
/* Read the first 6 bytes (the FLAP header) */
- read = recv(conn->fd, conn->header + conn->header_received,
- 6 - conn->header_received, 0);
+ if (conn->gsc)
+ read = purple_ssl_read(conn->gsc, buf, buflen);
+ else
+ read = recv(conn->fd, buf, buflen, 0);
/* Check if the FLAP server closed the connection */
if (read == 0)
@@ -918,13 +934,15 @@ flap_connection_recv_cb(gpointer data, g
conn->buffer_incoming.data.offset = 0;
}
- if (conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset)
+ buflen = conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset;
+ if (buflen)
{
+ buf = &conn->buffer_incoming.data.data[conn->buffer_incoming.data.offset];
/* Read data into the temporary FlapFrame until it is complete */
- read = recv(conn->fd,
- &conn->buffer_incoming.data.data[conn->buffer_incoming.data.offset],
- conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset,
- 0);
+ if (conn->gsc)
+ read = purple_ssl_read(conn->gsc, buf, buflen);
+ else
+ read = recv(conn->fd, buf, buflen, 0);
/* Check if the FLAP server closed the connection */
if (read == 0)
@@ -964,6 +982,22 @@ flap_connection_recv_cb(gpointer data, g
}
}
+void
+flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
+{
+ FlapConnection *conn = data;
+
+ flap_connection_recv(conn);
+}
+
+void
+flap_connection_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond)
+{
+ FlapConnection *conn = data;
+
+ flap_connection_recv(conn);
+}
+
static void
send_cb(gpointer data, gint source, PurpleInputCondition cond)
{
@@ -980,7 +1014,11 @@ send_cb(gpointer data, gint source, Purp
return;
}
- ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0);
+ if (conn->gsc)
+ ret = purple_ssl_write(conn->gsc, conn->buffer_outgoing->outptr,
+ writelen);
+ else
+ ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0);
if (ret <= 0)
{
if (ret < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
@@ -990,8 +1028,13 @@ send_cb(gpointer data, gint source, Purp
/* Error! */
purple_input_remove(conn->watcher_outgoing);
conn->watcher_outgoing = 0;
- close(conn->fd);
- conn->fd = -1;
+ if (conn->gsc) {
+ purple_ssl_close(conn->gsc);
+ conn->gsc = NULL;
+ } else {
+ close(conn->fd);
+ conn->fd = -1;
+ }
flap_connection_schedule_destroy(conn,
OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
return;
@@ -1017,11 +1060,17 @@ flap_connection_send_byte_stream(ByteStr
purple_circ_buffer_append(conn->buffer_outgoing, bs->data, count);
/* If we haven't already started writing stuff, then start the cycle */
- if ((conn->watcher_outgoing == 0) && (conn->fd >= 0))
+ if (conn->watcher_outgoing == 0)
{
- conn->watcher_outgoing = purple_input_add(conn->fd,
- PURPLE_INPUT_WRITE, send_cb, conn);
- send_cb(conn, conn->fd, 0);
+ if (conn->gsc) {
+ conn->watcher_outgoing = purple_input_add(conn->gsc->fd,
+ PURPLE_INPUT_WRITE, send_cb, conn);
+ send_cb(conn, 0, 0);
+ } else if (conn->fd >= 0) {
+ conn->watcher_outgoing = purple_input_add(conn->fd,
+ PURPLE_INPUT_WRITE, send_cb, conn);
+ send_cb(conn, 0, 0);
+ }
}
}
============================================================
--- libpurple/protocols/oscar/oscar.c 6454ece0e31365bec6d3967499b30a822161e7c2
+++ libpurple/protocols/oscar/oscar.c e25a1b43101fe903bcfdc41d1e089d66d0246b21
@@ -1088,59 +1088,62 @@ oscar_chat_kill(PurpleConnection *gc, st
}
/**
- * This is the callback function anytime purple_proxy_connect()
- * establishes a new TCP connection with an oscar host. Depending
- * on the type of host, we do a few different things here.
+ * This is called from the callback functions for establishing
+ * a TCP connection with an oscar host if an error occurred.
*/
static void
-connection_established_cb(gpointer data, gint source, const gchar *error_message)
+connection_common_error_cb(FlapConnection *conn, const gchar *error_message)
{
PurpleConnection *gc;
OscarData *od;
- PurpleAccount *account;
- FlapConnection *conn;
- conn = data;
od = conn->od;
gc = od->gc;
- account = purple_connection_get_account(gc);
- conn->connect_data = NULL;
- conn->fd = source;
-
- if (source < 0)
+ purple_debug_error("oscar", "unable to connect to FLAP "
+ "server of type 0x%04hx\n", conn->type);
+ if (conn->type == SNAC_FAMILY_AUTH)
{
- purple_debug_error("oscar", "unable to connect to FLAP "
- "server of type 0x%04hx\n", conn->type);
- if (conn->type == SNAC_FAMILY_AUTH)
- {
- gchar *msg;
- msg = g_strdup_printf(_("Could not connect to authentication server:\n%s"),
- error_message);
- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
- g_free(msg);
- }
- else if (conn->type == SNAC_FAMILY_LOCATE)
- {
- gchar *msg;
- msg = g_strdup_printf(_("Could not connect to BOS server:\n%s"),
- error_message);
- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
- g_free(msg);
- }
- else
- {
- /* Maybe we should call this for BOS connections, too? */
- flap_connection_schedule_destroy(conn,
- OSCAR_DISCONNECT_COULD_NOT_CONNECT, error_message);
- }
- return;
+ gchar *msg;
+ msg = g_strdup_printf(_("Could not connect to authentication server:\n%s"),
+ error_message);
+ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
}
+ else if (conn->type == SNAC_FAMILY_LOCATE)
+ {
+ gchar *msg;
+ msg = g_strdup_printf(_("Could not connect to BOS server:\n%s"),
+ error_message);
+ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+ g_free(msg);
+ }
+ else
+ {
+ /* Maybe we should call this for BOS connections, too? */
+ flap_connection_schedule_destroy(conn,
+ OSCAR_DISCONNECT_COULD_NOT_CONNECT, error_message);
+ }
+}
+/**
+ * This is called from the callback functions for establishing
+ * a TCP connection with an oscar host. Depending on the type
+ * of host, we do a few different things here.
+ */
+static void
+connection_common_established_cb(FlapConnection *conn)
+{
+ PurpleConnection *gc;
+ OscarData *od;
+ PurpleAccount *account;
+
+ od = conn->od;
+ gc = od->gc;
+ account = purple_connection_get_account(gc);
+
purple_debug_info("oscar", "connected to FLAP server of type 0x%04hx\n",
conn->type);
- conn->watcher_incoming = purple_input_add(conn->fd,
- PURPLE_INPUT_READ, flap_connection_recv_cb, conn);
if (conn->cookie == NULL)
flap_connection_send_version(od, conn);
else
@@ -1171,6 +1174,59 @@ static void
}
static void
+connection_established_cb(gpointer data, gint source, const gchar *error_message)
+{
+ FlapConnection *conn;
+
+ conn = data;
+
+ conn->connect_data = NULL;
+ conn->fd = source;
+
+ if (source < 0)
+ {
+ connection_common_error_cb(conn, error_message);
+ return;
+ }
+
+ conn->watcher_incoming = purple_input_add(conn->fd,
+ PURPLE_INPUT_READ, flap_connection_recv_cb, conn);
+ connection_common_established_cb(conn);
+}
+
+static void
+ssl_connection_established_cb(gpointer data, PurpleSslConnection *gsc,
+ PurpleInputCondition cond)
+{
+ FlapConnection *conn;
+
+ conn = data;
+
+ purple_ssl_input_add(gsc, flap_connection_recv_cb_ssl, conn);
+ connection_common_established_cb(conn);
+}
+
+static void
+ssl_connection_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error,
+ gpointer data)
+{
+ FlapConnection *conn;
+
+ conn = data;
+
+ if (conn->watcher_outgoing)
+ {
+ purple_input_remove(conn->watcher_outgoing);
+ conn->watcher_outgoing = 0;
+ }
+
+ /* sslconn frees the connection on error */
+ conn->gsc = NULL;
+
+ connection_common_error_cb(conn, purple_ssl_strerror(error));
+}
+
+static void
flap_connection_established_bos(OscarData *od, FlapConnection *conn)
{
PurpleConnection *gc = od->gc;
@@ -1430,17 +1486,35 @@ oscar_login(PurpleAccount *account)
gc->flags |= PURPLE_CONNECTION_AUTO_RESP;
}
+ od->use_ssl = purple_account_get_bool(account, "use_ssl", FALSE);
+
/* Connect to core Purple signals */
purple_prefs_connect_callback(gc, "/purple/away/idle_reporting", idle_reporting_pref_cb, gc);
purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc);
newconn = flap_connection_new(od, SNAC_FAMILY_AUTH);
- newconn->connect_data = purple_proxy_connect(NULL, account,
- purple_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER),
- purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT),
- connection_established_cb, newconn);
- if (newconn->connect_data == NULL)
- {
+ if (od->use_ssl) {
+ if (purple_ssl_is_supported()) {
+ /* FIXME SSL: This won't really work... Need to match on the server being the default
+ * non-ssl server and, if so, connect to the default ssl one (and possibly update
+ * the account setting).
+ */
+ newconn->gsc = purple_ssl_connect(account,
+ purple_account_get_string(account, "server", OSCAR_DEFAULT_SSL_LOGIN_SERVER),
+ purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT),
+ ssl_connection_established_cb, ssl_connection_error_cb, newconn);
+ } else {
+ purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+ _("SSL support unavailable"));
+ }
+ } else {
+ newconn->connect_data = purple_proxy_connect(NULL, account,
+ purple_account_get_string(account, "server", OSCAR_DEFAULT_LOGIN_SERVER),
+ purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT),
+ connection_established_cb, newconn);
+ }
+
+ if (newconn->gsc == NULL && newconn->connect_data == NULL) {
purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
_("Couldn't connect to host"));
return;
@@ -1565,10 +1639,21 @@ purple_parse_auth_resp(OscarData *od, Fl
newconn = flap_connection_new(od, SNAC_FAMILY_LOCATE);
newconn->cookielen = info->cookielen;
newconn->cookie = g_memdup(info->cookie, info->cookielen);
- newconn->connect_data = purple_proxy_connect(NULL, account, host, port,
- connection_established_cb, newconn);
+
+ if (od->use_ssl)
+ {
+ newconn->gsc = purple_ssl_connect(account, host, port,
+ ssl_connection_established_cb, ssl_connection_error_cb,
+ newconn);
+ }
+ else
+ {
+ newconn->connect_data = purple_proxy_connect(NULL, account, host, port,
+ connection_established_cb, newconn);
+ }
+
g_free(host);
- if (newconn->connect_data == NULL)
+ if (newconn->gsc == NULL && newconn->connect_data == NULL)
{
purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Could Not Connect"));
return 0;
@@ -1890,10 +1975,20 @@ purple_handle_redirect(OscarData *od, Fl
purple_debug_info("oscar", "Connecting to chat room %s exchange %hu\n", cc->name, cc->exchange);
}
- newconn->connect_data = purple_proxy_connect(NULL, account, host, port,
- connection_established_cb, newconn);
- if (newconn->connect_data == NULL)
+ if (od->use_ssl)
{
+ newconn->gsc = purple_ssl_connect(account, host, port,
+ ssl_connection_established_cb, ssl_connection_error_cb,
+ newconn);
+ }
+ else
+ {
+ newconn->connect_data = purple_proxy_connect(NULL, account, host, port,
+ connection_established_cb, newconn);
+ }
+
+ if (newconn->gsc == NULL && newconn->connect_data == NULL)
+ {
flap_connection_schedule_destroy(newconn,
OSCAR_DISCONNECT_COULD_NOT_CONNECT,
_("Unable to initialize connection"));
@@ -6856,6 +6951,10 @@ void oscar_init(PurplePluginProtocolInfo
option = purple_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT);
prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+ option = purple_account_option_bool_new(_("Use SSL (buggy)"), "use_ssl",
+ OSCAR_DEFAULT_USE_SSL);
+ prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+
option = purple_account_option_bool_new(
_("Always use AIM/ICQ proxy server for\nfile transfers and direct IM (slower,\nbut does not reveal your IP address)"), "always_use_rv_proxy",
OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY);
============================================================
--- libpurple/protocols/oscar/oscar.h de5f3e4d647f8d1aa4ce2ad067901849dce40970
+++ libpurple/protocols/oscar/oscar.h 38e6a7647ba753df4071c6c842ef9948c37637aa
@@ -34,6 +34,7 @@
#include "eventloop.h"
#include "internal.h"
#include "proxy.h"
+#include "sslconn.h"
#include <stdio.h>
#include <string.h>
@@ -418,6 +419,7 @@ struct _FlapConnection
gpointer new_conn_data;
int fd;
+ PurpleSslConnection *gsc;
guint8 header[6];
gssize header_received;
FlapFrame buffer_incoming;
@@ -475,6 +477,7 @@ struct _OscarData
GHashTable *buddyinfo;
GSList *requesticon;
+ gboolean use_ssl;
gboolean icq;
guint getblisttimer;
@@ -615,6 +618,8 @@ void flap_connection_recv_cb(gpointer da
FlapConnection *flap_connection_getbytype(OscarData *, int type);
FlapConnection *flap_connection_getbytype_all(OscarData *, int type);
void flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond);
+void flap_connection_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond);
+
void flap_connection_send(FlapConnection *conn, FlapFrame *frame);
void flap_connection_send_version(OscarData *od, FlapConnection *conn);
void flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy);
============================================================
--- libpurple/protocols/oscar/oscarcommon.h 49db0c1100450e5914b921e8ecc8720cf543ebee
+++ libpurple/protocols/oscar/oscarcommon.h 7f462e73048eb7a1e1a43d7f41a15df7aca67647
@@ -32,6 +32,7 @@
#define OSCAR_DEFAULT_LOGIN_SERVER "login.messaging.aol.com"
#define OSCAR_DEFAULT_LOGIN_PORT 5190
+#define OSCAR_DEFAULT_SSL_LOGIN_SERVER "slogin.oscar.aol.com"
#ifndef _WIN32
#define OSCAR_DEFAULT_CUSTOM_ENCODING "ISO-8859-1"
#else
@@ -42,6 +43,7 @@
#define OSCAR_DEFAULT_WEB_AWARE FALSE
#define OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY FALSE
#define OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS TRUE
+#define OSCAR_DEFAULT_USE_SSL FALSE
#ifdef _WIN32
const char *oscar_get_locale_charset(void);
============================================================
--- libpurple/protocols/oscar/peer.c de36aea0801ce5d0b1fac01c7148fd76a2462279
+++ libpurple/protocols/oscar/peer.c f24dea9ff39070d9e0f4cc33ec7c93a2ca7e9c4b
@@ -690,7 +690,10 @@ peer_connection_establish_listener_cb(in
return;
}
- listener_ip = purple_network_get_my_ip(bos_conn->fd);
+ if (bos_conn->gsc)
+ listener_ip = purple_network_get_my_ip(bos_conn->gsc->fd);
+ else
+ listener_ip = purple_network_get_my_ip(bos_conn->fd);
listener_port = purple_network_get_port_from_fd(conn->listenerfd);
if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
{
============================================================
--- libpurple/protocols/oscar/snactypes.h 95debb6dc8f2364878d461651b2bef9648cece5c
+++ libpurple/protocols/oscar/snactypes.h 6d0dd0df40c3043a233a04efca2f1db885110a04
@@ -40,14 +40,14 @@
#define SNAC_FAMILY_USERLOOKUP 0x000a
#define SNAC_FAMILY_STATS 0x000b
#define SNAC_FAMILY_TRANSLATE 0x000c
-#define SNAC_FAMILY_CHATNAV 0x000d
+#define SNAC_FAMILY_CHATNAV 0x000d /* XXX "provides info, searching and creating" */
#define SNAC_FAMILY_CHAT 0x000e
#define SNAC_FAMILY_ODIR 0x000f
-#define SNAC_FAMILY_BART 0x0010
+#define SNAC_FAMILY_BART 0x0010 /* XXX user avatars */
#define SNAC_FAMILY_FEEDBAG 0x0013
#define SNAC_FAMILY_ICQ 0x0015
#define SNAC_FAMILY_AUTH 0x0017
-#define SNAC_FAMILY_ALERT 0x0018
+#define SNAC_FAMILY_ALERT 0x0018 /* XXX email notification */
#define AIM_CB_FAM_SPECIAL 0xffff /* Internal libfaim use */
More information about the Commits
mailing list