mirror of
https://github.com/zeek/zeek.git
synced 2025-10-16 13:38:19 +00:00
231 lines
4.9 KiB
C++
231 lines
4.9 KiB
C++
// See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string>
|
|
#include <map>
|
|
|
|
using namespace std;
|
|
|
|
#include "NCP.h"
|
|
#include "Sessions.h"
|
|
|
|
#define xbyte(b, n) (((const u_char*) (b))[n])
|
|
#define extract_uint16(little_endian, bytes) \
|
|
((little_endian) ? \
|
|
uint16(xbyte(bytes, 0)) | ((uint16(xbyte(bytes, 1))) << 8) : \
|
|
uint16(xbyte(bytes, 1)) | ((uint16(xbyte(bytes, 0))) << 8))
|
|
|
|
NCP_Session::NCP_Session(Analyzer* a)
|
|
: analyzer(a)
|
|
{
|
|
req_frame_type = 0;
|
|
req_func = 0;
|
|
}
|
|
|
|
void NCP_Session::Deliver(int is_orig, int len, const u_char* data)
|
|
{
|
|
try
|
|
{
|
|
binpac::NCP::ncp_over_tcpip_frame frame(is_orig);
|
|
frame.Parse(data, data + len);
|
|
|
|
DeliverFrame(frame.ncp());
|
|
}
|
|
catch ( const binpac::Exception& e )
|
|
{
|
|
analyzer->Weird(e.msg().c_str());
|
|
}
|
|
}
|
|
|
|
void NCP_Session::DeliverFrame(const binpac::NCP::ncp_frame* frame)
|
|
{
|
|
if ( frame->is_orig() )
|
|
{
|
|
req_frame_type = frame->frame_type();
|
|
req_func = frame->request()->function();
|
|
if ( req_func == 0x57 ) // enhanced FILE_DIR services
|
|
{
|
|
req_func = (req_func << 8) |
|
|
frame->request()->subfunction();
|
|
}
|
|
}
|
|
|
|
EventHandlerPtr f = frame->is_orig() ? ncp_request : ncp_reply;
|
|
if ( f )
|
|
{
|
|
val_list* vl = new val_list;
|
|
vl->append(analyzer->BuildConnVal());
|
|
vl->append(new Val(frame->frame_type(), TYPE_COUNT));
|
|
vl->append(new Val(frame->body_length(), TYPE_COUNT));
|
|
|
|
if ( frame->is_orig() )
|
|
vl->append(new Val(req_func, TYPE_COUNT));
|
|
else
|
|
{
|
|
vl->append(new Val(req_frame_type, TYPE_COUNT));
|
|
vl->append(new Val(req_func, TYPE_COUNT));
|
|
vl->append(new Val(frame->reply()->completion_code(),
|
|
TYPE_COUNT));
|
|
}
|
|
|
|
analyzer->ConnectionEvent(f, vl);
|
|
}
|
|
}
|
|
|
|
FrameBuffer::FrameBuffer(int header_length)
|
|
{
|
|
hdr_len = header_length;
|
|
msg_buf = 0;
|
|
buf_len = 0;
|
|
Reset();
|
|
}
|
|
|
|
FrameBuffer::~FrameBuffer()
|
|
{
|
|
delete [] msg_buf;
|
|
}
|
|
|
|
void FrameBuffer::Reset()
|
|
{
|
|
// Allocate space for header.
|
|
if ( ! msg_buf )
|
|
{
|
|
buf_len = hdr_len;
|
|
msg_buf = new u_char[buf_len];
|
|
}
|
|
|
|
buf_n = 0;
|
|
msg_len = 0;
|
|
}
|
|
|
|
// Returns true if we have a complete frame
|
|
bool FrameBuffer::Deliver(int &len, const u_char* &data)
|
|
{
|
|
ASSERT(buf_len >= hdr_len);
|
|
|
|
if ( len == 0 )
|
|
return false;
|
|
|
|
if ( buf_n < hdr_len )
|
|
{
|
|
while ( buf_n < hdr_len && len > 0 )
|
|
{
|
|
ASSERT(buf_n < buf_len);
|
|
msg_buf[buf_n] = *data;
|
|
++buf_n; ++data; --len;
|
|
}
|
|
|
|
if ( buf_n < hdr_len )
|
|
return false;
|
|
|
|
compute_msg_length();
|
|
|
|
if ( msg_len > buf_len )
|
|
{
|
|
buf_len = msg_len * 2;
|
|
u_char* new_buf = new u_char[buf_len];
|
|
memcpy(new_buf, msg_buf, buf_n);
|
|
delete [] msg_buf;
|
|
msg_buf = new_buf;
|
|
}
|
|
}
|
|
|
|
while ( buf_n < msg_len && len > 0 )
|
|
{
|
|
msg_buf[buf_n] = *data;
|
|
++buf_n; ++data; --len;
|
|
}
|
|
|
|
return buf_n >= msg_len;
|
|
}
|
|
|
|
void NCP_FrameBuffer::compute_msg_length()
|
|
{
|
|
const u_char* data = Data();
|
|
msg_len = 0;
|
|
for ( int i = 0; i < 4; ++i )
|
|
msg_len = (msg_len << 8) | data[4+i];
|
|
}
|
|
|
|
Contents_NCP_Analyzer::Contents_NCP_Analyzer(Connection* conn, bool orig, NCP_Session* arg_session)
|
|
: TCP_SupportAnalyzer(AnalyzerTag::Contents_NCP, conn, orig)
|
|
{
|
|
session = arg_session;
|
|
resync = true;
|
|
|
|
TCP_Analyzer* tcp = static_cast<TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
|
if ( tcp )
|
|
resync = (orig ? tcp->OrigState() : tcp->RespState()) !=
|
|
TCP_ENDPOINT_ESTABLISHED;
|
|
}
|
|
|
|
Contents_NCP_Analyzer::~Contents_NCP_Analyzer()
|
|
{
|
|
}
|
|
|
|
void Contents_NCP_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
|
|
{
|
|
TCP_SupportAnalyzer::DeliverStream(len, data, orig);
|
|
|
|
TCP_Analyzer* tcp = static_cast<TCP_ApplicationAnalyzer*>(Parent())->TCP();
|
|
|
|
if ( tcp && tcp->HadGap(orig) )
|
|
return;
|
|
|
|
DEBUG_MSG("NCP deliver: len = %d resync = %d buffer.empty = %d\n",
|
|
len, resync, buffer.empty());
|
|
|
|
if ( buffer.empty() && resync )
|
|
{
|
|
// Assume NCP frames align with packet boundary.
|
|
if ( (IsOrig() && len < 22) || (! IsOrig() && len < 16) )
|
|
{ // ignore small fragmeents
|
|
DEBUG_MSG("NCP discard small pieces: %d\n", len);
|
|
return;
|
|
}
|
|
|
|
int frame_type_index = IsOrig() ? 16 : 8;
|
|
int frame_type = ((int) data[frame_type_index]) << 8 |
|
|
data[frame_type_index + 1];
|
|
|
|
if ( frame_type != 0x1111 && frame_type != 0x2222 &&
|
|
frame_type != 0x3333 && frame_type != 0x5555 &&
|
|
frame_type != 0x7777 && frame_type != 0x9999 )
|
|
// Skip this packet
|
|
return;
|
|
|
|
resync = false;
|
|
}
|
|
|
|
while ( buffer.Deliver(len, data) )
|
|
{
|
|
session->Deliver(IsOrig(), buffer.Len(), buffer.Data());
|
|
buffer.Reset();
|
|
}
|
|
}
|
|
|
|
void Contents_NCP_Analyzer::Undelivered(int seq, int len, bool orig)
|
|
{
|
|
TCP_SupportAnalyzer::Undelivered(seq, len, orig);
|
|
|
|
buffer.Reset();
|
|
resync = true;
|
|
}
|
|
|
|
NCP_Analyzer::NCP_Analyzer(Connection* conn)
|
|
: TCP_ApplicationAnalyzer(AnalyzerTag::NCP, conn)
|
|
{
|
|
session = new NCP_Session(this);
|
|
o_ncp = new Contents_NCP_Analyzer(conn, true, session);
|
|
r_ncp = new Contents_NCP_Analyzer(conn, false, session);
|
|
}
|
|
|
|
NCP_Analyzer::~NCP_Analyzer()
|
|
{
|
|
delete session;
|
|
delete o_ncp;
|
|
delete r_ncp;
|
|
}
|
|
|