diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2011-12-24 19:02:39 +0100 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2011-12-24 19:02:39 +0100 | 
| commit | 164352ef9d3e8b4b2eea8ec64c3b4590b2388b18 (patch) | |
| tree | 58d3424f7743d89ad4f94fc803ddd7e0563ec251 | |
| parent | e306fbf84aa37ab934c5ea18ccfd75da041af052 (diff) | |
| parent | 96f954df218e81f5580257c319b91217dac2f4bf (diff) | |
Merging mainline.
| -rw-r--r-- | bitlbee.conf | 23 | ||||
| -rw-r--r-- | bitlbee.h | 9 | ||||
| -rw-r--r-- | conf.c | 14 | ||||
| -rw-r--r-- | conf.h | 1 | ||||
| -rwxr-xr-x | configure | 4 | ||||
| -rw-r--r-- | debian/changelog | 30 | ||||
| -rw-r--r-- | debian/control | 14 | ||||
| -rwxr-xr-x | debian/rules | 16 | ||||
| -rw-r--r-- | doc/user-guide/commands.xml | 40 | ||||
| -rw-r--r-- | irc.h | 8 | ||||
| -rw-r--r-- | lib/events_glib.c | 3 | ||||
| -rw-r--r-- | lib/http_client.c | 21 | ||||
| -rw-r--r-- | lib/ssl_bogus.c | 9 | ||||
| -rw-r--r-- | lib/ssl_client.h | 19 | ||||
| -rw-r--r-- | lib/ssl_gnutls.c | 149 | ||||
| -rw-r--r-- | lib/ssl_nss.c | 26 | ||||
| -rw-r--r-- | lib/ssl_openssl.c | 28 | ||||
| -rw-r--r-- | protocols/bee.h | 2 | ||||
| -rw-r--r-- | protocols/jabber/io.c | 32 | ||||
| -rw-r--r-- | protocols/jabber/jabber.c | 7 | ||||
| -rw-r--r-- | protocols/jabber/jabber.h | 2 | ||||
| -rw-r--r-- | protocols/msn/soap.c | 10 | ||||
| -rw-r--r-- | protocols/skype/skype.c | 4 | ||||
| -rw-r--r-- | unix.c | 6 | 
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] @@ -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 + @@ -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 ); @@ -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[] ); @@ -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> @@ -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); @@ -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 */ | 
