Haraka 3.0.2 → 3.0.4

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.
Files changed (267) hide show
  1. package/.eslintrc.yaml +5 -9
  2. package/.prettierrc.yml +1 -0
  3. package/CONTRIBUTORS.md +11 -0
  4. package/Changes.md +1393 -1211
  5. package/Dockerfile +3 -3
  6. package/Plugins.md +119 -106
  7. package/README.md +7 -16
  8. package/TODO +1 -24
  9. package/bin/haraka +197 -298
  10. package/config/auth_flat_file.ini +2 -0
  11. package/config/auth_vpopmaild.ini +4 -2
  12. package/config/dhparams.pem +8 -0
  13. package/config/mail_from.is_resolvable.ini +4 -2
  14. package/config/me +1 -0
  15. package/config/outbound.ini +0 -2
  16. package/config/plugins +36 -35
  17. package/config/rabbitmq_amqplib.ini +8 -1
  18. package/config/smtp.ini +0 -1
  19. package/config/smtp.json +17 -0
  20. package/config/tls_cert.pem +23 -0
  21. package/config/tls_key.pem +28 -0
  22. package/connection.js +46 -73
  23. package/contrib/bsd-rc.d/haraka +3 -1
  24. package/contrib/plugin2npm.sh +6 -36
  25. package/docs/Connection.md +1 -1
  26. package/docs/CoreConfig.md +2 -2
  27. package/docs/Logging.md +7 -21
  28. package/docs/Outbound.md +104 -210
  29. package/docs/Plugins.md +47 -40
  30. package/docs/Transaction.md +59 -82
  31. package/docs/{plugins → deprecated}/connect.rdns_access.md +1 -1
  32. package/docs/{plugins → deprecated}/mail_from.access.md +1 -1
  33. package/docs/{plugins → deprecated}/rcpt_to.access.md +1 -1
  34. package/docs/plugins/auth/auth_vpopmaild.md +15 -19
  35. package/docs/plugins/auth/flat_file.md +23 -30
  36. package/docs/plugins/queue/rabbitmq_amqplib.md +7 -0
  37. package/docs/plugins/queue/smtp_forward.md +1 -1
  38. package/docs/plugins/queue/smtp_proxy.md +5 -10
  39. package/docs/plugins/relay.md +2 -2
  40. package/docs/plugins/tls.md +29 -9
  41. package/endpoint.js +16 -13
  42. package/haraka.js +10 -14
  43. package/host_pool.js +5 -5
  44. package/line_socket.js +3 -4
  45. package/logger.js +44 -28
  46. package/outbound/client_pool.js +27 -23
  47. package/outbound/config.js +4 -6
  48. package/outbound/fsync_writestream.js +1 -1
  49. package/outbound/hmail.js +180 -220
  50. package/outbound/index.js +86 -99
  51. package/outbound/qfile.js +1 -1
  52. package/outbound/queue.js +55 -43
  53. package/outbound/timer_queue.js +3 -2
  54. package/outbound/tls.js +19 -7
  55. package/package.json +66 -55
  56. package/plugins/.eslintrc.yaml +0 -6
  57. package/plugins/auth/auth_base.js +30 -12
  58. package/plugins/auth/auth_proxy.js +14 -12
  59. package/plugins/auth/auth_vpopmaild.js +30 -20
  60. package/plugins/auth/flat_file.js +17 -12
  61. package/plugins/block_me.js +1 -1
  62. package/plugins/data.signatures.js +2 -4
  63. package/plugins/early_talker.js +2 -1
  64. package/plugins/mail_from.is_resolvable.js +65 -135
  65. package/plugins/queue/deliver.js +4 -5
  66. package/plugins/queue/lmtp.js +11 -14
  67. package/plugins/queue/qmail-queue.js +2 -2
  68. package/plugins/queue/quarantine.js +2 -2
  69. package/plugins/queue/rabbitmq.js +16 -17
  70. package/plugins/queue/rabbitmq_amqplib.js +1 -1
  71. package/plugins/queue/smtp_forward.js +6 -6
  72. package/plugins/queue/smtp_proxy.js +10 -1
  73. package/plugins/queue/test.js +2 -2
  74. package/plugins/rcpt_to.host_list_base.js +5 -5
  75. package/plugins/rcpt_to.in_host_list.js +2 -2
  76. package/plugins/relay.js +6 -7
  77. package/plugins/reseed_rng.js +1 -1
  78. package/plugins/status.js +37 -33
  79. package/plugins/tls.js +2 -2
  80. package/plugins/xclient.js +3 -2
  81. package/plugins.js +51 -54
  82. package/run_tests +3 -30
  83. package/server.js +190 -190
  84. package/smtp_client.js +30 -23
  85. package/{tests → test}/config/plugins +0 -2
  86. package/{tests → test}/config/smtp.ini +1 -1
  87. package/test/config/tls/example.com/_.example.com.key +28 -0
  88. package/test/config/tls/example.com/example.com.crt +25 -0
  89. package/test/connection.js +302 -0
  90. package/test/endpoint.js +94 -0
  91. package/{tests → test}/fixtures/line_socket.js +1 -1
  92. package/{tests → test}/fixtures/util_hmailitem.js +19 -25
  93. package/{tests → test}/host_pool.js +42 -57
  94. package/test/logger.js +258 -0
  95. package/test/outbound/hmail.js +141 -0
  96. package/test/outbound/index.js +220 -0
  97. package/test/outbound/qfile.js +126 -0
  98. package/test/outbound_bounce_net_errors.js +142 -0
  99. package/{tests → test}/outbound_bounce_rfc3464.js +110 -122
  100. package/test/plugins/auth/auth_base.js +484 -0
  101. package/test/plugins/auth/auth_vpopmaild.js +83 -0
  102. package/test/plugins/early_talker.js +104 -0
  103. package/test/plugins/mail_from.is_resolvable.js +35 -0
  104. package/test/plugins/queue/smtp_forward.js +206 -0
  105. package/test/plugins/rcpt_to.host_list_base.js +122 -0
  106. package/test/plugins/rcpt_to.in_host_list.js +193 -0
  107. package/test/plugins/relay.js +303 -0
  108. package/test/plugins/status.js +130 -0
  109. package/test/plugins/tls.js +70 -0
  110. package/test/plugins.js +228 -0
  111. package/{tests → test}/queue/multibyte +0 -0
  112. package/{tests → test}/queue/plain +0 -0
  113. package/test/rfc1869.js +73 -0
  114. package/test/server.js +491 -0
  115. package/test/smtp_client.js +299 -0
  116. package/test/tls_socket.js +273 -0
  117. package/test/transaction.js +270 -0
  118. package/tls_socket.js +202 -252
  119. package/transaction.js +9 -24
  120. package/CONTRIBUTING.md +0 -1
  121. package/bin/dkimverify +0 -40
  122. package/config/access.domains +0 -13
  123. package/config/attachment.ctype.regex +0 -2
  124. package/config/attachment.filename.regex +0 -1
  125. package/config/avg.ini +0 -5
  126. package/config/bounce.ini +0 -15
  127. package/config/data.headers.ini +0 -61
  128. package/config/dkim/dkim_key_gen.sh +0 -78
  129. package/config/dkim_sign.ini +0 -4
  130. package/config/dkim_verify.ini +0 -7
  131. package/config/dnsbl.ini +0 -23
  132. package/config/greylist.ini +0 -43
  133. package/config/helo.checks.ini +0 -52
  134. package/config/lookup_rdns.strict.ini +0 -12
  135. package/config/lookup_rdns.strict.timeout +0 -1
  136. package/config/lookup_rdns.strict.whitelist +0 -1
  137. package/config/lookup_rdns.strict.whitelist_regex +0 -5
  138. package/config/messagesniffer.ini +0 -18
  139. package/config/rcpt_to.blocklist +0 -1
  140. package/config/rdns.allow_regexps +0 -0
  141. package/config/rdns.deny_regexps +0 -0
  142. package/config/spamassassin.ini +0 -56
  143. package/config.js +0 -6
  144. package/dkim.js +0 -614
  145. package/docs/plugins/avg.md +0 -35
  146. package/docs/plugins/bounce.md +0 -69
  147. package/docs/plugins/clamd.md +0 -147
  148. package/docs/plugins/esets.md +0 -8
  149. package/docs/plugins/greylist.md +0 -90
  150. package/docs/plugins/helo.checks.md +0 -135
  151. package/docs/plugins/messagesniffer.md +0 -163
  152. package/docs/plugins/relay_acl.md +0 -29
  153. package/docs/plugins/relay_all.md +0 -15
  154. package/docs/plugins/relay_force_routing.md +0 -33
  155. package/docs/plugins/spamassassin.md +0 -180
  156. package/outbound/mx_lookup.js +0 -70
  157. package/plugins/auth/auth_ldap.js +0 -3
  158. package/plugins/avg.js +0 -162
  159. package/plugins/backscatterer.js +0 -25
  160. package/plugins/bounce.js +0 -381
  161. package/plugins/clamd.js +0 -381
  162. package/plugins/data.headers.js +0 -4
  163. package/plugins/data.uribl.js +0 -4
  164. package/plugins/dkim_sign.js +0 -395
  165. package/plugins/dkim_verify.js +0 -62
  166. package/plugins/dns_list_base.js +0 -221
  167. package/plugins/dnsbl.js +0 -146
  168. package/plugins/dnswl.js +0 -58
  169. package/plugins/esets.js +0 -71
  170. package/plugins/graph.js +0 -5
  171. package/plugins/greylist.js +0 -645
  172. package/plugins/helo.checks.js +0 -533
  173. package/plugins/messagesniffer.js +0 -381
  174. package/plugins/rcpt_to.ldap.js +0 -3
  175. package/plugins/rcpt_to.max_count.js +0 -24
  176. package/plugins/relay_all.js +0 -13
  177. package/plugins/spamassassin.js +0 -384
  178. package/tests/config/dkim/example.com/dns +0 -29
  179. package/tests/config/dkim/example.com/private +0 -6
  180. package/tests/config/dkim/example.com/public +0 -4
  181. package/tests/config/dkim/example.com/selector +0 -1
  182. package/tests/config/dkim.private.key +0 -6
  183. package/tests/config/dkim_sign.ini +0 -4
  184. package/tests/config/helo.checks.ini +0 -52
  185. package/tests/connection.js +0 -327
  186. package/tests/endpoint.js +0 -128
  187. package/tests/fixtures/vm_harness.js +0 -59
  188. package/tests/logger.js +0 -327
  189. package/tests/outbound/hmail.js +0 -112
  190. package/tests/outbound/index.js +0 -324
  191. package/tests/outbound/qfile.js +0 -67
  192. package/tests/outbound_bounce_net_errors.js +0 -173
  193. package/tests/plugins/auth/auth_base.js +0 -463
  194. package/tests/plugins/auth/auth_vpopmaild.js +0 -91
  195. package/tests/plugins/bounce.js +0 -307
  196. package/tests/plugins/clamd.js +0 -224
  197. package/tests/plugins/deprecated/relay_acl.js +0 -140
  198. package/tests/plugins/deprecated/relay_all.js +0 -59
  199. package/tests/plugins/dkim_sign.js +0 -315
  200. package/tests/plugins/dkim_signer.js +0 -108
  201. package/tests/plugins/dns_list_base.js +0 -259
  202. package/tests/plugins/dnsbl.js +0 -101
  203. package/tests/plugins/early_talker.js +0 -115
  204. package/tests/plugins/greylist.js +0 -58
  205. package/tests/plugins/helo.checks.js +0 -525
  206. package/tests/plugins/mail_from.is_resolvable.js +0 -116
  207. package/tests/plugins/queue/smtp_forward.js +0 -221
  208. package/tests/plugins/rcpt_to.host_list_base.js +0 -132
  209. package/tests/plugins/rcpt_to.in_host_list.js +0 -218
  210. package/tests/plugins/relay.js +0 -339
  211. package/tests/plugins/spamassassin.js +0 -171
  212. package/tests/plugins/status.js +0 -138
  213. package/tests/plugins/tls.js +0 -84
  214. package/tests/plugins.js +0 -247
  215. package/tests/rfc1869.js +0 -61
  216. package/tests/server.js +0 -510
  217. package/tests/smtp_client/auth.js +0 -105
  218. package/tests/smtp_client/basic.js +0 -101
  219. package/tests/smtp_client.js +0 -80
  220. package/tests/tls_socket.js +0 -333
  221. package/tests/transaction.js +0 -284
  222. /package/docs/{plugins → deprecated}/dkim_sign.md +0 -0
  223. /package/docs/{plugins → deprecated}/dkim_verify.md +0 -0
  224. /package/docs/{plugins → deprecated}/dnsbl.md +0 -0
  225. /package/docs/{plugins → deprecated}/dnswl.md +0 -0
  226. /package/docs/{plugins → deprecated}/rcpt_to.routes.md +0 -0
  227. /package/{tests → test}/.eslintrc.yaml +0 -0
  228. /package/{tests → test}/config/auth_flat_file.ini +0 -0
  229. /package/{tests → test}/config/dhparams.pem +0 -0
  230. /package/{tests → test}/config/host_list +0 -0
  231. /package/{tests → test}/config/outbound_tls_cert.pem +0 -0
  232. /package/{tests → test}/config/outbound_tls_key.pem +0 -0
  233. /package/{tests → test}/config/smtp_forward.ini +0 -0
  234. /package/{tests → test}/config/tls/ec.pem +0 -0
  235. /package/{tests → test}/config/tls/haraka.local.pem +0 -0
  236. /package/{tests → test}/config/tls/mismatched.pem +0 -0
  237. /package/{tests → test}/config/tls.ini +0 -0
  238. /package/{tests → test}/config/tls_cert.pem +0 -0
  239. /package/{tests → test}/config/tls_key.pem +0 -0
  240. /package/{tests → test}/fixtures/todo_qfile.txt +0 -0
  241. /package/{tests → test}/installation/config/test-plugin-flat +0 -0
  242. /package/{tests → test}/installation/config/test-plugin.ini +0 -0
  243. /package/{tests → test}/installation/config/tls.ini +0 -0
  244. /package/{tests → test}/installation/node_modules/load_first/index.js +0 -0
  245. /package/{tests → test}/installation/node_modules/load_first/package.json +0 -0
  246. /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin-flat +0 -0
  247. /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin.ini +0 -0
  248. /package/{tests → test}/installation/node_modules/test-plugin/package.json +0 -0
  249. /package/{tests → test}/installation/node_modules/test-plugin/test-plugin.js +0 -0
  250. /package/{tests → test}/installation/plugins/base_plugin.js +0 -0
  251. /package/{tests → test}/installation/plugins/folder_plugin/index.js +0 -0
  252. /package/{tests → test}/installation/plugins/folder_plugin/package.json +0 -0
  253. /package/{tests → test}/installation/plugins/inherits.js +0 -0
  254. /package/{tests → test}/installation/plugins/load_first.js +0 -0
  255. /package/{tests → test}/installation/plugins/plugin.js +0 -0
  256. /package/{tests → test}/installation/plugins/tls.js +0 -0
  257. /package/{tests → test}/loud/config/dhparams.pem +0 -0
  258. /package/{tests → test}/loud/config/tls/goobered.pem +0 -0
  259. /package/{tests → test}/loud/config/tls.ini +0 -0
  260. /package/{tests → test}/mail_specimen/base64-root-part.txt +0 -0
  261. /package/{tests → test}/mail_specimen/varied-fold-lengths-preserve-data.txt +0 -0
  262. /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_fixed +0 -0
  263. /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_haraka +0 -0
  264. /package/{tests → test}/queue/1508269674999_1508269674999_0_34002_socVUF_1_haraka +0 -0
  265. /package/{tests → test}/queue/1508455115683_1508455115683_0_90253_9Q4o4V_1_haraka +0 -0
  266. /package/{tests → test}/queue/zero-length +0 -0
  267. /package/{tests → test}/test-queue/delete-me +0 -0
