Mercurial > hg > nginx-tests
comparison mail_oauth.t @ 1985:b5e2609d34a3
Tests: added tests for OAUTHBEARER and XOAUTH2 auth methods.
Based on a patch by Rob Mueller.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 03 Jun 2024 18:15:28 +0300 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1984:81519d01f238 | 1985:b5e2609d34a3 |
---|---|
1 #!/usr/bin/perl | |
2 | |
3 # (C) Maxim Dounin | |
4 | |
5 # Tests for mail module, XOAUTH2 and OAUTHBEARER authentication. | |
6 | |
7 ############################################################################### | |
8 | |
9 use warnings; | |
10 use strict; | |
11 | |
12 use Test::More; | |
13 | |
14 use MIME::Base64; | |
15 use Socket qw/ CRLF /; | |
16 | |
17 BEGIN { use FindBin; chdir($FindBin::Bin); } | |
18 | |
19 use lib 'lib'; | |
20 use Test::Nginx; | |
21 use Test::Nginx::IMAP; | |
22 use Test::Nginx::POP3; | |
23 use Test::Nginx::SMTP; | |
24 | |
25 ############################################################################### | |
26 | |
27 select STDERR; $| = 1; | |
28 select STDOUT; $| = 1; | |
29 | |
30 local $SIG{PIPE} = 'IGNORE'; | |
31 | |
32 my $t = Test::Nginx->new()->has(qw/mail imap pop3 smtp http map rewrite/) | |
33 ->write_file_expand('nginx.conf', <<'EOF'); | |
34 | |
35 %%TEST_GLOBALS%% | |
36 | |
37 daemon off; | |
38 | |
39 events { | |
40 } | |
41 | |
42 mail { | |
43 proxy_pass_error_message on; | |
44 proxy_timeout 15s; | |
45 timeout 2s; | |
46 auth_http http://127.0.0.1:8080/mail/auth; | |
47 | |
48 server { | |
49 listen 127.0.0.1:8143; | |
50 protocol imap; | |
51 imap_auth plain oauthbearer xoauth2; | |
52 } | |
53 server { | |
54 listen 127.0.0.1:8110; | |
55 protocol pop3; | |
56 pop3_auth plain oauthbearer xoauth2; | |
57 } | |
58 server { | |
59 listen 127.0.0.1:8025; | |
60 protocol smtp; | |
61 smtp_auth plain oauthbearer xoauth2; | |
62 } | |
63 } | |
64 | |
65 http { | |
66 %%TEST_GLOBALS_HTTP%% | |
67 | |
68 map $http_auth_protocol $proxy_port { | |
69 imap %%PORT_8144%%; | |
70 pop3 %%PORT_8111%%; | |
71 smtp %%PORT_8026%%; | |
72 } | |
73 | |
74 map $http_auth_user:$http_auth_pass $reply { | |
75 test@example.com:secretok OK; | |
76 test=,@example.com:secretok OK; | |
77 default auth-failed; | |
78 } | |
79 | |
80 map $http_auth_pass $passw { | |
81 secretok secret; | |
82 } | |
83 | |
84 map $http_auth_pass $sasl { | |
85 saslfail "eyJzY2hlbWVzIjoiQmVhcmVyIiwic3RhdHVzIjoiNDAwIn0="; | |
86 } | |
87 | |
88 server { | |
89 listen 127.0.0.1:8080; | |
90 server_name localhost; | |
91 | |
92 location = /mail/auth { | |
93 add_header Auth-Status $reply; | |
94 add_header Auth-Server 127.0.0.1; | |
95 add_header Auth-Port $proxy_port; | |
96 add_header Auth-Pass $passw; | |
97 add_header Auth-Wait 1; | |
98 add_header Auth-Error-SASL $sasl; | |
99 return 204; | |
100 } | |
101 } | |
102 } | |
103 | |
104 EOF | |
105 | |
106 $t->run_daemon(\&Test::Nginx::IMAP::imap_test_daemon); | |
107 $t->run_daemon(\&Test::Nginx::POP3::pop3_test_daemon); | |
108 $t->run_daemon(\&Test::Nginx::SMTP::smtp_test_daemon); | |
109 $t->try_run('no oauth support')->plan(48); | |
110 | |
111 $t->waitforsocket('127.0.0.1:' . port(8144)); | |
112 $t->waitforsocket('127.0.0.1:' . port(8111)); | |
113 $t->waitforsocket('127.0.0.1:' . port(8026)); | |
114 | |
115 ############################################################################### | |
116 | |
117 # AUTHBEARER SASL mechanism | |
118 # https://datatracker.ietf.org/doc/html/rfc7628 | |
119 | |
120 # XOAUTH2 SASL mechanism | |
121 # https://developers.google.com/gmail/imap/xoauth2-protocol | |
122 | |
123 my $s; | |
124 my $token = encode_base64( | |
125 "n,a=test\@example.com,\001auth=Bearer secretok\001\001", ''); | |
126 my $token_escaped = encode_base64( | |
127 "n,a=test=3D=2C\@example.com,\001auth=Bearer secretok\001\001", ''); | |
128 my $token_saslfail = encode_base64( | |
129 "n,a=test\@example.com,\001auth=Bearer saslfail\001\001", ''); | |
130 my $token_bad = encode_base64( | |
131 "n,a=test\@example.com,\001auth=Bearer bad\001\001", ''); | |
132 | |
133 my $token_xoauth2 = encode_base64( | |
134 "user=test\@example.com\001auth=Bearer secretok\001\001", ''); | |
135 my $token_xoauth2_saslfail = encode_base64( | |
136 "user=test\@example.com\001auth=Bearer saslfail\001\001", ''); | |
137 my $token_xoauth2_bad = encode_base64( | |
138 "user=test\@example.com\001auth=Bearer bad\001\001", ''); | |
139 | |
140 # IMAP | |
141 | |
142 $s = Test::Nginx::IMAP->new(); | |
143 $s->read(); | |
144 $s->send('1 AUTHENTICATE OAUTHBEARER ' . $token); | |
145 $s->ok('imap oauthbearer success'); | |
146 | |
147 $s = Test::Nginx::IMAP->new(); | |
148 $s->read(); | |
149 $s->send('1 AUTHENTICATE OAUTHBEARER ' . $token_escaped); | |
150 $s->ok('imap oauthbearer escaped login'); | |
151 | |
152 $s = Test::Nginx::IMAP->new(); | |
153 $s->read(); | |
154 $s->send('1 AUTHENTICATE OAUTHBEARER'); | |
155 $s->check(qr/\+ /, 'imap oauthbearer challenge'); | |
156 $s->send($token); | |
157 $s->ok('imap oauthbearer success after challenge'); | |
158 | |
159 $s = Test::Nginx::IMAP->new(); | |
160 $s->read(); | |
161 $s->send('1 AUTHENTICATE OAUTHBEARER ' . $token_bad); | |
162 $s->check(qr/^1 NO auth-failed/, 'imap oauthbearer non-sasl error'); | |
163 | |
164 sleep(3); | |
165 | |
166 my @ready = $s->can_read(0); | |
167 is(scalar @ready, 1, "imap ready for reading"); | |
168 ok($s->eof(), "imap session closed"); | |
169 | |
170 # fail, sasl failure method | |
171 | |
172 $s = Test::Nginx::IMAP->new(); | |
173 $s->read(); | |
174 my $start = time; | |
175 $s->send('1 AUTHENTICATE OAUTHBEARER ' . $token_saslfail); | |
176 $s->check(qr/^\+ eyJz/, 'imap oauthbearer sasl failure'); | |
177 my $wait_time = time - $start; | |
178 ok($wait_time >= 1, 'imap oauthbearer error delayed'); | |
179 $s->send('AQ=='); | |
180 $s->check(qr/^1 NO auth-failed/, | |
181 'imap oauthbearer auth failure after dummy response'); | |
182 | |
183 # fail, sasl failure method, invalid client response | |
184 | |
185 $s = Test::Nginx::IMAP->new(); | |
186 $s->read(); | |
187 $s->send('1 AUTHENTICATE OAUTHBEARER ' . $token_saslfail); | |
188 $s->check(qr/^\+ eyJz/, 'imap oauthbearer sasl failure'); | |
189 $s->send('foo'); | |
190 $s->check(qr/^1 BAD /, 'imap oauthbearer invalid command after invalid line'); | |
191 | |
192 # fail, sasl failure method, multiple attempts, then success | |
193 | |
194 $s = Test::Nginx::IMAP->new(); | |
195 $s->read(); | |
196 | |
197 $s->send('1 AUTHENTICATE OAUTHBEARER ' . $token_saslfail); | |
198 $s->check(qr/^\+ eyJz/, 'imap oauthbearer sasl failure'); | |
199 $s->send('AQ=='); | |
200 $s->check(qr/^1 NO auth-failed/, | |
201 'imap oauthbearer auth failure after dummy response'); | |
202 | |
203 $s->send('1 AUTHENTICATE OAUTHBEARER ' . $token_saslfail); | |
204 $s->check(qr/^\+ eyJz/, 'imap oauthbearer sasl failure next'); | |
205 $s->send('foo'); | |
206 $s->check(qr/^1 BAD/, 'imap oauthbearer invalid command after invalid line'); | |
207 | |
208 $s->send('1 AUTHENTICATE OAUTHBEARER'); | |
209 $s->check(qr/\+ /, 'imap oauthbearer challenge after fail'); | |
210 $s->send($token); | |
211 $s->ok('imap oauthbearer success after fail'); | |
212 | |
213 # IMAP XOAUTH2 | |
214 | |
215 $s = Test::Nginx::IMAP->new(); | |
216 $s->read(); | |
217 $s->send('1 AUTHENTICATE XOAUTH2 ' . $token_xoauth2); | |
218 $s->ok('imap xoauth2 success'); | |
219 | |
220 $s = Test::Nginx::IMAP->new(); | |
221 $s->read(); | |
222 $s->send('1 AUTHENTICATE XOAUTH2'); | |
223 $s->check(qr/^\+ /, 'imap xoauth2 challenge'); | |
224 $s->send($token_xoauth2); | |
225 $s->ok('imap xoauth2 success after challenge'); | |
226 | |
227 $s = Test::Nginx::IMAP->new(); | |
228 $s->read(); | |
229 $s->send('1 AUTHENTICATE XOAUTH2 ' . $token_xoauth2_saslfail); | |
230 $s->check(qr/^\+ eyJz/, 'imap xoauth2 with bad token'); | |
231 $s->send(''); | |
232 $s->check(qr/^1 NO auth-failed/, 'imap xoauth2 auth failure after empty line'); | |
233 | |
234 $s->send('1 AUTHENTICATE XOAUTH2 ' . $token_xoauth2_saslfail); | |
235 $s->check(qr/^\+ eyJz/, 'imap xoauth2 with bad token next'); | |
236 $s->send('foo'); | |
237 $s->check(qr/^1 BAD/, 'imap xoauth2 invalid command after invalid line'); | |
238 | |
239 $s->send('1 AUTHENTICATE XOAUTH2 ' . $token_xoauth2); | |
240 $s->ok('imap xoauth2 success after fail'); | |
241 | |
242 # POP3 | |
243 | |
244 $s = Test::Nginx::POP3->new(); | |
245 $s->read(); | |
246 $s->send('AUTH OAUTHBEARER ' . $token); | |
247 $s->ok('pop3 oauthbearer success'); | |
248 | |
249 $s = Test::Nginx::POP3->new(); | |
250 $s->read(); | |
251 $s->send('AUTH OAUTHBEARER'); | |
252 $s->check(qr/^\+ /, 'pop3 oauthbearer challenge'); | |
253 $s->send($token); | |
254 $s->ok('pop3 oauthbearer success after challenge'); | |
255 | |
256 $s = Test::Nginx::POP3->new(); | |
257 $s->read(); | |
258 $s->send('AUTH OAUTHBEARER ' . $token_saslfail); | |
259 $s->check(qr/^\+ eyJz/, 'pop3 oauthbearer sasl failure'); | |
260 $s->send('AQ=='); | |
261 $s->check(qr/^-ERR /, 'pop3 oauthbearer auth failure after dummy response'); | |
262 | |
263 $s->send('AUTH OAUTHBEARER ' . $token_saslfail); | |
264 $s->check(qr/^\+ eyJz/, 'pop3 oauthbearer sasl failure next'); | |
265 $s->send(''); | |
266 $s->check(qr/^-ERR /, 'pop3 oauthbearer invalid command after invalid line'); | |
267 | |
268 $s->send('AUTH OAUTHBEARER ' . $token); | |
269 $s->ok('pop3 oauthbearer success after fail'); | |
270 | |
271 # POP3 XOAUTH2 | |
272 | |
273 $s = Test::Nginx::POP3->new(); | |
274 $s->read(); | |
275 $s->send('AUTH XOAUTH2 ' . $token_xoauth2); | |
276 $s->ok('pop3 xoauth2 success'); | |
277 | |
278 $s = Test::Nginx::POP3->new(); | |
279 $s->read(); | |
280 $s->send('AUTH XOAUTH2'); | |
281 $s->check(qr/^\+ /, 'pop3 xoauth2 challenge'); | |
282 $s->send($token_xoauth2); | |
283 $s->ok('pop3 xoauth2 success after challenge'); | |
284 | |
285 # SMTP | |
286 | |
287 $s = Test::Nginx::SMTP->new(); | |
288 $s->read(); | |
289 $s->send('EHLO example.com'); | |
290 $s->read(); | |
291 $s->send('AUTH OAUTHBEARER ' . $token); | |
292 $s->authok('smtp oauthbearer success'); | |
293 | |
294 $s = Test::Nginx::SMTP->new(); | |
295 $s->read(); | |
296 $s->send('EHLO example.com'); | |
297 $s->read(); | |
298 $s->send('AUTH OAUTHBEARER'); | |
299 $s->check(qr/^334 /, 'smtp oauthbearer challenge'); | |
300 $s->send($token); | |
301 $s->authok('smtp oauthbearer success after challenge'); | |
302 | |
303 $s = Test::Nginx::SMTP->new(); | |
304 $s->read(); | |
305 $s->send('EHLO example.com'); | |
306 $s->read(); | |
307 $s->send('AUTH OAUTHBEARER ' . $token_saslfail); | |
308 $s->check(qr/^334 eyJz/, 'smtp oauthbearer sasl failure'); | |
309 $s->send('AQ=='); | |
310 $s->check(qr/^535 /, 'smtp oauthbearer auth failure after dummy response'); | |
311 | |
312 $s->send('AUTH OAUTHBEARER ' . $token_saslfail); | |
313 $s->check(qr/^334 eyJz/, 'smtp oauthbearer sasl failure next'); | |
314 $s->send('foo'); | |
315 $s->check(qr/^500 /, 'smtp oauthbearer invalid command after invalid line'); | |
316 | |
317 $s->send('AUTH OAUTHBEARER ' . $token); | |
318 $s->authok('smtp oauthbearer success after fail'); | |
319 | |
320 # SMTP XOAUTH2 | |
321 | |
322 $s = Test::Nginx::SMTP->new(); | |
323 $s->read(); | |
324 $s->send('EHLO example.com'); | |
325 $s->read(); | |
326 $s->send('AUTH XOAUTH2 ' . $token_xoauth2); | |
327 $s->authok('smtp xoauth2 success'); | |
328 | |
329 $s = Test::Nginx::SMTP->new(); | |
330 $s->read(); | |
331 $s->send('EHLO example.com'); | |
332 $s->read(); | |
333 $s->send('AUTH XOAUTH2'); | |
334 $s->check(qr/^334 /, 'smtp xoauth2 challenge'); | |
335 $s->send($token_xoauth2); | |
336 $s->authok('smtp xoauth2 success after challenge'); | |
337 | |
338 ############################################################################### |