60 Commits

Author SHA1 Message Date
James Booth
160a124619 OpenSSL: Debug certificate chain 2015-09-14 00:57:44 +01:00
James Booth
450bbca8e7 OpenSSL: Added debug logging to certificate verification 2015-09-13 22:44:12 +01:00
James Booth
20380157ba OpenSSL: debug name string on cert verify fail 2015-09-11 01:18:48 +01:00
James Booth
3e12f33cce OpenSSL: Use simpler cert callback 2015-09-11 00:46:49 +01:00
James Booth
f05529b09a Added open SSL dummy certificate check callback 2015-09-10 23:14:08 +01:00
James Booth
cc486b2ebf Continue open SSL connect loop on recoverable errors 2015-09-10 23:06:05 +01:00
James Booth
165d2487bb Change openssl connect err check for < 0 instead of == -1 2015-09-10 22:54:14 +01:00
James Booth
32591e3e77 Reformat tls_openssl.c 2015-09-10 22:51:15 +01:00
James Booth
cd92f69c76 Fixed Changelog 2015-08-18 22:07:06 +01:00
James Booth
73080e0660 Fixed indentation in Changelog 2015-08-18 22:00:43 +01:00
James Booth
7cdef1e319 Check for name element when reading mechanisms
Fixes an issue where the server sends whitespace between
elements, a segfault would occur when performing a strcmp
on the name.
2015-08-03 23:05:04 +01:00
James Booth
527bc0573a Fixed _log_open_tag to remove namespace prefix with libexpat 2015-03-28 17:37:11 +00:00
James Booth
59d2dd55d2 Added codelite project to .gitignore 2015-03-26 20:58:05 +00:00
James Booth
b1cbcffdc7 Bumped version, added to Changelog 2015-03-26 20:52:48 +00:00
James Booth
154b70ed2c Merge remote-tracking branch 'cwtitan/namespace' 2015-03-26 20:44:10 +00:00
Codewalker
e33a98e498 Streamline xmpp_stanza_to_text for the namespace patch by following XML
namespace scoping guidelines and not outputting the xmlns attribute in
contexts where it can be inferred from the parent element.
2015-01-23 11:11:23 -06:00
shooding
239d365ea1 fix Makefile.am to respect openssl_CFLAGS, which is useful if openssl is not installed in the default path, e.g. cross-compiling. 2015-01-14 18:06:35 +08:00
Dmitry Podgorny
57ed30b2bc autotools: fixed build with old versions of automake
Automake-1.11 and some newer versions fail if m4/ doesn't exist. This
behaviour was changed to warning in version 1.13.2.
2015-01-03 01:01:07 +02:00
Codewalker
86f913b001 Fix use of snprintf (which does not exist on all platforms) in auth.c
by replacing it with xmpp_snprintf in order to be consistent with the
rest of the code. Also fixes compile error on MSVC.
2015-01-02 20:21:59 +02:00
Codewalker
e2f1c1e94a Add XML namespace support. 2014-12-28 22:46:16 -06:00
Codewalker
f62d817c71 Fix error spam in event loop when no connections are open.
On Win32 at least, select() will immediately fail with an error if
there are no file descriptors to wait for (max == 0). In the simple case
of a single XMPP session and an event loop that runs only while the
connection is open, this isn't a problem, but doesn't work for more
complex scenarios.

Add some handling so that if xmpp_run_once is called and there are no
active connections, simply sleep for duration of the timeout and
return.
2014-12-24 12:08:05 -06:00
Codewalker
b753e6cf18 Fix a bug where select() could fail due to negative max socket fd.
Connection objects in the disconnected state should not have their
fd taken into account when determining the maximum socket fd number,
as they are not set in the bitmask with FD_SET, and their fd could
be anything, even a wildly large or small number.
2014-12-24 12:04:39 -06:00
Dmitry Podgorny
0fed8a55e4 examples: updated header in component.c 2014-12-15 14:47:47 +02:00
Dmitry Podgorny
d28520ba30 added examples/component to .gitignore 2014-12-15 14:42:50 +02:00
Milan Kubik
c52ba85846 XEP-0114: Added an example for component connection.
The example is based on basic.c program.
To run the example, a configured server is needed.
2014-12-15 14:42:50 +02:00
Dmitry Podgorny
3b906f6ceb XEP-0114: minor fixes to auth.c
- src/sha1.c is used instead of openssl;
 - xmpp_alloc/free should be used instead of malloc/free;
 - coding style fixes.
