Cross Reference: /dovecot/src/auth/db-ldap.c
db-ldap.c revision 5f5870385cff47efd2f58e7892f251cf13761528
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
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "auth-common.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
44fc0a34c39f1ddb3a776918630010867a5dd04eTimo Sirainen#if defined(BUILTIN_LDAP) || defined(PLUGIN_BUILD)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen#include "network.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include "ioloop.h"
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen#include "array.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include "hash.h"
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen#include "aqueue.h"
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen#include "str.h"
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen#include "env-util.h"
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen#include "var-expand.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include "settings.h"
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen#include "userdb.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include "db-ldap.h"
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#include <stddef.h>
0cb57ee35d4cab9c03434d7abf312c081ed554d4Timo Sirainen#include <stdlib.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <unistd.h>
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#define HAVE_LDAP_SASL
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen#ifdef HAVE_SASL_SASL_H
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen# include <sasl/sasl.h>
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen#elif defined (HAVE_SASL_H)
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen# include <sasl.h>
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#else
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen# undef HAVE_LDAP_SASL
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#endif
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen#ifdef LDAP_OPT_X_TLS
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen# define OPENLDAP_TLS_OPTIONS
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen#endif
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen#if SASL_VERSION_MAJOR < 2
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen# undef HAVE_LDAP_SASL
d8c2d988a913d1aae9abf2dd50c611c87d81d72aTimo Sirainen#endif
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen
594d203bdcbd160688bce5d5a6d65783b919ad49Timo Sirainen#ifndef LDAP_SASL_QUIET
594d203bdcbd160688bce5d5a6d65783b919ad49Timo Sirainen# define LDAP_SASL_QUIET 0 /* Doesn't exist in Solaris LDAP */
594d203bdcbd160688bce5d5a6d65783b919ad49Timo Sirainen#endif
594d203bdcbd160688bce5d5a6d65783b919ad49Timo Sirainen
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen/* Older versions may require calling ldap_result() twice */
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen#if LDAP_VENDOR_VERSION <= 20112
3e1ded79bbc9166aa221bcf62d8eb2bee179c557Timo Sirainen# define OPENLDAP_ASYNC_WORKAROUND
3e1ded79bbc9166aa221bcf62d8eb2bee179c557Timo Sirainen#endif
3e1ded79bbc9166aa221bcf62d8eb2bee179c557Timo Sirainen
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen/* Solaris LDAP library doesn't have LDAP_OPT_SUCCESS */
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#ifndef LDAP_OPT_SUCCESS
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen# define LDAP_OPT_SUCCESS LDAP_SUCCESS
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#endif
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenstruct db_ldap_value {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const char **values;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen bool used;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen};
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstruct db_ldap_result_iterate_context {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen pool_t pool;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct auth_request *auth_request;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const ARRAY_TYPE(ldap_field) *attr_map;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen unsigned int attr_idx;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen /* ldap_attr_name => struct db_ldap_value */
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct hash_table *ldap_attrs;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct var_expand_table *var_table;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const char *val_1_arr[2];
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen string_t *var, *debug;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen};
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstruct db_ldap_sasl_bind_context {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *authcid;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *passwd;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *realm;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen const char *authzid;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen};
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen#define DEF_STR(name) DEF_STRUCT_STR(name, ldap_settings)
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen#define DEF_INT(name) DEF_STRUCT_INT(name, ldap_settings)
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen#define DEF_BOOL(name) DEF_STRUCT_BOOL(name, ldap_settings)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic struct setting_def setting_defs[] = {
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(hosts),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(uris),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(dn),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(dnpass),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_BOOL(auth_bind),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(auth_bind_userdn),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_BOOL(tls),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_BOOL(sasl_bind),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(sasl_mech),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(sasl_realm),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(sasl_authz_id),
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen DEF_STR(tls_ca_cert_file),
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen DEF_STR(tls_ca_cert_dir),
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen DEF_STR(tls_cert_file),
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen DEF_STR(tls_key_file),
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen DEF_STR(tls_cipher_suite),
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen DEF_STR(tls_require_cert),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(deref),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(scope),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(base),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_INT(ldap_version),
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen DEF_STR(debug_level),
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen DEF_STR(ldaprc_path),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(user_attrs),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(user_filter),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(pass_attrs),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(pass_filter),
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen DEF_STR(iterate_attrs),
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen DEF_STR(iterate_filter),
a84eb0599fa1d796206eaed65c4e3239f0799276Timo Sirainen DEF_STR(default_pass_scheme),
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen DEF_BOOL(userdb_warning_disable),
e25885d4c7c4b392c66bbf26a9b892362d90f001Timo Sirainen
e25885d4c7c4b392c66bbf26a9b892362d90f001Timo Sirainen { 0, NULL, 0 }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen};
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
ab0d9eecd85f74acae18fe88529302e0776cc500Timo Sirainenstatic struct ldap_settings default_ldap_settings = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .hosts = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .uris = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .dn = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .dnpass = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .auth_bind = FALSE,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .auth_bind_userdn = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .tls = FALSE,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .sasl_bind = FALSE,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .sasl_mech = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .sasl_realm = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .sasl_authz_id = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .tls_ca_cert_file = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .tls_ca_cert_dir = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .tls_cert_file = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .tls_key_file = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .tls_cipher_suite = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .tls_require_cert = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .deref = "never",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .scope = "subtree",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .base = NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .ldap_version = 3,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .debug_level = "0",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .ldaprc_path = "",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .user_attrs = "homeDirectory=home,uidNumber=uid,gidNumber=gid",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .user_filter = "(&(objectClass=posixAccount)(uid=%u))",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .pass_attrs = "uid=user,userPassword=password",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .pass_filter = "(&(objectClass=posixAccount)(uid=%u))",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .iterate_attrs = "uid=user",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .iterate_filter = "(objectClass=posixAccount)",
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen .default_pass_scheme = "crypt",
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen .userdb_warning_disable = FALSE
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen};
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainenstatic struct ldap_connection *ldap_connections = NULL;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainenstatic int db_ldap_bind(struct ldap_connection *conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_conn_close(struct ldap_connection *conn);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic int deref2str(const char *str)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (strcasecmp(str, "never") == 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return LDAP_DEREF_NEVER;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (strcasecmp(str, "searching") == 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return LDAP_DEREF_SEARCHING;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (strcasecmp(str, "finding") == 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return LDAP_DEREF_FINDING;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (strcasecmp(str, "always") == 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return LDAP_DEREF_ALWAYS;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_fatal("LDAP: Unknown deref option '%s'", str);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainenstatic int scope2str(const char *str)
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen{
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen if (strcasecmp(str, "base") == 0)
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen return LDAP_SCOPE_BASE;
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen if (strcasecmp(str, "onelevel") == 0)
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen return LDAP_SCOPE_ONELEVEL;
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen if (strcasecmp(str, "subtree") == 0)
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen return LDAP_SCOPE_SUBTREE;
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen i_fatal("LDAP: Unknown scope option '%s'", str);
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen}
e82af44fe25ca9b88210f313548dc08538e4a677Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen#ifdef OPENLDAP_TLS_OPTIONS
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainenstatic int tls_require_cert2str(const char *str)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen{
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen if (strcasecmp(str, "never") == 0)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen return LDAP_OPT_X_TLS_NEVER;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen if (strcasecmp(str, "hard") == 0)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen return LDAP_OPT_X_TLS_HARD;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen if (strcasecmp(str, "demand") == 0)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen return LDAP_OPT_X_TLS_DEMAND;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen if (strcasecmp(str, "allow") == 0)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen return LDAP_OPT_X_TLS_ALLOW;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen if (strcasecmp(str, "try") == 0)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen return LDAP_OPT_X_TLS_TRY;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen i_fatal("LDAP: Unknown tls_require_cert value '%s'", str);
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen}
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen#endif
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
78361883c67c58e339697c167ca285731f50287bTimo Sirainenstatic int ldap_get_errno(struct ldap_connection *conn)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen int ret, err;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ret = ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, (void *) &err);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (ret != LDAP_SUCCESS) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_error("LDAP: Can't get error number: %s",
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_err2string(ret));
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen return LDAP_UNAVAILABLE;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
78361883c67c58e339697c167ca285731f50287bTimo Sirainen return err;
78361883c67c58e339697c167ca285731f50287bTimo Sirainen}
78361883c67c58e339697c167ca285731f50287bTimo Sirainen
78361883c67c58e339697c167ca285731f50287bTimo Sirainenconst char *ldap_get_error(struct ldap_connection *conn)
78361883c67c58e339697c167ca285731f50287bTimo Sirainen{
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen const char *ret;
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen char *str = NULL;
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen ret = ldap_err2string(ldap_get_errno(conn));
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen ldap_get_option(conn->ld, LDAP_OPT_ERROR_STRING, (void *)&str);
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen if (str != NULL) {
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen ret = t_strconcat(ret, ", ", str, NULL);
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen ldap_memfree(str);
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen }
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen ldap_set_option(conn->ld, LDAP_OPT_ERROR_STRING, NULL);
c184857e1fc86878761f6e47896c9cc1fad2d666Timo Sirainen return ret;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainenstatic void ldap_conn_reconnect(struct ldap_connection *conn)
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (db_ldap_connect(conn) < 0)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen}
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic int ldap_handle_error(struct ldap_connection *conn)
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen{
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen int err = ldap_get_errno(conn);
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen switch (err) {
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_SUCCESS:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen i_unreached();
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_SIZELIMIT_EXCEEDED:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_TIMELIMIT_EXCEEDED:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_NO_SUCH_ATTRIBUTE:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_UNDEFINED_TYPE:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_INAPPROPRIATE_MATCHING:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_CONSTRAINT_VIOLATION:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_TYPE_OR_VALUE_EXISTS:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_INVALID_SYNTAX:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_NO_SUCH_OBJECT:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_ALIAS_PROBLEM:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_INVALID_DN_SYNTAX:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_IS_LEAF:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_ALIAS_DEREF_PROBLEM:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_FILTER_ERROR:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen /* invalid input */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_SERVER_DOWN:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_TIMEOUT:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_UNAVAILABLE:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_BUSY:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen#ifdef LDAP_CONNECT_ERROR
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_CONNECT_ERROR:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen#endif
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_LOCAL_ERROR:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen case LDAP_INVALID_CREDENTIALS:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen default:
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen /* connection problems */
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen ldap_conn_reconnect(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 0;
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen }
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen}
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic int db_ldap_request_bind(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *request)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request_bind *brequest =
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (struct ldap_request_bind *)request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->type == LDAP_REQUEST_TYPE_BIND);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->msgid == -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->conn_state == LDAP_CONN_STATE_BOUND_AUTH ||
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state == LDAP_CONN_STATE_BOUND_DEFAULT);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->msgid = ldap_bind(conn->ld, brequest->dn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->auth_request->mech_password,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAP_AUTH_SIMPLE);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->msgid == -1) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen "ldap_bind(%s) failed: %s",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen brequest->dn, ldap_get_error(conn));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ldap_handle_error(conn) < 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* broken request, remove it */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 0;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BINDING;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic int db_ldap_request_search(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *request)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request_search *srequest =
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (struct ldap_request_search *)request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->conn_state == LDAP_CONN_STATE_BOUND_DEFAULT);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->msgid == -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->msgid =
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ldap_search(conn->ld, srequest->base, conn->set.ldap_scope,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen srequest->filter, srequest->attributes, 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->msgid == -1) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "ldap_search(%s) parsing failed: %s",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen srequest->filter, ldap_get_error(conn));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ldap_handle_error(conn) < 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* broken request, remove it */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 0;
1a59321a1116f9819e7b2899379a44de339ce802Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic bool db_ldap_request_queue_next(struct ldap_connection *conn)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *const *requestp, *request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int ret = -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
89676692402d8a58415b2c11256652322091ebabTimo Sirainen /* connecting may call db_ldap_connect_finish(), which gets us back
89676692402d8a58415b2c11256652322091ebabTimo Sirainen here. so do the connection before checking the request queue. */
89676692402d8a58415b2c11256652322091ebabTimo Sirainen if (db_ldap_connect(conn) < 0)
89676692402d8a58415b2c11256652322091ebabTimo Sirainen return FALSE;
d779da03fd24e13b0c6fbfa9a93ad0e4132c9f47Timo Sirainen
42ec694fb0f2e1fb1d8afcfb441382daea487bd9Timo Sirainen if (conn->pending_count == aqueue_count(conn->request_queue)) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* no non-pending requests */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
42ec694fb0f2e1fb1d8afcfb441382daea487bd9Timo Sirainen if (conn->pending_count > DB_LDAP_MAX_PENDING_REQUESTS) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* wait until server has replied to some requests */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
1a59321a1116f9819e7b2899379a44de339ce802Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen requestp = array_idx(&conn->request_array,
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_idx(conn->request_queue,
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen conn->pending_count));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request = *requestp;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (conn->pending_count > 0 &&
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->type == LDAP_REQUEST_TYPE_BIND) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* we can't do binds until all existing requests are finished */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen switch (conn->conn_state) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_CONN_STATE_DISCONNECTED:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_CONN_STATE_BINDING:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* wait until we're in bound state */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_CONN_STATE_BOUND_AUTH:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->type == LDAP_REQUEST_TYPE_BIND)
0c822051bb9a910ee588fd97f7ec6f9df3d1b3c6Timo Sirainen break;
0c822051bb9a910ee588fd97f7ec6f9df3d1b3c6Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* bind to default dn first */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (void)db_ldap_bind(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_CONN_STATE_BOUND_DEFAULT:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* we can do anything in this state */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen switch (request->type) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_REQUEST_TYPE_BIND:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ret = db_ldap_request_bind(conn, request);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen case LDAP_REQUEST_TYPE_SEARCH:
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ret = db_ldap_request_search(conn, request);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen }
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ret > 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* success */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->msgid != -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->pending_count++;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return TRUE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen } else if (ret < 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* disconnected */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return FALSE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen } else {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* broken request, remove from queue */
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_delete_tail(conn->request_queue);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->callback(conn, request, NULL);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return TRUE;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainenstatic bool
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainendb_ldap_check_limits(struct ldap_connection *conn, struct ldap_request *request)
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen{
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen struct ldap_request *const *first_requestp;
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen unsigned int count;
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen time_t secs_diff;
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen count = aqueue_count(conn->request_queue);
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen if (count == 0)
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen return TRUE;
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen first_requestp = array_idx(&conn->request_array,
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen aqueue_idx(conn->request_queue, 0));
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen secs_diff = ioloop_time - (*first_requestp)->create_time;
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen if (secs_diff > DB_LDAP_REQUEST_LOST_TIMEOUT_SECS) {
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen "Connection appears to be hanging, reconnecting");
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen ldap_conn_reconnect(conn);
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen return TRUE;
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen }
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen return TRUE;
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen}
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenvoid db_ldap_request(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *request)
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen{
d95ef05d0c6ea5fdc8bc877dcf8f3b8fff6d8fb4Timo Sirainen i_assert(request->auth_request != NULL);
d95ef05d0c6ea5fdc8bc877dcf8f3b8fff6d8fb4Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->msgid = -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->create_time = ioloop_time;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
584a5375b70caa8bf7b202248aea84092bcb9c22Timo Sirainen if (!db_ldap_check_limits(conn, request)) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->callback(conn, request, NULL);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_append(conn->request_queue, &request);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (void)db_ldap_request_queue_next(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic int db_ldap_connect_finish(struct ldap_connection *conn, int ret)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ret == LDAP_SERVER_DOWN) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_error("LDAP: Can't connect to server: %s",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->set.uris != NULL ?
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->set.uris : conn->set.hosts);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ret != LDAP_SUCCESS) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_error("LDAP: binding failed (dn %s): %s",
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->set.dn == NULL ? "(none)" : conn->set.dn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ldap_get_error(conn));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen if (conn->to != NULL)
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen timeout_remove(&conn->to);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BOUND_DEFAULT;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen while (db_ldap_request_queue_next(conn))
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return 0;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_default_bind_finished(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen LDAPMessage *res)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int ret;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->default_bind_msgid = -1;
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ret = ldap_result2error(conn->ld, res, FALSE);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (db_ldap_connect_finish(conn, ret) < 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* lost connection, close it */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_abort_requests(struct ldap_connection *conn,
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen unsigned int max_count,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen unsigned int timeout_secs,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen bool error, const char *reason)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *const *requestp, *request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen time_t diff;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen while (aqueue_count(conn->request_queue) > 0 && max_count > 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen requestp = array_idx(&conn->request_array,
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_idx(conn->request_queue, 0));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request = *requestp;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen diff = ioloop_time - request->create_time;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (diff < (time_t)timeout_secs)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen break;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* timed out, abort */
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_delete_tail(conn->request_queue);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->msgid != -1) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count > 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->pending_count--;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen }
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen if (error) {
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen "%s", reason);
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen } else {
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen auth_request_log_info(request->auth_request, "ldap",
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen "%s", reason);
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->callback(conn, request, NULL);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen max_count--;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic struct ldap_request *
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainendb_ldap_find_request(struct ldap_connection *conn, int msgid,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned int *idx_r)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *const *requests, *request = NULL;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen unsigned int i, count;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen count = aqueue_count(conn->request_queue);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (count == 0)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return NULL;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen requests = array_idx(&conn->request_array, 0);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen for (i = 0; i < count; i++) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen request = requests[aqueue_idx(conn->request_queue, i)];
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (request->msgid == msgid) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen *idx_r = i;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return request;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (request->msgid == -1)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen break;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return NULL;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainendb_ldap_handle_result(struct ldap_connection *conn, LDAPMessage *res)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct ldap_request *request;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned int idx;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int msgid, ret;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen msgid = ldap_msgid(res);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (msgid == conn->default_bind_msgid) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_default_bind_finished(conn, res);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen }
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen request = db_ldap_find_request(conn, msgid, &idx);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request == NULL) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_error("LDAP: Reply with unknown msgid %d", msgid);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen return;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen i_assert(conn->pending_count > 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (request->type == LDAP_REQUEST_TYPE_BIND) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->conn_state == LDAP_CONN_STATE_BINDING);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BOUND_AUTH;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } else {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen switch (ldap_msgtype(res)) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen case LDAP_RES_SEARCH_ENTRY:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen case LDAP_RES_SEARCH_RESULT:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen break;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen case LDAP_RES_SEARCH_REFERENCE:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* we're going to ignore this */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen default:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen i_error("LDAP: Reply with unexpected type %d",
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ldap_msgtype(res));
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (ldap_msgtype(res) == LDAP_RES_SEARCH_ENTRY)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ret = LDAP_SUCCESS;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen else {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen conn->pending_count--;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen aqueue_delete(conn->request_queue, idx);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ret = ldap_result2error(conn->ld, res, 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (ret != LDAP_SUCCESS && request->type == LDAP_REQUEST_TYPE_SEARCH) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* handle search failures here */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request_search *srequest =
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen (struct ldap_request_search *)request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen auth_request_log_error(request->auth_request, "ldap",
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen "ldap_search(base=%s filter=%s) failed: %s",
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen srequest->base, srequest->filter,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_err2string(ret));
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen res = NULL;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->callback(conn, request, res);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (idx > 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* see if there are timed out requests */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen db_ldap_abort_requests(conn, idx,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen DB_LDAP_REQUEST_LOST_TIMEOUT_SECS,
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen TRUE, "Request lost");
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen}
ed5e91e58dfc372c2135c55427bf6f25a7725042Timo Sirainen
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic void ldap_input(struct ldap_connection *conn)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct timeval timeout;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen LDAPMessage *res;
c51fe409810cbb2432b72d6819bd183469fcaebcTimo Sirainen time_t prev_reply_diff;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen int ret;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen do {
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen if (conn->ld == NULL)
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen return;
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen memset(&timeout, 0, sizeof(timeout));
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ret = ldap_result(conn->ld, LDAP_RES_ANY, 0, &timeout, &res);
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen#ifdef OPENLDAP_ASYNC_WORKAROUND
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen if (ret == 0) {
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen /* try again, there may be another in buffer */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ret = ldap_result(conn->ld, LDAP_RES_ANY, 0,
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen &timeout, &res);
a8fc29f19ea6e2d472ba779b2dd5ca4e1f3dac79Timo Sirainen }
7d6389e4053c2dac1fb37180b5756b00785983dcTimo Sirainen#endif
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen if (ret <= 0)
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen break;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_handle_result(conn, res);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_msgfree(res);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } while (conn->io != NULL);
c51fe409810cbb2432b72d6819bd183469fcaebcTimo Sirainen
c51fe409810cbb2432b72d6819bd183469fcaebcTimo Sirainen prev_reply_diff = ioloop_time - conn->last_reply_stamp;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->last_reply_stamp = ioloop_time;
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (ret > 0) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* input disabled, continue once it's enabled */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen i_assert(conn->io == NULL);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } else if (ret == 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* send more requests */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen while (db_ldap_request_queue_next(conn))
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen ;
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen } else if (ldap_get_errno(conn) != LDAP_SERVER_DOWN) {
613daa324c2b61ec69291519a57186be7cc23286Timo Sirainen i_error("LDAP: ldap_result() failed: %s", ldap_get_error(conn));
0d68d1da0825e01be3f207042b9132ae8dfc9c06Timo Sirainen ldap_conn_reconnect(conn);
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen } else if (aqueue_count(conn->request_queue) > 0 ||
c51fe409810cbb2432b72d6819bd183469fcaebcTimo Sirainen prev_reply_diff < DB_LDAP_IDLE_RECONNECT_SECS) {
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen i_error("LDAP: Connection lost to LDAP server, reconnecting");
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen ldap_conn_reconnect(conn);
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen } else {
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen /* server probably disconnected an idle connection. don't
d39e77e1f7f58e1e21042a673b718541fa3f63c7Timo Sirainen reconnect until the next request comes. */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
54cc31729775282a6f3e0c02adcd1ab4cadc1cdfTimo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#ifdef HAVE_LDAP_SASL
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainenstatic int
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainensasl_interact(LDAP *ld ATTR_UNUSED, unsigned flags ATTR_UNUSED,
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen void *defaults, void *interact)
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct db_ldap_sasl_bind_context *context = defaults;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen sasl_interact_t *in;
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen const char *str;
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen for (in = interact; in->id != SASL_CB_LIST_END; in++) {
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen switch (in->id) {
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen case SASL_CB_GETREALM:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = context->realm;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen break;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen case SASL_CB_AUTHNAME:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = context->authcid;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen break;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen case SASL_CB_USER:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = context->authzid;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen break;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen case SASL_CB_PASS:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = context->passwd;
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen break;
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen default:
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen str = NULL;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen break;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen }
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen if (str != NULL) {
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen in->len = strlen(str);
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen in->result = str;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen }
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen }
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen return LDAP_SUCCESS;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen}
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#endif
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainenstatic void ldap_connection_timeout(struct ldap_connection *conn)
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen{
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen i_assert(conn->conn_state == LDAP_CONN_STATE_BINDING);
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen i_error("LDAP: Initial binding to LDAP server timed out");
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen db_ldap_conn_close(conn);
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen}
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainenstatic int db_ldap_bind(struct ldap_connection *conn)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen{
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen int msgid;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->conn_state != LDAP_CONN_STATE_BINDING);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->default_bind_msgid == -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
763fd2ac217023c0940415379abcd5eb7a0f7ba7Timo Sirainen msgid = ldap_bind(conn->ld, conn->set.dn, conn->set.dnpass,
763fd2ac217023c0940415379abcd5eb7a0f7ba7Timo Sirainen LDAP_AUTH_SIMPLE);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen if (msgid == -1) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(ldap_get_errno(conn) != LDAP_SUCCESS);
7cf0a6613fca9983b8a3443f9f6ef15df5a22162Timo Sirainen if (db_ldap_connect_finish(conn, ldap_get_errno(conn)) < 0) {
7cf0a6613fca9983b8a3443f9f6ef15df5a22162Timo Sirainen /* lost connection, close it */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
7cf0a6613fca9983b8a3443f9f6ef15df5a22162Timo Sirainen }
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen }
1a59321a1116f9819e7b2899379a44de339ce802Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BINDING;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->default_bind_msgid = msgid;
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen if (conn->to != NULL)
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen timeout_remove(&conn->to);
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen conn->to = timeout_add(DB_LDAP_REQUEST_LOST_TIMEOUT_SECS*1000,
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen ldap_connection_timeout, conn);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return 0;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen}
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainenstatic void db_ldap_get_fd(struct ldap_connection *conn)
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen{
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen int ret;
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen /* get the connection's fd */
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen ret = ldap_get_option(conn->ld, LDAP_OPT_DESC, (void *)&conn->fd);
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen if (ret != LDAP_SUCCESS) {
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen i_fatal("LDAP: Can't get connection fd: %s",
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen ldap_err2string(ret));
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn->fd <= STDERR_FILENO) {
d2ded6e1da2d07ac070888873ddc10999a6d87baTimo Sirainen /* Solaris LDAP library seems to be broken */
d2ded6e1da2d07ac070888873ddc10999a6d87baTimo Sirainen i_fatal("LDAP: Buggy LDAP library returned wrong fd: %d",
d2ded6e1da2d07ac070888873ddc10999a6d87baTimo Sirainen conn->fd);
d2ded6e1da2d07ac070888873ddc10999a6d87baTimo Sirainen }
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen i_assert(conn->fd != -1);
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen net_set_nonblock(conn->fd, TRUE);
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen}
b270b29d458f3cbd6e63320bb17e23f809da0045Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainenstatic void
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainendb_ldap_set_opt(struct ldap_connection *conn, int opt, const void *value,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen const char *optname, const char *value_str)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen{
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen int ret;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen ret = ldap_set_option(conn == NULL ? NULL : conn->ld, opt, value);
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen if (ret != LDAP_SUCCESS) {
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen i_fatal("LDAP: Can't set option %s to %s: %s",
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen optname, value_str, ldap_err2string(ret));
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen }
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen}
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainenstatic void
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainendb_ldap_set_opt_str(struct ldap_connection *conn, int opt, const char *value,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen const char *optname)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen{
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen if (value != NULL)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_opt(conn, opt, value, optname, value);
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen}
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainenstatic void db_ldap_set_tls_options(struct ldap_connection *conn)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen{
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen if (!conn->set.tls)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen return;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen#ifdef OPENLDAP_TLS_OPTIONS
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_CACERTFILE,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen conn->set.tls_ca_cert_file, "tls_ca_cert_file");
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_CACERTDIR,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen conn->set.tls_ca_cert_dir, "tls_ca_cert_dir");
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_CERTFILE,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen conn->set.tls_cert_file, "tls_cert_file");
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_KEYFILE,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen conn->set.tls_key_file, "tls_key_file");
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_opt_str(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen conn->set.tls_cipher_suite, "tls_cipher_suite");
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen if (conn->set.tls_require_cert != NULL) {
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen int value = tls_require_cert2str(conn->set.tls_require_cert);
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_opt(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &value,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen "tls_require_cert", conn->set.tls_require_cert);
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen }
f023d5a1665cc388131159914898ceecc526eda5Timo Sirainen#else
f023d5a1665cc388131159914898ceecc526eda5Timo Sirainen if (conn->set.tls_ca_cert_file != NULL ||
f023d5a1665cc388131159914898ceecc526eda5Timo Sirainen conn->set.tls_ca_cert_dir != NULL ||
f023d5a1665cc388131159914898ceecc526eda5Timo Sirainen conn->set.tls_cert_file != NULL ||
f023d5a1665cc388131159914898ceecc526eda5Timo Sirainen conn->set.tls_key_file != NULL ||
f023d5a1665cc388131159914898ceecc526eda5Timo Sirainen conn->set.tls_cipher_suite != NULL)
f023d5a1665cc388131159914898ceecc526eda5Timo Sirainen i_warning("LDAP: tls_* settings ignored, "
f023d5a1665cc388131159914898ceecc526eda5Timo Sirainen "your LDAP library doesn't seem to support them");
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen#endif
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen}
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainenstatic void db_ldap_set_options(struct ldap_connection *conn)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen{
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen unsigned int ldap_version;
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen int value;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_opt(conn, LDAP_OPT_DEREF, &conn->set.ldap_deref,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen "deref", conn->set.deref);
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen#ifdef LDAP_OPT_DEBUG_LEVEL
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen value = atoi(conn->set.debug_level);
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen if (value != 0) {
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen db_ldap_set_opt(NULL, LDAP_OPT_DEBUG_LEVEL, &value,
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen "debug_level", conn->set.debug_level);
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen }
f4a19b0cf11cdff437571708d9d788d02a906a00Timo Sirainen#endif
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
4756ae94c4db02e694c3425d9d949678117b66a3Timo Sirainen if (conn->set.ldap_version < 3) {
4756ae94c4db02e694c3425d9d949678117b66a3Timo Sirainen if (conn->set.sasl_bind)
4756ae94c4db02e694c3425d9d949678117b66a3Timo Sirainen i_fatal("LDAP: sasl_bind=yes requires ldap_version=3");
4756ae94c4db02e694c3425d9d949678117b66a3Timo Sirainen if (conn->set.tls)
4756ae94c4db02e694c3425d9d949678117b66a3Timo Sirainen i_fatal("LDAP: tls=yes requires ldap_version=3");
4756ae94c4db02e694c3425d9d949678117b66a3Timo Sirainen }
4756ae94c4db02e694c3425d9d949678117b66a3Timo Sirainen
4756ae94c4db02e694c3425d9d949678117b66a3Timo Sirainen ldap_version = conn->set.ldap_version;
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_opt(conn, LDAP_OPT_PROTOCOL_VERSION, &ldap_version,
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen "protocol_version", dec2str(ldap_version));
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_tls_options(conn);
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen}
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainenint db_ldap_connect(struct ldap_connection *conn)
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen{
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen int ret;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (conn->conn_state != LDAP_CONN_STATE_DISCONNECTED)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return 0;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->ld == NULL) {
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen if (conn->set.uris != NULL) {
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#ifdef LDAP_HAVE_INITIALIZE
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen if (ldap_initialize(&conn->ld, conn->set.uris) != LDAP_SUCCESS)
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen conn->ld = NULL;
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#else
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen i_fatal("LDAP: Your LDAP library doesn't support "
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen "'uris' setting, use 'hosts' instead.");
48559742084e98049335c21c53dfd1ff95f11cd8Timo Sirainen#endif
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen } else
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen conn->ld = ldap_init(conn->set.hosts, LDAP_PORT);
e65cc79f80577e83c706f0678c78e2c0bd91434fTimo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->ld == NULL)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_fatal("LDAP: ldap_init() failed with hosts: %s",
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->set.hosts);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
b96dcd982888d89e6f2508258d6d9588d79c7a26Timo Sirainen db_ldap_set_options(conn);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen if (conn->set.tls) {
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen#ifdef LDAP_HAVE_START_TLS_S
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen ret = ldap_start_tls_s(conn->ld, NULL, NULL);
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen if (ret != LDAP_SUCCESS) {
8f0a5540a21d235f4f830517c6211f6f92948f2cTimo Sirainen if (ret == LDAP_OPERATIONS_ERROR &&
8f0a5540a21d235f4f830517c6211f6f92948f2cTimo Sirainen strncmp(conn->set.uris, "ldaps:", 6) == 0) {
8f0a5540a21d235f4f830517c6211f6f92948f2cTimo Sirainen i_fatal("LDAP: Don't use both tls=yes "
8f0a5540a21d235f4f830517c6211f6f92948f2cTimo Sirainen "and ldaps URI");
8f0a5540a21d235f4f830517c6211f6f92948f2cTimo Sirainen }
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen i_error("LDAP: ldap_start_tls_s() failed: %s",
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen ldap_err2string(ret));
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen }
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen#else
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen i_error("LDAP: Your LDAP library doesn't support TLS");
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen#endif
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen }
40992309053d51192ae1b36d1dd6c057f2d37257Timo Sirainen
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen if (conn->set.sasl_bind) {
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen#ifdef HAVE_LDAP_SASL
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct db_ldap_sasl_bind_context context;
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen
dd2d3ef41dc407afb8afc49e18ff53640e4b4e02Timo Sirainen memset(&context, 0, sizeof(context));
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen context.authcid = conn->set.dn;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen context.passwd = conn->set.dnpass;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen context.realm = conn->set.sasl_realm;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen context.authzid = conn->set.sasl_authz_id;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen /* There doesn't seem to be a way to do SASL binding
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen asynchronously.. */
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen ret = ldap_sasl_interactive_bind_s(conn->ld, NULL,
23f8c5356cacdbd1cc09a39a08ef37a39125bb74Timo Sirainen conn->set.sasl_mech,
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen NULL, NULL, LDAP_SASL_QUIET,
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen sasl_interact, &context);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen if (db_ldap_connect_finish(conn, ret) < 0)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen#else
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen i_fatal("LDAP: sasl_bind=yes but no SASL support compiled in");
efb7a523ea2f7670ca07acaaa5aeb30692ad6cd3Timo Sirainen#endif
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_BOUND_DEFAULT;
a399486f2d8d5bed51bc6344baba61a7f2b0dcdbTimo Sirainen } else {
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen if (db_ldap_bind(conn) < 0)
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return -1;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_get_fd(conn);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen conn->io = io_add(conn->fd, IO_READ, ldap_input, conn);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen return 0;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenvoid db_ldap_enable_input(struct ldap_connection *conn, bool enable)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (!enable) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (conn->io != NULL)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen io_remove(&conn->io);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } else {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (conn->io == NULL && conn->fd != -1) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen conn->io = io_add(conn->fd, IO_READ, ldap_input, conn);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ldap_input(conn);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_disconnect_timeout(struct ldap_connection *conn)
095034a7699bfc464a07883f633551b5c313c4e7Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_abort_requests(conn, -1U,
1512eb3e1f8d7366122089a03e3c8688986a5a26Timo Sirainen DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS, FALSE,
1512eb3e1f8d7366122089a03e3c8688986a5a26Timo Sirainen "Aborting (timeout), we're not connected to LDAP server");
095034a7699bfc464a07883f633551b5c313c4e7Timo Sirainen
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen if (aqueue_count(conn->request_queue) == 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen /* no requests left, remove this timeout handler */
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen timeout_remove(&conn->to);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen}
095034a7699bfc464a07883f633551b5c313c4e7Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainenstatic void db_ldap_conn_close(struct ldap_connection *conn)
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen{
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen struct ldap_request *const *requests, *request;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen unsigned int i;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_DISCONNECTED;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->default_bind_msgid = -1;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen if (conn->to != NULL)
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen timeout_remove(&conn->to);
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen if (conn->pending_count != 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen requests = array_idx(&conn->request_array, 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen for (i = 0; i < conn->pending_count; i++) {
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen request = requests[aqueue_idx(conn->request_queue, i)];
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(request->msgid != -1);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen request->msgid = -1;
e023e3c2677ab66d7a7445eae9caf3d739e199cbTimo Sirainen }
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->pending_count = 0;
9e7182d6fa1940ec14cc2938699820b68ee1dc0dTimo Sirainen }
ebfcfd258acc89633c47d9c3b0b40a1a3f75cdcbTimo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->ld != NULL) {
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen ldap_unbind(conn->ld);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->ld = NULL;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen conn->fd = -1;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
baf992882696ce085fa9122a559dbba8e627e19fTimo Sirainen if (conn->io != NULL) {
baf992882696ce085fa9122a559dbba8e627e19fTimo Sirainen /* the fd may have already been closed before ldap_unbind(),
baf992882696ce085fa9122a559dbba8e627e19fTimo Sirainen so we'll have to use io_remove_closed(). */
baf992882696ce085fa9122a559dbba8e627e19fTimo Sirainen io_remove_closed(&conn->io);
baf992882696ce085fa9122a559dbba8e627e19fTimo Sirainen }
baf992882696ce085fa9122a559dbba8e627e19fTimo Sirainen
2d0a002723dac5c58c250f6566efb1f5e474c169Timo Sirainen if (aqueue_count(conn->request_queue) > 0) {
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->to = timeout_add(DB_LDAP_REQUEST_DISCONNECT_TIMEOUT_SECS *
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen 1000/2, db_ldap_disconnect_timeout, conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainenstruct ldap_field_find_context {
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen ARRAY_TYPE(string) attr_names;
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen pool_t pool;
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen};
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainenstatic const char *
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainendb_ldap_field_find(const char *data, void *context)
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen{
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen struct ldap_field_find_context *ctx = context;
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen char *ldap_attr;
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen if (*data != '\0') {
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen ldap_attr = p_strdup(ctx->pool, data);
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen array_append(&ctx->attr_names, &ldap_attr, 1);
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen }
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen return NULL;
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen}
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainenvoid db_ldap_set_attrs(struct ldap_connection *conn, const char *attrlist,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen char ***attr_names_r, ARRAY_TYPE(ldap_field) *attr_map,
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen const char *skip_attr)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen static struct var_expand_func_table var_funcs_table[] = {
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen { "ldap", db_ldap_field_find },
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen { NULL, NULL }
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen };
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen struct ldap_field_find_context ctx;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct ldap_field *field;
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen string_t *tmp_str;
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen const char *const *attr, *attr_data, *p;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen char *ldap_attr, *name, *templ;
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen unsigned int i;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen if (*attrlist == '\0')
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen return;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen attr = t_strsplit_spaces(attrlist, ",");
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen tmp_str = t_str_new(128);
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen ctx.pool = conn->pool;
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen p_array_init(&ctx.attr_names, conn->pool, 16);
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen for (i = 0; attr[i] != NULL; i++) {
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen /* allow spaces here so "foo=1, bar=2" works */
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen attr_data = attr[i];
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen while (*attr_data == ' ') attr_data++;
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen
99ee694f4099ea3dcc3b6b8331b093a8f1a2c604Timo Sirainen p = strchr(attr_data, '=');
acbf19bc103b663fbc311a3b2b88d586ea60c20dTimo Sirainen if (p == NULL)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_attr = name = p_strdup(conn->pool, attr_data);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen else {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_attr = p_strdup_until(conn->pool, attr_data, p);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen name = p_strdup(conn->pool, p + 1);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
9f431ccfb6932746db56245c8a3d3415717ef545Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen templ = strchr(name, '=');
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (templ == NULL)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen templ = "";
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen else {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen *templ++ = '\0';
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen str_truncate(tmp_str, 0);
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen var_expand_with_funcs(tmp_str, templ, NULL,
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen var_funcs_table, &ctx);
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (*name == '\0')
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen i_error("ldap: Invalid attrs entry: %s", attr_data);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen else if (skip_attr == NULL || strcmp(skip_attr, name) != 0) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen field = array_append_space(attr_map);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen field->name = name;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen field->value = templ;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen field->ldap_attr_name = ldap_attr;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (*ldap_attr != '\0')
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen array_append(&ctx.attr_names, &ldap_attr, 1);
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen }
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen (void)array_append_space(&ctx.attr_names);
63cf2e557bdd9dd8bb4e2ecb84763ef884231f18Timo Sirainen *attr_names_r = array_idx_modifiable(&ctx.attr_names, 0);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainenstatic struct var_expand_table *
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainendb_ldap_value_get_var_expand_table(pool_t pool,
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen struct auth_request *auth_request)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const struct var_expand_table *auth_table = NULL;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen struct var_expand_table *table;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen unsigned int count;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen auth_table = auth_request_get_var_expand_table(auth_request, NULL);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen for (count = 0; auth_table[count].key != '\0'; count++) ;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen count++;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen table = p_new(pool, struct var_expand_table, count + 2);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen table[0].key = '$';
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen memcpy(table + 1, auth_table, sizeof(*table) * count);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen return table;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen#define IS_LDAP_ESCAPED_CHAR(c) \
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen ((c) == '*' || (c) == '(' || (c) == ')' || (c) == '\\')
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen
3c9783956dea385b322cd7fa6bf8c98c17a907a0Timo Sirainenconst char *ldap_escape(const char *str,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen const struct auth_request *auth_request ATTR_UNUSED)
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen{
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen const char *p;
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen string_t *ret;
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen for (p = str; *p != '\0'; p++) {
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen if (IS_LDAP_ESCAPED_CHAR(*p))
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen break;
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen }
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen if (*p == '\0')
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen return str;
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen ret = t_str_new((size_t) (p - str) + 64);
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen str_append_n(ret, str, (size_t) (p - str));
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen for (; *p != '\0'; p++) {
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen if (IS_LDAP_ESCAPED_CHAR(*p))
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen str_append_c(ret, '\\');
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen str_append_c(ret, *p);
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen }
1c38a95332f1945c9806d7d83175a0d948f51291Timo Sirainen return str_c(ret);
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen}
d1f0acc7fc722e13e8296228703adfe8a884d59eTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenstatic bool
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenldap_field_hide_password(struct db_ldap_result_iterate_context *ctx,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const char *attr)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const struct ldap_field *field;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (ctx->auth_request->set->debug_passwords)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen return FALSE;
db966fce2a30ac996d90ad31daffe47734ef4ad9Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen array_foreach(ctx->attr_map, field) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (strcmp(field->ldap_attr_name, attr) == 0) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (strcmp(field->name, "password") == 0 ||
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen strcmp(field->name, "password_noscheme") == 0)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen return TRUE;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen }
db966fce2a30ac996d90ad31daffe47734ef4ad9Timo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen return FALSE;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainenstatic void
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenget_ldap_fields(struct db_ldap_result_iterate_context *ctx,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct ldap_connection *conn, LDAPMessage *entry)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct db_ldap_value *ldap_value;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen char *attr, **vals;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen unsigned int i, count;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen BerElement *ber;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen attr = ldap_first_attribute(conn->ld, entry, &ber);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen while (attr != NULL) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen vals = ldap_get_values(conn->ld, entry, attr);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_value = p_new(ctx->pool, struct db_ldap_value, 1);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (vals == NULL) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_value->values = p_new(ctx->pool, const char *, 1);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen count = 0;
337db2d47544b384b06cda46931560f9f54530b2Timo Sirainen } else {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen for (count = 0; vals[count] != NULL; count++) ;
337db2d47544b384b06cda46931560f9f54530b2Timo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_value->values = p_new(ctx->pool, const char *, count + 1);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen for (i = 0; i < count; i++)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_value->values[i] = p_strdup(ctx->pool, vals[i]);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (ctx->debug != NULL) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_printfa(ctx->debug, " %s=", attr);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (count == 0)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_append(ctx->debug, "<no values>");
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen else if (ldap_field_hide_password(ctx, attr))
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_append(ctx->debug, PASSWORD_HIDDEN_STR);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen else {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_append(ctx->debug, ldap_value->values[0]);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen for (i = 1; i < count; i++) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_printfa(ctx->debug, ",%s",
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_value->values[0]);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen hash_table_insert(ctx->ldap_attrs,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen p_strdup(ctx->pool, attr), ldap_value);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_value_free(vals);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_memfree(attr);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen attr = ldap_next_attribute(conn->ld, entry, ber);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ber_free(ber, 0);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenstruct db_ldap_result_iterate_context *
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainendb_ldap_result_iterate_init(struct ldap_connection *conn, LDAPMessage *entry,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct auth_request *auth_request,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const ARRAY_TYPE(ldap_field) *attr_map)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct db_ldap_result_iterate_context *ctx;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen pool_t pool;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen pool = pool_alloconly_create("ldap result iter", 1024);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ctx = p_new(pool, struct db_ldap_result_iterate_context, 1);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ctx->pool = pool;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ctx->auth_request = auth_request;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ctx->attr_map = attr_map;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ctx->ldap_attrs =
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen hash_table_create(default_pool, pool, 0, strcase_hash,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen (hash_cmp_callback_t *)strcasecmp);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (auth_request->set->debug)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ctx->debug = t_str_new(256);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen get_ldap_fields(ctx, conn, entry);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen return ctx;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainenstatic const char *db_ldap_field_expand(const char *data, void *context)
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen{
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen struct db_ldap_result_iterate_context *ctx = context;
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen struct db_ldap_value *ldap_value;
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen ldap_value = hash_table_lookup(ctx->ldap_attrs, data);
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen if (ldap_value == NULL) {
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen /* ldap attribute wasn't requested */
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen if (ctx->debug)
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen str_printfa(ctx->debug, "; %s missing", data);
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen return "";
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen }
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen ldap_value->used = TRUE;
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen if (ldap_value->values[0] == NULL) {
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen /* no value for ldap attribute */
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen return "";
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen }
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen if (ldap_value->values[1] != NULL) {
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen auth_request_log_warning(ctx->auth_request, "ldap",
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen "Multiple values found for '%s', using value '%s'",
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen data, ldap_value->values[0]);
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen }
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen return ldap_value->values[0];
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen}
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenstatic const char *const *
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainendb_ldap_result_return_value(struct db_ldap_result_iterate_context *ctx,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const struct ldap_field *field,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct db_ldap_value *ldap_value)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen{
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen static struct var_expand_func_table var_funcs_table[] = {
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen { "ldap", db_ldap_field_expand },
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen { NULL, NULL }
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen };
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const char *const *values;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen if (ldap_value != NULL)
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen values = ldap_value->values;
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen else {
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen /* LDAP attribute doesn't exist */
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen ctx->val_1_arr[0] = NULL;
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen values = ctx->val_1_arr;
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen }
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (*field->value == '\0') {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen /* use the LDAP attribute's value */
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen } else {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen /* template */
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen if (values[0] != NULL && values[1] != NULL) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen auth_request_log_warning(ctx->auth_request, "ldap",
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen "Multiple values found for '%s', "
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen "using value '%s'",
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen field->name, values[0]);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen }
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen if (ctx->var_table == NULL) {
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen ctx->var_table = db_ldap_value_get_var_expand_table(
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen ctx->pool, ctx->auth_request);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ctx->var = str_new(ctx->pool, 256);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
7c85bb54c14c0ca3e7171431f99a594615792086Timo Sirainen ctx->var_table[0].value = values[0];
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_truncate(ctx->var, 0);
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen var_expand_with_funcs(ctx->var, field->value, ctx->var_table,
c349375340580e4ef10b427323c6e67c14ae4996Timo Sirainen var_funcs_table, ctx);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ctx->val_1_arr[0] = str_c(ctx->var);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen values = ctx->val_1_arr;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen return values;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenbool db_ldap_result_iterate_next(struct db_ldap_result_iterate_context *ctx,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const char **name_r,
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const char *const **values_r)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const struct ldap_field *field;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct db_ldap_value *ldap_value;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (ctx->attr_idx == array_count(ctx->attr_map))
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen return FALSE;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen field = array_idx(ctx->attr_map, ctx->attr_idx++);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_value = *field->ldap_attr_name == '\0' ? NULL :
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen hash_table_lookup(ctx->ldap_attrs, field->ldap_attr_name);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (ldap_value != NULL)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen ldap_value->used = TRUE;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen else if (ctx->debug && *field->ldap_attr_name != '\0')
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_printfa(ctx->debug, "; %s missing", field->ldap_attr_name);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen *name_r = field->name;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen *values_r = db_ldap_result_return_value(ctx, field, ldap_value);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if ((*values_r)[0] == NULL) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen /* no values. don't confuse the caller with this reply. */
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen return db_ldap_result_iterate_next(ctx, name_r, values_r);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen return TRUE;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenstatic void
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainendb_ldap_result_finish_debug(struct db_ldap_result_iterate_context *ctx)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct hash_iterate_context *iter;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen void *key, *value;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen unsigned int orig_len, unused_count = 0;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen orig_len = str_len(ctx->debug);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (orig_len == 0) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen auth_request_log_debug(ctx->auth_request, "ldap",
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen "no fields returned by the server");
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen return;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen }
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_append(ctx->debug, "; ");
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen iter = hash_table_iterate_init(ctx->ldap_attrs);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen while (hash_table_iterate(iter, &key, &value)) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen const char *name = key;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct db_ldap_value *ldap_value = value;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (!ldap_value->used) {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_printfa(ctx->debug, "%s,", name);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen unused_count++;
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen }
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen hash_table_iterate_deinit(&iter);
1cb29929a19dea32779606cd54a1e63aefead88dTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (unused_count == 0)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_truncate(ctx->debug, orig_len);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen else {
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_truncate(ctx->debug, str_len(ctx->debug)-1);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen str_append(ctx->debug, " unused");
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen }
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen auth_request_log_debug(ctx->auth_request, "ldap",
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen "result: %s", str_c(ctx->debug) + 1);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainenvoid db_ldap_result_iterate_deinit(struct db_ldap_result_iterate_context **_ctx)
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen{
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen struct db_ldap_result_iterate_context *ctx = *_ctx;
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen *_ctx = NULL;
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen if (ctx->debug != NULL)
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen db_ldap_result_finish_debug(ctx);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen hash_table_destroy(&ctx->ldap_attrs);
0a8926b91a84abf462afdc1ed95def229377d7ffTimo Sirainen pool_unref(&ctx->pool);
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen}
4261a8b43792dc4db4b39e6910319835b7450e84Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainenstatic const char *parse_setting(const char *key, const char *value,
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen struct ldap_connection *conn)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return parse_setting_from_defs(conn->pool, setting_defs,
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen &conn->set, key, value);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainenstatic struct ldap_connection *ldap_conn_find(const char *config_path)
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen{
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen struct ldap_connection *conn;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen for (conn = ldap_connections; conn != NULL; conn = conn->next) {
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen if (strcmp(conn->config_path, config_path) == 0)
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen return conn;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen }
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen return NULL;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen}
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainenstruct ldap_connection *db_ldap_init(const char *config_path, bool userdb)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen struct ldap_connection *conn;
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen const char *str;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen pool_t pool;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen /* see if it already exists */
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn = ldap_conn_find(config_path);
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen if (conn != NULL) {
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen if (userdb)
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen conn->userdb_used = TRUE;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn->refcount++;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen return conn;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen }
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen
2e1e493b248dec0127b1eabeea5a8bc330378fcdTimo Sirainen if (*config_path == '\0')
2e1e493b248dec0127b1eabeea5a8bc330378fcdTimo Sirainen i_fatal("LDAP: Configuration file path not given");
2e1e493b248dec0127b1eabeea5a8bc330378fcdTimo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen pool = pool_alloconly_create("ldap_connection", 1024);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn = p_new(pool, struct ldap_connection, 1);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->pool = pool;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->refcount = 1;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen conn->userdb_used = userdb;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->conn_state = LDAP_CONN_STATE_DISCONNECTED;
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen conn->default_bind_msgid = -1;
16133a719ce8b6a5b8cedd721340cc1607c43433Timo Sirainen conn->fd = -1;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn->config_path = p_strdup(pool, config_path);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->set = default_ldap_settings;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen if (!settings_read(config_path, NULL, parse_setting,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen null_settings_section_callback, conn))
0cb57ee35d4cab9c03434d7abf312c081ed554d4Timo Sirainen exit(FATAL_DEFAULT);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (conn->set.base == NULL)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen i_fatal("LDAP: No base given");
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen if (conn->set.uris == NULL && conn->set.hosts == NULL)
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen i_fatal("LDAP: No uris or hosts set");
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen#ifndef LDAP_HAVE_INITIALIZE
3c9e09fa412f62259e3a10bfe9ac6afb1becc2f0Timo Sirainen if (conn->set.uris != NULL) {
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen i_fatal("LDAP: Dovecot compiled without support for LDAP uris "
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen "(ldap_initialize not found)");
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen }
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen#endif
b1504ccfa93e77d906e39e6aa31a592d69f6b5b4Timo Sirainen
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen if (*conn->set.ldaprc_path != '\0') {
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen str = getenv("LDAPRC");
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen if (str != NULL && strcmp(str, conn->set.ldaprc_path) != 0) {
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen i_fatal("LDAP: Multiple different ldaprc_path "
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen "settings not allowed (%s and %s)",
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen str, conn->set.ldaprc_path);
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen }
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen env_put(t_strconcat("LDAPRC=", conn->set.ldaprc_path, NULL));
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen }
f8464772990b52cb8de4553bc1135adcf72813b8Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen conn->set.ldap_deref = deref2str(conn->set.deref);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen conn->set.ldap_scope = scope2str(conn->set.scope);
e714eed72515794c46c6712a611e5ab924d903daTimo Sirainen
31088625f59b7359d70845d81ea9e3dd8a24eb63Timo Sirainen i_array_init(&conn->request_array, 512);
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen conn->request_queue = aqueue_init(&conn->request_array.arr);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen conn->next = ldap_connections;
c4457e497e01b57565d24da624968699b166e02aTimo Sirainen ldap_connections = conn;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return conn;
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid db_ldap_unref(struct ldap_connection **_conn)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct ldap_connection *conn = *_conn;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen struct ldap_connection **p;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *_conn = NULL;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen i_assert(conn->refcount >= 0);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen if (--conn->refcount > 0)
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen return;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen for (p = &ldap_connections; *p != NULL; p = &(*p)->next) {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen if (*p == conn) {
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen *p = conn->next;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen break;
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen }
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
3cff7935d606a75357472a3e4269e0b06ac1bef2Timo Sirainen db_ldap_abort_requests(conn, -1U, 0, FALSE, "Shutting down");
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->pending_count == 0);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen db_ldap_conn_close(conn);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen i_assert(conn->to == NULL);
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen
fc4ff2356fee6389d4cf2b3f12f4098a436f0502Timo Sirainen array_free(&conn->request_array);
63cde222abaaa2a9bdaa9a143698dbc8b23bd742Timo Sirainen aqueue_deinit(&conn->request_queue);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen pool_unref(&conn->pool);
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen}
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainenvoid db_ldap_check_userdb_warning(struct ldap_connection *conn)
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen{
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen const struct ldap_settings *def = &default_ldap_settings;
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen const char *set_name;
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen if (worker || conn->userdb_used || conn->set.userdb_warning_disable)
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen return;
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen if (strcmp(conn->set.user_attrs, def->user_attrs) != 0)
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen set_name = "user_attrs";
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen else if (strcmp(conn->set.user_filter, def->user_filter) != 0)
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen set_name = "user_filter";
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen else if (strcmp(conn->set.iterate_attrs, def->iterate_attrs) != 0)
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen set_name = "iterate_attrs";
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen else if (strcmp(conn->set.iterate_filter, def->iterate_filter) != 0)
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen set_name = "iterate_filter";
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen else
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen set_name = NULL;
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen if (set_name != NULL) {
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen i_warning("ldap: Ignoring changed %s in %s, "
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen "because userdb ldap not used. "
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen "(If this is intentional, set userdb_warning_disable=yes)",
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen set_name, conn->config_path);
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen }
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen}
964c86de7158ccafdfe665853579d71232e2634eTimo Sirainen
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen#ifndef BUILTIN_LDAP
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen/* Building a plugin */
cc03958ccda8258252c512412f8d5600ce383b14Timo Sirainenextern struct passdb_module_interface passdb_ldap_plugin;
cc03958ccda8258252c512412f8d5600ce383b14Timo Sirainenextern struct userdb_module_interface userdb_ldap_plugin;
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenvoid authdb_ldap_init(void);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenvoid authdb_ldap_deinit(void);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenvoid authdb_ldap_init(void)
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen{
cc03958ccda8258252c512412f8d5600ce383b14Timo Sirainen passdb_register_module(&passdb_ldap_plugin);
cc03958ccda8258252c512412f8d5600ce383b14Timo Sirainen userdb_register_module(&userdb_ldap_plugin);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen}
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainenvoid authdb_ldap_deinit(void)
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen{
cc03958ccda8258252c512412f8d5600ce383b14Timo Sirainen passdb_unregister_module(&passdb_ldap_plugin);
cc03958ccda8258252c512412f8d5600ce383b14Timo Sirainen userdb_unregister_module(&userdb_ldap_plugin);
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen}
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen#endif
be20a7ddf87cb56ee63016dd0029f0c523be09b6Timo Sirainen
965ed6ea3fc8f7637bd0d159d2fdb283a191ce34Timo Sirainen#endif