Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd92f69c76 | ||
|
|
73080e0660 | ||
|
|
7cdef1e319 | ||
|
|
527bc0573a | ||
|
|
59d2dd55d2 | ||
|
|
b1cbcffdc7 | ||
|
|
154b70ed2c | ||
|
|
e33a98e498 | ||
|
|
239d365ea1 | ||
|
|
57ed30b2bc | ||
|
|
86f913b001 | ||
|
|
e2f1c1e94a | ||
|
|
f62d817c71 | ||
|
|
b753e6cf18 | ||
|
|
0fed8a55e4 | ||
|
|
d28520ba30 | ||
|
|
c52ba85846 | ||
|
|
3b906f6ceb | ||
|
|
5d76e052ec | ||
|
|
37a40dec23 | ||
|
|
2093aac817 | ||
|
|
29fa1bf27e | ||
|
|
f364ed184b | ||
|
|
40c9fe22b3 | ||
|
|
c33c0a6998 | ||
|
|
92e674e412 | ||
|
|
9f82aac8ce | ||
|
|
a3f1b83f3a | ||
|
|
71f75b2e2e | ||
|
|
b23104f920 | ||
|
|
057f9068c6 | ||
|
|
3231214344 | ||
|
|
55efc601cb | ||
|
|
dcbf3fb4d5 | ||
|
|
e2acd98612 | ||
|
|
ee4f6d4e3c | ||
|
|
db14f2bd4a | ||
|
|
e768604533 | ||
|
|
1afcd485db | ||
|
|
58613ea7f3 | ||
|
|
bf5bf96e95 | ||
|
|
529a9bed44 | ||
|
|
fd4f26e5d4 | ||
|
|
e7f87c652e | ||
|
|
65d2535302 | ||
|
|
a981c0a733 | ||
|
|
b08625ef4a | ||
|
|
ea719cd02a | ||
|
|
52dcd26b8c | ||
|
|
cf361d35fe | ||
|
|
077afae693 | ||
|
|
783bad0897 |
15
.gitignore
vendored
15
.gitignore
vendored
@@ -22,22 +22,29 @@ autom4te.cache
|
|||||||
.sconsign*
|
.sconsign*
|
||||||
src/*.o
|
src/*.o
|
||||||
examples/*.o
|
examples/*.o
|
||||||
tests/*.o
|
|
||||||
tests/check_parser
|
|
||||||
*.a
|
*.a
|
||||||
|
*.pc
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.zip
|
*.zip
|
||||||
docs/html
|
docs/html
|
||||||
TAGS
|
TAGS
|
||||||
examples/basic
|
tags
|
||||||
examples/active
|
examples/active
|
||||||
examples/roster
|
examples/basic
|
||||||
examples/bot
|
examples/bot
|
||||||
|
examples/component
|
||||||
|
examples/roster
|
||||||
test_stamp
|
test_stamp
|
||||||
|
test-suite.log
|
||||||
tests/*.o
|
tests/*.o
|
||||||
|
tests/*.log
|
||||||
|
tests/*.trs
|
||||||
|
tests/check_parser
|
||||||
tests/test_base64
|
tests/test_base64
|
||||||
tests/test_ctx
|
tests/test_ctx
|
||||||
tests/test_hash
|
tests/test_hash
|
||||||
tests/test_jid
|
tests/test_jid
|
||||||
tests/test_sasl
|
tests/test_sasl
|
||||||
tests/test_sock
|
tests/test_sock
|
||||||
|
m4/
|
||||||
|
libstrophe.project
|
||||||
|
|||||||
11
ChangeLog
11
ChangeLog
@@ -1,3 +1,10 @@
|
|||||||
0.8.5
|
0.8.8
|
||||||
- libtoolize to generate .so
|
- XML namespace support
|
||||||
|
- XEP-0114 support
|
||||||
|
|
||||||
|
0.8.7
|
||||||
|
- SCRAM-SHA-1 authentication mechanism
|
||||||
|
- pkg-config support
|
||||||
|
|
||||||
|
0.8.5
|
||||||
|
- libtoolize to generate .so
|
||||||
|
|||||||
23
Makefile.am
23
Makefile.am
@@ -1,10 +1,12 @@
|
|||||||
AUTOMAKE_OPTIONS = subdir-objects
|
AUTOMAKE_OPTIONS = subdir-objects
|
||||||
|
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
AM_CFLAGS = -g -Wall
|
AM_CFLAGS = -g -Wall
|
||||||
|
|
||||||
PARSER_CFLAGS=@PARSER_CFLAGS@
|
PARSER_CFLAGS=@PARSER_CFLAGS@
|
||||||
PARSER_LIBS=@PARSER_LIBS@
|
PARSER_LIBS=@PARSER_LIBS@
|
||||||
|
|
||||||
|
SSL_CFLAGS = @openssl_CFLAGS@
|
||||||
SSL_LIBS = @openssl_LIBS@
|
SSL_LIBS = @openssl_LIBS@
|
||||||
|
|
||||||
STROPHE_FLAGS = -I$(top_srcdir)
|
STROPHE_FLAGS = -I$(top_srcdir)
|
||||||
@@ -13,15 +15,18 @@ STROPHE_LIBS = libstrophe.la
|
|||||||
## Main build targets
|
## Main build targets
|
||||||
lib_LTLIBRARIES = libstrophe.la
|
lib_LTLIBRARIES = libstrophe.la
|
||||||
|
|
||||||
libstrophe_la_CFLAGS=$(STROPHE_FLAGS) $(PARSER_CFLAGS)
|
libstrophe_la_CFLAGS = $(SSL_CFLAGS) $(STROPHE_FLAGS) $(PARSER_CFLAGS)
|
||||||
libstrophe_la_LDFLAGS=$(SSL_LIBS) $(PARSER_LIBS)
|
libstrophe_la_LDFLAGS = $(SSL_LIBS) $(PARSER_LIBS)
|
||||||
|
# Export only public API
|
||||||
|
libstrophe_la_LDFLAGS += -export-symbols-regex '^xmpp_'
|
||||||
libstrophe_la_SOURCES = src/auth.c src/conn.c src/ctx.c \
|
libstrophe_la_SOURCES = src/auth.c src/conn.c src/ctx.c \
|
||||||
src/event.c src/handler.c src/hash.c \
|
src/event.c src/handler.c src/hash.c \
|
||||||
src/jid.c src/md5.c src/sasl.c src/sha1.c \
|
src/jid.c src/md5.c src/sasl.c src/scram.c src/sha1.c \
|
||||||
src/snprintf.c src/sock.c src/stanza.c src/thread.c \
|
src/snprintf.c src/sock.c src/stanza.c src/thread.c \
|
||||||
src/tls_openssl.c src/util.c \
|
src/tls_openssl.c src/util.c \
|
||||||
src/common.h src/hash.h src/md5.h src/ostypes.h src/parser.h \
|
src/common.h src/hash.h src/md5.h src/ostypes.h src/parser.h \
|
||||||
src/sasl.h src/sha1.h src/sock.h src/thread.h src/tls.h src/util.h
|
src/sasl.h src/scram.h src/sha1.h src/sock.h src/thread.h src/tls.h \
|
||||||
|
src/util.h
|
||||||
|
|
||||||
if PARSER_EXPAT
|
if PARSER_EXPAT
|
||||||
libstrophe_la_SOURCES += src/parser_expat.c
|
libstrophe_la_SOURCES += src/parser_expat.c
|
||||||
@@ -32,10 +37,12 @@ endif
|
|||||||
include_HEADERS = strophe.h
|
include_HEADERS = strophe.h
|
||||||
noinst_HEADERS = strophepp.h
|
noinst_HEADERS = strophepp.h
|
||||||
|
|
||||||
|
pkgconfig_DATA = libstrophe.pc
|
||||||
|
|
||||||
EXTRA_DIST = docs
|
EXTRA_DIST = docs
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
noinst_PROGRAMS = examples/active examples/roster examples/basic examples/bot
|
noinst_PROGRAMS = examples/active examples/roster examples/basic examples/bot examples/component
|
||||||
examples_active_SOURCES = examples/active.c
|
examples_active_SOURCES = examples/active.c
|
||||||
examples_active_CFLAGS = $(STROPHE_FLAGS)
|
examples_active_CFLAGS = $(STROPHE_FLAGS)
|
||||||
examples_active_LDADD = $(STROPHE_LIBS)
|
examples_active_LDADD = $(STROPHE_LIBS)
|
||||||
@@ -47,7 +54,10 @@ examples_basic_CFLAGS = $(STROPHE_FLAGS)
|
|||||||
examples_basic_LDADD = $(STROPHE_LIBS)
|
examples_basic_LDADD = $(STROPHE_LIBS)
|
||||||
examples_bot_SOURCES = examples/bot.c
|
examples_bot_SOURCES = examples/bot.c
|
||||||
examples_bot_CFLAGS = $(STROPHE_FLAGS)
|
examples_bot_CFLAGS = $(STROPHE_FLAGS)
|
||||||
examples_bot_LDADD = $(STROPHE_LIBS)
|
examples_bot_LDADD = $(STROPHE_LIBS)
|
||||||
|
examples_component_SOURCES = examples/component.c
|
||||||
|
examples_component_CFLAGS = $(STROPHE_FLAGS)
|
||||||
|
examples_component_LDADD = $(STROPHE_LIBS)
|
||||||
|
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
@@ -57,3 +67,4 @@ tests_check_parser_SOURCES = tests/check_parser.c tests/test.h
|
|||||||
tests_check_parser_CFLAGS = @check_CFLAGS@ $(PARSER_CFLAGS) $(STROPHE_FLAGS) \
|
tests_check_parser_CFLAGS = @check_CFLAGS@ $(PARSER_CFLAGS) $(STROPHE_FLAGS) \
|
||||||
-I$(top_srcdir)/src
|
-I$(top_srcdir)/src
|
||||||
tests_check_parser_LDADD = @check_LIBS@ $(STROPHE_LIBS)
|
tests_check_parser_LDADD = @check_LIBS@ $(STROPHE_LIBS)
|
||||||
|
tests_check_parser_LDFLAGS = -static
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Some versions of aclocal fail if m4/ doesn't exist
|
||||||
|
mkdir -p m4
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
|
|||||||
70
configure.ac
70
configure.ac
@@ -1,4 +1,5 @@
|
|||||||
AC_INIT([libstrophe], [0.8.5], [jack@metajack.im])
|
AC_INIT([libstrophe], [0.8.8], [jack@metajack.im])
|
||||||
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AM_INIT_AUTOMAKE([foreign])
|
AM_INIT_AUTOMAKE([foreign])
|
||||||
LT_INIT([dlopen])
|
LT_INIT([dlopen])
|
||||||
|
|
||||||
@@ -11,7 +12,15 @@ AS_CASE([$host_os],
|
|||||||
[freebsd*], [PLATFORM="freebsd"],
|
[freebsd*], [PLATFORM="freebsd"],
|
||||||
[PLATFORM="nix"])
|
[PLATFORM="nix"])
|
||||||
|
|
||||||
PKG_CHECK_MODULES([openssl], [openssl], [], [AC_MSG_ERROR([openssl not found; openssl required])])
|
PKG_CHECK_MODULES([openssl], [openssl], [PC_REQUIRES+=(openssl)],
|
||||||
|
[AC_CHECK_HEADER([openssl/ssl.h],
|
||||||
|
[
|
||||||
|
openssl_LIBS="-lssl -lcrypto"
|
||||||
|
PC_LIBS+=($openssl_LIBS)
|
||||||
|
],
|
||||||
|
[AC_MSG_ERROR([openssl not found; openssl required])]
|
||||||
|
)])
|
||||||
|
|
||||||
PKG_CHECK_MODULES([check], [check >= 0.9.4], [], [AC_MSG_WARN([libcheck not found; unit tests will not be compilable])])
|
PKG_CHECK_MODULES([check], [check >= 0.9.4], [], [AC_MSG_WARN([libcheck not found; unit tests will not be compilable])])
|
||||||
|
|
||||||
AC_ARG_WITH([libxml2],
|
AC_ARG_WITH([libxml2],
|
||||||
@@ -21,18 +30,35 @@ AC_ARG_WITH([libxml2],
|
|||||||
|
|
||||||
if test "x$with_libxml2" != xno; then
|
if test "x$with_libxml2" != xno; then
|
||||||
PKG_CHECK_MODULES([libxml2], [libxml-2.0 >= 2.7],
|
PKG_CHECK_MODULES([libxml2], [libxml-2.0 >= 2.7],
|
||||||
[with_libxml2=yes], [dummy=1])
|
[
|
||||||
if test "x$with_libxml2" != xyes; then
|
with_libxml2=yes
|
||||||
old_CFLAGS=$CFLAGS
|
PC_REQUIRES+=(libxml-2.0)
|
||||||
CFLAGS="-I${includedir}/libxml2"
|
],
|
||||||
AC_CHECK_HEADER([libxml/parser.h],
|
[
|
||||||
[with_libxml2=yes; libxml2_CFLAGS="-I${includedir}/libxml2"; libxml2_LIBS="-lxml2"],
|
old_CFLAGS=$CFLAGS
|
||||||
[AC_MSG_ERROR([libxml2 not found.])])
|
CFLAGS="-I${includedir}/libxml2"
|
||||||
CFLAGS=$old_CFLAGS
|
AC_CHECK_HEADER([libxml/parser.h],
|
||||||
fi
|
[
|
||||||
|
with_libxml2=yes
|
||||||
|
libxml2_CFLAGS="-I${includedir}/libxml2"
|
||||||
|
libxml2_LIBS="-lxml2"
|
||||||
|
PC_LIBS+=($libxml2_LIBS)
|
||||||
|
PC_CFLAGS+=($libxml2_CFLAGS)
|
||||||
|
],
|
||||||
|
[AC_MSG_ERROR([libxml2 not found.])])
|
||||||
|
CFLAGS=$old_CFLAGS
|
||||||
|
])
|
||||||
else
|
else
|
||||||
PKG_CHECK_MODULES([expat], [expat >= 2.0.0], [],
|
PKG_CHECK_MODULES([expat], [expat >= 2.0.0],
|
||||||
[AC_CHECK_HEADER(expat.h, [expat_LIBS="-lexpat"], [AC_MSG_ERROR([expat not found; expat required.])])])
|
[PC_REQUIRES+=(expat)],
|
||||||
|
[AC_CHECK_HEADER([expat.h],
|
||||||
|
[
|
||||||
|
expat_LIBS="-lexpat"
|
||||||
|
PC_LIBS+=($expat_LIBS)
|
||||||
|
],
|
||||||
|
[AC_MSG_ERROR([expat not found; expat required.])]
|
||||||
|
)
|
||||||
|
])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$with_libxml2" = xyes; then
|
if test "x$with_libxml2" = xyes; then
|
||||||
@@ -53,16 +79,30 @@ AC_SEARCH_LIBS([socket], [socket])
|
|||||||
if test "x$PLATFORM" != xfreebsd; then
|
if test "x$PLATFORM" != xfreebsd; then
|
||||||
AC_CHECK_LIB([resolv], [res_query], [],
|
AC_CHECK_LIB([resolv], [res_query], [],
|
||||||
[AC_CHECK_LIB([resolv], [__res_query], [],
|
[AC_CHECK_LIB([resolv], [__res_query], [],
|
||||||
[AC_MSG_ERROR([libresolv not found; libresolv required. ])])])
|
[AC_MSG_ERROR([libresolv not found; libresolv required.])])])
|
||||||
|
PC_LIBS+=(-lresolv)
|
||||||
else
|
else
|
||||||
AC_MSG_NOTICE([skipping libresolv checks for freebsd])
|
AC_MSG_NOTICE([skipping libresolv checks for freebsd])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_HEADERS([arpa/nameser_compat.h])
|
AC_CHECK_HEADERS([arpa/nameser_compat.h])
|
||||||
|
|
||||||
|
|
||||||
|
m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR],
|
||||||
|
[AC_ARG_WITH([pkgconfigdir],
|
||||||
|
[AS_HELP_STRING([--with-pkgconfigdir],
|
||||||
|
[install directory for libstrophe.pc pkg-config file])],
|
||||||
|
[],[with_pkgconfigdir='$(libdir)/pkgconfig'])
|
||||||
|
AC_SUBST([pkgconfigdir], [${with_pkgconfigdir}])])
|
||||||
|
|
||||||
AM_CONDITIONAL([PARSER_EXPAT], [test x$with_parser != xlibxml2])
|
AM_CONDITIONAL([PARSER_EXPAT], [test x$with_parser != xlibxml2])
|
||||||
|
|
||||||
|
AC_SUBST([PC_REQUIRES], [${PC_REQUIRES[[@]]}])
|
||||||
|
AC_SUBST([PC_CFLAGS], [${PC_CFLAGS[[@]]}])
|
||||||
|
AC_SUBST([PC_LIBS], [${PC_LIBS[[@]]}])
|
||||||
|
|
||||||
AC_SUBST(PARSER_NAME)
|
AC_SUBST(PARSER_NAME)
|
||||||
AC_SUBST(PARSER_CFLAGS)
|
AC_SUBST(PARSER_CFLAGS)
|
||||||
AC_SUBST(PARSER_LIBS)
|
AC_SUBST(PARSER_LIBS)
|
||||||
AC_CONFIG_FILES([Makefile])
|
AC_CONFIG_FILES([Makefile libstrophe.pc])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* This example demonstrates basic handler functions by printing out
|
/* This example demonstrates basic handler functions by printing out
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* simple bot example
|
/* simple bot example
|
||||||
|
|||||||
97
examples/component.c
Normal file
97
examples/component.c
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/* component.c
|
||||||
|
** libstrophe XMPP client library -- external component (XEP-0114) example
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This example demonstrates simple connection to a server
|
||||||
|
** as an external component. See XEP-0114 for more details.
|
||||||
|
** This program requires correctly configured server to run.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <strophe.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* define a handler for connection events */
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (status == XMPP_CONN_CONNECT) {
|
||||||
|
fprintf(stderr, "DEBUG: connected\n");
|
||||||
|
xmpp_disconnect(conn);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "DEBUG: disconnected\n");
|
||||||
|
xmpp_stop(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
xmpp_ctx_t *ctx;
|
||||||
|
xmpp_conn_t *conn;
|
||||||
|
xmpp_log_t *log;
|
||||||
|
char *jid, *pass, *host, *port_err = NULL;
|
||||||
|
unsigned short port = 0;
|
||||||
|
|
||||||
|
/* take a jid and password on the command line */
|
||||||
|
if (argc < 4 || argc > 5) {
|
||||||
|
fprintf(stderr, "Usage: component <jid> <pass> <host> [<port>]\n\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
jid = argv[1];
|
||||||
|
pass = argv[2];
|
||||||
|
host = argv[3];
|
||||||
|
|
||||||
|
if (argc == 5) {
|
||||||
|
short tmp_port = (short) strtol(argv[4], &port_err, 10);
|
||||||
|
if (tmp_port < 0 || *port_err != '\0') {
|
||||||
|
fprintf(stderr, "Invalid value of <port> [%s].\n", argv[4]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
port = (unsigned short) tmp_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* init library */
|
||||||
|
xmpp_initialize();
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
conn = xmpp_conn_new(ctx);
|
||||||
|
|
||||||
|
/* setup authentication information */
|
||||||
|
xmpp_conn_set_jid(conn, jid);
|
||||||
|
xmpp_conn_set_pass(conn, pass);
|
||||||
|
|
||||||
|
/* initiate connection */
|
||||||
|
xmpp_connect_component(conn, host, port, 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);
|
||||||
|
xmpp_ctx_free(ctx);
|
||||||
|
|
||||||
|
/* final shutdown of the library */
|
||||||
|
xmpp_shutdown();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* This example demonstrates basic handler functions by printing out
|
/* This example demonstrates basic handler functions by printing out
|
||||||
|
|||||||
14
libstrophe.pc.in
Normal file
14
libstrophe.pc.in
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
prefix=@prefix@
|
||||||
|
exec_prefix=@exec_prefix@
|
||||||
|
libdir=@libdir@
|
||||||
|
includedir=@includedir@
|
||||||
|
|
||||||
|
Name: libstrophe
|
||||||
|
Description: A simple, lightweight C library for writing XMPP clients
|
||||||
|
URL: http://strophe.im/libstrophe/
|
||||||
|
Version: @VERSION@
|
||||||
|
Requires:
|
||||||
|
Requires.private: @PC_REQUIRES@
|
||||||
|
Libs: -L${libdir} -lstrophe
|
||||||
|
Libs.private: @PC_LIBS@
|
||||||
|
Cflags: -I${includedir} @PC_CFLAGS@
|
||||||
@@ -8,12 +8,24 @@ License: MIT/GPLv3
|
|||||||
URL: http://strophe.im/libstrophe/
|
URL: http://strophe.im/libstrophe/
|
||||||
Source0: libstrophe_git.tar.gz
|
Source0: libstrophe_git.tar.gz
|
||||||
|
|
||||||
|
BuildRequires: automake
|
||||||
|
BuildRequires: libtool
|
||||||
|
BuildRequires: openssl-devel
|
||||||
BuildRequires: expat-devel
|
BuildRequires: expat-devel
|
||||||
Requires: expat
|
Requires: expat
|
||||||
|
|
||||||
%description
|
%description
|
||||||
XMPP library in C
|
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
|
%prep
|
||||||
%setup -n libstrophe
|
%setup -n libstrophe
|
||||||
./bootstrap.sh
|
./bootstrap.sh
|
||||||
@@ -25,8 +37,21 @@ make %{?_smp_mflags}
|
|||||||
%install
|
%install
|
||||||
make install DESTDIR=%{buildroot}
|
make install DESTDIR=%{buildroot}
|
||||||
|
|
||||||
|
%post -p /sbin/ldconfig
|
||||||
|
|
||||||
|
%postun -p /sbin/ldconfig
|
||||||
|
|
||||||
%files
|
%files
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%{_libdir}/libstrophe.so*
|
||||||
|
%doc
|
||||||
|
|
||||||
|
%files devel
|
||||||
|
%defattr(-,root,root,-)
|
||||||
%{_libdir}/libstrophe.a
|
%{_libdir}/libstrophe.a
|
||||||
|
%{_libdir}/libstrophe.la
|
||||||
|
%{_libdir}/pkgconfig/libstrophe.pc
|
||||||
%{_includedir}/strophe.h
|
%{_includedir}/strophe.h
|
||||||
|
%doc
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
|||||||
357
src/auth.c
357
src/auth.c
@@ -1,30 +1,29 @@
|
|||||||
/* auth.c
|
/* auth.c
|
||||||
** strophe XMPP client library -- auth functions and handlers
|
** strophe XMPP client library -- auth functions and handlers
|
||||||
**
|
**
|
||||||
** Copyright (C) 2005-2009 Collecta, Inc.
|
** Copyright (C) 2005-2009 Collecta, Inc.
|
||||||
**
|
**
|
||||||
** This software is provided AS-IS with no warranty, either express or
|
** This software is provided AS-IS with no warranty, either express or
|
||||||
** implied.
|
** implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
* Authentication function and handlers.
|
* Authentication function and handlers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "sasl.h"
|
#include "sasl.h"
|
||||||
|
#include "sha1.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _MSC_VER
|
||||||
#define strcasecmp stricmp
|
#define strcasecmp stricmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -54,10 +53,21 @@
|
|||||||
*/
|
*/
|
||||||
#define LEGACY_TIMEOUT 15000 /* 15 seconds */
|
#define LEGACY_TIMEOUT 15000 /* 15 seconds */
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef HANDSHAKE_TIMEOUT
|
||||||
|
/** @def HANDSHAKE_TIMEOUT
|
||||||
|
* Time to wait for component authentication to complete
|
||||||
|
*/
|
||||||
|
#define HANDSHAKE_TIMEOUT 15000 /* 15 seconds */
|
||||||
|
#endif
|
||||||
|
|
||||||
static void _auth(xmpp_conn_t * const conn);
|
static void _auth(xmpp_conn_t * const conn);
|
||||||
static void _handle_open_tls(xmpp_conn_t * const conn);
|
|
||||||
static void _handle_open_sasl(xmpp_conn_t * const conn);
|
static void _handle_open_sasl(xmpp_conn_t * const conn);
|
||||||
|
|
||||||
|
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_missing_legacy(xmpp_conn_t * const conn,
|
static int _handle_missing_legacy(xmpp_conn_t * const conn,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
static int _handle_legacy(xmpp_conn_t * const conn,
|
static int _handle_legacy(xmpp_conn_t * const conn,
|
||||||
@@ -75,6 +85,10 @@ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn,
|
|||||||
static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
|
static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
|
||||||
xmpp_stanza_t * const stanza,
|
xmpp_stanza_t * const stanza,
|
||||||
void * const userdata);
|
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 * const conn,
|
static int _handle_missing_features_sasl(xmpp_conn_t * const conn,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
@@ -88,6 +102,8 @@ static int _handle_session(xmpp_conn_t * const conn,
|
|||||||
void * const userdata);
|
void * const userdata);
|
||||||
static int _handle_missing_session(xmpp_conn_t * const conn,
|
static int _handle_missing_session(xmpp_conn_t * const conn,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
|
static int _handle_missing_handshake(xmpp_conn_t * const conn,
|
||||||
|
void * const userdata);
|
||||||
|
|
||||||
/* stream:error handler */
|
/* stream:error handler */
|
||||||
static int _handle_error(xmpp_conn_t * const conn,
|
static int _handle_error(xmpp_conn_t * const conn,
|
||||||
@@ -100,7 +116,7 @@ static int _handle_error(xmpp_conn_t * const conn,
|
|||||||
/* free old stream error if it's still there */
|
/* free old stream error if it's still there */
|
||||||
if (conn->stream_error) {
|
if (conn->stream_error) {
|
||||||
xmpp_stanza_release(conn->stream_error->stanza);
|
xmpp_stanza_release(conn->stream_error->stanza);
|
||||||
if (conn->stream_error->text)
|
if (conn->stream_error->text)
|
||||||
xmpp_free(conn->ctx, conn->stream_error->text);
|
xmpp_free(conn->ctx, conn->stream_error->text);
|
||||||
xmpp_free(conn->ctx, conn->stream_error);
|
xmpp_free(conn->ctx, conn->stream_error);
|
||||||
}
|
}
|
||||||
@@ -221,14 +237,16 @@ static int _handle_features(xmpp_conn_t * const conn,
|
|||||||
/* check for SASL */
|
/* check for SASL */
|
||||||
child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
|
child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
|
||||||
if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_SASL) == 0)) {
|
if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_SASL) == 0)) {
|
||||||
for (mech = xmpp_stanza_get_children(child); mech;
|
for (mech = xmpp_stanza_get_children(child); mech;
|
||||||
mech = xmpp_stanza_get_next(mech)) {
|
mech = xmpp_stanza_get_next(mech)) {
|
||||||
if (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);
|
text = xmpp_stanza_get_text(mech);
|
||||||
if (strcasecmp(text, "PLAIN") == 0)
|
if (strcasecmp(text, "PLAIN") == 0)
|
||||||
conn->sasl_support |= SASL_MASK_PLAIN;
|
conn->sasl_support |= SASL_MASK_PLAIN;
|
||||||
else if (strcasecmp(text, "DIGEST-MD5") == 0)
|
else if (strcasecmp(text, "DIGEST-MD5") == 0)
|
||||||
conn->sasl_support |= SASL_MASK_DIGESTMD5;
|
conn->sasl_support |= SASL_MASK_DIGESTMD5;
|
||||||
|
else if (strcasecmp(text, "SCRAM-SHA-1") == 0)
|
||||||
|
conn->sasl_support |= SASL_MASK_SCRAMSHA1;
|
||||||
else if (strcasecmp(text, "ANONYMOUS") == 0)
|
else if (strcasecmp(text, "ANONYMOUS") == 0)
|
||||||
conn->sasl_support |= SASL_MASK_ANONYMOUS;
|
conn->sasl_support |= SASL_MASK_ANONYMOUS;
|
||||||
|
|
||||||
@@ -238,7 +256,7 @@ static int _handle_features(xmpp_conn_t * const conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_auth(conn);
|
_auth(conn);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +281,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
|
|||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
name = xmpp_stanza_get_name(stanza);
|
name = xmpp_stanza_get_name(stanza);
|
||||||
xmpp_debug(conn->ctx, "xmpp",
|
xmpp_debug(conn->ctx, "xmpp",
|
||||||
"handle proceedtls called for %s", name);
|
"handle proceedtls called for %s", name);
|
||||||
|
|
||||||
if (strcmp(name, "proceed") == 0) {
|
if (strcmp(name, "proceed") == 0) {
|
||||||
@@ -277,7 +295,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
|
|||||||
tls_free(conn->tls);
|
tls_free(conn->tls);
|
||||||
conn->tls = NULL;
|
conn->tls = NULL;
|
||||||
conn->tls_failed = 1;
|
conn->tls_failed = 1;
|
||||||
|
|
||||||
/* failed tls spoils the connection, so disconnect */
|
/* failed tls spoils the connection, so disconnect */
|
||||||
xmpp_disconnect(conn);
|
xmpp_disconnect(conn);
|
||||||
}
|
}
|
||||||
@@ -303,14 +321,14 @@ static int _handle_sasl_result(xmpp_conn_t * const conn,
|
|||||||
|
|
||||||
/* the server should send a <success> or <failure> stanza */
|
/* the server should send a <success> or <failure> stanza */
|
||||||
if (strcmp(name, "failure") == 0) {
|
if (strcmp(name, "failure") == 0) {
|
||||||
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth failed",
|
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth failed",
|
||||||
(char *)userdata);
|
(char *)userdata);
|
||||||
|
|
||||||
/* fall back to next auth method */
|
/* fall back to next auth method */
|
||||||
_auth(conn);
|
_auth(conn);
|
||||||
} else if (strcmp(name, "success") == 0) {
|
} else if (strcmp(name, "success") == 0) {
|
||||||
/* SASL PLAIN auth successful, we need to restart the stream */
|
/* SASL PLAIN auth successful, we need to restart the stream */
|
||||||
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth successful",
|
xmpp_debug(conn->ctx, "xmpp", "SASL %s auth successful",
|
||||||
(char *)userdata);
|
(char *)userdata);
|
||||||
|
|
||||||
/* reset parser */
|
/* reset parser */
|
||||||
@@ -355,10 +373,10 @@ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn,
|
|||||||
if (!auth) {
|
if (!auth) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
xmpp_stanza_set_name(auth, "response");
|
xmpp_stanza_set_name(auth, "response");
|
||||||
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
||||||
|
|
||||||
authdata = xmpp_stanza_new(conn->ctx);
|
authdata = xmpp_stanza_new(conn->ctx);
|
||||||
if (!authdata) {
|
if (!authdata) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
@@ -371,7 +389,7 @@ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn,
|
|||||||
xmpp_stanza_add_child(auth, authdata);
|
xmpp_stanza_add_child(auth, authdata);
|
||||||
xmpp_stanza_release(authdata);
|
xmpp_stanza_release(authdata);
|
||||||
|
|
||||||
handler_add(conn, _handle_digestmd5_rspauth,
|
handler_add(conn, _handle_digestmd5_rspauth,
|
||||||
XMPP_NS_SASL, NULL, NULL, NULL);
|
XMPP_NS_SASL, NULL, NULL, NULL);
|
||||||
|
|
||||||
xmpp_send(conn, auth);
|
xmpp_send(conn, auth);
|
||||||
@@ -404,7 +422,7 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
|
|||||||
if (!auth) {
|
if (!auth) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
xmpp_stanza_set_name(auth, "response");
|
xmpp_stanza_set_name(auth, "response");
|
||||||
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
||||||
xmpp_send(conn, auth);
|
xmpp_send(conn, auth);
|
||||||
@@ -416,6 +434,117 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* handle the challenge phase of SCRAM-SHA-1 auth */
|
||||||
|
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, *authdata;
|
||||||
|
char *name;
|
||||||
|
char *challenge;
|
||||||
|
char *scram_init = (char *)userdata;
|
||||||
|
|
||||||
|
name = xmpp_stanza_get_name(stanza);
|
||||||
|
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);
|
||||||
|
if (!text)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
challenge = (char *)base64_decode(conn->ctx, text, strlen(text));
|
||||||
|
xmpp_free(conn->ctx, text);
|
||||||
|
if (!challenge)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
response = sasl_scram_sha1(conn->ctx, challenge, scram_init,
|
||||||
|
conn->jid, conn->pass);
|
||||||
|
xmpp_free(conn->ctx, challenge);
|
||||||
|
if (!response)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
auth = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!auth)
|
||||||
|
goto err_free_response;
|
||||||
|
xmpp_stanza_set_name(auth, "response");
|
||||||
|
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
||||||
|
|
||||||
|
authdata = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!authdata)
|
||||||
|
goto err_release_auth;
|
||||||
|
xmpp_stanza_set_text(authdata, response);
|
||||||
|
xmpp_free(conn->ctx, response);
|
||||||
|
|
||||||
|
xmpp_stanza_add_child(auth, authdata);
|
||||||
|
xmpp_stanza_release(authdata);
|
||||||
|
|
||||||
|
xmpp_send(conn, auth);
|
||||||
|
xmpp_stanza_release(auth);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
xmpp_free(conn->ctx, scram_init);
|
||||||
|
return _handle_sasl_result(conn, stanza, "SCRAM-SHA-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
err_release_auth:
|
||||||
|
xmpp_stanza_release(auth);
|
||||||
|
err_free_response:
|
||||||
|
xmpp_free(conn->ctx, response);
|
||||||
|
err:
|
||||||
|
xmpp_free(conn->ctx, scram_init);
|
||||||
|
disconnect_mem_error(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *_get_nonce(xmpp_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
unsigned char buffer[sizeof(clock_t) + sizeof(time_t)] = {0};
|
||||||
|
clock_t ticks = clock();
|
||||||
|
time_t t;
|
||||||
|
|
||||||
|
if (ticks != (clock_t)-1) {
|
||||||
|
*(clock_t *)buffer = ticks;
|
||||||
|
}
|
||||||
|
t = time((time_t *)(buffer + sizeof(clock_t)));
|
||||||
|
if (t == (time_t)-1) {
|
||||||
|
*(time_t *)(buffer + sizeof(clock_t)) = (time_t)rand();
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64_encode(ctx, buffer, sizeof(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *_make_scram_sha1_init_msg(xmpp_conn_t * const conn)
|
||||||
|
{
|
||||||
|
size_t message_len;
|
||||||
|
char *node;
|
||||||
|
char *message;
|
||||||
|
char *nonce;
|
||||||
|
|
||||||
|
node = xmpp_jid_node(conn->ctx, conn->jid);
|
||||||
|
if (!node) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nonce = _get_nonce(conn->ctx);
|
||||||
|
if (!nonce) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
message_len = strlen(node) + strlen(nonce) + 8 + 1;
|
||||||
|
message = xmpp_alloc(conn->ctx, message_len);
|
||||||
|
if (message) {
|
||||||
|
xmpp_snprintf(message, message_len, "n,,n=%s,r=%s", node, nonce);
|
||||||
|
xmpp_free(conn->ctx, node);
|
||||||
|
}
|
||||||
|
xmpp_free(conn->ctx, nonce);
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
static xmpp_stanza_t *_make_starttls(xmpp_conn_t * const conn)
|
static xmpp_stanza_t *_make_starttls(xmpp_conn_t * const conn)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *starttls;
|
xmpp_stanza_t *starttls;
|
||||||
@@ -426,7 +555,7 @@ static xmpp_stanza_t *_make_starttls(xmpp_conn_t * const conn)
|
|||||||
xmpp_stanza_set_name(starttls, "starttls");
|
xmpp_stanza_set_name(starttls, "starttls");
|
||||||
xmpp_stanza_set_ns(starttls, XMPP_NS_TLS);
|
xmpp_stanza_set_ns(starttls, XMPP_NS_TLS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return starttls;
|
return starttls;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,19 +571,20 @@ static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t * const conn,
|
|||||||
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
|
||||||
xmpp_stanza_set_attribute(auth, "mechanism", mechanism);
|
xmpp_stanza_set_attribute(auth, "mechanism", mechanism);
|
||||||
}
|
}
|
||||||
|
|
||||||
return auth;
|
return auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* authenticate the connection
|
/* authenticate the connection
|
||||||
* this may get called multiple times. if any auth method fails,
|
* this may get called multiple times. if any auth method fails,
|
||||||
* this will get called again until one auth method succeeds or every
|
* this will get called again until one auth method succeeds or every
|
||||||
* method fails
|
* method fails
|
||||||
*/
|
*/
|
||||||
static void _auth(xmpp_conn_t * const conn)
|
static void _auth(xmpp_conn_t * const conn)
|
||||||
{
|
{
|
||||||
xmpp_stanza_t *auth, *authdata, *query, *child, *iq;
|
xmpp_stanza_t *auth, *authdata, *query, *child, *iq;
|
||||||
char *str, *authid;
|
char *str, *authid;
|
||||||
|
char *scram_init;
|
||||||
int anonjid;
|
int anonjid;
|
||||||
|
|
||||||
/* if there is no node in conn->jid, we assume anonymous connect */
|
/* if there is no node in conn->jid, we assume anonymous connect */
|
||||||
@@ -489,7 +619,7 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler_add(conn, _handle_proceedtls_default,
|
handler_add(conn, _handle_proceedtls_default,
|
||||||
XMPP_NS_TLS, NULL, NULL, NULL);
|
XMPP_NS_TLS, NULL, NULL, NULL);
|
||||||
|
|
||||||
xmpp_send(conn, auth);
|
xmpp_send(conn, auth);
|
||||||
@@ -514,9 +644,54 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
/* SASL ANONYMOUS was tried, unset flag */
|
/* SASL ANONYMOUS was tried, unset flag */
|
||||||
conn->sasl_support &= ~SASL_MASK_ANONYMOUS;
|
conn->sasl_support &= ~SASL_MASK_ANONYMOUS;
|
||||||
} else if (anonjid) {
|
} else if (anonjid) {
|
||||||
xmpp_error(conn->ctx, "auth",
|
xmpp_error(conn->ctx, "auth",
|
||||||
"No node in JID, and SASL ANONYMOUS unsupported.");
|
"No node in JID, and SASL ANONYMOUS unsupported.");
|
||||||
xmpp_disconnect(conn);
|
xmpp_disconnect(conn);
|
||||||
|
} 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_init = _make_scram_sha1_init_msg(conn);
|
||||||
|
if (!scram_init) {
|
||||||
|
xmpp_stanza_release(auth);
|
||||||
|
disconnect_mem_error(conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = (char *)base64_encode(conn->ctx, (unsigned char *)scram_init,
|
||||||
|
strlen(scram_init));
|
||||||
|
if (!str) {
|
||||||
|
xmpp_free(conn->ctx, scram_init);
|
||||||
|
xmpp_stanza_release(auth);
|
||||||
|
disconnect_mem_error(conn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
authdata = xmpp_stanza_new(conn->ctx);
|
||||||
|
if (!authdata) {
|
||||||
|
xmpp_free(conn->ctx, str);
|
||||||
|
xmpp_free(conn->ctx, scram_init);
|
||||||
|
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_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 &= ~SASL_MASK_SCRAMSHA1;
|
||||||
} else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
|
} else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
|
||||||
auth = _make_sasl_auth(conn, "DIGEST-MD5");
|
auth = _make_sasl_auth(conn, "DIGEST-MD5");
|
||||||
if (!auth) {
|
if (!auth) {
|
||||||
@@ -525,7 +700,7 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handler_add(conn, _handle_digestmd5_challenge,
|
handler_add(conn, _handle_digestmd5_challenge,
|
||||||
XMPP_NS_SASL, NULL, NULL, NULL);
|
XMPP_NS_SASL, NULL, NULL, NULL);
|
||||||
|
|
||||||
xmpp_send(conn, auth);
|
xmpp_send(conn, auth);
|
||||||
@@ -543,7 +718,7 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
if (!authdata) {
|
if (!authdata) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
authid = _get_authid(conn);
|
authid = _get_authid(conn);
|
||||||
if (!authid) {
|
if (!authid) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
@@ -556,6 +731,7 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
}
|
}
|
||||||
xmpp_stanza_set_text(authdata, str);
|
xmpp_stanza_set_text(authdata, str);
|
||||||
xmpp_free(conn->ctx, str);
|
xmpp_free(conn->ctx, str);
|
||||||
|
xmpp_free(conn->ctx, authid);
|
||||||
|
|
||||||
xmpp_stanza_add_child(auth, authdata);
|
xmpp_stanza_add_child(auth, authdata);
|
||||||
xmpp_stanza_release(authdata);
|
xmpp_stanza_release(authdata);
|
||||||
@@ -570,7 +746,7 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
conn->sasl_support &= ~SASL_MASK_PLAIN;
|
conn->sasl_support &= ~SASL_MASK_PLAIN;
|
||||||
} else if (conn->type == XMPP_CLIENT) {
|
} else if (conn->type == XMPP_CLIENT) {
|
||||||
/* legacy client authentication */
|
/* legacy client authentication */
|
||||||
|
|
||||||
iq = xmpp_stanza_new(conn->ctx);
|
iq = xmpp_stanza_new(conn->ctx);
|
||||||
if (!iq) {
|
if (!iq) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
@@ -656,7 +832,7 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
} else {
|
} else {
|
||||||
xmpp_stanza_release(authdata);
|
xmpp_stanza_release(authdata);
|
||||||
xmpp_stanza_release(iq);
|
xmpp_stanza_release(iq);
|
||||||
xmpp_error(conn->ctx, "auth",
|
xmpp_error(conn->ctx, "auth",
|
||||||
"Cannot authenticate without resource");
|
"Cannot authenticate without resource");
|
||||||
xmpp_disconnect(conn);
|
xmpp_disconnect(conn);
|
||||||
return;
|
return;
|
||||||
@@ -665,7 +841,7 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
xmpp_stanza_release(authdata);
|
xmpp_stanza_release(authdata);
|
||||||
|
|
||||||
handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL);
|
handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL);
|
||||||
handler_add_timed(conn, _handle_missing_legacy,
|
handler_add_timed(conn, _handle_missing_legacy,
|
||||||
LEGACY_TIMEOUT, NULL);
|
LEGACY_TIMEOUT, NULL);
|
||||||
|
|
||||||
xmpp_send(conn, iq);
|
xmpp_send(conn, iq);
|
||||||
@@ -677,7 +853,7 @@ static void _auth(xmpp_conn_t * const conn)
|
|||||||
/** Set up handlers at stream start.
|
/** Set up handlers at stream start.
|
||||||
* This function is called internally to Strophe for handling the opening
|
* 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
|
* of an XMPP stream. It's called by the parser when a stream is opened
|
||||||
* or reset, and adds the initial handlers for <stream:error/> and
|
* or reset, and adds the initial handlers for <stream:error/> and
|
||||||
* <stream:features/>. This function is not intended for use outside
|
* <stream:features/>. This function is not intended for use outside
|
||||||
* of Strophe.
|
* of Strophe.
|
||||||
*
|
*
|
||||||
@@ -690,11 +866,11 @@ void auth_handle_open(xmpp_conn_t * const conn)
|
|||||||
|
|
||||||
/* setup handler for stream:error */
|
/* setup handler for stream:error */
|
||||||
handler_add(conn, _handle_error,
|
handler_add(conn, _handle_error,
|
||||||
NULL, "stream:error", NULL, NULL);
|
XMPP_NS_STREAMS, "error", NULL, NULL);
|
||||||
|
|
||||||
/* setup handlers for incoming <stream:features> */
|
/* setup handlers for incoming <stream:features> */
|
||||||
handler_add(conn, _handle_features,
|
handler_add(conn, _handle_features,
|
||||||
NULL, "stream:features", NULL, NULL);
|
XMPP_NS_STREAMS, "features", NULL, NULL);
|
||||||
handler_add_timed(conn, _handle_missing_features,
|
handler_add_timed(conn, _handle_missing_features,
|
||||||
FEATURES_TIMEOUT, NULL);
|
FEATURES_TIMEOUT, NULL);
|
||||||
}
|
}
|
||||||
@@ -706,7 +882,7 @@ static void _handle_open_sasl(xmpp_conn_t * const conn)
|
|||||||
|
|
||||||
/* setup stream:features handlers */
|
/* setup stream:features handlers */
|
||||||
handler_add(conn, _handle_features_sasl,
|
handler_add(conn, _handle_features_sasl,
|
||||||
NULL, "stream:features", NULL, NULL);
|
XMPP_NS_STREAMS, "features", NULL, NULL);
|
||||||
handler_add_timed(conn, _handle_missing_features_sasl,
|
handler_add_timed(conn, _handle_missing_features_sasl,
|
||||||
FEATURES_TIMEOUT, NULL);
|
FEATURES_TIMEOUT, NULL);
|
||||||
}
|
}
|
||||||
@@ -739,7 +915,7 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
|
|||||||
/* if bind is required, go ahead and start it */
|
/* if bind is required, go ahead and start it */
|
||||||
if (conn->bind_required) {
|
if (conn->bind_required) {
|
||||||
/* bind resource */
|
/* bind resource */
|
||||||
|
|
||||||
/* setup response handlers */
|
/* setup response handlers */
|
||||||
handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL);
|
handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL);
|
||||||
handler_add_timed(conn, _handle_missing_bind,
|
handler_add_timed(conn, _handle_missing_bind,
|
||||||
@@ -771,7 +947,7 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
|
|||||||
resource = NULL;
|
resource = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we have a resource to request, do it. otherwise the
|
/* if we have a resource to request, do it. otherwise the
|
||||||
server will assign us one */
|
server will assign us one */
|
||||||
if (resource) {
|
if (resource) {
|
||||||
res = xmpp_stanza_new(conn->ctx);
|
res = xmpp_stanza_new(conn->ctx);
|
||||||
@@ -822,7 +998,7 @@ static int _handle_missing_features_sasl(xmpp_conn_t * const conn,
|
|||||||
xmpp_disconnect(conn);
|
xmpp_disconnect(conn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _handle_bind(xmpp_conn_t * const conn,
|
static int _handle_bind(xmpp_conn_t * const conn,
|
||||||
xmpp_stanza_t * const stanza,
|
xmpp_stanza_t * const stanza,
|
||||||
void * const userdata)
|
void * const userdata)
|
||||||
@@ -854,7 +1030,7 @@ static int _handle_bind(xmpp_conn_t * const conn,
|
|||||||
if (conn->session_required) {
|
if (conn->session_required) {
|
||||||
/* setup response handlers */
|
/* setup response handlers */
|
||||||
handler_add_id(conn, _handle_session, "_xmpp_session1", NULL);
|
handler_add_id(conn, _handle_session, "_xmpp_session1", NULL);
|
||||||
handler_add_timed(conn, _handle_missing_session,
|
handler_add_timed(conn, _handle_missing_session,
|
||||||
SESSION_TIMEOUT, NULL);
|
SESSION_TIMEOUT, NULL);
|
||||||
|
|
||||||
/* send session request */
|
/* send session request */
|
||||||
@@ -885,9 +1061,9 @@ static int _handle_bind(xmpp_conn_t * const conn,
|
|||||||
xmpp_stanza_release(iq);
|
xmpp_stanza_release(iq);
|
||||||
} else {
|
} else {
|
||||||
conn->authenticated = 1;
|
conn->authenticated = 1;
|
||||||
|
|
||||||
/* call connection handler */
|
/* call connection handler */
|
||||||
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL,
|
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL,
|
||||||
conn->userdata);
|
conn->userdata);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -924,7 +1100,7 @@ static int _handle_session(xmpp_conn_t * const conn,
|
|||||||
xmpp_debug(conn->ctx, "xmpp", "Session establishment successful.");
|
xmpp_debug(conn->ctx, "xmpp", "Session establishment successful.");
|
||||||
|
|
||||||
conn->authenticated = 1;
|
conn->authenticated = 1;
|
||||||
|
|
||||||
/* call connection handler */
|
/* call connection handler */
|
||||||
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
|
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
|
||||||
} else {
|
} else {
|
||||||
@@ -987,3 +1163,96 @@ static int _handle_missing_legacy(xmpp_conn_t * const conn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void auth_handle_component_open(xmpp_conn_t * const conn)
|
||||||
|
{
|
||||||
|
/* reset all timed handlers */
|
||||||
|
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_timed(conn, _handle_missing_handshake, HANDSHAKE_TIMEOUT, NULL);
|
||||||
|
|
||||||
|
_handle_component_auth(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Will compute SHA1 and authenticate the component to the server */
|
||||||
|
int _handle_component_auth(xmpp_conn_t * const conn)
|
||||||
|
{
|
||||||
|
uint8_t md_value[SHA1_DIGEST_SIZE];
|
||||||
|
SHA1_CTX mdctx;
|
||||||
|
char *digest;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
/* Feed the session id and passphrase to the algorithm.
|
||||||
|
* We need to compute SHA1(session_id + passphrase)
|
||||||
|
*/
|
||||||
|
SHA1_Init(&mdctx);
|
||||||
|
SHA1_Update(&mdctx, (uint8_t*)conn->stream_id, strlen(conn->stream_id));
|
||||||
|
SHA1_Update(&mdctx, (uint8_t*)conn->pass, strlen(conn->pass));
|
||||||
|
SHA1_Final(&mdctx, md_value);
|
||||||
|
|
||||||
|
digest = xmpp_alloc(conn->ctx, 2*sizeof(md_value)+1);
|
||||||
|
if (digest) {
|
||||||
|
/* convert the digest into string representation */
|
||||||
|
for (i = 0; i < sizeof(md_value); i++)
|
||||||
|
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));
|
||||||
|
|
||||||
|
/* 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_free(conn->ctx, digest);
|
||||||
|
} else {
|
||||||
|
xmpp_debug(conn->ctx, "auth", "Couldn't allocate memory for component "\
|
||||||
|
"handshake digest.");
|
||||||
|
xmpp_disconnect(conn);
|
||||||
|
return XMPP_EMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the received stanza is <handshake/> and set auth to true
|
||||||
|
* and fire connection handler.
|
||||||
|
*/
|
||||||
|
int _handle_component_hs_response(xmpp_conn_t * const conn,
|
||||||
|
xmpp_stanza_t * const stanza,
|
||||||
|
void * const userdata)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
xmpp_timed_handler_delete(conn, _handle_missing_handshake);
|
||||||
|
|
||||||
|
name = xmpp_stanza_get_name(stanza);
|
||||||
|
if (strcmp(name, "handshake") != 0) {
|
||||||
|
char *msg;
|
||||||
|
size_t msg_size;
|
||||||
|
xmpp_stanza_to_text(stanza, &msg, &msg_size);
|
||||||
|
if (msg) {
|
||||||
|
xmpp_debug(conn->ctx, "auth", "Handshake failed: %s", msg);
|
||||||
|
xmpp_free(conn->ctx, msg);
|
||||||
|
}
|
||||||
|
xmpp_disconnect(conn);
|
||||||
|
return XMPP_EINT;
|
||||||
|
} else {
|
||||||
|
conn->authenticated = 1;
|
||||||
|
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We don't need this handler anymore, return 0 so it can be deleted
|
||||||
|
* from the list of handlers.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _handle_missing_handshake(xmpp_conn_t * const conn, void * const userdata)
|
||||||
|
{
|
||||||
|
xmpp_error(conn->ctx, "xmpp", "Server did not reply to handshake request.");
|
||||||
|
xmpp_disconnect(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
11
src/common.h
11
src/common.h
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express or
|
** This software is provided AS-IS with no warranty, either express or
|
||||||
** implied.
|
** implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -21,12 +18,10 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#ifndef _WIN32
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
|
#include "ostypes.h"
|
||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
@@ -147,6 +142,7 @@ struct _xmpp_handlist_t {
|
|||||||
#define SASL_MASK_PLAIN 0x01
|
#define SASL_MASK_PLAIN 0x01
|
||||||
#define SASL_MASK_DIGESTMD5 0x02
|
#define SASL_MASK_DIGESTMD5 0x02
|
||||||
#define SASL_MASK_ANONYMOUS 0x04
|
#define SASL_MASK_ANONYMOUS 0x04
|
||||||
|
#define SASL_MASK_SCRAMSHA1 0x08
|
||||||
|
|
||||||
typedef void (*xmpp_open_handler)(xmpp_conn_t * const conn);
|
typedef void (*xmpp_open_handler)(xmpp_conn_t * const conn);
|
||||||
|
|
||||||
@@ -268,6 +264,7 @@ void disconnect_mem_error(xmpp_conn_t * const conn);
|
|||||||
|
|
||||||
/* auth functions */
|
/* auth functions */
|
||||||
void auth_handle_open(xmpp_conn_t * const conn);
|
void auth_handle_open(xmpp_conn_t * const conn);
|
||||||
|
void auth_handle_component_open(xmpp_conn_t * const conn);
|
||||||
|
|
||||||
/* replacement snprintf and vsnprintf */
|
/* replacement snprintf and vsnprintf */
|
||||||
int xmpp_snprintf (char *str, size_t count, const char *fmt, ...);
|
int xmpp_snprintf (char *str, size_t count, const char *fmt, ...);
|
||||||
|
|||||||
84
src/conn.c
84
src/conn.c
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -270,7 +267,7 @@ int xmpp_conn_release(xmpp_conn_t * const conn)
|
|||||||
|
|
||||||
if (conn->domain) xmpp_free(ctx, conn->domain);
|
if (conn->domain) xmpp_free(ctx, conn->domain);
|
||||||
if (conn->jid) xmpp_free(ctx, conn->jid);
|
if (conn->jid) xmpp_free(ctx, conn->jid);
|
||||||
if (conn->bound_jid) xmpp_free(ctx, conn->bound_jid);
|
if (conn->bound_jid) xmpp_free(ctx, conn->bound_jid);
|
||||||
if (conn->pass) xmpp_free(ctx, conn->pass);
|
if (conn->pass) xmpp_free(ctx, conn->pass);
|
||||||
if (conn->stream_id) xmpp_free(ctx, conn->stream_id);
|
if (conn->stream_id) xmpp_free(ctx, conn->stream_id);
|
||||||
if (conn->lang) xmpp_free(ctx, conn->lang);
|
if (conn->lang) xmpp_free(ctx, conn->lang);
|
||||||
@@ -442,6 +439,73 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Initiate a component connection to server.
|
||||||
|
* This function returns immediately after starting the connection
|
||||||
|
* process to the XMPP server, and notifiations of connection state changes
|
||||||
|
* will be sent to the internal callback function that will set up handler
|
||||||
|
* for the component handshake as defined in XEP-0114.
|
||||||
|
* The domain and port to connect to must be provided in this case as the JID
|
||||||
|
* provided to the call serves as component identifier to the server and is
|
||||||
|
* not subject to DNS resolution.
|
||||||
|
*
|
||||||
|
* @param conn a Strophe connection object
|
||||||
|
* @param server a string with domain to use directly as the domain can't be
|
||||||
|
* extracted from the component name/JID. If this is not set, the call
|
||||||
|
* will fail.
|
||||||
|
* @param port an integer port number to use to connect to server expecting
|
||||||
|
* an external component. If this is 0, the port 5347 will be assumed.
|
||||||
|
* @param callback a xmpp_conn_handler callback function that will receive
|
||||||
|
* notifications of connection status
|
||||||
|
* @param userdata an opaque data pointer that will be passed to the callback
|
||||||
|
*
|
||||||
|
* @return 0 on success and -1 on an error
|
||||||
|
*
|
||||||
|
* @ingroup Connections
|
||||||
|
*/
|
||||||
|
int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
|
||||||
|
unsigned short port, xmpp_conn_handler callback,
|
||||||
|
void * const userdata)
|
||||||
|
{
|
||||||
|
int connectport;
|
||||||
|
|
||||||
|
conn->type = XMPP_COMPONENT;
|
||||||
|
/* JID serves as an identificator here and will be used as "to" attribute
|
||||||
|
of the stream */
|
||||||
|
conn->domain = xmpp_strdup(conn->ctx, conn->jid);
|
||||||
|
|
||||||
|
/* The server domain, jid and password MUST be specified. */
|
||||||
|
if (!(server && conn->jid && conn->pass)) return -1;
|
||||||
|
|
||||||
|
|
||||||
|
connectport = port ? port : 5347;
|
||||||
|
|
||||||
|
xmpp_debug(conn->ctx, "xmpp", "Connecting via %s", server);
|
||||||
|
conn->sock = sock_connect(server, connectport);
|
||||||
|
xmpp_debug(conn->ctx, "xmpp", "sock_connect to %s:%d returned %d",
|
||||||
|
server, connectport, conn->sock);
|
||||||
|
if (conn->sock == -1) return -1;
|
||||||
|
|
||||||
|
/* XEP-0114 does not support TLS */
|
||||||
|
conn->tls_disabled = 1;
|
||||||
|
|
||||||
|
/* setup handler */
|
||||||
|
conn->conn_handler = callback;
|
||||||
|
conn->userdata = userdata;
|
||||||
|
|
||||||
|
conn_prepare_reset(conn, auth_handle_component_open);
|
||||||
|
|
||||||
|
/* FIXME: it could happen that the connect returns immediately as
|
||||||
|
* successful, though this is pretty unlikely. This would be a little
|
||||||
|
* hard to fix, since we'd have to detect and fire off the callback
|
||||||
|
* from within the event loop */
|
||||||
|
|
||||||
|
conn->state = XMPP_STATE_CONNECTING;
|
||||||
|
conn->timeout_stamp = time_stamp();
|
||||||
|
xmpp_debug(conn->ctx, "xmpp", "attempting to connect to %s", server);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Cleanly disconnect the connection.
|
/** Cleanly disconnect the connection.
|
||||||
* This function is only called by the stream parser when </stream:stream>
|
* This function is only called by the stream parser when </stream:stream>
|
||||||
* is received, and it not intended to be called by code outside of Strophe.
|
* is received, and it not intended to be called by code outside of Strophe.
|
||||||
@@ -684,6 +748,7 @@ static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
|
|||||||
size_t pos;
|
size_t pos;
|
||||||
int len;
|
int len;
|
||||||
int i;
|
int i;
|
||||||
|
char *attr;
|
||||||
|
|
||||||
if (!attrs) return;
|
if (!attrs) return;
|
||||||
|
|
||||||
@@ -692,10 +757,11 @@ static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
|
|||||||
if (len < 0) return;
|
if (len < 0) return;
|
||||||
|
|
||||||
pos += len;
|
pos += len;
|
||||||
|
|
||||||
for (i = 0; attrs[i]; i += 2) {
|
for (i = 0; attrs[i]; i += 2) {
|
||||||
|
attr = parser_attr_name(conn->ctx, attrs[i]);
|
||||||
len = xmpp_snprintf(&buf[pos], 4096 - pos, " %s='%s'",
|
len = xmpp_snprintf(&buf[pos], 4096 - pos, " %s='%s'",
|
||||||
attrs[i], attrs[i+1]);
|
attr, attrs[i+1]);
|
||||||
|
xmpp_free(conn->ctx, attr);
|
||||||
if (len < 0) return;
|
if (len < 0) return;
|
||||||
pos += len;
|
pos += len;
|
||||||
}
|
}
|
||||||
@@ -725,7 +791,7 @@ static void _handle_stream_start(char *name, char **attrs,
|
|||||||
xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
|
xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
|
||||||
char *id;
|
char *id;
|
||||||
|
|
||||||
if (strcmp(name, "stream:stream") != 0) {
|
if (strcmp(name, "stream")) {
|
||||||
printf("name = %s\n", name);
|
printf("name = %s\n", name);
|
||||||
xmpp_error(conn->ctx, "conn", "Server did not open valid stream.");
|
xmpp_error(conn->ctx, "conn", "Server did not open valid stream.");
|
||||||
conn_disconnect(conn);
|
conn_disconnect(conn);
|
||||||
@@ -743,7 +809,7 @@ static void _handle_stream_start(char *name, char **attrs,
|
|||||||
conn_disconnect(conn);
|
conn_disconnect(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call stream open handler */
|
/* call stream open handler */
|
||||||
conn->open_handler(conn);
|
conn->open_handler(conn);
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/ctx.c
20
src/ctx.c
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -252,29 +249,34 @@ void xmpp_log(const xmpp_ctx_t * const ctx,
|
|||||||
char *buf;
|
char *buf;
|
||||||
va_list copy;
|
va_list copy;
|
||||||
|
|
||||||
buf = smbuf;
|
|
||||||
va_copy(copy, ap);
|
va_copy(copy, ap);
|
||||||
ret = xmpp_vsnprintf(buf, 1023, fmt, ap);
|
ret = xmpp_vsnprintf(smbuf, sizeof(smbuf), fmt, ap);
|
||||||
if (ret > 1023) {
|
if (ret >= (int)sizeof(smbuf)) {
|
||||||
buf = (char *)xmpp_alloc(ctx, ret + 1);
|
buf = (char *)xmpp_alloc(ctx, ret + 1);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
xmpp_error(ctx, "log", "Failed allocating memory for log message.");
|
xmpp_error(ctx, "log", "Failed allocating memory for log message.");
|
||||||
va_end(copy);
|
va_end(copy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
oldret = ret;
|
oldret = ret;
|
||||||
ret = xmpp_vsnprintf(buf, ret + 1, fmt, copy);
|
ret = xmpp_vsnprintf(buf, ret + 1, fmt, copy);
|
||||||
if (ret > oldret) {
|
if (ret > oldret) {
|
||||||
xmpp_error(ctx, "log", "Unexpected error");
|
xmpp_error(ctx, "log", "Unexpected error");
|
||||||
|
xmpp_free(ctx, buf);
|
||||||
|
va_end(copy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
va_end(copy);
|
buf = smbuf;
|
||||||
}
|
}
|
||||||
|
va_end(copy);
|
||||||
|
|
||||||
if (ctx->log->handler)
|
if (ctx->log->handler)
|
||||||
ctx->log->handler(ctx->log->userdata, level, area, buf);
|
ctx->log->handler(ctx->log->userdata, level, area, buf);
|
||||||
|
|
||||||
|
if (buf != smbuf)
|
||||||
|
xmpp_free(ctx, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Write to the log at the ERROR level.
|
/** Write to the log at the ERROR level.
|
||||||
|
|||||||
19
src/event.c
19
src/event.c
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -40,11 +37,14 @@
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#define _sleep(x) usleep(x*1000)
|
||||||
#else
|
#else
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#define ETIMEDOUT WSAETIMEDOUT
|
#define ETIMEDOUT WSAETIMEDOUT
|
||||||
#define ECONNRESET WSAECONNRESET
|
#define ECONNRESET WSAECONNRESET
|
||||||
#define ECONNABORTED WSAECONNABORTED
|
#define ECONNABORTED WSAECONNABORTED
|
||||||
|
#define _sleep(x) Sleep(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <strophe.h>
|
#include <strophe.h>
|
||||||
@@ -221,13 +221,20 @@ void xmpp_run_once(xmpp_ctx_t *ctx, const unsigned long timeout)
|
|||||||
tls_read_bytes += tls_pending(conn->tls);
|
tls_read_bytes += tls_pending(conn->tls);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->sock > max) max = conn->sock;
|
if (conn->state != XMPP_STATE_DISCONNECTED && conn->sock > max)
|
||||||
|
max = conn->sock;
|
||||||
|
|
||||||
connitem = connitem->next;
|
connitem = connitem->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for events */
|
/* check for events */
|
||||||
ret = select(max + 1, &rfds, &wfds, NULL, &tv);
|
if (max > 0)
|
||||||
|
ret = select(max + 1, &rfds, &wfds, NULL, &tv);
|
||||||
|
else {
|
||||||
|
if (timeout > 0)
|
||||||
|
_sleep(timeout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* select errored */
|
/* select errored */
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -23,14 +20,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <stdint.h>
|
|
||||||
#else
|
|
||||||
#include "ostypes.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "ostypes.h"
|
||||||
|
|
||||||
/** Fire off all stanza handlers that match.
|
/** Fire off all stanza handlers that match.
|
||||||
* This function is called internally by the event loop whenever stanzas
|
* This function is called internally by the event loop whenever stanzas
|
||||||
|
|||||||
10
src/hash.c
10
src/hash.c
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -250,12 +247,13 @@ const char * hash_iter_next(hash_iterator_t *iter)
|
|||||||
{
|
{
|
||||||
hash_t *table = iter->table;
|
hash_t *table = iter->table;
|
||||||
hashentry_t *entry = iter->entry;
|
hashentry_t *entry = iter->entry;
|
||||||
int i = iter->index + 1;
|
int i;
|
||||||
|
|
||||||
/* advance until we find the next entry */
|
/* advance until we find the next entry */
|
||||||
if (entry != NULL) entry = entry->next;
|
if (entry != NULL) entry = entry->next;
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
/* we're off the end of list, search for a new entry */
|
/* we're off the end of list, search for a new entry */
|
||||||
|
i = iter->index + 1;
|
||||||
while (i < iter->table->length) {
|
while (i < iter->table->length) {
|
||||||
entry = table->entries[i];
|
entry = table->entries[i];
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
@@ -266,7 +264,7 @@ const char * hash_iter_next(hash_iterator_t *iter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((entry == NULL) || (i >= table->length)) {
|
if (entry == NULL) {
|
||||||
/* no more keys! */
|
/* no more keys! */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
@@ -43,6 +43,9 @@
|
|||||||
(cp)[3] = ((value) >> 24) & 0xFF; \
|
(cp)[3] = ((value) >> 24) & 0xFF; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
static void MD5Transform(uint32_t buf[4], const unsigned char inext[64],
|
||||||
|
struct MD5Context *ctx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||||
* initialization constants.
|
* initialization constants.
|
||||||
@@ -179,8 +182,8 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
|
|||||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||||
* the data and converts bytes into longwords for this routine.
|
* the data and converts bytes into longwords for this routine.
|
||||||
*/
|
*/
|
||||||
void MD5Transform(uint32_t buf[4], const unsigned char inext[64],
|
static void MD5Transform(uint32_t buf[4], const unsigned char inext[64],
|
||||||
struct MD5Context *ctx)
|
struct MD5Context *ctx)
|
||||||
{
|
{
|
||||||
register uint32_t a, b, c, d, i;
|
register uint32_t a, b, c, d, i;
|
||||||
uint32_t in[16];
|
uint32_t in[16];
|
||||||
|
|||||||
11
src/md5.h
11
src/md5.h
@@ -11,15 +11,8 @@
|
|||||||
#ifndef MD5_H
|
#ifndef MD5_H
|
||||||
#define MD5_H
|
#define MD5_H
|
||||||
|
|
||||||
/* we use the uint32_t type from stdint.h
|
|
||||||
* if it is not available, add a typedef here:
|
|
||||||
*/
|
|
||||||
/* make sure the stdint.h types are available */
|
/* make sure the stdint.h types are available */
|
||||||
#if defined(_MSC_VER) /* Microsoft Visual C++ */
|
#include "ostypes.h"
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct MD5Context {
|
struct MD5Context {
|
||||||
uint32_t buf[4];
|
uint32_t buf[4];
|
||||||
@@ -31,8 +24,6 @@ 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);
|
uint32_t len);
|
||||||
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
||||||
void MD5Transform(uint32_t buf[4], const unsigned char in[64],
|
|
||||||
struct MD5Context *ctx);
|
|
||||||
|
|
||||||
#ifdef DEBUG_MD5
|
#ifdef DEBUG_MD5
|
||||||
void MD5DumpBytes(unsigned char *b, int len);
|
void MD5DumpBytes(unsigned char *b, int len);
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
|
|||||||
@@ -7,10 +7,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -20,8 +17,18 @@
|
|||||||
#ifndef __LIBSTROPHE_OSTYPES_H__
|
#ifndef __LIBSTROPHE_OSTYPES_H__
|
||||||
#define __LIBSTROPHE_OSTYPES_H__
|
#define __LIBSTROPHE_OSTYPES_H__
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined (_MSC_VER) && _MSC_VER < 1600
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef short int int16_t;
|
||||||
|
typedef int int32_t;
|
||||||
|
typedef __int64 int64_t;
|
||||||
|
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef unsigned short int uint16_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
typedef unsigned __int64 uint64_t;
|
typedef unsigned __int64 uint64_t;
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __LIBSTROPHE_OSTYPES_H__ */
|
#endif /* __LIBSTROPHE_OSTYPES_H__ */
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express or
|
** This software is provided AS-IS with no warranty, either express or
|
||||||
** implied.
|
** implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -37,6 +34,7 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
|
|||||||
parser_stanza_callback stanzacb,
|
parser_stanza_callback stanzacb,
|
||||||
void *userdata);
|
void *userdata);
|
||||||
void parser_free(parser_t * const parser);
|
void parser_free(parser_t * const parser);
|
||||||
|
char* parser_attr_name(xmpp_ctx_t *ctx, char *nsname);
|
||||||
int parser_reset(parser_t *parser);
|
int parser_reset(parser_t *parser);
|
||||||
int parser_feed(parser_t *parser, char *chunk, int len);
|
int parser_feed(parser_t *parser, char *chunk, int len);
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -26,6 +23,9 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
/* ASCII FF is invalid UTF-8 and should never be present in well-formed XML */
|
||||||
|
#define NAMESPACE_SEP ('\xFF')
|
||||||
|
|
||||||
struct _parser_t {
|
struct _parser_t {
|
||||||
xmpp_ctx_t *ctx;
|
xmpp_ctx_t *ctx;
|
||||||
XML_Parser expat;
|
XML_Parser expat;
|
||||||
@@ -37,23 +37,71 @@ struct _parser_t {
|
|||||||
xmpp_stanza_t *stanza;
|
xmpp_stanza_t *stanza;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* return allocated string with the name from a delimited
|
||||||
|
* namespace/name string */
|
||||||
|
static char *_xml_name(xmpp_ctx_t *ctx, const char *nsname)
|
||||||
|
{
|
||||||
|
char *result = NULL;
|
||||||
|
const char *c;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
c = strchr(nsname, NAMESPACE_SEP);
|
||||||
|
if (c == NULL) return xmpp_strdup(ctx, nsname);
|
||||||
|
|
||||||
|
c++;
|
||||||
|
len = strlen(c);
|
||||||
|
result = xmpp_alloc(ctx, len + 1);
|
||||||
|
if (result != NULL) {
|
||||||
|
memcpy(result, c, len);
|
||||||
|
result[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return allocated string with the namespace from a delimited string */
|
||||||
|
static char *_xml_namespace(xmpp_ctx_t *ctx, const char *nsname)
|
||||||
|
{
|
||||||
|
char *result = NULL;
|
||||||
|
const char *c;
|
||||||
|
|
||||||
|
c = strchr(nsname, NAMESPACE_SEP);
|
||||||
|
if (c != NULL) {
|
||||||
|
result = xmpp_alloc(ctx, (c-nsname) + 1);
|
||||||
|
if (result != NULL) {
|
||||||
|
memcpy(result, nsname, (c-nsname));
|
||||||
|
result[c-nsname] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void _set_attributes(xmpp_stanza_t *stanza, const XML_Char **attrs)
|
static void _set_attributes(xmpp_stanza_t *stanza, const XML_Char **attrs)
|
||||||
{
|
{
|
||||||
|
char *attr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!attrs) return;
|
if (!attrs) return;
|
||||||
|
|
||||||
for (i = 0; attrs[i]; i += 2) {
|
for (i = 0; attrs[i]; i += 2) {
|
||||||
xmpp_stanza_set_attribute(stanza, attrs[i], attrs[i+1]);
|
/* namespaced attributes aren't used in xmpp, discard namespace */
|
||||||
|
attr = _xml_name(stanza->ctx, attrs[i]);
|
||||||
|
xmpp_stanza_set_attribute(stanza, attr, attrs[i+1]);
|
||||||
|
xmpp_free(stanza->ctx, attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _start_element(void *userdata,
|
static void _start_element(void *userdata,
|
||||||
const XML_Char *name,
|
const XML_Char *nsname,
|
||||||
const XML_Char **attrs)
|
const XML_Char **attrs)
|
||||||
{
|
{
|
||||||
parser_t *parser = (parser_t *)userdata;
|
parser_t *parser = (parser_t *)userdata;
|
||||||
xmpp_stanza_t *child;
|
xmpp_stanza_t *child;
|
||||||
|
char *ns, *name;
|
||||||
|
|
||||||
|
ns = _xml_namespace(parser->ctx, nsname);
|
||||||
|
name = _xml_name(parser->ctx, nsname);
|
||||||
|
|
||||||
if (parser->depth == 0) {
|
if (parser->depth == 0) {
|
||||||
/* notify the owner */
|
/* notify the owner */
|
||||||
@@ -74,6 +122,8 @@ static void _start_element(void *userdata,
|
|||||||
}
|
}
|
||||||
xmpp_stanza_set_name(parser->stanza, name);
|
xmpp_stanza_set_name(parser->stanza, name);
|
||||||
_set_attributes(parser->stanza, attrs);
|
_set_attributes(parser->stanza, attrs);
|
||||||
|
if (ns)
|
||||||
|
xmpp_stanza_set_ns(parser->stanza, ns);
|
||||||
} else {
|
} else {
|
||||||
/* starting a child of parser->stanza */
|
/* starting a child of parser->stanza */
|
||||||
child = xmpp_stanza_new(parser->ctx);
|
child = xmpp_stanza_new(parser->ctx);
|
||||||
@@ -82,6 +132,8 @@ static void _start_element(void *userdata,
|
|||||||
}
|
}
|
||||||
xmpp_stanza_set_name(child, name);
|
xmpp_stanza_set_name(child, name);
|
||||||
_set_attributes(child, attrs);
|
_set_attributes(child, attrs);
|
||||||
|
if (ns)
|
||||||
|
xmpp_stanza_set_ns(child, ns);
|
||||||
|
|
||||||
/* add child to parent */
|
/* add child to parent */
|
||||||
xmpp_stanza_add_child(parser->stanza, child);
|
xmpp_stanza_add_child(parser->stanza, child);
|
||||||
@@ -94,6 +146,9 @@ static void _start_element(void *userdata,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ns) xmpp_free(parser->ctx, ns);
|
||||||
|
if (name) xmpp_free(parser->ctx, name);
|
||||||
|
|
||||||
parser->depth++;
|
parser->depth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +220,11 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
|
|||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* parser_attr_name(xmpp_ctx_t *ctx, char *nsname)
|
||||||
|
{
|
||||||
|
return _xml_name(ctx, nsname);
|
||||||
|
}
|
||||||
|
|
||||||
/* free a parser */
|
/* free a parser */
|
||||||
void parser_free(parser_t *parser)
|
void parser_free(parser_t *parser)
|
||||||
{
|
{
|
||||||
@@ -183,7 +243,7 @@ int parser_reset(parser_t *parser)
|
|||||||
if (parser->stanza)
|
if (parser->stanza)
|
||||||
xmpp_stanza_release(parser->stanza);
|
xmpp_stanza_release(parser->stanza);
|
||||||
|
|
||||||
parser->expat = XML_ParserCreate(NULL);
|
parser->expat = XML_ParserCreateNS(NULL, NAMESPACE_SEP);
|
||||||
if (!parser->expat) return 0;
|
if (!parser->expat) return 0;
|
||||||
|
|
||||||
parser->depth = 0;
|
parser->depth = 0;
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -39,28 +36,91 @@ struct _parser_t {
|
|||||||
xmpp_stanza_t *stanza;
|
xmpp_stanza_t *stanza;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void _set_attributes(xmpp_stanza_t *stanza, const xmlChar **attrs)
|
static void _set_attributes(xmpp_stanza_t *stanza, int nattrs,
|
||||||
|
const xmlChar **attrs)
|
||||||
{
|
{
|
||||||
int i;
|
int i, len;
|
||||||
|
char *value;
|
||||||
|
|
||||||
if (!attrs) return;
|
if (!attrs) return;
|
||||||
|
|
||||||
for (i = 0; attrs[i]; i += 2) {
|
/* SAX2 uses array of localname/prefix/uri/value_begin/value_end */
|
||||||
xmpp_stanza_set_attribute(stanza, (const char *)attrs[i], (const char *)attrs[i+1]);
|
for (i = 0; i < nattrs*5; i += 5) {
|
||||||
|
len = attrs[i+4] - attrs[i+3];
|
||||||
|
value = xmpp_alloc(stanza->ctx, len + 1);
|
||||||
|
if (value) {
|
||||||
|
memcpy(value, attrs[i+3], len);
|
||||||
|
value[len] = '\0';
|
||||||
|
xmpp_stanza_set_attribute(stanza, (const char *)attrs[i], value);
|
||||||
|
xmpp_free(stanza->ctx, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
int c, i, o, len;
|
||||||
|
char *value;
|
||||||
|
char **ret;
|
||||||
|
|
||||||
|
if (!attrs) return NULL;
|
||||||
|
|
||||||
|
ret = xmpp_alloc(parser->ctx, (nattrs+1)*2*sizeof(char*));
|
||||||
|
if (!ret) return NULL;
|
||||||
|
memset(ret, 0, (nattrs+1)*2*sizeof(char*));
|
||||||
|
|
||||||
|
for (c = 0; c < nattrs; c++) {
|
||||||
|
i = c * 5;
|
||||||
|
o = c * 2;
|
||||||
|
|
||||||
|
len = attrs[i+4] - attrs[i+3];
|
||||||
|
value = xmpp_alloc(parser->ctx, len + 1);
|
||||||
|
if (value) {
|
||||||
|
memcpy(value, attrs[i+3], len);
|
||||||
|
value[len] = '\0';
|
||||||
|
ret[o] = xmpp_strdup(parser->ctx, (char*)attrs[i]);
|
||||||
|
ret[o+1] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _free_cbattrs(parser_t *parser, char **attrs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmpp_free(parser->ctx, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
static void _start_element(void *userdata,
|
static void _start_element(void *userdata,
|
||||||
const xmlChar *name, 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;
|
parser_t *parser = (parser_t *)userdata;
|
||||||
xmpp_stanza_t *child;
|
xmpp_stanza_t *child;
|
||||||
|
char **cbattrs;
|
||||||
|
|
||||||
if (parser->depth == 0) {
|
if (parser->depth == 0) {
|
||||||
/* notify the owner */
|
/* notify the owner */
|
||||||
if (parser->startcb)
|
if (parser->startcb)
|
||||||
parser->startcb((char *)name, (char **)attrs,
|
cbattrs = _convert_attrs(parser, nattrs, attrs);
|
||||||
|
parser->startcb((char *)name, cbattrs,
|
||||||
parser->userdata);
|
parser->userdata);
|
||||||
|
_free_cbattrs(parser, cbattrs);
|
||||||
} else {
|
} else {
|
||||||
/* build stanzas at depth 1 */
|
/* build stanzas at depth 1 */
|
||||||
if (!parser->stanza && parser->depth != 1) {
|
if (!parser->stanza && parser->depth != 1) {
|
||||||
@@ -74,7 +134,9 @@ static void _start_element(void *userdata,
|
|||||||
/* FIXME: can't allocate, disconnect */
|
/* FIXME: can't allocate, disconnect */
|
||||||
}
|
}
|
||||||
xmpp_stanza_set_name(parser->stanza, (char *)name);
|
xmpp_stanza_set_name(parser->stanza, (char *)name);
|
||||||
_set_attributes(parser->stanza, attrs);
|
_set_attributes(parser->stanza, nattrs, attrs);
|
||||||
|
if (uri)
|
||||||
|
xmpp_stanza_set_ns(parser->stanza, (char *)uri);
|
||||||
} else {
|
} else {
|
||||||
/* starting a child of conn->stanza */
|
/* starting a child of conn->stanza */
|
||||||
child = xmpp_stanza_new(parser->ctx);
|
child = xmpp_stanza_new(parser->ctx);
|
||||||
@@ -82,7 +144,9 @@ static void _start_element(void *userdata,
|
|||||||
/* FIXME: can't allocate, disconnect */
|
/* FIXME: can't allocate, disconnect */
|
||||||
}
|
}
|
||||||
xmpp_stanza_set_name(child, (char *)name);
|
xmpp_stanza_set_name(child, (char *)name);
|
||||||
_set_attributes(child, attrs);
|
_set_attributes(child, nattrs, attrs);
|
||||||
|
if (uri)
|
||||||
|
xmpp_stanza_set_ns(child, (char *)uri);
|
||||||
|
|
||||||
/* add child to parent */
|
/* add child to parent */
|
||||||
xmpp_stanza_add_child(parser->stanza, child);
|
xmpp_stanza_add_child(parser->stanza, child);
|
||||||
@@ -98,7 +162,8 @@ static void _start_element(void *userdata,
|
|||||||
parser->depth++;
|
parser->depth++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _end_element(void *userdata, const xmlChar *name)
|
static void _end_element(void *userdata, const xmlChar *name,
|
||||||
|
const xmlChar *prefix, const xmlChar *uri)
|
||||||
{
|
{
|
||||||
parser_t *parser = (parser_t *)userdata;
|
parser_t *parser = (parser_t *)userdata;
|
||||||
|
|
||||||
@@ -156,8 +221,9 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
|
|||||||
parser->ctx = ctx;
|
parser->ctx = ctx;
|
||||||
parser->xmlctx = NULL;
|
parser->xmlctx = NULL;
|
||||||
memset(&parser->handlers, 0, sizeof(xmlSAXHandler));
|
memset(&parser->handlers, 0, sizeof(xmlSAXHandler));
|
||||||
parser->handlers.startElement = _start_element;
|
parser->handlers.initialized = XML_SAX2_MAGIC;
|
||||||
parser->handlers.endElement = _end_element;
|
parser->handlers.startElementNs = _start_element;
|
||||||
|
parser->handlers.endElementNs = _end_element;
|
||||||
parser->handlers.characters = _characters;
|
parser->handlers.characters = _characters;
|
||||||
parser->startcb = startcb;
|
parser->startcb = startcb;
|
||||||
parser->endcb = endcb;
|
parser->endcb = endcb;
|
||||||
@@ -172,6 +238,11 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
|
|||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* parser_attr_name(xmpp_ctx_t *ctx, char *nsname)
|
||||||
|
{
|
||||||
|
return xmpp_strdup(ctx, nsname);
|
||||||
|
}
|
||||||
|
|
||||||
/* free a parser */
|
/* free a parser */
|
||||||
void parser_free(parser_t *parser)
|
void parser_free(parser_t *parser)
|
||||||
{
|
{
|
||||||
|
|||||||
133
src/sasl.c
133
src/sasl.c
@@ -6,36 +6,26 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
* SASL authentication.
|
* SASL authentication.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "ostypes.h"
|
||||||
#include "sasl.h"
|
#include "sasl.h"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
|
#include "sha1.h"
|
||||||
|
#include "scram.h"
|
||||||
|
|
||||||
/* make sure the stdint.h types are available */
|
#ifdef _WIN32
|
||||||
#if defined(_MSC_VER) /* Microsoft Visual C++ */
|
#define strtok_r strtok_s
|
||||||
typedef signed char int8_t;
|
|
||||||
typedef short int int16_t;
|
|
||||||
typedef int int32_t;
|
|
||||||
typedef __int64 int64_t;
|
|
||||||
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef unsigned short int uint16_t;
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
/* no uint64_t */
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -360,6 +350,113 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 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[SHA1_DIGEST_SIZE];
|
||||||
|
uint8_t sign[SHA1_DIGEST_SIZE];
|
||||||
|
char *r = NULL;
|
||||||
|
char *s = NULL;
|
||||||
|
char *i = NULL;
|
||||||
|
char *sval;
|
||||||
|
size_t sval_len;
|
||||||
|
long ival;
|
||||||
|
char *tmp;
|
||||||
|
char *ptr;
|
||||||
|
char *saveptr = NULL;
|
||||||
|
char *response;
|
||||||
|
char *auth;
|
||||||
|
char *response_b64;
|
||||||
|
char *sign_b64;
|
||||||
|
char *result = NULL;
|
||||||
|
size_t response_len;
|
||||||
|
size_t auth_len;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
tmp = xmpp_strdup(ctx, challenge);
|
||||||
|
if (!tmp) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = strtok_r(tmp, ",", &saveptr);
|
||||||
|
while (ptr) {
|
||||||
|
if (strncmp(ptr, "r=", 2) == 0) {
|
||||||
|
r = ptr;
|
||||||
|
} else if (strncmp(ptr, "s=", 2) == 0) {
|
||||||
|
s = ptr + 2;
|
||||||
|
} else if (strncmp(ptr, "i=", 2) == 0) {
|
||||||
|
i = ptr + 2;
|
||||||
|
}
|
||||||
|
ptr = strtok_r(NULL, ",", &saveptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r || !s || !i) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
sval = (char *)base64_decode(ctx, s, strlen(s));
|
||||||
|
if (!sval) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
sval_len = base64_decoded_len(ctx, s, strlen(s));
|
||||||
|
ival = strtol(i, &saveptr, 10);
|
||||||
|
|
||||||
|
auth_len = 10 + strlen(r) + strlen(first_bare) + strlen(challenge);
|
||||||
|
auth = xmpp_alloc(ctx, auth_len);
|
||||||
|
if (!auth) {
|
||||||
|
goto out_sval;
|
||||||
|
}
|
||||||
|
|
||||||
|
response_len = 39 + strlen(r);
|
||||||
|
response = xmpp_alloc(ctx, response_len);
|
||||||
|
if (!response) {
|
||||||
|
goto out_auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmpp_snprintf(response, response_len, "c=biws,%s", r);
|
||||||
|
xmpp_snprintf(auth, auth_len, "%s,%s,%s", first_bare + 3, challenge,
|
||||||
|
response);
|
||||||
|
|
||||||
|
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 = base64_encode(ctx, sign, sizeof(sign));
|
||||||
|
if (!sign_b64) {
|
||||||
|
goto out_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(response) + strlen(sign_b64) + 3 + 1 > response_len) {
|
||||||
|
xmpp_free(ctx, sign_b64);
|
||||||
|
goto out_response;
|
||||||
|
}
|
||||||
|
strcat(response, ",p=");
|
||||||
|
strcat(response, sign_b64);
|
||||||
|
xmpp_free(ctx, sign_b64);
|
||||||
|
|
||||||
|
response_b64 = base64_encode(ctx, (unsigned char *)response,
|
||||||
|
strlen(response));
|
||||||
|
if (!response_b64) {
|
||||||
|
goto out_response;
|
||||||
|
}
|
||||||
|
result = response_b64;
|
||||||
|
|
||||||
|
out_response:
|
||||||
|
xmpp_free(ctx, response);
|
||||||
|
out_auth:
|
||||||
|
xmpp_free(ctx, auth);
|
||||||
|
out_sval:
|
||||||
|
xmpp_free(ctx, sval);
|
||||||
|
out:
|
||||||
|
xmpp_free(ctx, tmp);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Base64 encoding routines. Implemented according to RFC 3548 */
|
/** Base64 encoding routines. Implemented according to RFC 3548 */
|
||||||
|
|
||||||
@@ -552,8 +649,8 @@ unsigned char *base64_decode(xmpp_ctx_t *ctx,
|
|||||||
if (hextet != 64) goto _base64_decode_error;
|
if (hextet != 64) goto _base64_decode_error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
*d = '\0';
|
||||||
}
|
}
|
||||||
*d = '\0';
|
|
||||||
return dbuf;
|
return dbuf;
|
||||||
|
|
||||||
_base64_decode_error:
|
_base64_decode_error:
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -26,6 +23,9 @@
|
|||||||
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);
|
||||||
char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
|
char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
|
||||||
const char *jid, const char *password);
|
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);
|
||||||
|
|
||||||
|
|
||||||
/** Base64 encoding routines. Implemented according to RFC 3548 */
|
/** Base64 encoding routines. Implemented according to RFC 3548 */
|
||||||
|
|||||||
143
src/scram.c
Normal file
143
src/scram.c
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/* scram.c
|
||||||
|
* strophe XMPP client library
|
||||||
|
*
|
||||||
|
* SCRAM-SHA1 helper functions according to RFC5802
|
||||||
|
* HMAC-SHA1 implementation according to RFC2104
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Dmitry Podgorny <pasis.ua@gmail.com>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* SCRAM-SHA1 helper functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "sha1.h"
|
||||||
|
#include "ostypes.h"
|
||||||
|
|
||||||
|
#include "scram.h"
|
||||||
|
|
||||||
|
/* block size for HMAC */
|
||||||
|
#define BLOCK_SIZE 64
|
||||||
|
#if BLOCK_SIZE < SHA1_DIGEST_SIZE
|
||||||
|
#error BLOCK_SIZE must not be less than SHA1_DIGEST_SIZE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const uint8_t ipad = 0x36;
|
||||||
|
static const uint8_t opad = 0x5C;
|
||||||
|
|
||||||
|
static void SHA1(const uint8_t* data, size_t len,
|
||||||
|
uint8_t digest[SHA1_DIGEST_SIZE])
|
||||||
|
{
|
||||||
|
SHA1_CTX ctx;
|
||||||
|
SHA1_Init(&ctx);
|
||||||
|
SHA1_Update(&ctx, data, len);
|
||||||
|
SHA1_Final(&ctx, digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HMAC_SHA1(const uint8_t *key, size_t key_len,
|
||||||
|
const uint8_t *text, size_t len,
|
||||||
|
uint8_t digest[SHA1_DIGEST_SIZE])
|
||||||
|
{
|
||||||
|
uint8_t key_pad[BLOCK_SIZE];
|
||||||
|
uint8_t key_ipad[BLOCK_SIZE];
|
||||||
|
uint8_t key_opad[BLOCK_SIZE];
|
||||||
|
uint8_t sha_digest[SHA1_DIGEST_SIZE];
|
||||||
|
int i;
|
||||||
|
SHA1_CTX ctx;
|
||||||
|
|
||||||
|
memset(key_pad, 0, sizeof(key_pad));
|
||||||
|
if (key_len <= BLOCK_SIZE) {
|
||||||
|
memcpy(key_pad, key, key_len);
|
||||||
|
} else {
|
||||||
|
/* according to RFC2104 */
|
||||||
|
SHA1(key, key_len, key_pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < BLOCK_SIZE; i++) {
|
||||||
|
key_ipad[i] = key_pad[i] ^ ipad;
|
||||||
|
key_opad[i] = key_pad[i] ^ opad;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHA1_Init(&ctx);
|
||||||
|
SHA1_Update(&ctx, key_ipad, BLOCK_SIZE);
|
||||||
|
SHA1_Update(&ctx, text, len);
|
||||||
|
SHA1_Final(&ctx, sha_digest);
|
||||||
|
|
||||||
|
SHA1_Init(&ctx);
|
||||||
|
SHA1_Update(&ctx, key_opad, BLOCK_SIZE);
|
||||||
|
SHA1_Update(&ctx, sha_digest, SHA1_DIGEST_SIZE);
|
||||||
|
SHA1_Final(&ctx, digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
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[SHA1_DIGEST_SIZE])
|
||||||
|
{
|
||||||
|
int j, k;
|
||||||
|
uint8_t tmp[128];
|
||||||
|
|
||||||
|
static uint8_t int1[] = {0x0, 0x0, 0x0, 0x1};
|
||||||
|
|
||||||
|
/* assume salt + INT(1) isn't longer than sizeof(tmp) */
|
||||||
|
assert(salt_len <= sizeof(tmp) - sizeof(int1));
|
||||||
|
|
||||||
|
memset(digest, 0, SHA1_DIGEST_SIZE);
|
||||||
|
if (i == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(tmp, salt, salt_len);
|
||||||
|
memcpy(&tmp[salt_len], int1, sizeof(int1));
|
||||||
|
|
||||||
|
/* 'text' for Hi is a 'key' for HMAC */
|
||||||
|
HMAC_SHA1(text, len, tmp, salt_len + sizeof(int1), digest);
|
||||||
|
memcpy(tmp, digest, SHA1_DIGEST_SIZE);
|
||||||
|
|
||||||
|
for (j = 1; j < i; j++) {
|
||||||
|
HMAC_SHA1(text, len, tmp, SHA1_DIGEST_SIZE, tmp);
|
||||||
|
for (k = 0; k < SHA1_DIGEST_SIZE; k++) {
|
||||||
|
digest[k] ^= tmp[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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[SHA1_DIGEST_SIZE])
|
||||||
|
{
|
||||||
|
uint8_t salted[SHA1_DIGEST_SIZE];
|
||||||
|
|
||||||
|
/* XXX: Normalize(password) is omitted */
|
||||||
|
|
||||||
|
SCRAM_SHA1_Hi(password, len, salt, salt_len, i, salted);
|
||||||
|
HMAC_SHA1(salted, SHA1_DIGEST_SIZE, (uint8_t *)"Client Key",
|
||||||
|
strlen("Client Key"), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCRAM_SHA1_ClientSignature(const uint8_t ClientKey[SHA1_DIGEST_SIZE],
|
||||||
|
const uint8_t *AuthMessage, size_t len,
|
||||||
|
uint8_t sign[SHA1_DIGEST_SIZE])
|
||||||
|
{
|
||||||
|
uint8_t stored[SHA1_DIGEST_SIZE];
|
||||||
|
|
||||||
|
SHA1(ClientKey, SHA1_DIGEST_SIZE, stored);
|
||||||
|
HMAC_SHA1(stored, SHA1_DIGEST_SIZE, AuthMessage, len, sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SCRAM_SHA1_ClientProof(const uint8_t ClientKey[SHA1_DIGEST_SIZE],
|
||||||
|
const uint8_t ClientSignature[SHA1_DIGEST_SIZE],
|
||||||
|
uint8_t proof[SHA1_DIGEST_SIZE])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
|
||||||
|
proof[i] = ClientKey[i] ^ ClientSignature[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/scram.h
Normal file
36
src/scram.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/* scram.h
|
||||||
|
* strophe XMPP client library -- SCRAM-SHA1 helper functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Dmitry Podgorny <pasis.ua@gmail.com>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* SCRAM-SHA1 helper functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBSTROPHE_SCRAM_H__
|
||||||
|
#define __LIBSTROPHE_SCRAM_H__
|
||||||
|
|
||||||
|
/* make sure the stdint.h types are available */
|
||||||
|
#include "ostypes.h"
|
||||||
|
|
||||||
|
#include "sha1.h"
|
||||||
|
|
||||||
|
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[SHA1_DIGEST_SIZE]);
|
||||||
|
|
||||||
|
void SCRAM_SHA1_ClientSignature(const uint8_t ClientKey[SHA1_DIGEST_SIZE],
|
||||||
|
const uint8_t *AuthMessage, size_t len,
|
||||||
|
uint8_t sign[SHA1_DIGEST_SIZE]);
|
||||||
|
|
||||||
|
void SCRAM_SHA1_ClientProof(const uint8_t ClientKey[SHA1_DIGEST_SIZE],
|
||||||
|
const uint8_t ClientSignature[SHA1_DIGEST_SIZE],
|
||||||
|
uint8_t proof[SHA1_DIGEST_SIZE]);
|
||||||
|
|
||||||
|
#endif /* __LIBSTROPHE_SCRAM_H__ */
|
||||||
47
src/sha1.c
47
src/sha1.c
@@ -86,35 +86,18 @@ A million repetitions of "a"
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* make sure the stdint.h types are available */
|
/* make sure the stdint.h types are available */
|
||||||
#if defined(_MSC_VER) /* Microsoft Visual C++ */
|
#include "ostypes.h"
|
||||||
typedef signed char int8_t;
|
|
||||||
typedef short int int16_t;
|
|
||||||
typedef int int32_t;
|
|
||||||
typedef __int64 int64_t;
|
|
||||||
|
|
||||||
typedef unsigned char uint8_t;
|
|
||||||
typedef unsigned short int uint16_t;
|
|
||||||
typedef unsigned int uint32_t;
|
|
||||||
/* no uint64_t */
|
|
||||||
#else
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
|
|
||||||
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
|
static uint32_t host_to_be(uint32_t i);
|
||||||
|
static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
|
||||||
|
|
||||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||||
|
|
||||||
/* blk0() and blk() perform the initial expand. */
|
/* blk0() and blk() perform the initial expand. */
|
||||||
/* I got the idea of expanding during the round function from SSLeay */
|
/* I got the idea of expanding during the round function from SSLeay */
|
||||||
/* FIXME: can we do this in an endian-proof way? */
|
#define blk0(i) (block->l[i] = host_to_be(block->l[i]))
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
#define blk0(i) block->l[i]
|
|
||||||
#else
|
|
||||||
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|
|
||||||
|(rol(block->l[i],8)&0x00FF00FF))
|
|
||||||
#endif
|
|
||||||
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
#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))
|
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||||
|
|
||||||
@@ -139,8 +122,28 @@ void SHAPrintContext(SHA1_CTX *context, char *msg){
|
|||||||
}
|
}
|
||||||
#endif /* VERBOSE */
|
#endif /* VERBOSE */
|
||||||
|
|
||||||
|
static uint32_t host_to_be(uint32_t i)
|
||||||
|
{
|
||||||
|
#define le_to_be(i) ((rol((i),24) & 0xFF00FF00) | (rol((i),8) & 0x00FF00FF))
|
||||||
|
#if defined(__BIG_ENDIAN__) || \
|
||||||
|
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
|
||||||
|
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||||
|
return i;
|
||||||
|
#elif defined(__LITTLE_ENDIAN__) || \
|
||||||
|
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
|
||||||
|
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||||
|
return le_to_be(i);
|
||||||
|
#else /* fallback to run-time check */
|
||||||
|
static const union {
|
||||||
|
uint32_t u;
|
||||||
|
unsigned char c;
|
||||||
|
} check = {1};
|
||||||
|
return check.c ? le_to_be(i) : i;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||||
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
|
static void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
|
||||||
{
|
{
|
||||||
uint32_t a, b, c, d, e;
|
uint32_t a, b, c, d, e;
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* make sure the stdint.h types are available */
|
||||||
|
#include "ostypes.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t state[5];
|
uint32_t state[5];
|
||||||
uint32_t count[2];
|
uint32_t count[2];
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
19
src/stanza.c
19
src/stanza.c
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -320,6 +317,20 @@ static int _render_stanza_recursive(xmpp_stanza_t *stanza,
|
|||||||
if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
|
if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
|
||||||
iter = hash_iter_new(stanza->attributes);
|
iter = hash_iter_new(stanza->attributes);
|
||||||
while ((key = hash_iter_next(iter))) {
|
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 &&
|
||||||
|
hash_get(stanza->parent->attributes, key) &&
|
||||||
|
!strcmp((char*)hash_get(stanza->attributes, key),
|
||||||
|
(char*)hash_get(stanza->parent->attributes, key)))
|
||||||
|
continue;
|
||||||
|
/* or if this is the stream namespace */
|
||||||
|
if (!stanza->parent &&
|
||||||
|
!strcmp((char*)hash_get(stanza->attributes, key),
|
||||||
|
XMPP_NS_CLIENT))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
tmp = _escape_xml(stanza->ctx,
|
tmp = _escape_xml(stanza->ctx,
|
||||||
(char *)hash_get(stanza->attributes, key));
|
(char *)hash_get(stanza->attributes, key));
|
||||||
if (tmp == NULL) return XMPP_EMEM;
|
if (tmp == NULL) return XMPP_EMEM;
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -25,7 +22,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/rand.h>
|
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "tls.h"
|
#include "tls.h"
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -75,11 +72,11 @@ tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
|
|||||||
SecPkgCred_CipherStrengths spc_cs;
|
SecPkgCred_CipherStrengths spc_cs;
|
||||||
SecPkgCred_SupportedProtocols spc_sp;
|
SecPkgCred_SupportedProtocols spc_sp;
|
||||||
|
|
||||||
OSVERSIONINFO osvi;
|
OSVERSIONINFO osvi;
|
||||||
|
|
||||||
memset(&osvi, 0, sizeof(osvi));
|
memset(&osvi, 0, sizeof(osvi));
|
||||||
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
||||||
|
|
||||||
GetVersionEx(&osvi);
|
GetVersionEx(&osvi);
|
||||||
|
|
||||||
/* no TLS support on win9x/me, despite what anyone says */
|
/* no TLS support on win9x/me, despite what anyone says */
|
||||||
@@ -102,7 +99,7 @@ tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pInitSecurityInterface =
|
if (!(pInitSecurityInterface =
|
||||||
(void *)GetProcAddress(tls->hsec32, "InitSecurityInterfaceA"))) {
|
(void *)GetProcAddress(tls->hsec32, "InitSecurityInterfaceA"))) {
|
||||||
tls_free(tls);
|
tls_free(tls);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -148,26 +145,26 @@ tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
|
|||||||
|
|
||||||
/* This bunch of queries should trip up wine until someone fixes
|
/* This bunch of queries should trip up wine until someone fixes
|
||||||
* schannel support there */
|
* schannel support there */
|
||||||
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_ALGS, &spc_sa);
|
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_ALGS, &spc_sa);
|
||||||
if (ret != SEC_E_OK)
|
if (ret != SEC_E_OK)
|
||||||
{
|
{
|
||||||
tls_free(tls);
|
tls_free(tls);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_CIPHER_STRENGTHS, &spc_cs);
|
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_CIPHER_STRENGTHS, &spc_cs);
|
||||||
if (ret != SEC_E_OK)
|
if (ret != SEC_E_OK)
|
||||||
{
|
{
|
||||||
tls_free(tls);
|
tls_free(tls);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_PROTOCOLS, &spc_sp);
|
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_PROTOCOLS, &spc_sp);
|
||||||
if (ret != SEC_E_OK)
|
if (ret != SEC_E_OK)
|
||||||
{
|
{
|
||||||
tls_free(tls);
|
tls_free(tls);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tls;
|
return tls;
|
||||||
}
|
}
|
||||||
@@ -196,7 +193,7 @@ void tls_free(tls_t *tls)
|
|||||||
FreeLibrary(tls->hsec32);
|
FreeLibrary(tls->hsec32);
|
||||||
tls->hsec32 = NULL;
|
tls->hsec32 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmpp_free(tls->ctx, tls);
|
xmpp_free(tls->ctx, tls);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -360,7 +357,7 @@ int tls_start(tls_t *tls)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls->sft->QueryContextAttributes(&(tls->hctxt), SECPKG_ATTR_STREAM_SIZES,
|
tls->sft->QueryContextAttributes(&(tls->hctxt), SECPKG_ATTR_STREAM_SIZES,
|
||||||
&(tls->spcss));
|
&(tls->spcss));
|
||||||
|
|
||||||
tls->recvbuffermaxlen = tls->spcss.cbHeader + tls->spcss.cbMaximumMessage
|
tls->recvbuffermaxlen = tls->spcss.cbHeader + tls->spcss.cbMaximumMessage
|
||||||
@@ -401,7 +398,7 @@ int tls_is_recoverable(int error)
|
|||||||
int tls_pending(tls_t *tls) {
|
int tls_pending(tls_t *tls) {
|
||||||
// There are 3 cases:
|
// There are 3 cases:
|
||||||
// - there is data in ready buffer, so it is by default pending
|
// - 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
|
// - there is data in recv buffer. If it is not decrypted yet, means it
|
||||||
// was incomplete. This should be processed again only if there is data
|
// was incomplete. This should be processed again only if there is data
|
||||||
// on the physical connection
|
// on the physical connection
|
||||||
// - there is data on the physical connection. This case is treated
|
// - there is data on the physical connection. This case is treated
|
||||||
@@ -440,7 +437,7 @@ int tls_read(tls_t *tls, void * const buff, const size_t len)
|
|||||||
read = tls_read(tls, newbuff, len - bytes);
|
read = tls_read(tls, newbuff, len - bytes);
|
||||||
|
|
||||||
if (read == -1) {
|
if (read == -1) {
|
||||||
if (tls_is_recoverable(tls->lasterror)) {
|
if (tls_is_recoverable(tls->lasterror)) {
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,11 +451,11 @@ int tls_read(tls_t *tls, void * const buff, const size_t len)
|
|||||||
/* next, top up our recv buffer */
|
/* next, top up our recv buffer */
|
||||||
bytes = sock_read(tls->sock, tls->recvbuffer + tls->recvbufferpos,
|
bytes = sock_read(tls->sock, tls->recvbuffer + tls->recvbufferpos,
|
||||||
tls->recvbuffermaxlen - tls->recvbufferpos);
|
tls->recvbuffermaxlen - tls->recvbufferpos);
|
||||||
|
|
||||||
if (bytes == 0) {
|
if (bytes == 0) {
|
||||||
tls->lasterror = WSAECONNRESET;
|
tls->lasterror = WSAECONNRESET;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes == -1) {
|
if (bytes == -1) {
|
||||||
if (!tls_is_recoverable(sock_error())) {
|
if (!tls_is_recoverable(sock_error())) {
|
||||||
@@ -499,7 +496,7 @@ int tls_read(tls_t *tls, void * const buff, const size_t len)
|
|||||||
ret = tls->sft->DecryptMessage(&(tls->hctxt), &sbddec, 0, NULL);
|
ret = tls->sft->DecryptMessage(&(tls->hctxt), &sbddec, 0, NULL);
|
||||||
|
|
||||||
if (ret == SEC_E_OK) {
|
if (ret == SEC_E_OK) {
|
||||||
memcpy(tls->readybuffer, sbdec[1].pvBuffer, sbdec[1].cbBuffer);
|
memcpy(tls->readybuffer, sbdec[1].pvBuffer, sbdec[1].cbBuffer);
|
||||||
tls->readybufferpos = 0;
|
tls->readybufferpos = 0;
|
||||||
tls->readybufferlen = sbdec[1].cbBuffer;
|
tls->readybufferlen = sbdec[1].cbBuffer;
|
||||||
/* have we got some data left over? If so, copy it to the start
|
/* have we got some data left over? If so, copy it to the start
|
||||||
@@ -631,8 +628,8 @@ int tls_write(tls_t *tls, const void * const buff, const size_t len)
|
|||||||
|
|
||||||
if (ret == -1 && !tls_is_recoverable(tls_error(tls))) {
|
if (ret == -1 && !tls_is_recoverable(tls_error(tls))) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remain > tls->spcss.cbMaximumMessage) {
|
if (remain > tls->spcss.cbMaximumMessage) {
|
||||||
sent += tls->spcss.cbMaximumMessage;
|
sent += tls->spcss.cbMaximumMessage;
|
||||||
remain -= tls->spcss.cbMaximumMessage;
|
remain -= tls->spcss.cbMaximumMessage;
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -24,11 +21,11 @@
|
|||||||
#else
|
#else
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "ostypes.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
/** implement our own strdup that uses the ctx allocator */
|
/** implement our own strdup that uses the ctx allocator */
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -19,11 +16,7 @@
|
|||||||
#ifndef __LIBSTROPHE_UTIL_H__
|
#ifndef __LIBSTROPHE_UTIL_H__
|
||||||
#define __LIBSTROPHE_UTIL_H__
|
#define __LIBSTROPHE_UTIL_H__
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
#include <stdint.h>
|
|
||||||
#else
|
|
||||||
#include "ostypes.h"
|
#include "ostypes.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* timing functions */
|
/* timing functions */
|
||||||
uint64_t time_stamp(void);
|
uint64_t time_stamp(void);
|
||||||
|
|||||||
12
strophe.h
12
strophe.h
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express or
|
** This software is provided AS-IS with no warranty, either express or
|
||||||
** implied.
|
** implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This software is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
@@ -225,9 +222,10 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
|
|||||||
xmpp_conn_handler callback,
|
xmpp_conn_handler callback,
|
||||||
void * const userdata);
|
void * const userdata);
|
||||||
|
|
||||||
/*
|
int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
|
||||||
int xmpp_connect_component(conn, name)
|
unsigned short port, xmpp_conn_handler callback,
|
||||||
*/
|
void * const userdata);
|
||||||
|
|
||||||
void xmpp_disconnect(xmpp_conn_t * const conn);
|
void xmpp_disconnect(xmpp_conn_t * const conn);
|
||||||
|
|
||||||
void xmpp_send(xmpp_conn_t * const conn,
|
void xmpp_send(xmpp_conn_t * const conn,
|
||||||
|
|||||||
@@ -5,11 +5,8 @@
|
|||||||
**
|
**
|
||||||
** This software is provided AS-IS with no warranty, either express or
|
** This software is provided AS-IS with no warranty, either express or
|
||||||
** implied.
|
** implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @file
|
/** @file
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express or
|
** This software is provided AS-IS with no warranty, either express or
|
||||||
** implied.
|
** implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -37,14 +34,14 @@ END_TEST
|
|||||||
int cbtest_got_start = 0;
|
int cbtest_got_start = 0;
|
||||||
void cbtest_handle_start(char *name, char **attrs, void *userdata)
|
void cbtest_handle_start(char *name, char **attrs, void *userdata)
|
||||||
{
|
{
|
||||||
if (strcmp(name, "stream:stream") == 0)
|
if (strcmp(name, "stream") == 0)
|
||||||
cbtest_got_start = 1;
|
cbtest_got_start = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cbtest_got_end = 0;
|
int cbtest_got_end = 0;
|
||||||
void cbtest_handle_end(char *name, void *userdata)
|
void cbtest_handle_end(char *name, void *userdata)
|
||||||
{
|
{
|
||||||
if (strcmp(name, "stream:stream") == 0)
|
if (strcmp(name, "stream") == 0)
|
||||||
cbtest_got_end = 1;
|
cbtest_got_end = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,9 +64,9 @@ START_TEST(callbacks)
|
|||||||
cbtest_handle_end,
|
cbtest_handle_end,
|
||||||
cbtest_handle_stanza, NULL);
|
cbtest_handle_stanza, NULL);
|
||||||
|
|
||||||
ret = parser_feed(parser, "<stream:stream>", 15);
|
ret = parser_feed(parser, "<stream>", 8);
|
||||||
ret = parser_feed(parser, "<message/>", 10);
|
ret = parser_feed(parser, "<message/>", 10);
|
||||||
parser_feed(parser, "</stream:stream>", 16);
|
parser_feed(parser, "</stream>", 9);
|
||||||
|
|
||||||
fail_unless(cbtest_got_start == 1);
|
fail_unless(cbtest_got_start == 1);
|
||||||
fail_unless(cbtest_got_end == 1);
|
fail_unless(cbtest_got_end == 1);
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
** This software is provided AS-IS with no warranty, either express
|
** This software is provided AS-IS with no warranty, either express
|
||||||
** or implied.
|
** or implied.
|
||||||
**
|
**
|
||||||
** This software is distributed under license and may not be copied,
|
** This program is dual licensed under the MIT and GPLv3 licenses.
|
||||||
** modified or distributed except as expressly authorized under the
|
|
||||||
** terms of the license contained in the file LICENSE.txt in this
|
|
||||||
** distribution.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user