1 /* packet-ncp-nmas.c
2  * Routines for Novell Modular Authentication Service
3  * Greg Morris <gmorris@novell.com>
4  * Copyright (c) Novell, Inc. 2002-2004
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-nmas.h"
18 
19 void proto_register_nmas(void);
20 
21 static gint ett_nmas = -1;
22 
23 static int proto_nmas = -1;
24 /* static int hf_func = -1; */
25 /* static int hf_subfunc = -1; */
26 static int hf_ping_version = -1;
27 static int hf_ping_flags = -1;
28 static int hf_frag_handle = -1;
29 static int hf_length = -1;
30 static int hf_subverb = -1;
31 static int hf_tree = -1;
32 static int hf_user = -1;
33 static int hf_nmas_version = -1;
34 static int hf_msg_version = -1;
35 static int hf_session_ident = -1;
36 static int hf_verb = -1;
37 static int hf_msg_verb = -1;
38 /* static int hf_attribute = -1; */
39 static int hf_clearance = -1;
40 static int hf_login_sequence = -1;
41 static int hf_opaque = -1;
42 static int hf_data = -1;
43 static int hf_return_code = -1;
44 static int hf_lsm_verb = -1;
45 static int hf_squeue_bytes = -1;
46 static int hf_cqueue_bytes = -1;
47 static int hf_num_creds = -1;
48 static int hf_cred_type = -1;
49 static int hf_login_state = -1;
50 static int hf_enc_cred = -1;
51 static int hf_enc_data = -1;
52 static int hf_reply_buffer_size = -1;
53 static int hf_encrypt_error = -1;
54 
55 static expert_field ei_encrypt_error = EI_INIT;
56 static expert_field ei_return_error = EI_INIT;
57 
58 static const value_string nmas_func_enum[] = {
59     { 0x01, "Ping" },
60     { 0x02, "Fragment" },
61     { 0x03, "Abort" },
62     { 0,    NULL }
63 };
64 
65 static const value_string nmas_msgverb_enum[] = {
66     { 1, "Echo Data" },
67     { 3, "Start Session" },
68     { 5, "Client Write Data" },
69     { 7, "Client Read Data" },
70     { 9, "End Session" },
71     { 0,          NULL }
72 };
73 
74 #if 0
75 static const value_string nmas_attribute_enum[] = {
76     { 1, "User Name" },
77     { 2, "Tree Name" },
78     { 4, "Clearance" },
79     { 11, "Login Sequence" },
80     { 0,          NULL }
81 };
82 #endif
83 
84 static const value_string nmas_lsmverb_enum[] = {
85     { 1, "Put Login Configuration" },
86     { 2, "Get Login Configuration" },
87     { 3, "Get All Configurations" },
88     { 4, "Delete Login Configuration" },
89     { 5, "Put Login Secret" },
90     { 6, "Delete Login Secret" },
91     { 7, "Set Password" },
92     { 8, "Change Password" },
93     { 9, "Delete Password" },
94     { 10, "Get Password" },
95     { 11, "Check Password Policy" },
96     { 0,          NULL }
97 };
98 
99 static const value_string nmas_errors_enum[] = {
100     { 0xFFFFF9A1, "(-1631) FRAGMENT FAILURE" },
101     { 0xFFFFF9A0, "(-1632) BAD REQUEST SYNTAX" },
102     { 0xFFFFF99F, "(-1633) BUFFER OVERFLOW" },
103     { 0xFFFFF99E, "(-1634) SYSTEM RESOURCES" },
104     { 0xFFFFF99D, "(-1635) INSUFFICIENT MEMORY" },
105     { 0xFFFFF99C, "(-1636) NOT SUPPORTED" },
106     { 0xFFFFF99B, "(-1637) BUFFER UNDERFLOW" },
107     { 0xFFFFF99A, "(-1638) NOT FOUND" },
108     { 0xFFFFF999, "(-1639) INVALID OPERATION" },
109     { 0xFFFFF998, "(-1640) ASN1 DECODE" },
110     { 0xFFFFF997, "(-1641) ASN1 ENCODE" },
111     { 0xFFFFF996, "(-1642) LOGIN FAILED" },
112     { 0xFFFFF995, "(-1643) INVALID PARAMETER" },
113     { 0xFFFFF994, "(-1644) TIMED OUT RECOVERABLE" },
114     { 0xFFFFF993, "(-1645) TIMED OUT NOT RECOVERABLE" },
115     { 0xFFFFF992, "(-1646) TIMED OUT UNKNOWN" },
116     { 0xFFFFF991, "(-1647) AUTHORIZATION FAILURE" },
117     { 0xFFFFF990, "(-1648) INVALID DISTINGUISHED NAME" },
118     { 0xFFFFF98F, "(-1649) CANNOT RESOLVE DISTINGUISHED NAME" },
119     { 0xFFFFF98E, "(-1650) CANNOT RESOLVE CONNECTION" },
120     { 0xFFFFF98D, "(-1651) NO CRYPTOGRAPHY" },
121     { 0xFFFFF98C, "(-1652) INVALID VERSION" },
122     { 0xFFFFF98B, "(-1653) SYNC NEEDED" },
123     { 0xFFFFF98A, "(-1654) PROTOCOL STATE" },
124     { 0xFFFFF989, "(-1655) INVALID HANDLE" },
125     { 0xFFFFF988, "(-1656) INVALID METHOD" },
126     { 0xFFFFF987, "(-1657) DEVELOPMENT VERSION" },
127     { 0xFFFFF986, "(-1658) MISSING KEY" },
128     { 0xFFFFF985, "(-1659) ACCESS NOT ALLOWED" },
129     { 0xFFFFF984, "(-1660) SEQUENCE NOT FOUND" },
130     { 0xFFFFF983, "(-1661) CLEARANCE NOT FOUND" },
131     { 0xFFFFF982, "(-1662) LOGIN SERVER METHOD NOT FOUND" },
132     { 0xFFFFF981, "(-1663) LOGIN CLIENT METHOD NOT FOUND" },
133     { 0xFFFFF980, "(-1664) SERVER NOT FOUND" },
134     { 0xFFFFF97F, "(-1665) LOGIN ATTRIBUTE NOT FOUND" },
135     { 0xFFFFF97E, "(-1666) LEGACY INVALID PASSWORD" },
136     { 0xFFFFF97D, "(-1667) ACCOUNT DISABLED" },
137     { 0xFFFFF97C, "(-1668) ACCOUNT LOCKED" },
138     { 0xFFFFF97B, "(-1669) ADDRESS RESTRICTION" },
139     { 0xFFFFF97A, "(-1670) CONNECTION CLEARED" },
140     { 0xFFFFF979, "(-1671) TIME RESTRICTION" },
141     { 0xFFFFF978, "(-1672) SHORT TERM SECRET" },
142     { 0xFFFFF977, "(-1673) NO NMAS ON TREE" },
143     { 0xFFFFF976, "(-1674) NO NMAS ON SERVER" },
144     { 0xFFFFF975, "(-1675) REQUEST CHALLENGED" },
145     { 0xFFFFF974, "(-1676) LOGIN CANCELED" },
146     { 0xFFFFF973, "(-1677) LOCAL CREDENTIAL STORE" },
147     { 0xFFFFF972, "(-1678) REMOTE CREDENTIAL STORE" },
148     { 0xFFFFF971, "(-1679) SMC NICM" },
149     { 0xFFFFF970, "(-1680) SEQUENCE NOT AUTHORIZED" },
150     { 0xFFFFF96F, "(-1681) TRANSPORT" },
151     { 0xFFFFF96E, "(-1682) CRYPTO FAILED INIT" },
152     { 0xFFFFF96D, "(-1683) DOUBLEBYTE FAILED INIT" },
153     { 0xFFFFF96C, "(-1684) CODEPAGE FAILED INIT" },
154     { 0xFFFFF96B, "(-1685) UNICODE FAILED INIT" },
155     { 0xFFFFF96A, "(-1686) DLL FAILED LOADING" },
156     { 0xFFFFF969, "(-1687) EVALUATION VERSION WARNING" },
157     { 0xFFFFF968, "(-1688) CONCURRENT LOGIN" },
158     { 0xFFFFF967, "(-1689) THREAD CREATE" },
159     { 0xFFFFF966, "(-1690) SECURE CHANNEL REQUIRED" },
160     { 0xFFFFF965, "(-1691) NO DEFAULT USER SEQUENCE" },
161     { 0xFFFFF964, "(-1692) NO TREENAME" },
162     { 0xFFFFF963, "(-1693) MECHANISM NOT FOUND" },
163     { 0,          NULL }
164 };
165 
166 #if 0
167 static int
168 align_4(tvbuff_t *tvb, int aoffset)
169 {
170     if (tvb_length_remaining(tvb, aoffset) > 4 ) {
171         return (aoffset%4);
172     }
173     return 0;
174 }
175 #endif
176 
177 static int
nmas_string(packet_info * pinfo,tvbuff_t * tvb,int hfinfo,proto_tree * nmas_tree,int offset,gboolean little)178 nmas_string(packet_info *pinfo, tvbuff_t* tvb, int hfinfo, proto_tree *nmas_tree, int offset, gboolean little)
179 {
180     int     foffset = offset;
181     guint32 str_length;
182     char    *buffer;
183     guint32 i;
184     guint16 c_char;
185     guint32 length_remaining = 0;
186 
187     buffer = (char *)wmem_alloc(pinfo->pool, ITEM_LABEL_LENGTH+1);
188     if (little) {
189         str_length = tvb_get_letohl(tvb, foffset);
190     } else {
191         str_length = tvb_get_ntohl(tvb, foffset);
192     }
193     foffset += 4;
194     if (str_length >= ITEM_LABEL_LENGTH) {
195         proto_tree_add_string(nmas_tree, hfinfo, tvb, foffset,
196             length_remaining + 4, "<String too long to process>");
197         foffset += length_remaining;
198         return foffset;
199     }
200     if (str_length == 0) {
201         proto_tree_add_string(nmas_tree, hfinfo, tvb, offset, 4,
202             "<Not Specified>");
203         return foffset;
204     }
205     /*
206      * XXX - other than the special-casing of null bytes,
207      * we could just use "proto_tree_add_item()", as for
208      * FT_STRING, FT_STRINGZ, and FT_UINT_STRING fields,
209      * the display representation of an item is generated
210      * using "format_text()", so it handles non-printable
211      * characters.
212      */
213     for ( i = 0; i < str_length; i++ ) {
214         c_char = tvb_get_guint8(tvb, foffset );
215         if (c_char<0x20 || c_char>0x7e) {
216             if (c_char != 0x00) {
217                 c_char = 0x2e;
218                 buffer[i] = c_char & 0xff;
219             } else {
220                 i--;
221                 str_length--;
222             }
223         } else {
224             buffer[i] = c_char & 0xff;
225         }
226         foffset++;
227         length_remaining--;
228 
229         if (length_remaining==1) {
230             i++;
231             break;
232         }
233     }
234     buffer[i] = '\0';
235 
236     if (little) {
237         str_length = tvb_get_letohl(tvb, offset);
238     } else {
239         str_length = tvb_get_ntohl(tvb, offset);
240     }
241     proto_tree_add_string(nmas_tree, hfinfo, tvb, offset+4, str_length, buffer);
242     return foffset;
243 }
244 
245 void
dissect_nmas_request(tvbuff_t * tvb,packet_info * pinfo,proto_tree * ncp_tree,ncp_req_hash_value * request_value)246 dissect_nmas_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, ncp_req_hash_value *request_value)
247 {
248     guint8              /*func,*/ subfunc;
249     guint32             msg_length=0, cur_string_len=0;
250     guint32             foffset;
251     guint32             subverb=0;
252     guint32             attribute=0;
253     guint8              msgverb=0;
254     proto_tree          *atree;
255 
256     foffset = 6;
257     /*func = tvb_get_guint8(tvb, foffset);*/
258     foffset += 1;
259     subfunc = tvb_get_guint8(tvb, foffset);
260     foffset += 1;
261 
262     /* Fill in the INFO column. */
263     col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMAS");
264     col_add_fstr(pinfo->cinfo, COL_INFO, "C NMAS - %s",
265         val_to_str(subfunc, nmas_func_enum, "Unknown (0x%02x)"));
266 
267     atree = proto_tree_add_subtree_format(ncp_tree, tvb, foffset, -1, ett_nmas, NULL, "Packet Type: %s",
268         val_to_str(subfunc, nmas_func_enum, "Unknown (0x%02x)"));
269     switch (subfunc) {
270     case 1:
271         proto_tree_add_item(atree, hf_ping_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
272         foffset += 4;
273         proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
274         /*foffset += 4;*/
275         break;
276     case 2:
277         proto_tree_add_item(atree, hf_frag_handle, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
278         /* Check for Fragment packet */
279         if (tvb_get_letohl(tvb, foffset)!=0xffffffff) {
280             break;
281         }
282         foffset += 4;
283         foffset += 4; /* Don't know what this is */
284         proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
285         msg_length = tvb_get_letohl(tvb, foffset);
286         foffset += 4;
287         foffset += 12;
288         msg_length -= 16;
289         proto_tree_add_item(atree, hf_subverb, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
290         subverb = tvb_get_letohl(tvb, foffset);
291         if (request_value) {
292             request_value->req_nds_flags=subverb; /* Store the NMAS fragment verb */
293         }
294         foffset += 4;
295         msg_length -= 4;
296         col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
297             val_to_str(subverb, nmas_subverb_enum, "Unknown subverb (%u)"));
298         switch (subverb) {
299         case 0:             /* Fragmented Ping */
300             proto_tree_add_item(atree, hf_ping_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
301             foffset += 4;
302             proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
303             /*foffset += 4;*/
304             break;
305         case 2:             /* Client Put Data */
306             proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, ENC_NA);
307             /*foffset += msg_length;*/
308             break;
309         case 4:             /* Client Get Data */
310         case 6:             /* Client Get User NDS Credentials */
311             /* No Op */
312             break;
313         case 8:             /* Login Store Management */
314             proto_tree_add_item(atree, hf_reply_buffer_size, tvb, foffset, 1, ENC_LITTLE_ENDIAN);
315             foffset += 4;
316             msgverb = tvb_get_guint8(tvb, foffset);
317             if (request_value) {
318                 request_value->nds_request_verb=msgverb; /* Use nds_request_verb for passed subverb */
319             }
320             proto_tree_add_item(atree, hf_lsm_verb, tvb, foffset, 1, ENC_LITTLE_ENDIAN);
321             /*foffset += 4;*/
322             col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
323                 val_to_str(msgverb, nmas_lsmverb_enum, "Unknown (%u)"));
324 
325             switch (msgverb) {
326             case 1:
327                 break;
328             case 2:
329                 break;
330             case 4:
331                 break;
332             case 5:
333                 break;
334             case 6:
335                 break;
336             default:
337                 break;
338             }
339             break;
340         case 10:            /* Writable Object Check */
341             /* The first GUINT32 value is the len of the header? */
342             foffset += 4;
343             /* The next two GUINT32 values are reserved and always 0 */
344             foffset += 8;
345             foffset = nmas_string(pinfo, tvb, hf_tree, atree, foffset, TRUE);
346             /*foffset = */nmas_string(pinfo, tvb, hf_user, atree, foffset, TRUE);
347             break;
348         case 1242:          /* Message Handler */
349             foffset += 4;
350             proto_tree_add_item(atree, hf_msg_version, tvb, foffset, 4, ENC_BIG_ENDIAN);
351             foffset += 4;
352             proto_tree_add_item(atree, hf_session_ident, tvb, foffset, 4, ENC_BIG_ENDIAN);
353             foffset += 4;
354             foffset += 3;
355             msgverb = tvb_get_guint8(tvb, foffset);
356             if (request_value) {
357                 request_value->nds_request_verb=msgverb; /* Use nds_request_verb for passed verb */
358             }
359             proto_tree_add_item(atree, hf_msg_verb, tvb, foffset, 1, ENC_BIG_ENDIAN);
360             foffset += 1;
361             /*msg_length -= 12;*/
362             col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
363                 val_to_str(msgverb, nmas_msgverb_enum, "Unknown (%u)"));
364 
365             switch(msgverb) {
366             case 1:
367                 msg_length = tvb_get_ntohl(tvb, foffset);
368                 proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_BIG_ENDIAN);
369                 foffset += 4;
370                 proto_tree_add_item(atree, hf_data, tvb, foffset, msg_length, ENC_NA);
371                 /*foffset += msg_length;*/
372                 break;
373             case 3:
374                 msg_length = tvb_get_ntohl(tvb, foffset);
375                 msg_length -= 4;
376                 proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_BIG_ENDIAN);
377                 foffset += 4;
378                 while (msg_length > 0) {
379                     attribute = tvb_get_ntohl(tvb, foffset);
380                     foffset += 4;
381                     cur_string_len=tvb_get_ntohl(tvb, foffset);
382                     switch (attribute) {
383                     case 1:
384                         foffset = nmas_string(pinfo, tvb, hf_user, atree, foffset, FALSE);
385                         break;
386                     case 2:
387                         foffset = nmas_string(pinfo, tvb, hf_tree, atree, foffset, FALSE);
388                         break;
389                     case 4:
390                         foffset = nmas_string(pinfo, tvb, hf_clearance, atree, foffset, FALSE);
391                         break;
392                     case 11:
393                         foffset = nmas_string(pinfo, tvb, hf_login_sequence, atree, foffset, FALSE);
394                         break;
395                     default:
396                         break;
397                     }
398                     msg_length -= cur_string_len;
399                     if (tvb_reported_length_remaining(tvb, foffset)<5) {
400                         break;
401                     }
402                 }
403                 break;
404             case 5:
405                 proto_tree_add_item(atree, hf_opaque, tvb, foffset,
406                     tvb_reported_length_remaining(tvb, foffset), ENC_NA);
407                 /*foffset += msg_length;*/
408                 break;
409             case 7:
410             case 9:
411                 /* No Op */
412                 break;
413             default:
414                 break;
415             }
416             break;
417         default:
418             break;
419         }
420         break;
421     case 3:
422         /* No Op */
423         break;
424     default:
425         break;
426     }
427 }
428 
429 void
dissect_nmas_reply(tvbuff_t * tvb,packet_info * pinfo,proto_tree * ncp_tree,guint8 func _U_,guint8 subfunc,ncp_req_hash_value * request_value)430 dissect_nmas_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, guint8 func _U_, guint8 subfunc, ncp_req_hash_value *request_value)
431 {
432     guint32             foffset=0, roffset=0;
433     guint32             subverb=0;
434     guint8              msgverb=0;
435     guint32             msg_length=0;
436     guint32             return_code=0, encrypt_error=0;
437     proto_tree          *atree;
438     proto_item          *expert_item;
439     const gchar         *str;
440 
441 
442     foffset = 8;
443     if (request_value) {
444         subverb = request_value->req_nds_flags;
445         msgverb = request_value->nds_request_verb;
446     }
447     col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMAS");
448     if (tvb_reported_length_remaining(tvb, foffset)<4) {
449         return;
450     }
451 
452     atree = proto_tree_add_subtree_format(ncp_tree, tvb, foffset, -1, ett_nmas, NULL, "Packet Type: %s",
453         val_to_str(subfunc, nmas_func_enum, "Unknown (0x%02x)"));
454     switch (subfunc) {
455     case 1:
456         proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
457         foffset += 4;
458         proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
459         /*foffset += 4;*/
460         break;
461     case 2:
462         proto_tree_add_uint(atree, hf_verb, tvb, foffset, -1, subverb);
463         proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
464         msg_length = tvb_get_letohl(tvb, foffset);
465         foffset +=4;
466         proto_tree_add_item(atree, hf_frag_handle, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
467         /* Check for a fragment packet */
468         if (tvb_get_letohl(tvb, foffset)!=0xffffffff) {
469             break;
470         }
471         foffset += 4;
472         return_code = tvb_get_letohl(tvb, foffset);
473         roffset = foffset;
474         foffset += 4;
475         msg_length -= 8;
476         if (return_code == 0 && msg_length > 0) {
477             switch (subverb) {
478             case 0:             /* Fragmented Ping */
479                 proto_tree_add_item(atree, hf_session_ident, tvb, foffset, 4, ENC_BIG_ENDIAN);
480                 /*foffset += 4;*/
481                 /*proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
482                 foffset += 4;*/
483                 break;
484             case 2:             /* Client Put Data */
485                 proto_tree_add_item(atree, hf_squeue_bytes, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
486                 foffset += 4;
487                 proto_tree_add_item(atree, hf_cqueue_bytes, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
488                 /*foffset += 4;*/
489                 break;
490             case 4:             /* Client Get Data */
491                 proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, ENC_NA);
492                 /*foffset += msg_length;*/
493                 break;
494             case 6:             /* Client Get User NDS Credentials */
495                 proto_tree_add_item(atree, hf_num_creds, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
496                 foffset += 4;
497                 proto_tree_add_item(atree, hf_cred_type, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
498                 foffset += 4;
499                 proto_tree_add_item(atree, hf_login_state, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
500                 foffset += 4;
501                 msg_length -= 12;
502                 proto_tree_add_item(atree, hf_enc_cred, tvb, foffset, msg_length, ENC_NA);
503                 /*foffset += msg_length;*/
504                 break;
505             case 8:             /* Login Store Management */
506                 proto_tree_add_uint_format(atree, hf_lsm_verb, tvb, foffset, -1, msgverb,
507                     "Subverb: %s", val_to_str(msgverb, nmas_lsmverb_enum, "Unknown (%u)"));
508                 switch(msgverb) {
509                     /* The data within these structures is all encrypted. */
510                 case 1:
511                 case 3:
512                 case 5:
513                 case 7:
514                 case 9:
515                     proto_tree_add_item(atree, hf_enc_data, tvb, foffset, msg_length, ENC_NA);
516                     /*foffset += msg_length;*/
517                     break;
518                 default:
519                     break;
520                 }
521                 break;
522             case 10:            /* Writable Object Check */
523                 proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
524                 /*foffset += 4;*/
525                 break;
526             case 1242:          /* Message Handler */
527                 proto_tree_add_uint_format(atree, hf_msg_verb, tvb, foffset, 1, msgverb,
528                                 "Subverb: %s", val_to_str(msgverb, nmas_msgverb_enum, "Unknown (%u)"));
529                 switch(msgverb) {
530                 case 1:
531                     msg_length = tvb_get_ntohl(tvb, foffset);
532                     proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_BIG_ENDIAN);
533                     foffset += 4;
534                     proto_tree_add_item(atree, hf_data, tvb, foffset, msg_length, ENC_NA);
535                     /*foffset += msg_length;*/
536                     break;
537                 case 3:
538                     proto_tree_add_item(atree, hf_session_ident, tvb, foffset, 4, ENC_BIG_ENDIAN);
539                     /*foffset += 4;*/
540                     break;
541                 case 5:
542                     /* No Op */
543                     break;
544                 case 7:
545                     encrypt_error = tvb_get_ntohl(tvb, foffset);
546                     str = try_val_to_str(encrypt_error, nmas_errors_enum);
547                     if (str) {
548                         col_add_fstr(pinfo->cinfo, COL_INFO, "R Payload Error - %s", str);
549                         expert_item = proto_tree_add_item(atree, hf_encrypt_error, tvb, foffset, 4, ENC_BIG_ENDIAN);
550                         expert_add_info_format(pinfo, expert_item, &ei_encrypt_error, "NMAS Payload Error: %s", str);
551                     } else {
552                         proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, ENC_NA);
553                     }
554                     /*foffset += msg_length;*/
555                     break;
556                 case 9:
557                     /* No Op */
558                     break;
559                 default:
560                     break;
561                 }
562                 break;
563             default:
564                 break;
565             }
566         }
567         str = try_val_to_str(return_code, nmas_errors_enum);
568         if (str) {
569             expert_item = proto_tree_add_item(atree, hf_return_code, tvb, roffset, 4, ENC_LITTLE_ENDIAN);
570             expert_add_info_format(pinfo, expert_item, &ei_return_error, "NMAS Error: 0x%08x %s", return_code, str);
571             col_add_fstr(pinfo->cinfo, COL_INFO, "R Error - %s", str);
572         } else {
573             if (return_code!=0) {
574                 expert_item = proto_tree_add_item(atree, hf_return_code, tvb, roffset, 4, ENC_LITTLE_ENDIAN);
575                 expert_add_info_format(pinfo, expert_item, &ei_return_error, "NMAS Error: 0x%08x is unknown", return_code);
576                 col_add_fstr(pinfo->cinfo, COL_INFO, "R Unknown NMAS Error - 0x%08x", return_code);
577             }
578         }
579 
580         if (return_code == 0) {
581             proto_tree_add_uint_format_value(atree, hf_return_code, tvb, roffset, 4, return_code, "Success (0x00000000)");
582         }
583         break;
584     case 3:
585         break;
586     default:
587         break;
588     }
589 }
590 
591 void
proto_register_nmas(void)592 proto_register_nmas(void)
593 {
594     static hf_register_info hf_nmas[] = {
595 #if 0
596         { &hf_func,
597         { "Function", "nmas.func",
598             FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
599 #endif
600 
601 #if 0
602         { &hf_subfunc,
603         { "Subfunction", "nmas.subfunc",
604             FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
605 #endif
606 
607         { &hf_ping_version,
608         { "Ping Version", "nmas.ping_version",
609             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
610 
611         { &hf_ping_flags,
612         { "Flags", "nmas.ping_flags",
613             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
614 
615         { &hf_frag_handle,
616         { "Fragment Handle", "nmas.frag_handle",
617             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
618 
619         { &hf_length,
620         { "Length", "nmas.length",
621             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
622 
623         { &hf_subverb,
624         { "Sub Verb", "nmas.subverb",
625             FT_UINT32, BASE_HEX, VALS(nmas_subverb_enum), 0x0, NULL, HFILL }},
626 
627         { &hf_tree,
628         { "Tree", "nmas.tree",
629             FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
630 
631         { &hf_user,
632         { "User", "nmas.user",
633             FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
634 
635         { &hf_nmas_version,
636         { "NMAS Protocol Version", "nmas.version",
637             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
638 
639         { &hf_msg_version,
640         { "Message Version", "nmas.msg_version",
641             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
642 
643         { &hf_session_ident,
644         { "Session Identifier", "nmas.session_ident",
645             FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
646 
647         { &hf_verb,
648         { "Verb", "nmas.verb",
649             FT_UINT8, BASE_HEX, VALS(nmas_subverb_enum), 0x0, NULL, HFILL }},
650 
651         { &hf_msg_verb,
652         { "Message Verb", "nmas.msg_verb",
653             FT_UINT8, BASE_HEX, VALS(nmas_msgverb_enum), 0x0, NULL, HFILL }},
654 
655 #if 0
656         { &hf_attribute,
657         { "Attribute Type", "nmas.attribute",
658             FT_UINT32, BASE_DEC, VALS(nmas_attribute_enum), 0x0, NULL, HFILL }},
659 #endif
660 
661         { &hf_clearance,
662         { "Requested Clearance", "nmas.clearance",
663             FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
664 
665         { &hf_login_sequence,
666         { "Requested Login Sequence", "nmas.login_seq",
667             FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
668 
669         { &hf_opaque,
670         { "Opaque Data", "nmas.opaque",
671             FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
672 
673         { &hf_data,
674         { "Data", "nmas.data",
675             FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
676 
677         { &hf_return_code,
678         { "Return Code", "nmas.return_code",
679             FT_UINT32, BASE_HEX, VALS(nmas_errors_enum), 0x0, NULL, HFILL }},
680 
681         { &hf_lsm_verb,
682         { "Login Store Message Verb", "nmas.lsm_verb",
683             FT_UINT8, BASE_HEX, VALS(nmas_lsmverb_enum), 0x0, NULL, HFILL }},
684 
685         { &hf_squeue_bytes,
686         { "Server Queue Number of Bytes", "nmas.squeue_bytes",
687             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
688 
689         { &hf_cqueue_bytes,
690         { "Client Queue Number of Bytes", "nmas.cqueue_bytes",
691             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
692 
693         { &hf_num_creds,
694         { "Number of Credentials", "nmas.num_creds",
695             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
696 
697         { &hf_cred_type,
698         { "Credential Type", "nmas.cred_type",
699             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
700 
701         { &hf_login_state,
702         { "Login State", "nmas.login_state",
703             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
704 
705         { &hf_enc_cred,
706         { "Encrypted Credential", "nmas.enc_cred",
707           FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
708 
709         { &hf_enc_data,
710         { "Encrypted Data", "nmas.enc_data",
711           FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
712 
713         { &hf_reply_buffer_size,
714         { "Reply Buffer Size", "nmas.buf_size",
715             FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
716 
717         { &hf_encrypt_error,
718         { "Payload Error", "nmas.encrypt_error",
719             FT_UINT32, BASE_HEX, VALS(nmas_errors_enum), 0x0,
720             "Payload/Encryption Return Code", HFILL }}
721     };
722 
723     static gint *ett[] = {
724         &ett_nmas
725     };
726 
727     static ei_register_info ei[] = {
728         { &ei_encrypt_error, { "nmas.encrypt_error.expert", PI_RESPONSE_CODE, PI_NOTE, "NMAS Payload Erro", EXPFILL }},
729         { &ei_return_error, { "nmas.return_code.expert", PI_RESPONSE_CODE, PI_NOTE, "NMAS Error", EXPFILL }},
730     };
731 
732     expert_module_t* expert_nmas;
733 
734     proto_nmas = proto_register_protocol("Novell Modular Authentication Service", "NMAS", "nmas");
735     proto_register_field_array(proto_nmas, hf_nmas, array_length(hf_nmas));
736     proto_register_subtree_array(ett, array_length(ett));
737     expert_nmas = expert_register_protocol(proto_nmas);
738     expert_register_field_array(expert_nmas, ei, array_length(ei));
739 }
740 
741 /*
742  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
743  *
744  * Local variables:
745  * c-basic-offset: 4
746  * tab-width: 8
747  * indent-tabs-mode: nil
748  * End:
749  *
750  * vi: set shiftwidth=4 tabstop=8 expandtab:
751  * :indentSize=4:tabSize=8:noTabs=true:
752  */
753