1999-08-18 00:57:54 +00:00
/* packet-telnet.c
2003-02-24 01:04:30 +00:00
* Routines for Telnet packet dissection ; see RFC 854 and RFC 855
1999-04-05 21:54:41 +00:00
* Copyright 1999 , Richard Sharpe < rsharpe @ ns . aus . com >
*
2006-05-21 04:49:01 +00:00
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
1999-04-05 21:54:41 +00:00
* Copyright 1998 Gerald Combs
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
2002-08-28 21:04:11 +00:00
*
1999-04-05 21:54:41 +00:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2002-08-28 21:04:11 +00:00
*
1999-04-05 21:54:41 +00:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2012-06-28 22:56:06 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
1999-04-05 21:54:41 +00:00
*/
2004-02-03 11:40:41 +00:00
/* Telnet authentication options as per RFC2941
* Kerberos v5 telnet authentication as per RFC2942
*/
2012-09-20 02:03:38 +00:00
# include "config.h"
1999-04-05 21:54:41 +00:00
2011-05-20 19:00:09 +00:00
# include <stdlib.h>
2002-01-21 07:37:49 +00:00
# include <epan/packet.h>
2013-02-27 03:58:23 +00:00
# include <epan/expert.h>
2007-05-06 22:34:05 +00:00
# include <epan/asn1.h>
2004-02-03 11:40:41 +00:00
# include "packet-kerberos.h"
2015-12-15 13:10:15 +00:00
# include "packet-ssl-utils.h"
2009-07-17 06:49:58 +00:00
# include "packet-tn3270.h"
2010-05-17 02:55:51 +00:00
# include "packet-tn5250.h"
1999-04-05 21:54:41 +00:00
2013-12-10 21:30:13 +00:00
void proto_reg_handoff_telnet ( void ) ;
void proto_register_telnet ( void ) ;
1999-07-29 05:47:07 +00:00
static int proto_telnet = - 1 ;
2013-02-27 03:58:23 +00:00
static int hf_telnet_cmd = - 1 ;
static int hf_telnet_subcmd = - 1 ;
2004-02-02 11:07:29 +00:00
static int hf_telnet_auth_cmd = - 1 ;
static int hf_telnet_auth_name = - 1 ;
static int hf_telnet_auth_type = - 1 ;
static int hf_telnet_auth_mod_who = - 1 ;
static int hf_telnet_auth_mod_how = - 1 ;
static int hf_telnet_auth_mod_cred_fwd = - 1 ;
static int hf_telnet_auth_mod_enc = - 1 ;
2004-02-03 11:40:41 +00:00
static int hf_telnet_auth_krb5_type = - 1 ;
1999-07-29 05:47:07 +00:00
2013-02-27 03:58:23 +00:00
static int hf_telnet_string_subopt_value = - 1 ;
static int hf_telnet_naws_subopt_width = - 1 ;
static int hf_telnet_naws_subopt_height = - 1 ;
static int hf_telnet_outmark_subopt_cmd = - 1 ;
static int hf_telnet_outmark_subopt_banner = - 1 ;
static int hf_telnet_comport_subopt_signature = - 1 ;
static int hf_telnet_comport_subopt_baud_rate = - 1 ;
static int hf_telnet_comport_subopt_data_size = - 1 ;
static int hf_telnet_comport_subopt_parity = - 1 ;
static int hf_telnet_comport_subopt_stop = - 1 ;
static int hf_telnet_comport_subopt_control = - 1 ;
2014-12-06 00:42:47 +00:00
static int hf_telnet_comport_linestate = - 1 ;
static int hf_telnet_comport_set_linestate_mask = - 1 ;
static int hf_telnet_comport_modemstate = - 1 ;
static int hf_telnet_comport_set_modemstate_mask = - 1 ;
static int hf_telnet_comport_subopt_flow_control_suspend = - 1 ;
static int hf_telnet_comport_subopt_flow_control_resume = - 1 ;
2013-02-27 03:58:23 +00:00
static int hf_telnet_comport_subopt_purge = - 1 ;
static int hf_telnet_rfc_subopt_cmd = - 1 ;
2014-12-06 00:42:47 +00:00
static int hf_telnet_tabstop = - 1 ;
2013-02-27 03:58:23 +00:00
2006-05-18 17:08:41 +00:00
static int hf_telnet_enc_cmd = - 1 ;
static int hf_telnet_enc_type = - 1 ;
2014-12-06 00:42:47 +00:00
static int hf_telnet_enc_type_data = - 1 ;
static int hf_telnet_enc_key_id = - 1 ;
2006-05-18 17:08:41 +00:00
2010-10-15 21:02:30 +00:00
static int hf_telnet_data = - 1 ;
2014-12-06 00:42:47 +00:00
static int hf_telnet_option_data = - 1 ;
static int hf_telnet_subcommand_data = - 1 ;
2010-10-15 21:02:30 +00:00
2013-02-27 03:58:23 +00:00
static int hf_tn3270_subopt = - 1 ;
static int hf_tn3270_connect = - 1 ;
static int hf_tn3270_is = - 1 ;
static int hf_tn3270_request_string = - 1 ;
static int hf_tn3270_reason = - 1 ;
static int hf_tn3270_request = - 1 ;
static int hf_tn3270_regime_subopt_value = - 1 ;
2014-12-06 00:42:47 +00:00
static int hf_tn3270_regime_cmd = - 1 ;
2013-02-27 03:58:23 +00:00
2015-12-11 23:47:15 +00:00
static int hf_telnet_starttls = - 1 ;
1999-11-16 11:44:20 +00:00
static gint ett_telnet = - 1 ;
2013-02-27 03:58:23 +00:00
static gint ett_telnet_cmd = - 1 ;
1999-11-16 11:44:20 +00:00
static gint ett_telnet_subopt = - 1 ;
2003-02-24 01:04:30 +00:00
static gint ett_status_subopt = - 1 ;
static gint ett_rcte_subopt = - 1 ;
static gint ett_olw_subopt = - 1 ;
static gint ett_ops_subopt = - 1 ;
static gint ett_crdisp_subopt = - 1 ;
static gint ett_htstops_subopt = - 1 ;
static gint ett_htdisp_subopt = - 1 ;
static gint ett_ffdisp_subopt = - 1 ;
static gint ett_vtstops_subopt = - 1 ;
static gint ett_vtdisp_subopt = - 1 ;
static gint ett_lfdisp_subopt = - 1 ;
static gint ett_extasc_subopt = - 1 ;
static gint ett_bytemacro_subopt = - 1 ;
static gint ett_det_subopt = - 1 ;
static gint ett_supdupout_subopt = - 1 ;
static gint ett_sendloc_subopt = - 1 ;
static gint ett_termtype_subopt = - 1 ;
static gint ett_tacacsui_subopt = - 1 ;
static gint ett_outmark_subopt = - 1 ;
static gint ett_tlocnum_subopt = - 1 ;
static gint ett_tn3270reg_subopt = - 1 ;
static gint ett_x3pad_subopt = - 1 ;
static gint ett_naws_subopt = - 1 ;
static gint ett_tspeed_subopt = - 1 ;
static gint ett_rfc_subopt = - 1 ;
static gint ett_linemode_subopt = - 1 ;
static gint ett_xdpyloc_subopt = - 1 ;
static gint ett_env_subopt = - 1 ;
static gint ett_auth_subopt = - 1 ;
static gint ett_enc_subopt = - 1 ;
static gint ett_newenv_subopt = - 1 ;
static gint ett_tn3270e_subopt = - 1 ;
2003-04-22 19:57:33 +00:00
static gint ett_xauth_subopt = - 1 ;
static gint ett_charset_subopt = - 1 ;
static gint ett_rsp_subopt = - 1 ;
static gint ett_comport_subopt = - 1 ;
2015-12-11 23:47:15 +00:00
static gint ett_starttls_subopt = - 1 ;
2003-04-22 19:57:33 +00:00
2013-08-23 03:17:34 +00:00
static expert_field ei_telnet_suboption_length = EI_INIT ;
static expert_field ei_telnet_invalid_subcommand = EI_INIT ;
static expert_field ei_telnet_invalid_linestate = EI_INIT ;
static expert_field ei_telnet_invalid_stop = EI_INIT ;
static expert_field ei_telnet_enc_cmd_unknown = EI_INIT ;
static expert_field ei_telnet_invalid_data_size = EI_INIT ;
static expert_field ei_telnet_invalid_modemstate = EI_INIT ;
static expert_field ei_telnet_invalid_parity = EI_INIT ;
static expert_field ei_telnet_kerberos_blob_too_long = EI_INIT ;
static expert_field ei_telnet_invalid_purge = EI_INIT ;
static expert_field ei_telnet_invalid_baud_rate = EI_INIT ;
static expert_field ei_telnet_invalid_control = EI_INIT ;
2013-08-05 18:09:43 +00:00
static dissector_handle_t telnet_handle ;
2009-07-17 06:49:58 +00:00
static dissector_handle_t tn3270_handle ;
2010-05-17 02:55:51 +00:00
static dissector_handle_t tn5250_handle ;
2015-12-15 13:10:15 +00:00
static dissector_handle_t ssl_handle ;
1999-11-16 11:44:20 +00:00
1999-04-05 21:54:41 +00:00
/* Some defines for Telnet */
2012-03-19 21:12:45 +00:00
# define TCP_PORT_TELNET 23
2000-04-08 07:07:42 +00:00
1999-04-05 21:54:41 +00:00
# define TN_IAC 255
# define TN_DONT 254
# define TN_DO 253
# define TN_WONT 252
# define TN_WILL 251
# define TN_SB 250
# define TN_GA 249
# define TN_EL 248
# define TN_EC 247
# define TN_AYT 246
# define TN_AO 245
# define TN_IP 244
# define TN_BRK 243
# define TN_DM 242
# define TN_NOP 241
# define TN_SE 240
# define TN_EOR 239
# define TN_ABORT 238
# define TN_SUSP 237
# define TN_EOF 236
2012-03-19 21:12:45 +00:00
# define TN_ARE 1
1999-04-05 21:54:41 +00:00
2013-02-27 03:58:23 +00:00
static const value_string cmd_vals [ ] = {
{ TN_EOF , " End of File " } ,
{ TN_SUSP , " Suspend Current Process " } ,
{ TN_ABORT , " Abort Process " } ,
{ TN_EOR , " End of Record " } ,
{ TN_SE , " Suboption End " } ,
{ TN_NOP , " No Operation " } ,
{ TN_DM , " Data Mark " } ,
{ TN_BRK , " Break " } ,
{ TN_IP , " Interrupt Process " } ,
{ TN_AO , " Abort Output " } ,
{ TN_AYT , " Are You There? " } ,
{ TN_EC , " Escape Character " } ,
{ TN_EL , " Erase Line " } ,
{ TN_GA , " Go Ahead " } ,
{ TN_DONT , " Don't " } ,
{ TN_DO , " Do " } ,
{ TN_WONT , " Won't " } ,
{ TN_WILL , " Will " } ,
{ TN_SB , " Suboption " } ,
{ 0 , NULL }
} ;
2003-04-22 19:57:33 +00:00
2003-02-24 01:04:30 +00:00
typedef enum {
2012-03-19 21:12:45 +00:00
NO_LENGTH , /* option has no data, hence no length */
FIXED_LENGTH , /* option always has the same length */
VARIABLE_LENGTH /* option is variable-length - optlen is minimum */
2003-02-24 01:04:30 +00:00
} tn_opt_len_type ;
/* Member of table of IP or TCP options. */
typedef struct tn_opt {
2012-03-19 21:12:45 +00:00
const char * name ; /* name of option */
gint * subtree_index ; /* pointer to subtree index for option */
tn_opt_len_type len_type ; /* type of option length field */
int optlen ; /* value length should be (minimum if VARIABLE) */
2013-02-27 03:58:23 +00:00
void ( * dissect ) ( packet_info * pinfo , const char * , tvbuff_t * , int , int , proto_tree * , proto_item * ) ;
2012-03-19 21:12:45 +00:00
/* routine to dissect option */
2003-02-24 01:04:30 +00:00
} tn_opt ;
2015-12-15 13:10:15 +00:00
typedef struct _telnet_conv_info {
guint32 starttls_requested_in ; /* Frame of first sender of START_TLS FOLLOWS */
guint32 starttls_port ; /* Source port for first sender */
} telnet_conv_info_t ;
2009-07-17 06:49:58 +00:00
static void
2010-05-13 15:19:40 +00:00
check_tn3270_model ( packet_info * pinfo _U_ , const char * terminaltype )
2009-07-17 06:49:58 +00:00
{
2012-03-19 21:12:45 +00:00
int model ;
2009-07-17 06:49:58 +00:00
if ( ( strcmp ( terminaltype , " IBM-3278-2-E " ) = = 0 ) | | ( strcmp ( terminaltype , " IBM-3278-2 " ) = = 0 ) | |
( strcmp ( terminaltype , " IBM-3278-3 " ) = = 0 ) | | ( strcmp ( terminaltype , " IBM-3278-4 " ) = = 0 ) | |
( strcmp ( terminaltype , " IBM-3278-5 " ) = = 0 ) | | ( strcmp ( terminaltype , " IBM-3277-2 " ) = = 0 ) | |
( strcmp ( terminaltype , " IBM-3279-3 " ) = = 0 ) | | ( strcmp ( terminaltype , " IBM-3279-4 " ) = = 0 ) | |
( strcmp ( terminaltype , " IBM-3279-2-E " ) = = 0 ) | | ( strcmp ( terminaltype , " IBM-3279-2 " ) = = 0 ) | |
2010-05-13 15:19:40 +00:00
( strcmp ( terminaltype , " IBM-3279-4-E " ) = = 0 ) ) {
2016-09-12 10:41:48 +00:00
model = terminaltype [ 9 ] - ' 0 ' ;
2012-03-19 21:12:45 +00:00
add_tn3270_conversation ( pinfo , 0 , model ) ;
2010-05-13 15:19:40 +00:00
}
}
2009-07-17 06:49:58 +00:00
2010-05-13 15:19:40 +00:00
static void
check_for_tn3270 ( packet_info * pinfo _U_ , const char * optname , const char * terminaltype )
{
if ( strcmp ( optname , " Terminal Type " ) ! = 0 ) {
2012-03-19 21:12:45 +00:00
return ;
2010-05-13 15:19:40 +00:00
}
check_tn3270_model ( pinfo , terminaltype ) ;
2010-05-17 02:55:51 +00:00
if ( ( strcmp ( terminaltype , " IBM-5555-C01 " ) = = 0 ) | | /* 24 x 80 Double-Byte Character Set color display */
( strcmp ( terminaltype , " IBM-5555-B01 " ) = = 0 ) | | /* 24 x 80 Double-Byte Character Set (DBCS)*/
( strcmp ( terminaltype , " IBM-3477-FC " ) = = 0 ) | | /* 27 x 132 color display*/
( strcmp ( terminaltype , " IBM-3477-FG " ) = = 0 ) | | /* 27 x 132 monochrome display*/
( strcmp ( terminaltype , " IBM-3180-2 " ) = = 0 ) | | /* 27 x 132 monochrome display*/
( strcmp ( terminaltype , " IBM-3179-2 " ) = = 0 ) | | /* 24 x 80 color display*/
( strcmp ( terminaltype , " IBM-3196-A1 " ) = = 0 ) | | /* 24 x 80 monochrome display*/
( strcmp ( terminaltype , " IBM-5292-2 " ) = = 0 ) | | /* 24 x 80 color display*/
( strcmp ( terminaltype , " IBM-5291-1 " ) = = 0 ) | | /* 24 x 80 monochrome display*/
2012-03-19 21:12:45 +00:00
( strcmp ( terminaltype , " IBM-5251-11 " ) = = 0 ) ) /* 24 x 80 monochrome display*/
add_tn5250_conversation ( pinfo , 0 ) ;
2009-07-17 06:49:58 +00:00
}
2015-12-15 13:10:15 +00:00
static telnet_conv_info_t *
telnet_get_session ( packet_info * pinfo )
{
conversation_t * conversation = find_or_create_conversation ( pinfo ) ;
telnet_conv_info_t * telnet_info ;
telnet_info = ( telnet_conv_info_t * ) conversation_get_proto_data ( conversation , proto_telnet ) ;
if ( ! telnet_info ) {
telnet_info = wmem_new0 ( wmem_file_scope ( ) , telnet_conv_info_t ) ;
conversation_add_proto_data ( conversation , proto_telnet , telnet_info ) ;
}
return telnet_info ;
}
2003-02-24 01:04:30 +00:00
static void
2013-02-27 03:58:23 +00:00
dissect_string_subopt ( packet_info * pinfo , const char * optname , tvbuff_t * tvb , int offset , int len ,
proto_tree * tree , proto_item * item )
2003-02-24 01:04:30 +00:00
{
guint8 cmd ;
cmd = tvb_get_guint8 ( tvb , offset ) ;
switch ( cmd ) {
2012-03-19 21:12:45 +00:00
case 0 : /* IS */
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_telnet_subcmd , tvb , offset , 1 , cmd , " Here's my %s " , optname ) ;
2003-02-24 01:04:30 +00:00
offset + + ;
len - - ;
if ( len > 0 ) {
2013-02-27 03:58:23 +00:00
proto_tree_add_item ( tree , hf_telnet_string_subopt_value , tvb , offset , len , ENC_NA | ENC_ASCII ) ;
2003-02-24 01:04:30 +00:00
}
2009-07-17 06:49:58 +00:00
check_for_tn3270 ( pinfo , optname , tvb_format_text ( tvb , offset , len ) ) ;
2003-02-24 01:04:30 +00:00
break ;
2012-03-19 21:12:45 +00:00
case 1 : /* SEND */
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_telnet_subcmd , tvb , offset , 1 , cmd , " Send your %s " , optname ) ;
2003-02-24 01:04:30 +00:00
offset + + ;
len - - ;
if ( len > 0 )
2014-12-06 00:42:47 +00:00
proto_tree_add_bytes_format ( tree , hf_telnet_subcommand_data , tvb , offset , len , NULL , " Extra data " ) ;
2003-02-24 01:04:30 +00:00
break ;
default :
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_subcommand , " Invalid %s subcommand %u " , optname , cmd ) ;
2013-02-27 03:58:23 +00:00
2003-02-24 01:04:30 +00:00
offset + + ;
len - - ;
if ( len > 0 )
2014-12-06 00:42:47 +00:00
proto_tree_add_item ( tree , hf_telnet_subcommand_data , tvb , offset , len , ENC_NA ) ;
2003-02-24 01:04:30 +00:00
break ;
}
}
2009-07-17 06:49:58 +00:00
static void
2013-02-27 03:58:23 +00:00
dissect_tn3270_regime_subopt ( packet_info * pinfo , const char * optname _U_ , tvbuff_t * tvb , int offset ,
2014-12-06 00:42:47 +00:00
int len , proto_tree * tree , proto_item * item _U_ )
2009-07-17 06:49:58 +00:00
{
# define TN3270_REGIME_ARE 0x01
# define TN3270_REGIME_IS 0x00
guint8 cmd ;
2012-03-19 21:12:45 +00:00
2009-07-17 06:49:58 +00:00
while ( len > 0 ) {
cmd = tvb_get_guint8 ( tvb , offset ) ;
switch ( cmd ) {
2012-03-19 21:12:45 +00:00
case TN3270_REGIME_ARE :
case TN3270_REGIME_IS :
if ( cmd = = TN3270_REGIME_ARE ) {
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_tn3270_regime_cmd , tvb , offset , 1 , cmd , " ARE " ) ;
2012-03-19 21:12:45 +00:00
add_tn3270_conversation ( pinfo , 0 , 0 ) ;
} else {
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_tn3270_regime_cmd , tvb , offset , 1 , cmd , " IS " ) ;
2012-03-19 21:12:45 +00:00
}
2013-02-27 03:58:23 +00:00
proto_tree_add_item ( tree , hf_tn3270_regime_subopt_value , tvb , offset + 1 , len - 1 , ENC_NA | ENC_ASCII ) ;
2012-03-19 21:12:45 +00:00
return ;
default :
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_tn3270_regime_cmd , tvb , offset , 1 , cmd , " Bogus value: %u " , cmd ) ;
2012-03-19 21:12:45 +00:00
break ;
2009-07-17 06:49:58 +00:00
}
offset + + ;
len - - ;
}
}
# define TN3270_ASSOCIATE 0x00
# define TN3270_CONNECT 0x01
# define TN3270_DEVICE_TYPE 0x02
# define TN3270_FUNCTIONS 0x03
# define TN3270_IS 0x04
# define TN3270_REASON 0x05
# define TN3270_REJECT 0x06
# define TN3270_REQUEST 0x07
# define TN3270_SEND 0x08
/* Reason_codes*/
# define TN3270_CONN_PARTNER 0x00
# define TN3270_DEVICE_IN_USE 0x01
# define TN3270_INV_ASSOCIATE 0x02
# define TN3270_INV_DEVICE_NAME 0x03
# define TN3270_INV_DEVICE_TYPE 0x04
# define TN3270_TYPE_NAME_ERROR 0x05
# define TN3270_UNKNOWN_ERROR 0x06
# define TN3270_UNSUPPORTED_REQ 0x07
/* Function Names*/
# define TN3270_BIND_IMAGE 0x00
# define TN3270_DATA_STREAM_CTL 0x01
# define TN3270_RESPONSES 0x02
# define TN3270_SCS_CTL_CODES 0x03
# define TN3270_SYSREQ 0x04
2013-02-27 03:58:23 +00:00
static const value_string tn3270_subopt_vals [ ] = {
{ TN3270_ASSOCIATE , " ASSOCIATE " } ,
{ TN3270_CONNECT , " CONNECT " } ,
{ TN3270_DEVICE_TYPE , " DEVICE-TYPE " } ,
{ TN3270_FUNCTIONS , " FUNCTIONS " } ,
{ TN3270_IS , " IS " } ,
{ TN3270_REASON , " REASON " } ,
{ TN3270_REJECT , " REJECT " } ,
{ TN3270_REQUEST , " REQUEST " } ,
{ TN3270_SEND , " SEND " } ,
{ 0 , NULL }
} ;
static const value_string tn3270_reason_vals [ ] = {
{ TN3270_CONN_PARTNER , " CONN-PARTNER " } ,
{ TN3270_DEVICE_IN_USE , " DEVICE-IN-USE " } ,
{ TN3270_INV_ASSOCIATE , " INV-ASSOCIATE " } ,
{ TN3270_INV_DEVICE_NAME , " INV-DEVICE-NAME " } ,
{ TN3270_INV_DEVICE_TYPE , " INV-DEVICE-TYPE " } ,
{ TN3270_TYPE_NAME_ERROR , " TYPE-NAME-ERROR " } ,
{ TN3270_UNKNOWN_ERROR , " UNKNOWN-ERROR " } ,
{ TN3270_UNSUPPORTED_REQ , " UNSUPPORTED-REQ " } ,
{ 0 , NULL }
} ;
static const value_string tn3270_request_vals [ ] = {
{ TN3270_BIND_IMAGE , " BIND-IMAGE " } ,
{ TN3270_DATA_STREAM_CTL , " DATA-STREAM-CTL " } ,
{ TN3270_RESPONSES , " RESPONSES " } ,
{ TN3270_SCS_CTL_CODES , " SCS-CTL-CODES " } ,
{ TN3270_SYSREQ , " SYSREQ " } ,
{ 0 , NULL }
} ;
2009-07-17 06:49:58 +00:00
static void
dissect_tn3270e_subopt ( packet_info * pinfo _U_ , const char * optname _U_ , tvbuff_t * tvb , int offset ,
2013-02-27 05:53:46 +00:00
int len , proto_tree * tree , proto_item * item _U_ )
2009-07-17 06:49:58 +00:00
{
guint8 cmd ;
2012-03-19 21:12:45 +00:00
int datalen ;
int connect_offset = 0 ;
int device_type = 0 ;
int rsn = 0 ;
2009-07-17 06:49:58 +00:00
while ( len > 0 ) {
cmd = tvb_get_guint8 ( tvb , offset ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( tree , hf_tn3270_subopt , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2009-07-17 06:49:58 +00:00
switch ( cmd ) {
case TN3270_CONNECT :
2013-02-27 03:58:23 +00:00
proto_tree_add_item ( tree , hf_tn3270_connect , tvb , offset + 1 , len , ENC_NA | ENC_ASCII ) ;
2009-07-17 06:49:58 +00:00
offset + = ( len - 1 ) ;
len - = ( len - 1 ) ;
break ;
case TN3270_IS :
device_type = tvb_get_guint8 ( tvb , offset - 1 ) ;
if ( device_type = = TN3270_DEVICE_TYPE ) {
/* If there is a terminal type to display, then it will be followed by CONNECT */
connect_offset = tvb_find_guint8 ( tvb , offset + 1 , len , TN3270_CONNECT ) ;
if ( connect_offset ! = - 1 ) {
datalen = connect_offset - ( offset + 1 ) ;
if ( datalen > 0 ) {
2013-02-27 03:58:23 +00:00
proto_tree_add_item ( tree , hf_tn3270_is , tvb , offset + 1 , datalen , ENC_NA | ENC_ASCII ) ;
2010-05-13 15:19:40 +00:00
check_tn3270_model ( pinfo , tvb_format_text ( tvb , offset + 1 , datalen ) ) ;
2009-07-17 06:49:58 +00:00
offset + = datalen ;
len - = datalen ;
}
}
}
break ;
case TN3270_REASON :
offset + + ;
len - - ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( tree , hf_tn3270_reason , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2009-07-17 06:49:58 +00:00
break ;
case TN3270_REQUEST :
2010-05-13 15:19:40 +00:00
add_tn3270_conversation ( pinfo , 1 , 0 ) ;
2009-07-17 06:49:58 +00:00
device_type = tvb_get_guint8 ( tvb , offset - 1 ) ;
if ( device_type = = TN3270_DEVICE_TYPE ) {
2013-02-27 03:58:23 +00:00
proto_tree_add_item ( tree , hf_tn3270_request_string , tvb , offset + 1 , len - 1 , ENC_NA | ENC_ASCII ) ;
2009-07-17 06:49:58 +00:00
offset + = ( len - 1 ) ;
len - = ( len - 1 ) ;
} else if ( device_type = = TN3270_FUNCTIONS ) {
2013-02-27 03:58:23 +00:00
while ( len > 0 ) {
2009-07-17 06:49:58 +00:00
rsn = tvb_get_guint8 ( tvb , offset ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( tree , hf_tn3270_request , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2013-03-29 00:26:23 +00:00
if ( try_val_to_str ( rsn , tn3270_request_vals ) = = NULL )
2013-02-27 03:58:23 +00:00
break ;
2009-07-17 06:49:58 +00:00
offset + + ;
len - - ;
}
}
break ;
}
offset + + ;
len - - ;
}
}
2015-12-11 23:47:15 +00:00
static void
dissect_starttls_subopt ( packet_info * pinfo _U_ , const char * optname _U_ , tvbuff_t * tvb , int offset ,
int len _U_ , proto_tree * tree , proto_item * item _U_ )
{
2015-12-15 13:10:15 +00:00
telnet_conv_info_t * session = telnet_get_session ( pinfo ) ;
2015-12-11 23:47:15 +00:00
proto_tree_add_item ( tree , hf_telnet_starttls , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-12-15 13:10:15 +00:00
if ( session - > starttls_requested_in = = 0 ) {
/* First sender (client or server) requesting to start TLS. */
2016-01-24 03:40:51 +00:00
session - > starttls_requested_in = pinfo - > num ;
2015-12-15 13:10:15 +00:00
session - > starttls_port = pinfo - > srcport ;
2016-01-24 03:40:51 +00:00
} else if ( session - > starttls_requested_in < pinfo - > num & &
2015-12-15 13:10:15 +00:00
session - > starttls_port ! = pinfo - > srcport ) {
/* Other side confirms that following data is TLS. */
ssl_starttls_ack ( ssl_handle , pinfo , telnet_handle ) ;
}
2015-12-11 23:47:15 +00:00
}
2013-02-27 03:58:23 +00:00
static const value_string telnet_outmark_subopt_cmd_vals [ ] = {
2016-09-19 01:48:50 +00:00
{ ' \x06 ' , " ACK " } ,
{ ' \x15 ' , " NAK " } ,
{ ' D ' , " Default " } ,
{ ' T ' , " Top " } ,
{ ' B ' , " Bottom " } ,
{ ' L ' , " Left " } ,
{ ' R ' , " Right " } ,
2013-02-27 03:58:23 +00:00
{ 0 , NULL }
} ;
2003-02-24 01:04:30 +00:00
static void
2004-02-03 11:40:41 +00:00
dissect_outmark_subopt ( packet_info * pinfo _U_ , const char * optname _U_ , tvbuff_t * tvb , int offset ,
2013-02-27 05:53:46 +00:00
int len , proto_tree * tree , proto_item * item _U_ )
2003-02-24 01:04:30 +00:00
{
2012-03-19 21:12:45 +00:00
int gs_offset , datalen ;
2003-02-24 01:04:30 +00:00
while ( len > 0 ) {
2016-09-19 01:48:50 +00:00
proto_tree_add_item ( tree , hf_telnet_outmark_subopt_cmd , tvb , offset , 1 , ENC_ASCII | ENC_NA ) ;
2003-02-24 01:04:30 +00:00
offset + + ;
len - - ;
/* Look for a GS */
gs_offset = tvb_find_guint8 ( tvb , offset , len , 29 ) ;
if ( gs_offset = = - 1 ) {
/* None found - run to the end of the packet. */
gs_offset = offset + len ;
}
datalen = gs_offset - offset ;
if ( datalen > 0 ) {
2013-02-27 03:58:23 +00:00
proto_tree_add_item ( tree , hf_telnet_outmark_subopt_banner , tvb , offset , datalen , ENC_NA | ENC_ASCII ) ;
2003-02-24 01:04:30 +00:00
offset + = datalen ;
len - = datalen ;
}
}
}
static void
2013-02-27 03:58:23 +00:00
dissect_htstops_subopt ( packet_info * pinfo , const char * optname , tvbuff_t * tvb , int offset , int len ,
proto_tree * tree , proto_item * item )
2003-02-24 01:04:30 +00:00
{
guint8 cmd ;
guint8 tabval ;
cmd = tvb_get_guint8 ( tvb , offset ) ;
switch ( cmd ) {
2012-03-19 21:12:45 +00:00
case 0 : /* IS */
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_telnet_subcmd , tvb , offset , 1 , cmd , " Here's my %s " , optname ) ;
2003-02-24 01:04:30 +00:00
offset + + ;
len - - ;
break ;
2012-03-19 21:12:45 +00:00
case 1 : /* SEND */
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_telnet_subcmd , tvb , offset , 1 , cmd , " Send your %s " , optname ) ;
2003-02-24 01:04:30 +00:00
offset + + ;
len - - ;
break ;
default :
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_subcommand , " Invalid %s subcommand %u " , optname , cmd ) ;
2003-02-24 01:04:30 +00:00
offset + + ;
len - - ;
if ( len > 0 )
2014-12-06 00:42:47 +00:00
proto_tree_add_item ( tree , hf_telnet_subcommand_data , tvb , offset , len , ENC_NA ) ;
2003-02-24 01:04:30 +00:00
return ;
}
while ( len > 0 ) {
tabval = tvb_get_guint8 ( tvb , offset ) ;
switch ( tabval ) {
case 0 :
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_telnet_tabstop , tvb , offset , 1 ,
tabval , " Sender wants to handle tab stops " ) ;
2003-02-24 01:04:30 +00:00
break ;
default :
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_telnet_tabstop , tvb , offset , 1 ,
tabval , " Sender wants receiver to handle tab stop at %u " ,
2003-02-24 01:04:30 +00:00
tabval ) ;
break ;
case 251 :
case 252 :
case 253 :
case 254 :
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_telnet_tabstop , tvb , offset , 1 ,
tabval , " Invalid value: %u " , tabval ) ;
2003-02-24 01:04:30 +00:00
break ;
case 255 :
2014-12-06 00:42:47 +00:00
proto_tree_add_uint_format ( tree , hf_telnet_tabstop , tvb , offset , 1 ,
tabval , " Sender wants receiver to handle tab stops " ) ;
2003-02-24 01:04:30 +00:00
break ;
}
offset + + ;
len - - ;
}
}
static void
2009-06-01 22:41:48 +00:00
dissect_naws_subopt ( packet_info * pinfo _U_ , const char * optname _U_ , tvbuff_t * tvb , int offset ,
2013-02-27 03:58:23 +00:00
int len _U_ , proto_tree * tree , proto_item * item _U_ )
2003-02-24 01:04:30 +00:00
{
2013-02-27 03:58:23 +00:00
proto_tree_add_item ( tree , hf_telnet_naws_subopt_width , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
2009-06-01 22:41:48 +00:00
offset + = 2 ;
2013-02-27 03:58:23 +00:00
proto_tree_add_item ( tree , hf_telnet_naws_subopt_height , tvb , offset , 2 , ENC_BIG_ENDIAN ) ;
2003-02-24 01:04:30 +00:00
}
2003-04-22 20:35:49 +00:00
/* BEGIN RFC-2217 (COM Port Control) Definitions */
2003-04-22 19:57:33 +00:00
2012-03-19 21:12:45 +00:00
# define TNCOMPORT_SIGNATURE 0
# define TNCOMPORT_SETBAUDRATE 1
# define TNCOMPORT_SETDATASIZE 2
# define TNCOMPORT_SETPARITY 3
# define TNCOMPORT_SETSTOPSIZE 4
# define TNCOMPORT_SETCONTROL 5
# define TNCOMPORT_NOTIFYLINESTATE 6
# define TNCOMPORT_NOTIFYMODEMSTATE 7
# define TNCOMPORT_FLOWCONTROLSUSPEND 8
2003-04-22 19:57:33 +00:00
# define TNCOMPORT_FLOWCONTROLRESUME 9
2012-03-19 21:12:45 +00:00
# define TNCOMPORT_SETLINESTATEMASK 10
# define TNCOMPORT_SETMODEMSTATEMASK 11
# define TNCOMPORT_PURGEDATA 12
2003-04-22 19:57:33 +00:00
2003-04-22 20:35:49 +00:00
/* END RFC-2217 (COM Port Control) Definitions */
2003-04-22 19:57:33 +00:00
static void
2013-02-27 03:58:23 +00:00
dissect_comport_subopt ( packet_info * pinfo , const char * optname , tvbuff_t * tvb , int offset , int len ,
proto_tree * tree , proto_item * item )
2012-03-19 21:12:45 +00:00
{
static const char * datasizes [ ] = {
2003-04-22 19:57:33 +00:00
" Request " ,
" <invalid> " ,
" <invalid> " ,
" <invalid> " ,
" <invalid> " ,
" 5 " ,
" 6 " ,
" 7 " ,
" 8 "
2012-03-19 21:12:45 +00:00
} ;
static const char * parities [ ] = {
2003-04-22 19:57:33 +00:00
" Request " ,
" None " ,
" Odd " ,
" Even " ,
" Mark " ,
" Space "
2012-03-19 21:12:45 +00:00
} ;
static const char * stops [ ] = {
2003-04-22 19:57:33 +00:00
" Request " ,
" 1 " ,
" 2 " ,
" 1.5 "
2012-03-19 21:12:45 +00:00
} ;
static const char * control [ ] = {
2003-04-22 19:57:33 +00:00
" Output Flow Control Request " ,
" Output Flow: None " ,
" Output Flow: XON/XOFF " ,
" Output Flow: CTS/RTS " ,
" Break Request " ,
" Break: ON " ,
" Break: OFF " ,
" DTR Request " ,
" DTR: ON " ,
" DTR: OFF " ,
" RTS Request " ,
" RTS: ON " ,
" RTS: OFF " ,
" Input Flow Control Request " ,
" Input Flow: None " ,
" Input Flow: XON/XOFF " ,
" Input Flow: CTS/RTS " ,
" Output Flow: DCD " ,
" Input Flow: DTR " ,
" Output Flow: DSR "
2012-03-19 21:12:45 +00:00
} ;
static const char * linestate_bits [ ] = {
2003-04-22 19:57:33 +00:00
" Data Ready " ,
" Overrun Error " ,
" Parity Error " ,
" Framing Error " ,
" Break Detected " ,
" Transfer Holding Register Empty " ,
" Transfer Shift Register Empty " ,
" Timeout Error "
2012-03-19 21:12:45 +00:00
} ;
static const char * modemstate_bits [ ] = {
" DCTS " ,
" DDSR " ,
" TERI " ,
" DDCD " ,
" CTS " ,
" DSR " ,
" RI " ,
" DCD "
} ;
static const char * purges [ ] = {
" Purge None " ,
" Purge RX " ,
" Purge TX " ,
" Purge RX/TX "
} ;
2009-09-24 04:52:35 +00:00
2003-04-22 19:57:33 +00:00
guint8 cmd ;
guint8 isservercmd ;
2005-06-18 15:41:26 +00:00
const char * source ;
2009-09-24 04:52:35 +00:00
2003-04-22 19:57:33 +00:00
cmd = tvb_get_guint8 ( tvb , offset ) ;
isservercmd = cmd > 99 ;
cmd = ( isservercmd ) ? ( cmd - 100 ) : cmd ;
source = ( isservercmd ) ? " Server " : " Client " ;
switch ( cmd ) {
case TNCOMPORT_SIGNATURE :
len - - ;
if ( len = = 0 ) {
2014-12-06 00:42:47 +00:00
proto_tree_add_string_format ( tree , hf_telnet_comport_subopt_signature , tvb , offset , 1 , " " , " %s Requests Signature " , source ) ;
2003-04-22 19:57:33 +00:00
} else {
2014-06-17 15:30:58 +00:00
guint8 * sig = tvb_get_string_enc ( wmem_packet_scope ( ) , tvb , offset + 1 , len , ENC_ASCII ) ;
2014-12-06 00:42:47 +00:00
proto_tree_add_string_format ( tree , hf_telnet_comport_subopt_signature , tvb , offset , 1 + len , sig ,
2013-02-27 03:58:23 +00:00
" %s Signature: %s " , source , sig ) ;
2003-04-22 19:57:33 +00:00
}
break ;
case TNCOMPORT_SETBAUDRATE :
len - - ;
if ( len > = 4 ) {
2012-03-19 21:12:45 +00:00
guint32 baud = tvb_get_ntohl ( tvb , offset + 1 ) ;
if ( baud = = 0 ) {
2013-02-27 03:58:23 +00:00
proto_tree_add_uint_format_value ( tree , hf_telnet_comport_subopt_baud_rate , tvb , offset , 5 , 0 , " %s Requests Baud Rate " , source ) ;
2012-03-19 21:12:45 +00:00
} else {
2013-02-27 03:58:23 +00:00
proto_tree_add_uint_format_value ( tree , hf_telnet_comport_subopt_baud_rate , tvb , offset , 5 , baud , " %s Baud Rate: %d " , source , baud ) ;
2012-03-19 21:12:45 +00:00
}
2003-04-22 19:57:33 +00:00
} else {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_baud_rate , " %s <Invalid Baud Rate Packet> " , source ) ;
2003-04-22 19:57:33 +00:00
}
break ;
2009-09-24 04:52:35 +00:00
2003-04-22 19:57:33 +00:00
case TNCOMPORT_SETDATASIZE :
len - - ;
if ( len > = 1 ) {
2012-03-19 21:12:45 +00:00
guint8 datasize = tvb_get_guint8 ( tvb , offset + 1 ) ;
const char * ds = ( datasize > 8 ) ? " <invalid> " : datasizes [ datasize ] ;
2013-09-12 16:15:54 +00:00
proto_tree_add_uint_format_value ( tree , hf_telnet_comport_subopt_data_size , tvb , offset , 2 , datasize ,
2013-02-27 03:58:23 +00:00
" %s Data Size: %s " , source , ds ) ;
2003-04-22 19:57:33 +00:00
} else {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_data_size , " %s <Invalid Data Size Packet> " , source ) ;
2003-04-22 19:57:33 +00:00
}
break ;
case TNCOMPORT_SETPARITY :
len - - ;
if ( len > = 1 ) {
2012-03-19 21:12:45 +00:00
guint8 parity = tvb_get_guint8 ( tvb , offset + 1 ) ;
const char * pr = ( parity > 5 ) ? " <invalid> " : parities [ parity ] ;
2013-09-12 16:15:54 +00:00
proto_tree_add_uint_format_value ( tree , hf_telnet_comport_subopt_parity , tvb , offset , 2 , parity ,
2013-02-27 03:58:23 +00:00
" %s Parity: %s " , source , pr ) ;
2003-04-22 19:57:33 +00:00
} else {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_parity , " %s <Invalid Parity Packet> " , source ) ;
2003-04-22 19:57:33 +00:00
}
break ;
case TNCOMPORT_SETSTOPSIZE :
len - - ;
if ( len > = 1 ) {
2012-03-19 21:12:45 +00:00
guint8 stop = tvb_get_guint8 ( tvb , offset + 1 ) ;
const char * st = ( stop > 3 ) ? " <invalid> " : stops [ stop ] ;
2013-09-12 16:15:54 +00:00
proto_tree_add_uint_format_value ( tree , hf_telnet_comport_subopt_stop , tvb , offset , 2 , stop ,
2013-02-27 03:58:23 +00:00
" %s Stop: %s " , source , st ) ;
2003-04-22 19:57:33 +00:00
} else {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_stop , " %s <Invalid Stop Packet> " , source ) ;
2003-04-22 19:57:33 +00:00
}
break ;
case TNCOMPORT_SETCONTROL :
len - - ;
if ( len > = 1 ) {
2012-03-19 21:12:45 +00:00
guint8 crt = tvb_get_guint8 ( tvb , offset + 1 ) ;
const char * c = ( crt > 19 ) ? " Control: <invalid> " : control [ crt ] ;
2013-09-12 16:15:54 +00:00
proto_tree_add_uint_format_value ( tree , hf_telnet_comport_subopt_control , tvb , offset , 2 , crt ,
2013-02-27 03:58:23 +00:00
" %s Stop: %s " , source , c ) ;
2003-04-22 19:57:33 +00:00
} else {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_control , " %s <Invalid Control Packet> " , source ) ;
2003-04-22 19:57:33 +00:00
}
break ;
2009-09-24 04:52:35 +00:00
2003-04-22 19:57:33 +00:00
case TNCOMPORT_SETLINESTATEMASK :
case TNCOMPORT_NOTIFYLINESTATE :
len - - ;
if ( len > = 1 ) {
2012-03-19 21:12:45 +00:00
const char * print_pattern = ( cmd = = TNCOMPORT_SETLINESTATEMASK ) ?
" %s Set Linestate Mask: %s " : " %s Linestate: %s " ;
2014-12-06 00:42:47 +00:00
int hf_line = ( cmd = = TNCOMPORT_SETLINESTATEMASK ) ?
hf_telnet_comport_set_linestate_mask : hf_telnet_comport_linestate ;
2012-03-19 21:12:45 +00:00
char ls_buffer [ 512 ] ;
guint8 ls = tvb_get_guint8 ( tvb , offset + 1 ) ;
int print_count = 0 ;
int idx ;
ls_buffer [ 0 ] = ' \0 ' ;
for ( idx = 0 ; idx < 8 ; idx + + ) {
int bit = ls & 1 ;
if ( bit ) {
if ( print_count ! = 0 ) {
g_strlcat ( ls_buffer , " , " , 512 ) ;
}
g_strlcat ( ls_buffer , linestate_bits [ idx ] , 512 ) ;
print_count + + ;
2003-04-22 19:57:33 +00:00
}
2012-03-19 21:12:45 +00:00
ls = ls > > 1 ;
}
2014-12-06 00:42:47 +00:00
proto_tree_add_string_format ( tree , hf_line , tvb , offset , 2 , ls_buffer , print_pattern , source , ls_buffer ) ;
2003-04-22 19:57:33 +00:00
} else {
2012-03-19 21:12:45 +00:00
const char * print_pattern = ( cmd = = TNCOMPORT_SETLINESTATEMASK ) ?
" %s <Invalid Linestate Mask> " : " %s <Invalid Linestate Packet> " ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_linestate , print_pattern , source ) ;
2003-04-22 19:57:33 +00:00
}
break ;
2009-09-24 04:52:35 +00:00
2003-04-22 19:57:33 +00:00
case TNCOMPORT_SETMODEMSTATEMASK :
case TNCOMPORT_NOTIFYMODEMSTATE :
len - - ;
if ( len > = 1 ) {
2012-03-19 21:12:45 +00:00
const char * print_pattern = ( cmd = = TNCOMPORT_SETMODEMSTATEMASK ) ?
" %s Set Modemstate Mask: %s " : " %s Modemstate: %s " ;
2014-12-06 00:42:47 +00:00
int hf_modem = ( cmd = = TNCOMPORT_SETMODEMSTATEMASK ) ?
hf_telnet_comport_set_modemstate_mask : hf_telnet_comport_modemstate ;
2012-03-19 21:12:45 +00:00
char ms_buffer [ 256 ] ;
guint8 ms = tvb_get_guint8 ( tvb , offset + 1 ) ;
int print_count = 0 ;
int idx ;
ms_buffer [ 0 ] = ' \0 ' ;
for ( idx = 0 ; idx < 8 ; idx + + ) {
int bit = ms & 1 ;
if ( bit ) {
if ( print_count ! = 0 ) {
g_strlcat ( ms_buffer , " , " , 256 ) ;
}
g_strlcat ( ms_buffer , modemstate_bits [ idx ] , 256 ) ;
print_count + + ;
2003-04-22 19:57:33 +00:00
}
2012-03-19 21:12:45 +00:00
ms = ms > > 1 ;
}
2014-12-06 00:42:47 +00:00
proto_tree_add_string_format ( tree , hf_modem , tvb , offset , 2 , ms_buffer , print_pattern , source , ms_buffer ) ;
2003-04-22 19:57:33 +00:00
} else {
2012-03-19 21:12:45 +00:00
const char * print_pattern = ( cmd = = TNCOMPORT_SETMODEMSTATEMASK ) ?
" %s <Invalid Modemstate Mask> " : " %s <Invalid Modemstate Packet> " ;
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_modemstate , print_pattern , source ) ;
2003-04-22 19:57:33 +00:00
}
break ;
case TNCOMPORT_FLOWCONTROLSUSPEND :
len - - ;
2014-12-06 00:42:47 +00:00
proto_tree_add_none_format ( tree , hf_telnet_comport_subopt_flow_control_suspend , tvb , offset , 1 , " %s Flow Control Suspend " , source ) ;
2003-04-22 19:57:33 +00:00
break ;
2009-09-24 04:52:35 +00:00
2003-04-22 19:57:33 +00:00
case TNCOMPORT_FLOWCONTROLRESUME :
len - - ;
2014-12-06 00:42:47 +00:00
proto_tree_add_none_format ( tree , hf_telnet_comport_subopt_flow_control_resume , tvb , offset , 1 , " %s Flow Control Resume " , source ) ;
2003-04-22 19:57:33 +00:00
break ;
2009-09-24 04:52:35 +00:00
2003-04-22 19:57:33 +00:00
case TNCOMPORT_PURGEDATA :
len - - ;
if ( len > = 1 ) {
2012-03-19 21:12:45 +00:00
guint8 purge = tvb_get_guint8 ( tvb , offset + 1 ) ;
const char * p = ( purge > 3 ) ? " <Purge invalid> " : purges [ purge ] ;
2013-09-12 16:15:54 +00:00
proto_tree_add_uint_format_value ( tree , hf_telnet_comport_subopt_purge , tvb , offset , 2 , purge ,
2013-02-27 03:58:23 +00:00
" %s %s " , source , p ) ;
2003-04-22 19:57:33 +00:00
} else {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_purge , " %s <Invalid Purge Packet> " , source ) ;
2003-04-22 19:57:33 +00:00
}
break ;
2009-09-24 04:52:35 +00:00
2003-04-22 19:57:33 +00:00
default :
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , item , & ei_telnet_invalid_subcommand , " Invalid %s subcommand %u " , optname , cmd ) ;
2003-04-22 19:57:33 +00:00
offset + + ;
len - - ;
if ( len > 0 )
2014-12-06 00:42:47 +00:00
proto_tree_add_item ( tree , hf_telnet_subcommand_data , tvb , offset , len , ENC_NA ) ;
2003-04-22 19:57:33 +00:00
return ;
}
}
2003-02-24 01:04:30 +00:00
static const value_string rfc_opt_vals [ ] = {
2012-03-19 21:12:45 +00:00
{ 0 , " OFF " } ,
{ 1 , " ON " } ,
{ 2 , " RESTART-ANY " } ,
{ 3 , " RESTART-XON " } ,
{ 0 , NULL }
2003-02-24 01:04:30 +00:00
} ;
static void
2004-02-03 11:40:41 +00:00
dissect_rfc_subopt ( packet_info * pinfo _U_ , const char * optname _U_ , tvbuff_t * tvb , int offset ,
2013-02-27 03:58:23 +00:00
int len _U_ , proto_tree * tree , proto_item * item _U_ )
2003-02-24 01:04:30 +00:00
{
2013-02-27 03:58:23 +00:00
proto_tree_add_item ( tree , hf_telnet_rfc_subopt_cmd , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2003-02-24 01:04:30 +00:00
}
2012-03-19 21:12:45 +00:00
# define TN_ENC_IS 0
# define TN_ENC_SUPPORT 1
# define TN_ENC_REPLY 2
# define TN_ENC_START 3
# define TN_ENC_END 4
# define TN_ENC_REQUEST_START 5
# define TN_ENC_REQUEST_END 6
# define TN_ENC_ENC_KEYID 7
# define TN_ENC_DEC_KEYID 8
2006-05-18 17:08:41 +00:00
static const value_string enc_cmd_vals [ ] = {
2012-03-19 21:12:45 +00:00
{ TN_ENC_IS , " IS " } ,
{ TN_ENC_SUPPORT , " SUPPORT " } ,
{ TN_ENC_REPLY , " REPLY " } ,
{ TN_ENC_START , " START " } ,
{ TN_ENC_END , " END " } ,
{ TN_ENC_REQUEST_START , " REQUEST-START " } ,
{ TN_ENC_REQUEST_END , " REQUEST-END " } ,
{ TN_ENC_ENC_KEYID , " ENC_KEYID " } ,
{ TN_ENC_DEC_KEYID , " DEC_KEYID " } ,
{ 0 , NULL }
2006-05-18 17:08:41 +00:00
} ;
2012-03-19 21:12:45 +00:00
# define TN_ENCTYPE_NULL 0
# define TN_ENCTYPE_DES_CFB64 1
# define TN_ENCTYPE_DES_OFB64 2
# define TN_ENCTYPE_DES3_CFB64 3
# define TN_ENCTYPE_DES3_OFB64 4
# define TN_ENCTYPE_CAST5_40_CFB64 8
# define TN_ENCTYPE_CAST5_40_OFB64 9
# define TN_ENCTYPE_CAST128_CFB64 10
# define TN_ENCTYPE_CAST128_OFB64 11
2006-05-18 17:08:41 +00:00
static const value_string enc_type_vals [ ] = {
2012-03-19 21:12:45 +00:00
{ TN_ENCTYPE_NULL , " NULL " } ,
{ TN_ENCTYPE_DES_CFB64 , " DES_CFB64 " } ,
{ TN_ENCTYPE_DES_OFB64 , " DES_OFB64 " } ,
{ TN_ENCTYPE_DES3_CFB64 , " DES3_CFB64 " } ,
{ TN_ENCTYPE_DES3_OFB64 , " DES3_OFB64 " } ,
{ TN_ENCTYPE_CAST5_40_CFB64 , " CAST5_40_CFB64 " } ,
{ TN_ENCTYPE_CAST5_40_OFB64 , " CAST5_40_OFB64 " } ,
{ TN_ENCTYPE_CAST128_CFB64 , " CAST128_CFB64 " } ,
{ TN_ENCTYPE_CAST128_OFB64 , " CAST128_OFB64 " } ,
{ 0 , NULL }
2006-05-18 17:08:41 +00:00
} ;
2004-02-02 11:07:29 +00:00
2012-03-19 21:12:45 +00:00
# define TN_AC_IS 0
# define TN_AC_SEND 1
# define TN_AC_REPLY 2
# define TN_AC_NAME 3
2004-02-02 11:07:29 +00:00
static const value_string auth_cmd_vals [ ] = {
2012-03-19 21:12:45 +00:00
{ TN_AC_IS , " IS " } ,
{ TN_AC_SEND , " SEND " } ,
{ TN_AC_REPLY , " REPLY " } ,
{ TN_AC_NAME , " NAME " } ,
{ 0 , NULL }
2004-02-02 11:07:29 +00:00
} ;
2012-03-19 21:12:45 +00:00
# define TN_AT_NULL 0
# define TN_AT_KRB4 1
# define TN_AT_KRB5 2
# define TN_AT_SPX 3
# define TN_AT_MINK 4
# define TN_AT_SRP 5
# define TN_AT_RSA 6
# define TN_AT_SSL 7
# define TN_AT_LOKI 10
# define TN_AT_SSA 11
# define TN_AT_KEA_SJ 12
# define TN_AT_KEA_SJ_INTEG 13
# define TN_AT_DSS 14
# define TN_AT_NTLM 15
2004-02-02 11:07:29 +00:00
static const value_string auth_type_vals [ ] = {
2012-03-19 21:12:45 +00:00
{ TN_AT_NULL , " NULL " } ,
{ TN_AT_KRB4 , " Kerberos v4 " } ,
{ TN_AT_KRB5 , " Kerberos v5 " } ,
{ TN_AT_SPX , " SPX " } ,
{ TN_AT_MINK , " MINK " } ,
{ TN_AT_SRP , " SRP " } ,
{ TN_AT_RSA , " RSA " } ,
{ TN_AT_SSL , " SSL " } ,
{ TN_AT_LOKI , " LOKI " } ,
{ TN_AT_SSA , " SSA " } ,
{ TN_AT_KEA_SJ , " KEA_SJ " } ,
{ TN_AT_KEA_SJ_INTEG , " KEA_SJ_INTEG " } ,
{ TN_AT_DSS , " DSS " } ,
{ TN_AT_NTLM , " NTLM " } ,
{ 0 , NULL }
2004-02-02 11:07:29 +00:00
} ;
static const true_false_string auth_mod_cred_fwd = {
2012-03-19 21:12:45 +00:00
" Client WILL forward auth creds " ,
" Client will NOT forward auth creds "
2004-02-02 11:07:29 +00:00
} ;
static const true_false_string auth_mod_who = {
2012-03-19 21:12:45 +00:00
" Mask server to client " ,
" Mask client to server "
2004-02-02 11:07:29 +00:00
} ;
static const true_false_string auth_mod_how = {
2012-03-19 21:12:45 +00:00
" MUTUAL authentication " ,
" One Way authentication "
2004-02-02 11:07:29 +00:00
} ;
2012-03-19 21:12:45 +00:00
# define TN_AM_OFF 0x00
# define TN_AM_USING_TELOPT 0x01
# define TN_AM_AFTER_EXCHANGE 0x02
# define TN_AM_RESERVED 0x04
2004-02-02 11:07:29 +00:00
static const value_string auth_mod_enc [ ] = {
2012-03-19 21:12:45 +00:00
{ TN_AM_OFF , " Off " } ,
{ TN_AM_USING_TELOPT , " Telnet Options " } ,
{ TN_AM_AFTER_EXCHANGE , " After Exchange " } ,
{ TN_AM_RESERVED , " Reserved " } ,
{ 0 , NULL }
2004-02-02 11:07:29 +00:00
} ;
2012-03-19 21:12:45 +00:00
# define TN_KRB5_TYPE_AUTH 0
# define TN_KRB5_TYPE_REJECT 1
# define TN_KRB5_TYPE_ACCEPT 2
# define TN_KRB5_TYPE_RESPONSE 3
# define TN_KRB5_TYPE_FORWARD 4
# define TN_KRB5_TYPE_FORWARD_ACCEPT 5
# define TN_KRB5_TYPE_FORWARD_REJECT 6
2004-02-03 11:40:41 +00:00
static const value_string auth_krb5_types [ ] = {
2012-03-19 21:12:45 +00:00
{ TN_KRB5_TYPE_AUTH , " Auth " } ,
{ TN_KRB5_TYPE_REJECT , " Reject " } ,
{ TN_KRB5_TYPE_ACCEPT , " Accept " } ,
{ TN_KRB5_TYPE_RESPONSE , " Response " } ,
{ TN_KRB5_TYPE_FORWARD , " Forward " } ,
{ TN_KRB5_TYPE_FORWARD_ACCEPT , " Forward Accept " } ,
{ TN_KRB5_TYPE_FORWARD_REJECT , " Forward Reject " } ,
{ 0 , NULL }
2004-02-03 11:40:41 +00:00
} ;
static void
dissect_authentication_type_pair ( packet_info * pinfo _U_ , tvbuff_t * tvb , int offset , proto_tree * tree )
{
2015-05-22 02:20:29 +00:00
static const int * auth_mods [ ] = {
& hf_telnet_auth_mod_enc ,
& hf_telnet_auth_mod_cred_fwd ,
& hf_telnet_auth_mod_how ,
& hf_telnet_auth_mod_who ,
NULL
} ;
2004-02-03 11:40:41 +00:00
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( tree , hf_telnet_auth_type , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2015-05-22 02:20:29 +00:00
proto_tree_add_bitmask_list ( tree , tvb , offset + 1 , 1 , auth_mods , ENC_BIG_ENDIAN ) ;
2004-02-03 11:40:41 +00:00
}
2004-02-03 18:41:19 +00:00
/* no kerberos blobs are ever >10kb ? (arbitrary limit) */
2012-03-19 21:12:45 +00:00
# define MAX_KRB5_BLOB_LEN 10240
2004-02-03 18:41:19 +00:00
2004-02-03 11:40:41 +00:00
static tvbuff_t *
unescape_and_tvbuffify_telnet_option ( packet_info * pinfo , tvbuff_t * tvb , int offset , int len )
{
2012-03-19 21:12:45 +00:00
tvbuff_t * krb5_tvb ;
guint8 * buf ;
const guint8 * spos ;
guint8 * dpos ;
int skip , l ;
if ( len > = MAX_KRB5_BLOB_LEN )
return NULL ;
spos = tvb_get_ptr ( tvb , offset , len ) ;
2016-07-20 02:53:28 +00:00
buf = ( guint8 * ) wmem_alloc ( pinfo - > pool , len ) ;
2012-03-19 21:12:45 +00:00
dpos = buf ;
skip = 0 ;
l = len ;
while ( l > 0 ) {
if ( ( spos [ 0 ] = = 0xff ) & & ( spos [ 1 ] = = 0xff ) ) {
skip + + ;
l - = 2 ;
* ( dpos + + ) = 0xff ;
spos + = 2 ;
continue ;
}
* ( dpos + + ) = * ( spos + + ) ;
l - - ;
}
krb5_tvb = tvb_new_child_real_data ( tvb , buf , len - skip , len - skip ) ;
add_new_data_source ( pinfo , krb5_tvb , " Unpacked Telnet Option " ) ;
return krb5_tvb ;
2004-02-03 11:40:41 +00:00
}
/* as per RFC2942 */
static void
dissect_krb5_authentication_data ( packet_info * pinfo , tvbuff_t * tvb , int offset , int len , proto_tree * tree , guint8 acmd )
{
2012-03-19 21:12:45 +00:00
tvbuff_t * krb5_tvb ;
guint8 krb5_cmd ;
2013-02-27 03:58:23 +00:00
proto_item * ti ;
2004-02-03 11:40:41 +00:00
2012-03-19 21:12:45 +00:00
dissect_authentication_type_pair ( pinfo , tvb , offset , tree ) ;
offset + = 2 ;
len - = 2 ;
2004-02-03 11:40:41 +00:00
2012-03-19 21:12:45 +00:00
krb5_cmd = tvb_get_guint8 ( tvb , offset ) ;
2013-02-27 03:58:23 +00:00
ti = proto_tree_add_uint ( tree , hf_telnet_auth_krb5_type , tvb , offset , 1 , krb5_cmd ) ;
2012-03-19 21:12:45 +00:00
offset + + ;
len - - ;
/* IAC SB AUTHENTICATION IS <authentication-type-pair> AUTH <Kerberos V5 KRB_AP_REQ message> IAC SE */
if ( ( acmd = = TN_AC_IS ) & & ( krb5_cmd = = TN_KRB5_TYPE_AUTH ) ) {
if ( len ) {
krb5_tvb = unescape_and_tvbuffify_telnet_option ( pinfo , tvb , offset , len ) ;
if ( krb5_tvb )
dissect_kerberos_main ( krb5_tvb , pinfo , tree , FALSE , NULL ) ;
else
2013-09-12 16:15:54 +00:00
expert_add_info_format ( pinfo , ti , & ei_telnet_kerberos_blob_too_long , " Kerberos blob (too long to dissect - length %u > %u) " , len , MAX_KRB5_BLOB_LEN ) ;
2012-03-19 21:12:45 +00:00
}
}
2004-02-03 11:40:41 +00:00
2012-03-19 21:12:45 +00:00
/* IAC SB AUTHENTICATION REPLY <authentication-type-pair> ACCEPT IAC SE */
/* nothing more to dissect */
2004-02-03 11:40:41 +00:00
2012-03-19 21:12:45 +00:00
/* IAC SB AUTHENTICATION REPLY <authentication-type-pair> REJECT <optional reason for rejection> IAC SE*/
2004-02-03 11:40:41 +00:00
/*qqq*/
2012-03-19 21:12:45 +00:00
/* IAC SB AUTHENTICATION REPLY <authentication-type-pair> RESPONSE <KRB_AP_REP message> IAC SE */
if ( ( acmd = = TN_AC_REPLY ) & & ( krb5_cmd = = TN_KRB5_TYPE_RESPONSE ) ) {
if ( len ) {
krb5_tvb = unescape_and_tvbuffify_telnet_option ( pinfo , tvb , offset , len ) ;
dissect_kerberos_main ( krb5_tvb , pinfo , tree , FALSE , NULL ) ;
}
}
2004-02-03 11:40:41 +00:00
2012-03-19 21:12:45 +00:00
/* IAC SB AUTHENTICATION <authentication-type-pair> FORWARD <KRB_CRED message> IAC SE */
/* XXX unclear what this one looks like */
2004-02-03 11:40:41 +00:00
2012-03-19 21:12:45 +00:00
/* IAC SB AUTHENTICATION <authentication-type-pair> FORWARD_ACCEPT IAC SE */
/* nothing more to dissect */
2004-02-03 11:40:41 +00:00
2012-03-19 21:12:45 +00:00
/* IAC SB AUTHENTICATION <authentication-type-pair> FORWARD_REJECT */
/* nothing more to dissect */
2004-02-03 11:40:41 +00:00
}
2004-02-02 11:07:29 +00:00
static void
2013-09-12 16:15:54 +00:00
dissect_authentication_subopt ( packet_info * pinfo , const char * optname _U_ , tvbuff_t * tvb , int offset , int len ,
2013-02-27 05:53:46 +00:00
proto_tree * tree , proto_item * item _U_ )
2004-02-02 11:07:29 +00:00
{
2012-03-19 21:12:45 +00:00
guint8 acmd ;
2004-02-02 11:07:29 +00:00
2004-02-03 11:40:41 +00:00
/* XXX here we should really split it up in a conversation struct keeping
2012-03-19 21:12:45 +00:00
track of what method we actually use and not just assume it is always
kerberos v5
2004-02-03 11:40:41 +00:00
*/
2012-03-19 21:12:45 +00:00
acmd = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_uint ( tree , hf_telnet_auth_cmd , tvb , offset , 1 , acmd ) ;
offset + + ;
len - - ;
switch ( acmd ) {
case TN_AC_REPLY :
case TN_AC_IS :
2014-09-16 13:43:06 +00:00
/* XXX here we shouldn't just assume it is krb5 */
2012-03-19 21:12:45 +00:00
dissect_krb5_authentication_data ( pinfo , tvb , offset , len , tree , acmd ) ;
break ;
case TN_AC_SEND :
while ( len > 0 ) {
dissect_authentication_type_pair ( pinfo , tvb , offset , tree ) ;
offset + = 2 ;
len - = 2 ;
}
break ;
case TN_AC_NAME :
2014-04-06 14:57:33 +00:00
proto_tree_add_item ( tree , hf_telnet_auth_name , tvb , offset , len , ENC_ASCII | ENC_NA ) ;
2012-03-19 21:12:45 +00:00
break ;
}
2004-02-02 11:07:29 +00:00
}
2006-05-18 17:08:41 +00:00
/* This function only uses the octet in the buffer at 'offset' */
static void dissect_encryption_type ( tvbuff_t * tvb , int offset , proto_tree * tree ) {
2012-03-19 21:12:45 +00:00
guint8 etype ;
etype = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_uint ( tree , hf_telnet_enc_type , tvb , offset , 1 , etype ) ;
2006-05-18 17:08:41 +00:00
}
static void
2013-02-27 03:58:23 +00:00
dissect_encryption_subopt ( packet_info * pinfo , const char * optname _U_ , tvbuff_t * tvb , int offset , int len ,
proto_tree * tree , proto_item * item )
2006-05-18 17:08:41 +00:00
{
2012-03-19 21:12:45 +00:00
guint8 ecmd , key_first_octet ;
ecmd = tvb_get_guint8 ( tvb , offset ) ;
proto_tree_add_uint ( tree , hf_telnet_enc_cmd , tvb , offset , 1 , ecmd ) ;
offset + + ;
len - - ;
switch ( ecmd ) {
case TN_ENC_IS :
case TN_ENC_REPLY :
/* encryption type, type-specific data ... */
if ( len > 0 ) {
dissect_encryption_type ( tvb , offset , tree ) ;
offset + + ;
len - - ;
2014-12-06 00:42:47 +00:00
proto_tree_add_item ( tree , hf_telnet_enc_type_data , tvb , offset , len , ENC_NA ) ;
2012-03-19 21:12:45 +00:00
}
break ;
case TN_ENC_SUPPORT :
/* list of encryption types ... */
while ( len > 0 ) {
dissect_encryption_type ( tvb , offset , tree ) ;
offset + + ;
len - - ;
}
break ;
case TN_ENC_START :
/* keyid ... */
if ( len > 0 ) {
key_first_octet = tvb_get_guint8 ( tvb , offset ) ;
2014-12-06 00:42:47 +00:00
proto_tree_add_bytes_format ( tree , hf_telnet_enc_key_id , tvb , offset , len , NULL , ( key_first_octet = = 0 ) ? " Default key " : " Key ID " ) ;
2012-03-19 21:12:45 +00:00
}
break ;
case TN_ENC_END :
/* no data */
break ;
case TN_ENC_REQUEST_START :
/* (optional) keyid */
if ( len > 0 )
2014-12-06 00:42:47 +00:00
proto_tree_add_bytes_format ( tree , hf_telnet_enc_key_id , tvb , offset , len , NULL , " Key ID (advisory) " ) ;
2012-03-19 21:12:45 +00:00
break ;
case TN_ENC_REQUEST_END :
/* no data */
break ;
case TN_ENC_ENC_KEYID :
case TN_ENC_DEC_KEYID :
/* (optional) keyid - if not supplied, there are no more known keys */
if ( len > 0 )
2014-12-06 00:42:47 +00:00
proto_tree_add_item ( tree , hf_telnet_enc_key_id , tvb , offset , len , ENC_NA ) ;
2012-03-19 21:12:45 +00:00
break ;
default :
2013-08-23 03:17:34 +00:00
expert_add_info ( pinfo , item , & ei_telnet_enc_cmd_unknown ) ;
2012-03-19 21:12:45 +00:00
}
2006-05-18 17:08:41 +00:00
}
2003-02-24 01:04:30 +00:00
static tn_opt options [ ] = {
{
2012-03-19 21:12:45 +00:00
" Binary Transmission " , /* RFC 856 */
NULL , /* no suboption negotiation */
2003-02-24 01:04:30 +00:00
NO_LENGTH ,
0 ,
NULL
} ,
{
2012-03-19 21:12:45 +00:00
" Echo " , /* RFC 857 */
NULL , /* no suboption negotiation */
2003-02-24 01:04:30 +00:00
NO_LENGTH ,
0 ,
NULL
} ,
2009-09-24 04:52:35 +00:00
{
2012-03-19 21:12:45 +00:00
" Reconnection " , /* DOD Protocol Handbook */
2003-02-24 01:04:30 +00:00
NULL ,
NO_LENGTH ,
0 ,
NULL
} ,
{
2012-03-19 21:12:45 +00:00
" Suppress Go Ahead " , /* RFC 858 */
NULL , /* no suboption negotiation */
2003-02-24 01:04:30 +00:00
NO_LENGTH ,
0 ,
NULL
} ,
{
2012-03-19 21:12:45 +00:00
" Approx Message Size Negotiation " , /* Ethernet spec(!) */
2003-02-24 01:04:30 +00:00
NULL ,
NO_LENGTH ,
0 ,
NULL
} ,
{
2012-03-19 21:12:45 +00:00
" Status " , /* RFC 859 */
2003-02-24 01:04:30 +00:00
& ett_status_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Timing Mark " , /* RFC 860 */
NULL , /* no suboption negotiation */
2003-02-24 01:04:30 +00:00
NO_LENGTH ,
0 ,
NULL
} ,
{
2012-03-19 21:12:45 +00:00
" Remote Controlled Trans and Echo " , /* RFC 726 */
2003-02-24 01:04:30 +00:00
& ett_rcte_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Output Line Width " , /* DOD Protocol Handbook */
2003-02-24 01:04:30 +00:00
& ett_olw_subopt ,
2012-03-19 21:12:45 +00:00
VARIABLE_LENGTH , /* XXX - fill me in */
0 , /* XXX - fill me in */
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Output Page Size " , /* DOD Protocol Handbook */
2003-02-24 01:04:30 +00:00
& ett_ops_subopt ,
2012-03-19 21:12:45 +00:00
VARIABLE_LENGTH , /* XXX - fill me in */
0 , /* XXX - fill me in */
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Output Carriage-Return Disposition " , /* RFC 652 */
2003-02-24 01:04:30 +00:00
& ett_crdisp_subopt ,
FIXED_LENGTH ,
2 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Output Horizontal Tab Stops " , /* RFC 653 */
2003-02-24 01:04:30 +00:00
& ett_htstops_subopt ,
VARIABLE_LENGTH ,
1 ,
dissect_htstops_subopt
} ,
{
2012-03-19 21:12:45 +00:00
" Output Horizontal Tab Disposition " , /* RFC 654 */
2003-02-24 01:04:30 +00:00
& ett_htdisp_subopt ,
FIXED_LENGTH ,
2 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Output Formfeed Disposition " , /* RFC 655 */
2003-02-24 01:04:30 +00:00
& ett_ffdisp_subopt ,
FIXED_LENGTH ,
2 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Output Vertical Tabstops " , /* RFC 656 */
2003-02-24 01:04:30 +00:00
& ett_vtstops_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Output Vertical Tab Disposition " , /* RFC 657 */
2003-02-24 01:04:30 +00:00
& ett_vtdisp_subopt ,
FIXED_LENGTH ,
2 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Output Linefeed Disposition " , /* RFC 658 */
2003-02-24 01:04:30 +00:00
& ett_lfdisp_subopt ,
FIXED_LENGTH ,
2 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Extended ASCII " , /* RFC 698 */
2003-02-24 01:04:30 +00:00
& ett_extasc_subopt ,
FIXED_LENGTH ,
2 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Logout " , /* RFC 727 */
NULL , /* no suboption negotiation */
2003-02-24 01:04:30 +00:00
NO_LENGTH ,
0 ,
NULL
} ,
{
2012-03-19 21:12:45 +00:00
" Byte Macro " , /* RFC 735 */
2003-02-24 01:04:30 +00:00
& ett_bytemacro_subopt ,
VARIABLE_LENGTH ,
2 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Data Entry Terminal " , /* RFC 732, RFC 1043 */
2003-02-24 01:04:30 +00:00
& ett_det_subopt ,
VARIABLE_LENGTH ,
2 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" SUPDUP " , /* RFC 734, RFC 736 */
NULL , /* no suboption negotiation */
2003-02-24 01:04:30 +00:00
NO_LENGTH ,
0 ,
NULL
} ,
{
2012-03-19 21:12:45 +00:00
" SUPDUP Output " , /* RFC 749 */
2003-02-24 01:04:30 +00:00
& ett_supdupout_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Send Location " , /* RFC 779 */
2003-02-24 01:04:30 +00:00
& ett_sendloc_subopt ,
VARIABLE_LENGTH ,
0 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Terminal Type " , /* RFC 1091 */
2003-02-24 01:04:30 +00:00
& ett_termtype_subopt ,
VARIABLE_LENGTH ,
1 ,
dissect_string_subopt
} ,
{
2012-03-19 21:12:45 +00:00
" End of Record " , /* RFC 885 */
NULL , /* no suboption negotiation */
2003-02-24 01:04:30 +00:00
NO_LENGTH ,
0 ,
NULL
} ,
{
2012-03-19 21:12:45 +00:00
" TACACS User Identification " , /* RFC 927 */
2003-02-24 01:04:30 +00:00
& ett_tacacsui_subopt ,
FIXED_LENGTH ,
4 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Output Marking " , /* RFC 933 */
2003-02-24 01:04:30 +00:00
& ett_outmark_subopt ,
VARIABLE_LENGTH ,
1 ,
dissect_outmark_subopt ,
} ,
{
2012-03-19 21:12:45 +00:00
" Terminal Location Number " , /* RFC 946 */
2003-02-24 01:04:30 +00:00
& ett_tlocnum_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Telnet 3270 Regime " , /* RFC 1041 */
2003-02-24 01:04:30 +00:00
& ett_tn3270reg_subopt ,
VARIABLE_LENGTH ,
1 ,
2009-07-17 06:49:58 +00:00
dissect_tn3270_regime_subopt
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" X.3 PAD " , /* RFC 1053 */
2003-02-24 01:04:30 +00:00
& ett_x3pad_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Negotiate About Window Size " , /* RFC 1073, DW183 */
2003-02-24 01:04:30 +00:00
& ett_naws_subopt ,
FIXED_LENGTH ,
4 ,
dissect_naws_subopt
} ,
{
2012-03-19 21:12:45 +00:00
" Terminal Speed " , /* RFC 1079 */
2003-02-24 01:04:30 +00:00
& ett_tspeed_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Remote Flow Control " , /* RFC 1372 */
2003-02-24 01:04:30 +00:00
& ett_rfc_subopt ,
FIXED_LENGTH ,
1 ,
dissect_rfc_subopt
} ,
{
2012-03-19 21:12:45 +00:00
" Linemode " , /* RFC 1184 */
2003-02-24 01:04:30 +00:00
& ett_linemode_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" X Display Location " , /* RFC 1096 */
2003-02-24 01:04:30 +00:00
& ett_xdpyloc_subopt ,
VARIABLE_LENGTH ,
1 ,
dissect_string_subopt
} ,
{
2012-03-19 21:12:45 +00:00
" Environment Option " , /* RFC 1408, RFC 1571 */
2003-02-24 01:04:30 +00:00
& ett_env_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Authentication Option " , /* RFC 2941 */
2003-02-24 01:04:30 +00:00
& ett_auth_subopt ,
VARIABLE_LENGTH ,
1 ,
2009-09-24 04:52:35 +00:00
dissect_authentication_subopt
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Encryption Option " , /* RFC 2946 */
2003-02-24 01:04:30 +00:00
& ett_enc_subopt ,
VARIABLE_LENGTH ,
1 ,
2006-05-18 17:08:41 +00:00
dissect_encryption_subopt
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" New Environment Option " , /* RFC 1572 */
2003-02-24 01:04:30 +00:00
& ett_newenv_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-02-24 01:04:30 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" TN3270E " , /* RFC 1647 */
2003-02-24 01:04:30 +00:00
& ett_tn3270e_subopt ,
VARIABLE_LENGTH ,
1 ,
2009-07-17 06:49:58 +00:00
dissect_tn3270e_subopt
2003-02-24 01:04:30 +00:00
} ,
2003-04-22 19:57:33 +00:00
{
2012-03-19 21:12:45 +00:00
" XAUTH " , /* XAUTH */
2003-04-22 19:57:33 +00:00
& ett_xauth_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-04-22 19:57:33 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" CHARSET " , /* CHARSET */
2003-04-22 19:57:33 +00:00
& ett_charset_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-04-22 19:57:33 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" Remote Serial Port " , /* Remote Serial Port */
2003-04-22 19:57:33 +00:00
& ett_rsp_subopt ,
VARIABLE_LENGTH ,
1 ,
2012-03-19 21:12:45 +00:00
NULL /* XXX - fill me in */
2003-04-22 19:57:33 +00:00
} ,
{
2012-03-19 21:12:45 +00:00
" COM Port Control " , /* RFC 2217 */
2003-04-22 19:57:33 +00:00
& ett_comport_subopt ,
VARIABLE_LENGTH ,
1 ,
dissect_comport_subopt
2015-12-11 23:47:15 +00:00
} ,
{
" Suppress Local Echo " , /* draft-rfced-exp-atmar-00 */
NULL ,
NO_LENGTH ,
0 ,
NULL
} ,
{
" Start TLS " , /* draft-ietf-tn3270e-telnet-tls-06 */
& ett_starttls_subopt ,
FIXED_LENGTH ,
1 ,
dissect_starttls_subopt
} ,
{
" KERMIT " , /* RFC 2840 */
NULL ,
VARIABLE_LENGTH ,
1 ,
NULL /* XXX - stub */
} ,
{
" SEND-URL " , /* draft-croft-telnet-url-trans-00 */
NULL ,
VARIABLE_LENGTH ,
1 ,
NULL /* XXX - stub */
} ,
{
" FORWARD_X " , /* draft-altman-telnet-fwdx-03 */
NULL ,
VARIABLE_LENGTH ,
1 ,
NULL /* XXX - stub */
2006-05-18 17:08:41 +00:00
}
2009-09-24 04:52:35 +00:00
1999-04-05 21:54:41 +00:00
} ;
2012-03-19 21:12:45 +00:00
# define NOPTIONS array_length(options)
2000-03-23 10:25:38 +00:00
static int
2013-02-27 03:58:23 +00:00
telnet_sub_option ( packet_info * pinfo , proto_tree * option_tree , proto_item * option_item , tvbuff_t * tvb , int start_offset )
1999-04-05 21:54:41 +00:00
{
2012-03-19 21:12:45 +00:00
int offset = start_offset ;
guint8 opt_byte ;
int subneg_len ;
2003-02-24 01:04:30 +00:00
const char * opt ;
2012-03-19 21:12:45 +00:00
int iac_offset ;
guint len ;
tvbuff_t * unescaped_tvb ;
2013-02-27 03:58:23 +00:00
void ( * dissect ) ( packet_info * , const char * , tvbuff_t * , int , int , proto_tree * , proto_item * ) ;
2012-03-19 21:12:45 +00:00
gint cur_offset ;
gboolean iac_found ;
1999-04-05 21:54:41 +00:00
2005-06-18 15:41:26 +00:00
/*
2009-09-24 04:52:35 +00:00
* As data with value iac ( 0xff ) is possible , this value must be escaped
* with iac ( rfc 854 ) .
2005-06-18 15:41:26 +00:00
*/
int iac_data = 0 ;
2012-03-19 21:12:45 +00:00
offset + = 2 ; /* skip IAC and SB */
1999-04-05 21:54:41 +00:00
2003-02-24 01:04:30 +00:00
/* Get the option code */
2000-11-09 10:56:33 +00:00
opt_byte = tvb_get_guint8 ( tvb , offset ) ;
2005-03-13 05:48:43 +00:00
if ( opt_byte > = NOPTIONS ) {
2000-03-23 10:25:38 +00:00
opt = " <unknown option> " ;
2003-02-24 01:04:30 +00:00
dissect = NULL ;
} else {
opt = options [ opt_byte ] . name ;
dissect = options [ opt_byte ] . dissect ;
}
2000-03-23 10:25:38 +00:00
offset + + ;
2003-04-22 20:35:49 +00:00
/* Search for an unescaped IAC. */
2003-04-22 19:57:33 +00:00
cur_offset = offset ;
2015-05-22 02:20:29 +00:00
len = tvb_reported_length_remaining ( tvb , offset ) ;
2003-04-22 19:57:33 +00:00
do {
2012-03-19 21:12:45 +00:00
iac_offset = tvb_find_guint8 ( tvb , cur_offset , len , TN_IAC ) ;
iac_found = TRUE ;
if ( iac_offset = = - 1 ) {
/* None found - run to the end of the packet. */
offset + = len ;
} else {
if ( ( ( guint ) ( iac_offset + 1 ) > = len ) | |
( tvb_get_guint8 ( tvb , iac_offset + 1 ) ! = TN_IAC ) ) {
/* We really found a single IAC, so we're done */
offset = iac_offset ;
2003-04-22 19:57:33 +00:00
} else {
2012-03-19 21:12:45 +00:00
/*
* We saw an escaped IAC , so we have to move ahead to the
* next section
*/
iac_found = FALSE ;
cur_offset = iac_offset + 2 ;
iac_data + = 1 ;
2003-04-22 19:57:33 +00:00
}
2012-03-19 21:12:45 +00:00
}
1999-04-05 21:54:41 +00:00
2003-04-22 19:57:33 +00:00
} while ( ! iac_found ) ;
2009-09-24 04:52:35 +00:00
2000-03-23 10:25:38 +00:00
subneg_len = offset - start_offset ;
1999-04-05 21:54:41 +00:00
2012-03-19 21:12:45 +00:00
start_offset + = 3 ; /* skip IAC, SB, and option code */
2003-02-24 01:04:30 +00:00
subneg_len - = 3 ;
1999-04-05 21:54:41 +00:00
2003-02-24 01:04:30 +00:00
if ( subneg_len > 0 ) {
/* Now dissect the suboption parameters. */
2003-02-24 19:25:00 +00:00
if ( dissect ! = NULL ) {
2005-05-30 21:04:58 +00:00
switch ( options [ opt_byte ] . len_type ) {
case NO_LENGTH :
2012-03-19 21:12:45 +00:00
/* There isn't supposed to *be* sub-option negotiation for this. */
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , option_item , & ei_telnet_suboption_length , " Bogus suboption data " ) ;
2012-03-19 21:12:45 +00:00
return offset ;
2005-05-30 21:04:58 +00:00
case FIXED_LENGTH :
2012-03-19 21:12:45 +00:00
/* Make sure the length is what it's supposed to be. */
if ( subneg_len - iac_data ! = options [ opt_byte ] . optlen ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , option_item , & ei_telnet_suboption_length , " Suboption parameter length is %d, should be %d " , subneg_len , options [ opt_byte ] . optlen ) ;
2012-03-19 21:12:45 +00:00
return offset ;
}
break ;
2005-05-30 21:04:58 +00:00
case VARIABLE_LENGTH :
2012-03-19 21:12:45 +00:00
/* Make sure the length is greater than the minimum. */
if ( subneg_len - iac_data < options [ opt_byte ] . optlen ) {
2013-09-09 00:44:09 +00:00
expert_add_info_format ( pinfo , option_item , & ei_telnet_suboption_length , " Suboption parameter length is %d, should be at least %d " , subneg_len , options [ opt_byte ] . optlen ) ;
2012-03-19 21:12:45 +00:00
return offset ;
}
break ;
2005-05-30 21:04:58 +00:00
}
2003-02-24 19:25:00 +00:00
/* We have a dissector for this suboption's parameters; call it. */
2009-09-24 04:52:35 +00:00
if ( iac_data > 0 ) {
2009-06-02 00:04:55 +00:00
/* Data is escaped, we have to unescape it. */
unescaped_tvb = unescape_and_tvbuffify_telnet_option ( pinfo , tvb , start_offset , subneg_len ) ;
2013-02-27 03:58:23 +00:00
( * dissect ) ( pinfo , opt , unescaped_tvb , 0 , subneg_len - iac_data , option_tree , option_item ) ;
2009-06-02 00:04:55 +00:00
} else {
2013-02-27 03:58:23 +00:00
( * dissect ) ( pinfo , opt , tvb , start_offset , subneg_len , option_tree , option_item ) ;
2009-06-02 00:04:55 +00:00
}
2003-02-24 19:25:00 +00:00
} else {
/* We don't have a dissector for them; just show them as data. */
2009-09-24 04:52:35 +00:00
if ( iac_data > 0 ) {
2009-06-02 00:04:55 +00:00
/* Data is escaped, we have to unescape it. */
unescaped_tvb = unescape_and_tvbuffify_telnet_option ( pinfo , tvb , start_offset , subneg_len ) ;
2014-12-06 00:42:47 +00:00
proto_tree_add_item ( option_tree , hf_telnet_option_data , unescaped_tvb , 0 , subneg_len - iac_data , ENC_NA ) ;
2009-06-02 00:04:55 +00:00
} else {
2014-12-06 00:42:47 +00:00
proto_tree_add_item ( option_tree , hf_telnet_option_data , tvb , start_offset , subneg_len , ENC_NA ) ;
2009-06-02 00:04:55 +00:00
}
2003-02-24 19:25:00 +00:00
}
1999-04-05 21:54:41 +00:00
}
2000-03-23 10:25:38 +00:00
return offset ;
}
1999-04-05 21:54:41 +00:00
2013-02-27 03:58:23 +00:00
static void
2014-01-14 07:56:43 +00:00
telnet_suboption_name ( proto_tree * tree , tvbuff_t * tvb , int * offset , const gchar * * optname ,
2013-02-27 03:58:23 +00:00
proto_tree * * opt_tree , proto_item * * opt_item , const char * type )
2000-03-23 10:25:38 +00:00
{
2012-03-19 21:12:45 +00:00
guint8 opt_byte ;
2000-03-23 10:25:38 +00:00
const char * opt ;
2013-02-27 03:58:23 +00:00
gint ett = ett_telnet_subopt ;
2000-03-23 10:25:38 +00:00
2013-02-27 03:58:23 +00:00
opt_byte = tvb_get_guint8 ( tvb , * offset ) ;
if ( opt_byte > = NOPTIONS ) {
2000-03-23 10:25:38 +00:00
opt = " <unknown option> " ;
2013-02-27 03:58:23 +00:00
}
else {
2003-02-24 01:04:30 +00:00
opt = options [ opt_byte ] . name ;
2013-02-27 03:58:23 +00:00
if ( options [ opt_byte ] . subtree_index ! = NULL )
ett = * ( options [ opt_byte ] . subtree_index ) ;
}
* opt_item = proto_tree_add_uint_format_value ( tree , hf_telnet_subcmd , tvb , * offset , 1 , opt_byte , " %s " , opt ) ;
* opt_tree = proto_item_add_subtree ( * opt_item , ett ) ;
2002-08-28 21:04:11 +00:00
2013-02-27 03:58:23 +00:00
( * offset ) + + ;
2013-09-12 16:15:54 +00:00
( * optname ) = wmem_strdup_printf ( wmem_packet_scope ( ) , " %s %s " , type , opt ) ;
1999-04-05 21:54:41 +00:00
}
2000-03-23 10:25:38 +00:00
static int
2004-02-03 11:40:41 +00:00
telnet_command ( packet_info * pinfo , proto_tree * telnet_tree , tvbuff_t * tvb , int start_offset )
1999-04-05 21:54:41 +00:00
{
2012-03-19 21:12:45 +00:00
int offset = start_offset ;
2002-08-02 23:36:07 +00:00
guchar optcode ;
2014-01-14 07:56:43 +00:00
const gchar * optname ;
2013-02-27 03:58:23 +00:00
proto_item * cmd_item , * subopt_item = NULL ;
proto_tree * cmd_tree , * subopt_tree = NULL ;
2002-08-28 21:04:11 +00:00
2012-03-19 21:12:45 +00:00
offset + = 1 ; /* skip IAC */
2000-11-09 10:56:33 +00:00
optcode = tvb_get_guint8 ( tvb , offset ) ;
2013-09-12 16:15:54 +00:00
2014-07-06 23:32:03 +00:00
cmd_tree = proto_tree_add_subtree ( telnet_tree , tvb , start_offset , 2 , ett_telnet_cmd , & cmd_item , " Command header " ) ;
2014-12-13 17:52:20 +00:00
proto_tree_add_item ( cmd_tree , hf_telnet_cmd , tvb , offset , 1 , ENC_BIG_ENDIAN ) ;
2000-03-23 10:25:38 +00:00
offset + + ;
1999-04-05 21:54:41 +00:00
2013-02-27 03:58:23 +00:00
switch ( optcode ) {
1999-04-05 21:54:41 +00:00
case TN_WILL :
2013-02-27 03:58:23 +00:00
telnet_suboption_name ( cmd_tree , tvb , & offset , & optname , & subopt_tree , & subopt_item , " Will " ) ;
1999-04-05 21:54:41 +00:00
break ;
case TN_WONT :
2013-02-27 03:58:23 +00:00
telnet_suboption_name ( cmd_tree , tvb , & offset , & optname , & subopt_tree , & subopt_item , " Won't " ) ;
1999-04-05 21:54:41 +00:00
break ;
case TN_DO :
2013-02-27 03:58:23 +00:00
telnet_suboption_name ( cmd_tree , tvb , & offset , & optname , & subopt_tree , & subopt_item , " Do " ) ;
1999-04-05 21:54:41 +00:00
break ;
case TN_DONT :
2013-02-27 03:58:23 +00:00
telnet_suboption_name ( cmd_tree , tvb , & offset , & optname , & subopt_tree , & subopt_item , " Don't " ) ;
break ;
case TN_SB :
telnet_suboption_name ( cmd_tree , tvb , & offset , & optname , & subopt_tree , & subopt_item , " Suboption " ) ;
1999-04-05 21:54:41 +00:00
break ;
2002-10-25 21:09:36 +00:00
default :
2014-01-14 07:56:43 +00:00
optname = val_to_str_const ( optcode , cmd_vals , " <unknown option> " ) ;
2002-10-25 21:09:36 +00:00
break ;
1999-04-05 21:54:41 +00:00
}
2013-02-27 05:53:46 +00:00
proto_item_set_text ( cmd_item , " %s " , optname ) ;
2013-02-27 03:58:23 +00:00
if ( optcode = = TN_SB ) {
offset = telnet_sub_option ( pinfo , subopt_tree , subopt_item , tvb , start_offset ) ;
}
proto_item_set_len ( cmd_item , offset - start_offset ) ;
2000-03-23 10:25:38 +00:00
return offset ;
1999-04-05 21:54:41 +00:00
}
2000-09-29 19:06:12 +00:00
static void
2000-11-09 10:56:33 +00:00
telnet_add_text ( proto_tree * tree , tvbuff_t * tvb , int offset , int len )
2000-09-29 19:06:12 +00:00
{
2012-03-19 21:12:45 +00:00
gint next_offset ;
int linelen ;
guint8 c ;
2000-11-12 00:59:09 +00:00
gboolean last_char_was_cr ;
2000-09-29 19:06:12 +00:00
2000-11-13 08:58:17 +00:00
while ( len ! = 0 & & tvb_offset_exists ( tvb , offset ) ) {
2000-09-29 19:06:12 +00:00
/*
* Find the end of the line .
*/
2002-07-17 06:55:29 +00:00
linelen = tvb_find_line_end ( tvb , offset , len , & next_offset , FALSE ) ;
2012-03-19 21:12:45 +00:00
len - = next_offset - offset ; /* subtract out the line's characters */
2000-11-12 00:59:09 +00:00
/*
* In Telnet , CR NUL is the way you send a CR by itself in the
* default ASCII mode ; don ' t treat CR by itself as a line ending ,
* treat only CR NUL , CR LF , or LF by itself as a line ending .
*/
if ( next_offset = = offset + linelen + 1 & & len > = 1 ) {
/*
* Well , we saw a one - character line ending , so either it ' s a CR
* or an LF ; we have at least two characters left , including the
* CR .
*
* If the line ending is a CR , skip all subsequent CRs ; at
* least one capture appeared to have multiple CRs at the end of
* a line .
*/
if ( tvb_get_guint8 ( tvb , offset + linelen ) = = ' \r ' ) {
2012-03-19 21:12:45 +00:00
last_char_was_cr = TRUE ;
while ( len ! = 0 & & tvb_offset_exists ( tvb , next_offset ) ) {
2000-11-12 00:59:09 +00:00
c = tvb_get_guint8 ( tvb , next_offset ) ;
2012-03-19 21:12:45 +00:00
next_offset + + ; /* skip over that character */
len - - ;
2000-11-12 00:59:09 +00:00
if ( c = = ' \n ' | | ( c = = ' \0 ' & & last_char_was_cr ) ) {
/*
2012-03-19 21:12:45 +00:00
* LF is a line ending , whether preceded by CR or not .
* NUL is a line ending if preceded by CR .
*/
2000-11-12 00:59:09 +00:00
break ;
}
2012-03-19 21:12:45 +00:00
last_char_was_cr = ( c = = ' \r ' ) ;
}
2000-11-12 00:59:09 +00:00
}
}
/*
* Now compute the length of the line * including * the end - of - line
* indication , if any ; we display it all .
*/
2000-11-09 10:56:33 +00:00
linelen = next_offset - offset ;
2000-09-29 19:06:12 +00:00
2011-10-15 18:46:26 +00:00
proto_tree_add_item ( tree , hf_telnet_data , tvb , offset , linelen , ENC_ASCII | ENC_NA ) ;
2000-11-12 00:59:09 +00:00
offset = next_offset ;
2000-09-29 19:06:12 +00:00
}
}
2009-07-17 06:49:58 +00:00
static int find_unescaped_iac ( tvbuff_t * tvb , int offset , int len )
{
2012-03-19 21:12:45 +00:00
int iac_offset = offset ;
/* If we find an IAC (0XFF), make sure it is not followed by another 0XFF.
Such cases indicate that it is not an IAC at all */
while ( ( iac_offset = tvb_find_guint8 ( tvb , iac_offset , len , TN_IAC ) ) ! = - 1 & &
( tvb_get_guint8 ( tvb , iac_offset + 1 ) = = TN_IAC ) )
{
iac_offset + = 2 ;
2015-05-22 02:20:29 +00:00
len = tvb_reported_length_remaining ( tvb , iac_offset ) ;
2012-03-19 21:12:45 +00:00
}
return iac_offset ;
2009-07-17 06:49:58 +00:00
}
2015-11-14 14:23:33 +00:00
static int
dissect_telnet ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , void * data _U_ )
1999-04-05 21:54:41 +00:00
{
2012-03-19 21:12:45 +00:00
proto_tree * telnet_tree , * ti ;
tvbuff_t * next_tvb ;
gint offset = 0 ;
guint len = 0 ;
guint is_tn3270 = 0 ;
guint is_tn5250 = 0 ;
int data_len ;
gint iac_offset ;
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " TELNET " ) ;
col_set_str ( pinfo - > cinfo , COL_INFO , " Telnet Data ... " ) ;
is_tn3270 = find_tn3270_conversation ( pinfo ) ;
is_tn5250 = find_tn5250_conversation ( pinfo ) ;
ti = proto_tree_add_item ( tree , proto_telnet , tvb , offset , - 1 , ENC_NA ) ;
telnet_tree = proto_item_add_subtree ( ti , ett_telnet ) ;
/*
* Scan through the buffer looking for an IAC byte .
*/
2015-05-22 02:20:29 +00:00
while ( ( len = tvb_reported_length_remaining ( tvb , offset ) ) > 0 ) {
2012-03-19 21:12:45 +00:00
iac_offset = find_unescaped_iac ( tvb , offset , len ) ;
if ( iac_offset ! = - 1 ) {
/*
* We found an IAC byte .
* If there ' s any data before it , add that data to the
* tree , a line at a time .
*/
data_len = iac_offset - offset ;
if ( data_len > 0 ) {
if ( is_tn3270 ) {
2014-06-06 14:35:50 +00:00
next_tvb = tvb_new_subset_length ( tvb , offset , data_len ) ;
2012-03-19 21:12:45 +00:00
call_dissector ( tn3270_handle , next_tvb , pinfo , telnet_tree ) ;
} else if ( is_tn5250 ) {
2014-06-06 14:35:50 +00:00
next_tvb = tvb_new_subset_length ( tvb , offset , data_len ) ;
2012-03-19 21:12:45 +00:00
call_dissector ( tn5250_handle , next_tvb , pinfo , telnet_tree ) ;
} else
telnet_add_text ( telnet_tree , tvb , offset , data_len ) ;
}
/*
* Now interpret the command .
*/
offset = telnet_command ( pinfo , telnet_tree , tvb , iac_offset ) ;
} else {
/* get more data if tn3270 */
if ( is_tn3270 | | is_tn5250 ) {
pinfo - > desegment_offset = offset ;
pinfo - > desegment_len = DESEGMENT_ONE_MORE_SEGMENT ;
2015-11-14 14:23:33 +00:00
return tvb_captured_length ( tvb ) ;
2012-03-19 21:12:45 +00:00
}
/*
* We found no IAC byte , so what remains in the buffer
* is the last of the data in the packet .
* Add it to the tree , a line at a time , and then quit .
*/
telnet_add_text ( telnet_tree , tvb , offset , len ) ;
break ;
}
}
2015-11-14 14:23:33 +00:00
return tvb_captured_length ( tvb ) ;
1999-04-05 21:54:41 +00:00
}
1999-07-29 05:47:07 +00:00
void
proto_register_telnet ( void )
{
2012-03-19 21:12:45 +00:00
static hf_register_info hf [ ] = {
2013-02-27 03:58:23 +00:00
{ & hf_telnet_cmd ,
{ " Command " , " telnet.cmd " , FT_UINT8 , BASE_DEC ,
VALS ( cmd_vals ) , 0 , NULL , HFILL }
} ,
{ & hf_telnet_subcmd ,
{ " Subcommand " , " telnet.subcmd " , FT_UINT8 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
2012-03-19 21:12:45 +00:00
{ & hf_telnet_auth_name ,
{ " Name " , " telnet.auth.name " , FT_STRING , BASE_NONE ,
NULL , 0 , " Name of user being authenticated " , HFILL }
} ,
{ & hf_telnet_auth_cmd ,
{ " Auth Cmd " , " telnet.auth.cmd " , FT_UINT8 , BASE_DEC ,
VALS ( auth_cmd_vals ) , 0 , " Authentication Command " , HFILL }
} ,
{ & hf_telnet_auth_type ,
{ " Auth Type " , " telnet.auth.type " , FT_UINT8 , BASE_DEC ,
VALS ( auth_type_vals ) , 0 , " Authentication Type " , HFILL }
} ,
{ & hf_telnet_auth_mod_cred_fwd ,
{ " Cred Fwd " , " telnet.auth.mod.cred_fwd " , FT_BOOLEAN , 8 ,
TFS ( & auth_mod_cred_fwd ) , 0x08 , " Modifier: Whether client will forward creds or not " , HFILL }
} ,
{ & hf_telnet_auth_mod_who ,
{ " Who " , " telnet.auth.mod.who " , FT_BOOLEAN , 8 ,
TFS ( & auth_mod_who ) , 0x01 , " Modifier: Who to mask " , HFILL }
} ,
{ & hf_telnet_auth_mod_how ,
{ " How " , " telnet.auth.mod.how " , FT_BOOLEAN , 8 ,
TFS ( & auth_mod_how ) , 0x02 , " Modifier: How to mask " , HFILL }
} ,
{ & hf_telnet_auth_mod_enc ,
{ " Encrypt " , " telnet.auth.mod.enc " , FT_UINT8 , BASE_DEC ,
VALS ( auth_mod_enc ) , 0x14 , " Modifier: How to enable Encryption " , HFILL }
} ,
{ & hf_telnet_auth_krb5_type ,
{ " Command " , " telnet.auth.krb5.cmd " , FT_UINT8 , BASE_DEC ,
VALS ( auth_krb5_types ) , 0 , " Krb5 Authentication sub-command " , HFILL }
} ,
2013-02-27 03:58:23 +00:00
{ & hf_telnet_string_subopt_value ,
{ " Value " , " telnet.string_subopt.value " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_naws_subopt_width ,
{ " Width " , " telnet.naws_subopt.width " , FT_UINT16 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_naws_subopt_height ,
{ " Height " , " telnet.naws_subopt.height " , FT_UINT16 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_outmark_subopt_cmd ,
2016-09-19 01:48:50 +00:00
{ " Command " , " telnet.outmark_subopt.cmd " , FT_CHAR , BASE_HEX ,
2013-02-27 03:58:23 +00:00
VALS ( telnet_outmark_subopt_cmd_vals ) , 0 , NULL , HFILL }
} ,
{ & hf_telnet_outmark_subopt_banner ,
{ " Banner " , " telnet.outmark_subopt.banner " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_subopt_signature ,
{ " Signature " , " telnet.comport_subopt.signature " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_subopt_baud_rate ,
{ " Baud Rate " , " telnet.comport_subopt.baud_rate " , FT_UINT32 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_subopt_data_size ,
{ " Data Size " , " telnet.comport_subopt.data_size " , FT_UINT8 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_subopt_parity ,
{ " Parity " , " telnet.comport_subopt.parity " , FT_UINT8 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_subopt_stop ,
{ " Stop Bits " , " telnet.comport_subopt.stop " , FT_UINT8 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_subopt_control ,
{ " Control " , " telnet.comport_subopt.control " , FT_UINT8 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
2014-12-06 00:42:47 +00:00
{ & hf_telnet_comport_linestate ,
{ " Linestate " , " telnet.comport_subopt.linestate " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_set_linestate_mask ,
{ " Set Linestate Mask " , " telnet.comport_subopt.set_linestate_mask " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_modemstate ,
{ " Modemstate " , " telnet.comport_subopt.modemstate " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_set_modemstate_mask ,
{ " Set Modemstate Mask " , " telnet.comport_subopt.set_modemstate_mask " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_subopt_flow_control_suspend ,
{ " Flow Control Suspend " , " telnet.comport_subopt.flow_control_suspend " , FT_NONE , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_comport_subopt_flow_control_resume ,
{ " Flow Control Resume " , " telnet.comport_subopt.flow_control_resume " , FT_NONE , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
2013-02-27 03:58:23 +00:00
{ & hf_telnet_comport_subopt_purge ,
{ " Purge " , " telnet.comport_subopt.purge " , FT_UINT8 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_rfc_subopt_cmd ,
{ " Command " , " telnet.rfc_subopt.cmd " , FT_UINT8 , BASE_DEC ,
VALS ( rfc_opt_vals ) , 0 , NULL , HFILL }
} ,
2014-12-06 00:42:47 +00:00
{ & hf_telnet_tabstop ,
{ " Tabstop value " , " telnet.tabstop " , FT_UINT8 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
2012-03-19 21:12:45 +00:00
{ & hf_telnet_enc_cmd ,
{ " Enc Cmd " , " telnet.enc.cmd " , FT_UINT8 , BASE_DEC ,
VALS ( enc_cmd_vals ) , 0 , " Encryption command " , HFILL }
} ,
{ & hf_telnet_enc_type ,
{ " Enc Type " , " telnet.enc.type " , FT_UINT8 , BASE_DEC ,
VALS ( enc_type_vals ) , 0 , " Encryption type " , HFILL }
} ,
2014-12-06 00:42:47 +00:00
{ & hf_telnet_enc_type_data ,
{ " Type-specific data " , " telnet.enc.type_data " , FT_BYTES , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_enc_key_id ,
{ " Key ID " , " telnet.enc.key_id " , FT_BYTES , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
2012-03-19 21:12:45 +00:00
{ & hf_telnet_data ,
{ " Data " , " telnet.data " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
2014-12-06 00:42:47 +00:00
{ & hf_telnet_option_data ,
{ " Option data " , " telnet.option_data " , FT_BYTES , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_telnet_subcommand_data ,
{ " Subcommand data " , " telnet.subcommand_data " , FT_BYTES , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
2013-02-27 03:58:23 +00:00
{ & hf_tn3270_subopt ,
{ " Suboption " , " telnet.tn3270.subopt " , FT_UINT8 , BASE_DEC ,
VALS ( tn3270_subopt_vals ) , 0 , NULL , HFILL }
} ,
{ & hf_tn3270_connect ,
{ " Connect " , " telnet.tn3270.connect " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_tn3270_is ,
{ " Is " , " telnet.tn3270.is " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_tn3270_request_string ,
{ " Request " , " telnet.tn3270.request_string " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
{ & hf_tn3270_reason ,
{ " Reason " , " telnet.tn3270.reason " , FT_UINT8 , BASE_DEC ,
VALS ( tn3270_reason_vals ) , 0 , NULL , HFILL }
} ,
{ & hf_tn3270_request ,
{ " Request " , " telnet.tn3270.request " , FT_UINT8 , BASE_DEC ,
VALS ( tn3270_request_vals ) , 0 , NULL , HFILL }
} ,
{ & hf_tn3270_regime_subopt_value ,
{ " Value " , " telnet.tn3270.regime_subopt.value " , FT_STRING , BASE_NONE ,
NULL , 0 , NULL , HFILL }
} ,
2014-12-06 00:42:47 +00:00
{ & hf_tn3270_regime_cmd ,
{ " Cmd " , " telnet.regime_cmd " , FT_UINT8 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
2015-12-11 23:47:15 +00:00
{ & hf_telnet_starttls ,
{ " Follows " , " telnet.starttls " , FT_UINT8 , BASE_DEC ,
NULL , 0 , NULL , HFILL }
} ,
2012-03-19 21:12:45 +00:00
} ;
static gint * ett [ ] = {
& ett_telnet ,
2013-02-27 03:58:23 +00:00
& ett_telnet_cmd ,
2012-03-19 21:12:45 +00:00
& ett_telnet_subopt ,
& ett_status_subopt ,
& ett_rcte_subopt ,
& ett_olw_subopt ,
& ett_ops_subopt ,
& ett_crdisp_subopt ,
& ett_htstops_subopt ,
& ett_htdisp_subopt ,
& ett_ffdisp_subopt ,
& ett_vtstops_subopt ,
& ett_vtdisp_subopt ,
& ett_lfdisp_subopt ,
& ett_extasc_subopt ,
& ett_bytemacro_subopt ,
& ett_det_subopt ,
& ett_supdupout_subopt ,
& ett_sendloc_subopt ,
& ett_termtype_subopt ,
& ett_tacacsui_subopt ,
& ett_outmark_subopt ,
& ett_tlocnum_subopt ,
& ett_tn3270reg_subopt ,
& ett_x3pad_subopt ,
& ett_naws_subopt ,
& ett_tspeed_subopt ,
& ett_rfc_subopt ,
& ett_linemode_subopt ,
& ett_xdpyloc_subopt ,
& ett_env_subopt ,
& ett_auth_subopt ,
& ett_enc_subopt ,
& ett_newenv_subopt ,
& ett_tn3270e_subopt ,
& ett_xauth_subopt ,
& ett_charset_subopt ,
& ett_rsp_subopt ,
2015-12-11 23:47:15 +00:00
& ett_comport_subopt ,
& ett_starttls_subopt ,
2012-03-19 21:12:45 +00:00
} ;
2013-08-23 03:17:34 +00:00
static ei_register_info ei [ ] = {
{ & ei_telnet_invalid_subcommand , { " telnet.invalid_subcommand " , PI_PROTOCOL , PI_WARN , " Invalid subcommand " , EXPFILL } } ,
{ & ei_telnet_invalid_baud_rate , { " telnet.invalid_baud_rate " , PI_PROTOCOL , PI_WARN , " Invalid Baud Rate " , EXPFILL } } ,
{ & ei_telnet_invalid_data_size , { " telnet.invalid_data_size " , PI_PROTOCOL , PI_WARN , " Invalid Data Size " , EXPFILL } } ,
{ & ei_telnet_invalid_parity , { " telnet.invalid_parity " , PI_PROTOCOL , PI_WARN , " Invalid Parity Packet " , EXPFILL } } ,
{ & ei_telnet_invalid_stop , { " telnet.invalid_stop " , PI_PROTOCOL , PI_WARN , " Invalid Stop Packet " , EXPFILL } } ,
{ & ei_telnet_invalid_control , { " telnet.invalid_control " , PI_PROTOCOL , PI_WARN , " Invalid Control Packet " , EXPFILL } } ,
{ & ei_telnet_invalid_linestate , { " telnet.invalid_linestate " , PI_PROTOCOL , PI_WARN , " Invalid linestate " , EXPFILL } } ,
{ & ei_telnet_invalid_modemstate , { " telnet.invalid_modemstate " , PI_PROTOCOL , PI_WARN , " Invalid Modemstate " , EXPFILL } } ,
{ & ei_telnet_invalid_purge , { " telnet.invalid_purge " , PI_PROTOCOL , PI_WARN , " Invalid Purge Packet " , EXPFILL } } ,
{ & ei_telnet_kerberos_blob_too_long , { " telnet.kerberos_blob_too_long " , PI_PROTOCOL , PI_NOTE , " Kerberos blob too long to dissect " , EXPFILL } } ,
{ & ei_telnet_enc_cmd_unknown , { " telnet.enc.cmd.unknown " , PI_PROTOCOL , PI_WARN , " Unknown encryption command " , EXPFILL } } ,
{ & ei_telnet_suboption_length , { " telnet.suboption_length.invalid " , PI_PROTOCOL , PI_WARN , " Bogus suboption data " , EXPFILL } } ,
} ;
expert_module_t * expert_telnet ;
2012-03-19 21:12:45 +00:00
proto_telnet = proto_register_protocol ( " Telnet " , " TELNET " , " telnet " ) ;
proto_register_field_array ( proto_telnet , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2012-11-17 12:16:05 +00:00
2013-08-23 03:17:34 +00:00
expert_telnet = expert_register_protocol ( proto_telnet ) ;
expert_register_field_array ( expert_telnet , ei , array_length ( ei ) ) ;
2015-12-09 04:04:01 +00:00
telnet_handle = register_dissector ( " telnet " , dissect_telnet , proto_telnet ) ;
1999-07-29 05:47:07 +00:00
}
2000-04-08 07:07:42 +00:00
void
proto_reg_handoff_telnet ( void )
{
2016-10-07 20:25:01 +00:00
dissector_add_uint_with_preference ( " tcp.port " , TCP_PORT_TELNET , telnet_handle ) ;
2016-03-16 13:02:52 +00:00
tn3270_handle = find_dissector_add_dependency ( " tn3270 " , proto_telnet ) ;
tn5250_handle = find_dissector_add_dependency ( " tn5250 " , proto_telnet ) ;
2015-12-15 13:10:15 +00:00
ssl_handle = find_dissector ( " ssl " ) ;
2000-04-08 07:07:42 +00:00
}
2014-09-28 23:25:09 +00:00
/*
* Editor modelines - http : //www.wireshark.org/tools/modelines.html
*
* Local Variables :
* c - basic - offset : 2
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* ex : set shiftwidth = 2 tabstop = 8 expandtab :
* : indentSize = 2 : tabSize = 8 : noTabs = true :
*/