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.
Files changed (239) hide show
  1. package/.eslintrc.yaml +4 -9
  2. package/CONTRIBUTORS.md +11 -0
  3. package/Changes.md +1397 -1213
  4. package/Plugins.md +117 -105
  5. package/README.md +4 -13
  6. package/bin/haraka +198 -298
  7. package/config/auth_flat_file.ini +1 -0
  8. package/config/dhparams.pem +8 -0
  9. package/config/mail_from.is_resolvable.ini +4 -2
  10. package/config/me +1 -0
  11. package/config/outbound.ini +0 -2
  12. package/config/plugins +35 -36
  13. package/config/smtp.ini +1 -1
  14. package/config/smtp.json +17 -0
  15. package/config/tls.ini +2 -0
  16. package/config/tls_cert.pem +23 -0
  17. package/config/tls_key.pem +28 -0
  18. package/connection.js +46 -73
  19. package/contrib/bsd-rc.d/haraka +3 -1
  20. package/contrib/plugin2npm.sh +6 -36
  21. package/docs/CoreConfig.md +2 -2
  22. package/docs/Logging.md +7 -21
  23. package/docs/Outbound.md +104 -201
  24. package/docs/Plugins.md +2 -2
  25. package/docs/Transaction.md +59 -82
  26. package/docs/plugins/queue/smtp_proxy.md +5 -10
  27. package/docs/plugins/tls.md +37 -9
  28. package/endpoint.js +16 -13
  29. package/haraka.js +10 -14
  30. package/host_pool.js +5 -5
  31. package/http/html/index.html +6 -5
  32. package/line_socket.js +3 -4
  33. package/logger.js +44 -28
  34. package/outbound/client_pool.js +27 -23
  35. package/outbound/config.js +4 -6
  36. package/outbound/fsync_writestream.js +1 -1
  37. package/outbound/hmail.js +178 -218
  38. package/outbound/index.js +86 -99
  39. package/outbound/qfile.js +1 -1
  40. package/outbound/queue.js +51 -44
  41. package/outbound/timer_queue.js +3 -2
  42. package/outbound/tls.js +19 -7
  43. package/package.json +60 -51
  44. package/plugins/.eslintrc.yaml +0 -6
  45. package/plugins/auth/auth_base.js +4 -2
  46. package/plugins/auth/auth_proxy.js +14 -12
  47. package/plugins/auth/auth_vpopmaild.js +1 -1
  48. package/plugins/block_me.js +1 -1
  49. package/plugins/data.signatures.js +2 -4
  50. package/plugins/early_talker.js +2 -1
  51. package/plugins/mail_from.is_resolvable.js +65 -135
  52. package/plugins/queue/deliver.js +4 -5
  53. package/plugins/queue/lmtp.js +11 -12
  54. package/plugins/queue/qmail-queue.js +2 -2
  55. package/plugins/queue/quarantine.js +2 -2
  56. package/plugins/queue/rabbitmq.js +16 -17
  57. package/plugins/queue/smtp_forward.js +3 -3
  58. package/plugins/queue/smtp_proxy.js +10 -1
  59. package/plugins/queue/test.js +2 -2
  60. package/plugins/rcpt_to.host_list_base.js +5 -5
  61. package/plugins/rcpt_to.in_host_list.js +2 -2
  62. package/plugins/relay.js +6 -7
  63. package/plugins/reseed_rng.js +1 -1
  64. package/plugins/status.js +37 -33
  65. package/plugins/tls.js +2 -2
  66. package/plugins/xclient.js +3 -2
  67. package/plugins.js +50 -54
  68. package/run_tests +3 -30
  69. package/server.js +190 -190
  70. package/smtp_client.js +30 -23
  71. package/{tests → test}/config/plugins +0 -2
  72. package/{tests → test}/config/smtp.ini +3 -1
  73. package/test/config/tls/example.com/_.example.com.key +28 -0
  74. package/test/config/tls/example.com/example.com.crt +25 -0
  75. package/{tests/loud → test}/config/tls.ini +4 -2
  76. package/test/connection.js +302 -0
  77. package/test/endpoint.js +94 -0
  78. package/{tests → test}/fixtures/line_socket.js +1 -1
  79. package/{tests → test}/fixtures/util_hmailitem.js +19 -25
  80. package/{tests → test}/host_pool.js +42 -57
  81. package/test/logger.js +258 -0
  82. package/test/outbound/hmail.js +141 -0
  83. package/test/outbound/index.js +220 -0
  84. package/test/outbound/qfile.js +126 -0
  85. package/test/outbound_bounce_net_errors.js +142 -0
  86. package/{tests → test}/outbound_bounce_rfc3464.js +110 -122
  87. package/test/plugins/auth/auth_base.js +484 -0
  88. package/test/plugins/auth/auth_vpopmaild.js +83 -0
  89. package/test/plugins/early_talker.js +104 -0
  90. package/test/plugins/mail_from.is_resolvable.js +35 -0
  91. package/test/plugins/queue/smtp_forward.js +206 -0
  92. package/test/plugins/rcpt_to.host_list_base.js +122 -0
  93. package/test/plugins/rcpt_to.in_host_list.js +193 -0
  94. package/test/plugins/relay.js +303 -0
  95. package/test/plugins/status.js +130 -0
  96. package/test/plugins/tls.js +70 -0
  97. package/test/plugins.js +228 -0
  98. package/test/rfc1869.js +73 -0
  99. package/test/server.js +491 -0
  100. package/test/smtp_client.js +299 -0
  101. package/test/tls_socket.js +277 -0
  102. package/test/transaction.js +270 -0
  103. package/tls_socket.js +202 -252
  104. package/transaction.js +8 -23
  105. package/CONTRIBUTING.md +0 -1
  106. package/bin/dkimverify +0 -40
  107. package/config/access.domains +0 -13
  108. package/config/attachment.ctype.regex +0 -2
  109. package/config/attachment.filename.regex +0 -1
  110. package/config/avg.ini +0 -5
  111. package/config/bounce.ini +0 -15
  112. package/config/data.headers.ini +0 -61
  113. package/config/dkim/dkim_key_gen.sh +0 -78
  114. package/config/dkim_sign.ini +0 -4
  115. package/config/dkim_verify.ini +0 -7
  116. package/config/dnsbl.ini +0 -23
  117. package/config/greylist.ini +0 -43
  118. package/config/helo.checks.ini +0 -52
  119. package/config/messagesniffer.ini +0 -18
  120. package/config/spamassassin.ini +0 -56
  121. package/dkim.js +0 -614
  122. package/docs/plugins/avg.md +0 -35
  123. package/docs/plugins/bounce.md +0 -69
  124. package/docs/plugins/clamd.md +0 -147
  125. package/docs/plugins/esets.md +0 -8
  126. package/docs/plugins/greylist.md +0 -90
  127. package/docs/plugins/helo.checks.md +0 -135
  128. package/docs/plugins/messagesniffer.md +0 -163
  129. package/docs/plugins/spamassassin.md +0 -180
  130. package/outbound/mx_lookup.js +0 -70
  131. package/plugins/auth/auth_ldap.js +0 -3
  132. package/plugins/avg.js +0 -162
  133. package/plugins/backscatterer.js +0 -25
  134. package/plugins/bounce.js +0 -381
  135. package/plugins/clamd.js +0 -382
  136. package/plugins/data.uribl.js +0 -4
  137. package/plugins/dkim_sign.js +0 -395
  138. package/plugins/dkim_verify.js +0 -62
  139. package/plugins/dns_list_base.js +0 -221
  140. package/plugins/dnsbl.js +0 -146
  141. package/plugins/dnswl.js +0 -58
  142. package/plugins/esets.js +0 -71
  143. package/plugins/graph.js +0 -5
  144. package/plugins/greylist.js +0 -645
  145. package/plugins/helo.checks.js +0 -533
  146. package/plugins/messagesniffer.js +0 -381
  147. package/plugins/rcpt_to.ldap.js +0 -3
  148. package/plugins/rcpt_to.max_count.js +0 -24
  149. package/plugins/spamassassin.js +0 -384
  150. package/tests/config/dkim/example.com/dns +0 -29
  151. package/tests/config/dkim/example.com/private +0 -6
  152. package/tests/config/dkim/example.com/public +0 -4
  153. package/tests/config/dkim/example.com/selector +0 -1
  154. package/tests/config/dkim.private.key +0 -6
  155. package/tests/config/dkim_sign.ini +0 -4
  156. package/tests/config/helo.checks.ini +0 -52
  157. package/tests/connection.js +0 -327
  158. package/tests/endpoint.js +0 -128
  159. package/tests/fixtures/vm_harness.js +0 -59
  160. package/tests/logger.js +0 -327
  161. package/tests/outbound/hmail.js +0 -112
  162. package/tests/outbound/index.js +0 -324
  163. package/tests/outbound/qfile.js +0 -67
  164. package/tests/outbound_bounce_net_errors.js +0 -173
  165. package/tests/plugins/auth/auth_base.js +0 -463
  166. package/tests/plugins/auth/auth_vpopmaild.js +0 -91
  167. package/tests/plugins/bounce.js +0 -307
  168. package/tests/plugins/clamd.js +0 -224
  169. package/tests/plugins/deprecated/relay_acl.js +0 -140
  170. package/tests/plugins/deprecated/relay_all.js +0 -59
  171. package/tests/plugins/dkim_sign.js +0 -315
  172. package/tests/plugins/dkim_signer.js +0 -108
  173. package/tests/plugins/dns_list_base.js +0 -259
  174. package/tests/plugins/dnsbl.js +0 -101
  175. package/tests/plugins/early_talker.js +0 -115
  176. package/tests/plugins/greylist.js +0 -58
  177. package/tests/plugins/helo.checks.js +0 -525
  178. package/tests/plugins/mail_from.is_resolvable.js +0 -116
  179. package/tests/plugins/queue/smtp_forward.js +0 -221
  180. package/tests/plugins/rcpt_to.host_list_base.js +0 -132
  181. package/tests/plugins/rcpt_to.in_host_list.js +0 -218
  182. package/tests/plugins/relay.js +0 -339
  183. package/tests/plugins/spamassassin.js +0 -171
  184. package/tests/plugins/status.js +0 -138
  185. package/tests/plugins/tls.js +0 -84
  186. package/tests/plugins.js +0 -247
  187. package/tests/rfc1869.js +0 -61
  188. package/tests/server.js +0 -510
  189. package/tests/smtp_client/auth.js +0 -105
  190. package/tests/smtp_client/basic.js +0 -101
  191. package/tests/smtp_client.js +0 -80
  192. package/tests/tls_socket.js +0 -333
  193. package/tests/transaction.js +0 -284
  194. /package/docs/{plugins → deprecated}/dkim_sign.md +0 -0
  195. /package/docs/{plugins → deprecated}/dkim_verify.md +0 -0
  196. /package/docs/{plugins → deprecated}/dnsbl.md +0 -0
  197. /package/docs/{plugins → deprecated}/dnswl.md +0 -0
  198. /package/{tests → test}/.eslintrc.yaml +0 -0
  199. /package/{tests → test}/config/auth_flat_file.ini +0 -0
  200. /package/{tests → test}/config/dhparams.pem +0 -0
  201. /package/{tests → test}/config/host_list +0 -0
  202. /package/{tests → test}/config/outbound_tls_cert.pem +0 -0
  203. /package/{tests → test}/config/outbound_tls_key.pem +0 -0
  204. /package/{tests → test}/config/smtp_forward.ini +0 -0
  205. /package/{tests → test}/config/tls/ec.pem +0 -0
  206. /package/{tests → test}/config/tls/haraka.local.pem +0 -0
  207. /package/{tests → test}/config/tls/mismatched.pem +0 -0
  208. /package/{tests → test}/config/tls_cert.pem +0 -0
  209. /package/{tests → test}/config/tls_key.pem +0 -0
  210. /package/{tests → test}/fixtures/todo_qfile.txt +0 -0
  211. /package/{tests → test}/installation/config/test-plugin-flat +0 -0
  212. /package/{tests → test}/installation/config/test-plugin.ini +0 -0
  213. /package/{tests → test}/installation/config/tls.ini +0 -0
  214. /package/{tests → test}/installation/node_modules/load_first/index.js +0 -0
  215. /package/{tests → test}/installation/node_modules/load_first/package.json +0 -0
  216. /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin-flat +0 -0
  217. /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin.ini +0 -0
  218. /package/{tests → test}/installation/node_modules/test-plugin/package.json +0 -0
  219. /package/{tests → test}/installation/node_modules/test-plugin/test-plugin.js +0 -0
  220. /package/{tests → test}/installation/plugins/base_plugin.js +0 -0
  221. /package/{tests → test}/installation/plugins/folder_plugin/index.js +0 -0
  222. /package/{tests → test}/installation/plugins/folder_plugin/package.json +0 -0
  223. /package/{tests → test}/installation/plugins/inherits.js +0 -0
  224. /package/{tests → test}/installation/plugins/load_first.js +0 -0
  225. /package/{tests → test}/installation/plugins/plugin.js +0 -0
  226. /package/{tests → test}/installation/plugins/tls.js +0 -0
  227. /package/{tests → test}/loud/config/dhparams.pem +0 -0
  228. /package/{tests → test}/loud/config/tls/goobered.pem +0 -0
  229. /package/{tests → test/loud}/config/tls.ini +0 -0
  230. /package/{tests → test}/mail_specimen/base64-root-part.txt +0 -0
  231. /package/{tests → test}/mail_specimen/varied-fold-lengths-preserve-data.txt +0 -0
  232. /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_fixed +0 -0
  233. /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_haraka +0 -0
  234. /package/{tests → test}/queue/1508269674999_1508269674999_0_34002_socVUF_1_haraka +0 -0
  235. /package/{tests → test}/queue/1508455115683_1508455115683_0_90253_9Q4o4V_1_haraka +0 -0
  236. /package/{tests → test}/queue/multibyte +0 -0
  237. /package/{tests → test}/queue/plain +0 -0
  238. /package/{tests → test}/queue/zero-length +0 -0
  239. /package/{tests → test}/test-queue/delete-me +0 -0
