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
- IPv6 support
- Old style SSL support
- New API xmpp_uuid_gen()
0.8.8

View File

@@ -10,6 +10,7 @@
*/
#include <stdio.h>
#include <string.h>
#include <strophe.h>
@@ -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 <jid> <pass> [<host>]\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] <jid> <pass> [<host>]\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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -16,6 +16,7 @@
/** @defgroup Connections Connection management
*/
#include <errno.h>
#include <stdarg.h>
#include <string.h>
@@ -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;
};
}

View File

@@ -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);
}

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);
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,