69 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
Dmitry Podgorny
d693cc6d15 autotools: check for expat.h if pkg-config failed
Some distros provides libexpat without expat.pc. So PKG_CHECK_MODULES
fails even if libexpat is installed. To fix this AC_CHECK_HEADER added
back.
2014-08-08 19:49:46 +03:00
Fabian Freyer
46f371b311 autotools: cleaned up configure.ac and Makefile.am 2014-08-08 19:42:33 +03:00
Fabian Freyer
97c6e6d8d4 autotools: removed libresov check for freebsd. 2014-08-08 19:40:01 +03:00
Dmytro Podgornyi
9af64e244e examples/bot: removed non-standard strcpy_s/strcat_s
strncpy/strncat must be used instead. But in this case they don't make
sense, because string has enough space.
2014-08-08 18:27:02 +03:00
Dariusz Dwornikowski
90075b5feb Merge pull request #29 from fabianfreyer/fix-readme-homebrew
Updated homebrew install instructions
2014-08-08 15:30:19 +02:00
Fabian Freyer
519edba5de Added homebrew install instructions 2014-08-08 15:17:15 +02:00
Dariusz Dwornikowski
7255b49623 Merge pull request #16 from h0ru5/bot_fixed
patch for bot example to avoid crash when messages without type are sent
2014-08-08 08:35:51 +02:00
James Booth
2dc357438b Use dependency on libstophe.la to enable parallel make 2014-08-07 21:03:04 +01:00
h0ru5
4111cf772a patch to avoid crash when messages without type are sent 2014-01-06 22:46:16 +01:00
57 changed files with 1410 additions and 422 deletions

15
.gitignore vendored
View File

