mirror of
https://github.com/zeek/zeek.git
synced 2025-10-17 05:58:20 +00:00

This avoids potential for locale-dependent results of toupper() by instead using a function that simply maps ASCII characters a-z to A-Z.
101 lines
2.5 KiB
C++
101 lines
2.5 KiB
C++
%%{
|
|
#include "zeek/Reporter.h"
|
|
|
|
// Like toupper(), but avoid potential for locale-dependence.
|
|
static char netbios_toupper(char c)
|
|
{
|
|
if ( c >= 'a' && c <= 'z' )
|
|
return c - 32;
|
|
return c;
|
|
}
|
|
%%}
|
|
|
|
## Decode a NetBIOS name. See https://jeffpar.github.io/kbarchive/kb/194/Q194203/.
|
|
##
|
|
## name: The encoded NetBIOS name, e.g., ``"FEEIEFCAEOEFFEECEJEPFDCAEOEBENEF"``.
|
|
##
|
|
## Returns: The decoded NetBIOS name, e.g., ``"THE NETBIOS NAM"``. An empty
|
|
## string is returned if the argument is not a valid NetBIOS encoding
|
|
## (though an encoding that would decode to something that includes
|
|
## only null-bytes or space-characters also yields an empty string).
|
|
##
|
|
## .. zeek:see:: decode_netbios_name_type
|
|
function decode_netbios_name%(name: string%): string
|
|
%{
|
|
if ( name->Len() != 32 )
|
|
return val_mgr->EmptyString();
|
|
|
|
char buf[16];
|
|
const u_char* s = name->Bytes();
|
|
int i, j;
|
|
int length = 0;
|
|
|
|
for ( i = 0, j = 0; i < 16; ++i )
|
|
{
|
|
char c0 = netbios_toupper(s[j++]);
|
|
char c1 = netbios_toupper(s[j++]);
|
|
|
|
if ( c0 < 'A' || c0 > 'P' || c1 < 'A' || c1 > 'P' )
|
|
return val_mgr->EmptyString();
|
|
|
|
buf[i] = ((c0 - 'A') << 4) + (c1 - 'A');
|
|
|
|
if ( isalnum(buf[i]) || ispunct(buf[i]) || buf[i] == ' ' ||
|
|
// \x01\x02 is seen in at least one case as the first two bytes.
|
|
// I think that any \x01 and \x02 should always be passed through.
|
|
buf[i] < 3 )
|
|
++length;
|
|
else
|
|
break;
|
|
}
|
|
|
|
|
|
// The 16th byte indicates the suffix/type, so don't include it
|
|
if ( length == 16 )
|
|
length = 15;
|
|
|
|
// Walk back and remove any trailing spaces or nulls
|
|
for ( ; ; )
|
|
{
|
|
if ( length == 0 )
|
|
return val_mgr->EmptyString();
|
|
|
|
auto c = buf[length - 1];
|
|
|
|
if ( c != ' ' && c != 0 )
|
|
break;
|
|
|
|
--length;
|
|
}
|
|
|
|
return zeek::make_intrusive<zeek::StringVal>(length, buf);
|
|
%}
|
|
|
|
## Converts a NetBIOS name type to its corresponding numeric value.
|
|
## See https://en.wikipedia.org/wiki/NetBIOS#NetBIOS_Suffixes.
|
|
##
|
|
## name: An encoded NetBIOS name.
|
|
##
|
|
## Returns: The numeric value of *name* or 256 if it's not a valid encoding.
|
|
##
|
|
## .. zeek:see:: decode_netbios_name
|
|
function decode_netbios_name_type%(name: string%): count
|
|
%{
|
|
if ( name->Len() != 32 )
|
|
return val_mgr->Count(256);
|
|
|
|
const u_char* s = name->Bytes();
|
|
|
|
for ( auto i = 0; i < 32; ++i )
|
|
{
|
|
char c = netbios_toupper(s[i]);
|
|
|
|
if ( c < 'A' || c > 'P' )
|
|
return val_mgr->Count(256);
|
|
}
|
|
|
|
char c0 = toupper(s[30]);
|
|
char c1 = toupper(s[31]);
|
|
char return_val = ((c0 - 'A') << 4) + (c1 - 'A');
|
|
return zeek::val_mgr->Count(return_val);
|
|
%}
|