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 */
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen HASH_TABLE(void *, struct auth_request *) requests;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstatic ARRAY(struct auth_request *) auth_failures_arr;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainenstatic void auth_failure_timeout(void *context) ATTR_NULL(1);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschauth_request_handler_create(bool token_auth, auth_request_callback_t *callback,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch void *context, auth_request_callback_t *master_callback)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pool = pool_alloconly_create("auth request handler", 4096);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen handler = p_new(pool, struct auth_request_handler, 1);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen hash_table_create_direct(&handler->requests, pool, 0);
a7e2c98560cf54dc656711a237cb07da8a5a9ee4Timo Sirainenauth_request_handler_get_request_count(struct auth_request_handler *handler)
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainenvoid auth_request_handler_abort_requests(struct auth_request_handler *handler)
f19cf95ae8fc233567b1c7751595eb66876d684aTimo Sirainen iter = hash_table_iterate_init(handler->requests);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen while (hash_table_iterate(iter, handler->requests, &key, &auth_request)) {
cc4d0d30fbba883d5d1b600646491fb77bdb989cTimo Sirainen /* can't abort a pending passdb/userdb lookup */
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainenvoid auth_request_handler_unref(struct auth_request_handler **_handler)
fbee9bffb56d882b98146dd0de76a5bcccc2bdc3Timo Sirainen struct auth_request_handler *handler = *_handler;
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen i_assert(hash_table_count(handler->requests) == 0);
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen /* notify parent that we're done with all requests */
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainenvoid auth_request_handler_destroy(struct auth_request_handler **_handler)
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen struct auth_request_handler *handler = *_handler;
70905e51a5148bd5613cb04720807177474a2496Timo Sirainenvoid auth_request_handler_set(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void auth_request_handler_remove(struct auth_request_handler *handler,
ea95a057fa5f02d50027122cacd3147fce7679faTimo Sirainen /* already removed it */
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. */
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_remove(handler->requests, POINTER_CAST(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstatic void get_client_extra_fields(struct auth_request *request,
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen unsigned int src;
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen if (auth_stream_is_empty(request->extra_fields))
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen extra_fields = auth_stream_reply_export(request->extra_fields);
aefe17424820c57bcb05b0aaec4a930e8222baccTimo Sirainen if (!request->proxy && strstr(extra_fields, "userdb_") == NULL) {
aefe17424820c57bcb05b0aaec4a930e8222baccTimo Sirainen /* optimization: there are no userdb_* fields, we can just
aefe17424820c57bcb05b0aaec4a930e8222baccTimo Sirainen auth_stream_reply_import(reply, extra_fields);
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen if (strncmp(fields[src], "userdb_", 7) != 0) {
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen if (!seen_pass && strncmp(fields[src], "pass=", 5) == 0)
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). */
b82590193a2ebc23fcdf61a692d879fe53f996d1Timo Sirainen auth_stream_reply_find(reply, "master") == NULL) {
ccef83820a01bb37ad48653a05a9c5aa6560826aTimo Sirainen /* the master username needs to be forwarded */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenauth_request_handle_failure(struct auth_request *request,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen struct auth_request_handler *handler = request->handler;
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* we came here from flush_failures() */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* remove the request from requests-list */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen auth_request_handler_remove(handler, request);
9d75363d3fbabc2fbc2d80f06672e3ed8965804aTimo Sirainen /* passdb specifically requested not to delay the reply. */
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen /* failure. don't announce it immediately to avoid
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen a) timing attacks, b) flooding */
4b335788eb41dec2de5f78459d96387fcc710010Timo Sirainen timeout_add_short(AUTH_FAILURE_DELAY_CHECK_MSECS,
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenauth_request_handler_reply_success_finish(struct auth_request *request)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen struct auth_request_handler *handler = request->handler;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
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 auth_stream_reply_add(reply, NULL, dec2str(request->id));
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "user", request->user);
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 Sirainenauth_request_handler_reply_failure_finish(struct auth_request *request)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "user", request->user);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen else if (request->original_username != NULL) {
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen /* authentication succeeded, but we can't log in
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen as the wanted user */
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(reply, "nodelay", NULL);
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen auth_stream_reply_add(reply, "user_disabled", NULL);
190d84a496d6893ed54fe5bdb9e503285583d13fTimo Sirainen auth_stream_reply_add(reply, "pass_expired", NULL);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainenauth_request_handler_proxy_callback(bool success, struct auth_request *request)
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen struct auth_request_handler *handler = request->handler;
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_success_finish(request);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_request_handler_reply_failure_finish(request);
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainenvoid auth_request_handler_reply(struct auth_request *request,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen struct auth_request_handler *handler = request->handler;
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen /* the client connection was already closed. we can't do
5363f51ad46344f4e5952f2fef211a7cf8f95ddcTimo Sirainen anything but abort this request */
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);
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(reply_size));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, str_c(str));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen str = t_str_new(MAX_BASE64_ENCODED_SIZE(reply_size));
91233a89f0060f95542ed661683e5d99a50f1778Timo Sirainen auth_stream_reply_add(request->extra_fields, "resp", str_c(str));
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 auth_request_handler_reply_failure_finish(request);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* NOTE: request may be destroyed now */
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainenvoid auth_request_handler_reply_continue(struct auth_request *request,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen auth_request_handler_reply(request, AUTH_CLIENT_RESULT_CONTINUE,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void auth_request_handler_auth_fail(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_log_info(request, request->mech->mech_name, "%s", reason);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "reason", reason);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_remove(handler, request);
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainenstatic void auth_request_timeout(struct auth_request *request)
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen const char *str;
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen str = t_strdup_printf("Request %u.%u timeouted after %u secs, state=%d",
a72dde3805d0e9148de4caf44d6f4dc167431380Timo Sirainen (unsigned int)(time(NULL) - request->last_access),
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 auth_request_log_info(request, request->mech->mech_name,
48ac75465ae154b1d705f18de6d95045ab714b65Timo Sirainen auth_request_handler_remove(request->handler, request);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenstatic void auth_request_penalty_finish(struct auth_request *request)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainenauth_penalty_callback(unsigned int penalty, struct auth_request *request)
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen unsigned int secs;
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->to_penalty = timeout_add(secs * 1000,
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainenbool auth_request_handler_auth_begin(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const char *const *list, *name, *arg, *initial_resp;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int id;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* <id> <mechanism> [...] */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "sent broken AUTH request", handler->client_pid);
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 /* unsupported mechanism */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch i_error("BUG: Authentication client %u requested unsupported "
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch "authentication mechanism %s", handler->client_pid,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* parse optional parameters */
ab122a3bbae3b5fd2aad66e2f2840149d98cee52Timo Sirainen if (auth_request_import_auth(request, name, arg))
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen /* this must be the last parameter */
382c7aec3e3449ed8271c2a202b67cefaa31dc8eTimo Sirainen "sent AUTH parameters after 'resp'",
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "didn't specify service in request",
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen if (hash_table_lookup(handler->requests, POINTER_CAST(id)) != NULL) {
b5322c8270616a28f2e65cb3a09580c410bb0941Timo Sirainen "sent a duplicate ID %u", handler->client_pid, id);
d99107ddf4d9bccb710994482daf65276a9d6321Timo Sirainen request->to_abort = timeout_add(MASTER_AUTH_SERVER_TIMEOUT_SECS * 1000,
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_insert(handler->requests, POINTER_CAST(id), request);
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");
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 buf = buffer_create_dynamic(pool_datastack_create(),
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");
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen memcpy(initial_resp_data, buf->data, buf->used);
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen request->initial_response = initial_resp_data;
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen /* handler is referenced until auth_request_handler_reply()
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen is called. */
e76073ebaf90fa29abfdc364873acf78983949aaTimo Sirainen /* before we start authenticating, see if we need to wait first */
2c8ff32886e56a5e037169c9ebef4219f85a5629Timo Sirainen auth_penalty_lookup(auth_penalty, request, auth_penalty_callback);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenbool auth_request_handler_auth_continue(struct auth_request_handler *handler,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen unsigned int id;
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");
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(id));
cac6735a6cd73f2b815a1f3c1e21855075e7c81eTimo Sirainen "Authentication request timed out");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* accept input only once after mechanism has sent a CONT reply */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_auth_fail(handler, request,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen "Unexpected continuation");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buf = buffer_create_dynamic(pool_datastack_create(),
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");
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen /* handler is referenced until auth_request_handler_reply()
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen is called. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_continue(request, buf->data, buf->used);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenstatic void userdb_callback(enum userdb_result result,
50782de8a9d5ebe11ee61496b4e695a1d3875230Timo Sirainen struct auth_request_handler *handler = request->handler;
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen i_assert(request->state == AUTH_REQUEST_STATE_USERDB);
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen value = auth_stream_reply_find(request->userdb_reply,
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen auth_stream_reply_add(reply, "reason", value);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, "NOTFOUND", NULL);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(request->id));
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen "master_user",
e8e966468f2667c18ec3f0a22ee48f01fa3a6eeaTimo Sirainen if (*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 */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_export(request->userdb_reply));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* generate auth_token when master service provided session_pid */
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch auth_stream_reply_add(reply, "auth_token", auth_token);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen handler->master_callback(reply, request->master);
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen auth_master_connection_unref(&request->master);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Boschauth_master_request_failed(struct auth_request_handler *handler,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch struct auth_stream_reply *reply, unsigned int id)
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch auth_stream_reply_add(reply, NULL, dec2str(id));
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainenbool auth_request_handler_master_request(struct auth_request_handler *handler,
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch const char *const *params)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen reply = auth_stream_reply_init(pool_datastack_create());
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(client_id));
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch return auth_master_request_failed(handler, master, reply, id);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_handler_remove(handler, request);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch const char *name, *param = strchr(*params, '=');
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch (void)auth_request_import_master(request, name, param);
ab90f702ceedb7ba445a9a592be0b213b27cbafaStephan Bosch /* verify session pid if specified and possible */
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 return auth_master_request_failed(handler, master, reply, id);
615c4aba4cc0b17eefba3263b85972adaba04586Timo Sirainen if (request->state != AUTH_REQUEST_STATE_FINISHED ||
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i_error("Master requested unfinished authentication request "
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen auth_stream_reply_add(reply, NULL, dec2str(id));
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);
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen /* master and handler are referenced until userdb_callback i
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen auth_request_lookup_user(request, userdb_callback);
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainenvoid auth_request_handler_cancel_request(struct auth_request_handler *handler,
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(handler->requests, POINTER_CAST(client_id));
3b8d05391336c0e4d24c8ddcc962f350409ffbd3Timo Sirainen auth_request_handler_remove(handler, request);
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainenvoid auth_request_handler_flush_failures(bool flush_all)
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen struct auth_request **auth_requests, *auth_request;
a550b0fbcf7e876eeb88f4528209ed28cc416752Timo Sirainen unsigned int i, count;
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)];
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 &&
2872c818f9c6704609f4d67d984b033a63e3a108Timo Sirainen i_assert(auth_request->state == AUTH_REQUEST_STATE_FINISHED);
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenstatic void auth_failure_timeout(void *context ATTR_UNUSED)