1 /****************************************************************************
2 ** File: ftpctrl.c
3 **
4 ** Author: Mike Borella
5 **
6 ** Comments: FTP control module.
7 **
8 ** $Id: ftpctrl.c,v 1.5 2006/11/21 07:47:34 farooq-i-azam Exp $
9 **
10 ** This program is free software; you can redistribute it and/or modify
11 ** it under the terms of the GNU General Public License as published by
12 ** the Free Software Foundation; either version 2 of the License, or
13 ** (at your option) any later version.
14 **
15 ** This program is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ** GNU Library General Public License for more details.
19 **
20 ** You should have received a copy of the GNU General Public License
21 ** along with this program; if not, write to the Free Software
22 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 **
24 *****************************************************************************/
25 
26 #include "ftpctrl.h"
27 
28 extern struct arg_t * my_args;
29 
30 /*----------------------------------------------------------------------------
31 **
32 ** dump_ftpctrl()
33 **
34 ** Parse and display FTP control packets
35 **
36 **----------------------------------------------------------------------------
37 */
38 
dump_ftpctrl(packet_t * pkt)39 void dump_ftpctrl(packet_t *pkt)
40 {
41   u_int8_t * payload;
42   u_int32_t  size;
43   u_int8_t * ptr;
44 
45   /* Set the layer */
46   set_layer(LAYER_APPLICATION);
47 
48   /* find the payload size, then allocate memory and read the packet */
49   size = get_packet_apparentbytesleft(pkt);
50   if (size <= 0)
51     return;
52   payload = (u_int8_t *) my_malloc (size+1);
53   payload[size] = '\0';
54   if (get_packet_bytes(payload, pkt, size) == 0)
55     {
56       my_free(payload);
57       return;
58     }
59 
60   /* Get rid of carriage return and line feed at end of payload if it exists */
61   ptr = payload + strlen(payload);
62   while(1)
63     {
64       ptr --;
65       if (*ptr == 0x0D || *ptr == 0x0A)
66 	*ptr = '\0';
67       else
68 	break;
69     }
70 
71   /*
72    * FTP control connections either have commands or response codes.  If there
73    * is a response code, then this is a reply, otherwise it is a request. All
74    * response codes are 3 digits long followed by a space.  Exception: Some
75    * replies are split over multiple packets and do not have a numeric code
76    * to begin with.
77    *
78    * We determine the direction by looking at the source port.  Replies
79    * should always come from the FTP control port.
80    */
81 
82   if (state_get_srcport() == PORT_FTPCTRL)
83     {
84       if (isdigit(payload[0]) && isdigit(payload[1]) && isdigit(payload[2]) &&
85 	  isspace(payload[3]))
86 	{
87 	  /* process a reply with a reply code */
88 	  char replycode_str[4];
89 	  int replycode;
90 
91 	  strncpy(replycode_str, payload, 3);
92 	  replycode_str[3] = '\0';
93 	  replycode = atoi(replycode_str);
94 
95 	  if (my_args->m)
96 	    {
97 	      display_minimal_string("FTP control ");
98 	      display_minimal_string(replycode_str);
99               display_minimal_string(payload+3);
100 	    }
101 	  else
102 	    {
103 	      display_header_banner("FTP control");
104 	      display_string("Reply code", replycode_str);
105 	      display_string("Reply", payload+4);
106 	    }
107 	}
108       else
109 	{
110 	  /* process a reply without a reply code */
111 	  if (my_args->m)
112 	    {
113 	      display_minimal_string("FTP control ");
114               display_minimal_string(payload+3);
115 	    }
116 	  else
117 	    {
118 	      display_header_banner("FTP control");
119 	      display_string("Reply", payload);
120 	    }
121 	}
122     }
123   else
124     {
125       /* process a request */
126       u_int8_t * requestcode_str;
127       u_int8_t * ptr;
128 
129       /* find the first space, which separates the request code from request */
130       ptr = strchr(payload, ' ');
131       if (!ptr)
132 	{
133 	  /* This is the case where there is nothing following the code */
134 	  ptr = payload + strlen(payload);
135 	  requestcode_str = payload;
136 	  payload = NULL;
137 	}
138       else
139 	{
140 	  requestcode_str = my_malloc((ptr - payload) + 1);
141 	  strncpy(requestcode_str, payload, ptr - payload);
142 	  requestcode_str[ptr - payload] = '\0';
143 	}
144 
145       if (my_args->m)
146 	{
147 	  display_minimal_string("FTP control ");
148 	  display_minimal_string(requestcode_str);
149           display_minimal_string(" ");
150           display_minimal_string(ptr+1);
151 	}
152       else
153 	{
154           display_header_banner("FTP control");
155           display_string("Request code", requestcode_str);
156 	  if (payload && ptr)
157 	    display_string("Request", ptr+1);
158 	}
159 
160       /* free memory */
161       my_free(requestcode_str);
162     }
163 
164   /* free memory */
165   my_free(payload);
166 
167   /* dump the hex buffer */
168   hexbuffer_flush();
169 
170 }
171