2014-12-15 14:42:50 +02:00
Milan Kubík
5d76e052ec XEP-0114: external component authentication
New API xmpp_connect_component() introduced.
2014-12-15 14:41:18 +02:00
Dariusz Dwornikowski
37a40dec23 Merge pull request #42 from tdi/master
Update headers not to mention LICENSE.txt but licenses directly Closes #31
2014-11-13 13:13:37 +01:00
Dmitry Podgorny
2093aac817 rpm: include shared library and pkg-config file 2014-10-31 04:13:49 +02:00
Kristofer White
29fa1bf27e Updates to rpm/libstrophe.spec 2014-10-31 04:11:13 +02:00
Dmitry Podgorny
f364ed184b autotools: fixed building of check_parser
By default libtool choose dynamic library for linking. Since non-public
API is hidden in libstrophe.so check_parser has been broken. As solution
libtool takes static libstophe.a now.
2014-10-30 23:17:16 +02:00
Dmitry Podgorny
40c9fe22b3 .gitignore: added files generated by make check 2014-10-30 23:16:40 +02:00
Dmitry Podgorny
c33c0a6998 hash: removed useless condition in hash_iter_next
Situation ((entry != NULL) && (i >= table->length)) can never happen.
2014-10-29 18:43:06 +02:00
Sergey Anufrienko
92e674e412 fix bug leading to losing of hash entries in hash_iter_next 2014-10-28 16:42:28 +03:00
Dmitry Podgorny
9f82aac8ce sha1: compile-time endianness check for some compilers
Newer gcc and clang provide macro __BYTE_ORDER__.
2014-10-25 16:37:21 +03:00
Dmitry Podgorny
a3f1b83f3a sha1: run-time check for endianness
WORDS_BIGENDIAN is never defined what breaks sha1 on big-endian
architectures. Instead, make run-time check.
2014-10-25 16:03:18 +03:00
Dariusz Dwornikowski
71f75b2e2e Closes #31 2014-10-23 08:44:52 +02:00
Dmitry Podgorny
b23104f920 ChangeLog: set future version to 0.8.7 2014-10-21 10:23:12 +03:00
Dmitry Podgorny
057f9068c6 autotools: removed duplication in configure.ac 2014-10-21 10:21:55 +03:00
Fabian Freyer
3231214344 Added --with-pkgconfigdir 2014-10-08 18:13:32 +02:00
Fabian Freyer
55efc601cb Refactored configure.ac, added pkg-config support 2014-10-08 18:13:31 +02:00
Fabian Freyer
dcbf3fb4d5 autotools: check for ssl.h if pkg-config failed
Some distros provides libssl without openssl.pc.
2014-09-30 16:02:43 +03:00
Fabian Freyer
e2acd98612 autotools: added AC_CONFIG_MACRO_DIR 2014-09-30 16:00:36 +03:00
Dmitry Podgorny
ee4f6d4e3c ctx: fixed memory leak in xmpp_log()
Also fixed 2 bugs:
  - only 1022 bytes of the message is printed when length is 1023.
  - va_end() must be called after va_copy() otherwise we get
    undefined behaviour according to C99.