@@ -22,22 +22,29 @@ autom4te.cache
.sconsign*
src/*.o
examples/*.o
tests/*.o
tests/check_parser
*.a
*.pc
*.tar.gz
*.zip
docs/html
TAGS
examples/basic
tags
examples/active
examples/roster
examples/basic
examples/bot
examples/component
examples/roster
test_stamp
test-suite.log
tests/*.o
tests/*.log
tests/*.trs
tests/check_parser
tests/test_base64
tests/test_ctx
tests/test_hash
tests/test_jid
tests/test_sasl
tests/test_sock
m4/
libstrophe.project

View File

@@ -1,3 +1,10 @@
0.8.5
- libtoolize to generate .so
0.8.8
- 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,27 +1,32 @@
AUTOMAKE_OPTIONS = subdir-objects
ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS = -g -Wall
PARSER_CFLAGS=@PARSER_CFLAGS@
PARSER_LIBS=@PARSER_LIBS@
SSL_LIBS = -lssl -lcrypto -lz
SSL_CFLAGS = @openssl_CFLAGS@
SSL_LIBS = @openssl_LIBS@
STROPHE_FLAGS = -I$(top_srcdir)
STROPHE_LIBS = -lstrophe $(PARSER_LIBS) $(SSL_LIBS)
STROPHE_LIBS = libstrophe.la
## Main build targets
lib_LTLIBRARIES = libstrophe.la
libstrophe_la_CFLAGS=$(STROPHE_FLAGS) $(PARSER_CFLAGS)
libstrophe_la_LDFLAGS=$(SSL_LIBS) $(PARSER_LIBS)
libstrophe_la_CFLAGS = $(SSL_CFLAGS) $(STROPHE_FLAGS) $(PARSER_CFLAGS)
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 \
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/tls_openssl.c src/util.c \
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
libstrophe_la_SOURCES += src/parser_expat.c
@@ -32,10 +37,12 @@ endif
include_HEADERS = strophe.h
noinst_HEADERS = strophepp.h
pkgconfig_DATA = libstrophe.pc
EXTRA_DIST = docs
## 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_CFLAGS = $(STROPHE_FLAGS)
examples_active_LDADD = $(STROPHE_LIBS)
@@ -47,7 +54,10 @@ examples_basic_CFLAGS = $(STROPHE_FLAGS)
examples_basic_LDADD = $(STROPHE_LIBS)
examples_bot_SOURCES = examples/bot.c
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
@@ -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) \
-I$(top_srcdir)/src
tests_check_parser_LDADD = @check_LIBS@ $(STROPHE_LIBS)
tests_check_parser_LDFLAGS = -static

View File

@@ -56,10 +56,9 @@ check package.
### OS X (with Homebrew package manager)
You can install the requirements with:
You can install libstrophe with:
brew install expat
brew install check
brew install libstrophe
## Documentation

View File

@@ -1,3 +1,5 @@
#!/bin/sh
# Some versions of aclocal fail if m4/ doesn't exist
mkdir -p m4
autoreconf -i

View File

@@ -1,11 +1,26 @@
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])
LT_INIT([dlopen])
AC_PROG_CC
AM_PROG_CC_C_O
PKG_PROG_PKG_CONFIG
AC_CANONICAL_HOST
AS_CASE([$host_os],
[freebsd*], [PLATFORM="freebsd"],
[PLATFORM="nix"])
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])]
)])
AC_CHECK_HEADER(openssl/ssl.h, [], [AC_MSG_ERROR([couldn't find openssl headers, openssl required])])
PKG_CHECK_MODULES([check], [check >= 0.9.4], [], [AC_MSG_WARN([libcheck not found; unit tests will not be compilable])])
AC_ARG_WITH([libxml2],
@@ -15,41 +30,79 @@ AC_ARG_WITH([libxml2],
if test "x$with_libxml2" != xno; then
PKG_CHECK_MODULES([libxml2], [libxml-2.0 >= 2.7],
[with_libxml2=yes], [dummy=1])
if test "x$with_libxml2" != xyes; then
old_CFLAGS=$CFLAGS
CFLAGS="-I /usr/include/libxml2"
AC_CHECK_HEADER([libxml/parser.h],
[with_libxml2=yes; libxml2_CFLAGS="-I /usr/include/libxml2"; libxml2_LIBS="-lxml2"],
[AC_MSG_ERROR([couldn't find libxml2])])
CFLAGS=$old_CFLAGS
fi
[
with_libxml2=yes
PC_REQUIRES+=(libxml-2.0)
],
[
old_CFLAGS=$CFLAGS
CFLAGS="-I${includedir}/libxml2"
AC_CHECK_HEADER([libxml/parser.h],
[
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
AC_CHECK_HEADER(expat.h, [], [AC_MSG_ERROR([couldn't find expat headers; expat required])])
PKG_CHECK_MODULES([expat], [expat >= 2.0.0],
[PC_REQUIRES+=(expat)],
[AC_CHECK_HEADER([expat.h],
[
expat_LIBS="-lexpat"
PC_LIBS+=($expat_LIBS)
],
[AC_MSG_ERROR([expat not found; expat required.])]
)
])
fi
if test "x$with_libxml2" = xyes; then
with_parser=libxml2
PARSER_NAME=libxml2
PARSER_CFLAGS=\$\(libxml2_CFLAGS\)
PARSER_LIBS=\$\(libxml2_LIBS\)
PARSER_CFLAGS=$libxml2_CFLAGS
PARSER_LIBS=$libxml2_LIBS
else
with_parser=expat
PARSER_NAME=expat
PARSER_CFLAGS=
PARSER_LIBS=-lexpat
PARSER_CFLAGS=$expat_CFLAGS
PARSER_LIBS=$expat_LIBS
fi
AC_MSG_NOTICE([libstrophe will use the $with_parser XML parser])
AC_SEARCH_LIBS([socket], [socket])
AC_LINK_IFELSE([AC_LANG_CALL([#include <resolv.h>], [res_query])], [],[LIBS="$LIBS -lresolv"])
if test "x$PLATFORM" != xfreebsd; then
AC_CHECK_LIB([resolv], [res_query], [],
[AC_CHECK_LIB([resolv], [__res_query], [],
[AC_MSG_ERROR([libresolv not found; libresolv required.])])])
PC_LIBS+=(-lresolv)
else
AC_MSG_NOTICE([skipping libresolv checks for freebsd])
fi
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])
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_CFLAGS)
AC_SUBST(PARSER_LIBS)
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([Makefile libstrophe.pc])
AC_OUTPUT

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/* 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
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <stdio.h>

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/* simple bot example
@@ -77,7 +74,7 @@ int message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void
xmpp_ctx_t *ctx = (xmpp_ctx_t*)userdata;
if(!xmpp_stanza_get_child_by_name(stanza, "body")) return 1;
if(!strcmp(xmpp_stanza_get_attribute(stanza, "type"), "error")) return 1;
if(xmpp_stanza_get_attribute(stanza, "type") !=NULL && !strcmp(xmpp_stanza_get_attribute(stanza, "type"), "error")) return 1;
intext = xmpp_stanza_get_text(xmpp_stanza_get_child_by_name(stanza, "body"));

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
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/* 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/
Source0: libstrophe_git.tar.gz
BuildRequires: automake
BuildRequires: libtool
BuildRequires: openssl-devel
BuildRequires: expat-devel
Requires: expat
Requires: expat
%description
XMPP library in C
%package devel
Summary: Headers and libraries for building apps that use libstrophe
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}
%description devel
This package contains headers and libraries required to build applications that
use the strophe XMPP library.
%prep
%setup -n libstrophe
./bootstrap.sh
@@ -25,8 +37,21 @@ make %{?_smp_mflags}
%install
make install DESTDIR=%{buildroot}
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%defattr(-,root,root,-)
%{_libdir}/libstrophe.so*
%doc
%files devel
%defattr(-,root,root,-)
%{_libdir}/libstrophe.a
%{_libdir}/libstrophe.la
%{_libdir}/pkgconfig/libstrophe.pc
%{_includedir}/strophe.h
%doc
%changelog

View File

@@ -1,30 +1,29 @@
/* auth.c
** 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
** implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
/** @file
* Authentication function and handlers.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "strophe.h"
#include "common.h"
#include "sasl.h"
#include "sha1.h"
#ifdef _WIN32
#ifdef _MSC_VER
#define strcasecmp stricmp
#endif
@@ -54,10 +53,21 @@
*/
#define LEGACY_TIMEOUT 15000 /* 15 seconds */
#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 _handle_open_tls(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,
void * const userdata);
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,
xmpp_stanza_t * const stanza,
void * const userdata);
static int _handle_scram_sha1_challenge(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza,
void * const userdata);
static char *_make_scram_sha1_init_msg(xmpp_conn_t * const conn);
static int _handle_missing_features_sasl(xmpp_conn_t * const conn,
void * const userdata);
@@ -88,6 +102,8 @@ static int _handle_session(xmpp_conn_t * const conn,
void * const userdata);
static int _handle_missing_session(xmpp_conn_t * const conn,
void * const userdata);
static int _handle_missing_handshake(xmpp_conn_t * const conn,
void * const userdata);
/* stream:error handler */
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 */
if (conn->stream_error) {
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);
}
@@ -221,14 +237,16 @@ static int _handle_features(xmpp_conn_t * const conn,
/* check for SASL */
child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
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)) {
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);
if (strcasecmp(text, "PLAIN") == 0)
conn->sasl_support |= SASL_MASK_PLAIN;
else if (strcasecmp(text, "DIGEST-MD5") == 0)
conn->sasl_support |= SASL_MASK_DIGESTMD5;
else if (strcasecmp(text, "SCRAM-SHA-1") == 0)
conn->sasl_support |= SASL_MASK_SCRAMSHA1;
else if (strcasecmp(text, "ANONYMOUS") == 0)
conn->sasl_support |= SASL_MASK_ANONYMOUS;
@@ -238,7 +256,7 @@ static int _handle_features(xmpp_conn_t * const conn,
}
_auth(conn);
return 0;
}
@@ -263,7 +281,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
{
char *name;
name = xmpp_stanza_get_name(stanza);
xmpp_debug(conn->ctx, "xmpp",
xmpp_debug(conn->ctx, "xmpp",
"handle proceedtls called for %s", name);
if (strcmp(name, "proceed") == 0) {
@@ -277,7 +295,7 @@ static int _handle_proceedtls_default(xmpp_conn_t * const conn,
tls_free(conn->tls);
conn->tls = NULL;
conn->tls_failed = 1;
/* failed tls spoils the connection, so disconnect */
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 */
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);
/* fall back to next auth method */
_auth(conn);
} else if (strcmp(name, "success") == 0) {
/* 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);
/* reset parser */
@@ -355,10 +373,10 @@ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn,
if (!auth) {
disconnect_mem_error(conn);
return 0;
}
}
xmpp_stanza_set_name(auth, "response");
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
authdata = xmpp_stanza_new(conn->ctx);
if (!authdata) {
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_release(authdata);
handler_add(conn, _handle_digestmd5_rspauth,
handler_add(conn, _handle_digestmd5_rspauth,
XMPP_NS_SASL, NULL, NULL, NULL);
xmpp_send(conn, auth);
@@ -404,7 +422,7 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
if (!auth) {
disconnect_mem_error(conn);
return 0;
}
}
xmpp_stanza_set_name(auth, "response");
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
xmpp_send(conn, auth);
@@ -416,6 +434,117 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t * const conn,
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)
{
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_ns(starttls, XMPP_NS_TLS);
}
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_attribute(auth, "mechanism", mechanism);
}
return auth;
}
/* authenticate the connection
* this may get called multiple times. if any auth method fails,
/* authenticate the connection
* this may get called multiple times. if any auth method fails,
* this will get called again until one auth method succeeds or every
* method fails
* method fails
*/
static void _auth(xmpp_conn_t * const conn)
{
xmpp_stanza_t *auth, *authdata, *query, *child, *iq;
char *str, *authid;
char *scram_init;
int anonjid;
/* 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;
}
handler_add(conn, _handle_proceedtls_default,
handler_add(conn, _handle_proceedtls_default,
XMPP_NS_TLS, NULL, NULL, NULL);
xmpp_send(conn, auth);
@@ -514,9 +644,54 @@ static void _auth(xmpp_conn_t * const conn)
/* SASL ANONYMOUS was tried, unset flag */
conn->sasl_support &= ~SASL_MASK_ANONYMOUS;
} else if (anonjid) {
xmpp_error(conn->ctx, "auth",
xmpp_error(conn->ctx, "auth",
"No node in JID, and SASL ANONYMOUS unsupported.");
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) {
auth = _make_sasl_auth(conn, "DIGEST-MD5");
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_send(conn, auth);
@@ -543,7 +718,7 @@ static void _auth(xmpp_conn_t * const conn)
if (!authdata) {
disconnect_mem_error(conn);
return;
}
}
authid = _get_authid(conn);
if (!authid) {
disconnect_mem_error(conn);
@@ -556,6 +731,7 @@ static void _auth(xmpp_conn_t * const conn)
}
xmpp_stanza_set_text(authdata, str);
xmpp_free(conn->ctx, str);
xmpp_free(conn->ctx, authid);
xmpp_stanza_add_child(auth, authdata);
xmpp_stanza_release(authdata);
@@ -570,7 +746,7 @@ static void _auth(xmpp_conn_t * const conn)
conn->sasl_support &= ~SASL_MASK_PLAIN;
} else if (conn->type == XMPP_CLIENT) {
/* legacy client authentication */
iq = xmpp_stanza_new(conn->ctx);
if (!iq) {
disconnect_mem_error(conn);
@@ -656,7 +832,7 @@ static void _auth(xmpp_conn_t * const conn)
} else {
xmpp_stanza_release(authdata);
xmpp_stanza_release(iq);
xmpp_error(conn->ctx, "auth",
xmpp_error(conn->ctx, "auth",
"Cannot authenticate without resource");
xmpp_disconnect(conn);
return;
@@ -665,7 +841,7 @@ static void _auth(xmpp_conn_t * const conn)
xmpp_stanza_release(authdata);
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);
xmpp_send(conn, iq);
@@ -677,7 +853,7 @@ static void _auth(xmpp_conn_t * const conn)
/** Set up handlers at stream start.
* This function is called internally to Strophe for handling the opening
* of an XMPP stream. It's called by the parser when a stream is opened
* 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
* of Strophe.
*
@@ -690,11 +866,11 @@ void auth_handle_open(xmpp_conn_t * const conn)
/* setup handler for stream:error */
handler_add(conn, _handle_error,
NULL, "stream:error", NULL, NULL);
XMPP_NS_STREAMS, "error", NULL, NULL);
/* setup handlers for incoming <stream:features> */
handler_add(conn, _handle_features,
NULL, "stream:features", NULL, NULL);
XMPP_NS_STREAMS, "features", NULL, NULL);
handler_add_timed(conn, _handle_missing_features,
FEATURES_TIMEOUT, NULL);
}
@@ -706,7 +882,7 @@ static void _handle_open_sasl(xmpp_conn_t * const conn)
/* setup stream:features handlers */
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,
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 (conn->bind_required) {
/* bind resource */
/* setup response handlers */
handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL);
handler_add_timed(conn, _handle_missing_bind,
@@ -771,7 +947,7 @@ static int _handle_features_sasl(xmpp_conn_t * const conn,
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 */
if (resource) {
res = xmpp_stanza_new(conn->ctx);
@@ -822,7 +998,7 @@ static int _handle_missing_features_sasl(xmpp_conn_t * const conn,
xmpp_disconnect(conn);
return 0;
}
static int _handle_bind(xmpp_conn_t * const conn,
xmpp_stanza_t * const stanza,
void * const userdata)
@@ -854,7 +1030,7 @@ static int _handle_bind(xmpp_conn_t * const conn,
if (conn->session_required) {
/* setup response handlers */
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);
/* send session request */
@@ -885,9 +1061,9 @@ static int _handle_bind(xmpp_conn_t * const conn,
xmpp_stanza_release(iq);
} else {
conn->authenticated = 1;
/* call connection handler */
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL,
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL,
conn->userdata);
}
} else {
@@ -924,7 +1100,7 @@ static int _handle_session(xmpp_conn_t * const conn,
xmpp_debug(conn->ctx, "xmpp", "Session establishment successful.");
conn->authenticated = 1;
/* call connection handler */
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
} else {
@@ -987,3 +1163,96 @@ static int _handle_missing_legacy(xmpp_conn_t * const conn,
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
** implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -21,12 +18,10 @@
#include <stdio.h>
#include <stdarg.h>
#ifndef _WIN32
#include <stdint.h>
#endif
#include "strophe.h"
#include "ostypes.h"
#include "sock.h"
#include "tls.h"
#include "hash.h"
@@ -147,6 +142,7 @@ struct _xmpp_handlist_t {
#define SASL_MASK_PLAIN 0x01
#define SASL_MASK_DIGESTMD5 0x02
#define SASL_MASK_ANONYMOUS 0x04
#define SASL_MASK_SCRAMSHA1 0x08
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 */
void auth_handle_open(xmpp_conn_t * const conn);
void auth_handle_component_open(xmpp_conn_t * const conn);
/* replacement snprintf and vsnprintf */
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
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -270,7 +267,7 @@ int xmpp_conn_release(xmpp_conn_t * const conn)
if (conn->domain) xmpp_free(ctx, conn->domain);
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->stream_id) xmpp_free(ctx, conn->stream_id);
if (conn->lang) xmpp_free(ctx, conn->lang);
@@ -442,6 +439,73 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
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.
* 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.
@@ -684,6 +748,7 @@ static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
size_t pos;
int len;
int i;
char *attr;
if (!attrs) return;
@@ -692,10 +757,11 @@ static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
if (len < 0) return;
pos += len;
for (i = 0; attrs[i]; i += 2) {
attr = parser_attr_name(conn->ctx, attrs[i]);
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;
pos += len;
}
@@ -725,7 +791,7 @@ static void _handle_stream_start(char *name, char **attrs,
xmpp_conn_t *conn = (xmpp_conn_t *)userdata;
char *id;
if (strcmp(name, "stream:stream") != 0) {
if (strcmp(name, "stream")) {
printf("name = %s\n", name);
xmpp_error(conn->ctx, "conn", "Server did not open valid stream.");
conn_disconnect(conn);
@@ -743,7 +809,7 @@ static void _handle_stream_start(char *name, char **attrs,
conn_disconnect(conn);
}
}
/* call stream open handler */
conn->open_handler(conn);
}

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -252,29 +249,34 @@ void xmpp_log(const xmpp_ctx_t * const ctx,
char *buf;
va_list copy;
buf = smbuf;
va_copy(copy, ap);
ret = xmpp_vsnprintf(buf, 1023, fmt, ap);
if (ret > 1023) {
ret = xmpp_vsnprintf(smbuf, sizeof(smbuf), fmt, ap);
if (ret >= (int)sizeof(smbuf)) {
buf = (char *)xmpp_alloc(ctx, ret + 1);
if (!buf) {
buf = NULL;
xmpp_error(ctx, "log", "Failed allocating memory for log message.");
va_end(copy);
va_end(copy);
return;
}
oldret = ret;
ret = xmpp_vsnprintf(buf, ret + 1, fmt, copy);
if (ret > oldret) {
xmpp_error(ctx, "log", "Unexpected error");
xmpp_free(ctx, buf);
va_end(copy);
return;
}
} else {
va_end(copy);
buf = smbuf;
}
va_end(copy);
if (ctx->log->handler)
ctx->log->handler(ctx->log->userdata, level, area, buf);
if (buf != smbuf)
xmpp_free(ctx, buf);
}
/** 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
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -40,11 +37,14 @@
#ifndef _WIN32
#include <sys/select.h>
#include <errno.h>
#include <unistd.h>
#define _sleep(x) usleep(x*1000)
#else
#include <winsock2.h>
#define ETIMEDOUT WSAETIMEDOUT
#define ECONNRESET WSAECONNRESET
#define ECONNABORTED WSAECONNABORTED
#define _sleep(x) Sleep(x)
#endif
#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);
}
if (conn->sock > max) max = conn->sock;
if (conn->state != XMPP_STATE_DISCONNECTED && conn->sock > max)
max = conn->sock;
connitem = connitem->next;
}
/* 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 */
if (ret < 0) {

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -23,14 +20,9 @@
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <stdint.h>
#else
#include "ostypes.h"
#endif
#include "strophe.h"
#include "common.h"
#include "ostypes.h"
/** Fire off all stanza handlers that match.
* 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
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -250,12 +247,13 @@ const char * hash_iter_next(hash_iterator_t *iter)
{
hash_t *table = iter->table;
hashentry_t *entry = iter->entry;
int i = iter->index + 1;
int i;
/* advance until we find the next entry */
if (entry != NULL) entry = entry->next;
if (entry == NULL) {
/* we're off the end of list, search for a new entry */
i = iter->index + 1;
while (i < iter->table->length) {
entry = table->entries[i];
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! */
return NULL;
}

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -43,6 +43,9 @@
(cp)[3] = ((value) >> 24) & 0xFF; \
} 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
* 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
* the data and converts bytes into longwords for this routine.
*/
void MD5Transform(uint32_t buf[4], const unsigned char inext[64],
struct MD5Context *ctx)
static void MD5Transform(uint32_t buf[4], const unsigned char inext[64],
struct MD5Context *ctx)
{
register uint32_t a, b, c, d, i;
uint32_t in[16];

View File

@@ -11,15 +11,8 @@
#ifndef 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 */
#if defined(_MSC_VER) /* Microsoft Visual C++ */
typedef unsigned int uint32_t;
#else
#include <stdint.h>
#endif
#include "ostypes.h"
struct MD5Context {
uint32_t buf[4];
@@ -31,8 +24,6 @@ void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf,
uint32_t len);
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
void MD5DumpBytes(unsigned char *b, int len);

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <stdlib.h>

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include "strophe.h"

View File

@@ -7,10 +7,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -20,8 +17,18 @@
#ifndef __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;
#else
#include <stdint.h>
#endif
#endif /* __LIBSTROPHE_OSTYPES_H__ */

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express or
** implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -37,6 +34,7 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
parser_stanza_callback stanzacb,
void *userdata);
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_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
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -26,6 +23,9 @@
#include "common.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 {
xmpp_ctx_t *ctx;
XML_Parser expat;
@@ -37,23 +37,71 @@ struct _parser_t {
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)
{
char *attr;
int i;
if (!attrs) return;
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,
const XML_Char *name,
const XML_Char *nsname,
const XML_Char **attrs)
{
parser_t *parser = (parser_t *)userdata;
xmpp_stanza_t *child;
char *ns, *name;
ns = _xml_namespace(parser->ctx, nsname);
name = _xml_name(parser->ctx, nsname);
if (parser->depth == 0) {
/* notify the owner */
@@ -74,6 +122,8 @@ static void _start_element(void *userdata,
}
xmpp_stanza_set_name(parser->stanza, name);
_set_attributes(parser->stanza, attrs);
if (ns)
xmpp_stanza_set_ns(parser->stanza, ns);
} else {
/* starting a child of parser->stanza */
child = xmpp_stanza_new(parser->ctx);
@@ -82,6 +132,8 @@ static void _start_element(void *userdata,
}
xmpp_stanza_set_name(child, name);
_set_attributes(child, attrs);
if (ns)
xmpp_stanza_set_ns(child, ns);
/* add child to parent */
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++;
}
@@ -165,6 +220,11 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
return parser;
}
char* parser_attr_name(xmpp_ctx_t *ctx, char *nsname)
{
return _xml_name(ctx, nsname);
}
/* free a parser */
void parser_free(parser_t *parser)
{
@@ -183,7 +243,7 @@ int parser_reset(parser_t *parser)
if (parser->stanza)
xmpp_stanza_release(parser->stanza);
parser->expat = XML_ParserCreate(NULL);
parser->expat = XML_ParserCreateNS(NULL, NAMESPACE_SEP);
if (!parser->expat) return 0;
parser->depth = 0;

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -39,28 +36,91 @@ struct _parser_t {
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;
for (i = 0; attrs[i]; i += 2) {
xmpp_stanza_set_attribute(stanza, (const char *)attrs[i], (const char *)attrs[i+1]);
/* SAX2 uses array of localname/prefix/uri/value_begin/value_end */
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,
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;
xmpp_stanza_t *child;
char **cbattrs;
if (parser->depth == 0) {
/* notify the owner */
if (parser->startcb)
parser->startcb((char *)name, (char **)attrs,
cbattrs = _convert_attrs(parser, nattrs, attrs);
parser->startcb((char *)name, cbattrs,
parser->userdata);
_free_cbattrs(parser, cbattrs);
} else {
/* build stanzas at depth 1 */
if (!parser->stanza && parser->depth != 1) {
@@ -74,7 +134,9 @@ static void _start_element(void *userdata,
/* FIXME: can't allocate, disconnect */
}
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 {
/* starting a child of conn->stanza */
child = xmpp_stanza_new(parser->ctx);
@@ -82,7 +144,9 @@ static void _start_element(void *userdata,
/* FIXME: can't allocate, disconnect */
}
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 */
xmpp_stanza_add_child(parser->stanza, child);
@@ -98,7 +162,8 @@ static void _start_element(void *userdata,
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;
@@ -156,8 +221,9 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
parser->ctx = ctx;
parser->xmlctx = NULL;
memset(&parser->handlers, 0, sizeof(xmlSAXHandler));
parser->handlers.startElement = _start_element;
parser->handlers.endElement = _end_element;
parser->handlers.initialized = XML_SAX2_MAGIC;
parser->handlers.startElementNs = _start_element;
parser->handlers.endElementNs = _end_element;
parser->handlers.characters = _characters;
parser->startcb = startcb;
parser->endcb = endcb;
@@ -172,6 +238,11 @@ parser_t *parser_new(xmpp_ctx_t *ctx,
return parser;
}
char* parser_attr_name(xmpp_ctx_t *ctx, char *nsname)
{
return xmpp_strdup(ctx, nsname);
}
/* free a parser */
void parser_free(parser_t *parser)
{

View File

@@ -6,36 +6,26 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
* SASL authentication.
*/
#include <stdlib.h>
#include <string.h>
#include "strophe.h"
#include "common.h"
#include "ostypes.h"
#include "sasl.h"
#include "md5.h"
#include "sha1.h"
#include "scram.h"
/* make sure the stdint.h types are available */
#if defined(_MSC_VER) /* Microsoft Visual C++ */
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>
#ifdef _WIN32
#define strtok_r strtok_s
#endif
@@ -360,6 +350,113 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
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 */
@@ -552,8 +649,8 @@ unsigned char *base64_decode(xmpp_ctx_t *ctx,
if (hextet != 64) goto _base64_decode_error;
break;
}
*d = '\0';
}
*d = '\0';
return dbuf;
_base64_decode_error:

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -26,6 +23,9 @@
char *sasl_plain(xmpp_ctx_t *ctx, const char *authid, const char *password);
char *sasl_digest_md5(xmpp_ctx_t *ctx, const char *challenge,
const char *jid, const char *password);
char *sasl_scram_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 */

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>
/* make sure the stdint.h types are available */
#if defined(_MSC_VER) /* Microsoft Visual C++ */
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 "ostypes.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))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
/* FIXME: can we do this in an endian-proof way? */
#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 blk0(i) (block->l[i] = host_to_be(block->l[i]))
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
@@ -139,8 +122,28 @@ void SHAPrintContext(SHA1_CTX *context, char *msg){
}
#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. */
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;
typedef union {

View File

@@ -12,6 +12,9 @@
extern "C" {
#endif
/* make sure the stdint.h types are available */
#include "ostypes.h"
typedef struct {
uint32_t state[5];
uint32_t count[2];

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -320,6 +317,20 @@ static int _render_stanza_recursive(xmpp_stanza_t *stanza,
if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
iter = hash_iter_new(stanza->attributes);
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,
(char *)hash_get(stanza->attributes, key));
if (tmp == NULL) return XMPP_EMEM;

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -1,15 +1,12 @@
/* tls_openssl.c
** 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
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -25,8 +22,6 @@
#endif
#include <openssl/ssl.h>
#include <openssl/rand.h>
#include "common.h"
#include "tls.h"
#include "sock.h"
@@ -55,31 +50,136 @@ int tls_error(tls_t *tls)
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)
{
xmppctx = ctx;
tls_t *tls = xmpp_alloc(ctx, sizeof(*tls));
if (tls) {
int ret;
memset(tls, 0, sizeof(*tls));
memset(tls, 0, sizeof(*tls));
tls->ctx = ctx;
tls->sock = sock;
tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
tls->ctx = ctx;
tls->sock = sock;
tls->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
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_verify (tls->ssl_ctx, SSL_VERIFY_NONE, 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_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) {
tls->lasterror = SSL_get_error(tls->ssl, ret);
tls_error(tls);
tls_free(tls);
tls = NULL;
}
ret = SSL_set_fd(tls->ssl, sock);
if (ret <= 0) {
tls->lasterror = SSL_get_error(tls->ssl, ret);
tls_error(tls);
tls_free(tls);
tls = NULL;
}
}
return tls;
@@ -103,32 +203,35 @@ int tls_start(tls_t *tls)
int ret = -1;
/* Since we're non-blocking, loop the connect call until it
succeeds or fails */
while (ret == -1) {
ret = SSL_connect(tls->ssl);
succeeds or fails */
while (ret < 0) {
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 */
if (ret == -1) {
fd_set fds;
struct timeval tv;
// continue if recoverable
if (recoverable) {
fd_set fds;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 1000;
tv.tv_sec = 0;
tv.tv_usec = 1000;
FD_ZERO(&fds);
FD_SET(tls->sock, &fds);
select(tls->sock + 1, &fds, &fds, NULL, &tv);
}
FD_ZERO(&fds);
FD_SET(tls->sock, &fds);
select(tls->sock + 1, &fds, &fds, NULL, &tv);
} else {
ret = 1;
}
}
if (ret <= 0) {
tls->lasterror = SSL_get_error(tls->ssl, ret);
return 0;
tls->lasterror = SSL_get_error(tls->ssl, ret);
return 0;
}
return 1;
}
int tls_stop(tls_t *tls)
@@ -138,8 +241,8 @@ int tls_stop(tls_t *tls)
ret = SSL_shutdown(tls->ssl);
if (ret <= 0) {
tls->lasterror = SSL_get_error(tls->ssl, ret);
return 0;
tls->lasterror = SSL_get_error(tls->ssl, ret);
return 0;
}
return 1;
@@ -148,9 +251,9 @@ int tls_stop(tls_t *tls)
int tls_is_recoverable(int error)
{
return (error == SSL_ERROR_NONE || error == SSL_ERROR_WANT_READ
|| error == SSL_ERROR_WANT_WRITE
|| error == SSL_ERROR_WANT_CONNECT
|| error == SSL_ERROR_WANT_ACCEPT);
|| error == SSL_ERROR_WANT_WRITE
|| error == SSL_ERROR_WANT_CONNECT
|| error == SSL_ERROR_WANT_ACCEPT);
}
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);
if (ret <= 0) {
tls->lasterror = SSL_get_error(tls->ssl, ret);
tls->lasterror = SSL_get_error(tls->ssl, 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);
if (ret <= 0) {
tls->lasterror = SSL_get_error(tls->ssl, ret);
tls->lasterror = SSL_get_error(tls->ssl, ret);
}
return ret;

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -75,11 +72,11 @@ tls_t *tls_new(xmpp_ctx_t *ctx, sock_t sock)
SecPkgCred_CipherStrengths spc_cs;
SecPkgCred_SupportedProtocols spc_sp;
OSVERSIONINFO osvi;
memset(&osvi, 0, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(osvi);
OSVERSIONINFO osvi;
memset(&osvi, 0, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(&osvi);
/* 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;
}
if (!(pInitSecurityInterface =
if (!(pInitSecurityInterface =
(void *)GetProcAddress(tls->hsec32, "InitSecurityInterfaceA"))) {
tls_free(tls);
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
* schannel support there */
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_ALGS, &spc_sa);
if (ret != SEC_E_OK)
{
tls_free(tls);
return NULL;
}
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_CIPHER_STRENGTHS, &spc_cs);
if (ret != SEC_E_OK)
{
tls_free(tls);
return NULL;
}
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_PROTOCOLS, &spc_sp);
if (ret != SEC_E_OK)
{
tls_free(tls);
return NULL;
}
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_ALGS, &spc_sa);
if (ret != SEC_E_OK)
{
tls_free(tls);
return NULL;
}
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_CIPHER_STRENGTHS, &spc_cs);
if (ret != SEC_E_OK)
{
tls_free(tls);
return NULL;
}
ret = tls->sft->QueryCredentialsAttributes(&(tls->hcred), SECPKG_ATTR_SUPPORTED_PROTOCOLS, &spc_sp);
if (ret != SEC_E_OK)
{
tls_free(tls);
return NULL;
}
return tls;
}
@@ -196,7 +193,7 @@ void tls_free(tls_t *tls)
FreeLibrary(tls->hsec32);
tls->hsec32 = NULL;
}
xmpp_free(tls->ctx, tls);
return;
}
@@ -360,7 +357,7 @@ int tls_start(tls_t *tls)
return 0;
}
tls->sft->QueryContextAttributes(&(tls->hctxt), SECPKG_ATTR_STREAM_SIZES,
tls->sft->QueryContextAttributes(&(tls->hctxt), SECPKG_ATTR_STREAM_SIZES,
&(tls->spcss));
tls->recvbuffermaxlen = tls->spcss.cbHeader + tls->spcss.cbMaximumMessage
@@ -401,7 +398,7 @@ int tls_is_recoverable(int error)
int tls_pending(tls_t *tls) {
// There are 3 cases:
// - there is data in ready buffer, so it is by default pending
// - there is data in recv buffer. If it is not decrypted yet, means it
// - 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
// on the physical connection
// - 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);
if (read == -1) {
if (tls_is_recoverable(tls->lasterror)) {
if (tls_is_recoverable(tls->lasterror)) {
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 */
bytes = sock_read(tls->sock, tls->recvbuffer + tls->recvbufferpos,
tls->recvbuffermaxlen - tls->recvbufferpos);
if (bytes == 0) {
tls->lasterror = WSAECONNRESET;
return -1;
}
}
if (bytes == -1) {
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);
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->readybufferlen = sbdec[1].cbBuffer;
/* 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))) {
return -1;
}
}
if (remain > tls->spcss.cbMaximumMessage) {
sent += tls->spcss.cbMaximumMessage;
remain -= tls->spcss.cbMaximumMessage;

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -24,11 +21,11 @@
#else
#include <sys/time.h>
#include <time.h>
#include <stdint.h>
#endif
#include "strophe.h"
#include "common.h"
#include "ostypes.h"
#include "util.h"
/** 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
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -19,11 +16,7 @@
#ifndef __LIBSTROPHE_UTIL_H__
#define __LIBSTROPHE_UTIL_H__
#ifndef _WIN32
#include <stdint.h>
#else
#include "ostypes.h"
#endif
/* timing functions */
uint64_t time_stamp(void);

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express or
** implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This software is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file
@@ -225,9 +222,10 @@ int xmpp_connect_client(xmpp_conn_t * const conn,
xmpp_conn_handler callback,
void * const userdata);
/*
int xmpp_connect_component(conn, name)
*/
int xmpp_connect_component(xmpp_conn_t * const conn, const char * const server,
unsigned short port, xmpp_conn_handler callback,
void * const userdata);
void xmpp_disconnect(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
** implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
**
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
/** @file

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express or
** implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <stdlib.h>
@@ -37,14 +34,14 @@ END_TEST
int cbtest_got_start = 0;
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;
}
int cbtest_got_end = 0;
void cbtest_handle_end(char *name, void *userdata)
{
if (strcmp(name, "stream:stream") == 0)
if (strcmp(name, "stream") == 0)
cbtest_got_end = 1;
}
@@ -67,9 +64,9 @@ START_TEST(callbacks)
cbtest_handle_end,
cbtest_handle_stanza, NULL);
ret = parser_feed(parser, "<stream:stream>", 15);
ret = parser_feed(parser, "<stream>", 8);
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_end == 1);

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <stdio.h>

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <stdio.h>

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <stdlib.h>

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <stdio.h>

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <stdio.h>

View File

@@ -6,10 +6,7 @@
** This software is provided AS-IS with no warranty, either express
** or implied.
**
** This software is distributed under license and may not be copied,
** modified or distributed except as expressly authorized under the
** terms of the license contained in the file LICENSE.txt in this
** distribution.
** This program is dual licensed under the MIT and GPLv3 licenses.
*/
#include <stdio.h>