aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2011-12-24 19:02:39 +0100
committerWilmer van der Gaast <wilmer@gaast.net>2011-12-24 19:02:39 +0100
commit164352ef9d3e8b4b2eea8ec64c3b4590b2388b18 (patch)
tree58d3424f7743d89ad4f94fc803ddd7e0563ec251
parente306fbf84aa37ab934c5ea18ccfd75da041af052 (diff)
parent96f954df218e81f5580257c319b91217dac2f4bf (diff)
Merging mainline.
-rw-r--r--bitlbee.conf23
-rw-r--r--bitlbee.h9
-rw-r--r--conf.c14
-rw-r--r--conf.h1
-rwxr-xr-xconfigure4
-rw-r--r--debian/changelog30
-rw-r--r--debian/control14
-rwxr-xr-xdebian/rules16
-rw-r--r--doc/user-guide/commands.xml40
-rw-r--r--irc.h8
-rw-r--r--lib/events_glib.c3
-rw-r--r--lib/http_client.c21
-rw-r--r--lib/ssl_bogus.c9
-rw-r--r--lib/ssl_client.h19
-rw-r--r--lib/ssl_gnutls.c149
-rw-r--r--lib/ssl_nss.c26
-rw-r--r--lib/ssl_openssl.c28
-rw-r--r--protocols/bee.h2
-rw-r--r--protocols/jabber/io.c32
-rw-r--r--protocols/jabber/jabber.c7
-rw-r--r--protocols/jabber/jabber.h2
-rw-r--r--protocols/msn/soap.c10
-rw-r--r--protocols/skype/skype.c4
-rw-r--r--unix.c6
24 files changed, 398 insertions, 79 deletions
diff --git a/bitlbee.conf b/bitlbee.conf
index c5dafd9f..50bb060f 100644
--- a/bitlbee.conf
+++ b/bitlbee.conf
@@ -115,9 +115,9 @@
##
## (Obviously, the username and password are optional)
##
-## Proxy = http://john:doe@proxy.localnet.com:8080
-## Proxy = socks4://socksproxy.localnet.com
-## Proxy = socks5://socksproxy.localnet.com
+# Proxy = http://john:doe@proxy.localnet.com:8080
+# Proxy = socks4://socksproxy.localnet.com
+# Proxy = socks5://socksproxy.localnet.com
## Protocols offered by bitlbee
##
@@ -125,8 +125,23 @@
## allows to remove the support of protocol, even if compiled in. If
## nothing is given, there are no restrictions.
##
-## Protocols = jabber yahoo
+# Protocols = jabber yahoo
+## Trusted CAs
+##
+## Path to a file containing a list of trusted certificate authorities used in
+## the verification of server certificates.
+##
+## Uncomment this and make sure the file actually exists and contains all
+## certificate authorities you're willing to accept (default value should
+## work on at least Debian/Ubuntu systems with the "ca-certificates" package
+## installed). As long as the line is commented out, SSL certificate
+## verification is completely disabled.
+##
+## The location of this file may be different on other distros/OSes. For
+## example, try /etc/ssl/ca-bundle.pem on OpenSUSE.
+##
+# CAfile = /etc/ssl/certs/ca-certificates.crt
[defaults]
diff --git a/bitlbee.h b/bitlbee.h
index ace78880..847cecf8 100644
--- a/bitlbee.h
+++ b/bitlbee.h
@@ -26,6 +26,10 @@
#ifndef _BITLBEE_H
#define _BITLBEE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* Stupid GNU :-P */
#endif
@@ -174,4 +178,9 @@ char *set_eval_control_channel( set_t *set, char *new_name );
extern global_t global;
+#ifdef __cplusplus
+}
#endif
+
+#endif
+
diff --git a/conf.c b/conf.c
index b5993b4b..3592f769 100644
--- a/conf.c
+++ b/conf.c
@@ -66,6 +66,7 @@ conf_t *conf_load( int argc, char *argv[] )
conf->ft_max_kbps = G_MAXUINT;
conf->ft_listen = NULL;
conf->protocols = NULL;
+ conf->cafile = NULL;
proxytype = 0;
i = conf_loadini( conf, global.conf_file );
@@ -176,6 +177,14 @@ conf_t *conf_load( int argc, char *argv[] )
if( config_missing )
fprintf( stderr, "Warning: Unable to read configuration file `%s'.\n", global.conf_file );
+ if( conf->cafile && access( conf->cafile, R_OK ) != 0 )
+ {
+ /* Let's treat this as a serious problem so people won't think
+ they're secure when in fact they're not. */
+ fprintf( stderr, "Error: Could not read CA file %s: %s\n", conf->cafile, strerror( errno ) );
+ return NULL;
+ }
+
return conf;
}
@@ -339,6 +348,11 @@ static int conf_loadini( conf_t *conf, char *file )
g_strfreev( conf->protocols );
conf->protocols = g_strsplit_set( ini->value, " \t,;", -1 );
}
+ else if( g_strcasecmp( ini->key, "cafile" ) == 0 )
+ {
+ g_free( conf->cafile );
+ conf->cafile = g_strdup( ini->value );
+ }
else
{
fprintf( stderr, "Error: Unknown setting `%s` in configuration file (line %d).\n", ini->key, ini->line );
diff --git a/conf.h b/conf.h
index f4976039..7eca09c1 100644
--- a/conf.h
+++ b/conf.h
@@ -53,6 +53,7 @@ typedef struct conf
int ft_max_kbps;
char *ft_listen;
char **protocols;
+ char *cafile;
} conf_t;
G_GNUC_MALLOC conf_t *conf_load( int argc, char *argv[] );
diff --git a/configure b/configure
index 8fd61af5..2f1b5046 100755
--- a/configure
+++ b/configure
@@ -282,6 +282,10 @@ EFLAGS+=`$PKG_CONFIG --libs gnutls` `libgcrypt-config --libs`
CFLAGS+=`$PKG_CONFIG --cflags gnutls` `libgcrypt-config --cflags`
EOF
ssl=gnutls
+ if ! pkg-config gnutls --atleast-version=2.8; then
+ echo
+ echo 'Warning: With GnuTLS versions <2.8, certificate expire dates are not verified.'
+ fi
ret=1
elif libgnutls-config --version > /dev/null 2> /dev/null; then
cat <<EOF>>Makefile.settings
diff --git a/debian/changelog b/debian/changelog
index 5702b417..590d7b90 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,23 +1,41 @@
-bitlbee (3.0.4-1) unstable; urgency=low
+bitlbee (3.0.4+z-2) UNRELEASED; urgency=low
+
+ * Removed some version override stuff from Debian build scripts. Instead,
+ my buildbot now uses dch to generate a changelog entry with the right
+ version number.
+
+ -- Wilmer van der Gaast <wilmer@gaast.net> Fri, 23 Dec 2011 09:45:55 +0100
+
+bitlbee (3.0.4+bzr855-1) unstable; urgency=low
* New upstream release.
+ * This is not a vanilla 3.0.4 tree but a Bazaar snapshot. The source
+ release was a few weeks ago by now. There should be no significant
+ differences.
* Added bitlbee-plugin-skype and skyped packages, now part of BitlBee
- instead of a separate package.
- * Fixed dependencies of bitlbee-plugin-otr package to not break with
- binary MTUs. (Closes: #651612)
+ instead of a separate package. Not building these for Debian for now
+ though since python-skype was removed.
* ^B and some other things are stripped in outgoing XMPP stanzas.
(Closes: #507856)
* OTR module linking fix. Not with the fix from the Debian bug but with
one from bugs.bitlbee.org. I hope that covers it. (Closes: #646369)
* Closing a few old bugs that were filed against the Debian package
- instead of upstream:
+ instead of/as well as upstream:
- Joining password-protected MUCs is working for a while already, set
the password using "chan set". (Closes: #615624)
- "Headline:" msgs (Closes: #605459)
- Yahoo! was fixed long ago and Etch is deprecated. (Closes: #476529)
- identi.ca support is documented. (Closes: #613789)
- -- Wilmer van der Gaast <wilmer@gaast.net> Sun, 11 Dec 2011 16:53:31 +0000
+ -- Wilmer van der Gaast <wilmer@gaast.net> Tue, 20 Dec 2011 12:46:42 +0100
+
+bitlbee (3.0.3-1.1) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Use the standard ${source:Version} and ${binary:Version} substvars instead
+ of the custom and broken ${bee:Version} (closes: #651612).
+
+ -- Julien Cristau <jcristau@debian.org> Thu, 15 Dec 2011 20:34:32 +0100
bitlbee (3.0.3-1) unstable; urgency=low
diff --git a/debian/control b/debian/control
index 41fc0366..181feccb 100644
--- a/debian/control
+++ b/debian/control
@@ -11,7 +11,7 @@ DM-Upload-Allowed: yes
Package: bitlbee
Architecture: any
-Depends: ${misc:Depends}, ${shlibs:Depends}, debianutils (>= 1.16), bitlbee-common (= ${bee:Version})
+Depends: ${misc:Depends}, ${shlibs:Depends}, debianutils (>= 1.16), bitlbee-common (= ${source:Version})
Conflicts: bitlbee-libpurple
Replaces: bitlbee-libpurple
Description: An IRC to other chat networks gateway (default version)
@@ -21,7 +21,7 @@ Description: An IRC to other chat networks gateway (default version)
Package: bitlbee-libpurple
Architecture: any
-Depends: ${misc:Depends}, ${shlibs:Depends}, debianutils (>= 1.16), bitlbee-common (= ${bee:Version})
+Depends: ${misc:Depends}, ${shlibs:Depends}, debianutils (>= 1.16), bitlbee-common (= ${source:Version})
Conflicts: bitlbee
Replaces: bitlbee
Description: An IRC to other chat networks gateway (using libpurple)
@@ -50,7 +50,7 @@ Description: An IRC to other chat networks gateway (common files/docs)
Package: bitlbee-dev
Architecture: all
-Depends: ${misc:Depends}, bitlbee (>= ${bee:Version}), bitlbee (<< ${bee:Version}.1~), bitlbee-common (= ${bee:Version})
+Depends: ${misc:Depends}, bitlbee (>= ${source:Version}), bitlbee (<< ${source:Version}.1~), bitlbee-common (= ${source:Version})
Description: An IRC to other chat networks gateway (dev files)
This program can be used as an IRC server which forwards everything you
say to people on other chat networks: Jabber (which includes Google Talk
@@ -60,7 +60,7 @@ Description: An IRC to other chat networks gateway (dev files)
Package: bitlbee-plugin-otr
Architecture: any
-Depends: ${misc:Depends}, ${shlibs:Depends}, bitlbee (>= ${bee:Version}) | bitlbee-libpurple (>= ${bee:Version}), bitlbee (<< ${bee:Version}.1~) | bitlbee-libpurple (<< ${bee:Version}.1~), bitlbee-common (= ${bee:Version})
+Depends: ${misc:Depends}, ${shlibs:Depends}, bitlbee (= ${binary:Version}) | bitlbee-libpurple (= ${binary:Version}), bitlbee-common (= ${source:Version})
Description: An IRC to other chat networks gateway (OTR plugin)
This program can be used as an IRC server which forwards everything you
say to people on other chat networks: Jabber (which includes Google Talk
@@ -71,7 +71,7 @@ Description: An IRC to other chat networks gateway (OTR plugin)
Package: bitlbee-plugin-skype
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, bitlbee (>= ${bee:Version}) | bitlbee-libpurple (>= ${bee:Version}), bitlbee (<< ${bee:Version}.1~) | bitlbee-libpurple (<< ${bee:Version}.1~)
+Depends: ${misc:Depends}, ${shlibs:Depends}, bitlbee (= ${binary:Version}) | bitlbee-libpurple (= ${binary:Version}), bitlbee-common (= ${source:Version})
Recommends: skyped
Description: An IRC to other chat networks gateway (Skype plugin)
This program can be used as an IRC server which forwards everything you
@@ -82,8 +82,8 @@ Description: An IRC to other chat networks gateway (Skype plugin)
You need to download and install the Skype client for this to work.
Package: skyped
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, python (>= 2.5), python-gnutls, python-skype (>=0.9.28.7)
+Architecture: all
+Depends: ${misc:Depends}, ${shlibs:Depends}, python (>= 2.5), python-gnutls, python-skype (>=0.9.28.7)
Recommends: skype
Description: Daemon to control Skype remotely
Daemon to control the GUI Skype client. Currently required to control Skype
diff --git a/debian/rules b/debian/rules
index 57d60090..2c9e3a12 100755
--- a/debian/rules
+++ b/debian/rules
@@ -7,16 +7,18 @@
# exercise is over now.
#
-# Include the bitlbee-libpurple variant and OTR plugin by default
+# Include the bitlbee-libpurple variant and OTR plugin by default.
+# Don't build skype by default since it depends on deleted/non-free
+# packages. Need to at least get python-skype back into Debian.
BITLBEE_LIBPURPLE ?= 1
BITLBEE_OTR ?= plugin
-BITLBEE_SKYPE ?= plugin
+BITLBEE_SKYPE ?= 0
BITLBEE_CONFIGURE_FLAGS ?=
DEBUG ?= 0
ifndef BITLBEE_VERSION
# Want to use the full package version number instead of just the release.
-BITLBEE_CONFIGURE_VERSION ?= BITLBEE_VERSION=\"$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}')\"
+BITLBEE_CONFIGURE_VERSION ?= BITLBEE_VERSION=\"$(shell dpkg-parsechangelog | awk '/^Version:/ {print $$2}')\"
endif
ifneq ($(BITLBEE_LIBPURPLE),1)
@@ -71,11 +73,13 @@ install: build
$(MAKE) -C debian/build-native install-plugin-otr DESTDIR=`pwd`/debian/bitlbee-plugin-otr
$(MAKE) -C debian/build-native install-plugin-skype DESTDIR=`pwd`/debian/skyped
+ifneq ($(BITLBEE_SKYPE),0)
mkdir -p debian/bitlbee-plugin-skype/usr
mv debian/skyped/usr/lib debian/bitlbee-plugin-skype/usr
mkdir -p debian/skyped/usr/share/man/man1
mv debian/bitlbee-common/usr/share/man/man1/skyped* debian/skyped/usr/share/man/man1
+endif
ifeq ($(BITLBEE_LIBPURPLE),1)
$(MAKE) -C debian/build-libpurple install-bin DESTDIR=`pwd`/debian/bitlbee-libpurple
@@ -105,11 +109,7 @@ binary-common:
dh_fixperms
dh_installdeb
dh_shlibdeps
-ifdef BITLBEE_VERSION
- dh_gencontrol -- -v$(BITLBEE_VERSION) -Vbee:Version=$(BITLBEE_VERSION)
-else
- dh_gencontrol -- -Vbee:Version=$(shell dpkg-parsechangelog | grep ^Version: | awk '{print $$2}' | sed -e 's/+b[0-9]\+$$//')
-endif
+ dh_gencontrol
dh_md5sums
dh_builddeb
diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml
index 9bb2b9c8..dccf87ed 100644
--- a/doc/user-guide/commands.xml
+++ b/doc/user-guide/commands.xml
@@ -647,7 +647,7 @@
</description>
</bitlbee-setting>
- <bitlbee-setting name="auto_connect" type="boolean" scope="both">
+ <bitlbee-setting name="auto_connect" type="boolean" scope="account,global">
<default>true</default>
<description>
@@ -671,7 +671,7 @@
</description>
</bitlbee-setting>
- <bitlbee-setting name="auto_reconnect" type="boolean" scope="both">
+ <bitlbee-setting name="auto_reconnect" type="boolean" scope="account,global">
<default>true</default>
<description>
@@ -725,7 +725,7 @@
</description>
</bitlbee-setting>
- <bitlbee-setting name="away" type="string" scope="both">
+ <bitlbee-setting name="away" type="string" scope="account,global">
<description>
<para>
To mark yourself as away, it is recommended to just use <emphasis>/away</emphasis>, like on normal IRC networks. If you want to mark yourself as away on only one IM network, you can use this per-account setting.
@@ -1075,7 +1075,7 @@
</description>
</bitlbee-setting>
- <bitlbee-setting name="nick_format" type="string" scope="both">
+ <bitlbee-setting name="nick_format" type="string" scope="account,global">
<default>%-@nick</default>
<description>
@@ -1168,7 +1168,7 @@
</description>
</bitlbee-setting>
- <bitlbee-setting name="password" type="string" scope="both">
+ <bitlbee-setting name="password" type="string" scope="account,global">
<description>
<para>
Use this global setting to change your "NickServ" password.
@@ -1391,15 +1391,19 @@
<description>
<para>
- Currently only available for Jabber connections. Set this to true if the server accepts SSL connections.
+ Currently only available for Jabber connections. Set this to true if you want to connect to the server on an SSL-enabled port (usually 5223).
+ </para>
+
+ <para>
+ Please note that this method of establishing a secure connection to the server has long been deprecated. You are encouraged to look at the <emphasis>tls</emphasis> setting instead.
</para>
</description>
</bitlbee-setting>
- <bitlbee-setting name="status" type="string" scope="both">
+ <bitlbee-setting name="status" type="string" scope="account,global">
<description>
<para>
- Certain protocols (like Jabber/XMPP) support status messages, similar to away messages. They can be used to indicate things like your location or activity, without showing up as away/busy.
+ Most IM protocols support status messages, similar to away messages. They can be used to indicate things like your location or activity, without showing up as away/busy.
</para>
<para>
@@ -1407,7 +1411,7 @@
</para>
<para>
- Away states set using <emphasis>/away</emphasis> or the <emphasis>away</emphasis> setting will override this setting. To un-set the setting, use <emphasis>set -del status</emphasis>.
+ Away states set using <emphasis>/away</emphasis> or the <emphasis>away</emphasis> setting will override this setting. To clear the setting, use <emphasis>set -del status</emphasis>.
</para>
</description>
</bitlbee-setting>
@@ -1484,6 +1488,24 @@
</description>
</bitlbee-setting>
+ <bitlbee-setting name="tls_verify" type="boolean" scope="account">
+ <default>true</default>
+
+ <description>
+ <para>
+ Currently only available for Jabber connections in combination with the <emphasis>tls</emphasis> setting. Set this to <emphasis>true</emphasis> if you want BitlBee to strictly verify the server's certificate against a list of trusted certificate authorities.
+ </para>
+
+ <para>
+ The hostname used in the certificate verification is the value of the <emphasis>server</emphasis> setting if the latter is nonempty and the domain of the username else. If you get a hostname related error when connecting to Google Talk with a username from the gmail.com or googlemail.com domain, please try to empty the <emphasis>server</emphasis> setting.
+ </para>
+
+ <para>
+ Please note that no certificate verification is performed when the <emphasis>ssl</emphasis> setting is used, or when the <emphasis>CAfile</emphasis> setting in <emphasis>bitlbee.conf</emphasis> is not set.
+ </para>
+ </description>
+ </bitlbee-setting>
+
<bitlbee-setting name="to_char" type="string" scope="global">
<default>": "</default>
diff --git a/irc.h b/irc.h
index f186b96a..930b90b3 100644
--- a/irc.h
+++ b/irc.h
@@ -181,7 +181,7 @@ struct irc_channel_funcs
gboolean (*privmsg)( irc_channel_t *ic, const char *msg );
gboolean (*join)( irc_channel_t *ic );
gboolean (*part)( irc_channel_t *ic, const char *msg );
- gboolean (*topic)( irc_channel_t *ic, const char *new );
+ gboolean (*topic)( irc_channel_t *ic, const char *new_topic );
gboolean (*invite)( irc_channel_t *ic, irc_user_t *iu );
gboolean (*_init)( irc_channel_t *ic );
@@ -331,16 +331,16 @@ void irc_send_who( irc_t *irc, GSList *l, const char *channel );
void irc_send_msg( irc_user_t *iu, const char *type, const char *dst, const char *msg, const char *prefix );
void irc_send_msg_raw( irc_user_t *iu, const char *type, const char *dst, const char *msg );
void irc_send_msg_f( irc_user_t *iu, const char *type, const char *dst, const char *format, ... ) G_GNUC_PRINTF( 4, 5 );
-void irc_send_nick( irc_user_t *iu, const char *new );
+void irc_send_nick( irc_user_t *iu, const char *new_nick );
void irc_send_channel_user_mode_diff( irc_channel_t *ic, irc_user_t *iu,
- irc_channel_user_flags_t old, irc_channel_user_flags_t new );
+ irc_channel_user_flags_t old_flags, irc_channel_user_flags_t new_flags );
void irc_send_invite( irc_user_t *iu, irc_channel_t *ic );
/* irc_user.c */
irc_user_t *irc_user_new( irc_t *irc, const char *nick );
int irc_user_free( irc_t *irc, irc_user_t *iu );
irc_user_t *irc_user_by_name( irc_t *irc, const char *nick );
-int irc_user_set_nick( irc_user_t *iu, const char *new );
+int irc_user_set_nick( irc_user_t *iu, const char *new_nick );
gint irc_user_cmp( gconstpointer a_, gconstpointer b_ );
const char *irc_user_get_away( irc_user_t *iu );
void irc_user_quit( irc_user_t *iu, const char *msg );
diff --git a/lib/events_glib.c b/lib/events_glib.c
index 3fafc872..8f53fbbf 100644
--- a/lib/events_glib.c
+++ b/lib/events_glib.c
@@ -74,6 +74,9 @@ static gboolean gaim_io_invoke(GIOChannel *source, GIOCondition condition, gpoin
GaimIOClosure *closure = data;
b_input_condition gaim_cond = 0;
gboolean st;
+
+ if (condition & G_IO_NVAL)
+ return FALSE;
if (condition & GAIM_READ_COND)
gaim_cond |= B_EV_IO_READ;
diff --git a/lib/http_client.c b/lib/http_client.c
index 9d986412..98a99f7c 100644
--- a/lib/http_client.c
+++ b/lib/http_client.c
@@ -32,7 +32,7 @@
static gboolean http_connected( gpointer data, int source, b_input_condition cond );
-static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond );
+static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond );
static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond );
static void http_free( struct http_request *req );
@@ -46,7 +46,7 @@ struct http_request *http_dorequest( char *host, int port, int ssl, char *reques
if( ssl )
{
- req->ssl = ssl_connect( host, port, http_ssl_connected, req );
+ req->ssl = ssl_connect( host, port, TRUE, http_ssl_connected, req );
if( req->ssl == NULL )
error = 1;
}
@@ -162,19 +162,30 @@ static gboolean http_connected( gpointer data, int source, b_input_condition con
return FALSE;
error:
- req->status_string = g_strdup( "Error while writing HTTP request" );
+ if( req->status_string == NULL )
+ req->status_string = g_strdup( "Error while writing HTTP request" );
req->func( req );
http_free( req );
return FALSE;
}
-static gboolean http_ssl_connected( gpointer data, void *source, b_input_condition cond )
+static gboolean http_ssl_connected( gpointer data, int returncode, void *source, b_input_condition cond )
{
struct http_request *req = data;
if( source == NULL )
+ {
+ if( returncode != 0 )
+ {
+ char *err = ssl_verify_strerror( returncode );
+ req->status_string = g_strdup_printf(
+ "Certificate verification problem 0x%x: %s",
+ returncode, err ? err : "Unknown" );
+ g_free( err );
+ }
return http_connected( data, -1, cond );
+ }
req->fd = ssl_getfd( source );
@@ -438,7 +449,7 @@ got_reply:
if( new_proto == PROTO_HTTPS )
{
- req->ssl = ssl_connect( new_host, new_port, http_ssl_connected, req );
+ req->ssl = ssl_connect( new_host, new_port, TRUE, http_ssl_connected, req );
if( req->ssl == NULL )
error = 1;
}
diff --git a/lib/ssl_bogus.c b/lib/ssl_bogus.c
index f4ce5d4d..e134201d 100644
--- a/lib/ssl_bogus.c
+++ b/lib/ssl_bogus.c
@@ -31,7 +31,7 @@ void ssl_init( void )
{
}
-void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
+void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data )
{
return( NULL );
}
@@ -55,7 +55,7 @@ int ssl_getfd( void *conn )
return( -1 );
}
-void *ssl_starttls( int fd, ssl_input_function func, gpointer data )
+void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data )
{
return NULL;
}
@@ -69,3 +69,8 @@ int ssl_pending( void *conn )
{
return 0;
}
+
+char *ssl_verify_strerror( int code )
+{
+ return NULL;
+}
diff --git a/lib/ssl_client.h b/lib/ssl_client.h
index 091335c5..206fe9cb 100644
--- a/lib/ssl_client.h
+++ b/lib/ssl_client.h
@@ -39,11 +39,20 @@
#define SSL_OK 0
#define SSL_NOHANDSHAKE 1
#define SSL_AGAIN 2
+#define VERIFY_CERT_ERROR 2
+#define VERIFY_CERT_INVALID 4
+#define VERIFY_CERT_REVOKED 8
+#define VERIFY_CERT_SIGNER_NOT_FOUND 16
+#define VERIFY_CERT_SIGNER_NOT_CA 32
+#define VERIFY_CERT_INSECURE_ALGORITHM 64
+#define VERIFY_CERT_NOT_ACTIVATED 128
+#define VERIFY_CERT_EXPIRED 256
+#define VERIFY_CERT_WRONG_HOSTNAME 512
extern int ssl_errno;
/* This is what your callback function should look like. */
-typedef gboolean (*ssl_input_function)(gpointer, void*, b_input_condition);
+typedef gboolean (*ssl_input_function)(gpointer, int, void*, b_input_condition);
/* Perform any global initialization the SSL library might need. */
@@ -52,11 +61,11 @@ G_MODULE_EXPORT void ssl_init( void );
/* Connect to host:port, call the given function when the connection is
ready to be used for SSL traffic. This is all done asynchronously, no
blocking I/O! (Except for the DNS lookups, for now...) */
-G_MODULE_EXPORT void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data );
+G_MODULE_EXPORT void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data );
/* Start an SSL session on an existing fd. Useful for STARTTLS functionality,
for example in Jabber. */
-G_MODULE_EXPORT void *ssl_starttls( int fd, ssl_input_function func, gpointer data );
+G_MODULE_EXPORT void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data );
/* Obviously you need special read/write functions to read data. */
G_MODULE_EXPORT int ssl_read( void *conn, char *buf, int len );
@@ -89,4 +98,8 @@ G_MODULE_EXPORT int ssl_getfd( void *conn );
the same action as the handler that just received the SSL_AGAIN.) */
G_MODULE_EXPORT b_input_condition ssl_getdirection( void *conn );
+/* Converts a verification bitfield passed to ssl_input_function into
+ a more useful string. Or NULL if it had no useful bits set. */
+G_MODULE_EXPORT char *ssl_verify_strerror( int code );
+
G_MODULE_EXPORT size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res);
diff --git a/lib/ssl_gnutls.c b/lib/ssl_gnutls.c
index ccab8aca..f5e0ad47 100644
--- a/lib/ssl_gnutls.c
+++ b/lib/ssl_gnutls.c
@@ -24,6 +24,7 @@
*/
#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
#include <gcrypt.h>
#include <fcntl.h>
#include <unistd.h>
@@ -31,6 +32,7 @@
#include "ssl_client.h"
#include "sock.h"
#include "stdlib.h"
+#include "bitlbee.h"
int ssl_errno = 0;
@@ -53,6 +55,8 @@ struct scd
int fd;
gboolean established;
int inpa;
+ char *hostname;
+ gboolean verify;
gnutls_session session;
gnutls_certificate_credentials xcred;
@@ -73,7 +77,7 @@ void ssl_init( void )
atexit( gnutls_global_deinit );
}
-void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
+void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data )
{
struct scd *conn = g_new0( struct scd, 1 );
@@ -81,6 +85,8 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data
conn->func = func;
conn->data = data;
conn->inpa = -1;
+ conn->hostname = g_strdup( host );
+ conn->verify = verify && global.conf->cafile;
if( conn->fd < 0 )
{
@@ -91,7 +97,7 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data
return conn;
}
-void *ssl_starttls( int fd, ssl_input_function func, gpointer data )
+void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data )
{
struct scd *conn = g_new0( struct scd, 1 );
@@ -99,6 +105,13 @@ void *ssl_starttls( int fd, ssl_input_function func, gpointer data )
conn->func = func;
conn->data = data;
conn->inpa = -1;
+ conn->hostname = hostname;
+
+ /* For now, SSL verification is globally enabled by setting the cafile
+ setting in bitlbee.conf. Commented out by default because probably
+ not everyone has this file in the same place and plenty of folks
+ may not have the cert of their private Jabber server in it. */
+ conn->verify = verify && global.conf->cafile;
/* This function should be called via a (short) timeout instead of
directly from here, because these SSL calls are *supposed* to be
@@ -121,13 +134,110 @@ static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition
return ssl_connected( conn, conn->fd, B_EV_IO_WRITE );
}
+static int verify_certificate_callback( gnutls_session_t session )
+{
+ unsigned int status;
+ const gnutls_datum_t *cert_list;
+ unsigned int cert_list_size;
+ int gnutlsret;
+ int verifyret = 0;
+ gnutls_x509_crt_t cert;
+ const char *hostname;
+
+ hostname = gnutls_session_get_ptr(session );
+
+ gnutlsret = gnutls_certificate_verify_peers2( session, &status );
+ if( gnutlsret < 0 )
+ return VERIFY_CERT_ERROR;
+
+ if( status & GNUTLS_CERT_INVALID )
+ verifyret |= VERIFY_CERT_INVALID;
+
+ if( status & GNUTLS_CERT_REVOKED )
+ verifyret |= VERIFY_CERT_REVOKED;
+
+ if( status & GNUTLS_CERT_SIGNER_NOT_FOUND )
+ verifyret |= VERIFY_CERT_SIGNER_NOT_FOUND;
+
+ if( status & GNUTLS_CERT_SIGNER_NOT_CA )
+ verifyret |= VERIFY_CERT_SIGNER_NOT_CA;
+
+ if( status & GNUTLS_CERT_INSECURE_ALGORITHM )
+ verifyret |= VERIFY_CERT_INSECURE_ALGORITHM;
+
+#ifdef GNUTLS_CERT_NOT_ACTIVATED
+ /* Amusingly, the GnuTLS function used above didn't check for expiry
+ until GnuTLS 2.8 or so. (See CVE-2009-1417) */
+ if( status & GNUTLS_CERT_NOT_ACTIVATED )
+ verifyret |= VERIFY_CERT_NOT_ACTIVATED;
+
+ if( status & GNUTLS_CERT_EXPIRED )
+ verifyret |= VERIFY_CERT_EXPIRED;
+#endif
+
+ /* The following check is already performed inside
+ * gnutls_certificate_verify_peers2, so we don't need it.
+
+ * if( gnutls_certificate_type_get( session ) != GNUTLS_CRT_X509 )
+ * return GNUTLS_E_CERTIFICATE_ERROR;
+ */
+
+ if( gnutls_x509_crt_init( &cert ) < 0 )
+ return VERIFY_CERT_ERROR;
+
+ cert_list = gnutls_certificate_get_peers( session, &cert_list_size );
+ if( cert_list == NULL || gnutls_x509_crt_import( cert, &cert_list[0], GNUTLS_X509_FMT_DER ) < 0 )
+ return VERIFY_CERT_ERROR;
+
+ if( !gnutls_x509_crt_check_hostname( cert, hostname ) )
+ {
+ verifyret |= VERIFY_CERT_INVALID;
+ verifyret |= VERIFY_CERT_WRONG_HOSTNAME;
+ }
+
+ gnutls_x509_crt_deinit( cert );
+
+ return verifyret;
+}
+
+char *ssl_verify_strerror( int code )
+{
+ GString *ret = g_string_new( "" );
+
+ if( code & VERIFY_CERT_REVOKED )
+ g_string_append( ret, "certificate has been revoked, " );
+ if( code & VERIFY_CERT_SIGNER_NOT_FOUND )
+ g_string_append( ret, "certificate hasn't got a known issuer, " );
+ if( code & VERIFY_CERT_SIGNER_NOT_CA )
+ g_string_append( ret, "certificate's issuer is not a CA, " );
+ if( code & VERIFY_CERT_INSECURE_ALGORITHM )
+ g_string_append( ret, "certificate uses an insecure algorithm, " );
+ if( code & VERIFY_CERT_NOT_ACTIVATED )
+ g_string_append( ret, "certificate has not been activated, " );
+ if( code & VERIFY_CERT_EXPIRED )
+ g_string_append( ret, "certificate has expired, " );
+ if( code & VERIFY_CERT_WRONG_HOSTNAME )
+ g_string_append( ret, "certificate hostname mismatch, " );
+
+ if( ret->len == 0 )
+ {
+ g_string_free( ret, TRUE );
+ return NULL;
+ }
+ else
+ {
+ g_string_truncate( ret, ret->len - 2 );
+ return g_string_free( ret, FALSE );
+ }
+}
+
static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond )
{
struct scd *conn = data;
if( source == -1 )
{
- conn->func( conn->data, NULL, cond );
+ conn->func( conn->data, 0, NULL, cond );
g_free( conn );
return FALSE;
}
@@ -135,7 +245,15 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con
ssl_init();
gnutls_certificate_allocate_credentials( &conn->xcred );
+ if( conn->verify && global.conf->cafile )
+ {
+ gnutls_certificate_set_x509_trust_file( conn->xcred, global.conf->cafile, GNUTLS_X509_FMT_PEM );
+ gnutls_certificate_set_verify_flags( conn->xcred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT );
+ }
+
gnutls_init( &conn->session, GNUTLS_CLIENT );
+ if( conn->verify )
+ gnutls_session_set_ptr( conn->session, (void *) conn->hostname );
#if GNUTLS_VERSION_NUMBER < 0x020c00
gnutls_transport_set_lowat( conn->session, 0 );
#endif
@@ -151,7 +269,7 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con
static gboolean ssl_handshake( gpointer data, gint source, b_input_condition cond )
{
struct scd *conn = data;
- int st;
+ int st, stver;
if( ( st = gnutls_handshake( conn->session ) ) < 0 )
{
@@ -162,7 +280,7 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con
}
else
{
- conn->func( conn->data, NULL, cond );
+ conn->func( conn->data, 0, NULL, cond );
gnutls_deinit( conn->session );
gnutls_certificate_free_credentials( conn->xcred );
@@ -173,11 +291,24 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con
}
else
{
- /* For now we can't handle non-blocking perfectly everywhere... */
- sock_make_blocking( conn->fd );
+ if( conn->verify && ( stver = verify_certificate_callback( conn->session ) ) != 0 )
+ {
+ conn->func( conn->data, stver, NULL, cond );
+
+ gnutls_deinit( conn->session );
+ gnutls_certificate_free_credentials( conn->xcred );
+ closesocket( conn->fd );
+
+ g_free( conn );
+ }
+ else
+ {
+ /* For now we can't handle non-blocking perfectly everywhere... */
+ sock_make_blocking( conn->fd );
- conn->established = TRUE;
- conn->func( conn->data, conn, cond );
+ conn->established = TRUE;
+ conn->func( conn->data, 0, conn, cond );
+ }
}
return FALSE;
diff --git a/lib/ssl_nss.c b/lib/ssl_nss.c
index ec524ca6..d50620d5 100644
--- a/lib/ssl_nss.c
+++ b/lib/ssl_nss.c
@@ -51,6 +51,7 @@ struct scd
int fd;
PRFileDesc *prfd;
gboolean established;
+ gboolean verify;
};
static gboolean ssl_connected( gpointer data, gint source, b_input_condition cond );
@@ -101,7 +102,7 @@ void ssl_init( void )
initialized = TRUE;
}
-void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
+void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data )
{
struct scd *conn = g_new0( struct scd, 1 );
@@ -131,13 +132,14 @@ static gboolean ssl_starttls_real( gpointer data, gint source, b_input_condition
return ssl_connected( conn, conn->fd, B_EV_IO_WRITE );
}
-void *ssl_starttls( int fd, ssl_input_function func, gpointer data )
+void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data )
{
struct scd *conn = g_new0( struct scd, 1 );
conn->fd = fd;
conn->func = func;
conn->data = data;
+ conn->verify = verify && global.conf->cafile;
/* This function should be called via a (short) timeout instead of
directly from here, because these SSL calls are *supposed* to be
@@ -157,6 +159,17 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con
{
struct scd *conn = data;
+ /* Right now we don't have any verification functionality for NSS. */
+
+ if( conn->verify )
+ {
+ conn->func( conn->data, 1, NULL, cond );
+ if( source >= 0 ) closesocket( source );
+ g_free( conn );
+
+ return FALSE;
+ }
+
if( source == -1 )
goto ssl_connected_failure;
@@ -176,12 +189,12 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con
conn->established = TRUE;
- conn->func( conn->data, conn, cond );
+ conn->func( conn->data, 0, conn, cond );
return FALSE;
ssl_connected_failure:
- conn->func( conn->data, NULL, cond );
+ conn->func( conn->data, 0, NULL, cond );
PR_Close( conn -> prfd );
if( source >= 0 ) closesocket( source );
@@ -237,3 +250,8 @@ b_input_condition ssl_getdirection( void *conn )
/* Just in case someone calls us, let's return the most likely case: */
return B_EV_IO_READ;
}
+
+char *ssl_verify_strerror( int code )
+{
+ return g_strdup( "SSL certificate verification not supported by BitlBee NSS code." );
+}
diff --git a/lib/ssl_openssl.c b/lib/ssl_openssl.c
index 5f64042d..5c38d0e9 100644
--- a/lib/ssl_openssl.c
+++ b/lib/ssl_openssl.c
@@ -44,6 +44,7 @@ struct scd
gpointer data;
int fd;
gboolean established;
+ gboolean verify;
int inpa;
int lasterr; /* Necessary for SSL_get_error */
@@ -63,7 +64,7 @@ void ssl_init( void )
// SSLeay_add_ssl_algorithms();
}
-void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data )
+void *ssl_connect( char *host, int port, gboolean verify, ssl_input_function func, gpointer data )
{
struct scd *conn = g_new0( struct scd, 1 );
@@ -81,7 +82,7 @@ void *ssl_connect( char *host, int port, ssl_input_function func, gpointer data
return conn;
}
-void *ssl_starttls( int fd, ssl_input_function func, gpointer data )
+void *ssl_starttls( int fd, char *hostname, gboolean verify, ssl_input_function func, gpointer data )
{
struct scd *conn = g_new0( struct scd, 1 );
@@ -89,6 +90,7 @@ void *ssl_starttls( int fd, ssl_input_function func, gpointer data )
conn->func = func;
conn->data = data;
conn->inpa = -1;
+ conn->verify = verify && global.conf->cafile;
/* This function should be called via a (short) timeout instead of
directly from here, because these SSL calls are *supposed* to be
@@ -116,6 +118,17 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con
struct scd *conn = data;
SSL_METHOD *meth;
+ /* Right now we don't have any verification functionality for OpenSSL. */
+
+ if( conn->verify )
+ {
+ conn->func( conn->data, 1, NULL, cond );
+ if( source >= 0 ) closesocket( source );
+ g_free( conn );
+
+ return FALSE;
+ }
+
if( source == -1 )
goto ssl_connected_failure;
@@ -140,7 +153,7 @@ static gboolean ssl_connected( gpointer data, gint source, b_input_condition con
return ssl_handshake( data, source, cond );
ssl_connected_failure:
- conn->func( conn->data, NULL, cond );
+ conn->func( conn->data, 0, NULL, cond );
if( conn->ssl )
{
@@ -168,7 +181,7 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con
conn->lasterr = SSL_get_error( conn->ssl, st );
if( conn->lasterr != SSL_ERROR_WANT_READ && conn->lasterr != SSL_ERROR_WANT_WRITE )
{
- conn->func( conn->data, NULL, cond );
+ conn->func( conn->data, 0, NULL, cond );
SSL_shutdown( conn->ssl );
SSL_free( conn->ssl );
@@ -186,7 +199,7 @@ static gboolean ssl_handshake( gpointer data, gint source, b_input_condition con
conn->established = TRUE;
sock_make_blocking( conn->fd ); /* For now... */
- conn->func( conn->data, conn, cond );
+ conn->func( conn->data, 0, conn, cond );
return FALSE;
}
@@ -273,6 +286,11 @@ b_input_condition ssl_getdirection( void *conn )
return( ((struct scd*)conn)->lasterr == SSL_ERROR_WANT_WRITE ? B_EV_IO_WRITE : B_EV_IO_READ );
}
+char *ssl_verify_strerror( int code )
+{
+ return g_strdup( "SSL certificate verification not supported by BitlBee OpenSSL code." );
+}
+
size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res)
{
int output_length = 0;
diff --git a/protocols/bee.h b/protocols/bee.h
index 49ea6fb5..24f5824e 100644
--- a/protocols/bee.h
+++ b/protocols/bee.h
@@ -122,7 +122,7 @@ typedef struct bee_ui_funcs
gboolean (*chat_msg)( bee_t *bee, struct groupchat *c, bee_user_t *bu, const char *msg, time_t sent_at );
gboolean (*chat_add_user)( bee_t *bee, struct groupchat *c, bee_user_t *bu );
gboolean (*chat_remove_user)( bee_t *bee, struct groupchat *c, bee_user_t *bu );
- gboolean (*chat_topic)( bee_t *bee, struct groupchat *c, const char *new, bee_user_t *bu );
+ gboolean (*chat_topic)( bee_t *bee, struct groupchat *c, const char *new_topic, bee_user_t *bu );
gboolean (*chat_name_hint)( bee_t *bee, struct groupchat *c, const char *name );
gboolean (*chat_invite)( bee_t *bee, bee_user_t *bu, const char *name, const char *msg );
diff --git a/protocols/jabber/io.c b/protocols/jabber/io.c
index a28eea90..5b9149af 100644
--- a/protocols/jabber/io.c
+++ b/protocols/jabber/io.c
@@ -275,7 +275,7 @@ gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition c
return jabber_start_stream( ic );
}
-gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond )
+gboolean jabber_connected_ssl( gpointer data, int returncode, void *source, b_input_condition cond )
{
struct im_connection *ic = data;
struct jabber_data *jd;
@@ -291,8 +291,20 @@ gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition co
already, set it to NULL here to prevent a double cleanup: */
jd->ssl = NULL;
- imcb_error( ic, "Could not connect to server" );
- imc_logout( ic, TRUE );
+ if( returncode != 0 )
+ {
+ char *err = ssl_verify_strerror( returncode );
+ imcb_error( ic, "Certificate verification problem 0x%x: %s",
+ returncode, err ? err : "Unknown" );
+ g_free( err );
+ imc_logout( ic, FALSE );
+ }
+ else
+ {
+ imcb_error( ic, "Could not connect to server" );
+ imc_logout( ic, TRUE );
+ }
+
return FALSE;
}
@@ -396,7 +408,7 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data )
{
struct im_connection *ic = data;
struct jabber_data *jd = ic->proto_data;
- char *xmlns;
+ char *xmlns, *tlsname;
xmlns = xt_find_attr( node, "xmlns" );
@@ -422,7 +434,17 @@ static xt_status jabber_pkt_proceed_tls( struct xt_node *node, gpointer data )
imcb_log( ic, "Converting stream to TLS" );
jd->flags |= JFLAG_STARTTLS_DONE;
- jd->ssl = ssl_starttls( jd->fd, jabber_connected_ssl, ic );
+
+ /* If the user specified a server for the account, use this server as the
+ * hostname in the certificate verification. Else we use the domain from
+ * the username. */
+ if( ic->acc->server && *ic->acc->server )
+ tlsname = ic->acc->server;
+ else
+ tlsname = jd->server;
+
+ jd->ssl = ssl_starttls( jd->fd, tlsname, set_getbool( &ic->acc->set, "tls_verify" ),
+ jabber_connected_ssl, ic );
return XT_HANDLED;
}
diff --git a/protocols/jabber/jabber.c b/protocols/jabber/jabber.c
index 71287842..92256a71 100644
--- a/protocols/jabber/jabber.c
+++ b/protocols/jabber/jabber.c
@@ -86,7 +86,10 @@ static void jabber_init( account_t *acc )
s = set_add( &acc->set, "tls", "try", set_eval_tls, acc );
s->flags |= ACC_SET_OFFLINE_ONLY;
-
+
+ s = set_add( &acc->set, "tls_verify", "true", set_eval_bool, acc );
+ s->flags |= ACC_SET_OFFLINE_ONLY;
+
s = set_add( &acc->set, "user_agent", "BitlBee", NULL, acc );
s = set_add( &acc->set, "xmlconsole", "false", set_eval_bool, acc );
@@ -227,7 +230,7 @@ void jabber_connect( struct im_connection *ic )
non-standard ports... */
if( set_getbool( &acc->set, "ssl" ) )
{
- jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), jabber_connected_ssl, ic );
+ jd->ssl = ssl_connect( connect_to, set_getint( &acc->set, "port" ), FALSE, jabber_connected_ssl, ic );
jd->fd = jd->ssl ? ssl_getfd( jd->ssl ) : -1;
}
else
diff --git a/protocols/jabber/jabber.h b/protocols/jabber/jabber.h
index 49cfe8ee..76546bde 100644
--- a/protocols/jabber/jabber.h
+++ b/protocols/jabber/jabber.h
@@ -316,7 +316,7 @@ extern const struct jabber_away_state jabber_away_state_list[];
int jabber_write_packet( struct im_connection *ic, struct xt_node *node );
int jabber_write( struct im_connection *ic, char *buf, int len );
gboolean jabber_connected_plain( gpointer data, gint source, b_input_condition cond );
-gboolean jabber_connected_ssl( gpointer data, void *source, b_input_condition cond );
+gboolean jabber_connected_ssl( gpointer data, int returncode, void *source, b_input_condition cond );
gboolean jabber_start_stream( struct im_connection *ic );
void jabber_end_stream( struct im_connection *ic );
diff --git a/protocols/msn/soap.c b/protocols/msn/soap.c
index 7d9f3791..d9804f49 100644
--- a/protocols/msn/soap.c
+++ b/protocols/msn/soap.c
@@ -59,6 +59,7 @@ struct msn_soap_req_data
void *data;
struct im_connection *ic;
int ttl;
+ char *error;
char *url, *action, *payload;
struct http_request *http_req;
@@ -157,13 +158,17 @@ static void msn_soap_handle_response( struct http_request *http_req )
xt_free( parser );
}
+ if( http_req->status_code != 200 )
+ soap_req->error = g_strdup( http_req->status_string );
+
st = soap_req->handle_response( soap_req );
fail:
g_free( soap_req->url );
g_free( soap_req->action );
g_free( soap_req->payload );
- soap_req->url = soap_req->action = soap_req->payload = NULL;
+ g_free( soap_req->error );
+ soap_req->url = soap_req->action = soap_req->payload = soap_req->error = NULL;
if( st == MSN_SOAP_RETRY && --soap_req->ttl )
{
@@ -252,6 +257,7 @@ static void msn_soap_free( struct msn_soap_req_data *soap_req )
g_free( soap_req->url );
g_free( soap_req->action );
g_free( soap_req->payload );
+ g_free( soap_req->error );
g_free( soap_req );
}
@@ -409,7 +415,7 @@ static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap
if( sd->secret == NULL )
{
- msn_auth_got_passport_token( ic, NULL, sd->error );
+ msn_auth_got_passport_token( ic, NULL, sd->error ? sd->error : soap_req->error );
return MSN_SOAP_OK;
}
diff --git a/protocols/skype/skype.c b/protocols/skype/skype.c
index 5b1a6c30..760aeb3d 100644
--- a/protocols/skype/skype.c
+++ b/protocols/skype/skype.c
@@ -1156,7 +1156,7 @@ gboolean skype_start_stream(struct im_connection *ic)
return st;
}
-gboolean skype_connected(gpointer data, void *source, b_input_condition cond)
+gboolean skype_connected(gpointer data, int returncode, void *source, b_input_condition cond)
{
struct im_connection *ic = data;
struct skype_data *sd = ic->proto_data;
@@ -1184,7 +1184,7 @@ static void skype_login(account_t *acc)
imcb_log(ic, "Connecting");
sd->ssl = ssl_connect(set_getstr(&acc->set, "server"),
- set_getint(&acc->set, "port"), skype_connected, ic);
+ set_getint(&acc->set, "port"), FALSE, skype_connected, ic);
sd->fd = sd->ssl ? ssl_getfd(sd->ssl) : -1;
sd->username = g_strdup(acc->user);
diff --git a/unix.c b/unix.c
index 07215c07..2ad2edfc 100644
--- a/unix.c
+++ b/unix.c
@@ -40,6 +40,7 @@
#include <sys/wait.h>
#include <pwd.h>
#include <locale.h>
+#include <grp.h>
#if defined(OTR_BI) || defined(OTR_PI)
#include "otr.h"
@@ -151,9 +152,14 @@ int main( int argc, char *argv[] )
pw = getpwnam( global.conf->user );
if( pw )
{
+ initgroups( global.conf->user, pw->pw_gid );
setgid( pw->pw_gid );
setuid( pw->pw_uid );
}
+ else
+ {
+ log_message( LOGLVL_WARNING, "Failed to look up user %s.", global.conf->user );
+ }
}
/* Catch some signals to tell the user what's happening before quitting */