aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-ssh.c
diff options
context:
space:
mode:
authorBill Meier <wmeier@newsguy.com>2014-10-06 12:42:42 -0400
committerBill Meier <wmeier@newsguy.com>2014-10-06 17:10:35 +0000
commit2005fc6e780e2df78382a3c04dbdd574054eb6a5 (patch)
tree3d2f7165d21677ada41bde77cc065a545808a991 /epan/dissectors/packet-ssh.c
parent3377eca702cc0e8fe7b3f3409437f16b5b0b9b79 (diff)
Convert (what appear to be) "4 space tabs"; Adjust editor-modelines; Do some minor reformatting.
Change-Id: Ie078c826ed38a0d682f61fb3e95450b47a9d2c31 Reviewed-on: https://code.wireshark.org/review/4499 Reviewed-by: Bill Meier <wmeier@newsguy.com>
Diffstat (limited to 'epan/dissectors/packet-ssh.c')
-rw-r--r--epan/dissectors/packet-ssh.c2234
1 files changed, 1117 insertions, 1117 deletions
diff --git a/epan/dissectors/packet-ssh.c b/epan/dissectors/packet-ssh.c
index 411a825f23..b52f0c6bb3 100644
--- a/epan/dissectors/packet-ssh.c
+++ b/epan/dissectors/packet-ssh.c
@@ -65,58 +65,58 @@ void proto_register_ssh(void);
void proto_reg_handoff_ssh(void);
/* SSH Version 1 definition , from openssh ssh1.h */
-#define SSH1_MSG_NONE 0 /* no message */
-#define SSH1_MSG_DISCONNECT 1 /* cause (string) */
-#define SSH1_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
-#define SSH1_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
-#define SSH1_CMSG_USER 4 /* user (string) */
+#define SSH1_MSG_NONE 0 /* no message */
+#define SSH1_MSG_DISCONNECT 1 /* cause (string) */
+#define SSH1_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
+#define SSH1_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
+#define SSH1_CMSG_USER 4 /* user (string) */
-#define SSH_VERSION_UNKNOWN 0
-#define SSH_VERSION_1 1
-#define SSH_VERSION_2 2
+#define SSH_VERSION_UNKNOWN 0
+#define SSH_VERSION_1 1
+#define SSH_VERSION_2 2
/* proto data */
struct ssh_peer_data {
- guint counter;
+ guint counter;
- guint32 frame_version_start;
- guint32 frame_version_end;
+ guint32 frame_version_start;
+ guint32 frame_version_end;
- guint32 frame_key_start;
- guint32 frame_key_end;
+ guint32 frame_key_start;
+ guint32 frame_key_end;
- gchar* kex_proposal;
+ gchar* kex_proposal;
- /* For all subsequent proposals,
- [0] is client-to-server and [1] is server-to-client. */
+ /* For all subsequent proposals,
+ [0] is client-to-server and [1] is server-to-client. */
#define CLIENT_TO_SERVER_PROPOSAL 0
#define SERVER_TO_CLIENT_PROPOSAL 1
- gchar* mac_proposals[2];
- gchar* mac;
- gint mac_length;
+ gchar* mac_proposals[2];
+ gchar* mac;
+ gint mac_length;
- gchar* enc_proposals[2];
- gchar* enc;
+ gchar* enc_proposals[2];
+ gchar* enc;
- gchar* comp_proposals[2];
- gchar* comp;
+ gchar* comp_proposals[2];
+ gchar* comp;
- gint length_is_plaintext;
+ gint length_is_plaintext;
};
struct ssh_flow_data {
- guint version;
+ guint version;
- gchar* kex;
- int (*kex_specific_dissector)(guint8 msg_code, tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
+ gchar* kex;
+ int (*kex_specific_dissector)(guint8 msg_code, tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
- /* [0] is client's, [1] is server's */
+ /* [0] is client's, [1] is server's */
#define CLIENT_PEER_DATA 0
#define SERVER_PEER_DATA 1
- struct ssh_peer_data peer_data[2];
+ struct ssh_peer_data peer_data[2];
};
static int proto_ssh = -1;
@@ -186,138 +186,138 @@ static dissector_handle_t ssh_handle;
/* Message Numbers (from RFC 4250) (1-255) */
/* Transport layer protocol: generic (1-19) */
-#define SSH_MSG_DISCONNECT 1
-#define SSH_MSG_IGNORE 2
-#define SSH_MSG_UNIMPLEMENTED 3
-#define SSH_MSG_DEBUG 4
-#define SSH_MSG_SERVICE_REQUEST 5
-#define SSH_MSG_SERVICE_ACCEPT 6
+#define SSH_MSG_DISCONNECT 1
+#define SSH_MSG_IGNORE 2
+#define SSH_MSG_UNIMPLEMENTED 3
+#define SSH_MSG_DEBUG 4
+#define SSH_MSG_SERVICE_REQUEST 5
+#define SSH_MSG_SERVICE_ACCEPT 6
/* Transport layer protocol: Algorithm negotiation (20-29) */
-#define SSH_MSG_KEXINIT 20
-#define SSH_MSG_NEWKEYS 21
+#define SSH_MSG_KEXINIT 20
+#define SSH_MSG_NEWKEYS 21
/* Transport layer: Key exchange method specific (reusable) (30-49) */
-#define SSH_MSG_KEXDH_INIT 30
-#define SSH_MSG_KEXDH_REPLY 31
+#define SSH_MSG_KEXDH_INIT 30
+#define SSH_MSG_KEXDH_REPLY 31
-#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30
-#define SSH_MSG_KEX_DH_GEX_GROUP 31
-#define SSH_MSG_KEX_DH_GEX_INIT 32
-#define SSH_MSG_KEX_DH_GEX_REPLY 33
-#define SSH_MSG_KEX_DH_GEX_REQUEST 34
+#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30
+#define SSH_MSG_KEX_DH_GEX_GROUP 31
+#define SSH_MSG_KEX_DH_GEX_INIT 32
+#define SSH_MSG_KEX_DH_GEX_REPLY 33
+#define SSH_MSG_KEX_DH_GEX_REQUEST 34
/* User authentication protocol: generic (50-59) */
-#define SSH_MSG_USERAUTH_REQUEST 50
-#define SSH_MSG_USERAUTH_FAILURE 51
-#define SSH_MSG_USERAUTH_SUCCESS 52
-#define SSH_MSG_USERAUTH_BANNER 53
+#define SSH_MSG_USERAUTH_REQUEST 50
+#define SSH_MSG_USERAUTH_FAILURE 51
+#define SSH_MSG_USERAUTH_SUCCESS 52
+#define SSH_MSG_USERAUTH_BANNER 53
/* User authentication protocol: method specific (reusable) (50-79) */
/* Connection protocol: generic (80-89) */
-#define SSH_MSG_GLOBAL_REQUEST 80
-#define SSH_MSG_REQUEST_SUCCESS 81
-#define SSH_MSG_REQUEST_FAILURE 82
+#define SSH_MSG_GLOBAL_REQUEST 80
+#define SSH_MSG_REQUEST_SUCCESS 81
+#define SSH_MSG_REQUEST_FAILURE 82
/* Connection protocol: channel related messages (90-127) */
-#define SSH_MSG_CHANNEL_OPEN 90
-#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
-#define SSH_MSG_CHANNEL_OPEN_FAILURE 92
-#define SSH_MSG_CHANNEL_WINDOW_ADJUST 93
-#define SSH_MSG_CHANNEL_DATA 94
-#define SSH_MSG_CHANNEL_EXTENDED_DATA 95
-#define SSH_MSG_CHANNEL_EOF 96
-#define SSH_MSG_CHANNEL_CLOSE 97
-#define SSH_MSG_CHANNEL_REQUEST 98
-#define SSH_MSG_CHANNEL_SUCCESS 99
-#define SSH_MSG_CHANNEL_FAILURE 100
+#define SSH_MSG_CHANNEL_OPEN 90
+#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
+#define SSH_MSG_CHANNEL_OPEN_FAILURE 92
+#define SSH_MSG_CHANNEL_WINDOW_ADJUST 93
+#define SSH_MSG_CHANNEL_DATA 94
+#define SSH_MSG_CHANNEL_EXTENDED_DATA 95
+#define SSH_MSG_CHANNEL_EOF 96
+#define SSH_MSG_CHANNEL_CLOSE 97
+#define SSH_MSG_CHANNEL_REQUEST 98
+#define SSH_MSG_CHANNEL_SUCCESS 99
+#define SSH_MSG_CHANNEL_FAILURE 100
/* 128-191 reserved for client protocols */
/* 192-255 local extensions */
static const value_string ssh2_msg_vals[] = {
- { SSH_MSG_DISCONNECT, "Disconnect" },
- { SSH_MSG_IGNORE, "Ignore" },
- { SSH_MSG_UNIMPLEMENTED, "Unimplemented" },
- { SSH_MSG_DEBUG, "Debug" },
- { SSH_MSG_SERVICE_REQUEST, "Service Request" },
- { SSH_MSG_SERVICE_ACCEPT, "Service Accept" },
- { SSH_MSG_KEXINIT, "Key Exchange Init" },
- { SSH_MSG_NEWKEYS, "New Keys" },
- { SSH_MSG_USERAUTH_REQUEST, "User Authentication Request" },
- { SSH_MSG_USERAUTH_FAILURE, "User Authentication Failure" },
- { SSH_MSG_USERAUTH_SUCCESS, "User Authentication Success" },
- { SSH_MSG_USERAUTH_BANNER, "User Authentication Banner" },
- { SSH_MSG_GLOBAL_REQUEST, "Global Request" },
- { SSH_MSG_REQUEST_SUCCESS, "Request Success" },
- { SSH_MSG_REQUEST_FAILURE, "Request Failure" },
- { SSH_MSG_CHANNEL_OPEN, "Channel Open" },
- { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" },
- { SSH_MSG_CHANNEL_OPEN_FAILURE, "Channel Open Failure" },
- { SSH_MSG_CHANNEL_WINDOW_ADJUST, "Window Adjust" },
- { SSH_MSG_CHANNEL_DATA, "Channel Data" },
- { SSH_MSG_CHANNEL_EXTENDED_DATA, "Channel Extended Data" },
- { SSH_MSG_CHANNEL_EOF, "Channel EOF" },
- { SSH_MSG_CHANNEL_CLOSE, "Channel Close" },
- { SSH_MSG_CHANNEL_REQUEST, "Channel Request" },
- { SSH_MSG_CHANNEL_SUCCESS, "Channel Success" },
- { SSH_MSG_CHANNEL_FAILURE, "Channel Failure" },
- { 0, NULL }
+ { SSH_MSG_DISCONNECT, "Disconnect" },
+ { SSH_MSG_IGNORE, "Ignore" },
+ { SSH_MSG_UNIMPLEMENTED, "Unimplemented" },
+ { SSH_MSG_DEBUG, "Debug" },
+ { SSH_MSG_SERVICE_REQUEST, "Service Request" },
+ { SSH_MSG_SERVICE_ACCEPT, "Service Accept" },
+ { SSH_MSG_KEXINIT, "Key Exchange Init" },
+ { SSH_MSG_NEWKEYS, "New Keys" },
+ { SSH_MSG_USERAUTH_REQUEST, "User Authentication Request" },
+ { SSH_MSG_USERAUTH_FAILURE, "User Authentication Failure" },
+ { SSH_MSG_USERAUTH_SUCCESS, "User Authentication Success" },
+ { SSH_MSG_USERAUTH_BANNER, "User Authentication Banner" },
+ { SSH_MSG_GLOBAL_REQUEST, "Global Request" },
+ { SSH_MSG_REQUEST_SUCCESS, "Request Success" },
+ { SSH_MSG_REQUEST_FAILURE, "Request Failure" },
+ { SSH_MSG_CHANNEL_OPEN, "Channel Open" },
+ { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" },
+ { SSH_MSG_CHANNEL_OPEN_FAILURE, "Channel Open Failure" },
+ { SSH_MSG_CHANNEL_WINDOW_ADJUST, "Window Adjust" },
+ { SSH_MSG_CHANNEL_DATA, "Channel Data" },
+ { SSH_MSG_CHANNEL_EXTENDED_DATA, "Channel Extended Data" },
+ { SSH_MSG_CHANNEL_EOF, "Channel EOF" },
+ { SSH_MSG_CHANNEL_CLOSE, "Channel Close" },
+ { SSH_MSG_CHANNEL_REQUEST, "Channel Request" },
+ { SSH_MSG_CHANNEL_SUCCESS, "Channel Success" },
+ { SSH_MSG_CHANNEL_FAILURE, "Channel Failure" },
+ { 0, NULL }
};
static const value_string ssh2_kex_dh_msg_vals[] = {
- { SSH_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init" },
- { SSH_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply" },
- { 0, NULL }
+ { SSH_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init" },
+ { SSH_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply" },
+ { 0, NULL }
};
static const value_string ssh2_kex_dh_gex_msg_vals[] = {
- { SSH_MSG_KEX_DH_GEX_REQUEST_OLD, "Diffie-Hellman Group Exchange Request (Old)" },
- { SSH_MSG_KEX_DH_GEX_GROUP, "Diffie-Hellman Group Exchange Group" },
- { SSH_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman Group Exchange Init" },
- { SSH_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman Group Exchange Reply" },
- { SSH_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman Group Exchange Request" },
- { 0, NULL }
+ { SSH_MSG_KEX_DH_GEX_REQUEST_OLD, "Diffie-Hellman Group Exchange Request (Old)" },
+ { SSH_MSG_KEX_DH_GEX_GROUP, "Diffie-Hellman Group Exchange Group" },
+ { SSH_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman Group Exchange Init" },
+ { SSH_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman Group Exchange Reply" },
+ { SSH_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman Group Exchange Request" },
+ { 0, NULL }
};
static const value_string ssh1_msg_vals[] = {
- {SSH1_MSG_NONE, "No Message"},
- {SSH1_MSG_DISCONNECT, "Disconnect"},
- {SSH1_SMSG_PUBLIC_KEY, "Public Key"},
- {SSH1_CMSG_SESSION_KEY, "Session Key"},
- {SSH1_CMSG_USER, "User"},
- {0, NULL}
+ {SSH1_MSG_NONE, "No Message"},
+ {SSH1_MSG_DISCONNECT, "Disconnect"},
+ {SSH1_SMSG_PUBLIC_KEY, "Public Key"},
+ {SSH1_CMSG_SESSION_KEY, "Session Key"},
+ {SSH1_CMSG_USER, "User"},
+ {0, NULL}
};
static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
- int is_response,
- struct ssh_flow_data *global_data);
+ int is_response,
+ struct ssh_flow_data *global_data);
static int ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
- int hf_index_length, int hf_index_value, gchar **store);
+ int hf_index_length, int hf_index_value, gchar **store);
static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_flow_data *global_data,
- int offset, proto_tree *tree, int is_response,
- gboolean *need_desegmentation);
+ struct ssh_flow_data *global_data,
+ int offset, proto_tree *tree, int is_response,
+ gboolean *need_desegmentation);
static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_flow_data *global_data,
- int offset, proto_tree *tree, int is_response,
- gboolean *need_desegmentation);
+ struct ssh_flow_data *global_data,
+ int offset, proto_tree *tree, int is_response,
+ gboolean *need_desegmentation);
static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_flow_data *global_data,
- int offset, proto_tree *tree, int is_response,
- gboolean *need_desegmentation);
+ struct ssh_flow_data *global_data,
+ int offset, proto_tree *tree, int is_response,
+ gboolean *need_desegmentation);
static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
- packet_info *pinfo, int offset, proto_tree *tree);
+ packet_info *pinfo, int offset, proto_tree *tree);
static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
- packet_info *pinfo, int offset, proto_tree *tree);
+ packet_info *pinfo, int offset, proto_tree *tree);
static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_flow_data *global_data,
- int offset, proto_tree *tree, int is_response, guint *version,
- gboolean *need_desegmentation);
+ struct ssh_flow_data *global_data,
+ int offset, proto_tree *tree, int is_response, guint *version,
+ gboolean *need_desegmentation);
static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_peer_data *peer_data,
- int offset, proto_tree *tree);
+ struct ssh_peer_data *peer_data,
+ int offset, proto_tree *tree);
static void ssh_choose_algo(gchar *client, gchar *server, gchar **result);
static void ssh_set_mac_length(struct ssh_peer_data *peer_data);
static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data);
@@ -327,1103 +327,1103 @@ static void
dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- proto_tree *ssh_tree = NULL;
- proto_item *ti;
- conversation_t *conversation;
- int last_offset, offset = 0;
-
- gboolean is_response = (pinfo->destport != pinfo->match_uint),
- need_desegmentation;
- guint version;
-
- struct ssh_flow_data *global_data=NULL;
- struct ssh_peer_data *peer_data;
-
- conversation = find_or_create_conversation(pinfo);
-
- global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh);
- if (!global_data) {
- global_data = (struct ssh_flow_data *)wmem_alloc0(wmem_file_scope(), sizeof(struct ssh_flow_data));
- global_data->version=SSH_VERSION_UNKNOWN;
- global_data->kex_specific_dissector=ssh_dissect_kex_dh;
- global_data->peer_data[CLIENT_PEER_DATA].mac_length=-1;
- global_data->peer_data[SERVER_PEER_DATA].mac_length=-1;
-
- conversation_add_proto_data(conversation, proto_ssh, global_data);
- }
-
- peer_data = &global_data->peer_data[is_response];
-
- if (tree) {
- ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA);
- ssh_tree = proto_item_add_subtree(ti, ett_ssh);
- }
-
- version = global_data->version;
-
- switch(version) {
- case SSH_VERSION_UNKNOWN:
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
- break;
- case SSH_VERSION_1:
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
- break;
- case SSH_VERSION_2:
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
- break;
-
- }
-
- col_clear(pinfo->cinfo, COL_INFO);
-
- while(tvb_reported_length_remaining(tvb, offset)> 0) {
- gboolean after_version_start = (peer_data->frame_version_start == 0 ||
- pinfo->fd->num >= peer_data->frame_version_start);
- gboolean before_version_end = (peer_data->frame_version_end == 0 ||
- pinfo->fd->num <= peer_data->frame_version_end);
-
- need_desegmentation = FALSE;
- last_offset = offset;
-
- peer_data->counter++;
-
- if (after_version_start && before_version_end &&
- (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) {
- if (peer_data->frame_version_start == 0)
- peer_data->frame_version_start = pinfo->fd->num;
-
- offset = ssh_dissect_protocol(tvb, pinfo,
- global_data,
- offset, ssh_tree, is_response,
- &version, &need_desegmentation);
-
- if (!need_desegmentation) {
- peer_data->frame_version_end = pinfo->fd->num;
- global_data->version = version;
- }
- } else {
- switch(version) {
-
- case SSH_VERSION_UNKNOWN:
- offset = ssh_dissect_encrypted_packet(tvb, pinfo,
- &global_data->peer_data[is_response], offset, ssh_tree);
- break;
-
- case SSH_VERSION_1:
- offset = ssh_dissect_ssh1(tvb, pinfo, global_data,
- offset, ssh_tree, is_response,
- &need_desegmentation);
- break;
-
- case SSH_VERSION_2:
- offset = ssh_dissect_ssh2(tvb, pinfo, global_data,
- offset, ssh_tree, is_response,
- &need_desegmentation);
- break;
- }
- }
-
- if (need_desegmentation)
- return;
- if (offset <= last_offset)
- THROW(ReportedBoundsError);
- }
-
- col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client");
+ proto_tree *ssh_tree = NULL;
+ proto_item *ti;
+ conversation_t *conversation;
+ int last_offset, offset = 0;
+
+ gboolean is_response = (pinfo->destport != pinfo->match_uint),
+ need_desegmentation;
+ guint version;
+
+ struct ssh_flow_data *global_data=NULL;
+ struct ssh_peer_data *peer_data;
+
+ conversation = find_or_create_conversation(pinfo);
+
+ global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh);
+ if (!global_data) {
+ global_data = (struct ssh_flow_data *)wmem_alloc0(wmem_file_scope(), sizeof(struct ssh_flow_data));
+ global_data->version=SSH_VERSION_UNKNOWN;
+ global_data->kex_specific_dissector=ssh_dissect_kex_dh;
+ global_data->peer_data[CLIENT_PEER_DATA].mac_length=-1;
+ global_data->peer_data[SERVER_PEER_DATA].mac_length=-1;
+
+ conversation_add_proto_data(conversation, proto_ssh, global_data);
+ }
+
+ peer_data = &global_data->peer_data[is_response];
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA);
+ ssh_tree = proto_item_add_subtree(ti, ett_ssh);
+ }
+
+ version = global_data->version;
+
+ switch(version) {
+ case SSH_VERSION_UNKNOWN:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
+ break;
+ case SSH_VERSION_1:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
+ break;
+ case SSH_VERSION_2:
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
+ break;
+
+ }
+
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ while(tvb_reported_length_remaining(tvb, offset)> 0) {
+ gboolean after_version_start = (peer_data->frame_version_start == 0 ||
+ pinfo->fd->num >= peer_data->frame_version_start);
+ gboolean before_version_end = (peer_data->frame_version_end == 0 ||
+ pinfo->fd->num <= peer_data->frame_version_end);
+
+ need_desegmentation = FALSE;
+ last_offset = offset;
+
+ peer_data->counter++;
+
+ if (after_version_start && before_version_end &&
+ (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) {
+ if (peer_data->frame_version_start == 0)
+ peer_data->frame_version_start = pinfo->fd->num;
+
+ offset = ssh_dissect_protocol(tvb, pinfo,
+ global_data,
+ offset, ssh_tree, is_response,
+ &version, &need_desegmentation);
+
+ if (!need_desegmentation) {
+ peer_data->frame_version_end = pinfo->fd->num;
+ global_data->version = version;
+ }
+ } else {
+ switch(version) {
+
+ case SSH_VERSION_UNKNOWN:
+ offset = ssh_dissect_encrypted_packet(tvb, pinfo,
+ &global_data->peer_data[is_response], offset, ssh_tree);
+ break;
+
+ case SSH_VERSION_1:
+ offset = ssh_dissect_ssh1(tvb, pinfo, global_data,
+ offset, ssh_tree, is_response,
+ &need_desegmentation);
+ break;
+
+ case SSH_VERSION_2:
+ offset = ssh_dissect_ssh2(tvb, pinfo, global_data,
+ offset, ssh_tree, is_response,
+ &need_desegmentation);
+ break;
+ }
+ }
+
+ if (need_desegmentation)
+ return;
+ if (offset <= last_offset)
+ THROW(ReportedBoundsError);
+ }
+
+ col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client");
}
static int
ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_flow_data *global_data,
- int offset, proto_tree *tree, int is_response,
- gboolean *need_desegmentation)
+ struct ssh_flow_data *global_data,
+ int offset, proto_tree *tree, int is_response,
+ gboolean *need_desegmentation)
{
- proto_item *ssh2_tree=NULL;
-
- struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
-
- if (tree) {
- wmem_strbuf_t *title=wmem_strbuf_new(wmem_packet_scope(), "SSH Version 2");
-
- if (peer_data->enc || peer_data->mac || peer_data->comp) {
- wmem_strbuf_append_printf(title, " (");
- if (peer_data->enc)
- wmem_strbuf_append_printf(title, "encryption:%s%s",
- peer_data->enc,
- peer_data->mac || peer_data->comp
- ? " " : "");
- if (peer_data->mac)
- wmem_strbuf_append_printf(title, "mac:%s%s",
- peer_data->mac,
- peer_data->comp ? " " : "");
- if (peer_data->comp)
- wmem_strbuf_append_printf(title, "compression:%s",
- peer_data->comp);
- wmem_strbuf_append_printf(title, ")");
- }
-
- ssh2_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh2, NULL, wmem_strbuf_get_str(title));
- }
-
- if ((peer_data->frame_key_start == 0) ||
- ((peer_data->frame_key_start <= pinfo->fd->num) &&
- ((peer_data->frame_key_end == 0) || (pinfo->fd->num <= peer_data->frame_key_end)))) {
- offset = ssh_dissect_key_exchange(tvb, pinfo, global_data,
- offset, ssh2_tree, is_response,
- need_desegmentation);
- } else {
- offset = ssh_dissect_encrypted_packet(tvb, pinfo,
- &global_data->peer_data[is_response], offset, ssh2_tree);
- }
-
- return offset;
+ proto_item *ssh2_tree=NULL;
+
+ struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
+
+ if (tree) {
+ wmem_strbuf_t *title=wmem_strbuf_new(wmem_packet_scope(), "SSH Version 2");
+
+ if (peer_data->enc || peer_data->mac || peer_data->comp) {
+ wmem_strbuf_append_printf(title, " (");
+ if (peer_data->enc)
+ wmem_strbuf_append_printf(title, "encryption:%s%s",
+ peer_data->enc,
+ peer_data->mac || peer_data->comp
+ ? " " : "");
+ if (peer_data->mac)
+ wmem_strbuf_append_printf(title, "mac:%s%s",
+ peer_data->mac,
+ peer_data->comp ? " " : "");
+ if (peer_data->comp)
+ wmem_strbuf_append_printf(title, "compression:%s",
+ peer_data->comp);
+ wmem_strbuf_append_printf(title, ")");
+ }
+
+ ssh2_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh2, NULL, wmem_strbuf_get_str(title));
+ }
+
+ if ((peer_data->frame_key_start == 0) ||
+ ((peer_data->frame_key_start <= pinfo->fd->num) &&
+ ((peer_data->frame_key_end == 0) || (pinfo->fd->num <= peer_data->frame_key_end)))) {
+ offset = ssh_dissect_key_exchange(tvb, pinfo, global_data,
+ offset, ssh2_tree, is_response,
+ need_desegmentation);
+ } else {
+ offset = ssh_dissect_encrypted_packet(tvb, pinfo,
+ &global_data->peer_data[is_response], offset, ssh2_tree);
+ }
+
+ return offset;
}
static int
ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_flow_data *global_data,
- int offset, proto_tree *tree, int is_response,
- gboolean *need_desegmentation)
+ struct ssh_flow_data *global_data,
+ int offset, proto_tree *tree, int is_response,
+ gboolean *need_desegmentation)
{
- guint plen, padding_length, len;
- guint8 msg_code;
- guint remain_length;
-
- proto_item *ssh1_tree;
-
- struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
-
- ssh1_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh1, NULL, "SSH Version 1");
-
- /*
- * We use "tvb_ensure_length_remaining()" to make sure there
- * actually *is* data remaining.
- *
- * This means we're guaranteed that "remain_length" is positive.
- */
- remain_length = tvb_ensure_length_remaining(tvb, offset);
- /*
- * Can we do reassembly?
- */
- if (ssh_desegment && pinfo->can_desegment) {
- /*
- * Yes - would an SSH header starting at this offset be split
- * across segment boundaries?
- */
- if (remain_length < 4) {
- /*
- * Yes. Tell the TCP dissector where the data for
- * this message starts in the data it handed us and
- * that we need "some more data." Don't tell it
- * exactly how many bytes we need because if/when we
- * ask for even more (after the header) that will
- * break reassembly.
- */
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
- *need_desegmentation = TRUE;
- return offset;
- }
- }
- plen = tvb_get_ntohl(tvb, offset) ;
- padding_length = 8 - plen%8;
-
-
- if (ssh_desegment && pinfo->can_desegment) {
- if (plen+4+padding_length > remain_length) {
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = plen+padding_length - remain_length;
- *need_desegmentation = TRUE;
- return offset;
- }
- }
-
- if (plen >= 0xffff) {
- if (ssh1_tree && plen > 0) {
- proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
- offset, 4, plen, "Overly large length %x", plen);
- }
- plen = remain_length-4-padding_length;
- } else {
- if (ssh1_tree && plen > 0) {
- proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
- offset, 4, plen);
- }
- }
- offset+=4;
+ guint plen, padding_length, len;
+ guint8 msg_code;
+ guint remain_length;
+
+ proto_item *ssh1_tree;
+
+ struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
+
+ ssh1_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh1, NULL, "SSH Version 1");
+
+ /*
+ * We use "tvb_ensure_length_remaining()" to make sure there
+ * actually *is* data remaining.
+ *
+ * This means we're guaranteed that "remain_length" is positive.
+ */
+ remain_length = tvb_ensure_length_remaining(tvb, offset);
+ /*
+ * Can we do reassembly?
+ */
+ if (ssh_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - would an SSH header starting at this offset be split
+ * across segment boundaries?
+ */
+ if (remain_length < 4) {
+ /*
+ * Yes. Tell the TCP dissector where the data for
+ * this message starts in the data it handed us and
+ * that we need "some more data." Don't tell it
+ * exactly how many bytes we need because if/when we
+ * ask for even more (after the header) that will
+ * break reassembly.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+ plen = tvb_get_ntohl(tvb, offset) ;
+ padding_length = 8 - plen%8;
+
+
+ if (ssh_desegment && pinfo->can_desegment) {
+ if (plen+4+padding_length > remain_length) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = plen+padding_length - remain_length;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+
+ if (plen >= 0xffff) {
+ if (ssh1_tree && plen > 0) {
+ proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
+ offset, 4, plen, "Overly large length %x", plen);
+ }
+ plen = remain_length-4-padding_length;
+ } else {
+ if (ssh1_tree && plen > 0) {
+ proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
+ offset, 4, plen);
+ }
+ }
+ offset+=4;
/* padding length */
- if (tree) {
- proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
- offset, padding_length, padding_length);
- }
- offset += padding_length;
-
- /* msg_code */
- if ((peer_data->frame_key_start == 0) ||
- ((peer_data->frame_key_start >= pinfo->fd->num) && (pinfo->fd->num <= peer_data->frame_key_end))) {
- msg_code = tvb_get_guint8(tvb, offset);
-
- proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_NA);
- col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
- val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
- offset += 1;
- len = plen -1;
- if (!pinfo->fd->flags.visited) {
- if (peer_data->frame_key_start == 0)
- peer_data->frame_key_start = pinfo->fd->num;
- peer_data->frame_key_end = pinfo->fd->num;
- }
- } else {
- len = plen;
- col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
- }
- /* payload */
- if (ssh1_tree) {
- proto_tree_add_item(ssh1_tree, hf_ssh_payload,
- tvb, offset, len, ENC_NA);
- }
- offset+=len;
-
- return offset;
+ if (tree) {
+ proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
+ offset, padding_length, padding_length);
+ }
+ offset += padding_length;
+
+ /* msg_code */
+ if ((peer_data->frame_key_start == 0) ||
+ ((peer_data->frame_key_start >= pinfo->fd->num) && (pinfo->fd->num <= peer_data->frame_key_end))) {
+ msg_code = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_NA);
+ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
+ val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
+ offset += 1;
+ len = plen -1;
+ if (!pinfo->fd->flags.visited) {
+ if (peer_data->frame_key_start == 0)
+ peer_data->frame_key_start = pinfo->fd->num;
+ peer_data->frame_key_end = pinfo->fd->num;
+ }
+ } else {
+ len = plen;
+ col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
+ }
+ /* payload */
+ if (ssh1_tree) {
+ proto_tree_add_item(ssh1_tree, hf_ssh_payload,
+ tvb, offset, len, ENC_NA);
+ }
+ offset+=len;
+
+ return offset;
}
static int
ssh_tree_add_mpint(tvbuff_t *tvb, int offset, proto_tree *tree,
- int hf_ssh_mpint_selection)
+ int hf_ssh_mpint_selection)
{
- guint len = tvb_get_ntohl(tvb, offset);
- if (tree) {
- proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb,
- offset, 4, len);
- }
- offset+=4;
- if (tree) {
- proto_tree_add_item(tree, hf_ssh_mpint_selection,
- tvb, offset, len, ENC_NA);
- }
- return 4+len;
+ guint len = tvb_get_ntohl(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb,
+ offset, 4, len);
+ }
+ offset+=4;
+ if (tree) {
+ proto_tree_add_item(tree, hf_ssh_mpint_selection,
+ tvb, offset, len, ENC_NA);
+ }
+ return 4+len;
}
static int
ssh_tree_add_string(tvbuff_t *tvb, int offset, proto_tree *tree,
- int hf_ssh_string, int hf_ssh_string_length)
+ int hf_ssh_string, int hf_ssh_string_length)
{
- guint len = tvb_get_ntohl(tvb, offset);
- if (tree) {
- proto_tree_add_uint(tree, hf_ssh_string_length, tvb,
- offset, 4, len);
- }
- offset+=4;
- if (tree) {
- proto_tree_add_item(tree, hf_ssh_string,
- tvb, offset, len, ENC_NA);
- }
- return 4+len;
+ guint len = tvb_get_ntohl(tvb, offset);
+ if (tree) {
+ proto_tree_add_uint(tree, hf_ssh_string_length, tvb,
+ offset, 4, len);
+ }
+ offset+=4;
+ if (tree) {
+ proto_tree_add_item(tree, hf_ssh_string,
+ tvb, offset, len, ENC_NA);
+ }
+ return 4+len;
}
static int
ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_flow_data *global_data,
- int offset, proto_tree *tree, int is_response,
- gboolean *need_desegmentation)
+ struct ssh_flow_data *global_data,
+ int offset, proto_tree *tree, int is_response,
+ gboolean *need_desegmentation)
{
- guint plen, len;
- guint8 padding_length;
- guint remain_length;
- int last_offset=offset;
- guint msg_code;
-
- proto_item *ti;
- proto_item *key_ex_tree =NULL;
-
- struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
-
- /*
- * We use "tvb_ensure_length_remaining()" to make sure there
- * actually *is* data remaining.
- *
- * This means we're guaranteed that "remain_length" is positive.
- */
- remain_length = tvb_ensure_length_remaining(tvb, offset);
- /*
- * Can we do reassembly?
- */
- if (ssh_desegment && pinfo->can_desegment) {
- /*
- * Yes - would an SSH header starting at this offset
- * be split across segment boundaries?
- */
- if (remain_length < 4) {
- /*
- * Yes. Tell the TCP dissector where the data for
- * this message starts in the data it handed us and
- * that we need "some more data." Don't tell it
- * exactly how many bytes we need because if/when we
- * ask for even more (after the header) that will
- * break reassembly.
- */
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
- *need_desegmentation = TRUE;
- return offset;
- }
- }
- plen = tvb_get_ntohl(tvb, offset) ;
-
- if (ssh_desegment && pinfo->can_desegment) {
- if (plen +4 > remain_length) {
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = plen+4 - remain_length;
- *need_desegmentation = TRUE;
- return offset;
- }
- }
- /*
- * Need to check plen > 0x80000000 here
- */
-
- ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
- offset, 4, plen);
- if (plen >= 0xffff) {
- expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
- plen = remain_length-4;
- }
- offset+=4;
-
- /* padding length */
- padding_length = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length);
- offset += 1;
-
- key_ex_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_exchange, NULL, "Key Exchange");
-
- /* msg_code */
- msg_code = tvb_get_guint8(tvb, offset);
-
- if (msg_code >= 30 && msg_code < 40) {
- offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo, offset, key_ex_tree);
- } else {
- proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_NA);
- offset += 1;
-
- col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
- val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
-
- /* 16 bytes cookie */
- switch(msg_code)
- {
- case SSH_MSG_KEXINIT:
- if ((peer_data->frame_key_start == 0) || (peer_data->frame_key_start == pinfo->fd->num)) {
- offset = ssh_dissect_key_init(tvb, offset, key_ex_tree, is_response, global_data);
- peer_data->frame_key_start = pinfo->fd->num;
- }
- break;
- case SSH_MSG_NEWKEYS:
- if (peer_data->frame_key_end == 0) {
- peer_data->frame_key_end = pinfo->fd->num;
- ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].enc_proposals[is_response],
- global_data->peer_data[SERVER_PEER_DATA].enc_proposals[is_response],
- &peer_data->enc);
-
- /* some ciphers have their own MAC so the "negotiated" one is meaningless */
- if(peer_data->enc && (0 == strcmp(peer_data->enc, "aes128-gcm@openssh.com") ||
- 0 == strcmp(peer_data->enc, "aes256-gcm@openssh.com"))) {
- peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
- peer_data->mac_length = 16;
- peer_data->length_is_plaintext = 1;
- }
- else if(peer_data->enc && 0 == strcmp(peer_data->enc, "chacha20-poly1305@openssh.com")) {
- peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
- peer_data->mac_length = 16;
- }
- else {
- ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[is_response],
- global_data->peer_data[SERVER_PEER_DATA].mac_proposals[is_response],
- &peer_data->mac);
- ssh_set_mac_length(peer_data);
- }
-
- ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[is_response],
- global_data->peer_data[SERVER_PEER_DATA].comp_proposals[is_response],
- &peer_data->comp);
- }
- break;
- }
- }
-
- len = plen+4-padding_length-(offset-last_offset);
- if (len > 0) {
- proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA);
- }
- offset +=len;
-
- /* padding */
- proto_tree_add_item(key_ex_tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA);
- offset+= padding_length;
-
- return offset;
+ guint plen, len;
+ guint8 padding_length;
+ guint remain_length;
+ int last_offset=offset;
+ guint msg_code;
+
+ proto_item *ti;
+ proto_item *key_ex_tree =NULL;
+
+ struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
+
+ /*
+ * We use "tvb_ensure_length_remaining()" to make sure there
+ * actually *is* data remaining.
+ *
+ * This means we're guaranteed that "remain_length" is positive.
+ */
+ remain_length = tvb_ensure_length_remaining(tvb, offset);
+ /*
+ * Can we do reassembly?
+ */
+ if (ssh_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - would an SSH header starting at this offset
+ * be split across segment boundaries?
+ */
+ if (remain_length < 4) {
+ /*
+ * Yes. Tell the TCP dissector where the data for
+ * this message starts in the data it handed us and
+ * that we need "some more data." Don't tell it
+ * exactly how many bytes we need because if/when we
+ * ask for even more (after the header) that will
+ * break reassembly.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+ plen = tvb_get_ntohl(tvb, offset) ;
+
+ if (ssh_desegment && pinfo->can_desegment) {
+ if (plen +4 > remain_length) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = plen+4 - remain_length;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+ /*
+ * Need to check plen > 0x80000000 here
+ */
+
+ ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
+ offset, 4, plen);
+ if (plen >= 0xffff) {
+ expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
+ plen = remain_length-4;
+ }
+ offset+=4;
+
+ /* padding length */
+ padding_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length);
+ offset += 1;
+
+ key_ex_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_exchange, NULL, "Key Exchange");
+
+ /* msg_code */
+ msg_code = tvb_get_guint8(tvb, offset);
+
+ if (msg_code >= 30 && msg_code < 40) {
+ offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo, offset, key_ex_tree);
+ } else {
+ proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
+ val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
+
+ /* 16 bytes cookie */
+ switch(msg_code)
+ {
+ case SSH_MSG_KEXINIT:
+ if ((peer_data->frame_key_start == 0) || (peer_data->frame_key_start == pinfo->fd->num)) {
+ offset = ssh_dissect_key_init(tvb, offset, key_ex_tree, is_response, global_data);
+ peer_data->frame_key_start = pinfo->fd->num;
+ }
+ break;
+ case SSH_MSG_NEWKEYS:
+ if (peer_data->frame_key_end == 0) {
+ peer_data->frame_key_end = pinfo->fd->num;
+ ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].enc_proposals[is_response],
+ global_data->peer_data[SERVER_PEER_DATA].enc_proposals[is_response],
+ &peer_data->enc);
+
+ /* some ciphers have their own MAC so the "negotiated" one is meaningless */
+ if(peer_data->enc && (0 == strcmp(peer_data->enc, "aes128-gcm@openssh.com") ||
+ 0 == strcmp(peer_data->enc, "aes256-gcm@openssh.com"))) {
+ peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
+ peer_data->mac_length = 16;
+ peer_data->length_is_plaintext = 1;
+ }
+ else if(peer_data->enc && 0 == strcmp(peer_data->enc, "chacha20-poly1305@openssh.com")) {
+ peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
+ peer_data->mac_length = 16;
+ }
+ else {
+ ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[is_response],
+ global_data->peer_data[SERVER_PEER_DATA].mac_proposals[is_response],
+ &peer_data->mac);
+ ssh_set_mac_length(peer_data);
+ }
+
+ ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[is_response],
+ global_data->peer_data[SERVER_PEER_DATA].comp_proposals[is_response],
+ &peer_data->comp);
+ }
+ break;
+ }
+ }
+
+ len = plen+4-padding_length-(offset-last_offset);
+ if (len > 0) {
+ proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA);
+ }
+ offset +=len;
+
+ /* padding */
+ proto_tree_add_item(key_ex_tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA);
+ offset+= padding_length;
+
+ return offset;
}
static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
- packet_info *pinfo, int offset, proto_tree *tree)
+ packet_info *pinfo, int offset, proto_tree *tree)
{
- proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_NA);
- offset += 1;
+ proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_NA);
+ offset += 1;
- col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
- val_to_str(msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)"));
+ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
+ val_to_str(msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)"));
- switch (msg_code) {
- case SSH_MSG_KEXDH_INIT:
- offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e);
- break;
+ switch (msg_code) {
+ case SSH_MSG_KEXDH_INIT:
+ offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e);
+ break;
- case SSH_MSG_KEXDH_REPLY:
- offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length);
- offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f);
- offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length);
- break;
- }
+ case SSH_MSG_KEXDH_REPLY:
+ offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length);
+ offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f);
+ offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length);
+ break;
+ }
- return offset;
+ return offset;
}
static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
- packet_info *pinfo, int offset, proto_tree *tree)
+ packet_info *pinfo, int offset, proto_tree *tree)
{
- proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_NA);
- offset += 1;
-
- col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
- val_to_str(msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)"));
-
- switch (msg_code) {
- case SSH_MSG_KEX_DH_GEX_REQUEST_OLD:
- proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
- offset += 4;
- break;
-
- case SSH_MSG_KEX_DH_GEX_GROUP:
- offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_p);
- offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_g);
- break;
-
- case SSH_MSG_KEX_DH_GEX_INIT:
- offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e);
- break;
-
- case SSH_MSG_KEX_DH_GEX_REPLY:
- offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length);
- offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f);
- offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length);
- break;
-
- case SSH_MSG_KEX_DH_GEX_REQUEST:
- proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN);
- offset += 4;
- proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
- offset += 4;
- proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN);
- offset += 4;
- break;
- }
-
- return offset;
+ proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
+ val_to_str(msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)"));
+
+ switch (msg_code) {
+ case SSH_MSG_KEX_DH_GEX_REQUEST_OLD:
+ proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+
+ case SSH_MSG_KEX_DH_GEX_GROUP:
+ offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_p);
+ offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_g);
+ break;
+
+ case SSH_MSG_KEX_DH_GEX_INIT:
+ offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e);
+ break;
+
+ case SSH_MSG_KEX_DH_GEX_REPLY:
+ offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length);
+ offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f);
+ offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length);
+ break;
+
+ case SSH_MSG_KEX_DH_GEX_REQUEST:
+ proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ break;
+ }
+
+ return offset;
}
static int
ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_peer_data *peer_data,
- int offset, proto_tree *tree)
+ struct ssh_peer_data *peer_data,
+ int offset, proto_tree *tree)
{
- gint len;
- guint plen;
-
- len = tvb_reported_length_remaining(tvb, offset);
- col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
-
- if (tree) {
- gint encrypted_len = len;
-
- if (len > 4 && peer_data->length_is_plaintext) {
- plen = tvb_get_ntohl(tvb, offset) ;
- proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen);
- encrypted_len -= 4;
- }
- else if (len > 4) {
- proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA);
- encrypted_len -= 4;
- }
-
- if (peer_data->mac_length>0)
- encrypted_len -= peer_data->mac_length;
-
- proto_tree_add_item(tree, hf_ssh_encrypted_packet,
- tvb, offset+4, encrypted_len, ENC_NA);
-
- if (peer_data->mac_length>0)
- proto_tree_add_item(tree, hf_ssh_mac_string,
- tvb, offset+4+encrypted_len,
- peer_data->mac_length, ENC_NA);
- }
- offset+=len;
- return offset;
+ gint len;
+ guint plen;
+
+ len = tvb_reported_length_remaining(tvb, offset);
+ col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
+
+ if (tree) {
+ gint encrypted_len = len;
+
+ if (len > 4 && peer_data->length_is_plaintext) {
+ plen = tvb_get_ntohl(tvb, offset) ;
+ proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen);
+ encrypted_len -= 4;
+ }
+ else if (len > 4) {
+ proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA);
+ encrypted_len -= 4;
+ }
+
+ if (peer_data->mac_length>0)
+ encrypted_len -= peer_data->mac_length;
+
+ proto_tree_add_item(tree, hf_ssh_encrypted_packet,
+ tvb, offset+4, encrypted_len, ENC_NA);
+
+ if (peer_data->mac_length>0)
+ proto_tree_add_item(tree, hf_ssh_mac_string,
+ tvb, offset+4+encrypted_len,
+ peer_data->mac_length, ENC_NA);
+ }
+ offset+=len;
+ return offset;
}
static int
ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
- struct ssh_flow_data *global_data,
- int offset, proto_tree *tree, int is_response, guint * version,
- gboolean *need_desegmentation)
+ struct ssh_flow_data *global_data,
+ int offset, proto_tree *tree, int is_response, guint * version,
+ gboolean *need_desegmentation)
{
- guint remain_length;
- gint linelen, protolen;
-
- /*
- * If the first packet do not contain the banner,
- * it is dump in the middle of a flow or not a ssh at all
- */
- if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) {
- offset = ssh_dissect_encrypted_packet(tvb, pinfo,
- &global_data->peer_data[is_response], offset, tree);
- return offset;
- }
-
- if (!is_response) {
- if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) {
- *(version) = SSH_VERSION_2;
- } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) {
- *(version) = SSH_VERSION_2;
- } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) {
- *(version) = SSH_VERSION_1;
- }
- }
-
- /*
- * We use "tvb_ensure_length_remaining()" to make sure there
- * actually *is* data remaining.
- *
- * This means we're guaranteed that "remain_length" is positive.
- */
- remain_length = tvb_ensure_length_remaining(tvb, offset);
- /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
- */
- linelen = tvb_find_guint8(tvb, offset, -1, '\n');
-
- if (ssh_desegment && pinfo->can_desegment) {
- if (linelen == -1 || remain_length < (guint)linelen-offset) {
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = linelen-remain_length;
- *need_desegmentation = TRUE;
- return offset;
- }
- }
- if (linelen == -1) {
- /* XXX - reassemble across segment boundaries? */
- linelen = remain_length;
- protolen = linelen;
- } else {
- linelen = linelen - offset + 1;
-
- if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r')
- protolen = linelen - 2;
- else
- protolen = linelen - 1;
- }
-
- col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)",
- tvb_format_text(tvb, offset, protolen));
-
- proto_tree_add_item(tree, hf_ssh_protocol,
- tvb, offset, linelen, ENC_ASCII|ENC_NA);
- offset+=linelen;
- return offset;
+ guint remain_length;
+ gint linelen, protolen;
+
+ /*
+ * If the first packet do not contain the banner,
+ * it is dump in the middle of a flow or not a ssh at all
+ */
+ if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) {
+ offset = ssh_dissect_encrypted_packet(tvb, pinfo,
+ &global_data->peer_data[is_response], offset, tree);
+ return offset;
+ }
+
+ if (!is_response) {
+ if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) {
+ *(version) = SSH_VERSION_2;
+ } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) {
+ *(version) = SSH_VERSION_2;
+ } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) {
+ *(version) = SSH_VERSION_1;
+ }
+ }
+
+ /*
+ * We use "tvb_ensure_length_remaining()" to make sure there
+ * actually *is* data remaining.
+ *
+ * This means we're guaranteed that "remain_length" is positive.
+ */
+ remain_length = tvb_ensure_length_remaining(tvb, offset);
+ /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
+ */
+ linelen = tvb_find_guint8(tvb, offset, -1, '\n');
+
+ if (ssh_desegment && pinfo->can_desegment) {
+ if (linelen == -1 || remain_length < (guint)linelen-offset) {
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = linelen-remain_length;
+ *need_desegmentation = TRUE;
+ return offset;
+ }
+ }
+ if (linelen == -1) {
+ /* XXX - reassemble across segment boundaries? */
+ linelen = remain_length;
+ protolen = linelen;
+ } else {
+ linelen = linelen - offset + 1;
+
+ if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r')
+ protolen = linelen - 2;
+ else
+ protolen = linelen - 1;
+ }
+
+ col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)",
+ tvb_format_text(tvb, offset, protolen));
+
+ proto_tree_add_item(tree, hf_ssh_protocol,
+ tvb, offset, linelen, ENC_ASCII|ENC_NA);
+ offset+=linelen;
+ return offset;
}
static void
ssh_set_mac_length(struct ssh_peer_data *peer_data)
{
- char *size_str;
- guint size=0;
- char *mac_name = peer_data->mac;
- char *strip;
-
- if (!mac_name) return;
- mac_name = wmem_strdup(NULL, (const gchar *)mac_name);
- if (!mac_name) return;
-
- /* strip trailing "-etm@openssh.com" or "@openssh.com" */
- strip = strstr(mac_name, "-etm@openssh.com");
- if (strip) {
- peer_data->length_is_plaintext = 1;
- *strip = '\0';
- }
- else {
- strip = strstr(mac_name, "@openssh.com");
- if (strip) *strip = '\0';
- }
-
- if ((size_str=g_strrstr(mac_name, "-")) && ((size=atoi(size_str+1)))) {
- peer_data->mac_length = (size > 0) ? size / 8 : 0;
- }
- else if (strcmp(mac_name, "hmac-sha1") == 0) {
- peer_data->mac_length = 20;
- }
- else if (strcmp(mac_name, "hmac-md5") == 0) {
- peer_data->mac_length = 16;
- }
- else if (strcmp(mac_name, "hmac-ripemd160") == 0) {
- peer_data->mac_length = 20;
- }
- else if (strcmp(mac_name, "none") == 0) {
- peer_data->mac_length = 0;
- }
-
- wmem_free(NULL, mac_name);
+ char *size_str;
+ guint size=0;
+ char *mac_name = peer_data->mac;
+ char *strip;
+
+ if (!mac_name) return;
+ mac_name = wmem_strdup(NULL, (const gchar *)mac_name);
+ if (!mac_name) return;
+
+ /* strip trailing "-etm@openssh.com" or "@openssh.com" */
+ strip = strstr(mac_name, "-etm@openssh.com");
+ if (strip) {
+ peer_data->length_is_plaintext = 1;
+ *strip = '\0';
+ }
+ else {
+ strip = strstr(mac_name, "@openssh.com");
+ if (strip) *strip = '\0';
+ }
+
+ if ((size_str=g_strrstr(mac_name, "-")) && ((size=atoi(size_str+1)))) {
+ peer_data->mac_length = (size > 0) ? size / 8 : 0;
+ }
+ else if (strcmp(mac_name, "hmac-sha1") == 0) {
+ peer_data->mac_length = 20;
+ }
+ else if (strcmp(mac_name, "hmac-md5") == 0) {
+ peer_data->mac_length = 16;
+ }
+ else if (strcmp(mac_name, "hmac-ripemd160") == 0) {
+ peer_data->mac_length = 20;
+ }
+ else if (strcmp(mac_name, "none") == 0) {
+ peer_data->mac_length = 0;
+ }
+
+ wmem_free(NULL, mac_name);
}
static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data)
{
- const char *kex_name = global_data->kex;
+ const char *kex_name = global_data->kex;
- if (!kex_name) return;
+ if (!kex_name) return;
- if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 ||
- strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0)
- {
- global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex;
- }
+ if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 ||
+ strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0)
+ {
+ global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex;
+ }
}
static gint
ssh_gslist_compare_strings(gconstpointer a, gconstpointer b)
{
- if (a == NULL && b == NULL)
- return 0;
- if (a == NULL)
- return -1;
- if (b == NULL)
- return 1;
- return strcmp((const char*)a, (const char*)b);
+ if (a == NULL && b == NULL)
+ return 0;
+ if (a == NULL)
+ return -1;
+ if (b == NULL)
+ return 1;
+ return strcmp((const char*)a, (const char*)b);
}
/* expects that *result is NULL */
static void
ssh_choose_algo(gchar *client, gchar *server, gchar **result)
{
- gchar **server_strings=NULL;
- gchar **client_strings=NULL;
- gchar **step;
- GSList *server_list = NULL;
-
- if (!client || !server || !result || *result)
- return;
-
- server_strings = g_strsplit(server, ",", 0);
- for (step = server_strings; *step; step++) {
- server_list = g_slist_append(server_list, *step);
- }
-
- client_strings = g_strsplit(client, ",", 0);
- for (step = client_strings; *step; step++) {
- GSList *agreed;
- if ((agreed=g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
- *result = wmem_strdup(wmem_file_scope(), (const gchar *)agreed->data);
- break;
- }
- }
-
- g_strfreev(client_strings);
- g_slist_free(server_list);
- g_strfreev(server_strings);
+ gchar **server_strings=NULL;
+ gchar **client_strings=NULL;
+ gchar **step;
+ GSList *server_list = NULL;
+
+ if (!client || !server || !result || *result)
+ return;
+
+ server_strings = g_strsplit(server, ",", 0);
+ for (step = server_strings; *step; step++) {
+ server_list = g_slist_append(server_list, *step);
+ }
+
+ client_strings = g_strsplit(client, ",", 0);
+ for (step = client_strings; *step; step++) {
+ GSList *agreed;
+ if ((agreed=g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
+ *result = wmem_strdup(wmem_file_scope(), (const gchar *)agreed->data);
+ break;
+ }
+ }
+
+ g_strfreev(client_strings);
+ g_slist_free(server_list);
+ g_strfreev(server_strings);
}
static int
ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
- int is_response, struct ssh_flow_data *global_data)
+ int is_response, struct ssh_flow_data *global_data)
{
- int start_offset = offset;
+ int start_offset = offset;
- proto_item *tf;
+ proto_item *tf;
proto_tree *key_init_tree;
- struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
-
- key_init_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_init, &tf, "Algorithms");
- proto_tree_add_item(key_init_tree, hf_ssh_cookie,
- tvb, offset, 16, ENC_NA);
- offset += 16;
-
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms,
- &peer_data->kex_proposal);
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_server_host_key_algorithms_length,
- hf_ssh_server_host_key_algorithms, NULL);
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_encryption_algorithms_client_to_server_length,
- hf_ssh_encryption_algorithms_client_to_server,
- &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]);
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_encryption_algorithms_server_to_client_length,
- hf_ssh_encryption_algorithms_server_to_client,
- &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]);
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_mac_algorithms_client_to_server_length,
- hf_ssh_mac_algorithms_client_to_server,
- &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]);
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_mac_algorithms_server_to_client_length,
- hf_ssh_mac_algorithms_server_to_client,
- &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]);
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_compression_algorithms_client_to_server_length,
- hf_ssh_compression_algorithms_client_to_server,
- &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_compression_algorithms_server_to_client_length,
- hf_ssh_compression_algorithms_server_to_client,
- &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_languages_client_to_server_length,
- hf_ssh_languages_client_to_server, NULL);
- offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
- hf_ssh_languages_server_to_client_length,
- hf_ssh_languages_server_to_client, NULL);
-
- proto_tree_add_item(key_init_tree, hf_ssh_kex_first_packet_follows,
- tvb, offset, 1, ENC_BIG_ENDIAN);
- offset+=1;
-
- proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
- tvb, offset, 4, ENC_NA);
- offset+=4;
-
- if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal &&
- global_data->peer_data[SERVER_PEER_DATA].kex_proposal &&
- !global_data->kex)
- {
- /* Note: we're ignoring first_kex_packet_follows. */
- ssh_choose_algo(
- global_data->peer_data[CLIENT_PEER_DATA].kex_proposal,
- global_data->peer_data[SERVER_PEER_DATA].kex_proposal,
- &global_data->kex);
- ssh_set_kex_specific_dissector(global_data);
- }
-
- if (tf != NULL) {
- proto_item_set_len(tf, offset-start_offset);
- }
-
- return offset;
+ struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
+
+ key_init_tree=proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_init, &tf, "Algorithms");
+ proto_tree_add_item(key_init_tree, hf_ssh_cookie,
+ tvb, offset, 16, ENC_NA);
+ offset += 16;
+
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms,
+ &peer_data->kex_proposal);
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_server_host_key_algorithms_length,
+ hf_ssh_server_host_key_algorithms, NULL);
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_encryption_algorithms_client_to_server_length,
+ hf_ssh_encryption_algorithms_client_to_server,
+ &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]);
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_encryption_algorithms_server_to_client_length,
+ hf_ssh_encryption_algorithms_server_to_client,
+ &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]);
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_mac_algorithms_client_to_server_length,
+ hf_ssh_mac_algorithms_client_to_server,
+ &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]);
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_mac_algorithms_server_to_client_length,
+ hf_ssh_mac_algorithms_server_to_client,
+ &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]);
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_compression_algorithms_client_to_server_length,
+ hf_ssh_compression_algorithms_client_to_server,
+ &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_compression_algorithms_server_to_client_length,
+ hf_ssh_compression_algorithms_server_to_client,
+ &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_languages_client_to_server_length,
+ hf_ssh_languages_client_to_server, NULL);
+ offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
+ hf_ssh_languages_server_to_client_length,
+ hf_ssh_languages_server_to_client, NULL);
+
+ proto_tree_add_item(key_init_tree, hf_ssh_kex_first_packet_follows,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset+=1;
+
+ proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
+ tvb, offset, 4, ENC_NA);
+ offset+=4;
+
+ if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal &&
+ global_data->peer_data[SERVER_PEER_DATA].kex_proposal &&
+ !global_data->kex)
+ {
+ /* Note: we're ignoring first_kex_packet_follows. */
+ ssh_choose_algo(
+ global_data->peer_data[CLIENT_PEER_DATA].kex_proposal,
+ global_data->peer_data[SERVER_PEER_DATA].kex_proposal,
+ &global_data->kex);
+ ssh_set_kex_specific_dissector(global_data);
+ }
+
+ if (tf != NULL) {
+ proto_item_set_len(tf, offset-start_offset);
+ }
+
+ return offset;
}
static int
ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
- int hf_index_length, int hf_index_value, gchar **store)
+ int hf_index_length, int hf_index_value, gchar **store)
{
- guint32 len = tvb_get_ntohl(tvb, offset);
- proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len);
- offset += 4;
+ guint32 len = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len);
+ offset += 4;
- proto_tree_add_item(tree, hf_index_value, tvb, offset, len,
- ENC_ASCII);
- if (store)
- *store = tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII);
- offset += len;
+ proto_tree_add_item(tree, hf_index_value, tvb, offset, len,
+ ENC_ASCII);
+ if (store)
+ *store = tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII);
+ offset += len;
- return offset;
+ return offset;
}
void
proto_register_ssh(void)
{
- static hf_register_info hf[] = {
- { &hf_ssh_packet_length,
- { "Packet Length", "ssh.packet_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH packet length", HFILL }},
-
- { &hf_ssh_packet_length_encrypted,
- { "Packet Length (encrypted)", "ssh.packet_length_encrypted",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH packet length (encrypted)", HFILL }},
-
- { &hf_ssh_padding_length,
- { "Padding Length", "ssh.padding_length",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "SSH Packet Number", HFILL }},
-
- { &hf_ssh_msg_code,
- { "Message Code", "ssh.message_code",
- FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0,
- "SSH Message Code", HFILL }},
-
- { &hf_ssh2_msg_code,
- { "Message Code", "ssh.message_code",
- FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0,
- "SSH Message Code", HFILL }},
-
- { &hf_ssh2_kex_dh_msg_code,
- { "Message Code", "ssh.message_code",
- FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0,
- "SSH Message Code", HFILL }},
-
- { &hf_ssh2_kex_dh_gex_msg_code,
- { "Message Code", "ssh.message_code",
- FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0,
- "SSH Message Code", HFILL }},
-
- { &hf_ssh_mpint_g,
- { "DH base (G)", "ssh.dh.g",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH DH base (G)", HFILL }},
-
- { &hf_ssh_mpint_p,
- { "DH modulus (P)", "ssh.dh.p",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH DH modulus (P)", HFILL }},
-
- { &hf_ssh_mpint_e,
- { "DH client e", "ssh.dh.e",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH DH client e", HFILL }},
-
- { &hf_ssh_mpint_f,
- { "DH server f", "ssh.dh.f",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH DH server f", HFILL }},
-
- { &hf_ssh_mpint_length,
- { "Multi Precision Integer Length", "ssh.mpint_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH mpint length", HFILL }},
-
- { &hf_ssh_kexdh_host_key,
- { "KEX DH host key", "ssh.kexdh.host_key",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH KEX DH host key", HFILL }},
-
- { &hf_ssh_kexdh_h_sig,
- { "KEX DH H signature", "ssh.kexdh.h_sig",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH KEX DH H signature", HFILL }},
-
- { &hf_ssh_kexdh_host_key_length,
- { "KEX DH host key length", "ssh.kexdh.host_key_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH KEX DH host key length", HFILL }},
-
- { &hf_ssh_kexdh_h_sig_length,
- { "KEX DH H signature length", "ssh.kexdh.h_sig_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH KEX DH H signature length", HFILL }},
-
- { &hf_ssh_encrypted_packet,
- { "Encrypted Packet", "ssh.encrypted_packet",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH Protocol Packet", HFILL }},
-
- { &hf_ssh_protocol,
- { "Protocol", "ssh.protocol",
- FT_STRING, BASE_NONE, NULL, 0x0,
- "SSH Protocol", HFILL }},
-
- { &hf_ssh_cookie,
- { "Cookie", "ssh.cookie",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH Cookie", HFILL }},
-
- { &hf_ssh_kex_first_packet_follows,
- { "KEX First Packet Follows", "ssh.kex.first_packet_follows",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "SSH KEX Fist Packet Follows", HFILL }},
-
- { &hf_ssh_kex_reserved,
- { "Reserved", "ssh.kex.reserved",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH Protocol KEX Reserved", HFILL }},
-
- { &hf_ssh_dh_gex_min,
- { "DH GEX Min", "ssh.dh_gex.min",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH DH GEX Minimum", HFILL }},
-
- { &hf_ssh_dh_gex_nbits,
- { "DH GEX Number of Bits", "ssh.dh_gex.nbits",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH DH GEX Number of Bits", HFILL }},
-
- { &hf_ssh_dh_gex_max,
- { "DH GEX Max", "ssh.dh_gex.max",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH DH GEX Maximum", HFILL }},
-
- { &hf_ssh_payload,
- { "Payload", "ssh.payload",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH Payload", HFILL }},
-
- { &hf_ssh_padding_string,
- { "Padding String", "ssh.padding_string",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH Padding String", HFILL }},
-
- { &hf_ssh_mac_string,
- { "MAC", "ssh.mac",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "SSH Protocol Packet MAC", HFILL }},
-
- { &hf_ssh_kex_algorithms,
- { "kex_algorithms string", "ssh.kex_algorithms",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH kex_algorithms string", HFILL }},
-
- { &hf_ssh_server_host_key_algorithms,
- { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH server_host_key_algorithms string", HFILL }},
-
- { &hf_ssh_encryption_algorithms_client_to_server,
- { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH encryption_algorithms_client_to_server string", HFILL }},
-
- { &hf_ssh_encryption_algorithms_server_to_client,
- { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH encryption_algorithms_server_to_client string", HFILL }},
-
- { &hf_ssh_mac_algorithms_client_to_server,
- { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH mac_algorithms_client_to_server string", HFILL }},
-
- { &hf_ssh_mac_algorithms_server_to_client,
- { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH mac_algorithms_server_to_client string", HFILL }},
-
- { &hf_ssh_compression_algorithms_client_to_server,
- { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH compression_algorithms_client_to_server string", HFILL }},
-
- { &hf_ssh_compression_algorithms_server_to_client,
- { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH compression_algorithms_server_to_client string", HFILL }},
-
- { &hf_ssh_languages_client_to_server,
- { "languages_client_to_server string", "ssh.languages_client_to_server",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH languages_client_to_server string", HFILL }},
-
- { &hf_ssh_languages_server_to_client,
- { "languages_server_to_client string", "ssh.languages_server_to_client",
- FT_STRINGZ, BASE_NONE, NULL, 0x0,
- "SSH languages_server_to_client string", HFILL }},
-
- { &hf_ssh_kex_algorithms_length,
- { "kex_algorithms length", "ssh.kex_algorithms_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH kex_algorithms length", HFILL }},
-
- { &hf_ssh_server_host_key_algorithms_length,
- { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH server_host_key_algorithms length", HFILL }},
-
- { &hf_ssh_encryption_algorithms_client_to_server_length,
- { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH encryption_algorithms_client_to_server length", HFILL }},
-
- { &hf_ssh_encryption_algorithms_server_to_client_length,
- { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH encryption_algorithms_server_to_client length", HFILL }},
-
- { &hf_ssh_mac_algorithms_client_to_server_length,
- { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH mac_algorithms_client_to_server length", HFILL }},
-
- { &hf_ssh_mac_algorithms_server_to_client_length,
- { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH mac_algorithms_server_to_client length", HFILL }},
-
- { &hf_ssh_compression_algorithms_client_to_server_length,
- { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH compression_algorithms_client_to_server length", HFILL }},
-
- { &hf_ssh_compression_algorithms_server_to_client_length,
- { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH compression_algorithms_server_to_client length", HFILL }},
-
- { &hf_ssh_languages_client_to_server_length,
- { "languages_client_to_server length", "ssh.languages_client_to_server_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH languages_client_to_server length", HFILL }},
-
- { &hf_ssh_languages_server_to_client_length,
- { "languages_server_to_client length", "ssh.languages_server_to_client_length",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "SSH languages_server_to_client length", HFILL }},
- };
-
- static gint *ett[] = {
- &ett_ssh,
- &ett_key_exchange,
- &ett_ssh1,
- &ett_ssh2,
- &ett_key_init
- };
-
- static ei_register_info ei[] = {
- { &ei_ssh_packet_length, { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Overly large number", EXPFILL }},
- };
-
- module_t *ssh_module;
- expert_module_t *expert_ssh;
-
- proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh");
- proto_register_field_array(proto_ssh, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
- expert_ssh = expert_register_protocol(proto_ssh);
- expert_register_field_array(expert_ssh, ei, array_length(ei));
-
- ssh_module = prefs_register_protocol(proto_ssh, NULL);
- prefs_register_bool_preference(ssh_module, "desegment_buffers",
- "Reassemble SSH buffers spanning multiple TCP segments",
- "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
- "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
- &ssh_desegment);
-
- ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh);
+ static hf_register_info hf[] = {
+ { &hf_ssh_packet_length,
+ { "Packet Length", "ssh.packet_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH packet length", HFILL }},
+
+ { &hf_ssh_packet_length_encrypted,
+ { "Packet Length (encrypted)", "ssh.packet_length_encrypted",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH packet length (encrypted)", HFILL }},
+
+ { &hf_ssh_padding_length,
+ { "Padding Length", "ssh.padding_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "SSH Packet Number", HFILL }},
+
+ { &hf_ssh_msg_code,
+ { "Message Code", "ssh.message_code",
+ FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0,
+ "SSH Message Code", HFILL }},
+
+ { &hf_ssh2_msg_code,
+ { "Message Code", "ssh.message_code",
+ FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0,
+ "SSH Message Code", HFILL }},
+
+ { &hf_ssh2_kex_dh_msg_code,
+ { "Message Code", "ssh.message_code",
+ FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0,
+ "SSH Message Code", HFILL }},
+
+ { &hf_ssh2_kex_dh_gex_msg_code,
+ { "Message Code", "ssh.message_code",
+ FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0,
+ "SSH Message Code", HFILL }},
+
+ { &hf_ssh_mpint_g,
+ { "DH base (G)", "ssh.dh.g",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH DH base (G)", HFILL }},
+
+ { &hf_ssh_mpint_p,
+ { "DH modulus (P)", "ssh.dh.p",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH DH modulus (P)", HFILL }},
+
+ { &hf_ssh_mpint_e,
+ { "DH client e", "ssh.dh.e",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH DH client e", HFILL }},
+
+ { &hf_ssh_mpint_f,
+ { "DH server f", "ssh.dh.f",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH DH server f", HFILL }},
+
+ { &hf_ssh_mpint_length,
+ { "Multi Precision Integer Length", "ssh.mpint_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH mpint length", HFILL }},
+
+ { &hf_ssh_kexdh_host_key,
+ { "KEX DH host key", "ssh.kexdh.host_key",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH KEX DH host key", HFILL }},
+
+ { &hf_ssh_kexdh_h_sig,
+ { "KEX DH H signature", "ssh.kexdh.h_sig",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH KEX DH H signature", HFILL }},
+
+ { &hf_ssh_kexdh_host_key_length,
+ { "KEX DH host key length", "ssh.kexdh.host_key_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH KEX DH host key length", HFILL }},
+
+ { &hf_ssh_kexdh_h_sig_length,
+ { "KEX DH H signature length", "ssh.kexdh.h_sig_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH KEX DH H signature length", HFILL }},
+
+ { &hf_ssh_encrypted_packet,
+ { "Encrypted Packet", "ssh.encrypted_packet",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH Protocol Packet", HFILL }},
+
+ { &hf_ssh_protocol,
+ { "Protocol", "ssh.protocol",
+ FT_STRING, BASE_NONE, NULL, 0x0,
+ "SSH Protocol", HFILL }},
+
+ { &hf_ssh_cookie,
+ { "Cookie", "ssh.cookie",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH Cookie", HFILL }},
+
+ { &hf_ssh_kex_first_packet_follows,
+ { "KEX First Packet Follows", "ssh.kex.first_packet_follows",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "SSH KEX Fist Packet Follows", HFILL }},
+
+ { &hf_ssh_kex_reserved,
+ { "Reserved", "ssh.kex.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH Protocol KEX Reserved", HFILL }},
+
+ { &hf_ssh_dh_gex_min,
+ { "DH GEX Min", "ssh.dh_gex.min",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH DH GEX Minimum", HFILL }},
+
+ { &hf_ssh_dh_gex_nbits,
+ { "DH GEX Number of Bits", "ssh.dh_gex.nbits",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH DH GEX Number of Bits", HFILL }},
+
+ { &hf_ssh_dh_gex_max,
+ { "DH GEX Max", "ssh.dh_gex.max",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH DH GEX Maximum", HFILL }},
+
+ { &hf_ssh_payload,
+ { "Payload", "ssh.payload",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH Payload", HFILL }},
+
+ { &hf_ssh_padding_string,
+ { "Padding String", "ssh.padding_string",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH Padding String", HFILL }},
+
+ { &hf_ssh_mac_string,
+ { "MAC", "ssh.mac",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "SSH Protocol Packet MAC", HFILL }},
+
+ { &hf_ssh_kex_algorithms,
+ { "kex_algorithms string", "ssh.kex_algorithms",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH kex_algorithms string", HFILL }},
+
+ { &hf_ssh_server_host_key_algorithms,
+ { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH server_host_key_algorithms string", HFILL }},
+
+ { &hf_ssh_encryption_algorithms_client_to_server,
+ { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH encryption_algorithms_client_to_server string", HFILL }},
+
+ { &hf_ssh_encryption_algorithms_server_to_client,
+ { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH encryption_algorithms_server_to_client string", HFILL }},
+
+ { &hf_ssh_mac_algorithms_client_to_server,
+ { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH mac_algorithms_client_to_server string", HFILL }},
+
+ { &hf_ssh_mac_algorithms_server_to_client,
+ { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH mac_algorithms_server_to_client string", HFILL }},
+
+ { &hf_ssh_compression_algorithms_client_to_server,
+ { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH compression_algorithms_client_to_server string", HFILL }},
+
+ { &hf_ssh_compression_algorithms_server_to_client,
+ { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH compression_algorithms_server_to_client string", HFILL }},
+
+ { &hf_ssh_languages_client_to_server,
+ { "languages_client_to_server string", "ssh.languages_client_to_server",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH languages_client_to_server string", HFILL }},
+
+ { &hf_ssh_languages_server_to_client,
+ { "languages_server_to_client string", "ssh.languages_server_to_client",
+ FT_STRINGZ, BASE_NONE, NULL, 0x0,
+ "SSH languages_server_to_client string", HFILL }},
+
+ { &hf_ssh_kex_algorithms_length,
+ { "kex_algorithms length", "ssh.kex_algorithms_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH kex_algorithms length", HFILL }},
+
+ { &hf_ssh_server_host_key_algorithms_length,
+ { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH server_host_key_algorithms length", HFILL }},
+
+ { &hf_ssh_encryption_algorithms_client_to_server_length,
+ { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH encryption_algorithms_client_to_server length", HFILL }},
+
+ { &hf_ssh_encryption_algorithms_server_to_client_length,
+ { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH encryption_algorithms_server_to_client length", HFILL }},
+
+ { &hf_ssh_mac_algorithms_client_to_server_length,
+ { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH mac_algorithms_client_to_server length", HFILL }},
+
+ { &hf_ssh_mac_algorithms_server_to_client_length,
+ { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH mac_algorithms_server_to_client length", HFILL }},
+
+ { &hf_ssh_compression_algorithms_client_to_server_length,
+ { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH compression_algorithms_client_to_server length", HFILL }},
+
+ { &hf_ssh_compression_algorithms_server_to_client_length,
+ { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH compression_algorithms_server_to_client length", HFILL }},
+
+ { &hf_ssh_languages_client_to_server_length,
+ { "languages_client_to_server length", "ssh.languages_client_to_server_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH languages_client_to_server length", HFILL }},
+
+ { &hf_ssh_languages_server_to_client_length,
+ { "languages_server_to_client length", "ssh.languages_server_to_client_length",
+ FT_UINT32, BASE_DEC, NULL, 0x0,
+ "SSH languages_server_to_client length", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_ssh,
+ &ett_key_exchange,
+ &ett_ssh1,
+ &ett_ssh2,
+ &ett_key_init
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_ssh_packet_length, { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Overly large number", EXPFILL }},
+ };
+
+ module_t *ssh_module;
+ expert_module_t *expert_ssh;
+
+ proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh");
+ proto_register_field_array(proto_ssh, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+ expert_ssh = expert_register_protocol(proto_ssh);
+ expert_register_field_array(expert_ssh, ei, array_length(ei));
+
+ ssh_module = prefs_register_protocol(proto_ssh, NULL);
+ prefs_register_bool_preference(ssh_module, "desegment_buffers",
+ "Reassemble SSH buffers spanning multiple TCP segments",
+ "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
+ "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+ &ssh_desegment);
+
+ ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh);
}
void
proto_reg_handoff_ssh(void)
{
- dissector_add_uint("tcp.port", TCP_PORT_SSH, ssh_handle);
- dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle);
- dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle);
+ dissector_add_uint("tcp.port", TCP_PORT_SSH, ssh_handle);
+ dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle);
+ dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle);
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
- * c-basic-offset: 8
+ * c-basic-offset: 4
* tab-width: 8
- * indent-tabs-mode: t
+ * indent-tabs-mode: nil
* End:
*
- * vi: set shiftwidth=8 tabstop=8 noexpandtab:
- * :indentSize=8:tabSize=8:noTabs=false:
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
*/