"Fossies" - the Fresh Open Source Software Archive

Member "snort-2.9.17/src/dynamic-preprocessors/appid/service_plugins/service_ftp.c" (16 Oct 2020, 41655 Bytes) of package /linux/misc/snort-2.9.17.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "service_ftp.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.9.16.1_vs_2.9.17.

    1 /*
    2 ** Copyright (C) 2014-2020 Cisco and/or its affiliates. All rights reserved.
    3 ** Copyright (C) 2005-2013 Sourcefire, Inc.
    4 **
    5 ** This program is free software; you can redistribute it and/or modify
    6 ** it under the terms of the GNU General Public License Version 2 as
    7 ** published by the Free Software Foundation.  You may not use, modify or
    8 ** distribute this program under any other version of the GNU General
    9 ** Public License.
   10 **
   11 ** This program is distributed in the hope that it will be useful,
   12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 ** GNU General Public License for more details.
   15 **
   16 ** You should have received a copy of the GNU General Public License
   17 ** along with this program; if not, write to the Free Software
   18 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   19 */
   20 
   21 
   22 #include <ctype.h>
   23 #include <string.h>
   24 #include <stdlib.h>
   25 #include <stddef.h>
   26 #include <sys/types.h>
   27 #include <netinet/in.h>
   28 
   29 #include "appIdApi.h"
   30 #include "appInfoTable.h"
   31 #include "flow.h"
   32 #include "service_api.h"
   33 #include "service_util.h"
   34 
   35 #define FTP_PORT    21
   36 /*#define RNA_FTP_EXPECTED_ON_PORT    1 */
   37 
   38 typedef enum
   39 {
   40     FTP_STATE_CONNECTION,
   41     FTP_STATE_LOGIN,
   42     FTP_STATE_PASSWORD,
   43     FTP_STATE_ACCOUNT,
   44     FTP_STATE_CONNECTION_ERROR,
   45     FTP_STATE_MONITOR
   46 } FTPState;
   47 
   48 typedef enum
   49 {
   50     FTP_REPLY_BEGIN,
   51     FTP_REPLY_MULTI,
   52     FTP_REPLY_LONG,
   53     FTP_REPLY_MID
   54 } FTPReplyState;
   55 
   56 typedef enum
   57 {
   58     FTP_CMD_NONE,
   59     FTP_CMD_PORT_EPRT,
   60     FTP_CMD_PASV_EPSV
   61 } FTPCmd;
   62 
   63 #define MAX_STRING_SIZE 64
   64 typedef struct _SERVICE_FTP_DATA
   65 {
   66     FTPState state;
   67     FTPReplyState rstate;
   68     int code;
   69     char vendor[MAX_STRING_SIZE];
   70     char version[MAX_STRING_SIZE];
   71     FTPCmd cmd;
   72     sfaddr_t address;
   73     uint16_t port;
   74 } ServiceFTPData;
   75 
   76 #pragma pack(1)
   77 
   78 typedef struct _SERVICE_FTP_CODE
   79 {
   80     uint8_t code[3];
   81     uint8_t sp;
   82 } ServiceFTPCode;
   83 
   84 #pragma pack()
   85 
   86 static int ftp_init(const InitServiceAPI * const init_api);
   87 static int ftp_validate(ServiceValidationArgs* args);
   88 
   89 static tRNAServiceElement svc_element =
   90 {
   91     .next = NULL,
   92     .validate = &ftp_validate,
   93     .detectorType = DETECTOR_TYPE_DECODER,
   94     .name = "ftp",
   95     .ref_count = 1,
   96     .current_ref_count = 1,
   97 };
   98 
   99 static RNAServiceValidationPort pp[] =
  100 {
  101     {&ftp_validate, FTP_PORT, IPPROTO_TCP},
  102     {NULL, 0, 0}
  103 };
  104 
  105 tRNAServiceValidationModule ftp_service_mod =
  106 {
  107     "FTP",
  108     &ftp_init,
  109     pp
  110 };
  111 
  112 #define FTP_PATTERN1 "220 "
  113 #define FTP_PATTERN2 "220-"
  114 #define FTP_PATTERN3 "FTP"
  115 #define FTP_PATTERN4 "ftp"
  116 
  117 static tAppRegistryEntry appIdRegistry[] =
  118 {
  119     {APP_ID_FTP_CONTROL, APPINFO_FLAG_SERVICE_ADDITIONAL},
  120     {APP_ID_FTP_ACTIVE,  APPINFO_FLAG_SERVICE_ADDITIONAL},
  121     {APP_ID_FTP_PASSIVE, APPINFO_FLAG_SERVICE_ADDITIONAL},
  122     {APP_ID_FTPS,        APPINFO_FLAG_SERVICE_ADDITIONAL}
  123 };
  124 
  125 static int16_t ftp_data_app_id = 0;
  126 
  127 static int ftp_init(const InitServiceAPI * const init_api)
  128 {
  129 #ifdef TARGET_BASED
  130     ftp_data_app_id = init_api->dpd->addProtocolReference("ftp-data");
  131 #endif
  132 
  133     init_api->RegisterPattern(&ftp_validate, IPPROTO_TCP, (uint8_t *)FTP_PATTERN1, sizeof(FTP_PATTERN1)-1, 0, "ftp", init_api->pAppidConfig);
  134     init_api->RegisterPattern(&ftp_validate, IPPROTO_TCP, (uint8_t *)FTP_PATTERN2, sizeof(FTP_PATTERN2)-1, 0, "ftp", init_api->pAppidConfig);
  135     init_api->RegisterPattern(&ftp_validate, IPPROTO_TCP, (uint8_t *)FTP_PATTERN3, sizeof(FTP_PATTERN3)-1, -1, "ftp", init_api->pAppidConfig);
  136     init_api->RegisterPattern(&ftp_validate, IPPROTO_TCP, (uint8_t *)FTP_PATTERN4, sizeof(FTP_PATTERN4)-1, -1, "ftp", init_api->pAppidConfig);
  137     unsigned i;
  138     for (i=0; i < sizeof(appIdRegistry)/sizeof(*appIdRegistry); i++)
  139     {
  140         _dpd.debugMsg(DEBUG_LOG,"registering appId: %d\n",appIdRegistry[i].appId);
  141         init_api->RegisterAppId(&ftp_validate, appIdRegistry[i].appId, appIdRegistry[i].additionalInfo, init_api->pAppidConfig);
  142     }
  143 
  144     return 0;
  145 }
  146 
  147 static inline void CopyVendorString(ServiceFTPData *fd, const uint8_t *vendor, unsigned int vendorLen)
  148 {
  149     unsigned int copyLen = vendorLen < sizeof(fd->vendor)-1 ? vendorLen : sizeof(fd->vendor)-1;
  150     memcpy(fd->vendor, vendor, copyLen);
  151     fd->vendor[copyLen] = '\0';
  152 }
  153 static inline void CopyVersionString(ServiceFTPData *fd, const uint8_t *version, unsigned int versionLen)
  154 {
  155     unsigned int copyLen = versionLen < sizeof(fd->version)-1 ? versionLen : sizeof(fd->version)-1;
  156     while (copyLen > 0 && !isalnum(version[copyLen-1]))
  157     {
  158         copyLen--;
  159     }
  160     memcpy(fd->version, version, copyLen);
  161     fd->version[copyLen] = '\0';
  162 }
  163 
  164 typedef enum {
  165     VVP_PARSE_HP = 1,
  166     VVP_PARSE_FILEZILLA = 2,
  167     VVP_PARSE_MS = 3,
  168     VVP_PARSE_WU = 4,
  169     VVP_PARSE_PRO_FTPD = 5,
  170     VVP_PARSE_PURE_FTPD = 6,
  171     VVP_PARSE_NC_FTPD = 7
  172 } VVP_PARSE_ENUM;
  173 
  174 static int VendorVersionParse(const uint8_t *data, uint16_t init_offset,
  175                                uint16_t offset, ServiceFTPData *fd,
  176                                const uint8_t *vendorCandidate, unsigned int vendorCandidateLen,
  177                                const uint8_t *optionalVersion, unsigned int versionLen,
  178                                VVP_PARSE_ENUM vvp_parse_type )
  179 {
  180     const unsigned char *p;
  181     const unsigned char *end;
  182     const unsigned char *ver;
  183     unsigned int verlen;
  184     int ret = 0; // no match
  185 
  186     p = &data[init_offset];
  187     end = &data[offset-1];
  188     /* Search for the vendorCandidate string */
  189     if (vvp_parse_type == VVP_PARSE_WU)
  190     {
  191         /* Search for the version string */
  192         if ((p = service_strstr(p, end-p, optionalVersion, versionLen)))
  193         {
  194             /* If we like the version we will just assign the vendor */
  195             CopyVendorString(fd, vendorCandidate, vendorCandidateLen);
  196             ret = 1;
  197 
  198             /* Found the version string.  Move just past the version string */
  199             ver = p + versionLen;
  200             p = ver;
  201             verlen = 0;
  202             while (p < end && *p && *p != ' ' )
  203                 { p++; verlen++; }
  204             CopyVersionString(fd, ver, verlen);
  205         }
  206     }
  207     else if ((p=service_strstr(p, end-p, vendorCandidate, vendorCandidateLen)))
  208     {
  209         /* Found vendorCandidate string */
  210         CopyVendorString(fd, vendorCandidate, vendorCandidateLen);
  211         ret = 1;
  212         /* Move just past the vendor string */
  213         p += vendorCandidateLen;
  214         if (optionalVersion)
  215         {
  216             /* Search for the version string */
  217             if ((p = service_strstr(p, end-p, optionalVersion, versionLen)))
  218             {
  219                 /* Found the version string.  Move just past the version string */
  220                 ver = p + versionLen;
  221                 p = ver;
  222                 verlen = 0;
  223                 switch (vvp_parse_type)
  224                 {
  225                     case VVP_PARSE_HP:
  226                         while (p < end && *p && (isalnum(*p) || *p == '.'))
  227                             { p++; verlen++; }
  228                         break;
  229                     case VVP_PARSE_FILEZILLA:
  230                         while (p < end && *p && (isalnum(*p) || *p == '.' || *p == ' '))
  231                             { p++; verlen++; }
  232                         break;
  233                     case VVP_PARSE_MS:
  234                         while (p < end && *p && *p != ')' )
  235                             { p++; verlen++; }
  236                         break;
  237                     case VVP_PARSE_PRO_FTPD:
  238                         while (p < end && *p && *p != ' ' )
  239                             { p++; verlen++; }
  240                         break;
  241                     default:
  242                         break;
  243                 }
  244                 CopyVersionString(fd, ver, verlen);
  245             }
  246         }
  247     }
  248     return ret;
  249 }
  250 static int CheckVendorVersion(const uint8_t *data, uint16_t init_offset,
  251                                uint16_t offset, ServiceFTPData *fd, VVP_PARSE_ENUM vvp_parse_type )
  252 {
  253     static const unsigned char ven_hp[] = "Hewlett-Packard FTP Print Server";
  254     static const unsigned char ver_hp[] = "Version ";
  255     static const unsigned char ven_fzilla[] = "FileZilla Server";
  256     static const unsigned char ver_fzilla[] = "version ";
  257     static const unsigned char ven_ms[] = "Microsoft FTP Service";
  258     static const unsigned char ver_ms[] = "(Version ";
  259     static const unsigned char ven_wu[] = "wu";
  260     static const unsigned char ver_wu[] = "(Version wu-";
  261     static const unsigned char ven_proftpd[] = "ProFTPD";
  262     static const unsigned char ven_pureftpd[] = "Pure-FTPd";
  263     static const unsigned char ven_ncftpd[] = "NcFTPd";
  264 
  265     if (!data || init_offset >= offset)
  266         return 0;
  267 
  268     switch (vvp_parse_type)
  269     {
  270         case VVP_PARSE_HP:
  271             return VendorVersionParse(data, init_offset, offset,fd,
  272                        ven_hp, sizeof(ven_hp)-1,
  273                        ver_hp, sizeof(ver_hp)-1,
  274                        VVP_PARSE_HP);
  275         case VVP_PARSE_FILEZILLA:
  276             return VendorVersionParse(data, init_offset, offset,fd,
  277                        ven_fzilla, sizeof(ven_fzilla)-1,
  278                        ver_fzilla, sizeof(ver_fzilla)-1,
  279                        VVP_PARSE_FILEZILLA);
  280         case VVP_PARSE_MS:
  281             return VendorVersionParse(data, init_offset, offset,fd,
  282                        ven_ms, sizeof(ven_ms)-1,
  283                        ver_ms, sizeof(ver_ms)-1,
  284                        VVP_PARSE_MS);
  285         case VVP_PARSE_WU:
  286             return VendorVersionParse(data, init_offset, offset,fd,
  287                        ven_wu, sizeof(ven_wu)-1,
  288                        ver_wu, sizeof(ver_wu)-1,
  289                        VVP_PARSE_WU);
  290         case VVP_PARSE_PRO_FTPD:
  291             return VendorVersionParse(data, init_offset, offset,fd,
  292                        ven_proftpd, sizeof(ven_proftpd)-1,
  293                        (unsigned char*)" ", sizeof(" ")-1,
  294                        VVP_PARSE_PRO_FTPD);
  295         case VVP_PARSE_PURE_FTPD:
  296             return VendorVersionParse(data, init_offset, offset,fd,
  297                        ven_pureftpd, sizeof(ven_pureftpd)-1,
  298                        NULL, 0,
  299                        VVP_PARSE_PURE_FTPD);
  300         case VVP_PARSE_NC_FTPD:
  301             return VendorVersionParse(data, init_offset, offset,fd,
  302                        ven_ncftpd, sizeof(ven_ncftpd)-1,
  303                        NULL, 0,
  304                        VVP_PARSE_NC_FTPD);
  305     }
  306     return 0;
  307 }
  308 
  309 static int ftp_parse_response(const uint8_t *data, uint16_t *offset,
  310                               uint16_t size, ServiceFTPData *fd, FTPReplyState rstate)
  311 {   
  312     for (; *offset < size; (*offset)++)
  313     {   
  314         if (data[*offset] == 0x0D)
  315         {   
  316             (*offset)++;
  317             if (*offset >= size) return -1;
  318             if (data[*offset] == 0x0D)
  319             {   
  320                 (*offset)++;
  321                 if (*offset >= size) return -1;
  322             }
  323             if (data[*offset] != 0x0A) return -1;
  324             fd->rstate = rstate;
  325             break;
  326         }
  327         if (data[*offset] == 0x0A)
  328         {   
  329             fd->rstate = rstate;
  330             break;
  331         }
  332     }
  333     return 0;
  334 }
  335 
  336 static int ftp_validate_reply(const uint8_t *data, uint16_t *offset,
  337                               uint16_t size, ServiceFTPData *fd)
  338 {
  339     const ServiceFTPCode *code_hdr;
  340     int tmp;
  341     FTPReplyState tmp_state;
  342 
  343     for (; *offset < size; (*offset)++)
  344     {
  345         /* Trim any blank lines (be a little tolerant) */
  346         for (; *offset<size; (*offset)++)
  347         {
  348             if (data[*offset] != 0x0D && data[*offset] != 0x0A) break;
  349         }
  350 
  351         switch (fd->rstate)
  352         {
  353         case FTP_REPLY_BEGIN:
  354             if (size - (*offset) < (int)sizeof(ServiceFTPCode)) return -1;
  355 
  356             code_hdr = (ServiceFTPCode *)(data + *offset);
  357 
  358             if (code_hdr->sp == '-') fd->rstate = FTP_REPLY_MULTI;
  359             else if (code_hdr->sp != ' ' && code_hdr->sp != 0x09) return -1;
  360 
  361             if (code_hdr->code[0] < '1' || code_hdr->code[0] > '5') return -1;
  362             fd->code = (code_hdr->code[0] - '0') * 100;
  363 
  364             if (code_hdr->code[1] < '0' || code_hdr->code[1] > '5') return -1;
  365             fd->code += (code_hdr->code[1] - '0') * 10;
  366 
  367             if (!isdigit(code_hdr->code[2])) return -1;
  368             fd->code += code_hdr->code[2] - '0';
  369 
  370             *offset += sizeof(ServiceFTPCode);
  371             tmp_state = fd->rstate;
  372 
  373             if (!fd->vendor[0] && !fd->version[0])
  374             {
  375                 if (fd->code == 220)
  376                 {
  377                     // These vendor strings are present on the first "220" whether that is the "220-" or "220 "
  378                     if (!CheckVendorVersion(data, *offset, size, fd, VVP_PARSE_MS ) &&
  379                         !CheckVendorVersion(data, *offset, size, fd, VVP_PARSE_WU ) &&
  380                         !CheckVendorVersion(data, *offset, size, fd, VVP_PARSE_PRO_FTPD ) &&
  381                         !CheckVendorVersion(data, *offset, size, fd, VVP_PARSE_PURE_FTPD ) &&
  382                         !CheckVendorVersion(data, *offset, size, fd, VVP_PARSE_NC_FTPD ) &&
  383                         !CheckVendorVersion(data, *offset, size, fd, VVP_PARSE_FILEZILLA)
  384                         )
  385                     {
  386                         /* Look for (Vendor Version:  or  (Vendor Version) */
  387                         const unsigned char *end;
  388                         const unsigned char *p;
  389                         const unsigned char *ven;
  390                         const unsigned char *ver;
  391                         end = &data[size-1];
  392                         for (p=&data[*offset]; p<end && *p && *p!='('; p++);
  393                         if (p < end)
  394                         {
  395                             p++;
  396                             ven = p;
  397                             for (; p<end && *p && *p!=' '; p++);
  398                             if (p < end && *p)
  399                             {
  400                                 CopyVendorString(fd, ven, p-ven);
  401                                 ver = p + 1;
  402                                 for (p=ver; p<end && *p && *p!=':'; p++);
  403                                 if (p>=end || !(*p))
  404                                 {
  405                                     for (p=ver; p<end && *p && *p!=')'; p++);
  406                                 }
  407                                 if (p < end && *p)
  408                                 {
  409                                     CopyVersionString(fd, ver, p-ver);
  410                                 }
  411                             }
  412                         }
  413                     }
  414                 }
  415                 else if (fd->code == 230)
  416                 {
  417                     // These vendor strings are present on the first "230" whether that is the "230-" or "230 "
  418                     CheckVendorVersion(data, *offset, size, fd, VVP_PARSE_HP);
  419                 }
  420             }
  421 
  422         fd->rstate = FTP_REPLY_MID;
  423             if (ftp_parse_response(data, offset, size, fd, tmp_state))
  424         return -1;
  425         if (fd->rstate == FTP_REPLY_MID)
  426         fd->rstate = FTP_REPLY_LONG;
  427             break;
  428         case FTP_REPLY_MULTI:
  429             if (size - *offset < (int)sizeof(ServiceFTPCode))
  430             {
  431         fd->rstate = FTP_REPLY_MID;
  432         if (ftp_parse_response(data, offset, size, fd, FTP_REPLY_MULTI))
  433             return -1;
  434                 if (fd->rstate == FTP_REPLY_MID) 
  435             fd->rstate = FTP_REPLY_LONG;
  436             }
  437             else
  438             {
  439                 code_hdr = (ServiceFTPCode *)(data + *offset);
  440                 if ((code_hdr->sp == ' ' || code_hdr->sp == 0x09) &&
  441                     code_hdr->code[0] >= '1' && code_hdr->code[0] <= '5' &&
  442                     code_hdr->code[1] >= '1' && code_hdr->code[1] <= '5' &&
  443                     isdigit(code_hdr->code[2]))
  444                 {
  445                     tmp = (code_hdr->code[0] - '0') * 100;
  446                     tmp += (code_hdr->code[1] - '0') * 10;
  447                     tmp += code_hdr->code[2] - '0';
  448                     if (tmp == fd->code)
  449                     {
  450                         *offset += sizeof(ServiceFTPCode);
  451                         fd->rstate = FTP_REPLY_BEGIN;
  452                     }
  453                 }
  454                 tmp_state = fd->rstate;
  455         fd->rstate = FTP_REPLY_MID;
  456         if (ftp_parse_response(data, offset, size, fd, tmp_state))
  457             return -1;
  458                 if (fd->rstate == FTP_REPLY_MID)
  459            fd->rstate = FTP_REPLY_LONG;
  460             }
  461             break;
  462     case FTP_REPLY_LONG:
  463         fd->rstate = FTP_REPLY_MID;
  464         if (ftp_parse_response(data, offset, size, fd, FTP_REPLY_LONG))
  465         return -1;
  466             if ((++(*offset)) >= size)
  467             {
  468                 fd->rstate = FTP_REPLY_BEGIN;
  469                 break;
  470             }
  471         if (fd->rstate == FTP_REPLY_MID)
  472         {
  473                 fd->rstate = FTP_REPLY_LONG;
  474         break;
  475         }
  476             if (size - *offset < (int)sizeof(ServiceFTPCode))
  477             {   
  478         fd->rstate = FTP_REPLY_MID;
  479         if (ftp_parse_response(data, offset, size, fd, FTP_REPLY_LONG))
  480             return -1;
  481                 if (fd->rstate == FTP_REPLY_MID)
  482                     fd->rstate = FTP_REPLY_LONG;
  483             }
  484             else
  485         {
  486             code_hdr = (ServiceFTPCode *)(data + *offset);
  487                 if(code_hdr->code[0] >= '1' && code_hdr->code[0] <= '5' &&
  488                     code_hdr->code[1] >= '1' && code_hdr->code[1] <= '5' &&
  489                     isdigit(code_hdr->code[2]))
  490                 {
  491                     tmp = (code_hdr->code[0] - '0') * 100;
  492                     tmp += (code_hdr->code[1] - '0') * 10;
  493                     tmp += code_hdr->code[2] - '0';
  494                     if (tmp == fd->code)
  495                     {
  496                         *offset += sizeof(ServiceFTPCode);
  497             if (code_hdr->sp == ' ' || code_hdr->sp == 0x09)
  498             {
  499                 fd->rstate = FTP_REPLY_MID;
  500                 if (ftp_parse_response(data, offset, size, fd, FTP_REPLY_BEGIN))
  501                 return -1;
  502             }
  503             else if (code_hdr->sp == '-')
  504             {
  505                 fd->rstate = FTP_REPLY_MID;
  506                 if (ftp_parse_response(data, offset, size, fd, FTP_REPLY_MULTI))
  507                 return -1;
  508             }
  509             if (fd->rstate == FTP_REPLY_MID)
  510                             fd->rstate = FTP_REPLY_LONG;
  511                     }
  512                 }
  513         }
  514             break;  
  515         default:
  516             return -1;
  517         }
  518         if (fd->rstate == FTP_REPLY_BEGIN)
  519         {
  520             for (; *offset < size; (*offset)++)
  521             {
  522                 if (data[*offset] == 0x0D)
  523                 {
  524                     (*offset)++;
  525                     if (*offset >= size) return -1;
  526                     if (data[*offset] != 0x0A) return -1;
  527                 }
  528                 else if (!isspace(data[*offset])) break;
  529             }
  530             return fd->code;
  531         }
  532     }
  533     return 0;
  534 }
  535 
  536 static inline int _ftp_decode_number32(const uint8_t * *data, const uint8_t *end, uint8_t delimiter, uint32_t *number)
  537 {
  538     const uint8_t *local_data;
  539     uint32_t local_number = 0;
  540     for (local_data = *data; local_data < end && *local_data == ' '; local_data++);
  541     if (local_data < end && *local_data == delimiter)
  542     {
  543         *number = 0;
  544         return -1;
  545     }
  546     while (local_data < end && *local_data != delimiter)
  547     {
  548         if (!isdigit(*local_data))
  549         {
  550             *number = 0;
  551             return -1;
  552         }
  553         local_number *= 10;
  554         local_number += *local_data - '0';
  555         local_data++;
  556     }
  557     if (local_data >= end || *local_data != delimiter)
  558     {
  559         *number = 0;
  560         return -1;
  561     }
  562     *number = local_number;
  563     *data = local_data+1;
  564     return 0;
  565 }
  566 static int ftp_decode_octet(const uint8_t * *data, const uint8_t *end, uint8_t delimiter, uint32_t *number)
  567 {
  568     if (_ftp_decode_number32(data, end, delimiter, number) == -1) return -1;
  569     if (*number > 255)
  570     {
  571         *number = 0;
  572         return -1;
  573     }
  574     return 0;
  575 }
  576 
  577 static int ftp_decode_port_number(const uint8_t * *data, const uint8_t *end, uint8_t delimiter, uint32_t *number)
  578 {
  579     if (_ftp_decode_number32(data, end, delimiter, number) == -1) return -1;
  580     if (*number > 65535)
  581     {
  582         *number = 0;
  583         return -1;
  584     }
  585     return 0;
  586 }
  587 
  588 static int ftp_validate_pasv(const uint8_t *data, uint16_t size,
  589                              uint32_t *address, uint16_t *port)
  590 {
  591     const uint8_t *end;
  592     uint32_t tmp;
  593 
  594     *address = 0;
  595     *port = 0;
  596 
  597     end = data + size;
  598     data += sizeof(ServiceFTPCode);
  599 
  600     for (; data<end && *data!='('; data++);
  601     data++;
  602     if (data >= end) return 1;
  603 
  604     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  605     *address = tmp << 24;
  606     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  607     *address += tmp << 16;
  608     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  609     *address += tmp << 8;
  610     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  611     *address += tmp;
  612     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  613     *port = (uint16_t)(tmp << 8);
  614     if (ftp_decode_octet(&data, end, ')', &tmp)) return -1;
  615     *port += tmp;
  616     return 0;
  617 }
  618 
  619 static int ftp_validate_epsv(const uint8_t *data, uint16_t size,
  620                              uint16_t *port)
  621 {
  622     const uint8_t *end;
  623     uint8_t delimiter;
  624 
  625     *port = 0;
  626 
  627     end = data + size;
  628     data += sizeof(ServiceFTPCode);
  629 
  630     for (; data<end && *data!='('; data++);
  631     data++;
  632     if (data >= end) return 1;
  633 
  634     delimiter = *data++;
  635     if (data >= end) return 1;
  636 
  637     for (; data<end && *data!=delimiter; data++);
  638     data++;
  639     if (data >= end) return 1;
  640 
  641     for (; data<end && *data!=delimiter; data++);
  642     data++;
  643     if (data >= end) return 1;
  644 
  645     while (data < end && *data != delimiter)
  646     {
  647         if (!isdigit(*data)) return -1;
  648         *port *= 10;
  649         *port += *data - '0';
  650         data++;
  651     }
  652 
  653     return 0;
  654 }
  655 
  656 static int ftp_validate_port(const uint8_t *data, uint16_t size,
  657                              sfaddr_t *address, uint16_t *port)
  658 {
  659     const uint8_t *end;
  660     const uint8_t *p;
  661     uint32_t tmp;
  662     uint32_t addr;
  663     uint32_t addr2;
  664 
  665     memset(address,0,sizeof(sfaddr_t));
  666     *port = 0;
  667 
  668     end = data + size;
  669 
  670     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  671     addr = tmp << 24;
  672     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  673     addr += tmp << 16;
  674     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  675     addr += tmp << 8;
  676     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  677     addr += tmp;
  678     addr2 = htonl(addr); // make it network order before calling sfip_set_raw()
  679     sfip_set_raw(address, &addr2, AF_INET);
  680 
  681     if (ftp_decode_octet(&data, end, ',', &tmp)) return -1;
  682     *port = (uint16_t)(tmp << 8);
  683     p = end - 1;
  684     if (p > data)
  685     {
  686         if (*p == 0x0a)
  687         {
  688             p--;
  689             if (*p == 0x0d)
  690             {
  691                 if (ftp_decode_octet(&data, end, 0x0d, &tmp)) return -1;
  692                 *port += tmp;
  693                 return 0;
  694             }
  695         }
  696     }
  697     if (ftp_decode_octet(&data, end, 0x0a, &tmp)) return -1;
  698     *port += tmp;
  699     return 0;
  700 }
  701 /* RFC 2428 support */
  702 typedef struct addr_family_map_t
  703 {
  704     uint16_t eprt_fam;
  705     uint16_t sfaddr_fam;
  706 } addr_family_map;
  707 
  708 static addr_family_map RFC2428_known_address_families[] =
  709 {   { 1, AF_INET },
  710     { 2, AF_INET6 },
  711     { 0, 0 }
  712 };
  713 
  714 static int ftp_validate_eprt(const uint8_t *data, uint16_t size,
  715                              sfaddr_t *address, uint16_t *port)
  716 {
  717     int index;
  718     int addrFamilySupported = 0;
  719     uint8_t delimiter;
  720     const uint8_t *end;
  721     uint32_t tmp;
  722     char tmp_str[INET6_ADDRSTRLEN+1];
  723 
  724     memset(address,0,sizeof(sfaddr_t));
  725     *port = 0;
  726 
  727     end = data + size;
  728 
  729     delimiter = *data++; // all delimiters will match this one.
  730     if (ftp_decode_octet(&data, end, delimiter, &tmp))
  731         return -1;
  732 
  733     // Look up the address family in the table.
  734     for (index = 0; !addrFamilySupported && RFC2428_known_address_families[index].eprt_fam != 0; index++)
  735     {
  736         if ( RFC2428_known_address_families[index].eprt_fam == (uint16_t)tmp )
  737         {
  738             addrFamilySupported = RFC2428_known_address_families[index].sfaddr_fam;
  739         }
  740     }
  741     if (!addrFamilySupported) // not an ipv4 or ipv6 address being provided.
  742         return -1;
  743 
  744     for (index = 0;
  745         index < INET6_ADDRSTRLEN && data < end && *data != delimiter;
  746         index++, data++ )
  747     {
  748         tmp_str[index] = *data;
  749     }
  750     tmp_str[index] = '\0'; // make the copied portion be nul terminated.
  751 
  752     if (sfip_convert_ip_text_to_binary( addrFamilySupported, tmp_str, &address->ip ) != SFIP_SUCCESS)
  753         return -1;
  754 
  755     address->family = addrFamilySupported;
  756 
  757     data++; // skip the delimiter at the end of the address substring.
  758     if (ftp_decode_port_number(&data, end, delimiter, &tmp)) // an error is returned if port was greater than 65535
  759         return -1;
  760 
  761     *port = (uint16_t)tmp;
  762     return 0;
  763 }
  764 
  765 static inline void WatchForCommandResult(ServiceFTPData *fd, tAppIdData *flowp, FTPCmd command)
  766 {
  767     if (fd->state != FTP_STATE_MONITOR)
  768     {
  769         setAppIdFlag(flowp, APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_CONTINUE);
  770         fd->state = FTP_STATE_MONITOR;
  771     }
  772     fd->cmd = command;
  773 }
  774 
  775 static inline void CreateExpectedSession(tAppIdData *flowp, SFSnortPacket *ctrlPkt, sfaddr_t *cliIp, uint16_t cliPort,
  776                 sfaddr_t *srvIp, uint16_t srvPort, uint8_t proto, int flags, APPID_SESSION_DIRECTION dir)
  777 {
  778     tAppIdData *fp;
  779 
  780     fp = ftp_service_mod.api->flow_new(flowp, ctrlPkt, cliIp, cliPort, srvIp, srvPort, proto, ftp_data_app_id, flags);
  781     if (fp) // initialize data session
  782     {
  783         unsigned encryptedFlag = getAppIdFlag(flowp, APPID_SESSION_ENCRYPTED | APPID_SESSION_DECRYPTED);
  784         if (encryptedFlag == APPID_SESSION_ENCRYPTED)
  785         {
  786             fp->serviceAppId = APP_ID_FTPSDATA;
  787         }
  788         else
  789         {
  790             encryptedFlag = 0; // change (APPID_SESSION_ENCRYPTED | APPID_SESSION_DECRYPTED) case to zeroes.
  791             fp->serviceAppId = APP_ID_FTP_DATA;
  792         }
  793         PopulateExpectedFlow(flowp, fp, APPID_SESSION_IGNORE_ID_FLAGS | encryptedFlag, dir);
  794     }
  795 }
  796 
  797 static int ftp_validate(ServiceValidationArgs* args)
  798 {
  799     static const char FTP_PASV_CMD[] = "PASV";
  800     static const char FTP_EPSV_CMD[] = "EPSV";
  801     static const char FTP_PORT_CMD[] = "PORT ";
  802     static const char FTP_EPRT_CMD[] = "EPRT ";
  803     ServiceFTPData *fd;
  804     uint16_t offset;
  805     uint16_t init_offset;
  806     int code;
  807     int code_index;
  808     uint32_t address;
  809     uint16_t port;
  810     int retval = SERVICE_INPROCESS;
  811     tAppIdData *flowp = args->flowp;
  812     const uint8_t *data = args->data;
  813     SFSnortPacket *pkt = args->pkt;
  814     const int dir = args->dir;
  815     uint16_t size = args->size;
  816 
  817     if (!size)
  818         goto inprocess;
  819 
  820     //ignore packets while encryption is on in explicit mode. In future, this will be changed
  821     //to direct traffic to SSL detector to extract payload from certs. This will require manintaining
  822     //two detector states at the same time.
  823     if (getAppIdFlag(flowp, APPID_SESSION_ENCRYPTED))
  824     {
  825         if (!getAppIdFlag(flowp, APPID_SESSION_DECRYPTED))
  826         {
  827             goto inprocess;
  828         }
  829     }
  830 
  831     fd = ftp_service_mod.api->data_get(flowp, ftp_service_mod.flow_data_index);
  832     if (!fd)
  833     {
  834         fd = calloc(1, sizeof(*fd));
  835         if (!fd)
  836             return SERVICE_ENOMEM;
  837         if (ftp_service_mod.api->data_add(flowp, fd, ftp_service_mod.flow_data_index, &free))
  838         {
  839             free(fd);
  840             return SERVICE_ENOMEM;
  841         }
  842         fd->state = FTP_STATE_CONNECTION;
  843         fd->rstate = FTP_REPLY_BEGIN;
  844         fd->cmd = FTP_CMD_NONE;
  845     }
  846 
  847     if (dir != APP_ID_FROM_RESPONDER)
  848     {
  849         if (data[size-1] != 0x0a) goto inprocess;
  850 
  851         if (size > sizeof(FTP_PORT_CMD)-1 &&
  852             strncasecmp((char *)data, FTP_PORT_CMD, sizeof(FTP_PORT_CMD)-1) == 0)
  853         {
  854             if (ftp_validate_port(data+(sizeof(FTP_PORT_CMD)-1),
  855                                   size-(sizeof(FTP_PORT_CMD)-1),
  856                                   &fd->address, &fd->port) == 0)
  857             {
  858                 CreateExpectedSession(flowp, pkt, GET_DST_IP(pkt), 0, &fd->address, fd->port, flowp->proto,
  859                                       APPID_EARLY_SESSION_FLAG_FW_RULE, APP_ID_FROM_RESPONDER);
  860                 WatchForCommandResult(fd, flowp, FTP_CMD_PORT_EPRT);
  861             }
  862         }
  863         else if (size > sizeof(FTP_EPRT_CMD)-1 &&
  864             strncasecmp((char *)data, FTP_EPRT_CMD, sizeof(FTP_EPRT_CMD)-1) == 0)
  865         {
  866             if (ftp_validate_eprt(data+(sizeof(FTP_EPRT_CMD)-1),
  867                                   size-(sizeof(FTP_EPRT_CMD)-1),
  868                                   &fd->address, &fd->port) == 0)
  869             {
  870                 CreateExpectedSession(flowp, pkt, GET_DST_IP(pkt), 0, &fd->address, fd->port, flowp->proto,
  871                                       APPID_EARLY_SESSION_FLAG_FW_RULE, APP_ID_FROM_RESPONDER);
  872                 WatchForCommandResult(fd, flowp, FTP_CMD_PORT_EPRT);
  873             }
  874         }
  875         else if ( size > sizeof(FTP_PASV_CMD)-1 &&
  876                   ( strncasecmp((char *)data, FTP_PASV_CMD, sizeof(FTP_PASV_CMD)-1) == 0 ||
  877                     strncasecmp((char *)data, FTP_EPSV_CMD, sizeof(FTP_EPSV_CMD)-1) == 0 )
  878                 )
  879         {
  880             WatchForCommandResult(fd, flowp, FTP_CMD_PASV_EPSV);
  881         }
  882         goto inprocess;
  883     }
  884 
  885     offset = 0;
  886     while (offset < size)
  887     {
  888         init_offset = offset;
  889         if ((code=ftp_validate_reply(data, &offset, size, fd)) < 0) goto fail;
  890         if (!code) goto inprocess;
  891 
  892         switch (fd->state)
  893         {
  894         case FTP_STATE_CONNECTION:
  895             switch (code)
  896             {
  897             case 120: /*system will be ready in nn minutes */
  898                 break;
  899             case 220: /*service ready for new user */
  900                 fd->state = FTP_STATE_LOGIN;
  901                 break;
  902             case 110: /* restart mark reply */
  903             case 125: /* connection is open start transferring file */
  904             case 150: /* Opening command */
  905             case 200: /*command ok */
  906             case 202: /*command not implemented */
  907             case 211: /* system status */
  908             case 212: /* directory status */
  909             case 213: /* file status */
  910             case 214: /* help message */
  911             case 215: /* name system type */
  912             case 225: /* data connection open */
  913             case 226: /* Transfer complete */
  914             case 227: /*entering passive mode */
  915             case 230: /*user loggined */
  916             case 250: /* CWD command successful */
  917             case 257: /* PATHNAME created */
  918             case 331: /* login ok need password */
  919             case 332: /*new account for login */
  920             case 350: /*requested file action pending futher information */
  921             case 450: /*requested file action not taken */
  922             case 451: /*requested file action aborted */
  923             case 452: /*requested file action not taken not enough space */
  924             case 500: /*syntax error */
  925             case 501: /*not recognozed */
  926             case 502: /*not recognozed */
  927             case 503: /*bad sequence of commands */
  928             case 504: /*command not implemented */
  929             case 530: /*login incorrect */
  930             case 532: /*new account for storing file */
  931             case 550: /*requested action not taken */
  932             case 551: /*requested action aborted :page type unknown */
  933             case 552: /*requested action aborted */
  934             case 553: /*requested action not taken file name is not allowed */
  935                 setAppIdFlag(flowp, APPID_SESSION_SERVICE_DETECTED | APPID_SESSION_CONTINUE);
  936                 fd->state = FTP_STATE_MONITOR;
  937                 break;
  938             case 221: /*good bye */
  939             case 421: /*service not available closing connection */
  940                 fd->state = FTP_STATE_CONNECTION_ERROR;
  941                 break;
  942             default:
  943                 goto fail;
  944             }
  945             break;
  946         case FTP_STATE_LOGIN:
  947             code_index = code / 100;
  948             switch (code_index)
  949             {
  950             case 2:
  951                 switch (code)
  952                 {
  953                 case 221:
  954                     fd->state = FTP_STATE_CONNECTION_ERROR;
  955                     break;
  956                 case 230:
  957                     setAppIdFlag(flowp, APPID_SESSION_CONTINUE);
  958                     fd->state = FTP_STATE_MONITOR;
  959                     retval = SERVICE_SUCCESS;
  960                     break;
  961                 case 234:
  962                     {
  963                         retval = SERVICE_SUCCESS;
  964                         /*
  965                         // we do not set the state to FTP_STATE_MONITOR here because we don't know
  966                         // if there will be SSL decryption to allow us to see what we are interested in.
  967                         // Let the WatchForCommandResult() usage elsewhere take care of it.
  968                         */
  969                         setAppIdFlag(flowp, APPID_SESSION_CONTINUE | APPID_SESSION_ENCRYPTED | APPID_SESSION_STICKY_SERVICE);
  970                     }
  971                     break;
  972                 default:
  973                     break;
  974                 }
  975                 break;
  976             case 3:
  977                 switch (code)
  978                 {
  979                 case 331:
  980                     setAppIdFlag(flowp, APPID_SESSION_CONTINUE);
  981                     fd->state = FTP_STATE_PASSWORD;
  982                     retval = SERVICE_SUCCESS;
  983                     break;
  984                 case 332:
  985                     fd->state = FTP_STATE_ACCOUNT;
  986                     break;
  987                 default:
  988                     break;
  989                 }
  990                 break;
  991             case 4:
  992                 switch (code)
  993                 {
  994                 case 421:
  995                     fd->state = FTP_STATE_CONNECTION_ERROR;
  996                     break;
  997                 case 431:
  998                     break;
  999                 default:
 1000                     goto fail;
 1001                 }
 1002                 break;
 1003             case 5:
 1004                 break;
 1005             default:
 1006                 goto fail;
 1007             }
 1008             break;
 1009         case FTP_STATE_PASSWORD:
 1010             code_index = code / 100;
 1011             switch (code_index)
 1012             {
 1013             case 2:
 1014                 switch (code)
 1015                 {
 1016                 case 221:
 1017                     fd->state = FTP_STATE_CONNECTION_ERROR;
 1018                     break;
 1019                 case 202:
 1020                 case 230:
 1021                     setAppIdFlag(flowp, APPID_SESSION_CONTINUE);
 1022                     fd->state = FTP_STATE_MONITOR;
 1023                     retval = SERVICE_SUCCESS;
 1024                 default:
 1025                     break;
 1026                 }
 1027                 break;
 1028             case 3:
 1029                 switch (code)
 1030                 {
 1031                 case 332:
 1032                     fd->state = FTP_STATE_ACCOUNT;
 1033                     break;
 1034                 default:
 1035                     break;
 1036                 }
 1037                 break;
 1038             case 4:
 1039                 switch (code)
 1040                 {
 1041                 case 421:
 1042                     fd->state = FTP_STATE_CONNECTION_ERROR;
 1043                     break;
 1044                 default:
 1045                     goto fail;
 1046                 }
 1047                 break;
 1048             case 5:
 1049                 switch (code)
 1050                 {
 1051                 case 500:
 1052                 case 501:
 1053                 case 503:
 1054                 case 530:
 1055                     fd->state = FTP_STATE_LOGIN;
 1056                     break;
 1057                 default:
 1058                     goto fail;
 1059                 }
 1060                 break;
 1061             default:
 1062                 goto fail;
 1063             }
 1064             break;
 1065         case FTP_STATE_ACCOUNT:
 1066             code_index = code / 100;
 1067             switch (code_index)
 1068             {
 1069             case 2:
 1070                 switch (code)
 1071                 {
 1072                 case 202:
 1073                 case 230:
 1074                     setAppIdFlag(flowp, APPID_SESSION_CONTINUE);
 1075                     fd->state = FTP_STATE_MONITOR;
 1076                     retval = SERVICE_SUCCESS;
 1077                 default:
 1078                     break;
 1079                 }
 1080                 break;
 1081             case 3:
 1082                 switch (code)
 1083                 {
 1084                 case 332:
 1085                     fd->state = FTP_STATE_ACCOUNT;
 1086                     break;
 1087                 default:
 1088                     break;
 1089                 }
 1090                 break;
 1091             case 4:
 1092                 switch (code)
 1093                 {
 1094                 case 421:
 1095                     fd->state = FTP_STATE_CONNECTION_ERROR;
 1096                     break;
 1097                 default:
 1098                     goto fail;
 1099                 }
 1100                 break;
 1101             case 5:
 1102                 switch (code)
 1103                 {
 1104                 case 500:
 1105                 case 501:
 1106                 case 503:
 1107                 case 530:
 1108                     fd->state = FTP_STATE_LOGIN;
 1109                     break;
 1110                 default:
 1111                     goto fail;
 1112                 }
 1113                 break;
 1114             default:
 1115                 goto fail;
 1116             }
 1117             break;
 1118         case FTP_STATE_MONITOR: // looking for the DATA channel info in the result
 1119             switch (code)
 1120             {
 1121             case 227:
 1122                 {
 1123                     code = ftp_validate_pasv(data + init_offset,
 1124                                              (uint16_t)(offset-init_offset),
 1125                                              &address, &port);
 1126                     if (!code)
 1127                     {
 1128                         sfaddr_t ip;
 1129                         sfaddr_t *sip;
 1130                         sfaddr_t *dip;
 1131                         uint32_t addr;
 1132 
 1133                         dip = GET_DST_IP(pkt);
 1134                         sip = GET_SRC_IP(pkt);
 1135                         addr = htonl(address);
 1136                         sfip_set_raw(&ip, &addr, AF_INET);
 1137                         CreateExpectedSession(flowp, pkt, dip, 0, &ip, port, flowp->proto,
 1138                                               APPID_EARLY_SESSION_FLAG_FW_RULE, APP_ID_FROM_INITIATOR);
 1139 
 1140                         if (!sfip_fast_eq6(&ip, sip))
 1141                         {
 1142                             CreateExpectedSession(flowp, pkt, dip, 0, sip, port, flowp->proto,
 1143                                                   APPID_EARLY_SESSION_FLAG_FW_RULE, APP_ID_FROM_INITIATOR);
 1144                         }
 1145                         ftp_service_mod.api->add_payload(flowp, APP_ID_FTP_PASSIVE); // Passive mode FTP is reported as a payload id
 1146                     }
 1147                     else if (code < 0)
 1148                     {
 1149                         goto fail;
 1150                     }
 1151                 }
 1152                 break;
 1153             case 229:
 1154                 {
 1155                     code = ftp_validate_epsv(data + init_offset,
 1156                                              (uint16_t)(offset-init_offset),
 1157                                              &port);
 1158 
 1159                     if (!code)
 1160                     {
 1161                         sfaddr_t *sip;
 1162                         sfaddr_t *dip;
 1163 
 1164                         dip = GET_DST_IP(pkt);
 1165                         sip = GET_SRC_IP(pkt);
 1166                         CreateExpectedSession(flowp, pkt, dip, 0, sip, port, flowp->proto,
 1167                                               APPID_EARLY_SESSION_FLAG_FW_RULE, APP_ID_FROM_INITIATOR);
 1168                         ftp_service_mod.api->add_payload(flowp, APP_ID_FTP_PASSIVE); // Passive mode FTP is reported as a payload id
 1169                     }
 1170                     else if (code < 0)
 1171                     {
 1172                         goto fail;
 1173                     }
 1174                 }
 1175                 break;
 1176             case 200:
 1177                 if (fd->cmd == FTP_CMD_PORT_EPRT)
 1178                 {
 1179                     // Expected session is created on PORT/EPRT command
 1180                     ftp_service_mod.api->add_payload(flowp, APP_ID_FTP_ACTIVE); // Active mode FTP is reported as a payload id
 1181                 }
 1182                 break;
 1183             default:
 1184                 break;
 1185             }
 1186             fd->cmd = FTP_CMD_NONE;
 1187             break;
 1188         case FTP_STATE_CONNECTION_ERROR:
 1189         default:
 1190             goto fail;
 1191         }
 1192     }
 1193 
 1194     switch (retval)
 1195     {
 1196     default:
 1197     case SERVICE_INPROCESS:
 1198 inprocess:
 1199         if (!getAppIdFlag(flowp, APPID_SESSION_SERVICE_DETECTED))
 1200         {
 1201             ftp_service_mod.api->service_inprocess(flowp, pkt, dir, &svc_element, NULL);
 1202         }
 1203         return SERVICE_INPROCESS;
 1204 
 1205     case SERVICE_SUCCESS:
 1206         if (!getAppIdFlag(flowp, APPID_SESSION_SERVICE_DETECTED))
 1207         {
 1208             uint64_t encryptedFlag = getAppIdFlag(flowp, APPID_SESSION_ENCRYPTED | APPID_SESSION_DECRYPTED);
 1209             ftp_service_mod.api->add_service(flowp, pkt, dir, &svc_element,
 1210                                              encryptedFlag == APPID_SESSION_ENCRYPTED ? // FTPS only when encrypted==1 decrypted==0
 1211                                                 APP_ID_FTPS : APP_ID_FTP_CONTROL,
 1212                                              fd->vendor[0] ? fd->vendor:NULL,
 1213                                              fd->version[0] ? fd->version:NULL, NULL, NULL);
 1214         }
 1215         return SERVICE_SUCCESS;
 1216 
 1217     case SERVICE_NOMATCH:
 1218 fail:
 1219         if (!getAppIdFlag(flowp, APPID_SESSION_SERVICE_DETECTED))
 1220         {
 1221             ftp_service_mod.api->fail_service(flowp, pkt, dir, &svc_element,
 1222                                               ftp_service_mod.flow_data_index, args->pConfig, NULL);
 1223         }
 1224         clearAppIdFlag(flowp, APPID_SESSION_CONTINUE);
 1225         return SERVICE_NOMATCH;
 1226     }
 1227 }
 1228