1 /* config.c - configuration file handling routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 *
5 * Copyright 1998-2021 The OpenLDAP Foundation.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
10 * Public License.
11 *
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
15 */
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms are permitted
20 * provided that this notice is preserved and that due credit is given
21 * to the University of Michigan at Ann Arbor. The name of the University
22 * may not be used to endorse or promote products derived from this
23 * software without specific prior written permission. This software
24 * is provided ``as is'' without express or implied warranty.
25 */
26
27 #include "portable.h"
28
29 #include <stdio.h>
30
31 #include <ac/string.h>
32 #include <ac/ctype.h>
33 #include <ac/signal.h>
34 #include <ac/socket.h>
35 #include <ac/errno.h>
36 #include <ac/unistd.h>
37
38 #include <sys/types.h>
39 #include <sys/stat.h>
40
41 #ifndef S_ISREG
42 #define S_ISREG(m) ( ((m) & _S_IFMT ) == _S_IFREG )
43 #endif
44
45 #include "lload.h"
46 #include "lutil.h"
47 #include "lutil_ldap.h"
48 #include "lload-config.h"
49 #include "../slapd/slap-cfglog.h"
50
51 #ifdef _WIN32
52 #define LUTIL_ATOULX lutil_atoullx
53 #define Z "I"
54 #else
55 #define LUTIL_ATOULX lutil_atoulx
56 #define Z "z"
57 #endif
58
59 #define ARGS_STEP 512
60
61 /*
62 * defaults for various global variables
63 */
64 #ifdef BALANCER_MODULE
65 char *listeners_list = NULL;
66 #else /* !BALANCER_MODULE */
67 slap_mask_t global_allows = 0;
68 slap_mask_t global_disallows = 0;
69 int global_gentlehup = 0;
70 int global_idletimeout = 0;
71 char *global_host = NULL;
72
73 char *slapd_pid_file = NULL;
74 char *slapd_args_file = NULL;
75 #endif /* !BALANCER_MODULE */
76
77 static FILE *logfile;
78 static char *logfileName;
79
80 static struct timeval timeout_api_tv, timeout_net_tv,
81 timeout_write_tv = { 10, 0 };
82
83 lload_features_t lload_features;
84 int lload_write_coherence = 0;
85
86 ber_len_t sockbuf_max_incoming_client = LLOAD_SB_MAX_INCOMING_CLIENT;
87 ber_len_t sockbuf_max_incoming_upstream = LLOAD_SB_MAX_INCOMING_UPSTREAM;
88
89 int lload_conn_max_pdus_per_cycle = LLOAD_CONN_MAX_PDUS_PER_CYCLE_DEFAULT;
90
91 struct timeval *lload_timeout_api = NULL;
92 struct timeval *lload_timeout_net = NULL;
93 struct timeval *lload_write_timeout = &timeout_write_tv;
94
95 static slap_verbmasks tlskey[];
96
97 static int fp_getline( FILE *fp, ConfigArgs *c );
98 static void fp_getline_init( ConfigArgs *c );
99
100 static char *strtok_quote(
101 char *line,
102 char *sep,
103 char **quote_ptr,
104 int *inquote );
105
106 typedef struct ConfigFile {
107 struct ConfigFile *c_sibs;
108 struct ConfigFile *c_kids;
109 struct berval c_file;
110 BerVarray c_dseFiles;
111 } ConfigFile;
112
113 static ConfigFile *cfn;
114
115 static ConfigDriver config_fname;
116 static ConfigDriver config_generic;
117 static ConfigDriver config_tier;
118 static ConfigDriver config_backend;
119 static ConfigDriver config_bindconf;
120 static ConfigDriver config_restrict_oid;
121 #ifdef LDAP_TCP_BUFFER
122 static ConfigDriver config_tcp_buffer;
123 #endif /* LDAP_TCP_BUFFER */
124 static ConfigDriver config_restrict;
125 static ConfigDriver config_include;
126 static ConfigDriver config_feature;
127 #ifdef HAVE_TLS
128 static ConfigDriver config_tls_option;
129 static ConfigDriver config_tls_config;
130 #endif
131 #ifdef BALANCER_MODULE
132 static ConfigDriver config_share_tls_ctx;
133 static ConfigDriver backend_cf_gen;
134 #endif /* BALANCER_MODULE */
135
136 struct slap_bindconf bindconf = {};
137 struct berval lloadd_identity = BER_BVNULL;
138
139 enum {
140 CFG_ACL = 1,
141 CFG_BACKEND,
142 CFG_BINDCONF,
143 CFG_LISTEN,
144 CFG_LISTEN_URI,
145 CFG_TLS_RAND,
146 CFG_TLS_CIPHER,
147 CFG_TLS_PROTOCOL_MIN,
148 CFG_TLS_CERT_FILE,
149 CFG_TLS_CERT_KEY,
150 CFG_TLS_CA_PATH,
151 CFG_TLS_CA_FILE,
152 CFG_TLS_DH_FILE,
153 CFG_TLS_VERIFY,
154 CFG_TLS_CRLCHECK,
155 CFG_TLS_CRL_FILE,
156 CFG_TLS_SHARE_CTX,
157 CFG_CONCUR,
158 CFG_THREADS,
159 CFG_MIRRORMODE,
160 CFG_IOTHREADS,
161 CFG_MAXBUF_CLIENT,
162 CFG_MAXBUF_UPSTREAM,
163 CFG_FEATURE,
164 CFG_THREADQS,
165 CFG_TLS_ECNAME,
166 CFG_TLS_CACERT,
167 CFG_TLS_CERT,
168 CFG_TLS_KEY,
169 CFG_RESCOUNT,
170 CFG_IOTIMEOUT,
171 CFG_URI,
172 CFG_NUMCONNS,
173 CFG_BINDCONNS,
174 CFG_RETRY,
175 CFG_MAX_PENDING_OPS,
176 CFG_MAX_PENDING_CONNS,
177 CFG_STARTTLS,
178 CFG_CLIENT_PENDING,
179 CFG_RESTRICT_EXOP,
180 CFG_RESTRICT_CONTROL,
181 CFG_TIER,
182 CFG_WEIGHT,
183
184 CFG_LAST
185 };
186
187 /* alphabetical ordering */
188
189 static ConfigTable config_back_cf_table[] = {
190 /* This attr is read-only */
191 { "", "", 0, 0, 0,
192 ARG_MAGIC,
193 &config_fname,
194 NULL, NULL, NULL
195 },
196 { "argsfile", "file", 2, 2, 0,
197 ARG_STRING,
198 &slapd_args_file,
199 NULL, NULL, NULL
200 },
201 { "concurrency", "level", 2, 2, 0,
202 ARG_UINT|ARG_MAGIC|CFG_CONCUR,
203 &config_generic,
204 NULL, NULL, NULL
205 },
206 { "tier", "name", 2, 2, 0,
207 ARG_MAGIC|ARG_STRING|CFG_TIER,
208 &config_tier,
209 "( OLcfgBkAt:13.39 "
210 "NAME 'olcBkLloadTierType' "
211 "DESC 'Tier type' "
212 "EQUALITY caseIgnoreMatch "
213 "SYNTAX OMsDirectoryString "
214 "SINGLE-VALUE )",
215 NULL, NULL
216 },
217 /* conf-file only option */
218 { "backend-server", "backend options", 2, 0, 0,
219 ARG_MAGIC|CFG_BACKEND,
220 &config_backend,
221 NULL, NULL, NULL
222 },
223 { "bindconf", "backend credentials", 2, 0, 0,
224 ARG_MAGIC|CFG_BINDCONF,
225 &config_bindconf,
226 "( OLcfgBkAt:13.2 "
227 "NAME 'olcBkLloadBindconf' "
228 "DESC 'Backend credentials' "
229 /* No EQUALITY since this is a compound attribute (and needs
230 * splitting up anyway - which is a TODO) */
231 "SYNTAX OMsDirectoryString "
232 "SINGLE-VALUE )",
233 NULL, NULL
234 },
235 { "gentlehup", "on|off", 2, 2, 0,
236 #ifdef SIGHUP
237 ARG_ON_OFF,
238 &global_gentlehup,
239 #else
240 ARG_IGNORED,
241 NULL,
242 #endif
243 NULL, NULL, NULL
244 },
245 { "idletimeout", "timeout", 2, 2, 0,
246 ARG_UINT,
247 &global_idletimeout,
248 "( OLcfgBkAt:13.3 "
249 "NAME 'olcBkLloadIdleTimeout' "
250 "DESC 'Connection idle timeout' "
251 "EQUALITY integerMatch "
252 "SYNTAX OMsInteger "
253 "SINGLE-VALUE )",
254 NULL, NULL
255 },
256 { "include", "file", 2, 2, 0,
257 ARG_MAGIC,
258 &config_include,
259 NULL, NULL, NULL
260 },
261 { "io-threads", "count", 2, 0, 0,
262 ARG_UINT|ARG_MAGIC|CFG_IOTHREADS,
263 &config_generic,
264 "( OLcfgBkAt:13.4 "
265 "NAME 'olcBkLloadIOThreads' "
266 "DESC 'I/O thread count' "
267 "EQUALITY integerMatch "
268 "SYNTAX OMsInteger "
269 "SINGLE-VALUE )",
270 NULL, NULL
271 },
272 #ifdef BALANCER_MODULE
273 { "listen", "uri list", 2, 2, 0,
274 ARG_STRING|ARG_MAGIC|CFG_LISTEN,
275 &config_generic,
276 NULL, NULL, NULL
277 },
278 { "", "uri", 2, 2, 0,
279 ARG_MAGIC|CFG_LISTEN_URI,
280 &config_generic,
281 "( OLcfgBkAt:13.5 "
282 "NAME 'olcBkLloadListen' "
283 "DESC 'A listener adress' "
284 /* We don't handle adding/removing a value, so no EQUALITY yet */
285 "SYNTAX OMsDirectoryString )",
286 NULL, NULL
287 },
288 #endif /* BALANCER_MODULE */
289 { "logfile", "file", 2, 2, 0,
290 ARG_STRING|ARG_MAGIC|CFG_LOGFILE,
291 &config_logging,
292 NULL, NULL, NULL
293 },
294 { "logfile-only", "on|off", 2, 2, 0,
295 ARG_ON_OFF|ARG_MAGIC|CFG_LOGFILE_ONLY,
296 &config_logging,
297 NULL, NULL, NULL
298 },
299 { "logfile-rotate", "max> <Mbyte> <hours", 4, 4, 0,
300 ARG_MAGIC|CFG_LOGFILE_ROTATE,
301 &config_logging,
302 NULL, NULL, NULL
303 },
304 { "loglevel", "level", 2, 0, 0,
305 ARG_MAGIC|CFG_LOGLEVEL,
306 &config_logging,
307 NULL, NULL, NULL
308 },
309 { "pidfile", "file", 2, 2, 0,
310 ARG_STRING,
311 &slapd_pid_file,
312 NULL, NULL, NULL
313 },
314 { "restrict", "op_list", 2, 0, 0,
315 ARG_MAGIC,
316 &config_restrict,
317 NULL, NULL, NULL
318 },
319 { "sockbuf_max_incoming_client", "max", 2, 2, 0,
320 ARG_BER_LEN_T|ARG_MAGIC|CFG_MAXBUF_CLIENT,
321 &config_generic,
322 "( OLcfgBkAt:13.6 "
323 "NAME 'olcBkLloadSockbufMaxClient' "
324 "DESC 'The maximum LDAP PDU size accepted coming from clients' "
325 "EQUALITY integerMatch "
326 "SYNTAX OMsInteger "
327 "SINGLE-VALUE )",
328 NULL,
329 { .v_ber_t = LLOAD_SB_MAX_INCOMING_CLIENT }
330 },
331 { "sockbuf_max_incoming_upstream", "max", 2, 2, 0,
332 ARG_BER_LEN_T|ARG_MAGIC|CFG_MAXBUF_UPSTREAM,
333 &config_generic,
334 "( OLcfgBkAt:13.7 "
335 "NAME 'olcBkLloadSockbufMaxUpstream' "
336 "DESC 'The maximum LDAP PDU size accepted coming from upstream' "
337 "EQUALITY integerMatch "
338 "SYNTAX OMsInteger "
339 "SINGLE-VALUE )",
340 NULL,
341 { .v_ber_t = LLOAD_SB_MAX_INCOMING_UPSTREAM }
342 },
343 { "tcp-buffer", "[listener=<listener>] [{read|write}=]size", 0, 0, 0,
344 #ifdef LDAP_TCP_BUFFER
345 ARG_MAGIC,
346 &config_tcp_buffer,
347 #else
348 ARG_IGNORED,
349 NULL,
350 #endif
351 "( OLcfgBkAt:13.8 "
352 "NAME 'olcBkLloadTcpBuffer' "
353 "DESC 'TCP Buffer size' "
354 "EQUALITY caseIgnoreMatch "
355 "SYNTAX OMsDirectoryString "
356 "SINGLE-VALUE )",
357 NULL, NULL
358 },
359 { "threads", "count", 2, 2, 0,
360 ARG_UINT|ARG_MAGIC|CFG_THREADS,
361 &config_generic,
362 NULL, NULL, NULL
363 },
364 { "threadqueues", "count", 2, 2, 0,
365 ARG_UINT|ARG_MAGIC|CFG_THREADQS,
366 &config_generic,
367 NULL, NULL, NULL
368 },
369 { "max_pdus_per_cycle", "count", 2, 2, 0,
370 ARG_UINT|ARG_MAGIC|CFG_RESCOUNT,
371 &config_generic,
372 "( OLcfgBkAt:13.9 "
373 "NAME 'olcBkLloadMaxPDUPerCycle' "
374 "DESC 'Maximum number of PDUs to handle in a single cycle' "
375 "EQUALITY integerMatch "
376 "SYNTAX OMsInteger "
377 "SINGLE-VALUE )",
378 NULL, NULL
379 },
380 { "feature", "name", 2, 0, 0,
381 ARG_MAGIC|CFG_FEATURE,
382 &config_feature,
383 "( OLcfgBkAt:13.10 "
384 "NAME 'olcBkLloadFeature' "
385 "DESC 'Lload features enabled' "
386 "EQUALITY caseIgnoreMatch "
387 "SYNTAX OMsDirectoryString )",
388 NULL, NULL
389 },
390 { "TLSCACertificate", NULL, 2, 2, 0,
391 #ifdef HAVE_TLS
392 CFG_TLS_CACERT|ARG_BINARY|ARG_MAGIC,
393 &config_tls_option,
394 #else
395 ARG_IGNORED,
396 NULL,
397 #endif
398 "( OLcfgBkAt:13.11 "
399 "NAME 'olcBkLloadTLSCACertificate' "
400 "DESC 'X.509 certificate, must use ;binary' "
401 "EQUALITY certificateExactMatch "
402 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 "
403 "SINGLE-VALUE )",
404 NULL, NULL
405 },
406 { "TLSCACertificateFile", NULL, 2, 2, 0,
407 #ifdef HAVE_TLS
408 CFG_TLS_CA_FILE|ARG_STRING|ARG_MAGIC,
409 &config_tls_option,
410 #else
411 ARG_IGNORED,
412 NULL,
413 #endif
414 "( OLcfgBkAt:13.12 "
415 "NAME 'olcBkLloadTLSCACertificateFile' "
416 "EQUALITY caseExactMatch "
417 "SYNTAX OMsDirectoryString "
418 "SINGLE-VALUE )",
419 NULL, NULL
420 },
421 { "TLSCACertificatePath", NULL, 2, 2, 0,
422 #ifdef HAVE_TLS
423 CFG_TLS_CA_PATH|ARG_STRING|ARG_MAGIC,
424 &config_tls_option,
425 #else
426 ARG_IGNORED,
427 NULL,
428 #endif
429 "( OLcfgBkAt:13.13 "
430 "NAME 'olcBkLloadTLSCACertificatePath' "
431 "EQUALITY caseExactMatch "
432 "SYNTAX OMsDirectoryString "
433 "SINGLE-VALUE )",
434 NULL, NULL
435 },
436 { "TLSCertificate", NULL, 2, 2, 0,
437 #ifdef HAVE_TLS
438 CFG_TLS_CERT|ARG_BINARY|ARG_MAGIC,
439 &config_tls_option,
440 #else
441 ARG_IGNORED,
442 NULL,
443 #endif
444 "( OLcfgBkAt:13.14 "
445 "NAME 'olcBkLloadTLSCertificate' "
446 "DESC 'X.509 certificate, must use ;binary' "
447 "EQUALITY certificateExactMatch "
448 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 "
449 "SINGLE-VALUE )",
450 NULL, NULL
451 },
452 { "TLSCertificateFile", NULL, 2, 2, 0,
453 #ifdef HAVE_TLS
454 CFG_TLS_CERT_FILE|ARG_STRING|ARG_MAGIC,
455 &config_tls_option,
456 #else
457 ARG_IGNORED,
458 NULL,
459 #endif
460 "( OLcfgBkAt:13.15 "
461 "NAME 'olcBkLloadTLSCertificateFile' "
462 "EQUALITY caseExactMatch "
463 "SYNTAX OMsDirectoryString "
464 "SINGLE-VALUE )",
465 NULL, NULL
466 },
467 { "TLSCertificateKey", NULL, 2, 2, 0,
468 #ifdef HAVE_TLS
469 CFG_TLS_KEY|ARG_BINARY|ARG_MAGIC,
470 &config_tls_option,
471 #else
472 ARG_IGNORED,
473 NULL,
474 #endif
475 "( OLcfgBkAt:13.16 "
476 "NAME 'olcBkLloadTLSCertificateKey' "
477 "DESC 'X.509 privateKey, must use ;binary' "
478 "EQUALITY privateKeyMatch "
479 "SYNTAX 1.2.840.113549.1.8.1.1 "
480 "SINGLE-VALUE )",
481 NULL, NULL
482 },
483 { "TLSCertificateKeyFile", NULL, 2, 2, 0,
484 #ifdef HAVE_TLS
485 CFG_TLS_CERT_KEY|ARG_STRING|ARG_MAGIC,
486 &config_tls_option,
487 #else
488 ARG_IGNORED,
489 NULL,
490 #endif
491 "( OLcfgBkAt:13.17 "
492 "NAME 'olcBkLloadTLSCertificateKeyFile' "
493 "EQUALITY caseExactMatch "
494 "SYNTAX OMsDirectoryString "
495 "SINGLE-VALUE )",
496 NULL, NULL
497 },
498 { "TLSCipherSuite", NULL, 2, 2, 0,
499 #ifdef HAVE_TLS
500 CFG_TLS_CIPHER|ARG_STRING|ARG_MAGIC,
501 &config_tls_option,
502 #else
503 ARG_IGNORED,
504 NULL,
505 #endif
506 "( OLcfgBkAt:13.18 "
507 "NAME 'olcBkLloadTLSCipherSuite' "
508 "EQUALITY caseExactMatch "
509 "SYNTAX OMsDirectoryString "
510 "SINGLE-VALUE )",
511 NULL, NULL
512 },
513 { "TLSCRLCheck", NULL, 2, 2, 0,
514 #if defined(HAVE_TLS) && defined(HAVE_OPENSSL)
515 CFG_TLS_CRLCHECK|ARG_STRING|ARG_MAGIC,
516 &config_tls_config,
517 #else
518 ARG_IGNORED,
519 NULL,
520 #endif
521 "( OLcfgBkAt:13.19 "
522 "NAME 'olcBkLloadTLSCRLCheck' "
523 "EQUALITY caseIgnoreMatch "
524 "SYNTAX OMsDirectoryString "
525 "SINGLE-VALUE )",
526 NULL, NULL
527 },
528 { "TLSCRLFile", NULL, 2, 2, 0,
529 #if defined(HAVE_GNUTLS)
530 CFG_TLS_CRL_FILE|ARG_STRING|ARG_MAGIC,
531 &config_tls_option,
532 #else
533 ARG_IGNORED,
534 NULL,
535 #endif
536 "( OLcfgBkAt:13.20 "
537 "NAME 'olcBkLloadTLSCRLFile' "
538 "EQUALITY caseExactMatch "
539 "SYNTAX OMsDirectoryString "
540 "SINGLE-VALUE )",
541 NULL, NULL
542 },
543 { "TLSRandFile", NULL, 2, 2, 0,
544 #ifdef HAVE_TLS
545 CFG_TLS_RAND|ARG_STRING|ARG_MAGIC,
546 &config_tls_option,
547 #else
548 ARG_IGNORED,
549 NULL,
550 #endif
551 "( OLcfgBkAt:13.21 "
552 "NAME 'olcBkLloadTLSRandFile' "
553 "EQUALITY caseExactMatch "
554 "SYNTAX OMsDirectoryString "
555 "SINGLE-VALUE )",
556 NULL, NULL
557 },
558 { "TLSVerifyClient", NULL, 2, 2, 0,
559 #ifdef HAVE_TLS
560 CFG_TLS_VERIFY|ARG_STRING|ARG_MAGIC,
561 &config_tls_config,
562 #else
563 ARG_IGNORED,
564 NULL,
565 #endif
566 "( OLcfgBkAt:13.22 "
567 "NAME 'olcBkLloadVerifyClient' "
568 "EQUALITY caseIgnoreMatch "
569 "SYNTAX OMsDirectoryString "
570 "SINGLE-VALUE )",
571 NULL, NULL
572 },
573 { "TLSDHParamFile", NULL, 2, 2, 0,
574 #ifdef HAVE_TLS
575 CFG_TLS_DH_FILE|ARG_STRING|ARG_MAGIC,
576 &config_tls_option,
577 #else
578 ARG_IGNORED,
579 NULL,
580 #endif
581 "( OLcfgBkAt:13.23 "
582 "NAME 'olcBkLloadTLSDHParamFile' "
583 "EQUALITY caseExactMatch "
584 "SYNTAX OMsDirectoryString "
585 "SINGLE-VALUE )",
586 NULL, NULL
587 },
588 { "TLSECName", NULL, 2, 2, 0,
589 #ifdef HAVE_TLS
590 CFG_TLS_ECNAME|ARG_STRING|ARG_MAGIC,
591 &config_tls_option,
592 #else
593 ARG_IGNORED,
594 NULL,
595 #endif
596 "( OLcfgBkAt:13.24 "
597 "NAME 'olcBkLloadTLSECName' "
598 "EQUALITY caseExactMatch "
599 "SYNTAX OMsDirectoryString "
600 "SINGLE-VALUE )",
601 NULL, NULL
602 },
603 { "TLSProtocolMin", NULL, 2, 2, 0,
604 #ifdef HAVE_TLS
605 CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC,
606 &config_tls_config,
607 #else
608 ARG_IGNORED,
609 NULL,
610 #endif
611 "( OLcfgBkAt:13.25 "
612 "NAME 'olcBkLloadTLSProtocolMin' "
613 "EQUALITY caseIgnoreMatch "
614 "SYNTAX OMsDirectoryString "
615 "SINGLE-VALUE )",
616 NULL, NULL
617 },
618 { "TLSShareSlapdCTX", NULL, 2, 2, 0,
619 #if defined(HAVE_TLS) && defined(BALANCER_MODULE)
620 CFG_TLS_SHARE_CTX|ARG_ON_OFF|ARG_MAGIC,
621 &config_share_tls_ctx,
622 #else
623 ARG_IGNORED,
624 NULL,
625 #endif
626 "( OLcfgBkAt:13.33 "
627 "NAME 'olcBkLloadTLSShareSlapdCTX' "
628 "DESC 'Share slapd TLS context (all other lloadd TLS options cease to take effect)' "
629 "EQUALITY booleanMatch "
630 "SYNTAX OMsBoolean "
631 "SINGLE-VALUE )",
632 NULL, NULL
633 },
634 { "iotimeout", "ms timeout", 2, 2, 0,
635 ARG_UINT|ARG_MAGIC|CFG_IOTIMEOUT,
636 &config_generic,
637 "( OLcfgBkAt:13.26 "
638 "NAME 'olcBkLloadIOTimeout' "
639 "DESC 'I/O timeout threshold in miliseconds' "
640 "EQUALITY integerMatch "
641 "SYNTAX OMsInteger "
642 "SINGLE-VALUE )",
643 NULL, NULL
644 },
645 { "client_max_pending", NULL, 2, 2, 0,
646 ARG_MAGIC|ARG_UINT|CFG_CLIENT_PENDING,
647 &config_generic,
648 "( OLcfgBkAt:13.35 "
649 "NAME 'olcBkLloadClientMaxPending' "
650 "DESC 'Maximum pending operations per client connection' "
651 "EQUALITY integerMatch "
652 "SYNTAX OMsInteger "
653 "SINGLE-VALUE )",
654 NULL,
655 { .v_uint = 0 }
656 },
657 { "write_coherence", "seconds", 2, 2, 0,
658 ARG_INT,
659 &lload_write_coherence,
660 "( OLcfgBkAt:13.36 "
661 "NAME 'olcBkLloadWriteCoherence' "
662 "DESC 'Keep operations to the same backend after a write' "
663 "EQUALITY integerMatch "
664 "SYNTAX OMsInteger "
665 "SINGLE-VALUE )",
666 NULL,
667 { .v_int = 0 }
668 },
669 { "restrict_exop", "OID> <action", 3, 3, 0,
670 ARG_MAGIC|CFG_RESTRICT_EXOP,
671 &config_restrict_oid,
672 "( OLcfgBkAt:13.37 "
673 "NAME 'olcBkLloadRestrictExop' "
674 "DESC 'Restrict upstream selection after forwarding an extended operation' "
675 "EQUALITY caseIgnoreMatch "
676 "SYNTAX OMsDirectoryString )",
677 NULL, NULL
678 },
679 { "restrict_control", "OID> <action", 3, 3, 0,
680 ARG_MAGIC|CFG_RESTRICT_CONTROL,
681 &config_restrict_oid,
682 "( OLcfgBkAt:13.38 "
683 "NAME 'olcBkLloadRestrictControl' "
684 "DESC 'Restrict upstream selection after forwarding a control' "
685 "EQUALITY caseIgnoreMatch "
686 "SYNTAX OMsDirectoryString )",
687 NULL, NULL
688 },
689
690 /* cn=config only options */
691 #ifdef BALANCER_MODULE
692 { "", "uri", 2, 2, 0,
693 ARG_BERVAL|ARG_MAGIC|CFG_URI,
694 &backend_cf_gen,
695 "( OLcfgBkAt:13.27 "
696 "NAME 'olcBkLloadBackendUri' "
697 "DESC 'URI to contact the server on' "
698 "EQUALITY caseIgnoreMatch "
699 "SYNTAX OMsDirectoryString "
700 "SINGLE-VALUE )",
701 NULL, NULL
702 },
703 { "", NULL, 2, 2, 0,
704 ARG_UINT|ARG_MAGIC|CFG_NUMCONNS,
705 &backend_cf_gen,
706 "( OLcfgBkAt:13.28 "
707 "NAME 'olcBkLloadNumconns' "
708 "DESC 'Number of regular connections to maintain' "
709 "EQUALITY integerMatch "
710 "SYNTAX OMsInteger "
711 "SINGLE-VALUE )",
712 NULL, NULL
713 },
714 { "", NULL, 2, 2, 0,
715 ARG_UINT|ARG_MAGIC|CFG_BINDCONNS,
716 &backend_cf_gen,
717 "( OLcfgBkAt:13.29 "
718 "NAME 'olcBkLloadBindconns' "
719 "DESC 'Number of bind connections to maintain' "
720 "EQUALITY integerMatch "
721 "SYNTAX OMsInteger "
722 "SINGLE-VALUE )",
723 NULL, NULL
724 },
725 { "", NULL, 2, 2, 0,
726 ARG_UINT|ARG_MAGIC|CFG_RETRY,
727 &backend_cf_gen,
728 "( OLcfgBkAt:13.30 "
729 "NAME 'olcBkLloadRetry' "
730 "DESC 'Number of seconds to wait before trying to reconnect' "
731 "EQUALITY integerMatch "
732 "SYNTAX OMsInteger "
733 "SINGLE-VALUE )",
734 NULL, NULL
735 },
736 { "", NULL, 2, 2, 0,
737 ARG_UINT|ARG_MAGIC|CFG_MAX_PENDING_OPS,
738 &backend_cf_gen,
739 "( OLcfgBkAt:13.31 "
740 "NAME 'olcBkLloadMaxPendingOps' "
741 "DESC 'Maximum number of pending operations for this backend' "
742 "EQUALITY integerMatch "
743 "SYNTAX OMsInteger "
744 "SINGLE-VALUE )",
745 NULL, NULL
746 },
747 { "", NULL, 2, 2, 0,
748 ARG_UINT|ARG_MAGIC|CFG_MAX_PENDING_CONNS,
749 &backend_cf_gen,
750 "( OLcfgBkAt:13.32 "
751 "NAME 'olcBkLloadMaxPendingConns' "
752 "DESC 'Maximum number of pending operations on each connection' "
753 "EQUALITY integerMatch "
754 "SYNTAX OMsInteger "
755 "SINGLE-VALUE )",
756 NULL, NULL
757 },
758 { "", NULL, 2, 2, 0,
759 ARG_BERVAL|ARG_MAGIC|CFG_STARTTLS,
760 &backend_cf_gen,
761 "( OLcfgBkAt:13.34 "
762 "NAME 'olcBkLloadStartTLS' "
763 "DESC 'Whether StartTLS should be attempted on the connection' "
764 "EQUALITY caseIgnoreMatch "
765 "SYNTAX OMsDirectoryString "
766 "SINGLE-VALUE )",
767 NULL, NULL
768 },
769 { "", NULL, 2, 2, 0,
770 ARG_MAGIC|ARG_UINT|CFG_WEIGHT,
771 &backend_cf_gen,
772 "( OLcfgBkAt:13.40 "
773 "NAME 'olcBkLloadWeight' "
774 "DESC 'Backend weight' "
775 "SYNTAX OMsInteger "
776 "SINGLE-VALUE )",
777 NULL,
778 { .v_uint = 0 },
779 },
780 #endif /* BALANCER_MODULE */
781
782 { NULL, NULL, 0, 0, 0, ARG_IGNORED, NULL }
783 };
784
785 #ifdef BALANCER_MODULE
786 static ConfigCfAdd lload_cfadd;
787
788 static ConfigLDAPadd lload_backend_ldadd;
789 static ConfigLDAPadd lload_tier_ldadd;
790
791 #ifdef SLAP_CONFIG_DELETE
792 static ConfigLDAPdel lload_backend_lddel;
793 static ConfigLDAPdel lload_tier_lddel;
794 #endif /* SLAP_CONFIG_DELETE */
795
796 static ConfigOCs lloadocs[] = {
797 { "( OLcfgBkOc:13.1 "
798 "NAME 'olcBkLloadConfig' "
799 "DESC 'Lload backend configuration' "
800 "SUP olcBackendConfig "
801 "MUST ( olcBkLloadBindconf "
802 "$ olcBkLloadIOThreads "
803 "$ olcBkLloadListen "
804 "$ olcBkLloadSockbufMaxClient "
805 "$ olcBkLloadSockbufMaxUpstream "
806 "$ olcBkLloadMaxPDUPerCycle "
807 "$ olcBkLloadIOTimeout ) "
808 "MAY ( olcBkLloadFeature "
809 "$ olcBkLloadTcpBuffer "
810 "$ olcBkLloadTLSCACertificateFile "
811 "$ olcBkLloadTLSCACertificatePath "
812 "$ olcBkLloadTLSCertificateFile "
813 "$ olcBkLloadTLSCertificateKeyFile "
814 "$ olcBkLloadTLSCipherSuite "
815 "$ olcBkLloadTLSCRLCheck "
816 "$ olcBkLloadTLSRandFile "
817 "$ olcBkLloadVerifyClient "
818 "$ olcBkLloadTLSDHParamFile "
819 "$ olcBkLloadTLSECName "
820 "$ olcBkLloadTLSProtocolMin "
821 "$ olcBkLloadTLSCRLFile "
822 "$ olcBkLloadTLSShareSlapdCTX "
823 "$ olcBkLloadClientMaxPending "
824 "$ olcBkLloadWriteCoherence "
825 "$ olcBkLloadRestrictExop "
826 "$ olcBkLloadRestrictControl "
827 ") )",
828 Cft_Backend, config_back_cf_table,
829 NULL,
830 lload_cfadd,
831 },
832 { "( OLcfgBkOc:13.2 "
833 "NAME 'olcBkLloadBackendConfig' "
834 "DESC 'Lload backend server configuration' "
835 "SUP olcConfig STRUCTURAL "
836 "MUST ( cn "
837 "$ olcBkLloadBackendUri "
838 "$ olcBkLloadNumconns "
839 "$ olcBkLloadBindconns "
840 "$ olcBkLloadRetry "
841 "$ olcBkLloadMaxPendingOps "
842 "$ olcBkLloadMaxPendingConns ) "
843 "MAY ( olcBkLloadStartTLS "
844 "$ olcBkLloadWeight ) "
845 ") )",
846 Cft_Misc, config_back_cf_table,
847 lload_backend_ldadd,
848 NULL,
849 #ifdef SLAP_CONFIG_DELETE
850 lload_backend_lddel,
851 #endif /* SLAP_CONFIG_DELETE */
852 },
853 { "( OLcfgBkOc:13.3 "
854 "NAME 'olcBkLloadTierConfig' "
855 "DESC 'Lload tier configuration' "
856 "SUP olcConfig STRUCTURAL "
857 "MUST ( cn "
858 "$ olcBkLloadTierType "
859 ") )",
860 Cft_Misc, config_back_cf_table,
861 lload_tier_ldadd,
862 NULL,
863 #ifdef SLAP_CONFIG_DELETE
864 lload_tier_lddel,
865 #endif /* SLAP_CONFIG_DELETE */
866 },
867 { NULL, 0, NULL }
868 };
869 #endif /* BALANCER_MODULE */
870
871 static int config_syslog;
872
873 static int
config_generic(ConfigArgs * c)874 config_generic( ConfigArgs *c )
875 {
876 enum lcf_daemon flag = 0;
877 int rc = LDAP_SUCCESS;
878
879 if ( c->op == SLAP_CONFIG_EMIT ) {
880 switch ( c->type ) {
881 case CFG_IOTHREADS:
882 c->value_uint = lload_daemon_threads;
883 break;
884 case CFG_LISTEN_URI: {
885 LloadListener **ll = lloadd_get_listeners();
886 struct berval bv = BER_BVNULL;
887
888 for ( ; ll && *ll; ll++ ) {
889 /* The same url could have spawned several consecutive
890 * listeners */
891 if ( !BER_BVISNULL( &bv ) &&
892 !ber_bvcmp( &bv, &(*ll)->sl_url ) ) {
893 continue;
894 }
895 ber_dupbv( &bv, &(*ll)->sl_url );
896 ber_bvarray_add( &c->rvalue_vals, &bv );
897 }
898 } break;
899 case CFG_MAXBUF_CLIENT:
900 c->value_uint = sockbuf_max_incoming_client;
901 break;
902 case CFG_MAXBUF_UPSTREAM:
903 c->value_uint = sockbuf_max_incoming_upstream;
904 break;
905 case CFG_RESCOUNT:
906 c->value_uint = lload_conn_max_pdus_per_cycle;
907 break;
908 case CFG_IOTIMEOUT:
909 c->value_uint = 1000 * lload_write_timeout->tv_sec +
910 lload_write_timeout->tv_usec / 1000;
911 break;
912 case CFG_CLIENT_PENDING:
913 c->value_uint = lload_client_max_pending;
914 break;
915 default:
916 rc = 1;
917 break;
918 }
919 return rc;
920
921 } else if ( c->op == LDAP_MOD_DELETE ) {
922 /* We only need to worry about deletions to multi-value or MAY
923 * attributes that belong to the lloadd module - we don't have any at
924 * the moment */
925 return rc;
926 }
927
928 lload_change.type = LLOAD_CHANGE_MODIFY;
929 lload_change.object = LLOAD_DAEMON;
930
931 switch ( c->type ) {
932 case CFG_CONCUR:
933 ldap_pvt_thread_set_concurrency( c->value_uint );
934 break;
935 case CFG_LISTEN:
936 if ( lloadd_inited ) {
937 snprintf( c->cr_msg, sizeof(c->cr_msg),
938 "listen directive can only be specified once" );
939 ch_free( c->value_string );
940 return 1;
941 }
942 if ( lloadd_listeners_init( c->value_string ) ) {
943 snprintf( c->cr_msg, sizeof(c->cr_msg),
944 "could not open one of the listener sockets: %s",
945 c->value_string );
946 ch_free( c->value_string );
947 return 1;
948 }
949 ch_free( c->value_string );
950 break;
951 case CFG_LISTEN_URI: {
952 LDAPURLDesc *lud;
953 LloadListener *l;
954
955 if ( ldap_url_parse_ext(
956 c->line, &lud, LDAP_PVT_URL_PARSE_DEF_PORT ) ) {
957 snprintf( c->cr_msg, sizeof(c->cr_msg),
958 "string %s could not be parsed as an LDAP URL",
959 c->line );
960 goto fail;
961 }
962
963 /* A sanity check, although it will not catch everything */
964 if ( ( l = lload_config_check_my_url( c->line, lud ) ) ) {
965 snprintf( c->cr_msg, sizeof(c->cr_msg),
966 "Load Balancer already configured to listen on %s "
967 "(while adding %s)",
968 l->sl_url.bv_val, c->line );
969 goto fail;
970 }
971
972 if ( !lloadd_inited ) {
973 if ( lload_open_new_listener( c->line, lud ) ) {
974 snprintf( c->cr_msg, sizeof(c->cr_msg),
975 "could not open a listener for %s", c->line );
976 goto fail;
977 }
978 } else {
979 snprintf( c->cr_msg, sizeof(c->cr_msg),
980 "listener changes will not take effect until restart: "
981 "%s",
982 c->line );
983 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
984 }
985 } break;
986 case CFG_THREADS:
987 if ( c->value_uint < 2 ) {
988 snprintf( c->cr_msg, sizeof(c->cr_msg),
989 "threads=%d smaller than minimum value 2",
990 c->value_uint );
991 goto fail;
992
993 } else if ( c->value_uint > 2 * SLAP_MAX_WORKER_THREADS ) {
994 snprintf( c->cr_msg, sizeof(c->cr_msg),
995 "warning, threads=%d larger than twice the default "
996 "(2*%d=%d); YMMV",
997 c->value_uint, SLAP_MAX_WORKER_THREADS,
998 2 * SLAP_MAX_WORKER_THREADS );
999 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
1000 }
1001 if ( slapMode & SLAP_SERVER_MODE )
1002 ldap_pvt_thread_pool_maxthreads(
1003 &connection_pool, c->value_uint );
1004 connection_pool_max = c->value_uint; /* save for reference */
1005 break;
1006
1007 case CFG_THREADQS:
1008 if ( c->value_uint < 1 ) {
1009 snprintf( c->cr_msg, sizeof(c->cr_msg),
1010 "threadqueues=%d smaller than minimum value 1",
1011 c->value_uint );
1012 goto fail;
1013 }
1014 if ( slapMode & SLAP_SERVER_MODE )
1015 ldap_pvt_thread_pool_queues( &connection_pool, c->value_uint );
1016 connection_pool_queues = c->value_uint; /* save for reference */
1017 break;
1018
1019 case CFG_IOTHREADS: {
1020 int mask = 0;
1021 /* use a power of two */
1022 while ( c->value_uint > 1 ) {
1023 c->value_uint >>= 1;
1024 mask <<= 1;
1025 mask |= 1;
1026 }
1027 if ( !lloadd_inited ) {
1028 lload_daemon_mask = mask;
1029 lload_daemon_threads = mask + 1;
1030 flag = LLOAD_DAEMON_MOD_THREADS;
1031 } else {
1032 snprintf( c->cr_msg, sizeof(c->cr_msg),
1033 "io thread changes will not take effect until "
1034 "restart" );
1035 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
1036 }
1037 } break;
1038
1039 case CFG_RESCOUNT:
1040 lload_conn_max_pdus_per_cycle = c->value_uint;
1041 break;
1042
1043 case CFG_IOTIMEOUT:
1044 if ( c->value_uint > 0 ) {
1045 timeout_write_tv.tv_sec = c->value_uint / 1000;
1046 timeout_write_tv.tv_usec = 1000 * ( c->value_uint % 1000 );
1047 lload_write_timeout = &timeout_write_tv;
1048 } else {
1049 lload_write_timeout = NULL;
1050 }
1051 break;
1052 case CFG_MAXBUF_CLIENT:
1053 sockbuf_max_incoming_client = c->value_uint;
1054 break;
1055 case CFG_MAXBUF_UPSTREAM:
1056 sockbuf_max_incoming_upstream = c->value_uint;
1057 break;
1058 case CFG_CLIENT_PENDING:
1059 lload_client_max_pending = c->value_uint;
1060 break;
1061 default:
1062 Debug( LDAP_DEBUG_ANY, "%s: unknown CFG_TYPE %d\n",
1063 c->log, c->type );
1064 return 1;
1065 }
1066
1067 lload_change.flags.daemon |= flag;
1068
1069 return 0;
1070
1071 fail:
1072 if ( lload_change.type == LLOAD_CHANGE_ADD ) {
1073 /* Abort the ADD */
1074 lload_change.type = LLOAD_CHANGE_DEL;
1075 }
1076
1077 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
1078 return 1;
1079 }
1080
1081 static int
lload_backend_finish(ConfigArgs * ca)1082 lload_backend_finish( ConfigArgs *ca )
1083 {
1084 LloadBackend *b = ca->ca_private;
1085
1086 if ( ca->reply.err != LDAP_SUCCESS ) {
1087 /* Not reached since cleanup is only called on success */
1088 goto fail;
1089 }
1090
1091 if ( b->b_numconns <= 0 || b->b_numbindconns <= 0 ) {
1092 Debug( LDAP_DEBUG_ANY, "lload_backend_finish: "
1093 "invalid connection pool configuration\n" );
1094 goto fail;
1095 }
1096
1097 if ( b->b_retry_timeout < 0 ) {
1098 Debug( LDAP_DEBUG_ANY, "lload_backend_finish: "
1099 "invalid retry timeout configuration\n" );
1100 goto fail;
1101 }
1102
1103 b->b_retry_tv.tv_sec = b->b_retry_timeout / 1000;
1104 b->b_retry_tv.tv_usec = ( b->b_retry_timeout % 1000 ) * 1000;
1105
1106 /* daemon_base is only allocated after initial configuration happens, those
1107 * events are allocated on startup, we only deal with online Adds */
1108 if ( !b->b_retry_event && daemon_base ) {
1109 struct event *event;
1110 assert( CONFIG_ONLINE_ADD( ca ) );
1111 event = evtimer_new( daemon_base, backend_connect, b );
1112 if ( !event ) {
1113 Debug( LDAP_DEBUG_ANY, "lload_backend_finish: "
1114 "failed to allocate retry event\n" );
1115 goto fail;
1116 }
1117 b->b_retry_event = event;
1118 }
1119
1120 if ( BER_BVISEMPTY( &b->b_name ) ) {
1121 struct berval bv;
1122 LloadBackend *b2;
1123 int i = 1;
1124
1125 LDAP_CIRCLEQ_FOREACH ( b2, &b->b_tier->t_backends, b_next ) {
1126 i++;
1127 }
1128
1129 bv.bv_val = ca->cr_msg;
1130 bv.bv_len =
1131 snprintf( ca->cr_msg, sizeof(ca->cr_msg), "server %d", i );
1132
1133 ber_dupbv( &b->b_name, &bv );
1134 }
1135
1136 if ( b->b_tier->t_type.tier_add_backend( b->b_tier, b ) ) {
1137 goto fail;
1138 }
1139
1140 return LDAP_SUCCESS;
1141
1142 fail:
1143 if ( lload_change.type == LLOAD_CHANGE_ADD ) {
1144 /* Abort the ADD */
1145 lload_change.type = LLOAD_CHANGE_DEL;
1146 }
1147
1148 lload_backend_destroy( b );
1149 return -1;
1150 }
1151
1152 static int
backend_config_url(LloadBackend * b,struct berval * uri)1153 backend_config_url( LloadBackend *b, struct berval *uri )
1154 {
1155 LDAPURLDesc *lud = NULL;
1156 char *host = NULL;
1157 int rc, proto, tls = b->b_tls_conf;
1158
1159 /* Effect no changes until we've checked everything */
1160
1161 rc = ldap_url_parse_ext( uri->bv_val, &lud, LDAP_PVT_URL_PARSE_DEF_PORT );
1162 if ( rc != LDAP_URL_SUCCESS ) {
1163 Debug( LDAP_DEBUG_ANY, "backend_config_url: "
1164 "listen URL \"%s\" parse error=%d\n",
1165 uri->bv_val, rc );
1166 return -1;
1167 }
1168
1169 if ( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) {
1170 #ifdef HAVE_TLS
1171 /* Specifying ldaps:// overrides starttls= settings */
1172 tls = LLOAD_LDAPS;
1173 #else /* ! HAVE_TLS */
1174
1175 Debug( LDAP_DEBUG_ANY, "backend_config_url: "
1176 "TLS not supported (%s)\n",
1177 uri->bv_val );
1178 rc = -1;
1179 goto done;
1180 #endif /* ! HAVE_TLS */
1181 }
1182
1183 proto = ldap_pvt_url_scheme2proto( lud->lud_scheme );
1184 if ( proto == LDAP_PROTO_IPC ) {
1185 #ifdef LDAP_PF_LOCAL
1186 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
1187 host = LDAPI_SOCK;
1188 }
1189 #else /* ! LDAP_PF_LOCAL */
1190
1191 Debug( LDAP_DEBUG_ANY, "backend_config_url: "
1192 "URL scheme not supported: %s",
1193 url );
1194 rc = -1;
1195 goto done;
1196 #endif /* ! LDAP_PF_LOCAL */
1197 } else {
1198 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) {
1199 Debug( LDAP_DEBUG_ANY, "backend_config_url: "
1200 "backend url missing hostname: '%s'\n",
1201 uri->bv_val );
1202 rc = -1;
1203 goto done;
1204 }
1205 }
1206 if ( !host ) {
1207 host = lud->lud_host;
1208 }
1209
1210 if ( b->b_host ) {
1211 ch_free( b->b_host );
1212 }
1213
1214 b->b_proto = proto;
1215 b->b_tls = tls;
1216 b->b_port = lud->lud_port;
1217 b->b_host = ch_strdup( host );
1218
1219 done:
1220 ldap_free_urldesc( lud );
1221 return rc;
1222 }
1223
1224 static int
config_backend(ConfigArgs * c)1225 config_backend( ConfigArgs *c )
1226 {
1227 LloadBackend *b;
1228 LloadTier *tier;
1229 int i, rc = 0;
1230
1231 tier = LDAP_STAILQ_LAST( &tiers, LloadTier, t_next );
1232 if ( !tier ) {
1233 Debug( LDAP_DEBUG_ANY, "config_backend: "
1234 "no tier configured yet\n" );
1235 return -1;
1236 }
1237
1238 /* FIXME: maybe tier_add_backend could allocate it? */
1239 b = lload_backend_new();
1240 b->b_tier = tier;
1241
1242 for ( i = 1; i < c->argc; i++ ) {
1243 if ( lload_backend_parse( c->argv[i], b ) ) {
1244 if ( !tier->t_type.tier_backend_config ||
1245 tier->t_type.tier_backend_config( tier, b, c->argv[i] ) ) {
1246 Debug( LDAP_DEBUG_ANY, "config_backend: "
1247 "error parsing backend configuration item '%s'\n",
1248 c->argv[i] );
1249 return -1;
1250 }
1251 }
1252 }
1253
1254 if ( BER_BVISNULL( &b->b_uri ) ) {
1255 Debug( LDAP_DEBUG_ANY, "config_backend: "
1256 "backend address not specified\n" );
1257 rc = -1;
1258 goto done;
1259 }
1260
1261 if ( backend_config_url( b, &b->b_uri ) ) {
1262 rc = -1;
1263 goto done;
1264 }
1265
1266 c->ca_private = b;
1267 rc = lload_backend_finish( c );
1268 done:
1269 if ( rc ) {
1270 ch_free( b );
1271 }
1272 return rc;
1273 }
1274
1275 static int
config_bindconf(ConfigArgs * c)1276 config_bindconf( ConfigArgs *c )
1277 {
1278 int i;
1279
1280 if ( c->op == SLAP_CONFIG_EMIT ) {
1281 struct berval bv;
1282
1283 lload_bindconf_unparse( &bindconf, &bv );
1284
1285 for ( i = 0; isspace( (unsigned char)bv.bv_val[i] ); i++ )
1286 /* count spaces */;
1287
1288 if ( i ) {
1289 bv.bv_len -= i;
1290 AC_MEMCPY( bv.bv_val, &bv.bv_val[i], bv.bv_len + 1 );
1291 }
1292
1293 value_add_one( &c->rvalue_vals, &bv );
1294 ber_memfree( bv.bv_val );
1295 return LDAP_SUCCESS;
1296 } else if ( c->op == LDAP_MOD_DELETE ) {
1297 /* It's a MUST single-valued attribute, noop for now */
1298 lload_bindconf_free( &bindconf );
1299 return LDAP_SUCCESS;
1300 }
1301
1302 lload_change.type = LLOAD_CHANGE_MODIFY;
1303 lload_change.object = LLOAD_DAEMON;
1304 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_BINDCONF;
1305
1306 for ( i = 1; i < c->argc; i++ ) {
1307 if ( lload_bindconf_parse( c->argv[i], &bindconf ) ) {
1308 Debug( LDAP_DEBUG_ANY, "config_bindconf: "
1309 "error parsing backend configuration item '%s'\n",
1310 c->argv[i] );
1311 return -1;
1312 }
1313 }
1314
1315 if ( bindconf.sb_method == LDAP_AUTH_SASL ) {
1316 #ifndef HAVE_CYRUS_SASL
1317 Debug( LDAP_DEBUG_ANY, "config_bindconf: "
1318 "no sasl support available\n" );
1319 return -1;
1320 #endif
1321 }
1322
1323 if ( !BER_BVISNULL( &bindconf.sb_authzId ) ) {
1324 ber_dupbv( &lloadd_identity, &bindconf.sb_authzId );
1325 } else if ( !BER_BVISNULL( &bindconf.sb_authcId ) ) {
1326 ber_dupbv( &lloadd_identity, &bindconf.sb_authcId );
1327 } else if ( !BER_BVISNULL( &bindconf.sb_binddn ) ) {
1328 char *ptr;
1329
1330 lloadd_identity.bv_len = STRLENOF("dn:") + bindconf.sb_binddn.bv_len;
1331 lloadd_identity.bv_val = ch_malloc( lloadd_identity.bv_len + 1 );
1332
1333 ptr = lutil_strcopy( lloadd_identity.bv_val, "dn:" );
1334 ptr = lutil_strncopy(
1335 ptr, bindconf.sb_binddn.bv_val, bindconf.sb_binddn.bv_len );
1336 *ptr = '\0';
1337 }
1338
1339 if ( bindconf.sb_timeout_api ) {
1340 timeout_api_tv.tv_sec = bindconf.sb_timeout_api;
1341 lload_timeout_api = &timeout_api_tv;
1342 if ( lload_timeout_event ) {
1343 event_add( lload_timeout_event, lload_timeout_api );
1344 }
1345 } else {
1346 lload_timeout_api = NULL;
1347 if ( lload_timeout_event ) {
1348 event_del( lload_timeout_event );
1349 }
1350 }
1351
1352 if ( bindconf.sb_timeout_net ) {
1353 timeout_net_tv.tv_sec = bindconf.sb_timeout_net;
1354 lload_timeout_net = &timeout_net_tv;
1355 } else {
1356 lload_timeout_net = NULL;
1357 }
1358
1359 #ifdef HAVE_TLS
1360 if ( bindconf.sb_tls_do_init ) {
1361 lload_bindconf_tls_set( &bindconf, lload_tls_backend_ld );
1362 }
1363 #endif /* HAVE_TLS */
1364 return 0;
1365 }
1366
1367 #ifndef BALANCER_MODULE
1368 char *
oidm_find(char * oid)1369 oidm_find( char *oid )
1370 {
1371 if ( OID_LEADCHAR( *oid ) ) {
1372 return oid;
1373 }
1374 Debug( LDAP_DEBUG_ANY, "oidm_find: "
1375 "full OID parsing only available when compiled as a module\n" );
1376 return NULL;
1377 }
1378 #endif /* !BALANCER_MODULE */
1379
1380 static struct {
1381 const char *name;
1382 enum op_restriction action;
1383 } restrictopts[] = {
1384 { "ignore", LLOAD_OP_NOT_RESTRICTED },
1385 { "write", LLOAD_OP_RESTRICTED_WRITE },
1386 { "backend", LLOAD_OP_RESTRICTED_BACKEND },
1387 { "connection", LLOAD_OP_RESTRICTED_UPSTREAM },
1388 { "isolate", LLOAD_OP_RESTRICTED_ISOLATE },
1389 { "reject", LLOAD_OP_RESTRICTED_REJECT },
1390 { NULL }
1391 };
1392
1393 static void
restriction_free(struct restriction_entry * restriction)1394 restriction_free( struct restriction_entry *restriction )
1395 {
1396 ch_free( restriction->oid.bv_val );
1397 ch_free( restriction );
1398 }
1399
1400 static int
config_restrict_oid(ConfigArgs * c)1401 config_restrict_oid( ConfigArgs *c )
1402 {
1403 TAvlnode *node = NULL, **root = ( c->type == CFG_RESTRICT_EXOP ) ?
1404 &lload_exop_actions :
1405 &lload_control_actions;
1406 struct restriction_entry *entry = NULL;
1407 char *parsed_oid;
1408 int i, rc = -1;
1409
1410 if ( c->op == SLAP_CONFIG_EMIT ) {
1411 struct berval bv = { .bv_val = c->cr_msg };
1412
1413 if ( c->type == CFG_RESTRICT_EXOP && lload_default_exop_action ) {
1414 bv.bv_len = snprintf( bv.bv_val, sizeof(c->cr_msg), "1.1 %s",
1415 restrictopts[lload_default_exop_action].name );
1416 value_add_one( &c->rvalue_vals, &bv );
1417 }
1418 for ( node = ldap_tavl_end( *root, TAVL_DIR_LEFT );
1419 node;
1420 node = ldap_tavl_next( node, TAVL_DIR_RIGHT ) ) {
1421 entry = node->avl_data;
1422
1423 bv.bv_len = snprintf( bv.bv_val, sizeof(c->cr_msg), "%s %s",
1424 entry->oid.bv_val, restrictopts[entry->action].name );
1425 value_add_one( &c->rvalue_vals, &bv );
1426 }
1427
1428 return LDAP_SUCCESS;
1429
1430 } else if ( c->op == LDAP_MOD_DELETE ) {
1431 if ( !c->line ) {
1432 ldap_tavl_free( *root, (AVL_FREE)restriction_free );
1433 *root = NULL;
1434 if ( c->type == CFG_RESTRICT_EXOP ) {
1435 lload_default_exop_action = LLOAD_OP_NOT_RESTRICTED;
1436 }
1437 rc = LDAP_SUCCESS;
1438 } else {
1439 struct restriction_entry needle;
1440
1441 parsed_oid = strchr( c->line, ' ' );
1442 if ( !parsed_oid ) {
1443 return rc;
1444 }
1445
1446 memcpy( c->cr_msg, c->line, parsed_oid - c->line );
1447 c->cr_msg[parsed_oid - c->line] = '\0';
1448
1449 needle.oid.bv_val = oidm_find( c->cr_msg );
1450 needle.oid.bv_len = strlen( needle.oid.bv_val );
1451
1452 if ( !needle.oid.bv_val ) {
1453 return rc;
1454 } else if ( c->type == CFG_RESTRICT_EXOP &&
1455 !strcmp( needle.oid.bv_val, "1.1" ) ) {
1456 lload_default_exop_action = LLOAD_OP_NOT_RESTRICTED;
1457 } else {
1458 /* back-config should have checked we have this value */
1459 entry = ldap_tavl_delete( root, &needle,
1460 lload_restriction_cmp );
1461 assert( entry != NULL );
1462 }
1463 rc = LDAP_SUCCESS;
1464 }
1465 return rc;
1466 }
1467
1468 parsed_oid = oidm_find( c->argv[1] );
1469 if ( !parsed_oid ) {
1470 snprintf( c->cr_msg, sizeof(c->cr_msg), "Could not parse oid %s",
1471 c->argv[1] );
1472 goto done;
1473 }
1474
1475 for ( i = 0; restrictopts[i].name; i++ ) {
1476 if ( !strcasecmp( c->argv[2], restrictopts[i].name ) ) {
1477 break;
1478 }
1479 }
1480
1481 if ( !restrictopts[i].name ) {
1482 snprintf( c->cr_msg, sizeof(c->cr_msg), "Could not parse action %s",
1483 c->argv[2] );
1484 goto done;
1485 }
1486
1487 if ( !strcmp( parsed_oid, "1.1" ) ) {
1488 if ( lload_default_exop_action ) {
1489 snprintf( c->cr_msg, sizeof(c->cr_msg), "Default already set" );
1490 goto done;
1491 } else {
1492 lload_default_exop_action = i;
1493 }
1494 }
1495
1496 entry = ch_malloc( sizeof(struct restriction_entry) );
1497 /* Copy only if a reference to argv[1] was returned */
1498 ber_str2bv( parsed_oid, 0, parsed_oid == c->argv[1], &entry->oid );
1499 entry->action = i;
1500
1501 if ( ldap_tavl_insert( root, entry, lload_restriction_cmp,
1502 ldap_avl_dup_error ) ) {
1503 snprintf( c->cr_msg, sizeof(c->cr_msg),
1504 "%s with OID %s already restricted",
1505 c->type == CFG_RESTRICT_EXOP ? "Extended operation" : "Control",
1506 c->argv[1] );
1507 goto done;
1508 }
1509
1510 rc = LDAP_SUCCESS;
1511 done:
1512 if ( rc ) {
1513 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
1514 if ( parsed_oid ) ch_free( parsed_oid );
1515 if ( entry ) ch_free( entry );
1516 }
1517
1518 return rc;
1519 }
1520
1521 static int
config_tier(ConfigArgs * c)1522 config_tier( ConfigArgs *c )
1523 {
1524 int rc = LDAP_SUCCESS;
1525 struct lload_tier_type *tier_impl;
1526 LloadTier *tier = c->ca_private;
1527 struct berval bv;
1528 int i = 1;
1529
1530 if ( c->op == SLAP_CONFIG_EMIT ) {
1531 switch ( c->type ) {
1532 case CFG_TIER:
1533 c->value_string = ch_strdup( tier->t_type.tier_name );
1534 break;
1535 default:
1536 goto fail;
1537 break;
1538 }
1539 return rc;
1540
1541 } else if ( c->op == LDAP_MOD_DELETE ) {
1542 if ( lload_change.type != LLOAD_CHANGE_DEL ) {
1543 /*
1544 * TODO: Shouldn't really happen while this attribute is in the
1545 * RDN, but we don't enforce it yet.
1546 *
1547 * How would we go about changing the backend type if we ever supported that?
1548 */
1549 goto fail;
1550 }
1551 return rc;
1552 }
1553
1554 if ( CONFIG_ONLINE_ADD( c ) ) {
1555 assert( tier );
1556 lload_change.target = tier;
1557 return rc;
1558 }
1559
1560 tier_impl = lload_tier_find( c->value_string );
1561 if ( !tier_impl ) {
1562 goto fail;
1563 }
1564 tier = tier_impl->tier_init();
1565 if ( !tier ) {
1566 goto fail;
1567 }
1568
1569 lload_change.target = tier;
1570
1571 if ( LDAP_STAILQ_EMPTY( &tiers ) ) {
1572 LDAP_STAILQ_INSERT_HEAD( &tiers, tier, t_next );
1573 } else {
1574 LloadTier *tier2;
1575 LDAP_STAILQ_FOREACH ( tier2, &tiers, t_next ) {
1576 i++;
1577 }
1578 LDAP_STAILQ_INSERT_TAIL( &tiers, tier, t_next );
1579 }
1580
1581 bv.bv_val = c->cr_msg;
1582 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "tier %d", i );
1583 ber_dupbv( &tier->t_name, &bv );
1584
1585 return rc;
1586
1587 fail:
1588 if ( lload_change.type == LLOAD_CHANGE_ADD ) {
1589 /* Abort the ADD */
1590 lload_change.type = LLOAD_CHANGE_DEL;
1591 }
1592 return 1;
1593 }
1594
1595 static int
config_fname(ConfigArgs * c)1596 config_fname( ConfigArgs *c )
1597 {
1598 return 0;
1599 }
1600
1601 /*
1602 * [listener=<listener>] [{read|write}=]<size>
1603 */
1604
1605 #ifdef LDAP_TCP_BUFFER
1606 static BerVarray tcp_buffer;
1607 int tcp_buffer_num;
1608
1609 #define SLAP_TCP_RMEM ( 0x1U )
1610 #define SLAP_TCP_WMEM ( 0x2U )
1611
1612 static int
tcp_buffer_parse(struct berval * val,int argc,char ** argv,int * size,int * rw,LloadListener ** l)1613 tcp_buffer_parse(
1614 struct berval *val,
1615 int argc,
1616 char **argv,
1617 int *size,
1618 int *rw,
1619 LloadListener **l )
1620 {
1621 int i, rc = LDAP_SUCCESS;
1622 LDAPURLDesc *lud = NULL;
1623 char *ptr;
1624
1625 if ( val != NULL && argv == NULL ) {
1626 char *s = val->bv_val;
1627
1628 argv = ldap_str2charray( s, " \t" );
1629 if ( argv == NULL ) {
1630 return LDAP_OTHER;
1631 }
1632 }
1633
1634 i = 0;
1635 if ( strncasecmp( argv[i], "listener=", STRLENOF("listener=") ) == 0 ) {
1636 char *url = argv[i] + STRLENOF("listener=");
1637
1638 if ( ldap_url_parse_ext( url, &lud, LDAP_PVT_URL_PARSE_DEF_PORT ) ) {
1639 rc = LDAP_INVALID_SYNTAX;
1640 goto done;
1641 }
1642
1643 *l = lload_config_check_my_url( url, lud );
1644 if ( *l == NULL ) {
1645 rc = LDAP_NO_SUCH_ATTRIBUTE;
1646 goto done;
1647 }
1648
1649 i++;
1650 }
1651
1652 ptr = argv[i];
1653 if ( strncasecmp( ptr, "read=", STRLENOF("read=") ) == 0 ) {
1654 *rw |= SLAP_TCP_RMEM;
1655 ptr += STRLENOF("read=");
1656
1657 } else if ( strncasecmp( ptr, "write=", STRLENOF("write=") ) == 0 ) {
1658 *rw |= SLAP_TCP_WMEM;
1659 ptr += STRLENOF("write=");
1660
1661 } else {
1662 *rw |= ( SLAP_TCP_RMEM | SLAP_TCP_WMEM );
1663 }
1664
1665 /* accept any base */
1666 if ( lutil_atoix( size, ptr, 0 ) ) {
1667 rc = LDAP_INVALID_SYNTAX;
1668 goto done;
1669 }
1670
1671 done:;
1672 if ( val != NULL && argv != NULL ) {
1673 ldap_charray_free( argv );
1674 }
1675
1676 if ( lud != NULL ) {
1677 ldap_free_urldesc( lud );
1678 }
1679
1680 return rc;
1681 }
1682
1683 #ifdef BALANCER_MODULE
1684 static int
tcp_buffer_delete_one(struct berval * val)1685 tcp_buffer_delete_one( struct berval *val )
1686 {
1687 int rc = 0;
1688 int size = -1, rw = 0;
1689 LloadListener *l = NULL;
1690
1691 rc = tcp_buffer_parse( val, 0, NULL, &size, &rw, &l );
1692 if ( rc != 0 ) {
1693 return rc;
1694 }
1695
1696 if ( l != NULL ) {
1697 int i;
1698 LloadListener **ll = lloadd_get_listeners();
1699
1700 for ( i = 0; ll[i] != NULL; i++ ) {
1701 if ( ll[i] == l ) break;
1702 }
1703
1704 if ( ll[i] == NULL ) {
1705 return LDAP_NO_SUCH_ATTRIBUTE;
1706 }
1707
1708 if ( rw & SLAP_TCP_RMEM ) l->sl_tcp_rmem = -1;
1709 if ( rw & SLAP_TCP_WMEM ) l->sl_tcp_wmem = -1;
1710
1711 for ( i++; ll[i] != NULL && bvmatch( &l->sl_url, &ll[i]->sl_url );
1712 i++ ) {
1713 if ( rw & SLAP_TCP_RMEM ) ll[i]->sl_tcp_rmem = -1;
1714 if ( rw & SLAP_TCP_WMEM ) ll[i]->sl_tcp_wmem = -1;
1715 }
1716
1717 } else {
1718 /* NOTE: this affects listeners without a specific setting,
1719 * does not reset all listeners. If a listener without
1720 * specific settings was assigned a buffer because of
1721 * a global setting, it will not be reset. In any case,
1722 * buffer changes will only take place at restart. */
1723 if ( rw & SLAP_TCP_RMEM ) slapd_tcp_rmem = -1;
1724 if ( rw & SLAP_TCP_WMEM ) slapd_tcp_wmem = -1;
1725 }
1726
1727 return rc;
1728 }
1729
1730 static int
tcp_buffer_delete(BerVarray vals)1731 tcp_buffer_delete( BerVarray vals )
1732 {
1733 int i;
1734
1735 for ( i = 0; !BER_BVISNULL( &vals[i] ); i++ ) {
1736 tcp_buffer_delete_one( &vals[i] );
1737 }
1738
1739 return 0;
1740 }
1741 #endif /* BALANCER_MODULE */
1742
1743 static int
tcp_buffer_unparse(int size,int rw,LloadListener * l,struct berval * val)1744 tcp_buffer_unparse( int size, int rw, LloadListener *l, struct berval *val )
1745 {
1746 char buf[sizeof("2147483648")], *ptr;
1747
1748 /* unparse for later use */
1749 val->bv_len = snprintf( buf, sizeof(buf), "%d", size );
1750 if ( l != NULL ) {
1751 val->bv_len += STRLENOF( "listener="
1752 " " ) +
1753 l->sl_url.bv_len;
1754 }
1755
1756 if ( rw != ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ) ) {
1757 if ( rw & SLAP_TCP_RMEM ) {
1758 val->bv_len += STRLENOF("read=");
1759 } else if ( rw & SLAP_TCP_WMEM ) {
1760 val->bv_len += STRLENOF("write=");
1761 }
1762 }
1763
1764 val->bv_val = SLAP_MALLOC( val->bv_len + 1 );
1765
1766 ptr = val->bv_val;
1767
1768 if ( l != NULL ) {
1769 ptr = lutil_strcopy( ptr, "listener=" );
1770 ptr = lutil_strncopy( ptr, l->sl_url.bv_val, l->sl_url.bv_len );
1771 *ptr++ = ' ';
1772 }
1773
1774 if ( rw != ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ) ) {
1775 if ( rw & SLAP_TCP_RMEM ) {
1776 ptr = lutil_strcopy( ptr, "read=" );
1777 } else if ( rw & SLAP_TCP_WMEM ) {
1778 ptr = lutil_strcopy( ptr, "write=" );
1779 }
1780 }
1781
1782 ptr = lutil_strcopy( ptr, buf );
1783 *ptr = '\0';
1784
1785 assert( val->bv_val + val->bv_len == ptr );
1786
1787 return LDAP_SUCCESS;
1788 }
1789
1790 static int
tcp_buffer_add_one(int argc,char ** argv)1791 tcp_buffer_add_one( int argc, char **argv )
1792 {
1793 int rc = 0;
1794 int size = -1, rw = 0;
1795 LloadListener *l = NULL;
1796
1797 struct berval val;
1798
1799 /* parse */
1800 rc = tcp_buffer_parse( NULL, argc, argv, &size, &rw, &l );
1801 if ( rc != 0 ) {
1802 return rc;
1803 }
1804
1805 /* unparse for later use */
1806 rc = tcp_buffer_unparse( size, rw, l, &val );
1807 if ( rc != LDAP_SUCCESS ) {
1808 return rc;
1809 }
1810
1811 /* use parsed values */
1812 if ( l != NULL ) {
1813 int i;
1814 LloadListener **ll = lloadd_get_listeners();
1815
1816 for ( i = 0; ll[i] != NULL; i++ ) {
1817 if ( ll[i] == l ) break;
1818 }
1819
1820 if ( ll[i] == NULL ) {
1821 return LDAP_NO_SUCH_ATTRIBUTE;
1822 }
1823
1824 /* buffer only applies to TCP listeners;
1825 * we do not do any check here, and delegate them
1826 * to setsockopt(2) */
1827 if ( rw & SLAP_TCP_RMEM ) l->sl_tcp_rmem = size;
1828 if ( rw & SLAP_TCP_WMEM ) l->sl_tcp_wmem = size;
1829
1830 for ( i++; ll[i] != NULL && bvmatch( &l->sl_url, &ll[i]->sl_url );
1831 i++ ) {
1832 if ( rw & SLAP_TCP_RMEM ) ll[i]->sl_tcp_rmem = size;
1833 if ( rw & SLAP_TCP_WMEM ) ll[i]->sl_tcp_wmem = size;
1834 }
1835
1836 } else {
1837 /* NOTE: this affects listeners without a specific setting,
1838 * does not set all listeners */
1839 if ( rw & SLAP_TCP_RMEM ) slapd_tcp_rmem = size;
1840 if ( rw & SLAP_TCP_WMEM ) slapd_tcp_wmem = size;
1841 }
1842
1843 tcp_buffer = SLAP_REALLOC(
1844 tcp_buffer, sizeof(struct berval) * ( tcp_buffer_num + 2 ) );
1845 /* append */
1846 tcp_buffer[tcp_buffer_num] = val;
1847
1848 tcp_buffer_num++;
1849 BER_BVZERO( &tcp_buffer[tcp_buffer_num] );
1850
1851 return rc;
1852 }
1853
1854 static int
config_tcp_buffer(ConfigArgs * c)1855 config_tcp_buffer( ConfigArgs *c )
1856 {
1857 int rc = LDAP_SUCCESS;
1858
1859 #ifdef BALANCER_MODULE
1860 if ( c->op == SLAP_CONFIG_EMIT ) {
1861 if ( tcp_buffer == NULL || BER_BVISNULL( &tcp_buffer[0] ) ) {
1862 return 1;
1863 }
1864 value_add( &c->rvalue_vals, tcp_buffer );
1865 value_add( &c->rvalue_nvals, tcp_buffer );
1866
1867 return 0;
1868 } else if ( c->op == LDAP_MOD_DELETE ) {
1869 if ( !c->line ) {
1870 tcp_buffer_delete( tcp_buffer );
1871 ber_bvarray_free( tcp_buffer );
1872 tcp_buffer = NULL;
1873 tcp_buffer_num = 0;
1874
1875 } else {
1876 int size = -1, rw = 0;
1877 LloadListener *l = NULL;
1878
1879 struct berval val = BER_BVNULL;
1880
1881 int i;
1882
1883 if ( tcp_buffer_num == 0 ) {
1884 return 1;
1885 }
1886
1887 /* parse */
1888 rc = tcp_buffer_parse(
1889 NULL, c->argc - 1, &c->argv[1], &size, &rw, &l );
1890 if ( rc != 0 ) {
1891 return 1;
1892 }
1893
1894 /* unparse for later use */
1895 rc = tcp_buffer_unparse( size, rw, l, &val );
1896 if ( rc != LDAP_SUCCESS ) {
1897 return 1;
1898 }
1899
1900 for ( i = 0; !BER_BVISNULL( &tcp_buffer[i] ); i++ ) {
1901 if ( bvmatch( &tcp_buffer[i], &val ) ) {
1902 break;
1903 }
1904 }
1905
1906 if ( BER_BVISNULL( &tcp_buffer[i] ) ) {
1907 /* not found */
1908 rc = 1;
1909 goto done;
1910 }
1911
1912 tcp_buffer_delete_one( &tcp_buffer[i] );
1913 ber_memfree( tcp_buffer[i].bv_val );
1914 for ( ; i < tcp_buffer_num; i++ ) {
1915 tcp_buffer[i] = tcp_buffer[i + 1];
1916 }
1917 tcp_buffer_num--;
1918
1919 done:;
1920 if ( !BER_BVISNULL( &val ) ) {
1921 SLAP_FREE(val.bv_val);
1922 }
1923 }
1924
1925 return rc;
1926 }
1927 #endif /* BALANCER_MODULE */
1928
1929 rc = tcp_buffer_add_one( c->argc - 1, &c->argv[1] );
1930 if ( rc ) {
1931 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> unable to add value #%d",
1932 c->argv[0], tcp_buffer_num );
1933 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
1934 return 1;
1935 }
1936
1937 return 0;
1938 }
1939 #endif /* LDAP_TCP_BUFFER */
1940
1941 static int
config_restrict(ConfigArgs * c)1942 config_restrict( ConfigArgs *c )
1943 {
1944 slap_mask_t restrictops = 0;
1945 int i;
1946 slap_verbmasks restrictable_ops[] = {
1947 { BER_BVC("bind"), SLAP_RESTRICT_OP_BIND },
1948 { BER_BVC("add"), SLAP_RESTRICT_OP_ADD },
1949 { BER_BVC("modify"), SLAP_RESTRICT_OP_MODIFY },
1950 { BER_BVC("rename"), SLAP_RESTRICT_OP_RENAME },
1951 { BER_BVC("modrdn"), 0 },
1952 { BER_BVC("delete"), SLAP_RESTRICT_OP_DELETE },
1953 { BER_BVC("search"), SLAP_RESTRICT_OP_SEARCH },
1954 { BER_BVC("compare"), SLAP_RESTRICT_OP_COMPARE },
1955 { BER_BVC("read"), SLAP_RESTRICT_OP_READS },
1956 { BER_BVC("write"), SLAP_RESTRICT_OP_WRITES },
1957 { BER_BVC("extended"), SLAP_RESTRICT_OP_EXTENDED },
1958 { BER_BVC("extended=" LDAP_EXOP_START_TLS), SLAP_RESTRICT_EXOP_START_TLS },
1959 { BER_BVC("extended=" LDAP_EXOP_MODIFY_PASSWD), SLAP_RESTRICT_EXOP_MODIFY_PASSWD },
1960 { BER_BVC("extended=" LDAP_EXOP_X_WHO_AM_I), SLAP_RESTRICT_EXOP_WHOAMI },
1961 { BER_BVC("extended=" LDAP_EXOP_X_CANCEL), SLAP_RESTRICT_EXOP_CANCEL },
1962 { BER_BVC("all"), SLAP_RESTRICT_OP_ALL },
1963 { BER_BVNULL, 0 }
1964 };
1965
1966 i = verbs_to_mask( c->argc, c->argv, restrictable_ops, &restrictops );
1967 if ( i ) {
1968 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> unknown operation",
1969 c->argv[0] );
1970 Debug( LDAP_DEBUG_ANY, "%s: %s %s\n",
1971 c->log, c->cr_msg, c->argv[i] );
1972 return 1;
1973 }
1974 if ( restrictops & SLAP_RESTRICT_OP_EXTENDED )
1975 restrictops &= ~SLAP_RESTRICT_EXOP_MASK;
1976 return 0;
1977 }
1978
1979 static int
config_include(ConfigArgs * c)1980 config_include( ConfigArgs *c )
1981 {
1982 int savelineno = c->lineno;
1983 int rc;
1984 ConfigFile *cf;
1985 ConfigFile *cfsave = cfn;
1986 ConfigFile *cf2 = NULL;
1987
1988 /* Leftover from RE23. No dynamic config for include files */
1989 if ( c->op == SLAP_CONFIG_EMIT || c->op == LDAP_MOD_DELETE ) return 1;
1990
1991 cf = ch_calloc( 1, sizeof(ConfigFile) );
1992 if ( cfn->c_kids ) {
1993 for ( cf2 = cfn->c_kids; cf2 && cf2->c_sibs; cf2 = cf2->c_sibs )
1994 /* empty */;
1995 cf2->c_sibs = cf;
1996 } else {
1997 cfn->c_kids = cf;
1998 }
1999 cfn = cf;
2000 ber_str2bv( c->argv[1], 0, 1, &cf->c_file );
2001 rc = lload_read_config_file(
2002 c->argv[1], c->depth + 1, c, config_back_cf_table );
2003 c->lineno = savelineno - 1;
2004 cfn = cfsave;
2005 if ( rc ) {
2006 if ( cf2 )
2007 cf2->c_sibs = NULL;
2008 else
2009 cfn->c_kids = NULL;
2010 ch_free( cf->c_file.bv_val );
2011 ch_free( cf );
2012 } else {
2013 c->ca_private = cf;
2014 }
2015 return rc;
2016 }
2017
2018 static int
config_feature(ConfigArgs * c)2019 config_feature( ConfigArgs *c )
2020 {
2021 slap_verbmasks features[] = {
2022 #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS
2023 { BER_BVC("vc"), LLOAD_FEATURE_VC },
2024 #endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */
2025 { BER_BVC("proxyauthz"), LLOAD_FEATURE_PROXYAUTHZ },
2026 { BER_BVC("read_pause"), LLOAD_FEATURE_PAUSE },
2027 { BER_BVNULL, 0 }
2028 };
2029 slap_mask_t mask = 0;
2030 int i;
2031
2032 if ( c->op == SLAP_CONFIG_EMIT ) {
2033 return mask_to_verbs( features, lload_features, &c->rvalue_vals );
2034 }
2035
2036 lload_change.type = LLOAD_CHANGE_MODIFY;
2037 lload_change.object = LLOAD_DAEMON;
2038 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_FEATURES;
2039 if ( !lload_change.target ) {
2040 lload_change.target = (void *)(uintptr_t)~lload_features;
2041 }
2042
2043 if ( c->op == LDAP_MOD_DELETE ) {
2044 if ( !c->line ) {
2045 /* Last value has been deleted */
2046 lload_features = 0;
2047 } else {
2048 i = verb_to_mask( c->line, features );
2049 lload_features &= ~features[i].mask;
2050 }
2051 return 0;
2052 }
2053
2054 i = verbs_to_mask( c->argc, c->argv, features, &mask );
2055 if ( i ) {
2056 Debug( LDAP_DEBUG_ANY, "%s: <%s> unknown feature %s\n", c->log,
2057 c->argv[0], c->argv[i] );
2058 return 1;
2059 }
2060
2061 if ( mask & ~LLOAD_FEATURE_SUPPORTED_MASK ) {
2062 for ( i = 1; i < c->argc; i++ ) {
2063 int j = verb_to_mask( c->argv[i], features );
2064 if ( features[j].mask & ~LLOAD_FEATURE_SUPPORTED_MASK ) {
2065 Debug( LDAP_DEBUG_ANY, "%s: <%s> "
2066 "experimental feature %s is undocumented, unsupported "
2067 "and can change or disappear at any time!\n",
2068 c->log, c->argv[0], c->argv[i] );
2069 }
2070 }
2071 }
2072
2073 lload_features |= mask;
2074 return 0;
2075 }
2076
2077 #ifdef HAVE_TLS
2078 static int
config_tls_cleanup(ConfigArgs * c)2079 config_tls_cleanup( ConfigArgs *c )
2080 {
2081 int rc = 0;
2082
2083 if ( lload_tls_ld ) {
2084 int opt = 1;
2085
2086 ldap_pvt_tls_ctx_free( lload_tls_ctx );
2087 lload_tls_ctx = NULL;
2088
2089 /* Force new ctx to be created */
2090 rc = ldap_pvt_tls_set_option(
2091 lload_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
2092 if ( rc == 0 ) {
2093 /* The ctx's refcount is bumped up here */
2094 ldap_pvt_tls_get_option(
2095 lload_tls_ld, LDAP_OPT_X_TLS_CTX, &lload_tls_ctx );
2096 } else {
2097 if ( rc == LDAP_NOT_SUPPORTED )
2098 rc = LDAP_UNWILLING_TO_PERFORM;
2099 else
2100 rc = LDAP_OTHER;
2101 }
2102 }
2103 return rc;
2104 }
2105
2106 static int
config_tls_option(ConfigArgs * c)2107 config_tls_option( ConfigArgs *c )
2108 {
2109 int flag;
2110 int berval = 0;
2111 LDAP *ld = lload_tls_ld;
2112
2113 switch ( c->type ) {
2114 case CFG_TLS_RAND:
2115 flag = LDAP_OPT_X_TLS_RANDOM_FILE;
2116 ld = NULL;
2117 break;
2118 case CFG_TLS_CIPHER:
2119 flag = LDAP_OPT_X_TLS_CIPHER_SUITE;
2120 break;
2121 case CFG_TLS_CERT_FILE:
2122 flag = LDAP_OPT_X_TLS_CERTFILE;
2123 break;
2124 case CFG_TLS_CERT_KEY:
2125 flag = LDAP_OPT_X_TLS_KEYFILE;
2126 break;
2127 case CFG_TLS_CA_PATH:
2128 flag = LDAP_OPT_X_TLS_CACERTDIR;
2129 break;
2130 case CFG_TLS_CA_FILE:
2131 flag = LDAP_OPT_X_TLS_CACERTFILE;
2132 break;
2133 case CFG_TLS_DH_FILE:
2134 flag = LDAP_OPT_X_TLS_DHFILE;
2135 break;
2136 case CFG_TLS_ECNAME:
2137 flag = LDAP_OPT_X_TLS_ECNAME;
2138 break;
2139 #ifdef HAVE_GNUTLS
2140 case CFG_TLS_CRL_FILE:
2141 flag = LDAP_OPT_X_TLS_CRLFILE;
2142 break;
2143 #endif
2144 case CFG_TLS_CACERT:
2145 flag = LDAP_OPT_X_TLS_CACERT;
2146 berval = 1;
2147 break;
2148 case CFG_TLS_CERT:
2149 flag = LDAP_OPT_X_TLS_CERT;
2150 berval = 1;
2151 break;
2152 case CFG_TLS_KEY:
2153 flag = LDAP_OPT_X_TLS_KEY;
2154 berval = 1;
2155 break;
2156 default:
2157 Debug( LDAP_DEBUG_ANY, "%s: "
2158 "unknown tls_option <0x%x>\n",
2159 c->log, c->type );
2160 return 1;
2161 }
2162 if ( c->op == SLAP_CONFIG_EMIT ) {
2163 return ldap_pvt_tls_get_option( ld, flag,
2164 berval ? (void *)&c->value_bv : (void *)&c->value_string );
2165 }
2166
2167 lload_change.type = LLOAD_CHANGE_MODIFY;
2168 lload_change.object = LLOAD_DAEMON;
2169 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_TLS;
2170
2171 config_push_cleanup( c, config_tls_cleanup );
2172 if ( c->op == LDAP_MOD_DELETE ) {
2173 return ldap_pvt_tls_set_option( ld, flag, NULL );
2174 }
2175 if ( !berval ) ch_free( c->value_string );
2176 return ldap_pvt_tls_set_option(
2177 ld, flag, berval ? (void *)&c->value_bv : (void *)c->argv[1] );
2178 }
2179
2180 /* FIXME: this ought to be provided by libldap */
2181 static int
config_tls_config(ConfigArgs * c)2182 config_tls_config( ConfigArgs *c )
2183 {
2184 int i, flag;
2185
2186 switch ( c->type ) {
2187 case CFG_TLS_CRLCHECK:
2188 flag = LDAP_OPT_X_TLS_CRLCHECK;
2189 break;
2190 case CFG_TLS_VERIFY:
2191 flag = LDAP_OPT_X_TLS_REQUIRE_CERT;
2192 break;
2193 case CFG_TLS_PROTOCOL_MIN:
2194 flag = LDAP_OPT_X_TLS_PROTOCOL_MIN;
2195 break;
2196 default:
2197 Debug( LDAP_DEBUG_ANY, "%s: "
2198 "unknown tls_option <0x%x>\n",
2199 c->log, c->type );
2200 return 1;
2201 }
2202 if ( c->op == SLAP_CONFIG_EMIT ) {
2203 return lload_tls_get_config( lload_tls_ld, flag, &c->value_string );
2204 }
2205
2206 lload_change.type = LLOAD_CHANGE_MODIFY;
2207 lload_change.object = LLOAD_DAEMON;
2208 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_TLS;
2209
2210 config_push_cleanup( c, config_tls_cleanup );
2211 if ( c->op == LDAP_MOD_DELETE ) {
2212 int i = 0;
2213 return ldap_pvt_tls_set_option( lload_tls_ld, flag, &i );
2214 }
2215 ch_free( c->value_string );
2216 if ( isdigit( (unsigned char)c->argv[1][0] ) &&
2217 c->type != CFG_TLS_PROTOCOL_MIN ) {
2218 if ( lutil_atoi( &i, c->argv[1] ) != 0 ) {
2219 Debug( LDAP_DEBUG_ANY, "%s: "
2220 "unable to parse %s \"%s\"\n",
2221 c->log, c->argv[0], c->argv[1] );
2222 return 1;
2223 }
2224 return ldap_pvt_tls_set_option( lload_tls_ld, flag, &i );
2225 } else {
2226 return ldap_pvt_tls_config( lload_tls_ld, flag, c->argv[1] );
2227 }
2228 }
2229 #endif
2230
2231 #ifdef BALANCER_MODULE
2232 static int
config_share_tls_ctx(ConfigArgs * c)2233 config_share_tls_ctx( ConfigArgs *c )
2234 {
2235 int rc = LDAP_SUCCESS;
2236
2237 if ( c->op == SLAP_CONFIG_EMIT ) {
2238 c->value_int = lload_use_slap_tls_ctx;
2239 return rc;
2240 }
2241
2242 lload_change.type = LLOAD_CHANGE_MODIFY;
2243 lload_change.object = LLOAD_DAEMON;
2244 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_TLS;
2245
2246 if ( c->op == LDAP_MOD_DELETE ) {
2247 lload_use_slap_tls_ctx = 0;
2248 return rc;
2249 }
2250
2251 lload_use_slap_tls_ctx = c->value_int;
2252 return rc;
2253 }
2254 #endif /* BALANCER_MODULE */
2255
2256 void
lload_init_config_argv(ConfigArgs * c)2257 lload_init_config_argv( ConfigArgs *c )
2258 {
2259 c->argv = ch_calloc( ARGS_STEP + 1, sizeof(*c->argv) );
2260 c->argv_size = ARGS_STEP + 1;
2261 }
2262
2263 ConfigTable *
lload_config_find_keyword(ConfigTable * Conf,ConfigArgs * c)2264 lload_config_find_keyword( ConfigTable *Conf, ConfigArgs *c )
2265 {
2266 int i;
2267
2268 for ( i = 0; Conf[i].name; i++ )
2269 if ( ( Conf[i].length &&
2270 ( !strncasecmp(
2271 c->argv[0], Conf[i].name, Conf[i].length ) ) ) ||
2272 ( !strcasecmp( c->argv[0], Conf[i].name ) ) )
2273 break;
2274 if ( !Conf[i].name ) return NULL;
2275 if ( (Conf[i].arg_type & ARGS_TYPES) == ARG_BINARY ) {
2276 size_t decode_len = LUTIL_BASE64_DECODE_LEN( c->linelen );
2277 ch_free( c->tline );
2278 c->tline = ch_malloc( decode_len + 1 );
2279 c->linelen = lutil_b64_pton( c->line, c->tline, decode_len );
2280 if ( c->linelen < 0 ) {
2281 ch_free( c->tline );
2282 c->tline = NULL;
2283 return NULL;
2284 }
2285 c->line = c->tline;
2286 }
2287 c->ca_desc = Conf + i;
2288 return c->ca_desc;
2289 }
2290
2291 int
lload_config_check_vals(ConfigTable * Conf,ConfigArgs * c,int check_only)2292 lload_config_check_vals( ConfigTable *Conf, ConfigArgs *c, int check_only )
2293 {
2294 int arg_user, arg_type, arg_syn, iarg;
2295 unsigned uiarg;
2296 long larg;
2297 unsigned long ularg;
2298 ber_len_t barg;
2299
2300 if ( Conf->arg_type == ARG_IGNORED ) {
2301 Debug( LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
2302 c->log, Conf->name );
2303 return 0;
2304 }
2305 arg_type = Conf->arg_type & ARGS_TYPES;
2306 arg_user = Conf->arg_type & ARGS_USERLAND;
2307 arg_syn = Conf->arg_type & ARGS_SYNTAX;
2308
2309 if ( Conf->min_args && ( c->argc < Conf->min_args ) ) {
2310 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> missing <%s> argument",
2311 c->argv[0], Conf->what ? Conf->what : "" );
2312 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
2313 c->log, c->cr_msg );
2314 return ARG_BAD_CONF;
2315 }
2316 if ( Conf->max_args && ( c->argc > Conf->max_args ) ) {
2317 char *ignored = " ignored";
2318
2319 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> extra cruft after <%s>",
2320 c->argv[0], Conf->what );
2321
2322 ignored = "";
2323 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s%s\n",
2324 c->log, c->cr_msg, ignored );
2325 return ARG_BAD_CONF;
2326 }
2327 if ( (arg_syn & ARG_PAREN) && *c->argv[1] != '(' /*')'*/ ) {
2328 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> old format not supported",
2329 c->argv[0] );
2330 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
2331 c->log, c->cr_msg );
2332 return ARG_BAD_CONF;
2333 }
2334 if ( arg_type && !Conf->arg_item && !(arg_syn & ARG_OFFSET) ) {
2335 snprintf( c->cr_msg, sizeof(c->cr_msg),
2336 "<%s> invalid config_table, arg_item is NULL",
2337 c->argv[0] );
2338 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
2339 c->log, c->cr_msg );
2340 return ARG_BAD_CONF;
2341 }
2342 c->type = arg_user;
2343 memset( &c->values, 0, sizeof(c->values) );
2344 if ( arg_type == ARG_STRING ) {
2345 assert( c->argc == 2 );
2346 if ( !check_only ) c->value_string = ch_strdup( c->argv[1] );
2347 } else if ( arg_type == ARG_BERVAL ) {
2348 assert( c->argc == 2 );
2349 if ( !check_only ) ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
2350 } else if ( arg_type == ARG_BINARY ) {
2351 assert( c->argc == 2 );
2352 if ( !check_only ) {
2353 c->value_bv.bv_len = c->linelen;
2354 c->value_bv.bv_val = ch_malloc( c->linelen );
2355 AC_MEMCPY( c->value_bv.bv_val, c->line, c->linelen );
2356 }
2357 } else { /* all numeric */
2358 int j;
2359 iarg = 0;
2360 larg = 0;
2361 barg = 0;
2362 switch ( arg_type ) {
2363 case ARG_INT:
2364 assert( c->argc == 2 );
2365 if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
2366 snprintf( c->cr_msg, sizeof(c->cr_msg),
2367 "<%s> unable to parse \"%s\" as int",
2368 c->argv[0], c->argv[1] );
2369 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
2370 c->log, c->cr_msg );
2371 return ARG_BAD_CONF;
2372 }
2373 break;
2374 case ARG_UINT:
2375 assert( c->argc == 2 );
2376 if ( lutil_atoux( &uiarg, c->argv[1], 0 ) != 0 ) {
2377 snprintf( c->cr_msg, sizeof(c->cr_msg),
2378 "<%s> unable to parse \"%s\" as unsigned int",
2379 c->argv[0], c->argv[1] );
2380 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
2381 c->log, c->cr_msg );
2382 return ARG_BAD_CONF;
2383 }
2384 break;
2385 case ARG_LONG:
2386 assert( c->argc == 2 );
2387 if ( lutil_atolx( &larg, c->argv[1], 0 ) != 0 ) {
2388 snprintf( c->cr_msg, sizeof(c->cr_msg),
2389 "<%s> unable to parse \"%s\" as long",
2390 c->argv[0], c->argv[1] );
2391 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
2392 c->log, c->cr_msg );
2393 return ARG_BAD_CONF;
2394 }
2395 break;
2396 case ARG_ULONG:
2397 assert( c->argc == 2 );
2398 if ( LUTIL_ATOULX( &ularg, c->argv[1], 0 ) != 0 ) {
2399 snprintf( c->cr_msg, sizeof(c->cr_msg),
2400 "<%s> unable to parse \"%s\" as unsigned long",
2401 c->argv[0], c->argv[1] );
2402 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
2403 c->log, c->cr_msg );
2404 return ARG_BAD_CONF;
2405 }
2406 break;
2407 case ARG_BER_LEN_T: {
2408 unsigned long l;
2409 assert( c->argc == 2 );
2410 if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) {
2411 snprintf( c->cr_msg, sizeof(c->cr_msg),
2412 "<%s> unable to parse \"%s\" as ber_len_t",
2413 c->argv[0], c->argv[1] );
2414 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
2415 c->log, c->cr_msg );
2416 return ARG_BAD_CONF;
2417 }
2418 barg = (ber_len_t)l;
2419 } break;
2420 case ARG_ON_OFF:
2421 /* note: this is an explicit exception
2422 * to the "need exactly 2 args" rule */
2423 if ( c->argc == 1 ) {
2424 iarg = 1;
2425 } else if ( !strcasecmp( c->argv[1], "on" ) ||
2426 !strcasecmp( c->argv[1], "true" ) ||
2427 !strcasecmp( c->argv[1], "yes" ) ) {
2428 iarg = 1;
2429 } else if ( !strcasecmp( c->argv[1], "off" ) ||
2430 !strcasecmp( c->argv[1], "false" ) ||
2431 !strcasecmp( c->argv[1], "no" ) ) {
2432 iarg = 0;
2433 } else {
2434 snprintf( c->cr_msg, sizeof(c->cr_msg),
2435 "<%s> invalid value",
2436 c->argv[0] );
2437 Debug( LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
2438 c->log, c->cr_msg );
2439 return ARG_BAD_CONF;
2440 }
2441 break;
2442 }
2443 j = (arg_type & ARG_NONZERO) ? 1 : 0;
2444 if ( iarg < j && larg < j && barg < (unsigned)j ) {
2445 larg = larg ? larg : ( barg ? (long)barg : iarg );
2446 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> invalid value",
2447 c->argv[0] );
2448 Debug( LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
2449 c->log, c->cr_msg );
2450 return ARG_BAD_CONF;
2451 }
2452 switch ( arg_type ) {
2453 case ARG_ON_OFF:
2454 case ARG_INT:
2455 c->value_int = iarg;
2456 break;
2457 case ARG_UINT:
2458 c->value_uint = uiarg;
2459 break;
2460 case ARG_LONG:
2461 c->value_long = larg;
2462 break;
2463 case ARG_ULONG:
2464 c->value_ulong = ularg;
2465 break;
2466 case ARG_BER_LEN_T:
2467 c->value_ber_t = barg;
2468 break;
2469 }
2470 }
2471 return 0;
2472 }
2473
2474 int
lload_config_set_vals(ConfigTable * Conf,ConfigArgs * c)2475 lload_config_set_vals( ConfigTable *Conf, ConfigArgs *c )
2476 {
2477 int rc, arg_type;
2478 void *ptr = NULL;
2479
2480 arg_type = Conf->arg_type;
2481 if ( arg_type & ARG_MAGIC ) {
2482 c->cr_msg[0] = '\0';
2483 rc = ( *( (ConfigDriver *)Conf->arg_item ) )( c );
2484 if ( rc ) {
2485 if ( !c->cr_msg[0] ) {
2486 snprintf( c->cr_msg, sizeof(c->cr_msg),
2487 "<%s> handler exited with %d",
2488 c->argv[0], rc );
2489 Debug( LDAP_DEBUG_CONFIG, "%s: %s!\n", c->log, c->cr_msg );
2490 }
2491 return ARG_BAD_CONF;
2492 }
2493 return 0;
2494 }
2495 if ( arg_type & ARG_OFFSET ) {
2496 {
2497 snprintf( c->cr_msg, sizeof(c->cr_msg),
2498 "<%s> offset is missing base pointer",
2499 c->argv[0] );
2500 Debug( LDAP_DEBUG_CONFIG, "%s: %s!\n", c->log, c->cr_msg );
2501 return ARG_BAD_CONF;
2502 }
2503 ptr = (void *)( (char *)ptr + (long)Conf->arg_item );
2504 } else if ( arg_type & ARGS_TYPES ) {
2505 ptr = Conf->arg_item;
2506 }
2507 if ( arg_type & ARGS_TYPES ) switch ( arg_type & ARGS_TYPES ) {
2508 case ARG_ON_OFF:
2509 case ARG_INT:
2510 *(int *)ptr = c->value_int;
2511 break;
2512 case ARG_UINT:
2513 *(unsigned *)ptr = c->value_uint;
2514 break;
2515 case ARG_LONG:
2516 *(long *)ptr = c->value_long;
2517 break;
2518 case ARG_ULONG:
2519 *(size_t *)ptr = c->value_ulong;
2520 break;
2521 case ARG_BER_LEN_T:
2522 *(ber_len_t *)ptr = c->value_ber_t;
2523 break;
2524 case ARG_STRING: {
2525 char *cc = *(char **)ptr;
2526 if ( cc ) {
2527 if ( (arg_type & ARG_UNIQUE) &&
2528 c->op == SLAP_CONFIG_ADD ) {
2529 Debug( LDAP_DEBUG_CONFIG, "%s: already set %s!\n",
2530 c->log, Conf->name );
2531 return ARG_BAD_CONF;
2532 }
2533 ch_free( cc );
2534 }
2535 *(char **)ptr = c->value_string;
2536 break;
2537 }
2538 case ARG_BERVAL:
2539 case ARG_BINARY:
2540 *(struct berval *)ptr = c->value_bv;
2541 break;
2542 }
2543 return 0;
2544 }
2545
2546 int
lload_config_add_vals(ConfigTable * Conf,ConfigArgs * c)2547 lload_config_add_vals( ConfigTable *Conf, ConfigArgs *c )
2548 {
2549 int rc, arg_type;
2550
2551 arg_type = Conf->arg_type;
2552 if ( arg_type == ARG_IGNORED ) {
2553 Debug( LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
2554 c->log, Conf->name );
2555 return 0;
2556 }
2557 rc = lload_config_check_vals( Conf, c, 0 );
2558 if ( rc ) return rc;
2559 return lload_config_set_vals( Conf, c );
2560 }
2561
2562 int
lload_read_config_file(const char * fname,int depth,ConfigArgs * cf,ConfigTable * cft)2563 lload_read_config_file(
2564 const char *fname,
2565 int depth,
2566 ConfigArgs *cf,
2567 ConfigTable *cft )
2568 {
2569 FILE *fp;
2570 ConfigTable *ct;
2571 ConfigArgs *c;
2572 int rc;
2573 struct stat s;
2574
2575 c = ch_calloc( 1, sizeof(ConfigArgs) );
2576 if ( c == NULL ) {
2577 return 1;
2578 }
2579
2580 if ( depth ) {
2581 memcpy( c, cf, sizeof(ConfigArgs) );
2582 } else {
2583 c->depth = depth; /* XXX */
2584 }
2585
2586 c->valx = -1;
2587 c->fname = fname;
2588 lload_init_config_argv( c );
2589
2590 if ( stat( fname, &s ) != 0 ) {
2591 char ebuf[128];
2592 int saved_errno = errno;
2593 ldap_syslog = 1;
2594 Debug( LDAP_DEBUG_ANY, "could not stat config file \"%s\": %s (%d)\n",
2595 fname, AC_STRERROR_R( saved_errno, ebuf, sizeof(ebuf) ),
2596 saved_errno );
2597 ch_free( c->argv );
2598 ch_free( c );
2599 return 1;
2600 }
2601
2602 if ( !S_ISREG(s.st_mode) ) {
2603 ldap_syslog = 1;
2604 Debug( LDAP_DEBUG_ANY, "regular file expected, got \"%s\"\n", fname );
2605 ch_free( c->argv );
2606 ch_free( c );
2607 return 1;
2608 }
2609
2610 fp = fopen( fname, "r" );
2611 if ( fp == NULL ) {
2612 char ebuf[128];
2613 int saved_errno = errno;
2614 ldap_syslog = 1;
2615 Debug( LDAP_DEBUG_ANY, "could not open config file \"%s\": %s (%d)\n",
2616 fname, AC_STRERROR_R( saved_errno, ebuf, sizeof(ebuf) ),
2617 saved_errno );
2618 ch_free( c->argv );
2619 ch_free( c );
2620 return 1;
2621 }
2622
2623 Debug( LDAP_DEBUG_CONFIG, "reading config file %s\n", fname );
2624
2625 fp_getline_init( c );
2626
2627 c->tline = NULL;
2628
2629 while ( fp_getline( fp, c ) ) {
2630 /* skip comments and blank lines */
2631 if ( c->line[0] == '#' || c->line[0] == '\0' ) {
2632 continue;
2633 }
2634
2635 snprintf( c->log, sizeof(c->log), "%s: line %d",
2636 c->fname, c->lineno );
2637
2638 c->argc = 0;
2639 ch_free( c->tline );
2640 if ( lload_config_fp_parse_line( c ) ) {
2641 rc = 1;
2642 goto done;
2643 }
2644
2645 if ( c->argc < 1 ) {
2646 Debug( LDAP_DEBUG_ANY, "%s: bad config line\n", c->log );
2647 rc = 1;
2648 goto done;
2649 }
2650
2651 c->op = SLAP_CONFIG_ADD;
2652
2653 ct = lload_config_find_keyword( cft, c );
2654 if ( ct ) {
2655 c->table = Cft_Global;
2656 rc = lload_config_add_vals( ct, c );
2657 if ( !rc ) continue;
2658
2659 if ( rc & ARGS_USERLAND ) {
2660 /* XXX a usertype would be opaque here */
2661 Debug( LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n",
2662 c->log, c->argv[0] );
2663 rc = 1;
2664 goto done;
2665
2666 } else if ( rc == ARG_BAD_CONF ) {
2667 rc = 1;
2668 goto done;
2669 }
2670
2671 } else {
2672 Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
2673 "<%s> outside backend info and database definitions\n",
2674 c->log, *c->argv );
2675 rc = 1;
2676 goto done;
2677 }
2678 }
2679
2680 rc = 0;
2681
2682 done:
2683 ch_free( c->tline );
2684 fclose( fp );
2685 ch_free( c->argv );
2686 ch_free( c );
2687 return rc;
2688 }
2689
2690 int
lload_read_config(const char * fname,const char * dir)2691 lload_read_config( const char *fname, const char *dir )
2692 {
2693 if ( !fname ) fname = LLOADD_DEFAULT_CONFIGFILE;
2694
2695 cfn = ch_calloc( 1, sizeof(ConfigFile) );
2696
2697 return lload_read_config_file( fname, 0, NULL, config_back_cf_table );
2698 }
2699
2700 #ifndef BALANCER_MODULE
2701 int
config_push_cleanup(ConfigArgs * ca,ConfigDriver * cleanup)2702 config_push_cleanup( ConfigArgs *ca, ConfigDriver *cleanup )
2703 {
2704 /* Stub, cleanups only run in online config */
2705 return 0;
2706 }
2707 #endif /* !BALANCER_MODULE */
2708
2709 static slap_verbmasks tlskey[] = {
2710 { BER_BVC("no"), LLOAD_CLEARTEXT },
2711 { BER_BVC("yes"), LLOAD_STARTTLS_OPTIONAL },
2712 { BER_BVC("critical"), LLOAD_STARTTLS },
2713 { BER_BVNULL, 0 }
2714 };
2715
2716 static slap_verbmasks crlkeys[] = {
2717 { BER_BVC("none"), LDAP_OPT_X_TLS_CRL_NONE },
2718 { BER_BVC("peer"), LDAP_OPT_X_TLS_CRL_PEER },
2719 { BER_BVC("all"), LDAP_OPT_X_TLS_CRL_ALL },
2720 { BER_BVNULL, 0 }
2721 };
2722
2723 static slap_verbmasks vfykeys[] = {
2724 { BER_BVC("never"), LDAP_OPT_X_TLS_NEVER },
2725 { BER_BVC("allow"), LDAP_OPT_X_TLS_ALLOW },
2726 { BER_BVC("try"), LDAP_OPT_X_TLS_TRY },
2727 { BER_BVC("demand"), LDAP_OPT_X_TLS_DEMAND },
2728 { BER_BVC("hard"), LDAP_OPT_X_TLS_HARD },
2729 { BER_BVC("true"), LDAP_OPT_X_TLS_HARD },
2730 { BER_BVNULL, 0 }
2731 };
2732
2733 static slap_verbmasks methkey[] = {
2734 { BER_BVC("none"), LDAP_AUTH_NONE },
2735 { BER_BVC("simple"), LDAP_AUTH_SIMPLE },
2736 #ifdef HAVE_CYRUS_SASL
2737 { BER_BVC("sasl"), LDAP_AUTH_SASL },
2738 #endif
2739 { BER_BVNULL, 0 }
2740 };
2741
2742 int
lload_keepalive_parse(struct berval * val,void * bc,slap_cf_aux_table * tab0,const char * tabmsg,int unparse)2743 lload_keepalive_parse(
2744 struct berval *val,
2745 void *bc,
2746 slap_cf_aux_table *tab0,
2747 const char *tabmsg,
2748 int unparse )
2749 {
2750 if ( unparse ) {
2751 slap_keepalive *sk = (slap_keepalive *)bc;
2752 int rc = snprintf( val->bv_val, val->bv_len, "%d:%d:%d",
2753 sk->sk_idle, sk->sk_probes, sk->sk_interval );
2754 if ( rc < 0 ) {
2755 return -1;
2756 }
2757
2758 if ( (unsigned)rc >= val->bv_len ) {
2759 return -1;
2760 }
2761
2762 val->bv_len = rc;
2763
2764 } else {
2765 char *s = val->bv_val;
2766 char *next;
2767 slap_keepalive *sk = (slap_keepalive *)bc;
2768 slap_keepalive sk2;
2769
2770 if ( s[0] == ':' ) {
2771 sk2.sk_idle = 0;
2772 s++;
2773
2774 } else {
2775 sk2.sk_idle = strtol( s, &next, 10 );
2776 if ( next == s || next[0] != ':' ) {
2777 return -1;
2778 }
2779
2780 if ( sk2.sk_idle < 0 ) {
2781 return -1;
2782 }
2783
2784 s = ++next;
2785 }
2786
2787 if ( s[0] == ':' ) {
2788 sk2.sk_probes = 0;
2789 s++;
2790
2791 } else {
2792 sk2.sk_probes = strtol( s, &next, 10 );
2793 if ( next == s || next[0] != ':' ) {
2794 return -1;
2795 }
2796
2797 if ( sk2.sk_probes < 0 ) {
2798 return -1;
2799 }
2800
2801 s = ++next;
2802 }
2803
2804 if ( *s == '\0' ) {
2805 sk2.sk_interval = 0;
2806
2807 } else {
2808 sk2.sk_interval = strtol( s, &next, 10 );
2809 if ( next == s || next[0] != '\0' ) {
2810 return -1;
2811 }
2812
2813 if ( sk2.sk_interval < 0 ) {
2814 return -1;
2815 }
2816 }
2817
2818 *sk = sk2;
2819
2820 ber_memfree( val->bv_val );
2821 BER_BVZERO( val );
2822 }
2823
2824 return 0;
2825 }
2826
2827 static slap_cf_aux_table backendkey[] = {
2828 { BER_BVC("uri="), offsetof(LloadBackend, b_uri), 'b', 1, NULL },
2829
2830 { BER_BVC("numconns="), offsetof(LloadBackend, b_numconns), 'i', 0, NULL },
2831 { BER_BVC("bindconns="), offsetof(LloadBackend, b_numbindconns), 'i', 0, NULL },
2832 { BER_BVC("retry="), offsetof(LloadBackend, b_retry_timeout), 'i', 0, NULL },
2833
2834 { BER_BVC("max-pending-ops="), offsetof(LloadBackend, b_max_pending), 'i', 0, NULL },
2835 { BER_BVC("conn-max-pending="), offsetof(LloadBackend, b_max_conn_pending), 'i', 0, NULL },
2836 { BER_BVC("starttls="), offsetof(LloadBackend, b_tls_conf), 'i', 0, tlskey },
2837
2838 { BER_BVC("weight="), offsetof(LloadBackend, b_weight), 'i', 0, NULL },
2839
2840 { BER_BVNULL, 0, 0, 0, NULL }
2841 };
2842
2843 static slap_cf_aux_table bindkey[] = {
2844 { BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'i', 0, methkey },
2845 { BER_BVC("timeout="), offsetof(slap_bindconf, sb_timeout_api), 'i', 0, NULL },
2846 { BER_BVC("network-timeout="), offsetof(slap_bindconf, sb_timeout_net), 'i', 0, NULL },
2847 { BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, NULL },
2848 { BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL },
2849 { BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 'b', 0, NULL },
2850 { BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL },
2851 { BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 'b', 0, NULL },
2852 { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 1, NULL },
2853 { BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, NULL },
2854 { BER_BVC("keepalive="), offsetof(slap_bindconf, sb_keepalive), 'x', 0, (slap_verbmasks *)lload_keepalive_parse },
2855 { BER_BVC("tcp-user-timeout="), offsetof(slap_bindconf, sb_tcp_user_timeout), 'u', 0, NULL },
2856 #ifdef HAVE_TLS
2857 /* NOTE: replace "12" with the actual index
2858 * of the first TLS-related line */
2859 #define aux_TLS (bindkey+12) /* beginning of TLS keywords */
2860
2861 { BER_BVC("tls_cert="), offsetof(slap_bindconf, sb_tls_cert), 's', 1, NULL },
2862 { BER_BVC("tls_key="), offsetof(slap_bindconf, sb_tls_key), 's', 1, NULL },
2863 { BER_BVC("tls_cacert="), offsetof(slap_bindconf, sb_tls_cacert), 's', 1, NULL },
2864 { BER_BVC("tls_cacertdir="), offsetof(slap_bindconf, sb_tls_cacertdir), 's', 1, NULL },
2865 { BER_BVC("tls_reqcert="), offsetof(slap_bindconf, sb_tls_reqcert), 's', 0, NULL },
2866 { BER_BVC("tls_reqsan="), offsetof(slap_bindconf, sb_tls_reqsan), 's', 0, NULL },
2867 { BER_BVC("tls_cipher_suite="), offsetof(slap_bindconf, sb_tls_cipher_suite), 's', 0, NULL },
2868 { BER_BVC("tls_protocol_min="), offsetof(slap_bindconf, sb_tls_protocol_min), 's', 0, NULL },
2869 { BER_BVC("tls_ecname="), offsetof(slap_bindconf, sb_tls_ecname), 's', 0, NULL },
2870 #ifdef HAVE_OPENSSL
2871 { BER_BVC("tls_crlcheck="), offsetof(slap_bindconf, sb_tls_crlcheck), 's', 0, NULL },
2872 #endif
2873 #endif
2874 { BER_BVNULL, 0, 0, 0, NULL }
2875 };
2876
2877 /*
2878 * 's': char *
2879 * 'b': struct berval
2880 * 'i': int; if !NULL, compute using ((slap_verbmasks *)aux)
2881 * 'u': unsigned
2882 * 'I': long
2883 * 'U': unsigned long
2884 */
2885
2886 int
lload_cf_aux_table_parse(const char * word,void * dst,slap_cf_aux_table * tab0,LDAP_CONST char * tabmsg)2887 lload_cf_aux_table_parse(
2888 const char *word,
2889 void *dst,
2890 slap_cf_aux_table *tab0,
2891 LDAP_CONST char *tabmsg )
2892 {
2893 int rc = SLAP_CONF_UNKNOWN;
2894 slap_cf_aux_table *tab;
2895
2896 for ( tab = tab0; !BER_BVISNULL( &tab->key ); tab++ ) {
2897 if ( !strncasecmp( word, tab->key.bv_val, tab->key.bv_len ) ) {
2898 char **cptr;
2899 int *iptr, j;
2900 unsigned *uptr;
2901 long *lptr;
2902 unsigned long *ulptr;
2903 struct berval *bptr;
2904 const char *val = word + tab->key.bv_len;
2905
2906 switch ( tab->type ) {
2907 case 's':
2908 cptr = (char **)( (char *)dst + tab->off );
2909 *cptr = ch_strdup( val );
2910 rc = 0;
2911 break;
2912
2913 case 'b':
2914 bptr = (struct berval *)( (char *)dst + tab->off );
2915 assert( tab->aux == NULL );
2916 ber_str2bv( val, 0, 1, bptr );
2917 rc = 0;
2918 break;
2919
2920 case 'i':
2921 iptr = (int *)( (char *)dst + tab->off );
2922
2923 if ( tab->aux != NULL ) {
2924 slap_verbmasks *aux = (slap_verbmasks *)tab->aux;
2925
2926 assert( aux != NULL );
2927
2928 rc = 1;
2929 for ( j = 0; !BER_BVISNULL( &aux[j].word ); j++ ) {
2930 if ( !strcasecmp( val, aux[j].word.bv_val ) ) {
2931 *iptr = aux[j].mask;
2932 rc = 0;
2933 break;
2934 }
2935 }
2936
2937 } else {
2938 rc = lutil_atoix( iptr, val, 0 );
2939 }
2940 break;
2941
2942 case 'u':
2943 uptr = (unsigned *)( (char *)dst + tab->off );
2944
2945 rc = lutil_atoux( uptr, val, 0 );
2946 break;
2947
2948 case 'I':
2949 lptr = (long *)( (char *)dst + tab->off );
2950
2951 rc = lutil_atolx( lptr, val, 0 );
2952 break;
2953
2954 case 'U':
2955 ulptr = (unsigned long *)( (char *)dst + tab->off );
2956
2957 rc = lutil_atoulx( ulptr, val, 0 );
2958 break;
2959
2960 case 'x':
2961 if ( tab->aux != NULL ) {
2962 struct berval value;
2963 lload_cf_aux_table_parse_x *func =
2964 (lload_cf_aux_table_parse_x *)tab->aux;
2965
2966 ber_str2bv( val, 0, 1, &value );
2967
2968 rc = func( &value, (void *)( (char *)dst + tab->off ),
2969 tab, tabmsg, 0 );
2970
2971 } else {
2972 rc = 1;
2973 }
2974 break;
2975 }
2976
2977 if ( rc ) {
2978 Debug( LDAP_DEBUG_ANY, "invalid %s value %s\n", tabmsg, word );
2979 }
2980
2981 return rc;
2982 }
2983 }
2984
2985 return rc;
2986 }
2987
2988 int
lload_cf_aux_table_unparse(void * src,struct berval * bv,slap_cf_aux_table * tab0)2989 lload_cf_aux_table_unparse(
2990 void *src,
2991 struct berval *bv,
2992 slap_cf_aux_table *tab0 )
2993 {
2994 char buf[AC_LINE_MAX], *ptr;
2995 slap_cf_aux_table *tab;
2996 struct berval tmp;
2997
2998 ptr = buf;
2999 for ( tab = tab0; !BER_BVISNULL( &tab->key ); tab++ ) {
3000 char **cptr;
3001 int *iptr, i;
3002 unsigned *uptr;
3003 long *lptr;
3004 unsigned long *ulptr;
3005 struct berval *bptr;
3006
3007 cptr = (char **)( (char *)src + tab->off );
3008
3009 switch ( tab->type ) {
3010 case 'b':
3011 bptr = (struct berval *)( (char *)src + tab->off );
3012 cptr = &bptr->bv_val;
3013
3014 case 's':
3015 if ( *cptr ) {
3016 *ptr++ = ' ';
3017 ptr = lutil_strcopy( ptr, tab->key.bv_val );
3018 if ( tab->quote ) *ptr++ = '"';
3019 ptr = lutil_strcopy( ptr, *cptr );
3020 if ( tab->quote ) *ptr++ = '"';
3021 }
3022 break;
3023
3024 case 'i':
3025 iptr = (int *)( (char *)src + tab->off );
3026
3027 if ( tab->aux != NULL ) {
3028 slap_verbmasks *aux = (slap_verbmasks *)tab->aux;
3029
3030 for ( i = 0; !BER_BVISNULL( &aux[i].word ); i++ ) {
3031 if ( *iptr == aux[i].mask ) {
3032 *ptr++ = ' ';
3033 ptr = lutil_strcopy( ptr, tab->key.bv_val );
3034 ptr = lutil_strcopy( ptr, aux[i].word.bv_val );
3035 break;
3036 }
3037 }
3038
3039 } else {
3040 *ptr++ = ' ';
3041 ptr = lutil_strcopy( ptr, tab->key.bv_val );
3042 ptr += snprintf( ptr, sizeof(buf) - ( ptr - buf ), "%d",
3043 *iptr );
3044 }
3045 break;
3046
3047 case 'u':
3048 uptr = (unsigned *)( (char *)src + tab->off );
3049 *ptr++ = ' ';
3050 ptr = lutil_strcopy( ptr, tab->key.bv_val );
3051 ptr += snprintf( ptr, sizeof(buf) - ( ptr - buf ), "%u",
3052 *uptr );
3053 break;
3054
3055 case 'I':
3056 lptr = (long *)( (char *)src + tab->off );
3057 *ptr++ = ' ';
3058 ptr = lutil_strcopy( ptr, tab->key.bv_val );
3059 ptr += snprintf( ptr, sizeof(buf) - ( ptr - buf ), "%ld",
3060 *lptr );
3061 break;
3062
3063 case 'U':
3064 ulptr = (unsigned long *)( (char *)src + tab->off );
3065 *ptr++ = ' ';
3066 ptr = lutil_strcopy( ptr, tab->key.bv_val );
3067 ptr += snprintf( ptr, sizeof(buf) - ( ptr - buf ), "%lu",
3068 *ulptr );
3069 break;
3070
3071 case 'x': {
3072 char *saveptr = ptr;
3073 *ptr++ = ' ';
3074 ptr = lutil_strcopy( ptr, tab->key.bv_val );
3075 if ( tab->quote ) *ptr++ = '"';
3076 if ( tab->aux != NULL ) {
3077 struct berval value;
3078 lload_cf_aux_table_parse_x *func =
3079 (lload_cf_aux_table_parse_x *)tab->aux;
3080 int rc;
3081
3082 value.bv_val = ptr;
3083 value.bv_len = buf + sizeof(buf) - ptr;
3084
3085 rc = func( &value, (void *)( (char *)src + tab->off ), tab,
3086 "(unparse)", 1 );
3087 if ( rc == 0 ) {
3088 if ( value.bv_len ) {
3089 ptr += value.bv_len;
3090 } else {
3091 ptr = saveptr;
3092 break;
3093 }
3094 }
3095 }
3096 if ( tab->quote ) *ptr++ = '"';
3097 } break;
3098
3099 default:
3100 assert(0);
3101 }
3102 }
3103 tmp.bv_val = buf;
3104 tmp.bv_len = ptr - buf;
3105 ber_dupbv( bv, &tmp );
3106 return 0;
3107 }
3108
3109 int
lload_tls_get_config(LDAP * ld,int opt,char ** val)3110 lload_tls_get_config( LDAP *ld, int opt, char **val )
3111 {
3112 #ifdef HAVE_TLS
3113 slap_verbmasks *keys;
3114 int i, ival;
3115
3116 *val = NULL;
3117 switch ( opt ) {
3118 case LDAP_OPT_X_TLS_CRLCHECK:
3119 keys = crlkeys;
3120 break;
3121 case LDAP_OPT_X_TLS_REQUIRE_CERT:
3122 keys = vfykeys;
3123 break;
3124 case LDAP_OPT_X_TLS_PROTOCOL_MIN: {
3125 char buf[8];
3126 ldap_pvt_tls_get_option( ld, opt, &ival );
3127 snprintf( buf, sizeof(buf), "%d.%d",
3128 ( ival >> 8 ) & 0xff, ival & 0xff );
3129 *val = ch_strdup( buf );
3130 return 0;
3131 }
3132 default:
3133 return -1;
3134 }
3135 ldap_pvt_tls_get_option( ld, opt, &ival );
3136 for ( i = 0; !BER_BVISNULL( &keys[i].word ); i++ ) {
3137 if ( keys[i].mask == ival ) {
3138 *val = ch_strdup( keys[i].word.bv_val );
3139 return 0;
3140 }
3141 }
3142 #endif
3143 return -1;
3144 }
3145
3146 #ifdef HAVE_TLS
3147 static struct {
3148 const char *key;
3149 size_t offset;
3150 int opt;
3151 } bindtlsopts[] = {
3152 { "tls_cert", offsetof(slap_bindconf, sb_tls_cert), LDAP_OPT_X_TLS_CERTFILE },
3153 { "tls_key", offsetof(slap_bindconf, sb_tls_key), LDAP_OPT_X_TLS_KEYFILE },
3154 { "tls_cacert", offsetof(slap_bindconf, sb_tls_cacert), LDAP_OPT_X_TLS_CACERTFILE },
3155 { "tls_cacertdir", offsetof(slap_bindconf, sb_tls_cacertdir), LDAP_OPT_X_TLS_CACERTDIR },
3156 { "tls_cipher_suite", offsetof(slap_bindconf, sb_tls_cipher_suite), LDAP_OPT_X_TLS_CIPHER_SUITE },
3157 { "tls_ecname", offsetof(slap_bindconf, sb_tls_ecname), LDAP_OPT_X_TLS_ECNAME },
3158 { NULL, 0 }
3159 };
3160
3161 int
lload_bindconf_tls_set(slap_bindconf * bc,LDAP * ld)3162 lload_bindconf_tls_set( slap_bindconf *bc, LDAP *ld )
3163 {
3164 int i, rc, newctx = 0, res = 0;
3165 char *ptr = (char *)bc, **word;
3166
3167 if ( bc->sb_tls_do_init ) {
3168 for ( i = 0; bindtlsopts[i].opt; i++ ) {
3169 word = (char **)( ptr + bindtlsopts[i].offset );
3170 if ( *word ) {
3171 rc = ldap_set_option( ld, bindtlsopts[i].opt, *word );
3172 if ( rc ) {
3173 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: "
3174 "failed to set %s to %s\n",
3175 bindtlsopts[i].key, *word );
3176 res = -1;
3177 } else
3178 newctx = 1;
3179 }
3180 }
3181 if ( bc->sb_tls_reqcert ) {
3182 rc = ldap_pvt_tls_config(
3183 ld, LDAP_OPT_X_TLS_REQUIRE_CERT, bc->sb_tls_reqcert );
3184 if ( rc ) {
3185 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: "
3186 "failed to set tls_reqcert to %s\n",
3187 bc->sb_tls_reqcert );
3188 res = -1;
3189 } else {
3190 newctx = 1;
3191 /* retrieve the parsed setting for later use */
3192 ldap_get_option( ld, LDAP_OPT_X_TLS_REQUIRE_CERT,
3193 &bc->sb_tls_int_reqcert );
3194 }
3195 }
3196 if ( bc->sb_tls_reqsan ) {
3197 rc = ldap_pvt_tls_config(
3198 ld, LDAP_OPT_X_TLS_REQUIRE_SAN, bc->sb_tls_reqsan );
3199 if ( rc ) {
3200 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: "
3201 "failed to set tls_reqsan to %s\n",
3202 bc->sb_tls_reqsan );
3203 res = -1;
3204 } else {
3205 newctx = 1;
3206 /* retrieve the parsed setting for later use */
3207 ldap_get_option( ld, LDAP_OPT_X_TLS_REQUIRE_SAN,
3208 &bc->sb_tls_int_reqsan );
3209 }
3210 }
3211 if ( bc->sb_tls_protocol_min ) {
3212 rc = ldap_pvt_tls_config(
3213 ld, LDAP_OPT_X_TLS_PROTOCOL_MIN, bc->sb_tls_protocol_min );
3214 if ( rc ) {
3215 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: "
3216 "failed to set tls_protocol_min to %s\n",
3217 bc->sb_tls_protocol_min );
3218 res = -1;
3219 } else
3220 newctx = 1;
3221 }
3222 #ifdef HAVE_OPENSSL
3223 if ( bc->sb_tls_crlcheck ) {
3224 rc = ldap_pvt_tls_config(
3225 ld, LDAP_OPT_X_TLS_CRLCHECK, bc->sb_tls_crlcheck );
3226 if ( rc ) {
3227 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: "
3228 "failed to set tls_crlcheck to %s\n",
3229 bc->sb_tls_crlcheck );
3230 res = -1;
3231 } else
3232 newctx = 1;
3233 }
3234 #endif
3235 if ( !res ) bc->sb_tls_do_init = 0;
3236 }
3237
3238 if ( newctx ) {
3239 int opt = 0;
3240
3241 if ( bc->sb_tls_ctx ) {
3242 ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
3243 bc->sb_tls_ctx = NULL;
3244 }
3245 rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
3246 if ( rc )
3247 res = rc;
3248 else
3249 ldap_get_option( ld, LDAP_OPT_X_TLS_CTX, &bc->sb_tls_ctx );
3250 } else if ( bc->sb_tls_ctx ) {
3251 rc = ldap_set_option( ld, LDAP_OPT_X_TLS_CTX, bc->sb_tls_ctx );
3252 if ( rc == LDAP_SUCCESS ) {
3253 /* these options aren't actually inside the ctx, so have to be set again */
3254 ldap_set_option(
3255 ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &bc->sb_tls_int_reqcert );
3256 ldap_set_option(
3257 ld, LDAP_OPT_X_TLS_REQUIRE_SAN, &bc->sb_tls_int_reqsan );
3258 } else
3259 res = rc;
3260 }
3261
3262 return res;
3263 }
3264 #endif
3265
3266 int
lload_bindconf_tls_parse(const char * word,slap_bindconf * bc)3267 lload_bindconf_tls_parse( const char *word, slap_bindconf *bc )
3268 {
3269 #ifdef HAVE_TLS
3270 if ( lload_cf_aux_table_parse( word, bc, aux_TLS, "tls config" ) == 0 ) {
3271 bc->sb_tls_do_init = 1;
3272 return 0;
3273 }
3274 #endif
3275 return -1;
3276 }
3277
3278 int
lload_backend_parse(const char * word,LloadBackend * b)3279 lload_backend_parse( const char *word, LloadBackend *b )
3280 {
3281 return lload_cf_aux_table_parse( word, b, backendkey, "backend config" );
3282 }
3283
3284 int
lload_bindconf_parse(const char * word,slap_bindconf * bc)3285 lload_bindconf_parse( const char *word, slap_bindconf *bc )
3286 {
3287 #ifdef HAVE_TLS
3288 /* Detect TLS config changes explicitly */
3289 if ( lload_bindconf_tls_parse( word, bc ) == 0 ) {
3290 return 0;
3291 }
3292 #endif
3293 return lload_cf_aux_table_parse( word, bc, bindkey, "bind config" );
3294 }
3295
3296 int
lload_bindconf_unparse(slap_bindconf * bc,struct berval * bv)3297 lload_bindconf_unparse( slap_bindconf *bc, struct berval *bv )
3298 {
3299 return lload_cf_aux_table_unparse( bc, bv, bindkey );
3300 }
3301
3302 void
lload_bindconf_free(slap_bindconf * bc)3303 lload_bindconf_free( slap_bindconf *bc )
3304 {
3305 if ( !BER_BVISNULL( &bc->sb_uri ) ) {
3306 ch_free( bc->sb_uri.bv_val );
3307 BER_BVZERO( &bc->sb_uri );
3308 }
3309 if ( !BER_BVISNULL( &bc->sb_binddn ) ) {
3310 ch_free( bc->sb_binddn.bv_val );
3311 BER_BVZERO( &bc->sb_binddn );
3312 }
3313 if ( !BER_BVISNULL( &bc->sb_cred ) ) {
3314 ch_free( bc->sb_cred.bv_val );
3315 BER_BVZERO( &bc->sb_cred );
3316 }
3317 if ( !BER_BVISNULL( &bc->sb_saslmech ) ) {
3318 ch_free( bc->sb_saslmech.bv_val );
3319 BER_BVZERO( &bc->sb_saslmech );
3320 }
3321 if ( bc->sb_secprops ) {
3322 ch_free( bc->sb_secprops );
3323 bc->sb_secprops = NULL;
3324 }
3325 if ( !BER_BVISNULL( &bc->sb_realm ) ) {
3326 ch_free( bc->sb_realm.bv_val );
3327 BER_BVZERO( &bc->sb_realm );
3328 }
3329 if ( !BER_BVISNULL( &bc->sb_authcId ) ) {
3330 ch_free( bc->sb_authcId.bv_val );
3331 BER_BVZERO( &bc->sb_authcId );
3332 }
3333 if ( !BER_BVISNULL( &bc->sb_authzId ) ) {
3334 ch_free( bc->sb_authzId.bv_val );
3335 BER_BVZERO( &bc->sb_authzId );
3336 }
3337 #ifdef HAVE_TLS
3338 if ( bc->sb_tls_cert ) {
3339 ch_free( bc->sb_tls_cert );
3340 bc->sb_tls_cert = NULL;
3341 }
3342 if ( bc->sb_tls_key ) {
3343 ch_free( bc->sb_tls_key );
3344 bc->sb_tls_key = NULL;
3345 }
3346 if ( bc->sb_tls_cacert ) {
3347 ch_free( bc->sb_tls_cacert );
3348 bc->sb_tls_cacert = NULL;
3349 }
3350 if ( bc->sb_tls_cacertdir ) {
3351 ch_free( bc->sb_tls_cacertdir );
3352 bc->sb_tls_cacertdir = NULL;
3353 }
3354 if ( bc->sb_tls_reqcert ) {
3355 ch_free( bc->sb_tls_reqcert );
3356 bc->sb_tls_reqcert = NULL;
3357 }
3358 if ( bc->sb_tls_cipher_suite ) {
3359 ch_free( bc->sb_tls_cipher_suite );
3360 bc->sb_tls_cipher_suite = NULL;
3361 }
3362 if ( bc->sb_tls_protocol_min ) {
3363 ch_free( bc->sb_tls_protocol_min );
3364 bc->sb_tls_protocol_min = NULL;
3365 }
3366 #ifdef HAVE_OPENSSL_CRL
3367 if ( bc->sb_tls_crlcheck ) {
3368 ch_free( bc->sb_tls_crlcheck );
3369 bc->sb_tls_crlcheck = NULL;
3370 }
3371 #endif
3372 if ( bc->sb_tls_ctx ) {
3373 ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
3374 bc->sb_tls_ctx = NULL;
3375 }
3376 #endif
3377 }
3378
3379 void
lload_bindconf_tls_defaults(slap_bindconf * bc)3380 lload_bindconf_tls_defaults( slap_bindconf *bc )
3381 {
3382 #ifdef HAVE_TLS
3383 if ( bc->sb_tls_do_init ) {
3384 if ( !bc->sb_tls_cacert )
3385 ldap_pvt_tls_get_option( lload_tls_ld, LDAP_OPT_X_TLS_CACERTFILE,
3386 &bc->sb_tls_cacert );
3387 if ( !bc->sb_tls_cacertdir )
3388 ldap_pvt_tls_get_option( lload_tls_ld, LDAP_OPT_X_TLS_CACERTDIR,
3389 &bc->sb_tls_cacertdir );
3390 if ( !bc->sb_tls_cert )
3391 ldap_pvt_tls_get_option(
3392 lload_tls_ld, LDAP_OPT_X_TLS_CERTFILE, &bc->sb_tls_cert );
3393 if ( !bc->sb_tls_key )
3394 ldap_pvt_tls_get_option(
3395 lload_tls_ld, LDAP_OPT_X_TLS_KEYFILE, &bc->sb_tls_key );
3396 if ( !bc->sb_tls_cipher_suite )
3397 ldap_pvt_tls_get_option( lload_tls_ld, LDAP_OPT_X_TLS_CIPHER_SUITE,
3398 &bc->sb_tls_cipher_suite );
3399 if ( !bc->sb_tls_reqcert ) bc->sb_tls_reqcert = ch_strdup( "demand" );
3400 #ifdef HAVE_OPENSSL_CRL
3401 if ( !bc->sb_tls_crlcheck )
3402 lload_tls_get_config( lload_tls_ld, LDAP_OPT_X_TLS_CRLCHECK,
3403 &bc->sb_tls_crlcheck );
3404 #endif
3405 }
3406 #endif
3407 }
3408
3409 /* -------------------------------------- */
3410
3411 static char *
strtok_quote(char * line,char * sep,char ** quote_ptr,int * iqp)3412 strtok_quote( char *line, char *sep, char **quote_ptr, int *iqp )
3413 {
3414 int inquote;
3415 char *tmp;
3416 static char *next;
3417
3418 *quote_ptr = NULL;
3419 if ( line != NULL ) {
3420 next = line;
3421 }
3422 while ( *next && strchr( sep, *next ) ) {
3423 next++;
3424 }
3425
3426 if ( *next == '\0' ) {
3427 next = NULL;
3428 return NULL;
3429 }
3430 tmp = next;
3431
3432 for ( inquote = 0; *next; ) {
3433 switch ( *next ) {
3434 case '"':
3435 if ( inquote ) {
3436 inquote = 0;
3437 } else {
3438 inquote = 1;
3439 }
3440 AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
3441 break;
3442
3443 case '\\':
3444 if ( next[1] )
3445 AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
3446 next++; /* dont parse the escaped character */
3447 break;
3448
3449 default:
3450 if ( !inquote ) {
3451 if ( strchr( sep, *next ) != NULL ) {
3452 *quote_ptr = next;
3453 *next++ = '\0';
3454 return tmp;
3455 }
3456 }
3457 next++;
3458 break;
3459 }
3460 }
3461 *iqp = inquote;
3462
3463 return tmp;
3464 }
3465
3466 static char buf[AC_LINE_MAX];
3467 static char *line;
3468 static size_t lmax, lcur;
3469
3470 #define CATLINE( buf ) \
3471 do { \
3472 size_t len = strlen( buf ); \
3473 while ( lcur + len + 1 > lmax ) { \
3474 lmax += AC_LINE_MAX; \
3475 line = (char *)ch_realloc( line, lmax ); \
3476 } \
3477 strcpy( line + lcur, buf ); \
3478 lcur += len; \
3479 } while (0)
3480
3481 static void
fp_getline_init(ConfigArgs * c)3482 fp_getline_init( ConfigArgs *c )
3483 {
3484 c->lineno = -1;
3485 buf[0] = '\0';
3486 }
3487
3488 static int
fp_getline(FILE * fp,ConfigArgs * c)3489 fp_getline( FILE *fp, ConfigArgs *c )
3490 {
3491 char *p;
3492
3493 lcur = 0;
3494 CATLINE( buf );
3495 c->lineno++;
3496
3497 /* avoid stack of bufs */
3498 if ( strncasecmp( line, "include", STRLENOF("include") ) == 0 ) {
3499 buf[0] = '\0';
3500 c->line = line;
3501 return 1;
3502 }
3503
3504 while ( fgets( buf, sizeof(buf), fp ) ) {
3505 p = strchr( buf, '\n' );
3506 if ( p ) {
3507 if ( p > buf && p[-1] == '\r' ) {
3508 --p;
3509 }
3510 *p = '\0';
3511 }
3512 /* XXX ugly */
3513 c->line = line;
3514 if ( line[0] && ( p = line + strlen( line ) - 1 )[0] == '\\' &&
3515 p[-1] != '\\' ) {
3516 p[0] = '\0';
3517 lcur--;
3518
3519 } else {
3520 if ( !isspace( (unsigned char)buf[0] ) ) {
3521 return 1;
3522 }
3523 buf[0] = ' ';
3524 }
3525 CATLINE( buf );
3526 c->lineno++;
3527 }
3528
3529 buf[0] = '\0';
3530 c->line = line;
3531 return ( line[0] ? 1 : 0 );
3532 }
3533
3534 int
lload_config_fp_parse_line(ConfigArgs * c)3535 lload_config_fp_parse_line( ConfigArgs *c )
3536 {
3537 char *token;
3538 static char *const hide[] = { "bindconf", NULL };
3539 static char *const raw[] = { NULL };
3540 char *quote_ptr;
3541 int i = (int)( sizeof(hide) / sizeof(hide[0]) ) - 1;
3542 int inquote = 0;
3543
3544 c->tline = ch_strdup( c->line );
3545 c->linelen = strlen( c->line );
3546 token = strtok_quote( c->tline, " \t", "e_ptr, &inquote );
3547
3548 if ( token )
3549 for ( i = 0; hide[i]; i++ )
3550 if ( !strcasecmp( token, hide[i] ) ) break;
3551 if ( quote_ptr ) *quote_ptr = ' ';
3552 Debug( LDAP_DEBUG_CONFIG, "%s (%s%s)\n",
3553 c->log, hide[i] ? hide[i] : c->line, hide[i] ? " ***" : "" );
3554 if ( quote_ptr ) *quote_ptr = '\0';
3555
3556 for ( ;; token = strtok_quote( NULL, " \t", "e_ptr, &inquote ) ) {
3557 if ( c->argc >= c->argv_size ) {
3558 char **tmp;
3559 tmp = ch_realloc( c->argv,
3560 ( c->argv_size + ARGS_STEP ) * sizeof(*c->argv) );
3561 if ( !tmp ) {
3562 Debug( LDAP_DEBUG_ANY, "%s: out of memory\n", c->log );
3563 return -1;
3564 }
3565 c->argv = tmp;
3566 c->argv_size += ARGS_STEP;
3567 }
3568 if ( token == NULL ) break;
3569 c->argv[c->argc++] = token;
3570 }
3571 c->argv[c->argc] = NULL;
3572 if ( inquote ) {
3573 /* these directives parse c->line independently of argv tokenizing */
3574 for ( i = 0; raw[i]; i++ )
3575 if ( !strcasecmp( c->argv[0], raw[i] ) ) return 0;
3576
3577 Debug( LDAP_DEBUG_ANY, "%s: unterminated quoted string \"%s\"\n",
3578 c->log, c->argv[c->argc - 1] );
3579 return -1;
3580 }
3581 return 0;
3582 }
3583
3584 void
lload_config_destroy(void)3585 lload_config_destroy( void )
3586 {
3587 free( line );
3588 if ( slapd_args_file ) free( slapd_args_file );
3589 if ( slapd_pid_file ) free( slapd_pid_file );
3590 slap_loglevel_destroy();
3591 }
3592
3593 /* See if the given URL (in plain and parsed form) matches
3594 * any of the server's listener addresses. Return matching
3595 * LloadListener or NULL for no match.
3596 */
3597 LloadListener *
lload_config_check_my_url(const char * url,LDAPURLDesc * lud)3598 lload_config_check_my_url( const char *url, LDAPURLDesc *lud )
3599 {
3600 LloadListener **l = lloadd_get_listeners();
3601 int i, isMe;
3602
3603 /* Try a straight compare with LloadListener strings */
3604 for ( i = 0; l && l[i]; i++ ) {
3605 if ( !strcasecmp( url, l[i]->sl_url.bv_val ) ) {
3606 return l[i];
3607 }
3608 }
3609
3610 isMe = 0;
3611 /* If hostname is empty, or is localhost, or matches
3612 * our hostname, this url refers to this host.
3613 * Compare it against listeners and ports.
3614 */
3615 if ( !lud->lud_host || !lud->lud_host[0] ||
3616 !strncasecmp(
3617 "localhost", lud->lud_host, STRLENOF("localhost") ) ||
3618 !strcasecmp( global_host, lud->lud_host ) ) {
3619 for ( i = 0; l && l[i]; i++ ) {
3620 LDAPURLDesc *lu2;
3621 ldap_url_parse_ext(
3622 l[i]->sl_url.bv_val, &lu2, LDAP_PVT_URL_PARSE_DEF_PORT );
3623 do {
3624 if ( strcasecmp( lud->lud_scheme, lu2->lud_scheme ) ) break;
3625 if ( lud->lud_port != lu2->lud_port ) break;
3626 /* Listener on ANY address */
3627 if ( !lu2->lud_host || !lu2->lud_host[0] ) {
3628 isMe = 1;
3629 break;
3630 }
3631 /* URL on ANY address */
3632 if ( !lud->lud_host || !lud->lud_host[0] ) {
3633 isMe = 1;
3634 break;
3635 }
3636 /* Listener has specific host, must
3637 * match it
3638 */
3639 if ( !strcasecmp( lud->lud_host, lu2->lud_host ) ) {
3640 isMe = 1;
3641 break;
3642 }
3643 } while (0);
3644 ldap_free_urldesc( lu2 );
3645 if ( isMe ) {
3646 return l[i];
3647 }
3648 }
3649 }
3650 return NULL;
3651 }
3652
3653 #ifdef BALANCER_MODULE
3654 static int
backend_cf_gen(ConfigArgs * c)3655 backend_cf_gen( ConfigArgs *c )
3656 {
3657 LloadBackend *b = c->ca_private;
3658 enum lcf_backend flag = 0;
3659 int rc = LDAP_SUCCESS;
3660
3661 assert( b != NULL );
3662
3663 if ( c->op == SLAP_CONFIG_EMIT ) {
3664 switch ( c->type ) {
3665 case CFG_URI:
3666 c->value_bv = b->b_uri;
3667 break;
3668 case CFG_NUMCONNS:
3669 c->value_uint = b->b_numconns;
3670 break;
3671 case CFG_BINDCONNS:
3672 c->value_uint = b->b_numbindconns;
3673 break;
3674 case CFG_RETRY:
3675 c->value_uint = b->b_retry_timeout;
3676 break;
3677 case CFG_MAX_PENDING_CONNS:
3678 c->value_uint = b->b_max_conn_pending;
3679 break;
3680 case CFG_MAX_PENDING_OPS:
3681 c->value_uint = b->b_max_pending;
3682 break;
3683 case CFG_STARTTLS:
3684 enum_to_verb( tlskey, b->b_tls_conf, &c->value_bv );
3685 break;
3686 case CFG_WEIGHT:
3687 c->value_uint = b->b_weight;
3688 break;
3689 default:
3690 rc = 1;
3691 break;
3692 }
3693
3694 return rc;
3695 } else if ( c->op == LDAP_MOD_DELETE ) {
3696 /* We only need to worry about deletions to multi-value or MAY
3697 * attributes */
3698 switch ( c->type ) {
3699 case CFG_STARTTLS:
3700 b->b_tls_conf = LLOAD_CLEARTEXT;
3701 break;
3702 default:
3703 break;
3704 }
3705 return rc;
3706 }
3707
3708 switch ( c->type ) {
3709 case CFG_URI:
3710 rc = backend_config_url( b, &c->value_bv );
3711 if ( rc ) {
3712 backend_config_url( b, &b->b_uri );
3713 goto fail;
3714 }
3715 if ( !BER_BVISNULL( &b->b_uri ) ) {
3716 ch_free( b->b_uri.bv_val );
3717 }
3718 b->b_uri = c->value_bv;
3719 flag = LLOAD_BACKEND_MOD_OTHER;
3720 break;
3721 case CFG_NUMCONNS:
3722 if ( !c->value_uint ) {
3723 snprintf( c->cr_msg, sizeof(c->cr_msg),
3724 "invalid connection pool configuration" );
3725 goto fail;
3726 }
3727 b->b_numconns = c->value_uint;
3728 flag = LLOAD_BACKEND_MOD_CONNS;
3729 break;
3730 case CFG_BINDCONNS:
3731 if ( !c->value_uint ) {
3732 snprintf( c->cr_msg, sizeof(c->cr_msg),
3733 "invalid connection pool configuration" );
3734 goto fail;
3735 }
3736 b->b_numbindconns = c->value_uint;
3737 flag = LLOAD_BACKEND_MOD_CONNS;
3738 break;
3739 case CFG_RETRY:
3740 b->b_retry_timeout = c->value_uint;
3741 break;
3742 case CFG_MAX_PENDING_CONNS:
3743 b->b_max_conn_pending = c->value_uint;
3744 break;
3745 case CFG_MAX_PENDING_OPS:
3746 b->b_max_pending = c->value_uint;
3747 break;
3748 case CFG_STARTTLS: {
3749 int i = bverb_to_mask( &c->value_bv, tlskey );
3750 if ( BER_BVISNULL( &tlskey[i].word ) ) {
3751 snprintf( c->cr_msg, sizeof(c->cr_msg),
3752 "invalid starttls configuration" );
3753 goto fail;
3754 }
3755 #ifndef HAVE_TLS
3756 if ( tlskey[i].mask == LLOAD_STARTTLS_OPTIONAL ) {
3757 Debug( LDAP_DEBUG_ANY, "%s: "
3758 "lloadd compiled without TLS but starttls specified, "
3759 "it will be ignored\n",
3760 c->log );
3761 } else if ( tlskey[i].mask != LLOAD_CLEARTEXT ) {
3762 snprintf( c->cr_msg, sizeof(c->cr_msg),
3763 "invalid starttls configuration when compiled without "
3764 "TLS support" );
3765 goto fail;
3766 }
3767 #endif /* ! HAVE_TLS */
3768 b->b_tls_conf = tlskey[i].mask;
3769 } break;
3770 case CFG_WEIGHT:
3771 b->b_weight = c->value_uint;
3772 break;
3773 default:
3774 rc = 1;
3775 break;
3776 }
3777
3778 /* do not set this if it has already been set by another callback, e.g.
3779 * lload_backend_ldadd */
3780 if ( lload_change.type == LLOAD_CHANGE_UNDEFINED ) {
3781 lload_change.type = LLOAD_CHANGE_MODIFY;
3782 }
3783 lload_change.object = LLOAD_BACKEND;
3784 lload_change.target = b;
3785 lload_change.flags.backend |= flag;
3786
3787 config_push_cleanup( c, lload_backend_finish );
3788 return rc;
3789
3790 fail:
3791 if ( lload_change.type == LLOAD_CHANGE_ADD ) {
3792 /* Abort the ADD */
3793 lload_change.type = LLOAD_CHANGE_DEL;
3794 }
3795
3796 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
3797 return 1;
3798 }
3799
3800 int
lload_back_init_cf(BackendInfo * bi)3801 lload_back_init_cf( BackendInfo *bi )
3802 {
3803 /* Make sure we don't exceed the bits reserved for userland */
3804 config_check_userland( CFG_LAST );
3805
3806 bi->bi_cf_ocs = lloadocs;
3807
3808 return config_register_schema( config_back_cf_table, lloadocs );
3809 }
3810
3811 static int
lload_tier_ldadd(CfEntryInfo * p,Entry * e,ConfigArgs * ca)3812 lload_tier_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
3813 {
3814 LloadTier *tier;
3815 Attribute *a;
3816 AttributeDescription *ad = NULL;
3817 struct lload_tier_type *tier_impl;
3818 struct berval bv, type, rdn;
3819 const char *text;
3820 char *name;
3821
3822 Debug( LDAP_DEBUG_TRACE, "lload_tier_ldadd: "
3823 "a new tier is being added\n" );
3824
3825 if ( p->ce_type != Cft_Backend || !p->ce_bi ||
3826 p->ce_bi->bi_cf_ocs != lloadocs )
3827 return LDAP_CONSTRAINT_VIOLATION;
3828
3829 dnRdn( &e->e_name, &rdn );
3830 type.bv_len = strchr( rdn.bv_val, '=' ) - rdn.bv_val;
3831 type.bv_val = rdn.bv_val;
3832
3833 /* Find attr */
3834 slap_bv2ad( &type, &ad, &text );
3835 if ( ad != slap_schema.si_ad_cn ) return LDAP_NAMING_VIOLATION;
3836
3837 a = attr_find( e->e_attrs, ad );
3838 if ( !a || a->a_numvals != 1 ) return LDAP_NAMING_VIOLATION;
3839 bv = a->a_vals[0];
3840
3841 if ( bv.bv_val[0] == '{' && ( name = strchr( bv.bv_val, '}' ) ) ) {
3842 name++;
3843 bv.bv_len -= name - bv.bv_val;
3844 bv.bv_val = name;
3845 }
3846
3847 ad = NULL;
3848 slap_str2ad( "olcBkLloadTierType", &ad, &text );
3849 assert( ad != NULL );
3850
3851 a = attr_find( e->e_attrs, ad );
3852 if ( !a || a->a_numvals != 1 ) return LDAP_OBJECT_CLASS_VIOLATION;
3853
3854 tier_impl = lload_tier_find( a->a_vals[0].bv_val );
3855 if ( !tier_impl ) {
3856 Debug( LDAP_DEBUG_ANY, "lload_tier_ldadd: "
3857 "tier type %s not recongnised\n",
3858 bv.bv_val );
3859 return LDAP_OTHER;
3860 }
3861
3862 tier = tier_impl->tier_init();
3863 if ( !tier ) {
3864 return LDAP_OTHER;
3865 }
3866
3867 ber_dupbv( &tier->t_name, &bv );
3868
3869 ca->bi = p->ce_bi;
3870 ca->ca_private = tier;
3871
3872 /* ca cleanups are only run in the case of online config but we use it to
3873 * save the new config when done with the entry */
3874 ca->lineno = 0;
3875
3876 lload_change.type = LLOAD_CHANGE_ADD;
3877 lload_change.object = LLOAD_TIER;
3878 lload_change.target = tier;
3879
3880 return LDAP_SUCCESS;
3881 }
3882
3883 static int
lload_backend_ldadd(CfEntryInfo * p,Entry * e,ConfigArgs * ca)3884 lload_backend_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca )
3885 {
3886 LloadTier *tier = p->ce_private;
3887 LloadBackend *b;
3888 Attribute *a;
3889 AttributeDescription *ad = NULL;
3890 struct berval bv, type, rdn;
3891 const char *text;
3892 char *name;
3893
3894 Debug( LDAP_DEBUG_TRACE, "lload_backend_ldadd: "
3895 "a new backend-server is being added\n" );
3896
3897 if ( p->ce_type != Cft_Misc || !p->ce_bi ||
3898 p->ce_bi->bi_cf_ocs != lloadocs )
3899 return LDAP_CONSTRAINT_VIOLATION;
3900
3901 dnRdn( &e->e_name, &rdn );
3902 type.bv_len = strchr( rdn.bv_val, '=' ) - rdn.bv_val;
3903 type.bv_val = rdn.bv_val;
3904
3905 /* Find attr */
3906 slap_bv2ad( &type, &ad, &text );
3907 if ( ad != slap_schema.si_ad_cn ) return LDAP_NAMING_VIOLATION;
3908
3909 a = attr_find( e->e_attrs, ad );
3910 if ( !a || a->a_numvals != 1 ) return LDAP_NAMING_VIOLATION;
3911 bv = a->a_vals[0];
3912
3913 if ( bv.bv_val[0] == '{' && ( name = strchr( bv.bv_val, '}' ) ) ) {
3914 name++;
3915 bv.bv_len -= name - bv.bv_val;
3916 bv.bv_val = name;
3917 }
3918
3919 b = lload_backend_new();
3920 ber_dupbv( &b->b_name, &bv );
3921 b->b_tier = tier;
3922
3923 ca->bi = p->ce_bi;
3924 ca->ca_private = b;
3925 config_push_cleanup( ca, lload_backend_finish );
3926
3927 /* ca cleanups are only run in the case of online config but we use it to
3928 * save the new config when done with the entry */
3929 ca->lineno = 0;
3930
3931 lload_change.type = LLOAD_CHANGE_ADD;
3932 lload_change.object = LLOAD_BACKEND;
3933 lload_change.target = b;
3934
3935 return LDAP_SUCCESS;
3936 }
3937
3938 #ifdef SLAP_CONFIG_DELETE
3939 static int
lload_backend_lddel(CfEntryInfo * ce,Operation * op)3940 lload_backend_lddel( CfEntryInfo *ce, Operation *op )
3941 {
3942 LloadBackend *b = ce->ce_private;
3943
3944 lload_change.type = LLOAD_CHANGE_DEL;
3945 lload_change.object = LLOAD_BACKEND;
3946 lload_change.target = b;
3947
3948 return LDAP_SUCCESS;
3949 }
3950
3951 static int
lload_tier_lddel(CfEntryInfo * ce,Operation * op)3952 lload_tier_lddel( CfEntryInfo *ce, Operation *op )
3953 {
3954 LloadTier *tier = ce->ce_private;
3955
3956 lload_change.type = LLOAD_CHANGE_DEL;
3957 lload_change.object = LLOAD_TIER;
3958 lload_change.target = tier;
3959
3960 return LDAP_SUCCESS;
3961 }
3962 #endif /* SLAP_CONFIG_DELETE */
3963
3964 static int
lload_cfadd(Operation * op,SlapReply * rs,Entry * p,ConfigArgs * c)3965 lload_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *c )
3966 {
3967 struct berval bv;
3968 LloadTier *tier;
3969 int i = 0;
3970
3971 bv.bv_val = c->cr_msg;
3972 LDAP_STAILQ_FOREACH ( tier, &tiers, t_next ) {
3973 LloadBackend *b;
3974 ConfigOCs *coc;
3975 Entry *e;
3976 int j = 0;
3977
3978 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg),
3979 "cn=" SLAP_X_ORDERED_FMT "%s", i, tier->t_name.bv_val );
3980
3981 c->ca_private = tier;
3982 c->valx = i;
3983
3984 for ( coc = lloadocs; coc->co_type; coc++ ) {
3985 if ( !ber_bvcmp( coc->co_name, &tier->t_type.tier_oc ) ) {
3986 break;
3987 }
3988 }
3989 assert( coc->co_type );
3990
3991 e = config_build_entry( op, rs, p->e_private, c, &bv, coc, NULL );
3992 if ( !e ) {
3993 return 1;
3994 }
3995
3996 LDAP_CIRCLEQ_FOREACH ( b, &tier->t_backends, b_next ) {
3997 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg),
3998 "cn=" SLAP_X_ORDERED_FMT "%s", j, b->b_name.bv_val );
3999
4000 for ( coc = lloadocs; coc->co_type; coc++ ) {
4001 if ( !ber_bvcmp(
4002 coc->co_name, &tier->t_type.tier_backend_oc ) ) {
4003 break;
4004 }
4005 }
4006 assert( coc->co_type );
4007
4008 c->ca_private = b;
4009 c->valx = j;
4010
4011 if ( !config_build_entry(
4012 op, rs, e->e_private, c, &bv, coc, NULL ) ) {
4013 return 1;
4014 }
4015
4016 j++;
4017 }
4018
4019 i++;
4020 }
4021 return LDAP_SUCCESS;
4022 }
4023 #endif /* BALANCER_MODULE */
4024