⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pp_ftp.c

📁 Snort为国际上著名的轻量型入侵防御系统,为国内多家著名“自主知识产权”网络安全公司所使用。
💻 C
📖 第 1 页 / 共 4 页
字号:
                dirPtr = strtok(NULL, "/");            }            /* If reset == 1, there was a mismatch of what we             * had before.  Update it now */            while (dirPtr && reset)            {                iLen = strlen(dirPtr);                thisNode = malloc(sizeof(FTP_DIR_NODE));                thisNode->name = calloc(sizeof(char), iLen + 1);                memcpy(thisNode->name, dirPtr, iLen);                if (!Session->curr_directory)                {                    Session->curr_directory = thisNode;                    Session->head_directory = thisNode;                    thisNode->parent = NULL;                    thisNode->next = NULL;                }                else                {                    thisNode->parent = Session->curr_directory;                    thisNode->next = NULL;                    Session->curr_directory->next = thisNode;                    Session->curr_directory = thisNode;                }                dirPtr = strtok(NULL, "/");            }        }        break;    }}#endif /* MAINTAIN_DIR_STATE *//* * Function: do_stateful_checks(FTP_SESSION *Session, Packet *p, *                            FTP_CLIENT_REQ *req, int rsp_code) * * Purpose: Handle stateful checks and state updates for FTP response *          packets. * * Arguments: Session        => Pointer to session info *            p              => Pointer to the current packet struct *            req            => Pointer to current response from packet *                              (this function may be called multiple *                              times for pipelined requests). *            rsp_code       => Integer response value for server response * * Returns: int => return code indicating error or success * */int do_stateful_checks(FTP_SESSION *Session, SFSnortPacket *p,                       FTP_CLIENT_REQ *req, int rsp_code){    int iRet = FTPP_SUCCESS;    if (Session->server_conf->data_chan)    {        if (rsp_code == 226)        {            /* Just ignore this code -- end of transfer...             * If we saw all the other dat for this channel             * Session->data_chan_state should be NO_STATE. */        }        else if (Session->data_chan_state & DATA_CHAN_PASV_CMD_ISSUED)        {            if (ftp_cmd_pipe_index == Session->data_chan_index)            {                if (Session->data_xfer_index == -1)                    ftp_cmd_pipe_index = 0;                Session->data_chan_index = -1;                if (rsp_code == 227)                {                    u_int32_t ip=0;                    u_int16_t port=0;                    char *ip_begin = req->param_begin;                    Session->data_chan_state &= ~DATA_CHAN_PASV_CMD_ISSUED;                    Session->data_chan_state |= DATA_CHAN_PASV_CMD_ACCEPT;                    Session->data_chan_index = -1;                    /* Interpret response message to identify the                     * Server IP/Port.  Server response is inside                     * a pair of ()s.  Find the left (, and use same                     * means to find IP/Port as is done for the PORT                     * command. */                    while ((*ip_begin != '(') &&                           (ip_begin < req->param_end))                    {                        ip_begin++;                    }                    if (ip_begin < req->param_end)                    {                        ip_begin++;                        iRet = getIP(&ip_begin, req->param_end, ')',                                     &ip, &port);                        if (iRet == FTPP_SUCCESS)                        {                            Session->serverIP = htonl(ip);                            Session->serverPort = port;                            Session->clientIP = 0;                            Session->clientPort = 0;                        }                    }                    else                    {                        iRet = FTPP_MALFORMED_FTP_RESPONSE;                    }                }                else                {                    Session->data_chan_index = -1;                    Session->data_chan_state &= ~DATA_CHAN_PASV_CMD_ISSUED;                }            }        }        else if (Session->data_chan_state & DATA_CHAN_PORT_CMD_ISSUED)        {            if (ftp_cmd_pipe_index == Session->data_chan_index)            {                if (Session->data_xfer_index == -1)                    ftp_cmd_pipe_index = 0;                Session->data_chan_index = -1;                if (rsp_code == 200)                {                    Session->data_chan_state &= ~DATA_CHAN_PORT_CMD_ISSUED;                    Session->data_chan_state |= DATA_CHAN_PORT_CMD_ACCEPT;                    Session->data_chan_index = -1;                }                else if (ftp_cmd_pipe_index == Session->data_chan_index)                {                    Session->data_chan_index = -1;                    Session->data_chan_state &= ~DATA_CHAN_PORT_CMD_ISSUED;                }            }        }        else if (Session->data_chan_state & DATA_CHAN_XFER_CMD_ISSUED)        {            if (ftp_cmd_pipe_index == Session->data_xfer_index)            {                if (Session->data_chan_index == -1)                    ftp_cmd_pipe_index = 0;                Session->data_xfer_index = -1;                if ((rsp_code == 150) || (rsp_code == 125))                {                    struct in_addr client, server;                    Session->data_chan_state &= ~DATA_CHAN_XFER_CMD_ISSUED;                    Session->data_chan_state = DATA_CHAN_XFER_STARTED;                    if (Session->serverIP == 0)                    {                        /* This means we're not in passive mode. */                        /* Server is listening/sending from its own IP,                         * FTP Port -1 */                         /* Client IP, Port specified via PORT command */                        Session->serverIP = p->ip4_header->source.s_addr;                                            /* Can't necessarily guarantee this, especially                         * in the case of a proxy'd connection where the                         * data channel might not be on port 20 (or server                         * port-1).  Comment it out for now.                         */                        /*                        Session->serverPort = ntohs(p->tcph->th_sport) -1;                        */                    }                    if (Session->clientIP == 0)                    {                        /* This means we're in passive mode. */                        /* Server info is known. */                        /* Client IP is known from response packet, but                         * port is unknown */                        Session->clientIP = p->ip4_header->destination.s_addr;                    }                    client.s_addr = Session->clientIP;                    server.s_addr = Session->serverIP;                    if (Session->server_conf->data_chan)                    {                        /* Call into Streams to mark data channel as something                         * to ignore. */                        _dpd.streamAPI->ignore_session(Session->clientIP,                                Session->clientPort, Session->serverIP,                                Session->serverPort,                                p->ip4_header->proto, SSN_DIR_BOTH,                                0 /* Not permanent */ );                    }                }                /* Clear the session info for next transfer -->                 * reset host/port */                Session->serverIP = Session->clientIP = 0;                Session->serverPort = Session->clientPort = 0;                Session->data_chan_state = NO_STATE;            }        }    } /* if (Session->server_conf->data_chan) */    if (Session->global_conf->encrypted.on)    {        switch(Session->encr_state)        {        case AUTH_TLS_CMD_ISSUED:            if (rsp_code == 234)            {                /* Could check that response msg includes "TLS" */                Session->encr_state = AUTH_TLS_ENCRYPTED;                if (Session->global_conf->encrypted.alert)                {                    /* Alert on encrypted channel */                    ftp_eo_event_log(Session, FTP_EO_ENCRYPTED,                        NULL, NULL);                }                DEBUG_WRAP(_dpd.debugMsg(DEBUG_FTPTELNET,                     "FTP stream is now TLS encrypted\n"););            }            break;        case AUTH_SSL_CMD_ISSUED:            if (rsp_code == 234)            {                /* Could check that response msg includes "SSL" */                Session->encr_state = AUTH_SSL_ENCRYPTED;                if (Session->global_conf->encrypted.alert)                {                    /* Alert on encrypted channel */                    ftp_eo_event_log(Session, FTP_EO_ENCRYPTED,                        NULL, NULL);                }                DEBUG_WRAP(_dpd.debugMsg(DEBUG_FTPTELNET,                     "FTP stream is now SSL encrypted\n"););            }            break;        case AUTH_UNKNOWN_CMD_ISSUED:            if (rsp_code == 234)            {                Session->encr_state = AUTH_UNKNOWN_ENCRYPTED;                if (Session->global_conf->encrypted.alert)                {                    /* Alert on encrypted channel */                    ftp_eo_event_log(Session, FTP_EO_ENCRYPTED,                        NULL, NULL);                }                DEBUG_WRAP(_dpd.debugMsg(DEBUG_FTPTELNET,                    "FTP stream is now encrypted\n"););            }            break;        }    } /* if (Session->global_conf->encrypted.on) */#ifdef MAINTAIN_USER_STATE    switch (Session->user_state)    {    case USER_CMD_ISSUED:        if (rsp_code == 331)            Session->user_state = PASS_REQUIRED;        else if (rsp_code == 230)            Session->user_state = USER_LOGGED_IN;        else        {            Session->user_state = NO_STATE;            if (Session->user)            {                free(Session->user);                Session->user = NULL;            }        }        break;    case PASS_CMD_ISSUED:        if (rsp_code == 230)            Session->user_state = USER_LOGGED_IN;        else        {            Session->user_state = NO_STATE;            if (Session->user)            {                free(Session->user);                Session->user = NULL;            }        }        break;    case USER_LOGGED_IN:    case PASS_REQUIRED:        /* Uh, shouldn't get here */        /* Lost state */        break;    }#endif#ifdef MAINTAIN_DIR_STATE    switch(Session->dir_state)    {    case PWD_CMD_ISSUED:        if (rsp_code == Session->expected_dir_response)        {            adjust_dir(Session, PWD_CMD_ISSUED,                req->param_begin, req->param_size);        }        Session->expected_dir_response = 0;        Session->dir_state = NO_STATE;        break;    case CWD_CMD_ISSUED:        if (rsp_code == Session->expected_dir_response)        {            adjust_dir(Session, CWD_CMD_ISSUED, NULL, 0);        }        free(Session->dir_adjust);        Session->dir_adjust = NULL;        Session->expected_dir_response = 0;        Session->dir_state = NO_STATE;        break;    case CDUP_CMD_ISSUED:        if (rsp_code == Session->expected_dir_response)        {            adjust_dir(Session, CDUP_CMD_ISSUED, NULL, 0);        }        Session->expected_dir_response = 0;        Session->dir_state = NO_STATE;        break;    }#endif    return iRet;}/* * Function: check_ftp(FTP_SESSION *Session, Packet *p, int iMode) * * Purpose: Handle some trivial validation checks of an FTP packet.  Namely, *          check argument length and some protocol enforcement.   *  *          Wishful: This results in exposing the FTP command (and looking *          at the results) to the rules layer. * * Arguments: Session        => Pointer to session info *            p              => pointer to the current packet struct *            iMode          => Mode indicating server or client checks * * Returns: int => return code indicating error or success * */#define NUL 0x00#define CR 0x0d#define LF 0x0a#define SP 0x20#define DASH 0x2D#define FTP_CMD_OK 0#define FTP_CMD_INV 1#define FTP_RESPONSE_INV 1#define FTP_RESPONSE 2#define FTP_RESPONSE_2BCONT 2#define FTP_RESPONSE_CONT   3#define FTP_RESPONSE_CONT   3#define FTP_RESPONSE_ENDCONT 4int check_ftp(FTP_SESSION  *ftpssn, SFSnortPacket *p, int iMode){    int iRet = FTPP_SUCCESS;    int encrypted = 0;    int space = 0;    long state = FTP_CMD_OK;    int rsp_code = 0;    FTP_CLIENT_REQ *req;    FTP_CMD_CONF *CmdConf = NULL;    unsigned char *read_ptr;    unsigned char *end = p->payload + p->payload_size;    if (p->flags & FLAG_ALT_DECODE)        end = _dpd.altBuffer + p->normalized_payload_size;    if (iMode == FTPP_SI_CLIENT_MODE)    {        req = &ftpssn->client.request;        ftp_cmd_pipe_index = 0;    }    else if (iMode == FTPP_SI_SERVER_MODE)        req = (FTP_CLIENT_REQ *)&ftpssn->server.response;    else        return FTPP_INVALID_ARG;    while (req->pipeline_req)    {        state = FTP_CMD_OK;        read_ptr = req->pipeline_req;            /* Starts at the beginning of the buffer/line,         * so next up is a command */        req->cmd_begin = read_ptr;        while ((*read_ptr != SP) &&               (*read_ptr != CR) &&               (*read_ptr != LF) && /* Check for LF when there wasn't a CR,                                     * protocol violation, but accepted by                                     * some servers. */               (*read_ptr != DASH) &&               (read_ptr < end))        {            /* If the first char is a digit this is a response             * in server mode. */            if (isdigit(*read_ptr) && (iMode == FTPP_SI_SERVER_MODE))            {                state = FTP_RESPONSE;            }            /* Or, if this is not a char, this is garbage in client mode */            else if (!isalpha(*read_ptr) && (iMode == FTPP_SI_CLIENT_MODE))            {                state = FTP_CMD_INV;            }            read_ptr++;        }        req->cmd_end = read_ptr;        req->cmd_size = req->cmd_end - req->cmd_begin;        if (iMode == FTPP_SI_CLIENT_MODE)        {            if ( ((req->cmd_size != 4) && (req->cmd_size != 3)) ||                 (state == FTP_CMD_INV) )            {                /* Uh, something is very wrong...                 * nonalpha char seen or cmd is not 3 or 4 chars.                 * See if this might be encrypted, ie, non-alpha bytes. */                char *ptr = req->cmd_begin;                while (ptr < req->cmd_end)                {                    if (!isalpha(*ptr))                    {                        encrypted = 1;                        break;                    }                    ptr++;                }            }            if (encrypted)            {                /* If the session wasn't already marked as encrypted...                 * Don't want to double-alert if we've already                 * determined the session is encrypted and we're                 * checking encrypted sessions.                 */                if (ftpssn->encr_state == 0)                {                    ftpssn->encr_state = AUTH_UNKNOWN_ENCRYPTED;                    if (ftpssn->global_conf->encrypted.alert)                    {                        /* Alert on encrypted channel */                        ftp_eo_event_log(ftpssn, FTP_EO_ENCRYPTED,                            NULL, NULL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -