New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

haraka-plugin-p0f

Package Overview
Dependencies
Maintainers
4
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

haraka-plugin-p0f - npm Package Compare versions

Comparing version 1.0.2 to 1.0.3

7

Changes.md

@@ -0,6 +1,9 @@

## 1.0.3 - 2018-05-30
## 1.0.1 - 2017-09-11
- add_header option visible at config
- when socket_path is not configured, emit an error
## 1.0.2 - 2017-09-11
- when socket_path is not configured, emit an error
## 1.0.1 - 2017-09-01

@@ -7,0 +10,0 @@

@@ -7,177 +7,168 @@ 'use strict';

function P0FClient (path) {
const self = this;
class P0FClient {
constructor (path) {
this.sock = null;
this.send_queue = [];
this.receive_queue = [];
this.connected = false;
this.ready = false;
this.socket_has_error = false;
this.restart_interval = false;
this.sock = null;
this.send_queue = [];
this.receive_queue = [];
this.connected = false;
this.ready = false;
this.socket_has_error = false;
this.restart_interval = false;
function connect () {
self.sock = net.createConnection(path);
self.sock.setTimeout(5 * 1000);
this.connect(path);
}
self.sock.on('connect', function () {
self.sock.setTimeout(30 * 1000);
self.connected = true;
self.socket_has_error = false;
self.ready = true;
if (self.restart_interval) clearInterval(self.restart_interval);
self.process_send_queue();
});
connect (path) {
this.sock = net.createConnection(path);
this.sock.setTimeout(5 * 1000);
self.sock.on('data', function (data) {
this.sock.on('connect', () => {
this.sock.setTimeout(30 * 1000);
this.connected = true;
this.socket_has_error = false;
this.ready = true;
if (this.restart_interval) clearInterval(this.restart_interval);
this.process_send_queue();
})
this.sock.on('data', (data) => {
for (let i=0; i<data.length/232; i++) {
self.decode_response(data.slice(((i) ? 232*i : 0), 232*(i+1)));
this.decode_response(data.slice(((i) ? 232*i : 0), 232*(i+1)));
}
});
})
self.sock.on('drain', function () {
self.ready = true;
self.process_send_queue();
});
this.sock.on('drain', () => {
this.ready = true;
this.process_send_queue();
})
self.sock.on('error', function (error) {
self.connected = false;
error.message = error.message + ' (socket: ' + path + ')';
self.socket_has_error = error;
self.sock.destroy();
this.sock.on('error', (error) => {
this.connected = false;
error.message = `${error.message} (socket: ${path})`;
this.socket_has_error = error;
this.sock.destroy();
// Try and reconnect
if (!self.restart_interval) {
self.restart_interval = setInterval(function () {
connect();
}, 5 * 1000);
if (!this.restart_interval) {
this.restart_interval = setInterval(() => { connect(); }, 5 * 1000);
}
// Clear the receive queue
for (let i=0; i<self.receive_queue.length; i++) {
const item = self.receive_queue.shift();
item.cb(self.socket_has_error);
for (let i=0; i<this.receive_queue.length; i++) {
const item = this.receive_queue.shift();
item.cb(this.socket_has_error);
continue;
}
self.process_send_queue();
});
this.process_send_queue();
})
}
connect();
}
P0FClient.prototype.shutdown = function () {
if (this.restart_interval) {
clearInterval(this.restart_interval);
shutdown () {
if (this.restart_interval) {
clearInterval(this.restart_interval);
}
}
}
P0FClient.prototype.decode_response = function (data) {
decode_response (data) {
function decode_string (data2, start, end) {
let str = '';
for (let a=start; a<end; a++) {
const b = data2.readUInt8(a);
if (b === 0x0) break;
str = str + String.fromCharCode(b);
function decode_string (data2, start, end) {
let str = '';
for (let a=start; a<end; a++) {
const b = data2.readUInt8(a);
if (b === 0x0) break;
str = str + String.fromCharCode(b);
}
return str;
}
return str;
}
if (this.receive_queue.length <= 0) {
throw new Error('unexpected data received');
}
const item = this.receive_queue.shift();
if (this.receive_queue.length <= 0) {
throw new Error('unexpected data received');
}
const item = this.receive_queue.shift();
///////////////////
// Decode packet //
///////////////////
///////////////////
// Decode packet //
///////////////////
// Response magic dword (0x50304602), native endian.
if (data.readUInt32LE(0) !== 0x50304602) {
return item.cb(new Error('bad response magic!'));
}
// Response magic dword (0x50304602), native endian.
if (data.readUInt32LE(0) !== 0x50304602) {
return item.cb(new Error('bad response magic!'));
}
// Status dword: 0x00 for 'bad query', 0x10 for 'OK', and 0x20 for 'no match'
const st = data.readUInt32LE(4);
switch (st) {
case (0x00):
return item.cb(new Error('bad query'));
case (0x10): {
const p0f = {
query: item.ip,
first_seen: data.readUInt32LE(8),
last_seen: data.readUInt32LE(12),
total_conn: data.readUInt32LE(16),
uptime_min: data.readUInt32LE(20),
up_mod_days: data.readUInt32LE(24),
last_nat: data.readUInt32LE(28),
last_chg: data.readUInt32LE(32),
distance: data.readInt16LE(36),
bad_sw: data.readUInt8(38),
os_match_q: data.readUInt8(39),
os_name: decode_string(data, 40, 72),
os_flavor: decode_string(data, 72, 104),
http_name: decode_string(data, 104, 136),
http_flavor: decode_string(data, 136, 168),
link_type: decode_string(data, 168, 200),
language: decode_string(data, 200, 232),
// Status dword: 0x00 for 'bad query', 0x10 for 'OK', and 0x20 for 'no match'
const st = data.readUInt32LE(4);
switch (st) {
case (0x00):
return item.cb(new Error('bad query'));
case (0x10): {
const p0f = {
query: item.ip,
first_seen: data.readUInt32LE(8),
last_seen: data.readUInt32LE(12),
total_conn: data.readUInt32LE(16),
uptime_min: data.readUInt32LE(20),
up_mod_days: data.readUInt32LE(24),
last_nat: data.readUInt32LE(28),
last_chg: data.readUInt32LE(32),
distance: data.readInt16LE(36),
bad_sw: data.readUInt8(38),
os_match_q: data.readUInt8(39),
os_name: decode_string(data, 40, 72),
os_flavor: decode_string(data, 72, 104),
http_name: decode_string(data, 104, 136),
http_flavor: decode_string(data, 136, 168),
link_type: decode_string(data, 168, 200),
language: decode_string(data, 200, 232),
}
return item.cb(null, p0f);
}
return item.cb(null, p0f);
case (0x20):
return item.cb(null, null);
default:
throw new Error(`unknown status: ${st}`);
}
case (0x20):
return item.cb(null, null);
default:
throw new Error('unknown status: ' + st);
}
};
P0FClient.prototype.query = function (ip, cb) {
if (this.socket_has_error) {
return cb(this.socket_has_error);
query (ip, cb) {
if (this.socket_has_error) {
return cb(this.socket_has_error);
}
if (!this.connected) {
return cb(new Error('socket not connected'));
}
const addr = ipaddr.parse(ip);
const bytes = addr.toByteArray();
const buf = new Buffer(21);
buf.writeUInt32LE(0x50304601, 0); // query magic
buf.writeUInt8(((addr.kind() === 'ipv6') ? 0x6 : 0x4), 4);
for (let i=0; i < bytes.length; i++) {
buf.writeUInt8(bytes[i], 5 + i);
}
if (!this.ready) {
this.send_queue.push({ip: ip, cb: cb, buf: buf});
}
else {
this.receive_queue.push({ip: ip, cb: cb});
if (!this.sock.write(buf)) this.ready = false;
}
}
if (!this.connected) {
return cb(new Error('socket not connected'));
}
const addr = ipaddr.parse(ip);
const bytes = addr.toByteArray();
const buf = new Buffer(21);
buf.writeUInt32LE(0x50304601, 0); // query magic
buf.writeUInt8(((addr.kind() === 'ipv6') ? 0x6 : 0x4), 4);
for (let i=0; i < bytes.length; i++) {
buf.writeUInt8(bytes[i], 5 + i);
}
if (!this.ready) {
this.send_queue.push({ip: ip, cb: cb, buf: buf});
}
else {
this.receive_queue.push({ip: ip, cb: cb});
if (!this.sock.write(buf)) this.ready = false;
}
};
P0FClient.prototype.process_send_queue = function () {
if (this.send_queue.length === 0) { return; }
process_send_queue () {
if (this.send_queue.length === 0) { return; }
for (let i=0; i<this.send_queue.length; i++) {
let item;
if (this.socket_has_error) {
for (let i=0; i<this.send_queue.length; i++) {
let item;
if (this.socket_has_error) {
item = this.send_queue.shift();
item.cb(this.socket_has_error);
continue;
}
if (!this.ready) break;
item = this.send_queue.shift();
item.cb(this.socket_has_error);
continue;
this.receive_queue.push({ip: item.ip, cb: item.cb});
if (!this.sock.write(item.buf)) {
this.ready = false;
}
}
if (!this.ready) break;
item = this.send_queue.shift();
this.receive_queue.push({ip: item.ip, cb: item.cb});
if (!this.sock.write(item.buf)) {
this.ready = false;
}
}
};
function start_p0f_client (sp, server, next) {
if (!sp) {
server.logerror("main.socket_path not defined in p0f.ini!");
return next();
}
// Start p0f process
server.notes.p0f_client = new P0FClient(sp);
next();
}

@@ -189,4 +180,10 @@

this.load_p0f_ini();
};
this.register_hook('init_master', 'start_p0f_client')
this.register_hook('init_child', 'start_p0f_client')
this.register_hook('lookup_rdns', 'query_p0f')
this.register_hook('data_post', 'add_p0f_header')
}
exports.load_p0f_ini = function () {

@@ -199,11 +196,14 @@ const plugin = this;

exports.hook_init_master = function (next, server) {
start_p0f_client(this.cfg.main.socket_path, server, next);
exports.start_p0f_client = function (next, server) {
if (!this.cfg.main.socket_path) {
server.logerror("main.socket_path not defined in p0f.ini!");
return next();
}
// Start p0f process
server.notes.p0f_client = new P0FClient(this.cfg.main.socket_path);
next();
}
exports.hook_init_child = function (next, server) {
start_p0f_client(this.cfg.main.socket_path, server, next);
};
exports.hook_lookup_rdns = function onLookup (next, connection) {
exports.query_p0f = function onLookup (next, connection) {
const plugin = this;

@@ -213,3 +213,3 @@ if (connection.remote.is_private) return next();

if (!connection.server.notes.p0f_client) {
connection.logerror(plugin, 'missing server');
connection.logerror(plugin, 'missing p0f client');
return next();

@@ -232,16 +232,16 @@ }

next();
});
};
})
}
function format_results (r) {
const data = [];
if (r.os_name) data.push('os="' + r.os_name + ' ' + r.os_flavor + '"');
if (r.link_type) data.push('link_type="' + r.link_type + '"');
if (r.distance) data.push('distance=' + r.distance);
if (r.total_conn) data.push('total_conn=' + r.total_conn);
if (r.last_nat) data.push('shared_ip=' + ((r.last_nat === 0) ? 'N' : 'Y'));
if (r.os_name) data.push(`os="${r.os_name} ${r.os_flavor}"`);
if (r.link_type) data.push(`link_type="${r.link_type}"`);
if (r.distance) data.push(`distance=${r.distance}`);
if (r.total_conn) data.push(`total_conn=${r.total_conn}`);
if (r.last_nat) data.push(`shared_ip=${((r.last_nat === 0) ? 'N' : 'Y')}`);
return data.join(' ');
}
exports.hook_data_post = function (next, connection) {
exports.add_p0f_header = function (next, connection) {
const plugin = this;

@@ -248,0 +248,0 @@ if (connection.remote.is_private) return next();

{
"name": "haraka-plugin-p0f",
"version": "1.0.2",
"version": "1.0.3",
"description": "Haraka plugin that adds TCP fingerprinting",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -33,3 +33,3 @@

describe('lookup_rdns', () => {
it.skip('retrieves TCP fingerprint data from p0f server', function (done) {
it.skip('retrieves TCP fingerprint data from p0f server', (done) => {
done()

@@ -53,3 +53,3 @@ })

this.plugin.hook_data_post((code, value) => {
this.plugin.add_p0f_header((code, value) => {
assert.ok(Object.keys(this.connection.transaction.header.headers))

@@ -63,3 +63,3 @@ done()

this.connection.remote.is_private=true;
this.plugin.hook_data_post((code, value) => {
this.plugin.add_p0f_header((code, value) => {
assert.equal(code, undefined)

@@ -66,0 +66,0 @@ assert.equal(value, undefined)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc