#include "ftp_decoder_inner.h" #include "ftp_decoder.h" #include "ftp_decoder_util.h" #include #include #include #include #include void fstring_dup(const fstring *src, fstring *dst) { dst->iov_base = (char *)malloc(src->iov_len); assert(dst->iov_base); memcpy((void *)dst->iov_base, src->iov_base, src->iov_len); dst->iov_len = src->iov_len; } void fstring_safe_dup(const fstring *src, fstring *dst) { if (dst->iov_base) { free(dst->iov_base); // free it if exist } fstring_dup(src, dst); } void ftp_parse_result_free(struct ftp_parse_result *parse_result) { for (int i = 0; i < FTP_MSG_MAX; i++) { if (i != FTP_INVENTORY && i != FTP_FILE_CONTENT) { if (parse_result->result_array[i].iov_base) { free(parse_result->result_array[i].iov_base); } } } } static void ftp_str_split(const char *payload, size_t len, fstring *left, fstring *rigth, int delim) { const char *p = (char *)memchr(payload, delim, len); if (NULL == p) { left->iov_base = (char *)payload; left->iov_len = len; rigth->iov_base = NULL; rigth->iov_len = 0; } else { left->iov_base = (char *)payload; left->iov_len = p - payload; rigth->iov_base = (char *)p + 1; rigth->iov_len = len - left->iov_len - 1; } } long ftp_skip_tail_crlf(const char *payload, long len) { long new_len = 0; for (long i = 0; i < len; i++, new_len++) { if ((payload[i] == '\r' || payload[i] == '\n')) { break; } } return new_len; } int ftp_cmd_readline(struct ftp_interact_line *line, const char *payload, size_t len) { memset(line, 0, sizeof(struct ftp_interact_line)); long skip_crlf_len = ftp_skip_tail_crlf(payload, len); ftp_str_split(payload, skip_crlf_len, &line->cmd_refer, &line->arg_refer, ' '); return 0; } void ftp_strtolower(char *str, size_t len) { for (size_t i = 0; i < len; i++) { str[i] = tolower(str[i]); } } int ftp_mkdir_p(const char *path, mode_t mode) { struct stat st; errno = 0; /* Try to make the directory */ if (mkdir(path, mode) == 0) return 0; /* If it fails for any reason but EEXIST, fail */ if (errno != EEXIST) return -1; /* Check if the existing path is a directory */ if (stat(path, &st) != 0) return -1; /* If not, fail with ENOTDIR */ if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; return -1; } errno = 0; return 0; } int ftp_session_get_pkt_dir(struct session *sess) { const struct packet *pkt = session_get0_current_packet(sess); if (NULL == pkt) { return PACKET_DIRECTION_UNKNOWN; } return packet_get_direction(pkt); } struct ftp_context *ftp_decoder_context_deep_dup(const struct ftp_context *src) { struct ftp_context *new_ctx = (struct ftp_context *)calloc(1, sizeof(struct ftp_context)); for (int i = 0; i < FTP_MSG_MAX; i++) { if (i != FTP_INVENTORY && i != FTP_FILE_CONTENT) { fstring_safe_dup(&src->parse_result.result_array[i], &new_ctx->parse_result.result_array[i]); } } return new_ctx; } const char *ftp_message_type_to_string(enum ftp_msg_type fmsg_type) { switch (fmsg_type) { case FTP_BANNER: return "FTP_BANNER"; case FTP_ACCOUNT: return "FTP_ACCOUNT"; case FTP_PASSWORD: return "FTP_PASSWORD"; case FTP_URI: return "FTP_URI"; case FTP_TRANS_MODE: return "FTP_TRANS_MODE"; case FTP_TRANS_DIR: return "FTP_TRANS_DIR"; case FTP_INVENTORY: return "FTP_INVENTORY"; case FTP_FILE_CONTENT: return "FTP_FILE_CONTENT"; case FTP_MSG_MAX: return "UNKNOWN"; } return "UNKNOWN"; }