2014-09-10 01:03:34 +03:00
Dmitry Podgorny
db14f2bd4a auth: fixed memory leaks in _handle_scram_sha1_challenge() 2014-09-09 22:55:23 +03:00
Dmitry Podgorny
e768604533 autotools: fixed libstrophe's version
Repository contains tag 0.8.6, but version in configure.ac is still
0.8.5. So change it to the future release.
2014-09-09 20:54:01 +03:00
Dmitry Podgorny
1afcd485db conn: [style] fixed spacing 2014-09-09 20:53:30 +03:00
Vitaly Takmazov
58613ea7f3 fix MSVC build 2014-09-08 13:41:30 +03:00
Dmitry Podgorny
bf5bf96e95 sha1: removed xmpp_ prefix from SHA1 symbols
Prefix was introduced in a981c0a as a workaround. Now, non-public API is
not exported, so this patch hides SHA1 symbols for dynamic library.
2014-09-07 00:02:14 +03:00
Dmitry Podgorny
529a9bed44 autotools: export only public API for dynamic library 2014-09-06 23:52:42 +03:00
Dmitry Podgorny
fd4f26e5d4 tls_schannel: [style] removed trailing spaces 2014-09-06 23:43:43 +03:00
Dmitry Podgorny
e7f87c652e tls_schannel: [style] use LF for EOL, not CR+LF 2014-09-06 22:32:16 +03:00
Dmitry Podgorny
65d2535302 tls_openssl: removed unused openssl/rand.h 2014-09-06 22:31:53 +03:00
Dmitry Podgorny
a981c0a733 sha1: workaround for name collision with libcrypto
src/sha1.c is used only for internal purposes. So, just add prefix
xmpp_ to the SHA1 symbols.
2014-08-31 01:47:03 +03:00
Dmitry Podgorny
b08625ef4a md5: MD5Transform should be static 2014-08-31 01:46:19 +03:00
Dmitry Podgorny
ea719cd02a SCRAM-SHA-1 authentication mechanism support 2014-08-31 00:44:08 +03:00
Dmitry Podgorny
52dcd26b8c sasl: don't use uninitialized variable
base64_decode() used uninitialized variable when unable to allocate memory.

Reported-by: Fabian Freyer <fabian.freyer@physik.tu-berlin.de>
2014-08-30 15:14:22 +03:00
Dmitry Podgorny
cf361d35fe auth: removed useless static declaration
_handle_open_tls() declared as static function but not defined.
2014-08-26 14:53:15 +03:00
Dmitry Podgorny
077afae693 Added tags to .gitignore
This file is generated by ctags.
2014-08-26 14:26:43 +03:00
Damian Obernikowicz
783bad0897 Fixed memory leak 2014-08-20 00:36:59 +03:00
56 changed files with 1389 additions and 413 deletions

15
.gitignore vendored
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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.
*/ */
/* This example demonstrates basic handler functions by printing out /* This example demonstrates basic handler functions by printing out

View 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.
*/ */
#include <stdio.h> #include <stdio.h>

View 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.
*/ */
/* simple bot example /* simple bot example

97
examples/component.c Normal file
View 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;
}

View 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.
*/ */
/* This example demonstrates basic handler functions by printing out /* This example demonstrates basic handler functions by printing out

14
libstrophe.pc.in Normal file
View 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@

View File

@@ -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

View File

@@ -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;
}

View 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.
*/ */
/** @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, ...);

View 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
@@ -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);
} }

View 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
@@ -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.

View 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
@@ -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) {

View 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
@@ -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

View 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
@@ -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;
} }

View 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

View 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

View 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];

View File

@@ -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);

View 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.
*/ */
#include <stdlib.h> #include <stdlib.h>

View 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.
*/ */
#include "strophe.h" #include "strophe.h"

View File

@@ -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__ */

View 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.
*/ */
/** @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);

View 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
@@ -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;

View 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
@@ -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)
{ {

View File

@@ -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:

View 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
@@ -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
View 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
View 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__ */

View File

@@ -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 {

View File

@@ -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];

View 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

View 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

View 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
@@ -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;

View 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

View 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

View 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

View 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

View 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

View File

