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