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