Cross Reference: /dovecot/src/auth/auth-request-handler.c
auth-request-handler.c revision f0cd1d0022590d0a0d84f57e362774c2e96e2ea8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
657afb33796f8216c568ad813627da89970760beTimo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "auth-common.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "ioloop.h"
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen#include "array.h"
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen#include "aqueue.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "base64.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "hash.h"
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch#include "network.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "str.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "str-sanitize.h"
d99107ddf4d9bccb710994482daf65276a9d6321Timo Sirainen#include "master-interface.h"
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen#include "auth-penalty.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "auth-request.h"
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch#include "auth-token.h"
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen#include "auth-master-connection.h"
657afb33796f8216c568ad813627da89970760beTimo Sirainen#include "auth-request-handler.h"
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include <stdlib.h>
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
a3b3e5b452be15049a1f8bfd5b3bb640af41121cTimo Sirainen#define AUTH_FAILURE_DELAY_CHECK_MSECS 500
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstruct auth_request_handler {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen int refcount;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pool_t pool;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen HASH_TABLE(void *, struct auth_request *) requests;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int connect_uid, client_pid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_callback_t *callback;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen void *context;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_callback_t *master_callback;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen unsigned int destroyed:1;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch unsigned int token_auth:1;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen};
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstatic ARRAY(struct auth_request *) auth_failures_arr;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenstatic struct aqueue *auth_failures;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic struct timeout *to_auth_failures;
657afb33796f8216c568ad813627da89970760beTimo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic void auth_failure_timeout(void *context) ATTR_NULL(1);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen#undef auth_request_handler_create
657afb33796f8216c568ad813627da89970760beTimo Sirainenstruct auth_request_handler *
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschauth_request_handler_create(bool token_auth, auth_request_callback_t *callback,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch void *context, auth_request_callback_t *master_callback)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request_handler *handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pool_t pool;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pool = pool_alloconly_create("auth request handler", 4096);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler = p_new(pool, struct auth_request_handler, 1);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount = 1;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->pool = pool;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen hash_table_create_direct(&handler->requests, pool, 0);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->callback = callback;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->context = context;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->master_callback = master_callback;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch handler->token_auth = token_auth;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainenunsigned int
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainenauth_request_handler_get_request_count(struct auth_request_handler *handler)
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainen{
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainen return hash_table_count(handler->requests);
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainen}
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainenvoid auth_request_handler_abort_requests(struct auth_request_handler *handler)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen struct hash_iterate_context *iter;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen void *key;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen struct auth_request *auth_request;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen iter = hash_table_iterate_init(handler->requests);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen while (hash_table_iterate(iter, handler->requests, &key, &auth_request)) {
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen switch (auth_request->state) {
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_NEW:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_MECH_CONTINUE:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_FINISHED:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen auth_request_unref(&auth_request);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_remove(handler->requests, key);
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen break;
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_PASSDB:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_USERDB:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen /* can't abort a pending passdb/userdb lookup */
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen break;
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen case AUTH_REQUEST_STATE_MAX:
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen i_unreached();
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen }
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen }
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen hash_table_iterate_deinit(&iter);
8c6c6b95f482d2a2cdc74db5582aeb24871e3579Timo Sirainen}
8c6c6b95f482d2a2cdc74db5582aeb24871e3579Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainenvoid auth_request_handler_unref(struct auth_request_handler **_handler)
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen{
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen struct auth_request_handler *handler = *_handler;
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen *_handler = NULL;
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen i_assert(handler->refcount > 0);
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen if (--handler->refcount > 0)
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen return;
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen i_assert(hash_table_count(handler->requests) == 0);
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen /* notify parent that we're done with all requests */
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen handler->callback(NULL, handler->context);
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen hash_table_destroy(&handler->requests);
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen pool_unref(&handler->pool);
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen}
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainenvoid auth_request_handler_destroy(struct auth_request_handler **_handler)
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen{
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen struct auth_request_handler *handler = *_handler;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen *_handler = NULL;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen i_assert(!handler->destroyed);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen handler->destroyed = TRUE;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen auth_request_handler_unref(&handler);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen}
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainenvoid auth_request_handler_set(struct auth_request_handler *handler,
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen unsigned int connect_uid,
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen unsigned int client_pid)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->connect_uid = connect_uid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->client_pid = client_pid;
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void auth_request_handler_remove(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen i_assert(request->handler == handler);
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen if (request->removed_from_handler) {
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen /* already removed it */
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen return;
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen }
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen request->removed_from_handler = TRUE;
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen /* if db lookup is stuck, this call doesn't actually free the auth
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen request, so make sure we don't get back here. */
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen timeout_remove(&request->to_abort);
e69e7b734b625de1f8921b7e0d92afa1df6b900dTimo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_remove(handler->requests, POINTER_CAST(request->id));
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&request);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstatic void get_client_extra_fields(struct auth_request *request,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct auth_stream_reply *reply)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen const char **fields, *extra_fields;
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen unsigned int src;
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen bool seen_pass = FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen if (auth_stream_is_empty(request->extra_fields))
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return;
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen extra_fields = auth_stream_reply_export(request->extra_fields);
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen
aefe17424820c57bcb05b0aaec4a930e8222baccTimo Sirainen if (!request->proxy && strstr(extra_fields, "userdb_") == NULL) {
aefe17424820c57bcb05b0aaec4a930e8222baccTimo Sirainen /* optimization: there are no userdb_* fields, we can just
aefe17424820c57bcb05b0aaec4a930e8222baccTimo Sirainen import */
aefe17424820c57bcb05b0aaec4a930e8222baccTimo Sirainen auth_stream_reply_import(reply, extra_fields);
aefe17424820c57bcb05b0aaec4a930e8222baccTimo Sirainen return;
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen fields = t_strsplit_tab(extra_fields);
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen for (src = 0; fields[src] != NULL; src++) {
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen if (strncmp(fields[src], "userdb_", 7) != 0) {
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen if (!seen_pass && strncmp(fields[src], "pass=", 5) == 0)
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen seen_pass = TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_import(reply, fields[src]);
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (request->proxy) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* we're proxying */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen if (!seen_pass && request->mech_password != NULL) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* send back the password that was sent by user
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen (not the password in passdb). */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen auth_stream_reply_add(reply, "pass",
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen request->mech_password);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
b82590193a2ebc23fcdf61a692d879fe53f996d1Timo Sirainen if (request->master_user != NULL &&
b82590193a2ebc23fcdf61a692d879fe53f996d1Timo Sirainen auth_stream_reply_find(reply, "master") == NULL) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* the master username needs to be forwarded */
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen auth_stream_reply_add(reply, "master",
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen request->master_user);
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen }
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenstatic void
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenauth_request_handle_failure(struct auth_request *request,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct auth_stream_reply *reply)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen{
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen struct auth_request_handler *handler = request->handler;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request->delayed_failure) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* we came here from flush_failures() */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->callback(reply, handler->context);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* remove the request from requests-list */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_ref(request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_handler_remove(handler, request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (request->no_failure_delay) {
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen /* passdb specifically requested not to delay the reply. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->callback(reply, handler->context);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_unref(&request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* failure. don't announce it immediately to avoid
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen a) timing attacks, b) flooding */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen request->delayed_failure = TRUE;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen handler->refcount++;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen if (auth_penalty != NULL) {
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen auth_penalty_update(auth_penalty, request,
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen request->last_penalty + 1);
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen auth_request_refresh_last_access(request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen aqueue_append(auth_failures, &request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (to_auth_failures == NULL) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen to_auth_failures =
4b335788eb41dec2de5f78459d96387fcc710010Timo Sirainen timeout_add_short(AUTH_FAILURE_DELAY_CHECK_MSECS,
f0cd1d0022590d0a0d84f57e362774c2e96e2ea8Timo Sirainen auth_failure_timeout, (void *)NULL);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen}
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenstatic void
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenauth_request_handler_reply_success_finish(struct auth_request *request)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen{
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen struct auth_request_handler *handler = request->handler;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen struct auth_stream_reply *reply;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (request->last_penalty != 0 && auth_penalty != NULL) {
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen /* reset penalty */
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_penalty_update(auth_penalty, request, 0);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "OK", NULL);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "user", request->user);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen get_client_extra_fields(request, reply);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (request->no_login || handler->master_callback == NULL) {
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen /* this request doesn't have to wait for master
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen process to pick it up. delete it */
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_remove(handler, request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen handler->callback(reply, handler->context);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen}
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenstatic void
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenauth_request_handler_reply_failure_finish(struct auth_request *request)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen{
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen struct auth_stream_reply *reply;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (request->user != NULL)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "user", request->user);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else if (request->original_username != NULL) {
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "user",
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen request->original_username);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (request->internal_failure)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "temp", NULL);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else if (request->master_user != NULL) {
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen /* authentication succeeded, but we can't log in
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen as the wanted user */
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "authz", NULL);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (request->no_failure_delay)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "nodelay", NULL);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen get_client_extra_fields(request, reply);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen switch (request->passdb_result) {
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_INTERNAL_FAILURE:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_SCHEME_NOT_AVAILABLE:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_USER_UNKNOWN:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_PASSWORD_MISMATCH:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_OK:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen break;
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_USER_DISABLED:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen auth_stream_reply_add(reply, "user_disabled", NULL);
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen break;
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen case PASSDB_RESULT_PASS_EXPIRED:
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen auth_stream_reply_add(reply, "pass_expired", NULL);
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen break;
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen }
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handle_failure(request, reply);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen}
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenstatic void
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenauth_request_handler_proxy_callback(bool success, struct auth_request *request)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen{
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen struct auth_request_handler *handler = request->handler;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (success)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_success_finish(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_failure_finish(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_unref(&handler);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen}
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainenvoid auth_request_handler_reply(struct auth_request *request,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen enum auth_client_result result,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen const void *auth_reply, size_t reply_size)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen struct auth_request_handler *handler = request->handler;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct auth_stream_reply *reply;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen string_t *str;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen int ret;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen if (handler->destroyed) {
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen /* the client connection was already closed. we can't do
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen anything but abort this request */
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen request->internal_failure = TRUE;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen result = AUTH_CLIENT_RESULT_FAILURE;
e8a96ad5c10e9d5c0c4e2e88dd09a38fdb3e34b4Timo Sirainen /* make sure this request is set to finished state
e8a96ad5c10e9d5c0c4e2e88dd09a38fdb3e34b4Timo Sirainen (it's not with result=continue) */
e8a96ad5c10e9d5c0c4e2e88dd09a38fdb3e34b4Timo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen }
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen switch (result) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case AUTH_CLIENT_RESULT_CONTINUE:
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "CONT", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(reply_size));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen base64_encode(auth_reply, reply_size, str);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, str_c(str));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen request->accept_input = TRUE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->callback(reply, handler->context);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case AUTH_CLIENT_RESULT_SUCCESS:
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (reply_size > 0) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(reply_size));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen base64_encode(auth_reply, reply_size, str);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(request->extra_fields, "resp", str_c(str));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen ret = auth_request_proxy_finish(request,
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_proxy_callback);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen if (ret < 0)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_failure_finish(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else if (ret > 0)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_success_finish(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen return;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen case AUTH_CLIENT_RESULT_FAILURE:
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_proxy_finish_failure(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_failure_finish(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* NOTE: request may be destroyed now */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_handler_unref(&handler);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainenvoid auth_request_handler_reply_continue(struct auth_request *request,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen const void *reply, size_t reply_size)
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen{
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen auth_request_handler_reply(request, AUTH_CLIENT_RESULT_CONTINUE,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen reply, reply_size);
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen}
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void auth_request_handler_auth_fail(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *reason)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct auth_stream_reply *reply;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_log_info(request, request->mech->mech_name, "%s", reason);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "reason", reason);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->callback(reply, handler->context);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_remove(handler, request);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainenstatic void auth_request_timeout(struct auth_request *request)
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen{
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen const char *str;
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen str = t_strdup_printf("Request %u.%u timeouted after %u secs, state=%d",
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen request->handler->client_pid, request->id,
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen (unsigned int)(time(NULL) - request->last_access),
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen request->state);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen if (request->state != AUTH_REQUEST_STATE_MECH_CONTINUE) {
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen /* client's fault */
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen auth_request_log_error(request, request->mech->mech_name,
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen "%s", str);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen } else if (request->set->verbose) {
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen auth_request_log_info(request, request->mech->mech_name,
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen "%s", str);
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen }
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen auth_request_handler_remove(request->handler, request);
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen}
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenstatic void auth_request_penalty_finish(struct auth_request *request)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen{
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen timeout_remove(&request->to_penalty);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_request_initial(request);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen}
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenstatic void
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenauth_penalty_callback(unsigned int penalty, struct auth_request *request)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen{
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen unsigned int secs;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->last_penalty = penalty;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (penalty == 0)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_request_initial(request);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen else {
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen secs = auth_penalty_to_secs(penalty);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->to_penalty = timeout_add(secs * 1000,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen auth_request_penalty_finish,
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen}
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainenbool auth_request_handler_auth_begin(struct auth_request_handler *handler,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const char *args)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
7242e1ce7803b83bc82e239ef111b47c1c72dd4bAndrey Panin const struct mech_module *mech;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *const *list, *name, *arg, *initial_resp;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen void *initial_resp_data;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int id;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_t *buf;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen i_assert(!handler->destroyed);
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* <id> <mechanism> [...] */
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen list = t_strsplit_tab(args);
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (list[0] == NULL || list[1] == NULL ||
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen str_to_uint(list[0], &id) < 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("BUG: Authentication client %u "
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "sent broken AUTH request", handler->client_pid);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (handler->token_auth) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch mech = &mech_dovecot_token;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (strcmp(list[1], mech->mech_name) != 0) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* unsupported mechanism */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("BUG: Authentication client %u requested invalid "
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch "authentication mechanism %s (DOVECOT-TOKEN required)",
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch handler->client_pid, str_sanitize(list[1], MAX_MECH_NAME_LEN));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return FALSE;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch } else {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch mech = mech_module_find(list[1]);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (mech == NULL) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* unsupported mechanism */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("BUG: Authentication client %u requested unsupported "
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch "authentication mechanism %s", handler->client_pid,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch str_sanitize(list[1], MAX_MECH_NAME_LEN));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return FALSE;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen request = auth_request_new(mech);
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen request->handler = handler;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->connect_uid = handler->connect_uid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->client_pid = handler->client_pid;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->id = id;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* parse optional parameters */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen initial_resp = NULL;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen for (list += 2; *list != NULL; list++) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen arg = strchr(*list, '=');
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (arg == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen name = *list;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen arg = "";
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen name = t_strdup_until(*list, arg);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen arg++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ab122a3bbae3b5fd2aad66e2f2840149d98cee52Timo Sirainen if (auth_request_import_auth(request, name, arg))
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen ;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen else if (strcmp(name, "resp") == 0) {
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen initial_resp = arg;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen /* this must be the last parameter */
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen list++;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen break;
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen }
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen }
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen if (*list != NULL) {
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen i_error("BUG: Authentication client %u "
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen "sent AUTH parameters after 'resp'",
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen handler->client_pid);
7904d81873b36f8464c96be415881f92518452e6Timo Sirainen auth_request_unref(&request);
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen return FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request->service == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("BUG: Authentication client %u "
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "didn't specify service in request",
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->client_pid);
7904d81873b36f8464c96be415881f92518452e6Timo Sirainen auth_request_unref(&request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen if (hash_table_lookup(handler->requests, POINTER_CAST(id)) != NULL) {
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen i_error("BUG: Authentication client %u "
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen "sent a duplicate ID %u", handler->client_pid, id);
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen auth_request_unref(&request);
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen return FALSE;
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen }
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen auth_request_init(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
d99107ddf4d9bccb710994482daf65276a9d6321Timo Sirainen request->to_abort = timeout_add(MASTER_AUTH_SERVER_TIMEOUT_SECS * 1000,
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen auth_request_timeout, request);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_insert(handler->requests, POINTER_CAST(id), request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen if (request->set->ssl_require_client_cert &&
258ff7d4f03dd9d29eca3664e4acacdf7f528234Timo Sirainen !request->valid_client_cert) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* we fail without valid certificate */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Client didn't present valid SSL certificate");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen /* Empty initial response is a "=" base64 string. Completely empty
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen string shouldn't really be sent, but at least Exim does it,
4f2248a8a70985c7295afc3bf91c848e81d740d9Timo Sirainen so just allow it for backwards compatibility.. */
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen if (initial_resp != NULL && *initial_resp != '\0') {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size_t len = strlen(initial_resp);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen MAX_BASE64_DECODED_SIZE(len));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (base64_decode(initial_resp, len, NULL, buf) < 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Invalid base64 data in initial response");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen initial_resp_data =
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen p_malloc(request->pool, I_MAX(buf->used, 1));
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen memcpy(initial_resp_data, buf->data, buf->used);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->initial_response = initial_resp_data;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->initial_response_len = buf->used;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen /* handler is referenced until auth_request_handler_reply()
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen is called. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen /* before we start authenticating, see if we need to wait first */
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen auth_penalty_lookup(auth_penalty, request, auth_penalty_callback);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool auth_request_handler_auth_continue(struct auth_request_handler *handler,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const char *args)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *data;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size_t data_len;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_t *buf;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int id;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen data = strchr(args, '\t');
c53a3c54d388c0031aaa642e6b14d46eb86d9485Timo Sirainen if (data == NULL || str_to_uint(t_strdup_until(args, data), &id) < 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("BUG: Authentication client sent broken CONT request");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen data++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(id));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request == NULL) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct auth_stream_reply *reply;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(id));
cac6735a6cd73f2b815a1f3c1e21855075e7c81eTimo Sirainen auth_stream_reply_add(reply, "reason",
cac6735a6cd73f2b815a1f3c1e21855075e7c81eTimo Sirainen "Authentication request timed out");
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->callback(reply, handler->context);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* accept input only once after mechanism has sent a CONT reply */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (!request->accept_input) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Unexpected continuation");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->accept_input = FALSE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen data_len = strlen(data);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen MAX_BASE64_DECODED_SIZE(data_len));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (base64_decode(data, data_len, NULL, buf) < 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Invalid base64 data in continued response");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen /* handler is referenced until auth_request_handler_reply()
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen is called. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_continue(request, buf->data, buf->used);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return TRUE;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenstatic void userdb_callback(enum userdb_result result,
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen struct auth_request *request)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen struct auth_request_handler *handler = request->handler;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct auth_stream_reply *reply;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen const char *value;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen i_assert(request->state == AUTH_REQUEST_STATE_USERDB);
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen if (request->userdb_lookup_failed)
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen result = USERDB_RESULT_INTERNAL_FAILURE;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen switch (result) {
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case USERDB_RESULT_INTERNAL_FAILURE:
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (request->userdb_lookup_failed) {
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen value = auth_stream_reply_find(request->userdb_reply,
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen "reason");
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (value != NULL)
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen auth_stream_reply_add(reply, "reason", value);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen }
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case USERDB_RESULT_USER_UNKNOWN:
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "NOTFOUND", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen case USERDB_RESULT_OK:
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "USER", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
533929e773388b28e0932fb5cfbdf455def58fe6Timo Sirainen if (request->master_user != NULL &&
533929e773388b28e0932fb5cfbdf455def58fe6Timo Sirainen auth_stream_reply_find(request->userdb_reply,
533929e773388b28e0932fb5cfbdf455def58fe6Timo Sirainen "master_user") == NULL) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(request->userdb_reply,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen "master_user",
7e078be0d6f12ca56860641d36e3c517e3046895Timo Sirainen request->master_user);
7e078be0d6f12ca56860641d36e3c517e3046895Timo Sirainen }
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen if (*request->set->anonymous_username != '\0' &&
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen strcmp(request->user,
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen request->set->anonymous_username) == 0) {
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen /* this is an anonymous login, either via ANONYMOUS
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen SASL mechanism or simply logging in as the anonymous
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen user via another mechanism */
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen auth_stream_reply_add(request->userdb_reply,
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen "anonymous", NULL);
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_import(reply,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_export(request->userdb_reply));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* generate auth_token when master service provided session_pid */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (request->session_pid != (pid_t)-1) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch const char *auth_token =
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch auth_token_get(request->service,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch dec2str(request->session_pid),
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch request->user,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch request->session_id);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch auth_stream_reply_add(reply, "auth_token", auth_token);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->master_callback(reply, request->master);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen auth_master_connection_unref(&request->master);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_unref(&request);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen auth_request_handler_unref(&handler);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschstatic bool
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschauth_master_request_failed(struct auth_request_handler *handler,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch struct auth_master_connection *master,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch struct auth_stream_reply *reply, unsigned int id)
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch{
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch auth_stream_reply_add(reply, "FAIL", NULL);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch auth_stream_reply_add(reply, NULL, dec2str(id));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (handler->master_callback == NULL)
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return FALSE;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch handler->master_callback(reply, master);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return TRUE;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch}
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainenbool auth_request_handler_master_request(struct auth_request_handler *handler,
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen struct auth_master_connection *master,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch unsigned int id, unsigned int client_id,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch const char *const *params)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct auth_request *request;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct auth_stream_reply *reply;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch struct net_unix_cred cred;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(client_id));
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (request == NULL) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("Master request %u.%u not found",
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->client_pid, client_id);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return auth_master_request_failed(handler, master, reply, id);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_ref(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_remove(handler, request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch for (; *params != NULL; params++) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch const char *name, *param = strchr(*params, '=');
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (param == NULL) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch name = *params;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch param = "";
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch } else {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch name = t_strdup_until(*params, param);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch param++;
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch (void)auth_request_import_master(request, name, param);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* verify session pid if specified and possible */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch if (request->session_pid != (pid_t)-1 &&
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch net_getunixcred(master->fd, &cred) == 0 &&
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch cred.pid != (pid_t)-1 && request->session_pid != cred.pid) {
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("Session pid %ld provided by master for request %u.%u "
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch "did not match peer credentials (pid=%ld, uid=%ld)",
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch (long)request->session_pid,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch handler->client_pid, client_id,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch (long)cred.pid, (long)cred.uid);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return auth_master_request_failed(handler, master, reply, id);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch }
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen if (request->state != AUTH_REQUEST_STATE_FINISHED ||
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen !request->successful) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("Master requested unfinished authentication request "
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "%u.%u", handler->client_pid, client_id);
647eed98cb795ee9e42911750402dab720b57514Timo Sirainen auth_stream_reply_add(reply, "FAIL", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->master_callback(reply, master);
0a8ec3c561c26c492a50511692650ea302cc8c14Timo Sirainen auth_request_unref(&request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* the request isn't being referenced anywhere anymore,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen so we can do a bit of kludging.. replace the request's
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen old client_id with master's id. */
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_USERDB);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen request->id = id;
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen request->master = master;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen /* master and handler are referenced until userdb_callback i
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen s called. */
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen auth_master_connection_ref(master);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler->refcount++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_lookup_user(request, userdb_callback);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen return TRUE;
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainenvoid auth_request_handler_cancel_request(struct auth_request_handler *handler,
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen unsigned int client_id)
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen{
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen struct auth_request *request;
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(client_id));
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen if (request != NULL)
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen auth_request_handler_remove(handler, request);
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen}
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenvoid auth_request_handler_flush_failures(bool flush_all)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen struct auth_request **auth_requests, *auth_request;
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen unsigned int i, count;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen time_t diff;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen count = aqueue_count(auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (count == 0) {
a3b3e5b452be15049a1f8bfd5b3bb640af41121cTimo Sirainen if (to_auth_failures != NULL)
a3b3e5b452be15049a1f8bfd5b3bb640af41121cTimo Sirainen timeout_remove(&to_auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen return;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_requests = array_idx_modifiable(&auth_failures_arr, 0);
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen for (i = 0; i < count; i++) {
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request = auth_requests[aqueue_idx(auth_failures, 0)];
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* FIXME: assumess that failure_delay is always the same. */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen diff = ioloop_time - auth_request->last_access;
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen if (diff < (time_t)auth_request->set->failure_delay &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen !flush_all)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen break;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen aqueue_delete_tail(auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen i_assert(auth_request->state == AUTH_REQUEST_STATE_FINISHED);
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen auth_request_handler_reply(auth_request,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen AUTH_CLIENT_RESULT_FAILURE,
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen &uchar_nul, 0);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_unref(&auth_request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenstatic void auth_failure_timeout(void *context ATTR_UNUSED)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_handler_flush_failures(FALSE);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenvoid auth_request_handler_init(void)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen i_array_init(&auth_failures_arr, 128);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_failures = aqueue_init(&auth_failures_arr.arr);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenvoid auth_request_handler_deinit(void)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_handler_flush_failures(TRUE);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen array_free(&auth_failures_arr);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen aqueue_deinit(&auth_failures);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen if (to_auth_failures != NULL)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen timeout_remove(&to_auth_failures);
657afb33796f8216c568ad813627da89970760beTimo Sirainen}