📄 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//extern u_int8_t DecodeBuffer[DECODE_BLEN]; /* decode.c *//* * Used to keep track of pipelined commands and the last one * that resulted in a */static int ftp_cmd_pipe_index = 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 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;}/* * Function: validate_date_format( * FTP_DATE_FMT *ThisFmt, * char **this_param) * * Purpose: Recursively determines whether a date matches the * a valid format. * * Arguments: ThisFmt => Pointer to the current format * this_param => Pointer to start of the portion to validate. * Updated to end of valid section if valid. * * Returns: int => return code indicating error or success * */int validate_date_format(FTP_DATE_FMT *ThisFmt, const char **this_param){ int valid_string = 0; int checked_something_else = 0; int checked_next = 0; int iRet = FTPP_ALERT; const char *curr_ch; if (!ThisFmt) return FTPP_INVALID_ARG; if (!this_param || !(*this_param)) return FTPP_INVALID_ARG; curr_ch = *this_param; if (!ThisFmt->empty) { char *format_char = ThisFmt->format_string; do { switch (*format_char) { case 'n': if (!isdigit((int)(*curr_ch))) { /* Return for non-digit */ return FTPP_INVALID_DATE; } curr_ch++; format_char++; break; case 'C': if (!isalpha((int)(*curr_ch))) { /* Return for non-char */ return FTPP_INVALID_DATE; } curr_ch++; format_char++; break; default: if (*curr_ch != *format_char) { /* Return for non-matching char */ return FTPP_INVALID_DATE; } curr_ch++; format_char++; break; } valid_string = 1; } while ((*format_char != '\0') && !isspace((int)(*curr_ch))); if ((*format_char != '\0') && isspace((int)(*curr_ch))) { /* Didn't have enough chars to complete this format */ return FTPP_INVALID_DATE; } } if ((ThisFmt->optional) && !isspace((int)(*curr_ch))) { const char *tmp_ch = curr_ch; iRet = validate_date_format(ThisFmt->optional, &tmp_ch); if (iRet == FTPP_SUCCESS) curr_ch = tmp_ch; } if ((ThisFmt->next_a) && !isspace((int)(*curr_ch))) { const char *tmp_ch = curr_ch; checked_something_else = 1; iRet = validate_date_format(ThisFmt->next_a, &tmp_ch); if (iRet == FTPP_SUCCESS) { curr_ch = tmp_ch; } else if (ThisFmt->next_b) { iRet = validate_date_format(ThisFmt->next_b, &tmp_ch); if (iRet == FTPP_SUCCESS) curr_ch = tmp_ch; } if (ThisFmt->next) { iRet = validate_date_format(ThisFmt->next, &tmp_ch); if (iRet == FTPP_SUCCESS) { curr_ch = tmp_ch; checked_next = 1; } } if (iRet == FTPP_SUCCESS) { *this_param = curr_ch; return iRet; } } if ((!checked_next) && (ThisFmt->next)) { const char *tmp_ch = curr_ch; checked_something_else = 1; iRet = validate_date_format(ThisFmt->next, &tmp_ch); if (iRet == FTPP_SUCCESS) { curr_ch = tmp_ch; checked_next = 1; } } if ((isspace((int)(*curr_ch))) && ((!ThisFmt->next) || checked_next)) { *this_param = curr_ch; return FTPP_SUCCESS; } if (valid_string) { int all_okay = 0; if (checked_something_else) { if (iRet == FTPP_SUCCESS) all_okay = 1; } else { all_okay = 1; } if (all_okay) { *this_param = curr_ch; return FTPP_SUCCESS; } } return FTPP_INVALID_DATE;}/* * Function: validate_param( * Packet *p * char *param * char *end * FTP_PARAM_FMT *param_format, * FTP_SESSION *Session) * * Purpose: Validates the current parameter against the format * specified. * * Arguments: p => Pointer to the current packet * params_begin => Pointer to beginning of parameters * params_end => End of params buffer * param_format => Parameter format specifier for this command * Session => Pointer to the session info * * Returns: int => return code indicating error or success * */int validate_param(SFSnortPacket *p, const char *param, const char *end, FTP_PARAM_FMT *ThisFmt, FTP_SESSION *Session){ int iRet; const char *this_param = param; if (param > end) return FTPP_ALERT; switch (ThisFmt->type) { case e_head: /* shouldn't get here, but just in case */ break; case e_unrestricted: /* strings/filenames only occur as the last param, * so move to the end of the param buffer. */ { do { this_param++; } while (this_param < end); } break; case e_strformat: /* Check for 2 % signs within the parameter for an FTP command * 2 % signs is the magic number per existing rules (24 Sep 2004) */#define MAX_PERCENT_SIGNS 2 { int numPercents = 0; do { if (*this_param == '%') { numPercents++; if (numPercents >= MAX_PERCENT_SIGNS) { break; } } this_param++; } while ((this_param < end) && (*this_param != ' '));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -