Add support of getting server capabilities to IMAP parser.

This commit is contained in:
Johanna Amann 2015-07-23 11:15:57 -07:00
parent 4a5737708c
commit 1933299543
7 changed files with 99 additions and 4 deletions

View file

@ -6,6 +6,7 @@ include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DI
bro_plugin_begin(Bro IMAP) bro_plugin_begin(Bro IMAP)
bro_plugin_cc(Plugin.cc) bro_plugin_cc(Plugin.cc)
bro_plugin_cc(IMAP.cc) bro_plugin_cc(IMAP.cc)
bro_plugin_bif(events.bif)
bro_plugin_pac(imap.pac imap-analyzer.pac imap-protocol.pac) bro_plugin_pac(imap.pac imap-analyzer.pac imap-protocol.pac)
bro_plugin_end() bro_plugin_end()

View file

@ -0,0 +1,10 @@
## Generated for an SSL/TLS client's initial *hello* message. SSL/TLS sessions
## start with an unencrypted handshake, and Bro extracts as much information out
## of that as it can. This event provides access to the initial information
## sent by the client.
##
## c: The connection.
##
## capabilities: The list of IMAP capabilities as sent by the server.
event imap_capabilities%(c: connection, capabilities: string_vec%);

View file

@ -49,9 +49,25 @@ refine connection IMAP_Conn += {
return true; return true;
%} %}
function proc_server_capability(capabilities: Capability[]): bool
%{
VectorVal* capv = new VectorVal(internal_type("string_vec")->AsVectorType());
for ( unsigned int i = 0; i< capabilities->size(); i++ )
{
const bytestring& capability = (*capabilities)[i]->cap();
capv ->Assign(i, new StringVal(capability.length(), (const char*)capability.data()));
}
BifEvent::generate_imap_capabilities(bro_analyzer(), bro_analyzer()->Conn(), capv);
return true;
%}
}; };
refine typeattr IMAP_TOKEN += &let { refine typeattr ImapToken += &let {
proc: bool = $context.connection.proc_imap_token(is_orig, tag, command); proc: bool = $context.connection.proc_imap_token(is_orig, tag, command);
}; };
refine typeattr ServerCapability += &let {
proc: bool = $context.connection.proc_server_capability(capabilities);
};

View file

@ -1,17 +1,70 @@
# commands that we support parsing. The numbers do not really mean anything
# in this case
enum ImapCommand {
CMD_CAPABILITY,
CMD_UNKNOWN
}
type TAG = RE/[[:alnum:][:punct:]]+/; type TAG = RE/[[:alnum:][:punct:]]+/;
type CONTENT = RE/[^\r\n]*/; type CONTENT = RE/[^\r\n]*/;
type SPACING = RE/[ ]+/; type SPACING = RE/[ ]+/;
type OPTIONALSPACING = RE/[ ]*/; type OPTIONALSPACING = RE/[ ]*/;
type NEWLINE = RE/[\r\n]+/; type NEWLINE = RE/[\r\n]+/;
type OPTIONALNEWLINE = RE/[\r\n]*/;
type IMAP_PDU(is_orig: bool) = IMAP_TOKEN(is_orig)[] &until($input.length() == 0); type IMAP_PDU(is_orig: bool) = ImapToken(is_orig)[] &until($input.length() == 0);
type IMAP_TOKEN(is_orig: bool) = record { type ImapToken(is_orig: bool) = record {
tag : TAG; tag : TAG;
: SPACING; : SPACING;
command: TAG; command: TAG;
: OPTIONALSPACING; : OPTIONALSPACING;
client_or_server: case is_orig of {
true -> client: UnknownCommand(this) ;
false -> server: ServerContentText(this);
} &requires(pcommand) ;
} &let {
pcommand: int = $context.connection.determine_command(is_orig, tag, command);
};
type ServerContentText(rec: ImapToken) = case rec.pcommand of {
CMD_CAPABILITY -> capability: ServerCapability(rec);
default -> unknown: UnknownCommand(rec);
};
type Capability = record {
cap: TAG;
: OPTIONALSPACING;
nl: OPTIONALNEWLINE;
};
type ServerCapability(rec: ImapToken) = record {
capabilities: Capability[] &until($context.connection.strlen($element.nl) > 0);
};
type UnknownCommand(rec: ImapToken) = record {
tagcontent: CONTENT; tagcontent: CONTENT;
: NEWLINE; : NEWLINE;
}; };
refine connection IMAP_Conn += {
function determine_command(is_orig: bool, tag: bytestring, command: bytestring): int
%{
string cmdstr = std_str(command);
std::transform(cmdstr.begin(), cmdstr.end(), cmdstr.begin(), ::tolower);
string tagstr = std_str(tag);
if ( !is_orig && cmdstr == "capability" && tag == "*" ) {
return CMD_CAPABILITY;
}
return CMD_UNKNOWN;
%}
function strlen(str: bytestring): int
%{
return str.length();
%}
};

View file

@ -7,6 +7,8 @@
%include bro.pac %include bro.pac
%extern{ %extern{
#include "events.bif.h"
namespace analyzer { namespace imap { class IMAP_Analyzer; } } namespace analyzer { namespace imap { class IMAP_Analyzer; } }
namespace binpac { namespace IMAP { class IMAP_Conn; } } namespace binpac { namespace IMAP { class IMAP_Conn; } }
typedef analyzer::imap::IMAP_Analyzer* IMAPAnalyzer; typedef analyzer::imap::IMAP_Analyzer* IMAPAnalyzer;

View file

@ -0,0 +1 @@
[IMAP4rev1, CHILDREN, ENABLE, ID, IDLE, LIST-EXTENDED, LIST-STATUS, LITERAL+, MOVE, NAMESPACE, SASL-IR, SORT, SPECIAL-USE, THREAD=ORDEREDSUBJECT, UIDPLUS, UNSELECT, WITHIN, STARTTLS, AUTH=LOGIN, AUTH=PLAIN]

View file

@ -0,0 +1,12 @@
# @TEST-EXEC: bro -b -C -r $TRACES/tls/imap-starttls.pcap %INPUT
# @TEST-EXEC: btest-diff .stdout
@load base/protocols/ssl
@load base/protocols/conn
@load base/frameworks/dpd
@load base/protocols/imap
event imap_capabilities(c: connection, capabilities: string_vec)
{
print capabilities;
}