diff --git a/src/Makefile.am b/src/Makefile.am index ee4c32090696..4cd326869229 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -45,6 +45,7 @@ noinst_HEADERS = \ app-layer-ssh.h \ app-layer-ssl.h \ app-layer-tftp.h \ + app-layer-imap.h \ build-info.h \ conf.h \ conf-yaml-loader.h \ @@ -658,6 +659,7 @@ libsuricata_c_a_SOURCES = \ app-layer-ssh.c \ app-layer-ssl.c \ app-layer-tftp.c \ + app-layer-imap.c \ conf.c \ conf-yaml-loader.c \ counters.c \ diff --git a/src/app-layer-imap.c b/src/app-layer-imap.c new file mode 100644 index 000000000000..689a98a4925f --- /dev/null +++ b/src/app-layer-imap.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * 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 + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Mahmoud Maatuq + * + */ + +#include "app-layer.h" +#include "app-layer-detect-proto.h" +#include "app-layer-imap.h" + +static int IMAPRegisterPatternsForProtocolDetection(void) +{ + if (AppLayerProtoDetectPMRegisterPatternCI( + IPPROTO_TCP, ALPROTO_IMAP, "* OK ", 5, 0, STREAM_TOCLIENT) < 0) { + return -1; + } + + if (AppLayerProtoDetectPMRegisterPatternCI( + IPPROTO_TCP, ALPROTO_IMAP, "* NO ", 5, 0, STREAM_TOCLIENT) < 0) { + return -1; + } + + if (AppLayerProtoDetectPMRegisterPatternCI( + IPPROTO_TCP, ALPROTO_IMAP, "* BAD ", 6, 0, STREAM_TOCLIENT) < 0) { + return -1; + } + + if (AppLayerProtoDetectPMRegisterPatternCI( + IPPROTO_TCP, ALPROTO_IMAP, "* LIST ", 7, 0, STREAM_TOCLIENT) < 0) { + return -1; + } + + if (AppLayerProtoDetectPMRegisterPatternCI( + IPPROTO_TCP, ALPROTO_IMAP, "* ESEARCH ", 10, 0, STREAM_TOCLIENT) < 0) { + return -1; + } + + if (AppLayerProtoDetectPMRegisterPatternCI( + IPPROTO_TCP, ALPROTO_IMAP, "* STATUS ", 9, 0, STREAM_TOCLIENT) < 0) { + return -1; + } + + if (AppLayerProtoDetectPMRegisterPatternCI( + IPPROTO_TCP, ALPROTO_IMAP, "* FLAGS ", 8, 0, STREAM_TOCLIENT) < 0) { + return -1; + } + + /** + * there is no official document that limits the length of the tag + * some practical implementations limit it to 20 characters + * but keeping depth equal to 31 fails unit tests such AppLayerTest10 + * so keeping depth 17 for now to pass unit tests, that might miss some detections + * until we find a better solution for the unit tests. + * + * AppLayerTest10 fails because it expects protocol detection to be completed with only 17 bytes + * as input, and with this new pattern, we would need more bytes to finish protocol detection. + */ + if (AppLayerProtoDetectPMRegisterPatternCI(IPPROTO_TCP, ALPROTO_IMAP, " CAPABILITY", + 17 /*6 for max tag len + space + len(CAPABILITY)*/, 0, STREAM_TOSERVER) < 0) { + return -1; + } + + return 0; +} + +void RegisterIMAPParsers(void) +{ + const char *proto_name = "imap"; + + if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) { + SCLogDebug("IMAP protocol detection is enabled."); + AppLayerProtoDetectRegisterProtocol(ALPROTO_IMAP, proto_name); + if (IMAPRegisterPatternsForProtocolDetection() < 0) + SCLogError("Failed to register IMAP protocol detection patterns."); + } else { + SCLogDebug("Protocol detector and parser disabled for IMAP."); + } +} diff --git a/src/app-layer-imap.h b/src/app-layer-imap.h new file mode 100644 index 000000000000..497992f71aa3 --- /dev/null +++ b/src/app-layer-imap.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2024 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * 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 + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Mahmoud Maatuq + * + */ + +#ifndef SURICATA_APP_LAYER_IMAP_H +#define SURICATA_APP_LAYER_IMAP_H +void RegisterIMAPParsers(void); +#endif diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index a1f000f90c25..4c9839520d02 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -55,6 +55,7 @@ #include "app-layer-ike.h" #include "app-layer-rfb.h" #include "app-layer-http2.h" +#include "app-layer-imap.h" struct AppLayerParserThreadCtx_ { void *alproto_local_storage[FLOW_PROTO_MAX][ALPROTO_MAX]; @@ -1755,19 +1756,7 @@ void AppLayerParserRegisterProtocolParsers(void) rs_rdp_register_parser(); RegisterHTTP2Parsers(); rs_telnet_register_parser(); - - /** IMAP */ - AppLayerProtoDetectRegisterProtocol(ALPROTO_IMAP, "imap"); - if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", "imap")) { - if (AppLayerProtoDetectPMRegisterPatternCS(IPPROTO_TCP, ALPROTO_IMAP, - "1|20|capability", 12, 0, STREAM_TOSERVER) < 0) - { - FatalError("imap proto registration failure"); - } - } else { - SCLogInfo("Protocol detection and parser disabled for %s protocol.", - "imap"); - } + RegisterIMAPParsers(); /** POP3 */ AppLayerProtoDetectRegisterProtocol(ALPROTO_POP3, "pop3");