Add escaping of an apostrophe in XML output.
[obnox/wireshark/wip.git] / packet-aim-signon.c
1 /* packet-aim-signon.c
2  * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Signon
3  * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
4  * Copyright 2000, Ralf Hoelzer <ralf@well.com>
5  *
6  * $Id: packet-aim-signon.c,v 1.3 2004/04/26 18:21:10 obiot Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <ctype.h>
35
36 #include <glib.h>
37
38 #include <epan/packet.h>
39 #include <epan/strutil.h>
40
41 #include "packet-aim.h"
42
43 #define FAMILY_SIGNON     0x0017
44
45 /* Family Signon */
46 #define FAMILY_SIGNON_ERROR          0x0001
47 #define FAMILY_SIGNON_LOGON          0x0002
48 #define FAMILY_SIGNON_LOGON_REPLY    0x0003
49 #define FAMILY_SIGNON_UIN_REQ        0x0004
50 #define FAMILY_SIGNON_UIN_REPL       0x0005
51 #define FAMILY_SIGNON_SIGNON         0x0006
52 #define FAMILY_SIGNON_SIGNON_REPLY   0x0007
53 #define FAMILY_SIGNON_S_SECUREID_REQ 0x000a
54 #define FAMILY_SIGNON_C_SECUREID_REP 0x000b
55
56 static const value_string aim_fnac_family_signon[] = {
57   { FAMILY_SIGNON_LOGON, "Logon" },
58   { FAMILY_SIGNON_LOGON_REPLY, "Logon Reply" },
59   { FAMILY_SIGNON_UIN_REQ, "Request UIN" },
60   { FAMILY_SIGNON_UIN_REPL, "New UIN response" },
61   { FAMILY_SIGNON_SIGNON, "Sign-on" },
62   { FAMILY_SIGNON_SIGNON_REPLY, "Sign-on Reply" },
63   { FAMILY_SIGNON_S_SECUREID_REQ, "Server SecureID Request" },
64   { FAMILY_SIGNON_C_SECUREID_REP, "Client SecureID Reply" },
65   { 0, NULL }
66 };
67
68 static int dissect_aim_snac_signon(tvbuff_t *tvb, packet_info *pinfo, 
69                                     proto_tree *tree);
70 static int dissect_aim_snac_signon_logon(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
71 static int dissect_aim_snac_signon_logon_reply(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
72 static int dissect_aim_snac_signon_signon(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
73 static int dissect_aim_snac_signon_signon_reply(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
74
75 /* Initialize the protocol and registered fields */
76 static int proto_aim_signon = -1;
77 static int hf_aim_infotype = -1;
78 static int hf_aim_signon_challenge_len = -1;
79 static int hf_aim_signon_challenge = -1;
80
81
82 /* Initialize the subtree pointers */
83 static gint ett_aim_signon   = -1;
84
85 static int dissect_aim_snac_signon(tvbuff_t *tvb, packet_info *pinfo, 
86                                     proto_tree *tree)
87 {
88         struct aiminfo *aiminfo = pinfo->private_data;
89         int offset = 0;
90
91         proto_item *ti = NULL;
92         proto_tree *signon_tree = NULL;
93         if(tree) {
94                 ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Signon");
95                 signon_tree = proto_item_add_subtree(ti, ett_aim_signon);
96         }                                                                                   
97         
98   switch(aiminfo->subtype)
99     {
100         case FAMILY_SIGNON_ERROR:
101       return dissect_aim_snac_error(tvb, pinfo, offset, signon_tree);
102     case FAMILY_SIGNON_LOGON:
103       return dissect_aim_snac_signon_logon(tvb, pinfo, offset, signon_tree);
104     case FAMILY_SIGNON_LOGON_REPLY:
105       return dissect_aim_snac_signon_logon_reply(tvb, pinfo, offset, signon_tree);
106     case FAMILY_SIGNON_SIGNON:
107       return dissect_aim_snac_signon_signon(tvb, pinfo, offset, signon_tree);
108     case FAMILY_SIGNON_SIGNON_REPLY:
109       return dissect_aim_snac_signon_signon_reply(tvb, pinfo, offset, signon_tree);
110         case FAMILY_SIGNON_S_SECUREID_REQ:
111           /* No data */
112           return 0;
113         case FAMILY_SIGNON_UIN_REQ:
114         case FAMILY_SIGNON_UIN_REPL:
115         case FAMILY_SIGNON_C_SECUREID_REP:
116         /*FIXME*/       
117         default:
118           return 0;
119     }
120 }
121
122 static int dissect_aim_snac_signon_logon(tvbuff_t *tvb, packet_info *pinfo, 
123                                           int offset, proto_tree *tree)
124 {
125   while (tvb_length_remaining(tvb, offset) > 0) {
126     offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
127   }
128   return offset;
129 }
130
131 static int dissect_aim_snac_signon_logon_reply(tvbuff_t *tvb, 
132                                                 packet_info *pinfo, 
133                                                 int offset, proto_tree *tree)
134 {
135     if (check_col(pinfo->cinfo, COL_INFO)) 
136       col_append_fstr(pinfo->cinfo, COL_INFO, ", Login information reply");
137
138     while (tvb_length_remaining(tvb, offset) > 0) {
139       offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
140     }
141         return offset;
142 }
143
144 static int dissect_aim_snac_signon_signon(tvbuff_t *tvb, packet_info *pinfo, 
145                                            int offset, proto_tree *tree)
146 {
147   guint8 buddyname_length = 0;
148   char buddyname[MAX_BUDDYNAME_LENGTH + 1];
149
150   /* Info Type */
151   proto_tree_add_item(tree, hf_aim_infotype, tvb, offset, 2, FALSE);
152   offset += 2;
153
154   /* Unknown */
155   offset += 1;
156
157   /* Buddy Name */
158   buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
159   
160   if (check_col(pinfo->cinfo, COL_INFO)) {
161     col_append_fstr(pinfo->cinfo, COL_INFO, " Username: %s", buddyname);
162   }
163   
164   if(tree) {
165     proto_tree_add_text(tree, tvb, offset + 1, buddyname_length, 
166                         "Screen Name: %s", buddyname);
167   }
168   
169   offset += buddyname_length + 1;
170   return offset;
171 }
172
173 static int dissect_aim_snac_signon_signon_reply(tvbuff_t *tvb, 
174                                                  packet_info *pinfo, 
175                                                  int offset, proto_tree *tree)
176 {
177   guint16 challenge_length = 0;
178
179   if (check_col(pinfo->cinfo, COL_INFO)) 
180     col_append_fstr(pinfo->cinfo, COL_INFO, ", Sign-on reply");
181
182   /* Logon Challenge Length */
183   challenge_length = tvb_get_ntohs(tvb, offset);
184   proto_tree_add_item(tree, hf_aim_signon_challenge_len, tvb, offset, 2, FALSE);
185   offset += 2;
186
187   /* Challenge */
188   proto_tree_add_item(tree, hf_aim_signon_challenge, tvb, offset, challenge_length, FALSE);
189   offset += challenge_length;
190   return offset;
191 }
192
193 /* Register the protocol with Ethereal */
194 void
195 proto_register_aim_signon(void)
196 {
197
198 /* Setup list of header fields */
199   static hf_register_info hf[] = {
200     { &hf_aim_infotype,
201       { "Infotype", "aim.infotype", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
202     },
203     { &hf_aim_signon_challenge_len,
204       { "Signon challenge length", "aim.signon.challengelen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
205     },
206     { &hf_aim_signon_challenge,
207       { "Signon challenge", "aim.signon.challenge", FT_STRING, BASE_HEX, NULL, 0x0, "", HFILL }
208     },
209   };
210
211 /* Setup protocol subtree array */
212   static gint *ett[] = {
213     &ett_aim_signon,
214   };
215
216 /* Register the protocol name and description */
217   proto_aim_signon = proto_register_protocol("AIM Signon", "AIM Signon", "aim_signon");
218
219 /* Required function calls to register the header fields and subtrees used */
220   proto_register_field_array(proto_aim_signon, hf, array_length(hf));
221   proto_register_subtree_array(ett, array_length(ett));
222 }
223
224 void
225 proto_reg_handoff_aim_signon(void)
226 {
227   dissector_handle_t aim_handle;
228
229   aim_handle = new_create_dissector_handle(dissect_aim_snac_signon, proto_aim_signon);
230   dissector_add("aim.family", FAMILY_SIGNON, aim_handle);
231   aim_init_family(FAMILY_SIGNON, "Signon", aim_fnac_family_signon);
232 }