Wed, 15 Jul 2009 16:57:33 +0000
Add purple_ssl_connect_with_ssl_cn, which takes a host to connect to
in addition to a string with which to validate the SSL certificate.
Useful for OSCAR (and XMPP BOSH soon), where we have an IP to connect
to, but need to validate the SSL cert.
--- a/ChangeLog.API Wed Jul 15 15:32:11 2009 +0000 +++ b/ChangeLog.API Wed Jul 15 16:57:33 2009 +0000 @@ -56,6 +56,7 @@ * purple_request_field_get_group * purple_request_field_get_ui_data * purple_request_field_set_ui_data + * purple_ssl_connect_with_ssl_cn * purple_strequal * purple_utf8_strip_unprintables * purple_util_fetch_url_request_len_with_account
--- a/libpurple/protocols/oscar/flap_connection.c Wed Jul 15 15:32:11 2009 +0000 +++ b/libpurple/protocols/oscar/flap_connection.c Wed Jul 15 16:57:33 2009 +0000 @@ -505,7 +505,6 @@ g_free(conn->error_message); g_free(conn->cookie); - g_free(conn->ssl_cert_cn); /* * Free conn->internal, if necessary
--- a/libpurple/protocols/oscar/oscar.c Wed Jul 15 15:32:11 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.c Wed Jul 15 16:57:33 2009 +0000 @@ -1246,32 +1246,6 @@ } static void -ssl_proxy_conn_established_cb(gpointer data, gint source, const gchar *error_message) -{ - OscarData *od; - PurpleConnection *gc; - PurpleAccount *account; - FlapConnection *conn; - - conn = data; - od = conn->od; - gc = od->gc; - account = purple_connection_get_account(gc); - - conn->connect_data = NULL; - - if (source < 0) - { - connection_common_error_cb(conn, error_message); - return; - } - - conn->gsc = purple_ssl_connect_with_host_fd(account, source, - ssl_connection_established_cb, ssl_connection_error_cb, - conn->ssl_cert_cn, conn); -} - -static void flap_connection_established_bos(OscarData *od, FlapConnection *conn) { PurpleConnection *gc = od->gc; @@ -1943,12 +1917,13 @@ if (od->use_ssl) { /* - * This shouldn't be hardcoded except that the server isn't sending - * us a name to use for comparing the certificate common name. + * This shouldn't be hardcoded to "bos.oscar.aol.com" except that + * the server isn't sending us a name to use for comparing the + * certificate common name. */ - newconn->ssl_cert_cn = g_strdup("bos.oscar.aol.com"); - newconn->connect_data = purple_proxy_connect(NULL, account, host, port, - ssl_proxy_conn_established_cb, newconn); + newconn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port, + ssl_connection_established_cb, ssl_connection_error_cb, + "bos.oscar.aol.com", newconn); } else { @@ -1957,7 +1932,7 @@ } 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, _("Unable to connect")); return 0; @@ -2114,15 +2089,9 @@ if (redir->use_ssl) { - /* - * TODO: It should be possible to specify a certificate common name - * distinct from the host we're passing to purple_ssl_connect. The - * way to work around that is to use purple_proxy_connect + - * purple_ssl_connect_with_host_fd - */ - newconn->ssl_cert_cn = g_strdup(redir->ssl_cert_cn); - newconn->connect_data = purple_proxy_connect(NULL, account, host, port, - ssl_proxy_conn_established_cb, newconn); + newconn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port, + ssl_connection_established_cb, ssl_connection_error_cb, + redir->ssl_cert_cn, newconn); } else {
--- a/libpurple/protocols/oscar/oscar.h Wed Jul 15 15:32:11 2009 +0000 +++ b/libpurple/protocols/oscar/oscar.h Wed Jul 15 16:57:33 2009 +0000 @@ -429,7 +429,6 @@ guint16 cookielen; guint8 *cookie; gpointer new_conn_data; - gchar *ssl_cert_cn; int fd; PurpleSslConnection *gsc;
--- a/libpurple/sslconn.c Wed Jul 15 15:32:11 2009 +0000 +++ b/libpurple/sslconn.c Wed Jul 15 16:57:33 2009 +0000 @@ -100,6 +100,15 @@ PurpleSslInputFunction func, PurpleSslErrorFunction error_func, void *data) { + return purple_ssl_connect_with_ssl_cn(account, host, port, func, error_func, + NULL, data); +} + +PurpleSslConnection * +purple_ssl_connect_with_ssl_cn(PurpleAccount *account, const char *host, int port, + PurpleSslInputFunction func, PurpleSslErrorFunction error_func, + const char *ssl_cn, void *data) +{ PurpleSslConnection *gsc; g_return_val_if_fail(host != NULL, NULL); @@ -116,7 +125,7 @@ gsc = g_new0(PurpleSslConnection, 1); gsc->fd = -1; - gsc->host = g_strdup(host); + gsc->host = ssl_cn ? g_strdup(ssl_cn) : g_strdup(host); gsc->port = port; gsc->connect_cb_data = data; gsc->connect_cb = func;
--- a/libpurple/sslconn.h Wed Jul 15 15:32:11 2009 +0000 +++ b/libpurple/sslconn.h Wed Jul 15 16:57:33 2009 +0000 @@ -186,6 +186,30 @@ PurpleSslErrorFunction error_func, void *data); +/** + * Makes a SSL connection to the specified host and port, using the separate + * name to verify with the certificate. The caller should keep track of the + * returned value and use it to cancel the connection, if needed. + * + * @param account The account making the connection. + * @param host The destination host. + * @param port The destination port. + * @param func The SSL input handler function. + * @param error_func The SSL error handler function. This function + * should <strong>NOT</strong> call purple_ssl_close(). In + * the event of an error the #PurpleSslConnection will be + * destroyed for you. + * @param ssl_host The hostname of the other peer (to verify the CN) + * @param data User-defined data. + * + * @return The SSL connection handle. + */ +PurpleSslConnection *purple_ssl_connect_with_ssl_cn(PurpleAccount *account, const char *host, + int port, PurpleSslInputFunction func, + PurpleSslErrorFunction error_func, + const char *ssl_host, + void *data); + #if !(defined PURPLE_DISABLE_DEPRECATED) || (defined _PURPLE_SSLCONN_C_) /** * Makes a SSL connection using an already open file descriptor.