Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f915d7515 | ||
|
|
e25ca7719f | ||
|
|
2bf5cc0e41 | ||
|
|
30f3cc9263 | ||
|
|
e120109644 | ||
|
|
b4f13205d8 | ||
|
|
4797522d88 | ||
|
|
5ee06776ee | ||
|
|
c40b4c12c1 | ||
|
|
d8329960c5 | ||
|
|
94ece33f16 | ||
|
|
b179c2d277 | ||
|
|
ab568a2666 | ||
|
|
c10c930e8f | ||
|
|
6ddf424192 | ||
|
|
6aff44184e | ||
|
|
9cc9ea86bb | ||
|
|
13a0bc463c | ||
|
|
8ff510a3af | ||
|
|
633d1e9b52 | ||
|
|
a13ba65cfb | ||
|
|
0e6b0ef84d | ||
|
|
9a86efabe5 |
@@ -1,11 +1,11 @@
|
|||||||
language: c
|
language: c
|
||||||
install:
|
install:
|
||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
- sudo apt-get -y install libtool pkg-config libexpat1-dev libxml2-dev libssl-dev check
|
- sudo apt-get -y install libtool pkg-config libexpat1-dev libxml2-dev libssl-dev
|
||||||
before_script:
|
before_script:
|
||||||
- ./bootstrap.sh
|
- ./bootstrap.sh
|
||||||
script:
|
script:
|
||||||
- ./configure ${CONFIGURE_OPT} && make && make check-TESTS
|
- ./configure ${CONFIGURE_OPT} CFLAGS="-Werror" && make && make check
|
||||||
env:
|
env:
|
||||||
- CONFIGURE_OPT="--without-libxml2"
|
- CONFIGURE_OPT="--without-libxml2"
|
||||||
- CONFIGURE_OPT="--with-libxml2"
|
- CONFIGURE_OPT="--with-libxml2"
|
||||||
|
|||||||
11
ChangeLog
11
ChangeLog
@@ -1,3 +1,12 @@
|
|||||||
|
0.9.3
|
||||||
|
- PLAIN mechanism is used only when no other mechanisms are supported
|
||||||
|
- Legacy authentication is disabled by default, can be enabled with
|
||||||
|
connection flag XMPP_CONN_FLAG_LEGACY_AUTH
|
||||||
|
- Session is not established if it is optional
|
||||||
|
- Fixed a bug causing a reused connection not to cleanup properly
|
||||||
|
- Improved debug logging in OpenSSL module
|
||||||
|
- Few memory leaks fixed
|
||||||
|
|
||||||
0.9.2
|
0.9.2
|
||||||
- OpenSSL tls module verifies certificate by default. Set flag
|
- OpenSSL tls module verifies certificate by default. Set flag
|
||||||
XMPP_CONN_FLAG_TRUST_TLS to ignore result of the verification
|
XMPP_CONN_FLAG_TRUST_TLS to ignore result of the verification
|
||||||
@@ -12,6 +21,8 @@
|
|||||||
second in order to reduce CPU consumption
|
second in order to reduce CPU consumption
|
||||||
- Reduced memory usage in expat module
|
- Reduced memory usage in expat module
|
||||||
- New functions:
|
- New functions:
|
||||||
|
- xmpp_error_new()
|
||||||
|
- xmpp_send_error()
|
||||||
- xmpp_ctx_set_timeout()
|
- xmpp_ctx_set_timeout()
|
||||||
- xmpp_sha1_digest()
|
- xmpp_sha1_digest()
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
AUTOMAKE_OPTIONS = subdir-objects
|
AUTOMAKE_OPTIONS = subdir-objects
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
AM_CFLAGS = -g -Wall
|
|
||||||
|
|
||||||
PARSER_CFLAGS=@PARSER_CFLAGS@
|
PARSER_CFLAGS=@PARSER_CFLAGS@
|
||||||
PARSER_LIBS=@PARSER_LIBS@
|
PARSER_LIBS=@PARSER_LIBS@
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libstrophe], [0.9.2], [jack@metajack.im])
|
AC_INIT([libstrophe], [0.9.3], [jack@metajack.im])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AM_INIT_AUTOMAKE([foreign])
|
AM_INIT_AUTOMAKE([foreign])
|
||||||
LT_INIT([dlopen])
|
LT_INIT([dlopen])
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ include $(BUILD_STATIC_LIBRARY)
|
|||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := libexpat
|
LOCAL_MODULE := libexpat
|
||||||
LOCAL_CFLAGS := -DHAVE_MEMMOVE
|
LOCAL_CFLAGS := -DHAVE_MEMMOVE -DXML_DEV_URANDOM
|
||||||
#LOCAL_C_INCLUDES := \
|
#LOCAL_C_INCLUDES := \
|
||||||
# $(LOCAL_PATH)/expat
|
# $(LOCAL_PATH)/expat
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
APP_ABI := armeabi armeabi-v7a mips x86
|
APP_ABI := armeabi-v7a arm64-v8a
|
||||||
APP_PLATFORM := android-19
|
APP_PLATFORM := android-19
|
||||||
|
|||||||
259
src/auth.c
259
src/auth.c
@@ -61,6 +61,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void _auth(xmpp_conn_t * const conn);
|
static void _auth(xmpp_conn_t * const conn);
|
||||||
|
static void _auth_legacy(xmpp_conn_t *conn);
|
||||||
static void _handle_open_sasl(xmpp_conn_t * const conn);
|
static void _handle_open_sasl(xmpp_conn_t * const conn);
|
||||||
static void _handle_open_tls(xmpp_conn_t * const conn);
|
static void _handle_open_tls(xmpp_conn_t * const conn);
|
||||||
|
|
||||||
@@ -69,11 +70,6 @@ static int _handle_component_hs_response(xmpp_conn_t * const conn,
|
|||||||
xmpp_stanza_t * const stanza,
|
xmpp_stanza_t * const stanza,
|
||||||
void * const userdata);
|
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,
|
|
||||||
xmpp_stanza_t * const stanza,
|
|
||||||
void * const userdata);
|
|
||||||
static int _handle_features_sasl(xmpp_conn_t * const conn,
|
static int _handle_features_sasl(xmpp_conn_t * const conn,
|
||||||
xmpp_stanza_t * const stanza,
|
xmpp_stanza_t * const stanza,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
@@ -219,6 +215,7 @@ static int _handle_features(xmpp_conn_t * const conn,
|
|||||||
void * const userdata)
|
void * const userdata)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *child, *mech;
|
xmpp_stanza_t *child, *mech;
|
||||||
|
const char *ns;
|
||||||
char *text;
|
char *text;
|
||||||
|
|
||||||
/* remove the handler that detects missing stream:features */
|
/* remove the handler that detects missing stream:features */
|
||||||
@@ -228,8 +225,10 @@ static int _handle_features(xmpp_conn_t * const conn,
|
|||||||
if (!conn->secured) {
|
if (!conn->secured) {
|
||||||
if (!conn->tls_disabled) {
|
if (!conn->tls_disabled) {
|
||||||
child = xmpp_stanza_get_child_by_name(stanza, "starttls");
|
child = xmpp_stanza_get_child_by_name(stanza, "starttls");
|
||||||
if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_TLS) == 0))
|
if (child) {
|
||||||
conn->tls_support = 1;
|
ns = xmpp_stanza_get_ns(child);
|
||||||
|
conn->tls_support = ns != NULL && strcmp(ns, XMPP_NS_TLS) == 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
conn->tls_support = 0;
|
conn->tls_support = 0;
|
||||||
}
|
}
|
||||||
@@ -237,11 +236,15 @@ static int _handle_features(xmpp_conn_t * const conn,
|
|||||||
|
|
||||||
/* check for SASL */
|
/* check for SASL */
|
||||||
child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
|
child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
|
||||||
if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_SASL) == 0)) {
|
ns = child ? xmpp_stanza_get_ns(child) : NULL;
|
||||||
|
if (child && ns && strcmp(ns, 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)) {
|
mech = xmpp_stanza_get_next(mech)) {
|
||||||
if (xmpp_stanza_get_name(mech) && 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);
|
text = xmpp_stanza_get_text(mech);
|
||||||
|
if (text == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (strcasecmp(text, "PLAIN") == 0)
|
if (strcasecmp(text, "PLAIN") == 0)
|
||||||
conn->sasl_support |= SASL_MASK_PLAIN;
|
conn->sasl_support |= SASL_MASK_PLAIN;
|
||||||
else if (strcasecmp(text, "DIGEST-MD5") == 0)
|
else if (strcasecmp(text, "DIGEST-MD5") == 0)
|
||||||
@@ -256,6 +259,10 @@ static int _handle_features(xmpp_conn_t * const conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable PLAIN when other secure mechanisms are supported */
|
||||||
|
if (conn->sasl_support & ~(SASL_MASK_PLAIN | SASL_MASK_ANONYMOUS))
|
||||||
|
conn->sasl_support &= ~SASL_MASK_PLAIN;
|
||||||
|
|
||||||
_auth(conn);
|
_auth(conn);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -550,9 +557,11 @@ static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t * const conn,
|
|||||||
*/
|
*/
|
||||||
static void _auth(xmpp_conn_t * const conn)
|
static void _auth(xmpp_conn_t * const conn)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *auth, *authdata, *query, *child, *iq;
|
xmpp_stanza_t *auth;
|
||||||
char *str, *authid;
|
xmpp_stanza_t *authdata;
|
||||||
|
char *authid;
|
||||||
char *scram_init;
|
char *scram_init;
|
||||||
|
char *str;
|
||||||
int anonjid;
|
int anonjid;
|
||||||
|
|
||||||
/* if there is no node in conn->jid, we assume anonymous connect */
|
/* if there is no node in conn->jid, we assume anonymous connect */
|
||||||
@@ -719,105 +728,12 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
|
|
||||||
/* SASL PLAIN was tried */
|
/* SASL PLAIN was tried */
|
||||||
conn->sasl_support &= ~SASL_MASK_PLAIN;
|
conn->sasl_support &= ~SASL_MASK_PLAIN;
|
||||||
} else if (conn->type == XMPP_CLIENT) {
|
} else if (conn->type == XMPP_CLIENT && conn->auth_legacy_enabled) {
|
||||||
/* legacy client authentication */
|
/* legacy client authentication */
|
||||||
|
_auth_legacy(conn);
|
||||||
iq = xmpp_iq_new(conn->ctx, "set", "_xmpp_auth1");
|
} else {
|
||||||
if (!iq) {
|
xmpp_error(conn->ctx, "auth", "Cannot authenticate with known methods");
|
||||||
disconnect_mem_error(conn);
|
xmpp_disconnect(conn);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
query = xmpp_stanza_new(conn->ctx);
|
|
||||||
if (!query) {
|
|
||||||
xmpp_stanza_release(iq);
|
|
||||||
disconnect_mem_error(conn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xmpp_stanza_set_name(query, "query");
|
|
||||||
xmpp_stanza_set_ns(query, XMPP_NS_AUTH);
|
|
||||||
xmpp_stanza_add_child(iq, query);
|
|
||||||
xmpp_stanza_release(query);
|
|
||||||
|
|
||||||
child = xmpp_stanza_new(conn->ctx);
|
|
||||||
if (!child) {
|
|
||||||
xmpp_stanza_release(iq);
|
|
||||||
disconnect_mem_error(conn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xmpp_stanza_set_name(child, "username");
|
|
||||||
xmpp_stanza_add_child(query, child);
|
|
||||||
xmpp_stanza_release(child);
|
|
||||||
|
|
||||||
authdata = xmpp_stanza_new(conn->ctx);
|
|
||||||
if (!authdata) {
|
|
||||||
xmpp_stanza_release(iq);
|
|
||||||
disconnect_mem_error(conn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
str = xmpp_jid_node(conn->ctx, conn->jid);
|
|
||||||
xmpp_stanza_set_text(authdata, str);
|
|
||||||
xmpp_free(conn->ctx, str);
|
|
||||||
xmpp_stanza_add_child(child, authdata);
|
|
||||||
xmpp_stanza_release(authdata);
|
|
||||||
|
|
||||||
child = xmpp_stanza_new(conn->ctx);
|
|
||||||
if (!child) {
|
|
||||||
xmpp_stanza_release(iq);
|
|
||||||
disconnect_mem_error(conn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xmpp_stanza_set_name(child, "password");
|
|
||||||
xmpp_stanza_add_child(query, child);
|
|
||||||
xmpp_stanza_release(child);
|
|
||||||
|
|
||||||
authdata = xmpp_stanza_new(conn->ctx);
|
|
||||||
if (!authdata) {
|
|
||||||
xmpp_stanza_release(iq);
|
|
||||||
disconnect_mem_error(conn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xmpp_stanza_set_text(authdata, conn->pass);
|
|
||||||
xmpp_stanza_add_child(child, authdata);
|
|
||||||
xmpp_stanza_release(authdata);
|
|
||||||
|
|
||||||
child = xmpp_stanza_new(conn->ctx);
|
|
||||||
if (!child) {
|
|
||||||
xmpp_stanza_release(iq);
|
|
||||||
disconnect_mem_error(conn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xmpp_stanza_set_name(child, "resource");
|
|
||||||
xmpp_stanza_add_child(query, child);
|
|
||||||
xmpp_stanza_release(child);
|
|
||||||
|
|
||||||
authdata = xmpp_stanza_new(conn->ctx);
|
|
||||||
if (!authdata) {
|
|
||||||
xmpp_stanza_release(iq);
|
|
||||||
disconnect_mem_error(conn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
str = xmpp_jid_resource(conn->ctx, conn->jid);
|
|
||||||
if (str) {
|
|
||||||
xmpp_stanza_set_text(authdata, str);
|
|
||||||
xmpp_free(conn->ctx, str);
|
|
||||||
} else {
|
|
||||||
xmpp_stanza_release(authdata);
|
|
||||||
xmpp_stanza_release(iq);
|
|
||||||
xmpp_error(conn->ctx, "auth",
|
|
||||||
"Cannot authenticate without resource");
|
|
||||||
xmpp_disconnect(conn);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
xmpp_stanza_add_child(child, authdata);
|
|
||||||
xmpp_stanza_release(authdata);
|
|
||||||
|
|
||||||
handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL);
|
|
||||||
handler_add_timed(conn, _handle_missing_legacy,
|
|
||||||
LEGACY_TIMEOUT, NULL);
|
|
||||||
|
|
||||||
xmpp_send(conn, iq);
|
|
||||||
xmpp_stanza_release(iq);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -871,7 +787,8 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
|
|||||||
xmpp_stanza_t * const stanza,
|
xmpp_stanza_t * const stanza,
|
||||||
void * const userdata)
|
void * const userdata)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *bind, *session, *iq, *res, *text;
|
xmpp_stanza_t *bind, *session, *iq, *res, *text, *opt;
|
||||||
|
const char *ns;
|
||||||
char *resource;
|
char *resource;
|
||||||
|
|
||||||
/* remove missing features handler */
|
/* remove missing features handler */
|
||||||
@@ -880,16 +797,21 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
|
|||||||
/* we are expecting <bind/> and <session/> since this is a
|
/* we are expecting <bind/> and <session/> since this is a
|
||||||
XMPP style connection */
|
XMPP style connection */
|
||||||
|
|
||||||
|
/* check whether resource binding is required */
|
||||||
bind = xmpp_stanza_get_child_by_name(stanza, "bind");
|
bind = xmpp_stanza_get_child_by_name(stanza, "bind");
|
||||||
if (bind && strcmp(xmpp_stanza_get_ns(bind), XMPP_NS_BIND) == 0) {
|
if (bind) {
|
||||||
/* resource binding is required */
|
ns = xmpp_stanza_get_ns(bind);
|
||||||
conn->bind_required = 1;
|
conn->bind_required = ns != NULL && strcmp(ns, XMPP_NS_BIND) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check whether session establishment is required */
|
||||||
session = xmpp_stanza_get_child_by_name(stanza, "session");
|
session = xmpp_stanza_get_child_by_name(stanza, "session");
|
||||||
if (session && strcmp(xmpp_stanza_get_ns(session), XMPP_NS_SESSION) == 0) {
|
if (session) {
|
||||||
/* session establishment required */
|
ns = xmpp_stanza_get_ns(session);
|
||||||
conn->session_required = 1;
|
opt = xmpp_stanza_get_child_by_name(session, "optional");
|
||||||
|
if (!opt)
|
||||||
|
conn->session_required = ns != NULL &&
|
||||||
|
strcmp(ns, XMPP_NS_SESSION) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if bind is required, go ahead and start it */
|
/* if bind is required, go ahead and start it */
|
||||||
@@ -1092,6 +1014,15 @@ static int _handle_missing_session(xmpp_conn_t * const conn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _handle_missing_legacy(xmpp_conn_t * const conn,
|
||||||
|
void * const userdata)
|
||||||
|
{
|
||||||
|
xmpp_error(conn->ctx, "xmpp", "Server did not reply to legacy "\
|
||||||
|
"authentication request.");
|
||||||
|
xmpp_disconnect(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _handle_legacy(xmpp_conn_t * const conn,
|
static int _handle_legacy(xmpp_conn_t * const conn,
|
||||||
xmpp_stanza_t * const stanza,
|
xmpp_stanza_t * const stanza,
|
||||||
void * const userdata)
|
void * const userdata)
|
||||||
@@ -1128,13 +1059,97 @@ static int _handle_legacy(xmpp_conn_t * const conn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _handle_missing_legacy(xmpp_conn_t * const conn,
|
static void _auth_legacy(xmpp_conn_t *conn)
|
||||||
void * const userdata)
|
|
||||||
{
|
{
|
||||||
xmpp_error(conn->ctx, "xmpp", "Server did not reply to legacy "\
|
xmpp_stanza_t *iq;
|
||||||
"authentication request.");
|
xmpp_stanza_t *authdata;
|
||||||
xmpp_disconnect(conn);
|
xmpp_stanza_t *query;
|
||||||
return 0;
|
xmpp_stanza_t *child;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
xmpp_debug(conn->ctx, "auth", "Legacy authentication request");
|
||||||
|
|
||||||
|
iq = xmpp_iq_new(conn->ctx, "set", "_xmpp_auth1");
|
||||||
|
if (!iq)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
query = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!query)
|
||||||
|
goto err_free;
|
||||||
|
xmpp_stanza_set_name(query, "query");
|
||||||
|
xmpp_stanza_set_ns(query, XMPP_NS_AUTH);
|
||||||
|
xmpp_stanza_add_child(iq, query);
|
||||||
|
xmpp_stanza_release(query);
|
||||||
|
|
||||||
|
child = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!child)
|
||||||
|
goto err_free;
|
||||||
|
xmpp_stanza_set_name(child, "username");
|
||||||
|
xmpp_stanza_add_child(query, child);
|
||||||
|
xmpp_stanza_release(child);
|
||||||
|
|
||||||
|
authdata = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!authdata)
|
||||||
|
goto err_free;
|
||||||
|
str = xmpp_jid_node(conn->ctx, conn->jid);
|
||||||
|
if (!str) {
|
||||||
|
xmpp_stanza_release(authdata);
|
||||||
|
goto err_free;
|
||||||
|
}
|
||||||
|
xmpp_stanza_set_text(authdata, str);
|
||||||
|
xmpp_free(conn->ctx, str);
|
||||||
|
xmpp_stanza_add_child(child, authdata);
|
||||||
|
xmpp_stanza_release(authdata);
|
||||||
|
|
||||||
|
child = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!child)
|
||||||
|
goto err_free;
|
||||||
|
xmpp_stanza_set_name(child, "password");
|
||||||
|
xmpp_stanza_add_child(query, child);
|
||||||
|
xmpp_stanza_release(child);
|
||||||
|
|
||||||
|
authdata = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!authdata)
|
||||||
|
goto err_free;
|
||||||
|
xmpp_stanza_set_text(authdata, conn->pass);
|
||||||
|
xmpp_stanza_add_child(child, authdata);
|
||||||
|
xmpp_stanza_release(authdata);
|
||||||
|
|
||||||
|
child = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!child)
|
||||||
|
goto err_free;
|
||||||
|
xmpp_stanza_set_name(child, "resource");
|
||||||
|
xmpp_stanza_add_child(query, child);
|
||||||
|
xmpp_stanza_release(child);
|
||||||
|
|
||||||
|
authdata = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!authdata)
|
||||||
|
goto err_free;
|
||||||
|
str = xmpp_jid_resource(conn->ctx, conn->jid);
|
||||||
|
if (str) {
|
||||||
|
xmpp_stanza_set_text(authdata, str);
|
||||||
|
xmpp_free(conn->ctx, str);
|
||||||
|
} else {
|
||||||
|
xmpp_stanza_release(authdata);
|
||||||
|
xmpp_stanza_release(iq);
|
||||||
|
xmpp_error(conn->ctx, "auth", "Cannot authenticate without resource");
|
||||||
|
xmpp_disconnect(conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xmpp_stanza_add_child(child, authdata);
|
||||||
|
xmpp_stanza_release(authdata);
|
||||||
|
|
||||||
|
handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL);
|
||||||
|
handler_add_timed(conn, _handle_missing_legacy, LEGACY_TIMEOUT, NULL);
|
||||||
|
|
||||||
|
xmpp_send(conn, iq);
|
||||||
|
xmpp_stanza_release(iq);
|
||||||
|
return;
|
||||||
|
|
||||||
|
err_free:
|
||||||
|
xmpp_stanza_release(iq);
|
||||||
|
err:
|
||||||
|
disconnect_mem_error(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void auth_handle_component_open(xmpp_conn_t * const conn)
|
void auth_handle_component_open(xmpp_conn_t * const conn)
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ struct _xmpp_conn_t {
|
|||||||
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 */
|
||||||
|
int auth_legacy_enabled;
|
||||||
int secured; /* set when stream is secured with TLS */
|
int secured; /* set when stream is secured with TLS */
|
||||||
|
|
||||||
/* if server returns <bind/> or <session/> we must do them */
|
/* if server returns <bind/> or <session/> we must do them */
|
||||||
|
|||||||
19
src/conn.c
19
src/conn.c
@@ -140,6 +140,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx)
|
|||||||
conn->tls_trust = 0;
|
conn->tls_trust = 0;
|
||||||
conn->tls_failed = 0;
|
conn->tls_failed = 0;
|
||||||
conn->sasl_support = 0;
|
conn->sasl_support = 0;
|
||||||
|
conn->auth_legacy_enabled = 0;
|
||||||
conn->secured = 0;
|
conn->secured = 0;
|
||||||
|
|
||||||
conn->bind_required = 0;
|
conn->bind_required = 0;
|
||||||
@@ -713,7 +714,7 @@ void conn_parser_reset(xmpp_conn_t * const conn)
|
|||||||
/** Initiate termination of the connection to the XMPP server.
|
/** Initiate termination of the connection to the XMPP server.
|
||||||
* This function starts the disconnection sequence by sending
|
* This function starts the disconnection sequence by sending
|
||||||
* </stream:stream> to the XMPP server. This function will do nothing
|
* </stream:stream> to the XMPP server. This function will do nothing
|
||||||
* if the connection state is CONNECTING or CONNECTED.
|
* if the connection state is different from CONNECTING or CONNECTED.
|
||||||
*
|
*
|
||||||
* @param conn a Strophe connection object
|
* @param conn a Strophe connection object
|
||||||
*
|
*
|
||||||
@@ -755,10 +756,10 @@ void xmpp_send_raw_string(xmpp_conn_t * const conn,
|
|||||||
char *bigbuf;
|
char *bigbuf;
|
||||||
|
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
len = xmpp_vsnprintf(buf, 1024, fmt, ap);
|
len = xmpp_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if (len >= 1024) {
|
if (len >= sizeof(buf)) {
|
||||||
/* we need more space for this data, so we allocate a big
|
/* we need more space for this data, so we allocate a big
|
||||||
* enough buffer and print to that */
|
* enough buffer and print to that */
|
||||||
len++; /* account for trailing \0 */
|
len++; /* account for trailing \0 */
|
||||||
@@ -779,7 +780,6 @@ void xmpp_send_raw_string(xmpp_conn_t * const conn,
|
|||||||
xmpp_free(conn->ctx, bigbuf);
|
xmpp_free(conn->ctx, bigbuf);
|
||||||
} else {
|
} else {
|
||||||
xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
|
xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
|
||||||
|
|
||||||
xmpp_send_raw(conn, buf, len);
|
xmpp_send_raw(conn, buf, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -844,10 +844,9 @@ void xmpp_send(xmpp_conn_t * const conn,
|
|||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t len;
|
size_t len;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (conn->state == XMPP_STATE_CONNECTED) {
|
if (conn->state == XMPP_STATE_CONNECTED) {
|
||||||
if ((ret = xmpp_stanza_to_text(stanza, &buf, &len)) == 0) {
|
if (xmpp_stanza_to_text(stanza, &buf, &len) == 0) {
|
||||||
xmpp_send_raw(conn, buf, len);
|
xmpp_send_raw(conn, buf, len);
|
||||||
xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
|
xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
|
||||||
xmpp_free(conn->ctx, buf);
|
xmpp_free(conn->ctx, buf);
|
||||||
@@ -922,7 +921,8 @@ long xmpp_conn_get_flags(const xmpp_conn_t * const conn)
|
|||||||
flags = XMPP_CONN_FLAG_DISABLE_TLS * conn->tls_disabled |
|
flags = XMPP_CONN_FLAG_DISABLE_TLS * conn->tls_disabled |
|
||||||
XMPP_CONN_FLAG_MANDATORY_TLS * conn->tls_mandatory |
|
XMPP_CONN_FLAG_MANDATORY_TLS * conn->tls_mandatory |
|
||||||
XMPP_CONN_FLAG_LEGACY_SSL * conn->tls_legacy_ssl |
|
XMPP_CONN_FLAG_LEGACY_SSL * conn->tls_legacy_ssl |
|
||||||
XMPP_CONN_FLAG_TRUST_TLS * conn->tls_trust;
|
XMPP_CONN_FLAG_TRUST_TLS * conn->tls_trust |
|
||||||
|
XMPP_CONN_FLAG_LEGACY_AUTH * conn->auth_legacy_enabled;;
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
@@ -940,6 +940,7 @@ long xmpp_conn_get_flags(const xmpp_conn_t * const conn)
|
|||||||
* - XMPP_CONN_FLAG_MANDATORY_TLS
|
* - XMPP_CONN_FLAG_MANDATORY_TLS
|
||||||
* - XMPP_CONN_FLAG_LEGACY_SSL
|
* - XMPP_CONN_FLAG_LEGACY_SSL
|
||||||
* - XMPP_CONN_FLAG_TRUST_TLS
|
* - XMPP_CONN_FLAG_TRUST_TLS
|
||||||
|
* - XMPP_CONN_FLAG_LEGACY_AUTH
|
||||||
*
|
*
|
||||||
* @param conn a Strophe connection object
|
* @param conn a Strophe connection object
|
||||||
* @param flags ORed connection flags
|
* @param flags ORed connection flags
|
||||||
@@ -966,6 +967,7 @@ int xmpp_conn_set_flags(xmpp_conn_t * const conn, long flags)
|
|||||||
conn->tls_mandatory = (flags & XMPP_CONN_FLAG_MANDATORY_TLS) ? 1 : 0;
|
conn->tls_mandatory = (flags & XMPP_CONN_FLAG_MANDATORY_TLS) ? 1 : 0;
|
||||||
conn->tls_legacy_ssl = (flags & XMPP_CONN_FLAG_LEGACY_SSL) ? 1 : 0;
|
conn->tls_legacy_ssl = (flags & XMPP_CONN_FLAG_LEGACY_SSL) ? 1 : 0;
|
||||||
conn->tls_trust = (flags & XMPP_CONN_FLAG_TRUST_TLS) ? 1 : 0;
|
conn->tls_trust = (flags & XMPP_CONN_FLAG_TRUST_TLS) ? 1 : 0;
|
||||||
|
conn->auth_legacy_enabled = (flags & XMPP_CONN_FLAG_LEGACY_AUTH) ? 1 : 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1211,6 +1213,9 @@ static void _conn_reset(xmpp_conn_t * const conn)
|
|||||||
xmpp_free(ctx, tsq->data);
|
xmpp_free(ctx, tsq->data);
|
||||||
xmpp_free(ctx, tsq);
|
xmpp_free(ctx, tsq);
|
||||||
}
|
}
|
||||||
|
conn->send_queue_head = NULL;
|
||||||
|
conn->send_queue_tail = NULL;
|
||||||
|
conn->send_queue_len = 0;
|
||||||
|
|
||||||
if (conn->stream_error) {
|
if (conn->stream_error) {
|
||||||
xmpp_stanza_release(conn->stream_error->stanza);
|
xmpp_stanza_release(conn->stream_error->stanza);
|
||||||
|
|||||||
@@ -163,6 +163,8 @@ int hash_add(hash_t *table, const char * const key, void *data)
|
|||||||
entry->next = table->entries[table_index];
|
entry->next = table->entries[table_index];
|
||||||
table->entries[table_index] = entry;
|
table->entries[table_index] = entry;
|
||||||
table->num_keys++;
|
table->num_keys++;
|
||||||
|
} else {
|
||||||
|
if (table->free) table->free(ctx, entry->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->value = data;
|
entry->value = data;
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ static void _start_element(void *userdata,
|
|||||||
if (parser->depth == 0) {
|
if (parser->depth == 0) {
|
||||||
/* notify the owner */
|
/* notify the owner */
|
||||||
if (parser->startcb)
|
if (parser->startcb)
|
||||||
parser->startcb((char *)name, (char **)attrs,
|
parser->startcb(name, (char **)attrs,
|
||||||
parser->userdata);
|
parser->userdata);
|
||||||
} else {
|
} else {
|
||||||
/* build stanzas at depth 1 */
|
/* build stanzas at depth 1 */
|
||||||
|
|||||||
@@ -127,9 +127,11 @@ static void Hash_DRBG_Instantiate(Hash_DRBG_CTX *ctx,
|
|||||||
|
|
||||||
assert(entropy_input_len <= ENTROPY_MAX);
|
assert(entropy_input_len <= ENTROPY_MAX);
|
||||||
assert(nonce_len <= NONCE_MAX);
|
assert(nonce_len <= NONCE_MAX);
|
||||||
|
assert(nonce != NULL || nonce_len == 0);
|
||||||
|
|
||||||
memcpy(seed_material, entropy_input, entropy_input_len);
|
memcpy(seed_material, entropy_input, entropy_input_len);
|
||||||
memcpy(seed_material + entropy_input_len, nonce, nonce_len);
|
if (nonce != NULL)
|
||||||
|
memcpy(seed_material + entropy_input_len, nonce, nonce_len);
|
||||||
Hash_df(seed_material, entropy_input_len + nonce_len, seed, seedlen);
|
Hash_df(seed_material, entropy_input_len + nonce_len, seed, seedlen);
|
||||||
seed0[0] = 0;
|
seed0[0] = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ xmpp_rand_t *xmpp_rand_new(xmpp_ctx_t *ctx);
|
|||||||
*/
|
*/
|
||||||
void xmpp_rand_free(xmpp_ctx_t *ctx, xmpp_rand_t *rand);
|
void xmpp_rand_free(xmpp_ctx_t *ctx, xmpp_rand_t *rand);
|
||||||
|
|
||||||
/** Generate random integer
|
/** Generate random integer.
|
||||||
* Analogue of rand(3).
|
* Analogue of rand(3).
|
||||||
*
|
*
|
||||||
* @ingroup Random
|
* @ingroup Random
|
||||||
|
|||||||
30
src/stanza.c
30
src/stanza.c
@@ -344,10 +344,16 @@ static int _render_stanza_recursive(xmpp_stanza_t *stanza,
|
|||||||
}
|
}
|
||||||
tmp = _escape_xml(stanza->ctx,
|
tmp = _escape_xml(stanza->ctx,
|
||||||
(char *)hash_get(stanza->attributes, key));
|
(char *)hash_get(stanza->attributes, key));
|
||||||
if (tmp == NULL) return XMPP_EMEM;
|
if (tmp == NULL) {
|
||||||
|
hash_iter_release(iter);
|
||||||
|
return XMPP_EMEM;
|
||||||
|
}
|
||||||
ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp);
|
ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp);
|
||||||
xmpp_free(stanza->ctx, tmp);
|
xmpp_free(stanza->ctx, tmp);
|
||||||
if (ret < 0) return XMPP_EMEM;
|
if (ret < 0) {
|
||||||
|
hash_iter_release(iter);
|
||||||
|
return XMPP_EMEM;
|
||||||
|
}
|
||||||
_render_update(&written, buflen, ret, &left, &ptr);
|
_render_update(&written, buflen, ret, &left, &ptr);
|
||||||
}
|
}
|
||||||
hash_iter_release(iter);
|
hash_iter_release(iter);
|
||||||
@@ -421,7 +427,12 @@ int xmpp_stanza_to_text(xmpp_stanza_t *stanza,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = _render_stanza_recursive(stanza, buffer, length);
|
ret = _render_stanza_recursive(stanza, buffer, length);
|
||||||
if (ret < 0) return ret;
|
if (ret < 0) {
|
||||||
|
xmpp_free(stanza->ctx, buffer);
|
||||||
|
*buf = NULL;
|
||||||
|
*buflen = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if ((size_t)ret > length - 1) {
|
if ((size_t)ret > length - 1) {
|
||||||
tmp = xmpp_realloc(stanza->ctx, buffer, ret + 1);
|
tmp = xmpp_realloc(stanza->ctx, buffer, ret + 1);
|
||||||
@@ -435,7 +446,12 @@ int xmpp_stanza_to_text(xmpp_stanza_t *stanza,
|
|||||||
buffer = tmp;
|
buffer = tmp;
|
||||||
|
|
||||||
ret = _render_stanza_recursive(stanza, buffer, length);
|
ret = _render_stanza_recursive(stanza, buffer, length);
|
||||||
if ((size_t)ret > length - 1) return XMPP_EMEM;
|
if ((size_t)ret > length - 1) {
|
||||||
|
xmpp_free(stanza->ctx, buffer);
|
||||||
|
*buf = NULL;
|
||||||
|
*buflen = 0;
|
||||||
|
return XMPP_EMEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[length - 1] = 0;
|
buffer[length - 1] = 0;
|
||||||
@@ -573,7 +589,6 @@ int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
|
|||||||
|
|
||||||
val = xmpp_strdup(stanza->ctx, value);
|
val = xmpp_strdup(stanza->ctx, value);
|
||||||
if (!val) {
|
if (!val) {
|
||||||
hash_release(stanza->attributes);
|
|
||||||
return XMPP_EMEM;
|
return XMPP_EMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,10 +824,11 @@ xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t * const stanza,
|
|||||||
const char * const ns)
|
const char * const ns)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *child;
|
xmpp_stanza_t *child;
|
||||||
|
const char *child_ns;
|
||||||
|
|
||||||
for (child = stanza->children; child; child = child->next) {
|
for (child = stanza->children; child; child = child->next) {
|
||||||
if (xmpp_stanza_get_ns(child) &&
|
child_ns = xmpp_stanza_get_ns(child);
|
||||||
strcmp(ns, xmpp_stanza_get_ns(child)) == 0)
|
if (child_ns && strcmp(ns, child_ns) == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ enum {
|
|||||||
static void _tls_sock_wait(tls_t *tls, int error);
|
static void _tls_sock_wait(tls_t *tls, int error);
|
||||||
static void _tls_set_error(tls_t *tls, int error);
|
static void _tls_set_error(tls_t *tls, int error);
|
||||||
static void _tls_log_error(xmpp_ctx_t *ctx);
|
static void _tls_log_error(xmpp_ctx_t *ctx);
|
||||||
|
static void _tls_dump_cert_info(tls_t *tls);
|
||||||
|
|
||||||
void tls_initialize(void)
|
void tls_initialize(void)
|
||||||
{
|
{
|
||||||
@@ -188,6 +189,7 @@ int tls_start(tls_t *tls)
|
|||||||
x509_res = SSL_get_verify_result(tls->ssl);
|
x509_res = SSL_get_verify_result(tls->ssl);
|
||||||
xmpp_debug(tls->ctx, "tls", "Certificate verification %s",
|
xmpp_debug(tls->ctx, "tls", "Certificate verification %s",
|
||||||
x509_res == X509_V_OK ? "passed" : "FAILED");
|
x509_res == X509_V_OK ? "passed" : "FAILED");
|
||||||
|
_tls_dump_cert_info(tls);
|
||||||
|
|
||||||
_tls_set_error(tls, error);
|
_tls_set_error(tls, error);
|
||||||
return ret <= 0 ? 0 : 1;
|
return ret <= 0 ? 0 : 1;
|
||||||
@@ -199,6 +201,11 @@ int tls_stop(tls_t *tls)
|
|||||||
int error;
|
int error;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* According to OpenSSL.org, we must not call SSL_shutdown(3)
|
||||||
|
if a previous fatal error has occurred on a connection. */
|
||||||
|
if (tls->lasterror == SSL_ERROR_SYSCALL || tls->lasterror == SSL_ERROR_SSL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
++retries;
|
++retries;
|
||||||
ret = SSL_shutdown(tls->ssl);
|
ret = SSL_shutdown(tls->ssl);
|
||||||
@@ -307,3 +314,26 @@ static void _tls_log_error(xmpp_ctx_t *ctx)
|
|||||||
}
|
}
|
||||||
} while (e != 0);
|
} while (e != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _tls_dump_cert_info(tls_t *tls)
|
||||||
|
{
|
||||||
|
X509 *cert;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
cert = SSL_get_peer_certificate(tls->ssl);
|
||||||
|
if (cert == NULL)
|
||||||
|
xmpp_debug(tls->ctx, "tls", "Certificate was not presented by peer");
|
||||||
|
else {
|
||||||
|
name = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
|
||||||
|
if (name != NULL) {
|
||||||
|
xmpp_debug(tls->ctx, "tls", "Subject=%s", name);
|
||||||
|
OPENSSL_free(name);
|
||||||
|
}
|
||||||
|
name = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
|
||||||
|
if (name != NULL) {
|
||||||
|
xmpp_debug(tls->ctx, "tls", "Issuer=%s", name);
|
||||||
|
OPENSSL_free(name);
|
||||||
|
}
|
||||||
|
X509_free(cert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -169,6 +169,10 @@ typedef struct _xmpp_stanza_t xmpp_stanza_t;
|
|||||||
* Trust server's certificate even if it is invalid.
|
* Trust server's certificate even if it is invalid.
|
||||||
*/
|
*/
|
||||||
#define XMPP_CONN_FLAG_TRUST_TLS (1UL << 3)
|
#define XMPP_CONN_FLAG_TRUST_TLS (1UL << 3)
|
||||||
|
/** @def XMPP_CONN_FLAG_LEGACY_AUTH
|
||||||
|
* Enable legacy authentication support.
|
||||||
|
*/
|
||||||
|
#define XMPP_CONN_FLAG_LEGACY_AUTH (1UL << 4)
|
||||||
|
|
||||||
/* connect callback */
|
/* connect callback */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -16,18 +16,19 @@
|
|||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
#define TABLESIZE 100
|
#define TABLESIZE 100
|
||||||
#define TESTSIZE 500
|
#define TESTSIZE 500
|
||||||
|
|
||||||
/* static test data */
|
/* static test data */
|
||||||
const int nkeys = 5;
|
|
||||||
const char *keys[] = {
|
const char *keys[] = {
|
||||||
"foo", "bar", "baz", "quux", "xyzzy"
|
"foo", "bar", "baz", "quux", "xyzzy"
|
||||||
};
|
};
|
||||||
const char *values[] = {
|
const char *values[] = {
|
||||||
"wuzzle", "mug", "canonical", "rosebud", "lottery"
|
"wuzzle", "mug", "canonical", "rosebud", "lottery"
|
||||||
};
|
};
|
||||||
|
const int nkeys = ARRAY_SIZE(keys);
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -58,7 +59,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* allocate a hash table */
|
/* allocate a hash table */
|
||||||
table = hash_new(ctx, TABLESIZE, NULL);
|
table = hash_new(ctx, TABLESIZE, xmpp_free);
|
||||||
if (table == NULL) {
|
if (table == NULL) {
|
||||||
/* table allocation failed! */
|
/* table allocation failed! */
|
||||||
return 1;
|
return 1;
|
||||||
@@ -66,7 +67,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* test insertion */
|
/* test insertion */
|
||||||
for (i = 0; i < nkeys; i++) {
|
for (i = 0; i < nkeys; i++) {
|
||||||
err = hash_add(table, keys[i], (void*)values[i]);
|
err = hash_add(table, keys[i], xmpp_strdup(ctx, values[i]));
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +79,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* test replacing old values */
|
/* test replacing old values */
|
||||||
for (i = 0; i < nkeys; i++) {
|
for (i = 0; i < nkeys; i++) {
|
||||||
err = hash_add(table, keys[0], (void*)values[i]);
|
err = hash_add(table, keys[0], xmpp_strdup(ctx, values[i]));
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
if (hash_num_keys(table) != nkeys) return 1;
|
if (hash_num_keys(table) != nkeys) return 1;
|
||||||
result = hash_get(table, keys[0]);
|
result = hash_get(table, keys[0]);
|
||||||
@@ -86,7 +87,7 @@ int main(int argc, char **argv)
|
|||||||
if (strcmp(result, values[i]) != 0) return 1;
|
if (strcmp(result, values[i]) != 0) return 1;
|
||||||
}
|
}
|
||||||
/* restore value for the 1st key */
|
/* restore value for the 1st key */
|
||||||
hash_add(table, keys[0], (void*)values[0]);
|
hash_add(table, keys[0], xmpp_strdup(ctx, values[0]));
|
||||||
|
|
||||||
/* test cloning */
|
/* test cloning */
|
||||||
clone = hash_clone(table);
|
clone = hash_clone(table);
|
||||||
|
|||||||
Reference in New Issue
Block a user