wireshark/epan/dissectors/packet-fcsp.c

618 lines
20 KiB
C

/* packet-fc-sp.c
* Routines for Fibre Channel Security Protocol (FC-SP)
* This decoder is for FC-SP version 1.1
* Copyright 2003, Dinesh G Dutt <ddutt@cisco.com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/to_str.h>
#include <epan/expert.h>
void proto_register_fcsp(void);
/* Message Codes */
#define FC_AUTH_MSG_AUTH_REJECT 0x0A
#define FC_AUTH_MSG_AUTH_NEGOTIATE 0x0B
#define FC_AUTH_MSG_AUTH_DONE 0x0C
#define FC_AUTH_DHCHAP_CHALLENGE 0x10
#define FC_AUTH_DHCHAP_REPLY 0x11
#define FC_AUTH_DHCHAP_SUCCESS 0x12
#define FC_AUTH_FCAP_REQUEST 0x13
#define FC_AUTH_FCAP_ACKNOWLEDGE 0x14
#define FC_AUTH_FCAP_CONFIRM 0x15
#define FC_AUTH_FCPAP_INIT 0x16
#define FC_AUTH_FCPAP_ACCEPT 0x17
#define FC_AUTH_FCPAP_COMPLETE 0x18
#define FC_AUTH_NAME_TYPE_WWN 0x1
#define FC_AUTH_PROTO_TYPE_DHCHAP 0x1
#define FC_AUTH_PROTO_TYPE_FCAP 0x2
#define FC_AUTH_DHCHAP_HASH_MD5 0x5
#define FC_AUTH_DHCHAP_HASH_SHA1 0x6
#define FC_AUTH_DHCHAP_PARAM_HASHLIST 0x1
#define FC_AUTH_DHCHAP_PARAM_DHgIDLIST 0x2
/* Initialize the protocol and registered fields */
static int proto_fcsp = -1;
static int hf_auth_proto_ver = -1;
static int hf_auth_msg_code = -1;
static int hf_auth_flags = -1;
static int hf_auth_len = -1;
static int hf_auth_tid = -1;
static int hf_auth_initiator_wwn = -1;
static int hf_auth_initiator_name = -1;
static int hf_auth_usable_proto = -1;
static int hf_auth_rjt_code = -1;
static int hf_auth_rjt_codedet = -1;
static int hf_auth_responder_wwn = -1;
static int hf_auth_responder_name = -1;
/* static int hf_auth_dhchap_groupid = -1; */
/* static int hf_auth_dhchap_hashid = -1; */
static int hf_auth_dhchap_chal_len = -1;
static int hf_auth_dhchap_val_len = -1;
static int hf_auth_dhchap_rsp_len = -1;
static int hf_auth_initiator_name_type = -1;
static int hf_auth_initiator_name_len = -1;
static int hf_auth_responder_name_len = -1;
static int hf_auth_responder_name_type = -1;
static int hf_auth_proto_type = -1;
static int hf_auth_proto_param_len = -1;
static int hf_auth_dhchap_param_tag = -1;
static int hf_auth_dhchap_param_len = -1;
static int hf_auth_dhchap_hash_type = -1;
static int hf_auth_dhchap_group_type = -1;
static int hf_auth_dhchap_dhvalue = -1;
static int hf_auth_dhchap_chal_value = -1;
static int hf_auth_dhchap_rsp_value = -1;
/* Initialize the subtree pointers */
static gint ett_fcsp = -1;
static expert_field ei_auth_fcap_undecoded = EI_INIT;
static const value_string fcauth_msgcode_vals[] = {
{FC_AUTH_MSG_AUTH_REJECT, "AUTH_Reject"},
{FC_AUTH_MSG_AUTH_NEGOTIATE, "AUTH_Negotiate"},
{FC_AUTH_MSG_AUTH_DONE, "AUTH_Done"},
{FC_AUTH_DHCHAP_CHALLENGE, "DHCHAP_Challenge"},
{FC_AUTH_DHCHAP_REPLY, "DHCHAP_Reply"},
{FC_AUTH_DHCHAP_SUCCESS, "DHCHAP_Success"},
{FC_AUTH_FCAP_REQUEST, "FCAP_Request"},
{FC_AUTH_FCAP_ACKNOWLEDGE, "FCAP_Acknowledge"},
{FC_AUTH_FCAP_CONFIRM, "FCAP_Confirm"},
{FC_AUTH_FCPAP_INIT, "FCPAP_Init"},
{FC_AUTH_FCPAP_ACCEPT, "FCPAP_Accept"},
{FC_AUTH_FCPAP_COMPLETE, "FCPAP_Complete"},
{0, NULL},
};
static const value_string fcauth_rjtcode_vals[] = {
{0x01, "Authentication Failure"},
{0x02, "Logical Error"},
{0, NULL},
};
static const value_string fcauth_rjtcode_detail_vals[] = {
{0x01, "Authentication Mechanism Not Usable"},
{0x02, "DH Group Not Usable"},
{0x03, "Hash Algorithm Not Usable"},
{0x04, "Authentication Protocol Instance Already Started"},
{0x05, "Authentication Failed "},
{0x06, "Incorrect Payload "},
{0x07, "Incorrect Authentication Protocol Message"},
{0x08, "Protocol Reset"},
{0, NULL},
};
static const value_string fcauth_dhchap_param_vals[] = {
{FC_AUTH_DHCHAP_PARAM_HASHLIST, "HashList"},
{FC_AUTH_DHCHAP_PARAM_DHgIDLIST, "DHgIDList"},
{0, NULL},
};
static const value_string fcauth_dhchap_hash_algo_vals[] = {
{FC_AUTH_DHCHAP_HASH_MD5, "MD5"},
{FC_AUTH_DHCHAP_HASH_SHA1, "SHA-1"},
{0, NULL},
};
static const value_string fcauth_name_type_vals[] = {
{FC_AUTH_NAME_TYPE_WWN, "WWN"},
{0, NULL},
};
static const value_string fcauth_proto_type_vals[] = {
{FC_AUTH_PROTO_TYPE_DHCHAP, "DHCHAP"},
{FC_AUTH_PROTO_TYPE_FCAP, "FCAP"},
{0, NULL},
};
static const value_string fcauth_dhchap_dhgid_vals[] = {
{0, "DH NULL"},
{1, "DH Group 1024"},
{2, "DH Group 1280"},
{3, "DH Group 1536"},
{4, "DH Group 2048"},
{0, NULL},
};
/* this format is required because a script is used to build the C function
that calls all the protocol registration.
*/
static void dissect_fcsp_dhchap_auth_param(tvbuff_t *tvb, proto_tree *tree,
int offset, gint32 total_len)
{
guint16 auth_param_tag;
guint16 param_len, i;
if (tree) {
total_len -= 4;
while (total_len > 0) {
proto_tree_add_item(tree, hf_auth_dhchap_param_tag, tvb, offset,
2, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_auth_dhchap_param_len, tvb, offset+2,
2, ENC_BIG_ENDIAN);
auth_param_tag = tvb_get_ntohs(tvb, offset);
param_len = tvb_get_ntohs(tvb, offset+2)*4;
switch (auth_param_tag) {
case FC_AUTH_DHCHAP_PARAM_HASHLIST:
offset += 4;
total_len -= 4;
for (i = 0; i < param_len; i += 4) {
proto_tree_add_item(tree, hf_auth_dhchap_hash_type, tvb,
offset, 4, ENC_BIG_ENDIAN);
offset += 4;
}
break;
case FC_AUTH_DHCHAP_PARAM_DHgIDLIST:
offset += 4;
total_len -= 4;
for (i = 0; i < param_len; i += 4) {
proto_tree_add_item(tree, hf_auth_dhchap_group_type, tvb,
offset, 4, ENC_BIG_ENDIAN);
offset += 4;
}
break;
default:
/* If we don't recognize the auth_param_tag and the param_len
* is 0 then just return to prevent an infinite loop. See
* https://gitlab.com/wireshark/wireshark/-/issues/8359
*/
if (param_len == 0) {
return;
}
break;
}
total_len -= param_len;
}
}
}
static void dissect_fcsp_dhchap_challenge(tvbuff_t *tvb, proto_tree *tree)
{
int offset = 12;
guint16 name_type;
guint16 param_len, name_len;
if (tree) {
proto_tree_add_item(tree, hf_auth_responder_name_type, tvb, offset,
2, ENC_BIG_ENDIAN);
name_type = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(tree, hf_auth_responder_name_len, tvb, offset+2,
2, ENC_BIG_ENDIAN);
name_len = tvb_get_ntohs(tvb, offset+2);
if (name_type == FC_AUTH_NAME_TYPE_WWN) {
proto_tree_add_item(tree, hf_auth_responder_wwn, tvb, offset+4,
8, ENC_NA);
}
else {
proto_tree_add_item(tree, hf_auth_responder_name, tvb, offset+4,
name_len, ENC_NA);
}
offset += (4+name_len);
proto_tree_add_item(tree, hf_auth_dhchap_hash_type, tvb, offset,
4, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_auth_dhchap_group_type, tvb, offset+4,
4, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_auth_dhchap_chal_len, tvb, offset+8,
4, ENC_BIG_ENDIAN);
param_len = tvb_get_ntohl(tvb, offset+8);
proto_tree_add_item(tree, hf_auth_dhchap_chal_value, tvb, offset+12,
param_len, ENC_NA);
offset += (param_len + 12);
proto_tree_add_item(tree, hf_auth_dhchap_val_len, tvb, offset, 4, ENC_BIG_ENDIAN);
param_len = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(tree, hf_auth_dhchap_dhvalue, tvb, offset+4,
param_len, ENC_NA);
}
}
static void dissect_fcsp_dhchap_reply(tvbuff_t *tvb, proto_tree *tree)
{
int offset = 12;
guint32 param_len;
if (tree) {
proto_tree_add_item(tree, hf_auth_dhchap_rsp_len, tvb, offset, 4, ENC_BIG_ENDIAN);
param_len = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(tree, hf_auth_dhchap_rsp_value, tvb, offset+4,
param_len, ENC_NA);
offset += (param_len + 4);
proto_tree_add_item(tree, hf_auth_dhchap_val_len, tvb, offset, 4, ENC_BIG_ENDIAN);
param_len = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(tree, hf_auth_dhchap_dhvalue, tvb, offset+4,
param_len, ENC_NA);
offset += (param_len + 4);
proto_tree_add_item(tree, hf_auth_dhchap_chal_len, tvb, offset, 4, ENC_BIG_ENDIAN);
param_len = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(tree, hf_auth_dhchap_chal_value, tvb, offset+4,
param_len, ENC_NA);
}
}
static void dissect_fcsp_dhchap_success(tvbuff_t *tvb, proto_tree *tree)
{
int offset = 12;
guint32 param_len;
if (tree) {
proto_tree_add_item(tree, hf_auth_dhchap_rsp_len, tvb, offset, 4, ENC_BIG_ENDIAN);
param_len = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(tree, hf_auth_dhchap_rsp_value, tvb, offset+4,
param_len, ENC_NA);
}
}
static void dissect_fcsp_auth_negotiate(tvbuff_t *tvb, proto_tree *tree)
{
int offset = 12;
guint16 name_type, name_len, proto_type, param_len;
guint32 num_protos, i;
if (tree) {
proto_tree_add_item(tree, hf_auth_initiator_name_type, tvb, offset,
2, ENC_BIG_ENDIAN);
name_type = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(tree, hf_auth_initiator_name_len, tvb, offset+2,
2, ENC_BIG_ENDIAN);
name_len = tvb_get_ntohs(tvb, offset+2);
if (name_type == FC_AUTH_NAME_TYPE_WWN) {
proto_tree_add_item(tree, hf_auth_initiator_wwn, tvb, offset+4, 8, ENC_NA);
}
else {
proto_tree_add_item(tree, hf_auth_initiator_name, tvb, offset+4,
name_len, ENC_NA);
}
offset += (4+name_len);
proto_tree_add_item(tree, hf_auth_usable_proto, tvb, offset, 4, ENC_BIG_ENDIAN);
num_protos = tvb_get_ntohl(tvb, offset);
offset += 4;
for (i = 0; i < num_protos; i++) {
proto_tree_add_item(tree, hf_auth_proto_param_len, tvb, offset, 4, ENC_BIG_ENDIAN);
param_len = tvb_get_ntohl(tvb, offset);
offset += 4;
if (tvb_bytes_exist(tvb, offset, param_len)) {
proto_type = tvb_get_ntohl(tvb, offset);
proto_tree_add_item(tree, hf_auth_proto_type, tvb, offset, 4, ENC_BIG_ENDIAN);
switch (proto_type) {
case FC_AUTH_PROTO_TYPE_DHCHAP:
dissect_fcsp_dhchap_auth_param(tvb, tree, offset+4, param_len);
break;
case FC_AUTH_PROTO_TYPE_FCAP:
break;
default:
break;
}
}
offset += param_len;
}
}
}
static void dissect_fcsp_auth_done(tvbuff_t *tvb _U_, proto_tree *tree _U_)
{
}
static void dissect_fcsp_auth_rjt(tvbuff_t *tvb, proto_tree *tree)
{
int offset = 12;
if (tree) {
proto_tree_add_item(tree, hf_auth_rjt_code, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_auth_rjt_codedet, tvb, offset+1, 1, ENC_BIG_ENDIAN);
}
}
static int dissect_fcsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
proto_item *ti = NULL;
guint8 opcode;
int offset = 0;
proto_tree *fcsp_tree = NULL;
/* Make entry in the Info column on summary display */
opcode = tvb_get_guint8(tvb, 2);
col_add_str(pinfo->cinfo, COL_INFO,
val_to_str(opcode, fcauth_msgcode_vals, "0x%x"));
if (tree) {
ti = proto_tree_add_protocol_format(tree, proto_fcsp, tvb, 0,
tvb_captured_length(tvb), "FC-SP");
fcsp_tree = proto_item_add_subtree(ti, ett_fcsp);
proto_tree_add_item(fcsp_tree, hf_auth_flags, tvb, offset+1, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(fcsp_tree, hf_auth_msg_code, tvb, offset+2, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(fcsp_tree, hf_auth_proto_ver, tvb, offset+3, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(fcsp_tree, hf_auth_len, tvb, offset+4, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(fcsp_tree, hf_auth_tid, tvb, offset+8, 4, ENC_BIG_ENDIAN);
switch (opcode) {
case FC_AUTH_MSG_AUTH_REJECT:
dissect_fcsp_auth_rjt(tvb, tree);
break;
case FC_AUTH_MSG_AUTH_NEGOTIATE:
dissect_fcsp_auth_negotiate(tvb, tree);
break;
case FC_AUTH_MSG_AUTH_DONE:
dissect_fcsp_auth_done(tvb, tree);
break;
case FC_AUTH_DHCHAP_CHALLENGE:
dissect_fcsp_dhchap_challenge(tvb, tree);
break;
case FC_AUTH_DHCHAP_REPLY:
dissect_fcsp_dhchap_reply(tvb, tree);
break;
case FC_AUTH_DHCHAP_SUCCESS:
dissect_fcsp_dhchap_success(tvb, tree);
break;
case FC_AUTH_FCAP_REQUEST:
case FC_AUTH_FCAP_ACKNOWLEDGE:
case FC_AUTH_FCAP_CONFIRM:
case FC_AUTH_FCPAP_INIT:
case FC_AUTH_FCPAP_ACCEPT:
case FC_AUTH_FCPAP_COMPLETE:
proto_tree_add_expert(fcsp_tree, pinfo, &ei_auth_fcap_undecoded, tvb, offset+12, -1);
break;
default:
break;
}
}
return tvb_captured_length(tvb);
}
void
proto_register_fcsp(void)
{
/* Setup list of header fields See Section 1.6.1 for details*/
static hf_register_info hf[] = {
{ &hf_auth_proto_ver,
{ "Protocol Version", "fcsp.version",
FT_UINT8, BASE_HEX, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_msg_code,
{ "Message Code", "fcsp.opcode",
FT_UINT8, BASE_HEX, VALS(fcauth_msgcode_vals), 0x0,
NULL, HFILL}},
{ &hf_auth_flags,
{ "Flags", "fcsp.flags",
FT_UINT8, BASE_HEX, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_len,
{ "Packet Length", "fcsp.len",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_tid,
{ "Transaction Identifier", "fcsp.tid",
FT_UINT32, BASE_HEX, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_initiator_wwn,
{ "Initiator Name (WWN)", "fcsp.initwwn",
FT_FCWWN, BASE_NONE, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_initiator_name,
{ "Initiator Name (Unknown Type)", "fcsp.initname",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_initiator_name_type,
{ "Initiator Name Type", "fcsp.initnametype",
FT_UINT16, BASE_HEX, VALS(fcauth_name_type_vals), 0x0,
NULL, HFILL}},
{ &hf_auth_initiator_name_len,
{ "Initiator Name Length", "fcsp.initnamelen",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_usable_proto,
{ "Number of Usable Protocols", "fcsp.usableproto",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_rjt_code,
{ "Reason Code", "fcsp.rjtcode",
FT_UINT8, BASE_DEC, VALS(fcauth_rjtcode_vals), 0x0,
NULL, HFILL}},
{ &hf_auth_rjt_codedet,
{ "Reason Code Explanation", "fcsp.rjtcodet",
FT_UINT8, BASE_DEC, VALS(fcauth_rjtcode_detail_vals), 0x0,
NULL, HFILL}},
{ &hf_auth_responder_wwn,
{ "Responder Name (WWN)", "fcsp.rspwwn",
FT_FCWWN, BASE_NONE, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_responder_name,
{ "Responder Name (Unknown Type)", "fcsp.rspname",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_responder_name_type,
{ "Responder Name Type", "fcsp.rspnametype",
FT_UINT16, BASE_HEX, VALS(fcauth_name_type_vals), 0x0,
NULL, HFILL}},
{ &hf_auth_responder_name_len,
{ "Responder Name Type", "fcsp.rspnamelen",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
#if 0
{ &hf_auth_dhchap_hashid,
{ "Hash Identifier", "fcsp.dhchap.hashid",
FT_UINT32, BASE_HEX, NULL, 0x0,
NULL, HFILL}},
#endif
#if 0
{ &hf_auth_dhchap_groupid,
{ "DH Group Identifier", "fcsp.dhchap.groupid",
FT_UINT32, BASE_HEX, NULL, 0x0,
NULL, HFILL}},
#endif
{ &hf_auth_dhchap_chal_len,
{ "Challenge Value Length", "fcsp.dhchap.challen",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_dhchap_val_len,
{ "DH Value Length", "fcsp.dhchap.vallen",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_dhchap_rsp_len,
{ "Response Value Length", "fcsp.dhchap.rsplen",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_proto_type,
{ "Authentication Protocol Type", "fcsp.proto",
FT_UINT32, BASE_DEC, VALS(fcauth_proto_type_vals), 0x0,
NULL, HFILL}},
{ &hf_auth_proto_param_len,
{ "Protocol Parameters Length", "fcsp.protoparamlen",
FT_UINT32, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_dhchap_param_tag,
{ "Parameter Tag", "fcsp.dhchap.paramtype",
FT_UINT16, BASE_HEX, VALS(fcauth_dhchap_param_vals), 0x0,
NULL, HFILL}},
{ &hf_auth_dhchap_param_len,
{ "Parameter Length", "fcsp.dhchap.paramlen",
FT_UINT16, BASE_DEC, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_dhchap_hash_type,
{ "Hash Algorithm", "fcsp.dhchap.hashtype",
FT_UINT32, BASE_DEC, VALS(fcauth_dhchap_hash_algo_vals), 0x0,
NULL, HFILL}},
{ &hf_auth_dhchap_group_type,
{ "DH Group", "fcsp.dhchap.dhgid",
FT_UINT32, BASE_DEC, VALS(fcauth_dhchap_dhgid_vals), 0x0,
NULL, HFILL}},
{ &hf_auth_dhchap_chal_value,
{ "Challenge Value", "fcsp.dhchap.chalval",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_dhchap_dhvalue,
{ "DH Value", "fcsp.dhchap.dhvalue",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL}},
{ &hf_auth_dhchap_rsp_value,
{ "Response Value", "fcsp.dhchap.rspval",
FT_BYTES, BASE_NONE, NULL, 0x0,
NULL, HFILL}},
};
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_fcsp,
};
static ei_register_info ei[] = {
{ &ei_auth_fcap_undecoded, { "fcsp.fcap_undecoded", PI_UNDECODED, PI_WARN, "FCAP Decoding Not Supported", EXPFILL }},
};
expert_module_t* expert_fcsp;
/* Register the protocol name and description */
proto_fcsp = proto_register_protocol("Fibre Channel Security Protocol", "FC-SP", "fcsp");
register_dissector("fcsp", dissect_fcsp, proto_fcsp);
proto_register_field_array(proto_fcsp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_fcsp = expert_register_protocol(proto_fcsp);
expert_register_field_array(expert_fcsp, ei, array_length(ei));
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/