Advertisement

suricata smtp协议解析源码注释四

阅读量:

一。data命令的数据处理函数SMTPProcessCommandDATA

SMTPParse-> SMTPProcessRequest-> SMTPProcessCommandDATA

对data命令后的数据解析工作,先判断命令是否是点“.”,如果是说明数据接收完毕,客户端不再发送数据,则设置解析状态,和解析标志tx->done=1。如果不是“.”,则调用MimeDecParseLine函数,完成数据行的解析。

复制代码
 static int SMTPProcessCommandDATA(SMTPState *state, Flow *f,

    
                               AppLayerParserState *pstate)
    
 {
    
     SCEnter();
    
  
    
     //合法性判断,不是数据模式返回
    
     if (!(state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
    
     /* looks like are still waiting for a confirmination from the server */
    
     return 0;
    
     }
    
  
    
     //如果当前数据就是一个“.”,则说明客户端发送数据结束,去掉数据模式标志
    
     if (state->current_line_len == 1 && state->current_line[0] == '.') {
    
     state->parser_state &= ~SMTP_PARSER_STATE_COMMAND_DATA_MODE;
    
     /* kinda like a hack.  The mail sent in DATA mode, would be
    
      * acknowledged with a reply.  We insert a dummy command to
    
      * the command buffer to be used by the reply handler to match
    
      * the reply received */
    
     //这里插入一个命令到命令数组,是因为遇到“.”后,服务器要返回一个响应到客户端
    
     //客户端处理响应是要根据命令数组解析对应的响应
    
     SMTPInsertCommandIntoCommandBuffer(SMTP_COMMAND_DATA_MODE, state, f);
    
  
    
     //多mime_state作结束工作,包括保存头部阶段,处理body数据,设置解析结束标志等
    
     if (smtp_config.decode_mime && state->curr_tx->mime_state != NULL) {
    
         /* Complete parsing task */
    
         int ret = MimeDecParseComplete(state->curr_tx->mime_state);
    
         if (ret != MIME_DEC_OK) {
    
             SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_PARSE_FAILED);
    
             SCLogDebug("MimeDecParseComplete() function failed");
    
         }
    
  
    
         /* Generate decoder events */
    
         SetMimeEvents(state);
    
     }
    
     state->curr_tx->done = 1;
    
     SCLogDebug("marked tx as done");
    
     }
    
  
    
     //如果是data命令模式才调用函数MimeDecParseLine进行数据行解析
    
     /* If DATA, then parse out a MIME message */
    
     if (state->current_command == SMTP_COMMAND_DATA &&
    
         (state->parser_state & SMTP_PARSER_STATE_COMMAND_DATA_MODE)) {
    
  
    
     if (smtp_config.decode_mime && state->curr_tx->mime_state != NULL) {
    
         int ret = MimeDecParseLine((const uint8_t *) state->current_line,
    
                 state->current_line_len, state->current_line_delimiter_len,
    
                 state->curr_tx->mime_state);
    
         if (ret != MIME_DEC_OK) {
    
             if (ret != MIME_DEC_ERR_STATE) {
    
                 /* Generate decoder events */
    
                 SetMimeEvents(state);
    
  
    
                 SCLogDebug("MimeDecParseLine() function returned an error code: %d", ret);
    
                 SMTPSetEvent(state, SMTP_DECODER_EVENT_MIME_PARSE_FAILED);
    
             }
    
             /* keep the parser in its error state so we can log that,
    
              * the parser will reject new data */
    
         }
    
     }
    
     }
    
  
    
     return 0;
    
 }
    
  
    
    
    
    

二。行数据解析函数MimeDecParseLine

SMTPParse-> SMTPProcessRequest-> SMTPProcessCommandDATA->MimeDecParseLine

该函数是个包裹函数,仅仅对行分隔符变量state->current_line_delimiter_len进行了赋值,其次调用ProcessMimeEntity对data命令的每行数据进行解析。

复制代码
 static int ProcessMimeEntity(const uint8_t *buf, uint32_t len,

    
     MimeDecParseState *state)
    
 {
    
     int ret = MIME_DEC_OK;
    
  
    
     SCLogDebug("START FLAG: %s", StateFlags[state->state_flag]);
    
     //合法性判断,这个标志在解析过程中遇到错误会设置
    
     if (state->state_flag == PARSE_ERROR) {
    
     SCLogDebug("START FLAG: PARSE_ERROR, bail");
    
     return MIME_DEC_ERR_STATE;
    
     }    
    
  
    
     /* Track long line */
    
     //每行数据不能超过998个字符,超过设置异常标志
    
     if (len > MAX_LINE_LEN) {
    
     state->stack->top->data->anomaly_flags |= ANOM_LONG_LINE;
    
     state->msg->anomaly_flags |= ANOM_LONG_LINE;
    
     SCLogDebug("Error: Max input line length exceeded %u > %u", len, 
    
             MAX_LINE_LEN);
    
     }    
    
  
    
     //如果是这两个标志说明后续数据为头部字段
    
     //1.HEADER_STARTED在初始化时设置,第一次解析肯定走这里,
    
     //还有在解析头部字段时找到冒号成功解析头部字段的名字时也会设置,表示解析到头部字段的名称,
    
     //后续的数据是字段名称对应的内容,需要进入头部字段解析函数解析出内容,解析头部字段的函数内
    
     //使用这个HEADER_STARTED标志作判断处理:就是如果没有冒号但是设置了HEADER_STARTED标志,
    
     //说明本次内容为没有头部信息的body数据,然后调用body数据处理函数进行处理
    
     //2.HEADER_READY在遇到doundary分界线时设置,表示后续将遇到信件体,
    
     //信件体看开始部分是头部字段,所以后续数据应该进入头部字段解析函数,解析头部信息。
    
     /* Looking for headers */
    
     if (state->state_flag == HEADER_READY ||
    
         state->state_flag == HEADER_STARTED) {
    
  
    
     SCLogDebug("Processing Headers");
    
  
    
     //调用头部解析函数
    
     /* Process message headers */
    
     ret = ProcessMimeHeaders(buf, len, state);
    
     if (ret != MIME_DEC_OK) {
    
         SCLogDebug("Error: ProcessMimeHeaders() function failed: %d",
    
                 ret);
    
         return ret; 
    
     }
    
     } else {
    
     /* Processing body */
    
     SCLogDebug("Processing Body of: %p", state->stack->top);
    
  
    
     //调用body数据解析函数
    
     ret = ProcessMimeBody(buf, len, state);
    
     if (ret != MIME_DEC_OK) {
    
         SCLogDebug("Error: ProcessMimeBody() function failed: %d",
    
                 ret);
    
         return ret; 
    
     }
    
     }
    
     SCLogDebug("END FLAG: %s", StateFlags[state->state_flag]);
    
  
    
     return ret;
    
 }
    
  
    
    
    
    

全部评论 (0)

还没有任何评论哟~