mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
IRC analyzer - make protocol confirmation more robust.
I noticed that the IRC analyzer always confirms connections, pretty much without regard what happened in it. This commit changes the logic of the IRC analyzer to check for valid commands before confirming.
This commit is contained in:
parent
92f2f66a60
commit
e411153f0d
2 changed files with 35 additions and 8 deletions
|
@ -5,6 +5,7 @@
|
|||
#include "zeek/analyzer/protocol/irc/IRC.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "zeek/Event.h"
|
||||
#include "zeek/NetVar.h"
|
||||
|
@ -42,6 +43,18 @@ inline void IRC_Analyzer::SkipLeadingWhitespace(string& str) {
|
|||
str = str.substr(first_char);
|
||||
}
|
||||
|
||||
bool IRC_Analyzer::IsValidClientCommand(const std::string& command) {
|
||||
static const std::unordered_set<std::string_view> validCommands =
|
||||
{"ADMIN", "AWAY", "CNOTICE", "CPRIVMSG", "CONNECT", "DIE", "ENCAP", "ERROR", "INFO",
|
||||
"INVITE", "ISON", "JOIN", "KICK", "KILL", "KNOCK", "LINKS", "LIST", "LUSERS",
|
||||
"MODE", "MOTD", "NAMES", "NICK", "NOTICE", "OPER", "PART", "PASS", "PING",
|
||||
"PONG", "PRIVMSG", "QUIT", "REHASH", "RULES", "SERVER", "SERVICE", "SERVLIST", "SERVER",
|
||||
"SETNAME", "SILENCE", "SQUERY", "SQUIT", "STATS", "SUMMON", "TIME", "TOPIC", "TRACE",
|
||||
"USER", "USERHOST", "USERS", "VERSION", "WALLOPS", "WHO", "WHOIS", "WHOWAS", "STARTTLS"};
|
||||
|
||||
return validCommands.find(command) != validCommands.end();
|
||||
}
|
||||
|
||||
void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) {
|
||||
static auto irc_join_list = id::find_type<TableType>("irc_join_list");
|
||||
static auto irc_join_info = id::find_type<RecordType>("irc_join_info");
|
||||
|
@ -54,6 +67,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) {
|
|||
|
||||
// check line size
|
||||
if ( length > 512 ) {
|
||||
if ( AnalyzerConfirmed() )
|
||||
Weird("irc_line_size_exceeded");
|
||||
return;
|
||||
}
|
||||
|
@ -62,6 +76,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) {
|
|||
SkipLeadingWhitespace(myline);
|
||||
|
||||
if ( myline.length() < 3 ) {
|
||||
if ( AnalyzerConfirmed() )
|
||||
Weird("irc_line_too_short");
|
||||
return;
|
||||
}
|
||||
|
@ -71,6 +86,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) {
|
|||
if ( myline[0] == ':' ) { // find end of prefix and extract it
|
||||
auto pos = myline.find(' ');
|
||||
if ( pos == string::npos ) {
|
||||
if ( AnalyzerConfirmed() )
|
||||
Weird("irc_invalid_line");
|
||||
return;
|
||||
}
|
||||
|
@ -80,15 +96,13 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) {
|
|||
SkipLeadingWhitespace(myline);
|
||||
}
|
||||
|
||||
if ( orig )
|
||||
AnalyzerConfirmation();
|
||||
|
||||
int code = 0;
|
||||
string command = "";
|
||||
|
||||
// Check if line is long enough to include status code or command.
|
||||
// (shortest command with optional params is "WHO")
|
||||
if ( myline.length() < 3 ) {
|
||||
if ( AnalyzerConfirmed() )
|
||||
Weird("irc_invalid_line");
|
||||
AnalyzerViolation("line too short");
|
||||
return;
|
||||
|
@ -101,6 +115,7 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) {
|
|||
myline = myline.substr(4);
|
||||
}
|
||||
else {
|
||||
if ( AnalyzerConfirmed() )
|
||||
Weird("irc_invalid_reply_number");
|
||||
AnalyzerViolation("invalid reply number");
|
||||
return;
|
||||
|
@ -127,6 +142,10 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) {
|
|||
// Extract parameters.
|
||||
string params = myline;
|
||||
|
||||
if ( ! AnalyzerConfirmed() && orig && IsValidClientCommand(command) ) {
|
||||
AnalyzerConfirmation();
|
||||
}
|
||||
|
||||
// special case
|
||||
if ( command == "STARTTLS" )
|
||||
return;
|
||||
|
|
|
@ -75,6 +75,14 @@ private:
|
|||
*/
|
||||
std::vector<std::string> SplitWords(const std::string& input, char split);
|
||||
|
||||
/**
|
||||
* Checks if a passed string is a valid command for an IRC client.
|
||||
*
|
||||
* \param command command to check
|
||||
* \return true if command is valid
|
||||
*/
|
||||
static bool IsValidClientCommand(const std::string& command);
|
||||
|
||||
analyzer::tcp::ContentLine_Analyzer* cl_orig;
|
||||
analyzer::tcp::ContentLine_Analyzer* cl_resp;
|
||||
bool starttls; // if true, connection has been upgraded to tls
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue