1 Commits

Author SHA1 Message Date
Dmitry Podgorny
070a64d9d5 WIP Unify error codes returned to the connection handler
Error argument in the connection handler is not always set and in some
cases provides meaningless values. For example, every TLS module returns
its specific error codes.

Current solution unifies error codes and allows to distinguish between
different types of disconnection.

Fixes #123.
2020-09-16 02:28:37 +03:00
53 changed files with 919 additions and 2628 deletions

1
.gitignore vendored
View File

@@ -61,7 +61,6 @@ tests/test_snprintf
tests/test_sock tests/test_sock
tests/test_stanza tests/test_stanza
tests/test_string tests/test_string
tests/test_xmppaddr
m4/ m4/
libstrophe.project libstrophe.project
libs/ libs/

View File

@@ -1,26 +1,24 @@
language: c language: c
dist: focal
install: install:
- sudo apt-get update - sudo apt-get update
- sudo apt-get -y install libtool pkg-config libexpat1-dev libxml2-dev libssl-dev libgnutls28-dev libc-ares-dev dos2unix - sudo apt-get -y install libtool pkg-config libexpat1-dev libxml2-dev libssl-dev libc-ares-dev dos2unix
stages: stages:
- style - style
- test - test
before_script:
- ./bootstrap.sh
env: env:
- CONFIGURE_OPT="--without-libxml2" - CONFIGURE_OPT="--without-libxml2"
- CONFIGURE_OPT="--with-libxml2" - CONFIGURE_OPT="--with-libxml2"
- CONFIGURE_OPT="--with-gnutls"
- CONFIGURE_OPT="--disable-tls" - CONFIGURE_OPT="--disable-tls"
- CONFIGURE_OPT="--enable-cares" - CONFIGURE_OPT="--enable-cares"
- CONFIGURE_OPT="PKG_CONFIG_PATH=${HOME}/libressl/lib/pkgconfig" LIBRESSL=yes LIBRESSL_COMMIT="v3.1.4" script: ./configure ${CONFIGURE_OPT} CFLAGS="-Werror" && make && make check
- CONFIGURE_OPT="PKG_CONFIG_PATH=${HOME}/libressl/lib/pkgconfig" LIBRESSL=yes LIBRESSL_COMMIT="v2.1.7"
before_script: ./travis/before_script.sh
script: ./bootstrap.sh && ./configure ${CONFIGURE_OPT} CFLAGS="-Werror -g3" && make && make check
jobs: jobs:
include: include:
- stage: style - stage: style
name: "Check coding style" name: "Check code style"
env: CONFIGURE_OPT="" script: ./configure && make format && git diff --exit-code
script: ./bootstrap.sh && ./configure && make format && git diff --exit-code env:
allow_failures: - CONFIGURE_OPT=""
- stage: style matrix:
fast_finish: true

View File

@@ -1,31 +1,3 @@
0.11.0
- SASL EXTERNAL support (XEP-0178)
- Client certificate can be provided for TLS negotiation. If the
certificate contains a single xmppAddr and JID is not provided with
xmpp_conn_set_jid(), the xmppAddr is chosen as JID
- <stream> element contains "from" attribute over TLS connections now
- GnuTLS can be selected optionally with configure script
- Support for manual certificate verification
- New API:
- xmpp_conn_set_client_cert()
- xmpp_conn_cert_xmppaddr_num()
- xmpp_conn_cert_xmppaddr()
- xmpp_conn_set_cafile()
- xmpp_conn_set_capath()
- xmpp_conn_set_certfail_handler()
- xmpp_conn_get_peer_cert()
- xmpp_tlscert_get_ctx()
- xmpp_tlscert_get_conn()
- xmpp_tlscert_get_pem()
- xmpp_tlscert_get_dnsname()
- xmpp_tlscert_get_string()
- xmpp_tlscert_get_description()
- xmpp_tlscert_free()
0.10.1
- Fixed compilation error when LibreSSL is used
- Fixed crash when NULL is provided as password
0.10.0 0.10.0
- Coding style has been unified - Coding style has been unified
- SCRAM-SHA-256 and SCRAM-SHA-512 support - SCRAM-SHA-256 and SCRAM-SHA-512 support

View File

@@ -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.11 PROJECT_NUMBER = 0.9
# 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
@@ -1047,7 +1047,7 @@ HTML_HEADER =
# that doxygen normally uses. # that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER = HTML_FOOTER = docs/footer.html
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of # sheet that is used by each HTML page. It can be used to fine-tune the look of

View File

