📄 pp_ftp.c
字号:
/* $Id$ *//* ** Copyright (C) 2004-2008 Sourcefire, Inc ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License Version 2 as ** published by the Free Software Foundation. You may not use, modify or ** distribute this program under any other version of the GNU General ** Public License. ** ** 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. *//* pp_ftp.c * * Purpose: FTP sessions contain commands and responses. Certain * commands are vectors of attack. This module checks * those FTP client commands and their parameter values, as * well as the server responses per the configuration. * * Arguments: None * * Effect: Alerts may be raised * * Comments: * *//* your preprocessor header file goes here */#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_STRINGS_H#include <strings.h>#endif#include <string.h>#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#ifndef WIN32#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <ctype.h>#else#include <windows.h>#endif#include "ftpp_eo_log.h"#include "pp_ftp.h"#include "pp_telnet.h"#include "ftpp_return_codes.h"#include "ftp_cmd_lookup.h"#include "ftp_bounce_lookup.h"//#include "decode.h"#include "debug.h"#include "stream_api.h"//#include "plugbase.h"#ifndef MAXHOSTNAMELEN /* Why doesn't Windows define this? */#define MAXHOSTNAMELEN 256#endif#ifdef SUP_IP6#include "ipv6_port.h"#endif/* * Used to keep track of pipelined commands and the last one * that resulted in a */static int ftp_cmd_pipe_index = 0;#if 0/* * Function: getIP(char **ip_start, * char *last_char, * char term_char, * u_int32_t *ipRet, * u_int16_t *portRet) * * Purpose: Returns a 32bit IP address and port from an FTP-style * string -- ie, a,b,c,d,p1,p2. Stops checking when term_char * is seen. Used to get address and port information from FTP * PORT command and server response to PASV command. * * Arguments ip_start => Pointer to pointer to the start of string. * Updated to end of IP address if successful. * last_char => End of string * term_char => Character delimiting the end of the address. * ipRet => Return pointer to 32bit address on success * portRet => Return pointer to 16bit port on success * * Returns: int => return code indicating error or success * */int getIP(const int type, const char **ip_start, const char *last_char, char term_char, snort_ip *ipRet, u_int16_t *portRet){ u_int32_t ip=0; u_int16_t port=0; int octet=0; const char *this_param = *ip_start; do { int value = 0; do { if (!isdigit((int)(*this_param))) { return FTPP_NON_DIGIT; } value = value * 10 + (*this_param - '0'); this_param++; } while ((this_param < last_char) && (*this_param != ',') && (*this_param != term_char)); if (value > 0xFF) { return FTPP_INVALID_ARG; } if (octet < 4) { ip = (ip << 8) + value; } else { port = (port << 8) + value; } if (*this_param != term_char) this_param++; octet++; } while ((this_param < last_char) && (*this_param != term_char) ); if (octet != 6) { return FTPP_MALFORMED_IP_PORT; }#ifdef SUP_IP6// XXX-IPv6 NOT YET IMPLEMENTED - IPv4 only at the moment sfip_set_raw(ipRet, &ip, AF_INET);#else *ipRet = ip;#endif *portRet = port; *ip_start = this_param; return FTPP_SUCCESS;}#endif/* * Function: getIP959(char **ip_start, * char *last_char, * char term_char, * u_int32_t *ipRet, * u_int16_t *portRet) * * Purpose: Returns a 32bit IP address and port from an RFC 959 FTP-style * string -- ie, a,b,c,d,p1,p2. Stops checking when term_char * is seen. Used to get address and port information from FTP * PORT command and server response to PASV command. * * Arguments ip_start => Pointer to pointer to the start of string. * Updated to end of IP address if successful. * last_char => End of string * term_char => Character delimiting the end of the address. * ipRet => Return pointer to 32bit address on success * portRet => Return pointer to 16bit port on success * * Returns: int => return code indicating error or success */static int getIP959( const char **ip_start, const char *last_char, char term_char, snort_ip *ipRet, u_int16_t *portRet){ u_int32_t ip=0; u_int16_t port=0; int octet=0; const char *this_param = *ip_start; do { int value = 0; do { if (!isdigit((int)(*this_param))) { return FTPP_NON_DIGIT; } value = value * 10 + (*this_param - '0'); this_param++; } while ((this_param < last_char) && (*this_param != ',') && (*this_param != term_char)); if (value > 0xFF) { return FTPP_INVALID_ARG; } if (octet < 4) { ip = (ip << 8) + value; } else { port = (port << 8) + value; } if (*this_param != term_char) this_param++; octet++; } while ((this_param < last_char) && (*this_param != term_char) ); if (octet != 6) { return FTPP_MALFORMED_IP_PORT; }#ifdef SUP_IP6 ip = htonl(ip); sfip_set_raw(ipRet, &ip, AF_INET);#else *ipRet = ip;#endif *portRet = port; *ip_start = this_param; return FTPP_SUCCESS;}/* * getIP1639() parses the LPRT command parameters which have this * format (ftyp == e_long_host_port): * * LPRT af,hal,h1,h2,h3,h4...,pal,p1,p2... * LPRT 4,4,132,235,1,2,2,24,131 * LPRT 6,16,16,128,0,...,0,8,128,0,32,12,65,123,2,20,162 * * (The above examples correspond to the EPRT examples below.) * * af (address family) is the IP version. h# and p# are in network * byte order (high byte first). * * This function is called for the LPSV response as well, which * has this format: * * 228 <human readable text> (af,hal,h1,h2,h3,h4...,pal,p1,p2...) */static int getIP1639 ( const char **ip_start, const char *last_char, char term_char, snort_ip* ipRet, u_int16_t *portRet){ char bytes[21]; /* max of 1+5+3 and 1+17+3 */ const char* tok = *ip_start; int nBytes = 0; bytes[0] = 0; /* first we just try to get a sequence of csv bytes */ while ( nBytes < sizeof(bytes) && tok < last_char ) { char* endPtr = (char*)tok; unsigned long val = strtoul(tok, &endPtr, 10); if ( val > 255 || endPtr == tok || ( *endPtr && *endPtr != ',' && endPtr != last_char ) ) { return FTPP_INVALID_ARG; } bytes[nBytes++] = (uint8_t)val; tok = (endPtr < last_char) ? endPtr + 1 : endPtr; } *ip_start = tok; /* now we check that the we have a valid sequence of */ /* bytes and convert the address and port accordingly */ switch ( bytes[0] ) { case 4: if ( nBytes != 9 || bytes[1] != 4 || bytes[6] != 2 ) return FTPP_INVALID_ARG; { uint32_t ip4 = 0; int n; for ( n = 0; n < 4; n++ ) ip4 = (ip4 << 8) | bytes[n+2];#ifdef SUP_IP6 /* don't call sfip_set_raw() on raw bytes to avoid possible word alignment issues */ ip4 = htonl(ip4); sfip_set_raw(ipRet, (void*)&ip4, AF_INET);#else *ipRet = ip4;#endif } *portRet = (bytes[7] << 8) | bytes[8]; break;#ifdef SUP_IP6 case 6: if ( nBytes != 21 || bytes[1] != 16 || bytes[18] != 2 ) return FTPP_INVALID_ARG; sfip_set_raw(ipRet, bytes+2, AF_INET6); *portRet = (bytes[19] << 8) | bytes[20]; break;#endif default: return FTPP_INVALID_ARG; } return FTPP_SUCCESS;}/* * getIP2428() parses the EPRT command parameters which have this * format (ftyp == e_extd_host_port): * * EPRT |<family>|address|<tcp-port>| * EPRT |1|132.235.1.2|6275| * EPRT |2|1080::8:800:200C:417A|5282| * * Note that the address family is 1|2 (as in RFC 2428), not 4|6 * (as in IP version), nor 2|10 (as in AF_INET[6]). * * This function is called for the EPSV response as well, which * has this format (ftyp == e_int): * * 229 <human readable text> (|||<tcp-port>|) * * The delimiter may be other than '|' if required to represent * the protocol address, but must be between 33-126 inclusive. * Other delimiters aren't required for IPv{4,6} but we allow * them for flexibility. * * It is assumed that *ip_start points to the first delimiter in * both cases. *//* * this copy is unfortunate but inet_pton() doesn't * like the delim and the src buf is const so ... */void CopyField ( char* buf, const char* tok, int max, const char* end, char delim){ int len = end - tok + 1; char* s; if ( len >= max ) { strncpy(buf, tok, max); buf[max-1] = '\0'; } else { strncpy(buf, tok, len); buf[len] = '\0'; } s = index(buf, delim);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -