Compare commits
22 Commits
control-au
...
generic-se
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
541c22cb13 | ||
|
|
06f2ba19b4 | ||
|
|
5690c4ed89 | ||
|
|
62953e9ecf | ||
|
|
5142eea2eb | ||
|
|
5dd9e4b0e0 | ||
|
|
4ec4f09b35 | ||
|
|
e24819a405 | ||
|
|
d0d1fa9835 | ||
|
|
da1229814c | ||
|
|
d82df1273c | ||
|
|
9fef4b7d02 | ||
|
|
4359536a17 | ||
|
|
03d43132bc | ||
|
|
4d59a9fe45 | ||
|
|
40f2452fb0 | ||
|
|
1cf09b1870 | ||
|
|
5edc480932 | ||
|
|
641211ecae | ||
|
|
d8fd6e6d14 | ||
|
|
9410530507 | ||
|
|
d6d71e97f8 |
53
.github/workflows/main.yml
vendored
53
.github/workflows/main.yml
vendored
@@ -50,28 +50,31 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
xssl_versions:
|
xssl_versions:
|
||||||
- { version: "master", continue: true, libressl: true }
|
- { version: "master", continue: true, libressl: true }
|
||||||
- { version: "OPENBSD_7_4", continue: true, libressl: true }
|
- { version: "OPENBSD_7_5", continue: true, libressl: true }
|
||||||
- { version: "v3.8.1", continue: true, libressl: true }
|
- { version: "v3.9.2", continue: true, libressl: true }
|
||||||
- { version: "OPENBSD_7_3", continue: true, libressl: true }
|
- { version: "OPENBSD_7_4", continue: true, libressl: true }
|
||||||
- { version: "OPENBSD_7_2", continue: true, libressl: true }
|
- { version: "v3.8.4", continue: true, libressl: true }
|
||||||
- { version: "OPENBSD_7_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
|
# https://github.com/libressl-portable/portable/issues/760
|
||||||
# - { version: "v3.5.2", continue: true, libressl: true }
|
# - { 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"
|
# OPENBSD_7_0 is basically the "fixed v3.4.3"
|
||||||
# - { version: "v3.4.3", continue: true, libressl: true }
|
# - { version: "v3.4.3", continue: true, libressl: true }
|
||||||
- { version: "v3.4.2", continue: true, libressl: true }
|
- { version: "v3.4.2", continue: true, libressl: true }
|
||||||
- { version: "OPENBSD_6_9", continue: true, libressl: true }
|
- { version: "OPENBSD_6_9", continue: true, libressl: true }
|
||||||
- { version: "v3.1.5", continue: true, libressl: true }
|
- { version: "v3.1.5", continue: true, libressl: true }
|
||||||
- { version: "v2.1.10", continue: true, libressl: true }
|
- { version: "v2.1.10", continue: true, libressl: true }
|
||||||
- { version: "openssl-3.0", continue: true, libressl: false }
|
- { version: "openssl-3.0", continue: true, libressl: false }
|
||||||
- { version: "openssl-3.0.10", continue: false, libressl: false }
|
- { version: "openssl-3.0.13", continue: false, libressl: false }
|
||||||
- { version: "openssl-3.1", continue: true, libressl: false }
|
- { version: "openssl-3.1", continue: true, libressl: false }
|
||||||
- { version: "openssl-3.1.2", continue: false, libressl: false }
|
- { version: "openssl-3.1.5", continue: false, libressl: false }
|
||||||
valgrind:
|
- { version: "openssl-3.2", continue: true, libressl: false }
|
||||||
- { configure: '' , make: 'check' }
|
- { version: "openssl-3.2.1", continue: false, libressl: false }
|
||||||
- { configure: '--enable-valgrind' , make: 'check-valgrind' }
|
- { version: "openssl-3.3", continue: true, libressl: false }
|
||||||
|
- { version: "openssl-3.3.0", continue: false, libressl: false }
|
||||||
name: xSSL tests
|
name: xSSL tests
|
||||||
continue-on-error: ${{ matrix.xssl_versions.continue }}
|
continue-on-error: ${{ matrix.xssl_versions.continue }}
|
||||||
steps:
|
steps:
|
||||||
@@ -89,11 +92,19 @@ jobs:
|
|||||||
- name: Build the library
|
- name: Build the library
|
||||||
run: |
|
run: |
|
||||||
./bootstrap.sh
|
./bootstrap.sh
|
||||||
./configure ${{ matrix.valgrind.configure }} PKG_CONFIG_PATH="${HOME}/xssl/lib/pkgconfig" CFLAGS="-Werror -g3" --prefix="${HOME}/xssl"
|
PKG_CONFIG_PATH="${HOME}/xssl/lib/pkgconfig" ./configure CFLAGS="-Werror -g3" --prefix="${HOME}/xssl"
|
||||||
make -j$(nproc)
|
make -j$(nproc)
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
make -j$(nproc) ${{ matrix.valgrind.make }}
|
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
|
||||||
- name: Error logs
|
- name: Error logs
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
18
ChangeLog
18
ChangeLog
@@ -1,3 +1,19 @@
|
|||||||
|
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
|
0.12.3
|
||||||
- Improve TCP-connection establishment (#221)
|
- Improve TCP-connection establishment (#221)
|
||||||
- Handle case where the server doesn't provide the `bind` feature (#224)
|
- Handle case where the server doesn't provide the `bind` feature (#224)
|
||||||
@@ -21,7 +37,7 @@
|
|||||||
- Fix some build steps when builddir != srcdir (#208)
|
- Fix some build steps when builddir != srcdir (#208)
|
||||||
- Allow the user to disable build of examples (#209)
|
- Allow the user to disable build of examples (#209)
|
||||||
- CI builds against OpenSSL 3 (#206)
|
- CI builds against OpenSSL 3 (#206)
|
||||||
- Change the call signature of the following API:
|
- Change the call signature of the following API (#208):
|
||||||
- xmpp_conn_set_client_cert() - the PKCS#12 file has now to be passed via the `cert`
|
- 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,
|
parameter. Originally it was via `key`. Currently both styles are supported,
|
||||||
but in a future release only passing via `cert` will be accepted.
|
but in a future release only passing via `cert` will be accepted.
|
||||||
|
|||||||
2
Doxyfile
2
Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Strophe
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 0.12
|
PROJECT_NUMBER = 0.13
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# 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
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ or if you have everything configured properly:
|
|||||||
|
|
||||||
Then open `docs/html/index.html`.
|
Then open `docs/html/index.html`.
|
||||||
|
|
||||||
An online version of the documentation of the latest release is available on http://strophe.im/libstrophe/
|
An online version of the documentation of the latest release is available on https://strophe.im/libstrophe/
|
||||||
|
|
||||||
Releases
|
Releases
|
||||||
--------
|
--------
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
m4_define([v_maj], [0])
|
m4_define([v_maj], [0])
|
||||||
m4_define([v_min], [12])
|
m4_define([v_min], [13])
|
||||||
m4_define([v_patch], [3])
|
m4_define([v_patch], [1])
|
||||||
m4_define([project_version], [v_maj.v_min.v_patch])
|
m4_define([project_version], [v_maj.v_min.v_patch])
|
||||||
|
|
||||||
m4_define([lt_cur], m4_eval(v_maj + v_min))
|
m4_define([lt_cur], m4_eval(v_maj + v_min))
|
||||||
|
|||||||
@@ -115,8 +115,8 @@ int main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* setup authentication information */
|
/* setup authentication information */
|
||||||
xmpp_conn_set_jid(conn, argv[1]);
|
xmpp_conn_set_string(conn, XMPP_SETTING_JID, argv[1]);
|
||||||
xmpp_conn_set_pass(conn, argv[2]);
|
xmpp_conn_set_string(conn, XMPP_SETTING_PASS, argv[2]);
|
||||||
|
|
||||||
/* initiate connection */
|
/* initiate connection */
|
||||||
xmpp_connect_client(conn, NULL, 0, conn_handler, ctx);
|
xmpp_connect_client(conn, NULL, 0, conn_handler, ctx);
|
||||||
|
|||||||
@@ -116,9 +116,9 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* setup authentication information */
|
/* setup authentication information */
|
||||||
if (jid)
|
if (jid)
|
||||||
xmpp_conn_set_jid(conn, jid);
|
xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
|
||||||
if (password)
|
if (password)
|
||||||
xmpp_conn_set_pass(conn, password);
|
xmpp_conn_set_string(conn, XMPP_SETTING_PASS, password);
|
||||||
|
|
||||||
/* initiate connection */
|
/* initiate connection */
|
||||||
if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) {
|
if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) {
|
||||||
|
|||||||
@@ -293,20 +293,24 @@ create_connection:
|
|||||||
xmpp_conn_set_flags(conn, flags);
|
xmpp_conn_set_flags(conn, flags);
|
||||||
|
|
||||||
/* ask for a password if key is protected */
|
/* ask for a password if key is protected */
|
||||||
xmpp_conn_set_password_callback(conn, password_callback, NULL);
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_PASSWORD_CALLBACK,
|
||||||
|
password_callback);
|
||||||
/* try at max 3 times in case the user enters the password wrong */
|
/* try at max 3 times in case the user enters the password wrong */
|
||||||
xmpp_conn_set_password_retries(conn, 3);
|
xmpp_conn_set_int(conn, XMPP_SETTING_PASSWORD_RETRIES, 3);
|
||||||
/* setup authentication information */
|
/* setup authentication information */
|
||||||
if (key)
|
if (key) {
|
||||||
xmpp_conn_set_client_cert(conn, cert, key);
|
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, cert);
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_KEY, key);
|
||||||
|
}
|
||||||
if (jid)
|
if (jid)
|
||||||
xmpp_conn_set_jid(conn, jid);
|
xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
|
||||||
if (password)
|
if (password)
|
||||||
xmpp_conn_set_pass(conn, password);
|
xmpp_conn_set_string(conn, XMPP_SETTING_PASS, password);
|
||||||
|
|
||||||
/* enable TCP keepalive, using canned callback function */
|
/* enable TCP keepalive, using canned callback function */
|
||||||
if (tcp_keepalive)
|
if (tcp_keepalive)
|
||||||
xmpp_conn_set_sockopt_callback(conn, xmpp_sockopt_cb_keepalive);
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_SOCKOPT_CALLBACK,
|
||||||
|
xmpp_sockopt_cb_keepalive);
|
||||||
|
|
||||||
/* set Stream-Mangement state if available */
|
/* set Stream-Mangement state if available */
|
||||||
if (sm_state) {
|
if (sm_state) {
|
||||||
|
|||||||
@@ -331,27 +331,31 @@ int main(int argc, char **argv)
|
|||||||
xmpp_conn_set_flags(conn, flags);
|
xmpp_conn_set_flags(conn, flags);
|
||||||
/* configure TCP keepalive (optional) */
|
/* configure TCP keepalive (optional) */
|
||||||
if (tcp_keepalive)
|
if (tcp_keepalive)
|
||||||
xmpp_conn_set_sockopt_callback(conn, sockopt_cb);
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_SOCKOPT_CALLBACK,
|
||||||
|
sockopt_cb);
|
||||||
|
|
||||||
/* ask for a password if key is protected */
|
/* ask for a password if key is protected */
|
||||||
xmpp_conn_set_password_callback(conn, password_callback, NULL);
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_PASSWORD_CALLBACK,
|
||||||
|
password_callback);
|
||||||
/* try at max 3 times in case the user enters the password wrong */
|
/* try at max 3 times in case the user enters the password wrong */
|
||||||
xmpp_conn_set_password_retries(conn, 3);
|
xmpp_conn_set_int(conn, XMPP_SETTING_PASSWORD_RETRIES, 3);
|
||||||
/* setup authentication information */
|
/* setup authentication information */
|
||||||
if (key) {
|
if (key) {
|
||||||
xmpp_conn_set_client_cert(conn, cert, key);
|
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, cert);
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_KEY, key);
|
||||||
}
|
}
|
||||||
if (jid)
|
if (jid)
|
||||||
xmpp_conn_set_jid(conn, jid);
|
xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
|
||||||
if (password)
|
if (password)
|
||||||
xmpp_conn_set_pass(conn, password);
|
xmpp_conn_set_string(conn, XMPP_SETTING_PASS, password);
|
||||||
|
|
||||||
if (certfail)
|
if (certfail)
|
||||||
xmpp_conn_set_certfail_handler(conn, certfail_handler);
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_CERTFAIL_HANDLER,
|
||||||
|
certfail_handler);
|
||||||
if (capath)
|
if (capath)
|
||||||
xmpp_conn_set_capath(conn, capath);
|
xmpp_conn_set_string(conn, XMPP_SETTING_CAPATH, capath);
|
||||||
if (cafile)
|
if (cafile)
|
||||||
xmpp_conn_set_cafile(conn, cafile);
|
xmpp_conn_set_string(conn, XMPP_SETTING_CAFILE, cafile);
|
||||||
|
|
||||||
/* initiate connection */
|
/* initiate connection */
|
||||||
if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) {
|
if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) {
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ int main(int argc, char **argv)
|
|||||||
conn = xmpp_conn_new(ctx);
|
conn = xmpp_conn_new(ctx);
|
||||||
|
|
||||||
/* setup authentication information */
|
/* setup authentication information */
|
||||||
xmpp_conn_set_jid(conn, jid);
|
xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
|
||||||
xmpp_conn_set_pass(conn, pass);
|
xmpp_conn_set_string(conn, XMPP_SETTING_PASS, pass);
|
||||||
|
|
||||||
/* initiate connection */
|
/* initiate connection */
|
||||||
xmpp_connect_component(conn, host, port, conn_handler, ctx);
|
xmpp_connect_component(conn, host, port, conn_handler, ctx);
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* jid can be a jid or domain for "raw" connection */
|
/* jid can be a jid or domain for "raw" connection */
|
||||||
domain = xmpp_jid_domain(ctx, jid);
|
domain = xmpp_jid_domain(ctx, jid);
|
||||||
xmpp_conn_set_jid(conn, domain);
|
xmpp_conn_set_string(conn, XMPP_SETTING_JID, domain);
|
||||||
xmpp_free(ctx, domain);
|
xmpp_free(ctx, domain);
|
||||||
|
|
||||||
/* private data */
|
/* private data */
|
||||||
|
|||||||
@@ -118,8 +118,8 @@ int main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* setup authentication information */
|
/* setup authentication information */
|
||||||
xmpp_conn_set_jid(conn, argv[1]);
|
xmpp_conn_set_string(conn, XMPP_SETTING_JID, argv[1]);
|
||||||
xmpp_conn_set_pass(conn, argv[2]);
|
xmpp_conn_set_string(conn, XMPP_SETTING_PASS, argv[2]);
|
||||||
|
|
||||||
/* initiate connection */
|
/* initiate connection */
|
||||||
xmpp_connect_client(conn, NULL, 0, conn_handler, ctx);
|
xmpp_connect_client(conn, NULL, 0, conn_handler, ctx);
|
||||||
|
|||||||
@@ -269,8 +269,8 @@ int main(int argc, char **argv)
|
|||||||
log = xmpp_get_default_logger(XMPP_LEVEL_INFO);
|
log = xmpp_get_default_logger(XMPP_LEVEL_INFO);
|
||||||
ctx = xmpp_ctx_new(NULL, log);
|
ctx = xmpp_ctx_new(NULL, log);
|
||||||
conn = xmpp_conn_new(ctx);
|
conn = xmpp_conn_new(ctx);
|
||||||
xmpp_conn_set_jid(conn, jid);
|
xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
|
||||||
xmpp_conn_set_pass(conn, pass);
|
xmpp_conn_set_string(conn, XMPP_SETTING_PASS, pass);
|
||||||
vcard.ctx = ctx;
|
vcard.ctx = ctx;
|
||||||
xmpp_connect_client(conn, NULL, 0, conn_handler, &vcard);
|
xmpp_connect_client(conn, NULL, 0, conn_handler, &vcard);
|
||||||
xmpp_run(ctx);
|
xmpp_run(ctx);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ includedir=@includedir@
|
|||||||
|
|
||||||
Name: libstrophe
|
Name: libstrophe
|
||||||
Description: A simple, lightweight C library for writing XMPP clients
|
Description: A simple, lightweight C library for writing XMPP clients
|
||||||
URL: http://strophe.im/libstrophe/
|
URL: https://strophe.im/libstrophe/
|
||||||
Version: @VERSION@
|
Version: @VERSION@
|
||||||
Requires:
|
Requires:
|
||||||
Requires.private: @PC_REQUIRES@
|
Requires.private: @PC_REQUIRES@
|
||||||
|
|||||||
154
src/auth.c
154
src/auth.c
@@ -799,9 +799,7 @@ static void _auth(xmpp_conn_t *conn)
|
|||||||
conn->ctx, "auth",
|
conn->ctx, "auth",
|
||||||
"Password hasn't been set, and SASL ANONYMOUS unsupported.");
|
"Password hasn't been set, and SASL ANONYMOUS unsupported.");
|
||||||
xmpp_disconnect(conn);
|
xmpp_disconnect(conn);
|
||||||
} else if ((conn->sasl_support & SASL_MASK_SCRAM_PLUS) ||
|
} else if (conn->sasl_support & SASL_MASK_SCRAM) {
|
||||||
((conn->sasl_support & SASL_MASK_SCRAM_WEAK) &&
|
|
||||||
!conn->only_strong_auth)) {
|
|
||||||
size_t n;
|
size_t n;
|
||||||
scram_ctx = strophe_alloc(conn->ctx, sizeof(*scram_ctx));
|
scram_ctx = strophe_alloc(conn->ctx, sizeof(*scram_ctx));
|
||||||
memset(scram_ctx, 0, sizeof(*scram_ctx));
|
memset(scram_ctx, 0, sizeof(*scram_ctx));
|
||||||
@@ -859,8 +857,7 @@ static void _auth(xmpp_conn_t *conn)
|
|||||||
|
|
||||||
/* SASL algorithm was tried, unset flag */
|
/* SASL algorithm was tried, unset flag */
|
||||||
conn->sasl_support &= ~scram_ctx->alg->mask;
|
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");
|
auth = _make_sasl_auth(conn, "DIGEST-MD5");
|
||||||
if (!auth) {
|
if (!auth) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
@@ -874,8 +871,7 @@ static void _auth(xmpp_conn_t *conn)
|
|||||||
|
|
||||||
/* SASL DIGEST-MD5 was tried, unset flag */
|
/* SASL DIGEST-MD5 was tried, unset flag */
|
||||||
conn->sasl_support &= ~SASL_MASK_DIGESTMD5;
|
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");
|
auth = _make_sasl_auth(conn, "PLAIN");
|
||||||
if (!auth) {
|
if (!auth) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
@@ -1099,21 +1095,19 @@ static int _handle_features_compress(xmpp_conn_t *conn,
|
|||||||
static int
|
static int
|
||||||
_handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
_handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *bind, *session, *opt;
|
xmpp_stanza_t *bind, *session;
|
||||||
xmpp_stanza_t *resume;
|
xmpp_stanza_t *resume;
|
||||||
const char *ns;
|
|
||||||
char h[11];
|
char h[11];
|
||||||
|
|
||||||
UNUSED(userdata);
|
UNUSED(userdata);
|
||||||
|
|
||||||
/* remove missing features handler */
|
/* Remove missing features handler */
|
||||||
xmpp_timed_handler_delete(conn, _handle_missing_features_sasl);
|
xmpp_timed_handler_delete(conn, _handle_missing_features_sasl);
|
||||||
|
|
||||||
/* check whether resource binding is required */
|
/* Check whether resource binding is required */
|
||||||
bind = xmpp_stanza_get_child_by_name(stanza, "bind");
|
bind = xmpp_stanza_get_child_by_name_and_ns(stanza, "bind", XMPP_NS_BIND);
|
||||||
if (bind) {
|
if (bind) {
|
||||||
ns = xmpp_stanza_get_ns(bind);
|
conn->bind_required = 1;
|
||||||
conn->bind_required = ns != NULL && strcmp(ns, XMPP_NS_BIND) == 0;
|
|
||||||
bind = xmpp_stanza_copy(bind);
|
bind = xmpp_stanza_copy(bind);
|
||||||
if (!bind) {
|
if (!bind) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
@@ -1123,25 +1117,31 @@ _handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
|||||||
conn->bind_required = 0;
|
conn->bind_required = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check whether session establishment is required */
|
/* Check whether session establishment is required.
|
||||||
session = xmpp_stanza_get_child_by_name(stanza, "session");
|
*
|
||||||
|
* 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);
|
||||||
if (session) {
|
if (session) {
|
||||||
ns = xmpp_stanza_get_ns(session);
|
conn->session_required =
|
||||||
opt = xmpp_stanza_get_child_by_name(session, "optional");
|
xmpp_stanza_get_child_by_name(session, "optional") == NULL;
|
||||||
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)) {
|
if (xmpp_stanza_get_child_by_name_and_ns(stanza, "sm", XMPP_NS_SM)) {
|
||||||
/* stream management supported */
|
|
||||||
conn->sm_state->sm_support = 1;
|
conn->sm_state->sm_support = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we are expecting either <bind/> and <session/> since this is a
|
/* We are expecting either <bind/> and optionally <session/> since this is a
|
||||||
XMPP style connection or we <resume/> the previous session */
|
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 &&
|
if (!conn->sm_disable && conn->sm_state->can_resume &&
|
||||||
conn->sm_state->previd && conn->sm_state->bound_jid) {
|
conn->sm_state->previd && conn->sm_state->bound_jid) {
|
||||||
resume = xmpp_stanza_new(conn->ctx);
|
resume = xmpp_stanza_new(conn->ctx);
|
||||||
@@ -1188,11 +1188,57 @@ static int _handle_missing_features_sasl(xmpp_conn_t *conn, void *userdata)
|
|||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
_handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||||
{
|
{
|
||||||
const char *type;
|
const char *type;
|
||||||
xmpp_stanza_t *iq, *session, *binding, *jid_stanza, *enable = NULL;
|
xmpp_stanza_t *binding, *jid_stanza;
|
||||||
|
|
||||||
UNUSED(userdata);
|
UNUSED(userdata);
|
||||||
|
|
||||||
@@ -1215,58 +1261,19 @@ _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 */
|
/* establish a session if required */
|
||||||
if (conn->session_required) {
|
if (conn->session_required) {
|
||||||
/* setup response handlers */
|
_session_start(conn);
|
||||||
handler_add_id(conn, _handle_session, "_xmpp_session1", NULL);
|
}
|
||||||
handler_add_timed(conn, _handle_missing_session, SESSION_TIMEOUT,
|
/* send enable directly after the bind request */
|
||||||
NULL);
|
else if (conn->sm_state->sm_support && !conn->sm_disable) {
|
||||||
|
_sm_enable(conn);
|
||||||
/* 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
|
/* 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
|
* stream-management, we're done here and the stream-negotiation was
|
||||||
* successful
|
* successful
|
||||||
*/
|
*/
|
||||||
if (!conn->session_required && !enable) {
|
else {
|
||||||
_stream_negotiation_success(conn);
|
_stream_negotiation_success(conn);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1303,8 +1310,11 @@ _handle_session(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
|||||||
xmpp_disconnect(conn);
|
xmpp_disconnect(conn);
|
||||||
} else if (type && strcmp(type, "result") == 0) {
|
} else if (type && strcmp(type, "result") == 0) {
|
||||||
strophe_debug(conn->ctx, "xmpp", "Session establishment successful.");
|
strophe_debug(conn->ctx, "xmpp", "Session establishment successful.");
|
||||||
|
if (conn->sm_state->sm_support && !conn->sm_disable) {
|
||||||
_stream_negotiation_success(conn);
|
_sm_enable(conn);
|
||||||
|
} else {
|
||||||
|
_stream_negotiation_success(conn);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
strophe_error(conn->ctx, "xmpp",
|
strophe_error(conn->ctx, "xmpp",
|
||||||
"Server sent malformed session reply.");
|
"Server sent malformed session reply.");
|
||||||
|
|||||||
11
src/common.h
11
src/common.h
@@ -175,9 +175,11 @@ struct _xmpp_send_queue_t {
|
|||||||
#define SASL_MASK_EXTERNAL (1 << 6)
|
#define SASL_MASK_EXTERNAL (1 << 6)
|
||||||
#define SASL_MASK_SCRAMSHA1_PLUS (1 << 7)
|
#define SASL_MASK_SCRAMSHA1_PLUS (1 << 7)
|
||||||
#define SASL_MASK_SCRAMSHA256_PLUS (1 << 8)
|
#define SASL_MASK_SCRAMSHA256_PLUS (1 << 8)
|
||||||
|
#define SASL_MASK_SCRAMSHA512_PLUS (1 << 9)
|
||||||
|
|
||||||
#define SASL_MASK_SCRAM_PLUS \
|
#define SASL_MASK_SCRAM_PLUS \
|
||||||
(SASL_MASK_SCRAMSHA1_PLUS | SASL_MASK_SCRAMSHA256_PLUS)
|
(SASL_MASK_SCRAMSHA1_PLUS | SASL_MASK_SCRAMSHA256_PLUS | \
|
||||||
|
SASL_MASK_SCRAMSHA512_PLUS)
|
||||||
#define SASL_MASK_SCRAM_WEAK \
|
#define SASL_MASK_SCRAM_WEAK \
|
||||||
(SASL_MASK_SCRAMSHA1 | SASL_MASK_SCRAMSHA256 | SASL_MASK_SCRAMSHA512)
|
(SASL_MASK_SCRAMSHA1 | SASL_MASK_SCRAMSHA256 | SASL_MASK_SCRAMSHA512)
|
||||||
#define SASL_MASK_SCRAM (SASL_MASK_SCRAM_PLUS | SASL_MASK_SCRAM_WEAK)
|
#define SASL_MASK_SCRAM (SASL_MASK_SCRAM_PLUS | SASL_MASK_SCRAM_WEAK)
|
||||||
@@ -259,8 +261,6 @@ struct _xmpp_conn_t {
|
|||||||
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 auth_legacy_enabled;
|
||||||
int weak_auth_enabled;
|
|
||||||
int only_strong_auth;
|
|
||||||
int secured; /* set when stream is secured with TLS */
|
int secured; /* set when stream is secured with TLS */
|
||||||
xmpp_certfail_handler certfail_handler;
|
xmpp_certfail_handler certfail_handler;
|
||||||
xmpp_password_callback password_callback;
|
xmpp_password_callback password_callback;
|
||||||
@@ -280,7 +280,8 @@ struct _xmpp_conn_t {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct xmpp_compression *state;
|
struct xmpp_compression *state;
|
||||||
int allowed, supported, dont_reset;
|
int allowed, dont_reset, level;
|
||||||
|
int supported;
|
||||||
} compression;
|
} compression;
|
||||||
|
|
||||||
char *lang;
|
char *lang;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ static int _conn_decompress(struct xmpp_compression *comp,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
strophe_error(comp->conn->ctx, "zlib", "inflate error %d", ret);
|
strophe_error(comp->conn->ctx, "zlib", "inflate error %d", ret);
|
||||||
comp->conn->error = EBADFD;
|
comp->conn->error = ret;
|
||||||
conn_disconnect(comp->conn);
|
conn_disconnect(comp->conn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ _compression_write(xmpp_conn_t *conn, const void *buff, size_t len, int flush)
|
|||||||
}
|
}
|
||||||
if (ret != Z_OK) {
|
if (ret != Z_OK) {
|
||||||
strophe_error(conn->ctx, "zlib", "deflate error %d", ret);
|
strophe_error(conn->ctx, "zlib", "deflate error %d", ret);
|
||||||
conn->error = EBADFD;
|
conn->error = ret;
|
||||||
conn_disconnect(conn);
|
conn_disconnect(conn);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -227,22 +227,22 @@ int compression_init(xmpp_conn_t *conn)
|
|||||||
|
|
||||||
comp->compression.stream.next_out = comp->compression.buffer;
|
comp->compression.stream.next_out = comp->compression.buffer;
|
||||||
comp->compression.stream.avail_out = STROPHE_COMPRESSION_BUFFER_SIZE;
|
comp->compression.stream.avail_out = STROPHE_COMPRESSION_BUFFER_SIZE;
|
||||||
int err = deflateInit(&comp->compression.stream, Z_DEFAULT_COMPRESSION);
|
int ret = deflateInit(&comp->compression.stream, conn->compression.level);
|
||||||
if (err != Z_OK) {
|
if (ret != Z_OK) {
|
||||||
strophe_free_and_null(conn->ctx, comp->compression.buffer);
|
strophe_free_and_null(conn->ctx, comp->compression.buffer);
|
||||||
conn->error = EBADFD;
|
conn->error = ret;
|
||||||
conn_disconnect(conn);
|
conn_disconnect(conn);
|
||||||
return err;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
_init_zlib_compression(conn->ctx, &comp->decompression);
|
_init_zlib_compression(conn->ctx, &comp->decompression);
|
||||||
|
|
||||||
err = inflateInit(&comp->decompression.stream);
|
ret = inflateInit(&comp->decompression.stream);
|
||||||
if (err != Z_OK) {
|
if (ret != Z_OK) {
|
||||||
strophe_free_and_null(conn->ctx, comp->decompression.buffer);
|
strophe_free_and_null(conn->ctx, comp->decompression.buffer);
|
||||||
conn->error = EBADFD;
|
conn->error = ret;
|
||||||
conn_disconnect(conn);
|
conn_disconnect(conn);
|
||||||
return err;
|
return ret;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
415
src/conn.c
415
src/conn.c
@@ -167,6 +167,8 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx)
|
|||||||
tls_clear_password_cache(conn);
|
tls_clear_password_cache(conn);
|
||||||
conn->password_retries = 1;
|
conn->password_retries = 1;
|
||||||
|
|
||||||
|
conn->compression.level = -1;
|
||||||
|
|
||||||
conn->parser =
|
conn->parser =
|
||||||
parser_new(conn->ctx, _handle_stream_start, _handle_stream_end,
|
parser_new(conn->ctx, _handle_stream_start, _handle_stream_end,
|
||||||
_handle_stream_stanza, conn);
|
_handle_stream_stanza, conn);
|
||||||
@@ -217,32 +219,6 @@ xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn)
|
|||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Register sockopt callback
|
|
||||||
* Set function to be called when a new socket is created to allow setting
|
|
||||||
* socket options before connection is started.
|
|
||||||
*
|
|
||||||
* If the connection is already connected, this callback will be called
|
|
||||||
* immediately.
|
|
||||||
*
|
|
||||||
* To set options that can only be applied to disconnected sockets, the
|
|
||||||
* callback must be registered before connecting.
|
|
||||||
*
|
|
||||||
* @param conn The Strophe connection object this callback is being registered
|
|
||||||
* for
|
|
||||||
* @param callback a xmpp_sockopt_callback callback function that will receive
|
|
||||||
* notifications of connection status
|
|
||||||
*
|
|
||||||
* @ingroup Connections
|
|
||||||
*/
|
|
||||||
|
|
||||||
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
|
|
||||||
xmpp_sockopt_callback callback)
|
|
||||||
{
|
|
||||||
conn->sockopt_cb = callback;
|
|
||||||
if (conn->state != XMPP_STATE_DISCONNECTED)
|
|
||||||
callback(conn, &conn->sock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Release a Strophe connection object.
|
/** Release a Strophe connection object.
|
||||||
* Decrement the reference count by one for a connection, freeing the
|
* Decrement the reference count by one for a connection, freeing the
|
||||||
* connection object if the count reaches 0.
|
* connection object if the count reaches 0.
|
||||||
@@ -366,6 +342,204 @@ int xmpp_conn_release(xmpp_conn_t *conn)
|
|||||||
return released;
|
return released;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Configure a connection-related int setting
|
||||||
|
*
|
||||||
|
* `setting` can be one of:
|
||||||
|
* - \ref XMPP_SETTING_PASSWORD_RETRIES
|
||||||
|
* Set the number of retry attempts to decrypt a private key file. \n
|
||||||
|
* In case the user enters the password manually it can be useful to
|
||||||
|
* directly retry if the decryption of the key file failed.
|
||||||
|
*
|
||||||
|
* - \ref XMPP_SETTING_COMPRESSION_LEVEL
|
||||||
|
* Set the compression level. \n
|
||||||
|
* For zlib the valid range is `-1` to `9`.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param setting The setting that shall be configured
|
||||||
|
* @param value The value, the settings should get
|
||||||
|
*
|
||||||
|
* @ingroup Connections
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_int(xmpp_conn_t *conn,
|
||||||
|
xmpp_conn_setting_t setting,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
switch (setting) {
|
||||||
|
case XMPP_SETTING_PASSWORD_RETRIES:
|
||||||
|
if (value <= 0)
|
||||||
|
conn->password_retries = 1;
|
||||||
|
else
|
||||||
|
conn->password_retries = value;
|
||||||
|
break;
|
||||||
|
case XMPP_SETTING_COMPRESSION_LEVEL:
|
||||||
|
conn->compression.level = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strophe_warn(conn->ctx, "xmpp", "Invalid Int setting %d", setting);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Configure a connection-related string setting
|
||||||
|
*
|
||||||
|
* `setting` can be one of:
|
||||||
|
* - \ref XMPP_SETTING_JID
|
||||||
|
* Set the JID of the user that will be bound to the connection. \n
|
||||||
|
* This should not be used after a connection is created. \n
|
||||||
|
* If the supplied JID is missing the node, SASL ANONYMOUS authentication
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* - \ref XMPP_SETTING_PASS
|
||||||
|
* Set the password used to authenticate the connection.
|
||||||
|
*
|
||||||
|
* - \ref XMPP_SETTING_CAFILE
|
||||||
|
* Set CAfile.
|
||||||
|
*
|
||||||
|
* - \ref XMPP_SETTING_CAPATH
|
||||||
|
* Set CApath.
|
||||||
|
*
|
||||||
|
* - \ref XMPP_SETTING_CLIENT_CERT
|
||||||
|
* Set the Client Certificate or PKCS#12 encoded file that will be bound to
|
||||||
|
* the connection. \n
|
||||||
|
* This should not be used after a connection is created. \n
|
||||||
|
* In case the PKCS#12 file is encrypted, a callback must be set via
|
||||||
|
* \ref xmpp_conn_set_functionpointer with the option
|
||||||
|
* \ref XMPP_SETTING_PASSWORD_CALLBACK so the TLS stack can retrieve the
|
||||||
|
* password.
|
||||||
|
*
|
||||||
|
* - \ref XMPP_SETTING_CLIENT_KEY
|
||||||
|
* Set the Private Key that will be bound to the connection. \n
|
||||||
|
* This should not be used after a connection is created. \n
|
||||||
|
* In case the Private Key is encrypted, a callback must be set via
|
||||||
|
* \ref xmpp_conn_set_functionpointer with the option
|
||||||
|
* \ref XMPP_SETTING_PASSWORD_CALLBACK so the TLS stack can retrieve the
|
||||||
|
* password.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* If any value was previously set, it will be discarded.
|
||||||
|
* The function will make a copy of the value given.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param setting The setting that shall be configured
|
||||||
|
* @param value The value, the settings should get
|
||||||
|
*
|
||||||
|
* @ingroup Connections
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_string(xmpp_conn_t *conn,
|
||||||
|
xmpp_conn_setting_t setting,
|
||||||
|
const char *value)
|
||||||
|
{
|
||||||
|
char **target;
|
||||||
|
switch (setting) {
|
||||||
|
case XMPP_SETTING_JID:
|
||||||
|
target = &conn->jid;
|
||||||
|
break;
|
||||||
|
case XMPP_SETTING_PASS:
|
||||||
|
target = &conn->pass;
|
||||||
|
break;
|
||||||
|
case XMPP_SETTING_CAFILE:
|
||||||
|
target = &conn->tls_cafile;
|
||||||
|
break;
|
||||||
|
case XMPP_SETTING_CAPATH:
|
||||||
|
target = &conn->tls_capath;
|
||||||
|
break;
|
||||||
|
case XMPP_SETTING_CLIENT_CERT:
|
||||||
|
target = &conn->tls_client_cert;
|
||||||
|
break;
|
||||||
|
case XMPP_SETTING_CLIENT_KEY:
|
||||||
|
target = &conn->tls_client_key;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strophe_warn(conn->ctx, "xmpp", "Invalid String setting %d", setting);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*target)
|
||||||
|
strophe_free(conn->ctx, *target);
|
||||||
|
*target = NULL;
|
||||||
|
if (value) {
|
||||||
|
*target = strophe_strdup(conn->ctx, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Configure a connection-related pointer setting
|
||||||
|
*
|
||||||
|
* `setting` can be one of:
|
||||||
|
* - \ref XMPP_SETTING_PASSWORD_CALLBACK_USERDATA
|
||||||
|
* Set the userdata pointer that is pass when the password-retrieval
|
||||||
|
* callback is called. \ref XMPP_SETTING_PASSWORD_CALLBACK
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param setting The setting that shall be configured
|
||||||
|
* @param value The value, the settings should get
|
||||||
|
*
|
||||||
|
* @ingroup Connections
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_pointer(xmpp_conn_t *conn,
|
||||||
|
xmpp_conn_setting_t setting,
|
||||||
|
void *value)
|
||||||
|
{
|
||||||
|
switch (setting) {
|
||||||
|
case XMPP_SETTING_PASSWORD_CALLBACK_USERDATA:
|
||||||
|
conn->password_callback_userdata = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strophe_warn(conn->ctx, "xmpp", "Invalid Pointer setting %d", setting);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Configure a connection-related functionpointer setting
|
||||||
|
*
|
||||||
|
* `setting` can be one of:
|
||||||
|
* - \ref XMPP_SETTING_PASSWORD_CALLBACK
|
||||||
|
* Set the Callback function which will be called when the TLS stack can't
|
||||||
|
* decrypt a password protected key file. The userdata pointer can be set
|
||||||
|
* via \ref xmpp_conn_set_pointer with the setting
|
||||||
|
* \ref XMPP_SETTING_PASSWORD_CALLBACK_USERDATA
|
||||||
|
*
|
||||||
|
* - \ref XMPP_SETTING_CERTFAIL_HANDLER
|
||||||
|
* Set the Handler function which will be called when the TLS stack can't
|
||||||
|
* verify the CA of the server we're trying to connect to.
|
||||||
|
*
|
||||||
|
* - \ref XMPP_SETTING_SOCKOPT_CALLBACK
|
||||||
|
* Set function to be called when a new socket is created to allow setting
|
||||||
|
* socket options before connection is started. \n
|
||||||
|
* If the connection is already connected, this callback will be called
|
||||||
|
* immediately. \n
|
||||||
|
* To set options that can only be applied to disconnected sockets, the
|
||||||
|
* callback must be registered before connecting.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param setting The setting that shall be configured
|
||||||
|
* @param value The value, the settings should get
|
||||||
|
*
|
||||||
|
* @ingroup Connections
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_functionpointer_impl(xmpp_conn_t *conn,
|
||||||
|
xmpp_conn_setting_t setting,
|
||||||
|
xmpp_conn_pfn_t value)
|
||||||
|
{
|
||||||
|
switch (setting) {
|
||||||
|
case XMPP_SETTING_PASSWORD_CALLBACK:
|
||||||
|
conn->password_callback = (xmpp_password_callback)value;
|
||||||
|
break;
|
||||||
|
case XMPP_SETTING_CERTFAIL_HANDLER:
|
||||||
|
conn->certfail_handler = (xmpp_certfail_handler)value;
|
||||||
|
break;
|
||||||
|
case XMPP_SETTING_SOCKOPT_CALLBACK:
|
||||||
|
conn->sockopt_cb = (xmpp_sockopt_callback)value;
|
||||||
|
if (conn->state != XMPP_STATE_DISCONNECTED)
|
||||||
|
conn->sockopt_cb(conn, &conn->sock);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strophe_warn(conn->ctx, "xmpp", "Invalid Functionpointer setting %d",
|
||||||
|
setting);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Get the JID which is or will be bound to the connection.
|
/** Get the JID which is or will be bound to the connection.
|
||||||
*
|
*
|
||||||
* @param conn a Strophe connection object
|
* @param conn a Strophe connection object
|
||||||
@@ -397,66 +571,6 @@ const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *conn)
|
|||||||
return conn->bound_jid;
|
return conn->bound_jid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the JID of the user that will be bound to the connection.
|
|
||||||
* If any JID was previously set, it will be discarded. This should not be
|
|
||||||
* be used after a connection is created. The function will make a copy of
|
|
||||||
* the JID string. If the supplied JID is missing the node, SASL
|
|
||||||
* ANONYMOUS authentication will be used.
|
|
||||||
*
|
|
||||||
* @param conn a Strophe connection object
|
|
||||||
* @param jid a full or bare JID
|
|
||||||
*
|
|
||||||
* @ingroup Connections
|
|
||||||
*/
|
|
||||||
void xmpp_conn_set_jid(xmpp_conn_t *conn, const char *jid)
|
|
||||||
{
|
|
||||||
if (conn->jid)
|
|
||||||
strophe_free(conn->ctx, conn->jid);
|
|
||||||
conn->jid = strophe_strdup(conn->ctx, jid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the Handler function which will be called when the TLS stack can't
|
|
||||||
* verify the CA of the server we're trying to connect to.
|
|
||||||
*
|
|
||||||
* @param conn a Strophe connection object
|
|
||||||
* @param hndl certfail Handler function
|
|
||||||
*
|
|
||||||
* @ingroup TLS
|
|
||||||
*/
|
|
||||||
void xmpp_conn_set_certfail_handler(xmpp_conn_t *const conn,
|
|
||||||
xmpp_certfail_handler hndl)
|
|
||||||
{
|
|
||||||
conn->certfail_handler = hndl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the CAfile
|
|
||||||
*
|
|
||||||
* @param conn a Strophe connection object
|
|
||||||
* @param path path to a certificate file
|
|
||||||
*
|
|
||||||
* @ingroup TLS
|
|
||||||
*/
|
|
||||||
void xmpp_conn_set_cafile(xmpp_conn_t *const conn, const char *path)
|
|
||||||
{
|
|
||||||
if (conn->tls_cafile)
|
|
||||||
strophe_free(conn->ctx, conn->tls_cafile);
|
|
||||||
conn->tls_cafile = strophe_strdup(conn->ctx, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the CApath
|
|
||||||
*
|
|
||||||
* @param conn a Strophe connection object
|
|
||||||
* @param path path to a folder containing certificates
|
|
||||||
*
|
|
||||||
* @ingroup TLS
|
|
||||||
*/
|
|
||||||
void xmpp_conn_set_capath(xmpp_conn_t *const conn, const char *path)
|
|
||||||
{
|
|
||||||
if (conn->tls_capath)
|
|
||||||
strophe_free(conn->ctx, conn->tls_capath);
|
|
||||||
conn->tls_capath = strophe_strdup(conn->ctx, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieve the peer certificate
|
/** Retrieve the peer certificate
|
||||||
*
|
*
|
||||||
* The returned Certificate object must be free'd by calling
|
* The returned Certificate object must be free'd by calling
|
||||||
@@ -473,41 +587,6 @@ xmpp_tlscert_t *xmpp_conn_get_peer_cert(xmpp_conn_t *const conn)
|
|||||||
return tls_peer_cert(conn);
|
return tls_peer_cert(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the Callback function which will be called when the TLS stack can't
|
|
||||||
* decrypt a password protected key file.
|
|
||||||
*
|
|
||||||
* @param conn a Strophe connection object
|
|
||||||
* @param cb The callback function that shall be called
|
|
||||||
* @param userdata An opaque data pointer that will be passed to the callback
|
|
||||||
*
|
|
||||||
* @ingroup TLS
|
|
||||||
*/
|
|
||||||
void xmpp_conn_set_password_callback(xmpp_conn_t *conn,
|
|
||||||
xmpp_password_callback cb,
|
|
||||||
void *userdata)
|
|
||||||
{
|
|
||||||
conn->password_callback = cb;
|
|
||||||
conn->password_callback_userdata = userdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the number of retry attempts to decrypt a private key file.
|
|
||||||
*
|
|
||||||
* In case the user enters the password manually it can be useful to
|
|
||||||
* directly retry if the decryption of the key file failed.
|
|
||||||
*
|
|
||||||
* @param conn a Strophe connection object
|
|
||||||
* @param retries The number of retries that should be tried
|
|
||||||
*
|
|
||||||
* @ingroup TLS
|
|
||||||
*/
|
|
||||||
void xmpp_conn_set_password_retries(xmpp_conn_t *conn, unsigned int retries)
|
|
||||||
{
|
|
||||||
if (retries == 0)
|
|
||||||
conn->password_retries = 1;
|
|
||||||
else
|
|
||||||
conn->password_retries = retries;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieve the path of the key file that shall be unlocked.
|
/** Retrieve the path of the key file that shall be unlocked.
|
||||||
*
|
*
|
||||||
* This makes usually sense to be called from the
|
* This makes usually sense to be called from the
|
||||||
@@ -524,49 +603,6 @@ const char *xmpp_conn_get_keyfile(const xmpp_conn_t *conn)
|
|||||||
return conn->tls_client_key;
|
return conn->tls_client_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the Client Certificate and Private Key or PKCS#12 encoded file that
|
|
||||||
* will be bound to the connection. If any of them was previously set, it
|
|
||||||
* will be discarded. This should not be used after a connection is created.
|
|
||||||
* The function will make a copy of the strings passed in.
|
|
||||||
*
|
|
||||||
* In case the Private Key is encrypted, a callback must be set via
|
|
||||||
* \ref xmpp_conn_set_password_callback so the TLS stack can retrieve the
|
|
||||||
* password.
|
|
||||||
*
|
|
||||||
* In case one wants to use a PKCS#12 encoded file, it should be passed via
|
|
||||||
* the `cert` parameter and `key` should be NULL. Passing a PKCS#12 file in
|
|
||||||
* `key` is deprecated.
|
|
||||||
*
|
|
||||||
* @param conn a Strophe connection object
|
|
||||||
* @param cert path to a certificate file or a P12 file
|
|
||||||
* @param key path to a private key file or a P12 file
|
|
||||||
*
|
|
||||||
* @ingroup TLS
|
|
||||||
*/
|
|
||||||
void xmpp_conn_set_client_cert(xmpp_conn_t *const conn,
|
|
||||||
const char *const cert,
|
|
||||||
const char *const key)
|
|
||||||
{
|
|
||||||
strophe_debug(conn->ctx, "conn", "set client cert %s %s", cert, key);
|
|
||||||
if (conn->tls_client_cert)
|
|
||||||
strophe_free(conn->ctx, conn->tls_client_cert);
|
|
||||||
conn->tls_client_cert = NULL;
|
|
||||||
if (conn->tls_client_key)
|
|
||||||
strophe_free(conn->ctx, conn->tls_client_key);
|
|
||||||
conn->tls_client_key = NULL;
|
|
||||||
if (cert && key) {
|
|
||||||
conn->tls_client_cert = strophe_strdup(conn->ctx, cert);
|
|
||||||
conn->tls_client_key = strophe_strdup(conn->ctx, key);
|
|
||||||
} else if (cert && !key) {
|
|
||||||
conn->tls_client_cert = strophe_strdup(conn->ctx, cert);
|
|
||||||
} else if (!cert && key) {
|
|
||||||
strophe_warn(conn->ctx, "xmpp",
|
|
||||||
"xmpp_conn_set_client_cert: Passing PKCS#12 in 'key' "
|
|
||||||
"parameter is deprecated. Use 'cert' instead");
|
|
||||||
conn->tls_client_cert = strophe_strdup(conn->ctx, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the number of xmppAddr entries in the client certificate.
|
/** Get the number of xmppAddr entries in the client certificate.
|
||||||
*
|
*
|
||||||
* @param conn a Strophe connection object
|
* @param conn a Strophe connection object
|
||||||
@@ -607,22 +643,6 @@ const char *xmpp_conn_get_pass(const xmpp_conn_t *conn)
|
|||||||
return conn->pass;
|
return conn->pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the password used to authenticate the connection.
|
|
||||||
* If any password was previously set, it will be discarded. The function
|
|
||||||
* will make a copy of the password string.
|
|
||||||
*
|
|
||||||
* @param conn a Strophe connection object
|
|
||||||
* @param pass the password
|
|
||||||
*
|
|
||||||
* @ingroup Connections
|
|
||||||
*/
|
|
||||||
void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass)
|
|
||||||
{
|
|
||||||
if (conn->pass)
|
|
||||||
strophe_free(conn->ctx, conn->pass);
|
|
||||||
conn->pass = pass ? strophe_strdup(conn->ctx, pass) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the strophe context that the connection is associated with.
|
/** Get the strophe context that the connection is associated with.
|
||||||
* @param conn a Strophe connection object
|
* @param conn a Strophe connection object
|
||||||
*
|
*
|
||||||
@@ -1092,6 +1112,7 @@ int conn_tls_start(xmpp_conn_t *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (conn->tls != NULL) {
|
if (conn->tls != NULL) {
|
||||||
|
struct conn_interface old_intf = conn->intf;
|
||||||
conn->intf = tls_intf;
|
conn->intf = tls_intf;
|
||||||
conn->intf.conn = conn;
|
conn->intf.conn = conn;
|
||||||
if (tls_start(conn->tls)) {
|
if (tls_start(conn->tls)) {
|
||||||
@@ -1102,6 +1123,7 @@ int conn_tls_start(xmpp_conn_t *conn)
|
|||||||
tls_free(conn->tls);
|
tls_free(conn->tls);
|
||||||
conn->tls = NULL;
|
conn->tls = NULL;
|
||||||
conn->tls_failed = 1;
|
conn->tls_failed = 1;
|
||||||
|
conn->intf = old_intf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
@@ -1133,8 +1155,6 @@ long xmpp_conn_get_flags(const xmpp_conn_t *conn)
|
|||||||
XMPP_CONN_FLAG_DISABLE_SM * conn->sm_disable |
|
XMPP_CONN_FLAG_DISABLE_SM * conn->sm_disable |
|
||||||
XMPP_CONN_FLAG_ENABLE_COMPRESSION * conn->compression.allowed |
|
XMPP_CONN_FLAG_ENABLE_COMPRESSION * conn->compression.allowed |
|
||||||
XMPP_CONN_FLAG_COMPRESSION_DONT_RESET * conn->compression.dont_reset |
|
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;
|
XMPP_CONN_FLAG_LEGACY_AUTH * conn->auth_legacy_enabled;
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
@@ -1149,14 +1169,14 @@ long xmpp_conn_get_flags(const xmpp_conn_t *conn)
|
|||||||
*
|
*
|
||||||
* Supported flags are:
|
* Supported flags are:
|
||||||
*
|
*
|
||||||
* - XMPP_CONN_FLAG_DISABLE_TLS
|
* - \ref XMPP_CONN_FLAG_DISABLE_TLS
|
||||||
* - XMPP_CONN_FLAG_MANDATORY_TLS
|
* - \ref XMPP_CONN_FLAG_MANDATORY_TLS
|
||||||
* - XMPP_CONN_FLAG_LEGACY_SSL
|
* - \ref XMPP_CONN_FLAG_LEGACY_SSL
|
||||||
* - XMPP_CONN_FLAG_TRUST_TLS
|
* - \ref XMPP_CONN_FLAG_TRUST_TLS
|
||||||
* - XMPP_CONN_FLAG_LEGACY_AUTH
|
* - \ref XMPP_CONN_FLAG_LEGACY_AUTH
|
||||||
* - XMPP_CONN_FLAG_DISABLE_SM
|
* - \ref XMPP_CONN_FLAG_DISABLE_SM
|
||||||
* - XMPP_CONN_FLAG_ENABLE_COMPRESSION
|
* - \ref XMPP_CONN_FLAG_ENABLE_COMPRESSION
|
||||||
* - XMPP_CONN_FLAG_COMPRESSION_DONT_RESET
|
* - \ref XMPP_CONN_FLAG_COMPRESSION_DONT_RESET
|
||||||
*
|
*
|
||||||
* @param conn a Strophe connection object
|
* @param conn a Strophe connection object
|
||||||
* @param flags ORed connection flags
|
* @param flags ORed connection flags
|
||||||
@@ -1190,14 +1210,11 @@ int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags)
|
|||||||
(flags & XMPP_CONN_FLAG_ENABLE_COMPRESSION) ? 1 : 0;
|
(flags & XMPP_CONN_FLAG_ENABLE_COMPRESSION) ? 1 : 0;
|
||||||
conn->compression.dont_reset =
|
conn->compression.dont_reset =
|
||||||
(flags & XMPP_CONN_FLAG_COMPRESSION_DONT_RESET) ? 1 : 0;
|
(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 |
|
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_SSL | XMPP_CONN_FLAG_TRUST_TLS |
|
||||||
XMPP_CONN_FLAG_LEGACY_AUTH | XMPP_CONN_FLAG_DISABLE_SM |
|
XMPP_CONN_FLAG_LEGACY_AUTH | XMPP_CONN_FLAG_DISABLE_SM |
|
||||||
XMPP_CONN_FLAG_ENABLE_COMPRESSION |
|
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) {
|
if (flags) {
|
||||||
strophe_error(conn->ctx, "conn", "Flags 0x%04lx unknown", flags);
|
strophe_error(conn->ctx, "conn", "Flags 0x%04lx unknown", flags);
|
||||||
return XMPP_EINVOP;
|
return XMPP_EINVOP;
|
||||||
@@ -1440,6 +1457,7 @@ char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn,
|
|||||||
xmpp_queue_element_t which)
|
xmpp_queue_element_t which)
|
||||||
{
|
{
|
||||||
xmpp_send_queue_t *t;
|
xmpp_send_queue_t *t;
|
||||||
|
int disconnected = conn->state == XMPP_STATE_DISCONNECTED;
|
||||||
|
|
||||||
/* Fast return paths */
|
/* Fast return paths */
|
||||||
/* empty queue */
|
/* empty queue */
|
||||||
@@ -1448,7 +1466,7 @@ char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn,
|
|||||||
/* one element in queue */
|
/* one element in queue */
|
||||||
if (conn->send_queue_head == conn->send_queue_tail) {
|
if (conn->send_queue_head == conn->send_queue_tail) {
|
||||||
/* head is already sent out partially */
|
/* head is already sent out partially */
|
||||||
if (conn->send_queue_head->wip)
|
if (conn->send_queue_head->wip && !disconnected)
|
||||||
return NULL;
|
return NULL;
|
||||||
/* the element is no USER element */
|
/* the element is no USER element */
|
||||||
if (conn->send_queue_head->owner != XMPP_QUEUE_USER)
|
if (conn->send_queue_head->owner != XMPP_QUEUE_USER)
|
||||||
@@ -1472,7 +1490,7 @@ char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* head is already sent out partially */
|
/* head is already sent out partially */
|
||||||
if (t == conn->send_queue_head && t->wip)
|
if (t == conn->send_queue_head && t->wip && !disconnected)
|
||||||
t = t->next;
|
t = t->next;
|
||||||
|
|
||||||
/* search forward to find the first USER element */
|
/* search forward to find the first USER element */
|
||||||
@@ -1486,8 +1504,11 @@ char *xmpp_conn_send_queue_drop_element(xmpp_conn_t *conn,
|
|||||||
/* In case there exists a SM stanza that is linked to the
|
/* In case there exists a SM stanza that is linked to the
|
||||||
* one we're currently dropping, also delete that one.
|
* 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));
|
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 */
|
/* Finally drop the element */
|
||||||
return _drop_send_queue_element(conn, t);
|
return _drop_send_queue_element(conn, t);
|
||||||
}
|
}
|
||||||
|
|||||||
185
src/deprecated.c
185
src/deprecated.c
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
/** Allocate memory in a Strophe context.
|
/** Allocate memory in a Strophe context.
|
||||||
* All Strophe functions will use this to allocate memory.
|
* All Strophe functions will use this to allocate memory.
|
||||||
@@ -86,6 +87,10 @@ char *xmpp_strndup(const xmpp_ctx_t *ctx, const char *s, size_t len)
|
|||||||
return strophe_strndup(ctx, s, len);
|
return strophe_strndup(ctx, s, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Write to the log.
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
void xmpp_log(const xmpp_ctx_t *ctx,
|
void xmpp_log(const xmpp_ctx_t *ctx,
|
||||||
xmpp_log_level_t level,
|
xmpp_log_level_t level,
|
||||||
const char *area,
|
const char *area,
|
||||||
@@ -217,6 +222,10 @@ char *xmpp_strtok_r(char *s, const char *delim, char **saveptr)
|
|||||||
return strophe_strtok_r(s, delim, saveptr);
|
return strophe_strtok_r(s, delim, saveptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** snprintf(3) implementation.
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
int xmpp_snprintf(char *str, size_t count, const char *fmt, ...)
|
int xmpp_snprintf(char *str, size_t count, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -228,11 +237,184 @@ int xmpp_snprintf(char *str, size_t count, const char *fmt, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** vsnprintf(3) implementation.
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
int xmpp_vsnprintf(char *str, size_t count, const char *fmt, va_list arg)
|
int xmpp_vsnprintf(char *str, size_t count, const char *fmt, va_list arg)
|
||||||
{
|
{
|
||||||
return strophe_vsnprintf(str, count, fmt, arg);
|
return strophe_vsnprintf(str, count, fmt, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set the JID of the user that will be bound to the connection.
|
||||||
|
* If any JID was previously set, it will be discarded. This should not be
|
||||||
|
* be used after a connection is created. The function will make a copy of
|
||||||
|
* the JID string. If the supplied JID is missing the node, SASL
|
||||||
|
* ANONYMOUS authentication will be used.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param jid a full or bare JID
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_jid(xmpp_conn_t *conn, const char *jid)
|
||||||
|
{
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_JID, jid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the password used to authenticate the connection.
|
||||||
|
* If any password was previously set, it will be discarded. The function
|
||||||
|
* will make a copy of the password string.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param pass the password
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass)
|
||||||
|
{
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_PASS, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the CAfile
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param path path to a certificate file
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_cafile(xmpp_conn_t *const conn, const char *path)
|
||||||
|
{
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_CAFILE, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the CApath
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param path path to a folder containing certificates
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_capath(xmpp_conn_t *const conn, const char *path)
|
||||||
|
{
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_CAPATH, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the Client Certificate and Private Key or PKCS#12 encoded file that
|
||||||
|
* will be bound to the connection. If any of them was previously set, it
|
||||||
|
* will be discarded. This should not be used after a connection is created.
|
||||||
|
* The function will make a copy of the strings passed in.
|
||||||
|
*
|
||||||
|
* In case the Private Key is encrypted, a callback must be set via
|
||||||
|
* \ref xmpp_conn_set_password_callback so the TLS stack can retrieve the
|
||||||
|
* password.
|
||||||
|
*
|
||||||
|
* In case one wants to use a PKCS#12 encoded file, it should be passed via
|
||||||
|
* the `cert` parameter and `key` should be NULL. Passing a PKCS#12 file in
|
||||||
|
* `key` is deprecated.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param cert path to a certificate file or a P12 file
|
||||||
|
* @param key path to a private key file or a P12 file
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_client_cert(xmpp_conn_t *const conn,
|
||||||
|
const char *const cert,
|
||||||
|
const char *const key)
|
||||||
|
{
|
||||||
|
strophe_debug(conn->ctx, "conn", "set client cert %s %s", cert, key);
|
||||||
|
if (!cert && key) {
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, key);
|
||||||
|
strophe_warn(conn->ctx, "xmpp",
|
||||||
|
"xmpp_conn_set_client_cert: Passing PKCS#12 in 'key' "
|
||||||
|
"parameter is deprecated. Use 'cert' instead");
|
||||||
|
} else {
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, cert);
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_KEY, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the number of retry attempts to decrypt a private key file.
|
||||||
|
*
|
||||||
|
* In case the user enters the password manually it can be useful to
|
||||||
|
* directly retry if the decryption of the key file failed.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param retries The number of retries that should be tried
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_password_retries(xmpp_conn_t *conn, unsigned int retries)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
if (retries > INT_MAX) {
|
||||||
|
val = INT_MAX;
|
||||||
|
strophe_warn(conn->ctx, "xmpp", "retries capped from %u to %d", retries,
|
||||||
|
val);
|
||||||
|
} else {
|
||||||
|
val = (int)retries;
|
||||||
|
}
|
||||||
|
xmpp_conn_set_int(conn, XMPP_SETTING_PASSWORD_RETRIES, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the Callback function which will be called when the TLS stack can't
|
||||||
|
* decrypt a password protected key file.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param cb The callback function that shall be called
|
||||||
|
* @param userdata An opaque data pointer that will be passed to the callback
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_password_callback(xmpp_conn_t *conn,
|
||||||
|
xmpp_password_callback cb,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_PASSWORD_CALLBACK, cb);
|
||||||
|
xmpp_conn_set_pointer(conn, XMPP_SETTING_PASSWORD_CALLBACK_USERDATA,
|
||||||
|
userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the Handler function which will be called when the TLS stack can't
|
||||||
|
* verify the CA of the server we're trying to connect to.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param hndl certfail Handler function
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
|
void xmpp_conn_set_certfail_handler(xmpp_conn_t *const conn,
|
||||||
|
xmpp_certfail_handler hndl)
|
||||||
|
{
|
||||||
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_CERTFAIL_HANDLER, hndl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Register sockopt callback
|
||||||
|
* Set function to be called when a new socket is created to allow setting
|
||||||
|
* socket options before connection is started.
|
||||||
|
*
|
||||||
|
* If the connection is already connected, this callback will be called
|
||||||
|
* immediately.
|
||||||
|
*
|
||||||
|
* To set options that can only be applied to disconnected sockets, the
|
||||||
|
* callback must be registered before connecting.
|
||||||
|
*
|
||||||
|
* @param conn The Strophe connection object this callback is being registered
|
||||||
|
* for
|
||||||
|
* @param callback a xmpp_sockopt_callback callback function that will receive
|
||||||
|
* notifications of connection status
|
||||||
|
*
|
||||||
|
* @ingroup Deprecated
|
||||||
|
*/
|
||||||
|
|
||||||
|
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
|
||||||
|
xmpp_sockopt_callback callback)
|
||||||
|
{
|
||||||
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_SOCKOPT_CALLBACK,
|
||||||
|
callback);
|
||||||
|
}
|
||||||
|
|
||||||
/** Set TCP keepalive parameters
|
/** Set TCP keepalive parameters
|
||||||
* Turn on TCP keepalive and set timeout and interval. Zero timeout
|
* Turn on TCP keepalive and set timeout and interval. Zero timeout
|
||||||
* disables TCP keepalives. The parameters are applied immediately for
|
* disables TCP keepalives. The parameters are applied immediately for
|
||||||
@@ -253,7 +435,8 @@ void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval)
|
|||||||
conn->ka_timeout = timeout;
|
conn->ka_timeout = timeout;
|
||||||
conn->ka_interval = interval;
|
conn->ka_interval = interval;
|
||||||
conn->ka_count = 0;
|
conn->ka_count = 0;
|
||||||
xmpp_conn_set_sockopt_callback(conn, xmpp_sockopt_cb_keepalive);
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_SOCKOPT_CALLBACK,
|
||||||
|
xmpp_sockopt_cb_keepalive);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Disable TLS for this connection, called by users of the library.
|
/** Disable TLS for this connection, called by users of the library.
|
||||||
|
|||||||
11
src/scram.c
11
src/scram.c
@@ -78,12 +78,23 @@ const struct hash_alg scram_sha512 = {
|
|||||||
(void (*)(void *, const uint8_t *, size_t))sha512_process,
|
(void (*)(void *, const uint8_t *, size_t))sha512_process,
|
||||||
(void (*)(void *, uint8_t *))sha512_done};
|
(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
|
/* The order of this list defines the order in which the SCRAM algorithms are
|
||||||
* tried if the server supports them.
|
* tried if the server supports them.
|
||||||
* Their order is derived from
|
* Their order is derived from
|
||||||
* https://datatracker.ietf.org/doc/html/draft-ietf-kitten-password-storage
|
* https://datatracker.ietf.org/doc/html/draft-ietf-kitten-password-storage
|
||||||
*/
|
*/
|
||||||
const struct hash_alg *scram_algs[] = {
|
const struct hash_alg *scram_algs[] = {
|
||||||
|
/* *1 */
|
||||||
|
&scram_sha512_plus,
|
||||||
/* *1 */
|
/* *1 */
|
||||||
&scram_sha256_plus,
|
&scram_sha256_plus,
|
||||||
/* *1 */
|
/* *1 */
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ static void sock_getaddrinfo(xmpp_sock_t *xsock)
|
|||||||
rc = getaddrinfo(xsock->srv_rr_cur->target, service, &hints,
|
rc = getaddrinfo(xsock->srv_rr_cur->target, service, &hints,
|
||||||
&xsock->ainfo_list);
|
&xsock->ainfo_list);
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
strophe_debug(xsock->ctx, "sock", "getaddrinfo() failed with %d",
|
strophe_debug(xsock->ctx, "sock",
|
||||||
|
"getaddrinfo() failed with %s (%d)", gai_strerror(rc),
|
||||||
rc);
|
rc);
|
||||||
xsock->ainfo_list = NULL;
|
xsock->ainfo_list = NULL;
|
||||||
}
|
}
|
||||||
@@ -207,7 +208,7 @@ sock_t sock_connect(xmpp_sock_t *xsock)
|
|||||||
{
|
{
|
||||||
struct addrinfo *ainfo;
|
struct addrinfo *ainfo;
|
||||||
sock_t sock;
|
sock_t sock;
|
||||||
int rc = 0;
|
int rc;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -228,6 +229,7 @@ sock_t sock_connect(xmpp_sock_t *xsock)
|
|||||||
|
|
||||||
sock = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
|
sock = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
|
||||||
if (sock != INVALID_SOCKET) {
|
if (sock != INVALID_SOCKET) {
|
||||||
|
rc = 0;
|
||||||
if (xsock->conn->sockopt_cb) {
|
if (xsock->conn->sockopt_cb) {
|
||||||
/* Don't allow user to overwrite sockfd value. */
|
/* Don't allow user to overwrite sockfd value. */
|
||||||
sock_t sock_copy = sock;
|
sock_t sock_copy = sock;
|
||||||
@@ -235,7 +237,7 @@ sock_t sock_connect(xmpp_sock_t *xsock)
|
|||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
strophe_debug(xsock->ctx, "sock",
|
strophe_debug(xsock->ctx, "sock",
|
||||||
"User's setsockopt callback"
|
"User's setsockopt callback"
|
||||||
"failed with %d (errno=%d)",
|
" failed with %d (errno=%d)",
|
||||||
rc, errno);
|
rc, errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,10 @@
|
|||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
#define STROPHE_ERR_func_error_string(e) ERR_func_error_string(e)
|
#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
|
#else
|
||||||
#define STROPHE_ERR_func_error_string(e) ""
|
#define STROPHE_ERR_func_error_string(e) ""
|
||||||
|
#define STROPHE_SSL_get1_peer_certificate(s) SSL_get1_peer_certificate(s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
@@ -109,6 +111,7 @@ struct _tls {
|
|||||||
X509 *client_cert;
|
X509 *client_cert;
|
||||||
void *channel_binding_data;
|
void *channel_binding_data;
|
||||||
size_t channel_binding_size;
|
size_t channel_binding_size;
|
||||||
|
FILE *keylogfile;
|
||||||
int lasterror;
|
int lasterror;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -556,6 +559,36 @@ static int _tls_password_callback(char *buf, int size, int rwflag, void *u)
|
|||||||
return tls_caching_password_callback(buf, size, 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_new(xmpp_conn_t *conn)
|
||||||
{
|
{
|
||||||
tls_t *tls = strophe_alloc(conn->ctx, sizeof(*tls));
|
tls_t *tls = strophe_alloc(conn->ctx, sizeof(*tls));
|
||||||
@@ -699,6 +732,8 @@ tls_t *tls_new(xmpp_conn_t *conn)
|
|||||||
ret = SSL_set_fd(tls->ssl, conn->sock);
|
ret = SSL_set_fd(tls->ssl, conn->sock);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto err_free_ssl;
|
goto err_free_ssl;
|
||||||
|
|
||||||
|
_try_open_keylogfile(tls);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tls;
|
return tls;
|
||||||
@@ -717,6 +752,8 @@ err:
|
|||||||
|
|
||||||
void tls_free(tls_t *tls)
|
void tls_free(tls_t *tls)
|
||||||
{
|
{
|
||||||
|
if (tls->keylogfile)
|
||||||
|
fclose(tls->keylogfile);
|
||||||
strophe_free(tls->ctx, tls->channel_binding_data);
|
strophe_free(tls->ctx, tls->channel_binding_data);
|
||||||
SSL_free(tls->ssl);
|
SSL_free(tls->ssl);
|
||||||
X509_free(tls->client_cert);
|
X509_free(tls->client_cert);
|
||||||
@@ -727,7 +764,7 @@ void tls_free(tls_t *tls)
|
|||||||
xmpp_tlscert_t *tls_peer_cert(xmpp_conn_t *conn)
|
xmpp_tlscert_t *tls_peer_cert(xmpp_conn_t *conn)
|
||||||
{
|
{
|
||||||
if (conn && conn->tls && conn->tls->ssl) {
|
if (conn && conn->tls && conn->tls->ssl) {
|
||||||
X509 *cert = SSL_get_peer_certificate(conn->tls->ssl);
|
X509 *cert = STROPHE_SSL_get1_peer_certificate(conn->tls->ssl);
|
||||||
if (cert) {
|
if (cert) {
|
||||||
xmpp_tlscert_t *tlscert = _x509_to_tlscert(conn->ctx, cert);
|
xmpp_tlscert_t *tlscert = _x509_to_tlscert(conn->ctx, cert);
|
||||||
X509_free(cert);
|
X509_free(cert);
|
||||||
@@ -750,8 +787,9 @@ int tls_init_channel_binding(tls_t *tls,
|
|||||||
{
|
{
|
||||||
const char *label = NULL;
|
const char *label = NULL;
|
||||||
size_t labellen = 0;
|
size_t labellen = 0;
|
||||||
|
int ssl_version = SSL_version(tls->ssl);
|
||||||
|
|
||||||
switch (SSL_version(tls->ssl)) {
|
switch (ssl_version) {
|
||||||
case SSL3_VERSION:
|
case SSL3_VERSION:
|
||||||
*binding_prefix = "tls-unique";
|
*binding_prefix = "tls-unique";
|
||||||
*binding_prefix_len = strlen("tls-unique");
|
*binding_prefix_len = strlen("tls-unique");
|
||||||
@@ -774,7 +812,7 @@ int tls_init_channel_binding(tls_t *tls,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
strophe_error(tls->ctx, "tls", "Unsupported TLS Version: %s",
|
strophe_error(tls->ctx, "tls", "Unsupported TLS/SSL Version: %s",
|
||||||
SSL_get_version(tls->ssl));
|
SSL_get_version(tls->ssl));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -785,11 +823,28 @@ int tls_init_channel_binding(tls_t *tls,
|
|||||||
if (!tls->channel_binding_data)
|
if (!tls->channel_binding_data)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (SSL_export_keying_material(tls->ssl, tls->channel_binding_data,
|
if (ssl_version <= TLS1_2_VERSION) {
|
||||||
tls->channel_binding_size, label, labellen,
|
size_t len;
|
||||||
NULL, 0, 0) != 1) {
|
if (SSL_session_reused(tls->ssl)) {
|
||||||
strophe_error(tls->ctx, "tls", "Could not get channel binding data");
|
len = SSL_get_peer_finished(tls->ssl, tls->channel_binding_data,
|
||||||
return -1;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -981,7 +1036,7 @@ static void _tls_dump_cert_info(tls_t *tls)
|
|||||||
X509 *cert;
|
X509 *cert;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
cert = SSL_get_peer_certificate(tls->ssl);
|
cert = STROPHE_SSL_get1_peer_certificate(tls->ssl);
|
||||||
if (cert == NULL)
|
if (cert == NULL)
|
||||||
strophe_debug(tls->ctx, "tls", "Certificate was not presented by peer");
|
strophe_debug(tls->ctx, "tls", "Certificate was not presented by peer");
|
||||||
else {
|
else {
|
||||||
|
|||||||
110
strophe.h
110
strophe.h
@@ -208,14 +208,6 @@ typedef struct _xmpp_sm_t xmpp_sm_state_t;
|
|||||||
* Only enable this flag if you know what you're doing.
|
* Only enable this flag if you know what you're doing.
|
||||||
*/
|
*/
|
||||||
#define XMPP_CONN_FLAG_COMPRESSION_DONT_RESET (1UL << 7)
|
#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 */
|
/* connect callback */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -379,37 +371,70 @@ typedef int (*xmpp_sockopt_callback)(xmpp_conn_t *conn, void *sock);
|
|||||||
/* an example callback that sets basic keepalive parameters */
|
/* an example callback that sets basic keepalive parameters */
|
||||||
int xmpp_sockopt_cb_keepalive(xmpp_conn_t *conn, void *sock);
|
int xmpp_sockopt_cb_keepalive(xmpp_conn_t *conn, void *sock);
|
||||||
|
|
||||||
void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text);
|
|
||||||
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx);
|
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx);
|
||||||
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn);
|
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn);
|
||||||
int xmpp_conn_release(xmpp_conn_t *conn);
|
int xmpp_conn_release(xmpp_conn_t *conn);
|
||||||
|
|
||||||
|
/** Connection settings
|
||||||
|
*/
|
||||||
|
typedef enum xmpp_conn_setting_t {
|
||||||
|
/* String values */
|
||||||
|
XMPP_SETTING_JID = 0x0, /**< JID */
|
||||||
|
XMPP_SETTING_PASS, /**< Password */
|
||||||
|
XMPP_SETTING_CAFILE, /**< CAfile */
|
||||||
|
XMPP_SETTING_CAPATH, /**< CApath */
|
||||||
|
XMPP_SETTING_CLIENT_CERT, /**< Client Certificate */
|
||||||
|
XMPP_SETTING_CLIENT_KEY, /**< Key of Client Certificate */
|
||||||
|
|
||||||
|
/* Int values */
|
||||||
|
XMPP_SETTING_PASSWORD_RETRIES = 0x40, /**< Number of retry attempts to
|
||||||
|
decrypt a private key file. */
|
||||||
|
XMPP_SETTING_COMPRESSION_LEVEL, /**< Compression level. */
|
||||||
|
|
||||||
|
/* Pointer values */
|
||||||
|
XMPP_SETTING_PASSWORD_CALLBACK_USERDATA = 0x80, /**< Userdata for password
|
||||||
|
callback function */
|
||||||
|
|
||||||
|
/* Functionpointer values */
|
||||||
|
XMPP_SETTING_PASSWORD_CALLBACK = 0xC0, /**< Callback function to retrieve
|
||||||
|
password for key file. */
|
||||||
|
XMPP_SETTING_CERTFAIL_HANDLER, /**< Handler function when certificate chain
|
||||||
|
can't be verified */
|
||||||
|
XMPP_SETTING_SOCKOPT_CALLBACK, /**< Callback function when a new socket is
|
||||||
|
created. */
|
||||||
|
} xmpp_conn_setting_t;
|
||||||
|
|
||||||
|
void xmpp_conn_set_int(xmpp_conn_t *conn,
|
||||||
|
xmpp_conn_setting_t setting,
|
||||||
|
int value);
|
||||||
|
void xmpp_conn_set_string(xmpp_conn_t *conn,
|
||||||
|
xmpp_conn_setting_t setting,
|
||||||
|
const char *value);
|
||||||
|
void xmpp_conn_set_pointer(xmpp_conn_t *conn,
|
||||||
|
xmpp_conn_setting_t setting,
|
||||||
|
void *value);
|
||||||
|
/* Provide a wrapper macro, so users don't have to cast their function pointer
|
||||||
|
* type manually. */
|
||||||
|
typedef int (*xmpp_conn_pfn_t)();
|
||||||
|
#define xmpp_conn_set_functionpointer(c, s, p) \
|
||||||
|
do { \
|
||||||
|
xmpp_conn_set_functionpointer_impl(c, s, (xmpp_conn_pfn_t)p); \
|
||||||
|
} while (0)
|
||||||
|
void xmpp_conn_set_functionpointer_impl(xmpp_conn_t *conn,
|
||||||
|
xmpp_conn_setting_t setting,
|
||||||
|
xmpp_conn_pfn_t pfn);
|
||||||
|
|
||||||
long xmpp_conn_get_flags(const xmpp_conn_t *conn);
|
long xmpp_conn_get_flags(const xmpp_conn_t *conn);
|
||||||
int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags);
|
int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags);
|
||||||
const char *xmpp_conn_get_jid(const xmpp_conn_t *conn);
|
const char *xmpp_conn_get_jid(const xmpp_conn_t *conn);
|
||||||
const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *conn);
|
const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *conn);
|
||||||
void xmpp_conn_set_jid(xmpp_conn_t *conn, const char *jid);
|
|
||||||
void xmpp_conn_set_cafile(xmpp_conn_t *const conn, const char *path);
|
|
||||||
void xmpp_conn_set_capath(xmpp_conn_t *const conn, const char *path);
|
|
||||||
void xmpp_conn_set_certfail_handler(xmpp_conn_t *const conn,
|
|
||||||
xmpp_certfail_handler hndl);
|
|
||||||
xmpp_tlscert_t *xmpp_conn_get_peer_cert(xmpp_conn_t *const conn);
|
xmpp_tlscert_t *xmpp_conn_get_peer_cert(xmpp_conn_t *const conn);
|
||||||
void xmpp_conn_set_password_callback(xmpp_conn_t *conn,
|
|
||||||
xmpp_password_callback cb,
|
|
||||||
void *userdata);
|
|
||||||
void xmpp_conn_set_password_retries(xmpp_conn_t *conn, unsigned int retries);
|
|
||||||
const char *xmpp_conn_get_keyfile(const xmpp_conn_t *conn);
|
const char *xmpp_conn_get_keyfile(const xmpp_conn_t *conn);
|
||||||
void xmpp_conn_set_client_cert(xmpp_conn_t *conn,
|
|
||||||
const char *cert,
|
|
||||||
const char *key);
|
|
||||||
unsigned int xmpp_conn_cert_xmppaddr_num(xmpp_conn_t *conn);
|
unsigned int xmpp_conn_cert_xmppaddr_num(xmpp_conn_t *conn);
|
||||||
char *xmpp_conn_cert_xmppaddr(xmpp_conn_t *conn, unsigned int n);
|
char *xmpp_conn_cert_xmppaddr(xmpp_conn_t *conn, unsigned int n);
|
||||||
const char *xmpp_conn_get_pass(const xmpp_conn_t *conn);
|
const char *xmpp_conn_get_pass(const xmpp_conn_t *conn);
|
||||||
void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass);
|
|
||||||
xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t *conn);
|
xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t *conn);
|
||||||
int xmpp_conn_is_secured(xmpp_conn_t *conn);
|
int xmpp_conn_is_secured(xmpp_conn_t *conn);
|
||||||
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
|
|
||||||
xmpp_sockopt_callback callback);
|
|
||||||
int xmpp_conn_is_connecting(xmpp_conn_t *conn);
|
int xmpp_conn_is_connecting(xmpp_conn_t *conn);
|
||||||
int xmpp_conn_is_connected(xmpp_conn_t *conn);
|
int xmpp_conn_is_connected(xmpp_conn_t *conn);
|
||||||
int xmpp_conn_is_disconnected(xmpp_conn_t *conn);
|
int xmpp_conn_is_disconnected(xmpp_conn_t *conn);
|
||||||
@@ -453,6 +478,7 @@ int xmpp_conn_tls_start(xmpp_conn_t *conn);
|
|||||||
void xmpp_disconnect(xmpp_conn_t *conn);
|
void xmpp_disconnect(xmpp_conn_t *conn);
|
||||||
|
|
||||||
void xmpp_send(xmpp_conn_t *conn, xmpp_stanza_t *stanza);
|
void xmpp_send(xmpp_conn_t *conn, xmpp_stanza_t *stanza);
|
||||||
|
void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text);
|
||||||
|
|
||||||
void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...);
|
void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...);
|
||||||
void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len);
|
void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len);
|
||||||
@@ -715,11 +741,19 @@ 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);
|
void xmpp_rand_nonce(xmpp_rand_t *rand, char *output, size_t len);
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Formerly "private but exported" functions made public for now to announce
|
* Formerly "private but exported" functions made public for now to announce
|
||||||
* deprecation */
|
* deprecation */
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#if !defined(XMPP_DEPRECATED)
|
||||||
|
/**
|
||||||
|
* 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 defined(__GNUC__)
|
||||||
#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
|
#if (__GNUC__ * 100 + __GNUC_MINOR__ >= 405)
|
||||||
#define XMPP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x)))
|
#define XMPP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x)))
|
||||||
@@ -731,6 +765,7 @@ void xmpp_rand_nonce(xmpp_rand_t *rand, char *output, size_t len);
|
|||||||
#else
|
#else
|
||||||
#define XMPP_DEPRECATED(x)
|
#define XMPP_DEPRECATED(x)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
XMPP_DEPRECATED(internal) void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size);
|
XMPP_DEPRECATED(internal) void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size);
|
||||||
XMPP_DEPRECATED(internal)
|
XMPP_DEPRECATED(internal)
|
||||||
@@ -770,6 +805,31 @@ void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval);
|
|||||||
XMPP_DEPRECATED(xmpp_conn_set_flags)
|
XMPP_DEPRECATED(xmpp_conn_set_flags)
|
||||||
void xmpp_conn_disable_tls(xmpp_conn_t *conn);
|
void xmpp_conn_disable_tls(xmpp_conn_t *conn);
|
||||||
|
|
||||||
|
XMPP_DEPRECATED(xmpp_conn_set_string)
|
||||||
|
void xmpp_conn_set_jid(xmpp_conn_t *conn, const char *jid);
|
||||||
|
XMPP_DEPRECATED(xmpp_conn_set_string)
|
||||||
|
void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass);
|
||||||
|
XMPP_DEPRECATED(xmpp_conn_set_string)
|
||||||
|
void xmpp_conn_set_cafile(xmpp_conn_t *const conn, const char *path);
|
||||||
|
XMPP_DEPRECATED(xmpp_conn_set_string)
|
||||||
|
void xmpp_conn_set_capath(xmpp_conn_t *const conn, const char *path);
|
||||||
|
XMPP_DEPRECATED(xmpp_conn_set_string)
|
||||||
|
void xmpp_conn_set_client_cert(xmpp_conn_t *conn,
|
||||||
|
const char *cert,
|
||||||
|
const char *key);
|
||||||
|
XMPP_DEPRECATED(xmpp_conn_set_int)
|
||||||
|
void xmpp_conn_set_password_retries(xmpp_conn_t *conn, unsigned int retries);
|
||||||
|
XMPP_DEPRECATED(xmpp_conn_set_functionpointer)
|
||||||
|
void xmpp_conn_set_password_callback(xmpp_conn_t *conn,
|
||||||
|
xmpp_password_callback cb,
|
||||||
|
void *userdata);
|
||||||
|
XMPP_DEPRECATED(xmpp_conn_set_functionpointer)
|
||||||
|
void xmpp_conn_set_certfail_handler(xmpp_conn_t *const conn,
|
||||||
|
xmpp_certfail_handler hndl);
|
||||||
|
XMPP_DEPRECATED(xmpp_conn_set_functionpointer)
|
||||||
|
void xmpp_conn_set_sockopt_callback(xmpp_conn_t *conn,
|
||||||
|
xmpp_sockopt_callback callback);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#undef HAVE_VSNPRINTF
|
#undef HAVE_VSNPRINTF
|
||||||
#undef HAVE_SNPRINTF
|
#undef HAVE_SNPRINTF
|
||||||
@@ -28,7 +29,14 @@ int main(void)
|
|||||||
char *int_fmt[] = {"%-1.5d", "%1.5d", "%123.9d", "%5.5d",
|
char *int_fmt[] = {"%-1.5d", "%1.5d", "%123.9d", "%5.5d",
|
||||||
"%10.5d", "% 10.5d", "%+22.33d", "%01.3d",
|
"%10.5d", "% 10.5d", "%+22.33d", "%01.3d",
|
||||||
"%4d", "0x%x", "0x%04x", NULL};
|
"%4d", "0x%x", "0x%04x", NULL};
|
||||||
long int_nums[] = {-1, 134, 91340, 341, 0203, 0x76543210, 0};
|
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};
|
||||||
int x, y;
|
int x, y;
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
@@ -60,6 +68,19 @@ int main(void)
|
|||||||
}
|
}
|
||||||
num++;
|
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);
|
printf("%d tests failed out of %d.\n", fail, num);
|
||||||
return fail != 0 ? 1 : 0;
|
return fail != 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ static void test_stanza_error(xmpp_ctx_t *ctx)
|
|||||||
xmpp_stanza_reply_error(stanza, "cancel", "service-unavailable", NULL);
|
xmpp_stanza_reply_error(stanza, "cancel", "service-unavailable", NULL);
|
||||||
assert(error != NULL);
|
assert(error != NULL);
|
||||||
mood = xmpp_stanza_new_from_string(ctx, str_mood);
|
mood = xmpp_stanza_new_from_string(ctx, str_mood);
|
||||||
assert(stanza != NULL);
|
assert(mood != NULL);
|
||||||
|
|
||||||
assert(xmpp_stanza_get_to(error) != NULL);
|
assert(xmpp_stanza_get_to(error) != NULL);
|
||||||
COMPARE("romeo@montague.lit/home", xmpp_stanza_get_to(error));
|
COMPARE("romeo@montague.lit/home", xmpp_stanza_get_to(error));
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#define XMPP_DEPRECATED(x)
|
||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
@@ -41,12 +42,14 @@ int main()
|
|||||||
} client_cert[] = {
|
} client_cert[] = {
|
||||||
{0, "tests/cert.pem", "tests/key.pem"},
|
{0, "tests/cert.pem", "tests/key.pem"},
|
||||||
{1, "tests/cert.pem", "tests/key_encrypted.pem"},
|
{1, "tests/cert.pem", "tests/key_encrypted.pem"},
|
||||||
{0, NULL, "tests/cert.emptypass.pfx"},
|
|
||||||
{0, NULL, "tests/cert.nopass.pfx"},
|
|
||||||
{1, NULL, "tests/cert.pfx"},
|
|
||||||
{0, "tests/cert.emptypass.pfx", NULL},
|
{0, "tests/cert.emptypass.pfx", NULL},
|
||||||
{0, "tests/cert.nopass.pfx", NULL},
|
{0, "tests/cert.nopass.pfx", NULL},
|
||||||
{1, "tests/cert.pfx", NULL},
|
{1, "tests/cert.pfx", NULL},
|
||||||
|
/* Backward compatibility checks for change introduced in #208
|
||||||
|
* To be removed, once xmpp_conn_set_client_cert() is gone */
|
||||||
|
{0, NULL, "tests/cert.emptypass.pfx"},
|
||||||
|
{0, NULL, "tests/cert.nopass.pfx"},
|
||||||
|
{1, NULL, "tests/cert.pfx"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *srcdir;
|
const char *srcdir;
|
||||||
@@ -78,9 +81,15 @@ int main()
|
|||||||
keyfile = NULL;
|
keyfile = NULL;
|
||||||
|
|
||||||
if (client_cert[m].needs_callback)
|
if (client_cert[m].needs_callback)
|
||||||
xmpp_conn_set_password_callback(conn, password_callback, NULL);
|
xmpp_conn_set_functionpointer(conn, XMPP_SETTING_PASSWORD_CALLBACK,
|
||||||
|
password_callback);
|
||||||
|
|
||||||
xmpp_conn_set_client_cert(conn, certfile, keyfile);
|
if (certfile) {
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_CERT, certfile);
|
||||||
|
xmpp_conn_set_string(conn, XMPP_SETTING_CLIENT_KEY, keyfile);
|
||||||
|
} else {
|
||||||
|
xmpp_conn_set_client_cert(conn, certfile, keyfile);
|
||||||
|
}
|
||||||
|
|
||||||
xmppaddr_num[0] = '0' + xmpp_conn_cert_xmppaddr_num(conn);
|
xmppaddr_num[0] = '0' + xmpp_conn_cert_xmppaddr_num(conn);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user