mirror of
https://github.com/samba-team/samba.git
synced 2024-12-27 03:21:53 +03:00
e12dbc7307
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
708 lines
25 KiB
Perl
Executable File
708 lines
25 KiB
Perl
Executable File
#! /usr/bin/perl
|
|
#
|
|
# Summarise tshark pdml output into a form suitable for the load test tool
|
|
#
|
|
# Copyright (C) Catalyst.Net Ltd 2017
|
|
#
|
|
# Catalyst.Net's contribution was written by Gary Lockyer
|
|
# <gary@catalyst.net.nz>.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# 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
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
use warnings;
|
|
use strict;
|
|
|
|
use Getopt::Long;
|
|
use Pod::Usage;
|
|
|
|
BEGIN {
|
|
unless (eval "require XML::Twig") {
|
|
warn "traffic_summary requires the perl module XML::Twig\n" .
|
|
"on Ubuntu/Debian releases run\n".
|
|
" sudo apt install libxml-twig-perl \n".
|
|
"or install from CPAN\n".
|
|
"\nThe reported error was:\n$@";
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
my %ip_map; # Map of IP address to sequence number
|
|
my $ip_sequence = 0; # count of unique IP addresses seen
|
|
|
|
|
|
my $timestamp; # Packet timestamp
|
|
my $stream; # Wireshark stream number
|
|
my $ip_proto; # IP protocol (IANA protocl number)
|
|
my $source; # source IP address
|
|
my $dest; # destination address
|
|
my $proto; # application protocol name
|
|
my $description; # protocol specific description
|
|
my %proto_data; # protocol specific data captured for the current packet
|
|
my $malformed_packet; # Indicates the current packet has errors
|
|
my $ldap_filter; # cleaned ldap filter
|
|
my $ldap_attributes; # attributes requested in an ldap query
|
|
|
|
|
|
|
|
# Dispatch table mapping the wireshark variables of interest to the
|
|
# functions responsible for processing them
|
|
my %field_dispatch_table = (
|
|
'timestamp' => \×tamp,
|
|
'ip.src' => \&ip_src,
|
|
'ipv6.src' => \&ip_src,
|
|
'ip.dst' => \&ip_dst,
|
|
'ipv6.dst' => \&ip_dst,
|
|
'ip.proto' => \&ip_proto,
|
|
'udp.stream' => \&stream,
|
|
'tcp.stream' => \&stream,
|
|
'dns.flags.opcode' => \&field_data,
|
|
'dns.flags.response' => \&field_data,
|
|
'netlogon.opnum' => \&field_data,
|
|
'kerberos.msg_type' => \&field_data,
|
|
'smb.cmd' => \&field_data,
|
|
'smb2.cmd' => \&field_data,
|
|
'ldap.protocolOp' => \&field_data,
|
|
'gss-api.OID' => \&field_data,
|
|
'ldap.gssapi_encrypted_payload' => \&field_data,
|
|
'ldap.baseObject' => \&field_data,
|
|
'ldap.scope' => \&field_data,
|
|
'ldap.AttributeDescription' => \&ldap_attribute,
|
|
'ldap.modification_element' => \&ldap_add_modify,
|
|
'ldap.AttributeList_item_element' => \&ldap_add_modify,
|
|
'ldap.operation' => \&field_data,
|
|
'ldap.authentication' => \&field_data,
|
|
'lsarpc.opnum' => \&field_data,
|
|
'samr.opnum' => \&field_data,
|
|
'dcerpc.pkt_type' => \&field_data,
|
|
'epm.opnum' => \&field_data,
|
|
'dnsserver.opnum' => \&field_data,
|
|
'drsuapi.opnum' => \&field_data,
|
|
'browser.command' => \&field_data,
|
|
'smb_netlogon.command' => \&field_data,
|
|
'srvsvc.opnum' => \&field_data,
|
|
'nbns.flags.opcode' => \&field_data,
|
|
'nbns.flags.response' => \&field_data,
|
|
'_ws.expert.message' => \&field_data,
|
|
);
|
|
|
|
# Dispatch table mapping protocols to the routine responsible for formatting
|
|
# their output. Protocols not in this table are ignored.
|
|
#
|
|
my %proto_dispatch_table = (
|
|
'dns' => sub { return format_opcode( 'dns.flags.response')},
|
|
'rpc_netlogon' => sub { return format_opcode( 'netlogon.opnum')},
|
|
'kerberos' => \&format_kerberos,
|
|
'smb' => sub { return format_opcode( 'smb.cmd')},
|
|
'smb2' => sub { return format_opcode( 'smb2.cmd')},
|
|
'ldap' => \&format_ldap,
|
|
'cldap' => \&format_ldap,
|
|
'lsarpc' => sub { return format_opcode( 'lsarpc.opnum')},
|
|
'samr' => sub { return format_opcode( 'samr.opnum')},
|
|
'dcerpc' => sub { return format_opcode( 'dcerpc.pkt_type')},
|
|
'epm' => sub { return format_opcode( 'epm.opnum')},
|
|
'dnsserver' => sub { return format_opcode( 'dnsserver.opnum')},
|
|
'drsuapi' => sub { return format_opcode( 'drsuapi.opnum')},
|
|
'browser' => sub { return format_opcode( 'browser.command')},
|
|
'smb_netlogon' => sub { return format_opcode( 'smb_netlogon.command')},
|
|
'srvsvc' => sub { return format_opcode( 'srvsvc.opnum')},
|
|
'nbns' => sub { return format_opcode( 'nbns.flags.response')},
|
|
);
|
|
|
|
# XPath entry to extract the kerberos cname
|
|
my $kerberos_cname_path =
|
|
'packet/proto/field[@name = "kerberos.as_req_element"]'
|
|
. '/field[@name = "kerberos.req_body_element"]'
|
|
. '/field[@name = "kerberos.cname_element"]'
|
|
. '/field[@name = "kerberos.name_string"]'
|
|
. '/field[@name = "kerberos.KerberosString"]';
|
|
|
|
# XPath entry to extract the ldap filter
|
|
my $ldap_filter_path =
|
|
'field[@name = "ldap.searchRequest_element"]/field';
|
|
|
|
|
|
# Create an XML Twig parser and register the event handlers.
|
|
#
|
|
my $t = XML::Twig->new(
|
|
start_tag_handlers => {
|
|
'packet' => \&packet_start,
|
|
},
|
|
twig_handlers => {
|
|
'packet' => \&packet,
|
|
'proto' => \&protocol,
|
|
'field' => \&field,
|
|
$kerberos_cname_path => \&kerberos_cname,
|
|
$ldap_filter_path => \&ldap_filter,
|
|
},
|
|
);
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Main loop
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
my $help = 0;
|
|
GetOptions( 'help|h' => \$help) or pod2usage(2);
|
|
pod2usage(1) if $help;
|
|
|
|
if (@ARGV) {
|
|
foreach my $file (@ARGV) {
|
|
eval {
|
|
$t->parsefile( $file);
|
|
};
|
|
if ($@) {
|
|
print STDERR "Unable to process $file, ".
|
|
"did you run tshark with the -T pdml option?";
|
|
}
|
|
}
|
|
} else {
|
|
pod2usage(1) if -t STDIN;
|
|
eval {
|
|
$t->parse( \*STDIN);
|
|
};
|
|
if ($@) {
|
|
print STDERR "Unable to process input, ".
|
|
"are you running tshark with the -T pdml option?";
|
|
}
|
|
}
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# New packet detected reset the globals
|
|
#------------------------------------------------------------------------------
|
|
sub packet_start
|
|
{
|
|
my ($t, $packet) = @_;
|
|
$timestamp = "";
|
|
$stream = "";
|
|
$ip_proto = "";
|
|
$source = "";
|
|
$dest = "";
|
|
$description = undef;
|
|
%proto_data = ();
|
|
$malformed_packet = undef;
|
|
$ldap_filter = "";
|
|
$ldap_attributes = "";
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Complete packet element parsed from the XML feed
|
|
# output the protocol summary if required
|
|
#------------------------------------------------------------------------------
|
|
sub packet
|
|
{
|
|
my ($t, $packet) = @_;
|
|
|
|
my $data;
|
|
if (exists $proto_dispatch_table{$proto}) {
|
|
if ($malformed_packet) {
|
|
$data = "\t\t** Malformed Packet ** " . ($proto_data{'_ws.expert.message.show'} || '');
|
|
} else {
|
|
my $rsub = $proto_dispatch_table{$proto};
|
|
$data = &$rsub();
|
|
}
|
|
print "$timestamp\t$ip_proto\t$stream\t$source\t$dest\t$proto\t$data\n";
|
|
}
|
|
$t->purge;
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Complete protocol element parsed from the XML input
|
|
# Update the protocol name
|
|
#------------------------------------------------------------------------------
|
|
sub protocol
|
|
{
|
|
my ($t, $protocol) = @_;
|
|
if ($protocol->{att}->{showname}) {
|
|
}
|
|
# Tag a packet as malformed if the protocol is _ws.malformed
|
|
# and the hide attribute is not 'yes'
|
|
if ($protocol->{att}->{name} eq '_ws.malformed'
|
|
&& !($protocol->{att}->{hide} && $protocol->{att}->{hide} eq 'yes')
|
|
) {
|
|
$malformed_packet = 1;
|
|
}
|
|
# Don't set the protocol name if it's a wireshark malformed
|
|
# protocol entry, or the packet was truncated during capture
|
|
my $p = $protocol->{att}->{name};
|
|
if ($p ne '_ws.malformed' && $p ne '_ws.short') {
|
|
$proto = $p;
|
|
}
|
|
}
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Complete field element parsed, extract any data of interest
|
|
#------------------------------------------------------------------------------
|
|
sub field
|
|
{
|
|
my ($t, $field) = @_;
|
|
my $name = $field->{att}->{name};
|
|
|
|
# Only process the field if it has a corresponding entry in
|
|
# %field_dispatch_table
|
|
if (exists $field_dispatch_table{$name}) {
|
|
my $rsub = $field_dispatch_table{$name};
|
|
&$rsub( $field);
|
|
}
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Process a timestamp field element
|
|
#------------------------------------------------------------------------------
|
|
sub timestamp
|
|
{
|
|
my ($field) = @_;
|
|
$timestamp = $field->{att}->{value};
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Process a wireshark stream element, used to group a sequence of requests
|
|
# and responses between two IP addresses
|
|
#------------------------------------------------------------------------------
|
|
sub stream
|
|
{
|
|
my ($field) = @_;
|
|
$stream = $field->{att}->{show};
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Process a source ip address field, mapping the IP address to it's
|
|
# corresponding sequence number.
|
|
#------------------------------------------------------------------------------
|
|
sub ip_src
|
|
{
|
|
my ($field) = @_;
|
|
$source = map_ip( $field);
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Process a destination ip address field, mapping the IP address to it's
|
|
# corresponding sequence number.
|
|
#------------------------------------------------------------------------------
|
|
sub ip_dst
|
|
{
|
|
my ($field) = @_;
|
|
$dest = map_ip( $field);
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Process an ip protocol element, extracting IANA protocol number
|
|
#------------------------------------------------------------------------------
|
|
sub ip_proto
|
|
{
|
|
my ($field) = @_;
|
|
$ip_proto = $field->{att}->{value};
|
|
}
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Extract an ldap attribute and append it to ldap_attributes
|
|
#------------------------------------------------------------------------------
|
|
sub ldap_attribute
|
|
{
|
|
my ($field) = @_;
|
|
my $attribute = $field->{att}->{show};
|
|
|
|
if (defined $attribute) {
|
|
$ldap_attributes .= "," if $ldap_attributes;
|
|
$ldap_attributes .= $attribute;
|
|
}
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Process a field element, extract the value, show and showname attributes
|
|
# and store them in the %proto_data hash.
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
sub field_data
|
|
{
|
|
my ($field) = @_;
|
|
my $name = $field->{att}->{name};
|
|
$proto_data{$name.'.value'} = $field->{att}->{value};
|
|
$proto_data{$name.'.show'} = $field->{att}->{show};
|
|
$proto_data{$name.'.showname'} = $field->{att}->{showname};
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Process a kerberos cname element, if the cname ends with a $ it's a machine
|
|
# name. Otherwise it's a user name.
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
sub kerberos_cname
|
|
{
|
|
my ($t, $field) = @_;
|
|
my $cname = $field->{att}->{show};
|
|
my $type;
|
|
if( $cname =~ /\$$/) {
|
|
$type = 'machine';
|
|
} else {
|
|
$type = 'user';
|
|
}
|
|
$proto_data{'kerberos.cname.type'} = $type;
|
|
}
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Process an ldap filter, remove the values but keep the attribute names
|
|
#------------------------------------------------------------------------------
|
|
sub ldap_filter
|
|
{
|
|
my ($t, $field) = @_;
|
|
if ( $field->{att}->{show} && $field->{att}->{show} =~ /^Filter:/) {
|
|
my $filter = $field->{att}->{show};
|
|
|
|
# extract and save the objectClass to keep the value
|
|
my @object_classes;
|
|
while ( $filter =~ m/\((objectClass=.*?)\)/g) {
|
|
push @object_classes, $1;
|
|
}
|
|
|
|
# extract and save objectCategory and the top level value
|
|
my @object_categories;
|
|
while ( $filter =~ m/(\(objectCategory=.*?,|\(objectCategory=.*?\))/g
|
|
) {
|
|
push @object_categories, $1;
|
|
}
|
|
|
|
# Remove all the values from the attributes
|
|
# Input
|
|
# Filter: (nCName=DC=DomainDnsZones,DC=sub1,DC=ad,DC=rh,DC=at,DC=net)
|
|
# Output
|
|
# (nCName)
|
|
$filter =~ s/^Filter:\s*//; # Remove the 'Filter: ' prefix
|
|
$filter =~ s/=.*?\)/\)/g; # Remove from the = to the first )
|
|
|
|
# Now restore the parts of objectClass and objectCategory that are being
|
|
# retained
|
|
#
|
|
for my $cat (@object_categories) {
|
|
$filter =~ s/\(objectCategory\)/$cat/;
|
|
}
|
|
|
|
for my $class (@object_classes) {
|
|
$filter =~ s/\(objectClass\)/($class)/;
|
|
}
|
|
|
|
$ldap_filter = $filter;
|
|
} else {
|
|
# Ok not an ldap filter so call the default field handler
|
|
field( $t, $field);
|
|
}
|
|
}
|
|
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Extract the attributes from ldap modification and add requests
|
|
#------------------------------------------------------------------------------
|
|
sub ldap_add_modify
|
|
{
|
|
my ($field) = @_;
|
|
my $type = $field->first_child('field[@name="ldap.type"]');
|
|
my $attribute = $type->{att}->{show} if $type;
|
|
if (defined $attribute) {
|
|
$ldap_attributes .= "," if $ldap_attributes;
|
|
$ldap_attributes .= $attribute;
|
|
}
|
|
}
|
|
#------------------------------------------------------------------------------
|
|
# Map an IP address to a unique sequence number. Assigning it a sequence number
|
|
# if one has not already been assigned.
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
sub map_ip
|
|
{
|
|
my ($field) = @_;
|
|
my $ip = $field->{att}->{show};
|
|
if ( !exists( $ip_map{$ip})) {
|
|
$ip_sequence++;
|
|
$ip_map{$ip} = $ip_sequence;
|
|
}
|
|
return $ip_map{$ip};
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Format a protocol operation code for output.
|
|
#
|
|
#------------------------------------------------------------------------------
|
|
sub format_opcode
|
|
{
|
|
my ($name) = @_;
|
|
my $operation = $proto_data{$name.'.show'};
|
|
my $description = $proto_data{$name.'.showname'} || '';
|
|
|
|
# Strip off the common prefix text, and the trailing (n).
|
|
# This tidies up most but not all descriptions.
|
|
$description =~ s/^[^:]*?: ?// if $description;
|
|
$description =~ s/^Message is a // if $description;
|
|
$description =~ s/\(\d+\)\s*$// if $description;
|
|
$description =~ s/\s*$// if $description;
|
|
|
|
return "$operation\t$description";
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Format ldap protocol details for output
|
|
#------------------------------------------------------------------------------
|
|
sub format_ldap
|
|
{
|
|
my ($name) = @_;
|
|
if ( exists( $proto_data{'ldap.protocolOp.show'})
|
|
|| exists( $proto_data{'gss-api.OID.show'})
|
|
) {
|
|
my $operation = $proto_data{'ldap.protocolOp.show'};
|
|
my $description = $proto_data{'ldap.protocolOp.showname'} || '';
|
|
my $oid = $proto_data{'gss-api.OID.show'} || '';
|
|
my $base_object = $proto_data{'ldap.baseObject.show'} || '';
|
|
my $scope = $proto_data{'ldap.scope.show'} || '';
|
|
|
|
# Now extract operation specific data
|
|
my $extra;
|
|
my $extra_desc;
|
|
$operation = '' if !defined $operation;
|
|
if ($operation eq 6) {
|
|
# Modify operation
|
|
$extra = $proto_data{'ldap.operation.show'};
|
|
$extra_desc = $proto_data{'ldap.operation.showname'};
|
|
} elsif ($operation eq 0) {
|
|
# Bind operation
|
|
$extra = $proto_data{'ldap.authentication.show'};
|
|
$extra_desc = $proto_data{'ldap.authentication.showname'};
|
|
}
|
|
$extra = '' if !defined $extra;
|
|
$extra_desc = '' if !defined $extra_desc;
|
|
|
|
|
|
# strip the values out of the base object
|
|
if ($base_object) {
|
|
$base_object =~ s/^<//; # leading '<' if present
|
|
$base_object =~ s/>$//; # trailing '>' if present
|
|
$base_object =~ s/=.*?,/,/g; # from = up to the next comma
|
|
$base_object =~ s/=.*?$//; # from = up to the end of string
|
|
}
|
|
|
|
# strip off the leading prefix on the extra_description
|
|
# and the trailing (n);
|
|
$extra_desc =~ s/^[^:]*?: ?// if $extra_desc;
|
|
$extra_desc =~ s/\(\d+\)\s*$// if $extra_desc;
|
|
$extra_desc =~ s/\s*$// if $extra_desc;
|
|
|
|
# strip off the common prefix on the description
|
|
# and the trailing (n);
|
|
$description =~ s/^[^:]*?: ?// if $description;
|
|
$description =~ s/\(\d+\)\s*$// if $description;
|
|
$description =~ s/\s*$// if $description;
|
|
|
|
return "$operation\t$description\t$scope\t$base_object"
|
|
."\t$ldap_filter\t$ldap_attributes\t$extra\t$extra_desc\t$oid";
|
|
} else {
|
|
return "\t*** Unknown ***";
|
|
}
|
|
}
|
|
|
|
#------------------------------------------------------------------------------
|
|
# Format kerberos protocol details for output.
|
|
#------------------------------------------------------------------------------
|
|
sub format_kerberos
|
|
{
|
|
my $msg_type = $proto_data{'kerberos.msg_type.show'} || '';
|
|
my $cname_type = $proto_data{'kerberos.cname.type'} || '';
|
|
my $description = $proto_data{'kerberos.msg_type.showname'} || '';
|
|
|
|
# Tidy up the description
|
|
$description =~ s/^[^:]*?: ?// if $description;
|
|
$description =~ s/\(\d+\)\s*$// if $description;
|
|
$description =~ s/\s*$// if $description;
|
|
return "$msg_type\t$description\t$cname_type";
|
|
}
|
|
|
|
=pod
|
|
|
|
=head1 NAME
|
|
|
|
traffic_summary.pl - summarise tshark pdml output
|
|
|
|
=head1 USAGE
|
|
|
|
B<traffic_summary.pl> [FILE...]
|
|
|
|
Summarise samba network traffic from tshark pdml output. Produces a tsv
|
|
delimited summary of samba activity.
|
|
|
|
To process unencrypted traffic
|
|
|
|
tshark -r capture.file -T pdml | traffic_summary.pl
|
|
|
|
To process encrypted kerberos traffic
|
|
|
|
tshark -r capture.file -K krb5.keytab -o kerberos.decrypt:true -T pdml | traffic_summary.pl
|
|
|
|
To display more detailed documentation, including details of the output format
|
|
|
|
perldoc traffic_summary.pl
|
|
|
|
NOTE: tshark pdml output is very verbose, so it's better to pipe the tshark
|
|
output directly to traffic_summary, rather than generating
|
|
intermediate pdml format files.
|
|
|
|
=head1 OPTIONS
|
|
B<--help> Display usage message and exit.
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
Summarises tshark pdml output into a format suitable for load analysis
|
|
and input into load generation tools.
|
|
|
|
It reads the pdml input from stdin or the list of files passed on the command line.
|
|
|
|
|
|
=head2 Output format
|
|
The output is tab delimited fields and one line per summarised packet.
|
|
|
|
=head3 Fields
|
|
B<timestamp> Packet timestamp
|
|
B<IP protocol> The IANA protocol number
|
|
B<Wireshark Stream Number> Calculated by wireshark groups related requests and responses
|
|
B<Source IP> The unique sequence number for the source IP address
|
|
B<Destination IP> The unique sequence number for the destination IP address
|
|
B<protocl> The protocol name
|
|
B<opcode> The protocol operation code
|
|
B<Description> The protocol or operation description
|
|
B<extra> Extra protocol specific data, may be more than one field
|
|
|
|
|
|
=head2 IP address mapping
|
|
Rather than capturing and printing the IP addresses. Each unique IP address
|
|
seen is assigned a sequence number. So the first IP address seen will be 1,
|
|
the second 2 ...
|
|
|
|
=head2 Packets collected
|
|
Packets containing the following protocol records are summarised:
|
|
dns
|
|
rpc_netlogon
|
|
kerberos
|
|
smb
|
|
smb2
|
|
ldap
|
|
cldap
|
|
lsarpc
|
|
samr
|
|
dcerpc
|
|
epm
|
|
dnsserver
|
|
drsuapi
|
|
browser
|
|
smb_netlogon
|
|
srvsvc
|
|
nbns
|
|
|
|
Any other packets are ignored.
|
|
|
|
In addition to the standard elements extra data is returned for the following
|
|
protocol record.
|
|
|
|
=head3 kerberos
|
|
cname_type machine cname ends with a $
|
|
user cname does not end with a $
|
|
|
|
=head3 ldap
|
|
|
|
scope Query Scope
|
|
0 - Base
|
|
1 - One level
|
|
2 - sub tree
|
|
base_object ldap base object
|
|
ldap_filter the ldap filter, attribute names are retained but the values
|
|
are removed.
|
|
ldap_attributes ldap attributes, only the names are retained any values are
|
|
discarded, with the following two exceptions
|
|
objectClass all the attribute values are retained
|
|
objectCategory the top level value is retained
|
|
i.e. everything from the = to the first ,
|
|
|
|
=head3 ldap modifiyRequest
|
|
In addition to the standard ldap fields the modification type is also captured
|
|
|
|
modify_operator for modifyRequests this contains the modifiy operation
|
|
0 - add
|
|
1 - delete
|
|
2 - replace
|
|
modify_description a description of the operation if available
|
|
|
|
=head3 modify bindRequest
|
|
In addition to the standard ldap fields details of the authentication
|
|
type are captured
|
|
|
|
authentication type 0 - Simple
|
|
3 - SASL
|
|
description Description of the authentication mechanism
|
|
oid GSS-API OID's
|
|
1.2.840.113554.1.2.2 - Kerberos v5
|
|
1.2.840.48018.1.2.2 - Kerberos V5
|
|
(incorrect, used by old Windows versions)
|
|
1.3.6.1.5.5.2 - SPNEGO
|
|
1.3.6.1.5.2.5 - IAKERB
|
|
1.3.6.1.4.1.311.2.2.10 - NTLM SSP
|
|
1.3.6.1.5.5.14 - SCRAM-SHA-1
|
|
1.3.6.1.5.5.18 - SCRAM-SHA-256
|
|
1.3.6.1.5.5.15.1.1.* - GSS-EAP
|
|
1.3.6.1.5.2.7 - PKU2U
|
|
1.3.6.1.5.5.1.1 - SPKM-1
|
|
1.3.6.1.5.5.1.2 - SPKM-2
|
|
1.3.6.1.5.5.1.3 - SPKM-3
|
|
1.3.6.1.5.5.9 - LIPKEY
|
|
1.2.752.43.14.2 - NETLOGON
|
|
|
|
=head1 DEPENDENCIES
|
|
tshark
|
|
XML::Twig For Ubuntu libxml-twig-perl, or from CPAN
|
|
use Getopt::Long
|
|
use Pod::Usage
|
|
|
|
|
|
=head1 Diagnostics
|
|
|
|
=head2 ** Unknown **
|
|
Unable to determine the operation being performed, for ldap it typically
|
|
indicates a kerberos encrypted operation.
|
|
|
|
=head2 ** Malformed Packet **
|
|
tshark indicated that the packet was malformed, for ldap it usually indicates TLS
|
|
encrypted traffic.
|
|
|
|
=head1 LISENCE AND COPYRIGHT
|
|
|
|
Copyright (C) Catalyst.Net Ltd 2017
|
|
|
|
Catalyst.Net's contribution was written by Gary Lockyer
|
|
<gary@catalyst.net.nz>.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
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
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
=cut
|