@@ -0,0 +1,299 @@
1
+ const assert = require('node:assert')
2
+ const path = require('node:path');
3
+
4
+ const fixtures = require('haraka-test-fixtures');
5
+ const message = require('haraka-email-message')
6
+
7
+ const smtp_client = require('../smtp_client');
8
+ const test_socket = require('./fixtures/line_socket')
9
+
10
+ function getClientOpts (socket) {
11
+ return { port: 25, host: 'localhost', connect_timeout: 30, idle_timeout: 30, socket }
12
+ }
13
+
14
+ describe('smtp_client', () => {
15
+
16
+ it('testUpgradeIsCalledOnSTARTTLS', () => {
17
+
18
+ const plugin = new fixtures.plugin('queue/smtp_forward');
19
+
20
+ // switch config directory to 'test/config'
21
+ plugin.config = plugin.config.module_config(path.resolve('test'));
22
+
23
+ plugin.register();
24
+
25
+ const cmds = {};
26
+ let upgradeArgs = {};
27
+
28
+ const socket = {
29
+ setTimeout: arg => { },
30
+ setKeepAlive: arg => { },
31
+ on: (eventName, callback) => {
32
+ cmds[eventName] = callback;
33
+ },
34
+ upgrade: arg => {
35
+ upgradeArgs = arg;
36
+ }
37
+ }
38
+
39
+ const client = new smtp_client.smtp_client(getClientOpts(socket));
40
+ client.load_tls_config({ key: Buffer.from('OutboundTlsKeyLoaded')});
41
+
42
+ client.command = 'starttls';
43
+ cmds.line('250 Hello client.example.com\r\n');
44
+
45
+ const { StringDecoder } = require('string_decoder');
46
+ const decoder = new StringDecoder('utf8');
47
+
48
+ const cent = Buffer.from(upgradeArgs.key);
49
+ assert.equal(decoder.write(cent), 'OutboundTlsKeyLoaded');
50
+ })
51
+
52
+ it('startTLS', () => {
53
+
54
+ let cmd = '';
55
+
56
+ const socket = {
57
+ setTimeout: arg => { },
58
+ setKeepAlive: arg => { },
59
+ on: (eventName, callback) => { },
60
+ upgrade: arg => { },
61
+ write: arg => { cmd = arg; }
62
+ };
63
+
64
+ const client = new smtp_client.smtp_client(getClientOpts(socket));
65
+ client.tls_options = {};
66
+
67
+ client.secured = false;
68
+ client.response = [ 'STARTTLS' ]
69
+
70
+ smtp_client.onCapabilitiesOutbound(client, false, undefined, { 'enable_tls': true });
71
+
72
+ assert.equal(cmd, 'STARTTLS\r\n');
73
+ })
74
+
75
+ describe('auth', () => {
76
+
77
+ beforeEach((done) => {
78
+ smtp_client.get_client({ notes: {}}, (client) => {
79
+ this.client = client
80
+ done()
81
+ },
82
+ {
83
+ socket: test_socket.connect(),
84
+ }
85
+ )
86
+ })
87
+
88
+ it('authenticates during SMTP conversation', (done) => {
89
+
90
+ const message_stream = new message.stream(
91
+ { main : { spool_after : 1024 } }, "123456789"
92
+ );
93
+
94
+ const data = [];
95
+ let reading_body = false;
96
+ data.push('220 hi');
97
+
98
+ this.client.on('greeting', command => {
99
+ assert.equal(this.client.response[0], 'hi');
100
+ assert.equal('EHLO', command);
101
+ this.client.send_command(command, 'example.com');
102
+ });
103
+
104
+ data.push('EHLO example.com');
105
+ data.push('250 hello');
106
+
107
+ this.client.on('helo', () => {
108
+ assert.equal(this.client.response[0], 'hello');
109
+ this.client.send_command('AUTH', 'PLAIN AHRlc3QAdGVzdHBhc3M=');
110
+ this.client.send_command('MAIL', 'FROM: me@example.com');
111
+ });
112
+
113
+ data.push('AUTH PLAIN AHRlc3QAdGVzdHBhc3M='); // test/testpass
114
+ data.push('235 Authentication successful.');
115
+
116
+ data.push('MAIL FROM: me@example.com');
117
+ data.push('250 sender ok');
118
+
119
+ this.client.on('mail', () => {
120
+ assert.equal(this.client.response[0], 'sender ok');
121
+ this.client.send_command('RCPT', 'TO: you@example.com');
122
+ });
123
+
124
+ data.push('RCPT TO: you@example.com');
125
+ data.push('250 recipient ok');
126
+
127
+ this.client.on('rcpt', () => {
128
+ assert.equal(this.client.response[0], 'recipient ok');
129
+ this.client.send_command('DATA');
130
+ });
131
+
132
+ data.push('DATA');
133
+ data.push('354 go ahead');
134
+
135
+ this.client.on('data', () => {
136
+ assert.equal(this.client.response[0], 'go ahead');
137
+ this.client.start_data(message_stream);
138
+ message_stream.on('end', () => {
139
+ this.client.socket.write('.\r\n');
140
+ });
141
+ message_stream.add_line('Header: test\r\n');
142
+ message_stream.add_line('\r\n');
143
+ message_stream.add_line('hi\r\n');
144
+ message_stream.add_line_end();
145
+ });
146
+
147
+ data.push('.');
148
+ data.push('250 message queued');
149
+
150
+ this.client.on('dot', () => {
151
+ assert.equal(this.client.response[0], 'message queued');
152
+ this.client.send_command('QUIT');
153
+ });
154
+
155
+ data.push('QUIT');
156
+ data.push('221 goodbye');
157
+
158
+ this.client.on('quit', () => {
159
+ assert.equal(this.client.response[0], 'goodbye');
160
+ done()
161
+ });
162
+
163
+ this.client.socket.write = function (line) {
164
+ if (data.length == 0) {
165
+ assert.ok(false);
166
+ return;
167
+ }
168
+ assert.equal(`${data.shift()}\r\n`, line);
169
+ if (reading_body && line == '.\r\n') {
170
+ reading_body = false;
171
+ }
172
+ if (!reading_body) {
173
+ if (line == 'DATA\r\n') {
174
+ reading_body = true;
175
+ }
176
+ while (true) {
177
+ const line2 = data.shift();
178
+ this.emit('line', `${line2}\r\n`);
179
+ if (line2[3] == ' ') break;
180
+ }
181
+ }
182
+
183
+ return true;
184
+ };
185
+
186
+ this.client.socket.emit('line', data.shift());
187
+ })
188
+ })
189
+
190
+ describe('basic', () => {
191
+
192
+ beforeEach((done) => {
193
+ smtp_client.get_client({notes: {}}, (client) => {
194
+ this.client = client
195
+ done()
196
+ },
197
+ {
198
+ socket: test_socket.connect(),
199
+ })
200
+ })
201
+
202
+ it('conducts a SMTP session', (done) => {
203
+
204
+ const message_stream = new message.stream(
205
+ { main : { spool_after : 1024 } }, '123456789'
206
+ );
207
+
208
+ const data = [];
209
+ let reading_body = false;
210
+ data.push('220 hi');
211
+
212
+ this.client.on('greeting', command => {
213
+ assert.equal(this.client.response[0], 'hi');
214
+ assert.equal('EHLO', command);
215
+ this.client.send_command(command, 'example.com');
216
+ });
217
+
218
+ data.push('EHLO example.com');
219
+ data.push('250 hello');
220
+
221
+ this.client.on('helo', () => {
222
+ assert.equal(this.client.response[0], 'hello');
223
+ this.client.send_command('MAIL', 'FROM: me@example.com');
224
+ });
225
+
226
+ data.push('MAIL FROM: me@example.com');
227
+ data.push('250 sender ok');
228
+
229
+ this.client.on('mail', () => {
230
+ assert.equal(this.client.response[0], 'sender ok');
231
+ this.client.send_command('RCPT', 'TO: you@example.com');
232
+ });
233
+
234
+ data.push('RCPT TO: you@example.com');
235
+ data.push('250 recipient ok');
236
+
237
+ this.client.on('rcpt', () => {
238
+ assert.equal(this.client.response[0], 'recipient ok');
239
+ this.client.send_command('DATA');
240
+ });
241
+
242
+ data.push('DATA');
243
+ data.push('354 go ahead');
244
+
245
+ this.client.on('data', () => {
246
+ assert.equal(this.client.response[0], 'go ahead');
247
+ this.client.start_data(message_stream);
248
+ message_stream.on('end', () => {
249
+ this.client.socket.write('.\r\n');
250
+ });
251
+ message_stream.add_line('Header: test\r\n');
252
+ message_stream.add_line('\r\n');
253
+ message_stream.add_line('hi\r\n');
254
+ message_stream.add_line_end();
255
+ });
256
+
257
+ data.push('.');
258
+ data.push('250 message queued');
259
+
260
+ this.client.on('dot', () => {
261
+ assert.equal(this.client.response[0], 'message queued');
262
+ this.client.send_command('QUIT');
263
+ });
264
+
265
+ data.push('QUIT');
266
+ data.push('221 goodbye');
267
+
268
+ this.client.on('quit', () => {
269
+ assert.equal(this.client.response[0], 'goodbye');
270
+ done()
271
+ });
272
+
273
+ this.client.socket.write = function (line) {
274
+ if (data.length == 0) {
275
+ assert.ok(false);
276
+ return;
277
+ }
278
+ assert.equal(`${data.shift() }\r\n`, line);
279
+ if (reading_body && line == '.\r\n') {
280
+ reading_body = false;
281
+ }
282
+ if (reading_body) return true;
283
+
284
+ if (line == 'DATA\r\n') {
285
+ reading_body = true;
286
+ }
287
+ while (true) {
288
+ const line2 = data.shift();
289
+ this.emit('line', `${line2 }\r\n`);
290
+ if (line2[3] == ' ') break;
291
+ }
292
+
293
+ return true;
294
+ };
295
+
296
+ this.client.socket.emit('line', data.shift());
297
+ })
298
+ })
299
+ })
@@ -0,0 +1,277 @@
1
+ const assert = require('node:assert')
2
+ const fs = require('node:fs/promises')
3
+ const path = require('node:path')
4
+ const os = require('node:os')
5
+
6
+ const _setup = (done) => {
7
+ this.socket = require('../tls_socket');
8
+
9
+ // use test/config instead of ./config
10
+ this.socket.config = this.socket.config.module_config(path.resolve('test'));
11
+ done();
12
+ }
13
+
14
+ describe('tls_socket', () => {
15
+ beforeEach(_setup)
16
+
17
+ it('loads', () => {
18
+ assert.ok(this.socket);
19
+ })
20
+ it('exports createConnection', () => {
21
+ assert.equal(typeof this.socket.createConnection, 'function');
22
+ })
23
+ it('exports createServer', () => {
24
+ // console.log(this.socket);
25
+ assert.equal(typeof this.socket.createServer, 'function');
26
+ })
27
+ it('exports shutdown', () => {
28
+ // console.log(this.socket);
29
+ assert.equal(typeof this.socket.shutdown, 'function');
30
+ })
31
+
32
+ describe('createServer', () => {
33
+ beforeEach(_setup)
34
+
35
+ it('returns a net.Server', () => {
36
+ const server = this.socket.createServer(sock => {
37
+ // TODO: socket test?
38
+ })
39
+ assert.ok(server)
40
+ })
41
+ })
42
+
43
+ describe('load_tls_ini', () => {
44
+ beforeEach(_setup)
45
+
46
+ it('tls.ini loads', () => {
47
+ assert.ok(this.socket.load_tls_ini().main !== undefined);
48
+ assert.ok(this.socket.certsByHost['*'].key);
49
+ // console.log(this.socket.cfg);
50
+ // console.log(this.socket.certsByHost);
51
+ })
52
+ })
53
+
54
+ describe('get_loud_certs_dir', () => {
55
+ beforeEach(_setup)
56
+
57
+ it('loads certs from test/loud/config/tls', async () => {
58
+ this.socket.config = this.socket.config.module_config(path.resolve('test', 'loud'));
59
+ this.socket.load_tls_ini()
60
+ const certs = await this.socket.get_certs_dir('tls')
61
+ assert.ok(certs);
62
+ })
63
+ })
64
+
65
+ describe('get_certs_dir', () => {
66
+ beforeEach(_setup)
67
+
68
+ it('loads certs from test/config/tls', async () => {
69
+ this.socket.config = this.socket.config.module_config(path.resolve('test'));
70
+ this.socket.load_tls_ini()
71
+ try {
72
+ const certs = await this.socket.get_certs_dir('tls')
73
+ assert.ok(certs['*'])
74
+ assert.ok(certs['mail.haraka.io'])
75
+ assert.ok(certs['haraka.local'])
76
+ assert.ok(certs['*.example.com'])
77
+ }
78
+ catch (err) {
79
+ assert.ifError(err);
80
+ }
81
+ })
82
+ })
83
+
84
+ describe('getSocketOpts', () => {
85
+ beforeEach(_setup)
86
+
87
+ it('gets socket opts for *', async () => {
88
+ const certs = await this.socket.get_certs_dir('tls')
89
+ this.socket.getSocketOpts('*').then(opts => {
90
+ // console.log(opts);
91
+ assert.ok(opts.key);
92
+ assert.ok(opts.cert);
93
+ })
94
+ })
95
+ })
96
+
97
+ describe('ensureDhparams', () => {
98
+ beforeEach(_setup)
99
+ it('generates a missing dhparams file', () => {
100
+ this.socket.load_tls_ini();
101
+ this.socket.ensureDhparams((err, dhparams) => {
102
+ // console.log(dhparams);
103
+ assert.ifError(err);
104
+ assert.ok(dhparams);
105
+ })
106
+ })
107
+ })
108
+
109
+ describe('load_tls_ini2', () => {
110
+ beforeEach((done) => {
111
+ this.socket = require('../tls_socket');
112
+ delete process.env.HARAKA_TEST_DIR;
113
+ done();
114
+ })
115
+
116
+ it('loads missing tls.ini default config', () => {
117
+ this.socket.config = this.socket.config.module_config(path.resolve('non-exist'));
118
+ assert.deepEqual(this.socket.load_tls_ini(),
119
+ {
120
+ main: {
121
+ requestCert: true,
122
+ rejectUnauthorized: false,
123
+ honorCipherOrder: true,
124
+ requestOCSP: false,
125
+ // enableOCSPStapling: false,
126
+ requireAuthorized: [],
127
+ mutual_tls: false,
128
+ no_starttls_ports: [],
129
+ },
130
+ redis: { disable_for_failed_hosts: false },
131
+ no_tls_hosts: {},
132
+ mutual_auth_hosts: {},
133
+ mutual_auth_hosts_exclude: {},
134
+ });
135
+ })
136
+
137
+ it('loads tls.ini from test dir', () => {
138
+ this.socket.config = this.socket.config.module_config(path.resolve('test'));
139
+ assert.deepEqual(this.socket.load_tls_ini(), {
140
+ main: {
141
+ requestCert: true,
142
+ rejectUnauthorized: false,
143
+ honorCipherOrder: true,
144
+ requestOCSP: false,
145
+ key: 'tls_key.pem',
146
+ cert: 'tls_cert.pem',
147
+ dhparam: 'dhparams.pem',
148
+ ciphers: 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384',
149
+ minVersion: 'TLSv1',
150
+ requireAuthorized: [2465, 2587],
151
+ mutual_tls: false,
152
+ no_starttls_ports: [2525],
153
+ },
154
+ redis: { disable_for_failed_hosts: false },
155
+ no_tls_hosts: {
156
+ '192.168.1.1': undefined,
157
+ '172.16.0.0/16': undefined,
158
+ },
159
+ mutual_auth_hosts: {},
160
+ mutual_auth_hosts_exclude: {},
161
+ outbound: {
162
+ key: 'outbound_tls_key.pem',
163
+ cert: 'outbound_tls_cert.pem',
164
+ ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
165
+ minVersion: 'TLSv1',
166
+ dhparam: 'dhparams.pem',
167
+ rejectUnauthorized: false,
168
+ requestCert: false,
169
+ honorCipherOrder: false,
170
+ force_tls_hosts: ['first.example.com', 'second.example.net'],
171
+ no_tls_hosts: ['127.0.0.2', '192.168.31.1/24'],
172
+ }
173
+ })
174
+ })
175
+ })
176
+
177
+ describe('parse_x509', () => {
178
+ beforeEach(_setup)
179
+
180
+ it('returns empty object on empty input', async () => {
181
+ const res = await this.socket.parse_x509()
182
+ assert.deepEqual(res, {});
183
+ })
184
+
185
+ it('returns key from BEGIN PRIVATE KEY block', async () => {
186
+ const res = await this.socket.parse_x509('-BEGIN PRIVATE KEY-\nhello\n--END PRIVATE KEY--\n-its me-\n');
187
+ assert.deepEqual(
188
+ res.keys[0].toString(),
189
+ '-BEGIN PRIVATE KEY-\nhello\n--END PRIVATE KEY--',
190
+ );
191
+ assert.deepEqual(res.cert, undefined);
192
+ })
193
+
194
+ it('returns key from BEGIN RSA PRIVATE KEY block', async () => {
195
+ const res = await this.socket.parse_x509('-BEGIN RSA PRIVATE KEY-\nhello\n--END RSA PRIVATE KEY--\n-its me-\n');
196
+ assert.deepEqual(
197
+ res.keys[0].toString(),
198
+ '-BEGIN RSA PRIVATE KEY-\nhello\n--END RSA PRIVATE KEY--',
199
+ );
200
+ assert.deepEqual(res.cert, undefined);
201
+ })
202
+
203
+ it.skip('returns a key and certificate chain', async () => {
204
+ // doesn't work, b/c parse now parses and needs non-snipped
205
+ const str = `-----BEGIN RSA PRIVATE KEY-----
206
+ MIIEogIBAAKCAQEAoDGOlvw6lQptaNwqxYsW4aJCPIgvjYw3qA9Y0qykp8I8PapT
207
+ ercA8BsInrZg5+3wt2PT1+REprBvv6xfHyQ08o/udsSCBRf4Awadp0fxzUulENNi
208
+ 3wWuuPy0WgaE4jam7tWItDBeEhXkEfcMTr9XkFxenuTcNw9O1+E8TtNP9KMmJDAe
209
+ <snip>
210
+ F+T5AoGAMRH1+JrjTpPYcs1hOyHMWnxkHv7fsJMJY/KN2NPoTlI4d4V1W5xyCZ0D
211
+ rl7RlVdVTQdZ9VjkWVjJcafNSmNyQEK4IQsaczwOU59IPhC/nUAyRgeoRbKWPQ4r
212
+ mj3g7uX9f07j34c01mH1zLgDa24LO9SW7B5ZbYYu4DORk7005B4=
213
+ -----END RSA PRIVATE KEY-----
214
+ -----BEGIN CERTIFICATE-----
215
+ MIIFVzCCBD+gAwIBAgISA/5ofbB6cUAp/PrYaBxTITF2MA0GCSqGSIb3DQEBCwUA
216
+ MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
217
+ <snip>
218
+ kOk4JdlpuBSPwx9wNAEYF15/4LDyev+tyAg7GxCZ9MW53leOxF+j2NQgc4kRIdQc
219
+ DYsruShsnwn4HErJKQAfE5Aq77UM32hfKzMb2PH6Ebw0TB2NCLVocOULAGTw4NPO
220
+ wBpsGsIFUxeDHZvhKohZyNqLrj7gR+XlKRKM
221
+ -----END CERTIFICATE-----
222
+
223
+ -----BEGIN CERTIFICATE-----
224
+ MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
225
+ TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
226
+ cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
227
+ <snip>
228
+ HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
229
+ MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
230
+ nLRbwHOoq7hHwg==
231
+ -----END CERTIFICATE-----
232
+
233
+ -----BEGIN CERTIFICATE-----
234
+ MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
235
+ MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
236
+ DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
237
+ <snip>
238
+ WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
239
+ he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
240
+ Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
241
+ -----END CERTIFICATE-----`
242
+ const res = await this.socket.parse_x509(str);
243
+ assert.deepEqual(res.key.length, 446);
244
+ assert.deepEqual(res.cert.length, 1195);
245
+ })
246
+
247
+ it('returns cert and key from EC pem', async () => {
248
+ const fp = await fs.readFile(path.join('test','config','tls','ec.pem'))
249
+ const res = await this.socket.parse_x509(fp.toString())
250
+ assert.deepEqual(
251
+ res.keys[0].toString().split(os.EOL).join('\n'),
252
+ `-----BEGIN EC PRIVATE KEY-----
253
+ MHcCAQEEIIDhiI5q6l7txfMJ6kIEYjK12EFcHLvDIkfWIwzdZBsloAoGCCqGSM49
254
+ AwEHoUQDQgAEZg2nHEFy9nquFPF3DQyQE28e/ytjXeb4nD/8U+L4KHKFtglaX3R4
255
+ uZ+5JcwfcDghpL4Z8h4ouUD/xqe957e2+g==
256
+ -----END EC PRIVATE KEY-----`
257
+ );
258
+ assert.deepEqual(
259
+ res.chain[0].toString().split(os.EOL).join('\n'),
260
+ `-----BEGIN CERTIFICATE-----
261
+ MIICaTCCAg+gAwIBAgIUEDa9VX16wCdo97WvIk7jyEBz1wQwCgYIKoZIzj0EAwIw
262
+ gYkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT
263
+ ZWF0dGxlMRQwEgYDVQQKDAtIYXJha2EgTWFpbDEXMBUGA1UEAwwObWFpbC5oYXJh
264
+ a2EuaW8xJDAiBgkqhkiG9w0BCQEWFWhhcmFrYS5tYWlsQGdtYWlsLmNvbTAeFw0y
265
+ MTEwMTQwNjQxMTlaFw0yMjEwMTQwNjQxMTlaMIGJMQswCQYDVQQGEwJVUzETMBEG
266
+ A1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEUMBIGA1UECgwLSGFy
267
+ YWthIE1haWwxFzAVBgNVBAMMDm1haWwuaGFyYWthLmlvMSQwIgYJKoZIhvcNAQkB
268
+ FhVoYXJha2EubWFpbEBnbWFpbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
269
+ AARmDaccQXL2eq4U8XcNDJATbx7/K2Nd5vicP/xT4vgocoW2CVpfdHi5n7klzB9w
270
+ OCGkvhnyHii5QP/Gp73nt7b6o1MwUTAdBgNVHQ4EFgQU094ROMLHmLEspT4ZoCfX
271
+ Rz0mR/YwHwYDVR0jBBgwFoAU094ROMLHmLEspT4ZoCfXRz0mR/YwDwYDVR0TAQH/
272
+ BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAsmshzvMDjmYDHyGRrKdMmsnnESFd
273
+ GMtfRXYIv0AZe7ICIGD2Sta9LL0zZ44ARGXhh+sPjxd78I/+0FdIPsofr2I+
274
+ -----END CERTIFICATE-----`);
275
+ })
276
+ })
277
+ })