comparison libpurple/protocols/qq/qq_base.c @ 28213:33921125348d

The output buffer passed to qq_encrypt needs to be 17 bytes bigger than the data you're encrypting, not 16 bytes bigger. Fixes #10191. It's hard to say whether this actually causes problems. My guess is that it does not. However, the way the qq protocol plugin constructs the plain text buffer to be passed to qq_encrypt is error prone, and the many calls to g_newa(guint8, MAX_PACKET_SIZE) are really bad because MAX_PACKET_SIZE is 64KB. This is a ridiculous amount of space to request on the stack. All these qq_put8 qq_put16 qq_put32 qq_putdata functions should be changed to insert data into a dynamically allocated GString instead of the stack-allocated buffers that they use now. This eliminates the potential for accidentally overwriting the end of the buffer. And the second g_newa() for the output buffer passed into qq_encrypt() should be changed to allocate space on the heap in most places because, as previously noted, 64KB is a ridiculous amount of memory to request from the stack. Heap allocation may be expensive when compared to stack allocation, but I feel it's usually worth it to eliminate the possibilty of buffer overflow.
author Mark Doliner <mark@kingant.net>
date Fri, 04 Sep 2009 22:50:26 +0000
parents f541583e31bd
children f1437342cc0e
comparison
equal deleted inserted replaced
28210:9af95186dde4 28213:33921125348d
243 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 243 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
244 qd = (qq_data *) gc->proto_data; 244 qd = (qq_data *) gc->proto_data;
245 245
246 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); 246 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
247 247
248 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); 248 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
249 memset(raw_data, 0, MAX_PACKET_SIZE - 16); 249 memset(raw_data, 0, MAX_PACKET_SIZE - 17);
250 250
251 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ 251 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
252 252
253 bytes = 0; 253 bytes = 0;
254 /* now generate the encrypted data 254 /* now generate the encrypted data
255 * 000-015 use password_twice_md5 as key to encrypt empty string */ 255 * 000-015 use password_twice_md5 as key to encrypt empty string */
256 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); 256 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5);
607 qd = (qq_data *) gc->proto_data; 607 qd = (qq_data *) gc->proto_data;
608 608
609 raw_data = g_newa(guint8, 128); 609 raw_data = g_newa(guint8, 128);
610 memset(raw_data, 0, 128); 610 memset(raw_data, 0, 128);
611 611
612 encrypted = g_newa(guint8, 128 + 16); /* 16 bytes more */ 612 encrypted = g_newa(guint8, 128 + 17); /* 17 bytes more */
613 613
614 bytes = 0; 614 bytes = 0;
615 if (qd->redirect == NULL) { 615 if (qd->redirect == NULL) {
616 /* first packet to get server */ 616 /* first packet to get server */
617 qd->redirect_len = 15; 617 qd->redirect_len = 15;
680 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 680 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
681 qd = (qq_data *) gc->proto_data; 681 qd = (qq_data *) gc->proto_data;
682 682
683 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); 683 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
684 684
685 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); 685 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
686 memset(raw_data, 0, MAX_PACKET_SIZE - 16); 686 memset(raw_data, 0, MAX_PACKET_SIZE - 17);
687 687
688 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ 688 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
689 689
690 bytes = 0; 690 bytes = 0;
691 bytes += qq_put8(raw_data + bytes, qd->ld.token_len); 691 bytes += qq_put8(raw_data + bytes, qd->ld.token_len);
692 bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len); 692 bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len);
693 bytes += qq_put8(raw_data + bytes, 3); /* Subcommand */ 693 bytes += qq_put8(raw_data + bytes, 3); /* Subcommand */
719 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 719 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
720 qd = (qq_data *) gc->proto_data; 720 qd = (qq_data *) gc->proto_data;
721 721
722 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); 722 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
723 723
724 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); 724 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
725 memset(raw_data, 0, MAX_PACKET_SIZE - 16); 725 memset(raw_data, 0, MAX_PACKET_SIZE - 17);
726 726
727 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ 727 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
728 728
729 bytes = 0; 729 bytes = 0;
730 bytes += qq_put8(raw_data + bytes, qd->ld.token_len); 730 bytes += qq_put8(raw_data + bytes, qd->ld.token_len);
731 bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len); 731 bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len);
732 bytes += qq_put8(raw_data + bytes, 3); /* Subcommand */ 732 bytes += qq_put8(raw_data + bytes, 3); /* Subcommand */
763 qd = (qq_data *) gc->proto_data; 763 qd = (qq_data *) gc->proto_data;
764 764
765 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); 765 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
766 g_return_if_fail(code != NULL && code_len > 0); 766 g_return_if_fail(code != NULL && code_len > 0);
767 767
768 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); 768 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
769 memset(raw_data, 0, MAX_PACKET_SIZE - 16); 769 memset(raw_data, 0, MAX_PACKET_SIZE - 17);
770 770
771 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ 771 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
772 772
773 bytes = 0; 773 bytes = 0;
774 bytes += qq_put8(raw_data + bytes, qd->ld.token_len); 774 bytes += qq_put8(raw_data + bytes, qd->ld.token_len);
775 bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len); 775 bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len);
776 bytes += qq_put8(raw_data + bytes, 4); /* Subcommand */ 776 bytes += qq_put8(raw_data + bytes, 4); /* Subcommand */
996 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 996 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
997 qd = (qq_data *) gc->proto_data; 997 qd = (qq_data *) gc->proto_data;
998 998
999 g_return_if_fail(qd->ld.token_ex != NULL && qd->ld.token_ex_len > 0); 999 g_return_if_fail(qd->ld.token_ex != NULL && qd->ld.token_ex_len > 0);
1000 1000
1001 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); 1001 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
1002 memset(raw_data, 0, MAX_PACKET_SIZE - 16); 1002 memset(raw_data, 0, MAX_PACKET_SIZE - 17);
1003 1003
1004 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ 1004 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
1005 1005
1006 /* Encrypted password and put in encrypted */ 1006 /* Encrypted password and put in encrypted */
1007 bytes = 0; 1007 bytes = 0;
1008 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); 1008 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5));
1009 bytes += qq_put16(raw_data + bytes, 0); 1009 bytes += qq_put16(raw_data + bytes, 0);
1164 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 1164 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
1165 qd = (qq_data *) gc->proto_data; 1165 qd = (qq_data *) gc->proto_data;
1166 1166
1167 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); 1167 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
1168 1168
1169 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); 1169 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
1170 memset(raw_data, 0, MAX_PACKET_SIZE - 16); 1170 memset(raw_data, 0, MAX_PACKET_SIZE - 17);
1171 1171
1172 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ 1172 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
1173 1173
1174 /* Encrypted password and put in encrypted */ 1174 /* Encrypted password and put in encrypted */
1175 bytes = 0; 1175 bytes = 0;
1176 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); 1176 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5));
1177 bytes += qq_put16(raw_data + bytes, 0); 1177 bytes += qq_put16(raw_data + bytes, 0);
1340 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 1340 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
1341 qd = (qq_data *) gc->proto_data; 1341 qd = (qq_data *) gc->proto_data;
1342 1342
1343 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); 1343 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
1344 1344
1345 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); 1345 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 17);
1346 memset(raw_data, 0, MAX_PACKET_SIZE - 16); 1346 memset(raw_data, 0, MAX_PACKET_SIZE - 17);
1347 1347
1348 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ 1348 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 17 bytes more */
1349 1349
1350 /* Encrypted password and put in encrypted */ 1350 /* Encrypted password and put in encrypted */
1351 bytes = 0; 1351 bytes = 0;
1352 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); 1352 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5));
1353 bytes += qq_put16(raw_data + bytes, 0); 1353 bytes += qq_put16(raw_data + bytes, 0);