conn: implemented old-style SSL connection

Added new API xmpp_conn_set_old_style_ssl(). This function forces
using of old-style SSL connection.
This commit is contained in:
Dmitry Podgorny
2015-10-12 22:16:23 +03:00
parent 254b9d73a1
commit 36af7afa27
7 changed files with 140 additions and 55 deletions

View File

@@ -1,5 +1,6 @@
0.8.9 0.8.9
- IPv6 support - IPv6 support
- Old style SSL support
- New API xmpp_uuid_gen() - New API xmpp_uuid_gen()
0.8.8 0.8.8

View File

@@ -10,6 +10,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <strophe.h> #include <strophe.h>
@@ -36,20 +37,32 @@ int main(int argc, char **argv)
xmpp_ctx_t *ctx; xmpp_ctx_t *ctx;
xmpp_conn_t *conn; xmpp_conn_t *conn;
xmpp_log_t *log; 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 */ /* take a jid and password on the command line */
if (argc < 3 || argc > 4) { for (i = 1; i < argc; ++i) {
fprintf(stderr, "Usage: basic <jid> <pass> [<host>]\n\n"); 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] <jid> <pass> [<host>]\n\n"
"Options:\n"
" --disable-tls Disable TLS.\n"
" --old-ssl Use old style SSL.\n");
return 1; return 1;
} }
jid = argv[1]; jid = argv[i];
pass = argv[2]; pass = argv[i + 1];
host = NULL; if (i + 2 < argc)
host = argv[i + 2];
if (argc == 4)
host = argv[3];
/* init library */ /* init library */
xmpp_initialize(); xmpp_initialize();
@@ -61,6 +74,12 @@ int main(int argc, char **argv)
/* create a connection */ /* create a connection */
conn = xmpp_conn_new(ctx); 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 */ /* setup authentication information */
xmpp_conn_set_jid(conn, jid); xmpp_conn_set_jid(conn, jid);
xmpp_conn_set_pass(conn, pass); xmpp_conn_set_pass(conn, pass);

View File

