Oops, disregard that, I was silly. Too much copy paste with not enough
attention paid to what I was doing ;)
Please let me know if this one looks better (I tested it, it too works
and should fail more gracefully).
Thanks,
Tom
Tom Callahan wrote:
I just did the minimal modification to get it working with the new p0f
API (it does indeed work for me); theoretically it should be roughly as
complete as the old p0f plugin. In the interests of completeness I'll
fix it up and send in a better version though.
Thanks,
Tom
Robert Spier wrote:
Thanks Tom, but did you test this? It might work, but failure cases
aren't going to.
It references log_err and cleanup:, neither of which exist.
(Turns out the whole plugin needs some rewriting to fail better, it
has some dies that need removing.)
Tom Callahan wrote:
I think it was discussed on list some time ago that the p0f plugin no
longer worked with new versions of p0f but no one pushed the new plugin
version out to the list and/or updated it in git. Attached version has
been modified based on the more recent version of pofq.pl and so should
work.
Tom
# -*- perl -*-
=pod
An Identification Plugin
./p0f -u qpsmtpd -d -q -Q /tmp/.p0f_socket 'dst port 25' -o /dev/null && \
chown qpsmtpd /tmp/.p0f_socket
and add
ident/p0f /tmp/.p0f_socket
to config/plugins
it puts things into the 'p0f' connection notes so other plugins can do
things based on source OS.
=cut
#All code heavily based upon the p0fq.pl included with the p0f distribution.
use IO::Socket;
use Net::IP;
sub register {
my ($self, $qp, $p0f_socket) = @_;
$p0f_socket =~ /(.*)/; # untaint
$self->{_args}->{p0f_socket} = $1;
}
sub hook_connect {
my($self, $qp) = @_;
my $QUERY_MAGIC = 0x0defaced;
my $p0f_socket = $self->{_args}->{p0f_socket};
my $srcip = $self->qp->connection->remote_ip;
my $srcport = $self->qp->connection->remote_port;
my $destip = $self->qp->connection->local_ip;
my $destport = $self->qp->connection->local_port;
my $src = new Net::IP ($srcip) or $self->log(LOGERROR, "p0f:
".Net::IP::Error()), return (DECLINED);
my $dst = new Net::IP ($destip) or $self->log(LOGERROR, "p0f:
".NET::IP::Error()), return (DECLINED);
my $query = pack("L L L N N S S", $QUERY_MAGIC, 1, rand ^ 42 ^ time,
$src->intip(), $dst->intip(), $srcport, $destport);
# Open the connection to p0f
socket(SOCK, PF_UNIX, SOCK_STREAM, 0) or $self->log(LOGERROR, "p0f: socket:
$!"), return (DECLINED);
connect(SOCK, sockaddr_un($p0f_socket)) or $self->log(LOGERROR, "p0f:
connect: $!"), return (DECLINED);
defined syswrite SOCK, $query or $self->log(LOGERROR, "p0f: write: $!"),
close SOCK, return (DECLINED);
my $response;
defined sysread SOCK, $response, 1024 or $self->log(LOGERROR, "p0f: read:
$!"), close SOCK, return (DECLINED);
close SOCK;
# Extract the response from p0f
my ($magic, $id, $type, $genre, $detail, $dist, $link, $tos, $fw,
$nat, $real, $score, $mflags, $uptime) =
unpack ("L L C Z20 Z40 c Z30 Z30 C C C s S N", $response);
if ($magic != $QUERY_MAGIC) {
$self->log(LOGERROR, "p0f: Bad response magic.");
return (DECLINED);
}
if ($type == 1) {
$self->log(LOGERROR, "p0f: P0f did not honor our query");
return (DECLINED);
}
if ($type == 2) {
$self->log(LOGWARN, "p0f: This connection is no longer in the cache");
return (DECLINED);
}
my $p0f = { genre => $genre,
detail => $detail,
distance => $dist,
link => $link,
uptime => $uptime,
};
$self->qp->connection->notes('p0f',$p0f);
$self->log(LOGNOTICE, "Results: ".$p0f->{genre}." (".$p0f->{detail}.")");
$self->log(LOGERROR,"error: $@") if $@;
return DECLINED;
}