2 * Routines for Fibre Channel Security Protocol (FC-SP)
3 * This decoder is for FC-SP version 1.1
4 * Copyright 2003, Dinesh G Dutt <ddutt@cisco.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include <epan/to_str.h>
33 #include <epan/conversation.h>
34 #include <epan/etypes.h>
35 #include "packet-scsi.h"
36 #include "packet-fc.h"
39 #define FC_AUTH_MSG_AUTH_REJECT 0x0A
40 #define FC_AUTH_MSG_AUTH_NEGOTIATE 0x0B
41 #define FC_AUTH_MSG_AUTH_DONE 0x0C
42 #define FC_AUTH_DHCHAP_CHALLENGE 0x10
43 #define FC_AUTH_DHCHAP_REPLY 0x11
44 #define FC_AUTH_DHCHAP_SUCCESS 0x12
45 #define FC_AUTH_FCAP_REQUEST 0x13
46 #define FC_AUTH_FCAP_ACKNOWLEDGE 0x14
47 #define FC_AUTH_FCAP_CONFIRM 0x15
48 #define FC_AUTH_FCPAP_INIT 0x16
49 #define FC_AUTH_FCPAP_ACCEPT 0x17
50 #define FC_AUTH_FCPAP_COMPLETE 0x18
52 #define FC_AUTH_NAME_TYPE_WWN 0x1
54 #define FC_AUTH_PROTO_TYPE_DHCHAP 0x1
55 #define FC_AUTH_PROTO_TYPE_FCAP 0x2
57 #define FC_AUTH_DHCHAP_HASH_MD5 0x5
58 #define FC_AUTH_DHCHAP_HASH_SHA1 0x6
60 #define FC_AUTH_DHCHAP_PARAM_HASHLIST 0x1
61 #define FC_AUTH_DHCHAP_PARAM_DHgIDLIST 0x2
63 /* Initialize the protocol and registered fields */
64 static int proto_fcsp
= -1;
65 static int hf_auth_proto_ver
= -1;
66 static int hf_auth_msg_code
= -1;
67 static int hf_auth_flags
= -1;
68 static int hf_auth_len
= -1;
69 static int hf_auth_tid
= -1;
70 static int hf_auth_initiator_wwn
= -1;
71 static int hf_auth_initiator_name
= -1;
72 static int hf_auth_usable_proto
= -1;
73 static int hf_auth_rjt_code
= -1;
74 static int hf_auth_rjt_codedet
= -1;
75 static int hf_auth_responder_wwn
= -1;
76 static int hf_auth_responder_name
= -1;
77 /* static int hf_auth_dhchap_groupid = -1; */
78 /* static int hf_auth_dhchap_hashid = -1; */
79 static int hf_auth_dhchap_chal_len
= -1;
80 static int hf_auth_dhchap_val_len
= -1;
81 static int hf_auth_dhchap_rsp_len
= -1;
82 static int hf_auth_initiator_name_type
= -1;
83 static int hf_auth_initiator_name_len
= -1;
84 static int hf_auth_responder_name_len
= -1;
85 static int hf_auth_responder_name_type
= -1;
86 static int hf_auth_proto_type
= -1;
87 static int hf_auth_proto_param_len
= -1;
88 static int hf_auth_dhchap_param_tag
= -1;
89 static int hf_auth_dhchap_param_len
= -1;
90 static int hf_auth_dhchap_hash_type
= -1;
91 static int hf_auth_dhchap_group_type
= -1;
92 static int hf_auth_dhchap_dhvalue
= -1;
93 static int hf_auth_dhchap_chal_value
= -1;
94 static int hf_auth_dhchap_rsp_value
= -1;
96 /* Initialize the subtree pointers */
97 static gint ett_fcsp
= -1;
99 static const value_string fcauth_msgcode_vals
[] = {
100 {FC_AUTH_MSG_AUTH_REJECT
, "AUTH_Reject"},
101 {FC_AUTH_MSG_AUTH_NEGOTIATE
, "AUTH_Negotiate"},
102 {FC_AUTH_MSG_AUTH_DONE
, "AUTH_Done"},
103 {FC_AUTH_DHCHAP_CHALLENGE
, "DHCHAP_Challenge"},
104 {FC_AUTH_DHCHAP_REPLY
, "DHCHAP_Reply"},
105 {FC_AUTH_DHCHAP_SUCCESS
, "DHCHAP_Success"},
106 {FC_AUTH_FCAP_REQUEST
, "FCAP_Request"},
107 {FC_AUTH_FCAP_ACKNOWLEDGE
, "FCAP_Acknowledge"},
108 {FC_AUTH_FCAP_CONFIRM
, "FCAP_Confirm"},
109 {FC_AUTH_FCPAP_INIT
, "FCPAP_Init"},
110 {FC_AUTH_FCPAP_ACCEPT
, "FCPAP_Accept"},
111 {FC_AUTH_FCPAP_COMPLETE
, "FCPAP_Complete"},
115 static const value_string fcauth_rjtcode_vals
[] = {
116 {0x01, "Authentication Failure"},
117 {0x02, "Logical Error"},
121 static const value_string fcauth_rjtcode_detail_vals
[] = {
122 {0x01, "Authentication Mechanism Not Usable"},
123 {0x02, "DH Group Not Usable"},
124 {0x03, "Hash Algorithm Not Usable"},
125 {0x04, "Authentication Protocol Instance Already Started"},
126 {0x05, "Authentication Failed "},
127 {0x06, "Incorrect Payload "},
128 {0x07, "Incorrect Authentication Protocol Message"},
129 {0x08, "Protocol Reset"},
133 static const value_string fcauth_dhchap_param_vals
[] = {
134 {FC_AUTH_DHCHAP_PARAM_HASHLIST
, "HashList"},
135 {FC_AUTH_DHCHAP_PARAM_DHgIDLIST
, "DHgIDList"},
139 static const value_string fcauth_dhchap_hash_algo_vals
[] = {
140 {FC_AUTH_DHCHAP_HASH_MD5
, "MD5"},
141 {FC_AUTH_DHCHAP_HASH_SHA1
, "SHA-1"},
145 static const value_string fcauth_name_type_vals
[] = {
146 {FC_AUTH_NAME_TYPE_WWN
, "WWN"},
150 static const value_string fcauth_proto_type_vals
[] = {
151 {FC_AUTH_PROTO_TYPE_DHCHAP
, "DHCHAP"},
152 {FC_AUTH_PROTO_TYPE_FCAP
, "FCAP"},
156 static const value_string fcauth_dhchap_dhgid_vals
[] = {
158 {1, "DH Group 1024"},
159 {2, "DH Group 1280"},
160 {3, "DH Group 1536"},
161 {4, "DH Group 2048"},
165 /* this format is required because a script is used to build the C function
166 that calls all the protocol registration.
169 static void dissect_fcsp_dhchap_auth_param(tvbuff_t
*tvb
, proto_tree
*tree
,
170 int offset
, gint32 total_len
)
172 guint16 auth_param_tag
;
173 guint16 param_len
, i
;
178 while (total_len
> 0) {
179 proto_tree_add_item(tree
, hf_auth_dhchap_param_tag
, tvb
, offset
,
181 proto_tree_add_item(tree
, hf_auth_dhchap_param_len
, tvb
, offset
+2,
184 auth_param_tag
= tvb_get_ntohs(tvb
, offset
);
185 param_len
= tvb_get_ntohs(tvb
, offset
+2)*4;
187 switch (auth_param_tag
) {
188 case FC_AUTH_DHCHAP_PARAM_HASHLIST
:
191 for (i
= 0; i
< param_len
; i
+= 4) {
192 proto_tree_add_item(tree
, hf_auth_dhchap_hash_type
, tvb
,
193 offset
, 4, ENC_BIG_ENDIAN
);
197 case FC_AUTH_DHCHAP_PARAM_DHgIDLIST
:
200 for (i
= 0; i
< param_len
; i
+= 4) {
201 proto_tree_add_item(tree
, hf_auth_dhchap_group_type
, tvb
,
202 offset
, 4, ENC_BIG_ENDIAN
);
207 /* If we don't recognize the auth_param_tag and the param_len
208 * is 0 then just return to prevent an infinite loop. See
209 * https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8359
211 if (param_len
== 0) {
217 total_len
-= param_len
;
222 static void dissect_fcsp_dhchap_challenge(tvbuff_t
*tvb
, proto_tree
*tree
)
226 guint16 param_len
, name_len
;
229 proto_tree_add_item(tree
, hf_auth_responder_name_type
, tvb
, offset
,
231 name_type
= tvb_get_ntohs(tvb
, offset
);
233 proto_tree_add_item(tree
, hf_auth_responder_name_len
, tvb
, offset
+2,
236 name_len
= tvb_get_ntohs(tvb
, offset
+2);
238 if (name_type
== FC_AUTH_NAME_TYPE_WWN
) {
239 proto_tree_add_string(tree
, hf_auth_responder_wwn
, tvb
, offset
+4,
240 8, tvb_fcwwn_to_str(tvb
, offset
+4));
243 proto_tree_add_item(tree
, hf_auth_responder_name
, tvb
, offset
+4,
246 offset
+= (4+name_len
);
248 proto_tree_add_item(tree
, hf_auth_dhchap_hash_type
, tvb
, offset
,
250 proto_tree_add_item(tree
, hf_auth_dhchap_group_type
, tvb
, offset
+4,
252 proto_tree_add_item(tree
, hf_auth_dhchap_chal_len
, tvb
, offset
+8,
254 param_len
= tvb_get_ntohl(tvb
, offset
+8);
256 proto_tree_add_item(tree
, hf_auth_dhchap_chal_value
, tvb
, offset
+12,
258 offset
+= (param_len
+ 12);
260 proto_tree_add_item(tree
, hf_auth_dhchap_val_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
261 param_len
= tvb_get_ntohl(tvb
, offset
);
263 proto_tree_add_item(tree
, hf_auth_dhchap_dhvalue
, tvb
, offset
+4,
269 static void dissect_fcsp_dhchap_reply(tvbuff_t
*tvb
, proto_tree
*tree
)
275 proto_tree_add_item(tree
, hf_auth_dhchap_rsp_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
276 param_len
= tvb_get_ntohl(tvb
, offset
);
278 proto_tree_add_item(tree
, hf_auth_dhchap_rsp_value
, tvb
, offset
+4,
280 offset
+= (param_len
+ 4);
282 proto_tree_add_item(tree
, hf_auth_dhchap_val_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
283 param_len
= tvb_get_ntohl(tvb
, offset
);
285 proto_tree_add_item(tree
, hf_auth_dhchap_dhvalue
, tvb
, offset
+4,
287 offset
+= (param_len
+ 4);
289 proto_tree_add_item(tree
, hf_auth_dhchap_chal_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
290 param_len
= tvb_get_ntohl(tvb
, offset
);
292 proto_tree_add_item(tree
, hf_auth_dhchap_chal_value
, tvb
, offset
+4,
297 static void dissect_fcsp_dhchap_success(tvbuff_t
*tvb
, proto_tree
*tree
)
303 proto_tree_add_item(tree
, hf_auth_dhchap_rsp_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
304 param_len
= tvb_get_ntohl(tvb
, offset
);
306 proto_tree_add_item(tree
, hf_auth_dhchap_rsp_value
, tvb
, offset
+4,
312 static void dissect_fcsp_auth_negotiate(tvbuff_t
*tvb
, proto_tree
*tree
)
315 guint16 name_type
, name_len
, proto_type
, param_len
;
316 guint32 num_protos
, i
;
319 proto_tree_add_item(tree
, hf_auth_initiator_name_type
, tvb
, offset
,
321 name_type
= tvb_get_ntohs(tvb
, offset
);
323 proto_tree_add_item(tree
, hf_auth_initiator_name_len
, tvb
, offset
+2,
325 name_len
= tvb_get_ntohs(tvb
, offset
+2);
327 if (name_type
== FC_AUTH_NAME_TYPE_WWN
) {
328 proto_tree_add_string(tree
, hf_auth_initiator_wwn
, tvb
, offset
+4, 8,
329 tvb_fcwwn_to_str(tvb
, offset
+4));
332 proto_tree_add_item(tree
, hf_auth_initiator_name
, tvb
, offset
+4,
336 offset
+= (4+name_len
);
338 proto_tree_add_item(tree
, hf_auth_usable_proto
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
339 num_protos
= tvb_get_ntohl(tvb
, offset
);
342 for (i
= 0; i
< num_protos
; i
++) {
343 proto_tree_add_item(tree
, hf_auth_proto_param_len
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
344 param_len
= tvb_get_ntohl(tvb
, offset
);
347 if (tvb_bytes_exist(tvb
, offset
, param_len
)) {
348 proto_type
= tvb_get_ntohl(tvb
, offset
);
350 proto_tree_add_item(tree
, hf_auth_proto_type
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
351 switch (proto_type
) {
352 case FC_AUTH_PROTO_TYPE_DHCHAP
:
353 dissect_fcsp_dhchap_auth_param(tvb
, tree
, offset
+4, param_len
);
355 case FC_AUTH_PROTO_TYPE_FCAP
:
366 static void dissect_fcsp_auth_done(tvbuff_t
*tvb _U_
, proto_tree
*tree _U_
)
370 static void dissect_fcsp_auth_rjt(tvbuff_t
*tvb
, proto_tree
*tree
)
375 proto_tree_add_item(tree
, hf_auth_rjt_code
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
376 proto_tree_add_item(tree
, hf_auth_rjt_codedet
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
380 static void dissect_fcsp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
382 proto_item
*ti
= NULL
;
385 proto_tree
*fcsp_tree
= NULL
;
387 /* Make entry in the Info column on summary display */
388 opcode
= tvb_get_guint8(tvb
, 2);
390 col_add_str(pinfo
->cinfo
, COL_INFO
,
391 val_to_str(opcode
, fcauth_msgcode_vals
, "0x%x"));
394 ti
= proto_tree_add_protocol_format(tree
, proto_fcsp
, tvb
, 0,
395 tvb_length(tvb
), "FC-SP");
396 fcsp_tree
= proto_item_add_subtree(ti
, ett_fcsp
);
398 proto_tree_add_item(fcsp_tree
, hf_auth_flags
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
399 proto_tree_add_item(fcsp_tree
, hf_auth_msg_code
, tvb
, offset
+2, 1, ENC_BIG_ENDIAN
);
400 proto_tree_add_item(fcsp_tree
, hf_auth_proto_ver
, tvb
, offset
+3, 1,
402 proto_tree_add_item(fcsp_tree
, hf_auth_len
, tvb
, offset
+4, 4, ENC_BIG_ENDIAN
);
403 proto_tree_add_item(fcsp_tree
, hf_auth_tid
, tvb
, offset
+8, 4, ENC_BIG_ENDIAN
);
406 case FC_AUTH_MSG_AUTH_REJECT
:
407 dissect_fcsp_auth_rjt(tvb
, tree
);
409 case FC_AUTH_MSG_AUTH_NEGOTIATE
:
410 dissect_fcsp_auth_negotiate(tvb
, tree
);
412 case FC_AUTH_MSG_AUTH_DONE
:
413 dissect_fcsp_auth_done(tvb
, tree
);
415 case FC_AUTH_DHCHAP_CHALLENGE
:
416 dissect_fcsp_dhchap_challenge(tvb
, tree
);
418 case FC_AUTH_DHCHAP_REPLY
:
419 dissect_fcsp_dhchap_reply(tvb
, tree
);
421 case FC_AUTH_DHCHAP_SUCCESS
:
422 dissect_fcsp_dhchap_success(tvb
, tree
);
424 case FC_AUTH_FCAP_REQUEST
:
425 case FC_AUTH_FCAP_ACKNOWLEDGE
:
426 case FC_AUTH_FCAP_CONFIRM
:
427 case FC_AUTH_FCPAP_INIT
:
428 case FC_AUTH_FCPAP_ACCEPT
:
429 case FC_AUTH_FCPAP_COMPLETE
:
430 proto_tree_add_text(fcsp_tree
, tvb
, offset
+12, tvb_length(tvb
),
431 "FCAP Decoding Not Supported");
440 proto_register_fcsp(void)
442 /* Setup list of header fields See Section 1.6.1 for details*/
443 static hf_register_info hf
[] = {
444 { &hf_auth_proto_ver
,
445 { "Protocol Version", "fcsp.version",
446 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
450 { "Message Code", "fcsp.opcode",
451 FT_UINT8
, BASE_HEX
, VALS(fcauth_msgcode_vals
), 0x0,
455 { "Flags", "fcsp.flags",
456 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
460 { "Packet Length", "fcsp.len",
461 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
465 { "Transaction Identifier", "fcsp.tid",
466 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
469 { &hf_auth_initiator_wwn
,
470 { "Initiator Name (WWN)", "fcsp.initwwn",
471 FT_STRING
, BASE_NONE
, NULL
, 0x0,
474 { &hf_auth_initiator_name
,
475 { "Initiator Name (Unknown Type)", "fcsp.initname",
476 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
479 { &hf_auth_initiator_name_type
,
480 { "Initiator Name Type", "fcsp.initnametype",
481 FT_UINT16
, BASE_HEX
, VALS(fcauth_name_type_vals
), 0x0,
484 { &hf_auth_initiator_name_len
,
485 { "Initiator Name Length", "fcsp.initnamelen",
486 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
489 { &hf_auth_usable_proto
,
490 { "Number of Usable Protocols", "fcsp.usableproto",
491 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
495 { "Reason Code", "fcsp.rjtcode",
496 FT_UINT8
, BASE_DEC
, VALS(fcauth_rjtcode_vals
), 0x0,
499 { &hf_auth_rjt_codedet
,
500 { "Reason Code Explanation", "fcsp.rjtcodet",
501 FT_UINT8
, BASE_DEC
, VALS(fcauth_rjtcode_detail_vals
), 0x0,
504 { &hf_auth_responder_wwn
,
505 { "Responder Name (WWN)", "fcsp.rspwwn",
506 FT_STRING
, BASE_NONE
, NULL
, 0x0,
509 { &hf_auth_responder_name
,
510 { "Responder Name (Unknown Type)", "fcsp.rspname",
511 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
514 { &hf_auth_responder_name_type
,
515 { "Responder Name Type", "fcsp.rspnametype",
516 FT_UINT16
, BASE_HEX
, VALS(fcauth_name_type_vals
), 0x0,
519 { &hf_auth_responder_name_len
,
520 { "Responder Name Type", "fcsp.rspnamelen",
521 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
525 { &hf_auth_dhchap_hashid
,
526 { "Hash Identifier", "fcsp.dhchap.hashid",
527 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
532 { &hf_auth_dhchap_groupid
,
533 { "DH Group Identifier", "fcsp.dhchap.groupid",
534 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
538 { &hf_auth_dhchap_chal_len
,
539 { "Challenge Value Length", "fcsp.dhchap.challen",
540 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
543 { &hf_auth_dhchap_val_len
,
544 { "DH Value Length", "fcsp.dhchap.vallen",
545 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
548 { &hf_auth_dhchap_rsp_len
,
549 { "Response Value Length", "fcsp.dhchap.rsplen",
550 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
553 { &hf_auth_proto_type
,
554 { "Authentication Protocol Type", "fcsp.proto",
555 FT_UINT32
, BASE_DEC
, VALS(fcauth_proto_type_vals
), 0x0,
558 { &hf_auth_proto_param_len
,
559 { "Protocol Parameters Length", "fcsp.protoparamlen",
560 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
563 { &hf_auth_dhchap_param_tag
,
564 { "Parameter Tag", "fcsp.dhchap.paramtype",
565 FT_UINT16
, BASE_HEX
, VALS(fcauth_dhchap_param_vals
), 0x0,
568 { &hf_auth_dhchap_param_len
,
569 { "Parameter Length", "fcsp.dhchap.paramlen",
570 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
573 { &hf_auth_dhchap_hash_type
,
574 { "Hash Algorithm", "fcsp.dhchap.hashtype",
575 FT_UINT32
, BASE_DEC
, VALS(fcauth_dhchap_hash_algo_vals
), 0x0,
578 { &hf_auth_dhchap_group_type
,
579 { "DH Group", "fcsp.dhchap.dhgid",
580 FT_UINT32
, BASE_DEC
, VALS(fcauth_dhchap_dhgid_vals
), 0x0,
583 { &hf_auth_dhchap_chal_value
,
584 { "Challenge Value", "fcsp.dhchap.chalval",
585 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
588 { &hf_auth_dhchap_dhvalue
,
589 { "DH Value", "fcsp.dhchap.dhvalue",
590 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
593 { &hf_auth_dhchap_rsp_value
,
594 { "Response Value", "fcsp.dhchap.rspval",
595 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
600 /* Setup protocol subtree array */
601 static gint
*ett
[] = {
605 /* Register the protocol name and description */
606 proto_fcsp
= proto_register_protocol("Fibre Channel Security Protocol",
609 register_dissector("fcsp", dissect_fcsp
, proto_fcsp
);
611 proto_register_field_array(proto_fcsp
, hf
, array_length(hf
));
612 proto_register_subtree_array(ett
, array_length(ett
));