@@ -1,15 +1,12 @@
/* tls_openssl.c /* tls_openssl.c
** strophe XMPP client library -- TLS abstraction openssl impl. ** strophe XMPP client library -- TLS abstraction openssl impl.
** **
** Copyright (C) 2005-008 Collecta, Inc. ** Copyright (C) 2005-008 Collecta, Inc.
** **
** 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,8 +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"
#include "sock.h" #include "sock.h"
@@ -55,31 +50,136 @@ int tls_error(tls_t *tls)
return tls->lasterror; return tls->lasterror;
} }
int
convert_ASN1TIME(ASN1_TIME *ansi_time, char* buf, size_t len)
{
BIO *bio = BIO_new(BIO_s_mem());
int rc = ASN1_TIME_print(bio, ansi_time);
if (rc <= 0) {
BIO_free(bio);
return 0;
}
rc = BIO_gets(bio, buf, len);
if (rc <= 0) {
BIO_free(bio);
return 0;
}
BIO_free(bio);
return 1;
}
void
hex_encode(unsigned char* readbuf, void *writebuf, size_t len)
{
size_t i;
for(i=0; i < len; i++) {
char *l = (char*) (2*i + ((intptr_t) writebuf));
sprintf(l, "%02x", readbuf[i]);
}
}
static xmpp_ctx_t *xmppctx;
static void
print_certificate(X509* cert) {
char subj[1024+1];
char issuer[1024+1];
X509_NAME_oneline(X509_get_subject_name(cert), subj, 1024);
X509_NAME_oneline(X509_get_issuer_name(cert), issuer, 1024);
xmpp_debug(xmppctx, "TLS", "SUBJECT : %s", subj);
xmpp_debug(xmppctx, "TLS", "ISSUER : %s", issuer);
}
static int
verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
{
X509 *cert = X509_STORE_CTX_get_current_cert(x509_ctx);
const STACK_OF(X509) *sk = X509_STORE_CTX_get1_chain(x509_ctx);
int slen = sk_num((const _STACK *)sk);
unsigned i;
X509 *certsk;
xmpp_debug(xmppctx, "TLS", "STACK");
for(i=0; i<slen; i++) {
certsk = (X509*) sk_value((const _STACK *)sk, i);
print_certificate(certsk);
}
xmpp_debug(xmppctx, "TLS", "ENDSTACK");
X509_NAME *subject = X509_get_subject_name(cert);
char *nameline = X509_NAME_oneline(subject, NULL, 0);
xmpp_debug(xmppctx, "TLS", "SUBJECT : %s", nameline);
OPENSSL_free(nameline);
X509_NAME *issuer = X509_get_issuer_name(cert);
nameline = X509_NAME_oneline(issuer, NULL, 0);
xmpp_debug(xmppctx, "TLS", "ISSUER : %s", nameline);
OPENSSL_free(nameline);
ASN1_TIME *not_before = X509_get_notBefore(cert);
char not_before_str[128];
int not_before_res = convert_ASN1TIME(not_before, not_before_str, 128);
if (not_before_res) {
xmpp_debug(xmppctx, "TLS", "NOT BEFORE : %s", not_before_str);
}
ASN1_TIME *not_after = X509_get_notAfter(cert);
char not_after_str[128];
int not_after_res = convert_ASN1TIME(not_after, not_after_str, 128);
if (not_after_res) {
xmpp_debug(xmppctx, "TLS", "NOT AFTER : %s", not_after_str);
}
char buf[20];
const EVP_MD *digest = EVP_sha1();
unsigned len;
int rc = X509_digest(cert, digest, (unsigned char*) buf, &len);
if (rc != 0 && len == 20) {
char strbuf[2*20+1];
hex_encode(buf, strbuf, 20);
xmpp_debug(xmppctx, "TLS", "FINGERPRINT : %s", strbuf);
}
if (preverify_ok) {
xmpp_debug(xmppctx, "TLS", "VERIFY SUCCESS");
return 1;
} else {
xmpp_debug(xmppctx, "TLS", "VERIFY FAILED");
int err = X509_STORE_CTX_get_error(x509_ctx);
const char *errstr = X509_verify_cert_error_string(err);
xmpp_debug(xmppctx, "TLS", "ERROR: %s", errstr);
return 1;
}
}
tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock) tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
{ {
xmppctx = ctx;
tls_t *tls = xmpp_alloc(ctx, sizeof(*tls)); tls_t *tls = xmpp_alloc(ctx, sizeof(*tls));
if (tls) { if (tls) {
int ret; int ret;
memset(tls, 0, sizeof(*tls)); memset(tls, 0, sizeof(*tls));
tls->ctx = ctx; tls->ctx = ctx;
tls->sock = sock; tls->sock = sock;
tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL); SSL_CTX_set_client_cert_cb(tls->ssl_ctx, NULL);
SSL_CTX_set_mode (tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); SSL_CTX_set_mode (tls->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
SSL_CTX_set_verify (tls->ssl_ctx, SSL_VERIFY_NONE, NULL); SSL_CTX_set_verify (tls->ssl_ctx, SSL_VERIFY_PEER, verify_callback);
tls->ssl = SSL_new(tls->ssl_ctx);
tls->ssl = SSL_new(tls->ssl_ctx); ret = SSL_set_fd(tls->ssl, sock);
if (ret <= 0) {
ret = SSL_set_fd(tls->ssl, sock); tls->lasterror = SSL_get_error(tls->ssl, ret);
if (ret <= 0) { tls_error(tls);
tls->lasterror = SSL_get_error(tls->ssl, ret); tls_free(tls);
tls_error(tls); tls = NULL;
tls_free(tls); }
tls = NULL;
}
} }
return tls; return tls;
@@ -103,32 +203,35 @@ int tls_start(tls_t *tls)
int ret = -1; int ret = -1;
/* Since we're non-blocking, loop the connect call until it /* Since we're non-blocking, loop the connect call until it
succeeds or fails */ succeeds or fails */
while (ret == -1) { while (ret < 0) {
ret = SSL_connect(tls->ssl); ret = SSL_connect(tls->ssl);
int err = SSL_get_error(tls->ssl, ret);
int recoverable = tls_is_recoverable(err);
/* wait for something to happen on the sock before looping back */ // continue if recoverable
if (ret == -1) { if (recoverable) {
fd_set fds; fd_set fds;
struct timeval tv; struct timeval tv;
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 1000; tv.tv_usec = 1000;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(tls->sock, &fds); FD_SET(tls->sock, &fds);
select(tls->sock + 1, &fds, &fds, NULL, &tv); select(tls->sock + 1, &fds, &fds, NULL, &tv);
} } else {
ret = 1;
}
} }
if (ret <= 0) { if (ret <= 0) {
tls->lasterror = SSL_get_error(tls->ssl, ret); tls->lasterror = SSL_get_error(tls->ssl, ret);
return 0; return 0;
} }
return 1; return 1;
} }
int tls_stop(tls_t *tls) int tls_stop(tls_t *tls)
@@ -138,8 +241,8 @@ int tls_stop(tls_t *tls)
ret = SSL_shutdown(tls->ssl); ret = SSL_shutdown(tls->ssl);
if (ret <= 0) { if (ret <= 0) {
tls->lasterror = SSL_get_error(tls->ssl, ret); tls->lasterror = SSL_get_error(tls->ssl, ret);
return 0; return 0;
} }
return 1; return 1;
@@ -148,9 +251,9 @@ int tls_stop(tls_t *tls)
int tls_is_recoverable(int error) int tls_is_recoverable(int error)
{ {
return (error == SSL_ERROR_NONE || error == SSL_ERROR_WANT_READ return (error == SSL_ERROR_NONE || error == SSL_ERROR_WANT_READ
|| error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_WRITE
|| error == SSL_ERROR_WANT_CONNECT || error == SSL_ERROR_WANT_CONNECT
|| error == SSL_ERROR_WANT_ACCEPT); || error == SSL_ERROR_WANT_ACCEPT);
} }
int tls_pending(tls_t *tls) int tls_pending(tls_t *tls)
@@ -163,7 +266,7 @@ int tls_read(tls_t *tls, void * const buff, const size_t len)
int ret = SSL_read(tls->ssl, buff, len); int ret = SSL_read(tls->ssl, buff, len);
if (ret <= 0) { if (ret <= 0) {
tls->lasterror = SSL_get_error(tls->ssl, ret); tls->lasterror = SSL_get_error(tls->ssl, ret);
} }
return ret; return ret;
@@ -174,7 +277,7 @@ int tls_write(tls_t *tls, const void * const buff, const size_t len)
int ret = SSL_write(tls->ssl, buff, len); int ret = SSL_write(tls->ssl, buff, len);
if (ret <= 0) { if (ret <= 0) {
tls->lasterror = SSL_get_error(tls->ssl, ret); tls->lasterror = SSL_get_error(tls->ssl, ret);
} }
return ret; return ret;

View 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
@@ -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;

View 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
@@ -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 */

View 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,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);

View 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 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,

View File

@@ -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

View 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);

View 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.
*/ */
#include <stdio.h> #include <stdio.h>

View 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.
*/ */
#include <stdio.h> #include <stdio.h>

View 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.
*/ */
#include <stdlib.h> #include <stdlib.h>

View 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.
*/ */
#include <stdio.h> #include <stdio.h>

View 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.
*/ */
#include <stdio.h> #include <stdio.h>

View 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.
*/ */
#include <stdio.h> #include <stdio.h>