package/plugins/clamd.js DELETED
@@ -1,381 +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
- return next();
273
- }
274
- if (!plugin.cfg.reject.virus) { return next(); }
275
-
276
- // Check skip list exclusions
277
- for (const element of plugin.skip_list_exclude) {
278
- if (!element.test(virus)) continue;
279
- return next(DENY,
280
- `Message is infected with ${virus || 'UNKNOWN'}`);
281
- }
282
-
283
- // Check skip list
284
- for (const element of plugin.skip_list) {
285
- if (!element.test(virus)) continue;
286
- connection.logwarn(plugin, `${virus} matches exclusion`);
287
- txn.add_header('X-Haraka-Virus', virus);
288
- return next();
289
- }
290
- return next(DENY, `Message is infected with ${
291
- virus || 'UNKNOWN'}`);
292
- }
293
-
294
- if (/size limit exceeded/.test(result)) {
295
- txn.results.add(plugin, {
296
- err: 'INSTREAM size limit exceeded. Check ' +
297
- 'StreamMaxLength in clamd.conf',
298
- });
299
- // Continue as StreamMaxLength default is 25Mb
300
- return next();
301
- }
302
-
303
- // The current host returned an unknown result. If other hosts are available,
304
- // then try those before returning a DENYSOFT.
305
- if (hosts.length) {
306
- connection.logwarn(plugin, `unknown result: '${result}' from host ${host}`);
307
- socket.destroy();
308
- return try_next_host();
309
- }
310
- txn.results.add(plugin, { err: `unknown result: '${result}' from host ${host}`});
311
- if (!plugin.cfg.reject.error) return next();
312
- return next(DENYSOFT, 'Error running virus scanner');
313
- });
314
-
315
- clamd_connect(socket, host);
316
- }
317
-
318
- // Start the process
319
- try_next_host();
320
- }
321
-
322
- exports.should_check = function (connection) {
323
-
324
- let result = true; // default
325
- if (!connection?.transaction) return false
326
-
327
- if (this.cfg.check.authenticated == false && connection.notes.auth_user) {
328
- connection.transaction.results.add(this, { skip: 'authed'});
329
- result = false;
330
- }
331
-
332
- if (this.cfg.check.relay == false && connection.relaying) {
333
- connection.transaction.results.add(this, { skip: 'relay'});
334
- result = false;
335
- }
336
-
337
- if (this.cfg.check.local_ip == false && connection.remote.is_local) {
338
- connection.transaction.results.add(this, { skip: 'local_ip'});
339
- result = false;
340
- }
341
-
342
- if (this.cfg.check.private_ip == false && connection.remote.is_private) {
343
- if (this.cfg.check.local_ip == true && connection.remote.is_local) {
344
- // local IPs are included in private IPs
345
- }
346
- else {
347
- connection.transaction.results.add(this, { skip: 'private_ip'});
348
- result = false;
349
- }
350
- }
351
-
352
- return result;
353
- }
354
-
355
- exports.send_clamd_predata = (socket, cb) => {
356
- socket.write("zINSTREAM\0", () => {
357
- const received = 'Received: from Haraka clamd plugin\r\n';
358
- const buf = Buffer.alloc(received.length + 4);
359
- buf.writeUInt32BE(received.length, 0);
360
- buf.write(received, 4);
361
- socket.write(buf, cb)
362
- })
363
- }
364
-
365
- function clamd_connect (socket, host) {
366
-
367
- if (host.match(/^\//)) {
368
- socket.connect(host); // starts with /, unix socket
369
- return
370
- }
371
-
372
- const match = /^\[([^\] ]+)\](?::(\d+))?/.exec(host);
373
- if (match) {
374
- socket.connect((match[2] || 3310), match[1]); // IPv6 literal
375
- return
376
- }
377
-
378
- // IP:port, hostname:port or hostname
379
- const hostport = host.split(/:/);
380
- socket.connect((hostport[1] || 3310), hostport[0]);
381
- }
@@ -1,4 +0,0 @@
1
-
2
- exports.register = function () {
3
- this.logerror(this, "data.headers is deprecated, remove it from config/plugins. See 'haraka -h headers'");
4
- }
@@ -1,4 +0,0 @@
1
-
2
- exports.register = function () {
3
- this.logerror(this, "data.uribl was moved to haraka-plugin-uribl. Update the plugin name in config/plugins to just 'uribl'");
4
- }