@@ -280,32 +280,19 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
void * const userdata) void * const userdata)
{ {
char *name; char *name;
name = xmpp_stanza_get_name(stanza); name = xmpp_stanza_get_name(stanza);
xmpp_debug(conn->ctx, "xmpp", xmpp_debug(conn->ctx, "xmpp", "handle proceedtls called for %s", name);
"handle proceedtls called for %s", name);
if (strcmp(name, "proceed") == 0) { if (strcmp(name, "proceed") == 0) {
xmpp_debug(conn->ctx, "xmpp", "proceeding with TLS"); xmpp_debug(conn->ctx, "xmpp", "proceeding with TLS");
conn->tls = tls_new(conn->ctx, conn->sock); if (conn_tls_start(conn) == 0) {
conn_open_stream(conn);
if (!tls_start(conn->tls)) } else {
{ /* failed tls spoils the connection, so disconnect */
xmpp_debug(conn->ctx, "xmpp", "Couldn't start TLS! error %d", tls_error(conn->tls)); xmpp_disconnect(conn);
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);
}
} }
return 0; return 0;

View File

@@ -146,6 +146,12 @@ struct _xmpp_handlist_t {
#define SASL_MASK_ANONYMOUS 0x04 #define SASL_MASK_ANONYMOUS 0x04
#define SASL_MASK_SCRAMSHA1 0x08 #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); typedef void (*xmpp_open_handler)(xmpp_conn_t * const conn);
struct _xmpp_conn_t { struct _xmpp_conn_t {
@@ -162,6 +168,7 @@ struct _xmpp_conn_t {
int tls_support; int tls_support;
int tls_disabled; int tls_disabled;
int tls_is_old_ssl;
int tls_failed; /* set when tls fails, so we don't try again */ int tls_failed; /* set when tls fails, so we don't try again */
int sasl_support; /* if true, field is a bitfield of supported int sasl_support; /* if true, field is a bitfield of supported
mechanisms */ mechanisms */
@@ -215,6 +222,7 @@ struct _xmpp_conn_t {
void conn_disconnect(xmpp_conn_t * const conn); void conn_disconnect(xmpp_conn_t * const conn);
void conn_disconnect_clean(xmpp_conn_t * const conn); void conn_disconnect_clean(xmpp_conn_t * const conn);
void conn_open_stream(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_prepare_reset(xmpp_conn_t * const conn, xmpp_open_handler handler);
void conn_parser_reset(xmpp_conn_t * const conn); void conn_parser_reset(xmpp_conn_t * const conn);

View File

@@ -16,6 +16,7 @@
/** @defgroup Connections Connection management /** @defgroup Connections Connection management
*/ */
#include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
@@ -55,6 +56,7 @@ static void _handle_stream_end(char *name,
void * const userdata); void * const userdata);
static void _handle_stream_stanza(xmpp_stanza_t *stanza, static void _handle_stream_stanza(xmpp_stanza_t *stanza,
void * const userdata); void * const userdata);
static int _conn_default_port(xmpp_conn_t * const conn);
/** Create a new Strophe connection object. /** 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_support = 0;
conn->tls_disabled = 0; conn->tls_disabled = 0;
conn->tls_is_old_ssl = 0;
conn->tls_failed = 0; conn->tls_failed = 0;
conn->sasl_support = 0; conn->sasl_support = 0;
conn->secured = 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 * @param altdomain a string with domain to use if SRV lookup fails. If this
* is NULL, the domain from the JID will be used. * is NULL, the domain from the JID will be used.
* @param altport an integer port number to use if SRV lookup fails. If this * @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 * @param callback a xmpp_conn_handler callback function that will receive
* notifications of connection status * notifications of connection status
* @param userdata an opaque data pointer that will be passed to the callback * @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, xmpp_conn_handler callback,
void * const userdata) void * const userdata)
{ {
char connectdomain[2048]; char domain[2048];
int connectport; int port;
const char * domain; const char *prefdomain = NULL;
int found;
conn->type = XMPP_CLIENT; conn->type = XMPP_CLIENT;
conn->domain = xmpp_jid_domain(conn->ctx, conn->jid); conn->domain = xmpp_jid_domain(conn->ctx, conn->jid);
if (!conn->domain) return -1; if (!conn->domain) return -1;
if (altdomain) { if (altdomain != NULL) {
xmpp_debug(conn->ctx, "xmpp", "Connecting via altdomain."); xmpp_debug(conn->ctx, "xmpp", "Connecting via altdomain.");
strcpy(connectdomain, altdomain); prefdomain = altdomain;
connectport = altport ? altport : 5222; port = altport ? altport : _conn_default_port(conn);
} else if (!sock_srv_lookup("xmpp-client", "tcp", conn->domain, } else {
connectdomain, 2048, &connectport)) { found = sock_srv_lookup("xmpp-client", "tcp", conn->domain,
xmpp_debug(conn->ctx, "xmpp", "SRV lookup failed."); domain, sizeof(domain), &port);
if (!altdomain) if (!found) {
domain = conn->domain; xmpp_debug(conn->ctx, "xmpp", "SRV lookup failed, "
else "connecting via domain.");
domain = altdomain; prefdomain = conn->domain;
xmpp_debug(conn->ctx, "xmpp", "Using alternate domain %s, port %d", port = altport ? altport : _conn_default_port(conn);
altdomain, altport); }
strcpy(connectdomain, domain); if (conn->tls_is_old_ssl) {
connectport = altport ? altport : 5222; /* 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", 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; if (conn->sock == -1) return -1;
/* setup handler */ /* setup handler */
@@ -433,7 +445,7 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
conn->state = XMPP_STATE_CONNECTING; conn->state = XMPP_STATE_CONNECTING;
conn->timeout_stamp = time_stamp(); 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; 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; 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); xmpp_debug(conn->ctx, "xmpp", "Connecting via %s", server);
conn->sock = sock_connect(server, connectport); conn->sock = sock_connect(server, connectport);
@@ -730,6 +742,36 @@ void conn_open_stream(xmpp_conn_t * const conn)
XMPP_NS_STREAMS); 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. /** Disable TLS for this connection, called by users of the library.
* Occasionally a server will be misconfigured to send the starttls * Occasionally a server will be misconfigured to send the starttls
* feature, but wil not support the handshake. * 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; 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) static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
{ {
char buf[4096]; char buf[4096];
@@ -837,3 +884,16 @@ static void _handle_stream_stanza(xmpp_stanza_t *stanza,
handler_fire_stanza(conn, 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;
};
}

View File

@@ -258,9 +258,10 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
/* connection complete */ /* connection complete */
/* check for error */ /* check for error */
if (sock_connect_error(conn->sock) != 0) { ret = sock_connect_error(conn->sock);
if (ret != 0) {
/* connection failed */ /* connection failed */
xmpp_debug(ctx, "xmpp", "connection failed"); xmpp_debug(ctx, "xmpp", "connection failed, error %d", ret);
conn_disconnect(conn); conn_disconnect(conn);
break; break;
} }
@@ -268,6 +269,14 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
conn->state = XMPP_STATE_CONNECTED; conn->state = XMPP_STATE_CONNECTED;
xmpp_debug(ctx, "xmpp", "connection successful"); 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 */ /* send stream init */
conn_open_stream(conn); conn_open_stream(conn);

View File

@@ -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); 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); 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_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, int xmpp_connect_client(xmpp_conn_t * const conn,
const char * const altdomain, const char * const altdomain,