Compare commits
1 Commits
0.11.0
...
unify-erro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
070a64d9d5 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -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/
|
||||||
|
|||||||
22
.travis.yml
22
.travis.yml
@@ -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
|
||||||
|
|||||||
28
ChangeLog
28
ChangeLog
@@ -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
|
||||||
|
|||||||
4
Doxyfile
4
Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Strophe
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 0.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
|
||||||
|
|||||||
41
Makefile.am
41
Makefile.am
@@ -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
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
28
configure.ac
28
configure.ac
@@ -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}])
|
||||||
|
|||||||
2
docs/footer.html
Normal file
2
docs/footer.html
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -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;
|
||||||
|
|||||||
168
examples/basic.c
168
examples/basic.c
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
272
src/auth.c
272
src/auth.c
@@ -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.");
|
||||||
}
|
}
|
||||||
|
|||||||
95
src/common.h
95
src/common.h
@@ -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__ */
|
||||||
|
|||||||
463
src/conn.c
463
src/conn.c
@@ -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 <stream:stream> tag to the server.
|
/** Send the opening <stream:stream> 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;
|
|
||||||
}
|
|
||||||
|
|||||||
13
src/crypto.c
13
src/crypto.c
@@ -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
104
src/ctx.c
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
35
src/event.c
35
src/event.c
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
11
src/hash.h
11
src/hash.h
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
18
src/sock.c
18
src/sock.c
@@ -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;
|
||||||
|
|||||||
18
src/sock.h
18
src/sock.h
@@ -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__ */
|
||||||
|
|||||||
187
src/stanza.c
187
src/stanza.c
@@ -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
214
src/tls.c
@@ -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;
|
|
||||||
}
|
|
||||||
25
src/tls.h
25
src/tls.h
@@ -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__ */
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
334
src/tls_gnutls.c
334
src/tls_gnutls.c
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
59
src/util.c
59
src/util.c
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
356
strophe.h
@@ -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 */
|
||||||
|
|
||||||
|
|||||||
@@ -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-----
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
-----BEGIN EC PRIVATE KEY-----
|
|
||||||
MF8CAQEEGF7SsbTSOjzb97nFc7Qbt4sic+1nZk+ETqAKBggqhkjOPQMBAaE0AzIA
|
|
||||||
BI/tSR5cZ9iHCVw0JwmKLvV3TbxPg3kDdouB0R2WKEdEWwXMIHkE85RReISg+9/J
|
|
||||||
DQ==
|
|
||||||
-----END EC PRIVATE KEY-----
|
|
||||||
@@ -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)
|
||||||
|
|||||||
29
tests/test.h
29
tests/test.h
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
Reference in New Issue
Block a user