Haraka 3.0.3 → 3.0.5
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 +4 -9
- package/CONTRIBUTORS.md +11 -0
- package/Changes.md +1397 -1213
- package/Plugins.md +117 -105
- package/README.md +4 -13
- package/bin/haraka +198 -298
- package/config/auth_flat_file.ini +1 -0
- package/config/dhparams.pem +8 -0
- package/config/mail_from.is_resolvable.ini +4 -2
- package/config/me +1 -0
- package/config/outbound.ini +0 -2
- package/config/plugins +35 -36
- package/config/smtp.ini +1 -1
- package/config/smtp.json +17 -0
- package/config/tls.ini +2 -0
- package/config/tls_cert.pem +23 -0
- package/config/tls_key.pem +28 -0
- package/connection.js +46 -73
- package/contrib/bsd-rc.d/haraka +3 -1
- package/contrib/plugin2npm.sh +6 -36
- package/docs/CoreConfig.md +2 -2
- package/docs/Logging.md +7 -21
- package/docs/Outbound.md +104 -201
- package/docs/Plugins.md +2 -2
- package/docs/Transaction.md +59 -82
- package/docs/plugins/queue/smtp_proxy.md +5 -10
- package/docs/plugins/tls.md +37 -9
- package/endpoint.js +16 -13
- package/haraka.js +10 -14
- package/host_pool.js +5 -5
- package/http/html/index.html +6 -5
- package/line_socket.js +3 -4
- package/logger.js +44 -28
- package/outbound/client_pool.js +27 -23
- package/outbound/config.js +4 -6
- package/outbound/fsync_writestream.js +1 -1
- package/outbound/hmail.js +178 -218
- package/outbound/index.js +86 -99
- package/outbound/qfile.js +1 -1
- package/outbound/queue.js +51 -44
- package/outbound/timer_queue.js +3 -2
- package/outbound/tls.js +19 -7
- package/package.json +60 -51
- package/plugins/.eslintrc.yaml +0 -6
- package/plugins/auth/auth_base.js +4 -2
- package/plugins/auth/auth_proxy.js +14 -12
- package/plugins/auth/auth_vpopmaild.js +1 -1
- package/plugins/block_me.js +1 -1
- package/plugins/data.signatures.js +2 -4
- package/plugins/early_talker.js +2 -1
- package/plugins/mail_from.is_resolvable.js +65 -135
- package/plugins/queue/deliver.js +4 -5
- package/plugins/queue/lmtp.js +11 -12
- package/plugins/queue/qmail-queue.js +2 -2
- package/plugins/queue/quarantine.js +2 -2
- package/plugins/queue/rabbitmq.js +16 -17
- package/plugins/queue/smtp_forward.js +3 -3
- package/plugins/queue/smtp_proxy.js +10 -1
- package/plugins/queue/test.js +2 -2
- package/plugins/rcpt_to.host_list_base.js +5 -5
- package/plugins/rcpt_to.in_host_list.js +2 -2
- package/plugins/relay.js +6 -7
- package/plugins/reseed_rng.js +1 -1
- package/plugins/status.js +37 -33
- package/plugins/tls.js +2 -2
- package/plugins/xclient.js +3 -2
- package/plugins.js +50 -54
- package/run_tests +3 -30
- package/server.js +190 -190
- package/smtp_client.js +30 -23
- package/{tests → test}/config/plugins +0 -2
- package/{tests → test}/config/smtp.ini +3 -1
- package/test/config/tls/example.com/_.example.com.key +28 -0
- package/test/config/tls/example.com/example.com.crt +25 -0
- package/{tests/loud → test}/config/tls.ini +4 -2
- package/test/connection.js +302 -0
- package/test/endpoint.js +94 -0
- package/{tests → test}/fixtures/line_socket.js +1 -1
- package/{tests → test}/fixtures/util_hmailitem.js +19 -25
- package/{tests → test}/host_pool.js +42 -57
- package/test/logger.js +258 -0
- package/test/outbound/hmail.js +141 -0
- package/test/outbound/index.js +220 -0
- package/test/outbound/qfile.js +126 -0
- package/test/outbound_bounce_net_errors.js +142 -0
- package/{tests → test}/outbound_bounce_rfc3464.js +110 -122
- package/test/plugins/auth/auth_base.js +484 -0
- package/test/plugins/auth/auth_vpopmaild.js +83 -0
- package/test/plugins/early_talker.js +104 -0
- package/test/plugins/mail_from.is_resolvable.js +35 -0
- package/test/plugins/queue/smtp_forward.js +206 -0
- package/test/plugins/rcpt_to.host_list_base.js +122 -0
- package/test/plugins/rcpt_to.in_host_list.js +193 -0
- package/test/plugins/relay.js +303 -0
- package/test/plugins/status.js +130 -0
- package/test/plugins/tls.js +70 -0
- package/test/plugins.js +228 -0
- package/test/rfc1869.js +73 -0
- package/test/server.js +491 -0
- package/test/smtp_client.js +299 -0
- package/test/tls_socket.js +277 -0
- package/test/transaction.js +270 -0
- package/tls_socket.js +202 -252
- package/transaction.js +8 -23
- package/CONTRIBUTING.md +0 -1
- package/bin/dkimverify +0 -40
- package/config/access.domains +0 -13
- package/config/attachment.ctype.regex +0 -2
- package/config/attachment.filename.regex +0 -1
- package/config/avg.ini +0 -5
- package/config/bounce.ini +0 -15
- package/config/data.headers.ini +0 -61
- package/config/dkim/dkim_key_gen.sh +0 -78
- package/config/dkim_sign.ini +0 -4
- package/config/dkim_verify.ini +0 -7
- package/config/dnsbl.ini +0 -23
- package/config/greylist.ini +0 -43
- package/config/helo.checks.ini +0 -52
- package/config/messagesniffer.ini +0 -18
- package/config/spamassassin.ini +0 -56
- package/dkim.js +0 -614
- package/docs/plugins/avg.md +0 -35
- package/docs/plugins/bounce.md +0 -69
- package/docs/plugins/clamd.md +0 -147
- package/docs/plugins/esets.md +0 -8
- package/docs/plugins/greylist.md +0 -90
- package/docs/plugins/helo.checks.md +0 -135
- package/docs/plugins/messagesniffer.md +0 -163
- package/docs/plugins/spamassassin.md +0 -180
- package/outbound/mx_lookup.js +0 -70
- package/plugins/auth/auth_ldap.js +0 -3
- package/plugins/avg.js +0 -162
- package/plugins/backscatterer.js +0 -25
- package/plugins/bounce.js +0 -381
- package/plugins/clamd.js +0 -382
- package/plugins/data.uribl.js +0 -4
- package/plugins/dkim_sign.js +0 -395
- package/plugins/dkim_verify.js +0 -62
- package/plugins/dns_list_base.js +0 -221
- package/plugins/dnsbl.js +0 -146
- package/plugins/dnswl.js +0 -58
- package/plugins/esets.js +0 -71
- package/plugins/graph.js +0 -5
- package/plugins/greylist.js +0 -645
- package/plugins/helo.checks.js +0 -533
- package/plugins/messagesniffer.js +0 -381
- package/plugins/rcpt_to.ldap.js +0 -3
- package/plugins/rcpt_to.max_count.js +0 -24
- package/plugins/spamassassin.js +0 -384
- package/tests/config/dkim/example.com/dns +0 -29
- package/tests/config/dkim/example.com/private +0 -6
- package/tests/config/dkim/example.com/public +0 -4
- package/tests/config/dkim/example.com/selector +0 -1
- package/tests/config/dkim.private.key +0 -6
- package/tests/config/dkim_sign.ini +0 -4
- package/tests/config/helo.checks.ini +0 -52
- package/tests/connection.js +0 -327
- package/tests/endpoint.js +0 -128
- package/tests/fixtures/vm_harness.js +0 -59
- package/tests/logger.js +0 -327
- package/tests/outbound/hmail.js +0 -112
- package/tests/outbound/index.js +0 -324
- package/tests/outbound/qfile.js +0 -67
- package/tests/outbound_bounce_net_errors.js +0 -173
- package/tests/plugins/auth/auth_base.js +0 -463
- package/tests/plugins/auth/auth_vpopmaild.js +0 -91
- package/tests/plugins/bounce.js +0 -307
- package/tests/plugins/clamd.js +0 -224
- package/tests/plugins/deprecated/relay_acl.js +0 -140
- package/tests/plugins/deprecated/relay_all.js +0 -59
- package/tests/plugins/dkim_sign.js +0 -315
- package/tests/plugins/dkim_signer.js +0 -108
- package/tests/plugins/dns_list_base.js +0 -259
- package/tests/plugins/dnsbl.js +0 -101
- package/tests/plugins/early_talker.js +0 -115
- package/tests/plugins/greylist.js +0 -58
- package/tests/plugins/helo.checks.js +0 -525
- package/tests/plugins/mail_from.is_resolvable.js +0 -116
- package/tests/plugins/queue/smtp_forward.js +0 -221
- package/tests/plugins/rcpt_to.host_list_base.js +0 -132
- package/tests/plugins/rcpt_to.in_host_list.js +0 -218
- package/tests/plugins/relay.js +0 -339
- package/tests/plugins/spamassassin.js +0 -171
- package/tests/plugins/status.js +0 -138
- package/tests/plugins/tls.js +0 -84
- package/tests/plugins.js +0 -247
- package/tests/rfc1869.js +0 -61
- package/tests/server.js +0 -510
- package/tests/smtp_client/auth.js +0 -105
- package/tests/smtp_client/basic.js +0 -101
- package/tests/smtp_client.js +0 -80
- package/tests/tls_socket.js +0 -333
- package/tests/transaction.js +0 -284
- /package/docs/{plugins → deprecated}/dkim_sign.md +0 -0
- /package/docs/{plugins → deprecated}/dkim_verify.md +0 -0
- /package/docs/{plugins → deprecated}/dnsbl.md +0 -0
- /package/docs/{plugins → deprecated}/dnswl.md +0 -0
- /package/{tests → test}/.eslintrc.yaml +0 -0
- /package/{tests → test}/config/auth_flat_file.ini +0 -0
- /package/{tests → test}/config/dhparams.pem +0 -0
- /package/{tests → test}/config/host_list +0 -0
- /package/{tests → test}/config/outbound_tls_cert.pem +0 -0
- /package/{tests → test}/config/outbound_tls_key.pem +0 -0
- /package/{tests → test}/config/smtp_forward.ini +0 -0
- /package/{tests → test}/config/tls/ec.pem +0 -0
- /package/{tests → test}/config/tls/haraka.local.pem +0 -0
- /package/{tests → test}/config/tls/mismatched.pem +0 -0
- /package/{tests → test}/config/tls_cert.pem +0 -0
- /package/{tests → test}/config/tls_key.pem +0 -0
- /package/{tests → test}/fixtures/todo_qfile.txt +0 -0
- /package/{tests → test}/installation/config/test-plugin-flat +0 -0
- /package/{tests → test}/installation/config/test-plugin.ini +0 -0
- /package/{tests → test}/installation/config/tls.ini +0 -0
- /package/{tests → test}/installation/node_modules/load_first/index.js +0 -0
- /package/{tests → test}/installation/node_modules/load_first/package.json +0 -0
- /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin-flat +0 -0
- /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin.ini +0 -0
- /package/{tests → test}/installation/node_modules/test-plugin/package.json +0 -0
- /package/{tests → test}/installation/node_modules/test-plugin/test-plugin.js +0 -0
- /package/{tests → test}/installation/plugins/base_plugin.js +0 -0
- /package/{tests → test}/installation/plugins/folder_plugin/index.js +0 -0
- /package/{tests → test}/installation/plugins/folder_plugin/package.json +0 -0
- /package/{tests → test}/installation/plugins/inherits.js +0 -0
- /package/{tests → test}/installation/plugins/load_first.js +0 -0
- /package/{tests → test}/installation/plugins/plugin.js +0 -0
- /package/{tests → test}/installation/plugins/tls.js +0 -0
- /package/{tests → test}/loud/config/dhparams.pem +0 -0
- /package/{tests → test}/loud/config/tls/goobered.pem +0 -0
- /package/{tests → test/loud}/config/tls.ini +0 -0
- /package/{tests → test}/mail_specimen/base64-root-part.txt +0 -0
- /package/{tests → test}/mail_specimen/varied-fold-lengths-preserve-data.txt +0 -0
- /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_fixed +0 -0
- /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_haraka +0 -0
- /package/{tests → test}/queue/1508269674999_1508269674999_0_34002_socVUF_1_haraka +0 -0
- /package/{tests → test}/queue/1508455115683_1508455115683_0_90253_9Q4o4V_1_haraka +0 -0
- /package/{tests → test}/queue/multibyte +0 -0
- /package/{tests → test}/queue/plain +0 -0
- /package/{tests → test}/queue/zero-length +0 -0
- /package/{tests → test}/test-queue/delete-me +0 -0
package/plugins/clamd.js
DELETED
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
// clamd
|
|
2
|
-
|
|
3
|
-
const sock = require('./line_socket');
|
|
4
|
-
const utils = require('haraka-utils');
|
|
5
|
-
|
|
6
|
-
exports.load_excludes = function () {
|
|
7
|
-
|
|
8
|
-
this.loginfo('Loading excludes file');
|
|
9
|
-
const list = this.config.get('clamd.excludes','list', () => {
|
|
10
|
-
this.load_excludes();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const new_skip_list_exclude = [];
|
|
14
|
-
const new_skip_list = [];
|
|
15
|
-
for (const element of list) {
|
|
16
|
-
let re;
|
|
17
|
-
switch (element[0]) {
|
|
18
|
-
case '!':
|
|
19
|
-
|
|
20
|
-
if (element[1] === '/') {
|
|
21
|
-
// Regexp exclude
|
|
22
|
-
try {
|
|
23
|
-
re = new RegExp(element.substr(2, element.length-2),'i');
|
|
24
|
-
new_skip_list_exclude.push(re);
|
|
25
|
-
}
|
|
26
|
-
catch (e) {
|
|
27
|
-
this.logerror(`${e.message} (entry: ${element})`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
// Wildcard exclude
|
|
32
|
-
try {
|
|
33
|
-
re = new RegExp(
|
|
34
|
-
utils.wildcard_to_regexp(element.substr(1)),'i');
|
|
35
|
-
new_skip_list_exclude.push(re);
|
|
36
|
-
}
|
|
37
|
-
catch (e) {
|
|
38
|
-
this.logerror(`${e.message} (entry: ${element})`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
break;
|
|
42
|
-
case '/':
|
|
43
|
-
// Regexp skip
|
|
44
|
-
try {
|
|
45
|
-
re = new RegExp(element.substr(1, element.length-2),'i');
|
|
46
|
-
new_skip_list.push(re);
|
|
47
|
-
}
|
|
48
|
-
catch (e) {
|
|
49
|
-
this.logerror(`${e.message} (entry: ${element})`);
|
|
50
|
-
}
|
|
51
|
-
break;
|
|
52
|
-
default:
|
|
53
|
-
// Wildcard skip
|
|
54
|
-
try {
|
|
55
|
-
re = new RegExp(utils.wildcard_to_regexp(element),'i');
|
|
56
|
-
new_skip_list.push(re);
|
|
57
|
-
}
|
|
58
|
-
catch (e) {
|
|
59
|
-
this.logerror(`${e.message} (entry: ${element})`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Make the new lists visible
|
|
65
|
-
this.skip_list_exclude = new_skip_list_exclude;
|
|
66
|
-
this.skip_list = new_skip_list;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
exports.load_clamd_ini = function () {
|
|
70
|
-
|
|
71
|
-
this.cfg = this.config.get('clamd.ini', {
|
|
72
|
-
booleans: [
|
|
73
|
-
'-main.randomize_host_order',
|
|
74
|
-
'-main.only_with_attachments',
|
|
75
|
-
'+reject.virus',
|
|
76
|
-
'+reject.error',
|
|
77
|
-
|
|
78
|
-
// clamd options that are disabled by default. If admin enables
|
|
79
|
-
// them for clamd, Haraka should reject by default.
|
|
80
|
-
'+reject.Broken.Executable',
|
|
81
|
-
'+reject.Structured', // DLP options
|
|
82
|
-
'+reject.Encrypted',
|
|
83
|
-
'+reject.PUA',
|
|
84
|
-
'+reject.OLE2',
|
|
85
|
-
'+reject.Safebrowsing',
|
|
86
|
-
'+reject.UNOFFICIAL',
|
|
87
|
-
|
|
88
|
-
// clamd.conf options enabled by default, but prone to false
|
|
89
|
-
// positives.
|
|
90
|
-
'-reject.Phishing',
|
|
91
|
-
|
|
92
|
-
'+check.authenticated',
|
|
93
|
-
'+check.private_ip',
|
|
94
|
-
'+check.local_ip'
|
|
95
|
-
],
|
|
96
|
-
}, () => {
|
|
97
|
-
this.load_clamd_ini();
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const defaults = {
|
|
101
|
-
clamd_socket: 'localhost:3310',
|
|
102
|
-
timeout: 30,
|
|
103
|
-
connect_timeout: 10,
|
|
104
|
-
max_size: 26214400,
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
for (const key in defaults) {
|
|
108
|
-
if (this.cfg.main[key] === undefined) {
|
|
109
|
-
this.cfg.main[key] = defaults[key];
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const rejectPatterns = {
|
|
114
|
-
'Broken.Executable': '^Broken\\.Executable\\.?',
|
|
115
|
-
Encrypted: '^Encrypted\\.',
|
|
116
|
-
PUA: '^PUA\\.',
|
|
117
|
-
Structured: '^Heuristics\\.Structured\\.',
|
|
118
|
-
OLE2: '^Heuristics\\.OLE2\\.ContainsMacros',
|
|
119
|
-
Safebrowsing: '^Heuristics\\.Safebrowsing\\.',
|
|
120
|
-
Phishing: '^Heuristics\\.Phishing\\.',
|
|
121
|
-
UNOFFICIAL: '\\.UNOFFICIAL$',
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const all_reject_opts = [];
|
|
125
|
-
const enabled_reject_opts = [];
|
|
126
|
-
Object.keys(rejectPatterns).forEach(opt => {
|
|
127
|
-
all_reject_opts.push(rejectPatterns[opt]);
|
|
128
|
-
if (!this.cfg.reject[opt]) return;
|
|
129
|
-
enabled_reject_opts.push(rejectPatterns[opt]);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
if (enabled_reject_opts.length) {
|
|
133
|
-
this.allRE = new RegExp(all_reject_opts.join('|'));
|
|
134
|
-
this.rejectRE = new RegExp(enabled_reject_opts.join('|'));
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// resolve mismatch between docs (...attachment) and code (...attachments)
|
|
138
|
-
if (this.cfg.main.only_with_attachment !== undefined) {
|
|
139
|
-
this.cfg.main.only_with_attachments =
|
|
140
|
-
!!this.cfg.main.only_with_attachment;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
exports.register = function () {
|
|
145
|
-
this.load_excludes();
|
|
146
|
-
this.load_clamd_ini();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
exports.hook_data = function (next, connection) {
|
|
150
|
-
|
|
151
|
-
if (!this.cfg.main.only_with_attachments) return next();
|
|
152
|
-
|
|
153
|
-
if (!this.should_check(connection)) return next();
|
|
154
|
-
|
|
155
|
-
const txn = connection.transaction;
|
|
156
|
-
txn.parse_body = true;
|
|
157
|
-
txn.attachment_hooks((ctype, filename, body) => {
|
|
158
|
-
connection.logdebug(this,
|
|
159
|
-
`found ctype=${ctype}, filename=${filename}`);
|
|
160
|
-
txn.notes.clamd_found_attachment = true;
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
return next();
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
exports.hook_data_post = function (next, connection) {
|
|
167
|
-
const plugin = this;
|
|
168
|
-
if (!plugin.should_check(connection)) return next();
|
|
169
|
-
|
|
170
|
-
const txn = connection.transaction;
|
|
171
|
-
const { cfg } = plugin;
|
|
172
|
-
// Do we need to run?
|
|
173
|
-
if (cfg.main.only_with_attachments && !txn.notes.clamd_found_attachment) {
|
|
174
|
-
connection.logdebug(plugin, 'skipping: no attachments found');
|
|
175
|
-
txn.results.add(plugin, {skip: 'no attachments'});
|
|
176
|
-
return next();
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Limit message size
|
|
180
|
-
if (txn.data_bytes > cfg.main.max_size) {
|
|
181
|
-
txn.results.add(plugin, {skip: 'exceeds max size', emit: true});
|
|
182
|
-
return next();
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const hosts = cfg.main.clamd_socket.split(/[,; ]+/);
|
|
186
|
-
|
|
187
|
-
if (cfg.main.randomize_host_order) {
|
|
188
|
-
hosts.sort(() => 0.5 - Math.random());
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function try_next_host () {
|
|
192
|
-
let connected = false;
|
|
193
|
-
if (!hosts.length) {
|
|
194
|
-
if (txn) txn.results.add(plugin, {err: 'connecting' });
|
|
195
|
-
if (!plugin.cfg.reject.error) return next();
|
|
196
|
-
return next(DENYSOFT, 'Error connecting to virus scanner');
|
|
197
|
-
}
|
|
198
|
-
const host = hosts.shift();
|
|
199
|
-
connection.logdebug(plugin, `trying host: ${host}`);
|
|
200
|
-
const socket = new sock.Socket();
|
|
201
|
-
|
|
202
|
-
socket.on('timeout', () => {
|
|
203
|
-
socket.destroy();
|
|
204
|
-
if (!connected) {
|
|
205
|
-
connection.logerror(plugin, `Timeout connecting to ${host}`);
|
|
206
|
-
return try_next_host();
|
|
207
|
-
}
|
|
208
|
-
if (txn) txn.results.add(plugin, {err: 'clamd timed out' });
|
|
209
|
-
if (!plugin.cfg.reject.error) return next();
|
|
210
|
-
return next(DENYSOFT, 'Virus scanner timed out');
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
socket.on('error', err => {
|
|
214
|
-
socket.destroy();
|
|
215
|
-
if (!connected) {
|
|
216
|
-
connection.logerror(plugin,
|
|
217
|
-
`Connection to ${host} failed: ${err.message}`);
|
|
218
|
-
return try_next_host();
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// If an error occurred after connection and there are other hosts left to try,
|
|
222
|
-
// then try those before returning DENYSOFT.
|
|
223
|
-
if (hosts.length) {
|
|
224
|
-
connection.logwarn(plugin, `error on host ${host}: ${err.message}`);
|
|
225
|
-
return try_next_host();
|
|
226
|
-
}
|
|
227
|
-
if (txn) txn.results.add(plugin, {err: `error on host ${host}: ${err.message}` });
|
|
228
|
-
if (!plugin.cfg.reject.error) return next();
|
|
229
|
-
return next(DENYSOFT, 'Virus scanner error');
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
socket.on('connect', () => {
|
|
233
|
-
connected = true;
|
|
234
|
-
socket.setTimeout((cfg.main.timeout || 30) * 1000);
|
|
235
|
-
const hp = socket.address();
|
|
236
|
-
const addressInfo = hp === null ? '' : ` ${hp.address}:${hp.port}`;
|
|
237
|
-
connection.logdebug(plugin, `connected to host${addressInfo}`);
|
|
238
|
-
plugin.send_clamd_predata(socket, () => {
|
|
239
|
-
txn.message_stream.pipe(socket, { clamd_style: true });
|
|
240
|
-
})
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
let result = '';
|
|
244
|
-
socket.on('line', line => {
|
|
245
|
-
connection.logprotocol(plugin, `C:${line.split('').filter((x) => {
|
|
246
|
-
return 31 < x.charCodeAt(0) && 127 > x.charCodeAt(0)
|
|
247
|
-
}).join('')}` );
|
|
248
|
-
result = line.replace(/\r?\n/, '');
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
socket.setTimeout((cfg.main.connect_timeout || 10) * 1000);
|
|
252
|
-
|
|
253
|
-
socket.on('end', () => {
|
|
254
|
-
if (!txn) return next();
|
|
255
|
-
if (/^stream: OK/.test(result)) { // OK
|
|
256
|
-
txn.results.add(plugin, {pass: 'clean', emit: true});
|
|
257
|
-
return next();
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const m = /^stream: (\S+) FOUND/.exec(result);
|
|
261
|
-
if (m) {
|
|
262
|
-
let virus; // Virus found
|
|
263
|
-
if (m[1]) { virus = m[1]; }
|
|
264
|
-
txn.results.add(plugin, {
|
|
265
|
-
fail: virus ? virus : 'virus',
|
|
266
|
-
emit: true
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
if (virus && plugin.rejectRE && // enabled
|
|
270
|
-
plugin.allRE.test(virus) && // has a reject option
|
|
271
|
-
!plugin.rejectRE.test(virus)) { // reject=false set
|
|
272
|
-
txn.add_header('X-Haraka-Virus', virus);
|
|
273
|
-
return next();
|
|
274
|
-
}
|
|
275
|
-
if (!plugin.cfg.reject.virus) { return next(); }
|
|
276
|
-
|
|
277
|
-
// Check skip list exclusions
|
|
278
|
-
for (const element of plugin.skip_list_exclude) {
|
|
279
|
-
if (!element.test(virus)) continue;
|
|
280
|
-
return next(DENY,
|
|
281
|
-
`Message is infected with ${virus || 'UNKNOWN'}`);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Check skip list
|
|
285
|
-
for (const element of plugin.skip_list) {
|
|
286
|
-
if (!element.test(virus)) continue;
|
|
287
|
-
connection.logwarn(plugin, `${virus} matches exclusion`);
|
|
288
|
-
txn.add_header('X-Haraka-Virus', virus);
|
|
289
|
-
return next();
|
|
290
|
-
}
|
|
291
|
-
return next(DENY, `Message is infected with ${
|
|
292
|
-
virus || 'UNKNOWN'}`);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (/size limit exceeded/.test(result)) {
|
|
296
|
-
txn.results.add(plugin, {
|
|
297
|
-
err: 'INSTREAM size limit exceeded. Check ' +
|
|
298
|
-
'StreamMaxLength in clamd.conf',
|
|
299
|
-
});
|
|
300
|
-
// Continue as StreamMaxLength default is 25Mb
|
|
301
|
-
return next();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// The current host returned an unknown result. If other hosts are available,
|
|
305
|
-
// then try those before returning a DENYSOFT.
|
|
306
|
-
if (hosts.length) {
|
|
307
|
-
connection.logwarn(plugin, `unknown result: '${result}' from host ${host}`);
|
|
308
|
-
socket.destroy();
|
|
309
|
-
return try_next_host();
|
|
310
|
-
}
|
|
311
|
-
txn.results.add(plugin, { err: `unknown result: '${result}' from host ${host}`});
|
|
312
|
-
if (!plugin.cfg.reject.error) return next();
|
|
313
|
-
return next(DENYSOFT, 'Error running virus scanner');
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
clamd_connect(socket, host);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Start the process
|
|
320
|
-
try_next_host();
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
exports.should_check = function (connection) {
|
|
324
|
-
|
|
325
|
-
let result = true; // default
|
|
326
|
-
if (!connection?.transaction) return false
|
|
327
|
-
|
|
328
|
-
if (this.cfg.check.authenticated == false && connection.notes.auth_user) {
|
|
329
|
-
connection.transaction.results.add(this, { skip: 'authed'});
|
|
330
|
-
result = false;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
if (this.cfg.check.relay == false && connection.relaying) {
|
|
334
|
-
connection.transaction.results.add(this, { skip: 'relay'});
|
|
335
|
-
result = false;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
if (this.cfg.check.local_ip == false && connection.remote.is_local) {
|
|
339
|
-
connection.transaction.results.add(this, { skip: 'local_ip'});
|
|
340
|
-
result = false;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
if (this.cfg.check.private_ip == false && connection.remote.is_private) {
|
|
344
|
-
if (this.cfg.check.local_ip == true && connection.remote.is_local) {
|
|
345
|
-
// local IPs are included in private IPs
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
connection.transaction.results.add(this, { skip: 'private_ip'});
|
|
349
|
-
result = false;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return result;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
exports.send_clamd_predata = (socket, cb) => {
|
|
357
|
-
socket.write("zINSTREAM\0", () => {
|
|
358
|
-
const received = 'Received: from Haraka clamd plugin\r\n';
|
|
359
|
-
const buf = Buffer.alloc(received.length + 4);
|
|
360
|
-
buf.writeUInt32BE(received.length, 0);
|
|
361
|
-
buf.write(received, 4);
|
|
362
|
-
socket.write(buf, cb)
|
|
363
|
-
})
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function clamd_connect (socket, host) {
|
|
367
|
-
|
|
368
|
-
if (host.match(/^\//)) {
|
|
369
|
-
socket.connect(host); // starts with /, unix socket
|
|
370
|
-
return
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const match = /^\[([^\] ]+)\](?::(\d+))?/.exec(host);
|
|
374
|
-
if (match) {
|
|
375
|
-
socket.connect((match[2] || 3310), match[1]); // IPv6 literal
|
|
376
|
-
return
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// IP:port, hostname:port or hostname
|
|
380
|
-
const hostport = host.split(/:/);
|
|
381
|
-
socket.connect((hostport[1] || 3310), hostport[0]);
|
|
382
|
-
}
|
package/plugins/data.uribl.js
DELETED