diff --git a/src/Makefile.am b/src/Makefile.am index df37a5e9dc08..f0c87660d05b 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,6 +51,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 \ @@ -676,6 +677,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..8b236480a4d2 --- /dev/null +++ b/src/app-layer-imap.c @@ -0,0 +1,94 @@ +/* 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 "rust-bindings.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 dpeth 17 for now to pass unit tests, that might miss some detections + * until we find a better solution for the unit tests. + */ + 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..3b18cc119b2f --- /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 __APP_LAYER_IMAP_H__ +#define __APP_LAYER_IMAP_H__ +void RegisterIMAPParsers(void); +#endif diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index a856e79cd187..346ca961b182 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -61,6 +61,7 @@ #include "app-layer-quic.h" #include "app-layer-rdp.h" #include "app-layer-http2.h" +#include "app-layer-imap.h" struct AppLayerParserThreadCtx_ { void *alproto_local_storage[FLOW_PROTO_MAX][ALPROTO_MAX]; @@ -1772,21 +1773,7 @@ void AppLayerParserRegisterProtocolParsers(void) RegisterRdpParsers(); 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) - { - SCLogInfo("imap proto registration failure"); - exit(EXIT_FAILURE); - } - } else { - SCLogInfo("Protocol detection and parser disabled for %s protocol.", - "imap"); - } - + RegisterIMAPParsers(); ValidateParsers(); return; }