Fix some gcc 4.6 "set but not used [-Wunused-but-set-variable]" warnings;
[metze/wireshark/wip.git] / epan / dissectors / packet-ncp-sss.c
1 /* packet-ncp-sss.c
2  * Routines for Novell SecretStore Services
3  * Greg Morris <gmorris@novell.com>
4  * Copyright (c) Novell, Inc. 2002-2003
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
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 <glib.h>
32 #include <epan/packet.h>
33 #include <epan/strutil.h>
34 #include "packet-ncp-int.h"
35 #include "packet-ncp-sss.h"
36
37 static gint ett_sss = -1;
38
39 static int proto_sss = -1;
40 static int hf_buffer_size = -1;
41 static int hf_ping_version = -1;
42 static int hf_flags = -1;
43 static int hf_context = -1;
44 static int hf_frag_handle = -1;
45 static int hf_length = -1;
46 static int hf_verb = -1;
47 static int hf_user = -1;
48 static int hf_secret = -1;
49 static int hf_sss_version = -1;
50 static int hf_return_code = -1;
51 static int hf_enc_cred = -1;
52 static int hf_enc_data = -1;
53 static int hfbit1 = -1;
54 static int hfbit2 = -1;
55 static int hfbit3 = -1;
56 static int hfbit4 = -1;
57 static int hfbit5 = -1;
58 static int hfbit6 = -1;
59 static int hfbit7 = -1;
60 static int hfbit8 = -1;
61 static int hfbit9 = -1;
62 static int hfbit10 = -1;
63 static int hfbit11 = -1;
64 static int hfbit12 = -1;
65 static int hfbit13 = -1;
66 static int hfbit14 = -1;
67 static int hfbit15 = -1;
68 static int hfbit16 = -1;
69 static int hfbit17 = -1;
70 static int hfbit18 = -1;
71 static int hfbit19 = -1;
72 static int hfbit20 = -1;
73 static int hfbit21 = -1;
74 static int hfbit22 = -1;
75 static int hfbit23 = -1;
76 static int hfbit24 = -1;
77 static int hfbit25 = -1;
78 static int hfbit26 = -1;
79 static int hfbit27 = -1;
80 static int hfbit28 = -1;
81 static int hfbit29 = -1;
82 static int hfbit30 = -1;
83 static int hfbit31 = -1;
84 static int hfbit32 = -1;
85
86 static const value_string sss_func_enum[] = {
87     { 0x00000001, "Ping Server" },
88     { 0x00000002, "Fragment" },
89     { 0x00000003, "Write App Secrets" },
90     { 0x00000004, "Add Secret ID" },
91     { 0x00000005, "Remove Secret ID" },
92     { 0x00000006, "Remove SecretStore" },
93     { 0x00000007, "Enumerate Secret IDs" },
94     { 0x00000008, "Unlock Store" },
95     { 0x00000009, "Set Master Password" },
96     { 0x0000000a, "Get Service Information" },
97     { 0,          NULL }
98 };
99
100
101 static const value_string sss_verb_enum[] = {
102     { 0x00000000, "Query Server" },
103     { 0x00000001, "Read App Secrets" },
104     { 0x00000002, "Write App Secrets" },
105     { 0x00000003, "Add Secret ID" },
106     { 0x00000004, "Remove Secret ID" },
107     { 0x00000005, "Remove SecretStore" },
108     { 0x00000006, "Enumerate Secret IDs" },
109     { 0x00000007, "Unlock Store" },
110     { 0x00000008, "Set Master Password" },
111     { 0x00000009, "Get Service Information" },
112     { 0x000000ff, "Fragment"},
113     { 0,          NULL }
114 };
115
116 static const value_string sss_errors_enum[] = {
117     { 0xFFFFFCE0, "(-800) Target object could not be found" },
118     { 0xFFFFFCDF, "(-801) NICI operations have failed" },
119     { 0xFFFFFCDE, "(-802) The Secret ID is not in the user secret store" },
120     { 0xFFFFFCDD, "(-803) Some internal operating system services have not been available" },
121     { 0xFFFFFCDC, "(-804) Access to the target Secret Store has been denied" },
122     { 0xFFFFFCDB, "(-805) NDS internal NDS services have not been available" },
123     { 0xFFFFFCDA, "(-806) Secret has not been initialized with a write" },
124     { 0xFFFFFCD9, "(-807) Size of the buffer is not in a nominal range between minimum and maximum" },
125     { 0xFFFFFCD8, "(-808) Client and server components are not of the compatible versions" },
126     { 0xFFFFFCD7, "(-809) Secret Store data on the server has been corrupted" },
127     { 0xFFFFFCD6, "(-810) Secret ID already exists in the SecretStore" },
128     { 0xFFFFFCD5, "(-811) User NDS password has been changed by the administrator" },
129     { 0xFFFFFCD4, "(-812) Target NDS user object not found" },
130     { 0xFFFFFCD3, "(-813) Target NDS user object does not have a Secret Store" },
131     { 0xFFFFFCD2, "(-814) Secret Store is not on the network" },
132     { 0xFFFFFCD1, "(-815) Length of the Secret ID buffer exceeds the limit" },
133     { 0xFFFFFCD0, "(-816) Length of the enumeration buffer is too short" },
134     { 0xFFFFFCCF, "(-817) User not authenticated" },
135     { 0xFFFFFCCE, "(-818) Not supported operations" },
136     { 0xFFFFFCCD, "(-819) Typed in NDS password not valid" },
137     { 0xFFFFFCCC, "(-820) Session keys of the client and server NICI are out of sync" },
138     { 0xFFFFFCCB, "(-821) Requested service not yet supported" },
139     { 0xFFFFFCCA, "(-822) NDS authentication type not supported" },
140     { 0xFFFFFCC9, "(-823) Unicode text conversion operation failed" },
141     { 0xFFFFFCC8, "(-824) Connection to server is lost" },
142     { 0xFFFFFCC7, "(-825) Cryptographic operation failed" },
143     { 0xFFFFFCC6, "(-826) Opening a connection to the server failed" },
144     { 0xFFFFFCC5, "(-827) Access to server connection failed" },
145     { 0xFFFFFCC4, "(-828) Size of the enumeration buffer exceeds the limit" },
146     { 0xFFFFFCC3, "(-829) Size of the Secret buffer exceeds the limit" },
147     { 0xFFFFFCC2, "(-830) Length of the Secret ID should be greater than zero" },
148     { 0xFFFFFCC1, "(-831) Protocol data corrupted on the wire" },
149     { 0xFFFFFCC0, "(-832) Enhanced protection's password validation failed. Access to the secret denied" },
150     { 0xFFFFFCBF, "(-833) Schema is not extended to support SecretStore on the target tree" },
151     { 0xFFFFFCBE, "(-834) One of the optional service attributes is not instantiated" },
152     { 0xFFFFFCBD, "(-835) Server has been upgraded and the users SecretStore should be updated" },
153     { 0xFFFFFCBC, "(-836) Master password could not be verified to read or unlock the secrets" },
154     { 0xFFFFFCBB, "(-837) Master password has not been set on the SecretStore" },
155     { 0xFFFFFCBA, "(-838) Ability to use master password has been disabled" },
156     { 0xFFFFFCB9, "(-839) Not a writeable replica of NDS" },
157     { 0xFFFFFCB8, "(-840) The API was unable to find a value for an attribute in the Directory" },
158     { 0xFFFFFCB7, "(-841) A parameter passed to the API has not been properly initialized" },
159     { 0xFFFFFCB6, "(-842) The connection to SecretStore requires SSL to be secure" },
160     { 0xFFFFFCB5, "(-843) The client could not locate a server that supports the policy override required by the caller" },
161     { 0xFFFFFCB4, "(-844) Attempt to unlock SecretStore failed because the store is not locked" },
162     { 0xFFFFFCB3, "(-845) NDS Replica on the server that holds SecretStore is out of sync with the replica ring" },
163     { 0xFFFFFC88, "(-888) Feature not yet implemented" },
164     { 0xFFFFFC7D, "(-899) Products BETA life has expired" },
165     { 0,          NULL }
166 };
167
168
169 static void
170 process_flags(proto_tree *sss_tree, tvbuff_t *tvb, guint32 foffset)
171 {
172     gchar                   flags_str[1024];
173     const gchar            *sep;
174     proto_item             *tinew;
175     proto_tree             *flags_tree;
176     guint32                 i;
177     guint32                 bvalue = 0;
178     guint32                 flags = 0;
179
180     bvalue = 0x00000001;
181     flags_str[0]='\0';
182     sep="";
183     flags = tvb_get_ntohl(tvb, foffset);
184     for (i = 0 ; i < 256; i++)
185     {
186         if (flags & bvalue)
187         {
188             g_strlcat(flags_str, sep, 1024);
189             switch(bvalue)
190             {
191                 case 0x00000001:
192                         g_strlcat(flags_str, "Enhanced Protection", 1024);
193                         break;
194                 case 0x00000002:
195                         g_strlcat(flags_str, "Create ID", 1024);
196                         break;
197                 case 0x00000004:
198                         g_strlcat(flags_str, "Remove Lock", 1024);
199                         break;
200                 case 0x00000008:
201                         g_strlcat(flags_str, "Repair", 1024);
202                         break;
203                 case 0x00000010:
204                         g_strlcat(flags_str, "Unicode", 1024);
205                         break;
206                 case 0x00000020:
207                         g_strlcat(flags_str, "EP Master Password Used", 1024);
208                         break;
209                 case 0x00000040:
210                         g_strlcat(flags_str, "EP Password Used", 1024);
211                         break;
212                 case 0x00000080:
213                         g_strlcat(flags_str, "Set Tree Name", 1024);
214                         break;
215                 case 0x00000100:
216                         g_strlcat(flags_str, "Get Context", 1024);
217                         break;
218                 case 0x00000200:
219                         g_strlcat(flags_str, "Destroy Context", 1024);
220                         break;
221                 case 0x00000400:
222                         g_strlcat(flags_str, "Not Defined", 1024);
223                         break;
224                 case 0x00000800:
225                         g_strlcat(flags_str, "Not Defined", 1024);
226                         break;
227                 case 0x00001000:
228                         g_strlcat(flags_str, "EP Lock", 1024);
229                         break;
230                 case 0x00002000:
231                         g_strlcat(flags_str, "Not Initialized", 1024);
232                         break;
233                 case 0x00004000:
234                         g_strlcat(flags_str, "Enhanced Protection", 1024);
235                         break;
236                 case 0x00008000:
237                         g_strlcat(flags_str, "Store Not Synced", 1024);
238                         break;
239                 case 0x00010000:
240                         g_strlcat(flags_str, "Admin Last Modified", 1024);
241                         break;
242                 case 0x00020000:
243                         g_strlcat(flags_str, "EP Password Present", 1024);
244                         break;
245                 case 0x00040000:
246                         g_strlcat(flags_str, "EP Master Password Present", 1024);
247                         break;
248                 case 0x00080000:
249                         g_strlcat(flags_str, "MP Disabled", 1024);
250                         break;
251                 case 0x00100000:
252                         g_strlcat(flags_str, "Not Defined", 1024);
253                         break;
254                 case 0x00200000:
255                         g_strlcat(flags_str, "Not Defined", 1024);
256                         break;
257                 case 0x00400000:
258                         g_strlcat(flags_str, "Not Defined", 1024);
259                         break;
260                 case 0x00800000:
261                         g_strlcat(flags_str, "Not Defined", 1024);
262                         break;
263                 case 0x01000000:
264                         g_strlcat(flags_str, "Not Defined", 1024);
265                         break;
266                 case 0x02000000:
267                         g_strlcat(flags_str, "Not Defined", 1024);
268                         break;
269                 case 0x04000000:
270                         g_strlcat(flags_str, "Not Defined", 1024);
271                         break;
272                 case 0x08000000:
273                         g_strlcat(flags_str, "Not Defined", 1024);
274                         break;
275                 case 0x10000000:
276                         g_strlcat(flags_str, "Not Defined", 1024);
277                         break;
278                 case 0x20000000:
279                         g_strlcat(flags_str, "Not Defined", 1024);
280                         break;
281                 case 0x40000000:
282                         g_strlcat(flags_str, "Not Defined", 1024);
283                         break;
284                 case 0x80000000:
285                         g_strlcat(flags_str, "Not Defined", 1024);
286                         break;
287                 default:
288                         break;
289             }
290             sep = ", ";
291         }
292             bvalue = bvalue*2;
293     }
294
295     tinew = proto_tree_add_uint_format(sss_tree, hf_flags, tvb, foffset, 4, flags, "%s 0x%08x", "Flags:", flags);
296     flags_tree = proto_item_add_subtree(tinew, ett_nds);
297
298     bvalue = 0x00000001;
299
300     for (i = 0 ; i < 256; i++ )
301     {
302         if (flags & bvalue)
303         {
304             switch(bvalue)
305             {
306                 case 0x00000001:
307                         proto_tree_add_item(flags_tree, hfbit1, tvb, foffset, 4, FALSE);
308                         break;
309                 case 0x00000002:
310                     proto_tree_add_item(flags_tree, hfbit2, tvb, foffset, 4, FALSE);
311                         break;
312                 case 0x00000004:
313                     proto_tree_add_item(flags_tree, hfbit3, tvb, foffset, 4, FALSE);
314                         break;
315                 case 0x00000008:
316                         proto_tree_add_item(flags_tree, hfbit4, tvb, foffset, 4, FALSE);
317                         break;
318                 case 0x00000010:
319                         proto_tree_add_item(flags_tree, hfbit5, tvb, foffset, 4, FALSE);
320                         break;
321                 case 0x00000020:
322                         proto_tree_add_item(flags_tree, hfbit6, tvb, foffset, 4, FALSE);
323                         break;
324                 case 0x00000040:
325                         proto_tree_add_item(flags_tree, hfbit7, tvb, foffset, 4, FALSE);
326                         break;
327                 case 0x00000080:
328                         proto_tree_add_item(flags_tree, hfbit8, tvb, foffset, 4, FALSE);
329                         break;
330                 case 0x00000100:
331                         proto_tree_add_item(flags_tree, hfbit9, tvb, foffset, 4, FALSE);
332                         break;
333                 case 0x00000200:
334                         proto_tree_add_item(flags_tree, hfbit10, tvb, foffset, 4, FALSE);
335                         break;
336                 case 0x00000400:
337                         proto_tree_add_item(flags_tree, hfbit11, tvb, foffset, 4, FALSE);
338                         break;
339                 case 0x00000800:
340                         proto_tree_add_item(flags_tree, hfbit12, tvb, foffset, 4, FALSE);
341                         break;
342                 case 0x00001000:
343                         proto_tree_add_item(flags_tree, hfbit13, tvb, foffset, 4, FALSE);
344                         break;
345                 case 0x00002000:
346                         proto_tree_add_item(flags_tree, hfbit14, tvb, foffset, 4, FALSE);
347                         break;
348                 case 0x00004000:
349                         proto_tree_add_item(flags_tree, hfbit15, tvb, foffset, 4, FALSE);
350                         break;
351                 case 0x00008000:
352                         proto_tree_add_item(flags_tree, hfbit16, tvb, foffset, 4, FALSE);
353                         break;
354                 case 0x00010000:
355                         proto_tree_add_item(flags_tree, hfbit17, tvb, foffset, 4, FALSE);
356                         break;
357                 case 0x00020000:
358                         proto_tree_add_item(flags_tree, hfbit18, tvb, foffset, 4, FALSE);
359                         break;
360                 case 0x00040000:
361                         proto_tree_add_item(flags_tree, hfbit19, tvb, foffset, 4, FALSE);
362                         break;
363                 case 0x00080000:
364                         proto_tree_add_item(flags_tree, hfbit20, tvb, foffset, 4, FALSE);
365                         break;
366                 case 0x00100000:
367                         proto_tree_add_item(flags_tree, hfbit21, tvb, foffset, 4, FALSE);
368                         break;
369                 case 0x00200000:
370                         proto_tree_add_item(flags_tree, hfbit22, tvb, foffset, 4, FALSE);
371                         break;
372                 case 0x00400000:
373                         proto_tree_add_item(flags_tree, hfbit23, tvb, foffset, 4, FALSE);
374                         break;
375                 case 0x00800000:
376                         proto_tree_add_item(flags_tree, hfbit24, tvb, foffset, 4, FALSE);
377                         break;
378                 case 0x01000000:
379                         proto_tree_add_item(flags_tree, hfbit25, tvb, foffset, 4, FALSE);
380                         break;
381                 case 0x02000000:
382                         proto_tree_add_item(flags_tree, hfbit26, tvb, foffset, 4, FALSE);
383                         break;
384                 case 0x04000000:
385                         proto_tree_add_item(flags_tree, hfbit27, tvb, foffset, 4, FALSE);
386                         break;
387                 case 0x08000000:
388                         proto_tree_add_item(flags_tree, hfbit28, tvb, foffset, 4, FALSE);
389                         break;
390                 case 0x10000000:
391                         proto_tree_add_item(flags_tree, hfbit29, tvb, foffset, 4, FALSE);
392                         break;
393                 case 0x20000000:
394                         proto_tree_add_item(flags_tree, hfbit30, tvb, foffset, 4, FALSE);
395                         break;
396                 case 0x40000000:
397                         proto_tree_add_item(flags_tree, hfbit31, tvb, foffset, 4, FALSE);
398                         break;
399                 case 0x80000000:
400                         proto_tree_add_item(flags_tree, hfbit32, tvb, foffset, 4, FALSE);
401                         break;
402                 default:
403                         break;
404             }
405         }
406         bvalue = bvalue*2;
407     }
408     return;
409 }
410
411 static int
412 find_delimiter(tvbuff_t *tvb, int foffset)
413 {
414     int i;
415     int length = 0;
416     guint16 c_char;
417
418     for (i=0; i < 256; i++)
419     {
420         c_char = tvb_get_guint8(tvb, foffset);
421         if (c_char == 0x2a || tvb_length_remaining(tvb, foffset)==0)
422         {
423             break;
424         }
425         foffset++;
426         length++;
427     }
428     return length;
429 }
430
431 static int
432 sss_string(tvbuff_t* tvb, int hfinfo, proto_tree *sss_tree, int offset, gboolean little, guint32 length)
433 {
434         int     foffset = offset;
435         guint32 str_length;
436         char    buffer[1024];
437         guint32 i;
438         guint16 c_char;
439         guint32 length_remaining = 0;
440
441         if (length==0)
442         {
443             if (little) {
444                 str_length = tvb_get_letohl(tvb, foffset);
445             }
446             else
447             {
448                 str_length = tvb_get_ntohl(tvb, foffset);
449             }
450             foffset += 4;
451         }
452         else
453         {
454             str_length = length;
455         }
456         length_remaining = tvb_length_remaining(tvb, foffset);
457         if(str_length > (guint)length_remaining || str_length > 1024)
458         {
459                 proto_tree_add_string(sss_tree, hfinfo, tvb, foffset,
460                     length_remaining + 4, "<String too long to process>");
461                 foffset += length_remaining;
462                 return foffset;
463         }
464         if(str_length == 0)
465         {
466             proto_tree_add_string(sss_tree, hfinfo, tvb, offset,
467                 4, "<Not Specified>");
468             return foffset;
469         }
470         for ( i = 0; i < str_length; i++ )
471         {
472                 c_char = tvb_get_guint8(tvb, foffset );
473                 if (c_char<0x20 || c_char>0x7e)
474                 {
475                         if (c_char != 0x00)
476                         {
477                                 c_char = 0x2e;
478                                 buffer[i] = c_char & 0xff;
479                         }
480                         else
481                         {
482                                 i--;
483                                 str_length--;
484                         }
485                 }
486                 else
487                 {
488                         buffer[i] = c_char & 0xff;
489                 }
490                 foffset++;
491                 length_remaining--;
492
493                 if(length_remaining==1)
494                 {
495                         i++;
496                         break;
497                 }
498         }
499         buffer[i] = '\0';
500
501         if (length==0)
502         {
503             if (little) {
504                 str_length = tvb_get_letohl(tvb, offset);
505             }
506             else
507             {
508                 str_length = tvb_get_ntohl(tvb, offset);
509             }
510             offset += 4;
511         }
512         else
513         {
514             str_length = length;
515         }
516         proto_tree_add_string(sss_tree, hfinfo, tvb, offset,
517                 str_length, buffer);
518         return foffset;
519 }
520
521 void
522 dissect_sss_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, ncp_req_hash_value *request_value)
523 {
524     guint8              /*func,*/ subfunc = 0;
525     guint32             subverb=0;
526     guint32             msg_length=0;
527     guint32             foffset= 0;
528     proto_tree          *atree;
529     proto_item          *aitem;
530
531
532     if (tvb_length_remaining(tvb, foffset)<4) {
533         return;
534     }
535     foffset = 6;
536     /*func = tvb_get_guint8(tvb, foffset);*/
537     foffset += 1;
538     subfunc = tvb_get_guint8(tvb, foffset);
539     foffset += 1;
540
541     /* Fill in the PROTOCOL & INFO  columns. */
542     col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSSS");
543     if (check_col(pinfo->cinfo, COL_INFO)) {
544        col_add_fstr(pinfo->cinfo, COL_INFO, "C SecretStore - %s", val_to_str(subfunc, sss_func_enum, "Unknown (%d)"));
545     }
546     switch (subfunc) {
547     case 1:
548         aitem = proto_tree_add_text(ncp_tree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Packet Type: %s", val_to_str(subfunc, sss_func_enum, "Unknown (%d)"));
549         atree = proto_item_add_subtree(aitem, ett_sss);
550         proto_tree_add_item(atree, hf_ping_version, tvb, foffset, 4, TRUE);
551         foffset += 4;
552         proto_tree_add_item(atree, hf_flags, tvb, foffset, 4, TRUE);
553         foffset += 4;
554         break;
555     case 2:
556         proto_tree_add_item(ncp_tree, hf_frag_handle, tvb, foffset, 4, TRUE);
557         if (tvb_get_letohl(tvb, foffset)==0xffffffff) /* Fragment handle of -1 means no fragment. So process packet */
558         {
559             foffset += 4;
560             proto_tree_add_item(ncp_tree, hf_buffer_size, tvb, foffset, 4, TRUE);
561             foffset += 4;
562             proto_tree_add_item(ncp_tree, hf_length, tvb, foffset, 4, TRUE);
563             foffset += 4;
564             foffset += 12; /* Blank Context */
565             subverb = tvb_get_letohl(tvb, foffset);
566             if (check_col(pinfo->cinfo, COL_INFO)) {
567                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str(subverb, sss_verb_enum, "Unknown (%d)"));
568             }
569             aitem = proto_tree_add_item(ncp_tree, hf_verb, tvb, foffset, 4, TRUE);
570             atree = proto_item_add_subtree(aitem, ett_sss);
571             if (request_value) {
572                 request_value->req_nds_flags=subverb;
573             }
574             foffset += 4;
575             process_flags(atree, tvb, foffset);
576             foffset += 4;
577             proto_tree_add_item(atree, hf_context, tvb, foffset, 4, FALSE);
578             foffset += 4;
579             switch (subverb) {
580             case 0:
581                 foffset += 4;
582                 foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
583                 break;
584             case 1:
585                 foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
586                 msg_length = tvb_get_letohl(tvb, foffset);
587                 foffset += (msg_length+4);   /* Unsure of what this length and parameter are */
588                 /* A bad secret of length greater then 256 characters will cause frag
589                    packets and then we will see these as malformed packets.
590                    So check to make sure we still have data in the packet anytime
591                    we read a secret. */
592                 if (tvb_length_remaining(tvb, foffset) > 4)
593                 {
594                     foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
595                 }
596                 break;
597             case 2:
598                 foffset += 4;
599                 foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
600                 if (tvb_length_remaining(tvb, foffset) > 4)
601                 {
602                     msg_length = tvb_get_letohl(tvb, foffset);
603                     foffset += 4;
604                     if (tvb_length_remaining(tvb, foffset) < (gint) msg_length)
605                     {
606                         proto_tree_add_item(atree, hf_enc_data, tvb, foffset, -1, TRUE);
607                     }
608                     else
609                     {
610                         proto_tree_add_item(atree, hf_enc_data, tvb, foffset, msg_length, TRUE);
611                     }
612                 }
613                 break;
614             case 3:
615             case 4:
616                 foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
617                 if (tvb_length_remaining(tvb, foffset) > 4)
618                 {
619                     foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
620                 }
621                 break;
622             case 5:
623                 break;
624             case 6:
625                 foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
626                 if (tvb_length_remaining(tvb, foffset) > 4)
627                 {
628                     foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
629                 }
630                 break;
631             case 7:
632                 msg_length = tvb_get_letohl(tvb, foffset);
633                 foffset += 4;
634                 proto_tree_add_item(atree, hf_enc_cred, tvb, foffset, msg_length, FALSE);
635                 break;
636             case 8:
637             case 9:
638             default:
639                 break;
640             }
641
642         }
643         else
644         {
645             if (check_col(pinfo->cinfo, COL_INFO)) {
646                col_set_str(pinfo->cinfo, COL_INFO, "C SecretStore - fragment");
647                proto_tree_add_text(ncp_tree, tvb, foffset, 4, "Fragment");
648             }
649             /* Fragments don't really carry a subverb so store 0xff as the subverb number */
650             if (request_value) {
651                 request_value->req_nds_flags=255;
652             }
653             if (tvb_length_remaining(tvb, foffset) > 8)
654             {
655                 foffset += 4;
656                 proto_tree_add_item(ncp_tree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), TRUE);
657             }
658         }
659         break;
660     case 3:
661         /* No Op */
662         break;
663     default:
664         break;
665     }
666 }
667
668 void
669 dissect_sss_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, guint8 subfunc, ncp_req_hash_value *request_value)
670 {
671     guint32             foffset=0;
672     guint32             subverb=0;
673     guint32             msg_length=0;
674     guint32             return_code=0;
675     guint32             number_of_items=0;
676     gint32              length_of_string=0;
677     guint32             i = 0;
678     const gchar         *str;
679
680     proto_tree          *atree;
681     proto_item          *aitem;
682     proto_item          *expert_item;
683
684
685     foffset = 8;
686     col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSSS");
687     if (tvb_length_remaining(tvb, foffset)<4) {
688         return;
689     }
690     aitem = proto_tree_add_text(ncp_tree, tvb, foffset, -1, "Function: %s", val_to_str(subfunc, sss_func_enum, "val_to_str"));
691     atree = proto_item_add_subtree(aitem, ett_sss);
692     switch (subfunc) {
693     case 1:
694         proto_tree_add_item(atree, hf_flags, tvb, foffset, 4, TRUE);
695         foffset += 4;
696         proto_tree_add_item(atree, hf_sss_version, tvb, foffset, 4, TRUE);
697         foffset += 4;
698         break;
699     case 2:
700         if (request_value) {
701             subverb = request_value->req_nds_flags;
702             str = match_strval(subverb, sss_verb_enum);
703             if (str) {
704                 proto_tree_add_text(atree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Verb: %s", str);
705             }
706         }
707         proto_tree_add_item(atree, hf_length, tvb, foffset, 4, TRUE);
708         msg_length = tvb_get_letohl(tvb, foffset);
709         return_code = tvb_get_ntohl(tvb, foffset+msg_length);
710         foffset += 4;
711         proto_tree_add_item(atree, hf_frag_handle, tvb, foffset, 4, TRUE);
712         foffset += 4;
713         msg_length -= 4;
714         if ((tvb_get_letohl(tvb, foffset-4)==0xffffffff) && (msg_length > 4))
715         {
716             foffset += 4;
717             return_code = tvb_get_letohl(tvb, foffset);
718             str = match_strval(return_code, sss_errors_enum);
719             if (str)
720             {
721                 expert_item = proto_tree_add_item(atree, hf_return_code, tvb, foffset, 4, TRUE);
722                 expert_add_info_format(pinfo, expert_item, PI_RESPONSE_CODE, PI_ERROR, "SSS Error: %s", str);
723                 if (check_col(pinfo->cinfo, COL_INFO)) {
724                    col_add_fstr(pinfo->cinfo, COL_INFO, "R Error - %s", val_to_str(return_code, sss_errors_enum, "Unknown (%d)"));
725                 }
726                 foffset+=4;
727             }
728             else
729             {
730                 proto_tree_add_text(atree, tvb, foffset, 4, "Return Code: Success (0x00000000)");
731                 if (tvb_length_remaining(tvb, foffset) > 8) {
732                     foffset += 4;
733                     if (request_value && subverb == 6)
734                     {
735                         foffset += 4;
736                         number_of_items = tvb_get_letohl(tvb, foffset);
737                         foffset += 8;
738                         for (i=0; i<number_of_items; i++)
739                         {
740                             length_of_string = find_delimiter(tvb, foffset);
741                             if (length_of_string > tvb_length_remaining(tvb, foffset))
742                             {
743                                 return;
744                             }
745                             foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, length_of_string);
746                             if (tvb_length_remaining(tvb, foffset) < 8)
747                             {
748                                 return;
749                             }
750                             foffset++;
751                         }
752
753                     }
754                     else
755                     {
756                         proto_tree_add_item(atree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), TRUE);
757                     }
758                 }
759             }
760         }
761         else
762         {
763             proto_tree_add_text(atree, tvb, foffset, 4, "Return Code: Success (0x00000000)");
764             if (tvb_length_remaining(tvb, foffset) > 8) {
765                 foffset += 4;
766                 proto_tree_add_item(atree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), TRUE);
767             }
768         }
769         break;
770     case 3:
771         break;
772     default:
773         break;
774     }
775 }
776
777 void
778 proto_register_sss(void)
779 {
780     static hf_register_info hf_sss[] = {
781         { &hf_buffer_size,
782         { "Buffer Size", "sss.buffer", FT_UINT32, BASE_DEC, NULL, 0x0,
783           NULL, HFILL }},
784
785         { &hf_ping_version,
786         { "Ping Version", "sss.ping_version", FT_UINT32, BASE_HEX, NULL, 0x0,
787           NULL, HFILL }},
788
789         { &hf_flags,
790         { "Flags", "sss.flags", FT_UINT32, BASE_HEX, NULL, 0x0,
791           NULL, HFILL }},
792
793         { &hf_context,
794         { "Context", "sss.context", FT_UINT32, BASE_HEX, NULL, 0x0,
795           NULL, HFILL }},
796
797         { &hf_frag_handle,
798         { "Fragment Handle", "sss.frag_handle", FT_UINT32, BASE_HEX, NULL, 0x0,
799           NULL, HFILL }},
800
801         { &hf_length,
802         { "Length", "sss.length", FT_UINT32, BASE_DEC, NULL, 0x0,
803           NULL, HFILL }},
804
805         { &hf_verb,
806         { "Verb",    "sss.verb",
807           FT_UINT32,    BASE_HEX,   VALS(sss_verb_enum),   0x0,
808           NULL, HFILL }},
809
810         { &hf_user,
811         { "User",    "sss.user",
812           FT_STRING,    BASE_NONE,   NULL,   0x0,
813           NULL, HFILL }},
814
815         { &hf_secret,
816         { "Secret ID",    "sss.secret",
817           FT_STRING,    BASE_NONE,   NULL,   0x0,
818           NULL, HFILL }},
819
820         { &hf_sss_version,
821         { "SecretStore Protocol Version", "sss.version", FT_UINT32, BASE_HEX, NULL, 0x0,
822           NULL, HFILL }},
823
824         { &hf_return_code,
825         { "Return Code", "sss.return_code", FT_UINT32, BASE_HEX, VALS(sss_errors_enum), 0x0,
826           NULL, HFILL }},
827
828         { &hf_enc_cred,
829         { "Encrypted Credential",    "sss.enc_cred",
830           FT_BYTES,    BASE_NONE,   NULL,   0x0,
831           NULL, HFILL }},
832
833         { &hf_enc_data,
834         { "Encrypted Data",    "sss.enc_data",
835           FT_BYTES,    BASE_NONE,   NULL,   0x0,
836           NULL, HFILL }},
837
838         { &hfbit1,
839         { "Enhanced Protection", "ncp.sss_bit1", FT_BOOLEAN, 32, NULL, 0x00000001, NULL, HFILL }},
840
841         { &hfbit2,
842         { "Create ID", "ncp.sss_bit2", FT_BOOLEAN, 32, NULL, 0x00000002, NULL, HFILL }},
843
844         { &hfbit3,
845         { "Remove Lock", "ncp.sss_bit3", FT_BOOLEAN, 32, NULL, 0x00000004, NULL, HFILL }},
846
847         { &hfbit4,
848         { "Repair", "ncp.sss_bit4", FT_BOOLEAN, 32, NULL, 0x00000008, NULL, HFILL }},
849
850         { &hfbit5,
851         { "Unicode", "ncp.sss_bit5", FT_BOOLEAN, 32, NULL, 0x00000010, NULL, HFILL }},
852
853         { &hfbit6,
854         { "EP Master Password Used", "ncp.sss_bit6", FT_BOOLEAN, 32, NULL, 0x00000020, NULL, HFILL }},
855
856         { &hfbit7,
857         { "EP Password Used", "ncp.sss_bit7", FT_BOOLEAN, 32, NULL, 0x00000040, NULL, HFILL }},
858
859         { &hfbit8,
860         { "Set Tree Name", "ncp.sss_bit8", FT_BOOLEAN, 32, NULL, 0x00000080, NULL, HFILL }},
861
862         { &hfbit9,
863         { "Get Context", "ncp.sss_bit9", FT_BOOLEAN, 32, NULL, 0x00000100, NULL, HFILL }},
864
865         { &hfbit10,
866         { "Destroy Context", "ncp.sss_bit10", FT_BOOLEAN, 32, NULL, 0x00000200, NULL, HFILL }},
867
868         { &hfbit11,
869         { "Not Defined", "ncp.sss_bit11", FT_BOOLEAN, 32, NULL, 0x00000400, NULL, HFILL }},
870
871         { &hfbit12,
872         { "Not Defined", "ncp.sss_bit12", FT_BOOLEAN, 32, NULL, 0x00000800, NULL, HFILL }},
873
874         { &hfbit13,
875         { "Not Defined", "ncp.sss_bit13", FT_BOOLEAN, 32, NULL, 0x00001000, NULL, HFILL }},
876
877         { &hfbit14,
878         { "Not Defined", "ncp.sss_bit14", FT_BOOLEAN, 32, NULL, 0x00002000, NULL, HFILL }},
879
880         { &hfbit15,
881         { "Not Defined", "ncp.sss_bit15", FT_BOOLEAN, 32, NULL, 0x00004000, NULL, HFILL }},
882
883         { &hfbit16,
884         { "Not Defined", "ncp.sss_bit16", FT_BOOLEAN, 32, NULL, 0x00008000, NULL, HFILL }},
885
886         { &hfbit17,
887         { "EP Lock", "ncp.sss_bit17", FT_BOOLEAN, 32, NULL, 0x00010000, NULL, HFILL }},
888
889         { &hfbit18,
890         { "Not Initialized", "ncp.sss_bit18", FT_BOOLEAN, 32, NULL, 0x00020000, NULL, HFILL }},
891
892         { &hfbit19,
893         { "Enhanced Protection", "ncp.sss_bit19", FT_BOOLEAN, 32, NULL, 0x00040000, NULL, HFILL }},
894
895         { &hfbit20,
896         { "Store Not Synced", "ncp.sss_bit20", FT_BOOLEAN, 32, NULL, 0x00080000, NULL, HFILL }},
897
898         { &hfbit21,
899         { "Admin Last Modified", "ncp.sss_bit21", FT_BOOLEAN, 32, NULL, 0x00100000, NULL, HFILL }},
900
901         { &hfbit22,
902         { "EP Password Present", "ncp.sss_bit22", FT_BOOLEAN, 32, NULL, 0x00200000, NULL, HFILL }},
903
904         { &hfbit23,
905         { "EP Master Password Present", "ncp.sss_bit23", FT_BOOLEAN, 32, NULL, 0x00400000, NULL, HFILL }},
906
907         { &hfbit24,
908         { "MP Disabled", "ncp.sss_bit24", FT_BOOLEAN, 32, NULL, 0x00800000, NULL, HFILL }},
909
910         { &hfbit25,
911         { "Not Defined", "ncp.sss_bit25", FT_BOOLEAN, 32, NULL, 0x01000000, NULL, HFILL }},
912
913         { &hfbit26,
914         { "Not Defined", "ncp.sss_bit26", FT_BOOLEAN, 32, NULL, 0x02000000, NULL, HFILL }},
915
916         { &hfbit27,
917         { "Not Defined", "ncp.sss_bit27", FT_BOOLEAN, 32, NULL, 0x04000000, NULL, HFILL }},
918
919         { &hfbit28,
920         { "Not Defined", "ncp.sss_bit28", FT_BOOLEAN, 32, NULL, 0x08000000, NULL, HFILL }},
921
922         { &hfbit29,
923         { "Not Defined", "ncp.sss_bit29", FT_BOOLEAN, 32, NULL, 0x10000000, NULL, HFILL }},
924
925         { &hfbit30,
926         { "Not Defined", "ncp.sss_bit30", FT_BOOLEAN, 32, NULL, 0x20000000, NULL, HFILL }},
927
928         { &hfbit31,
929         { "Not Defined", "ncp.sss_bit31", FT_BOOLEAN, 32, NULL, 0x40000000, NULL, HFILL }},
930
931         { &hfbit32,
932         { "Not Defined", "ncp.sss_bit32", FT_BOOLEAN, 32, NULL, 0x80000000, NULL, HFILL }},
933
934     };
935
936         static gint *ett[] = {
937             &ett_sss,
938         };
939         /*module_t *sss_module;*/
940
941         proto_sss = proto_register_protocol("Novell SecretStore Services", "SSS", "sss");
942         proto_register_field_array(proto_sss, hf_sss, array_length(hf_sss));
943         proto_register_subtree_array(ett, array_length(ett));
944 }