Haraka 3.1.2 → 3.1.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 (66) hide show
  1. package/.prettierignore +2 -0
  2. package/CONTRIBUTORS.md +24 -2
  3. package/Changes.md +48 -0
  4. package/Plugins.md +81 -64
  5. package/README.md +1 -1
  6. package/bin/haraka +9 -7
  7. package/config/connection.ini +10 -0
  8. package/config/smtp.ini +0 -9
  9. package/connection.js +15 -19
  10. package/docs/CoreConfig.md +2 -3
  11. package/docs/Plugins.md +1 -1
  12. package/docs/plugins/aliases.md +0 -2
  13. package/docs/plugins/queue/qmail-queue.md +0 -1
  14. package/docs/tutorials/Migrating_from_v1_to_v2.md +1 -1
  15. package/logger.js +2 -2
  16. package/outbound/client_pool.js +1 -1
  17. package/outbound/hmail.js +76 -83
  18. package/outbound/index.js +36 -34
  19. package/outbound/queue.js +231 -176
  20. package/package.json +29 -31
  21. package/plugins/prevent_credential_leaks.js +2 -2
  22. package/plugins/process_title.js +1 -1
  23. package/plugins/queue/smtp_forward.js +1 -1
  24. package/plugins/status.js +8 -5
  25. package/plugins/tls.js +1 -1
  26. package/plugins.js +19 -14
  27. package/rfc1869.js +10 -10
  28. package/run_tests +20 -2
  29. package/server.js +15 -10
  30. package/smtp_client.js +2 -9
  31. package/test/config/tls/haraka.local.pem +47 -47
  32. package/test/connection.js +286 -147
  33. package/test/fixtures/line_socket.js +1 -0
  34. package/test/fixtures/util_hmailitem.js +1 -1
  35. package/test/outbound/bounce_net_errors.js +176 -0
  36. package/test/outbound/bounce_rfc3464.js +303 -0
  37. package/test/outbound/hmail.js +140 -104
  38. package/test/outbound/index.js +61 -101
  39. package/test/outbound/qfile.js +25 -25
  40. package/test/outbound/queue.js +233 -0
  41. package/test/plugins/queue/smtp_forward.js +1 -1
  42. package/test/plugins/record_envelope_addresses.js +93 -0
  43. package/test/plugins/tls.js +2 -2
  44. package/test/plugins/xclient.js +137 -0
  45. package/test/rfc1869.js +43 -0
  46. package/test/smtp_client.js +6 -6
  47. package/test/transaction.js +486 -201
  48. package/tls_socket.js +3 -3
  49. package/transaction.js +33 -10
  50. package/config/me +0 -1
  51. package/config/rabbitmq.ini +0 -10
  52. package/config/rabbitmq_amqplib.ini +0 -19
  53. package/config/tls_cert.pem +0 -23
  54. package/config/tls_key.pem +0 -28
  55. package/docs/plugins/queue/rabbitmq.md +0 -34
  56. package/docs/plugins/queue/rabbitmq_amqplib.md +0 -51
  57. package/plugins/queue/rabbitmq.js +0 -141
  58. package/plugins/queue/rabbitmq_amqplib.js +0 -96
  59. package/test/config/tls/ec.pem +0 -23
  60. package/test/config/tls/mismatched.pem +0 -49
  61. package/test/outbound_bounce_net_errors.js +0 -157
  62. package/test/outbound_bounce_rfc3464.js +0 -366
  63. package/test/queue/multibyte +0 -0
  64. package/test/queue/plain +0 -0
  65. package/test/test-queue/delete-me +0 -0
  66. package/test/tls_socket.js +0 -273
