Fix remotely-triggerable crashes by validating strings in a few release-2.x.y
authorMark Doliner <markdoliner@pidgin.im>
Tue, 06 Dec 2011 06:40:23 +0000
branchrelease-2.x.y
changeset8431da66063b pushlog
parent 0d126855edbf
child 9d90f89322ea
Fix remotely-triggerable crashes by validating strings in a few
messages related to buddy list management. Fixes #14682

I changed the four functions that parse incoming authorization-related
SNACs. The changes are:

- Make sure we have a buddy name and it is valid UTF-8. If not, we
drop the SNAC and log a debug message (we can't do much with an empty,
invalid or incorrect buddy name). This wasn't a part of the bug
report and I doubt it's actually a problem, but it seems like a good
idea regardless.

- If the incoming message is not valid UTF-8 then use
purple_utf8_salvage() to replace invalid bytes with question marks. I
believe this fixes the bug in question.
ChangeLog
libpurple/protocols/oscar/family_feedbag.c
     1.1 --- a/ChangeLog
     1.2 +++ b/ChangeLog
     1.3 @@ -4,6 +4,10 @@
     1.4  	Finch:
     1.5  	* Fix compilation on OpenBSD.
     1.6  
     1.7 +	AIM and ICQ:
     1.8 +	* Fix remotely-triggerable crashes by validating strings in a few
     1.9 +	  messages related to buddy list management. (#14682)
    1.10 +
    1.11  	Bonjour:
    1.12  	* IPv6 fixes (Linus L├╝ssing)
    1.13  
     2.1 --- a/libpurple/protocols/oscar/family_feedbag.c
     2.2 +++ b/libpurple/protocols/oscar/family_feedbag.c
     2.3 @@ -1650,18 +1650,35 @@
     2.4  	int ret = 0;
     2.5  	aim_rxcallback_t userfunc;
     2.6  	guint16 tmp;
     2.7 -	char *bn, *msg;
     2.8 +	char *bn, *msg, *tmpstr;
     2.9  
    2.10  	/* Read buddy name */
    2.11 -	if ((tmp = byte_stream_get8(bs)))
    2.12 -		bn = byte_stream_getstr(bs, tmp);
    2.13 -	else
    2.14 -		bn = NULL;
    2.15 +	tmp = byte_stream_get8(bs);
    2.16 +	if (!tmp) {
    2.17 +		purple_debug_warning("oscar", "Dropping auth grant SNAC "
    2.18 +				"because username was empty\n");
    2.19 +		return 0;
    2.20 +	}
    2.21 +	bn = byte_stream_getstr(bs, tmp);
    2.22 +	if (!g_utf8_validate(bn, -1, NULL)) {
    2.23 +		purple_debug_warning("oscar", "Dropping auth grant SNAC "
    2.24 +				"because the username was not valid UTF-8\n");
    2.25 +		g_free(bn);
    2.26 +	}
    2.27  
    2.28 -	/* Read message (null terminated) */
    2.29 -	if ((tmp = byte_stream_get16(bs)))
    2.30 +	/* Read message */
    2.31 +	tmp = byte_stream_get16(bs);
    2.32 +	if (tmp) {
    2.33  		msg = byte_stream_getstr(bs, tmp);
    2.34 -	else
    2.35 +		if (!g_utf8_validate(msg, -1, NULL)) {
    2.36 +			/* Ugh, msg isn't UTF8.  Let's salvage. */
    2.37 +			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
    2.38 +					"grant from %s\n", bn);
    2.39 +			tmpstr = purple_utf8_salvage(msg);
    2.40 +			g_free(msg);
    2.41 +			msg = tmpstr;
    2.42 +		}
    2.43 +	} else
    2.44  		msg = NULL;
    2.45  
    2.46  	/* Unknown */
    2.47 @@ -1724,18 +1741,35 @@
    2.48  	int ret = 0;
    2.49  	aim_rxcallback_t userfunc;
    2.50  	guint16 tmp;
    2.51 -	char *bn, *msg;
    2.52 +	char *bn, *msg, *tmpstr;
    2.53  
    2.54  	/* Read buddy name */
    2.55 -	if ((tmp = byte_stream_get8(bs)))
    2.56 -		bn = byte_stream_getstr(bs, tmp);
    2.57 -	else
    2.58 -		bn = NULL;
    2.59 +	tmp = byte_stream_get8(bs);
    2.60 +	if (!tmp) {
    2.61 +		purple_debug_warning("oscar", "Dropping auth request SNAC "
    2.62 +				"because username was empty\n");
    2.63 +		return 0;
    2.64 +	}
    2.65 +	bn = byte_stream_getstr(bs, tmp);
    2.66 +	if (!g_utf8_validate(bn, -1, NULL)) {
    2.67 +		purple_debug_warning("oscar", "Dropping auth request SNAC "
    2.68 +				"because the username was not valid UTF-8\n");
    2.69 +		g_free(bn);
    2.70 +	}
    2.71  
    2.72 -	/* Read message (null terminated) */
    2.73 -	if ((tmp = byte_stream_get16(bs)))
    2.74 +	/* Read message */
    2.75 +	tmp = byte_stream_get16(bs);
    2.76 +	if (tmp) {
    2.77  		msg = byte_stream_getstr(bs, tmp);
    2.78 -	else
    2.79 +		if (!g_utf8_validate(msg, -1, NULL)) {
    2.80 +			/* Ugh, msg isn't UTF8.  Let's salvage. */
    2.81 +			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
    2.82 +					"request from %s\n", bn);
    2.83 +			tmpstr = purple_utf8_salvage(msg);
    2.84 +			g_free(msg);
    2.85 +			msg = tmpstr;
    2.86 +		}
    2.87 +	} else
    2.88  		msg = NULL;
    2.89  
    2.90  	/* Unknown */
    2.91 @@ -1808,21 +1842,38 @@
    2.92  	aim_rxcallback_t userfunc;
    2.93  	guint16 tmp;
    2.94  	guint8 reply;
    2.95 -	char *bn, *msg;
    2.96 +	char *bn, *msg, *tmpstr;
    2.97  
    2.98  	/* Read buddy name */
    2.99 -	if ((tmp = byte_stream_get8(bs)))
   2.100 -		bn = byte_stream_getstr(bs, tmp);
   2.101 -	else
   2.102 -		bn = NULL;
   2.103 +	tmp = byte_stream_get8(bs);
   2.104 +	if (!tmp) {
   2.105 +		purple_debug_warning("oscar", "Dropping auth reply SNAC "
   2.106 +				"because username was empty\n");
   2.107 +		return 0;
   2.108 +	}
   2.109 +	bn = byte_stream_getstr(bs, tmp);
   2.110 +	if (!g_utf8_validate(bn, -1, NULL)) {
   2.111 +		purple_debug_warning("oscar", "Dropping auth reply SNAC "
   2.112 +				"because the username was not valid UTF-8\n");
   2.113 +		g_free(bn);
   2.114 +	}
   2.115  
   2.116  	/* Read reply */
   2.117  	reply = byte_stream_get8(bs);
   2.118  
   2.119 -	/* Read message (null terminated) */
   2.120 -	if ((tmp = byte_stream_get16(bs)))
   2.121 +	/* Read message */
   2.122 +	tmp = byte_stream_get16(bs);
   2.123 +	if (tmp) {
   2.124  		msg = byte_stream_getstr(bs, tmp);
   2.125 -	else
   2.126 +		if (!g_utf8_validate(msg, -1, NULL)) {
   2.127 +			/* Ugh, msg isn't UTF8.  Let's salvage. */
   2.128 +			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
   2.129 +					"reply from %s\n", bn);
   2.130 +			tmpstr = purple_utf8_salvage(msg);
   2.131 +			g_free(msg);
   2.132 +			msg = tmpstr;
   2.133 +		}
   2.134 +	} else
   2.135  		msg = NULL;
   2.136  
   2.137  	/* Unknown */
   2.138 @@ -1848,10 +1899,18 @@
   2.139  	char *bn;
   2.140  
   2.141  	/* Read buddy name */
   2.142 -	if ((tmp = byte_stream_get8(bs)))
   2.143 -		bn = byte_stream_getstr(bs, tmp);
   2.144 -	else
   2.145 -		bn = NULL;
   2.146 +	tmp = byte_stream_get8(bs);
   2.147 +	if (!tmp) {
   2.148 +		purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
   2.149 +				"because username was empty\n");
   2.150 +		return 0;
   2.151 +	}
   2.152 +	bn = byte_stream_getstr(bs, tmp);
   2.153 +	if (!g_utf8_validate(bn, -1, NULL)) {
   2.154 +		purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
   2.155 +				"because the username was not valid UTF-8\n");
   2.156 +		g_free(bn);
   2.157 +	}
   2.158  
   2.159  	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
   2.160  		ret = userfunc(od, conn, frame, bn);