diff options
author | Guy Harris <guy@alum.mit.edu> | 2000-04-08 03:32:10 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2000-04-08 03:32:10 +0000 |
commit | 160928a318385aa2fb59af968ab1cd85847ad963 (patch) | |
tree | 9823911ac8dc8aa920a050318f9ea098f41393e7 /packet-rlogin.c | |
parent | 43c9217ba4083abf6632cdd35b8e0233fc67afb7 (diff) |
Jeff Foster's rlogin dissector, and changes to the TCP dissector to
export the urgent pointer (as the rlogin dissector needs it).
svn path=/trunk/; revision=1822
Diffstat (limited to 'packet-rlogin.c')
-rw-r--r-- | packet-rlogin.c | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/packet-rlogin.c b/packet-rlogin.c new file mode 100644 index 0000000000..d07393c441 --- /dev/null +++ b/packet-rlogin.c @@ -0,0 +1,480 @@ +/* packet-rlogin.c + * Routines for unix rlogin packet dissection + * Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com> + * + * $Id: packet-rlogin.c,v 1.1 2000/04/08 03:32:09 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@zing.org> + * Copyright 1998 Gerald Combs + * + * + * Based upon RFC-1282 - BSD Rlogin + * + * + * 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. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + */ + + + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +#ifdef HAVE_NETINET_IN_H +# include <netinet/in.h> +#endif + +#include <stdio.h> +#include <string.h> +#include <glib.h> +#include "packet.h" +#include "resolv.h" +#include "globals.h" +#include "alignment.h" +#include "conversation.h" + +#include "packet-tcp.h" + +#ifdef NEED_SNPRINTF_H +# ifdef HAVE_STDARG_H +# include <stdarg.h> +# else +# include <varargs.h> +# endif +# include "snprintf.h" +#endif + +#define CHECK_PACKET_LENGTH(X) if ((offset+X) > fd->cap_len){ \ + proto_tree_add_text(tree, offset, 0, "*** FRAME TOO SHORT ***"); \ + return; } + + +#define TCP_PORT_RLOGIN 513 + +static int proto_rlogin = -1; + +static int ett_rlogin = -1; +static int ett_rlogin_window = -1; +static int ett_rlogin_user_info = -1; +static int ett_rlogin_window_rows = -1; +static int ett_rlogin_window_cols = -1; +static int ett_rlogin_window_x_pixels = -1; +static int ett_rlogin_window_y_pixels = -1; + + +static int hf_user_info = -1; +static int hf_window_info = -1; +static int hf_window_info_rows = -1; +static int hf_window_info_cols = -1; +static int hf_window_info_x_pixels = -1; +static int hf_window_info_y_pixels = -1; + + +#define RLOGIN_PORT 513 + +#define row_pointer_t frame_data* +#define compare_packet_ptr(X) (X == (fd)) +#define get_packet_ptr (fd) + +#define NAME_LEN 32 + +typedef struct { + int state; + row_pointer_t info_row; + row_pointer_t last_row; + char name[ NAME_LEN]; + +}rlogin_hash_entry_t; + + +#define NONE 0 +#define USER_INFO_WAIT 1 +#define DONE 2 +#define BAD 2 + + +static GMemChunk *rlogin_vals = NULL; + +#define rlogin_hash_init_count 20 + +static guint32 last_abs_sec = 0; +static guint32 last_abs_usec= 0; + +static void +rlogin_init( void){ + +/* Routine to initialize rlogin protocol before each capture or filter pass. */ +/* Release any memory if needed. Then setup the memory chunks. */ + + last_abs_sec = 0; + last_abs_usec= 0; + + if (rlogin_vals) + g_mem_chunk_destroy(rlogin_vals); + + rlogin_vals = g_mem_chunk_new("rlogin_vals", + sizeof( rlogin_hash_entry_t), + rlogin_hash_init_count * sizeof( rlogin_hash_entry_t), + G_ALLOC_AND_FREE); +} + + +/**************** Decoder State Machine ******************/ + +static void +rlogin_state_machine( rlogin_hash_entry_t *hash_info, const u_char *pd, + int offset, frame_data *fd) { + +/* rlogin stream decoder */ +/* Just watched for second packet from client with the user name and */ +/* terminal type information. */ + + + if ( pi.destport != RLOGIN_PORT) /* not from client */ + return; + /* exit if not needed */ + if (( hash_info->state == DONE) || ( hash_info->state == BAD)) + return; + + /* test timestamp */ + if (( last_abs_sec > fd->abs_secs) || + (( last_abs_sec == fd->abs_secs) && ( last_abs_usec >= fd->abs_usecs))) + return; + + last_abs_sec = fd->abs_secs; /* save timestamp */ + last_abs_usec = fd->abs_usecs; + + if ( !IS_DATA_IN_FRAME(offset)) /* exit if no data */ + return; + + if ( hash_info->state == NONE){ /* new connection*/ + + if ( GBYTE( pd, offset + 1)) { /* expect a NULL */ + hash_info->state = DONE; /* quit, no NULL */ + return; + } + else { + if (( END_OF_FRAME) <= 1) /* if no data */ + hash_info->state = USER_INFO_WAIT; + else { + hash_info->state = DONE; + hash_info->info_row = get_packet_ptr; + } + } + } /* expect user data here */ +/*$$$ may need to do more checking here */ + else if ( hash_info->state == USER_INFO_WAIT) { + hash_info->state = DONE; + hash_info->info_row = get_packet_ptr; + /* save name for later*/ + strncpy( hash_info->name, &pd[ offset], NAME_LEN); + + hash_info->name[ NAME_LEN] = 0; + + if (check_col(fd, COL_INFO)) /* update summary */ + col_append_str( fd, COL_INFO, ", User information"); + + } +} + + +static void rlogin_display( rlogin_hash_entry_t *hash_info, const u_char *pd, + int offset, frame_data *fd, proto_tree *tree) { + +/* Display the proto tree */ + + proto_tree *rlogin_tree, *user_info_tree, *window_tree; + proto_item *ti; + guint8 *Ptr; + const char *str; + proto_item *user_info_item, *window_info_item; + + ti = proto_tree_add_item( tree, proto_rlogin, offset, + END_OF_FRAME, NULL, "Rlogin:" ); + + rlogin_tree = proto_item_add_subtree(ti, ett_rlogin); + + if ( !END_OF_FRAME) /* exit if no data */ + return; + + if ( tcp_urgent_pointer && /* if control message */ + BYTES_ARE_IN_FRAME(offset + tcp_urgent_pointer - 1, 1)) { + + int i = offset + tcp_urgent_pointer - 1; + guint16 Temp = GBYTE( pd, i); + + if ( i < offset) /* check for data in front */ + proto_tree_add_text( rlogin_tree, offset, i - offset, + "Data"); + + proto_tree_add_text( rlogin_tree, i, 1, "Control byte: %u (%s)", + Temp, + (Temp == 2) ? "Clear buffer" : + (Temp == 0x10) ? "Raw mode" : + (Temp == 0x20) ? "Cooked mode" : + (Temp == 0x80) ? "Window size request" : + "Unknown"); + offset = i; /* adjust offset */ + } + + else if ( !GBYTE( pd, offset)){ /* startup */ + if ( pi.srcport== RLOGIN_PORT) /* from server */ + proto_tree_add_text(rlogin_tree, offset, 1, + "Startup info received flag (0x00)"); + + else + proto_tree_add_text(rlogin_tree, offset, 1, + "Client Startup Flag (0x00)"); + ++offset; + } + + if ( compare_packet_ptr( hash_info->info_row)){ /* user info ?*/ + + user_info_item = proto_tree_add_item( rlogin_tree, hf_user_info, + offset, END_OF_FRAME, NULL ); + + str = &pd[ offset]; /* do server user name */ + + CHECK_PACKET_LENGTH( strlen( str)); + + user_info_tree = proto_item_add_subtree( user_info_item, + ett_rlogin_user_info); + + proto_tree_add_text( user_info_tree, offset, strlen( str) + 1, + "Server User Name: %s", str); + + offset += strlen( str) + 1; + str = &pd[ offset]; /* do client user name */ + CHECK_PACKET_LENGTH( strlen( str)); + proto_tree_add_text( user_info_tree, offset, strlen( str) + 1, + "Client User Name: %s", str); + + offset += strlen( str) + 1; + + str = &pd[ offset]; /* do terminal type/speed */ + CHECK_PACKET_LENGTH( strlen( str)); + proto_tree_add_text( user_info_tree, offset, strlen( str) + 1, + "Terminal Type/Speed: %s", str); + + offset += strlen( str) + 1; + } + +/* test for terminal information, the data will have 2 0xff bytes */ + + /* look for first 0xff byte */ + Ptr = (guint8*)memchr( &pd[ offset], 0xff, END_OF_FRAME); + + if (( Ptr) && (*(Ptr + 1) == 0xff)) { /* found terminal info */ + + int ti_offset = Ptr - pd; /* get offset */ + + if ( ti_offset < offset){ /*if data before terminal info*/ + proto_tree_add_text( rlogin_tree, offset, + (ti_offset - offset), "Data"); + offset = ti_offset; + } + + CHECK_PACKET_LENGTH( 12); + window_info_item = proto_tree_add_item( rlogin_tree, + hf_window_info, offset, 12, NULL ); + + window_tree = proto_item_add_subtree( window_info_item, + ett_rlogin_window); + + CHECK_PACKET_LENGTH( 2); + proto_tree_add_text( window_tree, offset, 2, + "Magic Cookie: (0xff, 0xff)"); + offset += 2; + + CHECK_PACKET_LENGTH( 2); + proto_tree_add_text( window_tree, offset, 2, + "Window size marker: 'ss'"); + offset += 2; + + CHECK_PACKET_LENGTH( 2); + proto_tree_add_item( window_tree, hf_window_info_rows, offset, + 2, pntohs( &pd[offset])); + offset += 2; + + CHECK_PACKET_LENGTH( 2); + proto_tree_add_item( window_tree, hf_window_info_cols, offset, + 2, pntohs( &pd[offset]) ); + offset += 2; + + CHECK_PACKET_LENGTH( 2); + proto_tree_add_item( window_tree, hf_window_info_x_pixels, + offset, 2, pntohs( &pd[offset])); + offset += 2; + + CHECK_PACKET_LENGTH( 2); + proto_tree_add_item( window_tree, hf_window_info_y_pixels, + offset, 2, pntohs( &pd[offset]) ); + offset += 2; + } + + if ( END_OF_FRAME != 0) /* if more data */ + proto_tree_add_text(rlogin_tree, offset, END_OF_FRAME, "Data"); + +} + + + +static void +dissect_rlogin(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { + + + guint8 *Ptr; + rlogin_hash_entry_t *hash_info = 0; + conversation_t *conversation; + + /* Lookup this connection*/ + conversation = find_conversation( &pi.src, &pi.dst, pi.ptype, + pi.srcport, pi.destport); + + if ( conversation) /* conversation found */ + hash_info = conversation->data; + + /* new conversation create local data structure */ + else { + hash_info = g_mem_chunk_alloc(rlogin_vals); + hash_info->state = NONE; + hash_info->info_row = 0; + hash_info->name[ 0] = 0; + + conversation_new( &pi.src, &pi.dst, pi.ptype, + pi.srcport, pi.destport, hash_info); + } + + if (check_col(fd, COL_PROTOCOL)) /* update protocol */ + col_add_str(fd, COL_PROTOCOL, "Rlogin"); + + if (check_col(fd, COL_INFO)){ /* display packet info*/ + + char temp[1000]; + + if ( hash_info->name[0]) { + strcpy( temp, "User name: "); + strcat( temp, hash_info->name); + strcat( temp, ", "); + } + else + temp[0] = 0; + + if ( !GBYTE(pd, offset)) + strcat( temp, "Start Handshake"); + else if ( tcp_urgent_pointer) + strcat( temp, "Control Message"); + + else { /* check for terminal info */ + Ptr = (guint8*)memchr( &pd[ offset], 0xff, END_OF_FRAME); + + if (( Ptr) && (*(Ptr + 1) == 0xff)) + strcat( temp, "Terminal Info"); + else { + int i; + strcat( temp, "Data:"); + i = strlen( temp); + strncat( temp, &pd[ offset], 128); + temp[ i + MIN( 128, END_OF_FRAME)] = 0; + } + } + + col_add_str(fd, COL_INFO, temp); + } + + rlogin_state_machine( hash_info, pd, offset, fd); + + if ( tree) /* if proto tree, decode data */ + rlogin_display( hash_info, pd, offset, fd, tree); +} + + +void +proto_register_rlogin( void){ + +/* Prep the rlogin protocol, for now, just register it */ + + static gint *ett[] = { + &ett_rlogin, + &ett_rlogin_window, + &ett_rlogin_window_rows, + &ett_rlogin_window_cols, + &ett_rlogin_window_x_pixels, + &ett_rlogin_window_y_pixels, + &ett_rlogin_user_info + }; + + static hf_register_info hf[] = { + + { &hf_user_info, + { "User Info", "rlogin.user_info", FT_NONE, BASE_NONE, + NULL, 0x0, "" + } + }, + { &hf_window_info, + { "Window Info", "rlogin.window_size", FT_NONE, BASE_NONE, + NULL, 0x0, "" + } + }, + { &hf_window_info_rows, + { "Rows", "rlogin.window_size.rows", FT_UINT16, BASE_DEC, + NULL, 0x0, "" + } + }, + { &hf_window_info_cols, + { "Columns", "rlogin.window_size.cols", FT_UINT16, BASE_DEC, + NULL, 0x0, "" + } + }, + { &hf_window_info_x_pixels, + { "X Pixels", "rlogin.window_size.x_pixels", FT_UINT16, BASE_DEC, + NULL, 0x0, "" + } + }, + { &hf_window_info_y_pixels, + { "Y Pixels", "rlogin.window_size.y_pixels", FT_UINT16, BASE_DEC, + NULL, 0x0, "" + } + } + }; + + + proto_rlogin = proto_register_protocol ( + "Rlogin Protocol", "rlogin"); + + proto_register_field_array(proto_rlogin, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_init_routine( &rlogin_init); /* register re-init routine */ + + +} + +void +proto_reg_handoff_rlogin(void) { + + /* dissector install routine */ + + dissector_add("tcp.port", TCP_PORT_RLOGIN, dissect_rlogin); +} |