Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
160a124619 | ||
|
|
450bbca8e7 | ||
|
|
20380157ba | ||
|
|
3e12f33cce | ||
|
|
f05529b09a | ||
|
|
cc486b2ebf | ||
|
|
165d2487bb | ||
|
|
32591e3e77 | ||
|
|
cd92f69c76 | ||
|
|
73080e0660 | ||
|
|
7cdef1e319 | ||
|
|
527bc0573a | ||
|
|
59d2dd55d2 | ||
|
|
b1cbcffdc7 | ||
|
|
154b70ed2c | ||
|
|
e33a98e498 | ||
|
|
239d365ea1 | ||
|
|
57ed30b2bc | ||
|
|
86f913b001 | ||
|
|
e2f1c1e94a | ||
|
|
f62d817c71 | ||
|
|
b753e6cf18 | ||
|
|
0fed8a55e4 | ||
|
|
d28520ba30 | ||
|
|
c52ba85846 | ||
|
|
3b906f6ceb | ||
|
|
5d76e052ec | ||
|
|
37a40dec23 | ||
|
|
71f75b2e2e |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -29,10 +29,11 @@ examples/*.o
|
||||
docs/html
|
||||
TAGS
|
||||
tags
|
||||
examples/basic
|
||||
examples/active
|
||||
examples/roster
|
||||
examples/basic
|
||||
examples/bot
|
||||
examples/component
|
||||
examples/roster
|
||||
test_stamp
|
||||
test-suite.log
|
||||
tests/*.o
|
||||
@@ -46,3 +47,4 @@ tests/test_jid
|
||||
tests/test_sasl
|
||||
tests/test_sock
|
||||
m4/
|
||||
libstrophe.project
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
0.8.8
|
||||
- XML namespace support
|
||||
- XEP-0114 support
|
||||
|
||||
0.8.7
|
||||
- SCRAM-SHA-1 authentication mechanism
|
||||
- pkg-config support
|
||||
|
||||
10
Makefile.am
10
Makefile.am
@@ -6,6 +6,7 @@ AM_CFLAGS = -g -Wall
|
||||
PARSER_CFLAGS=@PARSER_CFLAGS@
|
||||
PARSER_LIBS=@PARSER_LIBS@
|
||||
|
||||
SSL_CFLAGS = @openssl_CFLAGS@
|
||||
SSL_LIBS = @openssl_LIBS@
|
||||
|
||||
STROPHE_FLAGS = -I$(top_srcdir)
|
||||
@@ -14,7 +15,7 @@ STROPHE_LIBS = libstrophe.la
|
||||
## Main build targets
|
||||
lib_LTLIBRARIES = libstrophe.la
|
||||
|
||||
libstrophe_la_CFLAGS = $(STROPHE_FLAGS) $(PARSER_CFLAGS)
|
||||
libstrophe_la_CFLAGS = $(SSL_CFLAGS) $(STROPHE_FLAGS) $(PARSER_CFLAGS)
|
||||
libstrophe_la_LDFLAGS = $(SSL_LIBS) $(PARSER_LIBS)
|
||||
# Export only public API
|
||||
libstrophe_la_LDFLAGS += -export-symbols-regex '^xmpp_'
|
||||
@@ -41,7 +42,7 @@ pkgconfig_DATA = libstrophe.pc
|
||||
EXTRA_DIST = docs
|
||||
|
||||
## Examples
|
||||
noinst_PROGRAMS = examples/active examples/roster examples/basic examples/bot
|
||||
noinst_PROGRAMS = examples/active examples/roster examples/basic examples/bot examples/component
|
||||
examples_active_SOURCES = examples/active.c
|
||||
examples_active_CFLAGS = $(STROPHE_FLAGS)
|
||||
examples_active_LDADD = $(STROPHE_LIBS)
|
||||
@@ -53,7 +54,10 @@ examples_basic_CFLAGS = $(STROPHE_FLAGS)
|
||||
examples_basic_LDADD = $(STROPHE_LIBS)
|
||||
examples_bot_SOURCES = examples/bot.c
|
||||
examples_bot_CFLAGS = $(STROPHE_FLAGS)
|
||||
examples_bot_LDADD = $(STROPHE_LIBS)
|
||||
examples_bot_LDADD = $(STROPHE_LIBS)
|
||||
examples_component_SOURCES = examples/component.c
|
||||
examples_component_CFLAGS = $(STROPHE_FLAGS)
|
||||
examples_component_LDADD = $(STROPHE_LIBS)
|
||||
|
||||
|
||||
## Tests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Some versions of aclocal fail if m4/ doesn't exist
|
||||
mkdir -p m4
|
||||
autoreconf -i
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
AC_INIT([libstrophe], [0.8.7], [jack@metajack.im])
|
||||
AC_INIT([libstrophe], [0.8.8], [jack@metajack.im])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
LT_INIT([dlopen])
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/* This example demonstrates basic handler functions by printing out
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/* simple bot example
|
||||
|
||||
97
examples/component.c
Normal file
97
examples/component.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/* component.c
|
||||
** libstrophe XMPP client library -- external component (XEP-0114) example
|
||||
**
|
||||
** Copyright (C) 2005-2009 Collecta, Inc.
|
||||
**
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/* This example demonstrates simple connection to a server
|
||||
** as an external component. See XEP-0114 for more details.
|
||||
** This program requires correctly configured server to run.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <strophe.h>
|
||||
|
||||
|
||||
/* define a handler for connection events */
|
||||
void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status,
|
||||
const int error, xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
|
||||
|
||||
if (status == XMPP_CONN_CONNECT) {
|
||||
fprintf(stderr, "DEBUG: connected\n");
|
||||
xmpp_disconnect(conn);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "DEBUG: disconnected\n");
|
||||
xmpp_stop(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
xmpp_conn_t *conn;
|
||||
xmpp_log_t *log;
|
||||
char *jid, *pass, *host, *port_err = NULL;
|
||||
unsigned short port = 0;
|
||||
|
||||
/* take a jid and password on the command line */
|
||||
if (argc < 4 || argc > 5) {
|
||||
fprintf(stderr, "Usage: component <jid> <pass> <host> [<port>]\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
jid = argv[1];
|
||||
pass = argv[2];
|
||||
host = argv[3];
|
||||
|
||||
if (argc == 5) {
|
||||
short tmp_port = (short) strtol(argv[4], &port_err, 10);
|
||||
if (tmp_port < 0 || *port_err != '\0') {
|
||||
fprintf(stderr, "Invalid value of <port> [%s].\n", argv[4]);
|
||||
return 1;
|
||||
}
|
||||
port = (unsigned short) tmp_port;
|
||||
}
|
||||
|
||||
/* init library */
|
||||
xmpp_initialize();
|
||||
|
||||
/* create a context */
|
||||
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); /* pass NULL instead to silence output */
|
||||
ctx = xmpp_ctx_new(NULL, log);
|
||||
|
||||
/* create a connection */
|
||||
conn = xmpp_conn_new(ctx);
|
||||
|
||||
/* setup authentication information */
|
||||
xmpp_conn_set_jid(conn, jid);
|
||||
xmpp_conn_set_pass(conn, pass);
|
||||
|
||||
/* initiate connection */
|
||||
xmpp_connect_component(conn, host, port, conn_handler, ctx);
|
||||
|
||||
/* enter the event loop -
|
||||
our connect handler will trigger an exit */
|
||||
xmpp_run(ctx);
|
||||
|
||||
/* release our connection and context */
|
||||
xmpp_conn_release(conn);
|
||||
xmpp_ctx_free(ctx);
|
||||
|
||||
/* final shutdown of the library */
|
||||
xmpp_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/* This example demonstrates basic handler functions by printing out
|
||||
|
||||
189
src/auth.c
189
src/auth.c
@@ -1,18 +1,15 @@
|
||||
/* auth.c
|
||||
** strophe XMPP client library -- auth functions and handlers
|
||||
**
|
||||
** Copyright (C) 2005-2009 Collecta, Inc.
|
||||
** Copyright (C) 2005-2009 Collecta, Inc.
|
||||
**
|
||||
** This software is provided AS-IS with no warranty, either express or
|
||||
** implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
/** @file
|
||||
* Authentication function and handlers.
|
||||
*/
|
||||
|
||||
@@ -24,6 +21,7 @@
|
||||
#include "strophe.h"
|
||||
#include "common.h"
|
||||
#include "sasl.h"
|
||||
#include "sha1.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strcasecmp stricmp
|
||||
@@ -55,9 +53,21 @@
|
||||
*/
|
||||
#define LEGACY_TIMEOUT 15000 /* 15 seconds */
|
||||
#endif
|
||||
#ifndef HANDSHAKE_TIMEOUT
|
||||
/** @def HANDSHAKE_TIMEOUT
|
||||
* Time to wait for component authentication to complete
|
||||
*/
|
||||
#define HANDSHAKE_TIMEOUT 15000 /* 15 seconds */
|
||||
#endif
|
||||
|
||||
static void _auth(xmpp_conn_t * const conn);
|
||||
static void _handle_open_sasl(xmpp_conn_t * const conn);
|
||||
|
||||
static int _handle_component_auth(xmpp_conn_t * const conn);
|
||||
static int _handle_component_hs_response(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
|
||||
static int _handle_missing_legacy(xmpp_conn_t * const conn,
|
||||
void * const userdata);
|
||||
static int _handle_legacy(xmpp_conn_t * const conn,
|
||||
@@ -92,6 +102,8 @@ static int _handle_session(xmpp_conn_t * const conn,
|
||||
void * const userdata);
|
||||
static int _handle_missing_session(xmpp_conn_t * const conn,
|
||||
void * const userdata);
|
||||
static int _handle_missing_handshake(xmpp_conn_t * const conn,
|
||||
void * const userdata);
|
||||
|
||||
/* stream:error handler */
|
||||
static int _handle_error(xmpp_conn_t * const conn,
|
||||
@@ -104,7 +116,7 @@ static int _handle_error(xmpp_conn_t * const conn,
|
||||
/* free old stream error if it's still there */
|
||||
if (conn->stream_error) {
|
||||
xmpp_stanza_release(conn->stream_error->stanza);
|
||||
if (conn->stream_error->text)
|
||||
if (conn->stream_error->text)
|
||||
xmpp_free(conn->ctx, conn->stream_error->text);
|
||||
xmpp_free(conn->ctx, conn->stream_error);
|
||||
}
|
||||
@@ -225,9 +237,9 @@ static int _handle_features(xmpp_conn_t * const conn,
|
||||
/* check for SASL */
|
||||
child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
|
||||
if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_SASL) == 0)) {
|
||||
for (mech = xmpp_stanza_get_children(child); mech;
|
||||
for (mech = xmpp_stanza_get_children(child); mech;
|
||||
mech = xmpp_stanza_get_next(mech)) {
|
||||
if (strcmp(xmpp_stanza_get_name(mech), "mechanism") == 0) {
|
||||
if (xmpp_stanza_get_name(mech) && strcmp(xmpp_stanza_get_name(mech), "mechanism") == 0) {
|
||||
text = xmpp_stanza_get_text(mech);
|
||||
if (strcasecmp(text, "PLAIN") == 0)
|
||||
conn->sasl_support |= SASL_MASK_PLAIN;
|
||||
@@ -244,7 +256,7 @@ static int _handle_features(xmpp_conn_t * const conn,
|
||||
}
|
||||
|
||||
_auth(conn);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -269,7 +281,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
|
||||
{
|
||||
char *name;
|
||||
name = xmpp_stanza_get_name(stanza);
|
||||
xmpp_debug(conn->ctx, "xmpp",
|
||||
xmpp_debug(conn->ctx, "xmpp",
|
||||
"handle proceedtls called for %s", name);
|
||||
|
||||
if (strcmp(name, "proceed") == 0) {
|
||||
@@ -283,7 +295,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
|
||||
tls_free(conn->tls);
|
||||
conn->tls = NULL;
|
||||
conn->tls_failed = 1;
|
||||
|
||||
|
||||
/* failed tls spoils the connection, so disconnect */
|
||||
xmpp_disconnect(conn);
|
||||
}
|
||||
@@ -309,14 +321,14 @@ static int _handle_sasl_result(xmpp_conn_t * const conn,
|
||||
|
||||
/* the server should send a <success> or <failure> stanza */
|
||||
if (strcmp(name, "failure") == 0) {
|
||||
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth failed",
|
||||
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth failed",
|
||||
(char *)userdata);
|
||||
|
||||
|
||||
/* fall back to next auth method */
|
||||
_auth(conn);
|
||||
} else if (strcmp(name, "success") == 0) {
|
||||
/* SASL PLAIN auth successful, we need to restart the stream */
|
||||
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth successful",
|
||||
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth successful",
|
||||
(char *)userdata);
|
||||
|
||||
/* reset parser */
|
||||
@@ -361,10 +373,10 @@ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn,
|
||||
if (!auth) {
|
||||
disconnect_mem_error(conn);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
xmpp_stanza_set_name(auth, "response");
|
||||
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
||||
|
||||
|
||||
authdata = xmpp_stanza_new(conn->ctx);
|
||||
if (!authdata) {
|
||||
disconnect_mem_error(conn);
|
||||
@@ -377,7 +389,7 @@ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_add_child(auth, authdata);
|
||||
xmpp_stanza_release(authdata);
|
||||
|
||||
handler_add(conn, _handle_digestmd5_rspauth,
|
||||
handler_add(conn, _handle_digestmd5_rspauth,
|
||||
XMPP_NS_SASL, NULL, NULL, NULL);
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
@@ -410,7 +422,7 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
|
||||
if (!auth) {
|
||||
disconnect_mem_error(conn);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
xmpp_stanza_set_name(auth, "response");
|
||||
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
||||
xmpp_send(conn, auth);
|
||||
@@ -543,7 +555,7 @@ static xmpp_stanza_t *_make_starttls(xmpp_conn_t * const conn)
|
||||
xmpp_stanza_set_name(starttls, "starttls");
|
||||
xmpp_stanza_set_ns(starttls, XMPP_NS_TLS);
|
||||
}
|
||||
|
||||
|
||||
return starttls;
|
||||
}
|
||||
|
||||
@@ -559,14 +571,14 @@ static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
||||
xmpp_stanza_set_attribute(auth, "mechanism", mechanism);
|
||||
}
|
||||
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
/* authenticate the connection
|
||||
* this may get called multiple times. if any auth method fails,
|
||||
/* authenticate the connection
|
||||
* this may get called multiple times. if any auth method fails,
|
||||
* this will get called again until one auth method succeeds or every
|
||||
* method fails
|
||||
* method fails
|
||||
*/
|
||||
static void _auth(xmpp_conn_t * const conn)
|
||||
{
|
||||
@@ -607,7 +619,7 @@ static void _auth(xmpp_conn_t * const conn)
|
||||
return;
|
||||
}
|
||||
|
||||
handler_add(conn, _handle_proceedtls_default,
|
||||
handler_add(conn, _handle_proceedtls_default,
|
||||
XMPP_NS_TLS, NULL, NULL, NULL);
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
@@ -632,7 +644,7 @@ static void _auth(xmpp_conn_t * const conn)
|
||||
/* SASL ANONYMOUS was tried, unset flag */
|
||||
conn->sasl_support &= ~SASL_MASK_ANONYMOUS;
|
||||
} else if (anonjid) {
|
||||
xmpp_error(conn->ctx, "auth",
|
||||
xmpp_error(conn->ctx, "auth",
|
||||
"No node in JID, and SASL ANONYMOUS unsupported.");
|
||||
xmpp_disconnect(conn);
|
||||
} else if (conn->sasl_support & SASL_MASK_SCRAMSHA1) {
|
||||
@@ -688,7 +700,7 @@ static void _auth(xmpp_conn_t * const conn)
|
||||
|
||||
}
|
||||
|
||||
handler_add(conn, _handle_digestmd5_challenge,
|
||||
handler_add(conn, _handle_digestmd5_challenge,
|
||||
XMPP_NS_SASL, NULL, NULL, NULL);
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
@@ -706,7 +718,7 @@ static void _auth(xmpp_conn_t * const conn)
|
||||
if (!authdata) {
|
||||
disconnect_mem_error(conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
authid = _get_authid(conn);
|
||||
if (!authid) {
|
||||
disconnect_mem_error(conn);
|
||||
@@ -734,7 +746,7 @@ static void _auth(xmpp_conn_t * const conn)
|
||||
conn->sasl_support &= ~SASL_MASK_PLAIN;
|
||||
} else if (conn->type == XMPP_CLIENT) {
|
||||
/* legacy client authentication */
|
||||
|
||||
|
||||
iq = xmpp_stanza_new(conn->ctx);
|
||||
if (!iq) {
|
||||
disconnect_mem_error(conn);
|
||||
@@ -820,7 +832,7 @@ static void _auth(xmpp_conn_t * const conn)
|
||||
} else {
|
||||
xmpp_stanza_release(authdata);
|
||||
xmpp_stanza_release(iq);
|
||||
xmpp_error(conn->ctx, "auth",
|
||||
xmpp_error(conn->ctx, "auth",
|
||||
"Cannot authenticate without resource");
|
||||
xmpp_disconnect(conn);
|
||||
return;
|
||||
@@ -829,7 +841,7 @@ static void _auth(xmpp_conn_t * const conn)
|
||||
xmpp_stanza_release(authdata);
|
||||
|
||||
handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL);
|
||||
handler_add_timed(conn, _handle_missing_legacy,
|
||||
handler_add_timed(conn, _handle_missing_legacy,
|
||||
LEGACY_TIMEOUT, NULL);
|
||||
|
||||
xmpp_send(conn, iq);
|
||||
@@ -841,7 +853,7 @@ static void _auth(xmpp_conn_t * const conn)
|
||||
/** Set up handlers at stream start.
|
||||
* This function is called internally to Strophe for handling the opening
|
||||
* of an XMPP stream. It's called by the parser when a stream is opened
|
||||
* or reset, and adds the initial handlers for <stream:error/> and
|
||||
* or reset, and adds the initial handlers for <stream:error/> and
|
||||
* <stream:features/>. This function is not intended for use outside
|
||||
* of Strophe.
|
||||
*
|
||||
@@ -854,11 +866,11 @@ void auth_handle_open(xmpp_conn_t * const conn)
|
||||
|
||||
/* setup handler for stream:error */
|
||||
handler_add(conn, _handle_error,
|
||||
NULL, "stream:error", NULL, NULL);
|
||||
XMPP_NS_STREAMS, "error", NULL, NULL);
|
||||
|
||||
/* setup handlers for incoming <stream:features> */
|
||||
handler_add(conn, _handle_features,
|
||||
NULL, "stream:features", NULL, NULL);
|
||||
XMPP_NS_STREAMS, "features", NULL, NULL);
|
||||
handler_add_timed(conn, _handle_missing_features,
|
||||
FEATURES_TIMEOUT, NULL);
|
||||
}
|
||||
@@ -870,7 +882,7 @@ static void _handle_open_sasl(xmpp_conn_t * const conn)
|
||||
|
||||
/* setup stream:features handlers */
|
||||
handler_add(conn, _handle_features_sasl,
|
||||
NULL, "stream:features", NULL, NULL);
|
||||
XMPP_NS_STREAMS, "features", NULL, NULL);
|
||||
handler_add_timed(conn, _handle_missing_features_sasl,
|
||||
FEATURES_TIMEOUT, NULL);
|
||||
}
|
||||
@@ -903,7 +915,7 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
|
||||
/* if bind is required, go ahead and start it */
|
||||
if (conn->bind_required) {
|
||||
/* bind resource */
|
||||
|
||||
|
||||
/* setup response handlers */
|
||||
handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL);
|
||||
handler_add_timed(conn, _handle_missing_bind,
|
||||
@@ -935,7 +947,7 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
|
||||
resource = NULL;
|
||||
}
|
||||
|
||||
/* if we have a resource to request, do it. otherwise the
|
||||
/* if we have a resource to request, do it. otherwise the
|
||||
server will assign us one */
|
||||
if (resource) {
|
||||
res = xmpp_stanza_new(conn->ctx);
|
||||
@@ -986,7 +998,7 @@ static int _handle_missing_features_sasl(xmpp_conn_t * const conn,
|
||||
xmpp_disconnect(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int _handle_bind(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
@@ -1018,7 +1030,7 @@ static int _handle_bind(xmpp_conn_t * const conn,
|
||||
if (conn->session_required) {
|
||||
/* setup response handlers */
|
||||
handler_add_id(conn, _handle_session, "_xmpp_session1", NULL);
|
||||
handler_add_timed(conn, _handle_missing_session,
|
||||
handler_add_timed(conn, _handle_missing_session,
|
||||
SESSION_TIMEOUT, NULL);
|
||||
|
||||
/* send session request */
|
||||
@@ -1049,9 +1061,9 @@ static int _handle_bind(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_release(iq);
|
||||
} else {
|
||||
conn->authenticated = 1;
|
||||
|
||||
|
||||
/* call connection handler */
|
||||
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL,
|
||||
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL,
|
||||
conn->userdata);
|
||||
}
|
||||
} else {
|
||||
@@ -1088,7 +1100,7 @@ static int _handle_session(xmpp_conn_t * const conn,
|
||||
xmpp_debug(conn->ctx, "xmpp", "Session establishment successful.");
|
||||
|
||||
conn->authenticated = 1;
|
||||
|
||||
|
||||
/* call connection handler */
|
||||
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
|
||||
} else {
|
||||
@@ -1151,3 +1163,96 @@ static int _handle_missing_legacy(xmpp_conn_t * const conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void auth_handle_component_open(xmpp_conn_t * const conn)
|
||||
{
|
||||
/* reset all timed handlers */
|
||||
handler_reset_timed(conn, 0);
|
||||
|
||||
handler_add(conn, _handle_error, XMPP_NS_STREAMS, "error", NULL, NULL);
|
||||
handler_add(conn, _handle_component_hs_response, NULL,
|
||||
"handshake", NULL, NULL);
|
||||
handler_add_timed(conn, _handle_missing_handshake, HANDSHAKE_TIMEOUT, NULL);
|
||||
|
||||
_handle_component_auth(conn);
|
||||
}
|
||||
|
||||
/* Will compute SHA1 and authenticate the component to the server */
|
||||
int _handle_component_auth(xmpp_conn_t * const conn)
|
||||
{
|
||||
uint8_t md_value[SHA1_DIGEST_SIZE];
|
||||
SHA1_CTX mdctx;
|
||||
char *digest;
|
||||
size_t i;
|
||||
|
||||
/* Feed the session id and passphrase to the algorithm.
|
||||
* We need to compute SHA1(session_id + passphrase)
|
||||
*/
|
||||
SHA1_Init(&mdctx);
|
||||
SHA1_Update(&mdctx, (uint8_t*)conn->stream_id, strlen(conn->stream_id));
|
||||
SHA1_Update(&mdctx, (uint8_t*)conn->pass, strlen(conn->pass));
|
||||
SHA1_Final(&mdctx, md_value);
|
||||
|
||||
digest = xmpp_alloc(conn->ctx, 2*sizeof(md_value)+1);
|
||||
if (digest) {
|
||||
/* convert the digest into string representation */
|
||||
for (i = 0; i < sizeof(md_value); i++)
|
||||
xmpp_snprintf(digest+i*2, 3, "%02x", md_value[i]);
|
||||
digest[2*sizeof(md_value)] = '\0';
|
||||
|
||||
xmpp_debug(conn->ctx, "auth", "Digest: %s, len: %d",
|
||||
digest, strlen(digest));
|
||||
|
||||
/* Send the digest to the server */
|
||||
xmpp_send_raw_string(conn, "<handshake xmlns='%s'>%s</handshake>",
|
||||
XMPP_NS_COMPONENT, digest);
|
||||
xmpp_debug(conn->ctx, "auth", "Sent component handshake to the server.");
|
||||
xmpp_free(conn->ctx, digest);
|
||||
} else {
|
||||
xmpp_debug(conn->ctx, "auth", "Couldn't allocate memory for component "\
|
||||
"handshake digest.");
|
||||
xmpp_disconnect(conn);
|
||||
return XMPP_EMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if the received stanza is <handshake/> and set auth to true
|
||||
* and fire connection handler.
|
||||
*/
|
||||
int _handle_component_hs_response(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
char *name;
|
||||
|
||||
xmpp_timed_handler_delete(conn, _handle_missing_handshake);
|
||||
|
||||
name = xmpp_stanza_get_name(stanza);
|
||||
if (strcmp(name, "handshake") != 0) {
|
||||
char *msg;
|
||||
size_t msg_size;
|
||||
xmpp_stanza_to_text(stanza, &msg, &msg_size);
|
||||
if (msg) {
|
||||
xmpp_debug(conn->ctx, "auth", "Handshake failed: %s", msg);
|
||||
xmpp_free(conn->ctx, msg);
|
||||
}
|
||||
xmpp_disconnect(conn);
|
||||
return XMPP_EINT;
|
||||
} else {
|
||||
conn->authenticated = 1;
|
||||
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
|
||||
}
|
||||
|
||||
/* We don't need this handler anymore, return 0 so it can be deleted
|
||||
* from the list of handlers.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _handle_missing_handshake(xmpp_conn_t * const conn, void * const userdata)
|
||||
{
|
||||
xmpp_error(conn->ctx, "xmpp", "Server did not reply to handshake request.");
|
||||
xmpp_disconnect(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express or
|
||||
** implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -267,6 +264,7 @@ void disconnect_mem_error(xmpp_conn_t * const conn);
|
||||
|
||||
/* auth functions */
|
||||
void auth_handle_open(xmpp_conn_t * const conn);
|
||||
void auth_handle_component_open(xmpp_conn_t * const conn);
|
||||
|
||||
/* replacement snprintf and vsnprintf */
|
||||
int xmpp_snprintf (char *str, size_t count, const char *fmt, ...);
|
||||
|
||||
82
src/conn.c
82
src/conn.c
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -442,6 +439,73 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Initiate a component connection to server.
|
||||
* This function returns immediately after starting the connection
|
||||
* process to the XMPP server, and notifiations of connection state changes
|
||||
* will be sent to the internal callback function that will set up handler
|
||||
* for the component handshake as defined in XEP-0114.
|
||||
* The domain and port to connect to must be provided in this case as the JID
|
||||
* provided to the call serves as component identifier to the server and is
|
||||
* not subject to DNS resolution.
|
||||
*
|
||||
* @param conn a Strophe connection object
|
||||
* @param server a string with domain to use directly as the domain can't be
|
||||
* extracted from the component name/JID. If this is not set, the call
|
||||
* will fail.
|
||||
* @param port an integer port number to use to connect to server expecting
|
||||
* an external component. If this is 0, the port 5347 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
|
||||
*
|
||||
* @return 0 on success and -1 on an error
|
||||
*
|
||||
* @ingroup Connections
|
||||
*/
|
||||
int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
|
||||
unsigned short port, xmpp_conn_handler callback,
|
||||
void * const userdata)
|
||||
{
|
||||
int connectport;
|
||||
|
||||
conn->type = XMPP_COMPONENT;
|
||||
/* JID serves as an identificator here and will be used as "to" attribute
|
||||
of the stream */
|
||||
conn->domain = xmpp_strdup(conn->ctx, conn->jid);
|
||||
|
||||
/* The server domain, jid and password MUST be specified. */
|
||||
if (!(server && conn->jid && conn->pass)) return -1;
|
||||
|
||||
|
||||
connectport = port ? port : 5347;
|
||||
|
||||
xmpp_debug(conn->ctx, "xmpp", "Connecting via %s", server);
|
||||
conn->sock = sock_connect(server, connectport);
|
||||
xmpp_debug(conn->ctx, "xmpp", "sock_connect to %s:%d returned %d",
|
||||
server, connectport, conn->sock);
|
||||
if (conn->sock == -1) return -1;
|
||||
|
||||
/* XEP-0114 does not support TLS */
|
||||
conn->tls_disabled = 1;
|
||||
|
||||
/* setup handler */
|
||||
conn->conn_handler = callback;
|
||||
conn->userdata = userdata;
|
||||
|
||||
conn_prepare_reset(conn, auth_handle_component_open);
|
||||
|
||||
/* FIXME: it could happen that the connect returns immediately as
|
||||
* successful, though this is pretty unlikely. This would be a little
|
||||
* hard to fix, since we'd have to detect and fire off the callback
|
||||
* from within the event loop */
|
||||
|
||||
conn->state = XMPP_STATE_CONNECTING;
|
||||
conn->timeout_stamp = time_stamp();
|
||||
xmpp_debug(conn->ctx, "xmpp", "attempting to connect to %s", server);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Cleanly disconnect the connection.
|
||||
* This function is only called by the stream parser when </stream:stream>
|
||||
* is received, and it not intended to be called by code outside of Strophe.
|
||||
@@ -684,6 +748,7 @@ static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
|
||||
size_t pos;
|
||||
int len;
|
||||
int i;
|
||||
char *attr;
|
||||
|
||||
if (!attrs) return;
|
||||
|
||||
@@ -692,10 +757,11 @@ static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
|
||||
if (len < 0) return;
|
||||
|
||||
pos += len;
|
||||
|
||||
for (i = 0; attrs[i]; i += 2) {
|
||||
attr = parser_attr_name(conn->ctx, attrs[i]);
|
||||
len = xmpp_snprintf(&buf[pos], 4096 - pos, " %s='%s'",
|
||||
attrs[i], attrs[i+1]);
|
||||
attr, attrs[i+1]);
|
||||
xmpp_free(conn->ctx, attr);
|
||||
if (len < 0) return;
|
||||
pos += len;
|
||||
}
|
||||
@@ -725,7 +791,7 @@ static void _handle_stream_start(char *name, char **attrs,
|
||||
xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
|
||||
char *id;
|
||||
|
||||
if (strcmp(name, "stream:stream") != 0) {
|
||||
if (strcmp(name, "stream")) {
|
||||
printf("name = %s\n", name);
|
||||
xmpp_error(conn->ctx, "conn", "Server did not open valid stream.");
|
||||
conn_disconnect(conn);
|
||||
@@ -743,7 +809,7 @@ static void _handle_stream_start(char *name, char **attrs,
|
||||
conn_disconnect(conn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* call stream open handler */
|
||||
conn->open_handler(conn);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
19
src/event.c
19
src/event.c
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -40,11 +37,14 @@
|
||||
#ifndef _WIN32
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#define _sleep(x) usleep(x*1000)
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#define ETIMEDOUT WSAETIMEDOUT
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#define ECONNABORTED WSAECONNABORTED
|
||||
#define _sleep(x) Sleep(x)
|
||||
#endif
|
||||
|
||||
#include <strophe.h>
|
||||
@@ -221,13 +221,20 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
||||
tls_read_bytes += tls_pending(conn->tls);
|
||||
}
|
||||
|
||||
if (conn->sock > max) max = conn->sock;
|
||||
if (conn->state != XMPP_STATE_DISCONNECTED && conn->sock > max)
|
||||
max = conn->sock;
|
||||
|
||||
connitem = connitem->next;
|
||||
}
|
||||
|
||||
/* check for events */
|
||||
ret = select(max + 1, &rfds, &wfds, NULL, &tv);
|
||||
if (max > 0)
|
||||
ret = select(max + 1, &rfds, &wfds, NULL, &tv);
|
||||
else {
|
||||
if (timeout > 0)
|
||||
_sleep(timeout);
|
||||
return;
|
||||
}
|
||||
|
||||
/* select errored */
|
||||
if (ret < 0) {
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include "strophe.h"
|
||||
|
||||
@@ -7,10 +7,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express or
|
||||
** implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -37,6 +34,7 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
|
||||
parser_stanza_callback stanzacb,
|
||||
void *userdata);
|
||||
void parser_free(parser_t * const parser);
|
||||
char* parser_attr_name(xmpp_ctx_t *ctx, char *nsname);
|
||||
int parser_reset(parser_t *parser);
|
||||
int parser_feed(parser_t *parser, char *chunk, int len);
|
||||
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -26,6 +23,9 @@
|
||||
#include "common.h"
|
||||
#include "parser.h"
|
||||
|
||||
/* ASCII FF is invalid UTF-8 and should never be present in well-formed XML */
|
||||
#define NAMESPACE_SEP ('\xFF')
|
||||
|
||||
struct _parser_t {
|
||||
xmpp_ctx_t *ctx;
|
||||
XML_Parser expat;
|
||||
@@ -37,23 +37,71 @@ struct _parser_t {
|
||||
xmpp_stanza_t *stanza;
|
||||
};
|
||||
|
||||
/* return allocated string with the name from a delimited
|
||||
* namespace/name string */
|
||||
static char *_xml_name(xmpp_ctx_t *ctx, const char *nsname)
|
||||
{
|
||||
char *result = NULL;
|
||||
const char *c;
|
||||
int len;
|
||||
|
||||
c = strchr(nsname, NAMESPACE_SEP);
|
||||
if (c == NULL) return xmpp_strdup(ctx, nsname);
|
||||
|
||||
c++;
|
||||
len = strlen(c);
|
||||
result = xmpp_alloc(ctx, len + 1);
|
||||
if (result != NULL) {
|
||||
memcpy(result, c, len);
|
||||
result[len] = '\0';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* return allocated string with the namespace from a delimited string */
|
||||
static char *_xml_namespace(xmpp_ctx_t *ctx, const char *nsname)
|
||||
{
|
||||
char *result = NULL;
|
||||
const char *c;
|
||||
|
||||
c = strchr(nsname, NAMESPACE_SEP);
|
||||
if (c != NULL) {
|
||||
result = xmpp_alloc(ctx, (c-nsname) + 1);
|
||||
if (result != NULL) {
|
||||
memcpy(result, nsname, (c-nsname));
|
||||
result[c-nsname] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _set_attributes(xmpp_stanza_t *stanza, const XML_Char **attrs)
|
||||
{
|
||||
char *attr;
|
||||
int i;
|
||||
|
||||
if (!attrs) return;
|
||||
|
||||
for (i = 0; attrs[i]; i += 2) {
|
||||
xmpp_stanza_set_attribute(stanza, attrs[i], attrs[i+1]);
|
||||
/* namespaced attributes aren't used in xmpp, discard namespace */
|
||||
attr = _xml_name(stanza->ctx, attrs[i]);
|
||||
xmpp_stanza_set_attribute(stanza, attr, attrs[i+1]);
|
||||
xmpp_free(stanza->ctx, attr);
|
||||
}
|
||||
}
|
||||
|
||||
static void _start_element(void *userdata,
|
||||
const XML_Char *name,
|
||||
const XML_Char *nsname,
|
||||
const XML_Char **attrs)
|
||||
{
|
||||
parser_t *parser = (parser_t *)userdata;
|
||||
xmpp_stanza_t *child;
|
||||
char *ns, *name;
|
||||
|
||||
ns = _xml_namespace(parser->ctx, nsname);
|
||||
name = _xml_name(parser->ctx, nsname);
|
||||
|
||||
if (parser->depth == 0) {
|
||||
/* notify the owner */
|
||||
@@ -74,6 +122,8 @@ static void _start_element(void *userdata,
|
||||
}
|
||||
xmpp_stanza_set_name(parser->stanza, name);
|
||||
_set_attributes(parser->stanza, attrs);
|
||||
if (ns)
|
||||
xmpp_stanza_set_ns(parser->stanza, ns);
|
||||
} else {
|
||||
/* starting a child of parser->stanza */
|
||||
child = xmpp_stanza_new(parser->ctx);
|
||||
@@ -82,6 +132,8 @@ static void _start_element(void *userdata,
|
||||
}
|
||||
xmpp_stanza_set_name(child, name);
|
||||
_set_attributes(child, attrs);
|
||||
if (ns)
|
||||
xmpp_stanza_set_ns(child, ns);
|
||||
|
||||
/* add child to parent */
|
||||
xmpp_stanza_add_child(parser->stanza, child);
|
||||
@@ -94,6 +146,9 @@ static void _start_element(void *userdata,
|
||||
}
|
||||
}
|
||||
|
||||
if (ns) xmpp_free(parser->ctx, ns);
|
||||
if (name) xmpp_free(parser->ctx, name);
|
||||
|
||||
parser->depth++;
|
||||
}
|
||||
|
||||
@@ -165,6 +220,11 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
|
||||
return parser;
|
||||
}
|
||||
|
||||
char* parser_attr_name(xmpp_ctx_t *ctx, char *nsname)
|
||||
{
|
||||
return _xml_name(ctx, nsname);
|
||||
}
|
||||
|
||||
/* free a parser */
|
||||
void parser_free(parser_t *parser)
|
||||
{
|
||||
@@ -183,7 +243,7 @@ int parser_reset(parser_t *parser)
|
||||
if (parser->stanza)
|
||||
xmpp_stanza_release(parser->stanza);
|
||||
|
||||
parser->expat = XML_ParserCreate(NULL);
|
||||
parser->expat = XML_ParserCreateNS(NULL, NAMESPACE_SEP);
|
||||
if (!parser->expat) return 0;
|
||||
|
||||
parser->depth = 0;
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -39,28 +36,91 @@ struct _parser_t {
|
||||
xmpp_stanza_t *stanza;
|
||||
};
|
||||
|
||||
static void _set_attributes(xmpp_stanza_t *stanza, const xmlChar **attrs)
|
||||
static void _set_attributes(xmpp_stanza_t *stanza, int nattrs,
|
||||
const xmlChar **attrs)
|
||||
{
|
||||
int i;
|
||||
int i, len;
|
||||
char *value;
|
||||
|
||||
if (!attrs) return;
|
||||
|
||||
for (i = 0; attrs[i]; i += 2) {
|
||||
xmpp_stanza_set_attribute(stanza, (const char *)attrs[i], (const char *)attrs[i+1]);
|
||||
/* SAX2 uses array of localname/prefix/uri/value_begin/value_end */
|
||||
for (i = 0; i < nattrs*5; i += 5) {
|
||||
len = attrs[i+4] - attrs[i+3];
|
||||
value = xmpp_alloc(stanza->ctx, len + 1);
|
||||
if (value) {
|
||||
memcpy(value, attrs[i+3], len);
|
||||
value[len] = '\0';
|
||||
xmpp_stanza_set_attribute(stanza, (const char *)attrs[i], value);
|
||||
xmpp_free(stanza->ctx, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* SAX2 gives us the attrs in an incredibly inconvenient array,
|
||||
* convert it to what the start callback is expecting */
|
||||
static char **_convert_attrs(parser_t *parser, int nattrs,
|
||||
const xmlChar **attrs)
|
||||
{
|
||||
int c, i, o, len;
|
||||
char *value;
|
||||
char **ret;
|
||||
|
||||
if (!attrs) return NULL;
|
||||
|
||||
ret = xmpp_alloc(parser->ctx, (nattrs+1)*2*sizeof(char*));
|
||||
if (!ret) return NULL;
|
||||
memset(ret, 0, (nattrs+1)*2*sizeof(char*));
|
||||
|
||||
for (c = 0; c < nattrs; c++) {
|
||||
i = c * 5;
|
||||
o = c * 2;
|
||||
|
||||
len = attrs[i+4] - attrs[i+3];
|
||||
value = xmpp_alloc(parser->ctx, len + 1);
|
||||
if (value) {
|
||||
memcpy(value, attrs[i+3], len);
|
||||
value[len] = '\0';
|
||||
ret[o] = xmpp_strdup(parser->ctx, (char*)attrs[i]);
|
||||
ret[o+1] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _free_cbattrs(parser_t *parser, char **attrs)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!attrs)
|
||||
return;
|
||||
|
||||
for (i = 0; attrs[i]; i += 2) {
|
||||
if (attrs[i]) xmpp_free(parser->ctx, attrs[i]);
|
||||
if (attrs[i+1]) xmpp_free(parser->ctx, attrs[i+1]);
|
||||
}
|
||||
|
||||
xmpp_free(parser->ctx, attrs);
|
||||
}
|
||||
|
||||
static void _start_element(void *userdata,
|
||||
const xmlChar *name, const xmlChar **attrs)
|
||||
const xmlChar *name, const xmlChar *prefix,
|
||||
const xmlChar *uri, int nnamespaces,
|
||||
const xmlChar **namespaces, int nattrs,
|
||||
int ndefaulted, const xmlChar **attrs)
|
||||
{
|
||||
parser_t *parser = (parser_t *)userdata;
|
||||
xmpp_stanza_t *child;
|
||||
char **cbattrs;
|
||||
|
||||
if (parser->depth == 0) {
|
||||
/* notify the owner */
|
||||
if (parser->startcb)
|
||||
parser->startcb((char *)name, (char **)attrs,
|
||||
cbattrs = _convert_attrs(parser, nattrs, attrs);
|
||||
parser->startcb((char *)name, cbattrs,
|
||||
parser->userdata);
|
||||
_free_cbattrs(parser, cbattrs);
|
||||
} else {
|
||||
/* build stanzas at depth 1 */
|
||||
if (!parser->stanza && parser->depth != 1) {
|
||||
@@ -74,7 +134,9 @@ static void _start_element(void *userdata,
|
||||
/* FIXME: can't allocate, disconnect */
|
||||
}
|
||||
xmpp_stanza_set_name(parser->stanza, (char *)name);
|
||||
_set_attributes(parser->stanza, attrs);
|
||||
_set_attributes(parser->stanza, nattrs, attrs);
|
||||
if (uri)
|
||||
xmpp_stanza_set_ns(parser->stanza, (char *)uri);
|
||||
} else {
|
||||
/* starting a child of conn->stanza */
|
||||
child = xmpp_stanza_new(parser->ctx);
|
||||
@@ -82,7 +144,9 @@ static void _start_element(void *userdata,
|
||||
/* FIXME: can't allocate, disconnect */
|
||||
}
|
||||
xmpp_stanza_set_name(child, (char *)name);
|
||||
_set_attributes(child, attrs);
|
||||
_set_attributes(child, nattrs, attrs);
|
||||
if (uri)
|
||||
xmpp_stanza_set_ns(child, (char *)uri);
|
||||
|
||||
/* add child to parent */
|
||||
xmpp_stanza_add_child(parser->stanza, child);
|
||||
@@ -98,7 +162,8 @@ static void _start_element(void *userdata,
|
||||
parser->depth++;
|
||||
}
|
||||
|
||||
static void _end_element(void *userdata, const xmlChar *name)
|
||||
static void _end_element(void *userdata, const xmlChar *name,
|
||||
const xmlChar *prefix, const xmlChar *uri)
|
||||
{
|
||||
parser_t *parser = (parser_t *)userdata;
|
||||
|
||||
@@ -156,8 +221,9 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
|
||||
parser->ctx = ctx;
|
||||
parser->xmlctx = NULL;
|
||||
memset(&parser->handlers, 0, sizeof(xmlSAXHandler));
|
||||
parser->handlers.startElement = _start_element;
|
||||
parser->handlers.endElement = _end_element;
|
||||
parser->handlers.initialized = XML_SAX2_MAGIC;
|
||||
parser->handlers.startElementNs = _start_element;
|
||||
parser->handlers.endElementNs = _end_element;
|
||||
parser->handlers.characters = _characters;
|
||||
parser->startcb = startcb;
|
||||
parser->endcb = endcb;
|
||||
@@ -172,6 +238,11 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
|
||||
return parser;
|
||||
}
|
||||
|
||||
char* parser_attr_name(xmpp_ctx_t *ctx, char *nsname)
|
||||
{
|
||||
return xmpp_strdup(ctx, nsname);
|
||||
}
|
||||
|
||||
/* free a parser */
|
||||
void parser_free(parser_t *parser)
|
||||
{
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
* This software is provided AS-IS with no warranty, either express
|
||||
* or implied.
|
||||
*
|
||||
* This software is distributed under license and may not be copied,
|
||||
* modified or distributed except as expressly authorized under the
|
||||
* terms of the license contained in the file LICENSE.txt in this
|
||||
* distribution.
|
||||
* This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
* This software is provided AS-IS with no warranty, either express
|
||||
* or implied.
|
||||
*
|
||||
* This software is distributed under license and may not be copied,
|
||||
* modified or distributed except as expressly authorized under the
|
||||
* terms of the license contained in the file LICENSE.txt in this
|
||||
* distribution.
|
||||
* This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
19
src/stanza.c
19
src/stanza.c
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -320,6 +317,20 @@ static int _render_stanza_recursive(xmpp_stanza_t *stanza,
|
||||
if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
|
||||
iter = hash_iter_new(stanza->attributes);
|
||||
while ((key = hash_iter_next(iter))) {
|
||||
if (!strcmp(key, "xmlns")) {
|
||||
/* don't output namespace if parent stanza is the same */
|
||||
if (stanza->parent &&
|
||||
stanza->parent->attributes &&
|
||||
hash_get(stanza->parent->attributes, key) &&
|
||||
!strcmp((char*)hash_get(stanza->attributes, key),
|
||||
(char*)hash_get(stanza->parent->attributes, key)))
|
||||
continue;
|
||||
/* or if this is the stream namespace */
|
||||
if (!stanza->parent &&
|
||||
!strcmp((char*)hash_get(stanza->attributes, key),
|
||||
XMPP_NS_CLIENT))
|
||||
continue;
|
||||
}
|
||||
tmp = _escape_xml(stanza->ctx,
|
||||
(char *)hash_get(stanza->attributes, key));
|
||||
if (tmp == NULL) return XMPP_EMEM;
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
/* tls_openssl.c
|
||||
** strophe XMPP client library -- TLS abstraction openssl impl.
|
||||
**
|
||||
** Copyright (C) 2005-008 Collecta, Inc.
|
||||
** Copyright (C) 2005-008 Collecta, Inc.
|
||||
**
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -25,7 +22,6 @@
|
||||
#endif
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
#include "sock.h"
|
||||
@@ -54,31 +50,136 @@ int tls_error(tls_t *tls)
|
||||
return tls->lasterror;
|
||||
}
|
||||
|
||||
int
|
||||
convert_ASN1TIME(ASN1_TIME *ansi_time, char* buf, size_t len)
|
||||
{
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
int rc = ASN1_TIME_print(bio, ansi_time);
|
||||
if (rc <= 0) {
|
||||
BIO_free(bio);
|
||||
return 0;
|
||||
}
|
||||
rc = BIO_gets(bio, buf, len);
|
||||
if (rc <= 0) {
|
||||
BIO_free(bio);
|
||||
return 0;
|
||||
}
|
||||
BIO_free(bio);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
hex_encode(unsigned char* readbuf, void *writebuf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i < len; i++) {
|
||||
char *l = (char*) (2*i + ((intptr_t) writebuf));
|
||||
sprintf(l, "%02x", readbuf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static xmpp_ctx_t *xmppctx;
|
||||
|
||||
static void
|
||||
print_certificate(X509* cert) {
|
||||
char subj[1024+1];
|
||||
char issuer[1024+1];
|
||||
X509_NAME_oneline(X509_get_subject_name(cert), subj, 1024);
|
||||
X509_NAME_oneline(X509_get_issuer_name(cert), issuer, 1024);
|
||||
xmpp_debug(xmppctx, "TLS", "SUBJECT : %s", subj);
|
||||
xmpp_debug(xmppctx, "TLS", "ISSUER : %s", issuer);
|
||||
}
|
||||
|
||||
static int
|
||||
verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||
{
|
||||
X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx);
|
||||
|
||||
const STACK_OF(X509) *sk = X509_STORE_CTX_get1_chain(x509_ctx);
|
||||
int slen = sk_num((const _STACK *)sk);
|
||||
unsigned i;
|
||||
X509 *certsk;
|
||||
xmpp_debug(xmppctx, "TLS", "STACK");
|
||||
for(i=0; i<slen; i++) {
|
||||
certsk = (X509*) sk_value((const _STACK *)sk, i);
|
||||
print_certificate(certsk);
|
||||
}
|
||||
xmpp_debug(xmppctx, "TLS", "ENDSTACK");
|
||||
|
||||
X509_NAME *subject = X509_get_subject_name(cert);
|
||||
char *nameline = X509_NAME_oneline(subject, NULL, 0);
|
||||
xmpp_debug(xmppctx, "TLS", "SUBJECT : %s", nameline);
|
||||
OPENSSL_free(nameline);
|
||||
|
||||
X509_NAME *issuer = X509_get_issuer_name(cert);
|
||||
nameline = X509_NAME_oneline(issuer, NULL, 0);
|
||||
xmpp_debug(xmppctx, "TLS", "ISSUER : %s", nameline);
|
||||
OPENSSL_free(nameline);
|
||||
|
||||
ASN1_TIME *not_before = X509_get_notBefore(cert);
|
||||
char not_before_str[128];
|
||||
int not_before_res = convert_ASN1TIME(not_before, not_before_str, 128);
|
||||
if (not_before_res) {
|
||||
xmpp_debug(xmppctx, "TLS", "NOT BEFORE : %s", not_before_str);
|
||||
}
|
||||
|
||||
ASN1_TIME *not_after = X509_get_notAfter(cert);
|
||||
char not_after_str[128];
|
||||
int not_after_res = convert_ASN1TIME(not_after, not_after_str, 128);
|
||||
if (not_after_res) {
|
||||
xmpp_debug(xmppctx, "TLS", "NOT AFTER : %s", not_after_str);
|
||||
}
|
||||
|
||||
char buf[20];
|
||||
const EVP_MD *digest = EVP_sha1();
|
||||
unsigned len;
|
||||
|
||||
int rc = X509_digest(cert, digest, (unsigned char*) buf, &len);
|
||||
if (rc != 0 && len == 20) {
|
||||
char strbuf[2*20+1];
|
||||
hex_encode(buf, strbuf, 20);
|
||||
xmpp_debug(xmppctx, "TLS", "FINGERPRINT : %s", strbuf);
|
||||
}
|
||||
|
||||
if (preverify_ok) {
|
||||
xmpp_debug(xmppctx, "TLS", "VERIFY SUCCESS");
|
||||
return 1;
|
||||
} else {
|
||||
xmpp_debug(xmppctx, "TLS", "VERIFY FAILED");
|
||||
|
||||
int err = X509_STORE_CTX_get_error(x509_ctx);
|
||||
const char *errstr = X509_verify_cert_error_string(err);
|
||||
xmpp_debug(xmppctx, "TLS", "ERROR: %s", errstr);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
|
||||
{
|
||||
xmppctx = ctx;
|
||||
tls_t *tls = xmpp_alloc(ctx, sizeof(*tls));
|
||||
|
||||
if (tls) {
|
||||
int ret;
|
||||
memset(tls, 0, sizeof(*tls));
|
||||
memset(tls, 0, sizeof(*tls));
|
||||
|
||||
tls->ctx = ctx;
|
||||
tls->sock = sock;
|
||||
tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
tls->ctx = ctx;
|
||||
tls->sock = sock;
|
||||
tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
|
||||
SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL);
|
||||
SSL_CTX_set_mode (tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||
SSL_CTX_set_verify (tls->ssl_ctx, SSL_VERIFY_NONE, NULL);
|
||||
SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL);
|
||||
SSL_CTX_set_mode (tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||
SSL_CTX_set_verify (tls->ssl_ctx, SSL_VERIFY_PEER, verify_callback);
|
||||
tls->ssl = SSL_new(tls->ssl_ctx);
|
||||
|
||||
tls->ssl = SSL_new(tls->ssl_ctx);
|
||||
|
||||
ret = SSL_set_fd(tls->ssl, sock);
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
tls_error(tls);
|
||||
tls_free(tls);
|
||||
tls = NULL;
|
||||
}
|
||||
ret = SSL_set_fd(tls->ssl, sock);
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
tls_error(tls);
|
||||
tls_free(tls);
|
||||
tls = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return tls;
|
||||
@@ -102,32 +203,35 @@ int tls_start(tls_t *tls)
|
||||
int ret = -1;
|
||||
|
||||
/* Since we're non-blocking, loop the connect call until it
|
||||
succeeds or fails */
|
||||
while (ret == -1) {
|
||||
ret = SSL_connect(tls->ssl);
|
||||
succeeds or fails */
|
||||
while (ret < 0) {
|
||||
ret = SSL_connect(tls->ssl);
|
||||
int err = SSL_get_error(tls->ssl, ret);
|
||||
int recoverable = tls_is_recoverable(err);
|
||||
|
||||
/* wait for something to happen on the sock before looping back */
|
||||
if (ret == -1) {
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
// continue if recoverable
|
||||
if (recoverable) {
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1000;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 1000;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(tls->sock, &fds);
|
||||
|
||||
select(tls->sock + 1, &fds, &fds, NULL, &tv);
|
||||
}
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(tls->sock, &fds);
|
||||
|
||||
select(tls->sock + 1, &fds, &fds, NULL, &tv);
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
return 0;
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int tls_stop(tls_t *tls)
|
||||
@@ -137,8 +241,8 @@ int tls_stop(tls_t *tls)
|
||||
ret = SSL_shutdown(tls->ssl);
|
||||
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
return 0;
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -147,9 +251,9 @@ int tls_stop(tls_t *tls)
|
||||
int tls_is_recoverable(int error)
|
||||
{
|
||||
return (error == SSL_ERROR_NONE || error == SSL_ERROR_WANT_READ
|
||||
|| error == SSL_ERROR_WANT_WRITE
|
||||
|| error == SSL_ERROR_WANT_CONNECT
|
||||
|| error == SSL_ERROR_WANT_ACCEPT);
|
||||
|| error == SSL_ERROR_WANT_WRITE
|
||||
|| error == SSL_ERROR_WANT_CONNECT
|
||||
|| error == SSL_ERROR_WANT_ACCEPT);
|
||||
}
|
||||
|
||||
int tls_pending(tls_t *tls)
|
||||
@@ -162,7 +266,7 @@ int tls_read(tls_t *tls, void * const buff, const size_t len)
|
||||
int ret = SSL_read(tls->ssl, buff, len);
|
||||
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -173,7 +277,7 @@ int tls_write(tls_t *tls, const void * const buff, const size_t len)
|
||||
int ret = SSL_write(tls->ssl, buff, len);
|
||||
|
||||
if (ret <= 0) {
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
tls->lasterror = SSL_get_error(tls->ssl, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
12
strophe.h
12
strophe.h
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express or
|
||||
** implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This software is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
@@ -225,9 +222,10 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
|
||||
xmpp_conn_handler callback,
|
||||
void * const userdata);
|
||||
|
||||
/*
|
||||
int xmpp_connect_component(conn, name)
|
||||
*/
|
||||
int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
|
||||
unsigned short port, xmpp_conn_handler callback,
|
||||
void * const userdata);
|
||||
|
||||
void xmpp_disconnect(xmpp_conn_t * const conn);
|
||||
|
||||
void xmpp_send(xmpp_conn_t * const conn,
|
||||
|
||||
@@ -5,11 +5,8 @@
|
||||
**
|
||||
** This software is provided AS-IS with no warranty, either express or
|
||||
** implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
**
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express or
|
||||
** implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -37,14 +34,14 @@ END_TEST
|
||||
int cbtest_got_start = 0;
|
||||
void cbtest_handle_start(char *name, char **attrs, void *userdata)
|
||||
{
|
||||
if (strcmp(name, "stream:stream") == 0)
|
||||
if (strcmp(name, "stream") == 0)
|
||||
cbtest_got_start = 1;
|
||||
}
|
||||
|
||||
int cbtest_got_end = 0;
|
||||
void cbtest_handle_end(char *name, void *userdata)
|
||||
{
|
||||
if (strcmp(name, "stream:stream") == 0)
|
||||
if (strcmp(name, "stream") == 0)
|
||||
cbtest_got_end = 1;
|
||||
}
|
||||
|
||||
@@ -67,9 +64,9 @@ START_TEST(callbacks)
|
||||
cbtest_handle_end,
|
||||
cbtest_handle_stanza, NULL);
|
||||
|
||||
ret = parser_feed(parser, "<stream:stream>", 15);
|
||||
ret = parser_feed(parser, "<stream>", 8);
|
||||
ret = parser_feed(parser, "<message/>", 10);
|
||||
parser_feed(parser, "</stream:stream>", 16);
|
||||
parser_feed(parser, "</stream>", 9);
|
||||
|
||||
fail_unless(cbtest_got_start == 1);
|
||||
fail_unless(cbtest_got_end == 1);
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
** This software is provided AS-IS with no warranty, either express
|
||||
** or implied.
|
||||
**
|
||||
** This software is distributed under license and may not be copied,
|
||||
** modified or distributed except as expressly authorized under the
|
||||
** terms of the license contained in the file LICENSE.txt in this
|
||||
** distribution.
|
||||
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
Reference in New Issue
Block a user