@@ -1,273 +0,0 @@
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
- } catch (err) {
78
- assert.ifError(err)
79
- }
80
- })
81
- })
82
-
83
- describe('getSocketOpts', () => {
84
- beforeEach(_setup)
85
-
86
- it('gets socket opts for *', async () => {
87
- const certs = await this.socket.get_certs_dir('tls')
88
- this.socket.getSocketOpts('*').then((opts) => {
89
- // console.log(opts);
90
- assert.ok(opts.key)
91
- assert.ok(opts.cert)
92
- })
93
- })
94
- })
95
-
96
- describe('ensureDhparams', () => {
97
- beforeEach(_setup)
98
- it('generates a missing dhparams file', () => {
99
- this.socket.load_tls_ini()
100
- this.socket.ensureDhparams((err, dhparams) => {
101
- // console.log(dhparams);
102
- assert.ifError(err)
103
- assert.ok(dhparams)
104
- })
105
- })
106
- })
107
-
108
- describe('load_tls_ini2', () => {
109
- beforeEach((done) => {
110
- this.socket = require('../tls_socket')
111
- delete process.env.HARAKA_TEST_DIR
112
- done()
113
- })
114
-
115
- it('loads missing tls.ini default config', () => {
116
- this.socket.config = this.socket.config.module_config(path.resolve('non-exist'))
117
- assert.deepEqual(this.socket.load_tls_ini(), {
118
- main: {
119
- requestCert: true,
120
- rejectUnauthorized: false,
121
- honorCipherOrder: true,
122
- requestOCSP: false,
123
- // enableOCSPStapling: false,
124
- requireAuthorized: [],
125
- mutual_tls: false,
126
- no_starttls_ports: [],
127
- },
128
- redis: { disable_for_failed_hosts: false },
129
- no_tls_hosts: {},
130
- mutual_auth_hosts: {},
131
- mutual_auth_hosts_exclude: {},
132
- })
133
- })
134
-
135
- it('loads tls.ini from test dir', () => {
136
- this.socket.config = this.socket.config.module_config(path.resolve('test'))
137
- assert.deepEqual(this.socket.load_tls_ini(), {
138
- main: {
139
- requestCert: true,
140
- rejectUnauthorized: false,
141
- honorCipherOrder: true,
142
- requestOCSP: false,
143
- key: 'tls_key.pem',
144
- cert: 'tls_cert.pem',
145
- dhparam: 'dhparams.pem',
146
- ciphers:
147
- 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384',
148
- minVersion: 'TLSv1',
149
- requireAuthorized: [2465, 2587],
150
- mutual_tls: false,
151
- no_starttls_ports: [2525],
152
- },
153
- redis: { disable_for_failed_hosts: false },
154
- no_tls_hosts: {
155
- '192.168.1.1': undefined,
156
- '172.16.0.0/16': undefined,
157
- },
158
- mutual_auth_hosts: {},
159
- mutual_auth_hosts_exclude: {},
160
- outbound: {
161
- key: 'outbound_tls_key.pem',
162
- cert: 'outbound_tls_cert.pem',
163
- ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
164
- minVersion: 'TLSv1',
165
- dhparam: 'dhparams.pem',
166
- rejectUnauthorized: false,
167
- requestCert: false,
168
- honorCipherOrder: false,
169
- force_tls_hosts: ['first.example.com', 'second.example.net'],
170
- no_tls_hosts: ['127.0.0.2', '192.168.31.1/24'],
171
- },
172
- })
173
- })
174
- })
175
-
176
- describe('parse_x509', () => {
177
- beforeEach(_setup)
178
-
179
- it('returns empty object on empty input', async () => {
180
- const res = await this.socket.parse_x509()
181
- assert.deepEqual(res, {})
182
- })
183
-
184
- it('returns key from BEGIN PRIVATE KEY block', async () => {
185
- const res = await this.socket.parse_x509('-BEGIN PRIVATE KEY-\nhello\n--END PRIVATE KEY--\n-its me-\n')
186
- assert.deepEqual(res.keys[0].toString(), '-BEGIN PRIVATE KEY-\nhello\n--END PRIVATE KEY--')
187
- assert.deepEqual(res.cert, undefined)
188
- })
189
-
190
- it('returns key from BEGIN RSA PRIVATE KEY block', async () => {
191
- const res = await this.socket.parse_x509(
192
- '-BEGIN RSA PRIVATE KEY-\nhello\n--END RSA PRIVATE KEY--\n-its me-\n',
193
- )
194
- assert.deepEqual(res.keys[0].toString(), '-BEGIN RSA PRIVATE KEY-\nhello\n--END RSA PRIVATE KEY--')
195
- assert.deepEqual(res.cert, undefined)
196
- })
197
-
198
- it.skip('returns a key and certificate chain', async () => {
199
- // doesn't work, b/c parse now parses and needs non-snipped
200
- const str = `-----BEGIN RSA PRIVATE KEY-----
201
- MIIEogIBAAKCAQEAoDGOlvw6lQptaNwqxYsW4aJCPIgvjYw3qA9Y0qykp8I8PapT
202
- ercA8BsInrZg5+3wt2PT1+REprBvv6xfHyQ08o/udsSCBRf4Awadp0fxzUulENNi
203
- 3wWuuPy0WgaE4jam7tWItDBeEhXkEfcMTr9XkFxenuTcNw9O1+E8TtNP9KMmJDAe
204
- <snip>
205
- F+T5AoGAMRH1+JrjTpPYcs1hOyHMWnxkHv7fsJMJY/KN2NPoTlI4d4V1W5xyCZ0D
206
- rl7RlVdVTQdZ9VjkWVjJcafNSmNyQEK4IQsaczwOU59IPhC/nUAyRgeoRbKWPQ4r
207
- mj3g7uX9f07j34c01mH1zLgDa24LO9SW7B5ZbYYu4DORk7005B4=
208
- -----END RSA PRIVATE KEY-----
209
- -----BEGIN CERTIFICATE-----
210
- MIIFVzCCBD+gAwIBAgISA/5ofbB6cUAp/PrYaBxTITF2MA0GCSqGSIb3DQEBCwUA
211
- MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
212
- <snip>
213
- kOk4JdlpuBSPwx9wNAEYF15/4LDyev+tyAg7GxCZ9MW53leOxF+j2NQgc4kRIdQc
214
- DYsruShsnwn4HErJKQAfE5Aq77UM32hfKzMb2PH6Ebw0TB2NCLVocOULAGTw4NPO
215
- wBpsGsIFUxeDHZvhKohZyNqLrj7gR+XlKRKM
216
- -----END CERTIFICATE-----
217
-
218
- -----BEGIN CERTIFICATE-----
219
- MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
220
- TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
221
- cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
222
- <snip>
223
- HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
224
- MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
225
- nLRbwHOoq7hHwg==
226
- -----END CERTIFICATE-----
227
-
228
- -----BEGIN CERTIFICATE-----
229
- MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
230
- MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
231
- DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
232
- <snip>
233
- WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
234
- he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
235
- Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
236
- -----END CERTIFICATE-----`
237
- const res = await this.socket.parse_x509(str)
238
- assert.deepEqual(res.key.length, 446)
239
- assert.deepEqual(res.cert.length, 1195)
240
- })
241
-
242
- it('returns cert and key from EC pem', async () => {
243
- const fp = await fs.readFile(path.join('test', 'config', 'tls', 'ec.pem'))
244
- const res = await this.socket.parse_x509(fp.toString())
245
- assert.deepEqual(
246
- res.keys[0].toString().split(os.EOL).join('\n'),
247
- `-----BEGIN EC PRIVATE KEY-----
248
- MHcCAQEEIIDhiI5q6l7txfMJ6kIEYjK12EFcHLvDIkfWIwzdZBsloAoGCCqGSM49
249
- AwEHoUQDQgAEZg2nHEFy9nquFPF3DQyQE28e/ytjXeb4nD/8U+L4KHKFtglaX3R4
250
- uZ+5JcwfcDghpL4Z8h4ouUD/xqe957e2+g==
251
- -----END EC PRIVATE KEY-----`,
252
- )
253
- assert.deepEqual(
254
- res.chain[0].toString().split(os.EOL).join('\n'),
255
- `-----BEGIN CERTIFICATE-----
256
- MIICaTCCAg+gAwIBAgIUEDa9VX16wCdo97WvIk7jyEBz1wQwCgYIKoZIzj0EAwIw
257
- gYkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT
258
- ZWF0dGxlMRQwEgYDVQQKDAtIYXJha2EgTWFpbDEXMBUGA1UEAwwObWFpbC5oYXJh
259
- a2EuaW8xJDAiBgkqhkiG9w0BCQEWFWhhcmFrYS5tYWlsQGdtYWlsLmNvbTAeFw0y
260
- MTEwMTQwNjQxMTlaFw0yMjEwMTQwNjQxMTlaMIGJMQswCQYDVQQGEwJVUzETMBEG
261
- A1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEUMBIGA1UECgwLSGFy
262
- YWthIE1haWwxFzAVBgNVBAMMDm1haWwuaGFyYWthLmlvMSQwIgYJKoZIhvcNAQkB
263
- FhVoYXJha2EubWFpbEBnbWFpbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
264
- AARmDaccQXL2eq4U8XcNDJATbx7/K2Nd5vicP/xT4vgocoW2CVpfdHi5n7klzB9w
265
- OCGkvhnyHii5QP/Gp73nt7b6o1MwUTAdBgNVHQ4EFgQU094ROMLHmLEspT4ZoCfX
266
- Rz0mR/YwHwYDVR0jBBgwFoAU094ROMLHmLEspT4ZoCfXRz0mR/YwDwYDVR0TAQH/
267
- BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAsmshzvMDjmYDHyGRrKdMmsnnESFd
268
- GMtfRXYIv0AZe7ICIGD2Sta9LL0zZ44ARGXhh+sPjxd78I/+0FdIPsofr2I+
269
- -----END CERTIFICATE-----`,
270
- )
271
- })
272
- })
273
- })