mirror of
https://github.com/strophe/libstrophe.git
synced 2026-08-05 19:36:20 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d20957a98d |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
*.swp
|
||||
*.orig
|
||||
Makefile
|
||||
test-driver
|
||||
.libs
|
||||
@@ -55,18 +54,12 @@ tests/test_resolver
|
||||
tests/test_sasl
|
||||
tests/test_scram
|
||||
tests/test_sha1
|
||||
tests/test_sha256
|
||||
tests/test_sha512
|
||||
tests/test_snprintf
|
||||
tests/test_sock
|
||||
tests/test_stanza
|
||||
tests/test_string
|
||||
tests/test_xmppaddr
|
||||
m4/
|
||||
libstrophe.project
|
||||
libs/
|
||||
obj/
|
||||
expat/
|
||||
.settings/
|
||||
.project
|
||||
.cproject
|
||||
|
||||
25
.travis.yml
25
.travis.yml
@@ -1,26 +1,15 @@
|
||||
language: c
|
||||
dist: focal
|
||||
install:
|
||||
- sudo apt-get update
|
||||
- sudo apt-get -y install libtool pkg-config libexpat1-dev libxml2-dev libssl-dev libgnutls28-dev libc-ares-dev dos2unix
|
||||
stages:
|
||||
- style
|
||||
- test
|
||||
- sudo apt-get -y install libtool pkg-config libexpat1-dev libxml2-dev libssl-dev libc-ares-dev
|
||||
before_script:
|
||||
- ./bootstrap.sh
|
||||
script:
|
||||
- ./configure ${CONFIGURE_OPT} CFLAGS="-Werror" && make && make check
|
||||
env:
|
||||
- CONFIGURE_OPT="--without-libxml2"
|
||||
- CONFIGURE_OPT="--with-libxml2"
|
||||
- CONFIGURE_OPT="--with-gnutls"
|
||||
- CONFIGURE_OPT="--disable-tls"
|
||||
- CONFIGURE_OPT="--enable-cares"
|
||||
- CONFIGURE_OPT="PKG_CONFIG_PATH=${HOME}/libressl/lib/pkgconfig" LIBRESSL=yes LIBRESSL_COMMIT="v3.1.4"
|
||||
- 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:
|
||||
include:
|
||||
- stage: style
|
||||
name: "Check coding style"
|
||||
env: CONFIGURE_OPT=""
|
||||
script: ./bootstrap.sh && ./configure && make format && git diff --exit-code
|
||||
allow_failures:
|
||||
- stage: style
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
39
ChangeLog
39
ChangeLog
@@ -1,53 +1,14 @@
|
||||
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
|
||||
- Coding style has been unified
|
||||
- SCRAM-SHA-256 and SCRAM-SHA-512 support
|
||||
- c-ares support
|
||||
- LibreSSL support
|
||||
- Introduced global timed handlers that fire periodically regardless of
|
||||
connections status, such a handler can be used to implement deferred
|
||||
re-connection
|
||||
- examples/register implements XEP-0077
|
||||
- Fixed issue with IPv6 on Windows (#153)
|
||||
- Improved portability across systems such as Haiku, Windows
|
||||
- New API:
|
||||
- xmpp_stanza_get_child_by_name_and_ns()
|
||||
- xmpp_conn_is_connecting()
|
||||
- xmpp_conn_is_connected()
|
||||
- xmpp_conn_is_disconnected()
|
||||
- xmpp_stanza_new_from_string()
|
||||
- xmpp_stanza_add_child_ex()
|
||||
- xmpp_stanza_get_context()
|
||||
- xmpp_stanza_reply_error()
|
||||
- xmpp_global_timed_handler_add()
|
||||
- xmpp_global_timed_handler_delete()
|
||||
|
||||
0.9.3
|
||||
- PLAIN mechanism is used only when no other mechanisms are supported
|
||||
|
||||
4
Doxyfile
4
Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = Strophe
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = 0.11
|
||||
PROJECT_NUMBER = 0.9
|
||||
|
||||
# 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
|
||||
@@ -1047,7 +1047,7 @@ HTML_HEADER =
|
||||
# that doxygen normally uses.
|
||||
# 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
|
||||
# sheet that is used by each HTML page. It can be used to fine-tune the look of
|
||||
|
||||
66
Makefile.am
66
Makefile.am
@@ -5,13 +5,8 @@ ACLOCAL_AMFLAGS = -I m4
|
||||
PARSER_CFLAGS=@PARSER_CFLAGS@
|
||||
PARSER_LIBS=@PARSER_LIBS@
|
||||
|
||||
if TLS_WITH_GNUTLS
|
||||
SSL_CFLAGS = @gnutls_CFLAGS@
|
||||
SSL_LIBS = @gnutls_LIBS@
|
||||
else
|
||||
SSL_CFLAGS = @openssl_CFLAGS@
|
||||
SSL_LIBS = @openssl_LIBS@
|
||||
endif
|
||||
|
||||
RESOLV_CFLAGS = @RESOLV_CFLAGS@
|
||||
RESOLV_LIBS = @RESOLV_LIBS@
|
||||
@@ -43,12 +38,9 @@ libstrophe_la_SOURCES = \
|
||||
src/sasl.c \
|
||||
src/scram.c \
|
||||
src/sha1.c \
|
||||
src/sha256.c \
|
||||
src/sha512.c \
|
||||
src/snprintf.c \
|
||||
src/sock.c \
|
||||
src/stanza.c \
|
||||
src/tls.c \
|
||||
src/util.c \
|
||||
src/uuid.c
|
||||
libstrophe_la_SOURCES += \
|
||||
@@ -61,10 +53,7 @@ libstrophe_la_SOURCES += \
|
||||
src/resolver.h \
|
||||
src/sasl.h \
|
||||
src/scram.h \
|
||||
src/sha.h \
|
||||
src/sha1.h \
|
||||
src/sha256.h \
|
||||
src/sha512.h \
|
||||
src/snprintf.h \
|
||||
src/sock.h \
|
||||
src/tls.h \
|
||||
@@ -73,12 +62,8 @@ libstrophe_la_SOURCES += \
|
||||
if DISABLE_TLS
|
||||
libstrophe_la_SOURCES += src/tls_dummy.c
|
||||
else
|
||||
if TLS_WITH_GNUTLS
|
||||
libstrophe_la_SOURCES += src/tls_gnutls.c
|
||||
else
|
||||
libstrophe_la_SOURCES += src/tls_openssl.c
|
||||
endif
|
||||
endif
|
||||
|
||||
if PARSER_EXPAT
|
||||
libstrophe_la_SOURCES += src/parser_expat.c
|
||||
@@ -87,29 +72,27 @@ libstrophe_la_SOURCES += src/parser_libxml2.c
|
||||
endif
|
||||
|
||||
include_HEADERS = strophe.h
|
||||
noinst_HEADERS = strophepp.h
|
||||
|
||||
pkgconfig_DATA = libstrophe.pc
|
||||
|
||||
EXTRA_DIST = \
|
||||
_clang-format \
|
||||
Doxyfile \
|
||||
GPL-LICENSE.txt \
|
||||
LICENSE.txt \
|
||||
MIT-LICENSE.txt \
|
||||
bootstrap.sh \
|
||||
build-android.sh \
|
||||
docs/footer.html \
|
||||
examples/README.md \
|
||||
jni/Android.mk \
|
||||
jni/Application.mk \
|
||||
rpm/README \
|
||||
rpm/libstrophe.spec \
|
||||
src/tls_gnutls.c \
|
||||
src/tls_schannel.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
|
||||
noinst_PROGRAMS = \
|
||||
examples/active \
|
||||
@@ -151,8 +134,6 @@ examples_register_LDADD = $(STROPHE_LIBS)
|
||||
TESTS = \
|
||||
tests/check_parser \
|
||||
tests/test_sha1 \
|
||||
tests/test_sha256 \
|
||||
tests/test_sha512 \
|
||||
tests/test_md5 \
|
||||
tests/test_rand \
|
||||
tests/test_scram \
|
||||
@@ -165,22 +146,8 @@ TESTS = \
|
||||
tests/test_stanza \
|
||||
tests/test_resolver
|
||||
|
||||
if !DISABLE_TLS
|
||||
TESTS += tests/test_xmppaddr
|
||||
endif
|
||||
|
||||
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_CFLAGS = $(PARSER_CFLAGS) $(STROPHE_FLAGS) \
|
||||
-I$(top_srcdir)/src
|
||||
@@ -215,19 +182,12 @@ tests_test_resolver_LDFLAGS = -static
|
||||
tests_test_rand_SOURCES = tests/test_rand.c tests/test.c src/sha1.c
|
||||
tests_test_rand_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src
|
||||
|
||||
tests_test_scram_SOURCES = tests/test_scram.c tests/test.c src/sha1.c \
|
||||
src/sha256.c src/sha512.c
|
||||
tests_test_scram_SOURCES = tests/test_scram.c tests/test.c src/sha1.c
|
||||
tests_test_scram_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src
|
||||
|
||||
tests_test_sha1_SOURCES = tests/test_sha1.c src/sha1.c
|
||||
tests_test_sha1_CFLAGS = -I$(top_srcdir)/src
|
||||
|
||||
tests_test_sha256_SOURCES = tests/test_sha256.c tests/test.c src/sha256.c
|
||||
tests_test_sha256_CFLAGS = -I$(top_srcdir)/src
|
||||
|
||||
tests_test_sha512_SOURCES = tests/test_sha512.c tests/test.c src/sha512.c
|
||||
tests_test_sha512_CFLAGS = -I$(top_srcdir)/src
|
||||
|
||||
tests_test_md5_SOURCES = tests/test_md5.c tests/test.c src/md5.c
|
||||
tests_test_md5_CFLAGS = -I$(top_srcdir)/src
|
||||
|
||||
@@ -239,17 +199,7 @@ tests_test_string_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src
|
||||
tests_test_string_LDADD = $(STROPHE_LIBS)
|
||||
tests_test_string_LDFLAGS = -static
|
||||
|
||||
tests_test_stanza_SOURCES = tests/test_stanza.c tests/test.h
|
||||
tests_test_stanza_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src
|
||||
tests_test_stanza_SOURCES = tests/test_stanza.c
|
||||
tests_test_stanza_CFLAGS = $(STROPHE_FLAGS)
|
||||
tests_test_stanza_LDADD = $(STROPHE_LIBS)
|
||||
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:
|
||||
@echo " * run clang-format on all sources"
|
||||
@dos2unix -q src/*.[ch] *.h tests/*.[ch] examples/*.c
|
||||
@clang-format -i src/*.[ch] *.h tests/*.[ch] examples/*.c
|
||||
|
||||
@@ -5,7 +5,11 @@ libstrophe is a lightweight XMPP client library written in C. It has
|
||||
minimal dependencies and is configurable for various environments. It
|
||||
runs well on Linux, Unix and Windows based platforms.
|
||||
|
||||
libstrophe is dual licensed under MIT and GPLv3.
|
||||
Its goals are:
|
||||
|
||||
- usable quickly
|
||||
- well documented
|
||||
- reliable
|
||||
|
||||
Build Instructions
|
||||
------------------
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
---
|
||||
AlignConsecutiveAssignments: 'false'
|
||||
AlignEscapedNewlines: Left
|
||||
AllowShortBlocksOnASingleLine: 'true'
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: 'false'
|
||||
BinPackParameters: 'false'
|
||||
BreakBeforeBraces: Linux
|
||||
ColumnLimit: '80'
|
||||
DerivePointerAlignment: 'false'
|
||||
IndentGotoLabels: false
|
||||
IndentWidth: '4'
|
||||
PointerAlignment: Right
|
||||
SortIncludes: 'false'
|
||||
TabWidth: '4'
|
||||
UseTab: Never
|
||||
|
||||
...
|
||||
33
configure.ac
33
configure.ac
@@ -1,4 +1,4 @@
|
||||
AC_INIT([libstrophe], [0.11.0], [jack@metajack.im])
|
||||
AC_INIT([libstrophe], [0.9.3], [jack@metajack.im])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AM_INIT_AUTOMAKE([foreign])
|
||||
LT_INIT([dlopen])
|
||||
@@ -22,43 +22,19 @@ WARNING_FLAGS="-Wall"
|
||||
|
||||
AS_CASE([$PLATFORM],
|
||||
[haiku], [],
|
||||
[WARNING_FLAGS="$WARNING_FLAGS -Wextra"])
|
||||
[WARNING_FLAGS="$WARNING_FLAGS -Wextra -Wno-unused-parameter"])
|
||||
|
||||
AC_ARG_WITH([libxml2],
|
||||
[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],
|
||||
[AS_HELP_STRING([--disable-tls], [disable TLS support])])
|
||||
AC_ARG_ENABLE([cares],
|
||||
[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_CHECK_FUNCS([snprintf vsnprintf])
|
||||
AC_CHECK_DECLS([va_copy], [], [], [#include <stdarg.h>])
|
||||
#AC_CHECK_FUNCS([snprintf vsnprintf])
|
||||
|
||||
if test "x$enable_tls" != xno -a "x$with_gnutls" == xyes; 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
|
||||
if test "x$enable_tls" != xno; then
|
||||
PKG_CHECK_MODULES([openssl], [openssl],
|
||||
[PC_REQUIRES="openssl ${PC_REQUIRES}"],
|
||||
[AC_CHECK_HEADER([openssl/ssl.h],
|
||||
@@ -168,7 +144,6 @@ m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR],
|
||||
|
||||
AM_CONDITIONAL([PARSER_EXPAT], [test x$with_parser != xlibxml2])
|
||||
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_CFLAGS], [${PC_CFLAGS}])
|
||||
|
||||
2
docs/footer.html
Normal file
2
docs/footer.html
Normal file
@@ -0,0 +1,2 @@
|
||||
</body>
|
||||
</html>
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
#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;
|
||||
const char *type;
|
||||
|
||||
(void)userdata;
|
||||
|
||||
type = xmpp_stanza_get_type(stanza);
|
||||
if (strcmp(type, "error") == 0)
|
||||
fprintf(stderr, "ERROR: query failed\n");
|
||||
@@ -44,18 +44,13 @@ int handle_reply(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void conn_handler(xmpp_conn_t *conn,
|
||||
xmpp_conn_event_t status,
|
||||
int error,
|
||||
xmpp_stream_error_t *stream_error,
|
||||
void *userdata)
|
||||
void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status,
|
||||
const int error, xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
|
||||
xmpp_stanza_t *iq, *query;
|
||||
|
||||
(void)error;
|
||||
(void)stream_error;
|
||||
|
||||
if (status == XMPP_CONN_CONNECT) {
|
||||
fprintf(stderr, "DEBUG: connected\n");
|
||||
|
||||
|
||||
152
examples/basic.c
152
examples/basic.c
@@ -10,7 +10,6 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <strophe.h>
|
||||
@@ -19,149 +18,66 @@
|
||||
#define KA_TIMEOUT 60
|
||||
#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 */
|
||||
static void conn_handler(xmpp_conn_t *conn,
|
||||
xmpp_conn_event_t status,
|
||||
int error,
|
||||
xmpp_stream_error_t *stream_error,
|
||||
void *userdata)
|
||||
void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status,
|
||||
const int error, xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
|
||||
int secured;
|
||||
|
||||
(void)error;
|
||||
(void)stream_error;
|
||||
|
||||
if (status == XMPP_CONN_CONNECT) {
|
||||
fprintf(stderr, "DEBUG: connected\n");
|
||||
secured = xmpp_conn_is_secured(conn);
|
||||
fprintf(stderr, "DEBUG: connection is %s.\n",
|
||||
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);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "DEBUG: disconnected\n");
|
||||
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)
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
xmpp_conn_t *conn;
|
||||
xmpp_log_t *log;
|
||||
char *jid = NULL, *password = NULL, *cert = NULL, *key = NULL, *host = NULL,
|
||||
*capath = NULL, *cafile = NULL;
|
||||
char *jid, *pass, *host = NULL;
|
||||
long flags = 0;
|
||||
int tcp_keepalive = 0, verbosity = 0, certfail = 0;
|
||||
int tcp_keepalive = 0;
|
||||
int i;
|
||||
unsigned long port = 0;
|
||||
|
||||
/* take a jid and password on the command line */
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "--help") == 0)
|
||||
usage(0);
|
||||
else if (strcmp(argv[i], "--disable-tls") == 0)
|
||||
if (strcmp(argv[i], "--disable-tls") == 0)
|
||||
flags |= XMPP_CONN_FLAG_DISABLE_TLS;
|
||||
else if (strcmp(argv[i], "--mandatory-tls") == 0)
|
||||
flags |= XMPP_CONN_FLAG_MANDATORY_TLS;
|
||||
else if (strcmp(argv[i], "--trust-tls") == 0)
|
||||
flags |= XMPP_CONN_FLAG_TRUST_TLS;
|
||||
else if (strcmp(argv[i], "--legacy-ssl") == 0)
|
||||
flags |= XMPP_CONN_FLAG_LEGACY_SSL;
|
||||
else if (strcmp(argv[i], "--legacy-auth") == 0)
|
||||
flags |= XMPP_CONN_FLAG_LEGACY_AUTH;
|
||||
else if (strcmp(argv[i], "--verbose") == 0)
|
||||
verbosity++;
|
||||
else if (strcmp(argv[i], "--tcp-keepalive") == 0)
|
||||
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
|
||||
break;
|
||||
}
|
||||
if ((!jid && (!cert || !key)) || (argc - i) > 2) {
|
||||
usage(1);
|
||||
if ((argc - i) < 2 || (argc - i) > 3) {
|
||||
fprintf(stderr, "Usage: basic [options] <jid> <pass> [<host>]\n\n"
|
||||
"Options:\n"
|
||||
" --disable-tls Disable TLS.\n"
|
||||
" --mandatory-tls Deny plaintext connection.\n"
|
||||
" --legacy-ssl Use old style SSL.\n"
|
||||
" --tcp-keepalive Configure TCP keepalive.\n\n"
|
||||
"Note: --disable-tls conflicts with --mandatory-tls or "
|
||||
"--legacy-ssl\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (i < argc)
|
||||
host = argv[i];
|
||||
if (i + 1 < argc)
|
||||
port = strtoul(argv[i + 1], NULL, 0);
|
||||
jid = argv[i];
|
||||
pass = argv[i + 1];
|
||||
if (i + 2 < argc)
|
||||
host = argv[i + 2];
|
||||
|
||||
/*
|
||||
* Note, this example doesn't handle errors. Applications should check
|
||||
@@ -171,11 +87,9 @@ int main(int argc, char **argv)
|
||||
/* init library */
|
||||
xmpp_initialize();
|
||||
|
||||
/* pass NULL instead to silence output */
|
||||
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
|
||||
/* create a context */
|
||||
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); /* pass NULL instead to silence output */
|
||||
ctx = xmpp_ctx_new(NULL, log);
|
||||
xmpp_ctx_set_verbosity(ctx, verbosity);
|
||||
|
||||
/* create a connection */
|
||||
conn = xmpp_conn_new(ctx);
|
||||
@@ -183,32 +97,18 @@ int main(int argc, char **argv)
|
||||
/* configure connection properties (optional) */
|
||||
xmpp_conn_set_flags(conn, flags);
|
||||
/* configure TCP keepalive (optional) */
|
||||
if (tcp_keepalive)
|
||||
xmpp_conn_set_keepalive(conn, KA_TIMEOUT, KA_INTERVAL);
|
||||
if (tcp_keepalive) xmpp_conn_set_keepalive(conn, KA_TIMEOUT, KA_INTERVAL);
|
||||
|
||||
/* setup authentication information */
|
||||
if (cert && key) {
|
||||
xmpp_conn_set_client_cert(conn, cert, key);
|
||||
}
|
||||
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);
|
||||
xmpp_conn_set_pass(conn, pass);
|
||||
|
||||
/* 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 -
|
||||
our connect handler will trigger an exit */
|
||||
xmpp_run(ctx);
|
||||
}
|
||||
|
||||
/* release our connection and context */
|
||||
xmpp_conn_release(conn);
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
|
||||
#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;
|
||||
const char *ns;
|
||||
@@ -68,7 +69,8 @@ int version_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
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_stanza_t *body, *reply;
|
||||
@@ -85,8 +87,7 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
|
||||
intext = xmpp_stanza_get_text(body);
|
||||
|
||||
printf("Incoming message from %s: %s\n", xmpp_stanza_get_from(stanza),
|
||||
intext);
|
||||
printf("Incoming message from %s: %s\n", xmpp_stanza_get_from(stanza), intext);
|
||||
|
||||
reply = xmpp_stanza_reply(stanza);
|
||||
if (xmpp_stanza_get_type(reply) == NULL)
|
||||
@@ -114,29 +115,24 @@ int message_handler(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
}
|
||||
|
||||
/* define a handler for connection events */
|
||||
void conn_handler(xmpp_conn_t *conn,
|
||||
xmpp_conn_event_t status,
|
||||
int error,
|
||||
xmpp_stream_error_t *stream_error,
|
||||
void *userdata)
|
||||
void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status,
|
||||
const int error, xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
|
||||
|
||||
(void)error;
|
||||
(void)stream_error;
|
||||
|
||||
if (status == XMPP_CONN_CONNECT) {
|
||||
xmpp_stanza_t* pres;
|
||||
fprintf(stderr, "DEBUG: connected\n");
|
||||
xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL,
|
||||
ctx);
|
||||
xmpp_handler_add(conn, version_handler, "jabber:iq:version", "iq", NULL, ctx);
|
||||
xmpp_handler_add(conn, message_handler, NULL, "message", NULL, ctx);
|
||||
|
||||
/* Send initial <presence/> so that we appear online to contacts */
|
||||
pres = xmpp_presence_new(ctx);
|
||||
xmpp_send(conn, pres);
|
||||
xmpp_stanza_release(pres);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "DEBUG: disconnected\n");
|
||||
xmpp_stop(ctx);
|
||||
}
|
||||
@@ -161,9 +157,8 @@ int main(int argc, char **argv)
|
||||
/* init library */
|
||||
xmpp_initialize();
|
||||
|
||||
/* pass NULL instead to silence output */
|
||||
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
|
||||
/* create a context */
|
||||
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); /* pass NULL instead to silence output */
|
||||
ctx = xmpp_ctx_new(NULL, log);
|
||||
|
||||
/* create a connection */
|
||||
|
||||
@@ -19,22 +19,19 @@
|
||||
|
||||
#include <strophe.h>
|
||||
|
||||
|
||||
/* define a handler for connection events */
|
||||
void conn_handler(xmpp_conn_t *conn,
|
||||
xmpp_conn_event_t status,
|
||||
int error,
|
||||
xmpp_stream_error_t *stream_error,
|
||||
void *userdata)
|
||||
void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status,
|
||||
const int error, xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
|
||||
|
||||
(void)error;
|
||||
(void)stream_error;
|
||||
|
||||
if (status == XMPP_CONN_CONNECT) {
|
||||
fprintf(stderr, "DEBUG: connected\n");
|
||||
xmpp_disconnect(conn);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "DEBUG: disconnected\n");
|
||||
xmpp_stop(ctx);
|
||||
}
|
||||
@@ -70,9 +67,8 @@ int main(int argc, char **argv)
|
||||
/* init library */
|
||||
xmpp_initialize();
|
||||
|
||||
/* pass NULL instead to silence output */
|
||||
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG);
|
||||
/* create a context */
|
||||
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); /* pass NULL instead to silence output */
|
||||
ctx = xmpp_ctx_new(NULL, log);
|
||||
|
||||
/* create a connection */
|
||||
@@ -98,3 +94,4 @@ int main(int argc, char **argv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,9 @@ typedef struct {
|
||||
|
||||
#define FEATURES_TIMEOUT 5000 /* 5 seconds */
|
||||
|
||||
static void
|
||||
iq_reg_send_form(xmpp_reg_t *reg, xmpp_conn_t *conn, xmpp_stanza_t *stanza)
|
||||
static void iq_reg_send_form(xmpp_reg_t *reg,
|
||||
xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza)
|
||||
{
|
||||
xmpp_ctx_t *ctx = reg->ctx;
|
||||
xmpp_stanza_t *query;
|
||||
@@ -46,8 +47,8 @@ iq_reg_send_form(xmpp_reg_t *reg, xmpp_conn_t *conn, xmpp_stanza_t *stanza)
|
||||
xmpp_stanza_t *text;
|
||||
xmpp_stanza_t *iq;
|
||||
const char *name;
|
||||
size_t len;
|
||||
char buf[256];
|
||||
ssize_t rc;
|
||||
size_t size;
|
||||
char *s;
|
||||
|
||||
query = xmpp_stanza_get_child_by_name(stanza, "query");
|
||||
@@ -68,14 +69,12 @@ iq_reg_send_form(xmpp_reg_t *reg, xmpp_conn_t *conn, xmpp_stanza_t *stanza)
|
||||
xmpp_free(ctx, s);
|
||||
} else {
|
||||
printf("%s: ", name);
|
||||
s = fgets(buf, sizeof(buf), stdin);
|
||||
if (s != NULL) {
|
||||
len = strlen(s);
|
||||
if (len > 0 && s[len - 1] == '\n') {
|
||||
s[len - 1] = '\0';
|
||||
--len;
|
||||
}
|
||||
if (len > 0) {
|
||||
s = NULL;
|
||||
size = 0;
|
||||
rc = getline(&s, &size, stdin);
|
||||
if (rc > 0 && s[rc - 1] == '\n')
|
||||
s[rc - 1] = '\0';
|
||||
if (rc > 0 && strlen(s) > 0) {
|
||||
elem = xmpp_stanza_new(ctx);
|
||||
text = xmpp_stanza_new(ctx);
|
||||
xmpp_stanza_set_text(text, s);
|
||||
@@ -85,7 +84,7 @@ iq_reg_send_form(xmpp_reg_t *reg, xmpp_conn_t *conn, xmpp_stanza_t *stanza)
|
||||
xmpp_stanza_release(text);
|
||||
xmpp_stanza_release(elem);
|
||||
}
|
||||
}
|
||||
free(s);
|
||||
}
|
||||
next = xmpp_stanza_get_next(next);
|
||||
}
|
||||
@@ -102,12 +101,12 @@ 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;
|
||||
|
||||
(void)userdata;
|
||||
|
||||
type = xmpp_stanza_get_type(stanza);
|
||||
if (!type || strcmp(type, "error") == 0) {
|
||||
fprintf(stderr, "DEBUG: error during registration\n");
|
||||
@@ -127,7 +126,9 @@ quit:
|
||||
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_stanza_t *registered = NULL;
|
||||
@@ -162,26 +163,22 @@ quit:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_error(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
static int _handle_error(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
(void)stanza;
|
||||
(void)userdata;
|
||||
|
||||
fprintf(stderr, "DEBUG: received stream error\n");
|
||||
xmpp_disconnect(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _handle_proceedtls_default(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata)
|
||||
static int _handle_proceedtls_default(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
const char *name = xmpp_stanza_get_name(stanza);
|
||||
|
||||
(void)userdata;
|
||||
|
||||
if (strcmp(name, "proceed") == 0) {
|
||||
fprintf(stderr, "DEBUG: proceeding with TLS\n");
|
||||
if (xmpp_conn_tls_start(conn) == 0) {
|
||||
@@ -196,18 +193,18 @@ static int _handle_proceedtls_default(xmpp_conn_t *conn,
|
||||
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;
|
||||
|
||||
fprintf(stderr, "DEBUG: timeout\n");
|
||||
xmpp_disconnect(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
static int _handle_features(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_reg_t *reg = (xmpp_reg_t *)userdata;
|
||||
xmpp_ctx_t *ctx = reg->ctx;
|
||||
@@ -224,8 +221,8 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
child = xmpp_stanza_new(ctx);
|
||||
xmpp_stanza_set_name(child, "starttls");
|
||||
xmpp_stanza_set_ns(child, XMPP_NS_TLS);
|
||||
xmpp_handler_add(conn, _handle_proceedtls_default, XMPP_NS_TLS, NULL,
|
||||
NULL, NULL);
|
||||
xmpp_handler_add(conn, _handle_proceedtls_default,
|
||||
XMPP_NS_TLS, NULL, NULL, NULL);
|
||||
xmpp_send(conn, child);
|
||||
xmpp_stanza_release(child);
|
||||
return 0;
|
||||
@@ -258,18 +255,15 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void conn_handler(xmpp_conn_t *conn,
|
||||
xmpp_conn_event_t status,
|
||||
int error,
|
||||
xmpp_stream_error_t *stream_error,
|
||||
void *userdata)
|
||||
static void conn_handler(xmpp_conn_t * const conn,
|
||||
const xmpp_conn_event_t status,
|
||||
const int error,
|
||||
xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_reg_t *reg = (xmpp_reg_t *)userdata;
|
||||
int secured;
|
||||
|
||||
(void)error;
|
||||
(void)stream_error;
|
||||
|
||||
if (status == XMPP_CONN_RAW_CONNECT) {
|
||||
fprintf(stderr, "DEBUG: raw connection established\n");
|
||||
xmpp_conn_open_stream_default(conn);
|
||||
@@ -280,14 +274,14 @@ static void conn_handler(xmpp_conn_t *conn,
|
||||
secured ? "secured" : "NOT secured");
|
||||
|
||||
/* setup handler for stream:error */
|
||||
xmpp_handler_add(conn, _handle_error, XMPP_NS_STREAMS, "error", NULL,
|
||||
NULL);
|
||||
xmpp_handler_add(conn, _handle_error, XMPP_NS_STREAMS,
|
||||
"error", NULL, NULL);
|
||||
|
||||
/* setup handlers for incoming <stream:features> */
|
||||
xmpp_handler_add(conn, _handle_features, XMPP_NS_STREAMS, "features",
|
||||
NULL, reg);
|
||||
xmpp_timed_handler_add(conn, _handle_missing_features, FEATURES_TIMEOUT,
|
||||
NULL);
|
||||
xmpp_handler_add(conn, _handle_features, XMPP_NS_STREAMS,
|
||||
"features", NULL, reg);
|
||||
xmpp_timed_handler_add(conn, _handle_missing_features,
|
||||
FEATURES_TIMEOUT, NULL);
|
||||
} else {
|
||||
fprintf(stderr, "DEBUG: disconnected\n");
|
||||
xmpp_stop(reg->ctx);
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
|
||||
#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;
|
||||
const char *type, *name;
|
||||
|
||||
(void)userdata;
|
||||
|
||||
type = xmpp_stanza_get_type(stanza);
|
||||
if (strcmp(type, "error") == 0)
|
||||
fprintf(stderr, "ERROR: query failed\n");
|
||||
@@ -34,11 +34,13 @@ int handle_reply(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
for (item = xmpp_stanza_get_children(query); item;
|
||||
item = xmpp_stanza_get_next(item))
|
||||
if ((name = xmpp_stanza_get_attribute(item, "name")))
|
||||
printf("\t %s (%s) sub=%s\n", name,
|
||||
printf("\t %s (%s) sub=%s\n",
|
||||
name,
|
||||
xmpp_stanza_get_attribute(item, "jid"),
|
||||
xmpp_stanza_get_attribute(item, "subscription"));
|
||||
else
|
||||
printf("\t %s sub=%s\n", xmpp_stanza_get_attribute(item, "jid"),
|
||||
printf("\t %s sub=%s\n",
|
||||
xmpp_stanza_get_attribute(item, "jid"),
|
||||
xmpp_stanza_get_attribute(item, "subscription"));
|
||||
printf("END OF LIST\n");
|
||||
}
|
||||
@@ -49,18 +51,13 @@ int handle_reply(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void conn_handler(xmpp_conn_t *conn,
|
||||
xmpp_conn_event_t status,
|
||||
int error,
|
||||
xmpp_stream_error_t *stream_error,
|
||||
void *userdata)
|
||||
void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status,
|
||||
const int error, xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
|
||||
xmpp_stanza_t *iq, *query;
|
||||
|
||||
(void)error;
|
||||
(void)stream_error;
|
||||
|
||||
if (status == XMPP_CONN_CONNECT) {
|
||||
fprintf(stderr, "DEBUG: connected\n");
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <strophe.h>
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
char *uuid;
|
||||
|
||||
@@ -76,8 +76,8 @@ static void vcard_photo(vcard_t *vc, xmpp_stanza_t *stanza)
|
||||
xmpp_free(vc->ctx, img);
|
||||
}
|
||||
|
||||
static void
|
||||
vcard_print_string(vcard_t *vc, xmpp_stanza_t *stanza, const char *info)
|
||||
static void vcard_print_string(vcard_t *vc, xmpp_stanza_t *stanza,
|
||||
const char *info)
|
||||
{
|
||||
char *s = xmpp_stanza_get_text(stanza);
|
||||
|
||||
@@ -140,9 +140,14 @@ static vcard_cb_t vcard_cb_get(xmpp_stanza_t *stanza)
|
||||
const char *tag;
|
||||
vcard_cb_t cb;
|
||||
} vcard_tbl[] = {
|
||||
{"PHOTO", vcard_photo}, {"BDAY", vcard_bday}, {"DESC", vcard_desc},
|
||||
{"EMAIL", vcard_email}, {"FN", vcard_fn}, {"N", vcard_name},
|
||||
{"NICKNAME", vcard_nick}, {"URL", vcard_url},
|
||||
{ "PHOTO", vcard_photo },
|
||||
{ "BDAY", vcard_bday },
|
||||
{ "DESC", vcard_desc },
|
||||
{ "EMAIL", vcard_email },
|
||||
{ "FN", vcard_fn },
|
||||
{ "N", vcard_name },
|
||||
{ "NICKNAME", vcard_nick },
|
||||
{ "URL", vcard_url },
|
||||
};
|
||||
|
||||
tag = xmpp_stanza_get_name(stanza);
|
||||
@@ -160,17 +165,16 @@ exit:
|
||||
return cb;
|
||||
}
|
||||
|
||||
static int timedout(xmpp_conn_t *conn, void *userdata)
|
||||
static int timedout(xmpp_conn_t * const conn, void * const userdata)
|
||||
{
|
||||
(void)userdata;
|
||||
|
||||
fprintf(stderr, "Timeout reached.\n");
|
||||
xmpp_disconnect(conn);
|
||||
|
||||
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_cb_t cb;
|
||||
@@ -209,17 +213,16 @@ exit:
|
||||
static void send_vcard_req(xmpp_conn_t *conn, const char *to, const char *id)
|
||||
{
|
||||
printf("Requesting vCard from %s.\n", to);
|
||||
xmpp_send_raw_string(conn,
|
||||
"<iq from='%s' to='%s' type='get' id='%s'>"
|
||||
xmpp_send_raw_string(conn, "<iq from='%s' to='%s' type='get' id='%s'>"
|
||||
"<vCard xmlns='vcard-temp'/></iq>",
|
||||
xmpp_conn_get_bound_jid(conn), to, id);
|
||||
}
|
||||
|
||||
static void conn_handler(xmpp_conn_t *conn,
|
||||
xmpp_conn_event_t status,
|
||||
int error,
|
||||
xmpp_stream_error_t *stream_error,
|
||||
void *userdata)
|
||||
static void conn_handler(xmpp_conn_t * const conn,
|
||||
const xmpp_conn_event_t status,
|
||||
const int error,
|
||||
xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata)
|
||||
{
|
||||
vcard_t *vc = userdata;
|
||||
|
||||
@@ -250,8 +253,7 @@ int main(int argc, char **argv)
|
||||
if (argc < 4 || argc > 5) {
|
||||
prog = argc > 0 ? strdup(argv[0]) : NULL;
|
||||
printf("Usage: %s <login-jid> <password> <recipient-jid> "
|
||||
"[image-file]\n\n",
|
||||
prog == NULL ? "vcard" : basename(prog));
|
||||
"[image-file]\n\n", prog == NULL ? "vcard" : basename(prog));
|
||||
printf("If vCard contains a photo it will be stored to "
|
||||
"image-file. If you don't provide the image-file "
|
||||
"default filename will be generated.\n");
|
||||
@@ -279,3 +281,4 @@ int main(int argc, char **argv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libstrophe
|
||||
LOCAL_CFLAGS := -DHAVE_DECL_VA_COPY
|
||||
LOCAL_CFLAGS :=
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/.. \
|
||||
$(LOCAL_PATH)/../src \
|
||||
@@ -45,8 +45,6 @@ LOCAL_SRC_FILES := \
|
||||
../src/sasl.c \
|
||||
../src/scram.c \
|
||||
../src/sha1.c \
|
||||
../src/sha256.c \
|
||||
../src/sha512.c \
|
||||
../src/snprintf.c \
|
||||
../src/sock.c \
|
||||
../src/stanza.c \
|
||||
|
||||
31
rpm/README
Normal file
31
rpm/README
Normal file
@@ -0,0 +1,31 @@
|
||||
1. Setup
|
||||
|
||||
yum install gcc make autoconf automake expat-devel openssl-devel
|
||||
|
||||
Fedora:
|
||||
|
||||
yum install fedora-packager
|
||||
cd ~
|
||||
rpmdev-setuptree
|
||||
|
||||
CentOS:
|
||||
|
||||
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
|
||||
|
||||
Then make a tarball of sources:
|
||||
|
||||
tar czf libstrophe_git.tar.gz libstrophe
|
||||
|
||||
2. Build
|
||||
|
||||
cp libstrophe.spec ~/rpmbuild/SPECS
|
||||
cp libstrophe_git.tar.gz ~/rpmbuild/SOURCES
|
||||
rpmbuild -bb ~/rpmbuild/SPECS/libstrophe.spec
|
||||
|
||||
3. Install
|
||||
|
||||
yum localinstall ~/rpmbuild/RPMS/<arch>/libstrophe-1.1<dist>.<arch>.rpm
|
||||
|
||||
Or, if localinstall is not recognised:
|
||||
|
||||
rpm -i ~/rpmbuild/RPMS/<arch>/libstrophe-1.1<dist>.<arch>.rpm
|
||||
59
rpm/libstrophe.spec
Normal file
59
rpm/libstrophe.spec
Normal file
@@ -0,0 +1,59 @@
|
||||
Name: libstrophe
|
||||
Version: 1
|
||||
Release: 1%{?dist}_git
|
||||
Summary: xmpp library in C
|
||||
|
||||
Group: Application/System
|
||||
License: MIT/GPLv3
|
||||
URL: http://strophe.im/libstrophe/
|
||||
Source0: libstrophe_git.tar.gz
|
||||
|
||||
BuildRequires: autoconf
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
BuildRequires: openssl-devel
|
||||
BuildRequires: expat-devel
|
||||
Requires: openssl
|
||||
Requires: expat
|
||||
|
||||
%description
|
||||
XMPP library in C
|
||||
|
||||
%package devel
|
||||
Summary: Headers and libraries for building apps that use libstrophe
|
||||
Group: Development/Libraries
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
%description devel
|
||||
This package contains headers and libraries required to build applications that
|
||||
use the strophe XMPP library.
|
||||
|
||||
%prep
|
||||
%setup -n libstrophe
|
||||
./bootstrap.sh
|
||||
|
||||
%build
|
||||
%configure
|
||||
make %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
make install DESTDIR=%{buildroot}
|
||||
|
||||
%post -p /sbin/ldconfig
|
||||
|
||||
%postun -p /sbin/ldconfig
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/libstrophe.so*
|
||||
%doc
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root,-)
|
||||
%{_libdir}/libstrophe.a
|
||||
%{_libdir}/libstrophe.la
|
||||
%{_libdir}/pkgconfig/libstrophe.pc
|
||||
%{_includedir}/strophe.h
|
||||
%doc
|
||||
|
||||
%changelog
|
||||
494
src/auth.c
494
src/auth.c
@@ -60,49 +60,59 @@
|
||||
#define HANDSHAKE_TIMEOUT 15000 /* 15 seconds */
|
||||
#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 _handle_open_sasl(xmpp_conn_t *conn);
|
||||
static void _handle_open_tls(xmpp_conn_t *conn);
|
||||
static void _handle_open_sasl(xmpp_conn_t * const conn);
|
||||
static void _handle_open_tls(xmpp_conn_t * const conn);
|
||||
|
||||
static int _handle_component_auth(xmpp_conn_t *conn);
|
||||
static int _handle_component_hs_response(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata);
|
||||
static int _handle_component_auth(xmpp_conn_t * const conn);
|
||||
static int _handle_component_hs_response(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
|
||||
static int
|
||||
_handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata);
|
||||
static int
|
||||
_handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata);
|
||||
static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata);
|
||||
static int _handle_digestmd5_rspauth(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata);
|
||||
static int _handle_scram_challenge(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata);
|
||||
static char *_make_scram_init_msg(xmpp_conn_t *conn);
|
||||
static int _handle_features_sasl(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
static int _handle_sasl_result(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
static int _handle_digestmd5_challenge(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
static int _handle_scram_sha1_challenge(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
static char *_make_scram_sha1_init_msg(xmpp_conn_t * const conn);
|
||||
|
||||
static int _handle_missing_features_sasl(xmpp_conn_t *conn, void *userdata);
|
||||
static int _handle_missing_bind(xmpp_conn_t *conn, void *userdata);
|
||||
static int
|
||||
_handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata);
|
||||
static int
|
||||
_handle_session(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata);
|
||||
static int _handle_missing_session(xmpp_conn_t *conn, void *userdata);
|
||||
static int _handle_missing_handshake(xmpp_conn_t *conn, void *userdata);
|
||||
static int _handle_missing_features_sasl(xmpp_conn_t * const conn,
|
||||
void * const userdata);
|
||||
static int _handle_missing_bind(xmpp_conn_t * const conn,
|
||||
void * const userdata);
|
||||
static int _handle_bind(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
static int _handle_session(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
static int _handle_missing_session(xmpp_conn_t * const conn,
|
||||
void * const userdata);
|
||||
static int _handle_sm(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
static int _handle_missing_handshake(xmpp_conn_t * const conn,
|
||||
void * const userdata);
|
||||
|
||||
/* stream:error handler */
|
||||
static int
|
||||
_handle_error(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
static int _handle_error(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_stanza_t *child;
|
||||
const char *name;
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
/* free old stream error if it's still there */
|
||||
if (conn->stream_error) {
|
||||
xmpp_stanza_release(conn->stream_error->stanza);
|
||||
@@ -112,8 +122,7 @@ _handle_error(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
}
|
||||
|
||||
/* create stream error structure */
|
||||
conn->stream_error = (xmpp_stream_error_t *)xmpp_alloc(
|
||||
conn->ctx, sizeof(xmpp_stream_error_t));
|
||||
conn->stream_error = (xmpp_stream_error_t *)xmpp_alloc(conn->ctx, sizeof(xmpp_stream_error_t));
|
||||
|
||||
conn->stream_error->text = NULL;
|
||||
conn->stream_error->type = XMPP_SE_UNDEFINED_CONDITION;
|
||||
@@ -191,10 +200,9 @@ _handle_error(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
xmpp_debug(conn->ctx, "xmpp", "didn't get stream features");
|
||||
|
||||
/* legacy auth will be attempted */
|
||||
@@ -203,15 +211,16 @@ static int _handle_missing_features(xmpp_conn_t *conn, void *userdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
|
||||
|
||||
static int _handle_features(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_stanza_t *child, *mech;
|
||||
const char *ns;
|
||||
char *text;
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
/* remove the handler that detects missing stream:features */
|
||||
xmpp_timed_handler_delete(conn, _handle_missing_features);
|
||||
|
||||
@@ -234,25 +243,17 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
if (child && ns && strcmp(ns, XMPP_NS_SASL) == 0) {
|
||||
for (mech = xmpp_stanza_get_children(child); mech;
|
||||
mech = xmpp_stanza_get_next(mech)) {
|
||||
if (xmpp_stanza_get_name(mech) &&
|
||||
strcmp(xmpp_stanza_get_name(mech), "mechanism") == 0) {
|
||||
if (xmpp_stanza_get_name(mech) && strcmp(xmpp_stanza_get_name(mech), "mechanism") == 0) {
|
||||
text = xmpp_stanza_get_text(mech);
|
||||
if (text == NULL)
|
||||
continue;
|
||||
|
||||
if (strcasecmp(text, "PLAIN") == 0)
|
||||
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)
|
||||
conn->sasl_support |= SASL_MASK_DIGESTMD5;
|
||||
else if (strcasecmp(text, "SCRAM-SHA-1") == 0)
|
||||
conn->sasl_support |= SASL_MASK_SCRAMSHA1;
|
||||
else if (strcasecmp(text, "SCRAM-SHA-256") == 0)
|
||||
conn->sasl_support |= SASL_MASK_SCRAMSHA256;
|
||||
else if (strcasecmp(text, "SCRAM-SHA-512") == 0)
|
||||
conn->sasl_support |= SASL_MASK_SCRAMSHA512;
|
||||
else if (strcasecmp(text, "ANONYMOUS") == 0)
|
||||
conn->sasl_support |= SASL_MASK_ANONYMOUS;
|
||||
|
||||
@@ -272,28 +273,25 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
|
||||
/* returns the correct auth id for a component or a client.
|
||||
* 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;
|
||||
|
||||
if (conn->type == XMPP_CLIENT) {
|
||||
/* authid is the node portion of jid */
|
||||
if (!conn->jid)
|
||||
return NULL;
|
||||
if (!conn->jid) return NULL;
|
||||
authid = xmpp_jid_node(conn->ctx, conn->jid);
|
||||
}
|
||||
|
||||
return authid;
|
||||
}
|
||||
|
||||
static int _handle_proceedtls_default(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata)
|
||||
static int _handle_proceedtls_default(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
name = xmpp_stanza_get_name(stanza);
|
||||
xmpp_debug(conn->ctx, "xmpp", "handle proceedtls called for %s", name);
|
||||
|
||||
@@ -312,8 +310,9 @@ static int _handle_proceedtls_default(xmpp_conn_t *conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
static int _handle_sasl_result(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
@@ -321,7 +320,8 @@ _handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
|
||||
/* the server should send a <success> or <failure> stanza */
|
||||
if (strcmp(name, "failure") == 0) {
|
||||
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth failed", (char *)userdata);
|
||||
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth failed",
|
||||
(char *)userdata);
|
||||
|
||||
/* fall back to next auth method */
|
||||
_auth(conn);
|
||||
@@ -337,9 +337,8 @@ _handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
conn_open_stream(conn);
|
||||
} else {
|
||||
/* got unexpected reply */
|
||||
xmpp_error(conn->ctx, "xmpp",
|
||||
"Got unexpected reply to SASL %s authentication.",
|
||||
(char *)userdata);
|
||||
xmpp_error(conn->ctx, "xmpp", "Got unexpected reply to SASL %s"\
|
||||
"authentication.", (char *)userdata);
|
||||
xmpp_disconnect(conn);
|
||||
}
|
||||
|
||||
@@ -347,20 +346,18 @@ _handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
}
|
||||
|
||||
/* handle the challenge phase of digest auth */
|
||||
static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata)
|
||||
static int _handle_digestmd5_challenge(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
char *text;
|
||||
char *response;
|
||||
xmpp_stanza_t *auth, *authdata;
|
||||
const char *name;
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
name = xmpp_stanza_get_name(stanza);
|
||||
xmpp_debug(conn->ctx, "xmpp", "handle digest-md5 (challenge) called for %s",
|
||||
name);
|
||||
xmpp_debug(conn->ctx, "xmpp",\
|
||||
"handle digest-md5 (challenge) called for %s", name);
|
||||
|
||||
if (strcmp(name, "challenge") == 0) {
|
||||
text = xmpp_stanza_get_text(stanza);
|
||||
@@ -391,8 +388,8 @@ static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
|
||||
xmpp_stanza_add_child(auth, authdata);
|
||||
xmpp_stanza_release(authdata);
|
||||
|
||||
handler_add(conn, _handle_digestmd5_rspauth, XMPP_NS_SASL, NULL, NULL,
|
||||
NULL);
|
||||
handler_add(conn, _handle_digestmd5_rspauth,
|
||||
XMPP_NS_SASL, NULL, NULL, NULL);
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
xmpp_stanza_release(auth);
|
||||
@@ -406,18 +403,17 @@ static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
|
||||
}
|
||||
|
||||
/* handle the rspauth phase of digest auth */
|
||||
static int _handle_digestmd5_rspauth(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata)
|
||||
static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_stanza_t *auth;
|
||||
const char *name;
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
name = xmpp_stanza_get_name(stanza);
|
||||
xmpp_debug(conn->ctx, "xmpp", "handle digest-md5 (rspauth) called for %s",
|
||||
name);
|
||||
xmpp_debug(conn->ctx, "xmpp",
|
||||
"handle digest-md5 (rspauth) called for %s", name);
|
||||
|
||||
|
||||
if (strcmp(name, "challenge") == 0) {
|
||||
/* assume it's an rspauth response */
|
||||
@@ -437,28 +433,21 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t *conn,
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct scram_user_data {
|
||||
char *scram_init;
|
||||
const struct hash_alg *alg;
|
||||
};
|
||||
|
||||
/* handle the challenge phase of SCRAM-SHA-1 auth */
|
||||
static int _handle_scram_challenge(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata)
|
||||
static int _handle_scram_sha1_challenge(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
char *text;
|
||||
char *response;
|
||||
xmpp_stanza_t *auth;
|
||||
xmpp_stanza_t *authdata;
|
||||
xmpp_stanza_t *auth, *authdata;
|
||||
const char *name;
|
||||
char *challenge;
|
||||
struct scram_user_data *scram_ctx = (struct scram_user_data *)userdata;
|
||||
int rc;
|
||||
char *scram_init = (char *)userdata;
|
||||
|
||||
name = xmpp_stanza_get_name(stanza);
|
||||
xmpp_debug(conn->ctx, "xmpp", "handle %s (challenge) called for %s",
|
||||
scram_ctx->alg->scram_name, name);
|
||||
xmpp_debug(conn->ctx, "xmpp",
|
||||
"handle SCRAM-SHA-1 (challenge) called for %s", name);
|
||||
|
||||
if (strcmp(name, "challenge") == 0) {
|
||||
text = xmpp_stanza_get_text(stanza);
|
||||
@@ -470,8 +459,8 @@ static int _handle_scram_challenge(xmpp_conn_t *conn,
|
||||
if (!challenge)
|
||||
goto err;
|
||||
|
||||
response = sasl_scram(conn->ctx, scram_ctx->alg, challenge,
|
||||
scram_ctx->scram_init, conn->jid, conn->pass);
|
||||
response = sasl_scram_sha1(conn->ctx, challenge, scram_init,
|
||||
conn->jid, conn->pass);
|
||||
xmpp_free(conn->ctx, challenge);
|
||||
if (!response)
|
||||
goto err;
|
||||
@@ -494,37 +483,24 @@ static int _handle_scram_challenge(xmpp_conn_t *conn,
|
||||
xmpp_send(conn, auth);
|
||||
xmpp_stanza_release(auth);
|
||||
|
||||
rc = 1; /* Keep handler */
|
||||
} else {
|
||||
/*
|
||||
* Free scram_ctx after calling _handle_sasl_result(). If authentication
|
||||
* fails, we want to try other mechanism which may be different SCRAM
|
||||
* mechanism. If we freed scram_ctx before the function, _auth() would
|
||||
* be able to allocate new scram_ctx object with the same address and
|
||||
* handler_add() would consider new SCRAM handler as duplicate, because
|
||||
* current handler is not removed yet. As result, libstrophe wouldn't
|
||||
* handle incoming challenge stanza.
|
||||
*/
|
||||
rc = _handle_sasl_result(conn, stanza,
|
||||
(void *)scram_ctx->alg->scram_name);
|
||||
xmpp_free(conn->ctx, scram_ctx->scram_init);
|
||||
xmpp_free(conn->ctx, scram_ctx);
|
||||
xmpp_free(conn->ctx, scram_init);
|
||||
return _handle_sasl_result(conn, stanza, "SCRAM-SHA-1");
|
||||
}
|
||||
|
||||
return rc;
|
||||
return 1;
|
||||
|
||||
err_release_auth:
|
||||
xmpp_stanza_release(auth);
|
||||
err_free_response:
|
||||
xmpp_free(conn->ctx, response);
|
||||
err:
|
||||
xmpp_free(conn->ctx, scram_ctx->scram_init);
|
||||
xmpp_free(conn->ctx, scram_ctx);
|
||||
xmpp_free(conn->ctx, scram_init);
|
||||
disconnect_mem_error(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *_make_scram_init_msg(xmpp_conn_t *conn)
|
||||
static char *_make_scram_sha1_init_msg(xmpp_conn_t * const conn)
|
||||
{
|
||||
xmpp_ctx_t *ctx = conn->ctx;
|
||||
size_t message_len;
|
||||
@@ -547,7 +523,7 @@ static char *_make_scram_init_msg(xmpp_conn_t *conn)
|
||||
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;
|
||||
|
||||
@@ -561,7 +537,8 @@ static xmpp_stanza_t *_make_starttls(xmpp_conn_t *conn)
|
||||
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;
|
||||
|
||||
@@ -581,12 +558,12 @@ 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
|
||||
* method fails
|
||||
*/
|
||||
static void _auth(xmpp_conn_t *conn)
|
||||
static void _auth(xmpp_conn_t * const conn)
|
||||
{
|
||||
xmpp_stanza_t *auth;
|
||||
xmpp_stanza_t *authdata;
|
||||
struct scram_user_data *scram_ctx;
|
||||
char *authid;
|
||||
char *scram_init;
|
||||
char *str;
|
||||
int anonjid;
|
||||
|
||||
@@ -618,8 +595,8 @@ static void _auth(xmpp_conn_t *conn)
|
||||
return;
|
||||
}
|
||||
|
||||
handler_add(conn, _handle_proceedtls_default, XMPP_NS_TLS, NULL, NULL,
|
||||
NULL);
|
||||
handler_add(conn, _handle_proceedtls_default,
|
||||
XMPP_NS_TLS, NULL, NULL, NULL);
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
xmpp_stanza_release(auth);
|
||||
@@ -631,8 +608,7 @@ static void _auth(xmpp_conn_t *conn)
|
||||
}
|
||||
|
||||
if (conn->tls_mandatory && !xmpp_conn_is_secured(conn)) {
|
||||
xmpp_error(conn->ctx, "xmpp",
|
||||
"TLS is not supported, but set as "
|
||||
xmpp_error(conn->ctx, "xmpp", "TLS is not supported, but set as "
|
||||
"mandatory for this connection");
|
||||
conn_disconnect(conn);
|
||||
return;
|
||||
@@ -646,94 +622,37 @@ static void _auth(xmpp_conn_t *conn)
|
||||
return;
|
||||
}
|
||||
|
||||
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL,
|
||||
"ANONYMOUS");
|
||||
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL,
|
||||
NULL, NULL, "ANONYMOUS");
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
xmpp_stanza_release(auth);
|
||||
|
||||
/* SASL ANONYMOUS was tried, unset flag */
|
||||
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) {
|
||||
xmpp_error(conn->ctx, "auth",
|
||||
"No node in JID, and SASL ANONYMOUS unsupported.");
|
||||
xmpp_disconnect(conn);
|
||||
} 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) {
|
||||
scram_ctx = xmpp_alloc(conn->ctx, sizeof(*scram_ctx));
|
||||
if (conn->sasl_support & SASL_MASK_SCRAMSHA512)
|
||||
scram_ctx->alg = &scram_sha512;
|
||||
else if (conn->sasl_support & SASL_MASK_SCRAMSHA256)
|
||||
scram_ctx->alg = &scram_sha256;
|
||||
else if (conn->sasl_support & SASL_MASK_SCRAMSHA1)
|
||||
scram_ctx->alg = &scram_sha1;
|
||||
auth = _make_sasl_auth(conn, scram_ctx->alg->scram_name);
|
||||
} else if (conn->sasl_support & SASL_MASK_SCRAMSHA1) {
|
||||
auth = _make_sasl_auth(conn, "SCRAM-SHA-1");
|
||||
if (!auth) {
|
||||
disconnect_mem_error(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't free scram_init on success */
|
||||
scram_ctx->scram_init = _make_scram_init_msg(conn);
|
||||
if (!scram_ctx->scram_init) {
|
||||
xmpp_free(conn->ctx, scram_ctx);
|
||||
scram_init = _make_scram_sha1_init_msg(conn);
|
||||
if (!scram_init) {
|
||||
xmpp_stanza_release(auth);
|
||||
disconnect_mem_error(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
str = xmpp_base64_encode(conn->ctx,
|
||||
(unsigned char *)scram_ctx->scram_init,
|
||||
strlen(scram_ctx->scram_init));
|
||||
str = xmpp_base64_encode(conn->ctx, (unsigned char *)scram_init,
|
||||
strlen(scram_init));
|
||||
if (!str) {
|
||||
xmpp_free(conn->ctx, scram_ctx->scram_init);
|
||||
xmpp_free(conn->ctx, scram_ctx);
|
||||
xmpp_free(conn->ctx, scram_init);
|
||||
xmpp_stanza_release(auth);
|
||||
disconnect_mem_error(conn);
|
||||
return;
|
||||
@@ -742,8 +661,7 @@ static void _auth(xmpp_conn_t *conn)
|
||||
authdata = xmpp_stanza_new(conn->ctx);
|
||||
if (!authdata) {
|
||||
xmpp_free(conn->ctx, str);
|
||||
xmpp_free(conn->ctx, scram_ctx->scram_init);
|
||||
xmpp_free(conn->ctx, scram_ctx);
|
||||
xmpp_free(conn->ctx, scram_init);
|
||||
xmpp_stanza_release(auth);
|
||||
disconnect_mem_error(conn);
|
||||
return;
|
||||
@@ -753,23 +671,24 @@ static void _auth(xmpp_conn_t *conn)
|
||||
xmpp_stanza_add_child(auth, authdata);
|
||||
xmpp_stanza_release(authdata);
|
||||
|
||||
handler_add(conn, _handle_scram_challenge, XMPP_NS_SASL, NULL, NULL,
|
||||
(void *)scram_ctx);
|
||||
handler_add(conn, _handle_scram_sha1_challenge,
|
||||
XMPP_NS_SASL, NULL, NULL, (void *)scram_init);
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
xmpp_stanza_release(auth);
|
||||
|
||||
/* SASL SCRAM-SHA-1 was tried, unset flag */
|
||||
conn->sasl_support &= ~scram_ctx->alg->mask;
|
||||
conn->sasl_support &= ~SASL_MASK_SCRAMSHA1;
|
||||
} else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
|
||||
auth = _make_sasl_auth(conn, "DIGEST-MD5");
|
||||
if (!auth) {
|
||||
disconnect_mem_error(conn);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
handler_add(conn, _handle_digestmd5_challenge, XMPP_NS_SASL, NULL, NULL,
|
||||
NULL);
|
||||
handler_add(conn, _handle_digestmd5_challenge,
|
||||
XMPP_NS_SASL, NULL, NULL, NULL);
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
xmpp_stanza_release(auth);
|
||||
@@ -804,8 +723,8 @@ static void _auth(xmpp_conn_t *conn)
|
||||
xmpp_stanza_add_child(auth, authdata);
|
||||
xmpp_stanza_release(authdata);
|
||||
|
||||
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL,
|
||||
"PLAIN");
|
||||
handler_add(conn, _handle_sasl_result,
|
||||
XMPP_NS_SASL, NULL, NULL, "PLAIN");
|
||||
|
||||
xmpp_send(conn, auth);
|
||||
xmpp_stanza_release(auth);
|
||||
@@ -821,6 +740,7 @@ static void _auth(xmpp_conn_t *conn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Set up handlers at stream start.
|
||||
* This function is called internally to Strophe for handling the opening
|
||||
* of an XMPP stream. It's called by the parser when a stream is opened
|
||||
@@ -830,7 +750,7 @@ static void _auth(xmpp_conn_t *conn)
|
||||
*
|
||||
* @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 */
|
||||
handler_reset_timed(conn, 0);
|
||||
@@ -840,41 +760,40 @@ void auth_handle_open(xmpp_conn_t *conn)
|
||||
handler_add(conn, _handle_error, XMPP_NS_STREAMS, "error", NULL, NULL);
|
||||
|
||||
/* setup handlers for incoming <stream:features> */
|
||||
handler_add(conn, _handle_features, XMPP_NS_STREAMS, "features", NULL,
|
||||
NULL);
|
||||
handler_add(conn, _handle_features,
|
||||
XMPP_NS_STREAMS, "features", NULL, NULL);
|
||||
handler_add_timed(conn, _handle_missing_features, FEATURES_TIMEOUT, NULL);
|
||||
}
|
||||
|
||||
/* 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> */
|
||||
handler_add(conn, _handle_features, XMPP_NS_STREAMS, "features", NULL,
|
||||
NULL);
|
||||
handler_add(conn, _handle_features,
|
||||
XMPP_NS_STREAMS, "features", NULL, NULL);
|
||||
handler_add_timed(conn, _handle_missing_features, FEATURES_TIMEOUT, NULL);
|
||||
}
|
||||
|
||||
/* 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.");
|
||||
|
||||
/* setup stream:features handlers */
|
||||
handler_add(conn, _handle_features_sasl, XMPP_NS_STREAMS, "features", NULL,
|
||||
NULL);
|
||||
handler_add_timed(conn, _handle_missing_features_sasl, FEATURES_TIMEOUT,
|
||||
NULL);
|
||||
handler_add(conn, _handle_features_sasl,
|
||||
XMPP_NS_STREAMS, "features", NULL, NULL);
|
||||
handler_add_timed(conn, _handle_missing_features_sasl,
|
||||
FEATURES_TIMEOUT, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
static int _handle_features_sasl(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
xmpp_stanza_t *bind, *session, *iq, *res, *text, *opt;
|
||||
const char *ns;
|
||||
char *resource;
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
/* remove missing features handler */
|
||||
xmpp_timed_handler_delete(conn, _handle_missing_features_sasl);
|
||||
|
||||
@@ -894,8 +813,14 @@ _handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
ns = xmpp_stanza_get_ns(session);
|
||||
opt = xmpp_stanza_get_child_by_name(session, "optional");
|
||||
if (!opt)
|
||||
conn->session_required =
|
||||
ns != NULL && strcmp(ns, XMPP_NS_SESSION) == 0;
|
||||
conn->session_required = ns != NULL &&
|
||||
strcmp(ns, XMPP_NS_SESSION) == 0;
|
||||
}
|
||||
|
||||
opt = xmpp_stanza_get_child_by_ns(stanza, XMPP_NS_SM);
|
||||
if (opt && strcmp(xmpp_stanza_get_name(opt), "sm") == 0) {
|
||||
/* stream management supported */
|
||||
conn->sm_support = 1;
|
||||
}
|
||||
|
||||
/* if bind is required, go ahead and start it */
|
||||
@@ -904,7 +829,8 @@ _handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
|
||||
/* setup response handlers */
|
||||
handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL);
|
||||
handler_add_timed(conn, _handle_missing_bind, BIND_TIMEOUT, NULL);
|
||||
handler_add_timed(conn, _handle_missing_bind,
|
||||
BIND_TIMEOUT, NULL);
|
||||
|
||||
/* send bind request */
|
||||
iq = xmpp_iq_new(conn->ctx, "set", "_xmpp_bind1");
|
||||
@@ -963,8 +889,7 @@ _handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
xmpp_stanza_release(iq);
|
||||
} else {
|
||||
/* can't bind, disconnect */
|
||||
xmpp_error(conn->ctx, "xmpp",
|
||||
"Stream features does not allow "
|
||||
xmpp_error(conn->ctx, "xmpp", "Stream features does not allow "\
|
||||
"resource bind.");
|
||||
xmpp_disconnect(conn);
|
||||
}
|
||||
@@ -972,24 +897,21 @@ _handle_features_sasl(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
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);
|
||||
|
||||
xmpp_error(conn->ctx, "xmpp",
|
||||
"Did not receive stream features "
|
||||
xmpp_error(conn->ctx, "xmpp", "Did not receive stream features "\
|
||||
"after SASL authentication.");
|
||||
xmpp_disconnect(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
static int _handle_bind(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
const char *type;
|
||||
xmpp_stanza_t *iq, *session;
|
||||
|
||||
UNUSED(userdata);
|
||||
xmpp_stanza_t *iq, *enable, *session, *binding, *jid_stanza;
|
||||
|
||||
/* delete missing bind handler */
|
||||
xmpp_timed_handler_delete(conn, _handle_missing_bind);
|
||||
@@ -1000,12 +922,11 @@ _handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
xmpp_error(conn->ctx, "xmpp", "Binding failed.");
|
||||
xmpp_disconnect(conn);
|
||||
} else if (type && strcmp(type, "result") == 0) {
|
||||
xmpp_stanza_t *binding = xmpp_stanza_get_child_by_name(stanza, "bind");
|
||||
binding = xmpp_stanza_get_child_by_name(stanza, "bind");
|
||||
xmpp_debug(conn->ctx, "xmpp", "Bind successful.");
|
||||
|
||||
if (binding) {
|
||||
xmpp_stanza_t *jid_stanza =
|
||||
xmpp_stanza_get_child_by_name(binding, "jid");
|
||||
jid_stanza = xmpp_stanza_get_child_by_name(binding, "jid");
|
||||
if (jid_stanza) {
|
||||
conn->bound_jid = xmpp_stanza_get_text(jid_stanza);
|
||||
}
|
||||
@@ -1015,8 +936,8 @@ _handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
if (conn->session_required) {
|
||||
/* setup response handlers */
|
||||
handler_add_id(conn, _handle_session, "_xmpp_session1", NULL);
|
||||
handler_add_timed(conn, _handle_missing_session, SESSION_TIMEOUT,
|
||||
NULL);
|
||||
handler_add_timed(conn, _handle_missing_session,
|
||||
SESSION_TIMEOUT, NULL);
|
||||
|
||||
/* send session request */
|
||||
iq = xmpp_iq_new(conn->ctx, "set", "_xmpp_session1");
|
||||
@@ -1041,7 +962,23 @@ _handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
/* send session establishment request */
|
||||
xmpp_send(conn, iq);
|
||||
xmpp_stanza_release(iq);
|
||||
} else {
|
||||
}
|
||||
|
||||
if (conn->sm_support) {
|
||||
enable = xmpp_stanza_new(conn->ctx);
|
||||
if (!enable) {
|
||||
disconnect_mem_error(conn);
|
||||
return 0;
|
||||
}
|
||||
xmpp_stanza_set_name(enable, "enable");
|
||||
xmpp_stanza_set_ns(enable, XMPP_NS_SM);
|
||||
handler_add(conn, _handle_sm, XMPP_NS_SM, NULL, NULL, NULL);
|
||||
xmpp_send(conn, enable);
|
||||
xmpp_stanza_release(enable);
|
||||
conn->sm_sent_nr = 0;
|
||||
}
|
||||
|
||||
if (!conn->session_required) {
|
||||
conn->authenticated = 1;
|
||||
|
||||
/* call connection handler */
|
||||
@@ -1056,22 +993,20 @@ _handle_bind(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
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);
|
||||
|
||||
xmpp_error(conn->ctx, "xmpp", "Server did not reply to bind request.");
|
||||
xmpp_disconnect(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_session(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
static int _handle_session(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
const char *type;
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
/* delete missing session handler */
|
||||
xmpp_timed_handler_delete(conn, _handle_missing_session);
|
||||
|
||||
@@ -1095,34 +1030,47 @@ _handle_session(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
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);
|
||||
|
||||
xmpp_error(conn->ctx, "xmpp", "Server did not reply to session request.");
|
||||
xmpp_disconnect(conn);
|
||||
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);
|
||||
|
||||
xmpp_error(conn->ctx, "xmpp",
|
||||
"Server did not reply to legacy "
|
||||
xmpp_error(conn->ctx, "xmpp", "Server did not reply to legacy "\
|
||||
"authentication request.");
|
||||
xmpp_disconnect(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_handle_legacy(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
static int _handle_sm(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
name = xmpp_stanza_get_name(stanza);
|
||||
if (name && strcmp(name, "enabled") == 0) {
|
||||
conn->sm_enabled = 1;
|
||||
conn->sm_handled_nr = 0;
|
||||
} else {
|
||||
conn->sm_enabled = 0;
|
||||
xmpp_warn(conn->ctx, "auth", "Stream management failed.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _handle_legacy(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
const char *type;
|
||||
const char *name;
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
/* delete missing handler */
|
||||
xmpp_timed_handler_delete(conn, _handle_missing_legacy);
|
||||
|
||||
@@ -1130,8 +1078,7 @@ _handle_legacy(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
type = xmpp_stanza_get_type(stanza);
|
||||
name = xmpp_stanza_get_name(stanza);
|
||||
if (!type || strcmp(name, "iq") != 0) {
|
||||
xmpp_error(conn->ctx, "xmpp",
|
||||
"Server sent us an unexpected response "
|
||||
xmpp_error(conn->ctx, "xmpp", "Server sent us an unexpected response "\
|
||||
"to legacy authentication request.");
|
||||
xmpp_disconnect(conn);
|
||||
} else if (strcmp(type, "error") == 0) {
|
||||
@@ -1145,8 +1092,7 @@ _handle_legacy(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
|
||||
conn->authenticated = 1;
|
||||
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
|
||||
} else {
|
||||
xmpp_error(conn->ctx, "xmpp",
|
||||
"Server sent us a legacy authentication "
|
||||
xmpp_error(conn->ctx, "xmpp", "Server sent us a legacy authentication "\
|
||||
"response with a bad type.");
|
||||
xmpp_disconnect(conn);
|
||||
}
|
||||
@@ -1247,7 +1193,7 @@ err:
|
||||
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;
|
||||
|
||||
@@ -1255,8 +1201,8 @@ void auth_handle_component_open(xmpp_conn_t *conn)
|
||||
handler_reset_timed(conn, 0);
|
||||
|
||||
handler_add(conn, _handle_error, XMPP_NS_STREAMS, "error", NULL, NULL);
|
||||
handler_add(conn, _handle_component_hs_response, NULL, "handshake", NULL,
|
||||
NULL);
|
||||
handler_add(conn, _handle_component_hs_response, NULL,
|
||||
"handshake", NULL, NULL);
|
||||
handler_add_timed(conn, _handle_missing_handshake, HANDSHAKE_TIMEOUT, NULL);
|
||||
|
||||
rc = _handle_component_auth(conn);
|
||||
@@ -1267,7 +1213,7 @@ void auth_handle_component_open(xmpp_conn_t *conn)
|
||||
}
|
||||
|
||||
/* 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];
|
||||
SHA1_CTX mdctx;
|
||||
@@ -1295,18 +1241,16 @@ int _handle_component_auth(xmpp_conn_t *conn)
|
||||
xmpp_snprintf(digest+i*2, 3, "%02x", md_value[i]);
|
||||
digest[2*sizeof(md_value)] = '\0';
|
||||
|
||||
xmpp_debug(conn->ctx, "auth", "Digest: %s, len: %d", digest,
|
||||
strlen(digest));
|
||||
xmpp_debug(conn->ctx, "auth", "Digest: %s, len: %d",
|
||||
digest, strlen(digest));
|
||||
|
||||
/* Send the digest to the server */
|
||||
xmpp_send_raw_string(conn, "<handshake xmlns='%s'>%s</handshake>",
|
||||
XMPP_NS_COMPONENT, digest);
|
||||
xmpp_debug(conn->ctx, "auth",
|
||||
"Sent component handshake to the server.");
|
||||
xmpp_debug(conn->ctx, "auth", "Sent component handshake to the server.");
|
||||
xmpp_free(conn->ctx, digest);
|
||||
} else {
|
||||
xmpp_debug(conn->ctx, "auth",
|
||||
"Couldn't allocate memory for component "
|
||||
xmpp_debug(conn->ctx, "auth", "Couldn't allocate memory for component "\
|
||||
"handshake digest.");
|
||||
return XMPP_EMEM;
|
||||
}
|
||||
@@ -1317,14 +1261,12 @@ int _handle_component_auth(xmpp_conn_t *conn)
|
||||
/* Check if the received stanza is <handshake/> and set auth to true
|
||||
* and fire connection handler.
|
||||
*/
|
||||
int _handle_component_hs_response(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata)
|
||||
int _handle_component_hs_response(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
UNUSED(userdata);
|
||||
|
||||
xmpp_timed_handler_delete(conn, _handle_missing_handshake);
|
||||
|
||||
name = xmpp_stanza_get_name(stanza);
|
||||
@@ -1349,16 +1291,14 @@ int _handle_component_hs_response(xmpp_conn_t *conn,
|
||||
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);
|
||||
|
||||
xmpp_error(conn->ctx, "xmpp", "Server did not reply to handshake request.");
|
||||
xmpp_disconnect(conn);
|
||||
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);
|
||||
/* user handlers are not called before authentication is completed. */
|
||||
@@ -1366,7 +1306,7 @@ void auth_handle_open_raw(xmpp_conn_t *conn)
|
||||
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.");
|
||||
}
|
||||
|
||||
209
src/common.h
209
src/common.h
@@ -19,6 +19,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
#include "strophe.h"
|
||||
#include "ostypes.h"
|
||||
#include "sock.h"
|
||||
@@ -29,7 +30,78 @@
|
||||
#include "rand.h"
|
||||
#include "snprintf.h"
|
||||
|
||||
/** handlers **/
|
||||
/** run-time context **/
|
||||
|
||||
typedef enum {
|
||||
XMPP_LOOP_NOTSTARTED,
|
||||
XMPP_LOOP_RUNNING,
|
||||
XMPP_LOOP_QUIT
|
||||
} xmpp_loop_status_t;
|
||||
|
||||
typedef struct _xmpp_connlist_t {
|
||||
xmpp_conn_t *conn;
|
||||
struct _xmpp_connlist_t *next;
|
||||
} xmpp_connlist_t;
|
||||
|
||||
struct _xmpp_ctx_t {
|
||||
const xmpp_mem_t *mem;
|
||||
const xmpp_log_t *log;
|
||||
|
||||
xmpp_rand_t *rand;
|
||||
xmpp_loop_status_t loop_status;
|
||||
xmpp_connlist_t *connlist;
|
||||
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
|
||||
/* convenience functions for accessing the context */
|
||||
void *xmpp_alloc(const xmpp_ctx_t * const ctx, const 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 * const ctx, const char * const s);
|
||||
|
||||
void xmpp_log(const xmpp_ctx_t * const ctx,
|
||||
const xmpp_log_level_t level,
|
||||
const char * const area,
|
||||
const char * const fmt,
|
||||
va_list ap);
|
||||
|
||||
/* wrappers for xmpp_log at specific levels */
|
||||
void xmpp_error(const xmpp_ctx_t * const ctx,
|
||||
const char * const area,
|
||||
const char * const fmt,
|
||||
...);
|
||||
void xmpp_warn(const xmpp_ctx_t * const ctx,
|
||||
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 **/
|
||||
|
||||
/* opaque connection object */
|
||||
typedef enum {
|
||||
XMPP_STATE_DISCONNECTED,
|
||||
XMPP_STATE_CONNECTING,
|
||||
XMPP_STATE_CONNECTED
|
||||
} xmpp_conn_state_t;
|
||||
|
||||
typedef struct _xmpp_send_queue_t xmpp_send_queue_t;
|
||||
struct _xmpp_send_queue_t {
|
||||
char *data;
|
||||
size_t len;
|
||||
size_t written;
|
||||
|
||||
xmpp_send_queue_t *next;
|
||||
};
|
||||
|
||||
typedef struct _xmpp_handlist_t xmpp_handlist_t;
|
||||
struct _xmpp_handlist_t {
|
||||
@@ -61,84 +133,12 @@ struct _xmpp_handlist_t {
|
||||
} u;
|
||||
};
|
||||
|
||||
/** run-time context **/
|
||||
|
||||
typedef enum {
|
||||
XMPP_LOOP_NOTSTARTED,
|
||||
XMPP_LOOP_RUNNING,
|
||||
XMPP_LOOP_QUIT
|
||||
} xmpp_loop_status_t;
|
||||
|
||||
typedef struct _xmpp_connlist_t {
|
||||
xmpp_conn_t *conn;
|
||||
struct _xmpp_connlist_t *next;
|
||||
} xmpp_connlist_t;
|
||||
|
||||
struct _xmpp_ctx_t {
|
||||
const xmpp_mem_t *mem;
|
||||
const xmpp_log_t *log;
|
||||
int verbosity;
|
||||
|
||||
xmpp_rand_t *rand;
|
||||
xmpp_loop_status_t loop_status;
|
||||
xmpp_connlist_t *connlist;
|
||||
xmpp_handlist_t *timed_handlers;
|
||||
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
/* convenience functions for accessing the context */
|
||||
void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size);
|
||||
void *xmpp_realloc(const xmpp_ctx_t *ctx, void *p, size_t size);
|
||||
char *xmpp_strdup(const xmpp_ctx_t *ctx, const char *s);
|
||||
char *xmpp_strndup(const xmpp_ctx_t *ctx, const char *s, size_t len);
|
||||
|
||||
void xmpp_log(const xmpp_ctx_t *ctx,
|
||||
const xmpp_log_level_t level,
|
||||
const char *area,
|
||||
const char *fmt,
|
||||
va_list ap);
|
||||
|
||||
/* wrappers for xmpp_log at specific levels */
|
||||
void xmpp_error(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...);
|
||||
void xmpp_warn(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...);
|
||||
void xmpp_info(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...);
|
||||
void xmpp_debug(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...);
|
||||
void xmpp_debug_verbose(
|
||||
int level, const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...);
|
||||
|
||||
/** connection **/
|
||||
|
||||
/* opaque connection object */
|
||||
typedef enum {
|
||||
XMPP_STATE_DISCONNECTED,
|
||||
XMPP_STATE_CONNECTING,
|
||||
XMPP_STATE_CONNECTED
|
||||
} xmpp_conn_state_t;
|
||||
|
||||
typedef struct _xmpp_send_queue_t xmpp_send_queue_t;
|
||||
struct _xmpp_send_queue_t {
|
||||
char *data;
|
||||
size_t len;
|
||||
size_t written;
|
||||
|
||||
xmpp_send_queue_t *next;
|
||||
};
|
||||
|
||||
#define UNUSED(x) ((void)(x))
|
||||
|
||||
#define MAX_DOMAIN_LEN 256
|
||||
|
||||
#define SASL_MASK_PLAIN (1 << 0)
|
||||
#define SASL_MASK_DIGESTMD5 (1 << 1)
|
||||
#define SASL_MASK_ANONYMOUS (1 << 2)
|
||||
#define SASL_MASK_SCRAMSHA1 (1 << 3)
|
||||
#define SASL_MASK_SCRAMSHA256 (1 << 4)
|
||||
#define SASL_MASK_SCRAMSHA512 (1 << 5)
|
||||
#define SASL_MASK_EXTERNAL (1 << 6)
|
||||
|
||||
#define SASL_MASK_SCRAM \
|
||||
(SASL_MASK_SCRAMSHA1 | SASL_MASK_SCRAMSHA256 | SASL_MASK_SCRAMSHA512)
|
||||
|
||||
enum {
|
||||
XMPP_PORT_CLIENT = 5222,
|
||||
@@ -146,7 +146,7 @@ enum {
|
||||
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 {
|
||||
unsigned int ref;
|
||||
@@ -169,20 +169,19 @@ struct _xmpp_conn_t {
|
||||
int tls_mandatory;
|
||||
int tls_legacy_ssl;
|
||||
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 sasl_support; /* if true, field is a bitfield of supported
|
||||
mechanisms */
|
||||
int auth_legacy_enabled;
|
||||
int secured; /* set when stream is secured with TLS */
|
||||
xmpp_certfail_handler certfail_handler;
|
||||
|
||||
/* if server returns <bind/> or <session/> we must do them */
|
||||
int bind_required;
|
||||
int session_required;
|
||||
int sm_support;
|
||||
int sm_enabled;
|
||||
uint32_t sm_handled_nr;
|
||||
uint32_t sm_sent_nr;
|
||||
|
||||
char *lang;
|
||||
char *domain;
|
||||
@@ -223,13 +222,14 @@ struct _xmpp_conn_t {
|
||||
xmpp_handlist_t *handlers;
|
||||
};
|
||||
|
||||
void conn_disconnect(xmpp_conn_t *conn);
|
||||
void conn_disconnect_clean(xmpp_conn_t *conn);
|
||||
void conn_established(xmpp_conn_t *conn);
|
||||
void conn_open_stream(xmpp_conn_t *conn);
|
||||
int conn_tls_start(xmpp_conn_t *conn);
|
||||
void conn_prepare_reset(xmpp_conn_t *conn, xmpp_open_handler handler);
|
||||
void conn_parser_reset(xmpp_conn_t *conn);
|
||||
void conn_disconnect(xmpp_conn_t * const conn);
|
||||
void conn_disconnect_clean(xmpp_conn_t * const conn);
|
||||
void conn_established(xmpp_conn_t * const conn);
|
||||
void conn_open_stream(xmpp_conn_t * const conn);
|
||||
int conn_tls_start(xmpp_conn_t * const conn);
|
||||
void conn_prepare_reset(xmpp_conn_t * const conn, xmpp_open_handler handler);
|
||||
void conn_parser_reset(xmpp_conn_t * const conn);
|
||||
|
||||
|
||||
typedef enum {
|
||||
XMPP_STANZA_UNKNOWN,
|
||||
@@ -254,32 +254,33 @@ struct _xmpp_stanza_t {
|
||||
};
|
||||
|
||||
/* handler management */
|
||||
void handler_fire_stanza(xmpp_conn_t *conn, xmpp_stanza_t *stanza);
|
||||
uint64_t handler_fire_timed(xmpp_ctx_t *ctx);
|
||||
void handler_fire_stanza(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza);
|
||||
uint64_t handler_fire_timed(xmpp_ctx_t * const ctx);
|
||||
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,
|
||||
unsigned long period,
|
||||
void *userdata);
|
||||
void handler_add_id(xmpp_conn_t *conn,
|
||||
const unsigned long period,
|
||||
void * const userdata);
|
||||
void handler_add_id(xmpp_conn_t * const conn,
|
||||
xmpp_handler handler,
|
||||
const char *id,
|
||||
void *userdata);
|
||||
void handler_add(xmpp_conn_t *conn,
|
||||
const char * const id,
|
||||
void * const userdata);
|
||||
void handler_add(xmpp_conn_t * const conn,
|
||||
xmpp_handler handler,
|
||||
const char *ns,
|
||||
const char *name,
|
||||
const char *type,
|
||||
void *userdata);
|
||||
const char * const ns,
|
||||
const char * const name,
|
||||
const char * const type,
|
||||
void * const userdata);
|
||||
void handler_system_delete_all(xmpp_conn_t *conn);
|
||||
|
||||
/* utility functions */
|
||||
void disconnect_mem_error(xmpp_conn_t *conn);
|
||||
void disconnect_mem_error(xmpp_conn_t * const conn);
|
||||
|
||||
/* auth functions */
|
||||
void auth_handle_open(xmpp_conn_t *conn);
|
||||
void auth_handle_component_open(xmpp_conn_t *conn);
|
||||
void auth_handle_open_raw(xmpp_conn_t *conn);
|
||||
void auth_handle_open_stub(xmpp_conn_t *conn);
|
||||
void auth_handle_open(xmpp_conn_t * const conn);
|
||||
void auth_handle_component_open(xmpp_conn_t * const conn);
|
||||
void auth_handle_open_raw(xmpp_conn_t * const conn);
|
||||
void auth_handle_open_stub(xmpp_conn_t * const conn);
|
||||
|
||||
#endif /* __LIBSTROPHE_COMMON_H__ */
|
||||
|
||||
672
src/conn.c
672
src/conn.c
File diff suppressed because it is too large
Load Diff
131
src/crypto.c
131
src/crypto.c
@@ -91,8 +91,7 @@ char *xmpp_sha1(xmpp_ctx_t *ctx, const unsigned char *data, size_t len)
|
||||
*
|
||||
* @ingroup Digests
|
||||
*/
|
||||
void xmpp_sha1_digest(const unsigned char *data,
|
||||
size_t len,
|
||||
void xmpp_sha1_digest(const unsigned char *data, size_t len,
|
||||
unsigned char *digest)
|
||||
{
|
||||
crypto_SHA1((const uint8_t *)data, len, digest);
|
||||
@@ -215,43 +214,52 @@ void xmpp_sha1_to_digest(xmpp_sha1_t *sha1, unsigned char *digest)
|
||||
memcpy(digest, sha1->digest, SHA1_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/* Base64 encoding routines. Implemented according to RFC 3548. */
|
||||
|
||||
/* map of all byte values to the base64 values, or to
|
||||
'65' which indicates an invalid character. '=' is '64' */
|
||||
static const unsigned char _base64_invcharmap[256] = {
|
||||
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
|
||||
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
|
||||
65, 65, 65, 65, 65, 62, 65, 65, 65, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
|
||||
61, 65, 65, 65, 64, 65, 65, 65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 65, 65, 65, 65,
|
||||
65, 65, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
|
||||
43, 44, 45, 46, 47, 48, 49, 50, 51, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
|
||||
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
|
||||
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
|
||||
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
|
||||
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
|
||||
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
|
||||
65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
|
||||
65, 65, 65, 65, 65, 65, 65, 65, 65};
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,62, 65,65,65,63,
|
||||
52,53,54,55, 56,57,58,59, 60,61,65,65, 65,64,65,65,
|
||||
65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
||||
15,16,17,18, 19,20,21,22, 23,24,25,65, 65,65,65,65,
|
||||
65,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
||||
41,42,43,44, 45,46,47,48, 49,50,51,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65,
|
||||
65,65,65,65, 65,65,65,65, 65,65,65,65, 65,65,65,65
|
||||
};
|
||||
|
||||
/* map of all 6-bit values to their corresponding byte
|
||||
in the base64 alphabet. Padding char is the value '64' */
|
||||
static const char _base64_charmap[65] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '='};
|
||||
'A','B','C','D', 'E','F','G','H',
|
||||
'I','J','K','L', 'M','N','O','P',
|
||||
'Q','R','S','T', 'U','V','W','X',
|
||||
'Y','Z','a','b', 'c','d','e','f',
|
||||
'g','h','i','j', 'k','l','m','n',
|
||||
'o','p','q','r', 's','t','u','v',
|
||||
'w','x','y','z', '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 */
|
||||
return ((len + 2)/3) << 2;
|
||||
}
|
||||
|
||||
static char *
|
||||
base64_encode(xmpp_ctx_t *ctx, const unsigned char *buffer, size_t len)
|
||||
static char *base64_encode(xmpp_ctx_t *ctx,
|
||||
const unsigned char * const buffer, const size_t len)
|
||||
{
|
||||
size_t clen;
|
||||
char *cbuf, *c;
|
||||
@@ -303,37 +311,30 @@ base64_encode(xmpp_ctx_t *ctx, const unsigned char *buffer, size_t len)
|
||||
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;
|
||||
unsigned char c;
|
||||
size_t i;
|
||||
|
||||
if (len < 4)
|
||||
return 0;
|
||||
if (len < 4) return 0;
|
||||
|
||||
/* count the padding characters for the remainder */
|
||||
for (i = len; i > 0; --i) {
|
||||
c = _base64_invcharmap[(unsigned char)buffer[i-1]];
|
||||
if (c < 64)
|
||||
break;
|
||||
if (c == 64)
|
||||
++nudge;
|
||||
if (c > 64)
|
||||
return 0;
|
||||
if (c < 64) break;
|
||||
if (c == 64) ++nudge;
|
||||
if (c > 64) return 0;
|
||||
}
|
||||
if (nudge > 2)
|
||||
return 0;
|
||||
if (nudge > 2) return 0;
|
||||
|
||||
/* decoded steam is 3 bytes for every four */
|
||||
return 3 * (len >> 2) - nudge;
|
||||
}
|
||||
|
||||
static void base64_decode(xmpp_ctx_t *ctx,
|
||||
const char *buffer,
|
||||
size_t len,
|
||||
unsigned char **out,
|
||||
size_t *outlen)
|
||||
const char * const buffer, const size_t len,
|
||||
unsigned char **out, size_t *outlen)
|
||||
{
|
||||
size_t dlen;
|
||||
unsigned char *dbuf, *d;
|
||||
@@ -341,12 +342,10 @@ static void base64_decode(xmpp_ctx_t *ctx,
|
||||
size_t i;
|
||||
|
||||
/* len must be a multiple of 4 */
|
||||
if (len & 0x03)
|
||||
goto _base64_error;
|
||||
if (len & 0x03) goto _base64_error;
|
||||
|
||||
dlen = base64_decoded_len(buffer, len);
|
||||
if (dlen == 0)
|
||||
goto _base64_error;
|
||||
if (dlen == 0) goto _base64_error;
|
||||
|
||||
dbuf = xmpp_alloc(ctx, dlen + 1);
|
||||
if (dbuf != NULL) {
|
||||
@@ -354,27 +353,22 @@ static void base64_decode(xmpp_ctx_t *ctx,
|
||||
/* loop over each set of 4 characters, decoding 3 bytes */
|
||||
for (i = 0; i + 3 < len; i += 4) {
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[i]];
|
||||
if (hextet & 0xC0)
|
||||
break;
|
||||
if (hextet & 0xC0) break;
|
||||
word = hextet << 18;
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[i+1]];
|
||||
if (hextet & 0xC0)
|
||||
break;
|
||||
if (hextet & 0xC0) break;
|
||||
word |= hextet << 12;
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[i+2]];
|
||||
if (hextet & 0xC0)
|
||||
break;
|
||||
if (hextet & 0xC0) break;
|
||||
word |= hextet << 6;
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[i+3]];
|
||||
if (hextet & 0xC0)
|
||||
break;
|
||||
if (hextet & 0xC0) break;
|
||||
word |= hextet;
|
||||
*d++ = (word & 0x00FF0000) >> 16;
|
||||
*d++ = (word & 0x0000FF00) >> 8;
|
||||
*d++ = (word & 0x000000FF);
|
||||
}
|
||||
if (hextet > 64)
|
||||
goto _base64_decode_error;
|
||||
if (hextet > 64) goto _base64_decode_error;
|
||||
/* handle the remainder */
|
||||
switch (dlen % 3) {
|
||||
case 0:
|
||||
@@ -383,40 +377,32 @@ static void base64_decode(xmpp_ctx_t *ctx,
|
||||
case 1:
|
||||
/* redo the last quartet, checking for correctness */
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[len-4]];
|
||||
if (hextet & 0xC0)
|
||||
goto _base64_decode_error;
|
||||
if (hextet & 0xC0) goto _base64_decode_error;
|
||||
word = hextet << 2;
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[len-3]];
|
||||
if (hextet & 0xC0)
|
||||
goto _base64_decode_error;
|
||||
if (hextet & 0xC0) goto _base64_decode_error;
|
||||
word |= hextet >> 4;
|
||||
*d++ = word & 0xFF;
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[len-2]];
|
||||
if (hextet != 64)
|
||||
goto _base64_decode_error;
|
||||
if (hextet != 64) goto _base64_decode_error;
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[len-1]];
|
||||
if (hextet != 64)
|
||||
goto _base64_decode_error;
|
||||
if (hextet != 64) goto _base64_decode_error;
|
||||
break;
|
||||
case 2:
|
||||
/* redo the last quartet, checking for correctness */
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[len-4]];
|
||||
if (hextet & 0xC0)
|
||||
goto _base64_decode_error;
|
||||
if (hextet & 0xC0) goto _base64_decode_error;
|
||||
word = hextet << 10;
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[len-3]];
|
||||
if (hextet & 0xC0)
|
||||
goto _base64_decode_error;
|
||||
if (hextet & 0xC0) goto _base64_decode_error;
|
||||
word |= hextet << 4;
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[len-2]];
|
||||
if (hextet & 0xC0)
|
||||
goto _base64_decode_error;
|
||||
if (hextet & 0xC0) goto _base64_decode_error;
|
||||
word |= hextet >> 2;
|
||||
*d++ = (word & 0xFF00) >> 8;
|
||||
*d++ = (word & 0x00FF);
|
||||
hextet = _base64_invcharmap[(unsigned char)buffer[len-1]];
|
||||
if (hextet != 64)
|
||||
goto _base64_decode_error;
|
||||
if (hextet != 64) goto _base64_decode_error;
|
||||
break;
|
||||
}
|
||||
*d = '\0';
|
||||
@@ -498,11 +484,8 @@ char *xmpp_base64_decode_str(xmpp_ctx_t *ctx, const char *base64, size_t len)
|
||||
*
|
||||
* @ingroup Encodings
|
||||
*/
|
||||
void xmpp_base64_decode_bin(xmpp_ctx_t *ctx,
|
||||
const char *base64,
|
||||
size_t len,
|
||||
unsigned char **out,
|
||||
size_t *outlen)
|
||||
void xmpp_base64_decode_bin(xmpp_ctx_t *ctx, const char *base64, size_t len,
|
||||
unsigned char **out, size_t *outlen)
|
||||
{
|
||||
base64_decode(ctx, base64, len, out, outlen);
|
||||
}
|
||||
|
||||
143
src/ctx.c
143
src/ctx.c
@@ -50,10 +50,9 @@
|
||||
#include "resolver.h"
|
||||
#include "util.h"
|
||||
|
||||
/* Workaround for systems without va_copy support. */
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800 || \
|
||||
!defined(_MSC_VER) && !defined(HAVE_DECL_VA_COPY)
|
||||
#define va_copy(d, s) (memcpy(&d, &s, sizeof(va_list)))
|
||||
/* Workaround for visual studio without va_copy support. */
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800 || defined(__HAIKU__)
|
||||
#define va_copy(d,s) ((d) = (s))
|
||||
#endif
|
||||
|
||||
/** Initialize the Strophe library.
|
||||
@@ -114,7 +113,8 @@ void xmpp_shutdown(void)
|
||||
*/
|
||||
int xmpp_version_check(int major, int minor)
|
||||
{
|
||||
return (major == LIBXMPP_VERSION_MAJOR) && (minor >= LIBXMPP_VERSION_MINOR);
|
||||
return (major == LIBXMPP_VERSION_MAJOR) &&
|
||||
(minor >= LIBXMPP_VERSION_MINOR);
|
||||
}
|
||||
|
||||
/* We define the global default allocator, logger, and context here. */
|
||||
@@ -122,33 +122,35 @@ int xmpp_version_check(int major, int minor)
|
||||
/* Wrap stdlib routines malloc, free, and realloc for default memory
|
||||
* management.
|
||||
*/
|
||||
static void *_malloc(size_t size, void *userdata)
|
||||
static void *_malloc(const size_t size, void * const userdata)
|
||||
{
|
||||
UNUSED(userdata);
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void _free(void *p, void *userdata)
|
||||
static void _free(void *p, void * const userdata)
|
||||
{
|
||||
UNUSED(userdata);
|
||||
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);
|
||||
return realloc(p, size);
|
||||
}
|
||||
|
||||
/* default memory function map */
|
||||
static xmpp_mem_t xmpp_default_mem = {
|
||||
_malloc, /* use the thinly wrapped stdlib routines by default */
|
||||
_free, _realloc, NULL};
|
||||
_free,
|
||||
_realloc,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* log levels and names */
|
||||
static const char *_xmpp_log_level_name[4] = {"DEBUG", "INFO", "WARN", "ERROR"};
|
||||
static const xmpp_log_level_t _xmpp_default_logger_levels[] = {
|
||||
XMPP_LEVEL_DEBUG, XMPP_LEVEL_INFO, XMPP_LEVEL_WARN, XMPP_LEVEL_ERROR};
|
||||
static const char * const _xmpp_log_level_name[4] = {"DEBUG", "INFO", "WARN", "ERROR"};
|
||||
static const xmpp_log_level_t _xmpp_default_logger_levels[] = {XMPP_LEVEL_DEBUG,
|
||||
XMPP_LEVEL_INFO,
|
||||
XMPP_LEVEL_WARN,
|
||||
XMPP_LEVEL_ERROR};
|
||||
|
||||
/** Log a message.
|
||||
* The default logger writes to stderr.
|
||||
@@ -159,10 +161,10 @@ static const xmpp_log_level_t _xmpp_default_logger_levels[] = {
|
||||
* @param area the area the log message is for
|
||||
* @param msg the log message
|
||||
*/
|
||||
static void xmpp_default_logger(void *userdata,
|
||||
xmpp_log_level_t level,
|
||||
const char *area,
|
||||
const char *msg)
|
||||
static void xmpp_default_logger(void * const userdata,
|
||||
const xmpp_log_level_t level,
|
||||
const char * const area,
|
||||
const char * const msg)
|
||||
{
|
||||
xmpp_log_level_t filter_level = * (xmpp_log_level_t*)userdata;
|
||||
if (level >= filter_level)
|
||||
@@ -170,14 +172,11 @@ static void xmpp_default_logger(void *userdata,
|
||||
}
|
||||
|
||||
static const xmpp_log_t _xmpp_default_loggers[] = {
|
||||
{&xmpp_default_logger,
|
||||
(void *)&_xmpp_default_logger_levels[XMPP_LEVEL_DEBUG]},
|
||||
{&xmpp_default_logger,
|
||||
(void *)&_xmpp_default_logger_levels[XMPP_LEVEL_INFO]},
|
||||
{&xmpp_default_logger,
|
||||
(void *)&_xmpp_default_logger_levels[XMPP_LEVEL_WARN]},
|
||||
{&xmpp_default_logger,
|
||||
(void *)&_xmpp_default_logger_levels[XMPP_LEVEL_ERROR]}};
|
||||
{&xmpp_default_logger, (void*)&_xmpp_default_logger_levels[XMPP_LEVEL_DEBUG]},
|
||||
{&xmpp_default_logger, (void*)&_xmpp_default_logger_levels[XMPP_LEVEL_INFO]},
|
||||
{&xmpp_default_logger, (void*)&_xmpp_default_logger_levels[XMPP_LEVEL_WARN]},
|
||||
{&xmpp_default_logger, (void*)&_xmpp_default_logger_levels[XMPP_LEVEL_ERROR]}
|
||||
};
|
||||
|
||||
/** Get a default logger with filtering.
|
||||
* The default logger provides a basic logging setup which writes log
|
||||
@@ -193,8 +192,7 @@ static const xmpp_log_t _xmpp_default_loggers[] = {
|
||||
xmpp_log_t *xmpp_get_default_logger(xmpp_log_level_t level)
|
||||
{
|
||||
/* clamp to the known range */
|
||||
if (level > XMPP_LEVEL_ERROR)
|
||||
level = XMPP_LEVEL_ERROR;
|
||||
if (level > XMPP_LEVEL_ERROR) level = XMPP_LEVEL_ERROR;
|
||||
|
||||
return (xmpp_log_t*)&_xmpp_default_loggers[level];
|
||||
}
|
||||
@@ -211,7 +209,7 @@ static xmpp_log_t xmpp_default_log = {NULL, NULL};
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
@@ -222,7 +220,7 @@ void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size)
|
||||
* @param ctx a Strophe context object
|
||||
* @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);
|
||||
}
|
||||
@@ -236,7 +234,8 @@ void xmpp_free(const xmpp_ctx_t *ctx, void *p)
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
@@ -254,10 +253,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 ap variable argument list supplied for the format string
|
||||
*/
|
||||
void xmpp_log(const xmpp_ctx_t *ctx,
|
||||
xmpp_log_level_t level,
|
||||
const char *area,
|
||||
const char *fmt,
|
||||
void xmpp_log(const xmpp_ctx_t * const ctx,
|
||||
const xmpp_log_level_t level,
|
||||
const char * const area,
|
||||
const char * const fmt,
|
||||
va_list ap)
|
||||
{
|
||||
int oldret, ret;
|
||||
@@ -265,13 +264,6 @@ void xmpp_log(const xmpp_ctx_t *ctx,
|
||||
char *buf;
|
||||
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);
|
||||
ret = xmpp_vsnprintf(smbuf, sizeof(smbuf), fmt, ap);
|
||||
if (ret >= (int)sizeof(smbuf)) {
|
||||
@@ -295,6 +287,7 @@ void xmpp_log(const xmpp_ctx_t *ctx,
|
||||
}
|
||||
va_end(copy);
|
||||
|
||||
if (ctx->log->handler)
|
||||
ctx->log->handler(ctx->log->userdata, level, area, buf);
|
||||
|
||||
if (buf != smbuf)
|
||||
@@ -311,7 +304,10 @@ void xmpp_log(const xmpp_ctx_t *ctx,
|
||||
* @param fmt a printf-style format string followed by a variable list of
|
||||
* 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;
|
||||
|
||||
@@ -330,7 +326,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
|
||||
* 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;
|
||||
|
||||
@@ -349,7 +348,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
|
||||
* 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;
|
||||
|
||||
@@ -368,7 +370,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
|
||||
* 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;
|
||||
|
||||
@@ -377,30 +382,6 @@ void xmpp_debug(const xmpp_ctx_t *ctx, const char *area, const char *fmt, ...)
|
||||
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.
|
||||
* If mem is NULL, a default allocation setup will be used which
|
||||
* wraps malloc(), free(), and realloc() from the standard library.
|
||||
@@ -415,7 +396,8 @@ void xmpp_debug_verbose(
|
||||
*
|
||||
* @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;
|
||||
|
||||
@@ -436,7 +418,6 @@ xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t *mem, const xmpp_log_t *log)
|
||||
ctx->log = log;
|
||||
|
||||
ctx->connlist = NULL;
|
||||
ctx->timed_handlers = NULL;
|
||||
ctx->loop_status = XMPP_LOOP_NOTSTARTED;
|
||||
ctx->rand = xmpp_rand_new(ctx);
|
||||
ctx->timeout = EVENT_LOOP_DEFAULT_TIMEOUT;
|
||||
@@ -455,7 +436,7 @@ xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t *mem, const xmpp_log_t *log)
|
||||
*
|
||||
* @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 */
|
||||
xmpp_rand_free(ctx, ctx->rand);
|
||||
@@ -469,19 +450,7 @@ void xmpp_ctx_free(xmpp_ctx_t *ctx)
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
37
src/event.c
37
src/event.c
@@ -73,7 +73,7 @@
|
||||
*
|
||||
* @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_conn_t *conn;
|
||||
@@ -88,8 +88,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
|
||||
uint64_t usec;
|
||||
int tls_read_bytes = 0;
|
||||
|
||||
if (ctx->loop_status == XMPP_LOOP_QUIT)
|
||||
return;
|
||||
if (ctx->loop_status == XMPP_LOOP_QUIT) return;
|
||||
|
||||
/* send queued data */
|
||||
connitem = ctx->connlist;
|
||||
@@ -110,7 +109,6 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
|
||||
xmpp_debug(ctx, "xmpp", "Send error occurred, disconnecting.");
|
||||
conn->error = ECONNABORTED;
|
||||
conn_disconnect(conn);
|
||||
goto NEXT_ITEM;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,9 +132,6 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
|
||||
break; /* partial write or an error */
|
||||
|
||||
/* 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);
|
||||
tsq = sq;
|
||||
sq = sq->next;
|
||||
@@ -146,8 +141,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
|
||||
/* pop the top item */
|
||||
conn->send_queue_head = sq;
|
||||
/* if we've sent everything update the tail */
|
||||
if (!sq)
|
||||
conn->send_queue_tail = NULL;
|
||||
if (!sq) conn->send_queue_tail = NULL;
|
||||
}
|
||||
|
||||
/* tear down connection on error */
|
||||
@@ -158,7 +152,7 @@ void xmpp_run_once(xmpp_ctx_t *ctx, unsigned long timeout)
|
||||
conn->error = ECONNABORTED;
|
||||
conn_disconnect(conn);
|
||||
}
|
||||
NEXT_ITEM:
|
||||
|
||||
connitem = connitem->next;
|
||||
}
|
||||
|
||||
@@ -168,6 +162,7 @@ NEXT_ITEM:
|
||||
conn_parser_reset(connitem->conn);
|
||||
}
|
||||
|
||||
|
||||
/* fire any ready timed handlers, then make sure we don't wait past
|
||||
the time when timed handlers need to be called */
|
||||
next = handler_fire_timed(ctx);
|
||||
@@ -238,8 +233,7 @@ NEXT_ITEM:
|
||||
}
|
||||
|
||||
/* no events happened */
|
||||
if (ret == 0 && tls_read_bytes == 0)
|
||||
return;
|
||||
if (ret == 0 && tls_read_bytes == 0) return;
|
||||
|
||||
/* process events */
|
||||
connitem = ctx->connlist;
|
||||
@@ -267,35 +261,29 @@ NEXT_ITEM:
|
||||
|
||||
break;
|
||||
case XMPP_STATE_CONNECTED:
|
||||
if (FD_ISSET(conn->sock, &rfds) ||
|
||||
(conn->tls && tls_pending(conn->tls))) {
|
||||
if (FD_ISSET(conn->sock, &rfds) || (conn->tls && tls_pending(conn->tls))) {
|
||||
if (conn->tls) {
|
||||
ret = tls_read(conn->tls, buf, STROPE_MESSAGE_BUFFER_SIZE);
|
||||
} else {
|
||||
ret =
|
||||
sock_read(conn->sock, buf, STROPE_MESSAGE_BUFFER_SIZE);
|
||||
ret = sock_read(conn->sock, buf, STROPE_MESSAGE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
ret = parser_feed(conn->parser, buf, ret);
|
||||
if (!ret) {
|
||||
xmpp_debug(ctx, "xmpp", "parse error [%s]", buf);
|
||||
xmpp_send_error(conn, XMPP_SE_INVALID_XML,
|
||||
"parse error");
|
||||
xmpp_send_error(conn, XMPP_SE_INVALID_XML, "parse error");
|
||||
}
|
||||
} else {
|
||||
if (conn->tls) {
|
||||
if (!tls_is_recoverable(tls_error(conn->tls))) {
|
||||
xmpp_debug(ctx, "xmpp",
|
||||
"Unrecoverable TLS error, %d.",
|
||||
tls_error(conn->tls));
|
||||
xmpp_debug(ctx, "xmpp", "Unrecoverable TLS error, %d.", tls_error(conn->tls));
|
||||
conn->error = tls_error(conn->tls);
|
||||
conn_disconnect(conn);
|
||||
}
|
||||
} else {
|
||||
/* return of 0 means socket closed by server */
|
||||
xmpp_debug(ctx, "xmpp",
|
||||
"Socket closed by remote host.");
|
||||
xmpp_debug(ctx, "xmpp", "Socket closed by remote host.");
|
||||
conn->error = ECONNRESET;
|
||||
conn_disconnect(conn);
|
||||
}
|
||||
@@ -326,8 +314,7 @@ NEXT_ITEM:
|
||||
*/
|
||||
void xmpp_run(xmpp_ctx_t *ctx)
|
||||
{
|
||||
if (ctx->loop_status != XMPP_LOOP_NOTSTARTED)
|
||||
return;
|
||||
if (ctx->loop_status != XMPP_LOOP_NOTSTARTED) return;
|
||||
|
||||
ctx->loop_status = XMPP_LOOP_RUNNING;
|
||||
while (ctx->loop_status == XMPP_LOOP_RUNNING) {
|
||||
|
||||
317
src/handler.c
317
src/handler.c
@@ -24,8 +24,6 @@
|
||||
#include "common.h"
|
||||
#include "ostypes.h"
|
||||
|
||||
typedef int (*xmpp_void_handler)();
|
||||
|
||||
/* Remove item from the list pointed by head, but don't free it.
|
||||
* There can be a situation when user's handler deletes another handler which
|
||||
* is the previous in the list. handler_fire_stanza() and handler_fire_timed()
|
||||
@@ -35,14 +33,19 @@ typedef int (*xmpp_void_handler)();
|
||||
* TODO Convert handler lists to double-linked lists. Current implementation
|
||||
* works for O(n).
|
||||
*/
|
||||
static void _handler_item_remove(xmpp_handlist_t **head, xmpp_handlist_t *item)
|
||||
static void _handler_item_remove(xmpp_handlist_t **head,
|
||||
xmpp_handlist_t *item)
|
||||
{
|
||||
while (*head) {
|
||||
if (*head == item) {
|
||||
xmpp_handlist_t *i = *head;
|
||||
|
||||
if (i == item)
|
||||
*head = item->next;
|
||||
break;
|
||||
else if (i != NULL) {
|
||||
while (i->next != NULL && i->next != item)
|
||||
i = i->next;
|
||||
if (i->next == item) {
|
||||
i->next = item->next;
|
||||
}
|
||||
head = &(*head)->next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +56,8 @@ static void _handler_item_remove(xmpp_handlist_t **head, xmpp_handlist_t *item)
|
||||
* @param conn a Strophe connection 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;
|
||||
const char *id, *ns, *name, *type;
|
||||
@@ -71,8 +75,7 @@ void handler_fire_stanza(xmpp_conn_t *conn, xmpp_stanza_t *stanza)
|
||||
while (item) {
|
||||
/* don't fire user handlers until authentication succeeds and
|
||||
and skip newly added handlers */
|
||||
if ((item->user_handler && !conn->authenticated) ||
|
||||
!item->enabled) {
|
||||
if ((item->user_handler && !conn->authenticated) || !item->enabled) {
|
||||
item = item->next;
|
||||
continue;
|
||||
}
|
||||
@@ -124,12 +127,9 @@ void handler_fire_stanza(xmpp_conn_t *conn, xmpp_stanza_t *stanza)
|
||||
if (!ret) {
|
||||
/* handler is one-shot, so delete it */
|
||||
_handler_item_remove(&conn->handlers, item);
|
||||
if (item->u.ns)
|
||||
xmpp_free(conn->ctx, item->u.ns);
|
||||
if (item->u.name)
|
||||
xmpp_free(conn->ctx, item->u.name);
|
||||
if (item->u.type)
|
||||
xmpp_free(conn->ctx, item->u.type);
|
||||
if (item->u.ns) xmpp_free(conn->ctx, item->u.ns);
|
||||
if (item->u.name) xmpp_free(conn->ctx, item->u.name);
|
||||
if (item->u.type) xmpp_free(conn->ctx, item->u.type);
|
||||
xmpp_free(conn->ctx, item);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
uint64_t handler_fire_timed(xmpp_ctx_t *ctx)
|
||||
uint64_t handler_fire_timed(xmpp_ctx_t * const ctx)
|
||||
{
|
||||
xmpp_connlist_t *connitem;
|
||||
xmpp_handlist_t *item, *next;
|
||||
@@ -171,8 +171,7 @@ uint64_t handler_fire_timed(xmpp_ctx_t *ctx)
|
||||
while (item) {
|
||||
/* don't fire user handlers until authentication succeeds and
|
||||
skip newly added handlers */
|
||||
if ((item->user_handler && !conn->authenticated) ||
|
||||
!item->enabled) {
|
||||
if ((item->user_handler && !conn->authenticated) || !item->enabled) {
|
||||
item = item->next;
|
||||
continue;
|
||||
}
|
||||
@@ -189,7 +188,7 @@ uint64_t handler_fire_timed(xmpp_ctx_t *ctx)
|
||||
if (!ret) {
|
||||
/* delete handler if it returned false */
|
||||
_handler_item_remove(&conn->timed_handlers, item);
|
||||
xmpp_free(ctx, item);
|
||||
xmpp_free(conn->ctx, item);
|
||||
}
|
||||
} else if (min > (item->u.period - elapsed))
|
||||
min = item->u.period - elapsed;
|
||||
@@ -200,34 +199,6 @@ uint64_t handler_fire_timed(xmpp_ctx_t *ctx)
|
||||
connitem = connitem->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check timed handlers in context. These handlers fire periodically
|
||||
* regardless of connections state.
|
||||
* TODO Reduce copy-paste.
|
||||
*/
|
||||
item = ctx->timed_handlers;
|
||||
while (item) {
|
||||
next = item->next;
|
||||
timestamp = time_stamp();
|
||||
elapsed = time_elapsed(item->u.last_stamp, timestamp);
|
||||
if (elapsed >= item->u.period) {
|
||||
/* fire! */
|
||||
item->u.last_stamp = timestamp;
|
||||
ret =
|
||||
((xmpp_global_timed_handler)item->handler)(ctx, item->userdata);
|
||||
/* list may be changed during execution of a handler */
|
||||
next = item->next;
|
||||
if (!ret) {
|
||||
/* delete handler if it returned false */
|
||||
_handler_item_remove(&ctx->timed_handlers, item);
|
||||
xmpp_free(ctx, item);
|
||||
}
|
||||
} else if (min > (item->u.period - elapsed))
|
||||
min = item->u.period - elapsed;
|
||||
|
||||
item = next;
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
@@ -250,57 +221,44 @@ void handler_reset_timed(xmpp_conn_t *conn, int user_only)
|
||||
}
|
||||
}
|
||||
|
||||
static void _timed_handler_add(xmpp_ctx_t *ctx,
|
||||
xmpp_handlist_t **handlers_list,
|
||||
xmpp_void_handler handler,
|
||||
unsigned long period,
|
||||
void *userdata,
|
||||
int user_handler)
|
||||
static void _timed_handler_add(xmpp_conn_t * const conn,
|
||||
xmpp_timed_handler handler,
|
||||
const unsigned long period,
|
||||
void * const userdata,
|
||||
const int user_handler)
|
||||
{
|
||||
xmpp_handlist_t *item;
|
||||
xmpp_handlist_t *item, *tail;
|
||||
|
||||
/* check if handler is already in the list */
|
||||
for (item = *handlers_list; item; item = item->next) {
|
||||
for (item = conn->timed_handlers; item; item = item->next) {
|
||||
if (item->handler == handler && item->userdata == userdata) {
|
||||
xmpp_warn(ctx, "xmpp", "Timed handler already exists.");
|
||||
xmpp_warn(conn->ctx, "xmpp", "Timed handler already exists.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (item)
|
||||
return;
|
||||
if (item) return;
|
||||
|
||||
/* build new item */
|
||||
item = xmpp_alloc(ctx, sizeof(xmpp_handlist_t));
|
||||
if (!item)
|
||||
return;
|
||||
item = xmpp_alloc(conn->ctx, sizeof(xmpp_handlist_t));
|
||||
if (!item) return;
|
||||
|
||||
item->user_handler = user_handler;
|
||||
item->handler = handler;
|
||||
item->userdata = userdata;
|
||||
item->enabled = 0;
|
||||
item->next = NULL;
|
||||
|
||||
item->u.period = period;
|
||||
item->u.last_stamp = time_stamp();
|
||||
|
||||
/* append item to list */
|
||||
item->next = *handlers_list;
|
||||
*handlers_list = item;
|
||||
}
|
||||
|
||||
static void _timed_handler_delete(xmpp_ctx_t *ctx,
|
||||
xmpp_handlist_t **handlers_list,
|
||||
xmpp_void_handler handler)
|
||||
{
|
||||
xmpp_handlist_t *item;
|
||||
|
||||
while (*handlers_list) {
|
||||
item = *handlers_list;
|
||||
if (item->handler == handler) {
|
||||
*handlers_list = item->next;
|
||||
xmpp_free(ctx, item);
|
||||
} else {
|
||||
handlers_list = &item->next;
|
||||
}
|
||||
if (!conn->timed_handlers)
|
||||
conn->timed_handlers = item;
|
||||
else {
|
||||
tail = conn->timed_handlers;
|
||||
while (tail->next)
|
||||
tail = tail->next;
|
||||
tail->next = item;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,16 +269,35 @@ static void _timed_handler_delete(xmpp_ctx_t *ctx,
|
||||
*
|
||||
* @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);
|
||||
xmpp_handlist_t *item, *prev;
|
||||
|
||||
if (!conn->timed_handlers) return;
|
||||
|
||||
prev = NULL;
|
||||
item = conn->timed_handlers;
|
||||
while (item) {
|
||||
if (item->handler == handler) {
|
||||
if (prev)
|
||||
prev->next = item->next;
|
||||
else
|
||||
conn->timed_handlers = item->next;
|
||||
|
||||
xmpp_free(conn->ctx, item);
|
||||
item = prev ? prev->next : conn->timed_handlers;
|
||||
} else {
|
||||
prev = item;
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _id_handler_add(xmpp_conn_t *conn,
|
||||
static void _id_handler_add(xmpp_conn_t * const conn,
|
||||
xmpp_handler handler,
|
||||
const char *id,
|
||||
void *userdata,
|
||||
int user_handler)
|
||||
const char * const id,
|
||||
void * const userdata, int user_handler)
|
||||
{
|
||||
xmpp_handlist_t *item, *tail;
|
||||
|
||||
@@ -333,13 +310,11 @@ static void _id_handler_add(xmpp_conn_t *conn,
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
if (item)
|
||||
return;
|
||||
if (item) return;
|
||||
|
||||
/* build new item */
|
||||
item = xmpp_alloc(conn->ctx, sizeof(xmpp_handlist_t));
|
||||
if (!item)
|
||||
return;
|
||||
if (!item) return;
|
||||
|
||||
item->user_handler = user_handler;
|
||||
item->handler = handler;
|
||||
@@ -372,16 +347,15 @@ static void _id_handler_add(xmpp_conn_t *conn,
|
||||
*
|
||||
* @ingroup Handlers
|
||||
*/
|
||||
void xmpp_id_handler_delete(xmpp_conn_t *conn,
|
||||
void xmpp_id_handler_delete(xmpp_conn_t * const conn,
|
||||
xmpp_handler handler,
|
||||
const char *id)
|
||||
const char * const id)
|
||||
{
|
||||
xmpp_handlist_t *item, *prev, *next;
|
||||
|
||||
prev = NULL;
|
||||
item = (xmpp_handlist_t *)hash_get(conn->id_handlers, id);
|
||||
if (!item)
|
||||
return;
|
||||
if (!item) return;
|
||||
|
||||
while (item) {
|
||||
next = item->next;
|
||||
@@ -405,13 +379,12 @@ void xmpp_id_handler_delete(xmpp_conn_t *conn,
|
||||
}
|
||||
|
||||
/* add a stanza handler */
|
||||
static void _handler_add(xmpp_conn_t *conn,
|
||||
static void _handler_add(xmpp_conn_t * const conn,
|
||||
xmpp_handler handler,
|
||||
const char *ns,
|
||||
const char *name,
|
||||
const char *type,
|
||||
void *userdata,
|
||||
int user_handler)
|
||||
const char * const ns,
|
||||
const char * const name,
|
||||
const char * const type,
|
||||
void * const userdata, int user_handler)
|
||||
{
|
||||
xmpp_handlist_t *item, *tail;
|
||||
|
||||
@@ -424,13 +397,11 @@ static void _handler_add(xmpp_conn_t *conn,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (item)
|
||||
return;
|
||||
if (item) return;
|
||||
|
||||
/* build new item */
|
||||
item = (xmpp_handlist_t *)xmpp_alloc(conn->ctx, sizeof(xmpp_handlist_t));
|
||||
if (!item)
|
||||
return;
|
||||
if (!item) return;
|
||||
|
||||
item->user_handler = user_handler;
|
||||
item->handler = handler;
|
||||
@@ -446,25 +417,20 @@ static void _handler_add(xmpp_conn_t *conn,
|
||||
}
|
||||
} else
|
||||
item->u.ns = NULL;
|
||||
|
||||
if (name) {
|
||||
item->u.name = xmpp_strdup(conn->ctx, name);
|
||||
if (!item->u.name) {
|
||||
if (item->u.ns)
|
||||
xmpp_free(conn->ctx, item->u.ns);
|
||||
if (item->u.ns) xmpp_free(conn->ctx, item->u.ns);
|
||||
xmpp_free(conn->ctx, item);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
item->u.name = NULL;
|
||||
|
||||
if (type) {
|
||||
item->u.type = xmpp_strdup(conn->ctx, type);
|
||||
if (!item->u.type) {
|
||||
if (item->u.ns)
|
||||
xmpp_free(conn->ctx, item->u.ns);
|
||||
if (item->u.name)
|
||||
xmpp_free(conn->ctx, item->u.name);
|
||||
if (item->u.ns) xmpp_free(conn->ctx, item->u.ns);
|
||||
if (item->u.name) xmpp_free(conn->ctx, item->u.name);
|
||||
xmpp_free(conn->ctx, item);
|
||||
}
|
||||
} else
|
||||
@@ -488,12 +454,12 @@ static void _handler_add(xmpp_conn_t *conn,
|
||||
*
|
||||
* @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;
|
||||
|
||||
if (!conn->handlers)
|
||||
return;
|
||||
if (!conn->handlers) return;
|
||||
|
||||
prev = NULL;
|
||||
item = conn->handlers;
|
||||
@@ -504,12 +470,9 @@ void xmpp_handler_delete(xmpp_conn_t *conn, xmpp_handler handler)
|
||||
else
|
||||
conn->handlers = item->next;
|
||||
|
||||
if (item->u.ns)
|
||||
xmpp_free(conn->ctx, item->u.ns);
|
||||
if (item->u.name)
|
||||
xmpp_free(conn->ctx, item->u.name);
|
||||
if (item->u.type)
|
||||
xmpp_free(conn->ctx, item->u.type);
|
||||
if (item->u.ns) xmpp_free(conn->ctx, item->u.ns);
|
||||
if (item->u.name) xmpp_free(conn->ctx, item->u.name);
|
||||
if (item->u.type) xmpp_free(conn->ctx, item->u.type);
|
||||
xmpp_free(conn->ctx, item);
|
||||
item = prev ? prev->next : conn->handlers;
|
||||
} else {
|
||||
@@ -535,13 +498,12 @@ void xmpp_handler_delete(xmpp_conn_t *conn, xmpp_handler handler)
|
||||
*
|
||||
* @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,
|
||||
unsigned long period,
|
||||
void *userdata)
|
||||
const unsigned long period,
|
||||
void * const userdata)
|
||||
{
|
||||
_timed_handler_add(conn->ctx, &conn->timed_handlers, handler, period,
|
||||
userdata, 1);
|
||||
_timed_handler_add(conn, handler, period, userdata, 1);
|
||||
}
|
||||
|
||||
/** Add a timed system handler.
|
||||
@@ -553,13 +515,12 @@ void xmpp_timed_handler_add(xmpp_conn_t *conn,
|
||||
* @param period the time in milliseconds between firings
|
||||
* @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,
|
||||
unsigned long period,
|
||||
void *userdata)
|
||||
const unsigned long period,
|
||||
void * const userdata)
|
||||
{
|
||||
_timed_handler_add(conn->ctx, &conn->timed_handlers, handler, period,
|
||||
userdata, 0);
|
||||
_timed_handler_add(conn, handler, period, userdata, 0);
|
||||
}
|
||||
|
||||
/** Add an id based stanza handler.
|
||||
@@ -578,10 +539,10 @@ void handler_add_timed(xmpp_conn_t *conn,
|
||||
*
|
||||
* @ingroup Handlers
|
||||
*/
|
||||
void xmpp_id_handler_add(xmpp_conn_t *conn,
|
||||
void xmpp_id_handler_add(xmpp_conn_t * const conn,
|
||||
xmpp_handler handler,
|
||||
const char *id,
|
||||
void *userdata)
|
||||
const char * const id,
|
||||
void * const userdata)
|
||||
{
|
||||
_id_handler_add(conn, handler, id, userdata, 1);
|
||||
}
|
||||
@@ -595,10 +556,10 @@ void xmpp_id_handler_add(xmpp_conn_t *conn,
|
||||
* @param id a string with the id
|
||||
* @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,
|
||||
const char *id,
|
||||
void *userdata)
|
||||
const char * const id,
|
||||
void * const userdata)
|
||||
{
|
||||
_id_handler_add(conn, handler, id, userdata, 0);
|
||||
}
|
||||
@@ -625,12 +586,12 @@ void handler_add_id(xmpp_conn_t *conn,
|
||||
*
|
||||
* @ingroup Handlers
|
||||
*/
|
||||
void xmpp_handler_add(xmpp_conn_t *conn,
|
||||
void xmpp_handler_add(xmpp_conn_t * const conn,
|
||||
xmpp_handler handler,
|
||||
const char *ns,
|
||||
const char *name,
|
||||
const char *type,
|
||||
void *userdata)
|
||||
const char * const ns,
|
||||
const char * const name,
|
||||
const char * const type,
|
||||
void * const userdata)
|
||||
{
|
||||
_handler_add(conn, handler, ns, name, type, userdata, 1);
|
||||
}
|
||||
@@ -646,12 +607,12 @@ void xmpp_handler_add(xmpp_conn_t *conn,
|
||||
* @param type a string with the 'type' attribute value to match
|
||||
* @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,
|
||||
const char *ns,
|
||||
const char *name,
|
||||
const char *type,
|
||||
void *userdata)
|
||||
const char * const ns,
|
||||
const char * const name,
|
||||
const char * const type,
|
||||
void * const userdata)
|
||||
{
|
||||
_handler_add(conn, handler, ns, name, type, userdata, 0);
|
||||
}
|
||||
@@ -675,12 +636,9 @@ void handler_system_delete_all(xmpp_conn_t *conn)
|
||||
if (!item->user_handler) {
|
||||
next = item->next;
|
||||
_handler_item_remove(&conn->handlers, item);
|
||||
if (item->u.ns)
|
||||
xmpp_free(conn->ctx, item->u.ns);
|
||||
if (item->u.name)
|
||||
xmpp_free(conn->ctx, item->u.name);
|
||||
if (item->u.type)
|
||||
xmpp_free(conn->ctx, item->u.type);
|
||||
if (item->u.ns) xmpp_free(conn->ctx, item->u.ns);
|
||||
if (item->u.name) xmpp_free(conn->ctx, item->u.name);
|
||||
if (item->u.type) xmpp_free(conn->ctx, item->u.type);
|
||||
xmpp_free(conn->ctx, item);
|
||||
item = next;
|
||||
} else
|
||||
@@ -728,56 +686,5 @@ void handler_system_delete_all(xmpp_conn_t *conn)
|
||||
xmpp_free(conn->ctx, key2);
|
||||
}
|
||||
}
|
||||
if (iter)
|
||||
hash_iter_release(iter);
|
||||
}
|
||||
|
||||
/** Add a global timed handler.
|
||||
* The handler will fire for the first time once the period has elapsed,
|
||||
* and continue firing regularly after that. Strophe will try its best
|
||||
* to fire handlers as close to the period times as it can, but accuracy
|
||||
* will vary depending on the resolution of the event loop.
|
||||
*
|
||||
* The main difference between global and ordinary handlers:
|
||||
* - Ordinary handler is related to a connection, fires only when the
|
||||
* connection is in connected state and is removed once the connection is
|
||||
* destroyed.
|
||||
* - Global handler fires regardless of connections state and is related to
|
||||
* a Strophe context.
|
||||
*
|
||||
* The handler is executed in context of the respective event loop.
|
||||
*
|
||||
* If the handler function returns true, it will be kept, and if it
|
||||
* returns false, it will be deleted from the list of handlers.
|
||||
*
|
||||
* Notice, the same handler pointer may be added multiple times with different
|
||||
* userdata pointers. However, xmpp_global_timed_handler_delete() deletes
|
||||
* all occurrences.
|
||||
*
|
||||
* @param ctx a Strophe context object
|
||||
* @param handler a function pointer to a timed handler
|
||||
* @param period the time in milliseconds between firings
|
||||
* @param userdata an opaque data pointer that will be passed to the handler
|
||||
*
|
||||
* @ingroup Handlers
|
||||
*/
|
||||
void xmpp_global_timed_handler_add(xmpp_ctx_t *ctx,
|
||||
xmpp_global_timed_handler handler,
|
||||
unsigned long period,
|
||||
void *userdata)
|
||||
{
|
||||
_timed_handler_add(ctx, &ctx->timed_handlers, handler, period, userdata, 1);
|
||||
}
|
||||
|
||||
/** Delete a global timed handler.
|
||||
*
|
||||
* @param ctx a Strophe context object
|
||||
* @param handler function pointer to the handler
|
||||
*
|
||||
* @ingroup Handlers
|
||||
*/
|
||||
void xmpp_global_timed_handler_delete(xmpp_ctx_t *ctx,
|
||||
xmpp_global_timed_handler handler)
|
||||
{
|
||||
_timed_handler_delete(ctx, &ctx->timed_handlers, handler);
|
||||
if (iter) hash_iter_release(iter);
|
||||
}
|
||||
|
||||
28
src/hash.c
28
src/hash.c
@@ -46,7 +46,8 @@ struct _hash_iterator_t {
|
||||
};
|
||||
|
||||
/** 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;
|
||||
|
||||
@@ -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 */
|
||||
hash_t *hash_clone(hash_t *table)
|
||||
hash_t *hash_clone(hash_t * const table)
|
||||
{
|
||||
table->ref++;
|
||||
return table;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
hashentry_t *entry, *next;
|
||||
@@ -92,8 +93,7 @@ void hash_release(hash_t *table)
|
||||
while (entry != NULL) {
|
||||
next = entry->next;
|
||||
xmpp_free(ctx, entry->key);
|
||||
if (table->free)
|
||||
table->free(ctx, entry->value);
|
||||
if (table->free) table->free(ctx, entry->value);
|
||||
xmpp_free(ctx, entry);
|
||||
entry = next;
|
||||
}
|
||||
@@ -114,8 +114,7 @@ static int _hash_key(hash_t *table, const char *key)
|
||||
/* assume 32 bit ints */
|
||||
hash ^= ((unsigned)*c++ << shift);
|
||||
shift += 8;
|
||||
if (shift > 24)
|
||||
shift = 0;
|
||||
if (shift > 24) shift = 0;
|
||||
}
|
||||
return hash % (unsigned)table->length;
|
||||
}
|
||||
@@ -142,7 +141,7 @@ hashentry_t *_hash_entry_find(hash_t *table, const char *key)
|
||||
* each key can appear only once; the value of any
|
||||
* 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;
|
||||
hashentry_t *entry = NULL;
|
||||
@@ -154,8 +153,7 @@ int hash_add(hash_t *table, const char *key, void *data)
|
||||
if (entry == NULL) {
|
||||
/* allocate and fill a new entry */
|
||||
entry = xmpp_alloc(ctx, sizeof(hashentry_t));
|
||||
if (!entry)
|
||||
return -1;
|
||||
if (!entry) return -1;
|
||||
entry->key = xmpp_strdup(ctx, key);
|
||||
if (!entry->key) {
|
||||
xmpp_free(ctx, entry);
|
||||
@@ -166,8 +164,7 @@ int hash_add(hash_t *table, const char *key, void *data)
|
||||
table->entries[table_index] = entry;
|
||||
table->num_keys++;
|
||||
} else {
|
||||
if (table->free)
|
||||
table->free(ctx, entry->value);
|
||||
if (table->free) table->free(ctx, entry->value);
|
||||
}
|
||||
|
||||
entry->value = data;
|
||||
@@ -199,8 +196,7 @@ int hash_drop(hash_t *table, const char *key)
|
||||
if (!strcmp(key, entry->key)) {
|
||||
/* match, remove the entry */
|
||||
xmpp_free(ctx, entry->key);
|
||||
if (table->free)
|
||||
table->free(ctx, entry->value);
|
||||
if (table->free) table->free(ctx, entry->value);
|
||||
if (prev == NULL) {
|
||||
table->entries[table_index] = entry->next;
|
||||
} else {
|
||||
@@ -239,6 +235,7 @@ hash_iterator_t *hash_iter_new(hash_t *table)
|
||||
return iter;
|
||||
}
|
||||
|
||||
|
||||
/** release an iterator that is no longer needed */
|
||||
void hash_iter_release(hash_iterator_t *iter)
|
||||
{
|
||||
@@ -261,8 +258,7 @@ const char *hash_iter_next(hash_iterator_t *iter)
|
||||
int i;
|
||||
|
||||
/* advance until we find the next entry */
|
||||
if (entry != NULL)
|
||||
entry = entry->next;
|
||||
if (entry != NULL) entry = entry->next;
|
||||
if (entry == NULL) {
|
||||
/* we're off the end of list, search for a new entry */
|
||||
i = iter->index + 1;
|
||||
|
||||
11
src/hash.h
11
src/hash.h
@@ -18,22 +18,23 @@
|
||||
|
||||
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 */
|
||||
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 */
|
||||
hash_t *hash_clone(hash_t *table);
|
||||
hash_t *hash_clone(hash_t * const table);
|
||||
|
||||
/** 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.
|
||||
* each key can appear only once; the value of any
|
||||
* 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 */
|
||||
void *hash_get(hash_t *table, const char *key);
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
* @return an allocated string with the full JID or NULL if no domain
|
||||
* is specified
|
||||
*/
|
||||
char *xmpp_jid_new(xmpp_ctx_t *ctx,
|
||||
const char *node,
|
||||
char *xmpp_jid_new(xmpp_ctx_t *ctx, const char *node,
|
||||
const char *domain,
|
||||
const char *resource)
|
||||
{
|
||||
@@ -37,8 +36,7 @@ char *xmpp_jid_new(xmpp_ctx_t *ctx,
|
||||
size_t len, nlen, dlen, rlen;
|
||||
|
||||
/* jid must at least have a domain */
|
||||
if (domain == NULL)
|
||||
return NULL;
|
||||
if (domain == NULL) return NULL;
|
||||
|
||||
/* accumulate lengths */
|
||||
dlen = strlen(domain);
|
||||
|
||||
@@ -21,8 +21,7 @@ struct MD5Context {
|
||||
};
|
||||
|
||||
void MD5Init(struct MD5Context *context);
|
||||
void MD5Update(struct MD5Context *context,
|
||||
unsigned char const *buf,
|
||||
void MD5Update(struct MD5Context *context, unsigned char const *buf,
|
||||
uint32_t len);
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
||||
|
||||
|
||||
84
src/oocontext.cpp
Normal file
84
src/oocontext.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/* oocontext.cpp
|
||||
** strophe XMPP client library -- C++ context implementation
|
||||
**
|
||||
** Copyright (C) 2005-2009 Collecta, Inc.
|
||||
**
|
||||
** 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 <stdlib.h>
|
||||
|
||||
#include "strophe.h"
|
||||
#include "strophepp.h"
|
||||
|
||||
XMPP::Context::Context()
|
||||
{
|
||||
m_mem.alloc = callAlloc;
|
||||
m_mem.realloc = callRealloc;
|
||||
m_mem.free = callFree;
|
||||
m_mem.userdata = (void *)this;
|
||||
|
||||
m_log.handler = callLog;
|
||||
m_log.userdata = (void *)this;
|
||||
|
||||
m_ctx = ::xmpp_ctx_new(&m_mem, &m_log);
|
||||
}
|
||||
|
||||
XMPP::Context::~Context()
|
||||
{
|
||||
::xmpp_ctx_free(m_ctx);
|
||||
}
|
||||
|
||||
void *XMPP::Context::alloc(const size_t size)
|
||||
{
|
||||
return ::malloc(size);
|
||||
}
|
||||
|
||||
void *XMPP::Context::realloc(void *p, const size_t size)
|
||||
{
|
||||
return ::realloc(p, size);
|
||||
}
|
||||
|
||||
void XMPP::Context::free(void *p)
|
||||
{
|
||||
::free(p);
|
||||
}
|
||||
|
||||
void XMPP::Context::log(const xmpp_log_level_t level,
|
||||
const char * const area,
|
||||
const char * const msg)
|
||||
{
|
||||
/* do nothing by default */
|
||||
}
|
||||
|
||||
xmpp_ctx_t *XMPP::Context::getContext()
|
||||
{
|
||||
return m_ctx;
|
||||
}
|
||||
|
||||
void *XMPP::Context::callAlloc(const size_t size, void * const userdata)
|
||||
{
|
||||
return reinterpret_cast<Context *>(userdata)->alloc(size);
|
||||
}
|
||||
|
||||
void *XMPP::Context::callRealloc(void *p, const size_t size,
|
||||
void * const userdata)
|
||||
{
|
||||
return reinterpret_cast<Context *>(userdata)->realloc(p, size);
|
||||
}
|
||||
|
||||
void XMPP::Context::callFree(void *p, void * const userdata)
|
||||
{
|
||||
reinterpret_cast<Context *>(userdata)->free(p);
|
||||
}
|
||||
|
||||
void XMPP::Context::callLog(void * const userdata,
|
||||
const xmpp_log_level_t level,
|
||||
const char * const area,
|
||||
const char * const msg)
|
||||
{
|
||||
reinterpret_cast<Context *>(userdata)->log(level, area, msg);
|
||||
}
|
||||
77
src/oostanza.cpp
Normal file
77
src/oostanza.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/* oostanza.cpp
|
||||
** strophe XMPP client library -- C++ context implementation
|
||||
**
|
||||
** Copyright (C) 2005-2009 Collecta, Inc.
|
||||
**
|
||||
** 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 "strophe.h"
|
||||
#include "strophepp.h"
|
||||
|
||||
using namespace XMPP;
|
||||
|
||||
void *Stanza::operator new(size_t size, Context *ctx)
|
||||
{
|
||||
void *p;
|
||||
|
||||
/* we must allocate extra room for the Context object so that the
|
||||
destructor can access it to free the object. C++ does not allow
|
||||
us to access normal members in the destructor, so we have to hide
|
||||
it. This must be prepended as well, since C++ will add stuff to
|
||||
the end in subclasses. */
|
||||
|
||||
p = ctx->alloc(size + sizeof(Context *));
|
||||
if (!p) return p;
|
||||
|
||||
*reinterpret_cast<Context **>(p) = ctx;
|
||||
p = reinterpret_cast<void *>(reinterpret_cast<char *>(p) +
|
||||
sizeof(Context *));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void Stanza::operator delete(void *p)
|
||||
{
|
||||
Context *ctx;
|
||||
|
||||
ctx = *reinterpret_cast<Context **>(reinterpret_cast<char *>(p) - 4);
|
||||
ctx->free(reinterpret_cast<char *>(p) - 4);
|
||||
}
|
||||
|
||||
Stanza::Stanza(Context *ctx)
|
||||
{
|
||||
m_ctx = ctx;
|
||||
m_stanza = ::xmpp_stanza_new(ctx->getContext());
|
||||
// TODO: check for errors
|
||||
}
|
||||
|
||||
Stanza::~Stanza()
|
||||
{
|
||||
}
|
||||
|
||||
Stanza *Stanza::create(Context *ctx)
|
||||
{
|
||||
return new (ctx) Stanza(ctx);
|
||||
}
|
||||
|
||||
void Stanza::release()
|
||||
{
|
||||
if (::xmpp_stanza_release(m_stanza))
|
||||
delete this;
|
||||
}
|
||||
|
||||
Stanza *Stanza::clone()
|
||||
{
|
||||
::xmpp_stanza_clone(m_stanza);
|
||||
return this;
|
||||
}
|
||||
|
||||
Stanza *Stanza::copy()
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
10
src/parser.h
10
src/parser.h
@@ -20,9 +20,13 @@
|
||||
|
||||
typedef struct _parser_t parser_t;
|
||||
|
||||
typedef void (*parser_start_callback)(char *name, char **attrs, void *userdata);
|
||||
typedef void (*parser_end_callback)(char *name, void *userdata);
|
||||
typedef void (*parser_stanza_callback)(xmpp_stanza_t *stanza, void *userdata);
|
||||
typedef void (*parser_start_callback)(char *name,
|
||||
char **attrs,
|
||||
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_start_callback startcb,
|
||||
|
||||
@@ -94,8 +94,7 @@ static char *_xml_name(xmpp_ctx_t *ctx, const char *nsname)
|
||||
size_t len;
|
||||
|
||||
c = strchr(nsname, namespace_sep);
|
||||
if (c == NULL)
|
||||
return xmpp_strdup(ctx, nsname);
|
||||
if (c == NULL) return xmpp_strdup(ctx, nsname);
|
||||
|
||||
c++;
|
||||
len = strlen(c);
|
||||
@@ -131,8 +130,7 @@ static void _set_attributes(xmpp_stanza_t *stanza, const XML_Char **attrs)
|
||||
char *attr;
|
||||
int i;
|
||||
|
||||
if (!attrs)
|
||||
return;
|
||||
if (!attrs) return;
|
||||
|
||||
for (i = 0; attrs[i]; i += 2) {
|
||||
/* namespaced attributes aren't used in xmpp, discard namespace */
|
||||
@@ -162,8 +160,9 @@ static void complete_inner_text(parser_t *parser)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_start_element(void *userdata, const XML_Char *nsname, const XML_Char **attrs)
|
||||
static void _start_element(void *userdata,
|
||||
const XML_Char *nsname,
|
||||
const XML_Char **attrs)
|
||||
{
|
||||
parser_t *parser = (parser_t *)userdata;
|
||||
xmpp_stanza_t *child;
|
||||
@@ -175,7 +174,8 @@ _start_element(void *userdata, const XML_Char *nsname, const XML_Char **attrs)
|
||||
if (parser->depth == 0) {
|
||||
/* notify the owner */
|
||||
if (parser->startcb)
|
||||
parser->startcb(name, (char **)attrs, parser->userdata);
|
||||
parser->startcb(name, (char **)attrs,
|
||||
parser->userdata);
|
||||
} else {
|
||||
/* build stanzas at depth 1 */
|
||||
if (!parser->stanza && parser->depth != 1) {
|
||||
@@ -201,10 +201,8 @@ _start_element(void *userdata, const XML_Char *nsname, const XML_Char **attrs)
|
||||
}
|
||||
}
|
||||
|
||||
if (ns)
|
||||
xmpp_free(parser->ctx, ns);
|
||||
if (name)
|
||||
xmpp_free(parser->ctx, name);
|
||||
if (ns) xmpp_free(parser->ctx, ns);
|
||||
if (name) xmpp_free(parser->ctx, name);
|
||||
|
||||
parser->depth++;
|
||||
}
|
||||
@@ -226,7 +224,8 @@ static void _end_element(void *userdata, const XML_Char *name)
|
||||
parser->stanza = parser->stanza->parent;
|
||||
} else {
|
||||
if (parser->stanzacb)
|
||||
parser->stanzacb(parser->stanza, parser->userdata);
|
||||
parser->stanzacb(parser->stanza,
|
||||
parser->userdata);
|
||||
xmpp_stanza_release(parser->stanza);
|
||||
parser->stanza = NULL;
|
||||
}
|
||||
@@ -238,14 +237,13 @@ static void _characters(void *userdata, const XML_Char *s, int len)
|
||||
parser_t *parser = (parser_t *)userdata;
|
||||
char *p;
|
||||
|
||||
if (parser->depth < 2)
|
||||
return;
|
||||
if (parser->depth < 2) return;
|
||||
|
||||
/* Join all parts to a single resulting string. Stanza is created in
|
||||
* _start_element() and _end_element(). */
|
||||
if (parser->inner_text_used + len >= parser->inner_text_size) {
|
||||
parser->inner_text_size =
|
||||
parser->inner_text_used + len + 1 + INNER_TEXT_PADDING;
|
||||
parser->inner_text_size = parser->inner_text_used + len + 1 +
|
||||
INNER_TEXT_PADDING;
|
||||
p = xmpp_realloc(parser->ctx, parser->inner_text,
|
||||
parser->inner_text_size);
|
||||
if (p == NULL) {
|
||||
@@ -295,26 +293,12 @@ char *parser_attr_name(xmpp_ctx_t *ctx, char *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 */
|
||||
void parser_free(parser_t *parser)
|
||||
{
|
||||
if (parser->expat)
|
||||
XML_ParserFree(parser->expat);
|
||||
|
||||
if (parser->stanza) {
|
||||
_free_parent_stanza(parser->stanza);
|
||||
parser->stanza = NULL;
|
||||
}
|
||||
|
||||
if (parser->inner_text) {
|
||||
xmpp_free (parser->ctx, parser->inner_text);
|
||||
parser->inner_text = NULL;
|
||||
@@ -344,7 +328,7 @@ int parser_reset(parser_t *parser)
|
||||
}
|
||||
|
||||
if (parser->stanza) {
|
||||
_free_parent_stanza(parser->stanza);
|
||||
xmpp_stanza_release(parser->stanza);
|
||||
parser->stanza = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,14 +36,13 @@ struct _parser_t {
|
||||
xmpp_stanza_t *stanza;
|
||||
};
|
||||
|
||||
static void
|
||||
_set_attributes(xmpp_stanza_t *stanza, int nattrs, const xmlChar **attrs)
|
||||
static void _set_attributes(xmpp_stanza_t *stanza, int nattrs,
|
||||
const xmlChar **attrs)
|
||||
{
|
||||
int i, len;
|
||||
char *value;
|
||||
|
||||
if (!attrs)
|
||||
return;
|
||||
if (!attrs) return;
|
||||
|
||||
/* SAX2 uses array of localname/prefix/uri/value_begin/value_end */
|
||||
for (i = 0; i < nattrs*5; i += 5) {
|
||||
@@ -60,19 +59,17 @@ _set_attributes(xmpp_stanza_t *stanza, int nattrs, const xmlChar **attrs)
|
||||
|
||||
/* SAX2 gives us the attrs in an incredibly inconvenient array,
|
||||
* convert it to what the start callback is expecting */
|
||||
static char **
|
||||
_convert_attrs(parser_t *parser, int nattrs, const xmlChar **attrs)
|
||||
static char **_convert_attrs(parser_t *parser, int nattrs,
|
||||
const xmlChar **attrs)
|
||||
{
|
||||
int c, i, o, len;
|
||||
char *value;
|
||||
char **ret;
|
||||
|
||||
if (!attrs)
|
||||
return NULL;
|
||||
if (!attrs) return NULL;
|
||||
|
||||
ret = xmpp_alloc(parser->ctx, (nattrs+1)*2*sizeof(char*));
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!ret) return NULL;
|
||||
memset(ret, 0, (nattrs+1)*2*sizeof(char*));
|
||||
|
||||
for (c = 0; c < nattrs; c++) {
|
||||
@@ -100,39 +97,29 @@ static void _free_cbattrs(parser_t *parser, char **attrs)
|
||||
return;
|
||||
|
||||
for (i = 0; attrs[i]; i += 2) {
|
||||
if (attrs[i])
|
||||
xmpp_free(parser->ctx, attrs[i]);
|
||||
if (attrs[i + 1])
|
||||
xmpp_free(parser->ctx, attrs[i + 1]);
|
||||
if (attrs[i]) xmpp_free(parser->ctx, attrs[i]);
|
||||
if (attrs[i+1]) xmpp_free(parser->ctx, attrs[i+1]);
|
||||
}
|
||||
|
||||
xmpp_free(parser->ctx, attrs);
|
||||
}
|
||||
|
||||
static void _start_element(void *userdata,
|
||||
const xmlChar *name,
|
||||
const xmlChar *prefix,
|
||||
const xmlChar *uri,
|
||||
int nnamespaces,
|
||||
const xmlChar **namespaces,
|
||||
int nattrs,
|
||||
int ndefaulted,
|
||||
const xmlChar **attrs)
|
||||
const xmlChar *name, const xmlChar *prefix,
|
||||
const xmlChar *uri, int nnamespaces,
|
||||
const xmlChar **namespaces, int nattrs,
|
||||
int ndefaulted, const xmlChar **attrs)
|
||||
{
|
||||
parser_t *parser = (parser_t *)userdata;
|
||||
xmpp_stanza_t *child;
|
||||
char **cbattrs;
|
||||
|
||||
UNUSED(prefix);
|
||||
UNUSED(nnamespaces);
|
||||
UNUSED(namespaces);
|
||||
UNUSED(ndefaulted);
|
||||
|
||||
if (parser->depth == 0) {
|
||||
/* notify the owner */
|
||||
if (parser->startcb) {
|
||||
cbattrs = _convert_attrs(parser, nattrs, attrs);
|
||||
parser->startcb((char *)name, cbattrs, parser->userdata);
|
||||
parser->startcb((char *)name, cbattrs,
|
||||
parser->userdata);
|
||||
_free_cbattrs(parser, cbattrs);
|
||||
}
|
||||
} else {
|
||||
@@ -176,16 +163,11 @@ static void _start_element(void *userdata,
|
||||
parser->depth++;
|
||||
}
|
||||
|
||||
static void _end_element(void *userdata,
|
||||
const xmlChar *name,
|
||||
const xmlChar *prefix,
|
||||
const xmlChar *uri)
|
||||
static void _end_element(void *userdata, const xmlChar *name,
|
||||
const xmlChar *prefix, const xmlChar *uri)
|
||||
{
|
||||
parser_t *parser = (parser_t *)userdata;
|
||||
|
||||
UNUSED(prefix);
|
||||
UNUSED(uri);
|
||||
|
||||
parser->depth--;
|
||||
|
||||
if (parser->depth == 0) {
|
||||
@@ -198,7 +180,8 @@ static void _end_element(void *userdata,
|
||||
parser->stanza = parser->stanza->parent;
|
||||
} else {
|
||||
if (parser->stanzacb)
|
||||
parser->stanzacb(parser->stanza, parser->userdata);
|
||||
parser->stanzacb(parser->stanza,
|
||||
parser->userdata);
|
||||
xmpp_stanza_release(parser->stanza);
|
||||
parser->stanza = NULL;
|
||||
}
|
||||
@@ -211,8 +194,7 @@ static void _characters(void *userdata, const xmlChar *chr, int len)
|
||||
xmpp_stanza_t *stanza;
|
||||
|
||||
/* skip unimportant whitespace, etc */
|
||||
if (parser->depth < 2)
|
||||
return;
|
||||
if (parser->depth < 2) return;
|
||||
|
||||
/* create and populate stanza */
|
||||
stanza = xmpp_stanza_new(parser->ctx);
|
||||
@@ -262,22 +244,13 @@ char *parser_attr_name(xmpp_ctx_t *ctx, char *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 */
|
||||
void parser_free(parser_t *parser)
|
||||
{
|
||||
if (parser->xmlctx)
|
||||
xmlFreeParserCtxt(parser->xmlctx);
|
||||
if (parser->stanza)
|
||||
_free_parent_stanza(parser->stanza);
|
||||
xmpp_stanza_release(parser->stanza);
|
||||
xmpp_free(parser->ctx, parser);
|
||||
}
|
||||
|
||||
@@ -287,13 +260,13 @@ int parser_reset(parser_t *parser)
|
||||
if (parser->xmlctx)
|
||||
xmlFreeParserCtxt(parser->xmlctx);
|
||||
if (parser->stanza)
|
||||
_free_parent_stanza(parser->stanza);
|
||||
xmpp_stanza_release(parser->stanza);
|
||||
|
||||
parser->stanza = NULL;
|
||||
parser->depth = 0;
|
||||
|
||||
parser->xmlctx =
|
||||
xmlCreatePushParserCtxt(&parser->handlers, parser, NULL, 0, NULL);
|
||||
parser->xmlctx = xmlCreatePushParserCtxt(&parser->handlers,
|
||||
parser, NULL, 0, NULL);
|
||||
|
||||
return parser->xmlctx ? 1 : 0;
|
||||
}
|
||||
|
||||
20
src/rand.c
20
src/rand.c
@@ -62,8 +62,8 @@ struct _xmpp_rand_t {
|
||||
/* adds two arrays as numbers in big-endian representation and stores
|
||||
* result in the first one.
|
||||
*/
|
||||
static void
|
||||
arr_add(uint8_t *arr1, size_t arr1_len, uint8_t *arr2, size_t arr2_len)
|
||||
static void arr_add(uint8_t *arr1, size_t arr1_len,
|
||||
uint8_t *arr2, size_t arr2_len)
|
||||
{
|
||||
size_t i;
|
||||
uint32_t acc;
|
||||
@@ -89,10 +89,8 @@ static void store_be32(uint32_t val, uint8_t be[4])
|
||||
be[3] = (uint8_t)(val & 0xff);
|
||||
}
|
||||
|
||||
static void Hash_df(uint8_t *input_string,
|
||||
size_t input_string_len,
|
||||
uint8_t *output_string,
|
||||
size_t no_of_bytes_to_return)
|
||||
static void Hash_df(uint8_t *input_string, size_t input_string_len,
|
||||
uint8_t *output_string, size_t no_of_bytes_to_return)
|
||||
{
|
||||
uint8_t counter;
|
||||
uint8_t temp[round_up(seedlen, outlen)];
|
||||
@@ -121,8 +119,7 @@ static void Hash_df(uint8_t *input_string,
|
||||
static void Hash_DRBG_Instantiate(Hash_DRBG_CTX *ctx,
|
||||
uint8_t *entropy_input,
|
||||
size_t entropy_input_len,
|
||||
uint8_t *nonce,
|
||||
size_t nonce_len)
|
||||
uint8_t *nonce, size_t nonce_len)
|
||||
{
|
||||
uint8_t seed_material[ENTROPY_MAX + NONCE_MAX];
|
||||
uint8_t seed0[seedlen + 1];
|
||||
@@ -165,8 +162,8 @@ static void Hash_DRBG_Reseed(Hash_DRBG_CTX *ctx,
|
||||
ctx->reseed_counter = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
Hashgen(uint8_t *V, uint8_t *output, size_t requested_number_of_bytes)
|
||||
static void Hashgen(uint8_t *V, uint8_t *output,
|
||||
size_t requested_number_of_bytes)
|
||||
{
|
||||
uint8_t data[seedlen];
|
||||
uint8_t W[GENERATE_MAX];
|
||||
@@ -190,8 +187,7 @@ Hashgen(uint8_t *V, uint8_t *output, size_t requested_number_of_bytes)
|
||||
}
|
||||
|
||||
/* assume additional_input is zero length string */
|
||||
static int Hash_DRBG_Generate(Hash_DRBG_CTX *ctx,
|
||||
uint8_t *output,
|
||||
static int Hash_DRBG_Generate(Hash_DRBG_CTX *ctx, uint8_t *output,
|
||||
size_t requested_number_of_bytes)
|
||||
{
|
||||
uint8_t H[outlen];
|
||||
|
||||
343
src/resolver.c
343
src/resolver.c
@@ -16,7 +16,7 @@
|
||||
#if !defined(_WIN32) && !defined(HAVE_CARES)
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <resolv.h>
|
||||
#include <resolv.h> /* res_query */
|
||||
#endif /* _WIN32 && HAVE_CARES */
|
||||
|
||||
#ifdef HAVE_CARES
|
||||
@@ -52,8 +52,7 @@ static int resolver_ares_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
const unsigned char *buf,
|
||||
size_t len,
|
||||
resolver_srv_rr_t **srv_rr_list);
|
||||
static int resolver_ares_srv_lookup(xmpp_ctx_t *ctx,
|
||||
const char *fulldomain,
|
||||
static int resolver_ares_srv_lookup(xmpp_ctx_t *ctx, const char *fulldomain,
|
||||
resolver_srv_rr_t **srv_rr_list);
|
||||
#endif /* HAVE_CARES */
|
||||
|
||||
@@ -64,14 +63,12 @@ static int resolver_raw_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
resolver_srv_rr_t **srv_rr_list);
|
||||
#endif /* !HAVE_CARES */
|
||||
|
||||
#if defined(_WIN32) && !defined(HAVE_CARES)
|
||||
static int resolver_win32_srv_lookup(xmpp_ctx_t *ctx,
|
||||
const char *fulldomain,
|
||||
#ifdef _WIN32
|
||||
static int resolver_win32_srv_lookup(xmpp_ctx_t *ctx, const char *fulldomain,
|
||||
resolver_srv_rr_t **srv_rr_list);
|
||||
static int resolver_win32_srv_query(const char *fulldomain,
|
||||
unsigned char *buf,
|
||||
size_t len);
|
||||
#endif /* _WIN32 && !HAVE_CARES */
|
||||
unsigned char *buf, size_t len);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*******************************************************************************
|
||||
* Implementation.
|
||||
@@ -121,7 +118,8 @@ static void resolver_srv_list_sort(resolver_srv_rr_t **srv_rr_list)
|
||||
*/
|
||||
if ((rr_current->priority > rr_next->priority) ||
|
||||
(rr_current->priority == rr_next->priority &&
|
||||
rr_current->weight < rr_next->weight)) {
|
||||
rr_current->weight < rr_next->weight))
|
||||
{
|
||||
/* Swap node */
|
||||
swap = 1;
|
||||
if (rr_prev != NULL) {
|
||||
@@ -147,10 +145,8 @@ static void resolver_srv_list_sort(resolver_srv_rr_t **srv_rr_list)
|
||||
*srv_rr_list = rr_head;
|
||||
}
|
||||
|
||||
int resolver_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
const unsigned char *buf,
|
||||
size_t len,
|
||||
resolver_srv_rr_t **srv_rr_list)
|
||||
int resolver_srv_lookup_buf(xmpp_ctx_t *ctx, const unsigned char *buf,
|
||||
size_t len, resolver_srv_rr_t **srv_rr_list)
|
||||
{
|
||||
int set;
|
||||
|
||||
@@ -164,11 +160,8 @@ int resolver_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
return set;
|
||||
}
|
||||
|
||||
int resolver_srv_lookup(xmpp_ctx_t *ctx,
|
||||
const char *service,
|
||||
const char *proto,
|
||||
const char *domain,
|
||||
resolver_srv_rr_t **srv_rr_list)
|
||||
int resolver_srv_lookup(xmpp_ctx_t *ctx, const char *service, const char *proto,
|
||||
const char *domain, resolver_srv_rr_t **srv_rr_list)
|
||||
{
|
||||
#define RESOLVER_BUF_MAX 65536
|
||||
unsigned char *buf;
|
||||
@@ -179,15 +172,13 @@ int resolver_srv_lookup(xmpp_ctx_t *ctx,
|
||||
(void)buf;
|
||||
(void)len;
|
||||
|
||||
xmpp_snprintf(fulldomain, sizeof(fulldomain), "_%s._%s.%s", service, proto,
|
||||
domain);
|
||||
xmpp_snprintf(fulldomain, sizeof(fulldomain),
|
||||
"_%s._%s.%s", service, proto, domain);
|
||||
|
||||
*srv_rr_list = NULL;
|
||||
|
||||
#ifdef HAVE_CARES
|
||||
|
||||
set = resolver_ares_srv_lookup(ctx, fulldomain, srv_rr_list);
|
||||
|
||||
#else /* HAVE_CARES */
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -268,11 +259,9 @@ static uint8_t message_header_rcode(const struct message_header *header)
|
||||
* Returns length of the non-truncated resulting string, may be bigger than
|
||||
* name_max.
|
||||
*/
|
||||
static size_t message_name_append_safe(char *name,
|
||||
size_t name_len,
|
||||
static size_t message_name_append_safe(char *name, size_t name_len,
|
||||
size_t name_max,
|
||||
const char *tail,
|
||||
size_t tail_len)
|
||||
const char *tail, size_t tail_len)
|
||||
{
|
||||
size_t copy_len;
|
||||
|
||||
@@ -285,11 +274,9 @@ static size_t message_name_append_safe(char *name,
|
||||
}
|
||||
|
||||
/* Returns length of the compressed name. This is NOT the same as strlen(). */
|
||||
static unsigned message_name_get(const unsigned char *buf,
|
||||
size_t buf_len,
|
||||
static unsigned message_name_get(const unsigned char *buf, size_t buf_len,
|
||||
unsigned buf_offset,
|
||||
char *name,
|
||||
size_t name_max)
|
||||
char *name, size_t name_max)
|
||||
{
|
||||
size_t name_len = 0;
|
||||
unsigned i = buf_offset;
|
||||
@@ -297,29 +284,26 @@ static unsigned message_name_get(const unsigned char *buf,
|
||||
unsigned rc;
|
||||
unsigned char label_len;
|
||||
|
||||
|
||||
while (1) {
|
||||
if (i >= buf_len)
|
||||
return 0;
|
||||
if (i >= buf_len) return 0;
|
||||
label_len = buf[i++];
|
||||
if (label_len == 0)
|
||||
break;
|
||||
if (label_len == 0) break;
|
||||
|
||||
/* Label */
|
||||
if ((label_len & 0xc0) == 0) {
|
||||
if (i + label_len - 1 >= buf_len)
|
||||
return 0;
|
||||
if (i + label_len - 1 >= buf_len) return 0;
|
||||
if (name != NULL) {
|
||||
name_len = message_name_append_safe(name, name_len, name_max,
|
||||
(char *)&buf[i], label_len);
|
||||
name_len =
|
||||
message_name_append_safe(name, name_len, name_max, ".", 1);
|
||||
name_len = message_name_append_safe(name, name_len, name_max,
|
||||
".", 1);
|
||||
}
|
||||
i += label_len;
|
||||
|
||||
/* Pointer */
|
||||
} else if ((label_len & 0xc0) == 0xc0) {
|
||||
if (i >= buf_len)
|
||||
return 0;
|
||||
if (i >= buf_len) return 0;
|
||||
pointer = (label_len & 0x3f) << 8 | buf[i++];
|
||||
if (name != NULL && name_len >= name_max && name_max > 0) {
|
||||
/* We have filled the name buffer. Don't pass it recursively. */
|
||||
@@ -327,11 +311,10 @@ static unsigned message_name_get(const unsigned char *buf,
|
||||
name = NULL;
|
||||
name_max = 0;
|
||||
}
|
||||
rc = message_name_get(
|
||||
buf, buf_len, pointer, name != NULL ? &name[name_len] : NULL,
|
||||
rc = message_name_get(buf, buf_len, pointer,
|
||||
name != NULL ? &name[name_len] : NULL,
|
||||
name_max > name_len ? name_max - name_len : 0);
|
||||
if (rc == 0)
|
||||
return 0;
|
||||
if (rc == 0) return 0;
|
||||
/* Pointer is always the last. */
|
||||
break;
|
||||
|
||||
@@ -341,8 +324,7 @@ static unsigned message_name_get(const unsigned char *buf,
|
||||
}
|
||||
}
|
||||
if (label_len == 0) {
|
||||
if (name_len == 0)
|
||||
name_len = 1;
|
||||
if (name_len == 0) name_len = 1;
|
||||
/*
|
||||
* At this point name_len is length of the resulting name,
|
||||
* including '\0'. This value can be exported to allocate buffer
|
||||
@@ -360,14 +342,13 @@ static unsigned message_name_get(const unsigned char *buf,
|
||||
return i - buf_offset;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
message_name_len(const unsigned char *buf, size_t buf_len, unsigned buf_offset)
|
||||
static unsigned message_name_len(const unsigned char *buf, size_t buf_len,
|
||||
unsigned buf_offset)
|
||||
{
|
||||
return message_name_get(buf, buf_len, buf_offset, NULL, SIZE_MAX);
|
||||
}
|
||||
|
||||
#define BUF_OVERFLOW_CHECK(ptr, len) \
|
||||
do { \
|
||||
#define BUF_OVERFLOW_CHECK(ptr, len) do { \
|
||||
if ((ptr) >= (len)) { \
|
||||
if (*srv_rr_list != NULL) \
|
||||
resolver_srv_free(ctx, *srv_rr_list); \
|
||||
@@ -403,7 +384,8 @@ static int resolver_raw_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
header.nscount = xmpp_ntohs_ptr(&buf[8]);
|
||||
header.arcount = xmpp_ntohs_ptr(&buf[10]);
|
||||
if (message_header_qr(&header) != MESSAGE_RESPONSE ||
|
||||
message_header_rcode(&header) != 0) {
|
||||
message_header_rcode(&header) != 0)
|
||||
{
|
||||
return XMPP_DOMAIN_NOT_FOUND;
|
||||
}
|
||||
j = MESSAGE_HEADER_LEN;
|
||||
@@ -413,8 +395,7 @@ static int resolver_raw_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
BUF_OVERFLOW_CHECK(j, len);
|
||||
name_len = message_name_len(buf, len, j);
|
||||
/* error in name format */
|
||||
if (name_len == 0)
|
||||
return XMPP_DOMAIN_NOT_FOUND;
|
||||
if (name_len == 0) return XMPP_DOMAIN_NOT_FOUND;
|
||||
j += name_len + 4;
|
||||
}
|
||||
|
||||
@@ -422,8 +403,7 @@ static int resolver_raw_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
BUF_OVERFLOW_CHECK(j, len);
|
||||
name_len = message_name_len(buf, len, j);
|
||||
/* error in name format */
|
||||
if (name_len == 0)
|
||||
return XMPP_DOMAIN_NOT_FOUND;
|
||||
if (name_len == 0) return XMPP_DOMAIN_NOT_FOUND;
|
||||
j += name_len;
|
||||
BUF_OVERFLOW_CHECK(j + 16, len);
|
||||
type = xmpp_ntohs_ptr(&buf[j]);
|
||||
@@ -497,13 +477,11 @@ static int resolver_ares_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
return *srv_rr_list == NULL ? XMPP_DOMAIN_NOT_FOUND : XMPP_DOMAIN_FOUND;
|
||||
}
|
||||
|
||||
static void ares_srv_lookup_callback(
|
||||
void *arg, int status, int timeouts, unsigned char *buf, int len)
|
||||
static void ares_srv_lookup_callback(void *arg, int status, int timeouts,
|
||||
unsigned char *buf, int len)
|
||||
{
|
||||
struct resolver_ares_ctx *actx = arg;
|
||||
|
||||
(void)timeouts;
|
||||
|
||||
if (status != ARES_SUCCESS)
|
||||
actx->result = XMPP_DOMAIN_NOT_FOUND;
|
||||
else
|
||||
@@ -511,8 +489,7 @@ static void ares_srv_lookup_callback(
|
||||
&actx->srv_rr_list);
|
||||
}
|
||||
|
||||
static int resolver_ares_srv_lookup(xmpp_ctx_t *ctx,
|
||||
const char *fulldomain,
|
||||
static int resolver_ares_srv_lookup(xmpp_ctx_t *ctx, const char *fulldomain,
|
||||
resolver_srv_rr_t **srv_rr_list)
|
||||
{
|
||||
struct resolver_ares_ctx actx;
|
||||
@@ -551,7 +528,7 @@ static int resolver_ares_srv_lookup(xmpp_ctx_t *ctx,
|
||||
|
||||
#endif /* HAVE_CARES */
|
||||
|
||||
#if defined(_WIN32) && !defined(HAVE_CARES)
|
||||
#ifdef _WIN32
|
||||
/*******************************************************************************
|
||||
* Next part was copied from sock.c and contains old win32 code.
|
||||
*
|
||||
@@ -567,9 +544,10 @@ static int resolver_ares_srv_lookup(xmpp_ctx_t *ctx,
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windns.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <Iphlpapi.h>
|
||||
|
||||
struct dnsquery_header {
|
||||
struct dnsquery_header
|
||||
{
|
||||
unsigned short id;
|
||||
unsigned char qr;
|
||||
unsigned char opcode;
|
||||
@@ -585,16 +563,14 @@ struct dnsquery_header {
|
||||
unsigned short arcount;
|
||||
};
|
||||
|
||||
struct dnsquery_question {
|
||||
struct dnsquery_question
|
||||
{
|
||||
char qname[1024];
|
||||
unsigned short qtype;
|
||||
unsigned short qclass;
|
||||
};
|
||||
|
||||
static void netbuf_add_16bitnum(unsigned char *buf,
|
||||
int buflen,
|
||||
int *offset,
|
||||
unsigned short num)
|
||||
static void netbuf_add_16bitnum(unsigned char *buf, int buflen, int *offset, unsigned short num)
|
||||
{
|
||||
unsigned char *start = buf + *offset;
|
||||
unsigned char *p = start;
|
||||
@@ -606,8 +582,8 @@ static void netbuf_add_16bitnum(unsigned char *buf,
|
||||
*offset += 2;
|
||||
}
|
||||
|
||||
static void
|
||||
netbuf_add_domain_name(unsigned char *buf, int buflen, int *offset, char *name)
|
||||
static void netbuf_add_domain_name(unsigned char *buf, int buflen, int *offset,
|
||||
char *name)
|
||||
{
|
||||
unsigned char *start = buf + *offset;
|
||||
unsigned char *p = start;
|
||||
@@ -615,26 +591,31 @@ netbuf_add_domain_name(unsigned char *buf, int buflen, int *offset, char *name)
|
||||
|
||||
wordstart = (unsigned char *)name;
|
||||
|
||||
while (*wordstart) {
|
||||
while (*wordstart)
|
||||
{
|
||||
int len;
|
||||
wordend = wordstart;
|
||||
while (*wordend && *wordend != '.') {
|
||||
while (*wordend && *wordend != '.')
|
||||
{
|
||||
wordend++;
|
||||
}
|
||||
|
||||
len = (int)(wordend - wordstart);
|
||||
|
||||
if (len > 0x3F) {
|
||||
if (len > 0x3F)
|
||||
{
|
||||
len = 0x3F;
|
||||
}
|
||||
|
||||
*p++ = len;
|
||||
|
||||
while (wordstart != wordend) {
|
||||
while (wordstart != wordend)
|
||||
{
|
||||
*p++ = *wordstart++;
|
||||
}
|
||||
|
||||
if (*wordstart == '.') {
|
||||
if (*wordstart == '.')
|
||||
{
|
||||
wordstart++;
|
||||
}
|
||||
}
|
||||
@@ -644,21 +625,21 @@ netbuf_add_domain_name(unsigned char *buf, int buflen, int *offset, char *name)
|
||||
*offset += (int)(p - start);
|
||||
}
|
||||
|
||||
static void netbuf_add_dnsquery_header(unsigned char *buf,
|
||||
int buflen,
|
||||
int *offset,
|
||||
struct dnsquery_header *header)
|
||||
static void netbuf_add_dnsquery_header(unsigned char *buf, int buflen, int *offset, struct dnsquery_header *header)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
netbuf_add_16bitnum(buf, buflen, offset, header->id);
|
||||
|
||||
p = buf + *offset;
|
||||
*p++ = ((header->qr & 0x01) << 7) | ((header->opcode & 0x0F) << 3) |
|
||||
((header->aa & 0x01) << 2) | ((header->tc & 0x01) << 1) |
|
||||
((header->rd & 0x01));
|
||||
*p++ = ((header->ra & 0x01) << 7) | ((header->z & 0x07) << 4) |
|
||||
((header->rcode & 0x0F));
|
||||
*p++ = ((header->qr & 0x01) << 7)
|
||||
| ((header->opcode & 0x0F) << 3)
|
||||
| ((header->aa & 0x01) << 2)
|
||||
| ((header->tc & 0x01) << 1)
|
||||
| ((header->rd & 0x01));
|
||||
*p++ = ((header->ra & 0x01) << 7)
|
||||
| ((header->z & 0x07) << 4)
|
||||
| ((header->rcode & 0x0F));
|
||||
*offset += 2;
|
||||
|
||||
netbuf_add_16bitnum(buf, buflen, offset, header->qdcount);
|
||||
@@ -667,38 +648,31 @@ static void netbuf_add_dnsquery_header(unsigned char *buf,
|
||||
netbuf_add_16bitnum(buf, buflen, offset, header->arcount);
|
||||
}
|
||||
|
||||
static void netbuf_add_dnsquery_question(unsigned char *buf,
|
||||
int buflen,
|
||||
int *offset,
|
||||
struct dnsquery_question *question)
|
||||
static void netbuf_add_dnsquery_question(unsigned char *buf, int buflen, int *offset, struct dnsquery_question *question)
|
||||
{
|
||||
netbuf_add_domain_name(buf, buflen, offset, question->qname);
|
||||
netbuf_add_16bitnum(buf, buflen, offset, question->qtype);
|
||||
netbuf_add_16bitnum(buf, buflen, offset, question->qclass);
|
||||
}
|
||||
|
||||
static int resolver_win32_srv_lookup(xmpp_ctx_t *ctx,
|
||||
const char *fulldomain,
|
||||
static int resolver_win32_srv_lookup(xmpp_ctx_t *ctx, const char *fulldomain,
|
||||
resolver_srv_rr_t **srv_rr_list)
|
||||
{
|
||||
resolver_srv_rr_t *rr;
|
||||
HINSTANCE hdnsapi = NULL;
|
||||
|
||||
DNS_STATUS(WINAPI * pDnsQuery_A)
|
||||
(PCSTR, WORD, DWORD, PIP4_ARRAY, DNS_RECORDA **, PVOID *);
|
||||
DNS_STATUS (WINAPI * pDnsQuery_A)(PCSTR, WORD, DWORD, PIP4_ARRAY, DNS_RECORDA**, PVOID*);
|
||||
void (WINAPI * pDnsRecordListFree)(DNS_RECORDA*, DNS_FREE_TYPE);
|
||||
|
||||
if (hdnsapi = LoadLibrary("dnsapi.dll")) {
|
||||
pDnsQuery_A = (void *)GetProcAddress(hdnsapi, "DnsQuery_A");
|
||||
pDnsRecordListFree =
|
||||
(void *)GetProcAddress(hdnsapi, "DnsRecordListFree");
|
||||
pDnsRecordListFree = (void *)GetProcAddress(hdnsapi, "DnsRecordListFree");
|
||||
|
||||
if (pDnsQuery_A && pDnsRecordListFree) {
|
||||
DNS_RECORDA *dnsrecords = NULL;
|
||||
DNS_STATUS error;
|
||||
|
||||
error = pDnsQuery_A(fulldomain, DNS_TYPE_SRV, DNS_QUERY_STANDARD,
|
||||
NULL, &dnsrecords, NULL);
|
||||
error = pDnsQuery_A(fulldomain, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &dnsrecords, NULL);
|
||||
|
||||
if (error == 0) {
|
||||
DNS_RECORDA *current = dnsrecords;
|
||||
@@ -730,15 +704,15 @@ static int resolver_win32_srv_lookup(xmpp_ctx_t *ctx,
|
||||
return *srv_rr_list != NULL ? XMPP_DOMAIN_FOUND : XMPP_DOMAIN_NOT_FOUND;
|
||||
}
|
||||
|
||||
static int
|
||||
resolver_win32_srv_query(const char *fulldomain, unsigned char *buf, size_t len)
|
||||
static int resolver_win32_srv_query(const char *fulldomain,
|
||||
unsigned char *buf, size_t len)
|
||||
{
|
||||
int set = 0;
|
||||
int insize = 0;
|
||||
|
||||
/* if dnsapi didn't work/isn't there, try querying the dns server manually
|
||||
*/
|
||||
if (!set) {
|
||||
/* if dnsapi didn't work/isn't there, try querying the dns server manually */
|
||||
if (!set)
|
||||
{
|
||||
struct dnsquery_header header;
|
||||
struct dnsquery_question question;
|
||||
int offset = 0;
|
||||
@@ -749,17 +723,18 @@ resolver_win32_srv_query(const char *fulldomain, unsigned char *buf, size_t len)
|
||||
int numdnsservers = 0;
|
||||
int j;
|
||||
|
||||
/* Try getting the DNS server ips from GetNetworkParams() in iphlpapi
|
||||
* first */
|
||||
if (!numdnsservers) {
|
||||
/* Try getting the DNS server ips from GetNetworkParams() in iphlpapi first */
|
||||
if (!numdnsservers)
|
||||
{
|
||||
HINSTANCE hiphlpapi = NULL;
|
||||
DWORD (WINAPI * pGetNetworkParams)(PFIXED_INFO, PULONG);
|
||||
|
||||
if (hiphlpapi = LoadLibrary("Iphlpapi.dll")) {
|
||||
pGetNetworkParams =
|
||||
(void *)GetProcAddress(hiphlpapi, "GetNetworkParams");
|
||||
if (hiphlpapi = LoadLibrary("Iphlpapi.dll"))
|
||||
{
|
||||
pGetNetworkParams = (void *)GetProcAddress(hiphlpapi, "GetNetworkParams");
|
||||
|
||||
if (pGetNetworkParams) {
|
||||
if (pGetNetworkParams)
|
||||
{
|
||||
FIXED_INFO *fi;
|
||||
ULONG len;
|
||||
DWORD error;
|
||||
@@ -768,13 +743,13 @@ resolver_win32_srv_query(const char *fulldomain, unsigned char *buf, size_t len)
|
||||
len = 65535;
|
||||
fi = (FIXED_INFO *)buffer;
|
||||
|
||||
if ((error = pGetNetworkParams(fi, &len)) ==
|
||||
ERROR_SUCCESS) {
|
||||
if ((error = pGetNetworkParams(fi, &len)) == ERROR_SUCCESS)
|
||||
{
|
||||
IP_ADDR_STRING *pias = &(fi->DnsServerList);
|
||||
|
||||
while (pias && numdnsservers < 16) {
|
||||
strcpy(dnsserverips[numdnsservers++],
|
||||
pias->IpAddress.String);
|
||||
while (pias && numdnsservers < 16)
|
||||
{
|
||||
strcpy(dnsserverips[numdnsservers++], pias->IpAddress.String);
|
||||
pias = pias->Next;
|
||||
}
|
||||
}
|
||||
@@ -784,49 +759,48 @@ resolver_win32_srv_query(const char *fulldomain, unsigned char *buf, size_t len)
|
||||
}
|
||||
|
||||
/* Next, try getting the DNS server ips from the registry */
|
||||
if (!numdnsservers) {
|
||||
if (!numdnsservers)
|
||||
{
|
||||
HKEY search;
|
||||
LONG error;
|
||||
|
||||
error = RegOpenKeyEx(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0,
|
||||
KEY_READ, &search);
|
||||
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ, &search);
|
||||
|
||||
if (error != ERROR_SUCCESS) {
|
||||
error = RegOpenKeyEx(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
"SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0,
|
||||
KEY_READ, &search);
|
||||
if (error != ERROR_SUCCESS)
|
||||
{
|
||||
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP", 0, KEY_READ, &search);
|
||||
}
|
||||
|
||||
if (error == ERROR_SUCCESS) {
|
||||
if (error == ERROR_SUCCESS)
|
||||
{
|
||||
char name[512];
|
||||
DWORD len = 512;
|
||||
|
||||
error = RegQueryValueEx(search, "NameServer", NULL, NULL,
|
||||
(LPBYTE)name, &len);
|
||||
error = RegQueryValueEx(search, "NameServer", NULL, NULL, (LPBYTE)name, &len);
|
||||
|
||||
if (error != ERROR_SUCCESS) {
|
||||
error = RegQueryValueEx(search, "DhcpNameServer", NULL,
|
||||
NULL, (LPBYTE)name, &len);
|
||||
if (error != ERROR_SUCCESS)
|
||||
{
|
||||
error = RegQueryValueEx(search, "DhcpNameServer", NULL, NULL, (LPBYTE)name, &len);
|
||||
}
|
||||
|
||||
if (error == ERROR_SUCCESS) {
|
||||
if (error == ERROR_SUCCESS)
|
||||
{
|
||||
char *parse = "0123456789.", *start, *end;
|
||||
start = name;
|
||||
end = name;
|
||||
name[len] = '\0';
|
||||
|
||||
while (*start && numdnsservers < 16) {
|
||||
while (strchr(parse, *end)) {
|
||||
while (*start && numdnsservers < 16)
|
||||
{
|
||||
while (strchr(parse, *end))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
|
||||
strncpy(dnsserverips[numdnsservers++], start,
|
||||
end - start);
|
||||
strncpy(dnsserverips[numdnsservers++], start, end - start);
|
||||
|
||||
while (*end && !strchr(parse, *end)) {
|
||||
while (*end && !strchr(parse, *end))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
|
||||
@@ -838,71 +812,72 @@ resolver_win32_srv_query(const char *fulldomain, unsigned char *buf, size_t len)
|
||||
RegCloseKey(search);
|
||||
}
|
||||
|
||||
if (!numdnsservers) {
|
||||
if (!numdnsservers)
|
||||
{
|
||||
HKEY searchlist;
|
||||
LONG error;
|
||||
|
||||
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\P"
|
||||
"arameters\\Interfaces",
|
||||
0, KEY_READ, &searchlist);
|
||||
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", 0, KEY_READ, &searchlist);
|
||||
|
||||
if (error == ERROR_SUCCESS) {
|
||||
if (error == ERROR_SUCCESS)
|
||||
{
|
||||
unsigned int i;
|
||||
DWORD numinterfaces = 0;
|
||||
|
||||
RegQueryInfoKey(searchlist, NULL, NULL, NULL, &numinterfaces,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
RegQueryInfoKey(searchlist, NULL, NULL, NULL, &numinterfaces, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
for (i = 0; i < numinterfaces; i++) {
|
||||
for (i = 0; i < numinterfaces; i++)
|
||||
{
|
||||
char name[512];
|
||||
DWORD len = 512;
|
||||
HKEY searchentry;
|
||||
|
||||
RegEnumKeyEx(searchlist, i, (LPTSTR)name, &len, NULL, NULL,
|
||||
NULL, NULL);
|
||||
RegEnumKeyEx(searchlist, i, (LPTSTR)name, &len, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (RegOpenKeyEx(searchlist, name, 0, KEY_READ,
|
||||
&searchentry) == ERROR_SUCCESS) {
|
||||
if (RegQueryValueEx(searchentry, "DhcpNameServer", NULL,
|
||||
NULL, (LPBYTE)name,
|
||||
&len) == ERROR_SUCCESS) {
|
||||
if (RegOpenKeyEx(searchlist, name, 0, KEY_READ, &searchentry) == ERROR_SUCCESS)
|
||||
{
|
||||
if (RegQueryValueEx(searchentry, "DhcpNameServer", NULL, NULL, (LPBYTE)name, &len) == ERROR_SUCCESS)
|
||||
{
|
||||
char *parse = "0123456789.", *start, *end;
|
||||
start = name;
|
||||
end = name;
|
||||
name[len] = '\0';
|
||||
|
||||
while (*start && numdnsservers < 16) {
|
||||
while (strchr(parse, *end)) {
|
||||
while (*start && numdnsservers < 16)
|
||||
{
|
||||
while (strchr(parse, *end))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
|
||||
strncpy(dnsserverips[numdnsservers++], start,
|
||||
end - start);
|
||||
strncpy(dnsserverips[numdnsservers++], start, end - start);
|
||||
|
||||
while (*end && !strchr(parse, *end)) {
|
||||
while (*end && !strchr(parse, *end))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
|
||||
start = end;
|
||||
}
|
||||
} else if (RegQueryValueEx(searchentry, "NameServer",
|
||||
NULL, NULL, (LPBYTE)name,
|
||||
&len) == ERROR_SUCCESS) {
|
||||
}
|
||||
else if (RegQueryValueEx(searchentry, "NameServer", NULL, NULL, (LPBYTE)name, &len) == ERROR_SUCCESS)
|
||||
{
|
||||
char *parse = "0123456789.", *start, *end;
|
||||
start = name;
|
||||
end = name;
|
||||
name[len] = '\0';
|
||||
|
||||
while (*start && numdnsservers < 16) {
|
||||
while (strchr(parse, *end)) {
|
||||
while (*start && numdnsservers < 16)
|
||||
{
|
||||
while (strchr(parse, *end))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
|
||||
strncpy(dnsserverips[numdnsservers++], start,
|
||||
end - start);
|
||||
strncpy(dnsserverips[numdnsservers++], start, end - start);
|
||||
|
||||
while (*end && !strchr(parse, *end)) {
|
||||
while (*end && !strchr(parse, *end))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
|
||||
@@ -917,7 +892,8 @@ resolver_win32_srv_query(const char *fulldomain, unsigned char *buf, size_t len)
|
||||
}
|
||||
|
||||
/* If we have a DNS server, use it */
|
||||
if (numdnsservers) {
|
||||
if (numdnsservers)
|
||||
{
|
||||
ULONG nonblocking = 1;
|
||||
int i;
|
||||
|
||||
@@ -930,13 +906,14 @@ resolver_win32_srv_query(const char *fulldomain, unsigned char *buf, size_t len)
|
||||
|
||||
memset(&question, 0, sizeof(question));
|
||||
strncpy(question.qname, fulldomain, 1024);
|
||||
question.qtype = MESSAGE_T_SRV; /* SRV */
|
||||
question.qclass = MESSAGE_C_IN; /* INTERNET! */
|
||||
question.qtype = 33; /* SRV */
|
||||
question.qclass = 1; /* INTERNET! */
|
||||
|
||||
netbuf_add_dnsquery_question(buf, (int)len, &offset, &question);
|
||||
|
||||
insize = 0;
|
||||
for (i = 0; i < numdnsservers && insize <= 0; i++) {
|
||||
for (i = 0; i < numdnsservers && insize <= 0; i++)
|
||||
{
|
||||
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
ioctlsocket(sock, FIONBIO, &nonblocking);
|
||||
|
||||
@@ -947,18 +924,23 @@ resolver_win32_srv_query(const char *fulldomain, unsigned char *buf, size_t len)
|
||||
dnsaddr.sin_addr.s_addr = inet_addr(dnsserverips[i]);
|
||||
|
||||
addrlen = sizeof(dnsaddr);
|
||||
sendto(sock, (char *)buf, offset, 0,
|
||||
(struct sockaddr *)&dnsaddr, addrlen);
|
||||
for (j = 0; j < 50; j++) {
|
||||
insize = recvfrom(sock, (char *)buf, (int)len, 0,
|
||||
(struct sockaddr *)&dnsaddr, &addrlen);
|
||||
if (insize == SOCKET_ERROR) {
|
||||
if (sock_error() == WSAEWOULDBLOCK) {
|
||||
sendto(sock, (char *)buf, offset, 0, (struct sockaddr *)&dnsaddr, addrlen);
|
||||
for (j = 0; j < 50; j++)
|
||||
{
|
||||
insize = recvfrom(sock, (char *)buf, (int)len, 0, (struct sockaddr *)&dnsaddr, &addrlen);
|
||||
if (insize == SOCKET_ERROR)
|
||||
{
|
||||
if (sock_error() == WSAEWOULDBLOCK)
|
||||
{
|
||||
Sleep(100);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -967,9 +949,10 @@ resolver_win32_srv_query(const char *fulldomain, unsigned char *buf, size_t len)
|
||||
}
|
||||
set = insize > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return set ? insize : -1;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 && !HAVE_CARES */
|
||||
#endif /* _WIN32 */
|
||||
|
||||
@@ -46,10 +46,8 @@ void resolver_shutdown(void);
|
||||
*
|
||||
* @return XMPP_DOMAIN_FOUND on success or XMPP_DOMAIN_NOT_FOUND on fail
|
||||
*/
|
||||
int resolver_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
const unsigned char *buf,
|
||||
size_t len,
|
||||
resolver_srv_rr_t **srv_rr_list);
|
||||
int resolver_srv_lookup_buf(xmpp_ctx_t *ctx, const unsigned char *buf,
|
||||
size_t len, resolver_srv_rr_t **srv_rr_list);
|
||||
/** Resolve SRV record.
|
||||
*
|
||||
* @param ctx a Strophe context object
|
||||
@@ -60,11 +58,8 @@ int resolver_srv_lookup_buf(xmpp_ctx_t *ctx,
|
||||
*
|
||||
* @return XMPP_DOMAIN_FOUND on success or XMPP_DOMAIN_NOT_FOUND on fail
|
||||
*/
|
||||
int resolver_srv_lookup(xmpp_ctx_t *ctx,
|
||||
const char *service,
|
||||
const char *proto,
|
||||
const char *domain,
|
||||
resolver_srv_rr_t **srv_rr_list);
|
||||
int resolver_srv_lookup(xmpp_ctx_t *ctx, const char *service, const char *proto,
|
||||
const char *domain, resolver_srv_rr_t **srv_rr_list);
|
||||
|
||||
/** Release a list returned by resolver_srv_lookup() or
|
||||
* resolver_srv_lookup_buf().
|
||||
|
||||
104
src/sasl.c
104
src/sasl.c
@@ -21,6 +21,7 @@
|
||||
#include "ostypes.h"
|
||||
#include "sasl.h"
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include "scram.h"
|
||||
#include "rand.h"
|
||||
#include "util.h"
|
||||
@@ -35,9 +36,9 @@
|
||||
# endif
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
|
||||
/** generate authentication string for the SASL PLAIN mechanism */
|
||||
char *sasl_plain(xmpp_ctx_t *ctx, const char *authid, const char *password)
|
||||
{
|
||||
char *sasl_plain(xmpp_ctx_t *ctx, const char *authid, const char *password) {
|
||||
size_t idlen, passlen;
|
||||
size_t msglen;
|
||||
char *result = NULL;
|
||||
@@ -65,7 +66,7 @@ char *sasl_plain(xmpp_ctx_t *ctx, const char *authid, const char *password)
|
||||
/** helpers for digest auth */
|
||||
|
||||
/* 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;
|
||||
|
||||
@@ -112,17 +113,13 @@ static hash_t *_parse_digest_challenge(xmpp_ctx_t *ctx, const char *msg)
|
||||
s = text;
|
||||
while (*s != '\0') {
|
||||
/* skip any leading commas and spaces */
|
||||
while ((*s == ',') || (*s == ' '))
|
||||
s++;
|
||||
while ((*s == ',') || (*s == ' ')) s++;
|
||||
/* accumulate a key ending at '=' */
|
||||
t = s;
|
||||
while ((*t != '=') && (*t != '\0'))
|
||||
t++;
|
||||
if (*t == '\0')
|
||||
break; /* bad string */
|
||||
while ((*t != '=') && (*t != '\0')) t++;
|
||||
if (*t == '\0') break; /* bad string */
|
||||
key = _make_string(ctx, (char *)s, (t-s));
|
||||
if (key == NULL)
|
||||
break;
|
||||
if (key == NULL) break;
|
||||
/* advance our start pointer past the key */
|
||||
s = t + 1;
|
||||
t = s;
|
||||
@@ -139,8 +136,7 @@ static hash_t *_parse_digest_challenge(xmpp_ctx_t *ctx, const char *msg)
|
||||
}
|
||||
/* otherwise, accumulate a value ending in ',' or '\0' */
|
||||
} else {
|
||||
while ((*t != ',') && (*t != '\0'))
|
||||
t++;
|
||||
while ((*t != ',') && (*t != '\0')) t++;
|
||||
value = _make_string(ctx, (char *)s, (t-s));
|
||||
s = t;
|
||||
}
|
||||
@@ -172,8 +168,8 @@ static void _digest_to_hex(const char *digest, char *hex)
|
||||
}
|
||||
|
||||
/** append 'key="value"' to a buffer, growing as necessary */
|
||||
static char *
|
||||
_add_key(xmpp_ctx_t *ctx, hash_t *table, const char *key, char *buf, int quote)
|
||||
static char *_add_key(xmpp_ctx_t *ctx, hash_t *table, const char *key,
|
||||
char *buf, int *len, int quote)
|
||||
{
|
||||
int olen,nlen;
|
||||
int keylen, valuelen;
|
||||
@@ -185,8 +181,7 @@ _add_key(xmpp_ctx_t *ctx, hash_t *table, const char *key, char *buf, int quote)
|
||||
buf = xmpp_alloc(ctx, 1);
|
||||
buf[0] = '\0';
|
||||
}
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
if (buf == NULL) return NULL;
|
||||
|
||||
/* get current string length */
|
||||
olen = strlen(buf);
|
||||
@@ -209,33 +204,27 @@ _add_key(xmpp_ctx_t *ctx, hash_t *table, const char *key, char *buf, int quote)
|
||||
|
||||
if (buf != NULL) {
|
||||
c = buf + olen;
|
||||
if (olen)
|
||||
*c++ = ',';
|
||||
memcpy(c, key, keylen);
|
||||
c += keylen;
|
||||
if (olen) *c++ = ',';
|
||||
memcpy(c, key, keylen); c += keylen;
|
||||
*c++ = '=';
|
||||
memcpy(c, qvalue, valuelen);
|
||||
c += valuelen;
|
||||
memcpy(c, qvalue, valuelen); c += valuelen;
|
||||
*c++ = '\0';
|
||||
}
|
||||
|
||||
if (quote)
|
||||
xmpp_free(ctx, (char *)qvalue);
|
||||
if (quote) xmpp_free(ctx, (char *)qvalue);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** generate auth response string for the SASL DIGEST-MD5 mechanism */
|
||||
char *sasl_digest_md5(xmpp_ctx_t *ctx,
|
||||
const char *challenge,
|
||||
const char *jid,
|
||||
const char *password)
|
||||
{
|
||||
char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
|
||||
const char *jid, const char *password) {
|
||||
hash_t *table;
|
||||
char *result = NULL;
|
||||
char *node, *domain, *realm;
|
||||
char *value;
|
||||
char *response;
|
||||
int rlen;
|
||||
struct MD5Context MD5;
|
||||
unsigned char digest[16], HA1[16], HA2[16];
|
||||
char hex[32];
|
||||
@@ -351,15 +340,16 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx,
|
||||
|
||||
/* construct reply */
|
||||
result = NULL;
|
||||
result = _add_key(ctx, table, "username", result, 1);
|
||||
result = _add_key(ctx, table, "realm", result, 1);
|
||||
result = _add_key(ctx, table, "nonce", result, 1);
|
||||
result = _add_key(ctx, table, "cnonce", result, 1);
|
||||
result = _add_key(ctx, table, "nc", result, 0);
|
||||
result = _add_key(ctx, table, "qop", result, 0);
|
||||
result = _add_key(ctx, table, "digest-uri", result, 1);
|
||||
result = _add_key(ctx, table, "response", result, 0);
|
||||
result = _add_key(ctx, table, "charset", result, 0);
|
||||
rlen = 0;
|
||||
result = _add_key(ctx, table, "username", result, &rlen, 1);
|
||||
result = _add_key(ctx, table, "realm", result, &rlen, 1);
|
||||
result = _add_key(ctx, table, "nonce", result, &rlen, 1);
|
||||
result = _add_key(ctx, table, "cnonce", result, &rlen, 1);
|
||||
result = _add_key(ctx, table, "nc", result, &rlen, 0);
|
||||
result = _add_key(ctx, table, "qop", result, &rlen, 0);
|
||||
result = _add_key(ctx, table, "digest-uri", result, &rlen, 1);
|
||||
result = _add_key(ctx, table, "response", result, &rlen, 0);
|
||||
result = _add_key(ctx, table, "charset", result, &rlen, 0);
|
||||
|
||||
xmpp_free(ctx, node);
|
||||
xmpp_free(ctx, domain);
|
||||
@@ -372,16 +362,13 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx,
|
||||
return response;
|
||||
}
|
||||
|
||||
/** generate auth response string for the SASL SCRAM mechanism */
|
||||
char *sasl_scram(xmpp_ctx_t *ctx,
|
||||
const struct hash_alg *alg,
|
||||
const char *challenge,
|
||||
const char *first_bare,
|
||||
const char *jid,
|
||||
/** generate auth response string for the SASL SCRAM-SHA-1 mechanism */
|
||||
char *sasl_scram_sha1(xmpp_ctx_t *ctx, const char *challenge,
|
||||
const char *first_bare, const char *jid,
|
||||
const char *password)
|
||||
{
|
||||
uint8_t key[SCRAM_DIGEST_SIZE];
|
||||
uint8_t sign[SCRAM_DIGEST_SIZE];
|
||||
uint8_t key[SHA1_DIGEST_SIZE];
|
||||
uint8_t sign[SHA1_DIGEST_SIZE];
|
||||
char *r = NULL;
|
||||
char *s = NULL;
|
||||
char *i = NULL;
|
||||
@@ -398,8 +385,7 @@ char *sasl_scram(xmpp_ctx_t *ctx,
|
||||
char *result = NULL;
|
||||
size_t response_len;
|
||||
size_t auth_len;
|
||||
|
||||
UNUSED(jid);
|
||||
int j;
|
||||
|
||||
tmp = xmpp_strdup(ctx, challenge);
|
||||
if (!tmp) {
|
||||
@@ -434,8 +420,7 @@ char *sasl_scram(xmpp_ctx_t *ctx,
|
||||
goto out_sval;
|
||||
}
|
||||
|
||||
/* "c=biws," + r + ",p=" + sign_b64 + '\0' */
|
||||
response_len = 7 + strlen(r) + 3 + ((alg->digest_size + 2) / 3 * 4) + 1;
|
||||
response_len = 39 + strlen(r);
|
||||
response = xmpp_alloc(ctx, response_len);
|
||||
if (!response) {
|
||||
goto out_auth;
|
||||
@@ -445,17 +430,18 @@ char *sasl_scram(xmpp_ctx_t *ctx,
|
||||
xmpp_snprintf(auth, auth_len, "%s,%s,%s", first_bare + 3, challenge,
|
||||
response);
|
||||
|
||||
SCRAM_ClientKey(alg, (uint8_t *)password, strlen(password), (uint8_t *)sval,
|
||||
sval_len, (uint32_t)ival, key);
|
||||
SCRAM_ClientSignature(alg, key, (uint8_t *)auth, strlen(auth), sign);
|
||||
SCRAM_ClientProof(alg, sign, key, sign);
|
||||
SCRAM_SHA1_ClientKey((uint8_t *)password, strlen(password),
|
||||
(uint8_t *)sval, sval_len, (uint32_t)ival, key);
|
||||
SCRAM_SHA1_ClientSignature(key, (uint8_t *)auth, strlen(auth), sign);
|
||||
for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
|
||||
sign[j] ^= key[j];
|
||||
}
|
||||
|
||||
sign_b64 = xmpp_base64_encode(ctx, sign, alg->digest_size);
|
||||
sign_b64 = xmpp_base64_encode(ctx, sign, sizeof(sign));
|
||||
if (!sign_b64) {
|
||||
goto out_response;
|
||||
}
|
||||
|
||||
/* Check for buffer overflow */
|
||||
if (strlen(response) + strlen(sign_b64) + 3 + 1 > response_len) {
|
||||
xmpp_free(ctx, sign_b64);
|
||||
goto out_response;
|
||||
@@ -464,8 +450,8 @@ char *sasl_scram(xmpp_ctx_t *ctx,
|
||||
strcat(response, sign_b64);
|
||||
xmpp_free(ctx, sign_b64);
|
||||
|
||||
response_b64 =
|
||||
xmpp_base64_encode(ctx, (unsigned char *)response, strlen(response));
|
||||
response_b64 = xmpp_base64_encode(ctx, (unsigned char *)response,
|
||||
strlen(response));
|
||||
if (!response_b64) {
|
||||
goto out_response;
|
||||
}
|
||||
|
||||
14
src/sasl.h
14
src/sasl.h
@@ -17,20 +17,14 @@
|
||||
#define __LIBSTROPHE_SASL_H__
|
||||
|
||||
#include "strophe.h"
|
||||
#include "scram.h"
|
||||
|
||||
/** low-level sasl routines */
|
||||
|
||||
char *sasl_plain(xmpp_ctx_t *ctx, const char *authid, const char *password);
|
||||
char *sasl_digest_md5(xmpp_ctx_t *ctx,
|
||||
const char *challenge,
|
||||
const char *jid,
|
||||
const char *password);
|
||||
char *sasl_scram(xmpp_ctx_t *ctx,
|
||||
const struct hash_alg *alg,
|
||||
const char *challenge,
|
||||
const char *first_bare,
|
||||
const char *jid,
|
||||
char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
|
||||
const char *jid, const char *password);
|
||||
char *sasl_scram_sha1(xmpp_ctx_t *ctx, const char *challenge,
|
||||
const char *first_bare, const char *jid,
|
||||
const char *password);
|
||||
|
||||
#endif /* _LIBXMPP_SASL_H__ */
|
||||
|
||||
138
src/scram.c
138
src/scram.c
@@ -19,103 +19,56 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "sha256.h"
|
||||
#include "sha512.h"
|
||||
#include "ostypes.h"
|
||||
|
||||
#include "scram.h"
|
||||
|
||||
#define HMAC_BLOCK_SIZE_MAX 128
|
||||
#define HMAC_BLOCK_SIZE 64
|
||||
|
||||
static const uint8_t ipad = 0x36;
|
||||
static const uint8_t opad = 0x5C;
|
||||
|
||||
const struct hash_alg scram_sha1 = {
|
||||
"SCRAM-SHA-1",
|
||||
SASL_MASK_SCRAMSHA1,
|
||||
SHA1_DIGEST_SIZE,
|
||||
(void (*)(const uint8_t *, size_t, uint8_t *))crypto_SHA1,
|
||||
(void (*)(void *))crypto_SHA1_Init,
|
||||
(void (*)(void *, const uint8_t *, size_t))crypto_SHA1_Update,
|
||||
(void (*)(void *, uint8_t *))crypto_SHA1_Final};
|
||||
|
||||
const struct hash_alg scram_sha256 = {
|
||||
"SCRAM-SHA-256",
|
||||
SASL_MASK_SCRAMSHA256,
|
||||
SHA256_DIGEST_SIZE,
|
||||
(void (*)(const uint8_t *, size_t, uint8_t *))sha256_hash,
|
||||
(void (*)(void *))sha256_init,
|
||||
(void (*)(void *, const uint8_t *, size_t))sha256_process,
|
||||
(void (*)(void *, uint8_t *))sha256_done};
|
||||
|
||||
const struct hash_alg scram_sha512 = {
|
||||
"SCRAM-SHA-512",
|
||||
SASL_MASK_SCRAMSHA512,
|
||||
SHA512_DIGEST_SIZE,
|
||||
(void (*)(const uint8_t *, size_t, uint8_t *))sha512_hash,
|
||||
(void (*)(void *))sha512_init,
|
||||
(void (*)(void *, const uint8_t *, size_t))sha512_process,
|
||||
(void (*)(void *, uint8_t *))sha512_done};
|
||||
|
||||
union common_hash_ctx {
|
||||
SHA1_CTX sha1;
|
||||
sha256_context sha256;
|
||||
sha512_context sha512;
|
||||
};
|
||||
|
||||
static void crypto_HMAC(const struct hash_alg *alg,
|
||||
const uint8_t *key,
|
||||
size_t key_len,
|
||||
const uint8_t *text,
|
||||
size_t len,
|
||||
static void crypto_HMAC_SHA1(const uint8_t *key, size_t key_len,
|
||||
const uint8_t *text, size_t len,
|
||||
uint8_t *digest)
|
||||
{
|
||||
uint8_t key_pad[HMAC_BLOCK_SIZE_MAX];
|
||||
uint8_t key_ipad[HMAC_BLOCK_SIZE_MAX];
|
||||
uint8_t key_opad[HMAC_BLOCK_SIZE_MAX];
|
||||
uint8_t sha_digest[SCRAM_DIGEST_SIZE];
|
||||
size_t blocksize;
|
||||
size_t i;
|
||||
union common_hash_ctx ctx;
|
||||
uint8_t key_pad[HMAC_BLOCK_SIZE];
|
||||
uint8_t key_ipad[HMAC_BLOCK_SIZE];
|
||||
uint8_t key_opad[HMAC_BLOCK_SIZE];
|
||||
uint8_t sha_digest[SHA1_DIGEST_SIZE];
|
||||
int i;
|
||||
SHA1_CTX ctx;
|
||||
|
||||
assert(alg->digest_size <= HMAC_BLOCK_SIZE_MAX);
|
||||
blocksize = alg->digest_size < 48 ? 64 : 128;
|
||||
|
||||
memset(key_pad, 0, blocksize);
|
||||
if (key_len <= blocksize) {
|
||||
memset(key_pad, 0, sizeof(key_pad));
|
||||
if (key_len <= HMAC_BLOCK_SIZE) {
|
||||
memcpy(key_pad, key, key_len);
|
||||
} else {
|
||||
/* according to RFC2104 */
|
||||
alg->hash(key, key_len, key_pad);
|
||||
crypto_SHA1(key, key_len, key_pad);
|
||||
}
|
||||
|
||||
for (i = 0; i < blocksize; i++) {
|
||||
for (i = 0; i < HMAC_BLOCK_SIZE; i++) {
|
||||
key_ipad[i] = key_pad[i] ^ ipad;
|
||||
key_opad[i] = key_pad[i] ^ opad;
|
||||
}
|
||||
|
||||
alg->init((void *)&ctx);
|
||||
alg->update((void *)&ctx, key_ipad, blocksize);
|
||||
alg->update((void *)&ctx, text, len);
|
||||
alg->final((void *)&ctx, sha_digest);
|
||||
crypto_SHA1_Init(&ctx);
|
||||
crypto_SHA1_Update(&ctx, key_ipad, HMAC_BLOCK_SIZE);
|
||||
crypto_SHA1_Update(&ctx, text, len);
|
||||
crypto_SHA1_Final(&ctx, sha_digest);
|
||||
|
||||
alg->init((void *)&ctx);
|
||||
alg->update((void *)&ctx, key_opad, blocksize);
|
||||
alg->update((void *)&ctx, sha_digest, alg->digest_size);
|
||||
alg->final((void *)&ctx, digest);
|
||||
crypto_SHA1_Init(&ctx);
|
||||
crypto_SHA1_Update(&ctx, key_opad, HMAC_BLOCK_SIZE);
|
||||
crypto_SHA1_Update(&ctx, sha_digest, SHA1_DIGEST_SIZE);
|
||||
crypto_SHA1_Final(&ctx, digest);
|
||||
}
|
||||
|
||||
static void SCRAM_Hi(const struct hash_alg *alg,
|
||||
const uint8_t *text,
|
||||
size_t len,
|
||||
const uint8_t *salt,
|
||||
size_t salt_len,
|
||||
uint32_t i,
|
||||
static void SCRAM_SHA1_Hi(const uint8_t *text, size_t len,
|
||||
const uint8_t *salt, size_t salt_len, uint32_t i,
|
||||
uint8_t *digest)
|
||||
{
|
||||
size_t k;
|
||||
int k;
|
||||
uint32_t j;
|
||||
uint8_t tmp[128];
|
||||
|
||||
@@ -124,7 +77,7 @@ static void SCRAM_Hi(const struct hash_alg *alg,
|
||||
/* assume salt + INT(1) isn't longer than sizeof(tmp) */
|
||||
assert(salt_len <= sizeof(tmp) - sizeof(int1));
|
||||
|
||||
memset(digest, 0, alg->digest_size);
|
||||
memset(digest, 0, SHA1_DIGEST_SIZE);
|
||||
if (i == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -133,53 +86,46 @@ static void SCRAM_Hi(const struct hash_alg *alg,
|
||||
memcpy(&tmp[salt_len], int1, sizeof(int1));
|
||||
|
||||
/* 'text' for Hi is a 'key' for HMAC */
|
||||
crypto_HMAC(alg, text, len, tmp, salt_len + sizeof(int1), digest);
|
||||
memcpy(tmp, digest, alg->digest_size);
|
||||
crypto_HMAC_SHA1(text, len, tmp, salt_len + sizeof(int1), digest);
|
||||
memcpy(tmp, digest, SHA1_DIGEST_SIZE);
|
||||
|
||||
for (j = 1; j < i; j++) {
|
||||
crypto_HMAC(alg, text, len, tmp, alg->digest_size, tmp);
|
||||
for (k = 0; k < alg->digest_size; k++) {
|
||||
crypto_HMAC_SHA1(text, len, tmp, SHA1_DIGEST_SIZE, tmp);
|
||||
for (k = 0; k < SHA1_DIGEST_SIZE; k++) {
|
||||
digest[k] ^= tmp[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SCRAM_ClientKey(const struct hash_alg *alg,
|
||||
const uint8_t *password,
|
||||
size_t len,
|
||||
const uint8_t *salt,
|
||||
size_t salt_len,
|
||||
uint32_t i,
|
||||
void SCRAM_SHA1_ClientKey(const uint8_t *password, size_t len,
|
||||
const uint8_t *salt, size_t salt_len, uint32_t i,
|
||||
uint8_t *key)
|
||||
{
|
||||
uint8_t salted[SCRAM_DIGEST_SIZE];
|
||||
uint8_t salted[SHA1_DIGEST_SIZE];
|
||||
|
||||
/* XXX: Normalize(password) is omitted */
|
||||
|
||||
SCRAM_Hi(alg, password, len, salt, salt_len, i, salted);
|
||||
crypto_HMAC(alg, salted, alg->digest_size, (uint8_t *)"Client Key",
|
||||
SCRAM_SHA1_Hi(password, len, salt, salt_len, i, salted);
|
||||
crypto_HMAC_SHA1(salted, SHA1_DIGEST_SIZE, (uint8_t *)"Client Key",
|
||||
strlen("Client Key"), key);
|
||||
}
|
||||
|
||||
void SCRAM_ClientSignature(const struct hash_alg *alg,
|
||||
const uint8_t *ClientKey,
|
||||
const uint8_t *AuthMessage,
|
||||
size_t len,
|
||||
void SCRAM_SHA1_ClientSignature(const uint8_t *ClientKey,
|
||||
const uint8_t *AuthMessage, size_t len,
|
||||
uint8_t *sign)
|
||||
{
|
||||
uint8_t stored[SCRAM_DIGEST_SIZE];
|
||||
uint8_t stored[SHA1_DIGEST_SIZE];
|
||||
|
||||
alg->hash(ClientKey, alg->digest_size, stored);
|
||||
crypto_HMAC(alg, stored, alg->digest_size, AuthMessage, len, sign);
|
||||
crypto_SHA1(ClientKey, SHA1_DIGEST_SIZE, stored);
|
||||
crypto_HMAC_SHA1(stored, SHA1_DIGEST_SIZE, AuthMessage, len, sign);
|
||||
}
|
||||
|
||||
void SCRAM_ClientProof(const struct hash_alg *alg,
|
||||
const uint8_t *ClientKey,
|
||||
void SCRAM_SHA1_ClientProof(const uint8_t *ClientKey,
|
||||
const uint8_t *ClientSignature,
|
||||
uint8_t *proof)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < alg->digest_size; i++) {
|
||||
int i;
|
||||
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
|
||||
proof[i] = ClientKey[i] ^ ClientSignature[i];
|
||||
}
|
||||
}
|
||||
|
||||
39
src/scram.h
39
src/scram.h
@@ -1,5 +1,5 @@
|
||||
/* scram.h
|
||||
* strophe XMPP client library -- SCRAM helper functions
|
||||
* strophe XMPP client library -- SCRAM-SHA1 helper functions
|
||||
*
|
||||
* Copyright (C) 2013 Dmitry Podgorny <pasis.ua@gmail.com>
|
||||
*
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* SCRAM helper functions.
|
||||
* SCRAM-SHA1 helper functions.
|
||||
*/
|
||||
|
||||
#ifndef __LIBSTROPHE_SCRAM_H__
|
||||
@@ -19,40 +19,17 @@
|
||||
/* make sure the stdint.h types are available */
|
||||
#include "ostypes.h"
|
||||
|
||||
/* Maximum possible digest size. Used for buffers allocation. */
|
||||
#include "sha512.h"
|
||||
#define SCRAM_DIGEST_SIZE SHA512_DIGEST_SIZE
|
||||
#include "sha1.h"
|
||||
|
||||
struct hash_alg {
|
||||
const char *scram_name;
|
||||
int mask;
|
||||
size_t digest_size;
|
||||
void (*hash)(const uint8_t *, size_t, uint8_t *);
|
||||
void (*init)(void *);
|
||||
void (*update)(void *, const uint8_t *, size_t);
|
||||
void (*final)(void *, uint8_t *);
|
||||
};
|
||||
|
||||
extern const struct hash_alg scram_sha1;
|
||||
extern const struct hash_alg scram_sha256;
|
||||
extern const struct hash_alg scram_sha512;
|
||||
|
||||
void SCRAM_ClientKey(const struct hash_alg *alg,
|
||||
const uint8_t *password,
|
||||
size_t len,
|
||||
const uint8_t *salt,
|
||||
size_t salt_len,
|
||||
uint32_t i,
|
||||
void SCRAM_SHA1_ClientKey(const uint8_t *password, size_t len,
|
||||
const uint8_t *salt, size_t salt_len, uint32_t i,
|
||||
uint8_t *key);
|
||||
|
||||
void SCRAM_ClientSignature(const struct hash_alg *alg,
|
||||
const uint8_t *ClientKey,
|
||||
const uint8_t *AuthMessage,
|
||||
size_t len,
|
||||
void SCRAM_SHA1_ClientSignature(const uint8_t *ClientKey,
|
||||
const uint8_t *AuthMessage, size_t len,
|
||||
uint8_t *sign);
|
||||
|
||||
void SCRAM_ClientProof(const struct hash_alg *alg,
|
||||
const uint8_t *ClientKey,
|
||||
void SCRAM_SHA1_ClientProof(const uint8_t *ClientKey,
|
||||
const uint8_t *ClientSignature,
|
||||
uint8_t *proof);
|
||||
|
||||
|
||||
112
src/sha.h
112
src/sha.h
@@ -1,112 +0,0 @@
|
||||
/* public api for steve reid's public domain SHA-1 implementation */
|
||||
/* this file is in the public domain */
|
||||
|
||||
/** @file
|
||||
* SHA-1 hash API.
|
||||
*/
|
||||
|
||||
#ifndef __LIBSTROPHE_SHA_H__
|
||||
#define __LIBSTROPHE_SHA_H__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* make sure the stdint.h types are available */
|
||||
#include "ostypes.h"
|
||||
|
||||
#if defined(__BIG_ENDIAN__) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
|
||||
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
do { \
|
||||
uint32_t __t = (x); \
|
||||
memcpy(y, &__t, 4); \
|
||||
} while (0)
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
do { \
|
||||
memcpy(&(x), y, 4); \
|
||||
x &= 0xFFFFFFFF; \
|
||||
} while (0)
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
do { \
|
||||
uint64_t __t = (x); \
|
||||
memcpy(y, &__t, 8); \
|
||||
} while (0)
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
do { \
|
||||
memcpy(&(x), y, 8); \
|
||||
} while (0)
|
||||
|
||||
#elif defined(__LITTLE_ENDIAN__) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
|
||||
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
|
||||
#define STORE32H(x, y) \
|
||||
do { \
|
||||
(y)[0] = (uint8_t)(((x) >> 24) & 255); \
|
||||
(y)[1] = (uint8_t)(((x) >> 16) & 255); \
|
||||
(y)[2] = (uint8_t)(((x) >> 8) & 255); \
|
||||
(y)[3] = (uint8_t)((x)&255); \
|
||||
} while (0)
|
||||
|
||||
#define LOAD32H(x, y) \
|
||||
do { \
|
||||
x = ((uint32_t)((y)[0] & 255) << 24) | \
|
||||
((uint32_t)((y)[1] & 255) << 16) | \
|
||||
((uint32_t)((y)[2] & 255) << 8) | ((uint32_t)((y)[3] & 255)); \
|
||||
} while (0)
|
||||
|
||||
#define STORE64H(x, y) \
|
||||
do { \
|
||||
(y)[0] = (uint8_t)(((x) >> 56) & 255); \
|
||||
(y)[1] = (uint8_t)(((x) >> 48) & 255); \
|
||||
(y)[2] = (uint8_t)(((x) >> 40) & 255); \
|
||||
(y)[3] = (uint8_t)(((x) >> 32) & 255); \
|
||||
(y)[4] = (uint8_t)(((x) >> 24) & 255); \
|
||||
(y)[5] = (uint8_t)(((x) >> 16) & 255); \
|
||||
(y)[6] = (uint8_t)(((x) >> 8) & 255); \
|
||||
(y)[7] = (uint8_t)((x)&255); \
|
||||
} while (0)
|
||||
|
||||
#define LOAD64H(x, y) \
|
||||
do { \
|
||||
x = (((uint64_t)((y)[0] & 255)) << 56) | \
|
||||
(((uint64_t)((y)[1] & 255)) << 48) | \
|
||||
(((uint64_t)((y)[2] & 255)) << 40) | \
|
||||
(((uint64_t)((y)[3] & 255)) << 32) | \
|
||||
(((uint64_t)((y)[4] & 255)) << 24) | \
|
||||
(((uint64_t)((y)[5] & 255)) << 16) | \
|
||||
(((uint64_t)((y)[6] & 255)) << 8) | (((uint64_t)((y)[7] & 255))); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#error Unknown endianness not supported
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define CONST64(n) n##ui64
|
||||
#else
|
||||
#define CONST64(n) n##ULL
|
||||
#endif
|
||||
|
||||
#define RORc(x, y) \
|
||||
(((((uint32_t)(x)&0xFFFFFFFFUL) >> (uint32_t)((y)&31)) | \
|
||||
((uint32_t)(x) << (uint32_t)((32 - ((y)&31)) & 31))) & \
|
||||
0xFFFFFFFFUL)
|
||||
#define ROR64c(x, y) \
|
||||
(((((x)&CONST64(0xFFFFFFFFFFFFFFFF)) >> ((uint64_t)(y)&CONST64(63))) | \
|
||||
((x) << (((uint64_t)64 - ((y)&63)) & 63))) & \
|
||||
CONST64(0xFFFFFFFFFFFFFFFF))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LIBSTROPHE_SHA_H__ */
|
||||
82
src/sha1.c
82
src/sha1.c
@@ -75,6 +75,9 @@ move public api to sha1.h
|
||||
#include "ostypes.h"
|
||||
#include "sha1.h"
|
||||
|
||||
/* Don't change user's data */
|
||||
#define SHA1HANDSOFF
|
||||
|
||||
static uint32_t host_to_be(uint32_t i);
|
||||
static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
|
||||
|
||||
@@ -83,27 +86,16 @@ static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
|
||||
/* blk0() and blk() perform the initial expand. */
|
||||
/* I got the idea of expanding during the round function from SSLeay */
|
||||
#define blk0(i) (block->l[i] = host_to_be(block->l[i]))
|
||||
#define blk(i) \
|
||||
(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
|
||||
block->l[(i + 2) & 15] ^ block->l[i & 15], \
|
||||
1))
|
||||
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
||||
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v, w, x, y, z, i) \
|
||||
z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R1(v, w, x, y, z, i) \
|
||||
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R2(v, w, x, y, z, i) \
|
||||
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R3(v, w, x, y, z, i) \
|
||||
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R4(v, w, x, y, z, i) \
|
||||
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||
|
||||
|
||||
static uint32_t host_to_be(uint32_t i)
|
||||
{
|
||||
@@ -126,13 +118,6 @@ static uint32_t host_to_be(uint32_t i)
|
||||
#undef le_to_be
|
||||
}
|
||||
|
||||
static void *(*volatile SHA1_explicit_memset)(void *, int, size_t) = &memset;
|
||||
|
||||
static void SHA1_cleanse(void *p, size_t len)
|
||||
{
|
||||
SHA1_explicit_memset(p, 0, len);
|
||||
}
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
|
||||
{
|
||||
@@ -143,9 +128,13 @@ static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16* block;
|
||||
|
||||
#ifdef SHA1HANDSOFF
|
||||
static uint8_t workspace[64];
|
||||
block = (CHAR64LONG16*)workspace;
|
||||
memcpy(block, buffer, 64);
|
||||
#else
|
||||
block = (CHAR64LONG16*)buffer;
|
||||
#endif
|
||||
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
@@ -155,7 +144,6 @@ static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
|
||||
e = state[4];
|
||||
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
/* clang-format off */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
@@ -176,7 +164,6 @@ static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
/* clang-format on */
|
||||
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
@@ -186,13 +173,10 @@ static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
|
||||
state[4] += e;
|
||||
|
||||
/* Wipe variables */
|
||||
SHA1_cleanse(&a, sizeof(a));
|
||||
SHA1_cleanse(&b, sizeof(b));
|
||||
SHA1_cleanse(&c, sizeof(c));
|
||||
SHA1_cleanse(&d, sizeof(d));
|
||||
SHA1_cleanse(&e, sizeof(e));
|
||||
a = b = c = d = e = 0;
|
||||
}
|
||||
|
||||
|
||||
/* SHA1Init - Initialize new context */
|
||||
void crypto_SHA1_Init(SHA1_CTX* context)
|
||||
{
|
||||
@@ -205,8 +189,10 @@ void crypto_SHA1_Init(SHA1_CTX *context)
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
@@ -221,11 +207,12 @@ void crypto_SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len)
|
||||
SHA1_Transform(context->state, data + i);
|
||||
}
|
||||
j = 0;
|
||||
} else
|
||||
i = 0;
|
||||
}
|
||||
else i = 0;
|
||||
memcpy(&context->buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
void crypto_SHA1_Final(SHA1_CTX* context, uint8_t* digest)
|
||||
{
|
||||
@@ -233,30 +220,31 @@ void crypto_SHA1_Final(SHA1_CTX *context, uint8_t *digest)
|
||||
uint8_t finalcount[8];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >>
|
||||
((3 - (i & 3)) * 8)) &
|
||||
255); /* Endian independent */
|
||||
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
crypto_SHA1_Update(context, (uint8_t *)"\200", 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
crypto_SHA1_Update(context, (uint8_t *)"\0", 1);
|
||||
}
|
||||
/* Should cause a SHA1_Transform() */
|
||||
crypto_SHA1_Update(context, finalcount, 8);
|
||||
crypto_SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
|
||||
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
|
||||
digest[i] =
|
||||
(uint8_t)((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
|
||||
digest[i] = (uint8_t)
|
||||
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||
}
|
||||
|
||||
/* Wipe variables */
|
||||
SHA1_cleanse(context->buffer, 64);
|
||||
SHA1_cleanse(context->state, 20);
|
||||
SHA1_cleanse(context->count, 8);
|
||||
SHA1_cleanse(finalcount, 8); /* SWR */
|
||||
memset(context->buffer, 0, 64);
|
||||
memset(context->state, 0, 20);
|
||||
memset(context->count, 0, 8);
|
||||
memset(finalcount, 0, 8); /* SWR */
|
||||
|
||||
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */
|
||||
SHA1_Transform(context->state, context->buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void crypto_SHA1(const uint8_t* data, size_t len, uint8_t* digest)
|
||||
{
|
||||
SHA1_CTX ctx;
|
||||
|
||||
@@ -24,7 +24,8 @@ typedef struct {
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
|
||||
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(const uint8_t* data, size_t len, uint8_t* digest);
|
||||
|
||||
|
||||
210
src/sha256.c
210
src/sha256.c
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* Code originally from LibTomCrypt -- Licensed under the Public Domain/WTFPL2.0
|
||||
*/
|
||||
|
||||
#include "sha256.h"
|
||||
#include "sha.h"
|
||||
|
||||
/* Various logical functions */
|
||||
#define Ch(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define Maj(x, y, z) (((x | y) & z) | (x & y))
|
||||
#define S(x, n) RORc((x), (n))
|
||||
#define R(x, n) (((x)&0xFFFFFFFFUL) >> (n))
|
||||
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
|
||||
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
|
||||
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
|
||||
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
|
||||
|
||||
static void sha256_compress(sha256_context *md, const uint8_t *buf)
|
||||
{
|
||||
uint32_t S[8], W[64], t0, t1;
|
||||
int i;
|
||||
|
||||
/* copy state into S */
|
||||
for (i = 0; i < 8; i++) {
|
||||
S[i] = md->state[i];
|
||||
}
|
||||
|
||||
/* copy the state into 512-bits into W[0..15] */
|
||||
for (i = 0; i < 16; i++) {
|
||||
LOAD32H(W[i], buf + (4 * i));
|
||||
}
|
||||
|
||||
/* fill W[16..63] */
|
||||
for (i = 16; i < 64; i++) {
|
||||
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
|
||||
}
|
||||
|
||||
/* Compress */
|
||||
#define RND(a, b, c, d, e, f, g, h, i, ki) \
|
||||
t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
|
||||
t1 = Sigma0(a) + Maj(a, b, c); \
|
||||
d += t0; \
|
||||
h = t0 + t1;
|
||||
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 0, 0x428a2f98);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 1, 0x71374491);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 2, 0xb5c0fbcf);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 3, 0xe9b5dba5);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 4, 0x3956c25b);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 5, 0x59f111f1);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 6, 0x923f82a4);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 7, 0xab1c5ed5);
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 8, 0xd807aa98);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 9, 0x12835b01);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 10, 0x243185be);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 11, 0x550c7dc3);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 12, 0x72be5d74);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 13, 0x80deb1fe);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 14, 0x9bdc06a7);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 15, 0xc19bf174);
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 16, 0xe49b69c1);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 17, 0xefbe4786);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 18, 0x0fc19dc6);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 19, 0x240ca1cc);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 20, 0x2de92c6f);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 21, 0x4a7484aa);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 22, 0x5cb0a9dc);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 23, 0x76f988da);
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 24, 0x983e5152);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 25, 0xa831c66d);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 26, 0xb00327c8);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 27, 0xbf597fc7);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 28, 0xc6e00bf3);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 29, 0xd5a79147);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 30, 0x06ca6351);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 31, 0x14292967);
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 32, 0x27b70a85);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 33, 0x2e1b2138);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 34, 0x4d2c6dfc);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 35, 0x53380d13);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 36, 0x650a7354);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 37, 0x766a0abb);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 38, 0x81c2c92e);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 39, 0x92722c85);
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 40, 0xa2bfe8a1);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 41, 0xa81a664b);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 42, 0xc24b8b70);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 43, 0xc76c51a3);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 44, 0xd192e819);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 45, 0xd6990624);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 46, 0xf40e3585);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 47, 0x106aa070);
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 48, 0x19a4c116);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 49, 0x1e376c08);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 50, 0x2748774c);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 51, 0x34b0bcb5);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 52, 0x391c0cb3);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 53, 0x4ed8aa4a);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 54, 0x5b9cca4f);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 55, 0x682e6ff3);
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], 56, 0x748f82ee);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], 57, 0x78a5636f);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], 58, 0x84c87814);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], 59, 0x8cc70208);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], 60, 0x90befffa);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], 61, 0xa4506ceb);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], 62, 0xbef9a3f7);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], 63, 0xc67178f2);
|
||||
|
||||
#undef RND
|
||||
|
||||
/* feedback */
|
||||
for (i = 0; i < 8; i++) {
|
||||
md->state[i] = md->state[i] + S[i];
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_init(sha256_context *md)
|
||||
{
|
||||
md->curlen = 0;
|
||||
md->length = 0;
|
||||
md->state[0] = 0x6A09E667UL;
|
||||
md->state[1] = 0xBB67AE85UL;
|
||||
md->state[2] = 0x3C6EF372UL;
|
||||
md->state[3] = 0xA54FF53AUL;
|
||||
md->state[4] = 0x510E527FUL;
|
||||
md->state[5] = 0x9B05688CUL;
|
||||
md->state[6] = 0x1F83D9ABUL;
|
||||
md->state[7] = 0x5BE0CD19UL;
|
||||
}
|
||||
|
||||
void sha256_process(sha256_context *md, const uint8_t *in, size_t inlen)
|
||||
{
|
||||
size_t n;
|
||||
if (md->curlen > sizeof(md->buf)) {
|
||||
return;
|
||||
}
|
||||
if ((md->length + inlen) < md->length) {
|
||||
return;
|
||||
}
|
||||
while (inlen > 0) {
|
||||
if (md->curlen == 0 && inlen >= 64) {
|
||||
sha256_compress(md, in);
|
||||
md->length += 64 * 8;
|
||||
in += 64;
|
||||
inlen -= 64;
|
||||
} else {
|
||||
n = (((inlen) < ((64 - md->curlen))) ? (inlen)
|
||||
: ((64 - md->curlen)));
|
||||
memcpy(md->buf + md->curlen, in, (size_t)n);
|
||||
md->curlen += n;
|
||||
in += n;
|
||||
inlen -= n;
|
||||
if (md->curlen == 64) {
|
||||
sha256_compress(md, md->buf);
|
||||
md->length += 8 * 64;
|
||||
md->curlen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_done(sha256_context *md, uint8_t *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (md->curlen >= sizeof(md->buf)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* increase the length of the message */
|
||||
md->length += md->curlen * 8;
|
||||
|
||||
/* append the '1' bit */
|
||||
md->buf[md->curlen++] = (uint8_t)0x80;
|
||||
|
||||
/* if the length is currently above 56 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
* encoding like normal.
|
||||
*/
|
||||
if (md->curlen > 56) {
|
||||
while (md->curlen < 64) {
|
||||
md->buf[md->curlen++] = (uint8_t)0;
|
||||
}
|
||||
sha256_compress(md, md->buf);
|
||||
md->curlen = 0;
|
||||
}
|
||||
|
||||
/* pad upto 56 bytes of zeroes */
|
||||
while (md->curlen < 56) {
|
||||
md->buf[md->curlen++] = (uint8_t)0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
STORE64H(md->length, md->buf + 56);
|
||||
sha256_compress(md, md->buf);
|
||||
|
||||
/* copy output */
|
||||
for (i = 0; i < 8; i++) {
|
||||
STORE32H(md->state[i], out + (4 * i));
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_hash(const uint8_t *data, size_t len, uint8_t *digest)
|
||||
{
|
||||
sha256_context md;
|
||||
sha256_init(&md);
|
||||
sha256_process(&md, data, len);
|
||||
sha256_done(&md, digest);
|
||||
}
|
||||
34
src/sha256.h
34
src/sha256.h
@@ -1,34 +0,0 @@
|
||||
/* public api for LibTomCrypt SHA-256 implementation */
|
||||
|
||||
/** @file
|
||||
* SHA-256 hash API.
|
||||
*/
|
||||
|
||||
#ifndef __LIBSTROPHE_SHA256_H__
|
||||
#define __LIBSTROPHE_SHA256_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* make sure the stdint.h types are available */
|
||||
#include "ostypes.h"
|
||||
|
||||
typedef struct {
|
||||
uint64_t length;
|
||||
uint32_t state[8], curlen;
|
||||
uint8_t buf[64];
|
||||
} sha256_context;
|
||||
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
|
||||
void sha256_init(sha256_context *md);
|
||||
void sha256_process(sha256_context *md, const uint8_t *in, size_t inlen);
|
||||
void sha256_done(sha256_context *md, uint8_t *out);
|
||||
|
||||
void sha256_hash(const uint8_t *data, size_t len, uint8_t *digest);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LIBSTROPHE_SHA256_H__ */
|
||||
201
src/sha512.c
201
src/sha512.c
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Code originally from LibTomCrypt -- Licensed under the Public Domain/WTFPL2.0
|
||||
*/
|
||||
|
||||
#include "sha512.h"
|
||||
#include "sha.h"
|
||||
|
||||
/* the K array */
|
||||
static const uint64_t K[80] = {
|
||||
CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
|
||||
CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
|
||||
CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
|
||||
CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
|
||||
CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
|
||||
CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
|
||||
CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
|
||||
CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
|
||||
CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
|
||||
CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
|
||||
CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
|
||||
CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
|
||||
CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
|
||||
CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
|
||||
CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
|
||||
CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
|
||||
CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
|
||||
CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
|
||||
CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
|
||||
CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
|
||||
CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
|
||||
CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
|
||||
CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
|
||||
CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
|
||||
CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
|
||||
CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
|
||||
CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
|
||||
CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
|
||||
CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
|
||||
CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
|
||||
CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
|
||||
CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
|
||||
CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
|
||||
CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
|
||||
CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
|
||||
CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
|
||||
CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
|
||||
CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
|
||||
CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
|
||||
CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)};
|
||||
|
||||
/* Various logical functions */
|
||||
#define Ch(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define Maj(x, y, z) (((x | y) & z) | (x & y))
|
||||
#define S(x, n) ROR64c(x, n)
|
||||
#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF)) >> ((uint64_t)n))
|
||||
#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
|
||||
#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
|
||||
#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
|
||||
#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
|
||||
|
||||
/* compress 1024-bits */
|
||||
static void sha512_compress(sha512_context *md, const uint8_t *buf)
|
||||
{
|
||||
uint64_t S[8], W[80], t0, t1;
|
||||
int i;
|
||||
|
||||
/* copy state into S */
|
||||
for (i = 0; i < 8; i++) {
|
||||
S[i] = md->state[i];
|
||||
}
|
||||
|
||||
/* copy the state into 1024-bits into W[0..15] */
|
||||
for (i = 0; i < 16; i++) {
|
||||
LOAD64H(W[i], buf + (8 * i));
|
||||
}
|
||||
|
||||
/* fill W[16..79] */
|
||||
for (i = 16; i < 80; i++) {
|
||||
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
|
||||
}
|
||||
|
||||
/* Compress */
|
||||
#define RND(a, b, c, d, e, f, g, h, i) \
|
||||
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
|
||||
t1 = Sigma0(a) + Maj(a, b, c); \
|
||||
d += t0; \
|
||||
h = t0 + t1;
|
||||
|
||||
for (i = 0; i < 80; i += 8) {
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i + 0);
|
||||
RND(S[7], S[0], S[1], S[2], S[3], S[4], S[5], S[6], i + 1);
|
||||
RND(S[6], S[7], S[0], S[1], S[2], S[3], S[4], S[5], i + 2);
|
||||
RND(S[5], S[6], S[7], S[0], S[1], S[2], S[3], S[4], i + 3);
|
||||
RND(S[4], S[5], S[6], S[7], S[0], S[1], S[2], S[3], i + 4);
|
||||
RND(S[3], S[4], S[5], S[6], S[7], S[0], S[1], S[2], i + 5);
|
||||
RND(S[2], S[3], S[4], S[5], S[6], S[7], S[0], S[1], i + 6);
|
||||
RND(S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[0], i + 7);
|
||||
}
|
||||
|
||||
/* feedback */
|
||||
for (i = 0; i < 8; i++) {
|
||||
md->state[i] = md->state[i] + S[i];
|
||||
}
|
||||
}
|
||||
|
||||
void sha512_init(sha512_context *md)
|
||||
{
|
||||
md->curlen = 0;
|
||||
md->length = 0;
|
||||
md->state[0] = CONST64(0x6a09e667f3bcc908);
|
||||
md->state[1] = CONST64(0xbb67ae8584caa73b);
|
||||
md->state[2] = CONST64(0x3c6ef372fe94f82b);
|
||||
md->state[3] = CONST64(0xa54ff53a5f1d36f1);
|
||||
md->state[4] = CONST64(0x510e527fade682d1);
|
||||
md->state[5] = CONST64(0x9b05688c2b3e6c1f);
|
||||
md->state[6] = CONST64(0x1f83d9abfb41bd6b);
|
||||
md->state[7] = CONST64(0x5be0cd19137e2179);
|
||||
}
|
||||
|
||||
void sha512_process(sha512_context *md, const uint8_t *in, size_t inlen)
|
||||
{
|
||||
size_t n;
|
||||
if (md->curlen > sizeof(md->buf)) {
|
||||
return;
|
||||
}
|
||||
if ((md->length + inlen) < md->length) {
|
||||
return;
|
||||
}
|
||||
while (inlen > 0) {
|
||||
if (md->curlen == 0 && inlen >= 128) {
|
||||
sha512_compress(md, in);
|
||||
md->length += 128 * 8;
|
||||
in += 128;
|
||||
inlen -= 128;
|
||||
} else {
|
||||
n = (((inlen) < ((128u - md->curlen))) ? (inlen)
|
||||
: ((128u - md->curlen)));
|
||||
memcpy(md->buf + md->curlen, in, (size_t)n);
|
||||
md->curlen += n;
|
||||
in += n;
|
||||
inlen -= n;
|
||||
if (md->curlen == 128) {
|
||||
sha512_compress(md, md->buf);
|
||||
md->length += 8 * 128;
|
||||
md->curlen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha512_done(sha512_context *md, uint8_t *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (md->curlen >= sizeof(md->buf)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* increase the length of the message */
|
||||
md->length += md->curlen * CONST64(8);
|
||||
|
||||
/* append the '1' bit */
|
||||
md->buf[md->curlen++] = (uint8_t)0x80;
|
||||
|
||||
/* if the length is currently above 112 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
* encoding like normal.
|
||||
*/
|
||||
if (md->curlen > 112) {
|
||||
while (md->curlen < 128) {
|
||||
md->buf[md->curlen++] = (uint8_t)0;
|
||||
}
|
||||
sha512_compress(md, md->buf);
|
||||
md->curlen = 0;
|
||||
}
|
||||
|
||||
/* pad upto 120 bytes of zeroes
|
||||
* note: that from 112 to 120 is the 64 MSB of the length. We assume that
|
||||
* you won't hash > 2^64 bits of data... :-)
|
||||
*/
|
||||
while (md->curlen < 120) {
|
||||
md->buf[md->curlen++] = (uint8_t)0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
STORE64H(md->length, md->buf + 120);
|
||||
sha512_compress(md, md->buf);
|
||||
|
||||
/* copy output */
|
||||
for (i = 0; i < 8; i++) {
|
||||
STORE64H(md->state[i], out + (8 * i));
|
||||
}
|
||||
}
|
||||
|
||||
void sha512_hash(const uint8_t *data, size_t len, uint8_t *digest)
|
||||
{
|
||||
sha512_context md;
|
||||
sha512_init(&md);
|
||||
sha512_process(&md, data, len);
|
||||
sha512_done(&md, digest);
|
||||
}
|
||||
34
src/sha512.h
34
src/sha512.h
@@ -1,34 +0,0 @@
|
||||
/* public api for LibTomCrypt SHA-512 implementation */
|
||||
|
||||
/** @file
|
||||
* SHA-512 hash API.
|
||||
*/
|
||||
|
||||
#ifndef __LIBSTROPHE_SHA512_H__
|
||||
#define __LIBSTROPHE_SHA512_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* make sure the stdint.h types are available */
|
||||
#include "ostypes.h"
|
||||
|
||||
typedef struct {
|
||||
uint64_t length, state[8];
|
||||
uint8_t curlen;
|
||||
uint8_t buf[128];
|
||||
} sha512_context;
|
||||
|
||||
#define SHA512_DIGEST_SIZE 64
|
||||
|
||||
void sha512_init(sha512_context *cc);
|
||||
void sha512_process(sha512_context *cc, const uint8_t *data, size_t len);
|
||||
void sha512_done(sha512_context *cc, uint8_t *dst);
|
||||
|
||||
void sha512_hash(const uint8_t *data, size_t len, uint8_t *digest);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LIBSTROPHE_SHA512_H__ */
|
||||
232
src/snprintf.c
232
src/snprintf.c
@@ -85,29 +85,14 @@
|
||||
#define LDOUBLE double
|
||||
#endif
|
||||
|
||||
static int dopr(char *buffer, size_t maxlen, const char *format, va_list args);
|
||||
static int fmtstr(char *buffer,
|
||||
size_t *currlen,
|
||||
size_t maxlen,
|
||||
char *value,
|
||||
int flags,
|
||||
int min,
|
||||
int max);
|
||||
static int fmtint(char *buffer,
|
||||
size_t *currlen,
|
||||
size_t maxlen,
|
||||
long value,
|
||||
int base,
|
||||
int min,
|
||||
int max,
|
||||
int flags);
|
||||
static int fmtfp(char *buffer,
|
||||
size_t *currlen,
|
||||
size_t maxlen,
|
||||
LDOUBLE fvalue,
|
||||
int min,
|
||||
int max,
|
||||
int flags);
|
||||
static int dopr (char *buffer, size_t maxlen, const char *format,
|
||||
va_list args);
|
||||
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
|
||||
char *value, int flags, int min, int max);
|
||||
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
|
||||
long value, int base, int min, int max, int flags);
|
||||
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
LDOUBLE fvalue, int min, int max, int flags);
|
||||
static int dopr_outch (char *buffer, size_t *currlen, size_t maxlen, char c );
|
||||
|
||||
/*
|
||||
@@ -162,11 +147,13 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
ch = *format++;
|
||||
total = 0;
|
||||
|
||||
while (state != DP_S_DONE) {
|
||||
while (state != DP_S_DONE)
|
||||
{
|
||||
if (ch == '\0')
|
||||
state = DP_S_DONE;
|
||||
|
||||
switch (state) {
|
||||
switch(state)
|
||||
{
|
||||
case DP_S_DEFAULT:
|
||||
if (ch == '%')
|
||||
state = DP_S_FLAGS;
|
||||
@@ -175,7 +162,8 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
ch = *format++;
|
||||
break;
|
||||
case DP_S_FLAGS:
|
||||
switch (ch) {
|
||||
switch (ch)
|
||||
{
|
||||
case '-':
|
||||
flags |= DP_F_MINUS;
|
||||
ch = *format++;
|
||||
@@ -202,39 +190,50 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
}
|
||||
break;
|
||||
case DP_S_MIN:
|
||||
if (isdigit(ch)) {
|
||||
if (isdigit(ch))
|
||||
{
|
||||
min = 10*min + char_to_int (ch);
|
||||
ch = *format++;
|
||||
} else if (ch == '*') {
|
||||
}
|
||||
else if (ch == '*')
|
||||
{
|
||||
min = va_arg (args, int);
|
||||
ch = *format++;
|
||||
state = DP_S_DOT;
|
||||
} else
|
||||
}
|
||||
else
|
||||
state = DP_S_DOT;
|
||||
break;
|
||||
case DP_S_DOT:
|
||||
if (ch == '.') {
|
||||
if (ch == '.')
|
||||
{
|
||||
state = DP_S_MAX;
|
||||
ch = *format++;
|
||||
} else
|
||||
}
|
||||
else
|
||||
state = DP_S_MOD;
|
||||
break;
|
||||
case DP_S_MAX:
|
||||
if (isdigit(ch)) {
|
||||
if (isdigit(ch))
|
||||
{
|
||||
if (max < 0)
|
||||
max = 0;
|
||||
max = 10*max + char_to_int (ch);
|
||||
ch = *format++;
|
||||
} else if (ch == '*') {
|
||||
}
|
||||
else if (ch == '*')
|
||||
{
|
||||
max = va_arg (args, int);
|
||||
ch = *format++;
|
||||
state = DP_S_MOD;
|
||||
} else
|
||||
}
|
||||
else
|
||||
state = DP_S_MOD;
|
||||
break;
|
||||
case DP_S_MOD:
|
||||
/* Currently, we don't support Long Long, bummer */
|
||||
switch (ch) {
|
||||
switch (ch)
|
||||
{
|
||||
case 'h':
|
||||
cflags = DP_C_SHORT;
|
||||
ch = *format++;
|
||||
@@ -253,7 +252,8 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
state = DP_S_CONV;
|
||||
break;
|
||||
case DP_S_CONV:
|
||||
switch (ch) {
|
||||
switch (ch)
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
if (cflags == DP_C_SHORT)
|
||||
@@ -262,8 +262,7 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
value = va_arg (args, long int);
|
||||
else
|
||||
value = va_arg (args, int);
|
||||
total += fmtint(buffer, &currlen, maxlen, value, 10, min, max,
|
||||
flags);
|
||||
total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
|
||||
break;
|
||||
case 'o':
|
||||
flags |= DP_F_UNSIGNED;
|
||||
@@ -273,8 +272,7 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
value = va_arg (args, unsigned long int);
|
||||
else
|
||||
value = va_arg (args, unsigned int);
|
||||
total +=
|
||||
fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);
|
||||
total += fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
|
||||
break;
|
||||
case 'u':
|
||||
flags |= DP_F_UNSIGNED;
|
||||
@@ -284,8 +282,7 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
value = va_arg (args, unsigned long int);
|
||||
else
|
||||
value = va_arg (args, unsigned int);
|
||||
total += fmtint(buffer, &currlen, maxlen, value, 10, min, max,
|
||||
flags);
|
||||
total += fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
|
||||
break;
|
||||
case 'X':
|
||||
flags |= DP_F_UP;
|
||||
@@ -298,8 +295,7 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
value = va_arg (args, unsigned long int);
|
||||
else
|
||||
value = va_arg (args, unsigned int);
|
||||
total += fmtint(buffer, &currlen, maxlen, value, 16, min, max,
|
||||
flags);
|
||||
total += fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
|
||||
break;
|
||||
case 'f':
|
||||
if (cflags == DP_C_LDOUBLE)
|
||||
@@ -307,8 +303,7 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
else
|
||||
fvalue = va_arg (args, double);
|
||||
/* um, floating point? */
|
||||
total +=
|
||||
fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);
|
||||
total += fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
|
||||
break;
|
||||
case 'E':
|
||||
flags |= DP_F_UP;
|
||||
@@ -329,29 +324,32 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
fvalue = va_arg (args, double);
|
||||
break;
|
||||
case 'c':
|
||||
total +=
|
||||
dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));
|
||||
total += dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));
|
||||
break;
|
||||
case 's':
|
||||
strvalue = va_arg (args, char *);
|
||||
total +=
|
||||
fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);
|
||||
total += fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
|
||||
break;
|
||||
case 'p':
|
||||
strvalue = va_arg (args, void *);
|
||||
total += fmtint(buffer, &currlen, maxlen, (long)strvalue, 16,
|
||||
min, max, flags);
|
||||
total += fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min,
|
||||
max, flags);
|
||||
break;
|
||||
case 'n':
|
||||
if (cflags == DP_C_SHORT) {
|
||||
if (cflags == DP_C_SHORT)
|
||||
{
|
||||
short int *num;
|
||||
num = va_arg (args, short int *);
|
||||
*num = currlen;
|
||||
} else if (cflags == DP_C_LONG) {
|
||||
}
|
||||
else if (cflags == DP_C_LONG)
|
||||
{
|
||||
long int *num;
|
||||
num = va_arg (args, long int *);
|
||||
*num = currlen;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int *num;
|
||||
num = va_arg (args, int *);
|
||||
*num = currlen;
|
||||
@@ -380,7 +378,8 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
break; /* some picky compilers need this */
|
||||
}
|
||||
}
|
||||
if (buffer != NULL && maxlen > 0) {
|
||||
if (buffer != NULL && maxlen > 0)
|
||||
{
|
||||
if (currlen < maxlen - 1)
|
||||
buffer[currlen] = '\0';
|
||||
else
|
||||
@@ -389,24 +388,19 @@ static int dopr(char *buffer, size_t maxlen, const char *format, va_list args)
|
||||
return total;
|
||||
}
|
||||
|
||||
static int fmtstr(char *buffer,
|
||||
size_t *currlen,
|
||||
size_t maxlen,
|
||||
char *value,
|
||||
int flags,
|
||||
int min,
|
||||
int max)
|
||||
static int fmtstr (char *buffer, size_t *currlen, size_t maxlen,
|
||||
char *value, int flags, int min, int max)
|
||||
{
|
||||
int padlen, strln; /* amount to pad */
|
||||
int cnt = 0;
|
||||
int total = 0;
|
||||
|
||||
if (value == 0) {
|
||||
if (value == 0)
|
||||
{
|
||||
value = "<NULL>";
|
||||
}
|
||||
|
||||
for (strln = 0; value[strln]; ++strln)
|
||||
; /* strlen */
|
||||
for (strln = 0; value[strln]; ++strln); /* strlen */
|
||||
if (max >= 0 && max < strln)
|
||||
strln = max;
|
||||
padlen = min - strln;
|
||||
@@ -415,15 +409,18 @@ static int fmtstr(char *buffer,
|
||||
if (flags & DP_F_MINUS)
|
||||
padlen = -padlen; /* Left Justify */
|
||||
|
||||
while (padlen > 0) {
|
||||
while (padlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
--padlen;
|
||||
}
|
||||
while (*value && ((max < 0) || (cnt < max))) {
|
||||
while (*value && ((max < 0) || (cnt < max)))
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, *value++);
|
||||
++cnt;
|
||||
}
|
||||
while (padlen < 0) {
|
||||
while (padlen < 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
++padlen;
|
||||
}
|
||||
@@ -432,14 +429,8 @@ static int fmtstr(char *buffer,
|
||||
|
||||
/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
|
||||
|
||||
static int fmtint(char *buffer,
|
||||
size_t *currlen,
|
||||
size_t maxlen,
|
||||
long value,
|
||||
int base,
|
||||
int min,
|
||||
int max,
|
||||
int flags)
|
||||
static int fmtint (char *buffer, size_t *currlen, size_t maxlen,
|
||||
long value, int base, int min, int max, int flags)
|
||||
{
|
||||
int signvalue = 0;
|
||||
unsigned long uvalue;
|
||||
@@ -455,35 +446,37 @@ static int fmtint(char *buffer,
|
||||
|
||||
uvalue = value;
|
||||
|
||||
if (!(flags & DP_F_UNSIGNED)) {
|
||||
if(!(flags & DP_F_UNSIGNED))
|
||||
{
|
||||
if( value < 0 ) {
|
||||
signvalue = '-';
|
||||
uvalue = -value;
|
||||
} else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
|
||||
}
|
||||
else
|
||||
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
|
||||
signvalue = '+';
|
||||
else if (flags & DP_F_SPACE)
|
||||
else
|
||||
if (flags & DP_F_SPACE)
|
||||
signvalue = ' ';
|
||||
}
|
||||
|
||||
if (flags & DP_F_UP)
|
||||
caps = 1; /* Should characters be upper case? */
|
||||
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
|
||||
|
||||
do {
|
||||
convert[place++] = (caps ? "0123456789ABCDEF"
|
||||
: "0123456789abcdef")[uvalue % (unsigned)base];
|
||||
convert[place++] =
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")
|
||||
[uvalue % (unsigned)base ];
|
||||
uvalue = (uvalue / (unsigned)base );
|
||||
} while(uvalue && (place < 20));
|
||||
if (place == 20)
|
||||
place--;
|
||||
if (place == 20) place--;
|
||||
convert[place] = 0;
|
||||
|
||||
zpadlen = max - place;
|
||||
spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
|
||||
if (zpadlen < 0)
|
||||
zpadlen = 0;
|
||||
if (spadlen < 0)
|
||||
spadlen = 0;
|
||||
if (flags & DP_F_ZERO) {
|
||||
if (zpadlen < 0) zpadlen = 0;
|
||||
if (spadlen < 0) spadlen = 0;
|
||||
if (flags & DP_F_ZERO)
|
||||
{
|
||||
zpadlen = MAX(zpadlen, spadlen);
|
||||
spadlen = 0;
|
||||
}
|
||||
@@ -496,7 +489,8 @@ static int fmtint(char *buffer,
|
||||
#endif
|
||||
|
||||
/* Spaces */
|
||||
while (spadlen > 0) {
|
||||
while (spadlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
--spadlen;
|
||||
}
|
||||
@@ -506,8 +500,10 @@ static int fmtint(char *buffer,
|
||||
total += dopr_outch (buffer, currlen, maxlen, signvalue);
|
||||
|
||||
/* Zeros */
|
||||
if (zpadlen > 0) {
|
||||
while (zpadlen > 0) {
|
||||
if (zpadlen > 0)
|
||||
{
|
||||
while (zpadlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--zpadlen;
|
||||
}
|
||||
@@ -540,7 +536,8 @@ static LDOUBLE _snp_pow10(int exp)
|
||||
{
|
||||
LDOUBLE result = 1;
|
||||
|
||||
while (exp) {
|
||||
while (exp)
|
||||
{
|
||||
result *= 10;
|
||||
exp--;
|
||||
}
|
||||
@@ -560,13 +557,8 @@ static long _snp_round(LDOUBLE value)
|
||||
return intpart;
|
||||
}
|
||||
|
||||
static int fmtfp(char *buffer,
|
||||
size_t *currlen,
|
||||
size_t maxlen,
|
||||
LDOUBLE fvalue,
|
||||
int min,
|
||||
int max,
|
||||
int flags)
|
||||
static int fmtfp (char *buffer, size_t *currlen, size_t maxlen,
|
||||
LDOUBLE fvalue, int min, int max, int flags)
|
||||
{
|
||||
int signvalue = 0;
|
||||
LDOUBLE ufvalue;
|
||||
@@ -592,9 +584,11 @@ static int fmtfp(char *buffer,
|
||||
|
||||
if (fvalue < 0)
|
||||
signvalue = '-';
|
||||
else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
|
||||
else
|
||||
if (flags & DP_F_PLUS) /* Do a sign (+/i) */
|
||||
signvalue = '+';
|
||||
else if (flags & DP_F_SPACE)
|
||||
else
|
||||
if (flags & DP_F_SPACE)
|
||||
signvalue = ' ';
|
||||
|
||||
#if 0
|
||||
@@ -615,7 +609,8 @@ static int fmtfp(char *buffer,
|
||||
*/
|
||||
fracpart = _snp_round ((_snp_pow10 (max)) * (ufvalue - intpart));
|
||||
|
||||
if (fracpart >= _snp_pow10(max)) {
|
||||
if (fracpart >= _snp_pow10 (max))
|
||||
{
|
||||
intpart++;
|
||||
fracpart -= _snp_pow10 (max);
|
||||
}
|
||||
@@ -630,8 +625,7 @@ static int fmtfp(char *buffer,
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];
|
||||
intpart = (intpart / 10);
|
||||
} while(intpart && (iplace < 20));
|
||||
if (iplace == 20)
|
||||
iplace--;
|
||||
if (iplace == 20) iplace--;
|
||||
iconvert[iplace] = 0;
|
||||
|
||||
/* Convert fractional part */
|
||||
@@ -640,8 +634,7 @@ static int fmtfp(char *buffer,
|
||||
(caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];
|
||||
fracpart = (fracpart / 10);
|
||||
} while(fracpart && (fplace < 20));
|
||||
if (fplace == 20)
|
||||
fplace--;
|
||||
if (fplace == 20) fplace--;
|
||||
fconvert[fplace] = 0;
|
||||
|
||||
/* -1 for decimal point, another -1 if we are printing a sign */
|
||||
@@ -654,18 +647,22 @@ static int fmtfp(char *buffer,
|
||||
if (flags & DP_F_MINUS)
|
||||
padlen = -padlen; /* Left Justifty */
|
||||
|
||||
if ((flags & DP_F_ZERO) && (padlen > 0)) {
|
||||
if (signvalue) {
|
||||
if ((flags & DP_F_ZERO) && (padlen > 0))
|
||||
{
|
||||
if (signvalue)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, signvalue);
|
||||
--padlen;
|
||||
signvalue = 0;
|
||||
}
|
||||
while (padlen > 0) {
|
||||
while (padlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--padlen;
|
||||
}
|
||||
}
|
||||
while (padlen > 0) {
|
||||
while (padlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
--padlen;
|
||||
}
|
||||
@@ -679,19 +676,22 @@ static int fmtfp(char *buffer,
|
||||
* Decimal point. This should probably use locale to find the correct
|
||||
* char to print out.
|
||||
*/
|
||||
if (max > 0) {
|
||||
if (max > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, '.');
|
||||
|
||||
while (fplace > 0)
|
||||
total += dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
|
||||
}
|
||||
|
||||
while (zpadlen > 0) {
|
||||
while (zpadlen > 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, '0');
|
||||
--zpadlen;
|
||||
}
|
||||
|
||||
while (padlen < 0) {
|
||||
while (padlen < 0)
|
||||
{
|
||||
total += dopr_outch (buffer, currlen, maxlen, ' ');
|
||||
++padlen;
|
||||
}
|
||||
|
||||
55
src/sock.c
55
src/sock.c
@@ -21,8 +21,8 @@
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <mstcpip.h> /* tcp_keepalive */
|
||||
#include <Iphlpapi.h>
|
||||
#include <Mstcpip.h> /* tcp_keepalive */
|
||||
#else
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
@@ -69,7 +69,7 @@ static int _in_progress(int error)
|
||||
#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;
|
||||
char service[6];
|
||||
@@ -109,7 +109,7 @@ sock_t sock_connect(const char *host, unsigned short port)
|
||||
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 optval = (timeout && interval) ? 1 : 0;
|
||||
@@ -123,8 +123,7 @@ int sock_set_keepalive(sock_t sock, int timeout, int interval)
|
||||
ka.onoff = optval;
|
||||
ka.keepalivetime = timeout * 1000;
|
||||
ka.keepaliveinterval = interval * 1000;
|
||||
ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &ka, sizeof(ka), NULL, 0, &dw,
|
||||
NULL, NULL);
|
||||
ret = WSAIoctl(sock, SIO_KEEPALIVE_VALS, &ka, sizeof(ka), NULL, 0, &dw, NULL, NULL);
|
||||
#else
|
||||
ret = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
|
||||
if (ret < 0)
|
||||
@@ -132,19 +131,15 @@ int sock_set_keepalive(sock_t sock, int timeout, int interval)
|
||||
|
||||
if (optval) {
|
||||
#ifdef TCP_KEEPIDLE
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &timeout,
|
||||
sizeof(timeout));
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &timeout, sizeof(timeout));
|
||||
#elif defined(TCP_KEEPALIVE)
|
||||
/* QNX receives `struct timeval' as argument, but it seems OSX does int
|
||||
*/
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPALIVE, &timeout,
|
||||
sizeof(timeout));
|
||||
/* QNX receives `struct timeval' as argument, but it seems OSX does int */
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPALIVE, &timeout, sizeof(timeout));
|
||||
#endif /* TCP_KEEPIDLE */
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#ifdef TCP_KEEPINTVL
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &interval,
|
||||
sizeof(interval));
|
||||
ret = setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif /* TCP_KEEPINTVL */
|
||||
@@ -154,7 +149,7 @@ int sock_set_keepalive(sock_t sock, int timeout, int interval)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sock_close(sock_t sock)
|
||||
int sock_close(const sock_t sock)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return closesocket(sock);
|
||||
@@ -180,27 +175,27 @@ static int _sock_set_blocking_mode(sock_t sock, int blocking)
|
||||
#endif
|
||||
}
|
||||
|
||||
int sock_set_blocking(sock_t sock)
|
||||
int sock_set_blocking(const sock_t sock)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int sock_is_recoverable(int error)
|
||||
int sock_is_recoverable(const int error)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (error == WSAEINTR || error == WSAEWOULDBLOCK ||
|
||||
@@ -210,31 +205,29 @@ int sock_is_recoverable(int error)
|
||||
#endif
|
||||
}
|
||||
|
||||
int sock_connect_error(sock_t sock)
|
||||
int sock_connect_error(const sock_t sock)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
struct sockaddr *sa = (struct sockaddr *)&ss;
|
||||
struct sockaddr sa;
|
||||
socklen_t len;
|
||||
char temp;
|
||||
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
len = sizeof(ss);
|
||||
sa->sa_family = AF_UNSPEC;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_family = AF_UNSPEC;
|
||||
len = sizeof(sa);
|
||||
|
||||
/* we don't actually care about the peer name, we're just checking if
|
||||
* we're connected or not */
|
||||
if (getpeername(sock, sa, &len) == 0) {
|
||||
if (getpeername(sock, &sa, &len) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* it's possible that the error wasn't ENOTCONN, so if it wasn't,
|
||||
* return that */
|
||||
#ifdef _WIN32
|
||||
if (sock_error() != WSAENOTCONN)
|
||||
return sock_error();
|
||||
if (sock_error() != WSAENOTCONN) return sock_error();
|
||||
#else
|
||||
if (sock_error() != ENOTCONN)
|
||||
return sock_error();
|
||||
if (sock_error() != ENOTCONN) return sock_error();
|
||||
#endif
|
||||
|
||||
/* load the correct error into errno through error slippage */
|
||||
|
||||
18
src/sock.h
18
src/sock.h
@@ -30,16 +30,16 @@ void sock_shutdown(void);
|
||||
|
||||
int sock_error(void);
|
||||
|
||||
sock_t sock_connect(const char *host, unsigned short port);
|
||||
int sock_close(sock_t sock);
|
||||
sock_t sock_connect(const char * const host, const unsigned short port);
|
||||
int sock_close(const sock_t sock);
|
||||
|
||||
int sock_set_blocking(sock_t sock);
|
||||
int sock_set_nonblocking(sock_t sock);
|
||||
int sock_read(sock_t sock, void *buff, size_t len);
|
||||
int sock_write(sock_t sock, const void *buff, size_t len);
|
||||
int sock_is_recoverable(int error);
|
||||
int sock_set_blocking(const sock_t sock);
|
||||
int sock_set_nonblocking(const sock_t sock);
|
||||
int sock_read(const sock_t sock, void * const buff, const size_t len);
|
||||
int sock_write(const sock_t sock, const void * const buff, const size_t len);
|
||||
int sock_is_recoverable(const int error);
|
||||
/* checks for an error after connect, return 0 if connect successful */
|
||||
int sock_connect_error(sock_t sock);
|
||||
int sock_set_keepalive(sock_t sock, int timeout, int interval);
|
||||
int sock_connect_error(const sock_t sock);
|
||||
int sock_set_keepalive(const sock_t sock, int timeout, int interval);
|
||||
|
||||
#endif /* __LIBSTROPHE_SOCK_H__ */
|
||||
|
||||
407
src/stanza.c
407
src/stanza.c
@@ -22,7 +22,6 @@
|
||||
#include "strophe.h"
|
||||
#include "common.h"
|
||||
#include "hash.h"
|
||||
#include "parser.h"
|
||||
|
||||
/** Create a stanza object.
|
||||
* This function allocates and initializes a blank stanza object.
|
||||
@@ -64,7 +63,7 @@ xmpp_stanza_t *xmpp_stanza_new(xmpp_ctx_t *ctx)
|
||||
*
|
||||
* @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++;
|
||||
|
||||
@@ -74,7 +73,8 @@ xmpp_stanza_t *xmpp_stanza_clone(xmpp_stanza_t *stanza)
|
||||
/*
|
||||
* 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;
|
||||
const char *key;
|
||||
@@ -82,13 +82,11 @@ static int _stanza_copy_attributes(xmpp_stanza_t *dst, const xmpp_stanza_t *src)
|
||||
int rc = XMPP_EOK;
|
||||
|
||||
iter = hash_iter_new(src->attributes);
|
||||
if (!iter)
|
||||
rc = XMPP_EMEM;
|
||||
if (!iter) rc = XMPP_EMEM;
|
||||
|
||||
while (rc == XMPP_EOK && (key = hash_iter_next(iter))) {
|
||||
val = hash_get(src->attributes, key);
|
||||
if (!val)
|
||||
rc = XMPP_EINT;
|
||||
if (!val) rc = XMPP_EINT;
|
||||
if (rc == XMPP_EOK)
|
||||
rc = xmpp_stanza_set_attribute(dst, key, val);
|
||||
}
|
||||
@@ -113,20 +111,18 @@ static int _stanza_copy_attributes(xmpp_stanza_t *dst, const xmpp_stanza_t *src)
|
||||
*
|
||||
* @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;
|
||||
|
||||
copy = xmpp_stanza_new(stanza->ctx);
|
||||
if (!copy)
|
||||
goto copy_error;
|
||||
if (!copy) goto copy_error;
|
||||
|
||||
copy->type = stanza->type;
|
||||
|
||||
if (stanza->data) {
|
||||
copy->data = xmpp_strdup(stanza->ctx, stanza->data);
|
||||
if (!copy->data)
|
||||
goto copy_error;
|
||||
if (!copy->data) goto copy_error;
|
||||
}
|
||||
|
||||
if (stanza->attributes) {
|
||||
@@ -137,8 +133,7 @@ xmpp_stanza_t *xmpp_stanza_copy(const xmpp_stanza_t *stanza)
|
||||
tail = copy->children;
|
||||
for (child = stanza->children; child; child = child->next) {
|
||||
copychild = xmpp_stanza_copy(child);
|
||||
if (!copychild)
|
||||
goto copy_error;
|
||||
if (!copychild) goto copy_error;
|
||||
copychild->parent = copy;
|
||||
|
||||
if (tail) {
|
||||
@@ -153,8 +148,7 @@ xmpp_stanza_t *xmpp_stanza_copy(const xmpp_stanza_t *stanza)
|
||||
|
||||
copy_error:
|
||||
/* release all the hitherto allocated memory */
|
||||
if (copy)
|
||||
xmpp_stanza_release(copy);
|
||||
if (copy) xmpp_stanza_release(copy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -168,7 +162,7 @@ copy_error:
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
int xmpp_stanza_release(xmpp_stanza_t *stanza)
|
||||
int xmpp_stanza_release(xmpp_stanza_t * const stanza)
|
||||
{
|
||||
int released = 0;
|
||||
xmpp_stanza_t *child, *tchild;
|
||||
@@ -185,10 +179,8 @@ int xmpp_stanza_release(xmpp_stanza_t *stanza)
|
||||
xmpp_stanza_release(tchild);
|
||||
}
|
||||
|
||||
if (stanza->attributes)
|
||||
hash_release(stanza->attributes);
|
||||
if (stanza->data)
|
||||
xmpp_free(stanza->ctx, stanza->data);
|
||||
if (stanza->attributes) hash_release(stanza->attributes);
|
||||
if (stanza->data) xmpp_free(stanza->ctx, stanza->data);
|
||||
xmpp_free(stanza->ctx, stanza);
|
||||
released = 1;
|
||||
}
|
||||
@@ -204,7 +196,7 @@ int xmpp_stanza_release(xmpp_stanza_t *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;
|
||||
}
|
||||
@@ -217,7 +209,7 @@ xmpp_ctx_t *xmpp_stanza_get_context(const xmpp_stanza_t *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);
|
||||
}
|
||||
@@ -230,7 +222,7 @@ int xmpp_stanza_is_text(xmpp_stanza_t *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);
|
||||
}
|
||||
@@ -241,7 +233,7 @@ int xmpp_stanza_is_tag(xmpp_stanza_t *stanza)
|
||||
* 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;
|
||||
char *src;
|
||||
@@ -294,8 +286,9 @@ static char *_escape_xml(xmpp_ctx_t *ctx, char *text)
|
||||
}
|
||||
|
||||
/* small helper function */
|
||||
static void _render_update(
|
||||
int *written, int length, int lastwrite, size_t *left, char **ptr)
|
||||
static void _render_update(int *written, const int length,
|
||||
const int lastwrite,
|
||||
size_t *left, char **ptr)
|
||||
{
|
||||
*written += lastwrite;
|
||||
|
||||
@@ -313,8 +306,8 @@ static void _render_update(
|
||||
* return values < 0 indicate some error occurred,
|
||||
* and return values > buflen indicate buffer was not large enough
|
||||
*/
|
||||
static int
|
||||
_render_stanza_recursive(xmpp_stanza_t *stanza, char *buf, size_t buflen)
|
||||
static int _render_stanza_recursive(xmpp_stanza_t *stanza,
|
||||
char * const buf, size_t const buflen)
|
||||
{
|
||||
char *ptr = buf;
|
||||
size_t left = buflen;
|
||||
@@ -326,29 +319,23 @@ _render_stanza_recursive(xmpp_stanza_t *stanza, char *buf, size_t buflen)
|
||||
|
||||
written = 0;
|
||||
|
||||
if (stanza->type == XMPP_STANZA_UNKNOWN)
|
||||
return XMPP_EINVOP;
|
||||
if (stanza->type == XMPP_STANZA_UNKNOWN) return XMPP_EINVOP;
|
||||
|
||||
if (stanza->type == XMPP_STANZA_TEXT) {
|
||||
if (!stanza->data)
|
||||
return XMPP_EINVOP;
|
||||
if (!stanza->data) return XMPP_EINVOP;
|
||||
|
||||
tmp = _escape_xml(stanza->ctx, stanza->data);
|
||||
if (tmp == NULL)
|
||||
return XMPP_EMEM;
|
||||
if (tmp == NULL) return XMPP_EMEM;
|
||||
ret = xmpp_snprintf(ptr, left, "%s", tmp);
|
||||
xmpp_free(stanza->ctx, tmp);
|
||||
if (ret < 0)
|
||||
return XMPP_EMEM;
|
||||
if (ret < 0) return XMPP_EMEM;
|
||||
_render_update(&written, buflen, ret, &left, &ptr);
|
||||
} else { /* stanza->type == XMPP_STANZA_TAG */
|
||||
if (!stanza->data)
|
||||
return XMPP_EINVOP;
|
||||
if (!stanza->data) return XMPP_EINVOP;
|
||||
|
||||
/* write beginning of tag and attributes */
|
||||
ret = xmpp_snprintf(ptr, left, "<%s", stanza->data);
|
||||
if (ret < 0)
|
||||
return XMPP_EMEM;
|
||||
if (ret < 0) return XMPP_EMEM;
|
||||
_render_update(&written, buflen, ret, &left, &ptr);
|
||||
|
||||
if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
|
||||
@@ -356,10 +343,10 @@ _render_stanza_recursive(xmpp_stanza_t *stanza, char *buf, size_t buflen)
|
||||
while ((key = hash_iter_next(iter))) {
|
||||
if (!strcmp(key, "xmlns")) {
|
||||
/* don't output namespace if parent stanza is the same */
|
||||
if (stanza->parent && stanza->parent->attributes &&
|
||||
if (stanza->parent &&
|
||||
stanza->parent->attributes &&
|
||||
hash_get(stanza->parent->attributes, key) &&
|
||||
!strcmp(
|
||||
(char *)hash_get(stanza->attributes, key),
|
||||
!strcmp((char*)hash_get(stanza->attributes, key),
|
||||
(char*)hash_get(stanza->parent->attributes, key)))
|
||||
continue;
|
||||
/* or if this is the stream namespace */
|
||||
@@ -388,24 +375,21 @@ _render_stanza_recursive(xmpp_stanza_t *stanza, char *buf, size_t buflen)
|
||||
if (!stanza->children) {
|
||||
/* write end if singleton tag */
|
||||
ret = xmpp_snprintf(ptr, left, "/>");
|
||||
if (ret < 0)
|
||||
return XMPP_EMEM;
|
||||
if (ret < 0) return XMPP_EMEM;
|
||||
_render_update(&written, buflen, ret, &left, &ptr);
|
||||
} else {
|
||||
/* this stanza has child stanzas */
|
||||
|
||||
/* write end of start tag */
|
||||
ret = xmpp_snprintf(ptr, left, ">");
|
||||
if (ret < 0)
|
||||
return XMPP_EMEM;
|
||||
if (ret < 0) return XMPP_EMEM;
|
||||
_render_update(&written, buflen, ret, &left, &ptr);
|
||||
|
||||
/* iterate and recurse over child stanzas */
|
||||
child = stanza->children;
|
||||
while (child) {
|
||||
ret = _render_stanza_recursive(child, ptr, left);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < 0) return ret;
|
||||
|
||||
_render_update(&written, buflen, ret, &left, &ptr);
|
||||
|
||||
@@ -414,8 +398,7 @@ _render_stanza_recursive(xmpp_stanza_t *stanza, char *buf, size_t buflen)
|
||||
|
||||
/* write end tag */
|
||||
ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
|
||||
if (ret < 0)
|
||||
return XMPP_EMEM;
|
||||
if (ret < 0) return XMPP_EMEM;
|
||||
|
||||
_render_update(&written, buflen, ret, &left, &ptr);
|
||||
}
|
||||
@@ -439,7 +422,9 @@ _render_stanza_recursive(xmpp_stanza_t *stanza, char *buf, size_t buflen)
|
||||
*
|
||||
* @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;
|
||||
size_t length;
|
||||
@@ -500,13 +485,12 @@ int xmpp_stanza_to_text(xmpp_stanza_t *stanza, char **buf, size_t *buflen)
|
||||
*
|
||||
* @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)
|
||||
return XMPP_EINVOP;
|
||||
if (stanza->type == XMPP_STANZA_TEXT) return XMPP_EINVOP;
|
||||
|
||||
if (stanza->data)
|
||||
xmpp_free(stanza->ctx, stanza->data);
|
||||
if (stanza->data) xmpp_free(stanza->ctx, stanza->data);
|
||||
|
||||
stanza->type = XMPP_STANZA_TAG;
|
||||
stanza->data = xmpp_strdup(stanza->ctx, name);
|
||||
@@ -524,10 +508,9 @@ int xmpp_stanza_set_name(xmpp_stanza_t *stanza, const char *name)
|
||||
*
|
||||
* @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)
|
||||
return NULL;
|
||||
if (stanza->type == XMPP_STANZA_TEXT) return NULL;
|
||||
return stanza->data;
|
||||
}
|
||||
|
||||
@@ -539,7 +522,7 @@ const char *xmpp_stanza_get_name(xmpp_stanza_t *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) {
|
||||
return 0;
|
||||
@@ -562,9 +545,8 @@ int xmpp_stanza_get_attribute_count(xmpp_stanza_t *stanza)
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
int xmpp_stanza_get_attributes(xmpp_stanza_t *stanza,
|
||||
const char **attr,
|
||||
int attrlen)
|
||||
int xmpp_stanza_get_attributes(xmpp_stanza_t * const stanza,
|
||||
const char **attr, int attrlen)
|
||||
{
|
||||
hash_iterator_t *iter;
|
||||
const char *key;
|
||||
@@ -604,20 +586,18 @@ int xmpp_stanza_get_attributes(xmpp_stanza_t *stanza,
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
int xmpp_stanza_set_attribute(xmpp_stanza_t *stanza,
|
||||
const char *key,
|
||||
const char *value)
|
||||
int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
|
||||
const char * const key,
|
||||
const char * const value)
|
||||
{
|
||||
char *val;
|
||||
int rc;
|
||||
|
||||
if (stanza->type != XMPP_STANZA_TAG)
|
||||
return XMPP_EINVOP;
|
||||
if (stanza->type != XMPP_STANZA_TAG) return XMPP_EINVOP;
|
||||
|
||||
if (!stanza->attributes) {
|
||||
stanza->attributes = hash_new(stanza->ctx, 8, xmpp_free);
|
||||
if (!stanza->attributes)
|
||||
return XMPP_EMEM;
|
||||
if (!stanza->attributes) return XMPP_EMEM;
|
||||
}
|
||||
|
||||
val = xmpp_strdup(stanza->ctx, value);
|
||||
@@ -645,7 +625,8 @@ int xmpp_stanza_set_attribute(xmpp_stanza_t *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);
|
||||
}
|
||||
@@ -665,8 +646,7 @@ int xmpp_stanza_set_ns(xmpp_stanza_t *stanza, const char *ns)
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
int xmpp_stanza_add_child_ex(xmpp_stanza_t *stanza,
|
||||
xmpp_stanza_t *child,
|
||||
int xmpp_stanza_add_child_ex(xmpp_stanza_t *stanza, xmpp_stanza_t *child,
|
||||
int do_clone)
|
||||
{
|
||||
xmpp_stanza_t *s;
|
||||
@@ -682,8 +662,7 @@ int xmpp_stanza_add_child_ex(xmpp_stanza_t *stanza,
|
||||
stanza->children = child;
|
||||
else {
|
||||
s = stanza->children;
|
||||
while (s->next)
|
||||
s = s->next;
|
||||
while (s->next) s = s->next;
|
||||
s->next = child;
|
||||
child->prev = s;
|
||||
}
|
||||
@@ -720,15 +699,14 @@ int xmpp_stanza_add_child(xmpp_stanza_t *stanza, xmpp_stanza_t *child)
|
||||
*
|
||||
* @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)
|
||||
return XMPP_EINVOP;
|
||||
if (stanza->type == XMPP_STANZA_TAG) return XMPP_EINVOP;
|
||||
|
||||
stanza->type = XMPP_STANZA_TEXT;
|
||||
|
||||
if (stanza->data)
|
||||
xmpp_free(stanza->ctx, stanza->data);
|
||||
if (stanza->data) xmpp_free(stanza->ctx, stanza->data);
|
||||
stanza->data = xmpp_strdup(stanza->ctx, text);
|
||||
|
||||
return stanza->data == NULL ? XMPP_EMEM : XMPP_EOK;
|
||||
@@ -749,19 +727,16 @@ int xmpp_stanza_set_text(xmpp_stanza_t *stanza, const char *text)
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza,
|
||||
const char *text,
|
||||
size_t size)
|
||||
const char * const text,
|
||||
const size_t size)
|
||||
{
|
||||
if (stanza->type == XMPP_STANZA_TAG)
|
||||
return XMPP_EINVOP;
|
||||
if (stanza->type == XMPP_STANZA_TAG) return XMPP_EINVOP;
|
||||
|
||||
stanza->type = XMPP_STANZA_TEXT;
|
||||
|
||||
if (stanza->data)
|
||||
xmpp_free(stanza->ctx, stanza->data);
|
||||
if (stanza->data) xmpp_free(stanza->ctx, stanza->data);
|
||||
stanza->data = xmpp_alloc(stanza->ctx, size + 1);
|
||||
if (!stanza->data)
|
||||
return XMPP_EMEM;
|
||||
if (!stanza->data) return XMPP_EMEM;
|
||||
|
||||
memcpy(stanza->data, text, size);
|
||||
stanza->data[size] = 0;
|
||||
@@ -779,7 +754,7 @@ int xmpp_stanza_set_text_with_size(xmpp_stanza_t *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");
|
||||
}
|
||||
@@ -794,7 +769,7 @@ const char *xmpp_stanza_get_id(xmpp_stanza_t *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");
|
||||
}
|
||||
@@ -809,7 +784,7 @@ const char *xmpp_stanza_get_ns(xmpp_stanza_t *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");
|
||||
}
|
||||
@@ -824,7 +799,7 @@ const char *xmpp_stanza_get_type(xmpp_stanza_t *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");
|
||||
}
|
||||
@@ -839,7 +814,7 @@ const char *xmpp_stanza_get_to(xmpp_stanza_t *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");
|
||||
}
|
||||
@@ -855,8 +830,8 @@ const char *xmpp_stanza_get_from(xmpp_stanza_t *stanza)
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t *stanza,
|
||||
const char *name)
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t * const stanza,
|
||||
const char * const name)
|
||||
{
|
||||
xmpp_stanza_t *child;
|
||||
|
||||
@@ -881,8 +856,8 @@ xmpp_stanza_t *xmpp_stanza_get_child_by_name(xmpp_stanza_t *stanza,
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t *stanza,
|
||||
const char *ns)
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t * const stanza,
|
||||
const char * const ns)
|
||||
{
|
||||
xmpp_stanza_t *child;
|
||||
const char *child_ns;
|
||||
@@ -909,9 +884,9 @@ xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t *stanza,
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t *stanza,
|
||||
const char *name,
|
||||
const char *ns)
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t * const stanza,
|
||||
const char * const name,
|
||||
const char * const ns)
|
||||
{
|
||||
xmpp_stanza_t *child;
|
||||
const char *child_ns;
|
||||
@@ -940,7 +915,7 @@ xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t *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;
|
||||
}
|
||||
@@ -953,7 +928,7 @@ xmpp_stanza_t *xmpp_stanza_get_children(xmpp_stanza_t *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;
|
||||
}
|
||||
@@ -969,7 +944,7 @@ xmpp_stanza_t *xmpp_stanza_get_next(xmpp_stanza_t *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;
|
||||
xmpp_stanza_t *child;
|
||||
@@ -987,12 +962,10 @@ char *xmpp_stanza_get_text(xmpp_stanza_t *stanza)
|
||||
if (child->type == XMPP_STANZA_TEXT)
|
||||
len += strlen(child->data);
|
||||
|
||||
if (len == 0)
|
||||
return NULL;
|
||||
if (len == 0) return NULL;
|
||||
|
||||
text = (char *)xmpp_alloc(stanza->ctx, len + 1);
|
||||
if (!text)
|
||||
return NULL;
|
||||
if (!text) return NULL;
|
||||
|
||||
len = 0;
|
||||
for (child = stanza->children; child; child = child->next)
|
||||
@@ -1020,7 +993,7 @@ char *xmpp_stanza_get_text(xmpp_stanza_t *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)
|
||||
return stanza->data;
|
||||
@@ -1039,7 +1012,8 @@ const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t *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);
|
||||
}
|
||||
@@ -1055,7 +1029,8 @@ int xmpp_stanza_set_id(xmpp_stanza_t *stanza, const char *id)
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
@@ -1072,7 +1047,8 @@ int xmpp_stanza_set_type(xmpp_stanza_t *stanza, const char *type)
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
@@ -1089,7 +1065,8 @@ int xmpp_stanza_set_to(xmpp_stanza_t *stanza, const char *to)
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
@@ -1105,7 +1082,8 @@ int xmpp_stanza_set_from(xmpp_stanza_t *stanza, const char *from)
|
||||
*
|
||||
* @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)
|
||||
return NULL;
|
||||
@@ -1125,7 +1103,8 @@ const char *xmpp_stanza_get_attribute(xmpp_stanza_t *stanza, const char *name)
|
||||
*
|
||||
* @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)
|
||||
return -1;
|
||||
@@ -1148,26 +1127,23 @@ int xmpp_stanza_del_attribute(xmpp_stanza_t *stanza, const char *name)
|
||||
*
|
||||
* @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;
|
||||
const char *from;
|
||||
int rc;
|
||||
|
||||
from = xmpp_stanza_get_from(stanza);
|
||||
if (!from)
|
||||
goto copy_error;
|
||||
if (!from) goto copy_error;
|
||||
|
||||
copy = xmpp_stanza_new(stanza->ctx);
|
||||
if (!copy)
|
||||
goto copy_error;
|
||||
if (!copy) goto copy_error;
|
||||
|
||||
copy->type = stanza->type;
|
||||
|
||||
if (stanza->data) {
|
||||
copy->data = xmpp_strdup(stanza->ctx, stanza->data);
|
||||
if (!copy->data)
|
||||
goto copy_error;
|
||||
if (!copy->data) goto copy_error;
|
||||
}
|
||||
|
||||
if (stanza->attributes) {
|
||||
@@ -1177,119 +1153,20 @@ xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t *stanza)
|
||||
|
||||
xmpp_stanza_del_attribute(copy, "to");
|
||||
xmpp_stanza_del_attribute(copy, "from");
|
||||
xmpp_stanza_del_attribute(copy, "xmlns");
|
||||
rc = xmpp_stanza_set_to(copy, from);
|
||||
if (rc != XMPP_EOK)
|
||||
goto copy_error;
|
||||
if (rc != XMPP_EOK) goto copy_error;
|
||||
|
||||
return copy;
|
||||
|
||||
copy_error:
|
||||
if (copy)
|
||||
xmpp_stanza_release(copy);
|
||||
if (copy) xmpp_stanza_release(copy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Create an error stanza in reply to the provided stanza.
|
||||
*
|
||||
* Check https://tools.ietf.org/html/rfc6120#section-8.3 for details.
|
||||
*
|
||||
* @param stanza a Strophe stanza object
|
||||
* @param error_type type attribute in the <error/> child element
|
||||
* @param condition the defined-condition (e.g. "item-not-found")
|
||||
* @param text optional description, may be NULL
|
||||
*
|
||||
* @return a new Strophe stanza object
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
xmpp_stanza_t *xmpp_stanza_reply_error(xmpp_stanza_t *stanza,
|
||||
const char *error_type,
|
||||
const char *condition,
|
||||
const char *text)
|
||||
{
|
||||
xmpp_ctx_t *ctx = stanza->ctx;
|
||||
xmpp_stanza_t *reply = NULL;
|
||||
xmpp_stanza_t *error = NULL;
|
||||
xmpp_stanza_t *item = NULL;
|
||||
xmpp_stanza_t *text_stanza = NULL;
|
||||
const char *to;
|
||||
|
||||
if (!error_type || !condition)
|
||||
goto quit_err;
|
||||
|
||||
reply = xmpp_stanza_reply(stanza);
|
||||
if (!reply)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_set_type(reply, "error") != XMPP_EOK)
|
||||
goto quit_err;
|
||||
to = xmpp_stanza_get_to(stanza);
|
||||
if (to)
|
||||
if (xmpp_stanza_set_from(reply, to) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
|
||||
error = xmpp_stanza_new(ctx);
|
||||
if (!error)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_set_name(error, "error") != XMPP_EOK)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_set_type(error, error_type) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_add_child(reply, error) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
xmpp_stanza_release(error);
|
||||
|
||||
item = xmpp_stanza_new(ctx);
|
||||
if (!item)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_set_name(item, condition) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_set_ns(item, XMPP_NS_STANZAS_IETF) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_add_child(error, item) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
xmpp_stanza_release(item);
|
||||
|
||||
if (text) {
|
||||
item = xmpp_stanza_new(ctx);
|
||||
if (!item)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_set_name(item, "text") != XMPP_EOK)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_set_ns(item, XMPP_NS_STANZAS_IETF) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_add_child(error, item) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
xmpp_stanza_release(item);
|
||||
text_stanza = xmpp_stanza_new(ctx);
|
||||
if (!text_stanza)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_set_text(text_stanza, text) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
if (xmpp_stanza_add_child(item, text_stanza) != XMPP_EOK)
|
||||
goto quit_err;
|
||||
xmpp_stanza_release(text_stanza);
|
||||
}
|
||||
|
||||
return reply;
|
||||
|
||||
quit_err:
|
||||
if (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;
|
||||
}
|
||||
|
||||
static xmpp_stanza_t *_stanza_new_with_attrs(xmpp_ctx_t *ctx,
|
||||
const char *name,
|
||||
const char *type,
|
||||
const char *id,
|
||||
const char *to)
|
||||
static xmpp_stanza_t *
|
||||
_stanza_new_with_attrs(xmpp_ctx_t *ctx, const char * const name,
|
||||
const char * const type, const char * const id,
|
||||
const char * const to)
|
||||
{
|
||||
xmpp_stanza_t *stanza = xmpp_stanza_new(ctx);
|
||||
int ret;
|
||||
@@ -1322,10 +1199,8 @@ static xmpp_stanza_t *_stanza_new_with_attrs(xmpp_ctx_t *ctx,
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
xmpp_stanza_t *xmpp_message_new(xmpp_ctx_t *ctx,
|
||||
const char *type,
|
||||
const char *to,
|
||||
const char *id)
|
||||
xmpp_stanza_t *xmpp_message_new(xmpp_ctx_t *ctx, const char * const type,
|
||||
const char * const to, const char * const id)
|
||||
{
|
||||
return _stanza_new_with_attrs(ctx, "message", type, id, to);
|
||||
}
|
||||
@@ -1364,7 +1239,7 @@ char *xmpp_message_get_body(xmpp_stanza_t *msg)
|
||||
*
|
||||
* @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_stanza_t *body;
|
||||
@@ -1410,7 +1285,8 @@ int xmpp_message_set_body(xmpp_stanza_t *msg, const char *text)
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
@@ -1441,11 +1317,10 @@ xmpp_stanza_t *xmpp_presence_new(xmpp_ctx_t *ctx)
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
xmpp_stanza_t *
|
||||
xmpp_error_new(xmpp_ctx_t *ctx, xmpp_error_type_t type, const char *text)
|
||||
xmpp_stanza_t *xmpp_error_new(xmpp_ctx_t *ctx, xmpp_error_type_t const type,
|
||||
const char * const text)
|
||||
{
|
||||
xmpp_stanza_t *error =
|
||||
_stanza_new_with_attrs(ctx, "stream:error", NULL, NULL, NULL);
|
||||
xmpp_stanza_t *error = _stanza_new_with_attrs(ctx, "stream:error", NULL, NULL, NULL);
|
||||
xmpp_stanza_t *error_type = xmpp_stanza_new(ctx);
|
||||
|
||||
switch(type) {
|
||||
@@ -1547,59 +1422,3 @@ xmpp_error_new(xmpp_ctx_t *ctx, xmpp_error_type_t type, const char *text)
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void _stub_stream_start(char *name, char **attrs, void *userdata)
|
||||
{
|
||||
UNUSED(name);
|
||||
UNUSED(attrs);
|
||||
UNUSED(userdata);
|
||||
}
|
||||
|
||||
static void _stub_stream_end(char *name, void *userdata)
|
||||
{
|
||||
UNUSED(name);
|
||||
UNUSED(userdata);
|
||||
}
|
||||
|
||||
static void _stream_stanza(xmpp_stanza_t *stanza, void *userdata)
|
||||
{
|
||||
stanza = xmpp_stanza_clone(stanza);
|
||||
*(xmpp_stanza_t **)userdata = stanza;
|
||||
}
|
||||
|
||||
/** Create a stanza object from the string.
|
||||
* This function allocates and initializes a stanza object which represents
|
||||
* stanza located in the string.
|
||||
* The stanza will have a reference count of one, so the caller does not
|
||||
* need to clone it.
|
||||
*
|
||||
* @param ctx a Strophe context object
|
||||
* @param str stanza in NULL terminated string representation
|
||||
*
|
||||
* @return a stanza object or NULL on an error
|
||||
*
|
||||
* @ingroup Stanza
|
||||
*/
|
||||
xmpp_stanza_t *xmpp_stanza_new_from_string(xmpp_ctx_t *ctx, const char *str)
|
||||
{
|
||||
xmpp_stanza_t *stanza = NULL;
|
||||
parser_t *parser;
|
||||
int ret;
|
||||
|
||||
static const char *start = "<stream>";
|
||||
static const char *end = "</stream>";
|
||||
|
||||
parser = parser_new(ctx, _stub_stream_start, _stub_stream_end,
|
||||
_stream_stanza, &stanza);
|
||||
if (parser) {
|
||||
ret = parser_feed(parser, (char *)start, strlen(start)) &&
|
||||
parser_feed(parser, (char *)str, strlen(str)) &&
|
||||
parser_feed(parser, (char *)end, strlen(end));
|
||||
parser_free(parser);
|
||||
if (!ret && stanza) {
|
||||
xmpp_stanza_release(stanza);
|
||||
stanza = NULL;
|
||||
}
|
||||
}
|
||||
return stanza;
|
||||
}
|
||||
|
||||
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 _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_shutdown(void);
|
||||
|
||||
tls_t *tls_new(xmpp_conn_t *conn);
|
||||
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_start(tls_t *tls);
|
||||
@@ -51,15 +35,10 @@ int tls_stop(tls_t *tls);
|
||||
int tls_error(tls_t *tls);
|
||||
|
||||
int tls_pending(tls_t *tls);
|
||||
int tls_read(tls_t *tls, void *buff, size_t len);
|
||||
int tls_write(tls_t *tls, const 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 * const buff, const size_t len);
|
||||
|
||||
int tls_clear_pending_write(tls_t *tls);
|
||||
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__ */
|
||||
|
||||
@@ -33,96 +33,59 @@ void tls_shutdown(void)
|
||||
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)
|
||||
{
|
||||
UNUSED(conn);
|
||||
/* always fail */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void tls_free(tls_t *tls)
|
||||
{
|
||||
UNUSED(tls);
|
||||
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)
|
||||
{
|
||||
UNUSED(tls);
|
||||
UNUSED(cafilename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tls_start(tls_t *tls)
|
||||
{
|
||||
UNUSED(tls);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tls_stop(tls_t *tls)
|
||||
{
|
||||
UNUSED(tls);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tls_error(tls_t *tls)
|
||||
{
|
||||
UNUSED(tls);
|
||||
/* todo: some kind of error polling/dump */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_pending(tls_t *tls)
|
||||
{
|
||||
UNUSED(tls);
|
||||
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(buff);
|
||||
UNUSED(len);
|
||||
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(buff);
|
||||
UNUSED(len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tls_clear_pending_write(tls_t *tls)
|
||||
{
|
||||
UNUSED(tls);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tls_is_recoverable(int error)
|
||||
{
|
||||
UNUSED(error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
335
src/tls_gnutls.c
335
src/tls_gnutls.c
@@ -13,21 +13,20 @@
|
||||
* TLS implementation with GNUTLS
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/x509.h>
|
||||
#include <gnutls/x509-ext.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "tls.h"
|
||||
#include "sock.h"
|
||||
|
||||
/* FIXME this shouldn't be a constant string */
|
||||
#define CAFILE "/etc/ssl/certs/ca-certificates.crt"
|
||||
|
||||
struct _tls {
|
||||
xmpp_ctx_t *ctx; /* do we need this? */
|
||||
xmpp_conn_t *conn;
|
||||
sock_t sock;
|
||||
gnutls_session_t session;
|
||||
gnutls_certificate_credentials_t cred;
|
||||
gnutls_x509_crt_t client_cert;
|
||||
int lasterror;
|
||||
};
|
||||
|
||||
@@ -47,299 +46,19 @@ void tls_shutdown(void)
|
||||
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 = xmpp_alloc(conn->ctx, sizeof(tls_t));
|
||||
|
||||
if (tls) {
|
||||
memset(tls, 0, sizeof(*tls));
|
||||
tls->ctx = conn->ctx;
|
||||
tls->conn = conn;
|
||||
tls->sock = conn->sock;
|
||||
gnutls_init(&tls->session, GNUTLS_CLIENT);
|
||||
|
||||
gnutls_certificate_allocate_credentials(&tls->cred);
|
||||
tls_set_credentials(tls, NULL);
|
||||
|
||||
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);
|
||||
tls_set_credentials(tls, CAFILE);
|
||||
|
||||
gnutls_set_default_priority(tls->session);
|
||||
gnutls_session_set_ptr(tls->session, tls);
|
||||
|
||||
/* fixme: this may require setting a callback on win32? */
|
||||
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)
|
||||
{
|
||||
if (tls->client_cert)
|
||||
gnutls_x509_crt_deinit(tls->client_cert);
|
||||
gnutls_deinit(tls->session);
|
||||
gnutls_certificate_free_credentials(tls->cred);
|
||||
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)
|
||||
{
|
||||
UNUSED(cafilename);
|
||||
int err;
|
||||
|
||||
/* set trusted credentials -- takes a .pem filename */
|
||||
int err = gnutls_certificate_set_x509_system_trust(tls->cred);
|
||||
if (err >= 0 && tls->conn->tls_cafile)
|
||||
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);
|
||||
err = gnutls_certificate_set_x509_trust_file(tls->cred,
|
||||
cafilename, GNUTLS_X509_FMT_PEM);
|
||||
if (err >= 0) {
|
||||
err = gnutls_credentials_set(tls->session, GNUTLS_CRD_CERTIFICATE,
|
||||
tls->cred);
|
||||
@@ -400,9 +92,9 @@ int tls_set_credentials(tls_t *tls, const char *cafilename)
|
||||
|
||||
int tls_start(tls_t *tls)
|
||||
{
|
||||
sock_set_blocking(tls->conn->sock);
|
||||
sock_set_blocking(tls->sock);
|
||||
tls->lasterror = gnutls_handshake(tls->session);
|
||||
sock_set_nonblocking(tls->conn->sock);
|
||||
sock_set_nonblocking(tls->sock);
|
||||
|
||||
return tls->lasterror == GNUTLS_E_SUCCESS;
|
||||
}
|
||||
@@ -428,7 +120,7 @@ int tls_pending(tls_t *tls)
|
||||
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;
|
||||
|
||||
@@ -438,7 +130,7 @@ int tls_read(tls_t *tls, void *buff, size_t len)
|
||||
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;
|
||||
|
||||
@@ -450,6 +142,5 @@ int tls_write(tls_t *tls, const void *buff, size_t len)
|
||||
|
||||
int tls_clear_pending_write(tls_t *tls)
|
||||
{
|
||||
UNUSED(tls);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -47,34 +47,11 @@
|
||||
#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 {
|
||||
xmpp_ctx_t *ctx;
|
||||
sock_t sock;
|
||||
SSL_CTX *ssl_ctx;
|
||||
SSL *ssl;
|
||||
X509 *client_cert;
|
||||
int lasterror;
|
||||
};
|
||||
|
||||
@@ -85,130 +62,9 @@ enum {
|
||||
};
|
||||
|
||||
static void _tls_sock_wait(tls_t *tls, int error);
|
||||
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_log_error(xmpp_ctx_t *ctx);
|
||||
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) \
|
||||
_tls_error_str(error, table, ARRAY_SIZE(table))
|
||||
|
||||
#define TLS_ERROR_FIELD(x) [x] = #x
|
||||
const char *tls_errors[] = {
|
||||
TLS_ERROR_FIELD(SSL_ERROR_NONE),
|
||||
TLS_ERROR_FIELD(SSL_ERROR_SSL),
|
||||
TLS_ERROR_FIELD(SSL_ERROR_WANT_READ),
|
||||
TLS_ERROR_FIELD(SSL_ERROR_WANT_WRITE),
|
||||
TLS_ERROR_FIELD(SSL_ERROR_WANT_X509_LOOKUP),
|
||||
TLS_ERROR_FIELD(SSL_ERROR_SYSCALL),
|
||||
TLS_ERROR_FIELD(SSL_ERROR_ZERO_RETURN),
|
||||
TLS_ERROR_FIELD(SSL_ERROR_WANT_CONNECT),
|
||||
TLS_ERROR_FIELD(SSL_ERROR_WANT_ACCEPT),
|
||||
#ifndef LIBRESSL_VERSION_NUMBER
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
TLS_ERROR_FIELD(SSL_ERROR_WANT_ASYNC),
|
||||
TLS_ERROR_FIELD(SSL_ERROR_WANT_ASYNC_JOB),
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10101000L
|
||||
TLS_ERROR_FIELD(SSL_ERROR_WANT_CLIENT_HELLO_CB),
|
||||
#endif
|
||||
#endif /* !LIBRESSL_VERSION_NUMBER */
|
||||
};
|
||||
const char *cert_errors[] = {
|
||||
TLS_ERROR_FIELD(X509_V_OK),
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNSPECIFIED),
|
||||
#endif
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNABLE_TO_GET_CRL),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CERT_SIGNATURE_FAILURE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CRL_SIGNATURE_FAILURE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CERT_NOT_YET_VALID),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CERT_HAS_EXPIRED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CRL_NOT_YET_VALID),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CRL_HAS_EXPIRED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_OUT_OF_MEM),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CERT_CHAIN_TOO_LONG),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CERT_REVOKED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_INVALID_CA),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_PATH_LENGTH_EXCEEDED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_INVALID_PURPOSE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CERT_UNTRUSTED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_CERT_REJECTED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_SUBJECT_ISSUER_MISMATCH),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_AKID_SKID_MISMATCH),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_KEYUSAGE_NO_CERTSIGN),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_INVALID_NON_CA),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_INVALID_EXTENSION),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_INVALID_POLICY_EXTENSION),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_NO_EXPLICIT_POLICY),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_APPLICATION_VERIFICATION),
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
TLS_ERROR_FIELD(X509_V_ERR_DIFFERENT_CRL_SCOPE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNNESTED_RESOURCE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_PERMITTED_VIOLATION),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_EXCLUDED_VIOLATION),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_SUBTREE_MINMAX),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_UNSUPPORTED_NAME_SYNTAX),
|
||||
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_ALGORITHM),
|
||||
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_LOS_NOT_ALLOWED),
|
||||
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_EMAIL_MISMATCH),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_IP_ADDRESS_MISMATCH),
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||
#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_DANE_NO_MATCH),
|
||||
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_MD_TOO_WEAK),
|
||||
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_OCSP_VERIFY_NEEDED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_OCSP_VERIFY_FAILED),
|
||||
TLS_ERROR_FIELD(X509_V_ERR_OCSP_CERT_UNKNOWN),
|
||||
#endif /* !LIBRESSL_VERSION_NUMBER */
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
|
||||
};
|
||||
#undef TLS_ERROR_FIELD
|
||||
|
||||
void tls_initialize(void)
|
||||
{
|
||||
@@ -218,8 +74,6 @@ void tls_initialize(void)
|
||||
#else
|
||||
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||
#endif
|
||||
/* init xmppAddr OID */
|
||||
_tls_xaddr_nid();
|
||||
}
|
||||
|
||||
void tls_shutdown(void)
|
||||
@@ -230,7 +84,6 @@ void tls_shutdown(void)
|
||||
* memory rather than cause random crashes of the main program.
|
||||
*/
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
OBJ_cleanup();
|
||||
ERR_free_strings();
|
||||
EVP_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
@@ -250,265 +103,10 @@ int tls_error(tls_t *tls)
|
||||
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 = xmpp_alloc(conn->ctx, sizeof(*tls));
|
||||
int mode;
|
||||
|
||||
if (tls) {
|
||||
int ret;
|
||||
@@ -536,23 +134,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_TLSv1); /* BEAST */
|
||||
|
||||
if (conn->tls_client_cert && conn->tls_client_key) {
|
||||
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);
|
||||
|
||||
ret = SSL_CTX_set_default_verify_paths(tls->ssl_ctx);
|
||||
@@ -564,35 +146,21 @@ tls_t *tls_new(xmpp_conn_t *conn)
|
||||
*/
|
||||
xmpp_error(tls->ctx, "tls",
|
||||
"SSL_CTX_set_default_verify_paths() failed");
|
||||
goto err_free_cert;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
goto err_free_ctx;
|
||||
}
|
||||
|
||||
tls->ssl = SSL_new(tls->ssl_ctx);
|
||||
if (tls->ssl == NULL)
|
||||
goto err_free_cert;
|
||||
goto err_free_ctx;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x0908060L && !defined(OPENSSL_NO_TLSEXT)
|
||||
/* Enable SNI. */
|
||||
SSL_set_tlsext_host_name(tls->ssl, conn->domain);
|
||||
#endif
|
||||
|
||||
/* Trust server's certificate when user sets the flag explicitly.
|
||||
* Otherwise call the verification callback */
|
||||
if (conn->tls_trust)
|
||||
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);
|
||||
/* Trust server's certificate when user sets the flag explicitly. */
|
||||
mode = conn->tls_trust ? SSL_VERIFY_NONE : SSL_VERIFY_PEER;
|
||||
SSL_set_verify(tls->ssl, mode, 0);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
/* Hostname verification is supported in OpenSSL 1.0.2 and newer. */
|
||||
param = SSL_get0_param(tls->ssl);
|
||||
@@ -601,11 +169,9 @@ tls_t *tls_new(xmpp_conn_t *conn)
|
||||
* Allow only complete wildcards. RFC 6125 discourages wildcard usage
|
||||
* completely, and lists internationalized domain names as a reason
|
||||
* against partial wildcards.
|
||||
* See https://tools.ietf.org/html/rfc6125#section-7.2 for more
|
||||
* information.
|
||||
* See https://tools.ietf.org/html/rfc6125#section-7.2 for more information.
|
||||
*/
|
||||
X509_VERIFY_PARAM_set_hostflags(param,
|
||||
X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
X509_VERIFY_PARAM_set1_host(param, conn->domain, 0);
|
||||
#endif
|
||||
|
||||
@@ -618,8 +184,6 @@ tls_t *tls_new(xmpp_conn_t *conn)
|
||||
|
||||
err_free_ssl:
|
||||
SSL_free(tls->ssl);
|
||||
err_free_cert:
|
||||
X509_free(tls->client_cert);
|
||||
err_free_ctx:
|
||||
SSL_CTX_free(tls->ssl_ctx);
|
||||
err:
|
||||
@@ -631,28 +195,12 @@ err:
|
||||
void tls_free(tls_t *tls)
|
||||
{
|
||||
SSL_free(tls->ssl);
|
||||
X509_free(tls->client_cert);
|
||||
SSL_CTX_free(tls->ssl_ctx);
|
||||
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)
|
||||
{
|
||||
UNUSED(tls);
|
||||
UNUSED(cafilename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -679,15 +227,8 @@ int tls_start(tls_t *tls)
|
||||
}
|
||||
|
||||
x509_res = SSL_get_verify_result(tls->ssl);
|
||||
if (x509_res == X509_V_OK) {
|
||||
xmpp_debug(tls->ctx, "tls", "Certificate verification passed");
|
||||
} else {
|
||||
xmpp_debug(tls->ctx, "tls",
|
||||
"Certificate verification FAILED, result=%s(%ld)",
|
||||
TLS_ERROR_STR((int)x509_res, cert_errors), x509_res);
|
||||
if (ret > 0)
|
||||
xmpp_debug(tls->ctx, "tls", "User decided to connect anyways");
|
||||
}
|
||||
xmpp_debug(tls->ctx, "tls", "Certificate verification %s",
|
||||
x509_res == X509_V_OK ? "passed" : "FAILED");
|
||||
_tls_dump_cert_info(tls);
|
||||
|
||||
_tls_set_error(tls, error);
|
||||
@@ -730,9 +271,10 @@ int tls_stop(tls_t *tls)
|
||||
|
||||
int tls_is_recoverable(int error)
|
||||
{
|
||||
return (error == SSL_ERROR_NONE || error == SSL_ERROR_WANT_READ ||
|
||||
error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_CONNECT ||
|
||||
error == SSL_ERROR_WANT_ACCEPT);
|
||||
return (error == SSL_ERROR_NONE || error == SSL_ERROR_WANT_READ
|
||||
|| error == SSL_ERROR_WANT_WRITE
|
||||
|| error == SSL_ERROR_WANT_CONNECT
|
||||
|| error == SSL_ERROR_WANT_ACCEPT);
|
||||
}
|
||||
|
||||
int tls_pending(tls_t *tls)
|
||||
@@ -740,7 +282,7 @@ int tls_pending(tls_t *tls)
|
||||
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;
|
||||
|
||||
@@ -750,7 +292,7 @@ int tls_read(tls_t *tls, void *buff, size_t len)
|
||||
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;
|
||||
|
||||
@@ -762,7 +304,6 @@ int tls_write(tls_t *tls, const void *buff, size_t len)
|
||||
|
||||
int tls_clear_pending_write(tls_t *tls)
|
||||
{
|
||||
UNUSED(tls);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -774,8 +315,7 @@ static void _tls_sock_wait(tls_t *tls, int error)
|
||||
int nfds;
|
||||
int ret;
|
||||
|
||||
if (error == SSL_ERROR_NONE)
|
||||
return;
|
||||
if (error == SSL_ERROR_NONE) return;
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
FD_ZERO(&wfds);
|
||||
@@ -783,9 +323,8 @@ static void _tls_sock_wait(tls_t *tls, int error)
|
||||
FD_SET(tls->sock, &rfds);
|
||||
if (error == SSL_ERROR_WANT_WRITE)
|
||||
FD_SET(tls->sock, &wfds);
|
||||
nfds = (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE)
|
||||
? tls->sock + 1
|
||||
: 0;
|
||||
nfds = (error == SSL_ERROR_WANT_READ || error == SSL_ERROR_WANT_WRITE) ?
|
||||
tls->sock + 1 : 0;
|
||||
do {
|
||||
tv.tv_sec = TLS_TIMEOUT_SEC;
|
||||
tv.tv_usec = TLS_TIMEOUT_USEC;
|
||||
@@ -793,16 +332,10 @@ static void _tls_sock_wait(tls_t *tls, int error)
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
}
|
||||
|
||||
static const char *_tls_error_str(int error, const char **tbl, size_t tbl_size)
|
||||
{
|
||||
return (error >= 0 && (size_t)error < tbl_size) ? tbl[error] : "UNKNOWN";
|
||||
}
|
||||
|
||||
static void _tls_set_error(tls_t *tls, int error)
|
||||
{
|
||||
if (error != 0 && !tls_is_recoverable(error)) {
|
||||
xmpp_debug(tls->ctx, "tls", "error=%s(%d) errno=%d",
|
||||
TLS_ERROR_STR(error, tls_errors), error, errno);
|
||||
xmpp_debug(tls->ctx, "tls", "error=%d errno=%d", error, errno);
|
||||
_tls_log_error(tls->ctx);
|
||||
}
|
||||
tls->lasterror = error;
|
||||
@@ -844,111 +377,3 @@ static void _tls_dump_cert_info(tls_t *tls)
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
xmpp_ctx_t *ctx = conn->ctx;
|
||||
@@ -133,7 +118,8 @@ tls_t *tls_new(xmpp_conn_t *conn)
|
||||
|
||||
ret = tls->sft->QuerySecurityPackageInfo(UNISP_NAME, &(tls->spi));
|
||||
|
||||
if (ret != SEC_E_OK) {
|
||||
if (ret != SEC_E_OK)
|
||||
{
|
||||
tls_free(tls);
|
||||
return NULL;
|
||||
}
|
||||
@@ -154,11 +140,11 @@ tls_t *tls_new(xmpp_conn_t *conn)
|
||||
(void)algs;
|
||||
#endif
|
||||
|
||||
ret = tls->sft->AcquireCredentialsHandleA(
|
||||
NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, &scred, NULL, NULL,
|
||||
&(tls->hcred), NULL);
|
||||
ret = tls->sft->AcquireCredentialsHandleA(NULL, UNISP_NAME,
|
||||
SECPKG_CRED_OUTBOUND, NULL, &scred, NULL, NULL, &(tls->hcred), NULL);
|
||||
|
||||
if (ret != SEC_E_OK) {
|
||||
if (ret != SEC_E_OK)
|
||||
{
|
||||
tls_free(tls);
|
||||
return NULL;
|
||||
}
|
||||
@@ -169,23 +155,23 @@ tls_t *tls_new(xmpp_conn_t *conn)
|
||||
|
||||
/* This bunch of queries should trip up wine until someone fixes
|
||||
* schannel support there */
|
||||
ret = tls->sft->QueryCredentialsAttributes(
|
||||
&(tls->hcred), SECPKG_ATTR_SUPPORTED_ALGS, &spc_sa);
|
||||
if (ret != SEC_E_OK) {
|
||||
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_ALGS, &spc_sa);
|
||||
if (ret != SEC_E_OK)
|
||||
{
|
||||
tls_free(tls);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = tls->sft->QueryCredentialsAttributes(
|
||||
&(tls->hcred), SECPKG_ATTR_CIPHER_STRENGTHS, &spc_cs);
|
||||
if (ret != SEC_E_OK) {
|
||||
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_CIPHER_STRENGTHS, &spc_cs);
|
||||
if (ret != SEC_E_OK)
|
||||
{
|
||||
tls_free(tls);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = tls->sft->QueryCredentialsAttributes(
|
||||
&(tls->hcred), SECPKG_ATTR_SUPPORTED_PROTOCOLS, &spc_sp);
|
||||
if (ret != SEC_E_OK) {
|
||||
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_PROTOCOLS, &spc_sp);
|
||||
if (ret != SEC_E_OK)
|
||||
{
|
||||
tls_free(tls);
|
||||
return NULL;
|
||||
}
|
||||
@@ -222,17 +208,8 @@ void tls_free(tls_t *tls)
|
||||
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)
|
||||
{
|
||||
UNUSED(tls);
|
||||
UNUSED(cafilename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -248,10 +225,10 @@ int tls_start(tls_t *tls)
|
||||
/* use the domain there as our name */
|
||||
name = tls->conn->domain;
|
||||
|
||||
ctxtreq = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
|
||||
ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR |
|
||||
ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM |
|
||||
ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY;
|
||||
ctxtreq = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT
|
||||
| ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR
|
||||
| ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM
|
||||
| ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY;
|
||||
|
||||
memset(&(sbout[0]), 0, sizeof(sbout[0]));
|
||||
sbout[0].BufferType = SECBUFFER_TOKEN;
|
||||
@@ -274,16 +251,16 @@ int tls_start(tls_t *tls)
|
||||
sbdin.cBuffers = 2;
|
||||
sbdin.pBuffers = sbin;
|
||||
|
||||
ret = tls->sft->InitializeSecurityContextA(
|
||||
&(tls->hcred), NULL, name, ctxtreq, 0, 0, NULL, 0, &(tls->hctxt),
|
||||
&sbdout, &ctxtattr, NULL);
|
||||
ret = tls->sft->InitializeSecurityContextA(&(tls->hcred), NULL, name, ctxtreq, 0, 0,
|
||||
NULL, 0, &(tls->hctxt), &sbdout,
|
||||
&ctxtattr, NULL);
|
||||
|
||||
unsigned char *p = sbin[0].pvBuffer;
|
||||
int len = 0;
|
||||
|
||||
while (ret == SEC_I_CONTINUE_NEEDED ||
|
||||
ret == SEC_I_INCOMPLETE_CREDENTIALS ||
|
||||
ret == SEC_E_INCOMPLETE_MESSAGE) {
|
||||
while (ret == SEC_I_CONTINUE_NEEDED
|
||||
|| ret == SEC_I_INCOMPLETE_CREDENTIALS
|
||||
|| ret == SEC_E_INCOMPLETE_MESSAGE) {
|
||||
int inbytes = 0;
|
||||
|
||||
if (ret != SEC_E_INCOMPLETE_MESSAGE) {
|
||||
@@ -298,7 +275,9 @@ int tls_start(tls_t *tls)
|
||||
sent = sock_write(tls->sock, writebuff, writelen);
|
||||
if (sent == -1) {
|
||||
tls->lasterror = sock_error();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
writebuff += sent;
|
||||
writelen -= sent;
|
||||
}
|
||||
@@ -340,16 +319,20 @@ int tls_start(tls_t *tls)
|
||||
if (inbytes > 0) {
|
||||
len += inbytes;
|
||||
p += inbytes;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
tls->lasterror = sock_error();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sbin[0].cbBuffer = len;
|
||||
|
||||
ret = tls->sft->InitializeSecurityContextA(
|
||||
&(tls->hcred), &(tls->hctxt), name, ctxtreq, 0, 0, &sbdin, 0,
|
||||
&(tls->hctxt), &sbdout, &ctxtattr, NULL);
|
||||
ret = tls->sft->InitializeSecurityContextA(&(tls->hcred), &(tls->hctxt), name,
|
||||
ctxtreq, 0, 0, &sbdin, 0,
|
||||
&(tls->hctxt), &sbdout,
|
||||
&ctxtattr, NULL);
|
||||
}
|
||||
|
||||
if (ret == SEC_E_OK) {
|
||||
@@ -359,7 +342,9 @@ int tls_start(tls_t *tls)
|
||||
sent = sock_write(tls->sock, writebuff, writelen);
|
||||
if (sent == -1) {
|
||||
tls->lasterror = sock_error();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
writebuff += sent;
|
||||
writelen -= sent;
|
||||
}
|
||||
@@ -373,21 +358,20 @@ int tls_start(tls_t *tls)
|
||||
|
||||
if (ret != SEC_E_OK) {
|
||||
tls->lasterror = ret;
|
||||
xmpp_error(tls->ctx, "TLSS", "Schannel error 0x%lx",
|
||||
(unsigned long)ret);
|
||||
xmpp_error(tls->ctx, "TLSS", "Schannel error 0x%lx", (unsigned long)ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tls->sft->QueryContextAttributes(&(tls->hctxt), SECPKG_ATTR_STREAM_SIZES,
|
||||
&(tls->spcss));
|
||||
|
||||
tls->recvbuffermaxlen = tls->spcss.cbHeader + tls->spcss.cbMaximumMessage +
|
||||
tls->spcss.cbTrailer;
|
||||
tls->recvbuffermaxlen = tls->spcss.cbHeader + tls->spcss.cbMaximumMessage
|
||||
+ tls->spcss.cbTrailer;
|
||||
tls->recvbuffer = xmpp_alloc(tls->ctx, tls->recvbuffermaxlen);
|
||||
tls->recvbufferpos = 0;
|
||||
|
||||
tls->sendbuffermaxlen = tls->spcss.cbHeader + tls->spcss.cbMaximumMessage +
|
||||
tls->spcss.cbTrailer;
|
||||
tls->sendbuffermaxlen = tls->spcss.cbHeader + tls->spcss.cbMaximumMessage
|
||||
+ tls->spcss.cbTrailer;
|
||||
tls->sendbuffer = xmpp_alloc(tls->ctx, tls->sendbuffermaxlen);
|
||||
tls->sendbufferpos = 0;
|
||||
tls->sendbufferlen = 0;
|
||||
@@ -401,7 +385,6 @@ int tls_start(tls_t *tls)
|
||||
|
||||
int tls_stop(tls_t *tls)
|
||||
{
|
||||
UNUSED(tls);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -412,13 +395,12 @@ int tls_error(tls_t *tls)
|
||||
|
||||
int tls_is_recoverable(int error)
|
||||
{
|
||||
return (error == SEC_E_OK || error == SEC_E_INCOMPLETE_MESSAGE ||
|
||||
error == WSAEWOULDBLOCK || error == WSAEMSGSIZE ||
|
||||
error == WSAEINPROGRESS);
|
||||
return (error == SEC_E_OK || error == SEC_E_INCOMPLETE_MESSAGE
|
||||
|| error == WSAEWOULDBLOCK || error == WSAEMSGSIZE
|
||||
|| error == WSAEINPROGRESS);
|
||||
}
|
||||
|
||||
int tls_pending(tls_t *tls)
|
||||
{
|
||||
int tls_pending(tls_t *tls) {
|
||||
// There are 3 cases:
|
||||
// - there is data in ready buffer, so it is by default pending
|
||||
// - there is data in recv buffer. If it is not decrypted yet, means it
|
||||
@@ -434,12 +416,13 @@ int tls_pending(tls_t *tls)
|
||||
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;
|
||||
|
||||
/* first, if we've got some ready data, put that in the buffer */
|
||||
if (tls->readybufferpos < tls->readybufferlen) {
|
||||
if (tls->readybufferpos < tls->readybufferlen)
|
||||
{
|
||||
if (len < tls->readybufferlen - tls->readybufferpos) {
|
||||
bytes = len;
|
||||
} else {
|
||||
@@ -536,7 +519,8 @@ int tls_read(tls_t *tls, void *buff, size_t len)
|
||||
return -1;
|
||||
} else if (ret == SEC_I_RENEGOTIATE) {
|
||||
ret = tls_start(tls);
|
||||
if (!ret) {
|
||||
if (!ret)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -558,7 +542,8 @@ int tls_read(tls_t *tls, void *buff, size_t len)
|
||||
|
||||
int tls_clear_pending_write(tls_t *tls)
|
||||
{
|
||||
if (tls->sendbufferpos < tls->sendbufferlen) {
|
||||
if (tls->sendbufferpos < tls->sendbufferlen)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
bytes = sock_write(tls->sock, tls->sendbuffer + tls->sendbufferpos,
|
||||
@@ -579,7 +564,7 @@ int tls_clear_pending_write(tls_t *tls)
|
||||
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;
|
||||
SecBuffer sbenc[4];
|
||||
@@ -616,22 +601,23 @@ int tls_write(tls_t *tls, const void *buff, size_t len)
|
||||
|
||||
sbenc[1].pvBuffer = tls->sendbuffer + tls->spcss.cbHeader;
|
||||
|
||||
while (remain > 0) {
|
||||
while (remain > 0)
|
||||
{
|
||||
if (remain > tls->spcss.cbMaximumMessage) {
|
||||
sbenc[1].cbBuffer = tls->spcss.cbMaximumMessage;
|
||||
} else {
|
||||
sbenc[1].cbBuffer = remain;
|
||||
}
|
||||
|
||||
sbenc[2].pvBuffer =
|
||||
(unsigned char *)sbenc[1].pvBuffer + sbenc[1].cbBuffer;
|
||||
sbenc[2].pvBuffer = (unsigned char *)sbenc[1].pvBuffer
|
||||
+ sbenc[1].cbBuffer;
|
||||
sbenc[2].cbBuffer = tls->spcss.cbTrailer;
|
||||
|
||||
memcpy(sbenc[1].pvBuffer, p, sbenc[1].cbBuffer);
|
||||
p += tls->spcss.cbMaximumMessage;
|
||||
|
||||
tls->sendbufferlen =
|
||||
sbenc[0].cbBuffer + sbenc[1].cbBuffer + sbenc[2].cbBuffer;
|
||||
tls->sendbufferlen = sbenc[0].cbBuffer + sbenc[1].cbBuffer
|
||||
+ sbenc[2].cbBuffer;
|
||||
|
||||
ret = tls->sft->EncryptMessage(&(tls->hctxt), 0, &sbdenc, 0);
|
||||
|
||||
@@ -659,6 +645,7 @@ int tls_write(tls_t *tls, const void *buff, size_t len)
|
||||
if (ret == 0 || (ret == -1 && tls_is_recoverable(tls_error(tls)))) {
|
||||
return sent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return sent;
|
||||
|
||||
68
src/util.c
68
src/util.c
@@ -36,41 +36,21 @@
|
||||
* @param ctx a Strophe context object
|
||||
* @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)
|
||||
{
|
||||
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)
|
||||
char *xmpp_strdup(const xmpp_ctx_t * const ctx, const char * const s)
|
||||
{
|
||||
size_t len;
|
||||
char *copy;
|
||||
size_t l;
|
||||
|
||||
l = strlen(s);
|
||||
if (l > len)
|
||||
l = len;
|
||||
|
||||
copy = xmpp_alloc(ctx, l + 1);
|
||||
len = strlen(s);
|
||||
copy = xmpp_alloc(ctx, len + 1);
|
||||
if (!copy) {
|
||||
xmpp_error(ctx, "xmpp", "failed to allocate required memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(copy, s, l);
|
||||
copy[l] = '\0';
|
||||
memcpy(copy, s, len + 1);
|
||||
|
||||
return copy;
|
||||
}
|
||||
@@ -106,24 +86,13 @@ char *xmpp_strtok_r(char *s, const char *delim, char **saveptr)
|
||||
*/
|
||||
uint64_t time_stamp(void)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_XBOX_ONE)
|
||||
|
||||
#ifndef __GNUC__
|
||||
#define EPOCHFILETIME (116444736000000000i64)
|
||||
#else
|
||||
#define EPOCHFILETIME (116444736000000000LL)
|
||||
#endif
|
||||
|
||||
FILETIME ft;
|
||||
LARGE_INTEGER li;
|
||||
__int64 t;
|
||||
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
li.LowPart = ft.dwLowDateTime;
|
||||
li.HighPart = ft.dwHighDateTime;
|
||||
t = li.QuadPart; /* In 100-nanosecond intervals */
|
||||
t -= EPOCHFILETIME; /* Offset to the Epoch time */
|
||||
return (uint64_t)(t / 10000); /* Convert to milliseconds */
|
||||
#if defined(_XBOX_ONE)
|
||||
uint64_t SystemTime;
|
||||
GetSystemTimeAsFileTime((FILETIME*)&SystemTime);
|
||||
/* Convert 100 nanosec ticks to milliseconds */
|
||||
return (SystemTime / 10000);
|
||||
#elif defined(_WIN32)
|
||||
return timeGetTime();
|
||||
#else
|
||||
struct timeval tv;
|
||||
|
||||
@@ -155,17 +124,8 @@ uint64_t time_elapsed(uint64_t t1, uint64_t t2)
|
||||
*
|
||||
* @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_disconnect(conn);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
|
||||
#include "ostypes.h"
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#endif /* ARRAY_SIZE */
|
||||
|
||||
/* TODO evaluate x and y only once */
|
||||
#define xmpp_min(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
@@ -32,7 +28,4 @@ char *xmpp_strtok_r(char *s, const char *delim, char **saveptr);
|
||||
uint64_t time_stamp(void);
|
||||
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__ */
|
||||
|
||||
373
strophe.h
373
strophe.h
@@ -39,10 +39,6 @@ extern "C" {
|
||||
* Namespace definition for 'urn:ietf:params:xml:ns:xmpp-streams'.
|
||||
*/
|
||||
#define XMPP_NS_STREAMS_IETF "urn:ietf:params:xml:ns:xmpp-streams"
|
||||
/** @def XMPP_NS_STANZAS_IETF
|
||||
* Namespace definition for 'urn:ietf:params:xml:ns:xmpp-stanzas'.
|
||||
*/
|
||||
#define XMPP_NS_STANZAS_IETF "urn:ietf:params:xml:ns:xmpp-stanzas"
|
||||
/** @def XMPP_NS_TLS
|
||||
* Namespace definition for 'url:ietf:params:xml:ns:xmpp-tls'.
|
||||
*/
|
||||
@@ -79,6 +75,10 @@ extern "C" {
|
||||
* Namespace definition for 'jabber:iq:register'.
|
||||
*/
|
||||
#define XMPP_NS_REGISTER "jabber:iq:register"
|
||||
/** @def XMPP_NS_SM
|
||||
* Namespace definition for Stream Management.
|
||||
*/
|
||||
#define XMPP_NS_SM "urn:xmpp:sm:3"
|
||||
|
||||
/* error defines */
|
||||
/** @def XMPP_EOK
|
||||
@@ -122,22 +122,18 @@ typedef struct _xmpp_log_t xmpp_log_t;
|
||||
/* opaque run time context containing the above hooks */
|
||||
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 *mem, const xmpp_log_t *log);
|
||||
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);
|
||||
xmpp_ctx_t *xmpp_ctx_new(const xmpp_mem_t * const mem,
|
||||
const xmpp_log_t * const log);
|
||||
void xmpp_ctx_free(xmpp_ctx_t * const ctx);
|
||||
|
||||
/* free some blocks returned by other APIs, for example the
|
||||
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 {
|
||||
void *(*alloc)(size_t size, void *userdata);
|
||||
void (*free)(void *p, void *userdata);
|
||||
void *(*realloc)(void *p, size_t size, void *userdata);
|
||||
void *(*alloc)(const size_t size, void * const userdata);
|
||||
void (*free)(void *p, void * const userdata);
|
||||
void *(*realloc)(void *p, const size_t size, void * const userdata);
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
@@ -148,12 +144,16 @@ typedef enum {
|
||||
XMPP_LEVEL_ERROR
|
||||
} xmpp_log_level_t;
|
||||
|
||||
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,
|
||||
xmpp_log_level_t level,
|
||||
const char *area,
|
||||
const char *msg);
|
||||
typedef void (*xmpp_log_handler)(void * const userdata,
|
||||
const xmpp_log_level_t level,
|
||||
const char * const area,
|
||||
const char * const msg);
|
||||
|
||||
struct _xmpp_log_t {
|
||||
xmpp_log_handler handler;
|
||||
@@ -217,159 +217,104 @@ typedef enum {
|
||||
XMPP_SE_XML_NOT_WELL_FORMED
|
||||
} 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 {
|
||||
xmpp_error_type_t type;
|
||||
char *text;
|
||||
xmpp_stanza_t *stanza;
|
||||
} xmpp_stream_error_t;
|
||||
|
||||
typedef void (*xmpp_conn_handler)(xmpp_conn_t *conn,
|
||||
xmpp_conn_event_t event,
|
||||
int error,
|
||||
xmpp_stream_error_t *stream_error,
|
||||
void *userdata);
|
||||
typedef void (*xmpp_conn_handler)(xmpp_conn_t * const conn,
|
||||
const xmpp_conn_event_t event,
|
||||
const int error,
|
||||
xmpp_stream_error_t * const stream_error,
|
||||
void * const userdata);
|
||||
|
||||
/** The Handler function which will be called when the TLS stack can't
|
||||
* verify the authenticity of a Certificate that gets presented by
|
||||
* the server we're trying to connect to.
|
||||
*
|
||||
* When this function is called and details of the `cert` have to be
|
||||
* kept, please copy them yourself. The `cert` object will be free'd
|
||||
* 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 * const conn, xmpp_error_type_t const type, char * const text);
|
||||
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t * const ctx);
|
||||
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t * const conn);
|
||||
int xmpp_conn_release(xmpp_conn_t * const conn);
|
||||
|
||||
void xmpp_send_error(xmpp_conn_t *conn, xmpp_error_type_t type, char *text);
|
||||
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx);
|
||||
xmpp_conn_t *xmpp_conn_clone(xmpp_conn_t *conn);
|
||||
int xmpp_conn_release(xmpp_conn_t *conn);
|
||||
long xmpp_conn_get_flags(const xmpp_conn_t * const conn);
|
||||
int xmpp_conn_set_flags(xmpp_conn_t * const conn, long flags);
|
||||
const char *xmpp_conn_get_jid(const xmpp_conn_t * const 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_conn_set_flags(xmpp_conn_t *conn, long flags);
|
||||
const char *xmpp_conn_get_jid(const xmpp_conn_t *conn);
|
||||
const char *xmpp_conn_get_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,
|
||||
int xmpp_connect_client(xmpp_conn_t * const conn,
|
||||
const char * const altdomain,
|
||||
unsigned short altport,
|
||||
xmpp_conn_handler callback,
|
||||
void *userdata);
|
||||
void * const userdata);
|
||||
|
||||
int xmpp_connect_component(xmpp_conn_t *conn,
|
||||
const char *server,
|
||||
unsigned short port,
|
||||
xmpp_conn_handler callback,
|
||||
void *userdata);
|
||||
int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
|
||||
unsigned short port, xmpp_conn_handler callback,
|
||||
void * const userdata);
|
||||
|
||||
int xmpp_connect_raw(xmpp_conn_t *conn,
|
||||
const char *altdomain,
|
||||
int xmpp_connect_raw(xmpp_conn_t * const conn,
|
||||
const char * const altdomain,
|
||||
unsigned short altport,
|
||||
xmpp_conn_handler callback,
|
||||
void *userdata);
|
||||
int xmpp_conn_open_stream_default(xmpp_conn_t *conn);
|
||||
int xmpp_conn_open_stream(xmpp_conn_t *conn,
|
||||
char **attributes,
|
||||
void * const userdata);
|
||||
int xmpp_conn_open_stream_default(xmpp_conn_t * const conn);
|
||||
int xmpp_conn_open_stream(xmpp_conn_t * const conn, char **attributes,
|
||||
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 * const conn,
|
||||
const char * const fmt, ...);
|
||||
void xmpp_send_raw(xmpp_conn_t * const conn,
|
||||
const char * const data, const size_t len);
|
||||
|
||||
void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...);
|
||||
void xmpp_send_raw(xmpp_conn_t *conn, const char *data, size_t len);
|
||||
|
||||
/* handlers */
|
||||
|
||||
/* if the handler returns false it is removed */
|
||||
typedef int (*xmpp_timed_handler)(xmpp_conn_t *conn, void *userdata);
|
||||
/* if the handle returns false it is removed */
|
||||
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,
|
||||
unsigned long period,
|
||||
void *userdata);
|
||||
void xmpp_timed_handler_delete(xmpp_conn_t *conn, xmpp_timed_handler handler);
|
||||
const unsigned long period,
|
||||
void * const userdata);
|
||||
void xmpp_timed_handler_delete(xmpp_conn_t * const conn,
|
||||
xmpp_timed_handler handler);
|
||||
|
||||
|
||||
/* if the handler returns false it is removed */
|
||||
typedef int (*xmpp_global_timed_handler)(xmpp_ctx_t *ctx, void *userdata);
|
||||
typedef int (*xmpp_handler)(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza,
|
||||
void * const userdata);
|
||||
|
||||
void xmpp_global_timed_handler_add(xmpp_ctx_t *ctx,
|
||||
xmpp_global_timed_handler handler,
|
||||
unsigned long period,
|
||||
void *userdata);
|
||||
void xmpp_global_timed_handler_delete(xmpp_ctx_t *ctx,
|
||||
xmpp_global_timed_handler handler);
|
||||
|
||||
/* if the handler returns false it is removed */
|
||||
typedef int (*xmpp_handler)(xmpp_conn_t *conn,
|
||||
xmpp_stanza_t *stanza,
|
||||
void *userdata);
|
||||
|
||||
void xmpp_handler_add(xmpp_conn_t *conn,
|
||||
void xmpp_handler_add(xmpp_conn_t * const conn,
|
||||
xmpp_handler handler,
|
||||
const char *ns,
|
||||
const char *name,
|
||||
const char *type,
|
||||
void *userdata);
|
||||
void xmpp_handler_delete(xmpp_conn_t *conn, xmpp_handler handler);
|
||||
const char * const ns,
|
||||
const char * const name,
|
||||
const char * const type,
|
||||
void * const userdata);
|
||||
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,
|
||||
const char *id,
|
||||
void *userdata);
|
||||
void xmpp_id_handler_delete(xmpp_conn_t *conn,
|
||||
const char * const id,
|
||||
void * const userdata);
|
||||
void xmpp_id_handler_delete(xmpp_conn_t * const conn,
|
||||
xmpp_handler handler,
|
||||
const char *id);
|
||||
const char * const id);
|
||||
|
||||
/*
|
||||
void xmpp_register_stanza_handler(conn, stanza, xmlns, type, handler)
|
||||
@@ -379,97 +324,93 @@ void xmpp_register_stanza_handler(conn, stanza, xmlns, type, handler)
|
||||
|
||||
/* allocate and initialize a blank stanza */
|
||||
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);
|
||||
|
||||
/* 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 */
|
||||
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 */
|
||||
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_tag(xmpp_stanza_t *stanza);
|
||||
int xmpp_stanza_is_text(xmpp_stanza_t * const stanza);
|
||||
int xmpp_stanza_is_tag(xmpp_stanza_t * const stanza);
|
||||
|
||||
/* 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_child_by_name(xmpp_stanza_t *stanza,
|
||||
const char *name);
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t *stanza,
|
||||
const char *ns);
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t *stanza,
|
||||
const char *name,
|
||||
const char *ns);
|
||||
xmpp_stanza_t *xmpp_stanza_get_next(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 * const stanza,
|
||||
const char * const name);
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_ns(xmpp_stanza_t * const stanza,
|
||||
const char * const ns);
|
||||
xmpp_stanza_t *xmpp_stanza_get_child_by_name_and_ns(xmpp_stanza_t * const stanza,
|
||||
const char * const name,
|
||||
const char * const ns);
|
||||
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_ex(xmpp_stanza_t *stanza,
|
||||
xmpp_stanza_t *child,
|
||||
int xmpp_stanza_add_child_ex(xmpp_stanza_t *stanza, xmpp_stanza_t *child,
|
||||
int do_clone);
|
||||
|
||||
const char *xmpp_stanza_get_attribute(xmpp_stanza_t *stanza, const char *name);
|
||||
int xmpp_stanza_get_attribute_count(xmpp_stanza_t *stanza);
|
||||
int xmpp_stanza_get_attributes(xmpp_stanza_t *stanza,
|
||||
const char **attr,
|
||||
int attrlen);
|
||||
const char *xmpp_stanza_get_attribute(xmpp_stanza_t * const stanza,
|
||||
const char * const name);
|
||||
int xmpp_stanza_get_attribute_count(xmpp_stanza_t * const stanza);
|
||||
int xmpp_stanza_get_attributes(xmpp_stanza_t * const stanza,
|
||||
const char **attr, int attrlen);
|
||||
/* concatenate all child text nodes. this function
|
||||
* returns a string that must be freed by the caller */
|
||||
char *xmpp_stanza_get_text(xmpp_stanza_t *stanza);
|
||||
const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t *stanza);
|
||||
const char *xmpp_stanza_get_name(xmpp_stanza_t *stanza);
|
||||
char *xmpp_stanza_get_text(xmpp_stanza_t * const stanza);
|
||||
const char *xmpp_stanza_get_text_ptr(xmpp_stanza_t * const stanza);
|
||||
const char *xmpp_stanza_get_name(xmpp_stanza_t * const stanza);
|
||||
/* set_attribute adds/replaces attributes */
|
||||
int xmpp_stanza_set_attribute(xmpp_stanza_t *stanza,
|
||||
const char *key,
|
||||
const char *value);
|
||||
int xmpp_stanza_set_name(xmpp_stanza_t *stanza, const char *name);
|
||||
int xmpp_stanza_set_text(xmpp_stanza_t *stanza, const char *text);
|
||||
int xmpp_stanza_set_attribute(xmpp_stanza_t * const stanza,
|
||||
const char * const key,
|
||||
const char * const value);
|
||||
int xmpp_stanza_set_name(xmpp_stanza_t *stanza,
|
||||
const char * const name);
|
||||
int xmpp_stanza_set_text(xmpp_stanza_t *stanza,
|
||||
const char * const text);
|
||||
int xmpp_stanza_set_text_with_size(xmpp_stanza_t *stanza,
|
||||
const char *text,
|
||||
size_t size);
|
||||
int xmpp_stanza_del_attribute(xmpp_stanza_t *stanza, const char *name);
|
||||
const char * const text,
|
||||
const size_t size);
|
||||
int xmpp_stanza_del_attribute(xmpp_stanza_t * const stanza,
|
||||
const char * const name);
|
||||
|
||||
/* common stanza helpers */
|
||||
const char *xmpp_stanza_get_ns(xmpp_stanza_t *stanza);
|
||||
const char *xmpp_stanza_get_type(xmpp_stanza_t *stanza);
|
||||
const char *xmpp_stanza_get_id(xmpp_stanza_t *stanza);
|
||||
const char *xmpp_stanza_get_to(xmpp_stanza_t *stanza);
|
||||
const char *xmpp_stanza_get_from(xmpp_stanza_t *stanza);
|
||||
int xmpp_stanza_set_ns(xmpp_stanza_t *stanza, const char *ns);
|
||||
int xmpp_stanza_set_id(xmpp_stanza_t *stanza, const char *id);
|
||||
int xmpp_stanza_set_type(xmpp_stanza_t *stanza, const char *type);
|
||||
int xmpp_stanza_set_to(xmpp_stanza_t *stanza, const char *to);
|
||||
int xmpp_stanza_set_from(xmpp_stanza_t *stanza, const char *from);
|
||||
const char *xmpp_stanza_get_ns(xmpp_stanza_t * const stanza);
|
||||
const char *xmpp_stanza_get_type(xmpp_stanza_t * const stanza);
|
||||
const char *xmpp_stanza_get_id(xmpp_stanza_t * const stanza);
|
||||
const char *xmpp_stanza_get_to(xmpp_stanza_t * const stanza);
|
||||
const char *xmpp_stanza_get_from(xmpp_stanza_t * const stanza);
|
||||
int xmpp_stanza_set_ns(xmpp_stanza_t * const stanza, const char * const ns);
|
||||
int xmpp_stanza_set_id(xmpp_stanza_t * const stanza, const char * const id);
|
||||
int xmpp_stanza_set_type(xmpp_stanza_t * const stanza, const char * const type);
|
||||
int xmpp_stanza_set_to(xmpp_stanza_t * const stanza, const char * const to);
|
||||
int xmpp_stanza_set_from(xmpp_stanza_t * const stanza, const char * const from);
|
||||
|
||||
/* 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_error(xmpp_stanza_t *stanza,
|
||||
const char *error_type,
|
||||
const char *condition,
|
||||
const char *text);
|
||||
xmpp_stanza_t *xmpp_stanza_reply(xmpp_stanza_t * const stanza);
|
||||
|
||||
/* stanza subclasses */
|
||||
xmpp_stanza_t *xmpp_message_new(xmpp_ctx_t *ctx,
|
||||
const char *type,
|
||||
const char *to,
|
||||
const char *id);
|
||||
xmpp_stanza_t *xmpp_message_new(xmpp_ctx_t *ctx, const char * const type,
|
||||
const char * const to, const char * const id);
|
||||
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_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 type, const char *text);
|
||||
xmpp_stanza_t *xmpp_error_new(xmpp_ctx_t *ctx, xmpp_error_type_t const type,
|
||||
const char * const text);
|
||||
|
||||
/* jid */
|
||||
|
||||
/* these return new strings that must be xmpp_free()'d */
|
||||
char *xmpp_jid_new(xmpp_ctx_t *ctx,
|
||||
const char *node,
|
||||
char *xmpp_jid_new(xmpp_ctx_t *ctx, const char *node,
|
||||
const char *domain,
|
||||
const char *resource);
|
||||
char *xmpp_jid_bare(xmpp_ctx_t *ctx, const char *jid);
|
||||
@@ -479,21 +420,10 @@ char *xmpp_jid_resource(xmpp_ctx_t *ctx, const char *jid);
|
||||
|
||||
/* 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_stop(xmpp_ctx_t *ctx);
|
||||
void xmpp_ctx_set_timeout(xmpp_ctx_t *ctx, 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);
|
||||
void xmpp_ctx_set_timeout(xmpp_ctx_t * const ctx, const unsigned long timeout);
|
||||
|
||||
/* UUID */
|
||||
|
||||
@@ -509,8 +439,7 @@ char *xmpp_uuid_gen(xmpp_ctx_t *ctx);
|
||||
typedef struct _xmpp_sha1_t xmpp_sha1_t;
|
||||
|
||||
char *xmpp_sha1(xmpp_ctx_t *ctx, const unsigned char *data, size_t len);
|
||||
void xmpp_sha1_digest(const unsigned char *data,
|
||||
size_t len,
|
||||
void xmpp_sha1_digest(const unsigned char *data, size_t len,
|
||||
unsigned char *digest);
|
||||
|
||||
xmpp_sha1_t *xmpp_sha1_new(xmpp_ctx_t *ctx);
|
||||
@@ -523,14 +452,10 @@ void xmpp_sha1_to_digest(xmpp_sha1_t *sha1, unsigned char *digest);
|
||||
|
||||
/* Base64 */
|
||||
|
||||
char *
|
||||
xmpp_base64_encode(xmpp_ctx_t *ctx, const unsigned char *data, size_t len);
|
||||
char *xmpp_base64_encode(xmpp_ctx_t *ctx, const unsigned char *data, size_t len);
|
||||
char *xmpp_base64_decode_str(xmpp_ctx_t *ctx, const char *base64, size_t len);
|
||||
void xmpp_base64_decode_bin(xmpp_ctx_t *ctx,
|
||||
const char *base64,
|
||||
size_t len,
|
||||
unsigned char **out,
|
||||
size_t *outlen);
|
||||
void xmpp_base64_decode_bin(xmpp_ctx_t *ctx, const char *base64, size_t len,
|
||||
unsigned char **out, size_t *outlen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
133
strophepp.h
Normal file
133
strophepp.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/* strophepp.h
|
||||
** strophe XMPP client library C++ API
|
||||
**
|
||||
** Copyright (C) 2005-2009 Collecta, Inc.
|
||||
**
|
||||
** 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
|
||||
* Strophe public C++ API definitions.
|
||||
*/
|
||||
|
||||
#ifndef __LIBSTROPHE_STROPHEPP_H__
|
||||
#define __LIBSTROPHE_STROPHEPP_H__
|
||||
|
||||
#include "strophe.h"
|
||||
|
||||
namespace XMPP {
|
||||
class Context {
|
||||
private:
|
||||
xmpp_mem_t m_mem;
|
||||
xmpp_log_t m_log;
|
||||
xmpp_ctx_t *m_ctx;
|
||||
|
||||
public:
|
||||
Context();
|
||||
virtual ~Context();
|
||||
|
||||
virtual void *alloc(const size_t size);
|
||||
virtual void *realloc(void *p, const size_t size);
|
||||
virtual void free(void *p);
|
||||
virtual void log(const xmpp_log_level_t level,
|
||||
const char * const area,
|
||||
const char * const msg);
|
||||
|
||||
xmpp_ctx_t *getContext();
|
||||
|
||||
private:
|
||||
static void *callAlloc(const size_t size, void * const userdata);
|
||||
static void *callRealloc(void *p, const size_t size,
|
||||
void * const userdata);
|
||||
static void callFree(void *p, void * const userdata);
|
||||
static void callLog(void * const userdata,
|
||||
const xmpp_log_level_t level,
|
||||
const char * const area,
|
||||
const char * const msg);
|
||||
};
|
||||
|
||||
class Stanza {
|
||||
private:
|
||||
Context *m_ctx;
|
||||
xmpp_stanza_t *m_stanza;
|
||||
|
||||
void *operator new(size_t size, Context *ctx);
|
||||
void operator delete(void *p);
|
||||
Stanza(Context *ctx);
|
||||
virtual ~Stanza();
|
||||
|
||||
public:
|
||||
static Stanza *create(Context *ctx);
|
||||
void release();
|
||||
Stanza *clone();
|
||||
Stanza *copy();
|
||||
|
||||
int toText(const char ** const buf, size_t * const buflen);
|
||||
Stanza *getChildren();
|
||||
Stanza *getChildByName(const char * const name);
|
||||
Stanza *getNext();
|
||||
char *getAttribute(const char * const name);
|
||||
char *getNamespace();
|
||||
char *getText();
|
||||
char *getName();
|
||||
void addChild(Stanza *child);
|
||||
void setNamespace(const char * const ns);
|
||||
void setAttribute(const char * const key, const char * const value);
|
||||
void setName(const char * const name);
|
||||
void setText(const char * const text);
|
||||
void setText(const char * const text, const size_t size);
|
||||
char *getType();
|
||||
char *getId();
|
||||
char *getTo();
|
||||
char *getFrom();
|
||||
void setType(const char * const type);
|
||||
void setId(const char * const id);
|
||||
void setTo(const char * const to);
|
||||
void setFrom(const char * const from);
|
||||
};
|
||||
|
||||
class Connection {
|
||||
private:
|
||||
Context *m_ctx;
|
||||
xmpp_conn_t *conn;
|
||||
|
||||
void *operator new(size_t size, Context *ctx);
|
||||
Connection(Context *ctx);
|
||||
|
||||
public:
|
||||
static Connection *create(Context *ctx);
|
||||
virtual ~Connection();
|
||||
Connection *clone();
|
||||
void operator delete(void *p);
|
||||
|
||||
const char *getJID();
|
||||
void setJID(const char * const jid);
|
||||
const char *getPass();
|
||||
void setPass(const char * const pass);
|
||||
bool connectClient(const char * const domain,
|
||||
xmpp_conn_handler callback,
|
||||
void * const userdata);
|
||||
void disconnect();
|
||||
void send(Stanza *stanza);
|
||||
|
||||
void addTimedHandler(xmpp_timed_handler handler,
|
||||
const unsigned long perdio,
|
||||
void * const userdata);
|
||||
void deleteTimedHandler(xmpp_timed_handler handler);
|
||||
void addHandler(xmpp_handler handler,
|
||||
const char * const ns,
|
||||
const char * const name,
|
||||
const char * const type,
|
||||
void * const userdata);
|
||||
void deleteHandler(xmpp_handler handler);
|
||||
void addIdHandler(xmpp_handler handler,
|
||||
const char * const id,
|
||||
void * const userdata);
|
||||
void deleteIdHandler(xmpp_handler handler);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __LIBSTROPHE_STROPHEPP_H__ */
|
||||
@@ -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-----
|
||||
@@ -18,12 +18,11 @@
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#define fail_unless(expr) \
|
||||
do { \
|
||||
#define fail_unless(expr) do { \
|
||||
int result = (expr); \
|
||||
if (!result) { \
|
||||
printf("%s:%d: Assertion failed: %s\n", __FILE__, __LINE__, \
|
||||
#expr); \
|
||||
printf("%s:%d: Assertion failed: %s\n", \
|
||||
__FILE__, __LINE__, #expr); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -43,9 +42,6 @@ static void create_destroy(void)
|
||||
int cbtest_got_start = 0;
|
||||
void cbtest_handle_start(char *name, char **attrs, void *userdata)
|
||||
{
|
||||
(void)attrs;
|
||||
(void)userdata;
|
||||
|
||||
if (strcmp(name, "stream") == 0)
|
||||
cbtest_got_start = 1;
|
||||
}
|
||||
@@ -53,8 +49,6 @@ void cbtest_handle_start(char *name, char **attrs, void *userdata)
|
||||
int cbtest_got_end = 0;
|
||||
void cbtest_handle_end(char *name, void *userdata)
|
||||
{
|
||||
(void)userdata;
|
||||
|
||||
if (strcmp(name, "stream") == 0)
|
||||
cbtest_got_end = 1;
|
||||
}
|
||||
@@ -62,8 +56,6 @@ void cbtest_handle_end(char *name, void *userdata)
|
||||
int cbtest_got_stanza = 0;
|
||||
void cbtest_handle_stanza(xmpp_stanza_t *stanza, void *userdata)
|
||||
{
|
||||
(void)userdata;
|
||||
|
||||
if (strcmp(xmpp_stanza_get_name(stanza), "message") == 0)
|
||||
cbtest_got_stanza = 1;
|
||||
}
|
||||
@@ -75,7 +67,9 @@ static void callbacks(void)
|
||||
int ret;
|
||||
|
||||
ctx = xmpp_ctx_new(NULL, NULL);
|
||||
parser = parser_new(ctx, cbtest_handle_start, cbtest_handle_end,
|
||||
parser = parser_new(ctx,
|
||||
cbtest_handle_start,
|
||||
cbtest_handle_end,
|
||||
cbtest_handle_stanza, NULL);
|
||||
|
||||
ret = parser_feed(parser, "<stream>", 8);
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MF8CAQEEGF7SsbTSOjzb97nFc7Qbt4sic+1nZk+ETqAKBggqhkjOPQMBAaE0AzIA
|
||||
BI/tSR5cZ9iHCVw0JwmKLvV3TbxPg3kDdouB0R2WKEdEWwXMIHkE85RReISg+9/J
|
||||
DQ==
|
||||
-----END EC PRIVATE KEY-----
|
||||
@@ -55,8 +55,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
domain = argv[1];
|
||||
snprintf(fulldomain, sizeof(fulldomain), "_%s._%s.%s", service, proto,
|
||||
domain);
|
||||
snprintf(fulldomain, sizeof(fulldomain), "_%s._%s.%s",
|
||||
service, proto, domain);
|
||||
errno = 0;
|
||||
len = res_query(fulldomain, C_IN, T_SRV, buf, sizeof(buf));
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
static uint8_t char_to_bin(char c)
|
||||
{
|
||||
return c <= '9' ? (uint8_t)(c - '0')
|
||||
: c <= 'Z' ? (uint8_t)(c - 'A' + 10)
|
||||
: (uint8_t)(c - 'a' + 10);
|
||||
return c <= '9' ? (uint8_t)(c - '0') :
|
||||
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)
|
||||
|
||||
24
tests/test.h
24
tests/test.h
@@ -14,13 +14,11 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "ostypes.h"
|
||||
|
||||
#define TEST_MAIN \
|
||||
int main(int argc, char **argv) \
|
||||
{ \
|
||||
int main(int argc, char **argv) { \
|
||||
int num_failed; \
|
||||
Suite *s = parser_suite(); \
|
||||
SRunner *sr = srunner_create(s); \
|
||||
@@ -39,10 +37,10 @@
|
||||
const char *__v1 = v1; \
|
||||
const char *__v2 = v2; \
|
||||
if (strcmp(__v1, __v2) != 0) { \
|
||||
printf("Error: %s\n" \
|
||||
"Expected: %s\n" \
|
||||
"Got: %s\n", \
|
||||
#v1 " != " #v2, __v1, __v2); \
|
||||
printf("%s differs!\n" \
|
||||
"expected: %s\n" \
|
||||
"got: %s\n", \
|
||||
#v1, __v1, __v2); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -53,10 +51,14 @@
|
||||
const uint8_t *__v2 = (uint8_t *)(v2); \
|
||||
size_t __len1 = len1; \
|
||||
size_t __len2 = len2; \
|
||||
if (__len1 != __len2 || memcmp(__v1, __v2, __len1) != 0) { \
|
||||
printf("Error: %s\n", #v1 " != " #v2); \
|
||||
printf("Expected: 0x%s\n", test_bin_to_hex(__v1, __len1)); \
|
||||
printf("Got: 0x%s\n", test_bin_to_hex(__v2, __len2)); \
|
||||
if (__len1 != __len2 || \
|
||||
memcmp(__v1, __v2, __len1) != 0) \
|
||||
{ \
|
||||
printf("%s differs!\n", #v1); \
|
||||
printf("expected: 0x%s\n", \
|
||||
test_bin_to_hex(__v1, __len1)); \
|
||||
printf("got: 0x%s\n", \
|
||||
test_bin_to_hex(__v2, __len2)); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
|
||||
#include "test.h"
|
||||
|
||||
static const unsigned char test_2_raw[] = {0x14, 0xfb, 0x9c, 0x03,
|
||||
0xd9, 0x7e, 0x00};
|
||||
static const unsigned char test_4_raw[] = {0xd6, 0x2f, 0x27, 0x49, 0x7e, 0xdd,
|
||||
0xf3, 0xd5, 0x41, 0xbc, 0x1b, 0xe9,
|
||||
0xdf, 0xe9, 0xb3, 0x08, 0x00};
|
||||
static const unsigned char test_2_raw[] =
|
||||
{0x14, 0xfb, 0x9c, 0x03, 0xd9, 0x7e, 0x00};
|
||||
static const unsigned char test_4_raw[] =
|
||||
{0xd6, 0x2f, 0x27, 0x49, 0x7e, 0xdd, 0xf3, 0xd5,
|
||||
0x41, 0xbc, 0x1b, 0xe9, 0xdf, 0xe9, 0xb3, 0x08, 0x00};
|
||||
|
||||
static const struct {
|
||||
char *raw;
|
||||
@@ -36,11 +36,13 @@ static const struct {
|
||||
.base64 = "FPucA9l+",
|
||||
},
|
||||
{
|
||||
.raw = "From rest and sleep, which but thy pictures be, "
|
||||
.raw =
|
||||
"From rest and sleep, which but thy pictures be, "
|
||||
"Much pleasure; then from thee much more must flow, "
|
||||
"And soonest our best men with thee do go, "
|
||||
"Rest of their bones, and soul's delivery.",
|
||||
.base64 = "RnJvbSByZXN0IGFuZCBzbGVlcCwgd2hpY2ggYnV0IHRoeSBwaWN0dXJl"
|
||||
.base64 =
|
||||
"RnJvbSByZXN0IGFuZCBzbGVlcCwgd2hpY2ggYnV0IHRoeSBwaWN0dXJl"
|
||||
"cyBiZSwgTXVjaCBwbGVhc3VyZTsgdGhlbiBmcm9tIHRoZWUgbXVjaCBt"
|
||||
"b3JlIG11c3QgZmxvdywgQW5kIHNvb25lc3Qgb3VyIGJlc3QgbWVuIHdp"
|
||||
"dGggdGhlZSBkbyBnbywgUmVzdCBvZiB0aGVpciBib25lcywgYW5kIHNv"
|
||||
@@ -51,9 +53,11 @@ static const struct {
|
||||
.base64 = "1i8nSX7d89VBvBvp3+mzCA==",
|
||||
},
|
||||
{
|
||||
.raw = "realm=\"chesspark.com\",nonce=\"b243c0d663257a9149999cef2f83"
|
||||
.raw =
|
||||
"realm=\"chesspark.com\",nonce=\"b243c0d663257a9149999cef2f83"
|
||||
"a22116559e93\",qop=\"auth\",charset=utf-8,algorithm=md5-sess",
|
||||
.base64 = "cmVhbG09ImNoZXNzcGFyay5jb20iLG5vbmNlPSJiMjQzYzBkNjYzMjU3"
|
||||
.base64 =
|
||||
"cmVhbG09ImNoZXNzcGFyay5jb20iLG5vbmNlPSJiMjQzYzBkNjYzMjU3"
|
||||
"YTkxNDk5OTljZWYyZjgzYTIyMTE2NTU5ZTkzIixxb3A9ImF1dGgiLGNo"
|
||||
"YXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz",
|
||||
},
|
||||
@@ -90,30 +94,41 @@ static const struct {
|
||||
};
|
||||
|
||||
static const unsigned char bin_data[] = {
|
||||
0xda, 0xa8, 0x81, 0x80, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x5f, 0x78, 0x6d, 0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x67, 0x6d, 0x61, 0x69, 0x6c,
|
||||
0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x21, 0x00, 0x01, 0xc0, 0x0c, 0x00,
|
||||
0x21, 0x00, 0x01, 0x00, 0x00, 0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00,
|
||||
0x00, 0x14, 0x66, 0x04, 0x61, 0x6c, 0x74, 0x31, 0x04, 0x78, 0x6d, 0x70,
|
||||
0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
|
||||
0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x02,
|
||||
0x43, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x00, 0x14, 0x66, 0x04, 0x61, 0x6c,
|
||||
0x74, 0x34, 0x04, 0x78, 0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00,
|
||||
0x21, 0x00, 0x01, 0x00, 0x00, 0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00,
|
||||
0x00, 0x14, 0x66, 0x04, 0x61, 0x6c, 0x74, 0x32, 0x04, 0x78, 0x6d, 0x70,
|
||||
0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
|
||||
0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x02,
|
||||
0x43, 0x00, 0x19, 0x00, 0x05, 0x00, 0x00, 0x14, 0x66, 0x04, 0x78, 0x6d,
|
||||
0x70, 0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
|
||||
0x63, 0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00,
|
||||
0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x00, 0x14, 0x66, 0x04, 0x61,
|
||||
0x6c, 0x74, 0x33, 0x04, 0x78, 0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
|
||||
0xda, 0xa8, 0x81, 0x80, 0x00, 0x01, 0x00, 0x05,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0c, 0x5f, 0x78, 0x6d,
|
||||
0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x67,
|
||||
0x6d, 0x61, 0x69, 0x6c, 0x03, 0x63, 0x6f, 0x6d,
|
||||
0x00, 0x00, 0x21, 0x00, 0x01, 0xc0, 0x0c, 0x00,
|
||||
0x21, 0x00, 0x01, 0x00, 0x00, 0x02, 0x43, 0x00,
|
||||
0x1e, 0x00, 0x14, 0x00, 0x00, 0x14, 0x66, 0x04,
|
||||
0x61, 0x6c, 0x74, 0x31, 0x04, 0x78, 0x6d, 0x70,
|
||||
0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0xc0,
|
||||
0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x02,
|
||||
0x43, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x00, 0x14,
|
||||
0x66, 0x04, 0x61, 0x6c, 0x74, 0x34, 0x04, 0x78,
|
||||
0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
|
||||
0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00,
|
||||
0x00, 0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00,
|
||||
0x00, 0x14, 0x66, 0x04, 0x61, 0x6c, 0x74, 0x32,
|
||||
0x04, 0x78, 0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
|
||||
0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00,
|
||||
0x01, 0x00, 0x00, 0x02, 0x43, 0x00, 0x19, 0x00,
|
||||
0x05, 0x00, 0x00, 0x14, 0x66, 0x04, 0x78, 0x6d,
|
||||
0x70, 0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
|
||||
0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00,
|
||||
0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x00,
|
||||
0x14, 0x66, 0x04, 0x61, 0x6c, 0x74, 0x33, 0x04,
|
||||
0x78, 0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
|
||||
0x6d, 0x00,
|
||||
};
|
||||
|
||||
int main()
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
unsigned char *udec;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* test_ctx.c
|
||||
** libstrophe XMPP client library -- test routines for the library run-time
|
||||
*context
|
||||
** libstrophe XMPP client library -- test routines for the library run-time context
|
||||
**
|
||||
** Copyright (C) 2005-2009 Collecta, Inc.
|
||||
**
|
||||
@@ -22,41 +21,33 @@ static int mem_alloc_called = 0;
|
||||
static int mem_free_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;
|
||||
|
||||
mem_alloc_called++;
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void my_free(void *p, void *userdata)
|
||||
void my_free(void *p, void * const userdata)
|
||||
{
|
||||
(void)userdata;
|
||||
|
||||
mem_free_called++;
|
||||
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;
|
||||
|
||||
mem_realloc_called++;
|
||||
return realloc(p, size);
|
||||
}
|
||||
|
||||
void my_logger(void *userdata,
|
||||
xmpp_log_level_t level,
|
||||
const char *area,
|
||||
const char *msg)
|
||||
void my_logger(void * const userdata, const xmpp_log_level_t level,
|
||||
const char * const area, const char * const msg)
|
||||
{
|
||||
if (strcmp((char *)userdata, "asdf") == 0 && level == XMPP_LEVEL_DEBUG &&
|
||||
strcmp(area, "test") == 0 && strcmp(msg, "hello") == 0)
|
||||
if (strcmp((char *)userdata, "asdf") == 0 && level == XMPP_LEVEL_DEBUG
|
||||
&& strcmp(area, "test") == 0 && strcmp(msg, "hello") == 0)
|
||||
log_called++;
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
xmpp_mem_t mymem;
|
||||
@@ -65,8 +56,7 @@ int main()
|
||||
void *testptr1, *testptr2;
|
||||
|
||||
ctx = xmpp_ctx_new(NULL, NULL);
|
||||
if (ctx == NULL)
|
||||
return 1;
|
||||
if (ctx == NULL) return 1;
|
||||
|
||||
/* destroy context */
|
||||
xmpp_ctx_free(ctx);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -22,8 +22,12 @@
|
||||
#define TESTSIZE 500
|
||||
|
||||
/* static test data */
|
||||
const char *keys[] = {"foo", "bar", "baz", "quux", "xyzzy"};
|
||||
const char *values[] = {"wuzzle", "mug", "canonical", "rosebud", "lottery"};
|
||||
const char *keys[] = {
|
||||
"foo", "bar", "baz", "quux", "xyzzy"
|
||||
};
|
||||
const char *values[] = {
|
||||
"wuzzle", "mug", "canonical", "rosebud", "lottery"
|
||||
};
|
||||
const int nkeys = ARRAY_SIZE(keys);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@@ -64,8 +68,7 @@ int main(int argc, char **argv)
|
||||
/* test insertion */
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
err = hash_add(table, keys[i], xmpp_strdup(ctx, values[i]));
|
||||
if (err)
|
||||
return err;
|
||||
if (err) return err;
|
||||
}
|
||||
|
||||
/* test key count */
|
||||
@@ -77,15 +80,11 @@ int main(int argc, char **argv)
|
||||
/* test replacing old values */
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
err = hash_add(table, keys[0], xmpp_strdup(ctx, values[i]));
|
||||
if (err)
|
||||
return err;
|
||||
if (hash_num_keys(table) != nkeys)
|
||||
return 1;
|
||||
if (err) return err;
|
||||
if (hash_num_keys(table) != nkeys) return 1;
|
||||
result = hash_get(table, keys[0]);
|
||||
if (result == NULL)
|
||||
return 1;
|
||||
if (strcmp(result, values[i]) != 0)
|
||||
return 1;
|
||||
if (result == NULL) return 1;
|
||||
if (strcmp(result, values[i]) != 0) return 1;
|
||||
}
|
||||
/* restore value for the 1st key */
|
||||
hash_add(table, keys[0], xmpp_strdup(ctx, values[0]));
|
||||
@@ -133,19 +132,14 @@ int main(int argc, char **argv)
|
||||
|
||||
/* test drops */
|
||||
hash_drop(clone, keys[2]);
|
||||
if (hash_get(clone, keys[2]) != NULL)
|
||||
return 1;
|
||||
if (hash_get(clone, keys[2]) != NULL) return 1;
|
||||
hash_drop(clone, keys[1]);
|
||||
hash_drop(clone, keys[4]);
|
||||
if (hash_get(clone, keys[4]) != NULL)
|
||||
return 1;
|
||||
if (hash_get(clone, keys[1]) != NULL)
|
||||
return 1;
|
||||
if (hash_get(clone, keys[4]) != NULL) return 1;
|
||||
if (hash_get(clone, keys[1]) != NULL) return 1;
|
||||
/* keys 0,3 should still be available */
|
||||
if (hash_get(clone, keys[0]) == NULL)
|
||||
return 1;
|
||||
if (hash_get(clone, keys[3]) == NULL)
|
||||
return 1;
|
||||
if (hash_get(clone, keys[0]) == NULL) return 1;
|
||||
if (hash_get(clone, keys[3]) == NULL) return 1;
|
||||
|
||||
/* release our clone */
|
||||
hash_release(clone);
|
||||
|
||||
138
tests/test_jid.c
138
tests/test_jid.c
@@ -36,93 +36,61 @@ int test_jid(xmpp_ctx_t *ctx)
|
||||
node = xmpp_jid_node(ctx, jid1);
|
||||
domain = xmpp_jid_domain(ctx, jid1);
|
||||
resource = xmpp_jid_resource(ctx, jid1);
|
||||
printf("jid '%s' parsed to %s, %s, %s\n", jid1, _s(node), _s(domain),
|
||||
_s(resource));
|
||||
if (bare == NULL || strcmp(bare, "foo@bar.com"))
|
||||
return 1;
|
||||
if (node == NULL || strcmp(node, "foo"))
|
||||
return 1;
|
||||
if (domain == NULL || strcmp(domain, "bar.com"))
|
||||
return 1;
|
||||
if (resource != NULL)
|
||||
return 1;
|
||||
if (bare)
|
||||
xmpp_free(ctx, bare);
|
||||
if (node)
|
||||
xmpp_free(ctx, node);
|
||||
if (domain)
|
||||
xmpp_free(ctx, domain);
|
||||
if (resource)
|
||||
xmpp_free(ctx, resource);
|
||||
printf("jid '%s' parsed to %s, %s, %s\n",
|
||||
jid1, _s(node), _s(domain), _s(resource));
|
||||
if (bare == NULL || strcmp(bare, "foo@bar.com")) return 1;
|
||||
if (node == NULL || strcmp(node, "foo")) return 1;
|
||||
if (domain == NULL || strcmp(domain, "bar.com")) return 1;
|
||||
if (resource != NULL) return 1;
|
||||
if (bare) xmpp_free(ctx, bare);
|
||||
if (node) xmpp_free(ctx, node);
|
||||
if (domain) xmpp_free(ctx, domain);
|
||||
if (resource) xmpp_free(ctx, resource);
|
||||
|
||||
bare = xmpp_jid_bare(ctx, jid2);
|
||||
node = xmpp_jid_node(ctx, jid2);
|
||||
domain = xmpp_jid_domain(ctx, jid2);
|
||||
resource = xmpp_jid_resource(ctx, jid2);
|
||||
printf("jid '%s' parsed to %s, %s, %s\n", jid2, _s(node), _s(domain),
|
||||
_s(resource));
|
||||
if (bare == NULL || strcmp(bare, "anyone@example.com"))
|
||||
return 1;
|
||||
if (node == NULL || strcmp(node, "anyone"))
|
||||
return 1;
|
||||
if (domain == NULL || strcmp(domain, "example.com"))
|
||||
return 1;
|
||||
if (resource == NULL || strcmp(resource, "hullo"))
|
||||
return 1;
|
||||
if (bare)
|
||||
xmpp_free(ctx, bare);
|
||||
if (node)
|
||||
xmpp_free(ctx, node);
|
||||
if (domain)
|
||||
xmpp_free(ctx, domain);
|
||||
if (resource)
|
||||
xmpp_free(ctx, resource);
|
||||
printf("jid '%s' parsed to %s, %s, %s\n",
|
||||
jid2, _s(node), _s(domain), _s(resource));
|
||||
if (bare == NULL || strcmp(bare, "anyone@example.com")) return 1;
|
||||
if (node == NULL || strcmp(node, "anyone")) return 1;
|
||||
if (domain == NULL || strcmp(domain, "example.com")) return 1;
|
||||
if (resource == NULL || strcmp(resource, "hullo")) return 1;
|
||||
if (bare) xmpp_free(ctx, bare);
|
||||
if (node) xmpp_free(ctx, node);
|
||||
if (domain) xmpp_free(ctx, domain);
|
||||
if (resource) xmpp_free(ctx, resource);
|
||||
|
||||
bare = xmpp_jid_bare(ctx, jid3);
|
||||
node = xmpp_jid_node(ctx, jid3);
|
||||
domain = xmpp_jid_domain(ctx, jid3);
|
||||
resource = xmpp_jid_resource(ctx, jid3);
|
||||
printf("jid '%s' parsed to %s, %s, %s\n", jid3, _s(node), _s(domain),
|
||||
_s(resource));
|
||||
if (bare == NULL || strcmp(bare, "manic.porter@xyz.net"))
|
||||
return 1;
|
||||
if (node == NULL || strcmp(node, "manic.porter"))
|
||||
return 1;
|
||||
if (domain == NULL || strcmp(domain, "xyz.net"))
|
||||
return 1;
|
||||
if (resource == NULL || strcmp(resource, "frob"))
|
||||
return 1;
|
||||
if (bare)
|
||||
xmpp_free(ctx, bare);
|
||||
if (node)
|
||||
xmpp_free(ctx, node);
|
||||
if (domain)
|
||||
xmpp_free(ctx, domain);
|
||||
if (resource)
|
||||
xmpp_free(ctx, resource);
|
||||
printf("jid '%s' parsed to %s, %s, %s\n",
|
||||
jid3, _s(node), _s(domain), _s(resource));
|
||||
if (bare == NULL || strcmp(bare, "manic.porter@xyz.net")) return 1;
|
||||
if (node == NULL || strcmp(node, "manic.porter")) return 1;
|
||||
if (domain == NULL || strcmp(domain, "xyz.net")) return 1;
|
||||
if (resource == NULL || strcmp(resource, "frob")) return 1;
|
||||
if (bare) xmpp_free(ctx, bare);
|
||||
if (node) xmpp_free(ctx, node);
|
||||
if (domain) xmpp_free(ctx, domain);
|
||||
if (resource) xmpp_free(ctx, resource);
|
||||
|
||||
bare = xmpp_jid_bare(ctx, jid4);
|
||||
node = xmpp_jid_node(ctx, jid4);
|
||||
domain = xmpp_jid_domain(ctx, jid4);
|
||||
resource = xmpp_jid_resource(ctx, jid4);
|
||||
printf("jid '%s' parsed to %s, %s, %s\n", jid4, _s(node), _s(domain),
|
||||
_s(resource));
|
||||
if (bare == NULL || strcmp(bare, "domain.tld"))
|
||||
return 1;
|
||||
if (node != NULL)
|
||||
return 1;
|
||||
if (domain == NULL || strcmp(domain, "domain.tld"))
|
||||
return 1;
|
||||
if (resource != NULL)
|
||||
return 1;
|
||||
if (bare)
|
||||
xmpp_free(ctx, bare);
|
||||
if (node)
|
||||
xmpp_free(ctx, node);
|
||||
if (domain)
|
||||
xmpp_free(ctx, domain);
|
||||
if (resource)
|
||||
xmpp_free(ctx, resource);
|
||||
printf("jid '%s' parsed to %s, %s, %s\n",
|
||||
jid4, _s(node), _s(domain), _s(resource));
|
||||
if (bare == NULL || strcmp(bare, "domain.tld")) return 1;
|
||||
if (node != NULL) return 1;
|
||||
if (domain == NULL || strcmp(domain, "domain.tld")) return 1;
|
||||
if (resource != NULL) return 1;
|
||||
if (bare) xmpp_free(ctx, bare);
|
||||
if (node) xmpp_free(ctx, node);
|
||||
if (domain) xmpp_free(ctx, domain);
|
||||
if (resource) xmpp_free(ctx, resource);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -133,46 +101,38 @@ int test_jid_new(xmpp_ctx_t *ctx)
|
||||
|
||||
jid = xmpp_jid_new(ctx, "node", "domain", "resource");
|
||||
printf("new jid: '%s'\n", jid);
|
||||
if (strcmp(jid, "node@domain/resource"))
|
||||
return 1;
|
||||
if (strcmp(jid, "node@domain/resource")) return 1;
|
||||
xmpp_free(ctx, jid);
|
||||
|
||||
jid = xmpp_jid_new(ctx, "foo", "bar.com", NULL);
|
||||
printf("new jid: '%s'\n", jid);
|
||||
if (strcmp(jid, "foo@bar.com"))
|
||||
return 1;
|
||||
if (strcmp(jid, "foo@bar.com")) return 1;
|
||||
xmpp_free(ctx, jid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
int ret;
|
||||
|
||||
printf("allocating context... ");
|
||||
ctx = xmpp_ctx_new(NULL, NULL);
|
||||
if (ctx == NULL)
|
||||
printf("failed to create context\n");
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
if (ctx == NULL) printf("failed to create context\n");
|
||||
if (ctx == NULL) return -1;
|
||||
printf("ok.\n");
|
||||
|
||||
printf("testing jid routines...\n");
|
||||
ret = test_jid(ctx);
|
||||
if (ret)
|
||||
printf("testing jid routines... failed!\n");
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) printf("testing jid routines... failed!\n");
|
||||
if (ret) return ret;
|
||||
printf("testing jid routines... ok.\n");
|
||||
|
||||
printf("testing jid new routines...\n");
|
||||
ret = test_jid_new(ctx);
|
||||
if (ret)
|
||||
printf("testing jid new routines... failed!\n");
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) printf("testing jid new routines... failed!\n");
|
||||
if (ret) return ret;
|
||||
printf("testing jid new routines... ok.\n");
|
||||
|
||||
printf("freeing context... ");
|
||||
|
||||
@@ -57,7 +57,7 @@ static const struct {
|
||||
},
|
||||
};
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct MD5Context ctx;
|
||||
unsigned char digest[16];
|
||||
|
||||
@@ -21,31 +21,14 @@
|
||||
#include "rand.c"
|
||||
|
||||
/* stubs to build test without whole libstrophe */
|
||||
void *xmpp_alloc(const xmpp_ctx_t *ctx, size_t size)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)size;
|
||||
void *xmpp_alloc(const xmpp_ctx_t * const ctx, const size_t size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void xmpp_free(const xmpp_ctx_t *ctx, void *p)
|
||||
{
|
||||
(void)ctx;
|
||||
(void)p;
|
||||
}
|
||||
|
||||
#ifndef HAVE_SNPRINTF
|
||||
int xmpp_snprintf(char *str, size_t count, const char *fmt, ...)
|
||||
{
|
||||
(void)str;
|
||||
(void)count;
|
||||
(void)fmt;
|
||||
void xmpp_free(const xmpp_ctx_t * const ctx, void *p) { }
|
||||
int xmpp_snprintf (char *str, size_t count, const char *fmt, ...) {
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_SNPRINTF */
|
||||
|
||||
uint64_t time_stamp(void)
|
||||
{
|
||||
uint64_t time_stamp(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -138,8 +121,8 @@ int main()
|
||||
&entropy_input_len);
|
||||
test_hex_to_bin(test_vectors[i].nonce, nonce, &nonce_len);
|
||||
|
||||
Hash_DRBG_Instantiate(&ctx, entropy_input, entropy_input_len, nonce,
|
||||
nonce_len);
|
||||
Hash_DRBG_Instantiate(&ctx, entropy_input, entropy_input_len,
|
||||
nonce, nonce_len);
|
||||
COMPARE(test_vectors[i].V1, test_bin_to_hex(ctx.V, sizeof(ctx.V)));
|
||||
COMPARE(test_vectors[i].C1, test_bin_to_hex(ctx.C, sizeof(ctx.C)));
|
||||
assert(ctx.reseed_counter == 1);
|
||||
|
||||
@@ -19,51 +19,71 @@
|
||||
|
||||
/* res_query("_xmpp-client._tcp.jabber.kiev.ua", C_IN, T_SRV, ...) */
|
||||
static const unsigned char data1[] = {
|
||||
0x95, 0xf3, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x5f, 0x78, 0x6d, 0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x06, 0x6a, 0x61, 0x62, 0x62, 0x65,
|
||||
0x72, 0x04, 0x6b, 0x69, 0x65, 0x76, 0x02, 0x75, 0x61, 0x00, 0x00, 0x21,
|
||||
0x00, 0x01, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3b,
|
||||
0x00, 0x16, 0x00, 0x01, 0x00, 0x00, 0x14, 0x66, 0x06, 0x6a, 0x61, 0x62,
|
||||
0x62, 0x65, 0x72, 0x04, 0x6b, 0x69, 0x65, 0x76, 0x02, 0x75, 0x61, 0x00,
|
||||
0x95, 0xf3, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0c, 0x5f, 0x78, 0x6d,
|
||||
0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x06, 0x6a,
|
||||
0x61, 0x62, 0x62, 0x65, 0x72, 0x04, 0x6b, 0x69,
|
||||
0x65, 0x76, 0x02, 0x75, 0x61, 0x00, 0x00, 0x21,
|
||||
0x00, 0x01, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x3b, 0x00, 0x16, 0x00, 0x01,
|
||||
0x00, 0x00, 0x14, 0x66, 0x06, 0x6a, 0x61, 0x62,
|
||||
0x62, 0x65, 0x72, 0x04, 0x6b, 0x69, 0x65, 0x76,
|
||||
0x02, 0x75, 0x61, 0x00,
|
||||
};
|
||||
/* res_query("_xmpp-client._tcp.jabber.org", C_IN, T_SRV, ...) */
|
||||
static const unsigned char data2[] = {
|
||||
0xf2, 0x98, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x5f, 0x78, 0x6d, 0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x06, 0x6a, 0x61, 0x62, 0x62, 0x65,
|
||||
0x72, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00, 0x21, 0x00, 0x01, 0xc0, 0x0c,
|
||||
0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x03, 0x83, 0x00, 0x1a, 0x00, 0x1e,
|
||||
0x00, 0x1e, 0x14, 0x66, 0x07, 0x68, 0x65, 0x72, 0x6d, 0x65, 0x73, 0x32,
|
||||
0x06, 0x6a, 0x61, 0x62, 0x62, 0x65, 0x72, 0x03, 0x6f, 0x72, 0x67, 0x00,
|
||||
0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x03, 0x83, 0x00, 0x1c,
|
||||
0x00, 0x1f, 0x00, 0x1e, 0x14, 0x66, 0x09, 0x68, 0x65, 0x72, 0x6d, 0x65,
|
||||
0x73, 0x32, 0x76, 0x36, 0x06, 0x6a, 0x61, 0x62, 0x62, 0x65, 0x72, 0x03,
|
||||
0xf2, 0x98, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0c, 0x5f, 0x78, 0x6d,
|
||||
0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x06, 0x6a,
|
||||
0x61, 0x62, 0x62, 0x65, 0x72, 0x03, 0x6f, 0x72,
|
||||
0x67, 0x00, 0x00, 0x21, 0x00, 0x01, 0xc0, 0x0c,
|
||||
0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x03, 0x83,
|
||||
0x00, 0x1a, 0x00, 0x1e, 0x00, 0x1e, 0x14, 0x66,
|
||||
0x07, 0x68, 0x65, 0x72, 0x6d, 0x65, 0x73, 0x32,
|
||||
0x06, 0x6a, 0x61, 0x62, 0x62, 0x65, 0x72, 0x03,
|
||||
0x6f, 0x72, 0x67, 0x00, 0xc0, 0x0c, 0x00, 0x21,
|
||||
0x00, 0x01, 0x00, 0x00, 0x03, 0x83, 0x00, 0x1c,
|
||||
0x00, 0x1f, 0x00, 0x1e, 0x14, 0x66, 0x09, 0x68,
|
||||
0x65, 0x72, 0x6d, 0x65, 0x73, 0x32, 0x76, 0x36,
|
||||
0x06, 0x6a, 0x61, 0x62, 0x62, 0x65, 0x72, 0x03,
|
||||
0x6f, 0x72, 0x67, 0x00,
|
||||
};
|
||||
/* res_query("_xmpp-client._tcp.gmail.com", C_IN, T_SRV, ...) */
|
||||
static const unsigned char data3[] = {
|
||||
0xda, 0xa8, 0x81, 0x80, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x5f, 0x78, 0x6d, 0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x67, 0x6d, 0x61, 0x69, 0x6c,
|
||||
0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x21, 0x00, 0x01, 0xc0, 0x0c, 0x00,
|
||||
0x21, 0x00, 0x01, 0x00, 0x00, 0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00,
|
||||
0x00, 0x14, 0x66, 0x04, 0x61, 0x6c, 0x74, 0x31, 0x04, 0x78, 0x6d, 0x70,
|
||||
0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
|
||||
0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x02,
|
||||
0x43, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x00, 0x14, 0x66, 0x04, 0x61, 0x6c,
|
||||
0x74, 0x34, 0x04, 0x78, 0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00,
|
||||
0x21, 0x00, 0x01, 0x00, 0x00, 0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00,
|
||||
0x00, 0x14, 0x66, 0x04, 0x61, 0x6c, 0x74, 0x32, 0x04, 0x78, 0x6d, 0x70,
|
||||
0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
|
||||
0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x02,
|
||||
0x43, 0x00, 0x19, 0x00, 0x05, 0x00, 0x00, 0x14, 0x66, 0x04, 0x78, 0x6d,
|
||||
0x70, 0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
|
||||
0x63, 0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00,
|
||||
0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x00, 0x14, 0x66, 0x04, 0x61,
|
||||
0x6c, 0x74, 0x33, 0x04, 0x78, 0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
|
||||
0xda, 0xa8, 0x81, 0x80, 0x00, 0x01, 0x00, 0x05,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0c, 0x5f, 0x78, 0x6d,
|
||||
0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x67,
|
||||
0x6d, 0x61, 0x69, 0x6c, 0x03, 0x63, 0x6f, 0x6d,
|
||||
0x00, 0x00, 0x21, 0x00, 0x01, 0xc0, 0x0c, 0x00,
|
||||
0x21, 0x00, 0x01, 0x00, 0x00, 0x02, 0x43, 0x00,
|
||||
0x1e, 0x00, 0x14, 0x00, 0x00, 0x14, 0x66, 0x04,
|
||||
0x61, 0x6c, 0x74, 0x31, 0x04, 0x78, 0x6d, 0x70,
|
||||
0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0xc0,
|
||||
0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x02,
|
||||
0x43, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x00, 0x14,
|
||||
0x66, 0x04, 0x61, 0x6c, 0x74, 0x34, 0x04, 0x78,
|
||||
0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
|
||||
0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00,
|
||||
0x00, 0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00,
|
||||
0x00, 0x14, 0x66, 0x04, 0x61, 0x6c, 0x74, 0x32,
|
||||
0x04, 0x78, 0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
|
||||
0x6f, 0x6d, 0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00,
|
||||
0x01, 0x00, 0x00, 0x02, 0x43, 0x00, 0x19, 0x00,
|
||||
0x05, 0x00, 0x00, 0x14, 0x66, 0x04, 0x78, 0x6d,
|
||||
0x70, 0x70, 0x01, 0x6c, 0x06, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
|
||||
0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00,
|
||||
0x02, 0x43, 0x00, 0x1e, 0x00, 0x14, 0x00, 0x00,
|
||||
0x14, 0x66, 0x04, 0x61, 0x6c, 0x74, 0x33, 0x04,
|
||||
0x78, 0x6d, 0x70, 0x70, 0x01, 0x6c, 0x06, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
|
||||
0x6d, 0x00,
|
||||
};
|
||||
/* res_query("_xmpp-client._tcp.jabber.calyxinstitute.org", C_IN, T_SRV, ...) */
|
||||
static const unsigned char data4[] = {
|
||||
@@ -99,14 +119,17 @@ static const unsigned char data5[] = {
|
||||
};
|
||||
/* hacked data2 with two empty-string targets. */
|
||||
static const unsigned char data6[] = {
|
||||
0xf2, 0x98, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x0c, 0x5f, 0x78, 0x6d, 0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69,
|
||||
0x65, 0x6e, 0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x06, 0x6a, 0x61,
|
||||
0x62, 0x62, 0x65, 0x72, 0x03, 0x6f, 0x72, 0x67, 0x00, 0x00, 0x21,
|
||||
0x00, 0x01, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x03,
|
||||
0x83, 0x00, 0x07, 0x00, 0x1e, 0x00, 0x1e, 0x14, 0x66, 0x00, 0xc0,
|
||||
0x0c, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x03, 0x83, 0x00, 0x08,
|
||||
0x00, 0x1f, 0x00, 0x1e, 0x14, 0x66, 0xc0, 0x40,
|
||||
0xf2, 0x98, 0x81, 0x80, 0x00, 0x01, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0c, 0x5f, 0x78, 0x6d,
|
||||
0x70, 0x70, 0x2d, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x06, 0x6a,
|
||||
0x61, 0x62, 0x62, 0x65, 0x72, 0x03, 0x6f, 0x72,
|
||||
0x67, 0x00, 0x00, 0x21, 0x00, 0x01, 0xc0, 0x0c,
|
||||
0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x03, 0x83,
|
||||
0x00, 0x07, 0x00, 0x1e, 0x00, 0x1e, 0x14, 0x66,
|
||||
0x00, 0xc0, 0x0c, 0x00, 0x21, 0x00, 0x01, 0x00,
|
||||
0x00, 0x03, 0x83, 0x00, 0x08, 0x00, 0x1f, 0x00,
|
||||
0x1e, 0x14, 0x66, 0xc0, 0x40,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
@@ -164,13 +187,12 @@ static int srv_rr_list_len(resolver_srv_rr_t *list)
|
||||
{
|
||||
int nr;
|
||||
|
||||
for (nr = 0; list != NULL; ++nr, list = list->next)
|
||||
;
|
||||
for (nr = 0; list != NULL; ++nr, list = list->next);
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
xmpp_rand_t *rand;
|
||||
@@ -201,8 +223,8 @@ int main()
|
||||
port = srv_rr_list->port;
|
||||
COMPARE(tests[i].target, domain);
|
||||
if (tests[i].port != port) {
|
||||
printf("fail! got port=%u, but should be %u\n", (unsigned)port,
|
||||
(unsigned)tests[i].port);
|
||||
printf("fail! got port=%u, but should be %u\n",
|
||||
(unsigned)port, (unsigned)tests[i].port);
|
||||
return 1;
|
||||
}
|
||||
printf("ok\n");
|
||||
|
||||
@@ -69,8 +69,8 @@ int test_digest_md5(xmpp_ctx_t *ctx)
|
||||
{
|
||||
char *result;
|
||||
|
||||
result =
|
||||
sasl_digest_md5(ctx, challenge_md5, "somenode@somerealm", "secret");
|
||||
result = sasl_digest_md5(ctx, challenge_md5,
|
||||
"somenode@somerealm", "secret");
|
||||
printf("response:\n%s\n", result);
|
||||
if (strcmp(response_md5, result)) {
|
||||
/* generated incorrect response to challenge */
|
||||
@@ -80,33 +80,27 @@ int test_digest_md5(xmpp_ctx_t *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
int ret;
|
||||
|
||||
printf("allocating context... ");
|
||||
ctx = xmpp_ctx_new(NULL, NULL);
|
||||
if (ctx == NULL)
|
||||
printf("failed to create context\n");
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
if (ctx == NULL) printf("failed to create context\n");
|
||||
if (ctx == NULL) return -1;
|
||||
printf("ok.\n");
|
||||
|
||||
printf("testing SASL PLAIN... ");
|
||||
ret = test_plain(ctx);
|
||||
if (ret)
|
||||
printf("failed!\n");
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) printf("failed!\n");
|
||||
if (ret) return ret;
|
||||
printf("ok.\n");
|
||||
|
||||
printf("testing SASL DIGEST-MD5... ");
|
||||
ret = test_digest_md5(ctx);
|
||||
if (ret)
|
||||
printf("failed!\n");
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) printf("failed!\n");
|
||||
if (ret) return ret;
|
||||
printf("ok.\n");
|
||||
|
||||
printf("freeing context... ");
|
||||
|
||||
@@ -58,19 +58,19 @@ static const struct {
|
||||
},
|
||||
};
|
||||
|
||||
static void test_df(const struct hash_alg *alg)
|
||||
static void test_df(void)
|
||||
{
|
||||
size_t i;
|
||||
const char *s;
|
||||
uint8_t dk[SCRAM_DIGEST_SIZE];
|
||||
uint8_t dk[SHA1_DIGEST_SIZE];
|
||||
|
||||
printf("Derivation function SCRAM_Hi tests for %s.\n", alg->scram_name);
|
||||
printf("Derivation function tests (SCRAM_SHA1_Hi).\n");
|
||||
for (i = 0; i < ARRAY_SIZE(df_vectors); ++i) {
|
||||
printf("Test #%d: ", (int)i + 1);
|
||||
SCRAM_Hi(alg, (uint8_t *)df_vectors[i].P, df_vectors[i].P_len,
|
||||
SCRAM_SHA1_Hi((uint8_t *)df_vectors[i].P, df_vectors[i].P_len,
|
||||
(uint8_t *)df_vectors[i].S, df_vectors[i].S_len,
|
||||
df_vectors[i].c, dk);
|
||||
s = test_bin_to_hex(dk, alg->digest_size);
|
||||
s = test_bin_to_hex(dk, sizeof(dk));
|
||||
COMPARE(df_vectors[i].DK, s);
|
||||
printf("ok\n");
|
||||
}
|
||||
@@ -101,115 +101,42 @@ static const struct {
|
||||
},
|
||||
};
|
||||
|
||||
static void test_scram(const struct hash_alg *alg)
|
||||
static void test_scram(void)
|
||||
{
|
||||
uint8_t key[SCRAM_DIGEST_SIZE];
|
||||
uint8_t sign[SCRAM_DIGEST_SIZE];
|
||||
uint8_t key[SHA1_DIGEST_SIZE];
|
||||
uint8_t sign[SHA1_DIGEST_SIZE];
|
||||
uint8_t salt[256];
|
||||
size_t salt_len;
|
||||
char auth[512];
|
||||
const char *s;
|
||||
size_t i;
|
||||
size_t j;
|
||||
int j;
|
||||
|
||||
printf("SCRAM_ClientKey and SCRAM_ClientSignature tests for %s.\n",
|
||||
alg->scram_name);
|
||||
printf("SCRAM_SHA1_ClientKey and SCRAM_SHA1_ClientSignature tests.\n");
|
||||
for (i = 0; i < ARRAY_SIZE(scram_vectors); ++i) {
|
||||
printf("Test #%d: ", (int)i + 1);
|
||||
snprintf(auth, sizeof(auth), "%s,%s,%s", scram_vectors[i].initial + 3,
|
||||
scram_vectors[i].challenge, scram_vectors[i].response);
|
||||
snprintf(auth, sizeof(auth), "%s,%s,%s",
|
||||
scram_vectors[i].initial + 3, scram_vectors[i].challenge,
|
||||
scram_vectors[i].response);
|
||||
test_hex_to_bin(scram_vectors[i].salt, salt, &salt_len);
|
||||
|
||||
SCRAM_ClientKey(alg, (uint8_t *)scram_vectors[i].password,
|
||||
strlen(scram_vectors[i].password), salt, salt_len,
|
||||
scram_vectors[i].i, key);
|
||||
SCRAM_ClientSignature(alg, key, (uint8_t *)auth, strlen(auth), sign);
|
||||
for (j = 0; j < alg->digest_size; j++) {
|
||||
SCRAM_SHA1_ClientKey((uint8_t *)scram_vectors[i].password,
|
||||
strlen(scram_vectors[i].password),
|
||||
salt, salt_len, scram_vectors[i].i, key);
|
||||
SCRAM_SHA1_ClientSignature(key, (uint8_t *)auth, strlen(auth), sign);
|
||||
for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
|
||||
sign[j] ^= key[j];
|
||||
}
|
||||
s = test_bin_to_hex(sign, alg->digest_size);
|
||||
s = test_bin_to_hex(sign, SHA1_DIGEST_SIZE);
|
||||
COMPARE(scram_vectors[i].sign, s);
|
||||
printf("ok\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test vectors for HMAC (RFC2202, RFC4231).
|
||||
*/
|
||||
static const uint8_t hmac_key1[] = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b};
|
||||
static const uint8_t hmac_data1[] = {0x48, 0x69, 0x20, 0x54,
|
||||
0x68, 0x65, 0x72, 0x65};
|
||||
static const struct {
|
||||
const uint8_t *key;
|
||||
size_t key_len;
|
||||
const uint8_t *data;
|
||||
size_t data_len;
|
||||
const uint8_t sha1[SHA1_DIGEST_SIZE];
|
||||
const uint8_t sha256[SHA256_DIGEST_SIZE];
|
||||
const uint8_t sha512[SHA512_DIGEST_SIZE];
|
||||
} hmac_vectors[] = {
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
.key = hmac_key1,
|
||||
.key_len = sizeof(hmac_key1),
|
||||
.data = hmac_data1,
|
||||
.data_len = sizeof(hmac_data1),
|
||||
.sha1 = {0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b,
|
||||
0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00},
|
||||
.sha256 = {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53,
|
||||
0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
|
||||
0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,
|
||||
0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7},
|
||||
.sha512 = {0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0,
|
||||
0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, 0x23, 0x79, 0xf4, 0xe2,
|
||||
0xce, 0x4e, 0xc2, 0x78, 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1,
|
||||
0x7c, 0xde, 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02,
|
||||
0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, 0xbe, 0x9d,
|
||||
0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20,
|
||||
0x3a, 0x12, 0x68, 0x54},
|
||||
},
|
||||
};
|
||||
|
||||
static void test_hmac(const struct hash_alg *alg)
|
||||
{
|
||||
size_t i;
|
||||
uint8_t digest[SCRAM_DIGEST_SIZE];
|
||||
|
||||
printf("HMAC tests for %s.\n", alg->scram_name);
|
||||
for (i = 0; i < ARRAY_SIZE(hmac_vectors); ++i) {
|
||||
printf("Test #%d: ", (int)i + 1);
|
||||
memset(digest, 0, sizeof(digest));
|
||||
crypto_HMAC(alg, hmac_vectors[i].key, hmac_vectors[i].key_len,
|
||||
hmac_vectors[i].data, hmac_vectors[i].data_len, digest);
|
||||
switch (alg->digest_size) {
|
||||
case SHA1_DIGEST_SIZE:
|
||||
COMPARE_BUF(hmac_vectors[i].sha1, alg->digest_size, digest,
|
||||
alg->digest_size);
|
||||
break;
|
||||
case SHA256_DIGEST_SIZE:
|
||||
COMPARE_BUF(hmac_vectors[i].sha256, alg->digest_size, digest,
|
||||
alg->digest_size);
|
||||
break;
|
||||
case SHA512_DIGEST_SIZE:
|
||||
COMPARE_BUF(hmac_vectors[i].sha512, alg->digest_size, digest,
|
||||
alg->digest_size);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown digest size: %zu\n", alg->digest_size);
|
||||
exit(1);
|
||||
}
|
||||
printf("ok\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_df(&scram_sha1);
|
||||
test_scram(&scram_sha1);
|
||||
test_hmac(&scram_sha1);
|
||||
test_hmac(&scram_sha256);
|
||||
test_hmac(&scram_sha512);
|
||||
test_df();
|
||||
test_scram();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -12,11 +12,13 @@
|
||||
|
||||
/* Test Vectors (from FIPS PUB 180-1) */
|
||||
static char *test_data[] = {
|
||||
"abc", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"abc",
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"A million repetitions of 'a'",
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"};
|
||||
static char *test_results[] = {"A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
|
||||
static char *test_results[] = {
|
||||
"A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D",
|
||||
"84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1",
|
||||
"34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F",
|
||||
"AD5B3FDB CB526778 C2839D2F 151EA753 995E26A0"};
|
||||
@@ -37,7 +39,7 @@ static void digest_to_hex(const uint8_t *digest, char *output)
|
||||
*(c - 1) = '\0';
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
size_t k;
|
||||
SHA1_CTX context;
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/* Tests for SHA-256 from LibTomCrypt */
|
||||
/* This file is in the public domain */
|
||||
|
||||
/* gcc -o test_sha256 -I./src tests/test_sha256.c tests/test.c src/sha256.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha256.h"
|
||||
#include "test.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
static const struct {
|
||||
const char *msg;
|
||||
unsigned char hash[SHA256_DIGEST_SIZE];
|
||||
} tests[] = {
|
||||
{"abc",
|
||||
{0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40,
|
||||
0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17,
|
||||
0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}},
|
||||
{"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
{0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26,
|
||||
0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff,
|
||||
0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}},
|
||||
};
|
||||
|
||||
int i;
|
||||
unsigned char tmp[SHA256_DIGEST_SIZE];
|
||||
sha256_context md;
|
||||
|
||||
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
|
||||
sha256_init(&md);
|
||||
sha256_process(&md, (unsigned char *)tests[i].msg,
|
||||
(unsigned long)strlen(tests[i].msg));
|
||||
sha256_done(&md, tmp);
|
||||
COMPARE_BUF(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash));
|
||||
}
|
||||
|
||||
/* success */
|
||||
fprintf(stdout, "ok\n");
|
||||
return (0);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/* Tests for SHA-512 from LibTomCrypt */
|
||||
/* This file is in the public domain */
|
||||
|
||||
/* gcc -o test_sha512 -I./src tests/test_sha512.c tests/test.c src/sha512.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha512.h"
|
||||
#include "test.h"
|
||||
|
||||
static const uint8_t hash_1m_a[SHA512_DIGEST_SIZE] = {
|
||||
0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64, 0x4e, 0x2e, 0x42,
|
||||
0xc7, 0xbc, 0x15, 0xb4, 0x63, 0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20,
|
||||
0x44, 0x28, 0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb, 0xde,
|
||||
0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a, 0x4c, 0xb0, 0x43, 0x2c,
|
||||
0xe5, 0x77, 0xc3, 0x1b, 0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa,
|
||||
0x2e, 0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b};
|
||||
|
||||
int main()
|
||||
{
|
||||
static const struct {
|
||||
const char *msg;
|
||||
uint8_t hash[SHA512_DIGEST_SIZE];
|
||||
} tests[] = {
|
||||
{"abc",
|
||||
{0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73,
|
||||
0x49, 0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9,
|
||||
0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21,
|
||||
0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23,
|
||||
0xa3, 0xfe, 0xeb, 0xbd, 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8,
|
||||
0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f}},
|
||||
{"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklm"
|
||||
"nopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
|
||||
{0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, 0x8c, 0xf4, 0xf7,
|
||||
0x28, 0x14, 0xfc, 0x14, 0x3f, 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f,
|
||||
0x7f, 0xa1, 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, 0x50,
|
||||
0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, 0x33, 0x1b, 0x99, 0xde,
|
||||
0xc4, 0xb5, 0x43, 0x3a, 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26,
|
||||
0x54, 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09}},
|
||||
};
|
||||
|
||||
size_t i;
|
||||
uint8_t tmp[SHA512_DIGEST_SIZE];
|
||||
sha512_context md;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
||||
sha512_init(&md);
|
||||
sha512_process(&md, (uint8_t *)tests[i].msg, strlen(tests[i].msg));
|
||||
sha512_done(&md, tmp);
|
||||
COMPARE_BUF(tests[i].hash, sizeof(tests[i].hash), tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
/* special case: one million repetitions of the character 'a' */
|
||||
sha512_init(&md);
|
||||
for (i = 0; i < 1000000U; ++i)
|
||||
sha512_process(&md, (uint8_t *)"a", 1);
|
||||
sha512_done(&md, tmp);
|
||||
COMPARE_BUF(hash_1m_a, sizeof(hash_1m_a), tmp, sizeof(tmp));
|
||||
|
||||
/* success */
|
||||
fprintf(stdout, "ok\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -20,14 +20,38 @@ int main(void)
|
||||
{
|
||||
char buf1[LONG_STRING];
|
||||
char buf2[LONG_STRING];
|
||||
char *fp_fmt[] = {"%-1.5f", "%1.5f", "%123.9f", "%10.5f", "% 10.5f",
|
||||
"%+22.9f", "%+4.9f", "%01.3f", "%4f", "%3.1f",
|
||||
"%3.2f", "%.0f", "%.1f", NULL};
|
||||
double fp_nums[] = {-1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96,
|
||||
0.996, 0.9996, 1.996, 4.136, 0};
|
||||
char *int_fmt[] = {"%-1.5d", "%1.5d", "%123.9d", "%5.5d",
|
||||
"%10.5d", "% 10.5d", "%+22.33d", "%01.3d",
|
||||
"%4d", "0x%x", "0x%04x", NULL};
|
||||
char *fp_fmt[] = {
|
||||
"%-1.5f",
|
||||
"%1.5f",
|
||||
"%123.9f",
|
||||
"%10.5f",
|
||||
"% 10.5f",
|
||||
"%+22.9f",
|
||||
"%+4.9f",
|
||||
"%01.3f",
|
||||
"%4f",
|
||||
"%3.1f",
|
||||
"%3.2f",
|
||||
"%.0f",
|
||||
"%.1f",
|
||||
NULL
|
||||
};
|
||||
double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
|
||||
0.9996, 1.996, 4.136, 0};
|
||||
char *int_fmt[] = {
|
||||
"%-1.5d",
|
||||
"%1.5d",
|
||||
"%123.9d",
|
||||
"%5.5d",
|
||||
"%10.5d",
|
||||
"% 10.5d",
|
||||
"%+22.33d",
|
||||
"%01.3d",
|
||||
"%4d",
|
||||
"0x%x",
|
||||
"0x%04x",
|
||||
NULL
|
||||
};
|
||||
long int_nums[] = { -1, 134, 91340, 341, 0203, 0x76543210, 0};
|
||||
int x, y;
|
||||
int fail = 0;
|
||||
@@ -36,12 +60,13 @@ int main(void)
|
||||
printf ("Testing xmpp_snprintf format codes against system sprintf...\n");
|
||||
|
||||
for (x = 0; fp_fmt[x] != NULL ; x++)
|
||||
for (y = 0; fp_nums[y] != 0; y++) {
|
||||
for (y = 0; fp_nums[y] != 0 ; y++)
|
||||
{
|
||||
xmpp_snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);
|
||||
sprintf (buf2, fp_fmt[x], fp_nums[y]);
|
||||
if (strcmp(buf1, buf2)) {
|
||||
printf("xmpp_snprintf doesn't match Format: "
|
||||
"%s\n\txmpp_snprintf = %s\n\tsprintf = %s\n",
|
||||
if (strcmp (buf1, buf2))
|
||||
{
|
||||
printf("xmpp_snprintf doesn't match Format: %s\n\txmpp_snprintf = %s\n\tsprintf = %s\n",
|
||||
fp_fmt[x], buf1, buf2);
|
||||
fail++;
|
||||
}
|
||||
@@ -49,12 +74,13 @@ int main(void)
|
||||
}
|
||||
|
||||
for (x = 0; int_fmt[x] != NULL ; x++)
|
||||
for (y = 0; int_nums[y] != 0; y++) {
|
||||
for (y = 0; int_nums[y] != 0 ; y++)
|
||||
{
|
||||
xmpp_snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);
|
||||
sprintf (buf2, int_fmt[x], int_nums[y]);
|
||||
if (strcmp(buf1, buf2)) {
|
||||
printf("xmpp_snprintf doesn't match Format: "
|
||||
"%s\n\txmpp_snprintf = %s\n\tsprintf = %s\n",
|
||||
if (strcmp (buf1, buf2))
|
||||
{
|
||||
printf("xmpp_snprintf doesn't match Format: %s\n\txmpp_snprintf = %s\n\tsprintf = %s\n",
|
||||
int_fmt[x], buf1, buf2);
|
||||
fail++;
|
||||
}
|
||||
|
||||
@@ -23,24 +23,19 @@ int wait_for_connect(sock_t sock)
|
||||
fd_set wfds, efds;
|
||||
int ret;
|
||||
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(sock, &wfds);
|
||||
FD_ZERO(&efds);
|
||||
FD_SET(sock, &efds);
|
||||
FD_ZERO(&wfds); FD_SET(sock, &wfds);
|
||||
FD_ZERO(&efds); FD_SET(sock, &efds);
|
||||
|
||||
ret = select(sock + 1, NULL, &wfds, &efds, NULL);
|
||||
if (ret <= 0)
|
||||
return -1;
|
||||
if (ret <= 0) return -1;
|
||||
|
||||
if (FD_ISSET(sock, &efds))
|
||||
return 0;
|
||||
if (FD_ISSET(sock, &wfds))
|
||||
return 1;
|
||||
if (FD_ISSET(sock, &efds)) return 0;
|
||||
if (FD_ISSET(sock, &wfds)) return 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main()
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
sock_t sock;
|
||||
int err;
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#define MAGICPTR ((void *)0xfeedbeef)
|
||||
static unsigned long used_blocks = 0;
|
||||
@@ -34,10 +31,7 @@ static void stanza_free(void *ptr, void *userdata)
|
||||
{
|
||||
assert(userdata == MAGICPTR);
|
||||
|
||||
if (ptr != NULL) {
|
||||
assert(used_blocks > 0);
|
||||
--used_blocks;
|
||||
}
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
@@ -45,14 +39,6 @@ static void *stanza_realloc(void *ptr, size_t size, void *userdata)
|
||||
{
|
||||
assert(userdata == MAGICPTR);
|
||||
|
||||
if (ptr != NULL && size == 0) {
|
||||
/* equivalent to free(ptr) */
|
||||
assert(used_blocks > 0);
|
||||
--used_blocks;
|
||||
} else if (ptr == NULL) {
|
||||
/* equivalent to malloc(size) */
|
||||
++used_blocks;
|
||||
}
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
@@ -92,81 +78,6 @@ static void test_stanza_add_child(xmpp_ctx_t *ctx)
|
||||
assert(used_blocks == baseline);
|
||||
}
|
||||
|
||||
static void test_stanza_from_string(xmpp_ctx_t *ctx)
|
||||
{
|
||||
xmpp_stanza_t *stanza;
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
int ret;
|
||||
|
||||
static const char *str =
|
||||
"<signcrypt xmlns=\"urn:xmpp:openpgp:0\"><to "
|
||||
"jid=\"user@domain.com\"/><time "
|
||||
"stamp=\"2020-06-03T21:26:24+0200\"/><rpad/><payload><body "
|
||||
"xmlns=\"jabber:client\">Hello World!</body></payload></signcrypt>";
|
||||
|
||||
stanza = xmpp_stanza_new_from_string(ctx, str);
|
||||
assert(stanza != NULL);
|
||||
ret = xmpp_stanza_to_text(stanza, &buf, &buflen);
|
||||
assert(ret == XMPP_EOK);
|
||||
COMPARE(str, buf);
|
||||
xmpp_free(ctx, buf);
|
||||
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()
|
||||
{
|
||||
xmpp_ctx_t *ctx;
|
||||
@@ -176,8 +87,6 @@ int main()
|
||||
assert(ctx != NULL);
|
||||
|
||||
test_stanza_add_child(ctx);
|
||||
test_stanza_from_string(ctx);
|
||||
test_stanza_error(ctx);
|
||||
|
||||
xmpp_ctx_free(ctx);
|
||||
xmpp_shutdown();
|
||||
|
||||
@@ -75,8 +75,8 @@ static int test_strdup_one(xmpp_ctx_t *ctx, const char *s)
|
||||
|
||||
if (!s1 || !s2 || strcmp(s1, s2) != 0) {
|
||||
rc = -1;
|
||||
printf("strdup: '%s', xmpp_strdup: '%s'\n", s1 ? s1 : "<NULL>",
|
||||
s2 ? s2 : "<NULL>");
|
||||
printf("strdup: '%s', xmpp_strdup: '%s'\n",
|
||||
s1 ? s1 : "<NULL>", s2 ? s2 : "<NULL>");
|
||||
}
|
||||
|
||||
free(s1);
|
||||
|
||||
@@ -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