diff --git a/ChangeLog b/ChangeLog index 46dd1b7..fac39c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 0.8.9 - IPv6 support + - Old style SSL support - New API xmpp_uuid_gen() 0.8.8 diff --git a/examples/basic.c b/examples/basic.c index 859e195..ff17799 100644 --- a/examples/basic.c +++ b/examples/basic.c @@ -10,6 +10,7 @@ */ #include +#include #include @@ -36,20 +37,32 @@ int main(int argc, char **argv) xmpp_ctx_t *ctx; xmpp_conn_t *conn; xmpp_log_t *log; - char *jid, *pass, *host; + char *jid, *pass, *host = NULL; + int i; + int opt_disable_tls = 0; + int opt_old_ssl = 0; /* take a jid and password on the command line */ - if (argc < 3 || argc > 4) { - fprintf(stderr, "Usage: basic []\n\n"); + for (i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--disable-tls") == 0) + opt_disable_tls = 1; + else if (strcmp(argv[i], "--old-ssl") == 0) + opt_old_ssl = 1; + else + break; + } + if ((argc - i) < 2 || (argc - i) > 3) { + fprintf(stderr, "Usage: basic [options] []\n\n" + "Options:\n" + " --disable-tls Disable TLS.\n" + " --old-ssl Use old style SSL.\n"); return 1; } - jid = argv[1]; - pass = argv[2]; - host = NULL; - - if (argc == 4) - host = argv[3]; + jid = argv[i]; + pass = argv[i + 1]; + if (i + 2 < argc) + host = argv[i + 2]; /* init library */ xmpp_initialize(); @@ -61,6 +74,12 @@ int main(int argc, char **argv) /* create a connection */ conn = xmpp_conn_new(ctx); + /* configure connection properties */ + if (opt_disable_tls) + xmpp_conn_disable_tls(conn); + if (opt_old_ssl) + xmpp_conn_set_old_style_ssl(conn); + /* setup authentication information */ xmpp_conn_set_jid(conn, jid); xmpp_conn_set_pass(conn, pass); diff --git a/src/auth.c b/src/auth.c index 0b9d033..67d2bb1 100644 --- a/src/auth.c +++ b/src/auth.c @@ -280,32 +280,19 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn, void * const userdata) { char *name; + name = xmpp_stanza_get_name(stanza); - xmpp_debug(conn->ctx, "xmpp", - "handle proceedtls called for %s", name); + xmpp_debug(conn->ctx, "xmpp", "handle proceedtls called for %s", name); if (strcmp(name, "proceed") == 0) { xmpp_debug(conn->ctx, "xmpp", "proceeding with TLS"); - conn->tls = tls_new(conn->ctx, conn->sock); - - if (!tls_start(conn->tls)) - { - xmpp_debug(conn->ctx, "xmpp", "Couldn't start TLS! error %d", tls_error(conn->tls)); - tls_free(conn->tls); - conn->tls = NULL; - conn->tls_failed = 1; - - /* failed tls spoils the connection, so disconnect */ - xmpp_disconnect(conn); - } - else - { - conn->secured = 1; - conn_prepare_reset(conn, auth_handle_open); - - conn_open_stream(conn); - } + if (conn_tls_start(conn) == 0) { + conn_open_stream(conn); + } else { + /* failed tls spoils the connection, so disconnect */ + xmpp_disconnect(conn); + } } return 0; diff --git a/src/common.h b/src/common.h index bdf744b..4ea9165 100644 --- a/src/common.h +++ b/src/common.h @@ -146,6 +146,12 @@ struct _xmpp_handlist_t { #define SASL_MASK_ANONYMOUS 0x04 #define SASL_MASK_SCRAMSHA1 0x08 +enum { + XMPP_PORT_CLIENT = 5222, + XMPP_PORT_CLIENT_OLD_SSL = 5223, + XMPP_PORT_COMPONENT = 5347, +}; + typedef void (*xmpp_open_handler)(xmpp_conn_t * const conn); struct _xmpp_conn_t { @@ -162,6 +168,7 @@ struct _xmpp_conn_t { int tls_support; int tls_disabled; + int tls_is_old_ssl; int tls_failed; /* set when tls fails, so we don't try again */ int sasl_support; /* if true, field is a bitfield of supported mechanisms */ @@ -215,6 +222,7 @@ struct _xmpp_conn_t { void conn_disconnect(xmpp_conn_t * const conn); void conn_disconnect_clean(xmpp_conn_t * const conn); void conn_open_stream(xmpp_conn_t * const conn); +int conn_tls_start(xmpp_conn_t * const conn); void conn_prepare_reset(xmpp_conn_t * const conn, xmpp_open_handler handler); void conn_parser_reset(xmpp_conn_t * const conn); diff --git a/src/conn.c b/src/conn.c index 1c13fcd..a26adb3 100644 --- a/src/conn.c +++ b/src/conn.c @@ -16,6 +16,7 @@ /** @defgroup Connections Connection management */ +#include #include #include @@ -55,6 +56,7 @@ static void _handle_stream_end(char *name, void * const userdata); static void _handle_stream_stanza(xmpp_stanza_t *stanza, void * const userdata); +static int _conn_default_port(xmpp_conn_t * const conn); /** Create a new Strophe connection object. * @@ -106,6 +108,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx) conn->tls_support = 0; conn->tls_disabled = 0; + conn->tls_is_old_ssl = 0; conn->tls_failed = 0; conn->sasl_support = 0; conn->secured = 0; @@ -377,7 +380,7 @@ xmpp_ctx_t* xmpp_conn_get_context(xmpp_conn_t * const conn) * @param altdomain a string with domain to use if SRV lookup fails. If this * is NULL, the domain from the JID will be used. * @param altport an integer port number to use if SRV lookup fails. If this - * is 0, the default port (5222) will be assumed. + * is 0, the default port will be assumed. * @param callback a xmpp_conn_handler callback function that will receive * notifications of connection status * @param userdata an opaque data pointer that will be passed to the callback @@ -392,34 +395,43 @@ int xmpp_connect_client(xmpp_conn_t * const conn, xmpp_conn_handler callback, void * const userdata) { - char connectdomain[2048]; - int connectport; - const char * domain; + char domain[2048]; + int port; + const char *prefdomain = NULL; + int found; conn->type = XMPP_CLIENT; conn->domain = xmpp_jid_domain(conn->ctx, conn->jid); if (!conn->domain) return -1; - if (altdomain) { + if (altdomain != NULL) { xmpp_debug(conn->ctx, "xmpp", "Connecting via altdomain."); - strcpy(connectdomain, altdomain); - connectport = altport ? altport : 5222; - } else if (!sock_srv_lookup("xmpp-client", "tcp", conn->domain, - connectdomain, 2048, &connectport)) { - xmpp_debug(conn->ctx, "xmpp", "SRV lookup failed."); - if (!altdomain) - domain = conn->domain; - else - domain = altdomain; - xmpp_debug(conn->ctx, "xmpp", "Using alternate domain %s, port %d", - altdomain, altport); - strcpy(connectdomain, domain); - connectport = altport ? altport : 5222; + prefdomain = altdomain; + port = altport ? altport : _conn_default_port(conn); + } else { + found = sock_srv_lookup("xmpp-client", "tcp", conn->domain, + domain, sizeof(domain), &port); + if (!found) { + xmpp_debug(conn->ctx, "xmpp", "SRV lookup failed, " + "connecting via domain."); + prefdomain = conn->domain; + port = altport ? altport : _conn_default_port(conn); + } + if (conn->tls_is_old_ssl) { + /* SSL tunneled connection on 5223 port is legacy and doesn't + * have an SRV record. Force port 5223 here. + */ + port = XMPP_PORT_CLIENT_OLD_SSL; + } } - conn->sock = sock_connect(connectdomain, connectport); + if (prefdomain != NULL) { + strncpy(domain, prefdomain, sizeof(domain)); + domain[sizeof(domain) - 1] = '\0'; + } + conn->sock = sock_connect(domain, port); xmpp_debug(conn->ctx, "xmpp", "sock_connect to %s:%d returned %d", - connectdomain, connectport, conn->sock); + domain, port, conn->sock); if (conn->sock == -1) return -1; /* setup handler */ @@ -433,7 +445,7 @@ int xmpp_connect_client(xmpp_conn_t * const conn, conn->state = XMPP_STATE_CONNECTING; conn->timeout_stamp = time_stamp(); - xmpp_debug(conn->ctx, "xmpp", "attempting to connect to %s", connectdomain); + xmpp_debug(conn->ctx, "xmpp", "attempting to connect to %s", domain); return 0; } @@ -476,7 +488,7 @@ int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server, if (!(server && conn->jid && conn->pass)) return -1; - connectport = port ? port : 5347; + connectport = port ? port : _conn_default_port(conn); xmpp_debug(conn->ctx, "xmpp", "Connecting via %s", server); conn->sock = sock_connect(server, connectport); @@ -730,6 +742,36 @@ void conn_open_stream(xmpp_conn_t * const conn) XMPP_NS_STREAMS); } +int conn_tls_start(xmpp_conn_t * const conn) +{ + int rc; + + if (conn->tls_disabled) { + conn->tls = NULL; + rc = -ENOSYS; + } else { + conn->tls = tls_new(conn->ctx, conn->sock); + rc = conn->tls == NULL ? -ENOMEM : 0; + } + + if (conn->tls != NULL) { + if (tls_start(conn->tls)) { + conn->secured = 1; + conn_prepare_reset(conn, auth_handle_open); + } else { + rc = tls_error(conn->tls); + conn->error = rc; + tls_free(conn->tls); + conn->tls = NULL; + conn->tls_failed = 1; + } + } + if (rc != 0) + xmpp_debug(conn->ctx, "conn", "Couldn't start TLS! error %d", rc); + + return rc; +} + /** Disable TLS for this connection, called by users of the library. * Occasionally a server will be misconfigured to send the starttls * feature, but wil not support the handshake. @@ -741,6 +783,11 @@ void xmpp_conn_disable_tls(xmpp_conn_t * const conn) conn->tls_disabled = 1; } +void xmpp_conn_set_old_style_ssl(xmpp_conn_t * const conn) +{ + conn->tls_is_old_ssl = 1; +} + static void _log_open_tag(xmpp_conn_t *conn, char **attrs) { char buf[4096]; @@ -837,3 +884,16 @@ static void _handle_stream_stanza(xmpp_stanza_t *stanza, handler_fire_stanza(conn, stanza); } + +static int _conn_default_port(xmpp_conn_t * const conn) +{ + switch (conn->type) { + case XMPP_CLIENT: + return conn->tls_is_old_ssl ? XMPP_PORT_CLIENT_OLD_SSL : + XMPP_PORT_CLIENT; + case XMPP_COMPONENT: + return XMPP_PORT_COMPONENT; + default: + return -1; + }; +} diff --git a/src/event.c b/src/event.c index 9efd1c1..da04257 100644 --- a/src/event.c +++ b/src/event.c @@ -258,9 +258,10 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout) /* connection complete */ /* check for error */ - if (sock_connect_error(conn->sock) != 0) { + ret = sock_connect_error(conn->sock); + if (ret != 0) { /* connection failed */ - xmpp_debug(ctx, "xmpp", "connection failed"); + xmpp_debug(ctx, "xmpp", "connection failed, error %d", ret); conn_disconnect(conn); break; } @@ -268,7 +269,15 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout) conn->state = XMPP_STATE_CONNECTED; xmpp_debug(ctx, "xmpp", "connection successful"); - + if (conn->tls_is_old_ssl) { + xmpp_debug(ctx, "xmpp", "using old style SSL connection"); + ret = conn_tls_start(conn); + if (ret != 0) { + conn_disconnect(conn); + break; + } + } + /* send stream init */ conn_open_stream(conn); } diff --git a/strophe.h b/strophe.h index 98ab7f6..cebd234 100644 --- a/strophe.h +++ b/strophe.h @@ -215,6 +215,7 @@ const char *xmpp_conn_get_pass(const xmpp_conn_t * const conn); void xmpp_conn_set_pass(xmpp_conn_t * const conn, const char * const pass); xmpp_ctx_t* xmpp_conn_get_context(xmpp_conn_t * const conn); void xmpp_conn_disable_tls(xmpp_conn_t * const conn); +void xmpp_conn_set_old_style_ssl(xmpp_conn_t * const conn); int xmpp_connect_client(xmpp_conn_t * const conn, const char * const altdomain,