Haraka 3.1.3 → 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.
- package/.prettierignore +2 -0
- package/CONTRIBUTORS.md +23 -1
- package/Changes.md +38 -0
- package/Plugins.md +81 -64
- package/README.md +1 -1
- package/bin/haraka +7 -5
- package/connection.js +15 -19
- package/docs/Plugins.md +1 -1
- package/docs/plugins/aliases.md +0 -2
- package/docs/plugins/queue/qmail-queue.md +0 -1
- package/logger.js +2 -2
- package/outbound/hmail.js +76 -83
- package/outbound/index.js +36 -34
- package/outbound/queue.js +231 -176
- package/package.json +25 -26
- package/plugins/prevent_credential_leaks.js +2 -2
- package/plugins/process_title.js +1 -1
- package/plugins/queue/smtp_forward.js +1 -1
- package/plugins/status.js +8 -5
- package/plugins/tls.js +1 -1
- package/plugins.js +19 -14
- package/rfc1869.js +10 -10
- package/run_tests +20 -2
- package/server.js +15 -10
- package/smtp_client.js +2 -9
- package/test/config/tls/haraka.local.pem +47 -47
- package/test/connection.js +286 -147
- package/test/fixtures/line_socket.js +1 -0
- package/test/fixtures/util_hmailitem.js +1 -1
- package/test/outbound/bounce_net_errors.js +176 -0
- package/test/outbound/bounce_rfc3464.js +303 -0
- package/test/outbound/hmail.js +140 -104
- package/test/outbound/index.js +61 -101
- package/test/outbound/qfile.js +25 -25
- package/test/outbound/queue.js +233 -0
- package/test/plugins/queue/smtp_forward.js +1 -1
- package/test/plugins/record_envelope_addresses.js +93 -0
- package/test/plugins/tls.js +2 -2
- package/test/plugins/xclient.js +137 -0
- package/test/rfc1869.js +43 -0
- package/test/smtp_client.js +6 -6
- package/test/transaction.js +486 -201
- package/tls_socket.js +3 -3
- package/transaction.js +33 -10
- package/config/rabbitmq.ini +0 -10
- package/config/rabbitmq_amqplib.ini +0 -19
- package/docs/plugins/queue/rabbitmq.md +0 -34
- package/docs/plugins/queue/rabbitmq_amqplib.md +0 -51
- package/plugins/queue/rabbitmq.js +0 -141
- package/plugins/queue/rabbitmq_amqplib.js +0 -96
- package/test/config/tls/ec.pem +0 -23
- package/test/config/tls/mismatched.pem +0 -49
- package/test/outbound_bounce_net_errors.js +0 -157
- package/test/outbound_bounce_rfc3464.js +0 -366
- package/test/tls_socket.js +0 -273
package/test/tls_socket.js
DELETED
|
@@ -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
|
-
})
|