xref: /netbsd-src/external/bsd/openldap/dist/servers/lloadd/config.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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", &quote_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", &quote_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