Update manuf to current IEEE entries.
[obnox/wireshark/wip.git] / packet-ssh.c
1 /* packet-ssh.c
2  * Routines for ssh packet dissection
3  *
4  * Huagang XIE <huagang@intruvert.com>
5  *
6  * $Id: packet-ssh.c,v 1.5 2003/01/30 08:11:20 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from packet-mysql.c
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  *
28  *
29  * Note:  support SSH v1 and v2  now. 
30  * 
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <glib.h>
38 #include <epan/packet.h>
39 #include <epan/conversation.h>
40
41 #include "packet-smb-common.h"
42 #include "packet-tcp.h"
43 #include "reassemble.h"
44 #include "prefs.h"
45
46 /* get from openssh ssh2.h */
47 #define SSH2_MSG_DISCONNECT                             1
48 #define SSH2_MSG_IGNORE                                 2
49 #define SSH2_MSG_UNIMPLEMENTED                          3
50 #define SSH2_MSG_DEBUG                                  4
51 #define SSH2_MSG_SERVICE_REQUEST                        5
52 #define SSH2_MSG_SERVICE_ACCEPT                         6
53
54 /* transport layer: alg negotiation */
55
56 #define SSH2_MSG_KEXINIT                                20
57 #define SSH2_MSG_NEWKEYS                                21
58
59 /* transport layer: kex specific messages, can be reused */
60
61 #define SSH2_MSG_KEXDH_INIT                             30
62 #define SSH2_MSG_KEXDH_REPLY                            31
63
64 /*
65 #define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD                 30
66 #define SSH2_MSG_KEX_DH_GEX_GROUP                       31
67 */
68 #define SSH2_MSG_KEX_DH_GEX_INIT                        32
69 #define SSH2_MSG_KEX_DH_GEX_REPLY                       33
70 #define SSH2_MSG_KEX_DH_GEX_REQUEST                     34
71
72 /* SSH Version 1 definition , from openssh ssh1.h */
73
74 #define SSH_MSG_NONE                            0       /* no message */
75 #define SSH_MSG_DISCONNECT                      1       /* cause (string) */
76 #define SSH_SMSG_PUBLIC_KEY                     2       /* ck,msk,srvk,hostk */
77 #define SSH_CMSG_SESSION_KEY                    3       /* key (BIGNUM) */
78 #define SSH_CMSG_USER                           4       /* user (string) */
79
80
81 #define SSH_VERSION_UNKNOWN     0
82 #define SSH_VERSION_1           1
83 #define SSH_VERSION_2           2
84
85 /* proto data */
86
87 struct ssh_pdu_data{
88         guint   counter;
89         guint   number;
90 };
91
92 struct ssh_flow_data {
93         guint   req_counter;
94         guint   rsp_counter;
95         guint   version;
96 };
97 static GMemChunk *ssh_this_data=NULL;
98 static GMemChunk *ssh_global_data = NULL;
99
100 static int proto_ssh = -1;
101 static int hf_ssh_packet_length= -1;
102 static int hf_ssh_padding_length= -1;
103 static int hf_ssh_payload= -1;
104 static int hf_ssh_protocol= -1;
105 static int hf_ssh_encrypted_packet= -1;
106 static int hf_ssh_padding_string= -1;
107 static int hf_ssh_mac_string= -1;
108 static int hf_ssh_msg_code = -1;
109 static int hf_ssh_cookie = -1;
110 static int hf_ssh_kex_algorithms = -1;
111 static int hf_ssh_server_host_key_algorithms = -1;
112 static int hf_ssh_encryption_algorithms_client_to_server = -1;
113 static int hf_ssh_encryption_algorithms_server_to_client = -1;
114 static int hf_ssh_mac_algorithms_client_to_server=-1;
115 static int hf_ssh_mac_algorithms_server_to_client=-1;
116 static int hf_ssh_compression_algorithms_client_to_server=-1;
117 static int hf_ssh_compression_algorithms_server_to_client=-1;
118 static int hf_ssh_languages_client_to_server=-1;
119 static int hf_ssh_languages_server_to_client=-1;
120 static int hf_ssh_kex_algorithms_length= -1;
121 static int hf_ssh_server_host_key_algorithms_length= -1;
122 static int hf_ssh_encryption_algorithms_client_to_server_length= -1;
123 static int hf_ssh_encryption_algorithms_server_to_client_length= -1;
124 static int hf_ssh_mac_algorithms_client_to_server_length= -1;
125 static int hf_ssh_mac_algorithms_server_to_client_length= -1;
126 static int hf_ssh_compression_algorithms_client_to_server_length= -1;
127 static int hf_ssh_compression_algorithms_server_to_client_length= -1;
128 static int hf_ssh_languages_client_to_server_length= -1;
129 static int hf_ssh_languages_server_to_client_length= -1;
130
131 static gint ett_ssh = -1;
132 static gint ett_key_exchange= -1;
133 static gint ett_key_init= -1;
134 static gint ett_ssh1= -1;
135 static gint ett_ssh2= -1;
136
137 static gboolean ssh_desegment = TRUE;
138
139 #define TCP_PORT_SSH  22 
140
141 static const value_string ssh2_msg_vals[] = {
142         {SSH2_MSG_DISCONNECT, "Disconnect"},
143         {SSH2_MSG_IGNORE, "Ignore"},
144         {SSH2_MSG_UNIMPLEMENTED, "Unimplemented"},
145         {SSH2_MSG_DEBUG, "Debug"}       ,
146         {SSH2_MSG_SERVICE_REQUEST,"Service Request"},
147         {SSH2_MSG_SERVICE_ACCEPT,"Service Accept"},
148         {SSH2_MSG_KEXINIT, "Key Exchange"},
149         {SSH2_MSG_NEWKEYS,"New Keys"},
150         {SSH2_MSG_KEXDH_INIT, "Key Init"},
151         {SSH2_MSG_KEXDH_REPLY,"Key Reply"},
152         {SSH2_MSG_KEX_DH_GEX_INIT,"Diffie-Hellman GEX Init"},   
153         {SSH2_MSG_KEX_DH_GEX_REPLY,"Diffie-Hellman GEX Reply"},
154         {SSH2_MSG_KEX_DH_GEX_REQUEST,"Diffie-Hellman GEX Request"},
155         { 0,          NULL }
156 };
157
158 static const value_string ssh1_msg_vals[] = {
159         {SSH_MSG_NONE,"No Message"},
160         {SSH_MSG_DISCONNECT, "Disconnect"},
161         {SSH_SMSG_PUBLIC_KEY,"Public Key"},
162         {SSH_CMSG_SESSION_KEY,"Session Key"},
163         {SSH_CMSG_USER,"User"},
164 };
165
166
167 static const value_string ssh_opcode_vals[] = {
168   { 0,          NULL }
169 };
170
171 static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree);
172
173 static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
174                 int offset, proto_tree *tree,int is_response,
175                 int number, gboolean *need_desegmentation);
176 static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo, 
177                 int offset, proto_tree *tree,int is_response,
178                 int number, gboolean *need_desegmentation );
179 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo, 
180                 int offset, proto_tree *tree,int is_response,
181                 int number, gboolean *need_desegmentation );
182 static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo, 
183                 int offset, proto_tree *tree,int is_response,int *version,
184                 gboolean *need_desegmentation);
185 static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
186                 int offset, proto_tree *tree,int is_response);
187 proto_item * ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
188     gint start, gint length, gboolean little_endian);
189
190 static void
191 ssh_init_protocol(void)
192 {
193         if (ssh_global_data)
194                 g_mem_chunk_destroy(ssh_global_data);
195         if (ssh_this_data)
196                 g_mem_chunk_destroy(ssh_this_data);
197
198         ssh_global_data = g_mem_chunk_new("ssh_global_datas",
199                                       sizeof(struct ssh_flow_data),
200                                       100* sizeof(struct ssh_flow_data), G_ALLOC_AND_FREE);
201         ssh_this_data = g_mem_chunk_new("ssh_pku_data",
202                                       sizeof(struct ssh_pdu_data),
203                                       100* sizeof(struct ssh_pdu_data), G_ALLOC_AND_FREE);
204
205 }
206
207 static void
208 dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
209 {
210
211         proto_tree      *ssh_tree = NULL;
212         proto_item      *ti;
213         conversation_t  *conversation=NULL;
214         guint           remain_length;
215         guint           last_offset;
216         guint           this_number,number;
217
218         int             offset = 0;
219
220         gboolean        is_response;
221         gboolean        is_newdata;
222         gboolean        need_desegmentation;
223         guint           version;
224
225         struct ssh_pdu_data *this_data=NULL;
226         struct ssh_flow_data *global_data=NULL;
227
228         is_newdata = FALSE;
229         this_data = p_get_proto_data(pinfo->fd, proto_ssh);
230
231         conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
232                 pinfo->srcport, pinfo->destport, 0);
233
234         if (!conversation) {
235                 /* create a new conversation */
236                 conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
237                         pinfo->srcport, pinfo->destport, 0);
238         }
239
240         global_data = conversation_get_proto_data(conversation,proto_ssh);
241         if(!global_data ) {
242                 global_data = g_mem_chunk_alloc(ssh_global_data);
243                 global_data->req_counter=0;
244                 global_data->rsp_counter=0;
245                 global_data->version=SSH_VERSION_UNKNOWN;
246                 conversation_add_proto_data(conversation,proto_ssh,global_data);
247         }
248
249 /*
250  *      end of attaching data
251  */     
252         if (pinfo->destport == pinfo->match_port) {
253                 is_response=FALSE;
254                 if(!this_data) {
255                         this_data = g_mem_chunk_alloc(ssh_this_data);
256                         this_data->counter = global_data->req_counter++;
257                         p_add_proto_data(pinfo->fd, proto_ssh, this_data);
258                         is_newdata = TRUE;
259                 }
260         }else {
261                 is_response=TRUE;
262                 if(!this_data) {
263                         this_data = g_mem_chunk_alloc(ssh_global_data);
264                         this_data->counter = global_data->rsp_counter++;
265                         p_add_proto_data(pinfo->fd, proto_ssh, this_data);
266                         is_newdata = TRUE;
267                 }
268         }
269         if(tree) {
270                   ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, FALSE);
271                   ssh_tree = proto_item_add_subtree(ti, ett_ssh);
272         }
273         number = 0;
274         
275         version = global_data->version;
276
277         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
278                 switch(version) {
279                         case SSH_VERSION_UNKNOWN:
280                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
281                                 break;
282                         case SSH_VERSION_1:
283                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
284                                 break;
285                         case SSH_VERSION_2:
286                                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
287                                 break;
288                         
289                 }
290         }
291
292         if(this_data->counter != 0 && version == SSH_VERSION_UNKNOWN) {
293                 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
294                         offset,ssh_tree,is_response);
295                 return;
296         }
297                         
298         while((remain_length = tvb_reported_length_remaining(tvb,offset))> 0 ) {
299                 need_desegmentation = FALSE;
300                 last_offset = offset;
301                 this_number = this_data->counter+number;
302
303                 if(number > 1 && is_newdata) {
304                         /* update the this_data and flow_data */
305                         if(is_response) {
306                                 global_data->rsp_counter++;
307                         } else {
308                                 global_data->req_counter++;
309                         }
310                 }
311                                 
312                 number++;
313                 if(this_number == 0)  {
314                         offset = ssh_dissect_protocol(tvb, pinfo,
315                                         offset,ssh_tree, is_response,
316                                         &version, &need_desegmentation);
317                         if(!is_response) {
318                                 global_data->version= version;
319                         }
320                 } else {
321                         if(version == SSH_VERSION_1) {
322                                 offset = ssh_dissect_ssh1(tvb, pinfo,
323                                                 offset,ssh_tree,is_response,this_number, 
324                                                 &need_desegmentation);
325                         } else if(version == SSH_VERSION_2) {
326                                 offset = ssh_dissect_ssh2(tvb, pinfo,
327                                                 offset,ssh_tree,is_response,this_number,
328                                                 &need_desegmentation);
329                         }
330                 }
331
332                 if(need_desegmentation) return;
333         }
334 }
335
336 static int 
337 ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
338                 int offset, proto_tree *tree,int is_response, int this_number,
339                 gboolean *need_desegmentation)
340 {
341         proto_item *ti; 
342         proto_item *ssh2_tree=NULL;
343
344         if(tree) {
345                 ti=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 2");
346                 ssh2_tree = proto_item_add_subtree(ti ,ett_ssh2);
347         }
348         
349         if((is_response && this_number > 3) || (!is_response && this_number>4)) {
350                 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
351                                 offset,ssh2_tree,is_response);
352         } else {
353                 offset = ssh_dissect_key_exchange(tvb,pinfo,
354                         offset,ssh2_tree,is_response,this_number,
355                         need_desegmentation);
356         }
357
358         return offset;
359 }
360 static int 
361 ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
362                 int offset, proto_tree *tree,int is_response, 
363                 int number, gboolean *need_desegmentation)
364 {
365         guint   plen, padding_length,len;
366         guint8  msg_code;
367         guint   remain_length=0;
368
369         proto_item *ti; 
370         proto_item *ssh1_tree =NULL;
371
372         if(tree) {
373                 ti=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
374                 ssh1_tree = proto_item_add_subtree(ti ,ett_ssh1);
375         }
376         
377         remain_length = tvb_reported_length_remaining(tvb,offset);
378         if (ssh_desegment && pinfo->can_desegment) {
379                 if(remain_length < 4) {
380                         pinfo->desegment_offset = offset;
381                         pinfo->desegment_len = 4-remain_length;
382                         *need_desegmentation = TRUE;
383                         return offset;
384                 }
385         }
386         plen = tvb_get_ntohl(tvb, offset) ;
387         padding_length  = 8 - plen%8;
388
389
390         if (ssh_desegment && pinfo->can_desegment) {
391                 if(plen+4+padding_length >  remain_length ) {
392                         pinfo->desegment_offset = offset;
393                         pinfo->desegment_len = plen+padding_length - remain_length;
394                         *need_desegmentation = TRUE;
395                         return offset;
396                 }
397         }
398
399         if (check_col(pinfo->cinfo, COL_INFO)) {
400                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ", 
401                         is_response?"Server":"Client");
402         }
403
404         if(plen >= 0xffff) {
405                 if (ssh1_tree && plen > 0) {
406                           proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
407                             offset, 4, plen,"Overly large length %x",plen);
408                 }
409                 plen = remain_length-4-padding_length;
410         } else {
411                 if (ssh1_tree && plen > 0) {
412                           proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
413                             offset, 4, plen);
414                 }
415         }
416         offset+=4;
417 /* padding length */
418
419         if (tree) {
420                   proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
421                     offset, padding_length, padding_length);
422         }
423         offset += padding_length;
424 /*
425         if(tree) {
426                 tf=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
427                 ssh1_tree = proto_item_add_subtree(tf ,ett_ssh1);
428         }
429 */
430         /* msg_code */
431         if(number == 1 ) {
432                 msg_code = tvb_get_guint8(tvb, offset);
433                 if (tree) {
434                         proto_tree_add_uint_format(ssh1_tree, hf_ssh_msg_code, tvb,
435                                 offset, 1, msg_code,"Msg code: %s (%u)",
436                                 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"),
437                                 msg_code);
438                 }
439                 if (check_col(pinfo->cinfo, COL_INFO)) {
440                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s", 
441                         val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
442                 }
443                 offset += 1;
444                 len = plen -1;
445         } else {
446                 len = plen;
447                 if (check_col(pinfo->cinfo, COL_INFO)) {
448                         col_append_fstr(pinfo->cinfo, COL_INFO, "Encrypted packet len=%d", len);
449                 }
450         }
451         /* payload */
452         if (ssh1_tree ) {
453                 ssh_proto_tree_add_item(ssh1_tree, hf_ssh_payload,
454                     tvb, offset, len, FALSE);
455         }
456         offset+=len;
457
458         return offset;
459 }
460
461 static int 
462 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
463                 int offset, proto_tree *tree,int is_response,int number,
464                 gboolean *need_desegmentation)
465 {
466         guint   plen,len;
467         guint8  padding_length;
468         guint   remain_length=0;
469         guint   last_offset=offset;
470         guint   msg_code;
471
472         proto_item *tf;
473         proto_item *key_ex_tree =NULL;
474         
475         remain_length = tvb_reported_length_remaining(tvb,offset);
476         if (ssh_desegment && pinfo->can_desegment) {
477                 if(remain_length < 4) {
478                         pinfo->desegment_offset = offset;
479                         pinfo->desegment_len = 4-remain_length;
480                         *need_desegmentation = TRUE;
481                         return offset;
482                 }
483         }
484         plen = tvb_get_ntohl(tvb, offset) ;
485
486         if (ssh_desegment && pinfo->can_desegment) {
487                 if(plen +4 >  remain_length ) {
488                         pinfo->desegment_offset = offset;
489                         pinfo->desegment_len = plen+4 - remain_length;
490                         *need_desegmentation = TRUE;
491                         return offset;
492                 }
493         }
494         /*
495          * Need to check plen > 0x80000000 here 
496          */ 
497
498         if (check_col(pinfo->cinfo, COL_INFO)) {
499                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ", 
500                         is_response?"Server":"Client");
501         }
502
503         if(plen >= 0xffff) {
504                 if (tree) {
505                         proto_tree_add_uint_format(tree, hf_ssh_packet_length, tvb,
506                                 offset, 4, plen,"Overly large number 0x%x",plen);
507                 }
508                 plen = remain_length-4;
509         } else {
510                 if (tree) {
511                         proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
512                                 offset, 4, plen);
513                 }
514         }
515         offset+=4;
516 /* padding length */
517         padding_length = tvb_get_guint8(tvb, offset);
518         if (tree) {
519                   proto_tree_add_uint(tree, hf_ssh_padding_length, tvb,
520                     offset, 1, padding_length);
521         }
522         offset += 1;
523
524         if(tree) {
525                 tf=proto_tree_add_text(tree,tvb,offset,-1,"Key Exchange");
526                 key_ex_tree = proto_item_add_subtree(tf ,ett_key_exchange);
527         }
528         /* msg_code */
529         msg_code = tvb_get_guint8(tvb, offset);
530         if (tree) {
531                   proto_tree_add_uint_format(key_ex_tree, hf_ssh_msg_code, tvb,
532                     offset, 1, msg_code,"Msg code: %s (%u)",
533                         val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"),
534                         msg_code);
535                     
536         }
537         if (check_col(pinfo->cinfo, COL_INFO)) {
538                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s", 
539                         val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
540         }
541         offset += 1;
542         
543         /* 16 bytes cookie  */
544         if(number == 1) { 
545                 offset = ssh_dissect_key_init(tvb, offset,key_ex_tree);
546         }
547
548         len = plen+4-padding_length-(offset-last_offset);
549         if (tree ) {
550                 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_payload,
551                     tvb, offset, len, FALSE);
552         }
553         offset +=len; 
554
555         /* padding */
556         if(tree) {
557                 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_padding_string,
558                                 tvb, offset, padding_length, FALSE);
559         }
560         offset+= padding_length;
561
562         /* MAC , if there is still bytes, treat it as 16bytes MAC*/
563         if(msg_code == SSH2_MSG_KEX_DH_GEX_REPLY) {
564                 len = tvb_reported_length_remaining(tvb,offset);
565                 if(len == 16) {
566                         if(tree) {
567                                 proto_tree_add_item(key_ex_tree, hf_ssh_mac_string,
568                                         tvb, offset, len , FALSE);
569                         }
570                         offset+=len;
571                 }
572         }
573
574         return offset;
575 }
576 static int 
577 ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
578                 int offset, proto_tree *tree,int is_response)
579 {
580         guint len;
581
582         len = tvb_reported_length_remaining(tvb,offset);
583         if (check_col(pinfo->cinfo, COL_INFO)) {
584                 col_add_fstr(pinfo->cinfo, COL_INFO, "Encrypted %s packet len=%d", 
585                         is_response?"response":"request",len);
586         }
587         if (tree ) {
588                 ssh_proto_tree_add_item(tree, hf_ssh_encrypted_packet,
589                                 tvb, offset, len, FALSE);
590         }
591         offset+=len;
592         return offset;
593 }
594         
595 static int
596 ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
597                 int offset, proto_tree *tree, int is_response, int * version,
598                 gboolean *need_desegmentation)
599 {
600         gint    linelen;
601         guint   remain_length;
602         
603         /* 
604          *  If the first packet do not contain the banner, 
605          *  it is dump in the middle of a flow or not a ssh at all 
606          */
607         if(tvb_strncaseeql(tvb,offset,"SSH-",4) != 0 ) {
608                 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
609                         offset,tree,is_response);
610                 return offset;
611         }
612
613         if(!is_response) {
614                 if(tvb_strncaseeql(tvb,offset,"SSH-2.",6) == 0 ) {
615                         *(version) = SSH_VERSION_2;
616                 }else if(tvb_strncaseeql(tvb,offset,"SSH-1.99-",9) == 0 ) {
617                         *(version) = SSH_VERSION_2;
618                 }else if(tvb_strncaseeql(tvb,offset,"SSH-1.",6) == 0 ) {
619                         *(version) = SSH_VERSION_1;
620                }
621         }
622         
623         remain_length = tvb_reported_length_remaining(tvb,offset);
624         /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
625          */
626         linelen = tvb_find_guint8(tvb, offset, -1, '\n');
627
628         if (ssh_desegment && pinfo->can_desegment) {
629                 if(remain_length < (guint)(linelen-offset) || linelen == -1 ) {
630                         pinfo->desegment_offset = offset;
631                         pinfo->desegment_len = linelen-remain_length;
632                         *need_desegmentation = TRUE;
633                         return offset;
634                 }
635         }
636         if(linelen == -1 ) {
637                 linelen = remain_length;
638         } else {
639                 linelen = linelen - offset;
640         }
641
642         if (check_col(pinfo->cinfo, COL_INFO)) {
643                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Protocol: %s", 
644                         is_response?"Server":"Client", 
645                         tvb_format_text(tvb,offset,linelen)); 
646         }
647         if (tree ) {
648                 ssh_proto_tree_add_item(tree, hf_ssh_protocol,
649                                 tvb, offset, linelen+1, FALSE);
650         }
651         offset+=linelen+1;
652         return offset;
653 }
654
655 static int
656 ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree )
657 {
658         guint   len;
659
660         proto_item *tf;
661         proto_item *key_init_tree=NULL;
662
663
664         if(tree) {
665                 tf=proto_tree_add_text(tree,tvb,offset,-1,"Keys");
666                 key_init_tree = proto_item_add_subtree(tf ,ett_key_init);
667         }
668         if (tree) {
669                 proto_tree_add_item(key_init_tree, hf_ssh_cookie,
670                     tvb, offset, 16, FALSE);
671         }
672         offset += 16;
673
674         /* kex_algorithms */
675         len = tvb_get_ntohl(tvb, offset) ;
676         if(key_init_tree) {
677                 proto_tree_add_uint(key_init_tree,
678                         hf_ssh_kex_algorithms_length ,tvb,offset,4, len);
679         }
680         offset+=4;
681         if (key_init_tree ) {
682                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_kex_algorithms,
683                         tvb, offset, len , FALSE);
684         }
685         offset+=len;
686
687         /* server_host_key_algorithms */
688         len = tvb_get_ntohl(tvb, offset) ;
689         if(key_init_tree) {
690                 proto_tree_add_uint(key_init_tree,
691                         hf_ssh_server_host_key_algorithms_length ,tvb,offset,4, len);
692         }
693         offset+=4;
694         if (key_init_tree) {
695                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_server_host_key_algorithms,
696                         tvb, offset, len , FALSE);
697         }
698         offset+=len;
699
700         /* encryption_algorithms_client_to_server */
701         len = tvb_get_ntohl(tvb, offset) ;
702         if(key_init_tree) {
703                 proto_tree_add_uint(key_init_tree,
704                         hf_ssh_encryption_algorithms_client_to_server_length ,tvb,offset,4, len);
705         }
706         offset+=4;
707         if (key_init_tree ) {
708                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_encryption_algorithms_client_to_server,
709                         tvb, offset, len , FALSE);
710         }
711         offset+=len;
712         /* encryption_algorithms_server_to_client */
713         len = tvb_get_ntohl(tvb, offset) ;
714         if(key_init_tree) {
715                 proto_tree_add_uint(key_init_tree,
716                         hf_ssh_encryption_algorithms_server_to_client_length ,tvb,offset,4, len);
717         }
718         offset+=4;
719         if (key_init_tree ) {
720                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_encryption_algorithms_server_to_client,
721                         tvb, offset, len , FALSE);
722         }
723         offset+=len;
724
725         /* mac_algorithms_client_to_server */
726         len = tvb_get_ntohl(tvb, offset) ;
727         if(key_init_tree) {
728                 proto_tree_add_uint(key_init_tree,
729                         hf_ssh_mac_algorithms_client_to_server_length ,tvb,offset,4, len);
730         }
731         offset+=4;
732         if (key_init_tree ) {
733                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_mac_algorithms_client_to_server,
734                         tvb, offset, len , FALSE);
735         }
736         offset+=len;
737
738         /* mac_algorithms_server_to_client */
739         len = tvb_get_ntohl(tvb, offset) ;
740         if(key_init_tree) {
741                 proto_tree_add_uint(key_init_tree,
742                         hf_ssh_mac_algorithms_server_to_client_length ,tvb,offset,4, len);
743         }
744         offset+=4;
745         if (key_init_tree ) {
746                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_mac_algorithms_server_to_client,
747                         tvb, offset, len , FALSE);
748         }
749         offset+=len;
750         
751         /* compression_algorithms_client_to_server */
752         len = tvb_get_ntohl(tvb, offset) ;
753         if(key_init_tree) {
754                 proto_tree_add_uint(key_init_tree,
755                         hf_ssh_compression_algorithms_client_to_server_length ,tvb,offset,4, len);
756         }
757         offset+=4;
758         if (key_init_tree ) {
759                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_compression_algorithms_client_to_server,
760                         tvb, offset, len , FALSE);
761         }
762         offset+=len;
763
764         /* compression_algorithms_server_to_client */
765         len = tvb_get_ntohl(tvb, offset) ;
766         if(key_init_tree) {
767                 proto_tree_add_uint(key_init_tree,
768                         hf_ssh_compression_algorithms_server_to_client_length ,tvb,offset,4, len);
769         }
770         offset+=4;
771         if (key_init_tree ) {
772                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_compression_algorithms_server_to_client,
773                         tvb, offset, len , FALSE);
774         }
775         offset+=len;
776
777         /* languages_client_to_server */
778         len = tvb_get_ntohl(tvb, offset) ;
779         if(key_init_tree ) {
780                 proto_tree_add_uint(key_init_tree,
781                         hf_ssh_languages_client_to_server_length ,tvb,offset,4, len);
782         }
783         offset+=4;
784         if (key_init_tree ) {
785                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_languages_client_to_server,
786                         tvb, offset, len , FALSE);
787         }
788         offset+=len;
789
790         /* languages_server_to_client */
791         len = tvb_get_ntohl(tvb, offset) ;
792         if(tree ) {
793                 proto_tree_add_uint(key_init_tree,
794                         hf_ssh_languages_server_to_client_length ,tvb,offset,4, len);
795         }
796         offset+=4;
797         if (key_init_tree) {
798                 ssh_proto_tree_add_item(key_init_tree, hf_ssh_languages_server_to_client,
799                         tvb, offset, len , FALSE);
800         }
801         offset+=len;
802
803         return offset;
804 }
805 proto_item *
806 ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
807     gint start, gint length, gboolean little_endian)
808 {
809         if (tree && length <0xffff && length > 0) {
810                 return proto_tree_add_item(tree, hfindex, tvb, start, length,little_endian);
811         }
812         return NULL;
813 }
814
815 void
816 proto_register_ssh(void)
817 {
818   static hf_register_info hf[] = {
819     { &hf_ssh_packet_length,
820       { "Packet Length",              "ssh.packet_length",
821         FT_UINT32, BASE_DEC, NULL,  0x0,
822         "SSH packet length", HFILL }},
823
824     { &hf_ssh_padding_length,
825       { "Padding Length",         "ssh.padding_length",
826         FT_UINT8, BASE_DEC, NULL, 0x0,
827         "SSH Packet Number", HFILL }},
828
829     { &hf_ssh_msg_code,
830       { "Message Code",   "ssh.message_code",
831         FT_UINT8, BASE_DEC, NULL, 0x0,
832         "SSH Message Code", HFILL }},
833
834     { &hf_ssh_cookie,
835       { "Cookie",         "ssh.cookie",
836         FT_STRING, BASE_NONE, NULL, 0x0,
837         "SSH Cookie", HFILL }},
838
839
840     { &hf_ssh_encrypted_packet,
841       { "Encrypted Packet",       "ssh.encrypted_packet",
842         FT_BYTES, BASE_NONE, NULL, 0x0,
843         "SSH Protocol Packet", HFILL }},
844
845     { &hf_ssh_protocol,
846       { "Protocol",       "ssh.protocol",
847         FT_STRING, BASE_NONE, NULL, 0x0,
848         "SSH Protocol", HFILL }},
849
850     { &hf_ssh_payload,
851       { "Payload",        "ssh.payload",
852         FT_BYTES, BASE_NONE, NULL, 0x0,
853         "SSH Payload", HFILL }},
854
855     { &hf_ssh_padding_string,
856       { "Padding String",         "ssh.padding_string",
857         FT_STRING, BASE_NONE, NULL, 0x0,
858         "SSH Padding String", HFILL }},
859
860     { &hf_ssh_mac_string,
861       { "MAC String",     "ssh.mac_string",
862         FT_STRING, BASE_NONE, NULL, 0x0,
863         "SSH MAC String", HFILL }},
864
865   { &hf_ssh_kex_algorithms,
866       { "kex_algorithms string",         "ssh.kex_algorithms",
867         FT_STRINGZ, BASE_NONE, NULL, 0x0,
868         "SSH kex_algorithms string", HFILL }},
869
870   { &hf_ssh_server_host_key_algorithms,
871       { "server_host_key_algorithms string",         "ssh.server_host_key_algorithms",
872         FT_STRINGZ, BASE_NONE, NULL, 0x0,
873         "SSH server_host_key_algorithms string", HFILL }},
874
875   { &hf_ssh_encryption_algorithms_client_to_server,
876       { "encryption_algorithms_client_to_server string",         "ssh.encryption_algorithms_client_to_server",
877         FT_STRINGZ, BASE_NONE, NULL, 0x0,
878         "SSH encryption_algorithms_client_to_server string", HFILL }},
879
880   { &hf_ssh_encryption_algorithms_server_to_client,
881       { "encryption_algorithms_server_to_client string",         "ssh.encryption_algorithms_server_to_client",
882         FT_STRINGZ, BASE_NONE, NULL, 0x0,
883         "SSH encryption_algorithms_server_to_client string", HFILL }},
884
885   { &hf_ssh_mac_algorithms_client_to_server,
886       { "mac_algorithms_client_to_server string",         "ssh.mac_algorithms_client_to_server",
887         FT_STRINGZ, BASE_NONE, NULL, 0x0,
888         "SSH mac_algorithms_client_to_server string", HFILL }},
889
890   { &hf_ssh_mac_algorithms_server_to_client,
891       { "mac_algorithms_server_to_client string",         "ssh.mac_algorithms_server_to_client",
892         FT_STRINGZ, BASE_NONE, NULL, 0x0,
893         "SSH mac_algorithms_server_to_client string", HFILL }},
894
895   { &hf_ssh_compression_algorithms_client_to_server,
896       { "compression_algorithms_client_to_server string",         "ssh.compression_algorithms_client_to_server",
897         FT_STRINGZ, BASE_NONE, NULL, 0x0,
898         "SSH compression_algorithms_client_to_server string", HFILL }},
899
900   { &hf_ssh_compression_algorithms_server_to_client,
901       { "compression_algorithms_server_to_client string",         "ssh.compression_algorithms_server_to_client",
902         FT_STRINGZ, BASE_NONE, NULL, 0x0,
903         "SSH compression_algorithms_server_to_client string", HFILL }},
904
905   { &hf_ssh_languages_client_to_server,
906       { "languages_client_to_server string",         "ssh.languages_client_to_server",
907         FT_STRINGZ, BASE_NONE, NULL, 0x0,
908         "SSH languages_client_to_server string", HFILL }},
909
910   { &hf_ssh_languages_server_to_client,
911       { "languages_server_to_client string",         "ssh.languages_server_to_client",
912         FT_STRINGZ, BASE_NONE, NULL, 0x0,
913         "SSH languages_server_to_client string", HFILL }},
914         
915   { &hf_ssh_kex_algorithms_length,
916       { "kex_algorithms length",         "ssh.kex_algorithms_length",
917         FT_UINT32, BASE_DEC, NULL, 0x0,
918         "SSH kex_algorithms length", HFILL }},
919
920   { &hf_ssh_server_host_key_algorithms_length,
921       { "server_host_key_algorithms length",         "ssh.server_host_key_algorithms_length",
922         FT_UINT32, BASE_DEC, NULL, 0x0,
923         "SSH server_host_key_algorithms length", HFILL }},
924
925   { &hf_ssh_encryption_algorithms_client_to_server_length,
926       { "encryption_algorithms_client_to_server length",         "ssh.encryption_algorithms_client_to_server_length",
927         FT_UINT32, BASE_DEC, NULL, 0x0,
928         "SSH encryption_algorithms_client_to_server length", HFILL }},
929
930   { &hf_ssh_encryption_algorithms_server_to_client_length,
931       { "encryption_algorithms_server_to_client length",         "ssh.encryption_algorithms_server_to_client_length",
932         FT_UINT32, BASE_DEC, NULL, 0x0,
933         "SSH encryption_algorithms_server_to_client length", HFILL }},
934
935   { &hf_ssh_mac_algorithms_client_to_server_length,
936       { "mac_algorithms_client_to_server length",         "ssh.mac_algorithms_client_to_server_length",
937         FT_UINT32, BASE_DEC, NULL, 0x0,
938         "SSH mac_algorithms_client_to_server length", HFILL }},
939
940   { &hf_ssh_mac_algorithms_server_to_client_length,
941       { "mac_algorithms_server_to_client length",         "ssh.mac_algorithms_server_to_client_length",
942         FT_UINT32, BASE_DEC, NULL, 0x0,
943         "SSH mac_algorithms_server_to_client length", HFILL }},
944
945   { &hf_ssh_compression_algorithms_client_to_server_length,
946       { "compression_algorithms_client_to_server length",         "ssh.compression_algorithms_client_to_server_length",
947         FT_UINT32, BASE_DEC, NULL, 0x0,
948         "SSH compression_algorithms_client_to_server length", HFILL }},
949
950   { &hf_ssh_compression_algorithms_server_to_client_length,
951       { "compression_algorithms_server_to_client length",         "ssh.compression_algorithms_server_to_client_length",
952         FT_UINT32, BASE_DEC, NULL, 0x0,
953         "SSH compression_algorithms_server_to_client length", HFILL }},
954
955   { &hf_ssh_languages_client_to_server_length,
956       { "languages_client_to_server length",         "ssh.languages_client_to_server_length",
957         FT_UINT32, BASE_DEC, NULL, 0x0,
958         "SSH languages_client_to_server length", HFILL }},
959
960   { &hf_ssh_languages_server_to_client_length,
961       { "languages_server_to_client length",         "ssh.languages_server_to_client_length",
962         FT_UINT32, BASE_DEC, NULL, 0x0,
963         "SSH languages_server_to_client length", HFILL }},
964
965
966         };
967         static gint *ett[] = {
968                 &ett_ssh,
969                 &ett_key_exchange,
970                 &ett_ssh1,
971                 &ett_ssh2,
972                 &ett_key_init
973         };
974         module_t *ssh_module;
975
976         proto_ssh = proto_register_protocol("SSH Protocol",
977                                        "SSH", "ssh");
978          proto_register_field_array(proto_ssh, hf, array_length(hf));
979         proto_register_subtree_array(ett, array_length(ett));
980         register_init_routine(&ssh_init_protocol);
981
982         ssh_module = prefs_register_protocol(proto_ssh, NULL);
983         prefs_register_bool_preference(ssh_module, "desegment_buffers",
984                 "Desegment all SSH buffers spanning multiple TCP segments",
985                 "Whether the SSH dissector should desegment all SSH buffers spanning multiple TCP segments",
986                 &ssh_desegment);
987 }
988
989 void
990 proto_reg_handoff_ssh(void)
991 {
992         dissector_handle_t ssh_handle;
993
994         ssh_handle = create_dissector_handle(dissect_ssh, proto_ssh);
995   
996         dissector_add("tcp.port", TCP_PORT_SSH, ssh_handle);
997 }