haraka-plugin-karma 2.1.5 → 2.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
4
4
 
5
5
  ### Unreleased
6
6
 
7
+ ### [2.1.7] - 2025-01-31
8
+
9
+ - replace utils.in_array with [].includes
10
+ - dep(eslint): upgrade to v9
11
+ - doc(CONTRIBUTORS): updated
12
+
13
+ ### [2.1.6] - 2024-11-08
14
+
15
+ - fix missing error handler on redis client #61
16
+
7
17
  ### [2.1.5] - 2024-04-23
8
18
 
9
19
  - doc(README): remove spurious markdown link
@@ -130,3 +140,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
130
140
  [2.1.3]: https://github.com/haraka/haraka-plugin-karma/releases/tag/v2.1.3
131
141
  [2.1.4]: https://github.com/haraka/haraka-plugin-karma/releases/tag/v2.1.4
132
142
  [2.1.5]: https://github.com/haraka/haraka-plugin-karma/releases/tag/v2.1.5
143
+ [2.1.6]: https://github.com/haraka/haraka-plugin-karma/releases/tag/v2.1.6
package/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  [![Build Status][ci-img]][ci-url]
2
2
  [![Code Climate][clim-img]][clim-url]
3
- [![NPM][npm-img]][npm-url]
4
3
 
5
4
  # Karma - A heuristics based reputation engine for the Haraka MTA
6
5
 
@@ -200,5 +199,3 @@ Expect to use karma _with_ content filters.
200
199
  [cov-url]: https://codecov.io/github/haraka/haraka-plugin-karma
201
200
  [clim-img]: https://codeclimate.com/github/haraka/haraka-plugin-karma/badges/gpa.svg
202
201
  [clim-url]: https://codeclimate.com/github/haraka/haraka-plugin-karma
203
- [npm-img]: https://nodei.co/npm/haraka-plugin-karma.png
204
- [npm-url]: https://www.npmjs.com/package/haraka-plugin-karma
package/index.js CHANGED
@@ -124,6 +124,9 @@ exports.results_init = async function (next, connection) {
124
124
  }
125
125
 
126
126
  connection.notes.redis = redis.createClient(this.redisCfg.pubsub)
127
+ connection.notes.redis.on('error', (err) => {
128
+ connection.logerror(this, err.message)
129
+ })
127
130
  await connection.notes.redis.connect()
128
131
 
129
132
  const pattern = this.get_redis_sub_channel(connection)
