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
@@ -0,0 +1,484 @@
1
+ 'use strict';
2
+ const assert = require('node:assert')
3
+
4
+ const { Address } = require('address-rfc2821');
5
+ const fixtures = require('haraka-test-fixtures');
6
+ const utils = require('haraka-utils');
7
+
8
+ const _set_up = (done) => {
9
+
10
+ this.plugin = new fixtures.plugin('auth/auth_base');
11
+
12
+ this.plugin.get_plain_passwd = (user, cb) => {
13
+ if (user === 'test') return cb('testpass');
14
+ return cb(null);
15
+ };
16
+
17
+ this.connection = fixtures.connection.createConnection();
18
+ this.connection.capabilities=null;
19
+
20
+ done();
21
+ }
22
+
23
+ const _set_up_2 = (done) => {
24
+
25
+ this.plugin = new fixtures.plugin('auth/auth_base');
26
+
27
+ this.plugin.get_plain_passwd = (user, connection, cb) => {
28
+ connection.notes.auth_custom_note = 'custom_note';
29
+ if (user === 'test') return cb('testpass');
30
+ return cb(null);
31
+ };
32
+
33
+ this.connection = fixtures.connection.createConnection();
34
+ this.connection.capabilities=null;
35
+
36
+ done();
37
+ }
38
+
39
+ const _set_up_custom_pwcb_opts = (done) => {
40
+ this.plugin = new fixtures.plugin('auth/auth_base');
41
+
42
+ this.plugin.check_plain_passwd = (connection, user, passwd, pwok_cb) => {
43
+ switch (user) {
44
+ case 'legacyok_nomessage': return pwok_cb(true);
45
+ case 'legacyfail_nomessage': return pwok_cb(false);
46
+ case 'legacyok_message': return pwok_cb(true, 'GREAT SUCCESS');
47
+ case 'legacyfail_message': return pwok_cb(false, 'FAIL 123');
48
+ case 'newok': return pwok_cb(true, {message: 'KOKOKO', code: 215});
49
+ case 'newfail': return pwok_cb(false, {message: 'OHOHOH', code: 555});
50
+ default: throw 'what?!';
51
+ }
52
+ };
53
+
54
+ this.connection = fixtures.connection.createConnection();
55
+ this.connection.capabilities=null;
56
+ this.connection.notes.resp_strings = [];
57
+ this.connection.respond = (code, msg, cb) => {
58
+ this.connection.notes.resp_strings.push([code, msg]);
59
+ return cb();
60
+ }
61
+
62
+ done();
63
+ }
64
+
65
+ describe('auth_base', () => {
66
+
67
+ describe('hook_capabilities', () => {
68
+ beforeEach(_set_up)
69
+
70
+ it('no TLS, no auth', (done) => {
71
+ this.plugin.hook_capabilities((rc, msg) => {
72
+ assert.equal(undefined, rc);
73
+ assert.equal(undefined, msg);
74
+ assert.equal(null, this.connection.capabilities);
75
+ done();
76
+ }, this.connection);
77
+ })
78
+
79
+ it('with TLS, auth is offered', (done) => {
80
+ this.connection.tls.enabled=true;
81
+ this.connection.capabilities=[];
82
+ this.plugin.hook_capabilities((rc, msg) => {
83
+ assert.equal(undefined, rc);
84
+ assert.equal(undefined, msg);
85
+ assert.ok(this.connection.capabilities.length);
86
+ assert.ok(this.connection.capabilities[0] === 'AUTH PLAIN LOGIN CRAM-MD5');
87
+ // console.log(this.connection.capabilities);
88
+ done();
89
+ }, this.connection);
90
+ })
91
+ })
92
+
93
+ describe('get_plain_passwd', () => {
94
+ beforeEach(_set_up)
95
+
96
+ it('get_plain_passwd, no result', (done) => {
97
+ this.plugin.get_plain_passwd('user', pass => {
98
+ assert.equal(pass, null);
99
+ done();
100
+ });
101
+ })
102
+ it('get_plain_passwd, test user', (done) => {
103
+ this.plugin.get_plain_passwd('test', pass => {
104
+ assert.equal(pass, 'testpass');
105
+ done();
106
+ });
107
+ })
108
+ })
109
+
110
+ describe('check_plain_passwd', () => {
111
+ beforeEach(_set_up)
112
+
113
+ it('valid password', (done) => {
114
+ this.plugin.check_plain_passwd(this.connection, 'test', 'testpass', pass => {
115
+ assert.equal(pass, true);
116
+ done();
117
+ });
118
+ })
119
+
120
+ it('wrong password', (done) => {
121
+ this.plugin.check_plain_passwd(this.connection, 'test', 'test1pass', pass => {
122
+ assert.equal(pass, false);
123
+ done();
124
+ });
125
+ })
126
+
127
+ it('null password', (done) => {
128
+ this.plugin.check_plain_passwd(this.connection, 'test', null, pass => {
129
+ assert.equal(pass, false);
130
+ done();
131
+ });
132
+ })
133
+ })
134
+
135
+ describe('select_auth_method', () => {
136
+ beforeEach(_set_up)
137
+
138
+ it('no auth methods yield no result', (done) => {
139
+ this.plugin.select_auth_method((code) => {
140
+ assert.equal(code, null);
141
+ assert.equal(false, this.connection.relaying);
142
+ done();
143
+ }, this.connection, 'AUTH PLAIN');
144
+ })
145
+
146
+ it('invalid AUTH method, no result', (done) => {
147
+ this.connection.notes.allowed_auth_methods = ['PLAIN','LOGIN','CRAM-MD5'];
148
+ this.plugin.select_auth_method((code) => {
149
+ assert.equal(code, null);
150
+ assert.equal(false, this.connection.relaying);
151
+ done();
152
+ }, this.connection, 'AUTH FOO');
153
+ })
154
+
155
+ it('valid AUTH method, valid attempt', (done) => {
156
+ const method = `PLAIN ${utils.base64('discard\0test\0testpass')}`;
157
+ this.connection.notes.allowed_auth_methods = ['PLAIN','LOGIN'];
158
+ this.plugin.select_auth_method((code) => {
159
+ assert.equal(code, OK);
160
+ assert.ok(this.connection.relaying);
161
+ done();
162
+ }, this.connection, method);
163
+ })
164
+ })
165
+
166
+ describe('auth_plain', () => {
167
+ beforeEach(_set_up)
168
+
169
+ it('params type=string returns OK', (done) => {
170
+ this.plugin.auth_plain((rc) => {
171
+ assert.equal(rc, OK);
172
+ assert.equal(false, this.connection.relaying);
173
+ done();
174
+ }, this.connection, 'AUTH FOO');
175
+ })
176
+
177
+ it('params type=empty array, returns OK', (done) => {
178
+ this.plugin.auth_plain((rc) => {
179
+ assert.equal(rc, OK);
180
+ assert.equal(false, this.connection.relaying);
181
+ done();
182
+ }, this.connection, []);
183
+ })
184
+
185
+ it('params type=array, successful auth', (done) => {
186
+ const method = utils.base64('discard\0test\0testpass');
187
+ this.plugin.auth_plain((rc) => {
188
+ assert.equal(rc, OK);
189
+ assert.ok(this.connection.relaying);
190
+ done();
191
+ }, this.connection, [method]);
192
+ })
193
+
194
+ it('params type=with two line login', (done) => {
195
+ this.plugin.auth_plain((rc) => {
196
+ assert.equal(this.connection.notes.auth_plain_asked_login, true);
197
+ assert.equal(rc, OK);
198
+ done();
199
+ }, this.connection, '');
200
+ })
201
+ })
202
+
203
+ describe('check_user', () => {
204
+ beforeEach(_set_up_2)
205
+
206
+ it('bad auth', (done) => {
207
+ const credentials = ['matt','ttam'];
208
+ this.plugin.check_user((code) => {
209
+ assert.equal(code, OK);
210
+ assert.equal(this.connection.relaying, false);
211
+ assert.equal(this.connection.notes.auth_custom_note, 'custom_note');
212
+ done();
213
+ }, this.connection, credentials, 'PLAIN');
214
+ })
215
+
216
+ it('good auth', (done) => {
217
+ const credentials = ['test','testpass'];
218
+ this.plugin.check_user((code) => {
219
+ assert.equal(code, OK);
220
+ assert.ok(this.connection.relaying);
221
+ assert.equal(this.connection.notes.auth_custom_note, 'custom_note');
222
+ done();
223
+ }, this.connection, credentials, 'PLAIN');
224
+ })
225
+ })
226
+
227
+ describe('check_user_custom_opts', () => {
228
+ beforeEach(_set_up_custom_pwcb_opts)
229
+
230
+ it('legacyok_nomessage', (done) => {
231
+ this.plugin.check_user((code, msg) => {
232
+ assert.equal(code, OK);
233
+ assert.equal(this.connection.relaying, true);
234
+ assert.deepEqual(this.connection.notes.resp_strings, [[ 235, '2.7.0 Authentication successful' ]]);
235
+ done();
236
+ }, this.connection, ['legacyok_nomessage', 'any'], 'PLAIN');
237
+ })
238
+
239
+ it('legacyfail_nomessage', (done) => {
240
+ this.plugin.check_user((code, msg) => {
241
+ assert.equal(code, OK);
242
+ assert.equal(this.connection.relaying, false);
243
+ assert.deepEqual(this.connection.notes.resp_strings, [ [ 535, '5.7.8 Authentication failed' ] ]);
244
+ done();
245
+ }, this.connection, ['legacyfail_nomessage', 'any'], 'PLAIN');
246
+ })
247
+
248
+ it('legacyok_message', (done) => {
249
+ this.plugin.check_user((code, msg) => {
250
+ assert.equal(code, OK);
251
+ assert.equal(this.connection.relaying, true);
252
+ assert.deepEqual(this.connection.notes.resp_strings, [[ 235, 'GREAT SUCCESS' ]]);
253
+ done();
254
+ }, this.connection, ['legacyok_message', 'any'], 'PLAIN');
255
+ })
256
+
257
+ it('legacyfail_message', (done) => {
258
+ this.plugin.check_user((code, msg) => {
259
+ assert.equal(code, OK);
260
+ assert.equal(this.connection.relaying, false);
261
+ assert.deepEqual(this.connection.notes.resp_strings, [[ 535, 'FAIL 123' ]]);
262
+ done();
263
+ }, this.connection, ['legacyfail_message', 'any'], 'PLAIN');
264
+ })
265
+
266
+ it('newok', (done) => {
267
+ this.plugin.check_user((code, msg) => {
268
+ assert.equal(code, OK);
269
+ assert.equal(this.connection.relaying, true);
270
+ assert.deepEqual(this.connection.notes.resp_strings, [[ 215, 'KOKOKO' ]]);
271
+ done();
272
+ }, this.connection, ['newok', 'any'], 'PLAIN');
273
+ })
274
+
275
+ it('newfail', (done) => {
276
+ this.plugin.check_user((code, msg) => {
277
+ assert.equal(code, OK);
278
+ assert.equal(this.connection.relaying, false);
279
+ assert.deepEqual(this.connection.notes.resp_strings, [[ 555, 'OHOHOH' ]]);
280
+ done();
281
+ }, this.connection, ['newfail', 'any'], 'PLAIN');
282
+ })
283
+ })
284
+
285
+ describe('auth_notes_are_set', () => {
286
+ beforeEach(_set_up_2)
287
+
288
+ it('bad auth: no notes should be set', (done) => {
289
+ const credentials = ['matt','ttam'];
290
+ this.plugin.check_user((code) => {
291
+ assert.equal(this.connection.notes.auth_user, undefined);
292
+ assert.equal(this.connection.notes.auth_passwd, undefined);
293
+ done();
294
+ }, this.connection, credentials, 'PLAIN');
295
+ })
296
+
297
+ it('good auth: dont store password', (done) => {
298
+ const creds = ['test','testpass'];
299
+ this.plugin.blankout_password = true;
300
+ this.plugin.check_user((code) => {
301
+ assert.equal(this.connection.notes.auth_user, creds[0]);
302
+ assert.equal(this.connection.notes.auth_passwd, undefined);
303
+ done();
304
+ }, this.connection, creds, 'PLAIN');
305
+ })
306
+
307
+ it('good auth: store password (default)', (done) => {
308
+ const creds = ['test','testpass'];
309
+ this.plugin.check_user((code) => {
310
+ assert.equal(this.connection.notes.auth_user, creds[0]);
311
+ assert.equal(this.connection.notes.auth_passwd, creds[1]);
312
+ done();
313
+ }, this.connection, creds, 'PLAIN');
314
+ })
315
+ })
316
+
317
+ describe('hook_unrecognized_command', () => {
318
+ beforeEach(_set_up)
319
+
320
+ it('AUTH type FOO', (done) => {
321
+ const params = ['AUTH','FOO'];
322
+ this.connection.notes.allowed_auth_methods = ['PLAIN','LOGIN'];
323
+ this.plugin.hook_unrecognized_command((code) => {
324
+ assert.equal(code, null);
325
+ assert.equal(this.connection.relaying, false);
326
+ done();
327
+ }, this.connection, params);
328
+ })
329
+
330
+ it('AUTH PLAIN', (done) => {
331
+ const params = ['AUTH','PLAIN', utils.base64('discard\0test\0testpass')];
332
+ this.connection.notes.allowed_auth_methods = ['PLAIN','LOGIN'];
333
+ this.plugin.hook_unrecognized_command((code) => {
334
+ assert.equal(code, OK);
335
+ assert.ok(this.connection.relaying);
336
+ done();
337
+ }, this.connection, params);
338
+ })
339
+
340
+ it('AUTH PLAIN, authenticating', (done) => {
341
+ this.connection.notes.allowed_auth_methods = ['PLAIN','LOGIN'];
342
+ this.connection.notes.authenticating=true;
343
+ this.connection.notes.auth_method='PLAIN';
344
+ this.plugin.hook_unrecognized_command((code) => {
345
+ assert.equal(code, OK);
346
+ assert.ok(this.connection.relaying);
347
+ done();
348
+ }, this.connection, [utils.base64('discard\0test\0testpass')]);
349
+ })
350
+ })
351
+
352
+ describe('auth_login', () => {
353
+ beforeEach(_set_up)
354
+
355
+ it('AUTH LOGIN', (done) => {
356
+ const params = ['AUTH','LOGIN'];
357
+ this.connection.notes.allowed_auth_methods = ['PLAIN','LOGIN'];
358
+ this.plugin.hook_unrecognized_command((code) => {
359
+ assert.equal(code, OK);
360
+ assert.equal(this.connection.relaying, false);
361
+ assert.equal(this.connection.notes.auth_login_asked_login , true);
362
+
363
+ this.plugin.hook_unrecognized_command((code) => {
364
+ assert.equal(code, OK);
365
+ assert.equal(this.connection.notes.auth_login_userlogin, 'test');
366
+ assert.equal(this.connection.relaying, false);
367
+ this.plugin.hook_unrecognized_command((code) => {
368
+ assert.equal(code, OK);
369
+ assert.equal(this.connection.relaying, true);
370
+ done();
371
+ }, this.connection, [utils.base64('testpass')]);
372
+ }, this.connection, [utils.base64('test')]);
373
+ }, this.connection, params);
374
+ })
375
+
376
+ it('AUTH LOGIN <username>', (done) => {
377
+ const params = ['AUTH','LOGIN', utils.base64('test')];
378
+ this.connection.notes.allowed_auth_methods = ['PLAIN','LOGIN'];
379
+ this.plugin.hook_unrecognized_command((code) => {
380
+ assert.equal(code, OK);
381
+ assert.equal(this.connection.relaying, false);
382
+ assert.equal(this.connection.notes.auth_login_userlogin, 'test');
383
+ assert.equal(this.connection.notes.auth_login_asked_login , true);
384
+
385
+ this.plugin.hook_unrecognized_command((code2) => {
386
+ assert.equal(code2, OK);
387
+ assert.equal(this.connection.relaying, true);
388
+ done();
389
+ }, this.connection, [utils.base64('testpass')]);
390
+ }, this.connection, params);
391
+ })
392
+
393
+ it('AUTH LOGIN <username>, bad protocol', (done) => {
394
+
395
+ const params = ['AUTH','LOGIN', utils.base64('test')];
396
+ this.connection.notes.allowed_auth_methods = ['PLAIN','LOGIN'];
397
+ this.plugin.hook_unrecognized_command((code) => {
398
+ assert.equal(code, OK);
399
+ assert.equal(this.connection.relaying, false);
400
+ assert.equal(this.connection.notes.auth_login_userlogin, 'test');
401
+ assert.equal(this.connection.notes.auth_login_asked_login , true);
402
+
403
+ this.plugin.hook_unrecognized_command((code, msg) => {
404
+ assert.equal(code, DENYDISCONNECT);
405
+ assert.equal(msg, 'bad protocol');
406
+ assert.equal(this.connection.relaying, false);
407
+ done();
408
+ }, this.connection, ['AUTH', 'LOGIN']);
409
+ }, this.connection, params);
410
+ })
411
+
412
+ it('AUTH LOGIN, reauthentication', (done) => {
413
+ const params = ['AUTH','LOGIN', utils.base64('test')];
414
+ this.connection.notes.allowed_auth_methods = ['PLAIN','LOGIN'];
415
+ this.plugin.hook_unrecognized_command((code) => {
416
+ assert.equal(code, OK);
417
+ assert.equal(this.connection.relaying, false);
418
+ assert.equal(this.connection.notes.auth_login_userlogin, 'test');
419
+ assert.equal(this.connection.notes.auth_login_asked_login , true);
420
+
421
+ this.plugin.hook_unrecognized_command((code) => {
422
+ assert.equal(code, OK);
423
+ assert.equal(this.connection.relaying, true);
424
+ assert.equal(this.connection.notes.auth_login_userlogin, null);
425
+ assert.equal(this.connection.notes.auth_login_asked_login , false);
426
+
427
+ this.plugin.hook_unrecognized_command((code) => {
428
+ assert.equal(code, OK);
429
+ done();
430
+ }, this.connection, ['AUTH','LOGIN']);
431
+ }, this.connection, [utils.base64('testpass')]);
432
+ }, this.connection, params);
433
+ })
434
+ })
435
+
436
+ describe('hexi', () => {
437
+ beforeEach(_set_up)
438
+
439
+ it('hexi', () => {
440
+ assert.equal(this.plugin.hexi(512), 200);
441
+ assert.equal(this.plugin.hexi(8), 8);
442
+ })
443
+ })
444
+
445
+ describe('constrain_sender', () => {
446
+ beforeEach(_set_up)
447
+
448
+ it('constrain_sender, domain match', (done) => {
449
+ this.mfrom = new Address('user@example.com')
450
+ this.connection.results.add({name: 'auth'}, { user: 'user@example.com' })
451
+ this.plugin.constrain_sender((resCode) => {
452
+ assert.equal(resCode, undefined)
453
+ done();
454
+ },
455
+ this.connection,
456
+ [this.mfrom],
457
+ )
458
+ })
459
+
460
+ it('constrain_sender, domain mismatch', (done) => {
461
+ this.mfrom = new Address('user@example.net')
462
+ this.connection.results.add({name: 'auth'}, { user: 'user@example.com' })
463
+ this.plugin.constrain_sender((resCode, denyMsg) => {
464
+ assert.equal(resCode, DENY)
465
+ assert.ok(denyMsg)
466
+ done();
467
+ },
468
+ this.connection,
469
+ [this.mfrom],
470
+ )
471
+ })
472
+ it('constrain_sender, no domain', (done) => {
473
+ this.mfrom = new Address('user@example.com')
474
+ this.connection.results.add({name: 'auth'}, { user: 'user' })
475
+ this.plugin.constrain_sender((resCode) => {
476
+ assert.equal(resCode, undefined)
477
+ done();
478
+ },
479
+ this.connection,
480
+ [this.mfrom],
481
+ )
482
+ })
483
+ })
484
+ })
@@ -0,0 +1,83 @@
1
+ 'use strict';
2
+
3
+ const assert = require('node:assert')
4
+ const path = require('node:path');
5
+
6
+ const fixtures = require('haraka-test-fixtures');
7
+
8
+ const _set_up = (done) => {
9
+ this.backup = {};
10
+
11
+ this.plugin = new fixtures.plugin('auth/auth_vpopmaild');
12
+ this.plugin.inherits('auth/auth_base');
13
+
14
+ // reset the config/root_path
15
+ this.plugin.config.root_path = path.resolve(__dirname, '../../../config');
16
+ this.plugin.cfg = this.plugin.config.get('auth_vpopmaild.ini');
17
+
18
+ this.connection = fixtures.connection.createConnection();
19
+ this.connection.capabilities=null;
20
+
21
+ done();
22
+ }
23
+
24
+ describe('hook_capabilities', () => {
25
+ beforeEach(_set_up)
26
+
27
+ it('no TLS', (done) => {
28
+ this.plugin.hook_capabilities((rc, msg) => {
29
+ assert.equal(undefined, rc);
30
+ assert.equal(undefined, msg);
31
+ assert.equal(null, this.connection.capabilities);
32
+ done();
33
+ }, this.connection);
34
+ })
35
+
36
+ it('with TLS', (done) => {
37
+ this.connection.tls.enabled=true;
38
+ this.connection.capabilities=[];
39
+ this.plugin.hook_capabilities((rc, msg) => {
40
+ assert.equal(undefined, rc);
41
+ assert.equal(undefined, msg);
42
+ assert.ok(this.connection.capabilities.length);
43
+ done();
44
+ }, this.connection);
45
+ })
46
+
47
+ it('with TLS, sysadmin', (done) => {
48
+ this.connection.tls.enabled=true;
49
+ this.connection.capabilities=[];
50
+ this.plugin.hook_capabilities((rc, msg) => {
51
+ assert.equal(undefined, rc);
52
+ assert.equal(undefined, msg);
53
+ assert.ok(this.connection.capabilities.length);
54
+ done();
55
+ }, this.connection);
56
+ })
57
+ })
58
+
59
+ describe('get_vpopmaild_socket', () => {
60
+ beforeEach(_set_up)
61
+
62
+ it('any', () => {
63
+ const socket = this.plugin.get_vpopmaild_socket('foo@localhost.com');
64
+ assert.ok(socket);
65
+ socket.end();
66
+ })
67
+ })
68
+
69
+ describe('get_plain_passwd', () => {
70
+ beforeEach(_set_up)
71
+
72
+ it('matt@example.com', (done) => {
73
+ if (this.plugin.cfg['example.com'].sysadmin) {
74
+ this.plugin.get_plain_passwd('matt@example.com', (pass) => {
75
+ assert.ok(pass);
76
+ done();
77
+ });
78
+ }
79
+ else {
80
+ done();
81
+ }
82
+ })
83
+ })
@@ -0,0 +1,104 @@
1
+ 'use strict';
2
+ const assert = require('node:assert')
3
+
4
+ const fixtures = require('haraka-test-fixtures');
5
+
6
+ const _set_up = (done) => {
7
+ this.plugin = new fixtures.plugin('early_talker');
8
+ this.plugin.cfg = { main: { reject: true } };
9
+
10
+ this.connection = fixtures.connection.createConnection();
11
+ done();
12
+ }
13
+
14
+ describe('early_talker', () => {
15
+ beforeEach(_set_up)
16
+
17
+ it('no config', (done) => {
18
+ this.plugin.early_talker((rc, msg) => {
19
+ assert.equal(rc, undefined);
20
+ assert.equal(msg, undefined);
21
+ done();
22
+ }, this.connection);
23
+ })
24
+
25
+ it('relaying', (done) => {
26
+ this.plugin.pause = 1;
27
+ this.connection.relaying = true;
28
+ this.plugin.early_talker((rc, msg) => {
29
+ assert.equal(rc, undefined);
30
+ assert.equal(msg, undefined);
31
+ done();
32
+ }, this.connection);
33
+ })
34
+
35
+ it('is an early talker', (done) => {
36
+ const before = Date.now();
37
+ this.plugin.pause = 1001;
38
+ this.connection.early_talker = true;
39
+ this.plugin.early_talker((rc, msg) => {
40
+ assert.ok(Date.now() >= before + 1000);
41
+ assert.equal(rc, DENYDISCONNECT);
42
+ assert.equal(msg, 'You talk too soon');
43
+ done();
44
+ }, this.connection);
45
+ })
46
+
47
+ it('is an early talker, reject=false', (done) => {
48
+ const before = Date.now();
49
+ this.plugin.pause = 1001;
50
+ this.plugin.cfg.main.reject = false;
51
+ this.connection.early_talker = true;
52
+ this.plugin.early_talker((rc, msg) => {
53
+ assert.ok(Date.now() >= before + 1000);
54
+ assert.equal(undefined, rc);
55
+ assert.equal(undefined, msg);
56
+ assert.ok(this.connection.results.has('early_talker', 'fail', 'early'));
57
+ done();
58
+ }, this.connection);
59
+ })
60
+
61
+ it('relay whitelisted ip', (done) => {
62
+ this.plugin.pause = 1000;
63
+ this.plugin.whitelist = this.plugin.load_ip_list(['127.0.0.1']);
64
+ this.connection.remote.ip = '127.0.0.1';
65
+ this.connection.early_talker = true;
66
+ this.plugin.early_talker((rc, msg) => {
67
+ assert.equal(undefined, rc);
68
+ assert.equal(undefined, msg);
69
+ assert.ok(this.connection.results.has('early_talker', 'skip', 'whitelist'));
70
+ done();
71
+ }, this.connection);
72
+ })
73
+
74
+ it('relay whitelisted subnet', (done) => {
75
+ this.plugin.pause = 1000;
76
+ this.plugin.whitelist = this.plugin.load_ip_list(['127.0.0.0/16']);
77
+ this.connection.remote.ip = '127.0.0.88';
78
+ this.connection.early_talker = true;
79
+ this.plugin.early_talker((rc, msg) => {
80
+ assert.equal(undefined, rc);
81
+ assert.equal(undefined, msg);
82
+ assert.ok(this.connection.results.has('early_talker', 'skip', 'whitelist'));
83
+ done();
84
+ }, this.connection);
85
+ })
86
+
87
+ it('relay good senders', (done) => {
88
+ this.plugin.pause = 1000;
89
+ this.connection.results.add('karma', {good: 10});
90
+ this.connection.early_talker = true;
91
+ this.plugin.early_talker((rc, msg) => {
92
+ assert.equal(undefined, rc);
93
+ assert.equal(undefined, msg);
94
+ assert.ok(this.connection.results.has('early_talker', 'skip', '+karma'));
95
+ done();
96
+ }, this.connection);
97
+ })
98
+
99
+ it('test loading ip list', () => {
100
+ const whitelist = this.plugin.load_ip_list(['123.123.123.123', '127.0.0.0/16']);
101
+ assert.equal(whitelist[0][1], 32);
102
+ assert.equal(whitelist[1][1], 16);
103
+ })
104
+ })