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