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