@@ -5,13 +5,8 @@ ACLOCAL_AMFLAGS = -I m4
PARSER_CFLAGS=@PARSER_CFLAGS@ PARSER_CFLAGS=@PARSER_CFLAGS@
PARSER_LIBS=@PARSER_LIBS@ PARSER_LIBS=@PARSER_LIBS@
if TLS_WITH_GNUTLS
SSL_CFLAGS = @gnutls_CFLAGS@
SSL_LIBS = @gnutls_LIBS@
else
SSL_CFLAGS = @openssl_CFLAGS@ SSL_CFLAGS = @openssl_CFLAGS@
SSL_LIBS = @openssl_LIBS@ SSL_LIBS = @openssl_LIBS@
endif
RESOLV_CFLAGS = @RESOLV_CFLAGS@ RESOLV_CFLAGS = @RESOLV_CFLAGS@
RESOLV_LIBS = @RESOLV_LIBS@ RESOLV_LIBS = @RESOLV_LIBS@
@@ -48,7 +43,6 @@ libstrophe_la_SOURCES = \
src/snprintf.c \ src/snprintf.c \
src/sock.c \ src/sock.c \
src/stanza.c \ src/stanza.c \
src/tls.c \
src/util.c \ src/util.c \
src/uuid.c src/uuid.c
libstrophe_la_SOURCES += \ libstrophe_la_SOURCES += \
@@ -73,12 +67,8 @@ libstrophe_la_SOURCES += \
if DISABLE_TLS if DISABLE_TLS
libstrophe_la_SOURCES += src/tls_dummy.c libstrophe_la_SOURCES += src/tls_dummy.c
else else
if TLS_WITH_GNUTLS
libstrophe_la_SOURCES += src/tls_gnutls.c
else
libstrophe_la_SOURCES += src/tls_openssl.c libstrophe_la_SOURCES += src/tls_openssl.c
endif endif
endif
if PARSER_EXPAT if PARSER_EXPAT
libstrophe_la_SOURCES += src/parser_expat.c libstrophe_la_SOURCES += src/parser_expat.c
@@ -98,18 +88,14 @@ EXTRA_DIST = \
MIT-LICENSE.txt \ MIT-LICENSE.txt \
bootstrap.sh \ bootstrap.sh \
build-android.sh \ build-android.sh \
docs/footer.html \
examples/README.md \ examples/README.md \
jni/Android.mk \ jni/Android.mk \
jni/Application.mk \ jni/Application.mk \
src/tls_gnutls.c \
src/tls_schannel.c \ src/tls_schannel.c \
tests/res_query_dump.c tests/res_query_dump.c
if TLS_WITH_GNUTLS
EXTRA_DIST += src/tls_openssl.c
else
EXTRA_DIST += src/tls_gnutls.c
endif
## Examples ## Examples
noinst_PROGRAMS = \ noinst_PROGRAMS = \
examples/active \ examples/active \
@@ -165,22 +151,8 @@ TESTS = \
tests/test_stanza \ tests/test_stanza \
tests/test_resolver tests/test_resolver
if !DISABLE_TLS
TESTS += tests/test_xmppaddr
endif
check_PROGRAMS = $(TESTS) check_PROGRAMS = $(TESTS)
if FUZZ
check_PROGRAMS += tests/test_fuzz
tests_test_fuzz_SOURCES = tests/test_fuzz.c
tests_test_fuzz_CFLAGS = -fsanitize=fuzzer,address $(PARSER_CFLAGS) $(STROPHE_FLAGS) \
-I$(top_srcdir)/src
tests_test_fuzz_LDADD = $(STROPHE_LIBS)
tests_test_fuzz_LDFLAGS = -static
endif
tests_check_parser_SOURCES = tests/check_parser.c tests/test.h tests_check_parser_SOURCES = tests/check_parser.c tests/test.h
tests_check_parser_CFLAGS = $(PARSER_CFLAGS) $(STROPHE_FLAGS) \ tests_check_parser_CFLAGS = $(PARSER_CFLAGS) $(STROPHE_FLAGS) \
-I$(top_srcdir)/src -I$(top_srcdir)/src
@@ -239,16 +211,11 @@ tests_test_string_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src
tests_test_string_LDADD = $(STROPHE_LIBS) tests_test_string_LDADD = $(STROPHE_LIBS)
tests_test_string_LDFLAGS = -static tests_test_string_LDFLAGS = -static
tests_test_stanza_SOURCES = tests/test_stanza.c tests/test.h tests_test_stanza_SOURCES = tests/test_stanza.c
tests_test_stanza_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src tests_test_stanza_CFLAGS = $(STROPHE_FLAGS)
tests_test_stanza_LDADD = $(STROPHE_LIBS) tests_test_stanza_LDADD = $(STROPHE_LIBS)
tests_test_stanza_LDFLAGS = -static tests_test_stanza_LDFLAGS = -static
tests_test_xmppaddr_SOURCES = tests/test_xmppaddr.c
tests_test_xmppaddr_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src
tests_test_xmppaddr_LDADD = $(STROPHE_LIBS)
tests_test_xmppaddr_LDFLAGS = -static
format: format:
@echo " * run clang-format on all sources" @echo " * run clang-format on all sources"
@dos2unix -q src/*.[ch] *.h tests/*.[ch] examples/*.c @dos2unix -q src/*.[ch] *.h tests/*.[ch] examples/*.c

View File

@@ -8,7 +8,6 @@ BinPackParameters: 'false'
BreakBeforeBraces: Linux BreakBeforeBraces: Linux
ColumnLimit: '80' ColumnLimit: '80'
DerivePointerAlignment: 'false' DerivePointerAlignment: 'false'
IndentGotoLabels: false
IndentWidth: '4' IndentWidth: '4'
PointerAlignment: Right PointerAlignment: Right
SortIncludes: 'false' SortIncludes: 'false'

View File

@@ -1,4 +1,4 @@
AC_INIT([libstrophe], [0.11.0], [jack@metajack.im]) AC_INIT([libstrophe], [0.10.0], [jack@metajack.im])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([foreign]) AM_INIT_AUTOMAKE([foreign])
LT_INIT([dlopen]) LT_INIT([dlopen])
@@ -26,39 +26,16 @@ AS_CASE([$PLATFORM],
AC_ARG_WITH([libxml2], AC_ARG_WITH([libxml2],
[AS_HELP_STRING([--with-libxml2], [use libxml2 for XML parsing, expat is the default])]) [AS_HELP_STRING([--with-libxml2], [use libxml2 for XML parsing, expat is the default])])
AC_ARG_WITH([gnutls],
[AS_HELP_STRING([--with-gnutls], [use GnuTLS for TLS support, OpenSSL is the default])])
AC_ARG_ENABLE([tls], AC_ARG_ENABLE([tls],
[AS_HELP_STRING([--disable-tls], [disable TLS support])]) [AS_HELP_STRING([--disable-tls], [disable TLS support])])
AC_ARG_ENABLE([cares], AC_ARG_ENABLE([cares],
[AS_HELP_STRING([--enable-cares], [use c-ares for DNS resolution])]) [AS_HELP_STRING([--enable-cares], [use c-ares for DNS resolution])])
AC_ARG_ENABLE([fuzzing],
[AS_HELP_STRING([--enable-fuzzing], [turn on fuzzing test])],
[case "${enableval}" in yes) fuzzing=true ;; no) fuzzing=false ;; *) AC_MSG_ERROR([bad value ${enableval} for --enable-fuzzing]) ;; esac],[fuzzing=false])
AM_CONDITIONAL([FUZZ], [test x$fuzzing = xtrue])
if test "x$enable_fuzzing" = "xyes" ; then
if test "x$CC" != "xclang" ; then
AC_MSG_ERROR(["You need to set CC=clang to use --enable-fuzzing, used $CC"])
fi
fi
AC_SEARCH_LIBS([socket], [network socket]) AC_SEARCH_LIBS([socket], [network socket])
AC_CHECK_FUNCS([snprintf vsnprintf]) AC_CHECK_FUNCS([snprintf vsnprintf])
AC_CHECK_DECLS([va_copy], [], [], [#include <stdarg.h>]) AC_CHECK_DECLS([va_copy], [], [], [#include <stdarg.h>])
if test "x$enable_tls" != xno -a "x$with_gnutls" == xyes; then if test "x$enable_tls" != xno; then
PKG_CHECK_MODULES([gnutls], [gnutls],
[PC_REQUIRES="gnutls ${PC_REQUIRES}"],
[AC_CHECK_HEADER([gnutls/gnutls.h],
[
gnutls_LIBS="-lgnutls"
PC_LIBS="${gnutls_LIBS} ${PC_LIBS}"
],
[AC_MSG_ERROR([gnutls not found; gnutls required])]
)])
elif test "x$enable_tls" != xno; then
PKG_CHECK_MODULES([openssl], [openssl], PKG_CHECK_MODULES([openssl], [openssl],
[PC_REQUIRES="openssl ${PC_REQUIRES}"], [PC_REQUIRES="openssl ${PC_REQUIRES}"],
[AC_CHECK_HEADER([openssl/ssl.h], [AC_CHECK_HEADER([openssl/ssl.h],
@@ -168,7 +145,6 @@ m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR],
AM_CONDITIONAL([PARSER_EXPAT], [test x$with_parser != xlibxml2]) AM_CONDITIONAL([PARSER_EXPAT], [test x$with_parser != xlibxml2])
AM_CONDITIONAL([DISABLE_TLS], [test x$enable_tls = xno]) AM_CONDITIONAL([DISABLE_TLS], [test x$enable_tls = xno])
AM_CONDITIONAL([TLS_WITH_GNUTLS], [test x$with_gnutls = xyes])
AC_SUBST([PC_REQUIRES], [${PC_REQUIRES}]) AC_SUBST([PC_REQUIRES], [${PC_REQUIRES}])
AC_SUBST([PC_CFLAGS], [${PC_CFLAGS}]) AC_SUBST([PC_CFLAGS], [${PC_CFLAGS}])

View File

2
docs/footer.html Normal file
View File

@@ -0,0 +1,2 @@
</body>
</html>

View File

@@ -19,7 +19,9 @@
#include <strophe.h> #include <strophe.h>
int handle_reply(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) int handle_reply(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza,
void *const userdata)
{ {
xmpp_stanza_t *query, *item; xmpp_stanza_t *query, *item;
const char *type; const char *type;
@@ -44,11 +46,11 @@ int handle_reply(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
return 0; return 0;
} }
void conn_handler(xmpp_conn_t *conn, void conn_handler(xmpp_conn_t *const conn,
xmpp_conn_event_t status, const xmpp_conn_event_t status,
int error, const int error,
xmpp_stream_error_t *stream_error, xmpp_stream_error_t *const stream_error,
void *userdata) void *const userdata)
{ {
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
xmpp_stanza_t *iq, *query; xmpp_stanza_t *iq, *query;

View File

@@ -10,7 +10,6 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <strophe.h> #include <strophe.h>
@@ -19,26 +18,12 @@
#define KA_TIMEOUT 60 #define KA_TIMEOUT 60
#define KA_INTERVAL 1 #define KA_INTERVAL 1
static void print_tlscert(const xmpp_tlscert_t *cert)
{
const char *name;
size_t n;
for (n = 0; n < (unsigned)XMPP_CERT_ELEMENT_MAX; ++n) {
printf("\t%32s: %s\n", xmpp_tlscert_get_description(n),
xmpp_tlscert_get_string(cert, n));
}
n = 0;
while ((name = xmpp_tlscert_get_dnsname(cert, n++)) != NULL)
printf("\t%32s: %s\n", "dnsName", name);
printf("PEM:\n%s\n", xmpp_tlscert_get_pem(cert));
}
/* define a handler for connection events */ /* define a handler for connection events */
static void conn_handler(xmpp_conn_t *conn, void conn_handler(xmpp_conn_t *const conn,
xmpp_conn_event_t status, const xmpp_conn_event_t status,
int error, const int error,
xmpp_stream_error_t *stream_error, xmpp_stream_error_t *const stream_error,
void *userdata) void *const userdata)
{ {
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
int secured; int secured;
@@ -51,79 +36,44 @@ static void conn_handler(xmpp_conn_t *conn,
secured = xmpp_conn_is_secured(conn); secured = xmpp_conn_is_secured(conn);
fprintf(stderr, "DEBUG: connection is %s.\n", fprintf(stderr, "DEBUG: connection is %s.\n",
secured ? "secured" : "NOT secured"); secured ? "secured" : "NOT secured");
if (secured) {
xmpp_tlscert_t *cert = xmpp_conn_get_peer_cert(conn);
print_tlscert(cert);
xmpp_tlscert_free(cert);
}
xmpp_disconnect(conn); xmpp_disconnect(conn);
} else { } else {
fprintf(stderr, "DEBUG: disconnected\n"); switch (error) {
case XMPP_EOK:
fprintf(stderr, "DEBUG: disconnected successfully.\n");
break;
case XMPP_EINVOP:
/*
* This may happen when the requested functionality is not
* supported or some data is not provided when it is required (e.g.
* resource part).
*/
fprintf(stderr, "DEBUG: disconnected, invalid operation.\n");
break;
case XMPP_ECERT:
/*
* In this case, application can reconnect with
* XMPP_CONN_FLAG_TRUST_TLS if user permits.
*/
fprintf(stderr, "DEBUG: disconnected, invalid TLS certificate.\n");
}
xmpp_stop(ctx); xmpp_stop(ctx);
} }
} }
static int certfail_handler(const xmpp_tlscert_t *cert,
const char *const errormsg)
{
char read_char[16] = {0};
printf("Received certificate can't be validated!\n");
printf("Reason: %s\n", errormsg);
print_tlscert(cert);
printf("Do you agree to connect?\n[y(es)|n(o)]: ");
fflush(stdout);
if (fgets(read_char, sizeof(read_char), stdin) == NULL) {
printf("fgets() failed\n");
return 0;
}
printf("\n");
return read_char[0] == 'y' || read_char[0] == 'Y';
}
static void usage(int exit_code)
{
fprintf(stderr,
"Usage: basic [options] [<host> [<port>]]\n\n"
"Options:\n"
" --jid <jid> The JID to use to authenticate.\n"
" --pass <pass> The password of the JID.\n"
" --tls-cert <cert> Path to client certificate.\n"
" --capath <path> Path to an additional CA trust store "
"(directory).\n"
" --cafile <path> Path to an additional CA trust store "
"(single file).\n"
" --tls-key <key> Path to private key.\n\n"
" --disable-tls Disable TLS.\n"
" --mandatory-tls Deny plaintext connection.\n"
" --trust-tls Trust TLS certificate.\n"
" --enable-certfail Enable certfail handler.\n"
" --legacy-ssl Use old style SSL.\n"
" --legacy-auth Allow legacy authentication.\n"
" --verbose Increase the verbosity level.\n"
" --tcp-keepalive Configure TCP keepalive.\n\n"
"Note: --disable-tls conflicts with --mandatory-tls or "
"--legacy-ssl\n");
exit(exit_code);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
xmpp_ctx_t *ctx; xmpp_ctx_t *ctx;
xmpp_conn_t *conn; xmpp_conn_t *conn;
xmpp_log_t *log; xmpp_log_t *log;
char *jid = NULL, *password = NULL, *cert = NULL, *key = NULL, *host = NULL, char *jid, *pass, *host = NULL;
*capath = NULL, *cafile = NULL;
long flags = 0; long flags = 0;
int tcp_keepalive = 0, verbosity = 0, certfail = 0; int tcp_keepalive = 0;
int i; int i;
unsigned long port = 0;
/* take a jid and password on the command line */ /* take a jid and password on the command line */
for (i = 1; i < argc; ++i) { for (i = 1; i < argc; ++i) {
if (strcmp(argv[i], "--help") == 0) if (strcmp(argv[i], "--disable-tls") == 0)
usage(0);
else if (strcmp(argv[i], "--disable-tls") == 0)
flags |= XMPP_CONN_FLAG_DISABLE_TLS; flags |= XMPP_CONN_FLAG_DISABLE_TLS;
else if (strcmp(argv[i], "--mandatory-tls") == 0) else if (strcmp(argv[i], "--mandatory-tls") == 0)
flags |= XMPP_CONN_FLAG_MANDATORY_TLS; flags |= XMPP_CONN_FLAG_MANDATORY_TLS;
@@ -133,35 +83,29 @@ int main(int argc, char **argv)
flags |= XMPP_CONN_FLAG_LEGACY_SSL; flags |= XMPP_CONN_FLAG_LEGACY_SSL;
else if (strcmp(argv[i], "--legacy-auth") == 0) else if (strcmp(argv[i], "--legacy-auth") == 0)
flags |= XMPP_CONN_FLAG_LEGACY_AUTH; flags |= XMPP_CONN_FLAG_LEGACY_AUTH;
else if (strcmp(argv[i], "--verbose") == 0)
verbosity++;
else if (strcmp(argv[i], "--tcp-keepalive") == 0) else if (strcmp(argv[i], "--tcp-keepalive") == 0)
tcp_keepalive = 1; tcp_keepalive = 1;
else if (strcmp(argv[i], "--enable-certfail") == 0)
certfail = 1;
else if ((strcmp(argv[i], "--jid") == 0) && (++i < argc))
jid = argv[i];
else if ((strcmp(argv[i], "--pass") == 0) && (++i < argc))
password = argv[i];
else if ((strcmp(argv[i], "--tls-cert") == 0) && (++i < argc))
cert = argv[i];
else if ((strcmp(argv[i], "--tls-key") == 0) && (++i < argc))
key = argv[i];
else if ((strcmp(argv[i], "--capath") == 0) && (++i < argc))
capath = argv[i];
else if ((strcmp(argv[i], "--cafile") == 0) && (++i < argc))
cafile = argv[i];
else else
break; break;
} }
if ((!jid && (!cert || !key)) || (argc - i) > 2) { if ((argc - i) < 2 || (argc - i) > 3) {
usage(1); fprintf(stderr, "Usage: basic [options] <jid> <pass> [<host>]\n\n"
"Options:\n"
" --disable-tls Disable TLS.\n"
" --mandatory-tls Deny plaintext connection.\n"
" --trust-tls Trust TLS certificate.\n"
" --legacy-ssl Use old style SSL.\n"
" --legacy-auth Allow legacy authentication.\n"
" --tcp-keepalive Configure TCP keepalive.\n\n"
"Note: --disable-tls conflicts with --mandatory-tls or "
"--legacy-ssl\n");
return 1;
} }
if (i < argc) jid = argv[i];
host = argv[i]; pass = argv[i + 1];
if (i + 1 < argc) if (i + 2 < argc)
port = strtoul(argv[i + 1], NULL, 0); host = argv[i + 2];
/* /*
* Note, this example doesn't handle errors. Applications should check * Note, this example doesn't handle errors. Applications should check
@@ -175,7 +119,6 @@ int main(int argc, char **argv)
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
/* create a context */ /* create a context */
ctx = xmpp_ctx_new(NULL, log); ctx = xmpp_ctx_new(NULL, log);
xmpp_ctx_set_verbosity(ctx, verbosity);
/* create a connection */ /* create a connection */
conn = xmpp_conn_new(ctx); conn = xmpp_conn_new(ctx);
@@ -187,28 +130,15 @@ int main(int argc, char **argv)
xmpp_conn_set_keepalive(conn, KA_TIMEOUT, KA_INTERVAL); xmpp_conn_set_keepalive(conn, KA_TIMEOUT, KA_INTERVAL);
/* setup authentication information */ /* setup authentication information */
if (cert && key) { xmpp_conn_set_jid(conn, jid);
xmpp_conn_set_client_cert(conn, cert, key); xmpp_conn_set_pass(conn, pass);
}
if (jid)
xmpp_conn_set_jid(conn, jid);
if (password)
xmpp_conn_set_pass(conn, password);
if (certfail)
xmpp_conn_set_certfail_handler(conn, certfail_handler);
if (capath)
xmpp_conn_set_capath(conn, capath);
if (cafile)
xmpp_conn_set_cafile(conn, cafile);
/* initiate connection */ /* initiate connection */
if (xmpp_connect_client(conn, host, port, conn_handler, ctx) == XMPP_EOK) { xmpp_connect_client(conn, host, 0, conn_handler, ctx);
/* enter the event loop - /* enter the event loop -
our connect handler will trigger an exit */ our connect handler will trigger an exit */
xmpp_run(ctx); xmpp_run(ctx);
}
/* release our connection and context */ /* release our connection and context */
xmpp_conn_release(conn); xmpp_conn_release(conn);

View File

@@ -22,7 +22,9 @@
#include <strophe.h> #include <strophe.h>
int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) int version_handler(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza,
void *const userdata)
{ {
xmpp_stanza_t *reply, *query, *name, *version, *text; xmpp_stanza_t *reply, *query, *name, *version, *text;
const char *ns; const char *ns;
@@ -68,7 +70,9 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
return 1; return 1;
} }
int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) int message_handler(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza,
void *const userdata)
{ {
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
xmpp_stanza_t *body, *reply; xmpp_stanza_t *body, *reply;
@@ -114,11 +118,11 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
} }
/* define a handler for connection events */ /* define a handler for connection events */
void conn_handler(xmpp_conn_t *conn, void conn_handler(xmpp_conn_t *const conn,
xmpp_conn_event_t status, const xmpp_conn_event_t status,
int error, const int error,
xmpp_stream_error_t *stream_error, xmpp_stream_error_t *const stream_error,
void *userdata) void *const userdata)
{ {
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;

View File

@@ -20,11 +20,11 @@
#include <strophe.h> #include <strophe.h>
/* define a handler for connection events */ /* define a handler for connection events */
void conn_handler(xmpp_conn_t *conn, void conn_handler(xmpp_conn_t *const conn,
xmpp_conn_event_t status, const xmpp_conn_event_t status,
int error, const int error,
xmpp_stream_error_t *stream_error, xmpp_stream_error_t *const stream_error,
void *userdata) void *const userdata)
{ {
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;

View File

@@ -102,7 +102,9 @@ iq_reg_send_form(xmpp_reg_t *reg, xmpp_conn_t *conn, xmpp_stanza_t *stanza)
} }
} }
static int iq_reg2_cb(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) static int iq_reg2_cb(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza,
void *const userdata)
{ {
const char *type; const char *type;
@@ -127,7 +129,9 @@ quit:
return 0; return 0;
} }
static int iq_reg_cb(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) static int iq_reg_cb(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza,
void *const userdata)
{ {
xmpp_reg_t *reg = (xmpp_reg_t *)userdata; xmpp_reg_t *reg = (xmpp_reg_t *)userdata;
xmpp_stanza_t *registered = NULL; xmpp_stanza_t *registered = NULL;
@@ -162,8 +166,9 @@ quit:
return 0; return 0;
} }
static int static int _handle_error(xmpp_conn_t *const conn,
_handle_error(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *const stanza,
void *const userdata)
{ {
(void)stanza; (void)stanza;
(void)userdata; (void)userdata;
@@ -174,9 +179,9 @@ _handle_error(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
return 0; return 0;
} }
static int _handle_proceedtls_default(xmpp_conn_t *conn, static int _handle_proceedtls_default(xmpp_conn_t *const conn,
xmpp_stanza_t *stanza, xmpp_stanza_t *const stanza,
void *userdata) void *const userdata)
{ {
const char *name = xmpp_stanza_get_name(stanza); const char *name = xmpp_stanza_get_name(stanza);
@@ -196,7 +201,8 @@ static int _handle_proceedtls_default(xmpp_conn_t *conn,
return 0; return 0;
} }
static int _handle_missing_features(xmpp_conn_t *conn, void *userdata) static int _handle_missing_features(xmpp_conn_t *const conn,
void *const userdata)
{ {
(void)userdata; (void)userdata;
@@ -206,8 +212,9 @@ static int _handle_missing_features(xmpp_conn_t *conn, void *userdata)
return 0; return 0;
} }
static int static int _handle_features(xmpp_conn_t *const conn,
_handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *const stanza,
void *const userdata)
{ {
xmpp_reg_t *reg = (xmpp_reg_t *)userdata; xmpp_reg_t *reg = (xmpp_reg_t *)userdata;
xmpp_ctx_t *ctx = reg->ctx; xmpp_ctx_t *ctx = reg->ctx;
@@ -258,11 +265,11 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
return 0; return 0;
} }
static void conn_handler(xmpp_conn_t *conn, static void conn_handler(xmpp_conn_t *const conn,
xmpp_conn_event_t status, const xmpp_conn_event_t status,
int error, const int error,
xmpp_stream_error_t *stream_error, xmpp_stream_error_t *const stream_error,
void *userdata) void *const userdata)
{ {
xmpp_reg_t *reg = (xmpp_reg_t *)userdata; xmpp_reg_t *reg = (xmpp_reg_t *)userdata;
int secured; int secured;

View File

@@ -18,7 +18,9 @@
#include <strophe.h> #include <strophe.h>
int handle_reply(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) int handle_reply(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza,
void *const userdata)
{ {
xmpp_stanza_t *query, *item; xmpp_stanza_t *query, *item;
const char *type, *name; const char *type, *name;
@@ -49,11 +51,11 @@ int handle_reply(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
return 0; return 0;
} }
void conn_handler(xmpp_conn_t *conn, void conn_handler(xmpp_conn_t *const conn,
xmpp_conn_event_t status, const xmpp_conn_event_t status,
int error, const int error,
xmpp_stream_error_t *stream_error, xmpp_stream_error_t *const stream_error,
void *userdata) void *const userdata)
{ {
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata; xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
xmpp_stanza_t *iq, *query; xmpp_stanza_t *iq, *query;

View File

@@ -160,7 +160,7 @@ exit:
return cb; return cb;
} }
static int timedout(xmpp_conn_t *conn, void *userdata) static int timedout(xmpp_conn_t *const conn, void *const userdata)
{ {
(void)userdata; (void)userdata;
@@ -170,7 +170,9 @@ static int timedout(xmpp_conn_t *conn, void *userdata)
return 0; return 0;
} }
static int recv_vcard(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) static int recv_vcard(xmpp_conn_t *const conn,
xmpp_stanza_t *const stanza,
void *const userdata)
{ {
vcard_t *vc = userdata; vcard_t *vc = userdata;
vcard_cb_t cb; vcard_cb_t cb;
@@ -215,11 +217,11 @@ static void send_vcard_req(xmpp_conn_t *conn, const char *to, const char *id)
xmpp_conn_get_bound_jid(conn), to, id); xmpp_conn_get_bound_jid(conn), to, id);
} }
static void conn_handler(xmpp_conn_t *conn, static void conn_handler(xmpp_conn_t *const conn,
xmpp_conn_event_t status, const xmpp_conn_event_t status,
int error, const int error,
xmpp_stream_error_t *stream_error, xmpp_stream_error_t *const stream_error,
void *userdata) void *const userdata)
{ {
vcard_t *vc = userdata; vcard_t *vc = userdata;

View File

@@ -60,43 +60,51 @@
#define HANDSHAKE_TIMEOUT 15000 /* 15 seconds */ #define HANDSHAKE_TIMEOUT 15000 /* 15 seconds */
#endif #endif
static void _auth(xmpp_conn_t *conn); static void _auth(xmpp_conn_t *const conn);
static void _auth_legacy(xmpp_conn_t *conn); static void _auth_legacy(xmpp_conn_t *conn);
static void _handle_open_sasl(xmpp_conn_t *conn); static void _handle_open_sasl(xmpp_conn_t *const conn);
static void _handle_open_tls(xmpp_conn_t *conn); static void _handle_open_tls(xmpp_conn_t *const conn);
static int _handle_component_auth(xmpp_conn_t *conn); static int _handle_component_auth(xmpp_conn_t *const conn);
static int _handle_component_hs_response(xmpp_conn_t *conn, static int _handle_component_hs_response(xmpp_conn_t *const conn,
xmpp_stanza_t *stanza, xmpp_stanza_t *const stanza,
void *userdata); void *const userdata);
static int static int _handle_features_sasl(xmpp_conn_t *const conn,
_handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata); xmpp_stanza_t *const stanza,
static int void *const userdata);
_handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata); static int _handle_sasl_result(xmpp_conn_t *const conn,
static int _handle_digestmd5_challenge(xmpp_conn_t *conn, xmpp_stanza_t *const stanza,
xmpp_stanza_t *stanza, void *const userdata);
void *userdata); static int _handle_digestmd5_challenge(xmpp_conn_t *const conn,
static int _handle_digestmd5_rspauth(xmpp_conn_t *conn, xmpp_stanza_t *const stanza,
xmpp_stanza_t *stanza, void *const userdata);
void *userdata); static int _handle_digestmd5_rspauth(xmpp_conn_t *const conn,
static int _handle_scram_challenge(xmpp_conn_t *conn, xmpp_stanza_t *const stanza,
xmpp_stanza_t *stanza, void *const userdata);
void *userdata); static int _handle_scram_challenge(xmpp_conn_t *const conn,
static char *_make_scram_init_msg(xmpp_conn_t *conn); xmpp_stanza_t *const stanza,
void *const userdata);
static char *_make_scram_init_msg(xmpp_conn_t *const conn);
static int _handle_missing_features_sasl(xmpp_conn_t *conn, void *userdata); static int _handle_missing_features_sasl(xmpp_conn_t *const conn,
static int _handle_missing_bind(xmpp_conn_t *conn, void *userdata); void *const userdata);
static int static int _handle_missing_bind(xmpp_conn_t *const conn, void *const userdata);
_handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata); static int _handle_bind(xmpp_conn_t *const conn,
static int xmpp_stanza_t *const stanza,
_handle_session(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata); void *const userdata);
static int _handle_missing_session(xmpp_conn_t *conn, void *userdata); static int _handle_session(xmpp_conn_t *const conn,
static int _handle_missing_handshake(xmpp_conn_t *conn, void *userdata); xmpp_stanza_t *const stanza,
void *const userdata);
static int _handle_missing_session(xmpp_conn_t *const conn,
void *const userdata);
static int _handle_missing_handshake(xmpp_conn_t *const conn,
void *const userdata);
/* stream:error handler */ /* stream:error handler */
static int static int _handle_error(xmpp_conn_t *const conn,
_handle_error(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *const stanza,
void *const userdata)
{ {
xmpp_stanza_t *child; xmpp_stanza_t *child;
const char *name; const char *name;
@@ -191,7 +199,8 @@ _handle_error(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
} }
/* stream:features handlers */ /* stream:features handlers */
static int _handle_missing_features(xmpp_conn_t *conn, void *userdata) static int _handle_missing_features(xmpp_conn_t *const conn,
void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
@@ -203,8 +212,9 @@ static int _handle_missing_features(xmpp_conn_t *conn, void *userdata)
return 0; return 0;
} }
static int static int _handle_features(xmpp_conn_t *const conn,
_handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *const stanza,
void *const userdata)
{ {
xmpp_stanza_t *child, *mech; xmpp_stanza_t *child, *mech;
const char *ns; const char *ns;
@@ -242,9 +252,6 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
if (strcasecmp(text, "PLAIN") == 0) if (strcasecmp(text, "PLAIN") == 0)
conn->sasl_support |= SASL_MASK_PLAIN; conn->sasl_support |= SASL_MASK_PLAIN;
else if (strcasecmp(text, "EXTERNAL") == 0 &&
conn->tls_client_cert)
conn->sasl_support |= SASL_MASK_EXTERNAL;
else if (strcasecmp(text, "DIGEST-MD5") == 0) else if (strcasecmp(text, "DIGEST-MD5") == 0)
conn->sasl_support |= SASL_MASK_DIGESTMD5; conn->sasl_support |= SASL_MASK_DIGESTMD5;
else if (strcasecmp(text, "SCRAM-SHA-1") == 0) else if (strcasecmp(text, "SCRAM-SHA-1") == 0)
@@ -272,7 +279,7 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
/* returns the correct auth id for a component or a client. /* returns the correct auth id for a component or a client.
* returned string must be freed by caller */ * returned string must be freed by caller */
static char *_get_authid(xmpp_conn_t *conn) static char *_get_authid(xmpp_conn_t *const conn)
{ {
char *authid = NULL; char *authid = NULL;
@@ -286,9 +293,9 @@ static char *_get_authid(xmpp_conn_t *conn)
return authid; return authid;
} }
static int _handle_proceedtls_default(xmpp_conn_t *conn, static int _handle_proceedtls_default(xmpp_conn_t *const conn,
xmpp_stanza_t *stanza, xmpp_stanza_t *const stanza,
void *userdata) void *const userdata)
{ {
const char *name; const char *name;
@@ -312,8 +319,9 @@ static int _handle_proceedtls_default(xmpp_conn_t *conn,
return 0; return 0;
} }
static int static int _handle_sasl_result(xmpp_conn_t *const conn,
_handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *const stanza,
void *const userdata)
{ {
const char *name; const char *name;
@@ -338,18 +346,19 @@ _handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
} else { } else {
/* got unexpected reply */ /* got unexpected reply */
xmpp_error(conn->ctx, "xmpp", xmpp_error(conn->ctx, "xmpp",
"Got unexpected reply to SASL %s authentication.", "Got unexpected reply to SASL %s"
"authentication.",
(char *)userdata); (char *)userdata);
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINT);
} }
return 0; return 0;
} }
/* handle the challenge phase of digest auth */ /* handle the challenge phase of digest auth */
static int _handle_digestmd5_challenge(xmpp_conn_t *conn, static int _handle_digestmd5_challenge(xmpp_conn_t *const conn,
xmpp_stanza_t *stanza, xmpp_stanza_t *const stanza,
void *userdata) void *const userdata)
{ {
char *text; char *text;
char *response; char *response;
@@ -406,9 +415,9 @@ static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
} }
/* handle the rspauth phase of digest auth */ /* handle the rspauth phase of digest auth */
static int _handle_digestmd5_rspauth(xmpp_conn_t *conn, static int _handle_digestmd5_rspauth(xmpp_conn_t *const conn,
xmpp_stanza_t *stanza, xmpp_stanza_t *const stanza,
void *userdata) void *const userdata)
{ {
xmpp_stanza_t *auth; xmpp_stanza_t *auth;
const char *name; const char *name;
@@ -443,9 +452,9 @@ struct scram_user_data {
}; };
/* handle the challenge phase of SCRAM-SHA-1 auth */ /* handle the challenge phase of SCRAM-SHA-1 auth */
static int _handle_scram_challenge(xmpp_conn_t *conn, static int _handle_scram_challenge(xmpp_conn_t *const conn,
xmpp_stanza_t *stanza, xmpp_stanza_t *const stanza,
void *userdata) void *const userdata)
{ {
char *text; char *text;
char *response; char *response;
@@ -524,7 +533,7 @@ err:
return 0; return 0;
} }
static char *_make_scram_init_msg(xmpp_conn_t *conn) static char *_make_scram_init_msg(xmpp_conn_t *const conn)
{ {
xmpp_ctx_t *ctx = conn->ctx; xmpp_ctx_t *ctx = conn->ctx;
size_t message_len; size_t message_len;
@@ -547,7 +556,7 @@ static char *_make_scram_init_msg(xmpp_conn_t *conn)
return message; return message;
} }
static xmpp_stanza_t *_make_starttls(xmpp_conn_t *conn) static xmpp_stanza_t *_make_starttls(xmpp_conn_t *const conn)
{ {
xmpp_stanza_t *starttls; xmpp_stanza_t *starttls;
@@ -561,7 +570,8 @@ static xmpp_stanza_t *_make_starttls(xmpp_conn_t *conn)
return starttls; return starttls;
} }
static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t *conn, const char *mechanism) static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t *const conn,
const char *const mechanism)
{ {
xmpp_stanza_t *auth; xmpp_stanza_t *auth;
@@ -581,7 +591,7 @@ static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t *conn, const char *mechanism)
* this will get called again until one auth method succeeds or every * this will get called again until one auth method succeeds or every
* method fails * method fails
*/ */
static void _auth(xmpp_conn_t *conn) static void _auth(xmpp_conn_t *const conn)
{ {
xmpp_stanza_t *auth; xmpp_stanza_t *auth;
xmpp_stanza_t *authdata; xmpp_stanza_t *authdata;
@@ -634,7 +644,7 @@ static void _auth(xmpp_conn_t *conn)
xmpp_error(conn->ctx, "xmpp", xmpp_error(conn->ctx, "xmpp",
"TLS is not supported, but set as " "TLS is not supported, but set as "
"mandatory for this connection"); "mandatory for this connection");
conn_disconnect(conn); disconnect_with_error(conn, XMPP_EINVOP);
return; return;
} }
@@ -654,57 +664,10 @@ static void _auth(xmpp_conn_t *conn)
/* SASL ANONYMOUS was tried, unset flag */ /* SASL ANONYMOUS was tried, unset flag */
conn->sasl_support &= ~SASL_MASK_ANONYMOUS; conn->sasl_support &= ~SASL_MASK_ANONYMOUS;
} else if (conn->sasl_support & SASL_MASK_EXTERNAL) {
/* more crap here */
auth = _make_sasl_auth(conn, "EXTERNAL");
if (!auth) {
disconnect_mem_error(conn);
return;
}
authdata = xmpp_stanza_new(conn->ctx);
if (!authdata) {
xmpp_stanza_release(auth);
disconnect_mem_error(conn);
return;
}
str = tls_id_on_xmppaddr(conn, 0);
if (!str || (tls_id_on_xmppaddr_num(conn) == 1 &&
strcmp(str, conn->jid) == 0)) {
xmpp_stanza_set_text(authdata, "=");
} else {
xmpp_free(conn->ctx, str);
str = xmpp_base64_encode(conn->ctx, (void *)conn->jid,
strlen(conn->jid));
if (!str) {
xmpp_stanza_release(authdata);
xmpp_stanza_release(auth);
disconnect_mem_error(conn);
return;
}
xmpp_stanza_set_text(authdata, str);
}
xmpp_free(conn->ctx, str);
xmpp_stanza_add_child(auth, authdata);
xmpp_stanza_release(authdata);
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL,
"EXTERNAL");
xmpp_send(conn, auth);
xmpp_stanza_release(auth);
/* SASL EXTERNAL was tried, unset flag */
conn->sasl_support &= ~SASL_MASK_EXTERNAL;
} else if (anonjid) { } else if (anonjid) {
xmpp_error(conn->ctx, "auth", xmpp_error(conn->ctx, "auth",
"No node in JID, and SASL ANONYMOUS unsupported."); "No node in JID, and SASL ANONYMOUS unsupported.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINVOP);
} else if (conn->pass == NULL) {
xmpp_error(conn->ctx, "auth",
"Password hasn't been set, and SASL ANONYMOUS unsupported.");
xmpp_disconnect(conn);
} else if (conn->sasl_support & SASL_MASK_SCRAM) { } else if (conn->sasl_support & SASL_MASK_SCRAM) {
scram_ctx = xmpp_alloc(conn->ctx, sizeof(*scram_ctx)); scram_ctx = xmpp_alloc(conn->ctx, sizeof(*scram_ctx));
if (conn->sasl_support & SASL_MASK_SCRAMSHA512) if (conn->sasl_support & SASL_MASK_SCRAMSHA512)
@@ -817,7 +780,7 @@ static void _auth(xmpp_conn_t *conn)
_auth_legacy(conn); _auth_legacy(conn);
} else { } else {
xmpp_error(conn->ctx, "auth", "Cannot authenticate with known methods"); xmpp_error(conn->ctx, "auth", "Cannot authenticate with known methods");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EAUTH);
} }
} }
@@ -830,7 +793,7 @@ static void _auth(xmpp_conn_t *conn)
* *
* @param conn a Strophe connection object * @param conn a Strophe connection object
*/ */
void auth_handle_open(xmpp_conn_t *conn) void auth_handle_open(xmpp_conn_t *const conn)
{ {
/* reset all timed handlers */ /* reset all timed handlers */
handler_reset_timed(conn, 0); handler_reset_timed(conn, 0);
@@ -846,7 +809,7 @@ void auth_handle_open(xmpp_conn_t *conn)
} }
/* called when stream:stream tag received after TLS establishment */ /* called when stream:stream tag received after TLS establishment */
static void _handle_open_tls(xmpp_conn_t *conn) static void _handle_open_tls(xmpp_conn_t *const conn)
{ {
/* setup handlers for incoming <stream:features> */ /* setup handlers for incoming <stream:features> */
handler_add(conn, _handle_features, XMPP_NS_STREAMS, "features", NULL, handler_add(conn, _handle_features, XMPP_NS_STREAMS, "features", NULL,
@@ -855,7 +818,7 @@ static void _handle_open_tls(xmpp_conn_t *conn)
} }
/* called when stream:stream tag received after SASL auth */ /* called when stream:stream tag received after SASL auth */
static void _handle_open_sasl(xmpp_conn_t *conn) static void _handle_open_sasl(xmpp_conn_t *const conn)
{ {
xmpp_debug(conn->ctx, "xmpp", "Reopened stream successfully."); xmpp_debug(conn->ctx, "xmpp", "Reopened stream successfully.");
@@ -866,8 +829,9 @@ static void _handle_open_sasl(xmpp_conn_t *conn)
NULL); NULL);
} }
static int static int _handle_features_sasl(xmpp_conn_t *const conn,
_handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *const stanza,
void *const userdata)
{ {
xmpp_stanza_t *bind, *session, *iq, *res, *text, *opt; xmpp_stanza_t *bind, *session, *iq, *res, *text, *opt;
const char *ns; const char *ns;
@@ -966,25 +930,27 @@ _handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
xmpp_error(conn->ctx, "xmpp", xmpp_error(conn->ctx, "xmpp",
"Stream features does not allow " "Stream features does not allow "
"resource bind."); "resource bind.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINT);
} }
return 0; return 0;
} }
static int _handle_missing_features_sasl(xmpp_conn_t *conn, void *userdata) static int _handle_missing_features_sasl(xmpp_conn_t *const conn,
void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
xmpp_error(conn->ctx, "xmpp", xmpp_error(conn->ctx, "xmpp",
"Did not receive stream features " "Did not receive stream features "
"after SASL authentication."); "after SASL authentication.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_ETIMEDOUT);
return 0; return 0;
} }
static int static int _handle_bind(xmpp_conn_t *const conn,
_handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *const stanza,
void *const userdata)
{ {
const char *type; const char *type;
xmpp_stanza_t *iq, *session; xmpp_stanza_t *iq, *session;
@@ -998,7 +964,7 @@ _handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
type = xmpp_stanza_get_type(stanza); type = xmpp_stanza_get_type(stanza);
if (type && strcmp(type, "error") == 0) { if (type && strcmp(type, "error") == 0) {
xmpp_error(conn->ctx, "xmpp", "Binding failed."); xmpp_error(conn->ctx, "xmpp", "Binding failed.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINT);
} else if (type && strcmp(type, "result") == 0) { } else if (type && strcmp(type, "result") == 0) {
xmpp_stanza_t *binding = xmpp_stanza_get_child_by_name(stanza, "bind"); xmpp_stanza_t *binding = xmpp_stanza_get_child_by_name(stanza, "bind");
xmpp_debug(conn->ctx, "xmpp", "Bind successful."); xmpp_debug(conn->ctx, "xmpp", "Bind successful.");
@@ -1050,23 +1016,24 @@ _handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
} }
} else { } else {
xmpp_error(conn->ctx, "xmpp", "Server sent malformed bind reply."); xmpp_error(conn->ctx, "xmpp", "Server sent malformed bind reply.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINT);
} }
return 0; return 0;
} }
static int _handle_missing_bind(xmpp_conn_t *conn, void *userdata) static int _handle_missing_bind(xmpp_conn_t *const conn, void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
xmpp_error(conn->ctx, "xmpp", "Server did not reply to bind request."); xmpp_error(conn->ctx, "xmpp", "Server did not reply to bind request.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_ETIMEDOUT);
return 0; return 0;
} }
static int static int _handle_session(xmpp_conn_t *const conn,
_handle_session(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *const stanza,
void *const userdata)
{ {
const char *type; const char *type;
@@ -1079,7 +1046,7 @@ _handle_session(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
type = xmpp_stanza_get_type(stanza); type = xmpp_stanza_get_type(stanza);
if (type && strcmp(type, "error") == 0) { if (type && strcmp(type, "error") == 0) {
xmpp_error(conn->ctx, "xmpp", "Session establishment failed."); xmpp_error(conn->ctx, "xmpp", "Session establishment failed.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINT);
} else if (type && strcmp(type, "result") == 0) { } else if (type && strcmp(type, "result") == 0) {
xmpp_debug(conn->ctx, "xmpp", "Session establishment successful."); xmpp_debug(conn->ctx, "xmpp", "Session establishment successful.");
@@ -1089,34 +1056,36 @@ _handle_session(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata); conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
} else { } else {
xmpp_error(conn->ctx, "xmpp", "Server sent malformed session reply."); xmpp_error(conn->ctx, "xmpp", "Server sent malformed session reply.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINT);
} }
return 0; return 0;
} }
static int _handle_missing_session(xmpp_conn_t *conn, void *userdata) static int _handle_missing_session(xmpp_conn_t *const conn,
void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
xmpp_error(conn->ctx, "xmpp", "Server did not reply to session request."); xmpp_error(conn->ctx, "xmpp", "Server did not reply to session request.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_ETIMEDOUT);
return 0; return 0;
} }
static int _handle_missing_legacy(xmpp_conn_t *conn, void *userdata) static int _handle_missing_legacy(xmpp_conn_t *const conn, void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
xmpp_error(conn->ctx, "xmpp", xmpp_error(conn->ctx, "xmpp",
"Server did not reply to legacy " "Server did not reply to legacy "
"authentication request."); "authentication request.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_ETIMEDOUT);
return 0; return 0;
} }
static int static int _handle_legacy(xmpp_conn_t *const conn,
_handle_legacy(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata) xmpp_stanza_t *const stanza,
void *const userdata)
{ {
const char *type; const char *type;
const char *name; const char *name;
@@ -1133,11 +1102,11 @@ _handle_legacy(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
xmpp_error(conn->ctx, "xmpp", xmpp_error(conn->ctx, "xmpp",
"Server sent us an unexpected response " "Server sent us an unexpected response "
"to legacy authentication request."); "to legacy authentication request.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINT);
} else if (strcmp(type, "error") == 0) { } else if (strcmp(type, "error") == 0) {
/* legacy client auth failed, no more fallbacks */ /* legacy client auth failed, no more fallbacks */
xmpp_error(conn->ctx, "xmpp", "Legacy client authentication failed."); xmpp_error(conn->ctx, "xmpp", "Legacy client authentication failed.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EAUTH);
} else if (strcmp(type, "result") == 0) { } else if (strcmp(type, "result") == 0) {
/* auth succeeded */ /* auth succeeded */
xmpp_debug(conn->ctx, "xmpp", "Legacy auth succeeded."); xmpp_debug(conn->ctx, "xmpp", "Legacy auth succeeded.");
@@ -1148,7 +1117,7 @@ _handle_legacy(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
xmpp_error(conn->ctx, "xmpp", xmpp_error(conn->ctx, "xmpp",
"Server sent us a legacy authentication " "Server sent us a legacy authentication "
"response with a bad type."); "response with a bad type.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINT);
} }
return 0; return 0;
@@ -1228,7 +1197,7 @@ static void _auth_legacy(xmpp_conn_t *conn)
xmpp_stanza_release(authdata); xmpp_stanza_release(authdata);
xmpp_stanza_release(iq); xmpp_stanza_release(iq);
xmpp_error(conn->ctx, "auth", "Cannot authenticate without resource"); xmpp_error(conn->ctx, "auth", "Cannot authenticate without resource");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EINVOP);
return; return;
} }
xmpp_stanza_add_child(child, authdata); xmpp_stanza_add_child(child, authdata);
@@ -1247,7 +1216,7 @@ err:
disconnect_mem_error(conn); disconnect_mem_error(conn);
} }
void auth_handle_component_open(xmpp_conn_t *conn) void auth_handle_component_open(xmpp_conn_t *const conn)
{ {
int rc; int rc;
@@ -1262,12 +1231,12 @@ void auth_handle_component_open(xmpp_conn_t *conn)
rc = _handle_component_auth(conn); rc = _handle_component_auth(conn);
if (rc != 0) { if (rc != 0) {
xmpp_error(conn->ctx, "auth", "Component authentication failed."); xmpp_error(conn->ctx, "auth", "Component authentication failed.");
xmpp_disconnect(conn); disconnect_with_error(conn, rc);
} }
} }
/* Will compute SHA1 and authenticate the component to the server */ /* Will compute SHA1 and authenticate the component to the server */
int _handle_component_auth(xmpp_conn_t *conn) int _handle_component_auth(xmpp_conn_t *const conn)
{ {
uint8_t md_value[SHA1_DIGEST_SIZE]; uint8_t md_value[SHA1_DIGEST_SIZE];
SHA1_CTX mdctx; SHA1_CTX mdctx;
@@ -1317,9 +1286,9 @@ int _handle_component_auth(xmpp_conn_t *conn)
/* Check if the received stanza is <handshake/> and set auth to true /* Check if the received stanza is <handshake/> and set auth to true
* and fire connection handler. * and fire connection handler.
*/ */
int _handle_component_hs_response(xmpp_conn_t *conn, int _handle_component_hs_response(xmpp_conn_t *const conn,
xmpp_stanza_t *stanza, xmpp_stanza_t *const stanza,
void *userdata) void *const userdata)
{ {
const char *name; const char *name;
@@ -1329,15 +1298,8 @@ int _handle_component_hs_response(xmpp_conn_t *conn,
name = xmpp_stanza_get_name(stanza); name = xmpp_stanza_get_name(stanza);
if (strcmp(name, "handshake") != 0) { if (strcmp(name, "handshake") != 0) {
char *msg; xmpp_debug(conn->ctx, "auth", "Handshake failed.");
size_t msg_size; disconnect_with_error(conn, XMPP_EINT);
xmpp_stanza_to_text(stanza, &msg, &msg_size);
if (msg) {
xmpp_debug(conn->ctx, "auth", "Handshake failed: %s", msg);
xmpp_free(conn->ctx, msg);
}
xmpp_disconnect(conn);
return XMPP_EINT;
} else { } else {
conn->authenticated = 1; conn->authenticated = 1;
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata); conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
@@ -1349,16 +1311,16 @@ int _handle_component_hs_response(xmpp_conn_t *conn,
return 0; return 0;
} }
int _handle_missing_handshake(xmpp_conn_t *conn, void *userdata) int _handle_missing_handshake(xmpp_conn_t *const conn, void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
xmpp_error(conn->ctx, "xmpp", "Server did not reply to handshake request."); xmpp_error(conn->ctx, "xmpp", "Server did not reply to handshake request.");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_ETIMEDOUT);
return 0; return 0;
} }
void auth_handle_open_raw(xmpp_conn_t *conn) void auth_handle_open_raw(xmpp_conn_t *const conn)
{ {
handler_reset_timed(conn, 0); handler_reset_timed(conn, 0);
/* user handlers are not called before authentication is completed. */ /* user handlers are not called before authentication is completed. */
@@ -1366,7 +1328,7 @@ void auth_handle_open_raw(xmpp_conn_t *conn)
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata); conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
} }
void auth_handle_open_stub(xmpp_conn_t *conn) void auth_handle_open_stub(xmpp_conn_t *const conn)
{ {
xmpp_warn(conn->ctx, "auth", "Stub callback is called."); xmpp_warn(conn->ctx, "auth", "Stub callback is called.");
} }

View File

@@ -77,7 +77,6 @@ typedef struct _xmpp_connlist_t {
struct _xmpp_ctx_t { struct _xmpp_ctx_t {
const xmpp_mem_t *mem; const xmpp_mem_t *mem;
const xmpp_log_t *log; const xmpp_log_t *log;
int verbosity;
xmpp_rand_t *rand; xmpp_rand_t *rand;
xmpp_loop_status_t loop_status; xmpp_loop_status_t loop_status;
@@ -88,24 +87,33 @@ struct _xmpp_ctx_t {
}; };
/* convenience functions for accessing the context */ /* convenience functions for accessing the context */
void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size); void *xmpp_alloc(const xmpp_ctx_t *const ctx, const size_t size);
void *xmpp_realloc(const xmpp_ctx_t *ctx, void *p, size_t size); void *xmpp_realloc(const xmpp_ctx_t *const ctx, void *p, const size_t size);
char *xmpp_strdup(const xmpp_ctx_t *ctx, const char *s); char *xmpp_strdup(const xmpp_ctx_t *const ctx, const char *const s);
char *xmpp_strndup(const xmpp_ctx_t *ctx, const char *s, size_t len);
void xmpp_log(const xmpp_ctx_t *ctx, void xmpp_log(const xmpp_ctx_t *const ctx,
const xmpp_log_level_t level, const xmpp_log_level_t level,
const char *area, const char *const area,
const char *fmt, const char *const fmt,
va_list ap); va_list ap);
/* wrappers for xmpp_log at specific levels */ /* wrappers for xmpp_log at specific levels */
void xmpp_error(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...); void xmpp_error(const xmpp_ctx_t *const ctx,
void xmpp_warn(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...); const char *const area,
void xmpp_info(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...); const char *const fmt,
void xmpp_debug(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...); ...);
void xmpp_debug_verbose( void xmpp_warn(const xmpp_ctx_t *const ctx,
int level, const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...); const char *const area,
const char *const fmt,
...);
void xmpp_info(const xmpp_ctx_t *const ctx,
const char *const area,
const char *const fmt,
...);
void xmpp_debug(const xmpp_ctx_t *const ctx,
const char *const area,
const char *const fmt,
...);
/** connection **/ /** connection **/
@@ -135,7 +143,6 @@ struct _xmpp_send_queue_t {
#define SASL_MASK_SCRAMSHA1 (1 << 3) #define SASL_MASK_SCRAMSHA1 (1 << 3)
#define SASL_MASK_SCRAMSHA256 (1 << 4) #define SASL_MASK_SCRAMSHA256 (1 << 4)
#define SASL_MASK_SCRAMSHA512 (1 << 5) #define SASL_MASK_SCRAMSHA512 (1 << 5)
#define SASL_MASK_EXTERNAL (1 << 6)
#define SASL_MASK_SCRAM \ #define SASL_MASK_SCRAM \
(SASL_MASK_SCRAMSHA1 | SASL_MASK_SCRAMSHA256 | SASL_MASK_SCRAMSHA512) (SASL_MASK_SCRAMSHA1 | SASL_MASK_SCRAMSHA256 | SASL_MASK_SCRAMSHA512)
@@ -146,7 +153,7 @@ enum {
XMPP_PORT_COMPONENT = 5347, XMPP_PORT_COMPONENT = 5347,
}; };
typedef void (*xmpp_open_handler)(xmpp_conn_t *conn); typedef void (*xmpp_open_handler)(xmpp_conn_t *const conn);
struct _xmpp_conn_t { struct _xmpp_conn_t {
unsigned int ref; unsigned int ref;
@@ -169,16 +176,11 @@ struct _xmpp_conn_t {
int tls_mandatory; int tls_mandatory;
int tls_legacy_ssl; int tls_legacy_ssl;
int tls_trust; int tls_trust;
char *tls_cafile;
char *tls_capath;
char *tls_client_cert;
char *tls_client_key;
int tls_failed; /* set when tls fails, so we don't try again */ int tls_failed; /* set when tls fails, so we don't try again */
int sasl_support; /* if true, field is a bitfield of supported int sasl_support; /* if true, field is a bitfield of supported
mechanisms */ mechanisms */
int auth_legacy_enabled; int auth_legacy_enabled;
int secured; /* set when stream is secured with TLS */ int secured; /* set when stream is secured with TLS */
xmpp_certfail_handler certfail_handler;
/* if server returns <bind/> or <session/> we must do them */ /* if server returns <bind/> or <session/> we must do them */
int bind_required; int bind_required;
@@ -223,13 +225,13 @@ struct _xmpp_conn_t {
xmpp_handlist_t *handlers; xmpp_handlist_t *handlers;
}; };
void conn_disconnect(xmpp_conn_t *conn); void conn_disconnect(xmpp_conn_t *const conn);
void conn_disconnect_clean(xmpp_conn_t *conn); void conn_disconnect_clean(xmpp_conn_t *const conn);
void conn_established(xmpp_conn_t *conn); void conn_established(xmpp_conn_t *const conn);
void conn_open_stream(xmpp_conn_t *conn); void conn_open_stream(xmpp_conn_t *const conn);
int conn_tls_start(xmpp_conn_t *conn); int conn_tls_start(xmpp_conn_t *const conn);
void conn_prepare_reset(xmpp_conn_t *conn, xmpp_open_handler handler); void conn_prepare_reset(xmpp_conn_t *const conn, xmpp_open_handler handler);
void conn_parser_reset(xmpp_conn_t *conn); void conn_parser_reset(xmpp_conn_t *const conn);
typedef enum { typedef enum {
XMPP_STANZA_UNKNOWN, XMPP_STANZA_UNKNOWN,
@@ -254,32 +256,33 @@ struct _xmpp_stanza_t {
}; };
/* handler management */ /* handler management */
void handler_fire_stanza(xmpp_conn_t *conn, xmpp_stanza_t *stanza); void handler_fire_stanza(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza);
uint64_t handler_fire_timed(xmpp_ctx_t *ctx); uint64_t handler_fire_timed(xmpp_ctx_t *const ctx);
void handler_reset_timed(xmpp_conn_t *conn, int user_only); void handler_reset_timed(xmpp_conn_t *conn, int user_only);
void handler_add_timed(xmpp_conn_t *conn, void handler_add_timed(xmpp_conn_t *const conn,
xmpp_timed_handler handler, xmpp_timed_handler handler,
unsigned long period, const unsigned long period,
void *userdata); void *const userdata);
void handler_add_id(xmpp_conn_t *conn, void handler_add_id(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *id, const char *const id,
void *userdata); void *const userdata);
void handler_add(xmpp_conn_t *conn, void handler_add(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *ns, const char *const ns,
const char *name, const char *const name,
const char *type, const char *const type,
void *userdata); void *const userdata);
void handler_system_delete_all(xmpp_conn_t *conn); void handler_system_delete_all(xmpp_conn_t *conn);
/* utility functions */ /* utility functions */
void disconnect_mem_error(xmpp_conn_t *conn); void disconnect_with_error(xmpp_conn_t *const conn, int error);
void disconnect_mem_error(xmpp_conn_t *const conn);
/* auth functions */ /* auth functions */
void auth_handle_open(xmpp_conn_t *conn); void auth_handle_open(xmpp_conn_t *const conn);
void auth_handle_component_open(xmpp_conn_t *conn); void auth_handle_component_open(xmpp_conn_t *const conn);
void auth_handle_open_raw(xmpp_conn_t *conn); void auth_handle_open_raw(xmpp_conn_t *const conn);
void auth_handle_open_stub(xmpp_conn_t *conn); void auth_handle_open_stub(xmpp_conn_t *const conn);
#endif /* __LIBSTROPHE_COMMON_H__ */ #endif /* __LIBSTROPHE_COMMON_H__ */

View File

@@ -48,13 +48,10 @@
#define CONNECT_TIMEOUT 5000 /* 5 seconds */ #define CONNECT_TIMEOUT 5000 /* 5 seconds */
#endif #endif
static int _disconnect_cleanup(xmpp_conn_t *conn, void *userdata); static int _disconnect_cleanup(xmpp_conn_t *const conn, void *const userdata);
static char *_conn_build_stream_tag(xmpp_conn_t *conn, static char *_conn_build_stream_tag(xmpp_conn_t *const conn,
char **attributes, char **attributes,
size_t attributes_len); size_t attributes_len);
static int _conn_open_stream_with_attributes(xmpp_conn_t *conn,
char **attributes,
size_t attributes_len);
static void _conn_attributes_new(xmpp_conn_t *conn, static void _conn_attributes_new(xmpp_conn_t *conn,
char **attrs, char **attrs,
char ***attributes, char ***attributes,
@@ -62,22 +59,24 @@ static void _conn_attributes_new(xmpp_conn_t *conn,
static void _conn_attributes_destroy(xmpp_conn_t *conn, static void _conn_attributes_destroy(xmpp_conn_t *conn,
char **attributes, char **attributes,
size_t attributes_len); size_t attributes_len);
static void _handle_stream_start(char *name, char **attrs, void *userdata); static void
static void _handle_stream_end(char *name, void *userdata); _handle_stream_start(char *name, char **attrs, void *const userdata);
static void _handle_stream_stanza(xmpp_stanza_t *stanza, void *userdata); static void _handle_stream_end(char *name, void *const userdata);
static unsigned short _conn_default_port(xmpp_conn_t *conn, static void _handle_stream_stanza(xmpp_stanza_t *stanza, void *const userdata);
static unsigned short _conn_default_port(xmpp_conn_t *const conn,
xmpp_conn_type_t type); xmpp_conn_type_t type);
static void _conn_reset(xmpp_conn_t *conn); static void _conn_reset(xmpp_conn_t *const conn);
static int _conn_connect(xmpp_conn_t *conn, static int _conn_connect(xmpp_conn_t *const conn,
const char *domain, const char *const domain,
const char *host, const char *const host,
unsigned short port, unsigned short port,
xmpp_conn_type_t type, xmpp_conn_type_t type,
xmpp_conn_handler callback, xmpp_conn_handler callback,
void *userdata); void *const userdata);
static int _send_raw(xmpp_conn_t *conn, char *data, size_t len);
void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text) void xmpp_send_error(xmpp_conn_t *const conn,
xmpp_error_type_t const type,
char *const text)
{ {
xmpp_stanza_t *error = xmpp_error_new(conn->ctx, type, text); xmpp_stanza_t *error = xmpp_error_new(conn->ctx, type, text);
@@ -94,7 +93,7 @@ void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text)
* *
* @ingroup Connections * @ingroup Connections
*/ */
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx) xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *const ctx)
{ {
xmpp_conn_t *conn = NULL; xmpp_conn_t *conn = NULL;
xmpp_connlist_t *tail, *item; xmpp_connlist_t *tail, *item;
@@ -144,14 +143,9 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx)
conn->tls_legacy_ssl = 0; conn->tls_legacy_ssl = 0;
conn->tls_trust = 0; conn->tls_trust = 0;
conn->tls_failed = 0; conn->tls_failed = 0;
conn->tls_cafile = NULL;
conn->tls_capath = NULL;
conn->tls_client_cert = NULL;
conn->tls_client_key = NULL;
conn->sasl_support = 0; conn->sasl_support = 0;
conn->auth_legacy_enabled = 0; conn->auth_legacy_enabled = 0;
conn->secured = 0; conn->secured = 0;
conn->certfail_handler = NULL;
conn->bind_required = 0; conn->bind_required = 0;
conn->session_required = 0; conn->session_required = 0;
@@ -207,7 +201,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx)
* *
* @ingroup Connections * @ingroup Connections
*/ */
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn) xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *const conn)
{ {
conn->ref++; conn->ref++;
return conn; return conn;
@@ -225,7 +219,7 @@ xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval) void xmpp_conn_set_keepalive(xmpp_conn_t *const conn, int timeout, int interval)
{ {
int ret = 0; int ret = 0;
@@ -251,7 +245,7 @@ void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval)
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_conn_release(xmpp_conn_t *conn) int xmpp_conn_release(xmpp_conn_t *const conn)
{ {
xmpp_ctx_t *ctx; xmpp_ctx_t *ctx;
xmpp_connlist_t *item, *prev; xmpp_connlist_t *item, *prev;
@@ -344,14 +338,6 @@ int xmpp_conn_release(xmpp_conn_t *conn)
xmpp_free(ctx, conn->pass); xmpp_free(ctx, conn->pass);
if (conn->lang) if (conn->lang)
xmpp_free(ctx, conn->lang); xmpp_free(ctx, conn->lang);
if (conn->tls_client_cert)
xmpp_free(ctx, conn->tls_client_cert);
if (conn->tls_client_key)
xmpp_free(ctx, conn->tls_client_key);
if (conn->tls_cafile)
xmpp_free(ctx, conn->tls_cafile);
if (conn->tls_capath)
xmpp_free(ctx, conn->tls_capath);
xmpp_free(ctx, conn); xmpp_free(ctx, conn);
released = 1; released = 1;
} }
@@ -367,7 +353,7 @@ int xmpp_conn_release(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
const char *xmpp_conn_get_jid(const xmpp_conn_t *conn) const char *xmpp_conn_get_jid(const xmpp_conn_t *const conn)
{ {
return conn->jid; return conn->jid;
} }
@@ -385,7 +371,7 @@ const char *xmpp_conn_get_jid(const xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *conn) const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *const conn)
{ {
return conn->bound_jid; return conn->bound_jid;
} }
@@ -401,126 +387,13 @@ const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
void xmpp_conn_set_jid(xmpp_conn_t *conn, const char *jid) void xmpp_conn_set_jid(xmpp_conn_t *const conn, const char *const jid)
{ {
if (conn->jid) if (conn->jid)
xmpp_free(conn->ctx, conn->jid); xmpp_free(conn->ctx, conn->jid);
conn->jid = xmpp_strdup(conn->ctx, jid); conn->jid = xmpp_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 Connections
* @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 cert path to a certificate file
*
* @ingroup Connections
* @ingroup TLS
*/
void xmpp_conn_set_cafile(xmpp_conn_t *const conn, const char *path)
{
conn->tls_cafile = xmpp_strdup(conn->ctx, path);
}
/** Set the CApath
*
* @param conn a Strophe connection object
* @param cert path to a folder containing certificates
*
* @ingroup Connections
* @ingroup TLS
*/
void xmpp_conn_set_capath(xmpp_conn_t *const conn, const char *path)
{
conn->tls_capath = xmpp_strdup(conn->ctx, path);
}
/** Retrieve the peer certificate
*
* The returned Certificate object must be free'd by calling
* \ref xmpp_tlscert_free
*
* @param conn a Strophe connection object
*
* @return a Strophe Certificate object
*
* @ingroup Connections
* @ingroup TLS
*/
xmpp_tlscert_t *xmpp_conn_get_peer_cert(xmpp_conn_t *const conn)
{
return tls_peer_cert(conn);
}
/** Set the Client Certificate and Private Key that will be bound to the
* connection. If any of the both 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.
* Currently only non-encrypted Private Keys are supported.
*
* @param conn a Strophe connection object
* @param cert path to a certificate file
* @param key path to a private key file
*
* @ingroup Connections
* @ingroup TLS
*/
void xmpp_conn_set_client_cert(xmpp_conn_t *const conn,
const char *const cert,
const char *const key)
{
xmpp_debug(conn->ctx, "conn", "set client cert %s %s", cert, key);
if (conn->tls_client_cert)
xmpp_free(conn->ctx, conn->tls_client_cert);
conn->tls_client_cert = xmpp_strdup(conn->ctx, cert);
if (conn->tls_client_key)
xmpp_free(conn->ctx, conn->tls_client_key);
conn->tls_client_key = xmpp_strdup(conn->ctx, key);
}
/** Get the number of xmppAddr entries in the client certificate.
*
* @param conn a Strophe connection object
*
* @return the number of xmppAddr entries in the client certificate
*
* @ingroup Connections
* @ingroup TLS
*/
unsigned int xmpp_conn_cert_xmppaddr_num(xmpp_conn_t *const conn)
{
return tls_id_on_xmppaddr_num(conn);
}
/** Get a specific xmppAddr entry.
*
* @param conn a Strophe connection object
* @param n the index of the entry, starting at 0
*
* @return a string containing the xmppAddr or NULL if n is out of range
*
* @ingroup Connections
* @ingroup TLS
*/
char *xmpp_conn_cert_xmppaddr(xmpp_conn_t *const conn, unsigned int n)
{
return tls_id_on_xmppaddr(conn, n);
}
/** Get the password used for authentication of a connection. /** Get the password used for authentication of a connection.
* *
* @param conn a Strophe connection object * @param conn a Strophe connection object
@@ -529,7 +402,7 @@ char *xmpp_conn_cert_xmppaddr(xmpp_conn_t *const conn, unsigned int n)
* *
* @ingroup Connections * @ingroup Connections
*/ */
const char *xmpp_conn_get_pass(const xmpp_conn_t *conn) const char *xmpp_conn_get_pass(const xmpp_conn_t *const conn)
{ {
return conn->pass; return conn->pass;
} }
@@ -543,11 +416,11 @@ const char *xmpp_conn_get_pass(const xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass) void xmpp_conn_set_pass(xmpp_conn_t *const conn, const char *const pass)
{ {
if (conn->pass) if (conn->pass)
xmpp_free(conn->ctx, conn->pass); xmpp_free(conn->ctx, conn->pass);
conn->pass = pass ? xmpp_strdup(conn->ctx, pass) : NULL; conn->pass = xmpp_strdup(conn->ctx, pass);
} }
/** Get the strophe context that the connection is associated with. /** Get the strophe context that the connection is associated with.
@@ -557,7 +430,7 @@ void xmpp_conn_set_pass(xmpp_conn_t *conn, const char *pass)
* *
* @ingroup Connections * @ingroup Connections
*/ */
xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t *conn) xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t *const conn)
{ {
return conn->ctx; return conn->ctx;
} }
@@ -583,11 +456,11 @@ xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_connect_client(xmpp_conn_t *conn, int xmpp_connect_client(xmpp_conn_t *const conn,
const char *altdomain, const char *const altdomain,
unsigned short altport, unsigned short altport,
xmpp_conn_handler callback, xmpp_conn_handler callback,
void *userdata) void *const userdata)
{ {
resolver_srv_rr_t *srv_rr_list = NULL; resolver_srv_rr_t *srv_rr_list = NULL;
resolver_srv_rr_t *rr; resolver_srv_rr_t *rr;
@@ -597,25 +470,6 @@ int xmpp_connect_client(xmpp_conn_t *conn,
int found = XMPP_DOMAIN_NOT_FOUND; int found = XMPP_DOMAIN_NOT_FOUND;
int rc; int rc;
if (!conn->jid && conn->tls_client_cert) {
if (tls_id_on_xmppaddr_num(conn) != 1) {
xmpp_debug(conn->ctx, "xmpp",
"Client certificate contains multiple or no xmppAddr "
"and no JID was given to be used.");
return XMPP_EINVOP;
}
conn->jid = tls_id_on_xmppaddr(conn, 0);
if (!conn->jid)
return XMPP_EMEM;
xmpp_debug(conn->ctx, "xmpp", "Use jid %s from id-on-xmppAddr.",
conn->jid);
}
if (!conn->jid) {
xmpp_error(conn->ctx, "xmpp", "JID is not set.");
return XMPP_EINVOP;
}
domain = xmpp_jid_domain(conn->ctx, conn->jid); domain = xmpp_jid_domain(conn->ctx, conn->jid);
if (!domain) if (!domain)
return XMPP_EMEM; return XMPP_EMEM;
@@ -682,11 +536,11 @@ int xmpp_connect_client(xmpp_conn_t *conn,
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_connect_component(xmpp_conn_t *conn, int xmpp_connect_component(xmpp_conn_t *const conn,
const char *server, const char *const server,
unsigned short port, unsigned short port,
xmpp_conn_handler callback, xmpp_conn_handler callback,
void *userdata) void *const userdata)
{ {
/* The server domain, jid and password MUST be specified. */ /* The server domain, jid and password MUST be specified. */
if (!(server && conn->jid && conn->pass)) if (!(server && conn->jid && conn->pass))
@@ -729,18 +583,18 @@ int xmpp_connect_component(xmpp_conn_t *conn,
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_connect_raw(xmpp_conn_t *conn, int xmpp_connect_raw(xmpp_conn_t *const conn,
const char *altdomain, const char *const altdomain,
unsigned short altport, unsigned short altport,
xmpp_conn_handler callback, xmpp_conn_handler callback,
void *userdata) void *const userdata)
{ {
conn->is_raw = 1; conn->is_raw = 1;
return xmpp_connect_client(conn, altdomain, altport, callback, userdata); return xmpp_connect_client(conn, altdomain, altport, callback, userdata);
} }
/* Called when tcp connection is established. */ /* Called when tcp connection is established. */
void conn_established(xmpp_conn_t *conn) void conn_established(xmpp_conn_t *const conn)
{ {
if (conn->tls_legacy_ssl && !conn->is_raw) { if (conn->tls_legacy_ssl && !conn->is_raw) {
xmpp_debug(conn->ctx, "xmpp", "using legacy SSL connection"); xmpp_debug(conn->ctx, "xmpp", "using legacy SSL connection");
@@ -774,7 +628,7 @@ void conn_established(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_conn_open_stream_default(xmpp_conn_t *conn) int xmpp_conn_open_stream_default(xmpp_conn_t *const conn)
{ {
if (!conn->is_raw) if (!conn->is_raw)
return XMPP_EINVOP; return XMPP_EINVOP;
@@ -801,16 +655,24 @@ int xmpp_conn_open_stream_default(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_conn_open_stream(xmpp_conn_t *conn, int xmpp_conn_open_stream(xmpp_conn_t *const conn,
char **attributes, char **attributes,
size_t attributes_len) size_t attributes_len)
{ {
char *tag;
if (!conn->is_raw) if (!conn->is_raw)
return XMPP_EINVOP; return XMPP_EINVOP;
conn_prepare_reset(conn, auth_handle_open_raw); tag = _conn_build_stream_tag(conn, attributes, attributes_len);
if (!tag)
return XMPP_EMEM;
return _conn_open_stream_with_attributes(conn, attributes, attributes_len); conn_prepare_reset(conn, auth_handle_open_raw);
xmpp_send_raw_string(conn, "<?xml version=\"1.0\"?>%s", tag);
xmpp_free(conn->ctx, tag);
return XMPP_EOK;
} }
/** Start synchronous TLS handshake with the server. /** Start synchronous TLS handshake with the server.
@@ -819,7 +681,7 @@ int xmpp_conn_open_stream(xmpp_conn_t *conn,
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_conn_tls_start(xmpp_conn_t *conn) int xmpp_conn_tls_start(xmpp_conn_t *const conn)
{ {
return conn_tls_start(conn); return conn_tls_start(conn);
} }
@@ -830,7 +692,7 @@ int xmpp_conn_tls_start(xmpp_conn_t *conn)
* *
* @param conn a Strophe connection object * @param conn a Strophe connection object
*/ */
void conn_disconnect_clean(xmpp_conn_t *conn) void conn_disconnect_clean(xmpp_conn_t *const conn)
{ {
/* remove the timed handler */ /* remove the timed handler */
xmpp_timed_handler_delete(conn, _disconnect_cleanup); xmpp_timed_handler_delete(conn, _disconnect_cleanup);
@@ -844,7 +706,7 @@ void conn_disconnect_clean(xmpp_conn_t *conn)
* *
* @param conn a Strophe connection object * @param conn a Strophe connection object
*/ */
void conn_disconnect(xmpp_conn_t *conn) void conn_disconnect(xmpp_conn_t *const conn)
{ {
xmpp_debug(conn->ctx, "xmpp", "Closing socket."); xmpp_debug(conn->ctx, "xmpp", "Closing socket.");
conn->state = XMPP_STATE_DISCONNECTED; conn->state = XMPP_STATE_DISCONNECTED;
@@ -862,14 +724,14 @@ void conn_disconnect(xmpp_conn_t *conn)
/* prepares a parser reset. this is called from handlers. we can't /* prepares a parser reset. this is called from handlers. we can't
* reset the parser immediately as it is not re-entrant. */ * reset the parser immediately as it is not re-entrant. */
void conn_prepare_reset(xmpp_conn_t *conn, xmpp_open_handler handler) void conn_prepare_reset(xmpp_conn_t *const conn, xmpp_open_handler handler)
{ {
conn->reset_parser = 1; conn->reset_parser = 1;
conn->open_handler = handler; conn->open_handler = handler;
} }
/* reset the parser */ /* reset the parser */
void conn_parser_reset(xmpp_conn_t *conn) void conn_parser_reset(xmpp_conn_t *const conn)
{ {
conn->reset_parser = 0; conn->reset_parser = 0;
parser_reset(conn->parser); parser_reset(conn->parser);
@@ -884,7 +746,7 @@ void conn_parser_reset(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
void xmpp_disconnect(xmpp_conn_t *conn) void xmpp_disconnect(xmpp_conn_t *const conn)
{ {
if (conn->state != XMPP_STATE_CONNECTING && if (conn->state != XMPP_STATE_CONNECTING &&
conn->state != XMPP_STATE_CONNECTED) conn->state != XMPP_STATE_CONNECTED)
@@ -910,16 +772,13 @@ void xmpp_disconnect(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...) void xmpp_send_raw_string(xmpp_conn_t *const conn, const char *const fmt, ...)
{ {
va_list ap; va_list ap;
size_t len; size_t len;
char buf[1024]; /* small buffer for common case */ char buf[1024]; /* small buffer for common case */
char *bigbuf; char *bigbuf;
if (conn->state != XMPP_STATE_CONNECTED)
return;
va_start(ap, fmt); va_start(ap, fmt);
len = xmpp_vsnprintf(buf, sizeof(buf), fmt, ap); len = xmpp_vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap); va_end(ap);
@@ -938,10 +797,14 @@ void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...)
xmpp_vsnprintf(bigbuf, len, fmt, ap); xmpp_vsnprintf(bigbuf, len, fmt, ap);
va_end(ap); va_end(ap);
xmpp_debug(conn->ctx, "conn", "SENT: %s", bigbuf);
/* len - 1 so we don't send trailing \0 */ /* len - 1 so we don't send trailing \0 */
_send_raw(conn, bigbuf, len - 1); xmpp_send_raw(conn, bigbuf, len - 1);
xmpp_free(conn->ctx, bigbuf);
} else { } else {
/* go through xmpp_send_raw() which does the strdup() for us */ xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
xmpp_send_raw(conn, buf, len); xmpp_send_raw(conn, buf, len);
} }
} }
@@ -958,20 +821,41 @@ void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...)
* *
* @ingroup Connections * @ingroup Connections
*/ */
void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len) void xmpp_send_raw(xmpp_conn_t *const conn,
const char *const data,
const size_t len)
{ {
char *d; xmpp_send_queue_t *item;
if (conn->state != XMPP_STATE_CONNECTED) if (conn->state != XMPP_STATE_CONNECTED)
return; return;
d = xmpp_strndup(conn->ctx, data, len); /* create send queue item for queue */
if (!d) { item = xmpp_alloc(conn->ctx, sizeof(xmpp_send_queue_t));
xmpp_error(conn->ctx, "conn", "Failed to strndup"); if (!item)
return;
item->data = xmpp_alloc(conn->ctx, len);
if (!item->data) {
xmpp_free(conn->ctx, item);
return; return;
} }
memcpy(item->data, data, len);
item->len = len;
item->next = NULL;
item->written = 0;
_send_raw(conn, d, len); /* add item to the send queue */
if (!conn->send_queue_tail) {
/* first item, set head and tail */
conn->send_queue_head = item;
conn->send_queue_tail = item;
} else {
/* add to the tail */
conn->send_queue_tail->next = item;
conn->send_queue_tail = item;
}
conn->send_queue_len++;
} }
/** Send an XML stanza to the XMPP server. /** Send an XML stanza to the XMPP server.
@@ -983,20 +867,18 @@ void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len)
* *
* @ingroup Connections * @ingroup Connections
*/ */
void xmpp_send(xmpp_conn_t *conn, xmpp_stanza_t *stanza) void xmpp_send(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza)
{ {
char *buf = NULL; char *buf;
size_t len; size_t len;
if (conn->state != XMPP_STATE_CONNECTED) if (conn->state == XMPP_STATE_CONNECTED) {
return; if (xmpp_stanza_to_text(stanza, &buf, &len) == 0) {
xmpp_send_raw(conn, buf, len);
if (xmpp_stanza_to_text(stanza, &buf, &len) != 0) { xmpp_debug(conn->ctx, "conn", "SENT: %s", buf);
xmpp_error(conn->ctx, "conn", "Failed to stanza_to_text"); xmpp_free(conn->ctx, buf);
return; }
} }
_send_raw(conn, buf, len);
} }
/** Send the opening &lt;stream:stream&gt; tag to the server. /** Send the opening &lt;stream:stream&gt; tag to the server.
@@ -1005,36 +887,22 @@ void xmpp_send(xmpp_conn_t *conn, xmpp_stanza_t *stanza)
* *
* @param conn a Strophe connection object * @param conn a Strophe connection object
*/ */
void conn_open_stream(xmpp_conn_t *conn) void conn_open_stream(xmpp_conn_t *const conn)
{ {
size_t attributes_len; xmpp_send_raw_string(conn,
int rc; "<?xml version=\"1.0\"?>"
char *from = NULL; "<stream:stream to=\"%s\" "
char *ns = conn->type == XMPP_CLIENT ? XMPP_NS_CLIENT : XMPP_NS_COMPONENT; "xml:lang=\"%s\" "
char *attributes[12] = { "version=\"1.0\" "
"to", conn->domain, "xml:lang", conn->lang, "xmlns=\"%s\" "
"version", "1.0", "xmlns", ns, "xmlns:stream=\"%s\">",
"xmlns:stream", XMPP_NS_STREAMS, "from", NULL}; conn->domain, conn->lang,
conn->type == XMPP_CLIENT ? XMPP_NS_CLIENT
attributes_len = ARRAY_SIZE(attributes); : XMPP_NS_COMPONENT,
if (conn->tls && conn->jid && strchr(conn->jid, '@') != NULL) XMPP_NS_STREAMS);
from = xmpp_jid_bare(conn->ctx, conn->jid);
if (from)
attributes[attributes_len - 1] = from;
else
attributes_len -= 2;
rc = _conn_open_stream_with_attributes(conn, attributes, attributes_len);
if (rc != XMPP_EOK) {
xmpp_error(conn->ctx, "conn", "Cannot build stream tag: memory error");
conn_disconnect(conn);
}
if (from)
xmpp_free(conn->ctx, from);
} }
int conn_tls_start(xmpp_conn_t *conn) int conn_tls_start(xmpp_conn_t *const conn)
{ {
int rc; int rc;
@@ -1050,8 +918,8 @@ int conn_tls_start(xmpp_conn_t *conn)
if (tls_start(conn->tls)) { if (tls_start(conn->tls)) {
conn->secured = 1; conn->secured = 1;
} else { } else {
rc = XMPP_EINT; /* TODO: distinguish invalid certificates and other errors */
conn->error = tls_error(conn->tls); rc = XMPP_ECERT;
tls_free(conn->tls); tls_free(conn->tls);
conn->tls = NULL; conn->tls = NULL;
conn->tls_failed = 1; conn->tls_failed = 1;
@@ -1059,9 +927,9 @@ int conn_tls_start(xmpp_conn_t *conn)
} }
if (rc != 0) { if (rc != 0) {
xmpp_debug(conn->ctx, "conn", xmpp_debug(conn->ctx, "conn",
"Couldn't start TLS! " "Couldn't start TLS! error %d tls_error %d", rc,
"error %d tls_error %d", conn->tls == NULL ? 0 : tls_error(conn->tls));
rc, conn->error); conn->error = rc;
} }
return rc; return rc;
} }
@@ -1074,7 +942,7 @@ int conn_tls_start(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
long xmpp_conn_get_flags(const xmpp_conn_t *conn) long xmpp_conn_get_flags(const xmpp_conn_t *const conn)
{ {
long flags; long flags;
@@ -1083,6 +951,7 @@ long xmpp_conn_get_flags(const xmpp_conn_t *conn)
XMPP_CONN_FLAG_LEGACY_SSL * conn->tls_legacy_ssl | XMPP_CONN_FLAG_LEGACY_SSL * conn->tls_legacy_ssl |
XMPP_CONN_FLAG_TRUST_TLS * conn->tls_trust | XMPP_CONN_FLAG_TRUST_TLS * conn->tls_trust |
XMPP_CONN_FLAG_LEGACY_AUTH * conn->auth_legacy_enabled; XMPP_CONN_FLAG_LEGACY_AUTH * conn->auth_legacy_enabled;
;
return flags; return flags;
} }
@@ -1109,7 +978,7 @@ long xmpp_conn_get_flags(const xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags) int xmpp_conn_set_flags(xmpp_conn_t *const conn, long flags)
{ {
if (conn->state != XMPP_STATE_DISCONNECTED) { if (conn->state != XMPP_STATE_DISCONNECTED) {
xmpp_error(conn->ctx, "conn", xmpp_error(conn->ctx, "conn",
@@ -1144,7 +1013,7 @@ int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags)
* *
* @ingroup Connections * @ingroup Connections
*/ */
void xmpp_conn_disable_tls(xmpp_conn_t *conn) void xmpp_conn_disable_tls(xmpp_conn_t *const conn)
{ {
long flags = xmpp_conn_get_flags(conn); long flags = xmpp_conn_get_flags(conn);
@@ -1158,7 +1027,7 @@ void xmpp_conn_disable_tls(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_conn_is_secured(xmpp_conn_t *conn) int xmpp_conn_is_secured(xmpp_conn_t *const conn)
{ {
return conn->secured && !conn->tls_failed && conn->tls != NULL; return conn->secured && !conn->tls_failed && conn->tls != NULL;
} }
@@ -1168,7 +1037,7 @@ int xmpp_conn_is_secured(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_conn_is_connecting(xmpp_conn_t *conn) int xmpp_conn_is_connecting(xmpp_conn_t *const conn)
{ {
return conn->state == XMPP_STATE_CONNECTING; return conn->state == XMPP_STATE_CONNECTING;
} }
@@ -1178,7 +1047,7 @@ int xmpp_conn_is_connecting(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_conn_is_connected(xmpp_conn_t *conn) int xmpp_conn_is_connected(xmpp_conn_t *const conn)
{ {
return conn->state == XMPP_STATE_CONNECTED; return conn->state == XMPP_STATE_CONNECTED;
} }
@@ -1188,24 +1057,25 @@ int xmpp_conn_is_connected(xmpp_conn_t *conn)
* *
* @ingroup Connections * @ingroup Connections
*/ */
int xmpp_conn_is_disconnected(xmpp_conn_t *conn) int xmpp_conn_is_disconnected(xmpp_conn_t *const conn)
{ {
return conn->state == XMPP_STATE_DISCONNECTED; return conn->state == XMPP_STATE_DISCONNECTED;
} }
/* timed handler for cleanup if normal disconnect procedure takes too long */ /* timed handler for cleanup if normal disconnect procedure takes too long */
static int _disconnect_cleanup(xmpp_conn_t *conn, void *userdata) static int _disconnect_cleanup(xmpp_conn_t *const conn, void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
xmpp_debug(conn->ctx, "xmpp", "disconnection forced by cleanup timeout"); xmpp_debug(conn->ctx, "xmpp", "disconnection forced by cleanup timeout");
conn->error = conn->error ?: XMPP_ETIMEDOUT;
conn_disconnect(conn); conn_disconnect(conn);
return 0; return 0;
} }
static char *_conn_build_stream_tag(xmpp_conn_t *conn, static char *_conn_build_stream_tag(xmpp_conn_t *const conn,
char **attributes, char **attributes,
size_t attributes_len) size_t attributes_len)
{ {
@@ -1250,22 +1120,6 @@ static char *_conn_build_stream_tag(xmpp_conn_t *conn,
return tag; return tag;
} }
static int _conn_open_stream_with_attributes(xmpp_conn_t *conn,
char **attributes,
size_t attributes_len)
{
char *tag;
tag = _conn_build_stream_tag(conn, attributes, attributes_len);
if (!tag)
return XMPP_EMEM;
xmpp_send_raw_string(conn, "<?xml version=\"1.0\"?>%s", tag);
xmpp_free(conn->ctx, tag);
return XMPP_EOK;
}
static void _conn_attributes_new(xmpp_conn_t *conn, static void _conn_attributes_new(xmpp_conn_t *conn,
char **attrs, char **attrs,
char ***attributes, char ***attributes,
@@ -1338,11 +1192,11 @@ static char *_get_stream_attribute(char **attrs, char *name)
return NULL; return NULL;
} }
static void _handle_stream_start(char *name, char **attrs, void *userdata) static void _handle_stream_start(char *name, char **attrs, void *const userdata)
{ {
xmpp_conn_t *conn = (xmpp_conn_t *)userdata; xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
char *id; char *id;
int failed = 0; int ret = 0;
if (conn->stream_id) if (conn->stream_id)
xmpp_free(conn->ctx, conn->stream_id); xmpp_free(conn->ctx, conn->stream_id);
@@ -1356,25 +1210,26 @@ static void _handle_stream_start(char *name, char **attrs, void *userdata)
if (id && !conn->stream_id) { if (id && !conn->stream_id) {
xmpp_error(conn->ctx, "conn", "Memory allocation failed."); xmpp_error(conn->ctx, "conn", "Memory allocation failed.");
failed = 1; ret = XMPP_EMEM;
} }
} else { } else {
xmpp_error(conn->ctx, "conn", xmpp_error(conn->ctx, "conn",
"Server did not open valid stream." "Server did not open valid stream."
" name = %s.", " name = %s.",
name); name);
failed = 1; ret = XMPP_EINT;
} }
if (!failed) { if (ret == 0) {
/* call stream open handler */ /* call stream open handler */
conn->open_handler(conn); conn->open_handler(conn);
} else { } else {
conn->error = ret;
conn_disconnect(conn); conn_disconnect(conn);
} }
} }
static void _handle_stream_end(char *name, void *userdata) static void _handle_stream_end(char *name, void *const userdata)
{ {
xmpp_conn_t *conn = (xmpp_conn_t *)userdata; xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
@@ -1385,7 +1240,7 @@ static void _handle_stream_end(char *name, void *userdata)
conn_disconnect_clean(conn); conn_disconnect_clean(conn);
} }
static void _handle_stream_stanza(xmpp_stanza_t *stanza, void *userdata) static void _handle_stream_stanza(xmpp_stanza_t *stanza, void *const userdata)
{ {
xmpp_conn_t *conn = (xmpp_conn_t *)userdata; xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
char *buf; char *buf;
@@ -1399,7 +1254,7 @@ static void _handle_stream_stanza(xmpp_stanza_t *stanza, void *userdata)
handler_fire_stanza(conn, stanza); handler_fire_stanza(conn, stanza);
} }
static unsigned short _conn_default_port(xmpp_conn_t *conn, static unsigned short _conn_default_port(xmpp_conn_t *const conn,
xmpp_conn_type_t type) xmpp_conn_type_t type)
{ {
switch (type) { switch (type) {
@@ -1413,7 +1268,7 @@ static unsigned short _conn_default_port(xmpp_conn_t *conn,
}; };
} }
static void _conn_reset(xmpp_conn_t *conn) static void _conn_reset(xmpp_conn_t *const conn)
{ {
xmpp_ctx_t *ctx = conn->ctx; xmpp_ctx_t *ctx = conn->ctx;
xmpp_send_queue_t *sq, *tsq; xmpp_send_queue_t *sq, *tsq;
@@ -1464,13 +1319,13 @@ static void _conn_reset(xmpp_conn_t *conn)
handler_system_delete_all(conn); handler_system_delete_all(conn);
} }
static int _conn_connect(xmpp_conn_t *conn, static int _conn_connect(xmpp_conn_t *const conn,
const char *domain, const char *const domain,
const char *host, const char *const host,
unsigned short port, unsigned short port,
xmpp_conn_type_t type, xmpp_conn_type_t type,
xmpp_conn_handler callback, xmpp_conn_handler callback,
void *userdata) void *const userdata)
{ {
xmpp_open_handler open_handler; xmpp_open_handler open_handler;
@@ -1500,9 +1355,10 @@ static int _conn_connect(xmpp_conn_t *conn,
conn->conn_handler = callback; conn->conn_handler = callback;
conn->userdata = userdata; conn->userdata = userdata;
open_handler = conn->is_raw ? auth_handle_open_stub open_handler = conn->is_raw
: type == XMPP_CLIENT ? auth_handle_open ? auth_handle_open_stub
: auth_handle_component_open; : type == XMPP_CLIENT ? auth_handle_open
: auth_handle_component_open;
conn_prepare_reset(conn, open_handler); conn_prepare_reset(conn, open_handler);
/* FIXME: it could happen that the connect returns immediately as /* FIXME: it could happen that the connect returns immediately as
@@ -1516,36 +1372,3 @@ static int _conn_connect(xmpp_conn_t *conn,
return 0; return 0;
} }
static int _send_raw(xmpp_conn_t *conn, char *data, size_t len)
{
xmpp_send_queue_t *item;
/* create send queue item for queue */
item = xmpp_alloc(conn->ctx, sizeof(xmpp_send_queue_t));
if (!item) {
xmpp_error(conn->ctx, "conn", "DROPPED: %s", data);
xmpp_free(conn->ctx, data);
return XMPP_EMEM;
}
item->data = data;
item->len = len;
item->next = NULL;
item->written = 0;
/* add item to the send queue */
if (!conn->send_queue_tail) {
/* first item, set head and tail */
conn->send_queue_head = item;
conn->send_queue_tail = item;
} else {
/* add to the tail */
conn->send_queue_tail->next = item;
conn->send_queue_tail = item;
}
conn->send_queue_len++;
xmpp_debug_verbose(2, conn->ctx, "conn", "QUEUED: %s", data);
xmpp_debug_verbose(1, conn->ctx, "conn", "Added queue element: %p", item);
return XMPP_EOK;
}

View File

@@ -244,14 +244,15 @@ static const char _base64_charmap[65] = {
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '='}; '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '='};
static size_t base64_encoded_len(size_t len) static size_t base64_encoded_len(const size_t len)
{ {
/* encoded steam is 4 bytes for every three, rounded up */ /* encoded steam is 4 bytes for every three, rounded up */
return ((len + 2) / 3) << 2; return ((len + 2) / 3) << 2;
} }
static char * static char *base64_encode(xmpp_ctx_t *ctx,
base64_encode(xmpp_ctx_t *ctx, const unsigned char *buffer, size_t len) const unsigned char *const buffer,
const size_t len)
{ {
size_t clen; size_t clen;
char *cbuf, *c; char *cbuf, *c;
@@ -303,7 +304,7 @@ base64_encode(xmpp_ctx_t *ctx, const unsigned char *buffer, size_t len)
return cbuf; return cbuf;
} }
static size_t base64_decoded_len(const char *buffer, size_t len) static size_t base64_decoded_len(const char *const buffer, const size_t len)
{ {
size_t nudge = 0; size_t nudge = 0;
unsigned char c; unsigned char c;
@@ -330,8 +331,8 @@ static size_t base64_decoded_len(const char *buffer, size_t len)
} }
static void base64_decode(xmpp_ctx_t *ctx, static void base64_decode(xmpp_ctx_t *ctx,
const char *buffer, const char *const buffer,
size_t len, const size_t len,
unsigned char **out, unsigned char **out,
size_t *outlen) size_t *outlen)
{ {

104
src/ctx.c
View File

@@ -122,19 +122,19 @@ int xmpp_version_check(int major, int minor)
/* Wrap stdlib routines malloc, free, and realloc for default memory /* Wrap stdlib routines malloc, free, and realloc for default memory
* management. * management.
*/ */
static void *_malloc(size_t size, void *userdata) static void *_malloc(const size_t size, void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
return malloc(size); return malloc(size);
} }
static void _free(void *p, void *userdata) static void _free(void *p, void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
free(p); free(p);
} }
static void *_realloc(void *p, size_t size, void *userdata) static void *_realloc(void *p, const size_t size, void *const userdata)
{ {
UNUSED(userdata); UNUSED(userdata);
return realloc(p, size); return realloc(p, size);
@@ -146,7 +146,8 @@ static xmpp_mem_t xmpp_default_mem = {
_free, _realloc, NULL}; _free, _realloc, NULL};
/* log levels and names */ /* log levels and names */
static const char *_xmpp_log_level_name[4] = {"DEBUG", "INFO", "WARN", "ERROR"}; static const char *const _xmpp_log_level_name[4] = {"DEBUG", "INFO", "WARN",
"ERROR"};
static const xmpp_log_level_t _xmpp_default_logger_levels[] = { static const xmpp_log_level_t _xmpp_default_logger_levels[] = {
XMPP_LEVEL_DEBUG, XMPP_LEVEL_INFO, XMPP_LEVEL_WARN, XMPP_LEVEL_ERROR}; XMPP_LEVEL_DEBUG, XMPP_LEVEL_INFO, XMPP_LEVEL_WARN, XMPP_LEVEL_ERROR};
@@ -159,10 +160,10 @@ static const xmpp_log_level_t _xmpp_default_logger_levels[] = {
* @param area the area the log message is for * @param area the area the log message is for
* @param msg the log message * @param msg the log message
*/ */
static void xmpp_default_logger(void *userdata, static void xmpp_default_logger(void *const userdata,
xmpp_log_level_t level, const xmpp_log_level_t level,
const char *area, const char *const area,
const char *msg) const char *const msg)
{ {
xmpp_log_level_t filter_level = *(xmpp_log_level_t *)userdata; xmpp_log_level_t filter_level = *(xmpp_log_level_t *)userdata;
if (level >= filter_level) if (level >= filter_level)
@@ -211,7 +212,7 @@ static xmpp_log_t xmpp_default_log = {NULL, NULL};
* *
* @return a pointer to the allocated memory or NULL on an error * @return a pointer to the allocated memory or NULL on an error
*/ */
void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size) void *xmpp_alloc(const xmpp_ctx_t *const ctx, const size_t size)
{ {
return ctx->mem->alloc(size, ctx->mem->userdata); return ctx->mem->alloc(size, ctx->mem->userdata);
} }
@@ -222,7 +223,7 @@ void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size)
* @param ctx a Strophe context object * @param ctx a Strophe context object
* @param p a pointer referencing memory to be freed * @param p a pointer referencing memory to be freed
*/ */
void xmpp_free(const xmpp_ctx_t *ctx, void *p) void xmpp_free(const xmpp_ctx_t *const ctx, void *p)
{ {
ctx->mem->free(p, ctx->mem->userdata); ctx->mem->free(p, ctx->mem->userdata);
} }
@@ -236,7 +237,7 @@ void xmpp_free(const xmpp_ctx_t *ctx, void *p)
* *
* @return a pointer to the reallocated memory or NULL on an error * @return a pointer to the reallocated memory or NULL on an error
*/ */
void *xmpp_realloc(const xmpp_ctx_t *ctx, void *p, size_t size) void *xmpp_realloc(const xmpp_ctx_t *const ctx, void *p, const size_t size)
{ {
return ctx->mem->realloc(p, size, ctx->mem->userdata); return ctx->mem->realloc(p, size, ctx->mem->userdata);
} }
@@ -254,10 +255,10 @@ void *xmpp_realloc(const xmpp_ctx_t *ctx, void *p, size_t size)
* @param fmt a printf-style format string for the message * @param fmt a printf-style format string for the message
* @param ap variable argument list supplied for the format string * @param ap variable argument list supplied for the format string
*/ */
void xmpp_log(const xmpp_ctx_t *ctx, void xmpp_log(const xmpp_ctx_t *const ctx,
xmpp_log_level_t level, const xmpp_log_level_t level,
const char *area, const char *const area,
const char *fmt, const char *const fmt,
va_list ap) va_list ap)
{ {
int oldret, ret; int oldret, ret;
@@ -265,13 +266,6 @@ void xmpp_log(const xmpp_ctx_t *ctx,
char *buf; char *buf;
va_list copy; va_list copy;
if (!ctx->log->handler)
return;
if (ctx->log->handler == xmpp_default_logger &&
level < *(xmpp_log_level_t *)ctx->log->userdata)
return;
va_copy(copy, ap); va_copy(copy, ap);
ret = xmpp_vsnprintf(smbuf, sizeof(smbuf), fmt, ap); ret = xmpp_vsnprintf(smbuf, sizeof(smbuf), fmt, ap);
if (ret >= (int)sizeof(smbuf)) { if (ret >= (int)sizeof(smbuf)) {
@@ -295,7 +289,8 @@ void xmpp_log(const xmpp_ctx_t *ctx,
} }
va_end(copy); va_end(copy);
ctx->log->handler(ctx->log->userdata, level, area, buf); if (ctx->log->handler)
ctx->log->handler(ctx->log->userdata, level, area, buf);
if (buf != smbuf) if (buf != smbuf)
xmpp_free(ctx, buf); xmpp_free(ctx, buf);
@@ -311,7 +306,10 @@ void xmpp_log(const xmpp_ctx_t *ctx,
* @param fmt a printf-style format string followed by a variable list of * @param fmt a printf-style format string followed by a variable list of
* arguments to format * arguments to format
*/ */
void xmpp_error(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...) void xmpp_error(const xmpp_ctx_t *const ctx,
const char *const area,
const char *const fmt,
...)
{ {
va_list ap; va_list ap;
@@ -330,7 +328,10 @@ void xmpp_error(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...)
* @param fmt a printf-style format string followed by a variable list of * @param fmt a printf-style format string followed by a variable list of
* arguments to format * arguments to format
*/ */
void xmpp_warn(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...) void xmpp_warn(const xmpp_ctx_t *const ctx,
const char *const area,
const char *const fmt,
...)
{ {
va_list ap; va_list ap;
@@ -349,7 +350,10 @@ void xmpp_warn(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...)
* @param fmt a printf-style format string followed by a variable list of * @param fmt a printf-style format string followed by a variable list of
* arguments to format * arguments to format
*/ */
void xmpp_info(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...) void xmpp_info(const xmpp_ctx_t *const ctx,
const char *const area,
const char *const fmt,
...)
{ {
va_list ap; va_list ap;
@@ -368,7 +372,10 @@ void xmpp_info(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...)
* @param fmt a printf-style format string followed by a variable list of * @param fmt a printf-style format string followed by a variable list of
* arguments to format * arguments to format
*/ */
void xmpp_debug(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...) void xmpp_debug(const xmpp_ctx_t *const ctx,
const char *const area,
const char *const fmt,
...)
{ {
va_list ap; va_list ap;
@@ -377,30 +384,6 @@ void xmpp_debug(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
/** Write to the log at the DEBUG level if verbosity is enabled.
* This is a convenience function for writing to the log at the DEBUG level.
* It takes a printf-style format string followed by a variable list of
* arguments for formatting.
*
* @param level the verbosity level
* @param ctx a Strophe context object
* @param area the area to log for
* @param fmt a printf-style format string followed by a variable list of
* arguments to format
*/
void xmpp_debug_verbose(
int level, const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...)
{
va_list ap;
if (ctx->verbosity < level)
return;
va_start(ap, fmt);
xmpp_log(ctx, XMPP_LEVEL_DEBUG, area, fmt, ap);
va_end(ap);
}
/** Create and initialize a Strophe context object. /** Create and initialize a Strophe context object.
* If mem is NULL, a default allocation setup will be used which * If mem is NULL, a default allocation setup will be used which
* wraps malloc(), free(), and realloc() from the standard library. * wraps malloc(), free(), and realloc() from the standard library.
@@ -415,7 +398,8 @@ void xmpp_debug_verbose(
* *
* @ingroup Context * @ingroup Context
*/ */
xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t *mem, const xmpp_log_t *log) xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t *const mem,
const xmpp_log_t *const log)
{ {
xmpp_ctx_t *ctx = NULL; xmpp_ctx_t *ctx = NULL;
@@ -455,7 +439,7 @@ xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t *mem, const xmpp_log_t *log)
* *
* @ingroup Context * @ingroup Context
*/ */
void xmpp_ctx_free(xmpp_ctx_t *ctx) void xmpp_ctx_free(xmpp_ctx_t *const ctx)
{ {
/* mem and log are owned by their suppliers */ /* mem and log are owned by their suppliers */
xmpp_rand_free(ctx, ctx->rand); xmpp_rand_free(ctx, ctx->rand);
@@ -469,19 +453,7 @@ void xmpp_ctx_free(xmpp_ctx_t *ctx)
* *
* @ingroup Context * @ingroup Context
*/ */
void xmpp_ctx_set_timeout(xmpp_ctx_t *ctx, unsigned long timeout) void xmpp_ctx_set_timeout(xmpp_ctx_t *const ctx, const unsigned long timeout)
{ {
ctx->timeout = timeout; ctx->timeout = timeout;
} }
/** Set the verbosity level of a Strophe context.
*
* @param ctx a Strophe context object
* @param level the verbosity level
*
* @ingroup Context
*/
void xmpp_ctx_set_verbosity(xmpp_ctx_t *ctx, int level)
{
ctx->verbosity = level;
}

View File

@@ -41,15 +41,6 @@
#define _sleep(x) usleep((x)*1000) #define _sleep(x) usleep((x)*1000)
#else #else
#include <winsock2.h> #include <winsock2.h>
#ifndef ETIMEDOUT
#define ETIMEDOUT WSAETIMEDOUT
#endif
#ifndef ECONNRESET
#define ECONNRESET WSAECONNRESET
#endif
#ifndef ECONNABORTED
#define ECONNABORTED WSAECONNABORTED
#endif
#define _sleep(x) Sleep(x) #define _sleep(x) Sleep(x)
#endif #endif
@@ -73,7 +64,7 @@
* *
* @ingroup EventLoop * @ingroup EventLoop
*/ */
void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout) void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
{ {
xmpp_connlist_t *connitem; xmpp_connlist_t *connitem;
xmpp_conn_t *conn; xmpp_conn_t *conn;
@@ -107,26 +98,23 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls))) { if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls))) {
/* an error occurred */ /* an error occurred */
xmpp_debug(ctx, "xmpp", "Send error occurred, disconnecting."); conn->error = XMPP_EIO;
conn->error = ECONNABORTED;
conn_disconnect(conn);
goto NEXT_ITEM;
} }
} }
/* write all data from the send queue to the socket */ /* write all data from the send queue to the socket */
sq = conn->send_queue_head; sq = conn->send_queue_head;
while (sq) { while (!conn->error && sq) {
towrite = sq->len - sq->written; towrite = sq->len - sq->written;
if (conn->tls) { if (conn->tls) {
ret = tls_write(conn->tls, &sq->data[sq->written], towrite); ret = tls_write(conn->tls, &sq->data[sq->written], towrite);
if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls))) if (ret < 0 && !tls_is_recoverable(tls_error(conn->tls)))
conn->error = tls_error(conn->tls); conn->error = XMPP_EIO;
} else { } else {
ret = sock_write(conn->sock, &sq->data[sq->written], towrite); ret = sock_write(conn->sock, &sq->data[sq->written], towrite);
if (ret < 0 && !sock_is_recoverable(sock_error())) if (ret < 0 && !sock_is_recoverable(sock_error()))
conn->error = sock_error(); conn->error = XMPP_EIO;
} }
if (ret > 0 && ret < towrite) if (ret > 0 && ret < towrite)
sq->written += ret; /* not all data could be sent now */ sq->written += ret; /* not all data could be sent now */
@@ -134,9 +122,6 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
break; /* partial write or an error */ break; /* partial write or an error */
/* all data for this queue item written, delete and move on */ /* all data for this queue item written, delete and move on */
xmpp_debug(conn->ctx, "conn", "SENT: %s", sq->data);
xmpp_debug_verbose(1, ctx, "xmpp",
"Finished writing queue element: %p.", sq);
xmpp_free(ctx, sq->data); xmpp_free(ctx, sq->data);
tsq = sq; tsq = sq;
sq = sq->next; sq = sq->next;
@@ -155,10 +140,9 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
/* FIXME: need to tear down send queues and random other things /* FIXME: need to tear down send queues and random other things
* maybe this should be abstracted */ * maybe this should be abstracted */
xmpp_debug(ctx, "xmpp", "Send error occurred, disconnecting."); xmpp_debug(ctx, "xmpp", "Send error occurred, disconnecting.");
conn->error = ECONNABORTED;
conn_disconnect(conn); conn_disconnect(conn);
} }
NEXT_ITEM:
connitem = connitem->next; connitem = connitem->next;
} }
@@ -194,8 +178,8 @@ NEXT_ITEM:
conn->connect_timeout) conn->connect_timeout)
FD_SET(conn->sock, &wfds); FD_SET(conn->sock, &wfds);
else { else {
conn->error = ETIMEDOUT;
xmpp_info(ctx, "xmpp", "Connection attempt timed out."); xmpp_info(ctx, "xmpp", "Connection attempt timed out.");
conn->error = XMPP_ETIMEDOUT;
conn_disconnect(conn); conn_disconnect(conn);
} }
break; break;
@@ -256,6 +240,7 @@ NEXT_ITEM:
if (ret != 0) { if (ret != 0) {
/* connection failed */ /* connection failed */
xmpp_debug(ctx, "xmpp", "connection failed, error %d", ret); xmpp_debug(ctx, "xmpp", "connection failed, error %d", ret);
conn->error = XMPP_EIO;
conn_disconnect(conn); conn_disconnect(conn);
break; break;
} }
@@ -289,14 +274,14 @@ NEXT_ITEM:
xmpp_debug(ctx, "xmpp", xmpp_debug(ctx, "xmpp",
"Unrecoverable TLS error, %d.", "Unrecoverable TLS error, %d.",
tls_error(conn->tls)); tls_error(conn->tls));
conn->error = tls_error(conn->tls); conn->error = XMPP_EIO;
conn_disconnect(conn); conn_disconnect(conn);
} }
} else { } else {
/* return of 0 means socket closed by server */ /* return of 0 means socket closed by server */
xmpp_debug(ctx, "xmpp", xmpp_debug(ctx, "xmpp",
"Socket closed by remote host."); "Socket closed by remote host.");
conn->error = ECONNRESET; conn->error = ret == 0 ? XMPP_ERESET : XMPP_EIO;
conn_disconnect(conn); conn_disconnect(conn);
} }
} }

View File

@@ -53,7 +53,7 @@ static void _handler_item_remove(xmpp_handlist_t **head, xmpp_handlist_t *item)
* @param conn a Strophe connection object * @param conn a Strophe connection object
* @param stanza a Strophe stanza object * @param stanza a Strophe stanza object
*/ */
void handler_fire_stanza(xmpp_conn_t *conn, xmpp_stanza_t *stanza) void handler_fire_stanza(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza)
{ {
xmpp_handlist_t *item, *next, *head, *head_old; xmpp_handlist_t *item, *next, *head, *head_old;
const char *id, *ns, *name, *type; const char *id, *ns, *name, *type;
@@ -144,7 +144,7 @@ void handler_fire_stanza(xmpp_conn_t *conn, xmpp_stanza_t *stanza)
* *
* @return the time in milliseconds until the next handler will be ready * @return the time in milliseconds until the next handler will be ready
*/ */
uint64_t handler_fire_timed(xmpp_ctx_t *ctx) uint64_t handler_fire_timed(xmpp_ctx_t *const ctx)
{ {
xmpp_connlist_t *connitem; xmpp_connlist_t *connitem;
xmpp_handlist_t *item, *next; xmpp_handlist_t *item, *next;
@@ -253,9 +253,9 @@ void handler_reset_timed(xmpp_conn_t *conn, int user_only)
static void _timed_handler_add(xmpp_ctx_t *ctx, static void _timed_handler_add(xmpp_ctx_t *ctx,
xmpp_handlist_t **handlers_list, xmpp_handlist_t **handlers_list,
xmpp_void_handler handler, xmpp_void_handler handler,
unsigned long period, const unsigned long period,
void *userdata, void *const userdata,
int user_handler) const int user_handler)
{ {
xmpp_handlist_t *item; xmpp_handlist_t *item;
@@ -311,15 +311,16 @@ static void _timed_handler_delete(xmpp_ctx_t *ctx,
* *
* @ingroup Handlers * @ingroup Handlers
*/ */
void xmpp_timed_handler_delete(xmpp_conn_t *conn, xmpp_timed_handler handler) void xmpp_timed_handler_delete(xmpp_conn_t *const conn,
xmpp_timed_handler handler)
{ {
_timed_handler_delete(conn->ctx, &conn->timed_handlers, handler); _timed_handler_delete(conn->ctx, &conn->timed_handlers, handler);
} }
static void _id_handler_add(xmpp_conn_t *conn, static void _id_handler_add(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *id, const char *const id,
void *userdata, void *const userdata,
int user_handler) int user_handler)
{ {
xmpp_handlist_t *item, *tail; xmpp_handlist_t *item, *tail;
@@ -372,9 +373,9 @@ static void _id_handler_add(xmpp_conn_t *conn,
* *
* @ingroup Handlers * @ingroup Handlers
*/ */
void xmpp_id_handler_delete(xmpp_conn_t *conn, void xmpp_id_handler_delete(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *id) const char *const id)
{ {
xmpp_handlist_t *item, *prev, *next; xmpp_handlist_t *item, *prev, *next;
@@ -405,12 +406,12 @@ void xmpp_id_handler_delete(xmpp_conn_t *conn,
} }
/* add a stanza handler */ /* add a stanza handler */
static void _handler_add(xmpp_conn_t *conn, static void _handler_add(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *ns, const char *const ns,
const char *name, const char *const name,
const char *type, const char *const type,
void *userdata, void *const userdata,
int user_handler) int user_handler)
{ {
xmpp_handlist_t *item, *tail; xmpp_handlist_t *item, *tail;
@@ -488,7 +489,7 @@ static void _handler_add(xmpp_conn_t *conn,
* *
* @ingroup Handlers * @ingroup Handlers
*/ */
void xmpp_handler_delete(xmpp_conn_t *conn, xmpp_handler handler) void xmpp_handler_delete(xmpp_conn_t *const conn, xmpp_handler handler)
{ {
xmpp_handlist_t *prev, *item; xmpp_handlist_t *prev, *item;
@@ -535,10 +536,10 @@ void xmpp_handler_delete(xmpp_conn_t *conn, xmpp_handler handler)
* *
* @ingroup Handlers * @ingroup Handlers
*/ */
void xmpp_timed_handler_add(xmpp_conn_t *conn, void xmpp_timed_handler_add(xmpp_conn_t *const conn,
xmpp_timed_handler handler, xmpp_timed_handler handler,
unsigned long period, const unsigned long period,
void *userdata) void *const userdata)
{ {
_timed_handler_add(conn->ctx, &conn->timed_handlers, handler, period, _timed_handler_add(conn->ctx, &conn->timed_handlers, handler, period,
userdata, 1); userdata, 1);
@@ -553,10 +554,10 @@ void xmpp_timed_handler_add(xmpp_conn_t *conn,
* @param period the time in milliseconds between firings * @param period the time in milliseconds between firings
* @param userdata an opaque data pointer that will be passed to the handler * @param userdata an opaque data pointer that will be passed to the handler
*/ */
void handler_add_timed(xmpp_conn_t *conn, void handler_add_timed(xmpp_conn_t *const conn,
xmpp_timed_handler handler, xmpp_timed_handler handler,
unsigned long period, const unsigned long period,
void *userdata) void *const userdata)
{ {
_timed_handler_add(conn->ctx, &conn->timed_handlers, handler, period, _timed_handler_add(conn->ctx, &conn->timed_handlers, handler, period,
userdata, 0); userdata, 0);
@@ -578,10 +579,10 @@ void handler_add_timed(xmpp_conn_t *conn,
* *
* @ingroup Handlers * @ingroup Handlers
*/ */
void xmpp_id_handler_add(xmpp_conn_t *conn, void xmpp_id_handler_add(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *id, const char *const id,
void *userdata) void *const userdata)
{ {
_id_handler_add(conn, handler, id, userdata, 1); _id_handler_add(conn, handler, id, userdata, 1);
} }
@@ -595,10 +596,10 @@ void xmpp_id_handler_add(xmpp_conn_t *conn,
* @param id a string with the id * @param id a string with the id
* @param userdata an opaque data pointer that will be passed to the handler * @param userdata an opaque data pointer that will be passed to the handler
*/ */
void handler_add_id(xmpp_conn_t *conn, void handler_add_id(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *id, const char *const id,
void *userdata) void *const userdata)
{ {
_id_handler_add(conn, handler, id, userdata, 0); _id_handler_add(conn, handler, id, userdata, 0);
} }
@@ -625,12 +626,12 @@ void handler_add_id(xmpp_conn_t *conn,
* *
* @ingroup Handlers * @ingroup Handlers
*/ */
void xmpp_handler_add(xmpp_conn_t *conn, void xmpp_handler_add(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *ns, const char *const ns,
const char *name, const char *const name,
const char *type, const char *const type,
void *userdata) void *const userdata)
{ {
_handler_add(conn, handler, ns, name, type, userdata, 1); _handler_add(conn, handler, ns, name, type, userdata, 1);
} }
@@ -646,12 +647,12 @@ void xmpp_handler_add(xmpp_conn_t *conn,
* @param type a string with the 'type' attribute value to match * @param type a string with the 'type' attribute value to match
* @param userdata an opaque data pointer that will be passed to the handler * @param userdata an opaque data pointer that will be passed to the handler
*/ */
void handler_add(xmpp_conn_t *conn, void handler_add(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *ns, const char *const ns,
const char *name, const char *const name,
const char *type, const char *const type,
void *userdata) void *const userdata)
{ {
_handler_add(conn, handler, ns, name, type, userdata, 0); _handler_add(conn, handler, ns, name, type, userdata, 0);
} }
@@ -761,10 +762,10 @@ void handler_system_delete_all(xmpp_conn_t *conn)
* *
* @ingroup Handlers * @ingroup Handlers
*/ */
void xmpp_global_timed_handler_add(xmpp_ctx_t *ctx, void xmpp_global_timed_handler_add(xmpp_ctx_t *const ctx,
xmpp_global_timed_handler handler, xmpp_global_timed_handler handler,
unsigned long period, const unsigned long period,
void *userdata) void *const userdata)
{ {
_timed_handler_add(ctx, &ctx->timed_handlers, handler, period, userdata, 1); _timed_handler_add(ctx, &ctx->timed_handlers, handler, period, userdata, 1);
} }
@@ -776,7 +777,7 @@ void xmpp_global_timed_handler_add(xmpp_ctx_t *ctx,
* *
* @ingroup Handlers * @ingroup Handlers
*/ */
void xmpp_global_timed_handler_delete(xmpp_ctx_t *ctx, void xmpp_global_timed_handler_delete(xmpp_ctx_t *const ctx,
xmpp_global_timed_handler handler) xmpp_global_timed_handler handler)
{ {
_timed_handler_delete(ctx, &ctx->timed_handlers, handler); _timed_handler_delete(ctx, &ctx->timed_handlers, handler);

View File

@@ -46,7 +46,8 @@ struct _hash_iterator_t {
}; };
/** allocate and initialize a new hash table */ /** allocate and initialize a new hash table */
hash_t *hash_new(xmpp_ctx_t *ctx, int size, hash_free_func free_func) hash_t *
hash_new(xmpp_ctx_t *const ctx, const int size, hash_free_func free_func)
{ {
hash_t *result = NULL; hash_t *result = NULL;
@@ -71,14 +72,14 @@ hash_t *hash_new(xmpp_ctx_t *ctx, int size, hash_free_func free_func)
} }
/** obtain a new reference to an existing hash table */ /** obtain a new reference to an existing hash table */
hash_t *hash_clone(hash_t *table) hash_t *hash_clone(hash_t *const table)
{ {
table->ref++; table->ref++;
return table; return table;
} }
/** release a hash table that is no longer needed */ /** release a hash table that is no longer needed */
void hash_release(hash_t *table) void hash_release(hash_t *const table)
{ {
xmpp_ctx_t *ctx = table->ctx; xmpp_ctx_t *ctx = table->ctx;
hashentry_t *entry, *next; hashentry_t *entry, *next;
@@ -142,7 +143,7 @@ hashentry_t *_hash_entry_find(hash_t *table, const char *key)
* each key can appear only once; the value of any * each key can appear only once; the value of any
* identical key will be replaced * identical key will be replaced
*/ */
int hash_add(hash_t *table, const char *key, void *data) int hash_add(hash_t *table, const char *const key, void *data)
{ {
xmpp_ctx_t *ctx = table->ctx; xmpp_ctx_t *ctx = table->ctx;
hashentry_t *entry = NULL; hashentry_t *entry = NULL;

View File

@@ -18,22 +18,23 @@
typedef struct _hash_t hash_t; typedef struct _hash_t hash_t;
typedef void (*hash_free_func)(const xmpp_ctx_t *ctx, void *p); typedef void (*hash_free_func)(const xmpp_ctx_t *const ctx, void *p);
/** allocate and initialize a new hash table */ /** allocate and initialize a new hash table */
hash_t *hash_new(xmpp_ctx_t *ctx, int size, hash_free_func free_func); hash_t *
hash_new(xmpp_ctx_t *const ctx, const int size, hash_free_func free_func);
/** allocate a new reference to an existing hash table */ /** allocate a new reference to an existing hash table */
hash_t *hash_clone(hash_t *table); hash_t *hash_clone(hash_t *const table);
/** release a hash table when no longer needed */ /** release a hash table when no longer needed */
void hash_release(hash_t *table); void hash_release(hash_t *const table);
/** add a key, value pair to a hash table. /** add a key, value pair to a hash table.
* each key can appear only once; the value of any * each key can appear only once; the value of any
* identical key will be replaced * identical key will be replaced
*/ */
int hash_add(hash_t *table, const char *key, void *data); int hash_add(hash_t *table, const char *const key, void *data);
/** look up a key in a hash table */ /** look up a key in a hash table */
void *hash_get(hash_t *table, const char *key); void *hash_get(hash_t *table, const char *key);

View File

@@ -20,9 +20,12 @@
typedef struct _parser_t parser_t; typedef struct _parser_t parser_t;
typedef void (*parser_start_callback)(char *name, char **attrs, void *userdata); typedef void (*parser_start_callback)(char *name,
typedef void (*parser_end_callback)(char *name, void *userdata); char **attrs,
typedef void (*parser_stanza_callback)(xmpp_stanza_t *stanza, void *userdata); void *const userdata);
typedef void (*parser_end_callback)(char *name, void *const userdata);
typedef void (*parser_stanza_callback)(xmpp_stanza_t *stanza,
void *const userdata);
parser_t *parser_new(xmpp_ctx_t *ctx, parser_t *parser_new(xmpp_ctx_t *ctx,
parser_start_callback startcb, parser_start_callback startcb,

View File

@@ -295,26 +295,12 @@ char *parser_attr_name(xmpp_ctx_t *ctx, char *nsname)
return _xml_name(ctx, nsname); return _xml_name(ctx, nsname);
} }
static void _free_parent_stanza(xmpp_stanza_t *stanza)
{
xmpp_stanza_t *parent;
for (parent = stanza; parent->parent != NULL; parent = parent->parent)
;
xmpp_stanza_release(parent);
}
/* free a parser */ /* free a parser */
void parser_free(parser_t *parser) void parser_free(parser_t *parser)
{ {
if (parser->expat) if (parser->expat)
XML_ParserFree(parser->expat); XML_ParserFree(parser->expat);
if (parser->stanza) {
_free_parent_stanza(parser->stanza);
parser->stanza = NULL;
}
if (parser->inner_text) { if (parser->inner_text) {
xmpp_free(parser->ctx, parser->inner_text); xmpp_free(parser->ctx, parser->inner_text);
parser->inner_text = NULL; parser->inner_text = NULL;
@@ -344,7 +330,7 @@ int parser_reset(parser_t *parser)
} }
if (parser->stanza) { if (parser->stanza) {
_free_parent_stanza(parser->stanza); xmpp_stanza_release(parser->stanza);
parser->stanza = NULL; parser->stanza = NULL;
} }

View File

@@ -262,22 +262,13 @@ char *parser_attr_name(xmpp_ctx_t *ctx, char *nsname)
return xmpp_strdup(ctx, nsname); return xmpp_strdup(ctx, nsname);
} }
static void _free_parent_stanza(xmpp_stanza_t *stanza)
{
xmpp_stanza_t *parent;
for (parent = stanza; parent->parent != NULL; parent = parent->parent)
;
xmpp_stanza_release(parent);
}
/* free a parser */ /* free a parser */
void parser_free(parser_t *parser) void parser_free(parser_t *parser)
{ {
if (parser->xmlctx) if (parser->xmlctx)
xmlFreeParserCtxt(parser->xmlctx); xmlFreeParserCtxt(parser->xmlctx);
if (parser->stanza) if (parser->stanza)
_free_parent_stanza(parser->stanza); xmpp_stanza_release(parser->stanza);
xmpp_free(parser->ctx, parser); xmpp_free(parser->ctx, parser);
} }
@@ -287,7 +278,7 @@ int parser_reset(parser_t *parser)
if (parser->xmlctx) if (parser->xmlctx)
xmlFreeParserCtxt(parser->xmlctx); xmlFreeParserCtxt(parser->xmlctx);
if (parser->stanza) if (parser->stanza)
_free_parent_stanza(parser->stanza); xmpp_stanza_release(parser->stanza);
parser->stanza = NULL; parser->stanza = NULL;
parser->depth = 0; parser->depth = 0;

View File

@@ -65,7 +65,7 @@ char *sasl_plain(xmpp_ctx_t *ctx, const char *authid, const char *password)
/** helpers for digest auth */ /** helpers for digest auth */
/* create a new, null-terminated string from a substring */ /* create a new, null-terminated string from a substring */
static char *_make_string(xmpp_ctx_t *ctx, const char *s, unsigned len) static char *_make_string(xmpp_ctx_t *ctx, const char *s, const unsigned len)
{ {
char *result; char *result;

View File

@@ -206,7 +206,9 @@ void crypto_SHA1_Init(SHA1_CTX *context)
} }
/* Run your data through this. */ /* Run your data through this. */
void crypto_SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len) void crypto_SHA1_Update(SHA1_CTX *context,
const uint8_t *data,
const size_t len)
{ {
size_t i, j; size_t i, j;

View File

@@ -24,7 +24,9 @@ typedef struct {
#define SHA1_DIGEST_SIZE 20 #define SHA1_DIGEST_SIZE 20
void crypto_SHA1_Init(SHA1_CTX *context); void crypto_SHA1_Init(SHA1_CTX *context);
void crypto_SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len); void crypto_SHA1_Update(SHA1_CTX *context,
const uint8_t *data,
const size_t len);
void crypto_SHA1_Final(SHA1_CTX *context, uint8_t *digest); void crypto_SHA1_Final(SHA1_CTX *context, uint8_t *digest);
void crypto_SHA1(const uint8_t *data, size_t len, uint8_t *digest); void crypto_SHA1(const uint8_t *data, size_t len, uint8_t *digest);

View File

@@ -69,7 +69,7 @@ static int _in_progress(int error)
#endif #endif
} }
sock_t sock_connect(const char *host, unsigned short port) sock_t sock_connect(const char *const host, const unsigned short port)
{ {
sock_t sock; sock_t sock;
char service[6]; char service[6];
@@ -109,7 +109,7 @@ sock_t sock_connect(const char *host, unsigned short port)
return sock; return sock;
} }
int sock_set_keepalive(sock_t sock, int timeout, int interval) int sock_set_keepalive(const sock_t sock, int timeout, int interval)
{ {
int ret; int ret;
int optval = (timeout && interval) ? 1 : 0; int optval = (timeout && interval) ? 1 : 0;
@@ -154,7 +154,7 @@ int sock_set_keepalive(sock_t sock, int timeout, int interval)
return ret; return ret;
} }
int sock_close(sock_t sock) int sock_close(const sock_t sock)
{ {
#ifdef _WIN32 #ifdef _WIN32
return closesocket(sock); return closesocket(sock);
@@ -180,27 +180,27 @@ static int _sock_set_blocking_mode(sock_t sock, int blocking)
#endif #endif
} }
int sock_set_blocking(sock_t sock) int sock_set_blocking(const sock_t sock)
{ {
return _sock_set_blocking_mode(sock, 1); return _sock_set_blocking_mode(sock, 1);
} }
int sock_set_nonblocking(sock_t sock) int sock_set_nonblocking(const sock_t sock)
{ {
return _sock_set_blocking_mode(sock, 0); return _sock_set_blocking_mode(sock, 0);
} }
int sock_read(sock_t sock, void *buff, size_t len) int sock_read(const sock_t sock, void *const buff, const size_t len)
{ {
return recv(sock, buff, len, 0); return recv(sock, buff, len, 0);
} }
int sock_write(sock_t sock, const void *buff, size_t len) int sock_write(const sock_t sock, const void *const buff, const size_t len)
{ {
return send(sock, buff, len, 0); return send(sock, buff, len, 0);
} }
int sock_is_recoverable(int error) int sock_is_recoverable(const int error)
{ {
#ifdef _WIN32 #ifdef _WIN32
return (error == WSAEINTR || error == WSAEWOULDBLOCK || return (error == WSAEINTR || error == WSAEWOULDBLOCK ||
@@ -210,7 +210,7 @@ int sock_is_recoverable(int error)
#endif #endif
} }
int sock_connect_error(sock_t sock) int sock_connect_error(const sock_t sock)
{ {
struct sockaddr_storage ss; struct sockaddr_storage ss;
struct sockaddr *sa = (struct sockaddr *)&ss; struct sockaddr *sa = (struct sockaddr *)&ss;

View File

@@ -30,16 +30,16 @@ void sock_shutdown(void);
int sock_error(void); int sock_error(void);
sock_t sock_connect(const char *host, unsigned short port); sock_t sock_connect(const char *const host, const unsigned short port);
int sock_close(sock_t sock); int sock_close(const sock_t sock);
int sock_set_blocking(sock_t sock); int sock_set_blocking(const sock_t sock);
int sock_set_nonblocking(sock_t sock); int sock_set_nonblocking(const sock_t sock);
int sock_read(sock_t sock, void *buff, size_t len); int sock_read(const sock_t sock, void *const buff, const size_t len);
int sock_write(sock_t sock, const void *buff, size_t len); int sock_write(const sock_t sock, const void *const buff, const size_t len);
int sock_is_recoverable(int error); int sock_is_recoverable(const int error);
/* checks for an error after connect, return 0 if connect successful */ /* checks for an error after connect, return 0 if connect successful */
int sock_connect_error(sock_t sock); int sock_connect_error(const sock_t sock);
int sock_set_keepalive(sock_t sock, int timeout, int interval); int sock_set_keepalive(const sock_t sock, int timeout, int interval);
#endif /* __LIBSTROPHE_SOCK_H__ */ #endif /* __LIBSTROPHE_SOCK_H__ */

View File

@@ -64,7 +64,7 @@ xmpp_stanza_t *xmpp_stanza_new(xmpp_ctx_t *ctx)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_stanza_clone(xmpp_stanza_t *stanza) xmpp_stanza_t *xmpp_stanza_clone(xmpp_stanza_t *const stanza)
{ {
stanza->ref++; stanza->ref++;
@@ -74,7 +74,8 @@ xmpp_stanza_t *xmpp_stanza_clone(xmpp_stanza_t *stanza)
/* /*
* Copy the attributes of stanza src into stanza dst. Return -1 on error. * Copy the attributes of stanza src into stanza dst. Return -1 on error.
*/ */
static int _stanza_copy_attributes(xmpp_stanza_t *dst, const xmpp_stanza_t *src) static int _stanza_copy_attributes(xmpp_stanza_t *dst,
const xmpp_stanza_t *const src)
{ {
hash_iterator_t *iter; hash_iterator_t *iter;
const char *key; const char *key;
@@ -113,7 +114,7 @@ static int _stanza_copy_attributes(xmpp_stanza_t *dst, const xmpp_stanza_t *src)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_stanza_copy(const xmpp_stanza_t *stanza) xmpp_stanza_t *xmpp_stanza_copy(const xmpp_stanza_t *const stanza)
{ {
xmpp_stanza_t *copy, *child, *copychild, *tail; xmpp_stanza_t *copy, *child, *copychild, *tail;
@@ -168,7 +169,7 @@ copy_error:
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_release(xmpp_stanza_t *stanza) int xmpp_stanza_release(xmpp_stanza_t *const stanza)
{ {
int released = 0; int released = 0;
xmpp_stanza_t *child, *tchild; xmpp_stanza_t *child, *tchild;
@@ -204,7 +205,7 @@ int xmpp_stanza_release(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_ctx_t *xmpp_stanza_get_context(const xmpp_stanza_t *stanza) xmpp_ctx_t *xmpp_stanza_get_context(const xmpp_stanza_t *const stanza)
{ {
return stanza->ctx; return stanza->ctx;
} }
@@ -217,7 +218,7 @@ xmpp_ctx_t *xmpp_stanza_get_context(const xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_is_text(xmpp_stanza_t *stanza) int xmpp_stanza_is_text(xmpp_stanza_t *const stanza)
{ {
return (stanza && stanza->type == XMPP_STANZA_TEXT); return (stanza && stanza->type == XMPP_STANZA_TEXT);
} }
@@ -230,7 +231,7 @@ int xmpp_stanza_is_text(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_is_tag(xmpp_stanza_t *stanza) int xmpp_stanza_is_tag(xmpp_stanza_t *const stanza)
{ {
return (stanza && stanza->type == XMPP_STANZA_TAG); return (stanza && stanza->type == XMPP_STANZA_TAG);
} }
@@ -241,7 +242,7 @@ int xmpp_stanza_is_tag(xmpp_stanza_t *stanza)
* On failure, returns NULL. * On failure, returns NULL.
*/ */
static char *_escape_xml(xmpp_ctx_t *ctx, char *text) static char *_escape_xml(xmpp_ctx_t *const ctx, char *text)
{ {
size_t len = 0; size_t len = 0;
char *src; char *src;
@@ -294,8 +295,11 @@ static char *_escape_xml(xmpp_ctx_t *ctx, char *text)
} }
/* small helper function */ /* small helper function */
static void _render_update( static void _render_update(int *written,
int *written, int length, int lastwrite, size_t *left, char **ptr) const int length,
const int lastwrite,
size_t *left,
char **ptr)
{ {
*written += lastwrite; *written += lastwrite;
@@ -313,8 +317,9 @@ static void _render_update(
* return values < 0 indicate some error occurred, * return values < 0 indicate some error occurred,
* and return values > buflen indicate buffer was not large enough * and return values > buflen indicate buffer was not large enough
*/ */
static int static int _render_stanza_recursive(xmpp_stanza_t *stanza,
_render_stanza_recursive(xmpp_stanza_t *stanza, char *buf, size_t buflen) char *const buf,
size_t const buflen)
{ {
char *ptr = buf; char *ptr = buf;
size_t left = buflen; size_t left = buflen;
@@ -439,7 +444,9 @@ _render_stanza_recursive(xmpp_stanza_t *stanza, char *buf, size_t buflen)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_to_text(xmpp_stanza_t *stanza, char **buf, size_t *buflen) int xmpp_stanza_to_text(xmpp_stanza_t *stanza,
char **const buf,
size_t *const buflen)
{ {
char *buffer, *tmp; char *buffer, *tmp;
size_t length; size_t length;
@@ -500,7 +507,7 @@ int xmpp_stanza_to_text(xmpp_stanza_t *stanza, char **buf, size_t *buflen)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_set_name(xmpp_stanza_t *stanza, const char *name) int xmpp_stanza_set_name(xmpp_stanza_t *stanza, const char *const name)
{ {
if (stanza->type == XMPP_STANZA_TEXT) if (stanza->type == XMPP_STANZA_TEXT)
return XMPP_EINVOP; return XMPP_EINVOP;
@@ -524,7 +531,7 @@ int xmpp_stanza_set_name(xmpp_stanza_t *stanza, const char *name)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
const char *xmpp_stanza_get_name(xmpp_stanza_t *stanza) const char *xmpp_stanza_get_name(xmpp_stanza_t *const stanza)
{ {
if (stanza->type == XMPP_STANZA_TEXT) if (stanza->type == XMPP_STANZA_TEXT)
return NULL; return NULL;
@@ -539,7 +546,7 @@ const char *xmpp_stanza_get_name(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_get_attribute_count(xmpp_stanza_t *stanza) int xmpp_stanza_get_attribute_count(xmpp_stanza_t *const stanza)
{ {
if (stanza->attributes == NULL) { if (stanza->attributes == NULL) {
return 0; return 0;
@@ -562,7 +569,7 @@ int xmpp_stanza_get_attribute_count(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_get_attributes(xmpp_stanza_t *stanza, int xmpp_stanza_get_attributes(xmpp_stanza_t *const stanza,
const char **attr, const char **attr,
int attrlen) int attrlen)
{ {
@@ -604,9 +611,9 @@ int xmpp_stanza_get_attributes(xmpp_stanza_t *stanza,
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_set_attribute(xmpp_stanza_t *stanza, int xmpp_stanza_set_attribute(xmpp_stanza_t *const stanza,
const char *key, const char *const key,
const char *value) const char *const value)
{ {
char *val; char *val;
int rc; int rc;
@@ -645,7 +652,7 @@ int xmpp_stanza_set_attribute(xmpp_stanza_t *stanza,
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_set_ns(xmpp_stanza_t *stanza, const char *ns) int xmpp_stanza_set_ns(xmpp_stanza_t *const stanza, const char *const ns)
{ {
return xmpp_stanza_set_attribute(stanza, "xmlns", ns); return xmpp_stanza_set_attribute(stanza, "xmlns", ns);
} }
@@ -720,7 +727,7 @@ int xmpp_stanza_add_child(xmpp_stanza_t *stanza, xmpp_stanza_t *child)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_set_text(xmpp_stanza_t *stanza, const char *text) int xmpp_stanza_set_text(xmpp_stanza_t *stanza, const char *const text)
{ {
if (stanza->type == XMPP_STANZA_TAG) if (stanza->type == XMPP_STANZA_TAG)
return XMPP_EINVOP; return XMPP_EINVOP;
@@ -749,8 +756,8 @@ int xmpp_stanza_set_text(xmpp_stanza_t *stanza, const char *text)
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza, int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza,
const char *text, const char *const text,
size_t size) const size_t size)
{ {
if (stanza->type == XMPP_STANZA_TAG) if (stanza->type == XMPP_STANZA_TAG)
return XMPP_EINVOP; return XMPP_EINVOP;
@@ -779,7 +786,7 @@ int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza,
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
const char *xmpp_stanza_get_id(xmpp_stanza_t *stanza) const char *xmpp_stanza_get_id(xmpp_stanza_t *const stanza)
{ {
return xmpp_stanza_get_attribute(stanza, "id"); return xmpp_stanza_get_attribute(stanza, "id");
} }
@@ -794,7 +801,7 @@ const char *xmpp_stanza_get_id(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
const char *xmpp_stanza_get_ns(xmpp_stanza_t *stanza) const char *xmpp_stanza_get_ns(xmpp_stanza_t *const stanza)
{ {
return xmpp_stanza_get_attribute(stanza, "xmlns"); return xmpp_stanza_get_attribute(stanza, "xmlns");
} }
@@ -809,7 +816,7 @@ const char *xmpp_stanza_get_ns(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
const char *xmpp_stanza_get_type(xmpp_stanza_t *stanza) const char *xmpp_stanza_get_type(xmpp_stanza_t *const stanza)
{ {
return xmpp_stanza_get_attribute(stanza, "type"); return xmpp_stanza_get_attribute(stanza, "type");
} }
@@ -824,7 +831,7 @@ const char *xmpp_stanza_get_type(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
const char *xmpp_stanza_get_to(xmpp_stanza_t *stanza) const char *xmpp_stanza_get_to(xmpp_stanza_t *const stanza)
{ {
return xmpp_stanza_get_attribute(stanza, "to"); return xmpp_stanza_get_attribute(stanza, "to");
} }
@@ -839,7 +846,7 @@ const char *xmpp_stanza_get_to(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
const char *xmpp_stanza_get_from(xmpp_stanza_t *stanza) const char *xmpp_stanza_get_from(xmpp_stanza_t *const stanza)
{ {
return xmpp_stanza_get_attribute(stanza, "from"); return xmpp_stanza_get_attribute(stanza, "from");
} }
@@ -855,8 +862,8 @@ const char *xmpp_stanza_get_from(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t *stanza, xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t *const stanza,
const char *name) const char *const name)
{ {
xmpp_stanza_t *child; xmpp_stanza_t *child;
@@ -881,8 +888,8 @@ xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t *stanza,
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t *stanza, xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t *const stanza,
const char *ns) const char *const ns)
{ {
xmpp_stanza_t *child; xmpp_stanza_t *child;
const char *child_ns; const char *child_ns;
@@ -909,9 +916,9 @@ xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t *stanza,
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t *stanza, xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t *const stanza,
const char *name, const char *const name,
const char *ns) const char *const ns)
{ {
xmpp_stanza_t *child; xmpp_stanza_t *child;
const char *child_ns; const char *child_ns;
@@ -940,7 +947,7 @@ xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t *stanza,
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_stanza_get_children(xmpp_stanza_t *stanza) xmpp_stanza_t *xmpp_stanza_get_children(xmpp_stanza_t *const stanza)
{ {
return stanza->children; return stanza->children;
} }
@@ -953,7 +960,7 @@ xmpp_stanza_t *xmpp_stanza_get_children(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_stanza_get_next(xmpp_stanza_t *stanza) xmpp_stanza_t *xmpp_stanza_get_next(xmpp_stanza_t *const stanza)
{ {
return stanza->next; return stanza->next;
} }
@@ -969,7 +976,7 @@ xmpp_stanza_t *xmpp_stanza_get_next(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
char *xmpp_stanza_get_text(xmpp_stanza_t *stanza) char *xmpp_stanza_get_text(xmpp_stanza_t *const stanza)
{ {
size_t len, clen; size_t len, clen;
xmpp_stanza_t *child; xmpp_stanza_t *child;
@@ -1020,7 +1027,7 @@ char *xmpp_stanza_get_text(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t *stanza) const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t *const stanza)
{ {
if (stanza->type == XMPP_STANZA_TEXT) if (stanza->type == XMPP_STANZA_TEXT)
return stanza->data; return stanza->data;
@@ -1039,7 +1046,7 @@ const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t *stanza)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_set_id(xmpp_stanza_t *stanza, const char *id) int xmpp_stanza_set_id(xmpp_stanza_t *const stanza, const char *const id)
{ {
return xmpp_stanza_set_attribute(stanza, "id", id); return xmpp_stanza_set_attribute(stanza, "id", id);
} }
@@ -1055,7 +1062,7 @@ int xmpp_stanza_set_id(xmpp_stanza_t *stanza, const char *id)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_set_type(xmpp_stanza_t *stanza, const char *type) int xmpp_stanza_set_type(xmpp_stanza_t *const stanza, const char *const type)
{ {
return xmpp_stanza_set_attribute(stanza, "type", type); return xmpp_stanza_set_attribute(stanza, "type", type);
} }
@@ -1072,7 +1079,7 @@ int xmpp_stanza_set_type(xmpp_stanza_t *stanza, const char *type)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_set_to(xmpp_stanza_t *stanza, const char *to) int xmpp_stanza_set_to(xmpp_stanza_t *const stanza, const char *const to)
{ {
return xmpp_stanza_set_attribute(stanza, "to", to); return xmpp_stanza_set_attribute(stanza, "to", to);
} }
@@ -1089,7 +1096,7 @@ int xmpp_stanza_set_to(xmpp_stanza_t *stanza, const char *to)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_set_from(xmpp_stanza_t *stanza, const char *from) int xmpp_stanza_set_from(xmpp_stanza_t *const stanza, const char *const from)
{ {
return xmpp_stanza_set_attribute(stanza, "from", from); return xmpp_stanza_set_attribute(stanza, "from", from);
} }
@@ -1105,7 +1112,8 @@ int xmpp_stanza_set_from(xmpp_stanza_t *stanza, const char *from)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
const char *xmpp_stanza_get_attribute(xmpp_stanza_t *stanza, const char *name) const char *xmpp_stanza_get_attribute(xmpp_stanza_t *const stanza,
const char *const name)
{ {
if (stanza->type != XMPP_STANZA_TAG) if (stanza->type != XMPP_STANZA_TAG)
return NULL; return NULL;
@@ -1125,7 +1133,8 @@ const char *xmpp_stanza_get_attribute(xmpp_stanza_t *stanza, const char *name)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_stanza_del_attribute(xmpp_stanza_t *stanza, const char *name) int xmpp_stanza_del_attribute(xmpp_stanza_t *const stanza,
const char *const name)
{ {
if (stanza->type != XMPP_STANZA_TAG) if (stanza->type != XMPP_STANZA_TAG)
return -1; return -1;
@@ -1148,7 +1157,7 @@ int xmpp_stanza_del_attribute(xmpp_stanza_t *stanza, const char *name)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t *stanza) xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t *const stanza)
{ {
xmpp_stanza_t *copy = NULL; xmpp_stanza_t *copy = NULL;
const char *from; const char *from;
@@ -1203,16 +1212,16 @@ copy_error:
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_stanza_reply_error(xmpp_stanza_t *stanza, xmpp_stanza_t *xmpp_stanza_reply_error(xmpp_stanza_t *const stanza,
const char *error_type, const char *const error_type,
const char *condition, const char *const condition,
const char *text) const char *const text)
{ {
xmpp_ctx_t *ctx = stanza->ctx; xmpp_ctx_t *ctx = stanza->ctx;
xmpp_stanza_t *reply = NULL; xmpp_stanza_t *reply = NULL;
xmpp_stanza_t *error = NULL; xmpp_stanza_t *error;
xmpp_stanza_t *item = NULL; xmpp_stanza_t *item;
xmpp_stanza_t *text_stanza = NULL; xmpp_stanza_t *text_stanza;
const char *to; const char *to;
if (!error_type || !condition) if (!error_type || !condition)
@@ -1221,53 +1230,41 @@ xmpp_stanza_t *xmpp_stanza_reply_error(xmpp_stanza_t *stanza,
reply = xmpp_stanza_reply(stanza); reply = xmpp_stanza_reply(stanza);
if (!reply) if (!reply)
goto quit_err; goto quit_err;
if (xmpp_stanza_set_type(reply, "error") != XMPP_EOK)
goto quit_err; xmpp_stanza_set_type(reply, "error");
to = xmpp_stanza_get_to(stanza); to = xmpp_stanza_get_to(stanza);
if (to) if (to)
if (xmpp_stanza_set_from(reply, to) != XMPP_EOK) xmpp_stanza_set_from(reply, to);
goto quit_err;
error = xmpp_stanza_new(ctx); error = xmpp_stanza_new(ctx);
if (!error) if (!error)
goto quit_err; goto quit_err;
if (xmpp_stanza_set_name(error, "error") != XMPP_EOK) xmpp_stanza_set_name(error, "error");
goto quit_err; xmpp_stanza_set_type(error, error_type);
if (xmpp_stanza_set_type(error, error_type) != XMPP_EOK) xmpp_stanza_add_child(reply, error);
goto quit_err;
if (xmpp_stanza_add_child(reply, error) != XMPP_EOK)
goto quit_err;
xmpp_stanza_release(error); xmpp_stanza_release(error);
item = xmpp_stanza_new(ctx); item = xmpp_stanza_new(ctx);
if (!item) if (!item)
goto quit_err; goto quit_err;
if (xmpp_stanza_set_name(item, condition) != XMPP_EOK) xmpp_stanza_set_name(item, condition);
goto quit_err; xmpp_stanza_set_ns(item, XMPP_NS_STANZAS_IETF);
if (xmpp_stanza_set_ns(item, XMPP_NS_STANZAS_IETF) != XMPP_EOK) xmpp_stanza_add_child(error, item);
goto quit_err;
if (xmpp_stanza_add_child(error, item) != XMPP_EOK)
goto quit_err;
xmpp_stanza_release(item); xmpp_stanza_release(item);
if (text) { if (text) {
item = xmpp_stanza_new(ctx); item = xmpp_stanza_new(ctx);
if (!item) if (!item)
goto quit_err; goto quit_err;
if (xmpp_stanza_set_name(item, "text") != XMPP_EOK) xmpp_stanza_set_name(item, "text");
goto quit_err; xmpp_stanza_set_ns(item, XMPP_NS_STANZAS_IETF);
if (xmpp_stanza_set_ns(item, XMPP_NS_STANZAS_IETF) != XMPP_EOK) xmpp_stanza_add_child(error, item);
goto quit_err;
if (xmpp_stanza_add_child(error, item) != XMPP_EOK)
goto quit_err;
xmpp_stanza_release(item); xmpp_stanza_release(item);
text_stanza = xmpp_stanza_new(ctx); text_stanza = xmpp_stanza_new(ctx);
if (!text_stanza) if (!text_stanza)
goto quit_err; goto quit_err;
if (xmpp_stanza_set_text(text_stanza, text) != XMPP_EOK) xmpp_stanza_set_text(text_stanza, text);
goto quit_err; xmpp_stanza_add_child(item, text_stanza);
if (xmpp_stanza_add_child(item, text_stanza) != XMPP_EOK)
goto quit_err;
xmpp_stanza_release(text_stanza); xmpp_stanza_release(text_stanza);
} }
@@ -1276,20 +1273,14 @@ xmpp_stanza_t *xmpp_stanza_reply_error(xmpp_stanza_t *stanza,
quit_err: quit_err:
if (reply) if (reply)
xmpp_stanza_release(reply); xmpp_stanza_release(reply);
if (error)
xmpp_stanza_release(error);
if (item)
xmpp_stanza_release(item);
if (text_stanza)
xmpp_stanza_release(text_stanza);
return NULL; return NULL;
} }
static xmpp_stanza_t *_stanza_new_with_attrs(xmpp_ctx_t *ctx, static xmpp_stanza_t *_stanza_new_with_attrs(xmpp_ctx_t *ctx,
const char *name, const char *const name,
const char *type, const char *const type,
const char *id, const char *const id,
const char *to) const char *const to)
{ {
xmpp_stanza_t *stanza = xmpp_stanza_new(ctx); xmpp_stanza_t *stanza = xmpp_stanza_new(ctx);
int ret; int ret;
@@ -1323,9 +1314,9 @@ static xmpp_stanza_t *_stanza_new_with_attrs(xmpp_ctx_t *ctx,
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_message_new(xmpp_ctx_t *ctx, xmpp_stanza_t *xmpp_message_new(xmpp_ctx_t *ctx,
const char *type, const char *const type,
const char *to, const char *const to,
const char *id) const char *const id)
{ {
return _stanza_new_with_attrs(ctx, "message", type, id, to); return _stanza_new_with_attrs(ctx, "message", type, id, to);
} }
@@ -1364,7 +1355,7 @@ char *xmpp_message_get_body(xmpp_stanza_t *msg)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
int xmpp_message_set_body(xmpp_stanza_t *msg, const char *text) int xmpp_message_set_body(xmpp_stanza_t *msg, const char *const text)
{ {
xmpp_ctx_t *ctx = msg->ctx; xmpp_ctx_t *ctx = msg->ctx;
xmpp_stanza_t *body; xmpp_stanza_t *body;
@@ -1410,7 +1401,8 @@ int xmpp_message_set_body(xmpp_stanza_t *msg, const char *text)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t *xmpp_iq_new(xmpp_ctx_t *ctx, const char *type, const char *id) xmpp_stanza_t *
xmpp_iq_new(xmpp_ctx_t *ctx, const char *const type, const char *const id)
{ {
return _stanza_new_with_attrs(ctx, "iq", type, id, NULL); return _stanza_new_with_attrs(ctx, "iq", type, id, NULL);
} }
@@ -1441,8 +1433,9 @@ xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx)
* *
* @ingroup Stanza * @ingroup Stanza
*/ */
xmpp_stanza_t * xmpp_stanza_t *xmpp_error_new(xmpp_ctx_t *ctx,
xmpp_error_new(xmpp_ctx_t *ctx, xmpp_error_type_t type, const char *text) xmpp_error_type_t const type,
const char *const text)
{ {
xmpp_stanza_t *error = xmpp_stanza_t *error =
_stanza_new_with_attrs(ctx, "stream:error", NULL, NULL, NULL); _stanza_new_with_attrs(ctx, "stream:error", NULL, NULL, NULL);

214
src/tls.c
View File

@@ -1,214 +0,0 @@
/* tls.c
** strophe XMPP client library -- generic TLS functions
**
** Copyright (C) 2021 Steffen Jaeckel <jaeckel-floss@eyet-services.de>
**
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
* Generic TLS functionality.
*/
/** @defgroup TLS SSL/TLS specific functionality
* These functions provide SSL/TLS specific functionality.
*/
#include <errno.h>
#include <stdarg.h>
#include <string.h>
#include "strophe.h"
#include "common.h"
struct _dnsname_t {
char **data;
size_t cur, max;
};
const size_t tlscert_dnsnames_increment = 4;
/** Get the Strophe context which is assigned to this certificate.
*
* @param cert a Strophe TLS certificate object
*
* @return the Strophe context object where this certificate originates from
*
* @ingroup TLS
*/
xmpp_ctx_t *xmpp_tlscert_get_ctx(const xmpp_tlscert_t *cert)
{
return cert->ctx;
}
/** Get the Strophe connection which is assigned to this certificate.
*
* @param cert a Strophe TLS certificate object
*
* @return the Strophe connection object where this certificate originates from
*
* @ingroup TLS
*/
xmpp_conn_t *xmpp_tlscert_get_conn(const xmpp_tlscert_t *cert)
{
return cert->conn;
}
/** Get the complete PEM of this certificate.
*
* @param cert a Strophe TLS certificate object
*
* @return a string containing the PEM of this certificate
*
* @ingroup TLS
*/
const char *xmpp_tlscert_get_pem(const xmpp_tlscert_t *cert)
{
return cert->pem;
}
/** Get the dnsName entries out of the SubjectAlternativeNames.
*
* Note: Max. `MAX_NUM_DNSNAMES` are supported.
*
* @param cert a Strophe TLS certificate object
* @param n which dnsName entry
*
* @return a string with the n'th dnsName
*
* @ingroup TLS
*/
const char *xmpp_tlscert_get_dnsname(const xmpp_tlscert_t *cert, size_t n)
{
if (n >= cert->dnsnames->cur)
return NULL;
return cert->dnsnames->data[n];
}
/** Get various parts of the certificate as String.
*
* c.f. \ref xmpp_cert_element_t for details.
*
* @param cert a Strophe TLS certificate object
* @param elmnt which part of the certificate
*
* @return a string with the part of the certificate
*
* @ingroup TLS
*/
const char *xmpp_tlscert_get_string(const xmpp_tlscert_t *cert,
xmpp_cert_element_t elmnt)
{
if (elmnt >= XMPP_CERT_ELEMENT_MAX)
return NULL;
return cert->elements[elmnt];
}
/** Get a descriptive string for each xmpp_cert_element_t.
*
* c.f. \ref xmpp_cert_element_t for details.
*
* @param cert a Strophe TLS certificate object
* @param elmnt which element
*
* @return a string with the description
*
* @ingroup TLS
*/
const char *xmpp_tlscert_get_description(xmpp_cert_element_t elmnt)
{
static const char *descriptions[] = {
"X.509 Version",
"SerialNumber",
"Subject",
"Issuer",
"Issued On",
"Expires On",
"Public Key Algorithm",
"Certificate Signature Algorithm",
"Fingerprint SHA-1",
"Fingerprint SHA-256",
};
if (elmnt >= XMPP_CERT_ELEMENT_MAX)
return NULL;
return descriptions[elmnt];
}
/** Allocate and initialize a Strophe TLS certificate object.
*
* @param ctx a Strophe context object
*
* @return a certificate object or NULL
*/
xmpp_tlscert_t *tlscert_new(xmpp_ctx_t *ctx)
{
xmpp_tlscert_t *tlscert = xmpp_alloc(ctx, sizeof(*tlscert));
if (!tlscert)
return NULL;
memset(tlscert, 0, sizeof(*tlscert));
tlscert->dnsnames = xmpp_alloc(ctx, sizeof(*tlscert->dnsnames));
if (!tlscert->dnsnames) {
xmpp_free(ctx, tlscert);
return NULL;
}
memset(tlscert->dnsnames, 0, sizeof(*tlscert->dnsnames));
tlscert->ctx = ctx;
return tlscert;
}
/** Free a certificate object.
*
* @param cert a Strophe TLS certificate object
*
* @ingroup TLS
*/
void xmpp_tlscert_free(xmpp_tlscert_t *cert)
{
size_t n;
for (n = 0; n < ARRAY_SIZE(cert->elements); ++n) {
if (cert->elements[n])
xmpp_free(cert->ctx, cert->elements[n]);
}
if (cert->dnsnames->data) {
for (n = 0; n < cert->dnsnames->cur; ++n) {
if (cert->dnsnames->data[n])
xmpp_free(cert->ctx, cert->dnsnames->data[n]);
}
}
xmpp_free(cert->ctx, cert->dnsnames->data);
xmpp_free(cert->ctx, cert->dnsnames);
if (cert->pem)
xmpp_free(cert->ctx, cert->pem);
xmpp_free(cert->ctx, cert);
}
/** Add a dnsName to the Strophe TLS certificate object.
*
* @param cert a Strophe TLS certificate object
* @param dnsname dnsName that shall be stored
*
* @return classic Unix style - 0=success, 1=error
*/
int tlscert_add_dnsname(xmpp_tlscert_t *cert, const char *dnsname)
{
if ((cert->dnsnames->cur + 1) >= cert->dnsnames->max) {
char **dnsnames =
xmpp_realloc(cert->ctx, cert->dnsnames->data,
(cert->dnsnames->max + tlscert_dnsnames_increment) *
sizeof(char **));
if (!dnsnames)
return 1;
cert->dnsnames->data = dnsnames;
cert->dnsnames->max += tlscert_dnsnames_increment;
}
cert->dnsnames->data[cert->dnsnames->cur++] =
xmpp_strdup(cert->ctx, dnsname);
return 0;
}

View File

@@ -21,28 +21,12 @@
typedef struct _tls tls_t; typedef struct _tls tls_t;
typedef struct _dnsname_t dnsname_t;
struct _xmpp_tlscert_t {
xmpp_ctx_t *ctx;
xmpp_conn_t *conn;
char *pem;
char *elements[XMPP_CERT_ELEMENT_MAX];
dnsname_t *dnsnames;
};
/* provided by the real TLS implementation */
void tls_initialize(void); void tls_initialize(void);
void tls_shutdown(void); void tls_shutdown(void);
tls_t *tls_new(xmpp_conn_t *conn); tls_t *tls_new(xmpp_conn_t *conn);
void tls_free(tls_t *tls); void tls_free(tls_t *tls);
char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n);
unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn);
xmpp_tlscert_t *tls_peer_cert(xmpp_conn_t *conn);
int tls_set_credentials(tls_t *tls, const char *cafilename); int tls_set_credentials(tls_t *tls, const char *cafilename);
int tls_start(tls_t *tls); int tls_start(tls_t *tls);
@@ -51,15 +35,10 @@ int tls_stop(tls_t *tls);
int tls_error(tls_t *tls); int tls_error(tls_t *tls);
int tls_pending(tls_t *tls); int tls_pending(tls_t *tls);
int tls_read(tls_t *tls, void *buff, size_t len); int tls_read(tls_t *tls, void *const buff, const size_t len);
int tls_write(tls_t *tls, const void *buff, size_t len); int tls_write(tls_t *tls, const void *const buff, const size_t len);
int tls_clear_pending_write(tls_t *tls); int tls_clear_pending_write(tls_t *tls);
int tls_is_recoverable(int error); int tls_is_recoverable(int error);
/* provided by tls.c */
xmpp_tlscert_t *tlscert_new(xmpp_ctx_t *ctx);
int tlscert_add_dnsname(xmpp_tlscert_t *cert, const char *dnsname);
#endif /* __LIBSTROPHE_TLS_H__ */ #endif /* __LIBSTROPHE_TLS_H__ */

View File

@@ -33,21 +33,6 @@ void tls_shutdown(void)
return; return;
} }
char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n)
{
UNUSED(conn);
UNUSED(n);
/* always fail */
return NULL;
}
unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn)
{
UNUSED(conn);
/* always fail */
return 0;
}
tls_t *tls_new(xmpp_conn_t *conn) tls_t *tls_new(xmpp_conn_t *conn)
{ {
UNUSED(conn); UNUSED(conn);
@@ -61,12 +46,6 @@ void tls_free(tls_t *tls)
return; return;
} }
xmpp_tlscert_t *tls_peer_cert(xmpp_conn_t *conn)
{
UNUSED(conn);
return NULL;
}
int tls_set_credentials(tls_t *tls, const char *cafilename) int tls_set_credentials(tls_t *tls, const char *cafilename)
{ {
UNUSED(tls); UNUSED(tls);
@@ -99,7 +78,7 @@ int tls_pending(tls_t *tls)
return 0; return 0;
} }
int tls_read(tls_t *tls, void *buff, size_t len) int tls_read(tls_t *tls, void *const buff, const size_t len)
{ {
UNUSED(tls); UNUSED(tls);
UNUSED(buff); UNUSED(buff);
@@ -107,7 +86,7 @@ int tls_read(tls_t *tls, void *buff, size_t len)
return -1; return -1;
} }
int tls_write(tls_t *tls, const void *buff, size_t len) int tls_write(tls_t *tls, const void *const buff, const size_t len)
{ {
UNUSED(tls); UNUSED(tls);
UNUSED(buff); UNUSED(buff);

View File

@@ -13,21 +13,20 @@
* TLS implementation with GNUTLS * TLS implementation with GNUTLS
*/ */
#include <string.h>
#include <gnutls/gnutls.h> #include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <gnutls/x509-ext.h>
#include "common.h" #include "common.h"
#include "tls.h" #include "tls.h"
#include "sock.h" #include "sock.h"
/* FIXME this shouldn't be a constant string */
#define CAFILE "/etc/ssl/certs/ca-certificates.crt"
struct _tls { struct _tls {
xmpp_ctx_t *ctx; /* do we need this? */ xmpp_ctx_t *ctx; /* do we need this? */
xmpp_conn_t *conn; sock_t sock;
gnutls_session_t session; gnutls_session_t session;
gnutls_certificate_credentials_t cred; gnutls_certificate_credentials_t cred;
gnutls_x509_crt_t client_cert;
int lasterror; int lasterror;
}; };
@@ -47,299 +46,19 @@ void tls_shutdown(void)
gnutls_global_deinit(); gnutls_global_deinit();
} }
static gnutls_x509_crt_t _tls_load_cert(xmpp_conn_t *conn)
{
if (conn->tls && conn->tls->client_cert)
return conn->tls->client_cert;
gnutls_x509_crt_t cert;
gnutls_datum_t data;
int res;
if (gnutls_x509_crt_init(&cert) < 0)
return NULL;
if (gnutls_load_file(conn->tls_client_cert, &data) < 0)
goto LBL_ERR;
res = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_PEM);
gnutls_free(data.data);
if (res < 0)
goto LBL_ERR;
return cert;
LBL_ERR:
gnutls_x509_crt_deinit(cert);
return NULL;
}
static void _tls_free_cert(xmpp_conn_t *conn, gnutls_x509_crt_t cert)
{
if (conn->tls && conn->tls->client_cert == cert)
return;
gnutls_x509_crt_deinit(cert);
}
static int _tls_get_id_on_xmppaddr(xmpp_conn_t *conn,
gnutls_x509_crt_t cert,
unsigned int n,
char **ret)
{
gnutls_datum_t san;
size_t name_len, oid_len;
char oid[128], name[128];
name_len = oid_len = 128;
int res =
gnutls_x509_crt_get_subject_alt_name(cert, n, name, &name_len, NULL);
if (res == GNUTLS_SAN_OTHERNAME_XMPP) {
/* This is the happy flow path with fixed GnuTLS.
* While implementing this I stumbled over an issue in GnuTLS
* which lead to
* https://gitlab.com/gnutls/gnutls/-/merge_requests/1397
*/
if (ret) {
*ret = xmpp_strdup(conn->ctx, name);
}
return GNUTLS_SAN_OTHERNAME_XMPP;
}
if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
if (res != GNUTLS_SAN_OTHERNAME)
return GNUTLS_E_X509_UNKNOWN_SAN;
res = gnutls_x509_crt_get_subject_alt_othername_oid(cert, n, oid, &oid_len);
if (res == GNUTLS_SAN_OTHERNAME_XMPP) {
gnutls_datum_t xmpp_addr;
san.data = (unsigned char *)name;
san.size = name_len;
res = gnutls_x509_othername_to_virtual(oid, &san, NULL, &xmpp_addr);
if (res < 0) {
gnutls_free(xmpp_addr.data);
return GNUTLS_E_MEMORY_ERROR;
}
if (ret) {
*ret = xmpp_strdup(conn->ctx, (char *)xmpp_addr.data);
}
gnutls_free(xmpp_addr.data);
return GNUTLS_SAN_OTHERNAME_XMPP;
}
return GNUTLS_E_X509_UNKNOWN_SAN;
}
static int _tls_id_on_xmppaddr(xmpp_conn_t *conn,
gnutls_x509_crt_t cert,
unsigned int n,
char **ret)
{
int res = GNUTLS_E_SUCCESS;
unsigned int i, j;
for (i = j = 0; res != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; ++i) {
res = _tls_get_id_on_xmppaddr(conn, cert, i, NULL);
if (res == GNUTLS_SAN_OTHERNAME_XMPP) {
if (j == n) {
res = _tls_get_id_on_xmppaddr(conn, cert, i, ret);
break;
}
j++;
}
}
return res;
}
/** Search through the SubjectAlternativeNames and return the next
* id-on-xmppAddr element starting from `n`.
*/
char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n)
{
char *ret = NULL;
gnutls_x509_crt_t cert = _tls_load_cert(conn);
if (cert == NULL)
return NULL;
_tls_id_on_xmppaddr(conn, cert, n, &ret);
_tls_free_cert(conn, cert);
return ret;
}
unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn)
{
unsigned int ret = 0, n;
int res = GNUTLS_E_SUCCESS;
gnutls_x509_crt_t cert = _tls_load_cert(conn);
if (cert == NULL)
return 0;
for (n = 0; res != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; ++n) {
res = _tls_id_on_xmppaddr(conn, cert, n, NULL);
if (res == GNUTLS_SAN_OTHERNAME_XMPP)
ret++;
}
_tls_free_cert(conn, cert);
return ret;
}
static xmpp_tlscert_t *_x509_to_tlscert(xmpp_ctx_t *ctx, gnutls_x509_crt_t cert)
{
int res;
char buf[512], smallbuf[64];
size_t size, m;
unsigned int algo, n;
gnutls_datum_t data;
time_t time_val;
xmpp_tlscert_t *tlscert = tlscert_new(ctx);
gnutls_x509_crt_export2(cert, GNUTLS_X509_FMT_PEM, &data);
tlscert->pem = xmpp_alloc(ctx, data.size + 1);
memcpy(tlscert->pem, data.data, data.size);
tlscert->pem[data.size] = '\0';
gnutls_free(data.data);
size = sizeof(buf);
gnutls_x509_crt_get_dn(cert, buf, &size);
tlscert->elements[XMPP_CERT_SUBJECT] = xmpp_strdup(ctx, buf);
size = sizeof(buf);
gnutls_x509_crt_get_issuer_dn(cert, buf, &size);
tlscert->elements[XMPP_CERT_ISSUER] = xmpp_strdup(ctx, buf);
time_val = gnutls_x509_crt_get_activation_time(cert);
tlscert->elements[XMPP_CERT_NOTBEFORE] = xmpp_strdup(ctx, ctime(&time_val));
tlscert->elements[XMPP_CERT_NOTBEFORE]
[strlen(tlscert->elements[XMPP_CERT_NOTBEFORE]) - 1] =
'\0';
time_val = gnutls_x509_crt_get_expiration_time(cert);
tlscert->elements[XMPP_CERT_NOTAFTER] = xmpp_strdup(ctx, ctime(&time_val));
tlscert->elements[XMPP_CERT_NOTAFTER]
[strlen(tlscert->elements[XMPP_CERT_NOTAFTER]) - 1] = '\0';
size = sizeof(smallbuf);
gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, smallbuf, &size);
hex_encode(buf, smallbuf, size);
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA1] = xmpp_strdup(ctx, buf);
size = sizeof(smallbuf);
gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, smallbuf, &size);
hex_encode(buf, smallbuf, size);
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] = xmpp_strdup(ctx, buf);
xmpp_snprintf(buf, sizeof(buf), "%d", gnutls_x509_crt_get_version(cert));
tlscert->elements[XMPP_CERT_VERSION] = xmpp_strdup(ctx, buf);
algo = gnutls_x509_crt_get_pk_algorithm(cert, NULL);
tlscert->elements[XMPP_CERT_KEYALG] =
xmpp_strdup(ctx, gnutls_pk_algorithm_get_name(algo));
algo = gnutls_x509_crt_get_signature_algorithm(cert);
tlscert->elements[XMPP_CERT_SIGALG] =
xmpp_strdup(ctx, gnutls_sign_get_name(algo));
size = sizeof(smallbuf);
gnutls_x509_crt_get_serial(cert, smallbuf, &size);
hex_encode(buf, smallbuf, size);
tlscert->elements[XMPP_CERT_SERIALNUMBER] = xmpp_strdup(ctx, buf);
for (n = 0, m = 0, res = 0; res != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
++n) {
size = sizeof(buf);
res = gnutls_x509_crt_get_subject_alt_name(cert, n, buf, &size, NULL);
if (res == GNUTLS_SAN_DNSNAME) {
if (tlscert_add_dnsname(tlscert, buf))
xmpp_debug(ctx, "tls", "Can't store dnsName(%zu): %s", m, buf);
m++;
}
}
return tlscert;
}
static int _tls_verify(gnutls_session_t session)
{
tls_t *tls = gnutls_session_get_ptr(session);
const gnutls_datum_t *cert_list;
gnutls_certificate_type_t type;
gnutls_datum_t out;
unsigned int cert_list_size = 0, status;
gnutls_x509_crt_t cert;
if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509)
return -1;
if (gnutls_certificate_verify_peers2(session, &status) < 0) {
xmpp_error(tls->ctx, "tls", "Verify peers failed");
return -1;
}
type = gnutls_certificate_type_get(session);
if (gnutls_certificate_verification_status_print(status, type, &out, 0) <
0) {
xmpp_error(tls->ctx, "tls", "Status print failed");
return -1;
}
/* Return early if the Certificate is trusted
* OR if we trust all Certificates */
if (status == 0 || tls->conn->tls_trust)
return 0;
if (!tls->conn->certfail_handler) {
xmpp_error(tls->ctx, "tls",
"No certfail handler set, canceling connection attempt");
return -1;
}
cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
/* OpenSSL displays the certificate chain in reverse order than GnuTLS.
* To show consistent behavior to the user, traverse the list from the
* end.
*/
while (cert_list_size--) {
gnutls_x509_crt_init(&cert);
gnutls_x509_crt_import(cert, &cert_list[cert_list_size],
GNUTLS_X509_FMT_DER);
xmpp_tlscert_t *tlscert = _x509_to_tlscert(tls->ctx, cert);
if (!tlscert) {
gnutls_x509_crt_deinit(cert);
gnutls_free(out.data);
return -1;
}
if (tls->conn->certfail_handler(tlscert, (char *)out.data) == 0) {
xmpp_tlscert_free(tlscert);
gnutls_x509_crt_deinit(cert);
gnutls_free(out.data);
return -1;
}
xmpp_tlscert_free(tlscert);
gnutls_x509_crt_deinit(cert);
}
gnutls_free(out.data);
return 0;
}
tls_t *tls_new(xmpp_conn_t *conn) tls_t *tls_new(xmpp_conn_t *conn)
{ {
tls_t *tls = xmpp_alloc(conn->ctx, sizeof(tls_t)); tls_t *tls = xmpp_alloc(conn->ctx, sizeof(tls_t));
if (tls) { if (tls) {
memset(tls, 0, sizeof(*tls));
tls->ctx = conn->ctx; tls->ctx = conn->ctx;
tls->conn = conn; tls->sock = conn->sock;
gnutls_init(&tls->session, GNUTLS_CLIENT); gnutls_init(&tls->session, GNUTLS_CLIENT);
gnutls_certificate_allocate_credentials(&tls->cred); gnutls_certificate_allocate_credentials(&tls->cred);
tls_set_credentials(tls, NULL); tls_set_credentials(tls, CAFILE);
if (conn->tls_client_cert && conn->tls_client_key) {
tls->client_cert = _tls_load_cert(conn);
if (!tls->client_cert) {
xmpp_error(tls->ctx, "tls",
"could not read client certificate");
gnutls_certificate_free_credentials(tls->cred);
gnutls_deinit(tls->session);
xmpp_free(tls->ctx, tls);
return NULL;
}
gnutls_certificate_set_x509_key_file(
tls->cred, conn->tls_client_cert, conn->tls_client_key,
GNUTLS_X509_FMT_PEM);
}
gnutls_certificate_set_verify_function(tls->cred, _tls_verify);
gnutls_set_default_priority(tls->session); gnutls_set_default_priority(tls->session);
gnutls_session_set_ptr(tls->session, tls);
/* fixme: this may require setting a callback on win32? */ /* fixme: this may require setting a callback on win32? */
gnutls_transport_set_int(tls->session, conn->sock); gnutls_transport_set_int(tls->session, conn->sock);
@@ -350,45 +69,18 @@ tls_t *tls_new(xmpp_conn_t *conn)
void tls_free(tls_t *tls) void tls_free(tls_t *tls)
{ {
if (tls->client_cert)
gnutls_x509_crt_deinit(tls->client_cert);
gnutls_deinit(tls->session); gnutls_deinit(tls->session);
gnutls_certificate_free_credentials(tls->cred); gnutls_certificate_free_credentials(tls->cred);
xmpp_free(tls->ctx, tls); xmpp_free(tls->ctx, tls);
} }
xmpp_tlscert_t *tls_peer_cert(xmpp_conn_t *conn)
{
xmpp_tlscert_t *tlscert = NULL;
if (conn && conn->tls && conn->tls->session) {
unsigned int list_size = 0;
const gnutls_datum_t *der_cert =
gnutls_certificate_get_peers(conn->tls->session, &list_size);
if (der_cert && list_size) {
gnutls_x509_crt_t cert;
if (gnutls_x509_crt_init(&cert) < 0)
return NULL;
if (gnutls_x509_crt_import(cert, der_cert, GNUTLS_X509_FMT_DER) ==
0)
tlscert = _x509_to_tlscert(conn->ctx, cert);
gnutls_x509_crt_deinit(cert);
}
}
return tlscert;
}
int tls_set_credentials(tls_t *tls, const char *cafilename) int tls_set_credentials(tls_t *tls, const char *cafilename)
{ {
UNUSED(cafilename); int err;
/* set trusted credentials -- takes a .pem filename */ /* set trusted credentials -- takes a .pem filename */
int err = gnutls_certificate_set_x509_system_trust(tls->cred); err = gnutls_certificate_set_x509_trust_file(tls->cred, cafilename,
if (err >= 0 && tls->conn->tls_cafile) GNUTLS_X509_FMT_PEM);
err = gnutls_certificate_set_x509_trust_file(
tls->cred, tls->conn->tls_cafile, GNUTLS_X509_FMT_PEM);
if (err >= 0 && tls->conn->tls_capath)
err = gnutls_certificate_set_x509_trust_dir(
tls->cred, tls->conn->tls_capath, GNUTLS_X509_FMT_PEM);
if (err >= 0) { if (err >= 0) {
err = gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE, err = gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE,
tls->cred); tls->cred);
@@ -400,9 +92,9 @@ int tls_set_credentials(tls_t *tls, const char *cafilename)
int tls_start(tls_t *tls) int tls_start(tls_t *tls)
{ {
sock_set_blocking(tls->conn->sock); sock_set_blocking(tls->sock);
tls->lasterror = gnutls_handshake(tls->session); tls->lasterror = gnutls_handshake(tls->session);
sock_set_nonblocking(tls->conn->sock); sock_set_nonblocking(tls->sock);
return tls->lasterror == GNUTLS_E_SUCCESS; return tls->lasterror == GNUTLS_E_SUCCESS;
} }
@@ -428,7 +120,7 @@ int tls_pending(tls_t *tls)
return gnutls_record_check_pending(tls->session); return gnutls_record_check_pending(tls->session);
} }
int tls_read(tls_t *tls, void *buff, size_t len) int tls_read(tls_t *tls, void *const buff, const size_t len)
{ {
int ret; int ret;
@@ -438,7 +130,7 @@ int tls_read(tls_t *tls, void *buff, size_t len)
return ret; return ret;
} }
int tls_write(tls_t *tls, const void *buff, size_t len) int tls_write(tls_t *tls, const void *const buff, const size_t len)
{ {
int ret; int ret;

View File

@@ -47,34 +47,11 @@
#endif #endif
#endif #endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L
static const unsigned char *ASN1_STRING_get0_data(ASN1_STRING *asn1)
{
return ASN1_STRING_data(asn1);
}
#endif
#if OPENSSL_VERSION_NUMBER < 0x10000000L
static int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
ASN1_OBJECT **poid,
ASN1_TYPE **pvalue)
{
if (gen->type != GEN_OTHERNAME)
return 0;
if (poid)
*poid = gen->d.otherName->type_id;
if (pvalue)
*pvalue = gen->d.otherName->value;
return 1;
}
#endif
struct _tls { struct _tls {
xmpp_ctx_t *ctx; xmpp_ctx_t *ctx;
sock_t sock; sock_t sock;
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
SSL *ssl; SSL *ssl;
X509 *client_cert;
int lasterror; int lasterror;
}; };
@@ -89,12 +66,6 @@ static const char *_tls_error_str(int error, const char **tbl, size_t tbl_size);
static void _tls_set_error(tls_t *tls, int error); static void _tls_set_error(tls_t *tls, int error);
static void _tls_log_error(xmpp_ctx_t *ctx); static void _tls_log_error(xmpp_ctx_t *ctx);
static void _tls_dump_cert_info(tls_t *tls); static void _tls_dump_cert_info(tls_t *tls);
static X509 *_tls_cert_read(xmpp_conn_t *conn);
static int _tls_xaddr_nid(void);
static int _tls_xmppaddr_to_string(GENERAL_NAME *name, char **res);
static int _tls_dnsname_to_string(GENERAL_NAME *name, char **res);
static GENERAL_NAMES *_tls_conn_get_names(xmpp_conn_t *conn);
static GENERAL_NAMES *_tls_cert_get_names(X509 *client_cert);
#define TLS_ERROR_STR(error, table) \ #define TLS_ERROR_STR(error, table) \
_tls_error_str(error, table, ARRAY_SIZE(table)) _tls_error_str(error, table, ARRAY_SIZE(table))
@@ -110,7 +81,6 @@ const char *tls_errors[] = {
TLS_ERROR_FIELD(SSL_ERROR_ZERO_RETURN), TLS_ERROR_FIELD(SSL_ERROR_ZERO_RETURN),
TLS_ERROR_FIELD(SSL_ERROR_WANT_CONNECT), TLS_ERROR_FIELD(SSL_ERROR_WANT_CONNECT),
TLS_ERROR_FIELD(SSL_ERROR_WANT_ACCEPT), TLS_ERROR_FIELD(SSL_ERROR_WANT_ACCEPT),
#ifndef LIBRESSL_VERSION_NUMBER
#if OPENSSL_VERSION_NUMBER >= 0x10100000L #if OPENSSL_VERSION_NUMBER >= 0x10100000L
TLS_ERROR_FIELD(SSL_ERROR_WANT_ASYNC), TLS_ERROR_FIELD(SSL_ERROR_WANT_ASYNC),
TLS_ERROR_FIELD(SSL_ERROR_WANT_ASYNC_JOB), TLS_ERROR_FIELD(SSL_ERROR_WANT_ASYNC_JOB),
@@ -118,7 +88,6 @@ const char *tls_errors[] = {
#if OPENSSL_VERSION_NUMBER >= 0x10101000L #if OPENSSL_VERSION_NUMBER >= 0x10101000L
TLS_ERROR_FIELD(SSL_ERROR_WANT_CLIENT_HELLO_CB), TLS_ERROR_FIELD(SSL_ERROR_WANT_CLIENT_HELLO_CB),
#endif #endif
#endif /* !LIBRESSL_VERSION_NUMBER */
}; };
const char *cert_errors[] = { const char *cert_errors[] = {
TLS_ERROR_FIELD(X509_V_OK), TLS_ERROR_FIELD(X509_V_OK),
@@ -179,34 +148,30 @@ const char *cert_errors[] = {
TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX), TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX),
TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX), TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX),
TLS_ERROR_FIELD(X509_V_ERR_CRL_PATH_VALIDATION_ERROR), TLS_ERROR_FIELD(X509_V_ERR_CRL_PATH_VALIDATION_ERROR),
#ifndef LIBRESSL_VERSION_NUMBER
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_VERSION), TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_VERSION),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_ALGORITHM), TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_ALGORITHM),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_CURVE), TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_CURVE),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM), TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED), TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED),
TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256), TLS_ERROR_FIELD(X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256),
#endif /* !LIBRESSL_VERSION_NUMBER */
TLS_ERROR_FIELD(X509_V_ERR_HOSTNAME_MISMATCH), TLS_ERROR_FIELD(X509_V_ERR_HOSTNAME_MISMATCH),
TLS_ERROR_FIELD(X509_V_ERR_EMAIL_MISMATCH), TLS_ERROR_FIELD(X509_V_ERR_EMAIL_MISMATCH),
TLS_ERROR_FIELD(X509_V_ERR_IP_ADDRESS_MISMATCH), TLS_ERROR_FIELD(X509_V_ERR_IP_ADDRESS_MISMATCH),
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */ #endif
#if OPENSSL_VERSION_NUMBER >= 0x10100000L #if OPENSSL_VERSION_NUMBER >= 0x10100000L
TLS_ERROR_FIELD(X509_V_ERR_INVALID_CALL),
TLS_ERROR_FIELD(X509_V_ERR_STORE_LOOKUP),
#ifndef LIBRESSL_VERSION_NUMBER
TLS_ERROR_FIELD(X509_V_ERR_PATH_LOOP), TLS_ERROR_FIELD(X509_V_ERR_PATH_LOOP),
TLS_ERROR_FIELD(X509_V_ERR_DANE_NO_MATCH), TLS_ERROR_FIELD(X509_V_ERR_DANE_NO_MATCH),
TLS_ERROR_FIELD(X509_V_ERR_EE_KEY_TOO_SMALL), TLS_ERROR_FIELD(X509_V_ERR_EE_KEY_TOO_SMALL),
TLS_ERROR_FIELD(X509_V_ERR_CA_KEY_TOO_SMALL), TLS_ERROR_FIELD(X509_V_ERR_CA_KEY_TOO_SMALL),
TLS_ERROR_FIELD(X509_V_ERR_CA_MD_TOO_WEAK), TLS_ERROR_FIELD(X509_V_ERR_CA_MD_TOO_WEAK),
TLS_ERROR_FIELD(X509_V_ERR_INVALID_CALL),
TLS_ERROR_FIELD(X509_V_ERR_STORE_LOOKUP),
TLS_ERROR_FIELD(X509_V_ERR_NO_VALID_SCTS), TLS_ERROR_FIELD(X509_V_ERR_NO_VALID_SCTS),
TLS_ERROR_FIELD(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION), TLS_ERROR_FIELD(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION),
TLS_ERROR_FIELD(X509_V_ERR_OCSP_VERIFY_NEEDED), TLS_ERROR_FIELD(X509_V_ERR_OCSP_VERIFY_NEEDED),
TLS_ERROR_FIELD(X509_V_ERR_OCSP_VERIFY_FAILED), TLS_ERROR_FIELD(X509_V_ERR_OCSP_VERIFY_FAILED),
TLS_ERROR_FIELD(X509_V_ERR_OCSP_CERT_UNKNOWN), TLS_ERROR_FIELD(X509_V_ERR_OCSP_CERT_UNKNOWN),
#endif /* !LIBRESSL_VERSION_NUMBER */ #endif
#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
}; };
#undef TLS_ERROR_FIELD #undef TLS_ERROR_FIELD
@@ -218,8 +183,6 @@ void tls_initialize(void)
#else #else
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif #endif
/* init xmppAddr OID */
_tls_xaddr_nid();
} }
void tls_shutdown(void) void tls_shutdown(void)
@@ -230,7 +193,6 @@ void tls_shutdown(void)
* memory rather than cause random crashes of the main program. * memory rather than cause random crashes of the main program.
*/ */
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L
OBJ_cleanup();
ERR_free_strings(); ERR_free_strings();
EVP_cleanup(); EVP_cleanup();
CRYPTO_cleanup_all_ex_data(); CRYPTO_cleanup_all_ex_data();
@@ -250,265 +212,10 @@ int tls_error(tls_t *tls)
return tls->lasterror; return tls->lasterror;
} }
/** Search through the SubjectAlternativeNames and return the next
* id-on-xmppAddr element starting from `n`.
*/
char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n)
{
char *ret = NULL;
int i, j;
GENERAL_NAMES *names = _tls_conn_get_names(conn);
if (!names)
return NULL;
int num_names = sk_GENERAL_NAME_num(names);
for (i = j = 0; i < num_names; ++i) {
char *res;
GENERAL_NAME *name = sk_GENERAL_NAME_value(names, i);
if (name == NULL)
break;
if (_tls_xmppaddr_to_string(name, &res))
continue;
if (j == (int)n) {
xmpp_debug(conn->ctx, "tls", "extracted jid %s from id-on-xmppAddr",
res);
ret = xmpp_strdup(conn->ctx, res);
OPENSSL_free(res);
break;
}
j++;
OPENSSL_free(res);
}
GENERAL_NAMES_free(names);
return ret;
}
unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn)
{
unsigned int ret = 0;
GENERAL_NAMES *names = _tls_conn_get_names(conn);
if (!names)
return 0;
int j, num_names = sk_GENERAL_NAME_num(names);
for (j = 0; j < num_names; ++j) {
GENERAL_NAME *name = sk_GENERAL_NAME_value(names, j);
if (_tls_xmppaddr_to_string(name, NULL))
continue;
ret++;
}
GENERAL_NAMES_free(names);
return ret;
}
static int _convert_ASN1TIME(ASN1_TIME *ansi_time, char *buf, size_t len)
{
BIO *bio = BIO_new(BIO_s_mem());
int rc = ASN1_TIME_print(bio, ansi_time);
if (rc <= 0) {
BIO_free(bio);
return 0;
}
rc = BIO_gets(bio, buf, len);
if (rc <= 0) {
BIO_free(bio);
return 0;
}
BIO_free(bio);
return 1;
}
static char *_asn1_time_to_str(const xmpp_ctx_t *ctx, ASN1_TIME *t)
{
char buf[128];
int res = _convert_ASN1TIME(t, buf, sizeof(buf));
if (res) {
return xmpp_strdup(ctx, buf);
}
return NULL;
}
static char *
_get_fingerprint(const xmpp_ctx_t *ctx, X509 *err_cert, xmpp_cert_element_t el)
{
unsigned char buf[EVP_MAX_MD_SIZE];
unsigned int len;
const EVP_MD *digest;
switch (el) {
case XMPP_CERT_FINGERPRINT_SHA1:
digest = EVP_sha1();
break;
case XMPP_CERT_FINGERPRINT_SHA256:
digest = EVP_sha256();
break;
default:
return NULL;
}
if (X509_digest(err_cert, digest, buf, &len) != 0) {
char fingerprint[4 * EVP_MAX_MD_SIZE];
hex_encode(fingerprint, buf, len);
return xmpp_strdup(ctx, fingerprint);
}
return NULL;
}
static char *
_get_alg(const xmpp_ctx_t *ctx, X509 *err_cert, xmpp_cert_element_t el)
{
int rc, alg_nid = NID_undef;
switch (el) {
case XMPP_CERT_KEYALG: {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
alg_nid = OBJ_obj2nid(err_cert->cert_info->key->algor->algorithm);
#else
X509_PUBKEY *pubkey = X509_get_X509_PUBKEY(err_cert);
ASN1_OBJECT *ppkalg = NULL;
rc = X509_PUBKEY_get0_param(&ppkalg, NULL, NULL, NULL, pubkey);
if (rc) {
alg_nid = OBJ_obj2nid(ppkalg);
}
#endif
} break;
case XMPP_CERT_SIGALG: {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
alg_nid = OBJ_obj2nid(err_cert->sig_alg->algorithm);
#else
const X509_ALGOR *palg;
X509_get0_signature(NULL, &palg, err_cert);
alg_nid = OBJ_obj2nid(palg->algorithm);
#endif
} break;
default:
break;
}
if (alg_nid != NID_undef) {
const char *alg = OBJ_nid2ln(alg_nid);
if (alg) {
return xmpp_strdup(ctx, alg);
}
}
return NULL;
}
static xmpp_tlscert_t *_x509_to_tlscert(xmpp_ctx_t *ctx, X509 *cert)
{
char *subject, *issuer, buf[32];
xmpp_tlscert_t *tlscert = tlscert_new(ctx);
if (!tlscert)
return NULL;
BIO *b = BIO_new(BIO_s_mem());
if (!b)
goto ERR_OUT;
PEM_write_bio_X509(b, cert);
BUF_MEM *bptr;
BIO_get_mem_ptr(b, &bptr);
tlscert->pem = xmpp_alloc(ctx, bptr->length + 1);
if (!tlscert->pem)
goto ERR_OUT;
memcpy(tlscert->pem, bptr->data, bptr->length);
tlscert->pem[bptr->length] = '\0';
BIO_free(b);
subject = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
if (!subject)
goto ERR_OUT;
tlscert->elements[XMPP_CERT_SUBJECT] = xmpp_strdup(ctx, subject);
OPENSSL_free(subject);
issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
if (!issuer)
goto ERR_OUT;
tlscert->elements[XMPP_CERT_ISSUER] = xmpp_strdup(ctx, issuer);
OPENSSL_free(issuer);
tlscert->elements[XMPP_CERT_NOTBEFORE] =
_asn1_time_to_str(ctx, X509_get_notBefore(cert));
tlscert->elements[XMPP_CERT_NOTAFTER] =
_asn1_time_to_str(ctx, X509_get_notAfter(cert));
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA1] =
_get_fingerprint(ctx, cert, XMPP_CERT_FINGERPRINT_SHA1);
tlscert->elements[XMPP_CERT_FINGERPRINT_SHA256] =
_get_fingerprint(ctx, cert, XMPP_CERT_FINGERPRINT_SHA256);
xmpp_snprintf(buf, sizeof(buf), "%ld", X509_get_version(cert) + 1);
tlscert->elements[XMPP_CERT_VERSION] = xmpp_strdup(ctx, buf);
tlscert->elements[XMPP_CERT_KEYALG] = _get_alg(ctx, cert, XMPP_CERT_KEYALG);
tlscert->elements[XMPP_CERT_SIGALG] = _get_alg(ctx, cert, XMPP_CERT_SIGALG);
ASN1_INTEGER *serial = X509_get_serialNumber(cert);
BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL);
if (bn) {
char *serialnumber = BN_bn2hex(bn);
if (serialnumber) {
tlscert->elements[XMPP_CERT_SERIALNUMBER] =
xmpp_strdup(ctx, serialnumber);
OPENSSL_free(serialnumber);
}
BN_free(bn);
}
GENERAL_NAMES *names = _tls_cert_get_names(cert);
if (names) {
int j, num_names = sk_GENERAL_NAME_num(names);
size_t n = 0;
for (j = 0; j < num_names; ++j) {
char *res;
GENERAL_NAME *name = sk_GENERAL_NAME_value(names, j);
if (_tls_dnsname_to_string(name, &res))
continue;
if (tlscert_add_dnsname(tlscert, res))
xmpp_debug(ctx, "tls", "Can't store dnsName(%zu): %s", n, res);
n++;
OPENSSL_free(res);
}
GENERAL_NAMES_free(names);
}
return tlscert;
ERR_OUT:
xmpp_tlscert_free(tlscert);
return NULL;
}
static int _tls_verify(int preverify_ok, X509_STORE_CTX *x509_ctx)
{
if (preverify_ok == 1)
return 1;
SSL *ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
SSL_get_ex_data_X509_STORE_CTX_idx());
xmpp_conn_t *conn = SSL_get_app_data(ssl);
if (!conn->certfail_handler) {
xmpp_error(conn->ctx, "tls",
"No certfail handler set, canceling connection attempt");
return 0;
}
X509 *err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
xmpp_tlscert_t *tlscert = _x509_to_tlscert(conn->ctx, err_cert);
if (!tlscert)
return 0;
xmpp_debug(conn->ctx, "tls", "preverify_ok:%d\nSubject: %s\nIssuer: %s",
preverify_ok, tlscert->elements[XMPP_CERT_SUBJECT],
tlscert->elements[XMPP_CERT_ISSUER]);
int ret = conn->certfail_handler(
tlscert,
X509_verify_cert_error_string(X509_STORE_CTX_get_error(x509_ctx)));
xmpp_tlscert_free(tlscert);
return ret;
}
tls_t *tls_new(xmpp_conn_t *conn) tls_t *tls_new(xmpp_conn_t *conn)
{ {
tls_t *tls = xmpp_alloc(conn->ctx, sizeof(*tls)); tls_t *tls = xmpp_alloc(conn->ctx, sizeof(*tls));
int mode;
if (tls) { if (tls) {
int ret; int ret;
@@ -536,23 +243,7 @@ tls_t *tls_new(xmpp_conn_t *conn)
SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_SSLv3); /* POODLE */ SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_SSLv3); /* POODLE */
SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_TLSv1); /* BEAST */ SSL_CTX_set_options(tls->ssl_ctx, SSL_OP_NO_TLSv1); /* BEAST */
if (conn->tls_client_cert && conn->tls_client_key) { SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL);
tls->client_cert = _tls_cert_read(conn);
if (!tls->client_cert) {
xmpp_error(tls->ctx, "tls",
"could not read client certificate");
goto err_free_ctx;
}
SSL_CTX_use_certificate_file(tls->ssl_ctx, conn->tls_client_cert,
SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(tls->ssl_ctx, conn->tls_client_key,
SSL_FILETYPE_PEM);
} else {
/* If the server asks for a client certificate, don't send one. */
SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL);
}
SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
ret = SSL_CTX_set_default_verify_paths(tls->ssl_ctx); ret = SSL_CTX_set_default_verify_paths(tls->ssl_ctx);
@@ -564,35 +255,21 @@ tls_t *tls_new(xmpp_conn_t *conn)
*/ */
xmpp_error(tls->ctx, "tls", xmpp_error(tls->ctx, "tls",
"SSL_CTX_set_default_verify_paths() failed"); "SSL_CTX_set_default_verify_paths() failed");
goto err_free_cert; goto err_free_ctx;
}
if (conn->tls_cafile || conn->tls_capath) {
if (SSL_CTX_load_verify_locations(tls->ssl_ctx, conn->tls_cafile,
conn->tls_capath) == 0) {
xmpp_error(tls->ctx, "tls",
"SSL_CTX_load_verify_locations() failed");
_tls_log_error(tls->ctx);
goto err_free_cert;
}
} }
tls->ssl = SSL_new(tls->ssl_ctx); tls->ssl = SSL_new(tls->ssl_ctx);
if (tls->ssl == NULL) if (tls->ssl == NULL)
goto err_free_cert; goto err_free_ctx;
#if OPENSSL_VERSION_NUMBER >= 0x0908060L && !defined(OPENSSL_NO_TLSEXT) #if OPENSSL_VERSION_NUMBER >= 0x0908060L && !defined(OPENSSL_NO_TLSEXT)
/* Enable SNI. */ /* Enable SNI. */
SSL_set_tlsext_host_name(tls->ssl, conn->domain); SSL_set_tlsext_host_name(tls->ssl, conn->domain);
#endif #endif
/* Trust server's certificate when user sets the flag explicitly. /* Trust server's certificate when user sets the flag explicitly. */
* Otherwise call the verification callback */ mode = conn->tls_trust ? SSL_VERIFY_NONE : SSL_VERIFY_PEER;
if (conn->tls_trust) SSL_set_verify(tls->ssl, mode, NULL);
SSL_set_verify(tls->ssl, SSL_VERIFY_NONE, NULL);
else
SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, _tls_verify);
SSL_set_app_data(tls->ssl, conn);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L #if OPENSSL_VERSION_NUMBER >= 0x10002000L
/* Hostname verification is supported in OpenSSL 1.0.2 and newer. */ /* Hostname verification is supported in OpenSSL 1.0.2 and newer. */
param = SSL_get0_param(tls->ssl); param = SSL_get0_param(tls->ssl);
@@ -618,8 +295,6 @@ tls_t *tls_new(xmpp_conn_t *conn)
err_free_ssl: err_free_ssl:
SSL_free(tls->ssl); SSL_free(tls->ssl);
err_free_cert:
X509_free(tls->client_cert);
err_free_ctx: err_free_ctx:
SSL_CTX_free(tls->ssl_ctx); SSL_CTX_free(tls->ssl_ctx);
err: err:
@@ -631,24 +306,10 @@ err:
void tls_free(tls_t *tls) void tls_free(tls_t *tls)
{ {
SSL_free(tls->ssl); SSL_free(tls->ssl);
X509_free(tls->client_cert);
SSL_CTX_free(tls->ssl_ctx); SSL_CTX_free(tls->ssl_ctx);
xmpp_free(tls->ctx, tls); xmpp_free(tls->ctx, tls);
} }
xmpp_tlscert_t *tls_peer_cert(xmpp_conn_t *conn)
{
if (conn && conn->tls && conn->tls->ssl) {
X509 *cert = SSL_get_peer_certificate(conn->tls->ssl);
if (cert) {
xmpp_tlscert_t *tlscert = _x509_to_tlscert(conn->ctx, cert);
X509_free(cert);
return tlscert;
}
}
return NULL;
}
int tls_set_credentials(tls_t *tls, const char *cafilename) int tls_set_credentials(tls_t *tls, const char *cafilename)
{ {
UNUSED(tls); UNUSED(tls);
@@ -685,8 +346,6 @@ int tls_start(tls_t *tls)
xmpp_debug(tls->ctx, "tls", xmpp_debug(tls->ctx, "tls",
"Certificate verification FAILED, result=%s(%ld)", "Certificate verification FAILED, result=%s(%ld)",
TLS_ERROR_STR((int)x509_res, cert_errors), x509_res); TLS_ERROR_STR((int)x509_res, cert_errors), x509_res);
if (ret > 0)
xmpp_debug(tls->ctx, "tls", "User decided to connect anyways");
} }
_tls_dump_cert_info(tls); _tls_dump_cert_info(tls);
@@ -740,7 +399,7 @@ int tls_pending(tls_t *tls)
return SSL_pending(tls->ssl); return SSL_pending(tls->ssl);
} }
int tls_read(tls_t *tls, void *buff, size_t len) int tls_read(tls_t *tls, void *const buff, const size_t len)
{ {
int ret; int ret;
@@ -750,7 +409,7 @@ int tls_read(tls_t *tls, void *buff, size_t len)
return ret; return ret;
} }
int tls_write(tls_t *tls, const void *buff, size_t len) int tls_write(tls_t *tls, const void *const buff, const size_t len)
{ {
int ret; int ret;
@@ -844,111 +503,3 @@ static void _tls_dump_cert_info(tls_t *tls)
X509_free(cert); X509_free(cert);
} }
} }
static X509 *_tls_cert_read(xmpp_conn_t *conn)
{
if (conn->tls && conn->tls->client_cert)
return conn->tls->client_cert;
BIO *f = BIO_new_file(conn->tls_client_cert, "r");
if (!f) {
xmpp_debug(conn->ctx, "tls", "f == NULL");
return NULL;
}
X509 *c = PEM_read_bio_X509(f, NULL, NULL, NULL);
BIO_free(f);
if (!c) {
unsigned long error;
while ((error = ERR_get_error()) != 0) {
xmpp_debug(conn->ctx, "tls", "c == NULL: %s",
ERR_error_string(error, NULL));
}
}
return c;
}
static int _tls_xaddr_nid(void)
{
static int xaddr_nid = NID_undef;
if (xaddr_nid == NID_undef) {
xaddr_nid = OBJ_sn2nid("id-on-xmppAddr");
}
if (xaddr_nid == NID_undef) {
xaddr_nid = OBJ_create("1.3.6.1.5.5.7.8.5", "id-on-xmppAddr",
"XmppAddr Identifier");
}
return xaddr_nid;
}
static GENERAL_NAMES *_tls_conn_get_names(xmpp_conn_t *conn)
{
X509 *client_cert;
GENERAL_NAMES *names = NULL;
client_cert = _tls_cert_read(conn);
if (!client_cert)
return NULL;
names = _tls_cert_get_names(client_cert);
if (!conn->tls || !conn->tls->client_cert)
X509_free(client_cert);
return names;
}
static GENERAL_NAMES *_tls_cert_get_names(X509 *client_cert)
{
int san = X509_get_ext_by_NID(client_cert, NID_subject_alt_name, 0);
X509_EXTENSION *san_ext = X509_get_ext(client_cert, san);
if (!san_ext)
return NULL;
ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(san_ext);
if (!data)
return NULL;
const unsigned char *d = ASN1_STRING_get0_data(data);
if (!d)
return NULL;
return d2i_GENERAL_NAMES(NULL, &d, ASN1_STRING_length(data));
}
/** Convert GENERAL_NAME* to a string
*
* This checks whether the GENERAL_NAME* that is given has the
* correct id-on-xmppAddr set and then optionally converts this
* form ASN.1 to a string/char*.
*
* When `res` pointer is set to NULL this method doesn't allocate
* the result but only checks whether it is in the correct format.
*
* @param name Pointer to the GENERAL_NAME that shall be converted
* @param res Result-pointer (optional, can be NULL)
*
* @return classic Unix style - 0=success, 1=error
*/
static int _tls_xmppaddr_to_string(GENERAL_NAME *name, char **res)
{
ASN1_OBJECT *oid;
ASN1_TYPE *val;
if (!name || name->type != GEN_OTHERNAME)
return 1;
if (GENERAL_NAME_get0_otherName(name, &oid, &val) == 0)
return 1;
if (OBJ_obj2nid(oid) != _tls_xaddr_nid() || !val)
return 1;
if (!res)
return 0;
if (ASN1_STRING_to_UTF8((unsigned char **)res, val->value.asn1_string) < 0)
return 1;
return 0;
}
static int _tls_dnsname_to_string(GENERAL_NAME *name, char **res)
{
ASN1_STRING *str;
if (!name || name->type != GEN_DNS)
return 1;
str = GENERAL_NAME_get0_value(name, NULL);
if (str == NULL)
return 1;
if (!res)
return 0;
if (ASN1_STRING_to_UTF8((unsigned char **)res, str) < 0)
return 1;
return 0;
}

View File

@@ -61,21 +61,6 @@ void tls_shutdown(void)
return; return;
} }
char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n)
{
UNUSED(n);
/* always fail */
xmpp_error(conn->ctx, "tls", "Client-Authentication not implemented");
return NULL;
}
unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn)
{
/* always fail */
xmpp_error(conn->ctx, "tls", "Client-Authentication not implemented");
return 0;
}
tls_t *tls_new(xmpp_conn_t *conn) tls_t *tls_new(xmpp_conn_t *conn)
{ {
xmpp_ctx_t *ctx = conn->ctx; xmpp_ctx_t *ctx = conn->ctx;
@@ -222,13 +207,6 @@ void tls_free(tls_t *tls)
return; return;
} }
xmpp_tlscert_t *tls_peer_cert(xmpp_conn_t *conn)
{
/* always fail */
xmpp_error(conn->ctx, "tls", "tls_peer_cert() not implemented");
return NULL;
}
int tls_set_credentials(tls_t *tls, const char *cafilename) int tls_set_credentials(tls_t *tls, const char *cafilename)
{ {
UNUSED(tls); UNUSED(tls);
@@ -434,7 +412,7 @@ int tls_pending(tls_t *tls)
return 0; return 0;
} }
int tls_read(tls_t *tls, void *buff, size_t len) int tls_read(tls_t *tls, void *const buff, const size_t len)
{ {
int bytes; int bytes;
@@ -579,7 +557,7 @@ int tls_clear_pending_write(tls_t *tls)
return 1; return 1;
} }
int tls_write(tls_t *tls, const void *buff, size_t len) int tls_write(tls_t *tls, const void *const buff, const size_t len)
{ {
SecBufferDesc sbdenc; SecBufferDesc sbdenc;
SecBuffer sbenc[4]; SecBuffer sbenc[4];

View File

@@ -36,41 +36,21 @@
* @param ctx a Strophe context object * @param ctx a Strophe context object
* @param s a string * @param s a string
* *
* @return a newly allocated string with the same data as s or NULL on error * @return a new allocates string with the same data as s or NULL on error
*/ */
char *xmpp_strdup(const xmpp_ctx_t *ctx, const char *s) char *xmpp_strdup(const xmpp_ctx_t *const ctx, const char *const s)
{
return xmpp_strndup(ctx, s, SIZE_MAX);
}
/** Duplicate a string with a maximum length.
* This function replaces the standard strndup library call with a version
* that uses the Strophe context object's allocator.
*
* @param ctx a Strophe context object
* @param s a string
* @param len the maximum length of the string to copy
*
* @return a newly allocated string that contains at most `len` symbols
* of the original string or NULL on error
*/
char *xmpp_strndup(const xmpp_ctx_t *ctx, const char *s, size_t len)
{ {
size_t len;
char *copy; char *copy;
size_t l;
l = strlen(s); len = strlen(s);
if (l > len) copy = xmpp_alloc(ctx, len + 1);
l = len;
copy = xmpp_alloc(ctx, l + 1);
if (!copy) { if (!copy) {
xmpp_error(ctx, "xmpp", "failed to allocate required memory"); xmpp_error(ctx, "xmpp", "failed to allocate required memory");
return NULL; return NULL;
} }
memcpy(copy, s, l); memcpy(copy, s, len + 1);
copy[l] = '\0';
return copy; return copy;
} }
@@ -148,6 +128,20 @@ uint64_t time_elapsed(uint64_t t1, uint64_t t2)
return (uint64_t)(t2 - t1); return (uint64_t)(t2 - t1);
} }
/** Disconnect the stream with the error.
* This is a convenience function used internally by various parts of
* the Strophe library for terminating the connection because of an error.
*
* @param conn a Strophe connection object
* @param error an error code
*/
void disconnect_with_error(xmpp_conn_t *const conn, int error)
{
xmpp_error(conn->ctx, "xmpp", "Disconnecting with error %d", error);
conn->error = conn->error ?: error;
xmpp_disconnect(conn);
}
/** Disconnect the stream with a memory error. /** Disconnect the stream with a memory error.
* This is a convenience function used internally by various parts of * This is a convenience function used internally by various parts of
* the Strophe library for terminating the connection because of a * the Strophe library for terminating the connection because of a
@@ -155,17 +149,8 @@ uint64_t time_elapsed(uint64_t t1, uint64_t t2)
* *
* @param conn a Strophe connection object * @param conn a Strophe connection object
*/ */
void disconnect_mem_error(xmpp_conn_t *conn) void disconnect_mem_error(xmpp_conn_t *const conn)
{ {
xmpp_error(conn->ctx, "xmpp", "Memory allocation error"); xmpp_error(conn->ctx, "xmpp", "Memory allocation error");
xmpp_disconnect(conn); disconnect_with_error(conn, XMPP_EMEM);
}
void hex_encode(char *writebuf, void *readbuf, size_t len)
{
size_t i;
for (i = 0; i < len; i++) {
sprintf(writebuf, "%02x", ((unsigned char *)readbuf)[i]);
writebuf += 2;
}
} }

View File

@@ -32,7 +32,4 @@ char *xmpp_strtok_r(char *s, const char *delim, char **saveptr);
uint64_t time_stamp(void); uint64_t time_stamp(void);
uint64_t time_elapsed(uint64_t t1, uint64_t t2); uint64_t time_elapsed(uint64_t t1, uint64_t t2);
/* misc functions */
void hex_encode(char *writebuf, void *readbuf, size_t len);
#endif /* __LIBSTROPHE_UTIL_H__ */ #endif /* __LIBSTROPHE_UTIL_H__ */

356
strophe.h
View File

@@ -103,6 +103,26 @@ extern "C" {
* Internal failure error code. * Internal failure error code.
*/ */
#define XMPP_EINT -3 #define XMPP_EINT -3
/** @def XMPP_ECERT
* Certificate verification failed during TLS establishment.
*/
#define XMPP_ECERT -4
/** @def XMPP_ETIMEDOUT
* Operation timed out error code.
*/
#define XMPP_ETIMEDOUT -5
/** @def XMPP_EIO
* I/O error code.
*/
#define XMPP_EIO -6
/** @def XMPP_ERESET
* Error code for situation when connection closed by remote side.
*/
#define XMPP_ERESET -7
/** @def XMPP_EAUTH
* Authentication failed error code.
*/
#define XMPP_EAUTH -8
/* initialization and shutdown */ /* initialization and shutdown */
void xmpp_initialize(void); void xmpp_initialize(void);
@@ -122,22 +142,18 @@ typedef struct _xmpp_log_t xmpp_log_t;
/* opaque run time context containing the above hooks */ /* opaque run time context containing the above hooks */
typedef struct _xmpp_ctx_t xmpp_ctx_t; typedef struct _xmpp_ctx_t xmpp_ctx_t;
typedef struct _xmpp_tlscert_t xmpp_tlscert_t; xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t *const mem,
const xmpp_log_t *const log);
xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t *mem, const xmpp_log_t *log); void xmpp_ctx_free(xmpp_ctx_t *const ctx);
void xmpp_ctx_free(xmpp_ctx_t *ctx);
/* set the verbosity level of the ctx */
void xmpp_ctx_set_verbosity(xmpp_ctx_t *ctx, int level);
/* free some blocks returned by other APIs, for example the /* free some blocks returned by other APIs, for example the
buffer you get from xmpp_stanza_to_text */ buffer you get from xmpp_stanza_to_text */
void xmpp_free(const xmpp_ctx_t *ctx, void *p); void xmpp_free(const xmpp_ctx_t *const ctx, void *p);
struct _xmpp_mem_t { struct _xmpp_mem_t {
void *(*alloc)(size_t size, void *userdata); void *(*alloc)(const size_t size, void *const userdata);
void (*free)(void *p, void *userdata); void (*free)(void *p, void *const userdata);
void *(*realloc)(void *p, size_t size, void *userdata); void *(*realloc)(void *p, const size_t size, void *const userdata);
void *userdata; void *userdata;
}; };
@@ -150,10 +166,10 @@ typedef enum {
typedef enum { XMPP_UNKNOWN, XMPP_CLIENT, XMPP_COMPONENT } xmpp_conn_type_t; typedef enum { XMPP_UNKNOWN, XMPP_CLIENT, XMPP_COMPONENT } xmpp_conn_type_t;
typedef void (*xmpp_log_handler)(void *userdata, typedef void (*xmpp_log_handler)(void *const userdata,
xmpp_log_level_t level, const xmpp_log_level_t level,
const char *area, const char *const area,
const char *msg); const char *const msg);
struct _xmpp_log_t { struct _xmpp_log_t {
xmpp_log_handler handler; xmpp_log_handler handler;
@@ -217,159 +233,118 @@ typedef enum {
XMPP_SE_XML_NOT_WELL_FORMED XMPP_SE_XML_NOT_WELL_FORMED
} xmpp_error_type_t; } xmpp_error_type_t;
/** Certificate Elements
*
* @ingroup TLS
*/
typedef enum {
XMPP_CERT_VERSION, /**< X.509 Version */
XMPP_CERT_SERIALNUMBER, /**< SerialNumber */
XMPP_CERT_SUBJECT, /**< Subject */
XMPP_CERT_ISSUER, /**< Issuer */
XMPP_CERT_NOTBEFORE, /**< Issued on */
XMPP_CERT_NOTAFTER, /**< Expires on */
XMPP_CERT_KEYALG, /**< Public Key Algorithm */
XMPP_CERT_SIGALG, /**< Certificate Signature Algorithm */
XMPP_CERT_FINGERPRINT_SHA1, /**< Fingerprint SHA-1 */
XMPP_CERT_FINGERPRINT_SHA256, /**< Fingerprint SHA-256 */
XMPP_CERT_ELEMENT_MAX /**< Last element of the enum */
} xmpp_cert_element_t;
typedef struct { typedef struct {
xmpp_error_type_t type; xmpp_error_type_t type;
char *text; char *text;
xmpp_stanza_t *stanza; xmpp_stanza_t *stanza;
} xmpp_stream_error_t; } xmpp_stream_error_t;
typedef void (*xmpp_conn_handler)(xmpp_conn_t *conn, typedef void (*xmpp_conn_handler)(xmpp_conn_t *const conn,
xmpp_conn_event_t event, const xmpp_conn_event_t event,
int error, const int error,
xmpp_stream_error_t *stream_error, xmpp_stream_error_t *const stream_error,
void *userdata); void *const userdata);
/** The Handler function which will be called when the TLS stack can't void xmpp_send_error(xmpp_conn_t *const conn,
* verify the authenticity of a Certificate that gets presented by xmpp_error_type_t const type,
* the server we're trying to connect to. char *const text);
* xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *const ctx);
* When this function is called and details of the `cert` have to be xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *const conn);
* kept, please copy them yourself. The `cert` object will be free'd int xmpp_conn_release(xmpp_conn_t *const conn);
* automatically when this function returns.
*
* NB: `errormsg` is specific per certificate on OpenSSL and the same
* for all certificates on GnuTLS.
*
* @param cert a Strophe certificate object
* @param errormsg The error that caused this.
*
* @return 0 if the connection attempt should be terminated,
* 1 if the connection should be established.
*
* @ingroup TLS
*/
typedef int (*xmpp_certfail_handler)(const xmpp_tlscert_t *cert,
const char *const errormsg);
void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text); long xmpp_conn_get_flags(const xmpp_conn_t *const conn);
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx); int xmpp_conn_set_flags(xmpp_conn_t *const conn, long flags);
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn); const char *xmpp_conn_get_jid(const xmpp_conn_t *const conn);
int xmpp_conn_release(xmpp_conn_t *conn); const char *xmpp_conn_get_bound_jid(const xmpp_conn_t *const conn);
void xmpp_conn_set_jid(xmpp_conn_t *const conn, const char *const jid);
const char *xmpp_conn_get_pass(const xmpp_conn_t *const conn);
void xmpp_conn_set_pass(xmpp_conn_t *const conn, const char *const pass);
xmpp_ctx_t *xmpp_conn_get_context(xmpp_conn_t *const conn);
void xmpp_conn_disable_tls(xmpp_conn_t *const conn);
int xmpp_conn_is_secured(xmpp_conn_t *const conn);
void xmpp_conn_set_keepalive(xmpp_conn_t *const conn,
int timeout,
int interval);
int xmpp_conn_is_connecting(xmpp_conn_t *const conn);
int xmpp_conn_is_connected(xmpp_conn_t *const conn);
int xmpp_conn_is_disconnected(xmpp_conn_t *const conn);
long xmpp_conn_get_flags(const xmpp_conn_t *conn); int xmpp_connect_client(xmpp_conn_t *const conn,
int xmpp_conn_set_flags(xmpp_conn_t *conn, long flags); const char *const altdomain,
const char *xmpp_conn_get_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);
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);
char *xmpp_conn_cert_xmppaddr(xmpp_conn_t *conn, unsigned int n);
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);
void xmpp_conn_disable_tls(xmpp_conn_t *conn);
int xmpp_conn_is_secured(xmpp_conn_t *conn);
void xmpp_conn_set_keepalive(xmpp_conn_t *conn, int timeout, int interval);
int xmpp_conn_is_connecting(xmpp_conn_t *conn);
int xmpp_conn_is_connected(xmpp_conn_t *conn);
int xmpp_conn_is_disconnected(xmpp_conn_t *conn);
int xmpp_connect_client(xmpp_conn_t *conn,
const char *altdomain,
unsigned short altport, unsigned short altport,
xmpp_conn_handler callback, xmpp_conn_handler callback,
void *userdata); void *const userdata);
int xmpp_connect_component(xmpp_conn_t *conn, int xmpp_connect_component(xmpp_conn_t *const conn,
const char *server, const char *const server,
unsigned short port, unsigned short port,
xmpp_conn_handler callback, xmpp_conn_handler callback,
void *userdata); void *const userdata);
int xmpp_connect_raw(xmpp_conn_t *conn, int xmpp_connect_raw(xmpp_conn_t *const conn,
const char *altdomain, const char *const altdomain,
unsigned short altport, unsigned short altport,
xmpp_conn_handler callback, xmpp_conn_handler callback,
void *userdata); void *const userdata);
int xmpp_conn_open_stream_default(xmpp_conn_t *conn); int xmpp_conn_open_stream_default(xmpp_conn_t *const conn);
int xmpp_conn_open_stream(xmpp_conn_t *conn, int xmpp_conn_open_stream(xmpp_conn_t *const conn,
char **attributes, char **attributes,
size_t attributes_len); size_t attributes_len);
int xmpp_conn_tls_start(xmpp_conn_t *conn); int xmpp_conn_tls_start(xmpp_conn_t *const conn);
void xmpp_disconnect(xmpp_conn_t *conn); void xmpp_disconnect(xmpp_conn_t *const conn);
void xmpp_send(xmpp_conn_t *conn, xmpp_stanza_t *stanza); void xmpp_send(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza);
void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...); void xmpp_send_raw_string(xmpp_conn_t *const conn, const char *const fmt, ...);
void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len); void xmpp_send_raw(xmpp_conn_t *const conn,
const char *const data,
const size_t len);
/* handlers */ /* handlers */
/* if the handler returns false it is removed */ /* if the handler returns false it is removed */
typedef int (*xmpp_timed_handler)(xmpp_conn_t *conn, void *userdata); typedef int (*xmpp_timed_handler)(xmpp_conn_t *const conn,
void *const userdata);
void xmpp_timed_handler_add(xmpp_conn_t *conn, void xmpp_timed_handler_add(xmpp_conn_t *const conn,
xmpp_timed_handler handler, xmpp_timed_handler handler,
unsigned long period, const unsigned long period,
void *userdata); void *const userdata);
void xmpp_timed_handler_delete(xmpp_conn_t *conn, xmpp_timed_handler handler); void xmpp_timed_handler_delete(xmpp_conn_t *const conn,
xmpp_timed_handler handler);
/* if the handler returns false it is removed */ /* if the handler returns false it is removed */
typedef int (*xmpp_global_timed_handler)(xmpp_ctx_t *ctx, void *userdata); typedef int (*xmpp_global_timed_handler)(xmpp_ctx_t *const ctx,
void *const userdata);
void xmpp_global_timed_handler_add(xmpp_ctx_t *ctx, void xmpp_global_timed_handler_add(xmpp_ctx_t *const ctx,
xmpp_global_timed_handler handler, xmpp_global_timed_handler handler,
unsigned long period, const unsigned long period,
void *userdata); void *const userdata);
void xmpp_global_timed_handler_delete(xmpp_ctx_t *ctx, void xmpp_global_timed_handler_delete(xmpp_ctx_t *const ctx,
xmpp_global_timed_handler handler); xmpp_global_timed_handler handler);
/* if the handler returns false it is removed */ /* if the handler returns false it is removed */
typedef int (*xmpp_handler)(xmpp_conn_t *conn, typedef int (*xmpp_handler)(xmpp_conn_t *const conn,
xmpp_stanza_t *stanza, xmpp_stanza_t *const stanza,
void *userdata); void *const userdata);
void xmpp_handler_add(xmpp_conn_t *conn, void xmpp_handler_add(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *ns, const char *const ns,
const char *name, const char *const name,
const char *type, const char *const type,
void *userdata); void *const userdata);
void xmpp_handler_delete(xmpp_conn_t *conn, xmpp_handler handler); void xmpp_handler_delete(xmpp_conn_t *const conn, xmpp_handler handler);
void xmpp_id_handler_add(xmpp_conn_t *conn, void xmpp_id_handler_add(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *id, const char *const id,
void *userdata); void *const userdata);
void xmpp_id_handler_delete(xmpp_conn_t *conn, void xmpp_id_handler_delete(xmpp_conn_t *const conn,
xmpp_handler handler, xmpp_handler handler,
const char *id); const char *const id);
/* /*
void xmpp_register_stanza_handler(conn, stanza, xmlns, type, handler) void xmpp_register_stanza_handler(conn, stanza, xmlns, type, handler)
@@ -382,88 +357,94 @@ xmpp_stanza_t *xmpp_stanza_new(xmpp_ctx_t *ctx);
xmpp_stanza_t *xmpp_stanza_new_from_string(xmpp_ctx_t *ctx, const char *str); xmpp_stanza_t *xmpp_stanza_new_from_string(xmpp_ctx_t *ctx, const char *str);
/* clone a stanza */ /* clone a stanza */
xmpp_stanza_t *xmpp_stanza_clone(xmpp_stanza_t *stanza); xmpp_stanza_t *xmpp_stanza_clone(xmpp_stanza_t *const stanza);
/* copies a stanza and all children */ /* copies a stanza and all children */
xmpp_stanza_t *xmpp_stanza_copy(const xmpp_stanza_t *stanza); xmpp_stanza_t *xmpp_stanza_copy(const xmpp_stanza_t *const stanza);
/* free a stanza object and it's contents */ /* free a stanza object and it's contents */
int xmpp_stanza_release(xmpp_stanza_t *stanza); int xmpp_stanza_release(xmpp_stanza_t *const stanza);
xmpp_ctx_t *xmpp_stanza_get_context(const xmpp_stanza_t *stanza); xmpp_ctx_t *xmpp_stanza_get_context(const xmpp_stanza_t *const stanza);
int xmpp_stanza_is_text(xmpp_stanza_t *stanza); int xmpp_stanza_is_text(xmpp_stanza_t *const stanza);
int xmpp_stanza_is_tag(xmpp_stanza_t *stanza); int xmpp_stanza_is_tag(xmpp_stanza_t *const stanza);
/* marshall a stanza into text for transmission or display */ /* marshall a stanza into text for transmission or display */
int xmpp_stanza_to_text(xmpp_stanza_t *stanza, char **buf, size_t *buflen); int xmpp_stanza_to_text(xmpp_stanza_t *stanza,
char **const buf,
size_t *const buflen);
xmpp_stanza_t *xmpp_stanza_get_children(xmpp_stanza_t *stanza); xmpp_stanza_t *xmpp_stanza_get_children(xmpp_stanza_t *const stanza);
xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t *stanza, xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t *const stanza,
const char *name); const char *const name);
xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t *stanza, xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t *const stanza,
const char *ns); const char *const ns);
xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t *stanza, xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t *const stanza,
const char *name, const char *const name,
const char *ns); const char *const ns);
xmpp_stanza_t *xmpp_stanza_get_next(xmpp_stanza_t *stanza); xmpp_stanza_t *xmpp_stanza_get_next(xmpp_stanza_t *const stanza);
int xmpp_stanza_add_child(xmpp_stanza_t *stanza, xmpp_stanza_t *child); int xmpp_stanza_add_child(xmpp_stanza_t *stanza, xmpp_stanza_t *child);
int xmpp_stanza_add_child_ex(xmpp_stanza_t *stanza, int xmpp_stanza_add_child_ex(xmpp_stanza_t *stanza,
xmpp_stanza_t *child, xmpp_stanza_t *child,
int do_clone); int do_clone);
const char *xmpp_stanza_get_attribute(xmpp_stanza_t *stanza, const char *name); const char *xmpp_stanza_get_attribute(xmpp_stanza_t *const stanza,
int xmpp_stanza_get_attribute_count(xmpp_stanza_t *stanza); const char *const name);
int xmpp_stanza_get_attributes(xmpp_stanza_t *stanza, int xmpp_stanza_get_attribute_count(xmpp_stanza_t *const stanza);
int xmpp_stanza_get_attributes(xmpp_stanza_t *const stanza,
const char **attr, const char **attr,
int attrlen); int attrlen);
/* concatenate all child text nodes. this function /* concatenate all child text nodes. this function
* returns a string that must be freed by the caller */ * returns a string that must be freed by the caller */
char *xmpp_stanza_get_text(xmpp_stanza_t *stanza); char *xmpp_stanza_get_text(xmpp_stanza_t *const stanza);
const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t *stanza); const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t *const stanza);
const char *xmpp_stanza_get_name(xmpp_stanza_t *stanza); const char *xmpp_stanza_get_name(xmpp_stanza_t *const stanza);
/* set_attribute adds/replaces attributes */ /* set_attribute adds/replaces attributes */
int xmpp_stanza_set_attribute(xmpp_stanza_t *stanza, int xmpp_stanza_set_attribute(xmpp_stanza_t *const stanza,
const char *key, const char *const key,
const char *value); const char *const value);
int xmpp_stanza_set_name(xmpp_stanza_t *stanza, const char *name); int xmpp_stanza_set_name(xmpp_stanza_t *stanza, const char *const name);
int xmpp_stanza_set_text(xmpp_stanza_t *stanza, const char *text); int xmpp_stanza_set_text(xmpp_stanza_t *stanza, const char *const text);
int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza, int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza,
const char *text, const char *const text,
size_t size); const size_t size);
int xmpp_stanza_del_attribute(xmpp_stanza_t *stanza, const char *name); int xmpp_stanza_del_attribute(xmpp_stanza_t *const stanza,
const char *const name);
/* common stanza helpers */ /* common stanza helpers */
const char *xmpp_stanza_get_ns(xmpp_stanza_t *stanza); const char *xmpp_stanza_get_ns(xmpp_stanza_t *const stanza);
const char *xmpp_stanza_get_type(xmpp_stanza_t *stanza); const char *xmpp_stanza_get_type(xmpp_stanza_t *const stanza);
const char *xmpp_stanza_get_id(xmpp_stanza_t *stanza); const char *xmpp_stanza_get_id(xmpp_stanza_t *const stanza);
const char *xmpp_stanza_get_to(xmpp_stanza_t *stanza); const char *xmpp_stanza_get_to(xmpp_stanza_t *const stanza);
const char *xmpp_stanza_get_from(xmpp_stanza_t *stanza); const char *xmpp_stanza_get_from(xmpp_stanza_t *const stanza);
int xmpp_stanza_set_ns(xmpp_stanza_t *stanza, const char *ns); int xmpp_stanza_set_ns(xmpp_stanza_t *const stanza, const char *const ns);
int xmpp_stanza_set_id(xmpp_stanza_t *stanza, const char *id); int xmpp_stanza_set_id(xmpp_stanza_t *const stanza, const char *const id);
int xmpp_stanza_set_type(xmpp_stanza_t *stanza, const char *type); int xmpp_stanza_set_type(xmpp_stanza_t *const stanza, const char *const type);
int xmpp_stanza_set_to(xmpp_stanza_t *stanza, const char *to); int xmpp_stanza_set_to(xmpp_stanza_t *const stanza, const char *const to);
int xmpp_stanza_set_from(xmpp_stanza_t *stanza, const char *from); int xmpp_stanza_set_from(xmpp_stanza_t *const stanza, const char *const from);
/* allocate and initialize a stanza in reply to another */ /* allocate and initialize a stanza in reply to another */
xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t *stanza); xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t *const stanza);
xmpp_stanza_t *xmpp_stanza_reply_error(xmpp_stanza_t *stanza, xmpp_stanza_t *xmpp_stanza_reply_error(xmpp_stanza_t *const stanza,
const char *error_type, const char *const error_type,
const char *condition, const char *const condition,
const char *text); const char *const text);
/* stanza subclasses */ /* stanza subclasses */
xmpp_stanza_t *xmpp_message_new(xmpp_ctx_t *ctx, xmpp_stanza_t *xmpp_message_new(xmpp_ctx_t *ctx,
const char *type, const char *const type,
const char *to, const char *const to,
const char *id); const char *const id);
char *xmpp_message_get_body(xmpp_stanza_t *msg); char *xmpp_message_get_body(xmpp_stanza_t *msg);
int xmpp_message_set_body(xmpp_stanza_t *msg, const char *text); int xmpp_message_set_body(xmpp_stanza_t *msg, const char *const text);
xmpp_stanza_t *xmpp_iq_new(xmpp_ctx_t *ctx, const char *type, const char *id);
xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx);
xmpp_stanza_t * xmpp_stanza_t *
xmpp_error_new(xmpp_ctx_t *ctx, xmpp_error_type_t type, const char *text); xmpp_iq_new(xmpp_ctx_t *ctx, const char *const type, const char *const id);
xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx);
xmpp_stanza_t *xmpp_error_new(xmpp_ctx_t *ctx,
xmpp_error_type_t const type,
const char *const text);
/* jid */ /* jid */
@@ -479,21 +460,10 @@ char *xmpp_jid_resource(xmpp_ctx_t *ctx, const char *jid);
/* event loop */ /* event loop */
void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout); void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout);
void xmpp_run(xmpp_ctx_t *ctx); void xmpp_run(xmpp_ctx_t *ctx);
void xmpp_stop(xmpp_ctx_t *ctx); void xmpp_stop(xmpp_ctx_t *ctx);
void xmpp_ctx_set_timeout(xmpp_ctx_t *ctx, unsigned long timeout); void xmpp_ctx_set_timeout(xmpp_ctx_t *const ctx, const unsigned long timeout);
/* TLS certificates */
xmpp_ctx_t *xmpp_tlscert_get_ctx(const xmpp_tlscert_t *cert);
xmpp_conn_t *xmpp_tlscert_get_conn(const xmpp_tlscert_t *cert);
const char *xmpp_tlscert_get_pem(const xmpp_tlscert_t *cert);
const char *xmpp_tlscert_get_dnsname(const xmpp_tlscert_t *cert, size_t n);
const char *xmpp_tlscert_get_string(const xmpp_tlscert_t *cert,
xmpp_cert_element_t elmnt);
const char *xmpp_tlscert_get_description(xmpp_cert_element_t elmnt);
void xmpp_tlscert_free(xmpp_tlscert_t *cert);
/* UUID */ /* UUID */

View File

@@ -1,16 +0,0 @@
-----BEGIN CERTIFICATE-----
MIICfjCCAjSgAwIBAgIIW5u5Vwn2Mv0wCgYIKoZIzj0EAwIwSzFJMEcGA1UEAwxA
dmVyeS5sb25nLnVzZXJuYW1lQHNvLnRoZS5hc24xLmxlbmd0aC5pcy5hLnZhbGlk
LmFzY2lpLmNoYXJhY3RlcjAgFw0yMTAzMDExOTExMDBaGA8yMTIxMDMwMTE5MTEw
MFowSzFJMEcGA1UEAwxAdmVyeS5sb25nLnVzZXJuYW1lQHNvLnRoZS5hc24xLmxl
bmd0aC5pcy5hLnZhbGlkLmFzY2lpLmNoYXJhY3RlcjBJMBMGByqGSM49AgEGCCqG
SM49AwEBAzIABI/tSR5cZ9iHCVw0JwmKLvV3TbxPg3kDdouB0R2WKEdEWwXMIHkE
85RReISg+9/JDaOCAQ4wggEKMAkGA1UdEwQCMAAwHQYDVR0OBBYEFPjLGyHxqlOV
nXJQ9YBrnureO8LiMB8GA1UdIwQYMBaAFPjLGyHxqlOVnXJQ9YBrnureO8LiMAsG
A1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjCBmgYDVR0RBIGSMIGPoE4G
CCsGAQUFBwgFoEIMQHZlcnkubG9uZy51c2VybmFtZUBzby50aGUuYXNuMS5sZW5n
dGguaXMuYS52YWxpZC5hc2NpaS5jaGFyYWN0ZXKBDnlldEBub3RoZXIuc2Fugg53
d3cuc3Ryb3BoZS5pbaAdBggrBgEFBQcIBaARDA9zZWNvbmRAeG1wcC5qaWQwCgYI
KoZIzj0EAwIDOAAwNQIZAJmfqBhBMdaKCiWEuXu84K4+lznfzlRfmwIYCGRD1xk0
9cRa3V6PVwYWz6HcdRdMUBUj
-----END CERTIFICATE-----

View File

@@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MF8CAQEEGF7SsbTSOjzb97nFc7Qbt4sic+1nZk+ETqAKBggqhkjOPQMBAaE0AzIA
BI/tSR5cZ9iHCVw0JwmKLvV3TbxPg3kDdouB0R2WKEdEWwXMIHkE85RReISg+9/J
DQ==
-----END EC PRIVATE KEY-----

View File

@@ -16,9 +16,9 @@
static uint8_t char_to_bin(char c) static uint8_t char_to_bin(char c)
{ {
return c <= '9' ? (uint8_t)(c - '0') return c <= '9'
: c <= 'Z' ? (uint8_t)(c - 'A' + 10) ? (uint8_t)(c - '0')
: (uint8_t)(c - 'a' + 10); : c <= 'Z' ? (uint8_t)(c - 'A' + 10) : (uint8_t)(c - 'a' + 10);
} }
void test_hex_to_bin(const char *hex, uint8_t *bin, size_t *bin_len) void test_hex_to_bin(const char *hex, uint8_t *bin, size_t *bin_len)

View File

@@ -14,7 +14,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include "ostypes.h" #include "ostypes.h"
@@ -34,17 +33,17 @@
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif #endif
#define COMPARE(v1, v2) \ #define COMPARE(v1, v2) \
do { \ do { \
const char *__v1 = v1; \ const char *__v1 = v1; \
const char *__v2 = v2; \ const char *__v2 = v2; \
if (strcmp(__v1, __v2) != 0) { \ if (strcmp(__v1, __v2) != 0) { \
printf("Error: %s\n" \ printf("%s differs!\n" \
"Expected: %s\n" \ "expected: %s\n" \
"Got: %s\n", \ "got: %s\n", \
#v1 " != " #v2, __v1, __v2); \ #v1, __v1, __v2); \
exit(1); \ exit(1); \
} \ } \
} while (0) } while (0)
#define COMPARE_BUF(v1, len1, v2, len2) \ #define COMPARE_BUF(v1, len1, v2, len2) \
@@ -54,9 +53,9 @@
size_t __len1 = len1; \ size_t __len1 = len1; \
size_t __len2 = len2; \ size_t __len2 = len2; \
if (__len1 != __len2 || memcmp(__v1, __v2, __len1) != 0) { \ if (__len1 != __len2 || memcmp(__v1, __v2, __len1) != 0) { \
printf("Error: %s\n", #v1 " != " #v2); \ printf("%s differs!\n", #v1); \
printf("Expected: 0x%s\n", test_bin_to_hex(__v1, __len1)); \ printf("expected: 0x%s\n", test_bin_to_hex(__v1, __len1)); \
printf("Got: 0x%s\n", test_bin_to_hex(__v2, __len2)); \ printf("got: 0x%s\n", test_bin_to_hex(__v2, __len2)); \
exit(1); \ exit(1); \
} \ } \
} while (0) } while (0)

View File

@@ -22,7 +22,7 @@ static int mem_alloc_called = 0;
static int mem_free_called = 0; static int mem_free_called = 0;
static int mem_realloc_called = 0; static int mem_realloc_called = 0;
void *my_alloc(size_t size, void *userdata) void *my_alloc(const size_t size, void *const userdata)
{ {
(void)userdata; (void)userdata;
@@ -30,7 +30,7 @@ void *my_alloc(size_t size, void *userdata)
return malloc(size); return malloc(size);
} }
void my_free(void *p, void *userdata) void my_free(void *p, void *const userdata)
{ {
(void)userdata; (void)userdata;
@@ -38,7 +38,7 @@ void my_free(void *p, void *userdata)
return free(p); return free(p);
} }
void *my_realloc(void *p, size_t size, void *userdata) void *my_realloc(void *p, const size_t size, void *const userdata)
{ {
(void)userdata; (void)userdata;
@@ -46,10 +46,10 @@ void *my_realloc(void *p, size_t size, void *userdata)
return realloc(p, size); return realloc(p, size);
} }
void my_logger(void *userdata, void my_logger(void *const userdata,
xmpp_log_level_t level, const xmpp_log_level_t level,
const char *area, const char *const area,
const char *msg) const char *const msg)
{ {
if (strcmp((char *)userdata, "asdf") == 0 && level == XMPP_LEVEL_DEBUG && if (strcmp((char *)userdata, "asdf") == 0 && level == XMPP_LEVEL_DEBUG &&
strcmp(area, "test") == 0 && strcmp(msg, "hello") == 0) strcmp(area, "test") == 0 && strcmp(msg, "hello") == 0)

View File

@@ -1,49 +0,0 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "strophe.h"
#include "parser.h"
void xmpp_initialize(void);
void cbtest_handle_start(char *name, char **attrs, void *userdata)
{
(void)name;
(void)attrs;
(void)userdata;
}
void cbtest_handle_end(char *name, void *userdata)
{
(void)name;
(void)userdata;
}
void cbtest_handle_stanza(xmpp_stanza_t *stanza, void *userdata)
{
(void)stanza;
(void)userdata;
}
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
xmpp_ctx_t *ctx;
parser_t *parser;
char *dup = malloc(Size);
memcpy(dup, Data, Size);
ctx = xmpp_ctx_new(NULL, NULL);
parser = parser_new(ctx, cbtest_handle_start, cbtest_handle_end,
cbtest_handle_stanza, NULL);
parser_feed(parser, dup, Size);
free(dup);
parser_free(parser);
xmpp_ctx_free(ctx);
return 0;
}

View File

@@ -21,20 +21,19 @@
#include "rand.c" #include "rand.c"
/* stubs to build test without whole libstrophe */ /* stubs to build test without whole libstrophe */
void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size) void *xmpp_alloc(const xmpp_ctx_t *const ctx, const size_t size)
{ {
(void)ctx; (void)ctx;
(void)size; (void)size;
return NULL; return NULL;
} }
void xmpp_free(const xmpp_ctx_t *ctx, void *p) void xmpp_free(const xmpp_ctx_t *const ctx, void *p)
{ {
(void)ctx; (void)ctx;
(void)p; (void)p;
} }
#ifndef HAVE_SNPRINTF
int xmpp_snprintf(char *str, size_t count, const char *fmt, ...) int xmpp_snprintf(char *str, size_t count, const char *fmt, ...)
{ {
(void)str; (void)str;
@@ -42,7 +41,6 @@ int xmpp_snprintf(char *str, size_t count, const char *fmt, ...)
(void)fmt; (void)fmt;
return 0; return 0;
} }
#endif /* HAVE_SNPRINTF */
uint64_t time_stamp(void) uint64_t time_stamp(void)
{ {

View File

@@ -17,8 +17,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "test.h"
#define MAGICPTR ((void *)0xfeedbeef) #define MAGICPTR ((void *)0xfeedbeef)
static unsigned long used_blocks = 0; static unsigned long used_blocks = 0;
@@ -109,62 +107,9 @@ static void test_stanza_from_string(xmpp_ctx_t *ctx)
assert(stanza != NULL); assert(stanza != NULL);
ret = xmpp_stanza_to_text(stanza, &buf, &buflen); ret = xmpp_stanza_to_text(stanza, &buf, &buflen);
assert(ret == XMPP_EOK); assert(ret == XMPP_EOK);
COMPARE(str, buf); assert(strcmp(buf, str) == 0);
xmpp_free(ctx, buf); xmpp_free(ctx, buf);
xmpp_stanza_release(stanza); xmpp_stanza_release(stanza);
/* Error path. */
stanza = xmpp_stanza_new_from_string(ctx, "<uu><uu>tt");
assert(stanza == NULL);
}
static void test_stanza_error(xmpp_ctx_t *ctx)
{
xmpp_stanza_t *stanza;
xmpp_stanza_t *error;
xmpp_stanza_t *item;
char *buf;
size_t buflen;
const char *attr[10];
int attrlen = ARRAY_SIZE(attr);
int ret;
static const char *str =
"<iq from='romeo@montague.lit/home' to='juliet@capulet.lit/chamber' "
"type='get' id='e2e1'><ping xmlns='urn:xmpp:ping'/></iq>";
static const char *str_error =
"<error type=\"cancel\"><service-unavailable "
"xmlns=\"urn:ietf:params:xml:ns:xmpp-stanzas\"/></error>";
stanza = xmpp_stanza_new_from_string(ctx, str);
assert(stanza != NULL);
error =
xmpp_stanza_reply_error(stanza, "cancel", "service-unavailable", NULL);
assert(error != NULL);
assert(xmpp_stanza_get_to(error) != NULL);
COMPARE("romeo@montague.lit/home", xmpp_stanza_get_to(error));
assert(xmpp_stanza_get_from(error) != NULL);
COMPARE("juliet@capulet.lit/chamber", xmpp_stanza_get_from(error));
assert(xmpp_stanza_get_id(error) != NULL);
COMPARE("e2e1", xmpp_stanza_get_id(error));
assert(xmpp_stanza_get_type(error) != NULL);
COMPARE("error", xmpp_stanza_get_type(error));
ret = xmpp_stanza_get_attributes(error, attr, attrlen);
/* attr contains both attribute name and value. */
assert(ret == 8);
item = xmpp_stanza_get_child_by_name(error, "error");
assert(item != NULL);
ret = xmpp_stanza_to_text(item, &buf, &buflen);
assert(ret == XMPP_EOK);
COMPARE(str_error, buf);
xmpp_free(ctx, buf);
xmpp_stanza_release(stanza);
xmpp_stanza_release(error);
} }
int main() int main()
@@ -177,7 +122,6 @@ int main()
test_stanza_add_child(ctx); test_stanza_add_child(ctx);
test_stanza_from_string(ctx); test_stanza_from_string(ctx);
test_stanza_error(ctx);
xmpp_ctx_free(ctx); xmpp_ctx_free(ctx);
xmpp_shutdown(); xmpp_shutdown();

View File

@@ -1,69 +0,0 @@
/* test_xmppaddr.c
** libstrophe XMPP client library -- test routines for the xmppaddr
** certificate API's
**
** Copyright (C) 2021 Steffen Jaeckel
**
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "strophe.h"
#include "test.h"
int main()
{
xmpp_ctx_t *ctx;
xmpp_conn_t *conn;
xmpp_log_t *log;
char xmppaddr_num[] = "0";
unsigned int n;
xmpp_initialize();
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
ctx = xmpp_ctx_new(NULL, log);
conn = xmpp_conn_new(ctx);
xmpp_conn_set_client_cert(conn, "tests/cert.pem", "tests/key.pem");
xmppaddr_num[0] = xmppaddr_num[0] + xmpp_conn_cert_xmppaddr_num(conn);
COMPARE("2", xmppaddr_num);
for (n = 0; n < 3; ++n) {
char *r = xmpp_conn_cert_xmppaddr(conn, n);
switch (n) {
case 0:
COMPARE("very.long.username@so.the.asn1.length.is.a.valid.ascii."
"character",
r);
break;
case 1:
COMPARE("second@xmpp.jid", r);
break;
default:
if (r != NULL) {
printf("\nThere shall only be two id-on-xmppAddr SANs!\nFound "
"another one: %s\n",
r);
exit(1);
}
break;
}
free(r);
}
xmpp_conn_release(conn);
xmpp_ctx_free(ctx);
xmpp_shutdown();
return 0;
}

View File

@@ -1,14 +0,0 @@
#!/bin/sh
if [ "x$LIBRESSL" = "xyes" ]; then
cd "$HOME"
git clone https://github.com/libressl-portable/portable.git libressl-git
cd libressl-git
if [ -n "$LIBRESSL_COMMIT" ]; then
git checkout "$LIBRESSL_COMMIT"
fi
./autogen.sh
./configure --prefix="$HOME/libressl"
make -j"$(nproc)"
make install
fi