From 1ad34cf9a1aca11927413c39749adedbab036656 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Tue, 14 Jan 2025 16:17:57 -0800 Subject: [PATCH 1/6] doc(CONTRIBUTORS): added --- .release | 2 +- CONTRIBUTORS.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 CONTRIBUTORS.md diff --git a/.release b/.release index 029586b..0bf2a09 160000 --- a/.release +++ b/.release @@ -1 +1 @@ -Subproject commit 029586bf3a8693bd8f46fd441e05ba1596578d3a +Subproject commit 0bf2a098d4792848c2103dfce0f911e00a14709e diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000..ba83c90 --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,9 @@ +# Contributors + +This handcrafted artisinal software is brought to you by: + +|
msimerson (23)|
analogic (2)|
wioxjk (1)| +| :---: | :---: | :---: | + +this file is generated by [.release](https://github.com/msimerson/.release). +Contribute to this project to get your GitHub profile included here. From 7efd75abf66b05b7af9eaed30a10fb98198a5bb7 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Tue, 14 Jan 2025 16:28:52 -0800 Subject: [PATCH 2/6] populate [files] in package.json. - deps: bump versions - dep(eslint): upgrade to v9 - dep: eslint-plugin-haraka -> @haraka/eslint-config --- .codeclimate.yml | 4 ++-- .eslintrc.yaml | 21 --------------------- .github/workflows/ci.yml | 2 +- Changes.md | 14 ++++++++++++++ README.md | 3 --- eslint.config.mjs | 31 +++++++++++++++++++++++++++++++ package.json | 20 ++++++++++++-------- test/index.js | 4 ++-- 8 files changed, 62 insertions(+), 37 deletions(-) delete mode 100644 .eslintrc.yaml create mode 100644 eslint.config.mjs diff --git a/.codeclimate.yml b/.codeclimate.yml index dfe3bb6..399bbc5 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,9 +1,9 @@ engines: eslint: enabled: true - channel: "eslint-6" + channel: "eslint-9" config: - config: ".eslintrc.yaml" + config: "eslint.config.mjs" ratings: paths: diff --git a/.eslintrc.yaml b/.eslintrc.yaml deleted file mode 100644 index 85e8420..0000000 --- a/.eslintrc.yaml +++ /dev/null @@ -1,21 +0,0 @@ -env: - node: true - es6: true - mocha: true - -plugins: - - haraka - -extends: - - eslint:recommended - - plugin:haraka/recommended - -root: true - -globals: - OK: true - CONT: true - DENY: true - DENYSOFT: true - DENYDISCONNECT: true - DENYSOFTDISCONNECT: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5231a37..e9db940 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ name: CI -on: [ push ] +on: [ push, pull_request ] env: CI: true diff --git a/Changes.md b/Changes.md index 5322076..9f85539 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,16 @@ +# Changelog + +The format is based on [Keep a Changelog](https://keepachangelog.com/). + ### Unreleased +### [1.0.10] - 2025-01-14 + +- populate [files] in package.json. +- deps: bump versions +- dep(eslint): upgrade to v9 +- dep: eslint-plugin-haraka -> @haraka/eslint-config + ### [1.0.9] - 2022-11-10 - fix connect path argument causing server crash when socket missing @@ -57,3 +68,6 @@ [1.0.7]: https://github.com/haraka/haraka-plugin-p0f/releases/tag/1.0.7 [1.0.8]: https://github.com/haraka/haraka-plugin-p0f/releases/tag/1.0.8 +[1.0.10]: https://github.com/haraka/haraka-plugin-p0f/releases/tag/v1.0.10 +[1.0.6]: https://github.com/haraka/haraka-plugin-p0f/releases/tag/1.0.6 +[1.0.9]: https://github.com/haraka/haraka-plugin-p0f/releases/tag/1.0.9 diff --git a/README.md b/README.md index 544ce81..a0814a0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ [![Build Status][ci-img]][ci-url] [![Code Climate][clim-img]][clim-url] -[![NPM][npm-img]][npm-url] # haraka-plugin-p0f @@ -63,5 +62,3 @@ In the contrib/bsd-rc.d directory is a startup file for FreeBSD. [ci-url]: https://github.com/haraka/haraka-plugin-p0f/actions/workflows/ci.yml [clim-img]: https://codeclimate.com/github/haraka/haraka-plugin-p0f/badges/gpa.svg [clim-url]: https://codeclimate.com/github/haraka/haraka-plugin-p0f -[npm-img]: https://nodei.co/npm/haraka-plugin-p0f.png -[npm-url]: https://www.npmjs.com/package/haraka-plugin-p0f diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..4ac6458 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,31 @@ +import globals from "globals"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import js from "@eslint/js"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +export default [...compat.extends("@haraka"), { + languageOptions: { + globals: { + ...globals.node, + ...globals.mocha, + OK: true, + CONT: true, + DENY: true, + DENYSOFT: true, + DENYDISCONNECT: true, + DENYSOFTDISCONNECT: true, + }, + }, + rules: { + "no-unused-vars": "warn" + } +}]; \ No newline at end of file diff --git a/package.json b/package.json index c0f51d7..5dce2b2 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,18 @@ { "name": "haraka-plugin-p0f", - "version": "1.0.9", + "version": "1.0.10", "description": "Haraka plugin that adds TCP fingerprinting", + "files": [ + "config", "contrib", "CHANGELOG.md" + ], "main": "index.js", "scripts": { "cover": "NODE_ENV=cov npx nyc --reporter=lcovonly npm run test", "lint": "npx eslint *.js test", - "lintfix": "npx eslint --fix *.js test", - "test": "npx mocha" + "lint:fix": "npx eslint --fix *.js test", + "test": "npx mocha", + "versions": "npx dependency-version-checker check", + "versions:fix": "npx dependency-version-checker update" }, "repository": { "type": "git", @@ -25,12 +30,11 @@ }, "homepage": "https://github.com/haraka/haraka-plugin-p0f#readme", "devDependencies": { - "eslint": ">=8", - "eslint-plugin-haraka": "*", - "haraka-test-fixtures": "*", - "mocha": ">=9" + "@haraka/eslint-config": "^2.0.2", + "haraka-test-fixtures": "^1.3.8", + "mocha": "^11.1.0" }, "dependencies": { - "ipaddr.js": "^2.0.1" + "ipaddr.js": "^2.2.0" } } diff --git a/test/index.js b/test/index.js index 1dd8da5..09ffd2e 100644 --- a/test/index.js +++ b/test/index.js @@ -42,7 +42,7 @@ describe('data_post', () => { this.plugin.load_p0f_ini() this.plugin.cfg.main.add_header = 'X-p0f-Result' this.connection = new fixtures.connection.createConnection() - this.connection.transaction = new fixtures.transaction.createTransaction() + this.connection.init_transaction() this.connection.results.add({ name: 'p0f' }, { os_name: 'BeOS', os_flavor: 'forever'}) done() }) @@ -66,4 +66,4 @@ describe('data_post', () => { }, this.connection) }) -}) \ No newline at end of file +}) From e5d600c6abc1b8621f3e14289ab17956df764545 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Tue, 14 Jan 2025 16:29:38 -0800 Subject: [PATCH 3/6] doc(CONTRIBUTORS): added --- Changes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes.md b/Changes.md index 9f85539..6e3f92c 100644 --- a/Changes.md +++ b/Changes.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). ### [1.0.10] - 2025-01-14 +- doc(CONTRIBUTORS): added - populate [files] in package.json. - deps: bump versions - dep(eslint): upgrade to v9 From f829037410e0d173081e4741a44e544aa2ff0c44 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Tue, 14 Jan 2025 16:30:21 -0800 Subject: [PATCH 4/6] doc: mv Changes.md CHANGELOG.md --- Changes.md => CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) rename Changes.md => CHANGELOG.md (97%) diff --git a/Changes.md b/CHANGELOG.md similarity index 97% rename from Changes.md rename to CHANGELOG.md index 6e3f92c..bb41aaa 100644 --- a/Changes.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). ### [1.0.10] - 2025-01-14 +- doc: mv Changes.md CHANGELOG.md - doc(CONTRIBUTORS): added - populate [files] in package.json. - deps: bump versions From eba16cdcffd31236c5fb810fa820cdd57d1518d9 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Tue, 14 Jan 2025 16:33:34 -0800 Subject: [PATCH 5/6] automated code formatting with prettier --- .codeclimate.yml | 8 +- .github/dependabot.yml | 6 +- .github/workflows/ci.yml | 5 +- .github/workflows/codeql.yml | 6 +- .github/workflows/publish.yml | 2 +- .prettierrc | 2 + CHANGELOG.md | 10 +- CONTRIBUTORS.md | 4 +- README.md | 19 +- eslint.config.mjs | 53 ++-- index.js | 447 +++++++++++++++++----------------- package.json | 7 +- test/index.js | 86 ++++--- 13 files changed, 327 insertions(+), 328 deletions(-) create mode 100644 .prettierrc diff --git a/.codeclimate.yml b/.codeclimate.yml index 399bbc5..563da6b 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,10 +1,10 @@ engines: eslint: enabled: true - channel: "eslint-9" + channel: 'eslint-9' config: - config: "eslint.config.mjs" + config: 'eslint.config.mjs' ratings: - paths: - - "**.js" + paths: + - '**.js' diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0449e4a..d450132 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,9 +2,9 @@ version: 2 updates: - - package-ecosystem: "npm" - directory: "/" + - package-ecosystem: 'npm' + directory: '/' schedule: - interval: "weekly" + interval: 'weekly' allow: - dependency-type: production diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9db940..b33132b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,11 @@ name: CI -on: [ push, pull_request ] +on: [push, pull_request] env: CI: true jobs: - lint: uses: haraka/.github/.github/workflows/lint.yml@master @@ -15,5 +14,5 @@ jobs: # secrets: inherit ubuntu: - needs: [ lint ] + needs: [lint] uses: haraka/.github/.github/workflows/ubuntu.yml@master diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 383aca2..816e8c3 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,10 +1,10 @@ -name: "CodeQL" +name: 'CodeQL' on: push: - branches: [ master ] + branches: [master] pull_request: - branches: [ master ] + branches: [master] schedule: - cron: '18 7 * * 4' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d489fbd..e81c15f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,4 +13,4 @@ env: jobs: publish: uses: haraka/.github/.github/workflows/publish.yml@master - secrets: inherit \ No newline at end of file + secrets: inherit diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..8ded5e0 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,2 @@ +singleQuote: true +semi: false diff --git a/CHANGELOG.md b/CHANGELOG.md index bb41aaa..50898b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). ### [1.0.10] - 2025-01-14 +- automated code formatting with prettier - doc: mv Changes.md CHANGELOG.md - doc(CONTRIBUTORS): added - populate [files] in package.json. @@ -23,7 +24,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). - ci: only publish when package.json changes - Added systemd.service file (#25) - ### [1.0.7] - 2022-06-05 - ci: update GHA workflow with shared @@ -31,43 +31,35 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/). - ci: add submodule .release - test: require mocha >= 9 - ### 1.0.6 - 2021-11-10 - bump eslint 6 -> 8 - ### 1.0.5 - 2020-12-30 - es6: use object shorthand - update dep ipaddr.js version - ### 1.0.4 - 2019-12-23 - update to es6 classes - ### 1.0.3 - 2018-05-30 - add_header option visible at config - ### 1.0.2 - 2017-09-11 - when socket_path is not configured, emit an error - ### 1.0.1 - 2017-09-01 - repackaged as p0f, added contrib scripts, test release - ### 1.0.0 - 2017-07-27 - import from Haraka - [1.0.7]: https://github.com/haraka/haraka-plugin-p0f/releases/tag/1.0.7 [1.0.8]: https://github.com/haraka/haraka-plugin-p0f/releases/tag/1.0.8 [1.0.10]: https://github.com/haraka/haraka-plugin-p0f/releases/tag/v1.0.10 diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ba83c90..bce0698 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -2,8 +2,8 @@ This handcrafted artisinal software is brought to you by: -|
msimerson (23)|
analogic (2)|
wioxjk (1)| -| :---: | :---: | :---: | +|
msimerson (23) |
analogic (2) |
wioxjk (1) | +| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | this file is generated by [.release](https://github.com/msimerson/.release). Contribute to this project to get your GitHub profile included here. diff --git a/README.md b/README.md index a0814a0..803b0d6 100644 --- a/README.md +++ b/README.md @@ -11,25 +11,23 @@ This plugin inserts a _p0f_ connection note with information deduced from the TCP fingerprint. The note typically includes at least the link, detail, distance, uptime, genre. Here's an example: - genre => FreeBSD - detail => 8.x (1) - uptime => 1390 - link => ethernet/modem - distance => 17 + genre => FreeBSD + detail => 8.x (1) + uptime => 1390 + link => ethernet/modem + distance => 17 Which was parsed from this p0f fingerprint: 24.18.227.2:39435 - FreeBSD 8.x (1) (up: 1390 hrs) - -> 208.75.177.101:25 (distance 17, link: ethernet/modem) + -> 208.75.177.101:25 (distance 17, link: ethernet/modem) The following additional values may also be available in the _p0f_ connection note: magic, status, first_seen, last_seen, total_conn, uptime_min, up_mod_days, last_nat, last_chg, distance, bad_sw, os_match_q, os_name, os_flavor, http_name, http_flavor, link_type, and language. - -Configuration ------------------ +## Configuration 1. start p0f @@ -45,7 +43,6 @@ add an entry to config/plugins to enable p0f: p0f - 3. review settings in config/p0f.ini At a minimum, `[main]socket_path` must be defined. @@ -56,8 +53,8 @@ In the contrib/ubuntu-upstart directory is a config file (p0f.conf) for Ubuntu. In the contrib/bsd-rc.d directory is a startup file for FreeBSD. - + [ci-img]: https://github.com/haraka/haraka-plugin-p0f/actions/workflows/ci.yml/badge.svg [ci-url]: https://github.com/haraka/haraka-plugin-p0f/actions/workflows/ci.yml [clim-img]: https://codeclimate.com/github/haraka/haraka-plugin-p0f/badges/gpa.svg diff --git a/eslint.config.mjs b/eslint.config.mjs index 4ac6458..7272162 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,31 +1,34 @@ -import globals from "globals"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; -import js from "@eslint/js"; -import { FlatCompat } from "@eslint/eslintrc"; +import globals from 'globals' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import js from '@eslint/js' +import { FlatCompat } from '@eslint/eslintrc' -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all -}); + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}) -export default [...compat.extends("@haraka"), { +export default [ + ...compat.extends('@haraka'), + { languageOptions: { - globals: { - ...globals.node, - ...globals.mocha, - OK: true, - CONT: true, - DENY: true, - DENYSOFT: true, - DENYDISCONNECT: true, - DENYSOFTDISCONNECT: true, - }, + globals: { + ...globals.node, + ...globals.mocha, + OK: true, + CONT: true, + DENY: true, + DENYSOFT: true, + DENYDISCONNECT: true, + DENYSOFTDISCONNECT: true, + }, }, rules: { - "no-unused-vars": "warn" - } -}]; \ No newline at end of file + 'no-unused-vars': 'warn', + }, + }, +] diff --git a/index.js b/index.js index 5d627d1..fcfbd1a 100644 --- a/index.js +++ b/index.js @@ -1,262 +1,265 @@ -'use strict'; +'use strict' // p0f v3 client - http://lcamtuf.coredump.cx/p0f3/ -const net = require('net'); -const ipaddr = require('ipaddr.js'); +const net = require('net') +const ipaddr = require('ipaddr.js') class P0FClient { - constructor (path) { + 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.connect(path) + } + + connect(path) { + this.sock = net.createConnection(path) + this.sock.setTimeout(5 * 1000) + + 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 = null; - this.send_queue = []; - this.receive_queue = []; - this.connected = false; - this.ready = false; - this.socket_has_error = false; - this.restart_interval = false; + this.sock.on('data', (data) => { + for (let i = 0; i < data.length / 232; i++) { + this.decode_response(data.slice(i ? 232 * i : 0, 232 * (i + 1))) + } + }) - this.connect(path); - } + this.sock.on('drain', () => { + this.ready = true + this.process_send_queue() + }) - connect (path) { - this.sock = net.createConnection(path); - this.sock.setTimeout(5 * 1000); - - 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 { - this.ready = true; - this.process_send_queue(); - }) - - 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 (!this.restart_interval) { - this.restart_interval = setInterval(() => { this.connect(path); }, 5 * 1000); - } - // Clear the receive queue - for (let i=0; i { + this.connected = false + error.message = `${error.message} (socket: ${path})` + this.socket_has_error = error + this.sock.destroy() + + // Try and reconnect + if (!this.restart_interval) { + this.restart_interval = setInterval(() => { + this.connect(path) + }, 5 * 1000) + } + // Clear the receive queue + for (let i = 0; i < this.receive_queue.length; i++) { + const item = this.receive_queue.shift() + item.cb(this.socket_has_error) + continue + } + this.process_send_queue() + }) + } - shutdown () { - if (this.restart_interval) { - clearInterval(this.restart_interval); - } + shutdown() { + if (this.restart_interval) { + clearInterval(this.restart_interval) + } + } + + 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) + } + return str } - decode_response (data) { + if (this.receive_queue.length <= 0) { + throw new Error('unexpected data received') + } + const item = this.receive_queue.shift() - function decode_string (data2, start, end) { - let str = ''; - for (let a=start; a { - if (err) { - connection.results.add(plugin, {err: err.message}); - return next(); - } - - if (!result) { - connection.results.add(plugin, {err: 'no p0f results'}); - return next(); - } - - connection.loginfo(plugin, format_results(result)); - connection.results.add(plugin, result); - next(); - }) +exports.query_p0f = function onLookup(next, connection) { + const plugin = this + if (connection.remote.is_private) return next() + + if (!connection.server.notes.p0f_client) { + connection.logerror(plugin, 'missing p0f client') + return next() + } + + connection.server.notes.p0f_client.query( + connection.remote.ip, + (err, result) => { + if (err) { + connection.results.add(plugin, { err: err.message }) + return next() + } + + if (!result) { + connection.results.add(plugin, { err: 'no p0f results' }) + return next() + } + + connection.loginfo(plugin, format_results(result)) + connection.results.add(plugin, result) + 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')}`); - return data.join(' '); +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'}`) + return data.join(' ') } exports.add_p0f_header = function (next, connection) { - const plugin = this; - if (connection.remote.is_private) return next(); - - const header_name = plugin.cfg.main.add_header; - if (!header_name) { - connection.logdebug(plugin, 'header disabled in ini' ); - return next(); - } - - connection.transaction.remove_header(header_name); - const result = connection.results.get('p0f'); - if (!result || !result.os_name) { - connection.results.add(plugin, {err: 'no p0f note'}); - return next(); - } - - connection.logdebug(plugin, 'adding header'); - connection.transaction.add_header(header_name, format_results(result)); - - next(); + const plugin = this + if (connection.remote.is_private) return next() + + const header_name = plugin.cfg.main.add_header + if (!header_name) { + connection.logdebug(plugin, 'header disabled in ini') + return next() + } + + connection.transaction.remove_header(header_name) + const result = connection.results.get('p0f') + if (!result || !result.os_name) { + connection.results.add(plugin, { err: 'no p0f note' }) + return next() + } + + connection.logdebug(plugin, 'adding header') + connection.transaction.add_header(header_name, format_results(result)) + + next() } diff --git a/package.json b/package.json index 5dce2b2..a46e7b9 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,18 @@ "version": "1.0.10", "description": "Haraka plugin that adds TCP fingerprinting", "files": [ - "config", "contrib", "CHANGELOG.md" + "config", + "contrib", + "CHANGELOG.md" ], "main": "index.js", "scripts": { "cover": "NODE_ENV=cov npx nyc --reporter=lcovonly npm run test", + "format": "npm run prettier:fix && npm run lint:fix", "lint": "npx eslint *.js test", "lint:fix": "npx eslint --fix *.js test", + "prettier": "npx prettier . --check", + "prettier:fix": "npx prettier . --write --log-level=warn", "test": "npx mocha", "versions": "npx dependency-version-checker check", "versions:fix": "npx dependency-version-checker update" diff --git a/test/index.js b/test/index.js index 09ffd2e..b86befe 100644 --- a/test/index.js +++ b/test/index.js @@ -1,6 +1,5 @@ - // node.js built-in modules -const assert = require('assert') +const assert = require('assert') // npm modules const fixtures = require('haraka-test-fixtures') @@ -10,60 +9,59 @@ const fixtures = require('haraka-test-fixtures') // mocha: http://mochajs.org beforeEach((done) => { - this.plugin = new fixtures.plugin('p0f') - done() + this.plugin = new fixtures.plugin('p0f') + done() }) describe('p0f', () => { - it('loads', (done) => { - assert.ok(this.plugin) - done() - }) + it('loads', (done) => { + assert.ok(this.plugin) + done() + }) }) describe('load_p0f_ini', () => { - it('loads p0f.ini from config/p0f.ini', (done) => { - this.plugin.load_p0f_ini() - assert.ok(this.plugin.cfg) - done() - }) + it('loads p0f.ini from config/p0f.ini', (done) => { + this.plugin.load_p0f_ini() + assert.ok(this.plugin.cfg) + done() + }) }) describe('lookup_rdns', () => { - it.skip('retrieves TCP fingerprint data from p0f server', (done) => { - done() - }) + it.skip('retrieves TCP fingerprint data from p0f server', (done) => { + done() + }) }) describe('data_post', () => { + beforeEach((done) => { + this.plugin = new fixtures.plugin('p0f') + this.plugin.load_p0f_ini() + this.plugin.cfg.main.add_header = 'X-p0f-Result' + this.connection = new fixtures.connection.createConnection() + this.connection.init_transaction() + this.connection.results.add( + { name: 'p0f' }, + { os_name: 'BeOS', os_flavor: 'forever' }, + ) + done() + }) - beforeEach((done) => { - this.plugin = new fixtures.plugin('p0f') - this.plugin.load_p0f_ini() - this.plugin.cfg.main.add_header = 'X-p0f-Result' - this.connection = new fixtures.connection.createConnection() - this.connection.init_transaction() - this.connection.results.add({ name: 'p0f' }, { os_name: 'BeOS', os_flavor: 'forever'}) - done() - }) - - it('adds a header when data exists', (done) => { - - this.plugin.add_p0f_header((code, value) => { - assert.ok(Object.keys(this.connection.transaction.header.headers)) - done() - }, - this.connection) - }) + it('adds a header when data exists', (done) => { + this.plugin.add_p0f_header((code, value) => { + assert.ok(Object.keys(this.connection.transaction.header.headers)) + done() + }, this.connection) + }) - it('ignores private IPs', (done) => { - this.connection.remote.is_private=true; - this.plugin.add_p0f_header((code, value) => { - assert.equal(code, undefined) - assert.equal(value, undefined) - assert.equal(Object.keys(this.connection.transaction.header.headers), 0) - done() - }, - this.connection) - }) + it('ignores private IPs', (done) => { + this.connection.remote.is_private = true + this.plugin.add_p0f_header((code, value) => { + assert.equal(code, undefined) + assert.equal(value, undefined) + assert.equal(Object.keys(this.connection.transaction.header.headers), 0) + done() + }, this.connection) + }) }) From 45acf03f25996c335c98dd79b9de74e4b3554f4c Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Tue, 14 Jan 2025 16:33:41 -0800 Subject: [PATCH 6/6] chore: format --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 803b0d6..69e0d2e 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,16 @@ This plugin inserts a _p0f_ connection note with information deduced from the TCP fingerprint. The note typically includes at least the link, detail, distance, uptime, genre. Here's an example: - genre => FreeBSD - detail => 8.x (1) - uptime => 1390 - link => ethernet/modem - distance => 17 +genre => FreeBSD +detail => 8.x (1) +uptime => 1390 +link => ethernet/modem +distance => 17 Which was parsed from this p0f fingerprint: - 24.18.227.2:39435 - FreeBSD 8.x (1) (up: 1390 hrs) - -> 208.75.177.101:25 (distance 17, link: ethernet/modem) +24.18.227.2:39435 - FreeBSD 8.x (1) (up: 1390 hrs) +-> 208.75.177.101:25 (distance 17, link: ethernet/modem) The following additional values may also be available in the _p0f_ connection note: