Ethereal-dev: Re: [ethereal-dev] ICQ Crash - vprintf()
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Kojak <kojak@xxxxxxxxxx>
Date: Sun, 05 Dec 1999 22:19:02 +0100
> Program received signal SIGSEGV, Segmentation fault. > 0x4040f466 in vfprintf () > (gdb) Terminated > > >From the backtrace made in a core you wont see any symbols resolving > so i guess it triggers a bug in an external lib (gtk ?) > Nope it was a bug in my code. There was already a small fix, this patch fixes other bugs in the code, as well as adds a few more packets. The code also outputs which types it cannot decode. I want to get rid of them before the next formal release, but I have work to finish first, sorry. Have fun. Kojak Index: packet-icq.c =================================================================== RCS file: /cvsroot/ethereal/packet-icq.c,v retrieving revision 1.8 diff -u -r1.8 packet-icq.c --- packet-icq.c 1999/12/01 23:58:44 1.8 +++ packet-icq.c 1999/12/05 21:07:34 @@ -145,7 +145,7 @@ #define SRV_USER_ONL_PORT 0x0008 #define SRV_USER_ONL_REALIP 0x000c #define SRV_USER_ONL_X1 0x0010 -#define SRV_USER_ONL_STATUS 0x0011 +#define SRV_USER_ONL_STATUS 0x0013 #define SRV_USER_ONL_X2 0x0015 #define SRV_USER_OFFLINE 0x0078 @@ -166,6 +166,7 @@ /* * ICQv5 SRV_META_USER subcommands */ +#define META_EX_USER_FOUND 0x0190 #define META_USER_FOUND 0x019a #define META_ABOUT 0x00e6 #define META_USER_INFO 0x00c8 @@ -179,8 +180,22 @@ #define SRV_RECV_MSG_MINUTE 0x0009 #define SRV_RECV_MSG_MSG_TYPE 0x000a +#define SRV_RAND_USER 0x024e +#define SRV_RAND_USER_UIN 0x0000 +#define SRV_RAND_USER_IP 0x0004 +#define SRV_RAND_USER_PORT 0x0008 +#define SRV_RAND_USER_REAL_IP 0x000c +#define SRV_RAND_USER_CLASS 0x0010 +#define SRV_RAND_USER_X1 0x0011 +#define SRV_RAND_USER_STATUS 0x0015 +#define SRV_RAND_USER_TCP_VER 0x0019 + +/* This message has the same structure as cmd_send_msg */ +#define SRV_SYS_DELIVERED_MESS 0x0104 + cmdcode serverMetaSubCmdCode[] = { { "META_USER_FOUND", META_USER_FOUND }, + { "META_EX_USER_FOUND", META_EX_USER_FOUND }, { "META_ABOUT", META_ABOUT }, { "META_USER_INFO", META_USER_INFO }, { NULL, -1 } @@ -203,7 +218,7 @@ { "SRV_X2", 230 }, { "SRV_NOT_CONNECTED", 240 }, { "SRV_TRY_AGAIN", 250 }, - { "SRV_SYS_DELIVERED_MESS", 260 }, + { "SRV_SYS_DELIVERED_MESS", SRV_SYS_DELIVERED_MESS }, { "SRV_INFO_REPLY", 280 }, { "SRV_EXT_INFO_REPLY", 290 }, { "SRV_STATUS_UPDATE", 420 }, @@ -213,7 +228,7 @@ { "SRV_AUTH_UPDATE", 500 }, { "SRV_MULTI_PACKET", SRV_MULTI }, { "SRV_X1", 540 }, - { "SRV_RAND_USER", 590 }, + { "SRV_RAND_USER", SRV_RAND_USER }, { "SRV_META_USER", SRV_META_USER }, { NULL, -1 } }; @@ -275,6 +290,8 @@ #define CMD_SEND_TEXT_CODE_LEN 0x0000 #define CMD_SEND_TEXT_CODE_TEXT 0x0002 +#define CMD_MSG_TO_NEW_USER 0x0456 + #define CMD_QUERY_SERVERS 0x04ba #define CMD_QUERY_ADDONS 0x04c4 @@ -324,7 +341,7 @@ { "CMD_SEND_TEXT_CODE", CMD_SEND_TEXT_CODE }, { "CMD_ACK_MESSAGES", CMD_ACK_MESSAGES }, { "CMD_LOGIN_1", 1100 }, - { "CMD_MSG_TO_NEW_USER", 1110 }, + { "CMD_MSG_TO_NEW_USER", CMD_MSG_TO_NEW_USER }, { "CMD_INFO_REQ", 1120 }, { "CMD_EXT_INFO_REQ", 1130 }, { "CMD_CHANGE_PW", 1180 }, @@ -567,7 +584,51 @@ return p; } +/* + * The packet at pd has a (len, string) pair. + * Copy the string to a buffer, and display it in the tree. + * Observe any limits you might cross. + * + * If anything is wrong, return -1, since -1 is not a valid string + * length. Else, return the number of chars processed. + */ +static guint16 +proto_add_icq_attr(proto_tree* tree, /* The tree to add to */ + const char* pd, /* Pointer to the field */ + const int offset, /* Offset from the start of packet */ + const int size, /* The number of bytes left in pd */ + char* descr) /* The description to use in the tree */ +{ + guint16 len; + char* data; + int left = size; + + if (size<sizeof(guint16)) + return -1; + len = pletohs(pd); + left -= sizeof(guint16); + if (left<len) { + proto_tree_add_text(tree, + offset, + sizeof(guint16), + "Length: %d", len); + return -1; + } + + data = g_malloc(len); + + strncpy(data, pd + sizeof(guint16), len); + data[len - 1] = '\0'; + + proto_tree_add_text(tree, + offset, + sizeof(guint16) + len, + "%s[%d]: %s", descr, len, data); + g_free(data); + return len + sizeof(guint16); +} + static void icqv5_decode_msgType(proto_tree* tree, const unsigned char* pd, /* From start of messageType */ @@ -586,6 +647,7 @@ "First name", "Last name", "Email address", + "Unknown", "Reason"}; static char* emain_field_descr[] = { "Nickname", @@ -706,24 +768,35 @@ break; } case MSG_AUTH_REQ: - /* Five parts, separated by FE */ + /* Six parts, separated by FE */ i = 0; j = 0; - msgText = NULL; - for (n = 0; n < 5; n++) { - for (; - (i<left) && (pd[OFF_MSG_TEXT+i]!=0xfe); - i++) - ; - msgText = g_realloc(msgText, i-j); - strncpy(msgText, pd + OFF_MSG_TEXT + j, i - j - 1); - msgText[i-j-1] = '\0'; - proto_tree_add_text(subtree, - offset + OFF_MSG_TEXT + j, - i - j - 1, - "%s: %s", auth_req_field_descr[n], msgText); - j = ++i; - } + msgText = g_malloc(64); + for (n = 0; n < 6 && i<left; n++) { + while (i<left && pd[OFF_MSG_TEXT+i]!=0xfe) + i++; + if (i<=left) { + /* pd[OFF_MSG_TEXT+i] == 0xfe */ + if (i!=j) { + /* Otherwise, it'd be a null string */ + msgText = g_realloc(msgText, i - j); + strncpy(msgText, pd + OFF_MSG_TEXT + j, i-j); + msgText[i-j] = '\0'; + proto_tree_add_text(subtree, + offset + OFF_MSG_TEXT + j, + i - j, + "%s: %s", auth_req_field_descr[n], msgText); + } else { + proto_tree_add_text(subtree, + offset + OFF_MSG_TEXT + j, + i - j, + "%s: %s", auth_req_field_descr[n], "(null)"); + } + j = ++i; + /* i and j point after the 0xfe character */ + } + } + if (msgText != NULL) g_free(msgText); break; @@ -734,20 +807,30 @@ /* This is necessary, because g_realloc does not behave like * g_malloc if the first parameter == NULL */ msgText = g_malloc(64); - for (n = 0; n < 4; n++) { - for (; - (i<left) && (pd[OFF_MSG_TEXT+i]!=0xfe); - i++) - ; - msgText = g_realloc(msgText, i-j+1); - strncpy(msgText, pd + OFF_MSG_TEXT + j, i - j); - msgText[i-j] = '\0'; - proto_tree_add_text(subtree, - offset + OFF_MSG_TEXT + j, - i - j, - "%s: %s", auth_req_field_descr[n], msgText); - j = ++i; - } + for (n = 0; n < 4 && i<left; n++) { + while (i<left && pd[OFF_MSG_TEXT+i]!=0xfe) + i++; + if (i<=left) { + /* pd[OFF_MSG_TEXT+i] == 0xfe */ + if (i!=j) { + /* Otherwise, it'd be a null string */ + msgText = g_realloc(msgText, i - j); + strncpy(msgText, pd + OFF_MSG_TEXT + j, i-j); + msgText[i-j] = '\0'; + proto_tree_add_text(subtree, + offset + OFF_MSG_TEXT + j, + i - j, + "%s: %s", auth_req_field_descr[n], msgText); + } else { + proto_tree_add_text(subtree, + offset + OFF_MSG_TEXT + j, + i - j, + "%s: %s", auth_req_field_descr[n], "(null)"); + } + j = ++i; + /* i and j point after the 0xfe character */ + } + } if (msgText != NULL) g_free(msgText); break; @@ -1046,7 +1129,8 @@ icqv5_cmd_send_msg(proto_tree* tree, const u_char* pd, int offset, - int size) + int size, + int cmd) { proto_tree* subtree; proto_item* ti; @@ -1055,24 +1139,25 @@ guint16 msgLen = 0xffff; int left = size; /* left chars to do */ - if (left >= 4) { - receiverUIN = pletohl(pd + CMD_SEND_MSG_RECV_UIN); - left -= 4; - } - if (left >= 2) { - msgType = pletohs(pd + CMD_SEND_MSG_MSG_TYPE); - left -= 2; - } - if (left >= 2) { - msgLen = pletohs(pd + CMD_SEND_MSG_MSG_LEN); - left -= 2; - } + if (left < 4) + return; + receiverUIN = pletohl(pd + CMD_SEND_MSG_RECV_UIN); + left -= 4; + if (left < 2) + return; + msgType = pletohs(pd + CMD_SEND_MSG_MSG_TYPE); + left -= 2; + if (left < 2) + return; + msgLen = pletohs(pd + CMD_SEND_MSG_MSG_LEN); + left -= 2; + if (tree) { ti = proto_tree_add_item_format(tree, hf_icq_cmd, offset, size, - CMD_SEND_MSG, + cmd, "Body"); subtree = proto_item_add_subtree(ti, ett_icq_body); proto_tree_add_text(subtree, @@ -1326,8 +1411,8 @@ if (size >= SRV_USER_ONL_REALIP + 4) realipAddrp = &pd[SRV_USER_ONL_REALIP]; - if (size >= SRV_USER_ONL_STATUS + 4) - status = pletohl(pd + SRV_USER_ONL_STATUS); + if (size >= SRV_USER_ONL_STATUS + 2) + status = pletohs(pd + SRV_USER_ONL_STATUS); /* * Kojak: Hypothesis is that this field might be an encoding for the @@ -1363,7 +1448,7 @@ "RealIP: %s", ip_to_str(realipAddrp)); proto_tree_add_text(subtree, offset + SRV_USER_ONL_STATUS, - 4, + 2, "Status: %s", findStatus(status)); proto_tree_add_text(subtree, offset + SRV_USER_ONL_X2, @@ -1459,6 +1544,7 @@ int size) /* Number of chars left to do */ { proto_tree* subtree = NULL; + proto_tree* sstree = NULL; proto_item* ti = NULL; int left = size; const char* p = pd; @@ -1472,6 +1558,7 @@ result = pd[SRV_META_USER_RESULT]; if (tree) { +#if 0 ti = proto_tree_add_item_format(tree, hf_icq_cmd, offset, @@ -1487,7 +1574,40 @@ offset + SRV_META_USER_RESULT, 1, "%s", (result==0x0a)?"Success":"Failure"); + sstree = proto_item_add_subtree(ti, ett_icq_body_parts); +#else + ti = proto_tree_add_text(tree, + offset + SRV_META_USER_SUBCMD, + 2, + "%s", findSubCmd(subcmd)); + sstree = proto_item_add_subtree(ti, ett_icq_body_parts); + proto_tree_add_text(sstree, + offset + SRV_META_USER_RESULT, + 1, + "%s", (result==0x0a)?"Success":"Failure"); +#endif + + /* Skip the META_USER header */ + left -= 3; + p += 3; + switch(subcmd) { + case META_EX_USER_FOUND: + { + /* This is almost the same as META_USER_FOUND, + * however, there's an extra length field + */ + guint16 pktLen = -1; + + /* Read the lenght field */ + pktLen = pletohs(p); + proto_tree_add_text(sstree, + offset + size - left, + sizeof(guint16), + "Length: %d", pktLen); + + p += sizeof(guint16); left -= sizeof(guint16); + } case META_USER_FOUND: { /* The goto mentioned in this block should be local to this @@ -1496,92 +1616,51 @@ * They are used to "implement" a poorman's exception handling */ guint32 uin = -1; - char* nick = NULL; /* Nick */ - char* first = NULL; /* First name */ - char* last = NULL; /* Last name */ - char* email = NULL; - unsigned char auth = -1; int len = 0; + char *descr[] = { + "Nick", + "First name", + "Last name", + "Email", + NULL}; + char** d = descr; guint16 x2 = -1; guint32 x3 = -1; - proto_tree* sstree = proto_item_add_subtree(ti, ett_icq_body_parts); - - /* Skip over META_USER header */ - left -= 3; - p += 3; - /* Get the uin */ + unsigned char auth; + /* + * Read UIN + */ if (left<sizeof(guint32)) - goto stopMetaUser; + break; uin = pletohl(p); proto_tree_add_text(sstree, offset + size - left, sizeof(guint32), "UIN: %ld", uin); p+=sizeof(guint32);left-=sizeof(guint32); - /* Get the nickname */ - if (left<sizeof(guint16)) - goto stopMetaUser; - len = pletohs(p); - p+=sizeof(guint16);left-=sizeof(guint16); - if ((len<=0) || (left<len)) - goto stopMetaUser; - nick = g_malloc(len); - strncpy(nick, p, len); - proto_tree_add_text(sstree, - offset + size - left, - sizeof(guint16)+len, - "Nick(%d): %s", len, nick); - p+=len;left-=len; - /* Get the first name */ - if (left<sizeof(guint16)) - goto stopMetaUser; - len = pletohs(p); - p+=sizeof(guint16);left-=sizeof(guint16); - if ((len<=0) || (left<len)) - goto stopMetaUser; - first = g_malloc(len); - strncpy(first, p, len); - proto_tree_add_text(sstree, - offset + size - left, - sizeof(guint16)+len, - "First(%d): %s", len, first); - p+=len;left-=len; - /* Get last name */ - if (left<sizeof(guint16)) - goto stopMetaUser; - len = pletohs(p); - p+=sizeof(guint16);left-=sizeof(guint16); - if ((len<=0) || (left<len)) - goto stopMetaUser; - last = g_malloc(len); - strncpy(last, p, len); - proto_tree_add_text(sstree, - offset + size - left, - sizeof(guint16)+len, - "Last(%d): %s", len, last); - p+=len;left-=len; - /* Get email address */ - if (left<sizeof(guint16)) - goto stopMetaUser; - len = pletohs(p); - p+=sizeof(guint16);left-=sizeof(guint16); - if ((len<=0) || (left<len)) - goto stopMetaUser; - email = g_malloc(len); - strncpy(email, p, len); - proto_tree_add_text(sstree, - offset + size - left, - sizeof(guint16)+len, - "Email(%d): %s", len, email); - p+=len;left-=len; + + for ( ; *d!=NULL; d++) { + len = proto_add_icq_attr(sstree, + p, + offset + size - left, + left, + *d); + if (len == -1) + return; + p += len; left -= len; + } /* Get the authorize setting */ if (left<sizeof(unsigned char)) - goto stopMetaUser; + break; auth = *p; + proto_tree_add_text(sstree, + offset + size - left, + sizeof(guint16), + "authorization: %s", (auth==0x01)?"Neccessary":"Who needs it"); p++; left--; /* Get x2 */ if (left<sizeof(guint16)) - goto stopMetaUser; + break; x2 = pletohs(p); proto_tree_add_text(sstree, offset + size - left, @@ -1590,34 +1669,19 @@ p+=sizeof(guint16);left-=sizeof(guint16); /* Get x3 */ if (left<sizeof(guint32)) - goto stopMetaUser; + break; x3 = pletohl(p); proto_tree_add_text(sstree, offset + size - left, sizeof(guint32), "x3: %08x", x3); p+=sizeof(guint32);left-=sizeof(guint32); - - stopMetaUser: - if (nick!=NULL) - g_free(nick); - if (first!=NULL) - g_free(first); - if (last!=NULL) - g_free(last); - if (email!=NULL) - g_free(last); break; } case META_ABOUT: { int len; char* about = NULL; - proto_tree* sstree = proto_item_add_subtree(ti, ett_icq_body_parts); - - /* Skip over META_USER header */ - left -= 3; - p += 3; /* Get the about information */ if (left<sizeof(guint16)) break; @@ -1664,11 +1728,6 @@ unsigned char user_timezone = -1; unsigned char auth = -1; int len = 0; - proto_tree* sstree = proto_item_add_subtree(ti, ett_icq_body_parts); - - /* Skip over META_USER header */ - left -= 3; - p += 3; #if 0 /* Get the uin */ if (left<sizeof(guint32)) @@ -1819,6 +1878,96 @@ } } +static void +icqv5_srv_rand_user(proto_tree* tree, /* Tree to put the data in */ + const u_char* pd, /* Packet content */ + int offset, /* Offset from the start of the packet to the content */ + int size) /* Number of chars left to do */ +{ + proto_tree* subtree = NULL; + proto_item* ti = NULL; + guint32 uin = -1; + const unsigned char* IP = NULL; + guint32 port = -1; + const unsigned char* realIP = NULL; + unsigned char commClass = -1; + guint32 status; + guint16 tcpVer; + int left = size; + + if (tree) { + ti = proto_tree_add_item_format(tree, + hf_icq_cmd, + offset, + SRV_RAND_USER_TCP_VER + 2, + SRV_RAND_USER, + "Body"); + subtree = proto_item_add_subtree(ti, ett_icq_body); + /* guint32 UIN */ + if (left<sizeof(guint32)) + return; + uin = pletohl(pd + SRV_RAND_USER_UIN); + proto_tree_add_text(subtree, + offset + SRV_RAND_USER_UIN, + sizeof(guint32), + "UIN: %ld", uin); + left -= sizeof(guint32); + /* guint32 IP */ + if (left<sizeof(guint32)) + return; + IP = pd + SRV_RAND_USER_IP; + proto_tree_add_text(subtree, + offset + SRV_RAND_USER_IP, + sizeof(guint32), + "IP: %s", ip_to_str(IP)); + left -= sizeof(guint32); + /* guint32 portNum */ + if (left<sizeof(guint32)) + return; + port = pletohs(pd + SRV_RAND_USER_PORT); + proto_tree_add_text(subtree, + offset + SRV_RAND_USER_UIN, + sizeof(guint32), + "Port: %ld", port); + left -= sizeof(guint32); + /* guint32 realIP */ + if (left<sizeof(guint32)) + return; + realIP = pd + SRV_RAND_USER_REAL_IP; + proto_tree_add_text(subtree, + offset + SRV_RAND_USER_REAL_IP, + sizeof(guint32), + "RealIP: %s", ip_to_str(realIP)); + left -= sizeof(guint32); + /* guit16 Communication Class */ + if (left<sizeof(unsigned char)) + return; + commClass = pd[SRV_RAND_USER_CLASS]; + proto_tree_add_text(subtree, + offset + SRV_RAND_USER_CLASS, + sizeof(unsigned char), + "Class: %s", (commClass!=4)?"User to User":"Through Server"); + left -= sizeof(unsigned char); + /* guint32 status */ + if (left<sizeof(guint32)) + return; + status = pletohs(pd + SRV_RAND_USER_STATUS); + proto_tree_add_text(subtree, + offset + SRV_RAND_USER_STATUS, + sizeof(guint32), + "Status: (%ld) %s", status, findStatus(status)); + /* guint16 tcpVersion */ + if (left<sizeof(guint16)) + return; + tcpVer = pletohs(pd + SRV_RAND_USER_TCP_VER); + proto_tree_add_text(subtree, + offset + SRV_RAND_USER_TCP_VER, + sizeof(guint16), + "TCPVersion: %d", tcpVer); + left -= sizeof(guint16); + } +} + /* * Dissect all the v5 client traffic. This is encrypted, so be careful. */ @@ -1916,10 +2065,12 @@ pktsize - ICQ5_CL_HDRSIZE); break; case CMD_SEND_MSG: + case CMD_MSG_TO_NEW_USER: icqv5_cmd_send_msg(icq_tree, decr_pd + ICQ5_CL_HDRSIZE, offset + ICQ5_CL_HDRSIZE, - pktsize - ICQ5_CL_HDRSIZE); + pktsize - ICQ5_CL_HDRSIZE, + cmd); break; case CMD_RAND_SEARCH: icqv5_cmd_rand_search(icq_tree, @@ -2086,6 +2237,21 @@ "Checkcode: 0x%08x", checkcode); switch (cmd) { + case SRV_RAND_USER: + icqv5_srv_rand_user(icq_tree, + decr_pd + ICQ5_SRV_HDRSIZE, + offset + ICQ5_SRV_HDRSIZE, + pktsize - ICQ5_SRV_HDRSIZE); + break; + case SRV_SYS_DELIVERED_MESS: + /* The message structures are all the same. Why not run + * the same routine? */ + icqv5_cmd_send_msg(icq_tree, + decr_pd + ICQ5_SRV_HDRSIZE, + offset + ICQ5_SRV_HDRSIZE, + pktsize - ICQ5_SRV_HDRSIZE, + cmd); + break; case SRV_USER_ONLINE: icqv5_srv_user_online(icq_tree, decr_pd + ICQ5_SRV_HDRSIZE,
- Follow-Ups:
- Re: [ethereal-dev] ICQ Crash - vprintf()
- From: Guy Harris
- Re: [ethereal-dev] ICQ Crash - vprintf()
- References:
- [ethereal-dev] ICQ Crash - vprintf()
- From: Florian Lohoff
- [ethereal-dev] ICQ Crash - vprintf()
- Prev by Date: Re: [ethereal-dev] vlan updates and filtered capture
- Next by Date: Re: [ethereal-dev] vlan updates and filtered capture
- Previous by thread: Re: [ethereal-dev] ICQ Crash - vprintf()
- Next by thread: Re: [ethereal-dev] ICQ Crash - vprintf()
- Index(es):