2 Commits

Author SHA1 Message Date
Steffen Jaeckel
460e34552b Add option to enforce usage of SCRAM-*-PLUS variants
Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
2024-01-31 23:52:51 +01:00
Steffen Jaeckel
fac1900c3f Disable weak authentication methods per default
Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
2024-01-31 23:50:13 +01:00
21 changed files with 190 additions and 883 deletions

View File

@@ -14,8 +14,8 @@ jobs:
strategy:
matrix:
valgrind:
- { configure: '' , cflags: '', make: 'check' }
- { configure: '--enable-valgrind' , cflags: '-O2', make: 'check-valgrind' }
- { configure: '' , make: 'check' }
- { configure: '--enable-valgrind' , make: 'check-valgrind' }
options:
- { configure: '' }
- { configure: '--without-libxml2' }
@@ -35,7 +35,7 @@ jobs:
- name: Build the library
run: |
./bootstrap.sh
./configure ${{ matrix.options.configure }} ${{ matrix.valgrind.configure }} CFLAGS="-Werror -g3 ${{ matrix.valgrind.cflags }}"
./configure ${{ matrix.options.configure }} ${{ matrix.valgrind.configure }} CFLAGS="-Werror -g3"
make -j$(nproc)
- name: Run tests
run: |
@@ -50,31 +50,28 @@ jobs:
strategy:
matrix:
xssl_versions:
- { version: "master", continue: true, libressl: true }
- { version: "OPENBSD_7_5", continue: true, libressl: true }
- { version: "v3.9.2", continue: true, libressl: true }
- { version: "OPENBSD_7_4", continue: true, libressl: true }
- { version: "v3.8.4", continue: true, libressl: true }
- { version: "OPENBSD_7_3", continue: true, libressl: true }
- { version: "OPENBSD_7_2", continue: true, libressl: true }
- { version: "OPENBSD_7_1", continue: true, libressl: true }
- { version: "master", continue: true, libressl: true }
- { version: "OPENBSD_7_4", continue: true, libressl: true }
- { version: "v3.8.1", continue: true, libressl: true }
- { version: "OPENBSD_7_3", continue: true, libressl: true }
- { version: "OPENBSD_7_2", continue: true, libressl: true }
- { version: "OPENBSD_7_1", continue: true, libressl: true }
# https://github.com/libressl-portable/portable/issues/760
# - { version: "v3.5.2", continue: true, libressl: true }
- { version: "OPENBSD_7_0", continue: true, libressl: true }
- { version: "OPENBSD_7_0", continue: true, libressl: true }
# OPENBSD_7_0 is basically the "fixed v3.4.3"
# - { version: "v3.4.3", continue: true, libressl: true }
- { version: "v3.4.2", continue: true, libressl: true }
- { version: "OPENBSD_6_9", continue: true, libressl: true }
- { version: "v3.1.5", continue: true, libressl: true }
- { version: "v2.1.10", continue: true, libressl: true }
- { version: "openssl-3.0", continue: true, libressl: false }
- { version: "openssl-3.0.13", continue: false, libressl: false }
- { version: "openssl-3.1", continue: true, libressl: false }
- { version: "openssl-3.1.5", continue: false, libressl: false }
- { version: "openssl-3.2", continue: true, libressl: false }
- { version: "openssl-3.2.1", continue: false, libressl: false }
- { version: "openssl-3.3", continue: true, libressl: false }
- { version: "openssl-3.3.0", continue: false, libressl: false }
# - { version: "v3.4.3", continue: true, libressl: true }
- { version: "v3.4.2", continue: true, libressl: true }
- { version: "OPENBSD_6_9", continue: true, libressl: true }
- { version: "v3.1.5", continue: true, libressl: true }
- { version: "v2.1.10", continue: true, libressl: true }
- { version: "openssl-3.0", continue: true, libressl: false }
- { version: "openssl-3.0.10", continue: false, libressl: false }
- { version: "openssl-3.1", continue: true, libressl: false }
- { version: "openssl-3.1.2", continue: false, libressl: false }
valgrind:
- { configure: '' , make: 'check' }
- { configure: '--enable-valgrind' , make: 'check-valgrind' }
name: xSSL tests
continue-on-error: ${{ matrix.xssl_versions.continue }}
steps:
@@ -92,19 +89,11 @@ jobs:
- name: Build the library
run: |
./bootstrap.sh
PKG_CONFIG_PATH="${HOME}/xssl/lib/pkgconfig" ./configure CFLAGS="-Werror -g3" --prefix="${HOME}/xssl"
./configure ${{ matrix.valgrind.configure }} PKG_CONFIG_PATH="${HOME}/xssl/lib/pkgconfig" CFLAGS="-Werror -g3" --prefix="${HOME}/xssl"
make -j$(nproc)
- name: Run tests
run: |
LD_LIBRARY_PATH="${HOME}/xssl/lib" make -j$(nproc) check
- name: Build the library with Valgrind enabled
run: |
./bootstrap.sh
PKG_CONFIG_PATH="${HOME}/xssl/lib/pkgconfig" ./configure --enable-valgrind CFLAGS="-Werror -g3" --prefix="${HOME}/xssl"
make -j$(nproc)
- name: Run tests with Valgrind enabled
run: |
LD_LIBRARY_PATH="${HOME}/xssl/lib" make -j$(nproc) check-valgrind
make -j$(nproc) ${{ matrix.valgrind.make }}
- name: Error logs
if: ${{ failure() }}
run: |
@@ -135,11 +124,6 @@ jobs:
if: ${{ !failure() }}
run: |
cat testbuild.log
- name: Error logs
if: ${{ failure() }}
run: |
cat testbuild.log || true
cat testerr.log || true
code-style:
runs-on: ubuntu-20.04

2
.gitignore vendored
View File

@@ -46,7 +46,6 @@ examples/roster
examples/uuid
examples/vcard
testbuild*.log
testerr*.log
test-release/
test_stamp
test-suite*.log
@@ -66,7 +65,6 @@ tests/test_resolver
tests/test_sasl
tests/test_scram
tests/test_send_queue
tests/test_serialize_sm
tests/test_sha1
tests/test_sha256
tests/test_sha512

View File

