Haraka 2.8.28 → 3.0.1
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/.eslintrc.yaml +2 -10
- package/Changes.md +84 -2
- package/Dockerfile +1 -1
- package/Plugins.md +9 -4
- package/README.md +2 -6
- package/bin/haraka +5 -4
- package/config/outbound.ini +0 -7
- package/config/plugins +1 -1
- package/config/smtp.ini +1 -1
- package/config/smtp_forward.ini +2 -8
- package/config/smtp_proxy.ini +0 -6
- package/connection.js +178 -204
- package/coverage/lcov.info +13863 -0
- package/coverage/tmp/coverage-42958-1658373250585-0.json +1 -0
- package/coverage/tmp/coverage-42961-1658373250529-0.json +1 -0
- package/dkim.js +66 -73
- package/docs/Body.md +1 -22
- package/docs/CoreConfig.md +2 -2
- package/docs/Header.md +1 -47
- package/docs/Outbound.md +8 -36
- package/endpoint.js +1 -1
- package/haraka.js +1 -1
- package/host_pool.js +8 -12
- package/logger.js +25 -32
- package/outbound/client_pool.js +11 -153
- package/outbound/config.js +5 -11
- package/outbound/hmail.js +109 -143
- package/outbound/index.js +13 -25
- package/outbound/mx_lookup.js +10 -7
- package/outbound/queue.js +8 -12
- package/outbound/timer_queue.js +2 -4
- package/outbound/tls.js +17 -18
- package/outbound/todo.js +1 -0
- package/package.json +57 -55
- package/plugins/auth/auth_base.js +39 -63
- package/plugins/auth/auth_bridge.js +3 -4
- package/plugins/auth/auth_proxy.js +16 -16
- package/plugins/auth/auth_vpopmaild.js +30 -37
- package/plugins/auth/flat_file.js +9 -13
- package/plugins/avg.js +9 -11
- package/plugins/backscatterer.js +1 -1
- package/plugins/block_me.js +2 -6
- package/plugins/bounce.js +106 -124
- package/plugins/clamd.js +59 -63
- package/plugins/data.signatures.js +6 -6
- package/plugins/data.uribl.js +1 -415
- package/plugins/delay_deny.js +19 -20
- package/plugins/dkim_sign.js +56 -62
- package/plugins/dkim_verify.js +9 -8
- package/plugins/dns_list_base.js +43 -42
- package/plugins/dnsbl.js +41 -46
- package/plugins/dnswl.js +23 -26
- package/plugins/early_talker.js +24 -28
- package/plugins/esets.js +8 -11
- package/plugins/greylist.js +161 -190
- package/plugins/helo.checks.js +175 -197
- package/plugins/mail_from.is_resolvable.js +38 -38
- package/plugins/messagesniffer.js +33 -40
- package/plugins/prevent_credential_leaks.js +7 -5
- package/plugins/process_title.js +16 -17
- package/plugins/queue/deliver.js +2 -2
- package/plugins/queue/lmtp.js +5 -6
- package/plugins/queue/qmail-queue.js +11 -13
- package/plugins/queue/quarantine.js +25 -34
- package/plugins/queue/rabbitmq.js +3 -2
- package/plugins/queue/rabbitmq_amqplib.js +9 -9
- package/plugins/queue/smtp_bridge.js +5 -4
- package/plugins/queue/smtp_forward.js +81 -89
- package/plugins/queue/smtp_proxy.js +21 -22
- package/plugins/queue/test.js +2 -1
- package/plugins/rcpt_to.host_list_base.js +20 -30
- package/plugins/rcpt_to.in_host_list.js +12 -14
- package/plugins/rcpt_to.max_count.js +7 -5
- package/plugins/record_envelope_addresses.js +4 -6
- package/plugins/relay.js +64 -74
- package/plugins/reseed_rng.js +1 -2
- package/plugins/spamassassin.js +56 -68
- package/plugins/status.js +2 -3
- package/plugins/tarpit.js +8 -11
- package/plugins/tls.js +14 -17
- package/plugins/toobusy.js +6 -8
- package/plugins/xclient.js +14 -25
- package/plugins.js +24 -29
- package/rfc1869.js +2 -2
- package/server.js +3 -13
- package/smtp_client.js +138 -215
- package/tests/config/smtp_forward.ini +0 -6
- package/tests/fixtures/line_socket.js +1 -1
- package/tests/fixtures/util_hmailitem.js +5 -7
- package/tests/fixtures/vm_harness.js +2 -2
- package/tests/host_pool.js +13 -14
- package/tests/installation/plugins/inherits.js +1 -2
- package/tests/logger.js +2 -2
- package/tests/plugins/bounce.js +6 -8
- package/tests/plugins/dkim_signer.js +7 -7
- package/tests/plugins/dns_list_base.js +7 -7
- package/tests/plugins/helo.checks.js +1 -1
- package/tests/plugins/mail_from.is_resolvable.js +10 -54
- package/tests/plugins/queue/smtp_forward.js +11 -11
- package/tests/plugins/rcpt_to.host_list_base.js +1 -1
- package/tests/plugins/rcpt_to.in_host_list.js +1 -1
- package/tests/plugins/spamassassin.js +1 -1
- package/tests/queue/multibyte +0 -0
- package/tests/queue/plain +0 -0
- package/tests/rfc1869.js +4 -1
- package/tests/server.js +15 -9
- package/tests/smtp_client/auth.js +4 -14
- package/tests/smtp_client/basic.js +5 -15
- package/tests/smtp_client.js +7 -3
- package/tests/transaction.js +72 -19
- package/tls_socket.js +75 -85
- package/transaction.js +7 -9
- package/attachment_stream.js +0 -118
- package/bin/spf +0 -48
- package/chunkemitter.js +0 -75
- package/config/data.uribl.excludes +0 -202
- package/config/data.uribl.ini +0 -37
- package/config/spf.ini +0 -1
- package/docs/plugins/attachment.md +0 -92
- package/docs/plugins/data.uribl.md +0 -120
- package/docs/plugins/spf.md +0 -142
- package/mailbody.js +0 -502
- package/mailheader.js +0 -304
- package/messagestream.js +0 -441
- package/plugins/aliases.js +0 -120
- package/plugins/attachment.js +0 -503
- package/plugins/connect.p0f.js +0 -5
- package/plugins/spf.js +0 -327
- package/spf.js +0 -689
- package/tests/mailbody.js +0 -348
- package/tests/mailheader.js +0 -138
- package/tests/messagestream.js +0 -34
- package/tests/plugins/aliases.js +0 -376
- package/tests/plugins/spf.js +0 -251
- package/tests/spf.js +0 -96
package/plugins/dnsbl.js
CHANGED
|
@@ -1,85 +1,81 @@
|
|
|
1
1
|
// dnsbl plugin
|
|
2
2
|
|
|
3
3
|
exports.register = function () {
|
|
4
|
-
|
|
5
|
-
plugin.inherits('dns_list_base');
|
|
4
|
+
this.inherits('dns_list_base');
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
this.load_config();
|
|
8
7
|
|
|
9
|
-
if (
|
|
10
|
-
|
|
8
|
+
if (this.cfg.main.periodic_checks) {
|
|
9
|
+
this.check_zones(this.cfg.main.periodic_checks);
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
if (
|
|
14
|
-
|
|
12
|
+
if (this.cfg.main.search === 'all') {
|
|
13
|
+
this.register_hook('connect', 'connect_multi');
|
|
15
14
|
}
|
|
16
15
|
else {
|
|
17
|
-
|
|
16
|
+
this.register_hook('connect', 'connect_first');
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
exports.load_config = function () {
|
|
22
|
-
const plugin = this;
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
this.cfg = this.config.get('dnsbl.ini', {
|
|
25
23
|
booleans: ['+main.reject', '-main.enable_stats'],
|
|
26
24
|
}, () => {
|
|
27
|
-
|
|
25
|
+
this.load_config();
|
|
28
26
|
});
|
|
29
27
|
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
if (this.cfg.main.enable_stats && !this.enable_stats) {
|
|
29
|
+
this.loginfo('stats reporting enabled');
|
|
30
|
+
this.enable_stats = true;
|
|
33
31
|
}
|
|
34
|
-
if (!
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
if (!this.cfg.main.enable_stats && this.enable_stats) {
|
|
33
|
+
this.loginfo('stats reporting disabled');
|
|
34
|
+
this.enable_stats = false;
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
if (this.cfg.main.stats_redis_host &&
|
|
38
|
+
this.cfg.main.stats_redis_host !== this.redis_host) {
|
|
39
|
+
this.redis_host = this.cfg.main.stats_redis_host;
|
|
40
|
+
this.loginfo(`set stats redis host to: ${this.redis_host}`);
|
|
43
41
|
}
|
|
44
42
|
|
|
45
|
-
|
|
43
|
+
this.get_uniq_zones();
|
|
46
44
|
}
|
|
47
45
|
|
|
48
46
|
exports.get_uniq_zones = function () {
|
|
49
|
-
|
|
50
|
-
plugin.zones = [];
|
|
47
|
+
this.zones = [];
|
|
51
48
|
|
|
52
49
|
const unique_zones = {};
|
|
53
50
|
|
|
54
51
|
// Compatibility with old plugin
|
|
55
|
-
const legacy_zones =
|
|
56
|
-
for (
|
|
57
|
-
unique_zones[
|
|
52
|
+
const legacy_zones = this.config.get('dnsbl.zones', 'list');
|
|
53
|
+
for (const legacyZone of legacy_zones) {
|
|
54
|
+
unique_zones[legacyZone] = true;
|
|
58
55
|
}
|
|
59
56
|
|
|
60
|
-
if (
|
|
61
|
-
const new_zones =
|
|
62
|
-
for (
|
|
63
|
-
unique_zones[
|
|
57
|
+
if (this.cfg.main.zones) {
|
|
58
|
+
const new_zones = this.cfg.main.zones.split(/[\s,;]+/);
|
|
59
|
+
for (const newZone of new_zones) {
|
|
60
|
+
unique_zones[newZone] = true;
|
|
64
61
|
}
|
|
65
62
|
}
|
|
66
63
|
|
|
67
|
-
for (const key in unique_zones) {
|
|
68
|
-
return
|
|
64
|
+
for (const key in unique_zones) { this.zones.push(key); }
|
|
65
|
+
return this.zones;
|
|
69
66
|
}
|
|
70
67
|
|
|
71
68
|
exports.should_skip = function (connection) {
|
|
72
|
-
const plugin = this;
|
|
73
69
|
|
|
74
70
|
if (!connection) { return true; }
|
|
75
71
|
|
|
76
72
|
if (connection.remote.is_private) {
|
|
77
|
-
connection.logdebug(
|
|
73
|
+
connection.logdebug(this, `skip private: ${connection.remote.ip}`);
|
|
78
74
|
return true;
|
|
79
75
|
}
|
|
80
76
|
|
|
81
|
-
if (!
|
|
82
|
-
connection.logerror(
|
|
77
|
+
if (!this.zones || !this.zones.length) {
|
|
78
|
+
connection.logerror(this, "no zones");
|
|
83
79
|
return true;
|
|
84
80
|
}
|
|
85
81
|
|
|
@@ -112,21 +108,20 @@ exports.connect_first = function (next, connection) {
|
|
|
112
108
|
}
|
|
113
109
|
|
|
114
110
|
exports.connect_multi = function (next, connection) {
|
|
115
|
-
const plugin = this;
|
|
116
111
|
const remote_ip = connection.remote.ip;
|
|
117
112
|
|
|
118
|
-
if (
|
|
113
|
+
if (this.should_skip(connection)) { return next(); }
|
|
119
114
|
|
|
120
115
|
const hits = [];
|
|
121
116
|
function get_deny_msg () {
|
|
122
117
|
return `host [${remote_ip}] is blacklisted by ${hits.join(', ')}`;
|
|
123
118
|
}
|
|
124
119
|
|
|
125
|
-
|
|
120
|
+
this.multi(remote_ip, this.zones, (err, zone, a, pending) => {
|
|
126
121
|
if (err) {
|
|
127
|
-
connection.results.add(
|
|
122
|
+
connection.results.add(this, {err: err.message});
|
|
128
123
|
if (pending) return;
|
|
129
|
-
if (
|
|
124
|
+
if (this.cfg.main.reject && hits.length) {
|
|
130
125
|
return next(DENY, get_deny_msg());
|
|
131
126
|
}
|
|
132
127
|
return next();
|
|
@@ -134,16 +129,16 @@ exports.connect_multi = function (next, connection) {
|
|
|
134
129
|
|
|
135
130
|
if (a) {
|
|
136
131
|
hits.push(zone);
|
|
137
|
-
connection.results.add(
|
|
132
|
+
connection.results.add(this, {fail: zone});
|
|
138
133
|
}
|
|
139
134
|
else {
|
|
140
|
-
if (zone) connection.results.add(
|
|
135
|
+
if (zone) connection.results.add(this, {pass: zone});
|
|
141
136
|
}
|
|
142
137
|
|
|
143
138
|
if (pending) return;
|
|
144
|
-
connection.results.add(
|
|
139
|
+
connection.results.add(this, {emit: true});
|
|
145
140
|
|
|
146
|
-
if (
|
|
141
|
+
if (this.cfg.main.reject && hits.length) {
|
|
147
142
|
return next(DENY, get_deny_msg());
|
|
148
143
|
}
|
|
149
144
|
return next();
|
package/plugins/dnswl.js
CHANGED
|
@@ -2,59 +2,56 @@
|
|
|
2
2
|
// dnswl plugin
|
|
3
3
|
|
|
4
4
|
exports.register = function () {
|
|
5
|
-
|
|
6
|
-
plugin.inherits('dns_list_base');
|
|
5
|
+
this.inherits('dns_list_base');
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
this.load_dnswl_ini();
|
|
9
8
|
|
|
10
9
|
// IMPORTANT: don't run this on hook_rcpt otherwise we're an open relay...
|
|
11
10
|
['ehlo','helo','mail'].forEach(hook => {
|
|
12
|
-
|
|
11
|
+
this.register_hook(hook, 'check_dnswl');
|
|
13
12
|
});
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
exports.load_dnswl_ini = function () {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
plugin.load_dnswl_ini();
|
|
16
|
+
this.cfg = this.config.get('dnswl.ini', () => {
|
|
17
|
+
this.load_dnswl_ini();
|
|
20
18
|
});
|
|
21
19
|
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
if (this.cfg.main.enable_stats) {
|
|
21
|
+
this.logdebug('stats reporting enabled');
|
|
22
|
+
this.enable_stats = true;
|
|
25
23
|
}
|
|
26
24
|
|
|
27
|
-
if (
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
if (this.cfg.main.stats_redis_host) {
|
|
26
|
+
this.redis_host = this.cfg.main.stats_redis_host;
|
|
27
|
+
this.logdebug(`set stats redis host to: ${this.redis_host}`);
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
this.zones = [];
|
|
33
31
|
// Compatibility with old-plugin
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
this.zones = this.zones.concat(
|
|
33
|
+
this.config.get('dnswl.zones', 'list')
|
|
36
34
|
);
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
if (this.cfg.main.zones) {
|
|
36
|
+
this.zones = this.zones.concat(
|
|
37
|
+
this.cfg.main.zones.replace(/\s+/g,'').split(/[;,]/));
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
if (
|
|
43
|
-
|
|
40
|
+
if (this.cfg.main.periodic_checks) {
|
|
41
|
+
this.check_zones(this.cfg.main.periodic_checks);
|
|
44
42
|
}
|
|
45
43
|
}
|
|
46
44
|
|
|
47
45
|
exports.check_dnswl = (next, connection) => connection.notes.dnswl ? next(OK) : next()
|
|
48
46
|
|
|
49
47
|
exports.hook_connect = function (next, connection) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
connection.logerror(plugin, 'no zones');
|
|
48
|
+
if (!this.zones || !this.zones.length) {
|
|
49
|
+
connection.logerror(this, 'no zones');
|
|
53
50
|
return next();
|
|
54
51
|
}
|
|
55
|
-
|
|
52
|
+
this.first(connection.remote.ip, this.zones, (err, zone, a) => {
|
|
56
53
|
if (!a) return next();
|
|
57
|
-
connection.loginfo(
|
|
54
|
+
connection.loginfo(this, `${connection.remote.ip} is whitelisted by ${zone}: ${a}`);
|
|
58
55
|
connection.notes.dnswl = true;
|
|
59
56
|
return next(OK);
|
|
60
57
|
});
|
package/plugins/early_talker.js
CHANGED
|
@@ -1,38 +1,36 @@
|
|
|
1
1
|
// This plugin checks for clients that talk before we sent a response
|
|
2
2
|
|
|
3
3
|
const ipaddr = require('ipaddr.js');
|
|
4
|
-
const isIPv6 = require('net')
|
|
4
|
+
const { isIPv6 } = require('net');
|
|
5
5
|
|
|
6
6
|
exports.register = function () {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
plugin.register_hook('data', 'early_talker');
|
|
7
|
+
this.load_config();
|
|
8
|
+
this.register_hook('connect_init', 'early_talker');
|
|
9
|
+
this.register_hook('data', 'early_talker');
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
exports.load_config = function () {
|
|
14
|
-
const plugin = this;
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
this.cfg = this.config.get('early_talker.ini', {
|
|
17
15
|
booleans: [
|
|
18
16
|
'+main.reject'
|
|
19
17
|
]
|
|
20
18
|
},
|
|
21
19
|
() => {
|
|
22
|
-
|
|
20
|
+
this.load_config();
|
|
23
21
|
});
|
|
24
22
|
|
|
25
23
|
// Generate a white list of IP addresses
|
|
26
|
-
|
|
24
|
+
this.whitelist = this.load_ip_list(Object.keys(this.cfg.ip_whitelist));
|
|
27
25
|
|
|
28
|
-
if (
|
|
29
|
-
|
|
26
|
+
if (this.cfg.main?.pause) {
|
|
27
|
+
this.pause = this.cfg.main.pause * 1000;
|
|
30
28
|
return;
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
// config/early_talker.pause is in milliseconds
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
this.pause = this.config.get('early_talker.pause', () => {
|
|
33
|
+
this.load_config();
|
|
36
34
|
});
|
|
37
35
|
}
|
|
38
36
|
|
|
@@ -52,7 +50,7 @@ exports.early_talker = function (next, connection) {
|
|
|
52
50
|
return next(DENYDISCONNECT, "You talk too soon");
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
let pause = plugin
|
|
53
|
+
let { pause } = plugin;
|
|
56
54
|
if (plugin.hook === 'connect_init') {
|
|
57
55
|
const elapsed = (Date.now() - connection.start_time);
|
|
58
56
|
if (elapsed > plugin.pause) {
|
|
@@ -73,15 +71,14 @@ exports.early_talker = function (next, connection) {
|
|
|
73
71
|
* @return {Boolean} True if is whitelisted
|
|
74
72
|
*/
|
|
75
73
|
exports.ip_in_list = function (ip) {
|
|
76
|
-
const plugin = this;
|
|
77
74
|
|
|
78
|
-
if (!
|
|
75
|
+
if (!this.whitelist) return false;
|
|
79
76
|
|
|
80
77
|
const ipobj = ipaddr.parse(ip);
|
|
81
78
|
|
|
82
|
-
for (
|
|
79
|
+
for (const element of this.whitelist) {
|
|
83
80
|
try {
|
|
84
|
-
if (ipobj.match(
|
|
81
|
+
if (ipobj.match(element)) {
|
|
85
82
|
return true;
|
|
86
83
|
}
|
|
87
84
|
}
|
|
@@ -101,9 +98,9 @@ exports.ip_in_list = function (ip) {
|
|
|
101
98
|
exports.load_ip_list = list => {
|
|
102
99
|
const whitelist = [];
|
|
103
100
|
|
|
104
|
-
for (
|
|
101
|
+
for (const element of list) {
|
|
105
102
|
try {
|
|
106
|
-
let addr =
|
|
103
|
+
let addr = element;
|
|
107
104
|
if (addr.match(/\/\d+$/)) {
|
|
108
105
|
addr = ipaddr.parseCIDR(addr);
|
|
109
106
|
}
|
|
@@ -120,37 +117,36 @@ exports.load_ip_list = list => {
|
|
|
120
117
|
}
|
|
121
118
|
|
|
122
119
|
exports.should_check = function (connection) {
|
|
123
|
-
const plugin = this;
|
|
124
120
|
// Skip delays for privileged senders
|
|
125
121
|
|
|
126
122
|
if (connection.notes.auth_user) {
|
|
127
|
-
connection.results.add(
|
|
123
|
+
connection.results.add(this, { skip: 'authed'});
|
|
128
124
|
return false;
|
|
129
125
|
}
|
|
130
126
|
|
|
131
127
|
if (connection.relaying) {
|
|
132
|
-
connection.results.add(
|
|
128
|
+
connection.results.add(this, { skip: 'relay'});
|
|
133
129
|
return false;
|
|
134
130
|
}
|
|
135
131
|
|
|
136
|
-
if (
|
|
137
|
-
connection.results.add(
|
|
132
|
+
if (this.ip_in_list(connection.remote.ip)) {
|
|
133
|
+
connection.results.add(this, { skip: 'whitelist' });
|
|
138
134
|
return false;
|
|
139
135
|
}
|
|
140
136
|
|
|
141
137
|
const karma = connection.results.get('karma');
|
|
142
138
|
if (karma && karma.good > 0) {
|
|
143
|
-
connection.results.add(
|
|
139
|
+
connection.results.add(this, { skip: '+karma' });
|
|
144
140
|
return false;
|
|
145
141
|
}
|
|
146
142
|
|
|
147
143
|
if (connection.remote.is_local) {
|
|
148
|
-
connection.results.add(
|
|
144
|
+
connection.results.add(this, { skip: 'local_ip'});
|
|
149
145
|
return false;
|
|
150
146
|
}
|
|
151
147
|
|
|
152
148
|
if (connection.remote.is_private) {
|
|
153
|
-
connection.results.add(
|
|
149
|
+
connection.results.add(this, { skip: 'private_ip'});
|
|
154
150
|
return false;
|
|
155
151
|
}
|
|
156
152
|
|
package/plugins/esets.js
CHANGED
|
@@ -5,17 +5,16 @@ const virus_re = new RegExp('virus="([^"]+)"');
|
|
|
5
5
|
|
|
6
6
|
exports.hook_data_post = function (next, connection) {
|
|
7
7
|
const plugin = this;
|
|
8
|
-
const txn = connection.transaction;
|
|
9
8
|
const cfg = this.config.get('esets.ini');
|
|
10
9
|
|
|
11
10
|
// Write message to temporary file
|
|
12
11
|
const tmpdir = cfg.main.tmpdir || '/tmp';
|
|
13
|
-
const tmpfile = `${tmpdir}/${
|
|
12
|
+
const tmpfile = `${tmpdir}/${connection?.transaction?.uuid}.esets`;
|
|
14
13
|
const ws = fs.createWriteStream(tmpfile);
|
|
15
14
|
|
|
16
15
|
ws.once('error', err => {
|
|
17
16
|
connection.logerror(plugin, `Error writing temporary file: ${err.message}`);
|
|
18
|
-
|
|
17
|
+
next();
|
|
19
18
|
});
|
|
20
19
|
|
|
21
20
|
let start_time;
|
|
@@ -32,17 +31,15 @@ exports.hook_data_post = function (next, connection) {
|
|
|
32
31
|
[stdout, stderr].forEach(channel => {
|
|
33
32
|
if (channel) {
|
|
34
33
|
const lines = channel.split('\n');
|
|
35
|
-
for (
|
|
36
|
-
if (
|
|
34
|
+
for (const line of lines) {
|
|
35
|
+
if (line) connection.logdebug(plugin, `recv: ${line}`);
|
|
37
36
|
}
|
|
38
37
|
}
|
|
39
38
|
});
|
|
40
39
|
|
|
41
40
|
// Get virus name
|
|
42
|
-
let virus
|
|
43
|
-
if (
|
|
44
|
-
virus = virus[1];
|
|
45
|
-
}
|
|
41
|
+
let virus = virus_re.exec(stdout)
|
|
42
|
+
if (virus) virus = virus[1];
|
|
46
43
|
|
|
47
44
|
// Log a summary
|
|
48
45
|
const exit_code = parseInt((error) ? error.code : 0)
|
|
@@ -60,7 +57,7 @@ exports.hook_data_post = function (next, connection) {
|
|
|
60
57
|
return next(DENYSOFT, 'Virus scanner error');
|
|
61
58
|
}
|
|
62
59
|
}
|
|
63
|
-
|
|
60
|
+
next();
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
ws.once('close', () => {
|
|
@@ -70,5 +67,5 @@ exports.hook_data_post = function (next, connection) {
|
|
|
70
67
|
wsOnClose);
|
|
71
68
|
});
|
|
72
69
|
|
|
73
|
-
|
|
70
|
+
connection.transaction.message_stream.pipe(ws, { line_endings: '\r\n' });
|
|
74
71
|
}
|