@@ -361,8 +364,8 @@ exports.tarpit_delay = function (score, connection, hook, k) {
361
364
 
362
365
  // detect roaming users based on MSA ports that require auth
363
366
  if (
364
- utils.in_array(connection.local.port, [587, 465]) &&
365
- utils.in_array(hook, ['ehlo', 'connect'])
367
+ [587, 465].includes(connection.local.port) &&
368
+ ['ehlo', 'connect'].includes(hook)
366
369
  ) {
367
370
  return this.tarpit_delay_msa(connection, delay, k)
368
371
  }
@@ -670,6 +673,19 @@ exports.hook_data_post = function (next, connection) {
670
673
 
671
674
  if (this.should_we_skip(connection)) return next()
672
675
 
676
+ /*
677
+ This should not be a default due to highly probability of false positives,
678
+ but I've found it extremely effective against a recent (most of 2024) spam
679
+ campaign that Gmail apparently has no interest in stopping.
680
+ if (connection.transaction.header.get_decoded('subject').match(/\p{Emoji}/gu)) {
681
+ connection.results.add(this, { msg: 'subject_contains_emoji' })
682
+ if (connection.transaction.mail_from.host === 'gmail.com') {
683
+ connection.results.incr(this, { score: -10 })
684
+ connection.results.add(this, { msg: 'emoji_from_gmail' })
685
+ }
686
+ }
687
+ */
688
+
673
689
  this.check_awards(connection) // update awards
674
690
 
675
691
  const results = connection.results.collate(this)
package/package.json CHANGED
@@ -1,20 +1,19 @@
1
1
  {
2
2
  "name": "haraka-plugin-karma",
3
- "version": "2.1.5",
3
+ "version": "2.1.7",
4
4
  "description": "A heuristics scoring and reputation engine for SMTP connections",
5
5
  "main": "index.js",
6
6
  "files": [
7
7
  "CHANGELOG.md",
8
- "config",
9
- "test"
8
+ "config"
10
9
  ],
11
10
  "scripts": {
12
11
  "format": "npm run prettier:fix && npm run lint:fix",
13
- "lint": "npx eslint@^8 *.js test",
14
- "lint:fix": "npx eslint@^8 *.js test --fix",
12
+ "lint": "npx eslint@^9 *.js test",
13
+ "lint:fix": "npx eslint@^9 *.js test --fix",
15
14
  "prettier": "npx prettier . --check",
16
15
  "prettier:fix": "npx prettier . --write --log-level=warn",
17
- "test": "npx mocha@^10",
16
+ "test": "npx mocha@^11",
18
17
  "versions": "npx dependency-version-checker check",
19
18
  "versions:fix": "npx dependency-version-checker update"
20
19
  },
@@ -39,7 +38,11 @@
39
38
  "redis": "^4.6.13"
40
39
  },
41
40
  "devDependencies": {
42
- "@haraka/eslint-config": "^1.1.2",
41
+ "@haraka/eslint-config": "^2.0.2",
43
42
  "haraka-test-fixtures": "^1.3.4"
43
+ },
44
+ "prettier": {
45
+ "singleQuote": true,
46
+ "semi": false
44
47
  }
45
48
  }
package/test/karma.js DELETED
@@ -1,913 +0,0 @@
1
- 'use strict'
2
-
3
- const assert = require('assert')
4
-
5
- const Address = require('address-rfc2821').Address
6
- const fixtures = require('haraka-test-fixtures')
7
- const constants = require('haraka-constants')
8
-
9
- const stub = fixtures.stub.stub
10
-
11
- function _set_up(done) {
12
- this.plugin = new fixtures.plugin('karma')
13
-
14
- this.plugin.cfg = { main: {} }
15
- this.plugin.deny_hooks = { connect: true }
16
- this.plugin.tarpit_hooks = ['connect']
17
-
18
- this.connection = fixtures.connection.createConnection({}, { notes: {} })
19
- this.connection.init_transaction()
20
-
21
- done()
22
- }
23
-
24
- describe('karma_init', function () {
25
- beforeEach(function (done) {
26
- this.plugin = new fixtures.plugin('karma')
27
- done()
28
- })
29
-
30
- it('load_karma_ini', function (done) {
31
- this.plugin.inherits('haraka-plugin-redis')
32
- this.plugin.load_karma_ini()
33
- assert.ok(this.plugin.cfg.asn)
34
- assert.ok(this.plugin.deny_hooks)
35
- done()
36
- })
37
- })
38
-
39
- describe('results_init', function () {
40
- beforeEach(_set_up)
41
-
42
- it('init, pre', function (done) {
43
- const r = this.connection.results.get('karma')
44
- assert.equal(undefined, r)
45
- done()
46
- })
47
-
48
- it('init, empty cfg', function (done) {
49
- this.plugin.results_init(stub, this.connection)
50
- const r = this.connection.results.get('karma')
51
- assert.ok(r)
52
- done()
53
- })
54
-
55
- it('init, cfg', function (done) {
56
- this.plugin.cfg.awards = { test: 1 }
57
- this.plugin.results_init(stub, this.connection)
58
- const r = this.connection.results.get('karma')
59
- assert.ok(r)
60
- assert.ok(r.todo)
61
- done()
62
- })
63
-
64
- it('init, skip', function (done) {
65
- this.connection.remote.is_private = true
66
- this.plugin.results_init(stub, this.connection)
67
- const r = this.connection.results.get('karma')
68
- assert.equal(undefined, r)
69
- done()
70
- })
71
-
72
- it('init, private skip', function (done) {
73
- this.connection.notes.disable_karma = true
74
- this.plugin.results_init(stub, this.connection)
75
- const r = this.connection.results.get('karma')
76
- assert.equal(undefined, r)
77
- done()
78
- })
79
- })
80
-
81
- describe('assemble_note_obj', function () {
82
- beforeEach(_set_up)
83
-
84
- it('no auth fails', function (done) {
85
- const obj = this.plugin.assemble_note_obj(
86
- this.connection,
87
- 'notes.auth_fails',
88
- )
89
- assert.equal(undefined, obj)
90
- done()
91
- })
92
-
93
- it('has auth fails', function (done) {
94
- this.connection.notes.auth_fails = [1, 2]
95
- const obj = this.plugin.assemble_note_obj(
96
- this.connection,
97
- 'notes.auth_fails',
98
- )
99
- assert.deepEqual([1, 2], obj)
100
- done()
101
- })
102
- })
103
-
104
- describe('hook_deny', function () {
105
- beforeEach(_set_up)
106
-
107
- it('no params', function (done) {
108
- const next = function (rc) {
109
- assert.equal(constants.OK, rc, rc)
110
- done()
111
- }
112
- this.plugin.hook_deny(next, this.connection, ['', '', '', ''])
113
- })
114
-
115
- it('pi_name=karma', function (done) {
116
- const next = function (rc) {
117
- assert.equal(undefined, rc)
118
- done()
119
- }
120
- this.plugin.hook_deny(next, this.connection, ['', '', 'karma', ''])
121
- })
122
-
123
- it('pi_name=access', function (done) {
124
- const next = function (rc) {
125
- assert.equal(undefined, rc)
126
- done()
127
- }
128
- this.plugin.deny_exclude_plugins = { access: true }
129
- this.plugin.hook_deny(next, this.connection, ['', '', 'access', ''])
130
- })
131
-
132
- it('pi_hook=rcpt_to', function (done) {
133
- const next = function (rc) {
134
- assert.equal(undefined, rc)
135
- done()
136
- }
137
- this.plugin.deny_exclude_hooks = { rcpt_to: true }
138
- this.plugin.hook_deny(next, this.connection, [
139
- '',
140
- '',
141
- '',
142
- '',
143
- '',
144
- 'rcpt_to',
145
- ])
146
- })
147
-
148
- it('pi_hook=queue', function (done) {
149
- const next = function (rc) {
150
- assert.equal(undefined, rc)
151
- done()
152
- }
153
- this.plugin.deny_exclude_hooks = { queue: true }
154
- this.plugin.hook_deny(next, this.connection, ['', '', '', '', '', 'queue'])
155
- })
156
-
157
- it('denysoft', function (done) {
158
- const next = function (rc) {
159
- assert.equal(constants.OK, rc)
160
- done()
161
- }
162
- this.plugin.hook_deny(next, this.connection, [
163
- constants.DENYSOFT,
164
- '',
165
- '',
166
- '',
167
- '',
168
- '',
169
- ])
170
- })
171
- })
172
-
173
- describe('get_award_location', function () {
174
- beforeEach(_set_up)
175
-
176
- it('relaying=false', function (done) {
177
- this.connection.relaying = false
178
- const r = this.plugin.get_award_location(this.connection, 'relaying')
179
- assert.equal(false, r)
180
- done()
181
- })
182
-
183
- it('relaying=true', function (done) {
184
- this.connection.relaying = true
185
- const r = this.plugin.get_award_location(this.connection, 'relaying')
186
- assert.equal(true, r)
187
- done()
188
- })
189
-
190
- it('notes.undef=2', function (done) {
191
- const r = this.plugin.get_award_location(this.connection, 'notes.undef')
192
- assert.equal(undefined, r)
193
- done()
194
- })
195
-
196
- it('notes.tarpit=2', function (done) {
197
- this.connection.notes = { tarpit: 2 }
198
- const r = this.plugin.get_award_location(this.connection, 'notes.tarpit')
199
- assert.equal(2, r)
200
- done()
201
- })
202
-
203
- it('results.geoip', function (done) {
204
- this.connection.results.add('geoip', { country: 'US' })
205
- const r = this.plugin.get_award_location(this.connection, 'results.geoip')
206
- // console.log(r);
207
- assert.equal('US', r.country)
208
- done()
209
- })
210
-
211
- it('results.karma', function (done) {
212
- this.connection.results.add('karma', { score: -1 })
213
- const r = this.plugin.get_award_location(this.connection, 'results.karma')
214
- // console.log(r);
215
- assert.equal(-1, r.score)
216
- done()
217
- })
218
-
219
- it('results.karma, txn', function (done) {
220
- // results should be found in conn or txn
221
- this.connection.transaction.results.add('karma', { score: -1 })
222
- const r = this.plugin.get_award_location(this.connection, 'results.karma')
223
- // console.log(r);
224
- assert.equal(-1, r.score)
225
- done()
226
- })
227
-
228
- it('txn.results.karma', function (done) {
229
- // these results shouldn't be found, b/c txn specified
230
- this.connection.results.add('karma', { score: -1 })
231
- const r = this.plugin.get_award_location(
232
- this.connection,
233
- 'transaction.results.karma',
234
- )
235
- // console.log(r);
236
- assert.equal(undefined, r)
237
- done()
238
- })
239
-
240
- it('results.auth/auth_base', function (done) {
241
- this.connection.results.add('auth/auth_base', { fail: 'PLAIN' })
242
- const r = this.plugin.get_award_location(
243
- this.connection,
244
- 'results.auth/auth_base',
245
- )
246
- assert.equal('PLAIN', r.fail[0])
247
- done()
248
- })
249
- })
250
-
251
- describe('get_award_condition', function () {
252
- beforeEach(_set_up)
253
- it('geoip.distance', function (done) {
254
- assert.equal(
255
- 4000,
256
- this.plugin.get_award_condition(
257
- 'results.geoip.distance@4000',
258
- '-1 if gt',
259
- ),
260
- )
261
- assert.equal(
262
- 4000,
263
- this.plugin.get_award_condition(
264
- 'results.geoip.distance@uniq',
265
- '-1 if gt 4000',
266
- ),
267
- )
268
- done()
269
- })
270
-
271
- it('auth/auth_base', function (done) {
272
- assert.equal(
273
- 'plain',
274
- this.plugin.get_award_condition(
275
- 'results.auth/auth_base.fail@plain',
276
- '-1 if in',
277
- ),
278
- )
279
- done()
280
- })
281
- })
282
-
283
- describe('check_awards', function () {
284
- beforeEach(_set_up)
285
-
286
- it('no results', function (done) {
287
- const r = this.plugin.check_awards(this.connection)
288
- assert.equal(undefined, r)
289
- done()
290
- })
291
-
292
- it('no todo', function (done) {
293
- this.connection.results.add('karma', { todo: {} })
294
- const r = this.plugin.check_awards(this.connection)
295
- assert.equal(undefined, r)
296
- done()
297
- })
298
-
299
- it('geoip gt', function (done) {
300
- // populate the karma result with a todo item
301
- this.connection.results.add('karma', {
302
- todo: { 'results.geoip.distance@4000': '-1 if gt 4000' },
303
- })
304
- // test a non-matching criteria
305
- this.connection.results.add('geoip', { distance: 4000 })
306
- // check awards
307
- this.plugin.check_awards(this.connection)
308
- assert.equal(undefined, this.connection.results.get('karma').fail[0])
309
-
310
- // test a matching criteria
311
- this.connection.results.add('geoip', { distance: 4001 })
312
- // check awards
313
- this.plugin.check_awards(this.connection)
314
- // test that the award was applied
315
- assert.equal('geoip.distance', this.connection.results.get('karma').fail[0])
316
-
317
- done()
318
- })
319
-
320
- it('auth failure', function (done) {
321
- this.connection.results.add('karma', {
322
- todo: { 'results.auth/auth_base.fail@PLAIN': '-1 if in' },
323
- })
324
- this.connection.results.add('auth/auth_base', { fail: 'PLAIN' })
325
- const r = this.plugin.check_awards(this.connection)
326
- assert.equal(undefined, r)
327
- assert.equal(
328
- 'auth/auth_base.fail',
329
- this.connection.results.get('karma').fail[0],
330
- )
331
- done()
332
- })
333
-
334
- it('valid recipient', function (done) {
335
- this.connection.results.add('karma', {
336
- todo: { 'results.rcpt_to.qmd.pass@exist': '1 if in' },
337
- })
338
- this.connection.results.add('rcpt_to.qmd', { pass: 'exist' })
339
- const r = this.plugin.check_awards(this.connection)
340
- assert.equal(undefined, r)
341
- assert.equal('qmd.pass', this.connection.results.get('karma').pass[0])
342
- done()
343
- })
344
- })
345
-
346
- describe('apply_tarpit', function () {
347
- beforeEach(_set_up)
348
-
349
- it('tarpit=false', function (done) {
350
- const next = function (rc, msg) {
351
- assert.equal(undefined, rc)
352
- assert.equal(undefined, msg)
353
- done()
354
- }
355
- this.plugin.apply_tarpit(this.connection, 'connect', 0, next)
356
- })
357
-
358
- it('tarpit=true, score=0', function (done) {
359
- const next = function (rc, msg) {
360
- assert.equal(undefined, rc)
361
- assert.equal(undefined, msg)
362
- done()
363
- }
364
- this.plugin.cfg.tarpit = { max: 1, delay: 0 }
365
- this.plugin.apply_tarpit(this.connection, 'connect', 0, next)
366
- })
367
-
368
- it('tarpit=true, score=1', function (done) {
369
- const next = function (rc, msg) {
370
- assert.equal(undefined, rc)
371
- assert.equal(undefined, msg)
372
- done()
373
- }
374
- this.plugin.cfg.tarpit = { max: 1, delay: 0 }
375
- this.plugin.apply_tarpit(this.connection, 'connect', 1, next)
376
- })
377
-
378
- it('tarpit=true, score=-1', function (done) {
379
- const before = Date.now()
380
- const next = function (rc, msg) {
381
- assert.ok(Date.now() >= before + 1)
382
- assert.equal(undefined, rc)
383
- assert.equal(undefined, msg)
384
- done()
385
- }
386
- this.plugin.cfg.tarpit = { max: 1, delay: 0 }
387
- this.plugin.apply_tarpit(this.connection, 'connect', -1, next)
388
- })
389
-
390
- it('tarpit=true, score=-2, max=1', function (done) {
391
- const before = Date.now()
392
- const next = function (rc, msg) {
393
- assert.ok(Date.now() >= before + 1)
394
- assert.equal(undefined, rc)
395
- assert.equal(undefined, msg)
396
- done()
397
- }
398
- this.plugin.cfg.tarpit = { max: 1, delay: 0 }
399
- this.plugin.apply_tarpit(this.connection, 'connect', -2, next)
400
- })
401
-
402
- it('tarpit=true, score=connect, max=1', function (done) {
403
- const before = Date.now()
404
- const next = function (rc, msg) {
405
- assert.ok(Date.now() >= before + 1)
406
- assert.equal(undefined, rc)
407
- assert.equal(undefined, msg)
408
- done()
409
- }
410
- this.plugin.cfg.tarpit = { max: 1, delay: 0 }
411
- this.connection.results.add(this.plugin, { score: -2 })
412
- this.plugin.apply_tarpit(this.connection, 'connect', -2, next)
413
- })
414
- })
415
-
416
- describe('should_we_deny', function () {
417
- beforeEach(_set_up)
418
-
419
- it('no results', function (done) {
420
- const next = function (rc, msg) {
421
- assert.equal(undefined, rc)
422
- assert.equal(undefined, msg)
423
- done()
424
- }
425
- this.plugin.should_we_deny(next, this.connection, 'connect')
426
- })
427
-
428
- it('no score', function (done) {
429
- const next = function (rc, msg) {
430
- assert.equal(undefined, rc)
431
- assert.equal(undefined, msg)
432
- done()
433
- }
434
- this.connection.results.add(this.plugin, { test: 'blah' })
435
- this.plugin.should_we_deny(next, this.connection, 'connect')
436
- })
437
-
438
- it('invalid score', function (done) {
439
- const next = function (rc, msg) {
440
- assert.equal(undefined, rc)
441
- assert.equal(undefined, msg)
442
- done()
443
- }
444
- this.connection.results.add(this.plugin, { score: 'blah' })
445
- this.plugin.should_we_deny(next, this.connection, 'connect')
446
- })
447
-
448
- it('valid score, okay', function (done) {
449
- const next = function (rc, msg) {
450
- assert.equal(undefined, rc)
451
- assert.equal(undefined, msg)
452
- done()
453
- }.bind(this)
454
- this.plugin.cfg.tarpit = { max: 1, delay: 0 }
455
- this.connection.results.add(this.plugin, { score: -1 })
456
- this.plugin.should_we_deny(next, this.connection, 'connect')
457
- })
458
-
459
- it('valid score, -6, deny_hook', function (done) {
460
- const next = function (rc, msg) {
461
- assert.equal(constants.DENY, rc)
462
- assert.ok(msg)
463
- done()
464
- }.bind(this)
465
- this.plugin.cfg.tarpit = { max: 1, delay: 0 }
466
- this.plugin.deny_hooks = { connect: true }
467
- this.connection.results.add(this.plugin, { score: -6 })
468
- this.plugin.should_we_deny(next, this.connection, 'connect')
469
- })
470
-
471
- it('valid score, -6, pass_hook', function (done) {
472
- const next = function (rc, msg) {
473
- assert.equal(undefined, rc)
474
- assert.equal(undefined, msg)
475
- done()
476
- }.bind(this)
477
- this.plugin.cfg.tarpit = { max: 1, delay: 0 }
478
- this.plugin.deny_hooks = { helo: true }
479
- this.connection.results.add(this.plugin, { score: -6 })
480
- this.plugin.should_we_deny(next, this.connection, 'connect')
481
- })
482
- })
483
-
484
- describe('check_result_equal', function () {
485
- beforeEach(_set_up)
486
-
487
- it('equal match is scored', function (done) {
488
- const award = {
489
- id: 1,
490
- award: 2,
491
- operator: 'equals',
492
- value: 'clean',
493
- reason: 'testing',
494
- resolution: 'never',
495
- }
496
- this.plugin.check_result_equal(['clean'], award, this.connection)
497
- assert.equal(this.connection.results.store.karma.score, 2)
498
- assert.equal(this.connection.results.store.karma.awards[0], 1)
499
- done()
500
- })
501
-
502
- it('not equal match is not scored', function (done) {
503
- const award = {
504
- id: 1,
505
- award: 2,
506
- operator: 'equals',
507
- value: 'dirty',
508
- reason: 'testing',
509
- resolution: 'never',
510
- }
511
- this.plugin.check_result_equal(['clean'], award, this.connection)
512
- assert.equal(this.connection.results.store.karma, undefined)
513
- done()
514
- })
515
- })
516
-
517
- describe('check_result_gt', function () {
518
- beforeEach(_set_up)
519
-
520
- it('gt match is scored', function (done) {
521
- const award = {
522
- id: 5,
523
- award: 3,
524
- operator: 'gt',
525
- value: 3,
526
- reason: 'testing',
527
- resolution: 'never',
528
- }
529
- this.plugin.check_result_gt([4], award, this.connection)
530
- // console.log(this.connection.results.store);
531
- assert.equal(this.connection.results.store.karma.score, 3)
532
- assert.equal(this.connection.results.store.karma.awards[0], 5)
533
- done()
534
- })
535
- })
536
-
537
- describe('check_result_lt', function () {
538
- beforeEach(_set_up)
539
-
540
- it('lt match is scored', function (done) {
541
- const award = {
542
- id: 2,
543
- award: 3,
544
- operator: 'lt',
545
- value: 5,
546
- reason: 'testing',
547
- resolution: 'never',
548
- }
549
- this.plugin.check_result_lt([4], award, this.connection)
550
- // console.log(this.connection.results.store);
551
- assert.equal(this.connection.results.store.karma.score, 3)
552
- assert.equal(this.connection.results.store.karma.awards[0], 2)
553
- done()
554
- })
555
-
556
- it('lt match not scored', function (done) {
557
- const award = {
558
- id: 3,
559
- award: 3,
560
- operator: 'lt',
561
- value: 3,
562
- reason: 'testing',
563
- resolution: 'never',
564
- }
565
- this.plugin.check_result_lt([4], award, this.connection)
566
- // console.log(this.connection.results.store);
567
- assert.equal(this.connection.results.store.karma, undefined)
568
- done()
569
- })
570
- })
571
-
572
- describe('check_result_match', function () {
573
- beforeEach(_set_up)
574
-
575
- it('match pattern is scored', function (done) {
576
- const award = {
577
- id: 1,
578
- award: 2,
579
- operator: 'match',
580
- value: 'phish',
581
- reason: 'testing',
582
- resolution: 'never',
583
- }
584
- this.plugin.check_result_match(['isphishing'], award, this.connection)
585
- // console.log(this.connection.results.store);
586
- assert.equal(this.connection.results.store.karma.score, 2)
587
- assert.equal(this.connection.results.store.karma.awards[0], 1)
588
- done()
589
- })
590
-
591
- it('mismatch is not scored', function (done) {
592
- const award = {
593
- id: 1,
594
- award: 2,
595
- operator: 'match',
596
- value: 'dirty',
597
- reason: 'testing',
598
- resolution: 'never',
599
- }
600
- this.plugin.check_result_match(['clean'], award, this.connection)
601
- // console.log(this.connection.results.store);
602
- assert.equal(this.connection.results.store.karma, undefined)
603
- done()
604
- })
605
-
606
- it('FCrDNS match is scored', function (done) {
607
- const award = {
608
- id: 89,
609
- award: 2,
610
- operator: 'match',
611
- value: 'google.com',
612
- reason: 'testing',
613
- resolution: 'never',
614
- }
615
- this.plugin.check_result_match(
616
- ['mail-yk0-f182.google.com'],
617
- award,
618
- this.connection,
619
- )
620
- // console.log(this.connection.results.store);
621
- assert.equal(this.connection.results.store.karma.score, 2)
622
- assert.equal(this.connection.results.store.karma.awards[0], 89)
623
- done()
624
- })
625
- })
626
-
627
- describe('check_result_length', function () {
628
- beforeEach(_set_up)
629
- it('eq pattern is scored', function (done) {
630
- const award = {
631
- id: 1,
632
- award: 2,
633
- operator: 'length',
634
- value: 'eq 3',
635
- reason: 'testing',
636
- resolution: 'hah',
637
- }
638
- this.plugin.check_result_length(['3'], award, this.connection)
639
- // console.log(this.connection.results.store);
640
- assert.equal(this.connection.results.store.karma.score, 2)
641
- assert.equal(this.connection.results.store.karma.awards[0], 1)
642
- done()
643
- })
644
-
645
- it('eq pattern is not scored', function (done) {
646
- const award = {
647
- id: 1,
648
- award: 2,
649
- operator: 'length',
650
- value: 'eq 3',
651
- reason: 'testing',
652
- resolution: 'hah',
653
- }
654
- this.plugin.check_result_length(['4'], award, this.connection)
655
- // console.log(this.connection.results.store.karma);
656
- assert.deepEqual(this.connection.results.store.karma, undefined)
657
- done()
658
- })
659
-
660
- it('gt pattern is scored', function (done) {
661
- const award = {
662
- id: 1,
663
- award: 2,
664
- operator: 'length',
665
- value: 'gt 3',
666
- reason: 'testing',
667
- resolution: 'hah',
668
- }
669
- this.plugin.check_result_length(['5'], award, this.connection)
670
- // console.log(this.connection.results.store);
671
- assert.equal(this.connection.results.store.karma.score, 2)
672
- assert.equal(this.connection.results.store.karma.awards[0], 1)
673
- done()
674
- })
675
-
676
- it('gt pattern is not scored', function (done) {
677
- const award = {
678
- id: 1,
679
- award: 2,
680
- operator: 'length',
681
- value: 'gt 3',
682
- reason: 'testing',
683
- resolution: 'hah',
684
- }
685
- this.plugin.check_result_length(['3'], award, this.connection)
686
- // console.log(this.connection.results.store.karma);
687
- assert.deepEqual(this.connection.results.store.karma, undefined)
688
- done()
689
- })
690
-
691
- it('lt pattern is scored', function (done) {
692
- const award = {
693
- id: 1,
694
- award: 2,
695
- operator: 'length',
696
- value: 'lt 3',
697
- reason: 'testing',
698
- resolution: 'hah',
699
- }
700
- this.plugin.check_result_length(['2'], award, this.connection)
701
- // console.log(this.connection.results.store);
702
- assert.equal(this.connection.results.store.karma.score, 2)
703
- assert.equal(this.connection.results.store.karma.awards[0], 1)
704
- done()
705
- })
706
-
707
- it('lt pattern is not scored', function (done) {
708
- const award = {
709
- id: 1,
710
- award: 2,
711
- operator: 'length',
712
- value: 'lt 3',
713
- reason: 'testing',
714
- resolution: 'hah',
715
- }
716
- this.plugin.check_result_length(['3'], award, this.connection)
717
- // console.log(this.connection.results.store.karma);
718
- assert.deepEqual(this.connection.results.store.karma, undefined)
719
- done()
720
- })
721
- })
722
-
723
- describe('check_result_exists', function () {
724
- beforeEach(_set_up)
725
-
726
- it('exists pattern is scored', function (done) {
727
- const award = {
728
- id: 1,
729
- award: 2,
730
- operator: 'exists',
731
- value: 'any',
732
- reason: 'testing',
733
- resolution: 'high five',
734
- }
735
- this.plugin.check_result_exists(['3'], award, this.connection)
736
- // console.log(this.connection.results.store);
737
- assert.equal(this.connection.results.store.karma.score, 2)
738
- assert.equal(this.connection.results.store.karma.awards[0], 1)
739
- done()
740
- })
741
-
742
- it('not exists pattern is not scored', function (done) {
743
- const award = {
744
- id: 1,
745
- award: 3,
746
- operator: 'exists',
747
- value: '',
748
- reason: 'testing',
749
- resolution: 'misses',
750
- }
751
- this.plugin.check_result_exists([], award, this.connection)
752
- // console.log(this.connection.results.store);
753
- assert.equal(this.connection.results.store.karma, undefined)
754
- assert.equal(this.connection.results.store.karma, undefined)
755
- done()
756
- })
757
- })
758
-
759
- describe('check_result', function () {
760
- beforeEach(_set_up)
761
-
762
- it('geoip country is scored', function (done) {
763
- this.plugin.cfg.result_awards = {
764
- 1: 'geoip | country | equals | CN | 2',
765
- }
766
- this.plugin.preparse_result_awards()
767
- this.connection.results.add({ name: 'geoip' }, { country: 'CN' })
768
- this.plugin.check_result(
769
- this.connection,
770
- '{"plugin":"geoip","result":{"country":"CN"}}',
771
- )
772
- // console.log(this.connection.results.store);
773
- assert.equal(this.connection.results.store.karma.score, 2)
774
- assert.equal(this.connection.results.store.karma.awards[0], 1)
775
- done()
776
- })
777
-
778
- it('dnsbl listing is scored', function (done) {
779
- this.plugin.cfg.result_awards = {
780
- 2: 'dnsbl | fail | equals | dnsbl.sorbs.net | -5',
781
- }
782
- this.plugin.preparse_result_awards()
783
- this.connection.results.add({ name: 'dnsbl' }, { fail: 'dnsbl.sorbs.net' })
784
- this.plugin.check_result(
785
- this.connection,
786
- '{"plugin":"dnsbl","result":{"fail":"dnsbl.sorbs.net"}}',
787
- )
788
- // console.log(this.connection.results.store);
789
- assert.equal(this.connection.results.store.karma.score, -5)
790
- assert.equal(this.connection.results.store.karma.awards[0], 2)
791
- done()
792
- })
793
- })
794
-
795
- describe('check_spammy_tld', function () {
796
- beforeEach(_set_up)
797
-
798
- it('spammy TLD is scored: top', function (done) {
799
- this.plugin.cfg.spammy_tlds = { top: -3 }
800
- const mfrom = new Address('spamy@er7diogt.rrnsale.top')
801
- this.plugin.check_spammy_tld(mfrom, this.connection)
802
- // console.log(this.connection.results.store);
803
- assert.equal(this.connection.results.store.karma.score, -3)
804
- assert.equal(this.connection.results.store.karma.fail[0], 'spammy.TLD')
805
- done()
806
- })
807
-
808
- it('spammy TLD is scored: rocks', function (done) {
809
- this.plugin.cfg.spammy_tlds = { rocks: '-2' }
810
- const mfrom = new Address('spamy@foo.rocks')
811
- this.plugin.check_spammy_tld(mfrom, this.connection)
812
- // console.log(this.connection.results.store);
813
- assert.equal(this.connection.results.store.karma.score, -2)
814
- assert.equal(this.connection.results.store.karma.fail[0], 'spammy.TLD')
815
- done()
816
- })
817
- })
818
-
819
- describe('tls', function () {
820
- beforeEach(_set_up)
821
-
822
- it('unconfigured TLS does nothing', function (done) {
823
- this.connection.tls.enabled = true
824
- const mfrom = new Address('spamy@er7diogt.rrnsale.top')
825
- this.connection.current_line = 'MAIL FROM:<foo@test.com>'
826
- this.plugin.hook_mail(
827
- () => {
828
- assert.equal(this.connection.results.store.karma, undefined)
829
- done()
830
- },
831
- this.connection,
832
- [mfrom],
833
- )
834
- })
835
-
836
- it('TLS is scored', function (done) {
837
- this.plugin.cfg.tls = { set: 2, unset: -4 }
838
- this.connection.tls.enabled = true
839
- const mfrom = new Address('spamy@er7diogt.rrnsale.top')
840
- this.connection.current_line = 'MAIL FROM:<foo@test.com>'
841
- this.plugin.hook_mail(
842
- () => {
843
- // console.log(this.connection.results.store);
844
- assert.equal(this.connection.results.store.karma.score, 2)
845
- done()
846
- },
847
- this.connection,
848
- [mfrom],
849
- )
850
- })
851
-
852
- it('no TLS is scored', function (done) {
853
- this.plugin.cfg.tls = { set: 2, unset: -4 }
854
- this.connection.tls.enabled = false
855
- const mfrom = new Address('spamy@er7diogt.rrnsale.top')
856
- this.connection.current_line = 'MAIL FROM:<foo@test.com>'
857
- this.plugin.hook_mail(
858
- () => {
859
- // console.log(this.connection.results.store);
860
- assert.equal(this.connection.results.store.karma.score, -4)
861
- done()
862
- },
863
- this.connection,
864
- [mfrom],
865
- )
866
- })
867
- })
868
-
869
- describe('skipping hooks', function () {
870
- beforeEach(_set_up)
871
-
872
- it('notes.disable_karma', function (done) {
873
- function next(rc) {
874
- assert.equal(undefined, rc)
875
- }
876
- function last(rc) {
877
- assert.equal(undefined, rc)
878
- done()
879
- }
880
- this.connection.notes.disable_karma = true
881
-
882
- this.plugin.hook_deny(next, this.connection)
883
- this.plugin.hook_connect(next, this.connection)
884
- this.plugin.hook_ehlo(next, this.connection)
885
- this.plugin.hook_vrfy(next, this.connection)
886
- this.plugin.hook_noop(next, this.connection)
887
- this.plugin.hook_data(next, this.connection)
888
- this.plugin.hook_queue(next, this.connection)
889
- this.plugin.hook_reset_transaction(next, this.connection)
890
- this.plugin.hook_unrecognized_command(last, this.connection)
891
- })
892
-
893
- it('private skip', function (done) {
894
- function next(rc) {
895
- assert.equal(undefined, rc)
896
- }
897
- function last(rc) {
898
- assert.equal(undefined, rc)
899
- done()
900
- }
901
- this.connection.remote.is_private = true
902
-
903
- this.plugin.hook_deny(next, this.connection)
904
- this.plugin.hook_connect(next, this.connection)
905
- this.plugin.hook_ehlo(next, this.connection)
906
- this.plugin.hook_vrfy(next, this.connection)
907
- this.plugin.hook_noop(next, this.connection)
908
- this.plugin.hook_data(next, this.connection)
909
- this.plugin.hook_queue(next, this.connection)
910
- this.plugin.hook_reset_transaction(next, this.connection)
911
- this.plugin.hook_unrecognized_command(last, this.connection)
912
- })
913
- })