Make sure a struct is completely initialized before we try to use it. Fixes
[obnox/wireshark/wip.git] / epan / dissectors / packet-ssh.c
1 /* packet-ssh.c
2  * Routines for ssh packet dissection
3  *
4  * Huagang XIE <huagang@intruvert.com>
5  * Kees Cook <kees@outflux.net>
6  *
7  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * Copied from packet-mysql.c
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  *
29  *
30  * Note:  support SSH v1 and v2  now.
31  *
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #if HAVE_STDLIB_H
39 #include <stdlib.h>
40 #endif
41 #include <string.h>
42 #include <glib.h>
43 #include <epan/packet.h>
44 #include <epan/conversation.h>
45 #include <epan/emem.h>
46
47 #include "packet-tcp.h"
48 #include <epan/reassemble.h>
49 #include <epan/prefs.h>
50
51 /* get from openssh ssh2.h */
52 #define SSH2_MSG_DISCONNECT                             1
53 #define SSH2_MSG_IGNORE                                 2
54 #define SSH2_MSG_UNIMPLEMENTED                          3
55 #define SSH2_MSG_DEBUG                                  4
56 #define SSH2_MSG_SERVICE_REQUEST                        5
57 #define SSH2_MSG_SERVICE_ACCEPT                         6
58
59 /* transport layer: alg negotiation */
60
61 #define SSH2_MSG_KEXINIT                                20
62 #define SSH2_MSG_NEWKEYS                                21
63
64 /* transport layer: kex specific messages, can be reused */
65
66 #define SSH2_MSG_KEXDH_INIT                             30
67 #define SSH2_MSG_KEXDH_REPLY                            31
68
69 /*
70 #define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD                 30
71 #define SSH2_MSG_KEX_DH_GEX_GROUP                       31
72 */
73 #define SSH2_MSG_KEX_DH_GEX_INIT                        32
74 #define SSH2_MSG_KEX_DH_GEX_REPLY                       33
75 #define SSH2_MSG_KEX_DH_GEX_REQUEST                     34
76
77 /* SSH Version 1 definition , from openssh ssh1.h */
78
79 #define SSH_MSG_NONE                            0       /* no message */
80 #define SSH_MSG_DISCONNECT                      1       /* cause (string) */
81 #define SSH_SMSG_PUBLIC_KEY                     2       /* ck,msk,srvk,hostk */
82 #define SSH_CMSG_SESSION_KEY                    3       /* key (BIGNUM) */
83 #define SSH_CMSG_USER                           4       /* user (string) */
84
85
86 #define SSH_VERSION_UNKNOWN     0
87 #define SSH_VERSION_1           1
88 #define SSH_VERSION_2           2
89
90 /* proto data */
91
92 struct ssh_pdu_data{
93         guint   counter;
94         guint   number;
95 };
96
97 struct ssh_flow_data {
98         guint   req_counter;
99         guint   rsp_counter;
100         guint   version;
101
102         gchar*  mac_client_request;
103         gchar*  mac_server_offer;
104         gchar*  mac;
105         gint    mac_length;
106
107         gchar*  enc_client_request;
108         gchar*  enc_server_offer;
109         gchar*  enc;
110
111         gchar*  comp_client_request;
112         gchar*  comp_server_offer;
113         gchar*  comp;
114 };
115
116 static int proto_ssh = -1;
117 static int hf_ssh_packet_length= -1;
118 static int hf_ssh_padding_length= -1;
119 static int hf_ssh_payload= -1;
120 static int hf_ssh_protocol= -1;
121 static int hf_ssh_dh_gex_min= -1;
122 static int hf_ssh_dh_gex_nbits= -1;
123 static int hf_ssh_dh_gex_max= -1;
124 static int hf_ssh_encrypted_packet= -1;
125 static int hf_ssh_padding_string= -1;
126 static int hf_ssh_mac_string= -1;
127 static int hf_ssh_msg_code = -1;
128 static int hf_ssh_cookie = -1;
129 static int hf_ssh_mpint_g= -1;
130 static int hf_ssh_mpint_p= -1;
131 static int hf_ssh_mpint_e= -1;
132 static int hf_ssh_mpint_f= -1;
133 static int hf_ssh_mpint_length= -1;
134 static int hf_ssh_kexdh_host_key= -1;
135 static int hf_ssh_kexdh_host_key_length= -1;
136 static int hf_ssh_kexdh_h_sig= -1;
137 static int hf_ssh_kexdh_h_sig_length= -1;
138 static int hf_ssh_kex_algorithms = -1;
139 static int hf_ssh_server_host_key_algorithms = -1;
140 static int hf_ssh_encryption_algorithms_client_to_server = -1;
141 static int hf_ssh_encryption_algorithms_server_to_client = -1;
142 static int hf_ssh_mac_algorithms_client_to_server=-1;
143 static int hf_ssh_mac_algorithms_server_to_client=-1;
144 static int hf_ssh_compression_algorithms_client_to_server=-1;
145 static int hf_ssh_compression_algorithms_server_to_client=-1;
146 static int hf_ssh_languages_client_to_server=-1;
147 static int hf_ssh_languages_server_to_client=-1;
148 static int hf_ssh_kex_algorithms_length= -1;
149 static int hf_ssh_server_host_key_algorithms_length= -1;
150 static int hf_ssh_encryption_algorithms_client_to_server_length= -1;
151 static int hf_ssh_encryption_algorithms_server_to_client_length= -1;
152 static int hf_ssh_mac_algorithms_client_to_server_length= -1;
153 static int hf_ssh_mac_algorithms_server_to_client_length= -1;
154 static int hf_ssh_compression_algorithms_client_to_server_length= -1;
155 static int hf_ssh_compression_algorithms_server_to_client_length= -1;
156 static int hf_ssh_languages_client_to_server_length= -1;
157 static int hf_ssh_languages_server_to_client_length= -1;
158 static int hf_ssh_kex_first_packet_follows = -1;
159 static int hf_ssh_kex_reserved = -1;
160
161 static gint ett_ssh = -1;
162 static gint ett_key_exchange= -1;
163 static gint ett_key_init= -1;
164 static gint ett_ssh1= -1;
165 static gint ett_ssh2= -1;
166
167 static gboolean ssh_desegment = TRUE;
168
169 #define TCP_PORT_SSH  22
170
171 static const value_string ssh2_msg_vals[] = {
172         {SSH2_MSG_DISCONNECT, "Disconnect"},
173         {SSH2_MSG_IGNORE, "Ignore"},
174         {SSH2_MSG_UNIMPLEMENTED, "Unimplemented"},
175         {SSH2_MSG_DEBUG, "Debug"},
176         {SSH2_MSG_SERVICE_REQUEST, "Service Request"},
177         {SSH2_MSG_SERVICE_ACCEPT, "Service Accept"},
178         {SSH2_MSG_KEXINIT, "Key Exchange Init"},
179         {SSH2_MSG_NEWKEYS, "New Keys"},
180         {SSH2_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init"},
181         {SSH2_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply"},
182         {SSH2_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman GEX Init"},
183         {SSH2_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman GEX Reply"},
184         {SSH2_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman GEX Request"},
185         { 0,          NULL }
186 };
187
188 static const value_string ssh1_msg_vals[] = {
189         {SSH_MSG_NONE,"No Message"},
190         {SSH_MSG_DISCONNECT, "Disconnect"},
191         {SSH_SMSG_PUBLIC_KEY,"Public Key"},
192         {SSH_CMSG_SESSION_KEY,"Session Key"},
193         {SSH_CMSG_USER,"User"},
194         {0, NULL}
195 };
196
197
198 static const value_string ssh_opcode_vals[] _U_ = {
199   { 0,          NULL }
200 };
201
202 static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
203                 int is_response,
204                 struct ssh_flow_data *global_data);
205
206 static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
207                 struct ssh_flow_data *global_data,
208                 int offset, proto_tree *tree,int is_response,
209                 int number, gboolean *need_desegmentation);
210 static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
211                 struct ssh_flow_data *global_data,
212                 int offset, proto_tree *tree,int is_response,
213                 int number, gboolean *need_desegmentation );
214 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
215                 struct ssh_flow_data *global_data,
216                 int offset, proto_tree *tree,int is_response,
217                 int number, gboolean *need_desegmentation );
218 static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
219                 struct ssh_flow_data *global_data,
220                 int offset, proto_tree *tree,int is_response,guint *version,
221                 gboolean *need_desegmentation);
222 static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
223                 struct ssh_flow_data *global_data,
224                 int offset, proto_tree *tree,int is_response);
225 proto_item * ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
226     gint start, gint length, gboolean little_endian);
227
228
229
230 static void
231 dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
232 {
233
234         proto_tree      *ssh_tree = NULL;
235         proto_item      *ti;
236         conversation_t  *conversation=NULL;
237         gint            remain_length;
238         int             last_offset;
239         guint           this_number,number;
240
241         int             offset = 0;
242
243         gboolean        is_response;
244         gboolean        is_newdata;
245         gboolean        need_desegmentation;
246         guint           version;
247
248         struct ssh_pdu_data *this_data=NULL;
249         struct ssh_flow_data *global_data=NULL;
250
251         is_newdata = FALSE;
252         this_data = p_get_proto_data(pinfo->fd, proto_ssh);
253
254         conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
255                 pinfo->srcport, pinfo->destport, 0);
256
257         if (!conversation) {
258                 /* create a new conversation */
259                 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
260                         pinfo->srcport, pinfo->destport, 0);
261         }
262
263         global_data = conversation_get_proto_data(conversation,proto_ssh);
264         if(!global_data ) {
265                 global_data = se_alloc0(sizeof(struct ssh_flow_data));
266                 global_data->version=SSH_VERSION_UNKNOWN;
267                 global_data->mac_length=-1;
268
269                 conversation_add_proto_data(conversation,proto_ssh,global_data);
270         }
271
272 /*
273  *      end of attaching data
274  */
275         if (pinfo->destport == pinfo->match_port) {
276                 is_response=FALSE;
277                 if(!this_data) {
278                         this_data = se_alloc(sizeof(struct ssh_pdu_data));
279                         this_data->counter = global_data->req_counter++;
280                         p_add_proto_data(pinfo->fd, proto_ssh, this_data);
281                         is_newdata = TRUE;
282                 }
283         }else {
284                 is_response=TRUE;
285                 if(!this_data) {
286                         this_data = se_alloc(sizeof(struct ssh_flow_data));
287                         this_data->counter = global_data->rsp_counter++;
288                         p_add_proto_data(pinfo->fd, proto_ssh, this_data);
289                         is_newdata = TRUE;
290                 }
291         }
292         if(tree) {
293                   ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, FALSE);
294                   ssh_tree = proto_item_add_subtree(ti, ett_ssh);
295         }
296         number = 0;
297
298         version = global_data->version;
299
300         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
301                 switch(version) {
302                         case SSH_VERSION_UNKNOWN:
303                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
304                                 break;
305                         case SSH_VERSION_1:
306                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
307                                 break;
308                         case SSH_VERSION_2:
309                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
310                                 break;
311
312                 }
313         }
314
315         if(this_data->counter != 0 && version == SSH_VERSION_UNKNOWN) {
316                 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
317                         global_data,
318                         offset,ssh_tree,is_response);
319                 return;
320         }
321
322         while((remain_length = tvb_reported_length_remaining(tvb,offset))> 0 ) {
323                 need_desegmentation = FALSE;
324                 last_offset = offset;
325                 this_number = this_data->counter+number;
326
327                 if(number > 1 && is_newdata) {
328                         /* update the this_data and flow_data */
329                         if(is_response) {
330                                 global_data->rsp_counter++;
331                         } else {
332                                 global_data->req_counter++;
333                         }
334                 }
335
336                 number++;
337                 if(this_number == 0)  {
338                         offset = ssh_dissect_protocol(tvb, pinfo,
339                                         global_data,
340                                         offset,ssh_tree, is_response,
341                                         &version, &need_desegmentation);
342                         if(!is_response) {
343                                 global_data->version= version;
344                         }
345                 } else {
346                         switch(version) {
347
348                         case SSH_VERSION_UNKNOWN:
349                                 /*
350                                  * We use "tvb_ensure_length_remaining()"
351                                  * to make sure there actually *is* data
352                                  * remaining.
353                                  *
354                                  * This means we're guaranteed that
355                                  * "remain_length" is positive.
356                                  */
357                                 remain_length = tvb_ensure_length_remaining(tvb,
358                                     offset);
359                                 proto_tree_add_text(ssh_tree, tvb, offset,
360                                                 remain_length,
361                                                 "Unknown SSH version data");
362                                 offset += remain_length;
363                                 break;
364
365                         case SSH_VERSION_1:
366                                 offset = ssh_dissect_ssh1(tvb, pinfo, global_data,
367                                                 offset,ssh_tree,is_response,this_number,
368                                                 &need_desegmentation);
369                                 break;
370
371                         case SSH_VERSION_2:
372                                 offset = ssh_dissect_ssh2(tvb, pinfo, global_data,
373                                                 offset,ssh_tree,is_response,this_number,
374                                                 &need_desegmentation);
375                                 break;
376                         }
377                 }
378
379                 if(offset <= last_offset)
380                         THROW(ReportedBoundsError);
381                 if(need_desegmentation) return;
382         }
383 }
384
385 static int
386 ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
387                 struct ssh_flow_data *global_data,
388                 int offset, proto_tree *tree,int is_response, int this_number,
389                 gboolean *need_desegmentation)
390 {
391         proto_item *ti;
392         proto_item *ssh2_tree=NULL;
393
394         if(tree) {
395                 GString *title=g_string_new("SSH Version 2");
396
397                 if (global_data->enc || global_data->mac || global_data->comp) {
398                         g_string_append_printf(title," (");
399                         if (global_data->enc)
400                                 g_string_append_printf(title,"encryption:%s%s",
401                                         global_data->enc,
402                                         global_data->mac || global_data->comp
403                                                 ? " " : "");
404                         if (global_data->mac)
405                                 g_string_append_printf(title,"mac:%s%s",
406                                         global_data->mac,
407                                         global_data->comp ? " " : "");
408                         if (global_data->comp)
409                                 g_string_append_printf(title,"compression:%s",
410                                         global_data->comp);
411                         g_string_append_printf(title,")");
412                 }
413
414                 ti=proto_tree_add_text(tree,tvb,offset,-1,title->str);
415                 ssh2_tree = proto_item_add_subtree(ti ,ett_ssh2);
416                 if (title) g_string_free(title,TRUE);
417         }
418
419         if((is_response && this_number > 3) || (!is_response && this_number>4)) {
420                 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
421                                 global_data,
422                                 offset,ssh2_tree,is_response);
423         } else {
424                 offset = ssh_dissect_key_exchange(tvb,pinfo, global_data,
425                         offset,ssh2_tree,is_response,this_number,
426                         need_desegmentation);
427         }
428
429         return offset;
430 }
431 static int
432 ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
433                 struct ssh_flow_data *global_data _U_,
434                 int offset, proto_tree *tree,int is_response,
435                 int number, gboolean *need_desegmentation)
436 {
437         guint   plen, padding_length,len;
438         guint8  msg_code;
439         guint   remain_length;
440
441         proto_item *ti;
442         proto_item *ssh1_tree =NULL;
443
444         if(tree) {
445                 ti=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
446                 ssh1_tree = proto_item_add_subtree(ti ,ett_ssh1);
447         }
448
449         /*
450          * We use "tvb_ensure_length_remaining()" to make sure there
451          * actually *is* data remaining.
452          *
453          * This means we're guaranteed that "remain_length" is positive.
454          */
455         remain_length = tvb_ensure_length_remaining(tvb,offset);
456         if (ssh_desegment && pinfo->can_desegment) {
457                 if(remain_length < 4) {
458                         pinfo->desegment_offset = offset;
459                         pinfo->desegment_len = 4-remain_length;
460                         *need_desegmentation = TRUE;
461                         return offset;
462                 }
463         }
464         plen = tvb_get_ntohl(tvb, offset) ;
465         padding_length  = 8 - plen%8;
466
467
468         if (ssh_desegment && pinfo->can_desegment) {
469                 if(plen+4+padding_length >  remain_length ) {
470                         pinfo->desegment_offset = offset;
471                         pinfo->desegment_len = plen+padding_length - remain_length;
472                         *need_desegmentation = TRUE;
473                         return offset;
474                 }
475         }
476
477         if (check_col(pinfo->cinfo, COL_INFO)) {
478                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ",
479                         is_response?"Server":"Client");
480         }
481
482         if(plen >= 0xffff) {
483                 if (ssh1_tree && plen > 0) {
484                           proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
485                             offset, 4, plen,"Overly large length %x",plen);
486                 }
487                 plen = remain_length-4-padding_length;
488         } else {
489                 if (ssh1_tree && plen > 0) {
490                           proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
491                             offset, 4, plen);
492                 }
493         }
494         offset+=4;
495 /* padding length */
496
497         if (tree) {
498                   proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
499                     offset, padding_length, padding_length);
500         }
501         offset += padding_length;
502 /*
503         if(tree) {
504                 tf=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
505                 ssh1_tree = proto_item_add_subtree(tf ,ett_ssh1);
506         }
507 */
508         /* msg_code */
509         if(number == 1 ) {
510                 msg_code = tvb_get_guint8(tvb, offset);
511                 if (tree) {
512                         proto_tree_add_uint_format(ssh1_tree, hf_ssh_msg_code, tvb,
513                                 offset, 1, msg_code,"Msg code: %s (%u)",
514                                 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"),
515                                 msg_code);
516                 }
517                 if (check_col(pinfo->cinfo, COL_INFO)) {
518                         col_append_str(pinfo->cinfo, COL_INFO,
519                         val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
520                 }
521                 offset += 1;
522                 len = plen -1;
523         } else {
524                 len = plen;
525                 if (check_col(pinfo->cinfo, COL_INFO)) {
526                         col_append_fstr(pinfo->cinfo, COL_INFO, "Encrypted packet len=%d", len);
527                 }
528         }
529         /* payload */
530         if (ssh1_tree ) {
531                 ssh_proto_tree_add_item(ssh1_tree, hf_ssh_payload,
532                     tvb, offset, len, FALSE);
533         }
534         offset+=len;
535
536         return offset;
537 }
538
539 static int
540 ssh_tree_add_mpint(tvbuff_t *tvb, int offset, proto_tree *tree,
541         int hf_ssh_mpint_selection)
542 {
543         guint len = tvb_get_ntohl(tvb, offset);
544         if (tree) {
545                 proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb,
546                         offset, 4, len);
547         }
548         offset+=4;
549         if (tree) {
550                 ssh_proto_tree_add_item(tree, hf_ssh_mpint_selection,
551                         tvb, offset, len, FALSE);
552         }
553         return 4+len;
554 }
555
556 static int
557 ssh_tree_add_string(tvbuff_t *tvb, int offset, proto_tree *tree,
558         int hf_ssh_string, int hf_ssh_string_length)
559 {
560         guint len = tvb_get_ntohl(tvb, offset);
561         if (tree) {
562                 proto_tree_add_uint(tree, hf_ssh_string_length, tvb,
563                         offset, 4, len);
564         }
565         offset+=4;
566         if (tree) {
567                 ssh_proto_tree_add_item(tree, hf_ssh_string,
568                         tvb, offset, len, FALSE);
569         }
570         return 4+len;
571 }
572
573 static int
574 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
575                 struct ssh_flow_data *global_data,
576                 int offset, proto_tree *tree,int is_response,int number,
577                 gboolean *need_desegmentation)
578 {
579         guint   plen,len;
580         guint8  padding_length;
581         guint   remain_length;
582         int     last_offset=offset;
583         guint   msg_code;
584
585         proto_item *tf;
586         proto_item *key_ex_tree =NULL;
587
588         /*
589          * We use "tvb_ensure_length_remaining()" to make sure there
590          * actually *is* data remaining.
591          *
592          * This means we're guaranteed that "remain_length" is positive.
593          */
594         remain_length = tvb_ensure_length_remaining(tvb,offset);
595         if (ssh_desegment && pinfo->can_desegment) {
596                 if(remain_length < 4) {
597                         pinfo->desegment_offset = offset;
598                         pinfo->desegment_len = 4-remain_length;
599                         *need_desegmentation = TRUE;
600                         return offset;
601                 }
602         }
603         plen = tvb_get_ntohl(tvb, offset) ;
604
605         if (ssh_desegment && pinfo->can_desegment) {
606                 if(plen +4 >  remain_length ) {
607                         pinfo->desegment_offset = offset;
608                         pinfo->desegment_len = plen+4 - remain_length;
609                         *need_desegmentation = TRUE;
610                         return offset;
611                 }
612         }
613         /*
614          * Need to check plen > 0x80000000 here
615          */
616
617         if (check_col(pinfo->cinfo, COL_INFO)) {
618                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ",
619                         is_response?"Server":"Client");
620         }
621
622         if(plen >= 0xffff) {
623                 if (tree) {
624                         proto_tree_add_uint_format(tree, hf_ssh_packet_length, tvb,
625                                 offset, 4, plen,"Overly large number 0x%x",plen);
626                 }
627                 plen = remain_length-4;
628         } else {
629                 if (tree) {
630                         proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
631                                 offset, 4, plen);
632                 }
633         }
634         offset+=4;
635 /* padding length */
636         padding_length = tvb_get_guint8(tvb, offset);
637         if (tree) {
638                   proto_tree_add_uint(tree, hf_ssh_padding_length, tvb,
639                     offset, 1, padding_length);
640         }
641         offset += 1;
642
643         if(tree) {
644                 tf=proto_tree_add_text(tree,tvb,offset,-1,"Key Exchange");
645                 key_ex_tree = proto_item_add_subtree(tf ,ett_key_exchange);
646         }
647         /* msg_code */
648         msg_code = tvb_get_guint8(tvb, offset);
649         if (tree) {
650                   proto_tree_add_uint_format(key_ex_tree, hf_ssh_msg_code, tvb,
651                     offset, 1, msg_code,"Msg code: %s (%u)",
652                         val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"),
653                         msg_code);
654
655         }
656         if (check_col(pinfo->cinfo, COL_INFO)) {
657                 col_append_str(pinfo->cinfo, COL_INFO,
658                         val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
659         }
660         offset += 1;
661
662         /* 16 bytes cookie  */
663         if(number == 1) {
664                 offset = ssh_dissect_key_init(tvb, offset, key_ex_tree, is_response, global_data);
665         }
666         else {
667                 /* DH GEX Request (min/nbits/max) */
668                 if (msg_code == 34) {
669                         ssh_proto_tree_add_item(key_ex_tree, hf_ssh_dh_gex_min,
670                             tvb, offset, 4, FALSE);
671                         offset+=4;
672                         ssh_proto_tree_add_item(key_ex_tree, hf_ssh_dh_gex_nbits,
673                             tvb, offset, 4, FALSE);
674                         offset+=4;
675                         ssh_proto_tree_add_item(key_ex_tree, hf_ssh_dh_gex_max,
676                             tvb, offset, 4, FALSE);
677                         offset+=4;
678                 }
679                 /* DH Key Exchange Reply (g/p) */
680                 if (msg_code == 31) {
681                         offset+=ssh_tree_add_mpint(tvb,offset,key_ex_tree,hf_ssh_mpint_p);
682                         offset+=ssh_tree_add_mpint(tvb,offset,key_ex_tree,hf_ssh_mpint_g);
683                 }
684                 /* DH GEX Init (e) */
685                 if (msg_code == 32) {
686                         offset+=ssh_tree_add_mpint(tvb,offset,key_ex_tree,hf_ssh_mpint_e);
687                 }
688                 /* DH GEX Reply (f) */
689                 if (msg_code == 33) {
690                         offset+=ssh_tree_add_string(tvb,offset,key_ex_tree,hf_ssh_kexdh_host_key,hf_ssh_kexdh_host_key_length);
691                         offset+=ssh_tree_add_mpint(tvb,offset,key_ex_tree,hf_ssh_mpint_f);
692                         offset+=ssh_tree_add_string(tvb,offset,key_ex_tree,hf_ssh_kexdh_h_sig,hf_ssh_kexdh_h_sig_length);
693                 }
694         }
695
696         len = plen+4-padding_length-(offset-last_offset);
697         if (tree ) {
698                 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_payload,
699                     tvb, offset, len, FALSE);
700         }
701         offset +=len;
702
703         /* padding */
704         if(tree) {
705                 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_padding_string,
706                                 tvb, offset, padding_length, FALSE);
707         }
708         offset+= padding_length;
709
710         /* MAC , if there is still bytes, treat it as 16bytes MAC*/
711         if(msg_code == SSH2_MSG_KEX_DH_GEX_REPLY) {
712                 len = tvb_reported_length_remaining(tvb,offset);
713                 if(len == 16) {
714                         if(tree) {
715                                 proto_tree_add_item(key_ex_tree, hf_ssh_mac_string,
716                                         tvb, offset, len , FALSE);
717                         }
718                         offset+=len;
719                 }
720         }
721
722         return offset;
723 }
724 static int
725 ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
726                 struct ssh_flow_data *global_data,
727                 int offset, proto_tree *tree,int is_response)
728 {
729         gint len;
730
731         len = tvb_reported_length_remaining(tvb,offset);
732         if (check_col(pinfo->cinfo, COL_INFO)) {
733                 col_add_fstr(pinfo->cinfo, COL_INFO, "Encrypted %s packet len=%d",
734                         is_response?"response":"request",len);
735         }
736         if (tree ) {
737                 gint encrypted_len = len;
738
739                 if (global_data && global_data->mac_length>0)
740                         encrypted_len -= global_data->mac_length;
741
742                 ssh_proto_tree_add_item(tree, hf_ssh_encrypted_packet,
743                                 tvb, offset, encrypted_len, FALSE);
744
745                 if (global_data && global_data->mac_length>0)
746                         ssh_proto_tree_add_item(tree, hf_ssh_mac_string,
747                                 tvb, offset+encrypted_len,
748                                 global_data->mac_length , FALSE);
749         }
750         offset+=len;
751         return offset;
752 }
753
754 static int
755 ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
756                 struct ssh_flow_data *global_data,
757                 int offset, proto_tree *tree, int is_response, guint * version,
758                 gboolean *need_desegmentation)
759 {
760         guint   remain_length;
761         gint    linelen, protolen;
762
763         /*
764          *  If the first packet do not contain the banner,
765          *  it is dump in the middle of a flow or not a ssh at all
766          */
767         if(tvb_strncaseeql(tvb,offset,"SSH-",4) != 0 ) {
768                 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
769                         global_data,
770                         offset,tree,is_response);
771                 return offset;
772         }
773
774         if(!is_response) {
775                 if(tvb_strncaseeql(tvb,offset,"SSH-2.",6) == 0 ) {
776                         *(version) = SSH_VERSION_2;
777                 }else if(tvb_strncaseeql(tvb,offset,"SSH-1.99-",9) == 0 ) {
778                         *(version) = SSH_VERSION_2;
779                 }else if(tvb_strncaseeql(tvb,offset,"SSH-1.",6) == 0 ) {
780                         *(version) = SSH_VERSION_1;
781                }
782         }
783
784         /*
785          * We use "tvb_ensure_length_remaining()" to make sure there
786          * actually *is* data remaining.
787          *
788          * This means we're guaranteed that "remain_length" is positive.
789          */
790         remain_length = tvb_ensure_length_remaining(tvb,offset);
791         /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
792          */
793         linelen = tvb_find_guint8(tvb, offset, -1, '\n');
794
795         if (ssh_desegment && pinfo->can_desegment) {
796                 if(linelen == -1 || remain_length < (guint)linelen-offset ) {
797                         pinfo->desegment_offset = offset;
798                         pinfo->desegment_len = linelen-remain_length;
799                         *need_desegmentation = TRUE;
800                         return offset;
801                 }
802         }
803         if(linelen == -1 ) {
804                 /* XXX - reassemble across segment boundaries? */
805                 linelen = remain_length;
806                 protolen = linelen;
807         } else {
808                 linelen = linelen - offset + 1;
809                 protolen = linelen - 1;
810         }
811
812         if (check_col(pinfo->cinfo, COL_INFO)) {
813                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Protocol: %s",
814                         is_response?"Server":"Client",
815                         tvb_format_text(tvb,offset,protolen));
816         }
817         if (tree ) {
818                 ssh_proto_tree_add_item(tree, hf_ssh_protocol,
819                                 tvb, offset, linelen, FALSE);
820         }
821         offset+=linelen;
822         return offset;
823 }
824
825 #define SSH_PROPOSAL(item)\
826         { &hf_ssh_ ## item, &hf_ssh_ ## item ## _length }
827
828 static struct {
829         int *value, *length;
830 } ssh_proposals[] = {
831         SSH_PROPOSAL(kex_algorithms),
832         SSH_PROPOSAL(server_host_key_algorithms),
833         SSH_PROPOSAL(encryption_algorithms_client_to_server),
834         SSH_PROPOSAL(encryption_algorithms_server_to_client),
835         SSH_PROPOSAL(mac_algorithms_client_to_server),
836         SSH_PROPOSAL(mac_algorithms_server_to_client),
837         SSH_PROPOSAL(compression_algorithms_client_to_server),
838         SSH_PROPOSAL(compression_algorithms_server_to_client),
839         SSH_PROPOSAL(languages_client_to_server),
840         SSH_PROPOSAL(languages_server_to_client),
841         {NULL, NULL}
842 };
843
844 static void
845 ssh_set_mac_length(struct ssh_flow_data *global_data, gchar *mac_name)
846 {
847         char *size_str;
848         guint size=0;
849
850         if (!global_data || !mac_name) return;
851
852         if ((size_str=g_strrstr(mac_name,"-")) && ((size=atoi(size_str+1)))) {
853                 global_data->mac_length = size;
854         }
855         else if (strcmp(mac_name,"hmac-sha1") == 0) {
856                 global_data->mac_length = 20;
857         }
858         else if (strcmp(mac_name,"hmac-md5") == 0) {
859                 global_data->mac_length = 12;
860         }
861         else if (strcmp(mac_name,"none") == 0) {
862                 global_data->mac_length = 0;
863         }
864 }
865
866 static gint
867 ssh_gslist_compare_strings(gconstpointer a, gconstpointer b)
868 {
869         if (a == NULL && b == NULL)
870                 return 0;
871         if (a == NULL)
872                 return -1;
873         if (b == NULL)
874                 return 1;
875         return strcmp((char*)a,(char*)b);
876 }
877
878 /* expects that *result is NULL */
879 static void
880 ssh_choose_algo(gchar *client, gchar *server, gchar **result)
881 {
882         gchar **server_strings=NULL;
883         gchar **client_strings=NULL;
884         gchar **step;
885         GSList* server_list = NULL;
886
887         if (!client || !server || !result || *result)
888                 return;
889
890         server_strings = g_strsplit(server,",",0);
891         for (step = server_strings; *step; step++) {
892                 server_list = g_slist_append(server_list, *step);
893         }
894
895         client_strings = g_strsplit(client,",",0);
896         for (step = client_strings; *step; step++) {
897                 GSList *agreed;
898                 if ((agreed=g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
899                         *result = se_strdup(agreed->data);
900                         break;
901                 }
902         }
903
904         g_strfreev(client_strings);
905         g_slist_free(server_list);
906         g_strfreev(server_strings);
907 }
908
909 static void
910 ssh_evaluate_negotiation(tvbuff_t *tvb, int offset, int len,
911                          int hf_value, int hf_client, int hf_server,
912                          gchar **client, gchar **server, gchar **agreed)
913 {
914         if (!tvb || !client || !server || !agreed) return;
915
916         if (hf_value == hf_client && !*client) {
917                 *client = se_strdup(tvb_get_ephemeral_string(tvb, offset, len));
918         }
919
920         if (hf_value == hf_server && !*server) {
921                 *server = se_strdup(tvb_get_ephemeral_string(tvb, offset, len));
922         }
923
924         if (*client && *server && !*agreed) {
925                 ssh_choose_algo(*client, *server, agreed);
926         }
927 }
928
929 static int
930 ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
931                 int is_response _U_,
932                 struct ssh_flow_data *global_data )
933 {
934         guint   len;
935         int     i;
936         int start_offset = offset;
937
938         proto_item *tf = NULL;
939         proto_item *key_init_tree=NULL;
940
941         if (tree) {
942                 tf=proto_tree_add_text(tree,tvb,offset,-1,"Algorithms");
943                 key_init_tree = proto_item_add_subtree(tf, ett_key_init);
944                 proto_tree_add_item(key_init_tree, hf_ssh_cookie,
945                     tvb, offset, 16, FALSE);
946         }
947         offset += 16;
948
949         for (i = 0; ssh_proposals[i].value; i++) {
950                 len = tvb_get_ntohl(tvb, offset);
951                 if (key_init_tree) {
952                         proto_tree_add_uint(key_init_tree,
953                                 *ssh_proposals[i].length, tvb, offset, 4, len);
954                 }
955                 offset+=4;
956                 if (key_init_tree) {
957                         ssh_proto_tree_add_item(key_init_tree,
958                                 *ssh_proposals[i].value, tvb, offset, len, FALSE);
959                 }
960                 /* record negotiations */
961                 if (global_data) {
962                         /* figure out MAC */
963                         ssh_evaluate_negotiation(tvb, offset, len,
964                                                  *ssh_proposals[i].value,
965                                                  hf_ssh_mac_algorithms_client_to_server,
966                                                  hf_ssh_mac_algorithms_server_to_client,
967                                                  &global_data->mac_client_request,
968                                                  &global_data->mac_server_offer,
969                                                  &global_data->mac);
970                         if (global_data->mac && global_data->mac_length<0)
971                                 ssh_set_mac_length(global_data, global_data->mac);
972
973                         /* figure out Encryption */
974                         ssh_evaluate_negotiation(tvb, offset, len,
975                                                  *ssh_proposals[i].value,
976                                                  hf_ssh_encryption_algorithms_client_to_server,
977                                                  hf_ssh_encryption_algorithms_server_to_client,
978                                                  &global_data->enc_client_request,
979                                                  &global_data->enc_server_offer,
980                                                  &global_data->enc);
981
982                         /* figure out Compression */
983                         ssh_evaluate_negotiation(tvb, offset, len,
984                                                  *ssh_proposals[i].value,
985                                                  hf_ssh_compression_algorithms_client_to_server,
986                                                  hf_ssh_compression_algorithms_server_to_client,
987                                                  &global_data->comp_client_request,
988                                                  &global_data->comp_server_offer,
989                                                  &global_data->comp);
990                 }
991
992                 offset+=len;
993         }
994
995         ssh_proto_tree_add_item(key_init_tree, hf_ssh_kex_first_packet_follows,
996             tvb, offset, 1, FALSE);
997         offset+=1;
998
999         ssh_proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
1000             tvb, offset, 4, FALSE);
1001         offset+=4;
1002
1003         if (tf != NULL) {
1004                 proto_item_set_len(tf, offset-start_offset);
1005         }
1006
1007         return offset;
1008 }
1009 proto_item *
1010 ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1011     gint start, gint length, gboolean little_endian)
1012 {
1013         if (tree && length <0xffff && length > 0) {
1014                 return proto_tree_add_item(tree, hfindex, tvb, start, length,little_endian);
1015         }
1016         return NULL;
1017 }
1018
1019 void
1020 proto_register_ssh(void)
1021 {
1022   static hf_register_info hf[] = {
1023     { &hf_ssh_packet_length,
1024       { "Packet Length",      "ssh.packet_length",
1025         FT_UINT32, BASE_DEC, NULL,  0x0,
1026         "SSH packet length", HFILL }},
1027
1028     { &hf_ssh_padding_length,
1029       { "Padding Length",  "ssh.padding_length",
1030         FT_UINT8, BASE_DEC, NULL, 0x0,
1031         "SSH Packet Number", HFILL }},
1032
1033     { &hf_ssh_msg_code,
1034       { "Message Code",  "ssh.message_code",
1035         FT_UINT8, BASE_DEC, NULL, 0x0,
1036         "SSH Message Code", HFILL }},
1037
1038     { &hf_ssh_mpint_g,
1039       { "DH base (G)",  "ssh.dh.g",
1040         FT_BYTES, BASE_NONE, NULL, 0x0,
1041         "SSH DH base (G)", HFILL }},
1042
1043     { &hf_ssh_mpint_p,
1044       { "DH modulus (P)",  "ssh.dh.p",
1045         FT_BYTES, BASE_NONE, NULL, 0x0,
1046         "SSH DH modulus (P)", HFILL }},
1047
1048     { &hf_ssh_mpint_e,
1049       { "DH client e",  "ssh.dh.e",
1050         FT_BYTES, BASE_NONE, NULL, 0x0,
1051         "SSH DH client e", HFILL }},
1052
1053     { &hf_ssh_mpint_f,
1054       { "DH server f",  "ssh.dh.f",
1055         FT_BYTES, BASE_NONE, NULL, 0x0,
1056         "SSH DH server f", HFILL }},
1057
1058     { &hf_ssh_mpint_length,
1059       { "Multi Precision Integer Length",      "ssh.mpint_length",
1060         FT_UINT32, BASE_DEC, NULL,  0x0,
1061         "SSH mpint length", HFILL }},
1062
1063     { &hf_ssh_kexdh_host_key,
1064       { "KEX DH host key",         "ssh.kexdh.host_key",
1065         FT_BYTES, BASE_NONE, NULL, 0x0,
1066         "SSH KEX DH host key", HFILL }},
1067
1068     { &hf_ssh_kexdh_h_sig,
1069       { "KEX DH H signature",         "ssh.kexdh.h_sig",
1070         FT_BYTES, BASE_NONE, NULL, 0x0,
1071         "SSH KEX DH H signature", HFILL }},
1072
1073     { &hf_ssh_kexdh_host_key_length,
1074       { "KEX DH host key length",         "ssh.kexdh.host_key_length",
1075         FT_UINT32, BASE_DEC, NULL, 0x0,
1076         "SSH KEX DH host key length", HFILL }},
1077
1078     { &hf_ssh_kexdh_h_sig_length,
1079       { "KEX DH H signature length",         "ssh.kexdh.h_sig_length",
1080         FT_UINT32, BASE_DEC, NULL, 0x0,
1081         "SSH KEX DH H signature length", HFILL }},
1082
1083     { &hf_ssh_encrypted_packet,
1084       { "Encrypted Packet",  "ssh.encrypted_packet",
1085         FT_BYTES, BASE_NONE, NULL, 0x0,
1086         "SSH Protocol Packet", HFILL }},
1087
1088     { &hf_ssh_protocol,
1089       { "Protocol",  "ssh.protocol",
1090         FT_STRING, BASE_NONE, NULL, 0x0,
1091         "SSH Protocol", HFILL }},
1092
1093     { &hf_ssh_cookie,
1094       { "Cookie",  "ssh.cookie",
1095         FT_BYTES, BASE_NONE, NULL, 0x0,
1096         "SSH Cookie", HFILL }},
1097
1098     { &hf_ssh_kex_first_packet_follows,
1099       { "KEX First Packet Follows",      "ssh.kex.first_packet_follows",
1100         FT_UINT8, BASE_DEC, NULL, 0x0,
1101         "SSH KEX Fist Packet Follows", HFILL }},
1102
1103     { &hf_ssh_kex_reserved,
1104       { "Reserved",  "ssh.kex.reserved",
1105         FT_BYTES, BASE_NONE, NULL, 0x0,
1106         "SSH Protocol KEX Reserved", HFILL }},
1107
1108     { &hf_ssh_dh_gex_min,
1109       { "DH GEX Min",  "ssh.dh_gex.min",
1110         FT_BYTES, BASE_NONE, NULL, 0x0,
1111         "SSH DH GEX Minimum", HFILL }},
1112
1113     { &hf_ssh_dh_gex_nbits,
1114       { "DH GEX Numbers of Bits",  "ssh.dh_gex.nbits",
1115         FT_BYTES, BASE_NONE, NULL, 0x0,
1116         "SSH DH GEX Number of Bits", HFILL }},
1117
1118     { &hf_ssh_dh_gex_max,
1119       { "DH GEX Max",  "ssh.dh_gex.max",
1120         FT_BYTES, BASE_NONE, NULL, 0x0,
1121         "SSH DH GEX Maximum", HFILL }},
1122
1123     { &hf_ssh_payload,
1124       { "Payload",  "ssh.payload",
1125         FT_BYTES, BASE_NONE, NULL, 0x0,
1126         "SSH Payload", HFILL }},
1127
1128     { &hf_ssh_padding_string,
1129       { "Padding String",  "ssh.padding_string",
1130         FT_BYTES, BASE_NONE, NULL, 0x0,
1131         "SSH Padding String", HFILL }},
1132
1133     { &hf_ssh_mac_string,
1134       { "MAC",  "ssh.mac",
1135         FT_BYTES, BASE_NONE, NULL, 0x0,
1136         "SSH Protocol Packet MAC", HFILL }},
1137
1138   { &hf_ssh_kex_algorithms,
1139       { "kex_algorithms string",         "ssh.kex_algorithms",
1140         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1141         "SSH kex_algorithms string", HFILL }},
1142
1143   { &hf_ssh_server_host_key_algorithms,
1144       { "server_host_key_algorithms string",         "ssh.server_host_key_algorithms",
1145         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1146         "SSH server_host_key_algorithms string", HFILL }},
1147
1148   { &hf_ssh_encryption_algorithms_client_to_server,
1149       { "encryption_algorithms_client_to_server string",         "ssh.encryption_algorithms_client_to_server",
1150         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1151         "SSH encryption_algorithms_client_to_server string", HFILL }},
1152
1153   { &hf_ssh_encryption_algorithms_server_to_client,
1154       { "encryption_algorithms_server_to_client string",         "ssh.encryption_algorithms_server_to_client",
1155         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1156         "SSH encryption_algorithms_server_to_client string", HFILL }},
1157
1158   { &hf_ssh_mac_algorithms_client_to_server,
1159       { "mac_algorithms_client_to_server string",         "ssh.mac_algorithms_client_to_server",
1160         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1161         "SSH mac_algorithms_client_to_server string", HFILL }},
1162
1163   { &hf_ssh_mac_algorithms_server_to_client,
1164       { "mac_algorithms_server_to_client string",         "ssh.mac_algorithms_server_to_client",
1165         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1166         "SSH mac_algorithms_server_to_client string", HFILL }},
1167
1168   { &hf_ssh_compression_algorithms_client_to_server,
1169       { "compression_algorithms_client_to_server string",         "ssh.compression_algorithms_client_to_server",
1170         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1171         "SSH compression_algorithms_client_to_server string", HFILL }},
1172
1173   { &hf_ssh_compression_algorithms_server_to_client,
1174       { "compression_algorithms_server_to_client string",         "ssh.compression_algorithms_server_to_client",
1175         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1176         "SSH compression_algorithms_server_to_client string", HFILL }},
1177
1178   { &hf_ssh_languages_client_to_server,
1179       { "languages_client_to_server string",         "ssh.languages_client_to_server",
1180         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1181         "SSH languages_client_to_server string", HFILL }},
1182
1183   { &hf_ssh_languages_server_to_client,
1184       { "languages_server_to_client string",         "ssh.languages_server_to_client",
1185         FT_STRINGZ, BASE_NONE, NULL, 0x0,
1186         "SSH languages_server_to_client string", HFILL }},
1187
1188   { &hf_ssh_kex_algorithms_length,
1189       { "kex_algorithms length",         "ssh.kex_algorithms_length",
1190         FT_UINT32, BASE_DEC, NULL, 0x0,
1191         "SSH kex_algorithms length", HFILL }},
1192
1193   { &hf_ssh_server_host_key_algorithms_length,
1194       { "server_host_key_algorithms length",         "ssh.server_host_key_algorithms_length",
1195         FT_UINT32, BASE_DEC, NULL, 0x0,
1196         "SSH server_host_key_algorithms length", HFILL }},
1197
1198   { &hf_ssh_encryption_algorithms_client_to_server_length,
1199       { "encryption_algorithms_client_to_server length",         "ssh.encryption_algorithms_client_to_server_length",
1200         FT_UINT32, BASE_DEC, NULL, 0x0,
1201         "SSH encryption_algorithms_client_to_server length", HFILL }},
1202
1203   { &hf_ssh_encryption_algorithms_server_to_client_length,
1204       { "encryption_algorithms_server_to_client length",         "ssh.encryption_algorithms_server_to_client_length",
1205         FT_UINT32, BASE_DEC, NULL, 0x0,
1206         "SSH encryption_algorithms_server_to_client length", HFILL }},
1207
1208   { &hf_ssh_mac_algorithms_client_to_server_length,
1209       { "mac_algorithms_client_to_server length",         "ssh.mac_algorithms_client_to_server_length",
1210         FT_UINT32, BASE_DEC, NULL, 0x0,
1211         "SSH mac_algorithms_client_to_server length", HFILL }},
1212
1213   { &hf_ssh_mac_algorithms_server_to_client_length,
1214       { "mac_algorithms_server_to_client length",         "ssh.mac_algorithms_server_to_client_length",
1215         FT_UINT32, BASE_DEC, NULL, 0x0,
1216         "SSH mac_algorithms_server_to_client length", HFILL }},
1217
1218   { &hf_ssh_compression_algorithms_client_to_server_length,
1219       { "compression_algorithms_client_to_server length",         "ssh.compression_algorithms_client_to_server_length",
1220         FT_UINT32, BASE_DEC, NULL, 0x0,
1221         "SSH compression_algorithms_client_to_server length", HFILL }},
1222
1223   { &hf_ssh_compression_algorithms_server_to_client_length,
1224       { "compression_algorithms_server_to_client length",         "ssh.compression_algorithms_server_to_client_length",
1225         FT_UINT32, BASE_DEC, NULL, 0x0,
1226         "SSH compression_algorithms_server_to_client length", HFILL }},
1227
1228   { &hf_ssh_languages_client_to_server_length,
1229       { "languages_client_to_server length",         "ssh.languages_client_to_server_length",
1230         FT_UINT32, BASE_DEC, NULL, 0x0,
1231         "SSH languages_client_to_server length", HFILL }},
1232
1233   { &hf_ssh_languages_server_to_client_length,
1234       { "languages_server_to_client length",         "ssh.languages_server_to_client_length",
1235         FT_UINT32, BASE_DEC, NULL, 0x0,
1236         "SSH languages_server_to_client length", HFILL }},
1237
1238
1239         };
1240         static gint *ett[] = {
1241                 &ett_ssh,
1242                 &ett_key_exchange,
1243                 &ett_ssh1,
1244                 &ett_ssh2,
1245                 &ett_key_init
1246         };
1247         module_t *ssh_module;
1248
1249         proto_ssh = proto_register_protocol("SSH Protocol",
1250                                        "SSH", "ssh");
1251          proto_register_field_array(proto_ssh, hf, array_length(hf));
1252         proto_register_subtree_array(ett, array_length(ett));
1253
1254         ssh_module = prefs_register_protocol(proto_ssh, NULL);
1255         prefs_register_bool_preference(ssh_module, "desegment_buffers",
1256                 "Reassemble SSH buffers spanning multiple TCP segments",
1257                 "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
1258             "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1259                 &ssh_desegment);
1260 }
1261
1262 void
1263 proto_reg_handoff_ssh(void)
1264 {
1265         dissector_handle_t ssh_handle;
1266
1267         ssh_handle = create_dissector_handle(dissect_ssh, proto_ssh);
1268
1269         dissector_add("tcp.port", TCP_PORT_SSH, ssh_handle);
1270 }