@@ -1,29 +1,3 @@
0.14.0
- Add SM-state serialization mechanism (#239)
- Add support for `SCRAM-SHA-512-PLUS` (da122981)
- Add support for `SSLKEYLOGFILE` with OpenSSL (d82df127)
- Fix some issues related to Stream Management (03d43132, 4359536a)
- Fix a potential segfault (9fef4b7d)
- New API:
- xmpp_conn_set_sm_callback()
- xmpp_conn_restore_sm_state()
0.13.1
- Fix SCRAM-*-PLUS SASL mechanisms with OpenSSL and TLS < v1.3 (40f2452)
- Only signal "stream negotiation success" once (1cf09b1)
- Fix `sock_connect()` not looping over all DNS records returned if no `sockopt_cb` is set (5edc480)
- Replace usage of EBADFD, it's not in POSIX (#235)
0.13.0
- Fix connected/connecting signaling to user (#227)
- Fix wording of licensing terms (#225)
- Prepare for future changes in OpenSSL (#226)
- Improve Stream Management (#227) (#230)
- Add SCRAM-PLUS Variants (#228)
- Introduce XEP-0138 stream compression (#231)
- Deprecated the following API (#227):
- xmpp_conn_disable_tls() - replaced by a flag set by xmpp_conn_set_flags()
0.12.3
- Improve TCP-connection establishment (#221)
- Handle case where the server doesn't provide the `bind` feature (#224)
@@ -47,7 +21,7 @@
- Fix some build steps when builddir != srcdir (#208)
- Allow the user to disable build of examples (#209)
- CI builds against OpenSSL 3 (#206)
- Change the call signature of the following API (#208):
- Change the call signature of the following API:
- xmpp_conn_set_client_cert() - the PKCS#12 file has now to be passed via the `cert`
parameter. Originally it was via `key`. Currently both styles are supported,
but in a future release only passing via `cert` will be accepted.

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = Strophe
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 0.14
PROJECT_NUMBER = 0.12
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@@ -190,7 +190,6 @@ STATIC_TESTS = \
tests/test_jid \
tests/test_ctx \
tests/test_send_queue \
tests/test_serialize_sm \
tests/test_string \
tests/test_resolver
@@ -286,11 +285,6 @@ tests_test_send_queue_CFLAGS = -I$(top_srcdir)/src
tests_test_send_queue_LDADD = $(STROPHE_LIBS)
tests_test_send_queue_LDFLAGS = -static
tests_test_serialize_sm_SOURCES = tests/test_serialize_sm.c tests/test.c tests/test.h
tests_test_serialize_sm_CFLAGS = -I$(top_srcdir)/src
tests_test_serialize_sm_LDADD = $(STROPHE_LIBS)
tests_test_serialize_sm_LDFLAGS = -static
tests_test_snprintf_SOURCES = tests/test_snprintf.c
tests_test_snprintf_CFLAGS = -I$(top_srcdir)/src
@@ -333,7 +327,6 @@ dist-archives:
test-release: dist
@touch testbuild-$(PACKAGE_VERSION).log && ln -sf testbuild-$(PACKAGE_VERSION).log testbuild.log
@touch testerr-$(PACKAGE_VERSION).log && ln -sf testerr-$(PACKAGE_VERSION).log testerr.log
@mkdir -p test-release && cp $(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.* test-release && pushd test-release && \
tar xzf $(PACKAGE_TARNAME)-$(PACKAGE_VERSION).tar.gz && pushd $(PACKAGE_TARNAME)-$(PACKAGE_VERSION) && ./testbuild.sh && popd && rm -rf $(PACKAGE_TARNAME)-$(PACKAGE_VERSION) && \
echo "Success" && popd

View File

@@ -88,7 +88,7 @@ or if you have everything configured properly:
Then open `docs/html/index.html`.
An online version of the documentation of the latest release is available on https://strophe.im/libstrophe/
An online version of the documentation of the latest release is available on http://strophe.im/libstrophe/
Releases
--------

View File

@@ -1,6 +1,6 @@
m4_define([v_maj], [0])
m4_define([v_min], [14])
m4_define([v_patch], [0])
m4_define([v_min], [12])
m4_define([v_patch], [3])
m4_define([project_version], [v_maj.v_min.v_patch])
m4_define([lt_cur], m4_eval(v_maj + v_min))

View File

@@ -5,7 +5,7 @@ includedir=@includedir@
Name: libstrophe
Description: A simple, lightweight C library for writing XMPP clients
URL: https://strophe.im/libstrophe/
URL: http://strophe.im/libstrophe/
Version: @VERSION@
Requires:
Requires.private: @PC_REQUIRES@

View File

@@ -799,7 +799,9 @@ static void _auth(xmpp_conn_t *conn)
conn->ctx, "auth",
"Password hasn't been set, and SASL ANONYMOUS unsupported.");
xmpp_disconnect(conn);
} else if (conn->sasl_support & SASL_MASK_SCRAM) {
} else if ((conn->sasl_support & SASL_MASK_SCRAM_PLUS) ||
((conn->sasl_support & SASL_MASK_SCRAM_WEAK) &&
!conn->only_strong_auth)) {
size_t n;
scram_ctx = strophe_alloc(conn->ctx, sizeof(*scram_ctx));
memset(scram_ctx, 0, sizeof(*scram_ctx));
@@ -857,7 +859,8 @@ static void _auth(xmpp_conn_t *conn)
/* SASL algorithm was tried, unset flag */
conn->sasl_support &= ~scram_ctx->alg->mask;
} else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
} else if ((conn->sasl_support & SASL_MASK_DIGESTMD5) &&
conn->weak_auth_enabled) {
auth = _make_sasl_auth(conn, "DIGEST-MD5");
if (!auth) {
disconnect_mem_error(conn);
@@ -871,7 +874,8 @@ static void _auth(xmpp_conn_t *conn)
/* SASL DIGEST-MD5 was tried, unset flag */
conn->sasl_support &= ~SASL_MASK_DIGESTMD5;
} else if (conn->sasl_support & SASL_MASK_PLAIN) {
} else if ((conn->sasl_support & SASL_MASK_PLAIN) &&
conn->weak_auth_enabled) {
auth = _make_sasl_auth(conn, "PLAIN");
if (!auth) {
disconnect_mem_error(conn);
@@ -1095,19 +1099,21 @@ static int _handle_features_compress(xmpp_conn_t *conn,
static int
_handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
{
xmpp_stanza_t *bind, *session;
xmpp_stanza_t *bind, *session, *opt;
xmpp_stanza_t *resume;
const char *ns;
char h[11];
UNUSED(userdata);
/* Remove missing features handler */
/* remove missing features handler */
xmpp_timed_handler_delete(conn, _handle_missing_features_sasl);
/* Check whether resource binding is required */
bind = xmpp_stanza_get_child_by_name_and_ns(stanza, "bind", XMPP_NS_BIND);
/* check whether resource binding is required */
bind = xmpp_stanza_get_child_by_name(stanza, "bind");
if (bind) {
conn->bind_required = 1;
ns = xmpp_stanza_get_ns(bind);
conn->bind_required = ns != NULL && strcmp(ns, XMPP_NS_BIND) == 0;
bind = xmpp_stanza_copy(bind);
if (!bind) {
disconnect_mem_error(conn);
@@ -1117,31 +1123,25 @@ _handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
conn->bind_required = 0;
}
/* Check whether session establishment is required.
*
* The mechanism is deprecated, but we still support it.
*
* RFC3921 contains Ch. 3 "Session Establishment".
*
* RFC6121 removes this and explains in Ch. 1.4:
* "Interoperability Note: [...] Implementation and deployment experience
* has shown that this additional step is unnecessary. [...]" */
session = xmpp_stanza_get_child_by_name_and_ns(stanza, "session",
XMPP_NS_SESSION);
/* check whether session establishment is required */
session = xmpp_stanza_get_child_by_name(stanza, "session");
if (session) {
conn->session_required =
xmpp_stanza_get_child_by_name(session, "optional") == NULL;
ns = xmpp_stanza_get_ns(session);
opt = xmpp_stanza_get_child_by_name(session, "optional");
if (!opt)
conn->session_required =
ns != NULL && strcmp(ns, XMPP_NS_SESSION) == 0;
}
/* Check stream-management support */
if (xmpp_stanza_get_child_by_name_and_ns(stanza, "sm", XMPP_NS_SM)) {
/* stream management supported */
conn->sm_state->sm_support = 1;
}
/* We are expecting either <bind/> and optionally <session/> since this is a
/* we are expecting either <bind/> and <session/> since this is a
XMPP style connection or we <resume/> the previous session */
/* Check whether we can <resume/> the previous session */
/* check whether we can <resume/> the previous session */
if (!conn->sm_disable && conn->sm_state->can_resume &&
conn->sm_state->previd && conn->sm_state->bound_jid) {
resume = xmpp_stanza_new(conn->ctx);
@@ -1188,58 +1188,11 @@ static int _handle_missing_features_sasl(xmpp_conn_t *conn, void *userdata)
return 0;
}
static void _session_start(xmpp_conn_t *conn)
{
xmpp_stanza_t *session;
xmpp_stanza_t *iq = xmpp_iq_new(conn->ctx, "set", "_xmpp_session1");
if (!iq) {
disconnect_mem_error(conn);
return;
}
session = xmpp_stanza_new(conn->ctx);
if (!session) {
xmpp_stanza_release(iq);
disconnect_mem_error(conn);
return;
}
/* setup response handlers */
handler_add_id(conn, _handle_session, "_xmpp_session1", NULL);
handler_add_timed(conn, _handle_missing_session, SESSION_TIMEOUT, NULL);
xmpp_stanza_set_name(session, "session");
xmpp_stanza_set_ns(session, XMPP_NS_SESSION);
xmpp_stanza_add_child_ex(iq, session, 0);
/* send session establishment request */
send_stanza(conn, iq, XMPP_QUEUE_STROPHE);
}
static void _sm_enable(xmpp_conn_t *conn)
{
xmpp_stanza_t *enable = xmpp_stanza_new(conn->ctx);
if (!enable) {
disconnect_mem_error(conn);
return;
}
xmpp_stanza_set_name(enable, "enable");
xmpp_stanza_set_ns(enable, XMPP_NS_SM);
if (!conn->sm_state->dont_request_resume)
xmpp_stanza_set_attribute(enable, "resume", "true");
handler_add(conn, _handle_sm, XMPP_NS_SM, NULL, NULL, NULL);
send_stanza(conn, enable, XMPP_QUEUE_SM_STROPHE);
conn->sm_state->sm_sent_nr = 0;
conn->sm_state->sm_enabled = 1;
trigger_sm_callback(conn);
}
static int
_handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
{
const char *type;
xmpp_stanza_t *binding, *jid_stanza;
xmpp_stanza_t *iq, *session, *binding, *jid_stanza, *enable = NULL;
UNUSED(userdata);
@@ -1262,19 +1215,58 @@ _handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
}
}
/* send enable directly after the bind request */
if (conn->sm_state->sm_support && !conn->sm_disable) {
enable = xmpp_stanza_new(conn->ctx);
if (!enable) {
disconnect_mem_error(conn);
return 0;
}
xmpp_stanza_set_name(enable, "enable");
xmpp_stanza_set_ns(enable, XMPP_NS_SM);
if (!conn->sm_state->dont_request_resume)
xmpp_stanza_set_attribute(enable, "resume", "true");
handler_add(conn, _handle_sm, XMPP_NS_SM, NULL, NULL, NULL);
send_stanza(conn, enable, XMPP_QUEUE_SM_STROPHE);
conn->sm_state->sm_sent_nr = 0;
conn->sm_state->sm_enabled = 1;
}
/* establish a session if required */
if (conn->session_required) {
_session_start(conn);
}
/* send enable directly after the bind request */
else if (conn->sm_state->sm_support && !conn->sm_disable) {
_sm_enable(conn);
/* setup response handlers */
handler_add_id(conn, _handle_session, "_xmpp_session1", NULL);
handler_add_timed(conn, _handle_missing_session, SESSION_TIMEOUT,
NULL);
/* send session request */
iq = xmpp_iq_new(conn->ctx, "set", "_xmpp_session1");
if (!iq) {
disconnect_mem_error(conn);
return 0;
}
session = xmpp_stanza_new(conn->ctx);
if (!session) {
xmpp_stanza_release(iq);
disconnect_mem_error(conn);
return 0;
}
xmpp_stanza_set_name(session, "session");
xmpp_stanza_set_ns(session, XMPP_NS_SESSION);
xmpp_stanza_add_child_ex(iq, session, 0);
/* send session establishment request */
send_stanza(conn, iq, XMPP_QUEUE_STROPHE);
}
/* if there's no xmpp session required and we didn't try to enable
* stream-management, we're done here and the stream-negotiation was
* successful
*/
else {
if (!conn->session_required && !enable) {
_stream_negotiation_success(conn);
}
} else {
@@ -1311,11 +1303,8 @@ _handle_session(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
xmpp_disconnect(conn);
} else if (type && strcmp(type, "result") == 0) {
strophe_debug(conn->ctx, "xmpp", "Session establishment successful.");
if (conn->sm_state->sm_support && !conn->sm_disable) {
_sm_enable(conn);
} else {
_stream_negotiation_success(conn);
}
_stream_negotiation_success(conn);
} else {
strophe_error(conn->ctx, "xmpp",
"Server sent malformed session reply.");
@@ -1487,8 +1476,6 @@ static int _handle_sm(xmpp_conn_t *const conn,
name = NULL;
}
trigger_sm_callback(conn);
err_sm:
if (!name) {
char *err = "Couldn't convert stanza to text!";

View File

@@ -175,11 +175,9 @@ struct _xmpp_send_queue_t {
#define SASL_MASK_EXTERNAL (1 << 6)
#define SASL_MASK_SCRAMSHA1_PLUS (1 << 7)
#define SASL_MASK_SCRAMSHA256_PLUS (1 << 8)
#define SASL_MASK_SCRAMSHA512_PLUS (1 << 9)
#define SASL_MASK_SCRAM_PLUS \
(SASL_MASK_SCRAMSHA1_PLUS | SASL_MASK_SCRAMSHA256_PLUS | \
SASL_MASK_SCRAMSHA512_PLUS)
#define SASL_MASK_SCRAM_PLUS \
(SASL_MASK_SCRAMSHA1_PLUS | SASL_MASK_SCRAMSHA256_PLUS)
#define SASL_MASK_SCRAM_WEAK \
(SASL_MASK_SCRAMSHA1 | SASL_MASK_SCRAMSHA256 | SASL_MASK_SCRAMSHA512)
#define SASL_MASK_SCRAM (SASL_MASK_SCRAM_PLUS | SASL_MASK_SCRAM_WEAK)
@@ -261,6 +259,8 @@ struct _xmpp_conn_t {
int sasl_support; /* if true, field is a bitfield of supported
mechanisms */
int auth_legacy_enabled;
int weak_auth_enabled;
int only_strong_auth;
int secured; /* set when stream is secured with TLS */
xmpp_certfail_handler certfail_handler;
xmpp_password_callback password_callback;
@@ -323,8 +323,6 @@ struct _xmpp_conn_t {
hash_t *id_handlers;
xmpp_handlist_t *handlers;
xmpp_sockopt_callback sockopt_cb;
xmpp_sm_callback sm_callback;
void *sm_callback_ctx;
};
void conn_disconnect(xmpp_conn_t *conn);
@@ -378,7 +376,6 @@ void handler_add(xmpp_conn_t *conn,
void handler_system_delete_all(xmpp_conn_t *conn);
/* utility functions */
void trigger_sm_callback(xmpp_conn_t *conn);
void reset_sm_state(xmpp_sm_state_t *sm_state);
void disconnect_mem_error(xmpp_conn_t *conn);

View File

@@ -63,7 +63,7 @@ static int _conn_decompress(struct xmpp_compression *comp,
break;
default:
strophe_error(comp->conn->ctx, "zlib", "inflate error %d", ret);
comp->conn->error = ret;
comp->conn->error = EBADFD;
conn_disconnect(comp->conn);
break;
}
@@ -129,7 +129,7 @@ _compression_write(xmpp_conn_t *conn, const void *buff, size_t len, int flush)
}
if (ret != Z_OK) {
strophe_error(conn->ctx, "zlib", "deflate error %d", ret);
conn->error = ret;
conn->error = EBADFD;
conn_disconnect(conn);
return ret;
}
@@ -227,22 +227,22 @@ int compression_init(xmpp_conn_t *conn)
comp->compression.stream.next_out = comp->compression.buffer;
comp->compression.stream.avail_out = STROPHE_COMPRESSION_BUFFER_SIZE;
int ret = deflateInit(&comp->compression.stream, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK) {
int err = deflateInit(&comp->compression.stream, Z_DEFAULT_COMPRESSION);
if (err != Z_OK) {
strophe_free_and_null(conn->ctx, comp->compression.buffer);
conn->error = ret;
conn->error = EBADFD;
conn_disconnect(conn);
return ret;
return err;
}
_init_zlib_compression(conn->ctx, &comp->decompression);
ret = inflateInit(&comp->decompression.stream);
if (ret != Z_OK) {
err = inflateInit(&comp->decompression.stream);
if (err != Z_OK) {
strophe_free_and_null(conn->ctx, comp->decompression.buffer);
conn->error = ret;
conn->error = EBADFD;
conn_disconnect(conn);
return ret;
return err;
}
return 0;
}

View File

@@ -21,7 +21,6 @@
*/
#include <errno.h>
#include <netinet/in.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
@@ -1093,7 +1092,6 @@ int conn_tls_start(xmpp_conn_t *conn)
}
if (conn->tls != NULL) {
struct conn_interface old_intf = conn->intf;
conn->intf = tls_intf;
conn->intf.conn = conn;
if (tls_start(conn->tls)) {
@@ -1104,7 +1102,6 @@ int conn_tls_start(xmpp_conn_t *conn)
tls_free(conn->tls);
conn->tls = NULL;
conn->tls_failed = 1;
conn->intf = old_intf;
}
}
if (rc != 0) {
@@ -1136,6 +1133,8 @@ long xmpp_conn_get_flags(const xmpp_conn_t *conn)
XMPP_CONN_FLAG_DISABLE_SM * conn->sm_disable |
XMPP_CONN_FLAG_ENABLE_COMPRESSION * conn->compression.allowed |
XMPP_CONN_FLAG_COMPRESSION_DONT_RESET * conn->compression.dont_reset |
XMPP_CONN_FLAG_WEAK_AUTH * conn->weak_auth_enabled |
XMPP_CONN_FLAG_STRONG_AUTH * conn->only_strong_auth |
XMPP_CONN_FLAG_LEGACY_AUTH * conn->auth_legacy_enabled;
return flags;
@@ -1150,14 +1149,14 @@ long xmpp_conn_get_flags(const xmpp_conn_t *conn)
*
* Supported flags are:
*
* - \ref XMPP_CONN_FLAG_DISABLE_TLS
* - \ref XMPP_CONN_FLAG_MANDATORY_TLS
* - \ref XMPP_CONN_FLAG_LEGACY_SSL
* - \ref XMPP_CONN_FLAG_TRUST_TLS
* - \ref XMPP_CONN_FLAG_LEGACY_AUTH
* - \ref XMPP_CONN_FLAG_DISABLE_SM
* - \ref XMPP_CONN_FLAG_ENABLE_COMPRESSION
* - \ref XMPP_CONN_FLAG_COMPRESSION_DONT_RESET
* - XMPP_CONN_FLAG_DISABLE_TLS
* - XMPP_CONN_FLAG_MANDATORY_TLS
* - XMPP_CONN_FLAG_LEGACY_SSL
* - XMPP_CONN_FLAG_TRUST_TLS
* - XMPP_CONN_FLAG_LEGACY_AUTH
* - XMPP_CONN_FLAG_DISABLE_SM
* - XMPP_CONN_FLAG_ENABLE_COMPRESSION
* - XMPP_CONN_FLAG_COMPRESSION_DONT_RESET
*
* @param conn a Strophe connection object
* @param flags ORed connection flags
@@ -1191,11 +1190,14 @@ int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags)
(flags & XMPP_CONN_FLAG_ENABLE_COMPRESSION) ? 1 : 0;
conn->compression.dont_reset =
(flags & XMPP_CONN_FLAG_COMPRESSION_DONT_RESET) ? 1 : 0;
conn->weak_auth_enabled = (flags & XMPP_CONN_FLAG_WEAK_AUTH) ? 1 : 0;
conn->only_strong_auth = (flags & XMPP_CONN_FLAG_STRONG_AUTH) ? 1 : 0;
flags &= ~(XMPP_CONN_FLAG_DISABLE_TLS | XMPP_CONN_FLAG_MANDATORY_TLS |
XMPP_CONN_FLAG_LEGACY_SSL | XMPP_CONN_FLAG_TRUST_TLS |
XMPP_CONN_FLAG_LEGACY_AUTH | XMPP_CONN_FLAG_DISABLE_SM |
XMPP_CONN_FLAG_ENABLE_COMPRESSION |
XMPP_CONN_FLAG_COMPRESSION_DONT_RESET);
XMPP_CONN_FLAG_COMPRESSION_DONT_RESET |
XMPP_CONN_FLAG_WEAK_AUTH | XMPP_CONN_FLAG_STRONG_AUTH);
if (flags) {
strophe_error(conn->ctx, "conn", "Flags 0x%04lx unknown", flags);
return XMPP_EINVOP;
@@ -1254,365 +1256,6 @@ int xmpp_conn_is_disconnected(xmpp_conn_t *conn)
return conn->state == XMPP_STATE_DISCONNECTED;
}
/**
* This sets the Stream Management callback function
*
* After setting this API, the library will call the given callback function
* each time when the internal SM state is updated.
*
* This can be used in conjunction with \ref xmpp_conn_restore_sm_state to
* e.g. implement a mechanism that retains an SM state over potential
* application terminations.
*
* @param conn a Strophe connection object
* @param cb a callback function or NULL to disable
* @param ctx a context that will be passed on invocation of the callback
* function
*
* @ingroup Connections
*/
void xmpp_conn_set_sm_callback(xmpp_conn_t *conn,
xmpp_sm_callback cb,
void *ctx)
{
conn->sm_callback = cb;
conn->sm_callback_ctx = ctx;
}
struct sm_restore {
xmpp_conn_t *conn;
const unsigned char *state;
const unsigned char *const state_end, *const orig;
};
static int sm_load_u32(struct sm_restore *sm, uint8_t type, uint32_t *val)
{
if (*sm->state != type) {
strophe_error(
sm->conn->ctx, "conn",
"Invalid CBOR type at position %u: 0x%02x, expected: 0x%02x",
sm->state - sm->orig, *sm->state, type);
return XMPP_EINVOP;
}
sm->state++;
if ((sm->state + 4) > sm->state_end) {
strophe_error(sm->conn->ctx, "conn",
"Provided sm_state data is too short");
return XMPP_EINVOP;
}
uint32_t v;
memcpy(&v, sm->state, 4);
sm->state += 4;
*val = ntohl(v);
return 0;
}
static int sm_load_string(struct sm_restore *sm, char **val, size_t *len)
{
uint32_t l;
int ret = sm_load_u32(sm, 0x7a, &l);
if (ret)
return ret;
if ((sm->state + l) > sm->state_end) {
strophe_error(sm->conn->ctx, "conn",
"Provided sm_state data is too short");
return XMPP_EINVOP;
}
*val = strophe_alloc(sm->conn->ctx, l + 1);
if (!*val)
return XMPP_EMEM;
memcpy(*val, sm->state, l);
(*val)[l] = '\0';
sm->state += l;
*len = l;
return 0;
}
/**
* This restores the serialized Stream Management state
*
* After setting this API, the library will call the given callback function
* each time when the internal SM state is updated.
*
* This can be used in conjunction with \ref xmpp_conn_restore_sm_state to
* e.g. implement a mechanism that retains an SM state over potential
* application terminations.
*
* @param conn a Strophe connection object
* @param sm_state a buffer as passed to the SM callback
* @param sm_state_len the length of `sm_state`
*
* @ingroup Connections
*/
int xmpp_conn_restore_sm_state(xmpp_conn_t *conn,
const unsigned char *sm_state,
size_t sm_state_len)
{
/* We can only set the SM state when we're disconnected */
if (conn->state != XMPP_STATE_DISCONNECTED) {
strophe_error(conn->ctx, "conn",
"SM state can only be set the when we're disconnected");
return XMPP_EINVOP;
}
if (conn->sm_state) {
strophe_error(conn->ctx, "conn", "SM state is already set!");
return XMPP_EINVOP;
}
if (sm_state_len < 5 * 6) {
strophe_error(conn->ctx, "conn", "Provided sm_state data is too short");
return XMPP_EINVOP;
}
struct sm_restore sm = {.conn = conn,
.state = sm_state,
.state_end = sm_state + sm_state_len,
.orig = sm_state};
/* Check for pointer wrap-around, which should never happen */
if (sm.state_end < sm.state) {
strophe_error(conn->ctx, "conn",
"Internal error, pointer wrapped around");
return XMPP_EINVOP;
}
if (memcmp(sm.state, "\x1a\x00\x00\x00\x00", 5) != 0) {
strophe_error(conn->ctx, "conn", "Unknown sm_state version");
return XMPP_EINVOP;
}
sm.state += 5;
conn->sm_state = strophe_alloc(conn->ctx, sizeof(*conn->sm_state));
if (!conn->sm_state)
return XMPP_EMEM;
memset(conn->sm_state, 0, sizeof(*conn->sm_state));
conn->sm_state->ctx = conn->ctx;
conn->sm_state->sm_support = 1;
conn->sm_state->sm_enabled = 1;
conn->sm_state->can_resume = 1;
conn->sm_state->resume = 1;
int ret;
ret = sm_load_u32(&sm, 0x1a, &conn->sm_state->sm_sent_nr);
if (ret)
goto err_reload;
ret = sm_load_u32(&sm, 0x1a, &conn->sm_state->sm_handled_nr);
if (ret)
goto err_reload;
size_t id_len;
ret = sm_load_string(&sm, &conn->sm_state->id, &id_len);
if (ret)
goto err_reload;
uint32_t len, i;
ret = sm_load_u32(&sm, 0x9a, &len);
if (ret)
goto err_reload;
conn->send_queue_user_len = conn->send_queue_len = len;
for (i = 0; i < len; i++) {
xmpp_send_queue_t *item = strophe_alloc(conn->ctx, sizeof(*item));
if (!item) {
ret = XMPP_EMEM;
goto err_reload;
}
memset(item, 0, sizeof(*item));
if (!conn->send_queue_tail) {
conn->send_queue_head = item;
conn->send_queue_tail = item;
} else {
conn->send_queue_tail->next = item;
conn->send_queue_tail = item;
}
ret = sm_load_string(&sm, &item->data, &item->len);
if (ret)
goto err_reload;
item->owner = XMPP_QUEUE_USER;
}
ret = sm_load_u32(&sm, 0xba, &len);
if (ret)
goto err_reload;
for (i = 0; i < len; i++) {
xmpp_send_queue_t *item = strophe_alloc(conn->ctx, sizeof(*item));
if (!item) {
ret = XMPP_EMEM;
goto err_reload;
}
memset(item, 0, sizeof(*item));
add_queue_back(&conn->sm_state->sm_queue, item);
ret = sm_load_u32(&sm, 0x1a, &item->sm_h);
if (ret)
goto err_reload;
ret = sm_load_string(&sm, &item->data, &item->len);
if (ret)
goto err_reload;
item->owner = XMPP_QUEUE_USER;
}
return XMPP_EOK;
err_reload:
xmpp_free_sm_state(conn->sm_state);
return ret;
}
static int sm_store_u32(unsigned char **next_,
const unsigned char *const end,
uint8_t type,
uint32_t val)
{
unsigned char *next = *next_;
if (next + 5 > end)
return 1;
*next++ = type;
uint32_t v = htonl(val);
memcpy(next, &v, 4);
next += 4;
*next_ = next;
return 0;
}
static size_t sm_state_serialize(xmpp_conn_t *conn, unsigned char **buf)
{
if (!conn->sm_state->sm_support || !conn->sm_state->sm_enabled ||
!conn->sm_state->can_resume) {
*buf = NULL;
return 0;
}
uint32_t id_len = strlen(conn->sm_state->id);
xmpp_send_queue_t *peek = conn->sm_state->sm_queue.head;
size_t sm_queue_len = 0;
size_t sm_queue_size = 0;
while (peek) {
sm_queue_len++;
sm_queue_size += 10 + peek->len;
peek = peek->next;
}
uint32_t send_queue_len = 0;
size_t send_queue_size = 0;
peek = conn->send_queue_head;
while (peek) {
send_queue_len++;
send_queue_size += 5 + peek->len;
peek = peek->next;
}
size_t buf_size =
5 + 5 + 5 + 5 + id_len + 5 + send_queue_size + 5 + sm_queue_size;
*buf = strophe_alloc(conn->ctx, buf_size);
if (*buf == NULL)
return 0;
unsigned char *next = *buf;
const unsigned char *const end = next + buf_size;
/* Check for pointer wrap-around, which should never happen */
if (end < next) {
strophe_error(conn->ctx, "conn",
"Internal error, pointer wrapped around");
return 0;
}
memcpy(next, "\x1a\x00\x00\x00\x00", 5); // Version
next += 5;
if (sm_store_u32(&next, end, 0x1a, conn->sm_state->sm_sent_nr))
goto err_serialize;
if (sm_store_u32(&next, end, 0x1a, conn->sm_state->sm_handled_nr))
goto err_serialize;
if (sm_store_u32(&next, end, 0x7a, id_len))
goto err_serialize;
memcpy(next, conn->sm_state->id, id_len);
next += id_len;
if (sm_store_u32(&next, end, 0x9a, send_queue_len))
goto err_serialize;
peek = conn->send_queue_head;
while (peek) {
if (sm_store_u32(&next, end, 0x7a, (uint32_t)peek->len))
goto err_serialize;
if (next + peek->len > end)
goto err_serialize;
memcpy(next, peek->data, peek->len);
next += peek->len;
peek = peek->next;
}
if (sm_store_u32(&next, end, 0xba, sm_queue_len))
goto err_serialize;
peek = conn->sm_state->sm_queue.head;
while (peek) {
if (sm_store_u32(&next, end, 0x1a, peek->sm_h))
goto err_serialize;
if (sm_store_u32(&next, end, 0x7a, (uint32_t)peek->len))
goto err_serialize;
if (next + peek->len > end)
goto err_serialize;
memcpy(next, peek->data, peek->len);
next += peek->len;
peek = peek->next;
}
return buf_size;
err_serialize:
strophe_error(conn->ctx, "conn", "Can't serialize more data, buffer full");
strophe_free(conn->ctx, buf);
return 0;
}
void trigger_sm_callback(xmpp_conn_t *conn)
{
if (!conn || !conn->sm_callback)
return;
unsigned char *buf;
size_t size = sm_state_serialize(conn, &buf);
conn->sm_callback(conn, conn->sm_callback_ctx, buf, size);
strophe_free(conn->ctx, buf);
}
static void _reset_sm_state_for_reconnect(xmpp_conn_t *conn)
{
xmpp_sm_state_t *s = conn->sm_state;
if (s->previd) {
strophe_free(conn->ctx, s->previd);
s->previd = NULL;
}
if (s->can_resume) {
s->previd = s->id;
s->id = NULL;
s->bound_jid = conn->bound_jid;
conn->bound_jid = NULL;
} else if (s->id) {
strophe_free(conn->ctx, s->id);
s->id = NULL;
}
s->r_sent = s->sm_enabled = s->sm_support = s->resume = 0;
if (s->bind) {
xmpp_stanza_release(s->bind);
s->bind = NULL;
}
}
/**
* This returns the Stream Management state of a connection object after
* it has been disconnected.
@@ -1644,6 +1287,34 @@ xmpp_sm_state_t *xmpp_conn_get_sm_state(xmpp_conn_t *conn)
return ret;
}
static void _reset_sm_state_for_reconnect(xmpp_conn_t *conn)
{
xmpp_sm_state_t *s = conn->sm_state;
if (s->previd) {
strophe_free(conn->ctx, s->previd);
s->previd = NULL;
}
if (s->can_resume) {
s->previd = s->id;
s->id = NULL;
s->bound_jid = conn->bound_jid;
conn->bound_jid = NULL;
} else if (s->id) {
strophe_free(conn->ctx, s->id);
s->id = NULL;
}
s->r_sent = s->sm_enabled = s->sm_support = s->resume = 0;
if (s->bind) {
xmpp_stanza_release(s->bind);
s->bind = NULL;
}
}
/**
* @param conn a Strophe connection object
* @param sm_state A Stream Management state returned from a call to
@@ -1769,7 +1440,6 @@ char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn,
xmpp_queue_element_t which)
{
xmpp_send_queue_t *t;
int disconnected = conn->state == XMPP_STATE_DISCONNECTED;
/* Fast return paths */
/* empty queue */
@@ -1778,7 +1448,7 @@ char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn,
/* one element in queue */
if (conn->send_queue_head == conn->send_queue_tail) {
/* head is already sent out partially */
if (conn->send_queue_head->wip && !disconnected)
if (conn->send_queue_head->wip)
return NULL;
/* the element is no USER element */
if (conn->send_queue_head->owner != XMPP_QUEUE_USER)
@@ -1802,7 +1472,7 @@ char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn,
return NULL;
/* head is already sent out partially */
if (t == conn->send_queue_head && t->wip && !disconnected)
if (t == conn->send_queue_head && t->wip)
t = t->next;
/* search forward to find the first USER element */
@@ -1816,15 +1486,10 @@ char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn,
/* In case there exists a SM stanza that is linked to the
* one we're currently dropping, also delete that one.
*/
if (t->next && t->next->userdata == t) {
if (t->next && t->next->userdata == t)
strophe_free(conn->ctx, _drop_send_queue_element(conn, t->next));
/* reset the flag, so we restart to send `<r>` stanzas */
conn->sm_state->r_sent = 0;
}
/* Finally drop the element */
char *r = _drop_send_queue_element(conn, t);
trigger_sm_callback(conn);
return r;
return _drop_send_queue_element(conn, t);
}
/* timed handler for cleanup if normal disconnect procedure takes too long */
@@ -2018,7 +1683,6 @@ static void _handle_stream_end(char *name, void *userdata)
strophe_debug(conn->ctx, "xmpp", "RECV: </stream:stream>");
/* the session has been terminated properly, i.e. it can't be resumed */
conn->sm_state->can_resume = 0;
trigger_sm_callback(conn);
conn_disconnect_clean(conn);
}
@@ -2094,7 +1758,6 @@ static void _conn_sm_handle_stanza(xmpp_conn_t *const conn,
conn->sm_state->r_sent = 0;
}
}
trigger_sm_callback(conn);
}
static unsigned short _conn_default_port(xmpp_conn_t *conn,
@@ -2381,10 +2044,8 @@ static int _send_raw(xmpp_conn_t *conn,
strophe_debug_verbose(1, conn->ctx, "conn", "Q_ADD: %p", item);
if (!(owner & XMPP_QUEUE_SM) && conn->sm_state->sm_enabled &&
!conn->sm_state->r_sent) {
conn->sm_state->r_sent = 1;
send_raw(conn, req_ack, strlen(req_ack), XMPP_QUEUE_SM_STROPHE, item);
} else {
trigger_sm_callback(conn);
conn->sm_state->r_sent = 1;
}
return XMPP_EOK;
}

View File

@@ -174,7 +174,6 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
/* if we've sent everything update the tail */
if (!sq)
conn->send_queue_tail = NULL;
trigger_sm_callback(conn);
}
intf->flush(intf);

View File

@@ -78,23 +78,12 @@ const struct hash_alg scram_sha512 = {
(void (*)(void *, const uint8_t *, size_t))sha512_process,
(void (*)(void *, uint8_t *))sha512_done};
const struct hash_alg scram_sha512_plus = {
"SCRAM-SHA-512-PLUS",
SASL_MASK_SCRAMSHA512_PLUS,
SHA512_DIGEST_SIZE,
(void (*)(const uint8_t *, size_t, uint8_t *))sha512_hash,
(void (*)(void *))sha512_init,
(void (*)(void *, const uint8_t *, size_t))sha512_process,
(void (*)(void *, uint8_t *))sha512_done};
/* The order of this list defines the order in which the SCRAM algorithms are
* tried if the server supports them.
* Their order is derived from
* https://datatracker.ietf.org/doc/html/draft-ietf-kitten-password-storage
*/
const struct hash_alg *scram_algs[] = {
/* *1 */
&scram_sha512_plus,
/* *1 */
&scram_sha256_plus,
/* *1 */

View File

@@ -123,8 +123,7 @@ static void sock_getaddrinfo(xmpp_sock_t *xsock)
rc = getaddrinfo(xsock->srv_rr_cur->target, service, &hints,
&xsock->ainfo_list);
if (rc != 0) {
strophe_debug(xsock->ctx, "sock",
"getaddrinfo() failed with %s (%d)", gai_strerror(rc),
strophe_debug(xsock->ctx, "sock", "getaddrinfo() failed with %d",
rc);
xsock->ainfo_list = NULL;
}
@@ -208,7 +207,7 @@ sock_t sock_connect(xmpp_sock_t *xsock)
{
struct addrinfo *ainfo;
sock_t sock;
int rc;
int rc = 0;
char buf[64];
do {
@@ -229,7 +228,6 @@ sock_t sock_connect(xmpp_sock_t *xsock)
sock = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
if (sock != INVALID_SOCKET) {
rc = 0;
if (xsock->conn->sockopt_cb) {
/* Don't allow user to overwrite sockfd value. */
sock_t sock_copy = sock;
@@ -237,7 +235,7 @@ sock_t sock_connect(xmpp_sock_t *xsock)
if (rc != 0) {
strophe_debug(xsock->ctx, "sock",
"User's setsockopt callback"
" failed with %d (errno=%d)",
"failed with %d (errno=%d)",
rc, errno);
}
}

View File

@@ -51,10 +51,8 @@
#if OPENSSL_VERSION_NUMBER < 0x30000000L
#define STROPHE_ERR_func_error_string(e) ERR_func_error_string(e)
#define STROPHE_SSL_get1_peer_certificate(s) SSL_get_peer_certificate(s)
#else
#define STROPHE_ERR_func_error_string(e) ""
#define STROPHE_SSL_get1_peer_certificate(s) SSL_get1_peer_certificate(s)
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L
@@ -111,7 +109,6 @@ struct _tls {
X509 *client_cert;
void *channel_binding_data;
size_t channel_binding_size;
FILE *keylogfile;
int lasterror;
};
@@ -559,36 +556,6 @@ static int _tls_password_callback(char *buf, int size, int rwflag, void *u)
return tls_caching_password_callback(buf, size, u);
}
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
static void _keylog_cb(const SSL *ssl, const char *line)
{
xmpp_conn_t *conn = SSL_get_app_data(ssl);
fwrite(line, strlen(line), 1, conn->tls->keylogfile);
fputc('\n', conn->tls->keylogfile);
fflush(conn->tls->keylogfile);
}
#endif
static void _try_open_keylogfile(tls_t *tls)
{
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
const char *first_line = "# SSL Key logfile generated by libstrophe\n";
const char *SSLKEYLOGFILE = getenv("SSLKEYLOGFILE");
if (!SSLKEYLOGFILE || *SSLKEYLOGFILE == '\0')
return;
tls->keylogfile = fopen(SSLKEYLOGFILE, "abe");
if (!tls->keylogfile) {
strophe_warn(tls->ctx, "tls", "Could not open SSL keylog file %s",
SSLKEYLOGFILE);
return;
}
fwrite(first_line, strlen(first_line), 1, tls->keylogfile);
SSL_CTX_set_keylog_callback(tls->ssl_ctx, _keylog_cb);
#else
UNUSED(tls);
#endif
}
tls_t *tls_new(xmpp_conn_t *conn)
{
tls_t *tls = strophe_alloc(conn->ctx, sizeof(*tls));
@@ -732,8 +699,6 @@ tls_t *tls_new(xmpp_conn_t *conn)
ret = SSL_set_fd(tls->ssl, conn->sock);
if (ret <= 0)
goto err_free_ssl;
_try_open_keylogfile(tls);
}
return tls;
@@ -752,8 +717,6 @@ err:
void tls_free(tls_t *tls)
{
if (tls->keylogfile)
fclose(tls->keylogfile);
strophe_free(tls->ctx, tls->channel_binding_data);
SSL_free(tls->ssl);
X509_free(tls->client_cert);
@@ -764,7 +727,7 @@ void tls_free(tls_t *tls)
xmpp_tlscert_t *tls_peer_cert(xmpp_conn_t *conn)
{
if (conn && conn->tls && conn->tls->ssl) {
X509 *cert = STROPHE_SSL_get1_peer_certificate(conn->tls->ssl);
X509 *cert = SSL_get_peer_certificate(conn->tls->ssl);
if (cert) {
xmpp_tlscert_t *tlscert = _x509_to_tlscert(conn->ctx, cert);
X509_free(cert);
@@ -787,9 +750,8 @@ int tls_init_channel_binding(tls_t *tls,
{
const char *label = NULL;
size_t labellen = 0;
int ssl_version = SSL_version(tls->ssl);
switch (ssl_version) {
switch (SSL_version(tls->ssl)) {
case SSL3_VERSION:
*binding_prefix = "tls-unique";
*binding_prefix_len = strlen("tls-unique");
@@ -812,7 +774,7 @@ int tls_init_channel_binding(tls_t *tls,
break;
#endif
default:
strophe_error(tls->ctx, "tls", "Unsupported TLS/SSL Version: %s",
strophe_error(tls->ctx, "tls", "Unsupported TLS Version: %s",
SSL_get_version(tls->ssl));
return -1;
}
@@ -823,28 +785,11 @@ int tls_init_channel_binding(tls_t *tls,
if (!tls->channel_binding_data)
return -1;
if (ssl_version <= TLS1_2_VERSION) {
size_t len;
if (SSL_session_reused(tls->ssl)) {
len = SSL_get_peer_finished(tls->ssl, tls->channel_binding_data,
tls->channel_binding_size);
} else {
len = SSL_get_finished(tls->ssl, tls->channel_binding_data,
tls->channel_binding_size);
}
if (len != tls->channel_binding_size) {
strophe_error(tls->ctx, "tls",
"Got channel binding data of wrong size %zu", len);
return -1;
}
} else {
if (SSL_export_keying_material(tls->ssl, tls->channel_binding_data,
tls->channel_binding_size, label,
labellen, NULL, 0, 0) != 1) {
strophe_error(tls->ctx, "tls",
"Could not get channel binding data");
return -1;
}
if (SSL_export_keying_material(tls->ssl, tls->channel_binding_data,
tls->channel_binding_size, label, labellen,
NULL, 0, 0) != 1) {
strophe_error(tls->ctx, "tls", "Could not get channel binding data");
return -1;
}
return 0;
}
@@ -1036,7 +981,7 @@ static void _tls_dump_cert_info(tls_t *tls)
X509 *cert;
char *name;
cert = STROPHE_SSL_get1_peer_certificate(tls->ssl);
cert = SSL_get_peer_certificate(tls->ssl);
if (cert == NULL)
strophe_debug(tls->ctx, "tls", "Certificate was not presented by peer");
else {

View File

@@ -18,7 +18,6 @@
#define __LIBSTROPHE_STROPHE_H__
#include <stddef.h> /* size_t */
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@@ -209,6 +208,14 @@ typedef struct _xmpp_sm_t xmpp_sm_state_t;
* Only enable this flag if you know what you're doing.
*/
#define XMPP_CONN_FLAG_COMPRESSION_DONT_RESET (1UL << 7)
/** @def XMPP_CONN_FLAG_WEAK_AUTH
* Allow weak authentication methods (DIGEST-MD5 and PLAIN).
*/
#define XMPP_CONN_FLAG_WEAK_AUTH (1UL << 8)
/** @def XMPP_CONN_FLAG_STRONG_AUTH
* Only allow strong authentication methods (Only the SCRAM-*-PLUS variants).
*/
#define XMPP_CONN_FLAG_STRONG_AUTH (1UL << 9)
/* connect callback */
typedef enum {
@@ -415,38 +422,8 @@ typedef enum {
char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn,
xmpp_queue_element_t which);
int xmpp_conn_set_sm_state(xmpp_conn_t *conn, xmpp_sm_state_t *sm_state);
xmpp_sm_state_t *xmpp_conn_get_sm_state(xmpp_conn_t *conn);
/** The function which will be called when Strophe updates its internal SM
* state.
*
* Please note that you have to create a copy of the buffer, since the library
* will free the buffer right after return of the callback function.
*
*
* @param conn The Strophe connection object this callback
* originates from.
* @param ctx The `ctx` pointer as passed to
* \ref xmpp_conn_set_sm_callback
* @param sm_state A pointer to a buffer containing the serialized SM
* state.
* @param sm_state_len The length of `sm_state`.
*
* @return 0 on success, -1 on error
*
* @ingroup Connections
*/
typedef void (*xmpp_sm_callback)(xmpp_conn_t *conn,
void *ctx,
const unsigned char *sm_state,
size_t sm_state_len);
void xmpp_conn_set_sm_callback(xmpp_conn_t *conn,
xmpp_sm_callback cb,
void *ctx);
int xmpp_conn_restore_sm_state(xmpp_conn_t *conn,
const unsigned char *sm_state,
size_t sm_state_len);
int xmpp_conn_set_sm_state(xmpp_conn_t *conn, xmpp_sm_state_t *sm_state);
void xmpp_free_sm_state(xmpp_sm_state_t *sm_state);
@@ -738,18 +715,11 @@ void xmpp_rand_bytes(xmpp_rand_t *rand, unsigned char *output, size_t len);
*/
void xmpp_rand_nonce(xmpp_rand_t *rand, char *output, size_t len);
/*
/**
* Formerly "private but exported" functions made public for now to announce
* deprecation */
#include <stdarg.h>
/**
* XMPP_DEPRECATED(x) macro to show a compiler warning for deprecated API
* functions
*
* @param x The function that can be used as a replacement or 'internal' if
* there is no replacement
*/
#if defined(__GNUC__)
#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
#define XMPP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x)))

View File

@@ -1,7 +1,6 @@
#!/bin/sh
logfile="../../testbuild.log"
errfile="../../testerr.log"
err_out() {
tail $logfile
@@ -9,6 +8,6 @@ err_out() {
}
./bootstrap.sh
./configure >> $logfile 2>> $errfile || err_out
make -j$(( `nproc` * 2 + 1 )) >> $logfile 2>> $errfile || err_out
make check >> $logfile 2>> $errfile || err_out
./configure >> $logfile || err_out
make -j$(( `nproc` * 2 + 1 )) >> $logfile || err_out
make check >> $logfile || err_out

View File

@@ -1,166 +0,0 @@
/* SPDX-License-Identifier: MIT OR GPL-3.0-only */
/* test_serialize_sm.c
** libstrophe XMPP client library -- test routines for the send queue
**
** Copyright (C) 2024 Stephen Paul Weber
**
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This program is dual licensed under the MIT or GPLv3 licenses.
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "strophe.h"
#include "common.h"
#include "test.h"
void callback(xmpp_conn_t *conn,
void *ctx,
const unsigned char *sm_state,
size_t sm_state_len)
{
int *callback_count = ctx;
(*callback_count)++;
COMPARE_BUF("\x1a\x00\x00\x00\x00", 5, sm_state, 5);
COMPARE_BUF("\x1a\x00\x00\x00\x00", 5, sm_state + 10, 5);
COMPARE_BUF("\x7a\x00\x00\x00\x04SMID", 9, sm_state + 15, 9);
if (*callback_count == 1) {
COMPARE_BUF("\x1a\x00\x00\x00\x00", 5, sm_state + 5, 5);
COMPARE_BUF("\x9a\x00\x00\x00\x02", 5, sm_state + 24, 5);
COMPARE_BUF("\x7a\x00\x00\x00\x03"
"foo",
8, sm_state + 29, 8);
COMPARE_BUF("\x7a\x00\x00\x00\x1a<r xmlns='urn:xmpp:sm:3'/>", 31,
sm_state + 37, 31);
COMPARE_BUF("\xba\x00\x00\x00\x00", 5, sm_state + 68, 5);
ENSURE_EQ(sm_state_len, 73);
xmpp_conn_t *newconn = xmpp_conn_new(conn->ctx);
xmpp_conn_restore_sm_state(newconn, sm_state, sm_state_len);
ENSURE_EQ(newconn->sm_state->sm_sent_nr, 0);
ENSURE_EQ(newconn->sm_state->sm_handled_nr, 0);
COMPARE(newconn->sm_state->id, "SMID");
ENSURE_EQ(newconn->send_queue_len, 2);
ENSURE_EQ(newconn->send_queue_user_len, 2);
ENSURE_EQ((size_t)(newconn->sm_state->sm_queue.head), 0);
xmpp_conn_release(newconn);
}
if (*callback_count == 2) {
COMPARE_BUF("\x1a\x00\x00\x00\x01", 5, sm_state + 5, 5);
COMPARE_BUF("\x9a\x00\x00\x00\x01", 5, sm_state + 24, 5);
COMPARE_BUF("\x7a\x00\x00\x00\x1a<r xmlns='urn:xmpp:sm:3'/>", 31,
sm_state + 29, 31);
COMPARE_BUF("\xba\x00\x00\x00\x01", 5, sm_state + 60, 5);
COMPARE_BUF("\x1a\x00\x00\x00\x00", 5, sm_state + 65, 5);
COMPARE_BUF("\x7a\x00\x00\x00\x03"
"foo",
8, sm_state + 70, 8);
ENSURE_EQ(sm_state_len, 78);
xmpp_conn_t *newconn = xmpp_conn_new(conn->ctx);
xmpp_conn_restore_sm_state(newconn, sm_state, sm_state_len);
ENSURE_EQ(newconn->sm_state->sm_sent_nr, 1);
ENSURE_EQ(newconn->sm_state->sm_handled_nr, 0);
COMPARE(newconn->sm_state->id, "SMID");
ENSURE_EQ(newconn->send_queue_len, 1);
ENSURE_EQ(newconn->send_queue_user_len, 1);
ENSURE_EQ(newconn->sm_state->sm_queue.head->sm_h, 0);
xmpp_conn_release(newconn);
}
if (*callback_count == 3) {
COMPARE_BUF("\x1a\x00\x00\x00\x01", 5, sm_state + 5, 5);
COMPARE_BUF("\x9a\x00\x00\x00\x00", 5, sm_state + 24, 5);
COMPARE_BUF("\xba\x00\x00\x00\x01", 5, sm_state + 29, 5);
COMPARE_BUF("\x1a\x00\x00\x00\x00", 5, sm_state + 34, 5);
COMPARE_BUF("\x7a\x00\x00\x00\x03"
"foo",
8, sm_state + 39, 8);
ENSURE_EQ(sm_state_len, 47);
xmpp_conn_t *newconn = xmpp_conn_new(conn->ctx);
xmpp_conn_restore_sm_state(newconn, sm_state, sm_state_len);
ENSURE_EQ(newconn->sm_state->sm_sent_nr, 1);
ENSURE_EQ(newconn->sm_state->sm_handled_nr, 0);
COMPARE(newconn->sm_state->id, "SMID");
ENSURE_EQ(newconn->send_queue_len, 0);
ENSURE_EQ(newconn->send_queue_user_len, 0);
ENSURE_EQ(newconn->sm_state->sm_queue.head->sm_h, 0);
xmpp_conn_release(newconn);
}
}
int fake_read(struct conn_interface *intf, void *buff, size_t len)
{
return 0;
}
int fake_write(struct conn_interface *intf, const void *buff, size_t len)
{
return len;
}
int fake_flush(struct conn_interface *intf)
{
return 0;
}
int fake_error_is_recoverable(struct conn_interface *intf, int err)
{
return 0;
}
int main()
{
xmpp_ctx_t *ctx;
xmpp_conn_t *conn;
xmpp_log_t *log;
xmpp_conn_state_t state;
xmpp_sm_state_t *sm_state;
char *ret;
unsigned int n;
int callback_count = 0;
xmpp_initialize();
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
ctx = xmpp_ctx_new(NULL, log);
conn = xmpp_conn_new(ctx);
sm_state = strophe_alloc(ctx, sizeof(*sm_state));
memset(sm_state, 0, sizeof(*sm_state));
sm_state->ctx = ctx;
sm_state->sm_support = sm_state->sm_enabled = sm_state->can_resume = 1;
sm_state->id = strophe_strdup(ctx, "SMID");
xmpp_conn_set_sm_state(conn, sm_state);
xmpp_conn_set_sm_callback(conn, callback, &callback_count);
ENSURE_EQ(xmpp_conn_send_queue_len(conn), 0);
struct conn_interface intf = {fake_read, fake_write,
fake_flush, fake_flush,
fake_flush, fake_error_is_recoverable,
conn};
conn->intf = intf;
state = conn->state;
conn->state = XMPP_STATE_CONNECTED;
conn->sock = 123;
xmpp_send_raw(conn, "foo", 3);
ENSURE_EQ(xmpp_conn_send_queue_len(conn), 1);
ENSURE_EQ(callback_count, 1);
xmpp_run_once(ctx, 0);
ENSURE_EQ(callback_count, 3);
conn->state = state;
xmpp_conn_release(conn);
xmpp_ctx_free(ctx);
xmpp_shutdown();
return 0;
}

View File

@@ -7,7 +7,6 @@
#include <stdio.h>
#include <string.h>
#include <limits.h>
#undef HAVE_VSNPRINTF
#undef HAVE_SNPRINTF
@@ -29,14 +28,7 @@ int main(void)
char *int_fmt[] = {"%-1.5d", "%1.5d", "%123.9d", "%5.5d",
"%10.5d", "% 10.5d", "%+22.33d", "%01.3d",
"%4d", "0x%x", "0x%04x", NULL};
int int_nums[] = {-1, 134, 91340, 341, 0203,
0x76543210, INT_MIN, INT_MAX, 0};
char *long_fmt[] = {"%-1.5ld", "%1.5ld", "%123.9ld", "%5.5ld",
"%10.5ld", "% 10.5ld", "%+22.33ld", "%01.3ld",
"%4ld", "0x%lx", "0x%04lx", NULL};
long long_nums[] = {-1L, 134L, 91340L,
341L, 0203L, 0xFEDCBA9876543210L,
LONG_MIN, LONG_MAX, 0L};
long int_nums[] = {-1, 134, 91340, 341, 0203, 0x76543210, 0};
int x, y;
int fail = 0;
int num = 0;
@@ -68,19 +60,6 @@ int main(void)
}
num++;
}
for (x = 0; long_fmt[x] != NULL; x++)
for (y = 0; long_nums[y] != 0; y++) {
strophe_snprintf(buf1, sizeof(buf1), long_fmt[x], long_nums[y]);
sprintf(buf2, long_fmt[x], long_nums[y]);
if (strcmp(buf1, buf2)) {
printf("xmpp_snprintf doesn't match Format: "
"%s\n\txmpp_snprintf = %s\n\tsprintf = %s\n",
long_fmt[x], buf1, buf2);
fail++;
}
num++;
}
printf("%d tests failed out of %d.\n", fail, num);
return fail != 0 ? 1 : 0;
}

View File

@@ -175,7 +175,7 @@ static void test_stanza_error(xmpp_ctx_t *ctx)
xmpp_stanza_reply_error(stanza, "cancel", "service-unavailable", NULL);
assert(error != NULL);
mood = xmpp_stanza_new_from_string(ctx, str_mood);
assert(mood != NULL);
assert(stanza != NULL);
assert(xmpp_stanza_get_to(error) != NULL);
COMPARE("romeo@montague.lit/home", xmpp_stanza_get_to(error));