1 /*
2    Unix SMB/CIFS implementation.
3    Parameter loading functions
4    Copyright (C) Karl Auer 1993-1998
5 
6    Largely re-written by Andrew Tridgell, September 1994
7 
8    Copyright (C) Simo Sorce 2001
9    Copyright (C) Alexander Bokovoy 2002
10    Copyright (C) Stefan (metze) Metzmacher 2002
11    Copyright (C) Jim McDonough (jmcd@us.ibm.com)  2003.
12    Copyright (C) James Myers 2003 <myersjj@samba.org>
13    Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
14    Copyright (C) Andrew Bartlett 2011-2012
15 
16    This program is free software; you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation; either version 3 of the License, or
19    (at your option) any later version.
20 
21    This program is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25 
26    You should have received a copy of the GNU General Public License
27    along with this program.  If not, see <http://www.gnu.org/licenses/>.
28 */
29 
30 /*
31  *  Load parameters.
32  *
33  *  This module provides suitable callback functions for the params
34  *  module. It builds the internal table of service details which is
35  *  then used by the rest of the server.
36  *
37  * To add a parameter:
38  *
39  * 1) add it to the global or service structure definition
40  * 2) add it to the parm_table
41  * 3) add it to the list of available functions (eg: using FN_GLOBAL_STRING())
42  * 4) If it's a global then initialise it in init_globals. If a local
43  *    (ie. service) parameter then initialise it in the sDefault structure
44  *
45  *
46  * Notes:
47  *   The configuration file is processed sequentially for speed. It is NOT
48  *   accessed randomly as happens in 'real' Windows. For this reason, there
49  *   is a fair bit of sequence-dependent code here - ie., code which assumes
50  *   that certain things happen before others. In particular, the code which
51  *   happens at the boundary between sections is delicately poised, so be
52  *   careful!
53  *
54  */
55 
56 #include "includes.h"
57 #include "version.h"
58 #include "dynconfig/dynconfig.h"
59 #include "system/time.h"
60 #include "system/locale.h"
61 #include "system/network.h" /* needed for TCP_NODELAY */
62 #include "../lib/util/dlinklist.h"
63 #include "lib/param/param.h"
64 #define LOADPARM_SUBSTITUTION_INTERNALS 1
65 #include "lib/param/loadparm.h"
66 #include "auth/gensec/gensec.h"
67 #include "lib/param/s3_param.h"
68 #include "lib/util/bitmap.h"
69 #include "libcli/smb/smb_constants.h"
70 #include "tdb.h"
71 #include "librpc/gen_ndr/nbt.h"
72 #include "libds/common/roles.h"
73 #include "lib/util/samba_util.h"
74 #include "libcli/auth/ntlm_check.h"
75 
76 #ifdef HAVE_HTTPCONNECTENCRYPT
77 #include <cups/http.h>
78 #endif
79 
80 #define standard_sub_basic talloc_strdup
81 
82 #include "lib/param/param_global.h"
83 
lpcfg_default_service(struct loadparm_context * lp_ctx)84 struct loadparm_service *lpcfg_default_service(struct loadparm_context *lp_ctx)
85 {
86 	return lp_ctx->sDefault;
87 }
88 
lpcfg_rpc_low_port(struct loadparm_context * lp_ctx)89 int lpcfg_rpc_low_port(struct loadparm_context *lp_ctx)
90 {
91 	return lp_ctx->globals->rpc_low_port;
92 }
93 
lpcfg_rpc_high_port(struct loadparm_context * lp_ctx)94 int lpcfg_rpc_high_port(struct loadparm_context *lp_ctx)
95 {
96 	return lp_ctx->globals->rpc_high_port;
97 }
98 
99 /**
100  * Convenience routine to grab string parameters into temporary memory
101  * and run standard_sub_basic on them.
102  *
103  * The buffers can be written to by
104  * callers without affecting the source string.
105  */
106 
lpcfg_string(const char * s)107 static const char *lpcfg_string(const char *s)
108 {
109 #if 0  /* until REWRITE done to make thread-safe */
110 	size_t len = s ? strlen(s) : 0;
111 	char *ret;
112 #endif
113 
114 	/* The follow debug is useful for tracking down memory problems
115 	   especially if you have an inner loop that is calling a lp_*()
116 	   function that returns a string.  Perhaps this debug should be
117 	   present all the time? */
118 
119 #if 0
120 	DEBUG(10, ("lpcfg_string(%s)\n", s));
121 #endif
122 
123 #if 0  /* until REWRITE done to make thread-safe */
124 	if (!lp_talloc)
125 		lp_talloc = talloc_init("lp_talloc");
126 
127 	ret = talloc_array(lp_talloc, char, len + 100);	/* leave room for substitution */
128 
129 	if (!ret)
130 		return NULL;
131 
132 	if (!s)
133 		*ret = 0;
134 	else
135 		strlcpy(ret, s, len);
136 
137 	if (trim_string(ret, "\"", "\"")) {
138 		if (strchr(ret,'"') != NULL)
139 			strlcpy(ret, s, len);
140 	}
141 
142 	standard_sub_basic(ret,len+100);
143 	return (ret);
144 #endif
145 	return s;
146 }
147 
148 /*
149    In this section all the functions that are used to access the
150    parameters from the rest of the program are defined
151 */
152 
153 /*
154  * the creation of separate lpcfg_*() and lp_*() functions is to allow
155  * for code compatibility between existing Samba4 and Samba3 code.
156  */
157 
158 /* this global context supports the lp_*() function varients */
159 static struct loadparm_context *global_loadparm_context;
160 
161 #define FN_GLOBAL_SUBSTITUTED_STRING(fn_name,var_name) \
162  _PUBLIC_ char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx, \
163 		 const struct loadparm_substitution *lp_sub, TALLOC_CTX *mem_ctx) \
164 { \
165 	 if (lp_ctx == NULL) return NULL;				\
166 	 return lpcfg_substituted_string(mem_ctx, lp_sub, \
167 			 lp_ctx->globals->var_name ? lp_ctx->globals->var_name : ""); \
168 }
169 
170 #define FN_GLOBAL_CONST_STRING(fn_name,var_name)				\
171  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
172 	if (lp_ctx == NULL) return NULL;				\
173 	return lp_ctx->globals->var_name ? lpcfg_string(lp_ctx->globals->var_name) : ""; \
174 }
175 
176 #define FN_GLOBAL_LIST(fn_name,var_name)				\
177  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
178 	 if (lp_ctx == NULL) return NULL;				\
179 	 return lp_ctx->globals->var_name;				\
180  }
181 
182 #define FN_GLOBAL_BOOL(fn_name,var_name) \
183  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) {\
184 	 if (lp_ctx == NULL) return false;				\
185 	 return lp_ctx->globals->var_name;				\
186 }
187 
188 #define FN_GLOBAL_INTEGER(fn_name,var_name) \
189  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_context *lp_ctx) { \
190 	 return lp_ctx->globals->var_name;				\
191  }
192 
193 /* Local parameters don't need the ->s3_fns because the struct
194  * loadparm_service is shared and lpcfg_service() checks the ->s3_fns
195  * hook */
196 #define FN_LOCAL_SUBSTITUTED_STRING(fn_name,val) \
197  _PUBLIC_ char *lpcfg_ ## fn_name(struct loadparm_service *service, \
198 					struct loadparm_service *sDefault, TALLOC_CTX *ctx) { \
199 	 return(talloc_strdup(ctx, lpcfg_string((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault->val)))); \
200  }
201 
202 #define FN_LOCAL_CONST_STRING(fn_name,val) \
203  _PUBLIC_ const char *lpcfg_ ## fn_name(struct loadparm_service *service, \
204 					struct loadparm_service *sDefault) { \
205 	 return((const char *)((service != NULL && service->val != NULL) ? service->val : sDefault->val)); \
206  }
207 
208 #define FN_LOCAL_LIST(fn_name,val) \
209  _PUBLIC_ const char **lpcfg_ ## fn_name(struct loadparm_service *service, \
210 					 struct loadparm_service *sDefault) {\
211 	 return(const char **)(service != NULL && service->val != NULL? service->val : sDefault->val); \
212  }
213 
214 #define FN_LOCAL_PARM_BOOL(fn_name, val) FN_LOCAL_BOOL(fn_name, val)
215 
216 #define FN_LOCAL_BOOL(fn_name,val) \
217  _PUBLIC_ bool lpcfg_ ## fn_name(struct loadparm_service *service, \
218 				 struct loadparm_service *sDefault) {	\
219 	 return((service != NULL)? service->val : sDefault->val); \
220  }
221 
222 #define FN_LOCAL_INTEGER(fn_name,val) \
223  _PUBLIC_ int lpcfg_ ## fn_name(struct loadparm_service *service, \
224 				struct loadparm_service *sDefault) {	\
225 	 return((service != NULL)? service->val : sDefault->val); \
226  }
227 
228 #define FN_LOCAL_PARM_INTEGER(fn_name, val) FN_LOCAL_INTEGER(fn_name, val)
229 
230 #define FN_LOCAL_CHAR(fn_name,val) \
231  _PUBLIC_ char lpcfg_ ## fn_name(struct loadparm_service *service, \
232 				struct loadparm_service *sDefault) {	\
233 	 return((service != NULL)? service->val : sDefault->val); \
234  }
235 
236 #define FN_LOCAL_PARM_CHAR(fn_name,val) FN_LOCAL_CHAR(fn_name, val)
237 
238 #include "lib/param/param_functions.c"
239 
240 /* These functions cannot be auto-generated */
241 FN_LOCAL_BOOL(autoloaded, autoloaded)
242 FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
243 
244 /* local prototypes */
245 static struct loadparm_service *lpcfg_getservicebyname(struct loadparm_context *lp_ctx,
246 					const char *pszServiceName);
247 static bool do_section(const char *pszSectionName, void *);
248 static bool set_variable_helper(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
249 				const char *pszParmName, const char *pszParmValue);
250 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
251 				       struct loadparm_service *service,
252 				       const char *pszParmName,
253 				       const char *pszParmValue, int flags);
254 
255 /* The following are helper functions for parametrical options support. */
256 /* It returns a pointer to parametrical option value if it exists or NULL otherwise */
257 /* Actual parametrical functions are quite simple */
get_parametric_helper(struct loadparm_service * service,const char * type,const char * option,struct parmlist_entry * global_opts)258 struct parmlist_entry *get_parametric_helper(struct loadparm_service *service,
259 					     const char *type, const char *option,
260 					     struct parmlist_entry *global_opts)
261 {
262 	size_t type_len = strlen(type);
263 	size_t option_len = strlen(option);
264 	char param_key[type_len + option_len + 2];
265 	struct parmlist_entry *data = NULL;
266 
267 	snprintf(param_key, sizeof(param_key), "%s:%s", type, option);
268 
269 	/*
270 	 * Try to fetch the option from the data.
271 	 */
272 	if (service != NULL) {
273 		data = service->param_opt;
274 		while (data != NULL) {
275 			if (strwicmp(data->key, param_key) == 0) {
276 				return data;
277 			}
278 			data = data->next;
279 		}
280 	}
281 
282 	/*
283 	 * Fall back to fetching from the globals.
284 	 */
285 	data = global_opts;
286 	while (data != NULL) {
287 		if (strwicmp(data->key, param_key) == 0) {
288 			return data;
289 		}
290 		data = data->next;
291 	}
292 
293 	return NULL;
294 }
295 
lpcfg_get_parametric(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option)296 const char *lpcfg_get_parametric(struct loadparm_context *lp_ctx,
297 			      struct loadparm_service *service,
298 			      const char *type, const char *option)
299 {
300 	struct parmlist_entry *data;
301 
302 	if (lp_ctx == NULL)
303 		return NULL;
304 
305 	data = get_parametric_helper(service,
306 				     type, option, lp_ctx->globals->param_opt);
307 
308 	if (data == NULL) {
309 		return NULL;
310 	} else {
311 		return data->value;
312 	}
313 }
314 
315 
316 /**
317  * convenience routine to return int parameters.
318  */
lp_int(const char * s)319 int lp_int(const char *s)
320 {
321 
322 	if (!s || !*s) {
323 		DEBUG(0,("lp_int(%s): is called with NULL!\n",s));
324 		return -1;
325 	}
326 
327 	return strtol(s, NULL, 0);
328 }
329 
330 /**
331  * convenience routine to return unsigned long parameters.
332  */
lp_ulong(const char * s)333 unsigned long lp_ulong(const char *s)
334 {
335 	int error = 0;
336 	unsigned long int ret;
337 
338 	if (!s || !*s) {
339 		DBG_DEBUG("lp_ulong(%s): is called with NULL!\n",s);
340 		return -1;
341 	}
342 
343 	ret = smb_strtoul(s, NULL, 0, &error, SMB_STR_STANDARD);
344 	if (error != 0) {
345 		DBG_DEBUG("lp_ulong(%s): conversion failed\n",s);
346 		return -1;
347 	}
348 
349 	return ret;
350 }
351 
352 /**
353  * convenience routine to return unsigned long long parameters.
354  */
lp_ulonglong(const char * s)355 unsigned long long lp_ulonglong(const char *s)
356 {
357 	int error = 0;
358 	unsigned long long int ret;
359 
360 	if (!s || !*s) {
361 		DBG_DEBUG("lp_ulonglong(%s): is called with NULL!\n", s);
362 		return -1;
363 	}
364 
365 	ret = smb_strtoull(s, NULL, 0, &error, SMB_STR_STANDARD);
366 	if (error != 0) {
367 		DBG_DEBUG("lp_ulonglong(%s): conversion failed\n",s);
368 		return -1;
369 	}
370 
371 	return ret;
372 }
373 
374 /**
375  * convenience routine to return unsigned long parameters.
376  */
lp_long(const char * s)377 static long lp_long(const char *s)
378 {
379 
380 	if (!s) {
381 		DEBUG(0,("lp_long(%s): is called with NULL!\n",s));
382 		return -1;
383 	}
384 
385 	return strtol(s, NULL, 0);
386 }
387 
388 /**
389  * convenience routine to return unsigned long parameters.
390  */
lp_double(const char * s)391 static double lp_double(const char *s)
392 {
393 
394 	if (!s) {
395 		DEBUG(0,("lp_double(%s): is called with NULL!\n",s));
396 		return -1;
397 	}
398 
399 	return strtod(s, NULL);
400 }
401 
402 /**
403  * convenience routine to return boolean parameters.
404  */
lp_bool(const char * s)405 bool lp_bool(const char *s)
406 {
407 	bool ret = false;
408 
409 	if (!s || !*s) {
410 		DEBUG(0,("lp_bool(%s): is called with NULL!\n",s));
411 		return false;
412 	}
413 
414 	if (!set_boolean(s, &ret)) {
415 		DEBUG(0,("lp_bool(%s): value is not boolean!\n",s));
416 		return false;
417 	}
418 
419 	return ret;
420 }
421 
422 /**
423  * Return parametric option from a given service. Type is a part of option before ':'
424  * Parametric option has following syntax: 'Type: option = value'
425  * Returned value is allocated in 'lp_talloc' context
426  */
427 
lpcfg_parm_string(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option)428 const char *lpcfg_parm_string(struct loadparm_context *lp_ctx,
429 			      struct loadparm_service *service, const char *type,
430 			      const char *option)
431 {
432 	const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
433 
434 	if (value)
435 		return lpcfg_string(value);
436 
437 	return NULL;
438 }
439 
440 /**
441  * Return parametric option from a given service. Type is a part of option before ':'
442  * Parametric option has following syntax: 'Type: option = value'
443  * Returned value is allocated in 'lp_talloc' context
444  */
445 
lpcfg_parm_string_list(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option,const char * separator)446 const char **lpcfg_parm_string_list(TALLOC_CTX *mem_ctx,
447 				    struct loadparm_context *lp_ctx,
448 				    struct loadparm_service *service,
449 				    const char *type,
450 				    const char *option, const char *separator)
451 {
452 	const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
453 
454 	if (value != NULL) {
455 		char **l = str_list_make(mem_ctx, value, separator);
456 		return discard_const_p(const char *, l);
457 	}
458 
459 	return NULL;
460 }
461 
462 /**
463  * Return parametric option from a given service. Type is a part of option before ':'
464  * Parametric option has following syntax: 'Type: option = value'
465  */
466 
lpcfg_parm_int(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option,int default_v)467 int lpcfg_parm_int(struct loadparm_context *lp_ctx,
468 		   struct loadparm_service *service, const char *type,
469 		   const char *option, int default_v)
470 {
471 	const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
472 
473 	if (value)
474 		return lp_int(value);
475 
476 	return default_v;
477 }
478 
479 /**
480  * Return parametric option from a given service. Type is a part of
481  * option before ':'.
482  * Parametric option has following syntax: 'Type: option = value'.
483  */
484 
lpcfg_parm_bytes(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option,int default_v)485 int lpcfg_parm_bytes(struct loadparm_context *lp_ctx,
486 		  struct loadparm_service *service, const char *type,
487 		  const char *option, int default_v)
488 {
489 	uint64_t bval;
490 
491 	const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
492 
493 	if (value && conv_str_size_error(value, &bval)) {
494 		if (bval <= INT_MAX) {
495 			return (int)bval;
496 		}
497 	}
498 
499 	return default_v;
500 }
501 
502 /**
503  * Return parametric option from a given service.
504  * Type is a part of option before ':'
505  * Parametric option has following syntax: 'Type: option = value'
506  */
lpcfg_parm_ulong(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option,unsigned long default_v)507 unsigned long lpcfg_parm_ulong(struct loadparm_context *lp_ctx,
508 			    struct loadparm_service *service, const char *type,
509 			    const char *option, unsigned long default_v)
510 {
511 	const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
512 
513 	if (value)
514 		return lp_ulong(value);
515 
516 	return default_v;
517 }
518 
519 /**
520  * Return parametric option from a given service.
521  * Type is a part of option before ':'
522  * Parametric option has following syntax: 'Type: option = value'
523  */
lpcfg_parm_ulonglong(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option,unsigned long long default_v)524 unsigned long long lpcfg_parm_ulonglong(struct loadparm_context *lp_ctx,
525 					struct loadparm_service *service,
526 					const char *type, const char *option,
527 					unsigned long long default_v)
528 {
529 	const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
530 
531 	if (value) {
532 		return lp_ulonglong(value);
533 	}
534 
535 	return default_v;
536 }
537 
lpcfg_parm_long(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option,long default_v)538 long lpcfg_parm_long(struct loadparm_context *lp_ctx,
539 		     struct loadparm_service *service, const char *type,
540 		     const char *option, long default_v)
541 {
542 	const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
543 
544 	if (value)
545 		return lp_long(value);
546 
547 	return default_v;
548 }
549 
lpcfg_parm_double(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option,double default_v)550 double lpcfg_parm_double(struct loadparm_context *lp_ctx,
551 		      struct loadparm_service *service, const char *type,
552 		      const char *option, double default_v)
553 {
554 	const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
555 
556 	if (value != NULL)
557 		return lp_double(value);
558 
559 	return default_v;
560 }
561 
562 /**
563  * Return parametric option from a given service. Type is a part of option before ':'
564  * Parametric option has following syntax: 'Type: option = value'
565  */
566 
lpcfg_parm_bool(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * type,const char * option,bool default_v)567 bool lpcfg_parm_bool(struct loadparm_context *lp_ctx,
568 		     struct loadparm_service *service, const char *type,
569 		     const char *option, bool default_v)
570 {
571 	const char *value = lpcfg_get_parametric(lp_ctx, service, type, option);
572 
573 	if (value != NULL)
574 		return lp_bool(value);
575 
576 	return default_v;
577 }
578 
579 
580 /* this is used to prevent lots of mallocs of size 1 */
581 static const char lpcfg_string_empty[] = "";
582 
583 /**
584  Free a string value.
585 **/
lpcfg_string_free(char ** s)586 void lpcfg_string_free(char **s)
587 {
588 	if (s == NULL) {
589 		return;
590 	}
591 	if (*s == lpcfg_string_empty) {
592 		*s = NULL;
593 		return;
594 	}
595 	TALLOC_FREE(*s);
596 }
597 
598 /**
599  * Set a string value, deallocating any existing space, and allocing the space
600  * for the string
601  */
lpcfg_string_set(TALLOC_CTX * mem_ctx,char ** dest,const char * src)602 bool lpcfg_string_set(TALLOC_CTX *mem_ctx, char **dest, const char *src)
603 {
604 	lpcfg_string_free(dest);
605 
606 	if ((src == NULL) || (*src == '\0')) {
607 		*dest = discard_const_p(char, lpcfg_string_empty);
608 		return true;
609 	}
610 
611 	*dest = talloc_strdup(mem_ctx, src);
612 	if ((*dest) == NULL) {
613 		DEBUG(0,("Out of memory in string_set\n"));
614 		return false;
615 	}
616 
617 	return true;
618 }
619 
620 /**
621  * Set a string value, deallocating any existing space, and allocing the space
622  * for the string
623  */
lpcfg_string_set_upper(TALLOC_CTX * mem_ctx,char ** dest,const char * src)624 bool lpcfg_string_set_upper(TALLOC_CTX *mem_ctx, char **dest, const char *src)
625 {
626 	lpcfg_string_free(dest);
627 
628 	if ((src == NULL) || (*src == '\0')) {
629 		*dest = discard_const_p(char, lpcfg_string_empty);
630 		return true;
631 	}
632 
633 	*dest = strupper_talloc(mem_ctx, src);
634 	if ((*dest) == NULL) {
635 		DEBUG(0,("Out of memory in string_set_upper\n"));
636 		return false;
637 	}
638 
639 	return true;
640 }
641 
642 
643 
644 /**
645  * Add a new service to the services array initialising it with the given
646  * service.
647  */
648 
lpcfg_add_service(struct loadparm_context * lp_ctx,const struct loadparm_service * pservice,const char * name)649 struct loadparm_service *lpcfg_add_service(struct loadparm_context *lp_ctx,
650 					   const struct loadparm_service *pservice,
651 					   const char *name)
652 {
653 	int i;
654 	int num_to_alloc = lp_ctx->iNumServices + 1;
655 	struct parmlist_entry *data, *pdata;
656 
657 	if (lp_ctx->s3_fns != NULL) {
658 		smb_panic("Add a service should not be called on an s3 loadparm ctx");
659 	}
660 
661 	if (pservice == NULL) {
662 		pservice = lp_ctx->sDefault;
663 	}
664 
665 	/* it might already exist */
666 	if (name) {
667 		struct loadparm_service *service = lpcfg_getservicebyname(lp_ctx,
668 								    name);
669 		if (service != NULL) {
670 			/* Clean all parametric options for service */
671 			/* They will be added during parsing again */
672 			data = service->param_opt;
673 			while (data) {
674 				pdata = data->next;
675 				talloc_free(data);
676 				data = pdata;
677 			}
678 			service->param_opt = NULL;
679 			return service;
680 		}
681 	}
682 
683 	/* find an invalid one */
684 	for (i = 0; i < lp_ctx->iNumServices; i++)
685 		if (lp_ctx->services[i] == NULL)
686 			break;
687 
688 	/* if not, then create one */
689 	if (i == lp_ctx->iNumServices) {
690 		struct loadparm_service **tsp;
691 
692 		tsp = talloc_realloc(lp_ctx, lp_ctx->services, struct loadparm_service *, num_to_alloc);
693 
694 		if (!tsp) {
695 			DEBUG(0,("lpcfg_add_service: failed to enlarge services!\n"));
696 			return NULL;
697 		} else {
698 			lp_ctx->services = tsp;
699 			lp_ctx->services[lp_ctx->iNumServices] = NULL;
700 		}
701 
702 		lp_ctx->iNumServices++;
703 	}
704 
705 	lp_ctx->services[i] = talloc_zero(lp_ctx->services, struct loadparm_service);
706 	if (lp_ctx->services[i] == NULL) {
707 		DEBUG(0,("lpcfg_add_service: out of memory!\n"));
708 		return NULL;
709 	}
710 	copy_service(lp_ctx->services[i], pservice, NULL);
711 	if (name != NULL)
712 		lpcfg_string_set(lp_ctx->services[i], &lp_ctx->services[i]->szService, name);
713 	return lp_ctx->services[i];
714 }
715 
716 /**
717  * Add a new home service, with the specified home directory, defaults coming
718  * from service ifrom.
719  */
720 
lpcfg_add_home(struct loadparm_context * lp_ctx,const char * pszHomename,struct loadparm_service * default_service,const char * user,const char * pszHomedir)721 bool lpcfg_add_home(struct loadparm_context *lp_ctx,
722 		 const char *pszHomename,
723 		 struct loadparm_service *default_service,
724 		 const char *user, const char *pszHomedir)
725 {
726 	struct loadparm_service *service;
727 
728 	service = lpcfg_add_service(lp_ctx, default_service, pszHomename);
729 
730 	if (service == NULL)
731 		return false;
732 
733 	if (!(*(default_service->path))
734 	    || strequal(default_service->path, lp_ctx->sDefault->path)) {
735 		service->path = talloc_strdup(service, pszHomedir);
736 	} else {
737 		service->path = string_sub_talloc(service, lpcfg_path(default_service, lp_ctx->sDefault, service), "%H", pszHomedir);
738 	}
739 
740 	if (!(*(service->comment))) {
741 		service->comment = talloc_asprintf(service, "Home directory of %s", user);
742 	}
743 	service->available = default_service->available;
744 	service->browseable = default_service->browseable;
745 
746 	DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n",
747 		  pszHomename, user, service->path));
748 
749 	return true;
750 }
751 
752 /**
753  * Add a new printer service, with defaults coming from service iFrom.
754  */
755 
lpcfg_add_printer(struct loadparm_context * lp_ctx,const char * pszPrintername,struct loadparm_service * default_service)756 bool lpcfg_add_printer(struct loadparm_context *lp_ctx,
757 		       const char *pszPrintername,
758 		       struct loadparm_service *default_service)
759 {
760 	const char *comment = "From Printcap";
761 	struct loadparm_service *service;
762 	service = lpcfg_add_service(lp_ctx, default_service, pszPrintername);
763 
764 	if (service == NULL)
765 		return false;
766 
767 	/* note that we do NOT default the availability flag to True - */
768 	/* we take it from the default service passed. This allows all */
769 	/* dynamic printers to be disabled by disabling the [printers] */
770 	/* entry (if/when the 'available' keyword is implemented!).    */
771 
772 	/* the printer name is set to the service name. */
773 	lpcfg_string_set(service, &service->_printername, pszPrintername);
774 	lpcfg_string_set(service, &service->comment, comment);
775 	service->browseable = default_service->browseable;
776 	/* Printers cannot be read_only. */
777 	service->read_only = false;
778 	/* Printer services must be printable. */
779 	service->printable = true;
780 
781 	DEBUG(3, ("adding printer service %s\n", pszPrintername));
782 
783 	return true;
784 }
785 
786 /**
787  * Map a parameter's string representation to something we can use.
788  * Returns False if the parameter string is not recognised, else TRUE.
789  */
790 
lpcfg_map_parameter(const char * pszParmName)791 int lpcfg_map_parameter(const char *pszParmName)
792 {
793 	int iIndex;
794 
795 	for (iIndex = 0; parm_table[iIndex].label; iIndex++)
796 		if (strwicmp(parm_table[iIndex].label, pszParmName) == 0)
797 			return iIndex;
798 
799 	/* Warn only if it isn't parametric option */
800 	if (strchr(pszParmName, ':') == NULL)
801 		DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName));
802 	/* We do return 'fail' for parametric options as well because they are
803 	   stored in different storage
804 	 */
805 	return -1;
806 }
807 
808 
809 /**
810   return the parameter structure for a parameter
811 */
lpcfg_parm_struct(struct loadparm_context * lp_ctx,const char * name)812 struct parm_struct *lpcfg_parm_struct(struct loadparm_context *lp_ctx, const char *name)
813 {
814 	int num = lpcfg_map_parameter(name);
815 
816 	if (num < 0) {
817 		return NULL;
818 	}
819 
820 	return &parm_table[num];
821 }
822 
823 /**
824   return the parameter pointer for a parameter
825 */
lpcfg_parm_ptr(struct loadparm_context * lp_ctx,struct loadparm_service * service,struct parm_struct * parm)826 void *lpcfg_parm_ptr(struct loadparm_context *lp_ctx,
827 		  struct loadparm_service *service, struct parm_struct *parm)
828 {
829 	if (lp_ctx->s3_fns) {
830 		return lp_ctx->s3_fns->get_parm_ptr(service, parm);
831 	}
832 
833 	if (service == NULL) {
834 		if (parm->p_class == P_LOCAL)
835 			return ((char *)lp_ctx->sDefault)+parm->offset;
836 		else if (parm->p_class == P_GLOBAL)
837 			return ((char *)lp_ctx->globals)+parm->offset;
838 		else return NULL;
839 	} else {
840 		return ((char *)service) + parm->offset;
841 	}
842 }
843 
844 /**
845   return the parameter pointer for a parameter
846 */
lpcfg_parm_is_cmdline(struct loadparm_context * lp_ctx,const char * name)847 bool lpcfg_parm_is_cmdline(struct loadparm_context *lp_ctx, const char *name)
848 {
849 	int parmnum;
850 
851 	parmnum = lpcfg_map_parameter(name);
852 	if (parmnum == -1) return false;
853 
854 	return lp_ctx->flags[parmnum] & FLAG_CMDLINE;
855 }
856 
857 /**
858  * Find a service by name. Otherwise works like get_service.
859  */
860 
lpcfg_getservicebyname(struct loadparm_context * lp_ctx,const char * pszServiceName)861 static struct loadparm_service *lpcfg_getservicebyname(struct loadparm_context *lp_ctx,
862 					const char *pszServiceName)
863 {
864 	int iService;
865 
866 	if (lp_ctx->s3_fns) {
867 		return lp_ctx->s3_fns->get_service(pszServiceName);
868 	}
869 
870 	for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--)
871 		if (lp_ctx->services[iService] != NULL &&
872 		    strwicmp(lp_ctx->services[iService]->szService, pszServiceName) == 0) {
873 			return lp_ctx->services[iService];
874 		}
875 
876 	return NULL;
877 }
878 
879 /**
880  * Add a parametric option to a parmlist_entry,
881  * replacing old value, if already present.
882  */
set_param_opt(TALLOC_CTX * mem_ctx,struct parmlist_entry ** opt_list,const char * opt_name,const char * opt_value,unsigned priority)883 void set_param_opt(TALLOC_CTX *mem_ctx,
884 		   struct parmlist_entry **opt_list,
885 		   const char *opt_name,
886 		   const char *opt_value,
887 		   unsigned priority)
888 {
889 	struct parmlist_entry *new_opt, *opt;
890 
891 	opt = *opt_list;
892 
893 	/* Traverse destination */
894 	while (opt) {
895 		/* If we already have same option, override it */
896 		if (strwicmp(opt->key, opt_name) == 0) {
897 			if ((opt->priority & FLAG_CMDLINE) &&
898 			    !(priority & FLAG_CMDLINE)) {
899 				/* it's been marked as not to be
900 				   overridden */
901 				return;
902 			}
903 			TALLOC_FREE(opt->list);
904 			lpcfg_string_set(opt, &opt->value, opt_value);
905 			opt->priority = priority;
906 			return;
907 		}
908 		opt = opt->next;
909 	}
910 
911 	new_opt = talloc_pooled_object(
912 		mem_ctx, struct parmlist_entry,
913 		2, strlen(opt_name) + 1 + strlen(opt_value) + 1);
914 	if (new_opt == NULL) {
915 		smb_panic("OOM");
916 	}
917 	new_opt->key = NULL;
918 	lpcfg_string_set(new_opt, &new_opt->key, opt_name);
919 	new_opt->value = NULL;
920 	lpcfg_string_set(new_opt, &new_opt->value, opt_value);
921 
922 	new_opt->list = NULL;
923 	new_opt->priority = priority;
924 	DLIST_ADD(*opt_list, new_opt);
925 }
926 
927 /**
928  * Copy a service structure to another.
929  * If pcopymapDest is NULL then copy all fields
930  */
931 
copy_service(struct loadparm_service * pserviceDest,const struct loadparm_service * pserviceSource,struct bitmap * pcopymapDest)932 void copy_service(struct loadparm_service *pserviceDest,
933 		  const struct loadparm_service *pserviceSource,
934 		  struct bitmap *pcopymapDest)
935 {
936 	int i;
937 	bool bcopyall = (pcopymapDest == NULL);
938 	struct parmlist_entry *data;
939 
940 	for (i = 0; parm_table[i].label; i++)
941 		if (parm_table[i].p_class == P_LOCAL &&
942 		    (bcopyall || bitmap_query(pcopymapDest, i))) {
943 			const void *src_ptr =
944 				((const char *)pserviceSource) + parm_table[i].offset;
945 			void *dest_ptr =
946 				((char *)pserviceDest) + parm_table[i].offset;
947 
948 			switch (parm_table[i].type) {
949 				case P_BOOL:
950 				case P_BOOLREV:
951 					*(bool *)dest_ptr = *(const bool *)src_ptr;
952 					break;
953 
954 				case P_INTEGER:
955 				case P_BYTES:
956 				case P_OCTAL:
957 				case P_ENUM:
958 					*(int *)dest_ptr = *(const int *)src_ptr;
959 					break;
960 
961 				case P_CHAR:
962 					*(char *)dest_ptr = *(const char *)src_ptr;
963 					break;
964 
965 				case P_STRING:
966 					lpcfg_string_set(pserviceDest,
967 						   (char **)dest_ptr,
968 						   *(const char * const *)src_ptr);
969 					break;
970 
971 				case P_USTRING:
972 					lpcfg_string_set_upper(pserviceDest,
973 							 (char **)dest_ptr,
974 							 *(const char * const *)src_ptr);
975 					break;
976 				case P_CMDLIST:
977 				case P_LIST:
978 					TALLOC_FREE(*((char ***)dest_ptr));
979 					*(char ***)dest_ptr = str_list_copy(pserviceDest,
980 									    *discard_const_p(const char **, src_ptr));
981 					break;
982 				default:
983 					break;
984 			}
985 		}
986 
987 	if (bcopyall) {
988 		init_copymap(pserviceDest);
989 		if (pserviceSource->copymap)
990 			bitmap_copy(pserviceDest->copymap,
991 				    pserviceSource->copymap);
992 	}
993 
994 	for (data = pserviceSource->param_opt; data != NULL; data = data->next) {
995 		set_param_opt(pserviceDest, &pserviceDest->param_opt,
996 			      data->key, data->value, data->priority);
997 	}
998 }
999 
1000 /**
1001  * Check a service for consistency. Return False if the service is in any way
1002  * incomplete or faulty, else True.
1003  */
lpcfg_service_ok(struct loadparm_service * service)1004 bool lpcfg_service_ok(struct loadparm_service *service)
1005 {
1006 	bool bRetval;
1007 
1008 	bRetval = true;
1009 	if (service->szService[0] == '\0') {
1010 		DEBUG(0, ("The following message indicates an internal error:\n"));
1011 		DEBUG(0, ("No service name in service entry.\n"));
1012 		bRetval = false;
1013 	}
1014 
1015 	/* The [printers] entry MUST be printable. I'm all for flexibility, but */
1016 	/* I can't see why you'd want a non-printable printer service...        */
1017 	if (strwicmp(service->szService, PRINTERS_NAME) == 0) {
1018 		if (!service->printable) {
1019 			DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
1020 			       service->szService));
1021 			service->printable = true;
1022 		}
1023 		/* [printers] service must also be non-browsable. */
1024 		if (service->browseable)
1025 			service->browseable = false;
1026 	}
1027 
1028 	if (service->path[0] == '\0' &&
1029 	    strwicmp(service->szService, HOMES_NAME) != 0 &&
1030 	    service->msdfs_proxy[0] == '\0')
1031 	{
1032 		DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
1033 			service->szService));
1034 		service->available = false;
1035 	}
1036 
1037 	if (!service->available)
1038 		DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
1039 			  service->szService));
1040 
1041 	return bRetval;
1042 }
1043 
1044 
1045 /*******************************************************************
1046  Keep a linked list of all config files so we know when one has changed
1047  it's date and needs to be reloaded.
1048 ********************************************************************/
1049 
add_to_file_list(TALLOC_CTX * mem_ctx,struct file_lists ** list,const char * fname,const char * subfname)1050 void add_to_file_list(TALLOC_CTX *mem_ctx, struct file_lists **list,
1051 			     const char *fname, const char *subfname)
1052 {
1053 	struct file_lists *f = *list;
1054 
1055 	while (f) {
1056 		if (f->name && !strcmp(f->name, fname))
1057 			break;
1058 		f = f->next;
1059 	}
1060 
1061 	if (!f) {
1062 		f = talloc(mem_ctx, struct file_lists);
1063 		if (!f)
1064 			goto fail;
1065 		f->next = *list;
1066 		f->name = talloc_strdup(f, fname);
1067 		if (!f->name) {
1068 			TALLOC_FREE(f);
1069 			goto fail;
1070 		}
1071 		f->subfname = talloc_strdup(f, subfname);
1072 		if (!f->subfname) {
1073 			TALLOC_FREE(f);
1074 			goto fail;
1075 		}
1076 		*list = f;
1077 		f->modtime = file_modtime(subfname);
1078 	} else {
1079 		time_t t = file_modtime(subfname);
1080 		if (t)
1081 			f->modtime = t;
1082 	}
1083 	return;
1084 
1085 fail:
1086 	DEBUG(0, ("Unable to add file to file list: %s\n", fname));
1087 
1088 }
1089 
1090 /*******************************************************************
1091  Check if a config file has changed date.
1092 ********************************************************************/
lpcfg_file_list_changed(struct loadparm_context * lp_ctx)1093 bool lpcfg_file_list_changed(struct loadparm_context *lp_ctx)
1094 {
1095 	struct file_lists *f;
1096 	DEBUG(6, ("lpcfg_file_list_changed()\n"));
1097 
1098 	for (f = lp_ctx->file_lists; f != NULL; f = f->next) {
1099 		char *n2;
1100 		time_t mod_time;
1101 
1102 		n2 = standard_sub_basic(lp_ctx, f->name);
1103 
1104 		DEBUGADD(6, ("file %s -> %s  last mod_time: %s\n",
1105 			     f->name, n2, ctime(&f->modtime)));
1106 
1107 		mod_time = file_modtime(n2);
1108 
1109 		if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) {
1110 			DEBUGADD(6, ("file %s modified: %s\n", n2,
1111 				  ctime(&mod_time)));
1112 			f->modtime = mod_time;
1113 			talloc_free(f->subfname);
1114 			f->subfname = talloc_strdup(f, n2);
1115 			TALLOC_FREE(n2);
1116 			return true;
1117 		}
1118 		TALLOC_FREE(n2);
1119 	}
1120 	return false;
1121 }
1122 
1123 /*
1124  * set the value for a P_ENUM
1125  */
lp_set_enum_parm(struct parm_struct * parm,const char * pszParmValue,int * ptr)1126 bool lp_set_enum_parm( struct parm_struct *parm, const char *pszParmValue,
1127                               int *ptr )
1128 {
1129 	int i;
1130 
1131 	for (i = 0; parm->enum_list[i].name; i++) {
1132 		if (strwicmp(pszParmValue, parm->enum_list[i].name) == 0) {
1133 			*ptr = parm->enum_list[i].value;
1134 			return true;
1135 		}
1136 	}
1137 	DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
1138 		  pszParmValue, parm->label));
1139 	return false;
1140 }
1141 
1142 
1143 /***************************************************************************
1144  Handle the "realm" parameter
1145 ***************************************************************************/
1146 
handle_realm(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1147 bool handle_realm(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1148 		  const char *pszParmValue, char **ptr)
1149 {
1150 	char *upper;
1151 	char *lower;
1152 
1153 	upper = strupper_talloc(lp_ctx, pszParmValue);
1154 	if (upper == NULL) {
1155 		return false;
1156 	}
1157 
1158 	lower = strlower_talloc(lp_ctx, pszParmValue);
1159 	if (lower == NULL) {
1160 		TALLOC_FREE(upper);
1161 		return false;
1162 	}
1163 
1164 	lpcfg_string_set(lp_ctx->globals->ctx, &lp_ctx->globals->realm, upper);
1165 	lpcfg_string_set(lp_ctx->globals->ctx, &lp_ctx->globals->dnsdomain, lower);
1166 
1167 	return true;
1168 }
1169 
1170 /***************************************************************************
1171  Handle the include operation.
1172 ***************************************************************************/
1173 
handle_include(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1174 bool handle_include(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1175 			   const char *pszParmValue, char **ptr)
1176 {
1177 	char *fname;
1178 	const char *substitution_variable_substring;
1179 	char next_char;
1180 
1181 	if (lp_ctx->s3_fns) {
1182 		return lp_ctx->s3_fns->lp_include(lp_ctx, service, pszParmValue, ptr);
1183 	}
1184 
1185 	fname = standard_sub_basic(lp_ctx, pszParmValue);
1186 
1187 	add_to_file_list(lp_ctx, &lp_ctx->file_lists, pszParmValue, fname);
1188 
1189 	lpcfg_string_set(lp_ctx, ptr, fname);
1190 
1191 	if (file_exist(fname))
1192 		return pm_process(fname, do_section, lpcfg_do_parameter, lp_ctx);
1193 
1194        /*
1195         * If the file doesn't exist, we check that it isn't due to variable
1196         * substitution
1197         */
1198 	substitution_variable_substring = strchr(fname, '%');
1199 
1200 	if (substitution_variable_substring != NULL) {
1201 		next_char = substitution_variable_substring[1];
1202 		if ((next_char >= 'a' && next_char <= 'z')
1203 		    || (next_char >= 'A' && next_char <= 'Z')) {
1204 			DEBUG(2, ("Tried to load %s but variable substitution in "
1205 				 "filename, ignoring file.\n", fname));
1206 			return true;
1207 		}
1208 	}
1209 
1210 	DEBUG(2, ("Can't find include file %s\n", fname));
1211 
1212 	return false;
1213 }
1214 
1215 /***************************************************************************
1216  Handle the interpretation of the copy parameter.
1217 ***************************************************************************/
1218 
handle_copy(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1219 bool handle_copy(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1220 			const char *pszParmValue, char **ptr)
1221 {
1222 	bool bRetval;
1223 	struct loadparm_service *serviceTemp = NULL;
1224 
1225 	bRetval = false;
1226 
1227 	DEBUG(3, ("Copying service from service %s\n", pszParmValue));
1228 
1229 	serviceTemp = lpcfg_getservicebyname(lp_ctx, pszParmValue);
1230 
1231 	if (service == NULL) {
1232 		DEBUG(0, ("Unable to copy service - invalid service destination.\n"));
1233 		return false;
1234 	}
1235 
1236 	if (serviceTemp != NULL) {
1237 		if (serviceTemp == service) {
1238 			DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue));
1239 		} else {
1240 			copy_service(service,
1241 				     serviceTemp,
1242 				     service->copymap);
1243 			lpcfg_string_set(service, ptr, pszParmValue);
1244 
1245 			bRetval = true;
1246 		}
1247 	} else {
1248 		DEBUG(0, ("Unable to copy service - source not found: %s\n",
1249 			  pszParmValue));
1250 		bRetval = false;
1251 	}
1252 
1253 	return bRetval;
1254 }
1255 
handle_debug_list(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1256 bool handle_debug_list(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1257 			const char *pszParmValue, char **ptr)
1258 {
1259 	lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
1260 
1261 	return debug_parse_levels(pszParmValue);
1262 }
1263 
handle_logfile(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1264 bool handle_logfile(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1265 		    const char *pszParmValue, char **ptr)
1266 {
1267 	if (lp_ctx->s3_fns == NULL) {
1268 		debug_set_logfile(pszParmValue);
1269 	}
1270 
1271 	lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
1272 
1273 	return true;
1274 }
1275 
1276 /*
1277  * These special charset handling methods only run in the source3 code.
1278  */
1279 
handle_charset(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1280 bool handle_charset(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1281 			const char *pszParmValue, char **ptr)
1282 {
1283 	if (lp_ctx->s3_fns) {
1284 		if (*ptr == NULL || strcmp(*ptr, pszParmValue) != 0) {
1285 			struct smb_iconv_handle *ret = NULL;
1286 
1287 			ret = reinit_iconv_handle(NULL,
1288 						  lpcfg_dos_charset(lp_ctx),
1289 						  lpcfg_unix_charset(lp_ctx));
1290 			if (ret == NULL) {
1291 				smb_panic("reinit_iconv_handle failed");
1292 			}
1293 		}
1294 
1295 	}
1296 	return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
1297 
1298 }
1299 
handle_dos_charset(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1300 bool handle_dos_charset(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1301 			const char *pszParmValue, char **ptr)
1302 {
1303 	bool is_utf8 = false;
1304 	size_t len = strlen(pszParmValue);
1305 
1306 	if (lp_ctx->s3_fns) {
1307 		if (len == 4 || len == 5) {
1308 			/* Don't use StrCaseCmp here as we don't want to
1309 			   initialize iconv. */
1310 			if ((toupper_m(pszParmValue[0]) == 'U') &&
1311 			    (toupper_m(pszParmValue[1]) == 'T') &&
1312 			    (toupper_m(pszParmValue[2]) == 'F')) {
1313 				if (len == 4) {
1314 					if (pszParmValue[3] == '8') {
1315 						is_utf8 = true;
1316 					}
1317 				} else {
1318 					if (pszParmValue[3] == '-' &&
1319 					    pszParmValue[4] == '8') {
1320 						is_utf8 = true;
1321 					}
1322 				}
1323 			}
1324 		}
1325 
1326 		if (*ptr == NULL || strcmp(*ptr, pszParmValue) != 0) {
1327 			struct smb_iconv_handle *ret = NULL;
1328 			if (is_utf8) {
1329 				DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
1330 					"be UTF8, using (default value) %s instead.\n",
1331 					DEFAULT_DOS_CHARSET));
1332 				pszParmValue = DEFAULT_DOS_CHARSET;
1333 			}
1334 			ret = reinit_iconv_handle(NULL,
1335 						lpcfg_dos_charset(lp_ctx),
1336 						lpcfg_unix_charset(lp_ctx));
1337 			if (ret == NULL) {
1338 				smb_panic("reinit_iconv_handle failed");
1339 			}
1340 		}
1341 	}
1342 
1343 	return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
1344 }
1345 
handle_printing(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1346 bool handle_printing(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1347 			    const char *pszParmValue, char **ptr)
1348 {
1349 	static int parm_num = -1;
1350 
1351 	if (parm_num == -1) {
1352 		parm_num = lpcfg_map_parameter("printing");
1353 	}
1354 
1355 	if (!lp_set_enum_parm(&parm_table[parm_num], pszParmValue, (int*)ptr)) {
1356 		return false;
1357 	}
1358 
1359 	if (lp_ctx->s3_fns) {
1360 		if (service == NULL) {
1361 			init_printer_values(lp_ctx, lp_ctx->globals->ctx, lp_ctx->sDefault);
1362 		} else {
1363 			init_printer_values(lp_ctx, service, service);
1364 		}
1365 	}
1366 
1367 	return true;
1368 }
1369 
handle_ldap_debug_level(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1370 bool handle_ldap_debug_level(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1371 			     const char *pszParmValue, char **ptr)
1372 {
1373 	lp_ctx->globals->ldap_debug_level = lp_int(pszParmValue);
1374 
1375 	if (lp_ctx->s3_fns) {
1376 		lp_ctx->s3_fns->init_ldap_debugging();
1377 	}
1378 	return true;
1379 }
1380 
handle_netbios_aliases(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1381 bool handle_netbios_aliases(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1382 			    const char *pszParmValue, char **ptr)
1383 {
1384 	TALLOC_FREE(lp_ctx->globals->netbios_aliases);
1385 	lp_ctx->globals->netbios_aliases = str_list_make_v3_const(lp_ctx->globals->ctx,
1386 								  pszParmValue, NULL);
1387 
1388 	if (lp_ctx->s3_fns) {
1389 		return lp_ctx->s3_fns->set_netbios_aliases(lp_ctx->globals->netbios_aliases);
1390 	}
1391 	return true;
1392 }
1393 
1394 /*
1395  * idmap related parameters
1396  */
1397 
handle_idmap_backend(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1398 bool handle_idmap_backend(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1399 			  const char *pszParmValue, char **ptr)
1400 {
1401 	if (lp_ctx->s3_fns) {
1402 		lp_do_parameter_parametric(lp_ctx, service, "idmap config * : backend",
1403 					   pszParmValue, 0);
1404 	}
1405 
1406 	return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
1407 }
1408 
handle_idmap_uid(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1409 bool handle_idmap_uid(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1410 		      const char *pszParmValue, char **ptr)
1411 {
1412 	if (lp_ctx->s3_fns) {
1413 		lp_do_parameter_parametric(lp_ctx, service, "idmap config * : range",
1414 					   pszParmValue, 0);
1415 	}
1416 
1417 	return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
1418 }
1419 
handle_idmap_gid(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1420 bool handle_idmap_gid(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1421 		      const char *pszParmValue, char **ptr)
1422 {
1423 	if (lp_ctx->s3_fns) {
1424 		lp_do_parameter_parametric(lp_ctx, service, "idmap config * : range",
1425 					   pszParmValue, 0);
1426 	}
1427 
1428 	return lpcfg_string_set(lp_ctx->globals->ctx, ptr, pszParmValue);
1429 }
1430 
handle_smb_ports(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1431 bool handle_smb_ports(struct loadparm_context *lp_ctx, struct loadparm_service *service,
1432 		      const char *pszParmValue, char **ptr)
1433 {
1434 	static int parm_num = -1;
1435 	int i;
1436 	const char **list;
1437 
1438 	if (!pszParmValue || !*pszParmValue) {
1439 		return false;
1440 	}
1441 
1442 	if (parm_num == -1) {
1443 		parm_num = lpcfg_map_parameter("smb ports");
1444 		if (parm_num == -1) {
1445 			return false;
1446 		}
1447 	}
1448 
1449 	if (!set_variable_helper(lp_ctx->globals->ctx, parm_num, ptr, "smb ports",
1450 			       	pszParmValue)) {
1451 		return false;
1452 	}
1453 
1454 	list = lp_ctx->globals->smb_ports;
1455 	if (list == NULL) {
1456 		return false;
1457 	}
1458 
1459 	/* Check that each port is a valid integer and within range */
1460 	for (i = 0; list[i] != NULL; i++) {
1461 		char *end = NULL;
1462 		int port = 0;
1463 		port = strtol(list[i], &end, 10);
1464 		if (*end != '\0' || port <= 0 || port > 65535) {
1465 			TALLOC_FREE(list);
1466 			return false;
1467 		}
1468 	}
1469 
1470 	return true;
1471 }
1472 
handle_rpc_server_dynamic_port_range(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1473 bool handle_rpc_server_dynamic_port_range(struct loadparm_context *lp_ctx,
1474 					  struct loadparm_service *service,
1475 					  const char *pszParmValue,
1476 					  char **ptr)
1477 {
1478 	static int parm_num = -1;
1479 	int low_port = -1, high_port = -1;
1480 	int rc;
1481 
1482 	if (parm_num == -1) {
1483 		parm_num = lpcfg_map_parameter("rpc server dynamic port range");
1484 		if (parm_num == -1) {
1485 			return false;
1486 		}
1487 	}
1488 
1489 	if (pszParmValue == NULL || pszParmValue[0] == '\0') {
1490 		return false;
1491 	}
1492 
1493 	rc = sscanf(pszParmValue, "%d - %d", &low_port, &high_port);
1494 	if (rc != 2) {
1495 		return false;
1496 	}
1497 
1498 	if (low_port > high_port) {
1499 		return false;
1500 	}
1501 
1502 	if (low_port < SERVER_TCP_PORT_MIN|| high_port > SERVER_TCP_PORT_MAX) {
1503 		return false;
1504 	}
1505 
1506 	if (!set_variable_helper(lp_ctx->globals->ctx, parm_num, ptr,
1507 				 "rpc server dynamic port range",
1508 				 pszParmValue)) {
1509 		return false;
1510 	}
1511 
1512 	lp_ctx->globals->rpc_low_port = low_port;
1513 	lp_ctx->globals->rpc_high_port = high_port;
1514 
1515 	return true;
1516 }
1517 
handle_smb2_max_credits(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1518 bool handle_smb2_max_credits(struct loadparm_context *lp_ctx,
1519 			     struct loadparm_service *service,
1520 			     const char *pszParmValue, char **ptr)
1521 {
1522 	int value = lp_int(pszParmValue);
1523 
1524 	if (value <= 0) {
1525 		value = DEFAULT_SMB2_MAX_CREDITS;
1526 	}
1527 
1528 	*(int *)ptr = value;
1529 
1530 	return true;
1531 }
1532 
handle_cups_encrypt(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1533 bool handle_cups_encrypt(struct loadparm_context *lp_ctx,
1534 			 struct loadparm_service *service,
1535 			 const char *pszParmValue, char **ptr)
1536 {
1537 	int result = 0;
1538 #ifdef HAVE_HTTPCONNECTENCRYPT
1539 	int value = lp_int(pszParmValue);
1540 
1541 	switch (value) {
1542 		case Auto:
1543 			result = HTTP_ENCRYPT_REQUIRED;
1544 			break;
1545 		case true:
1546 			result = HTTP_ENCRYPT_ALWAYS;
1547 			break;
1548 		case false:
1549 			result = HTTP_ENCRYPT_NEVER;
1550 			break;
1551 		default:
1552 			result = 0;
1553 			break;
1554 	}
1555 #endif
1556 	*(int *)ptr = result;
1557 
1558 	return true;
1559 }
1560 
1561 /***************************************************************************
1562  Initialise a copymap.
1563 ***************************************************************************/
1564 
1565 /**
1566  * Initializes service copymap
1567  * Note: pservice *must* be valid TALLOC_CTX
1568  */
init_copymap(struct loadparm_service * pservice)1569 void init_copymap(struct loadparm_service *pservice)
1570 {
1571 	int i;
1572 
1573 	TALLOC_FREE(pservice->copymap);
1574 
1575 	pservice->copymap = bitmap_talloc(pservice, num_parameters());
1576 	if (!pservice->copymap) {
1577 		DEBUG(0,
1578 		      ("Couldn't allocate copymap!! (size %d)\n",
1579 		       (int)num_parameters()));
1580 	} else {
1581 		for (i = 0; i < num_parameters(); i++) {
1582 			bitmap_set(pservice->copymap, i);
1583 		}
1584 	}
1585 }
1586 
1587 /**
1588  * Process a parametric option
1589  */
lp_do_parameter_parametric(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmName,const char * pszParmValue,int flags)1590 static bool lp_do_parameter_parametric(struct loadparm_context *lp_ctx,
1591 				       struct loadparm_service *service,
1592 				       const char *pszParmName,
1593 				       const char *pszParmValue, int flags)
1594 {
1595 	struct parmlist_entry **data;
1596 	char *name;
1597 	TALLOC_CTX *mem_ctx;
1598 
1599 	while (isspace((unsigned char)*pszParmName)) {
1600 		pszParmName++;
1601 	}
1602 
1603 	name = strlower_talloc(lp_ctx, pszParmName);
1604 	if (!name) return false;
1605 
1606 	if (service == NULL) {
1607 		data = &lp_ctx->globals->param_opt;
1608 		/**
1609 		 * s3 code cannot deal with parametric options stored on the globals ctx.
1610 		 */
1611 		if (lp_ctx->s3_fns != NULL) {
1612 			mem_ctx = NULL;
1613 		} else {
1614 			mem_ctx = lp_ctx->globals->ctx;
1615 		}
1616 	} else {
1617 		data = &service->param_opt;
1618 		mem_ctx = service;
1619 	}
1620 
1621 	set_param_opt(mem_ctx, data, name, pszParmValue, flags);
1622 
1623 	talloc_free(name);
1624 
1625 	return true;
1626 }
1627 
set_variable_helper(TALLOC_CTX * mem_ctx,int parmnum,void * parm_ptr,const char * pszParmName,const char * pszParmValue)1628 static bool set_variable_helper(TALLOC_CTX *mem_ctx, int parmnum, void *parm_ptr,
1629 			 const char *pszParmName, const char *pszParmValue)
1630 {
1631 	size_t i;
1632 
1633 	/* switch on the type of variable it is */
1634 	switch (parm_table[parmnum].type)
1635 	{
1636 		case P_BOOL: {
1637 			bool b;
1638 			if (!set_boolean(pszParmValue, &b)) {
1639 				DEBUG(0, ("set_variable_helper(%s): value is not "
1640 					  "boolean!\n", pszParmValue));
1641 				return false;
1642 			}
1643 			*(bool *)parm_ptr = b;
1644 			}
1645 			break;
1646 
1647 		case P_BOOLREV: {
1648 			bool b;
1649 			if (!set_boolean(pszParmValue, &b)) {
1650 				DEBUG(0, ("set_variable_helper(%s): value is not "
1651 					  "boolean!\n", pszParmValue));
1652 				return false;
1653 			}
1654 			*(bool *)parm_ptr = !b;
1655 			}
1656 			break;
1657 
1658 		case P_INTEGER:
1659 			*(int *)parm_ptr = lp_int(pszParmValue);
1660 			break;
1661 
1662 		case P_CHAR:
1663 			*(char *)parm_ptr = *pszParmValue;
1664 			break;
1665 
1666 		case P_OCTAL:
1667 			i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
1668 			if ( i != 1 ) {
1669 				DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
1670 				return false;
1671 			}
1672 			break;
1673 
1674 		case P_BYTES:
1675 		{
1676 			uint64_t val;
1677 			if (conv_str_size_error(pszParmValue, &val)) {
1678 				if (val <= INT_MAX) {
1679 					*(int *)parm_ptr = (int)val;
1680 					break;
1681 				}
1682 			}
1683 
1684 			DEBUG(0, ("set_variable_helper(%s): value is not "
1685 			          "a valid size specifier!\n", pszParmValue));
1686 			return false;
1687 		}
1688 
1689 		case P_CMDLIST:
1690 			TALLOC_FREE(*(char ***)parm_ptr);
1691 			*(char ***)parm_ptr = str_list_make_v3(mem_ctx,
1692 							pszParmValue, NULL);
1693 			break;
1694 
1695 		case P_LIST:
1696 		{
1697 			char **new_list = str_list_make_v3(mem_ctx,
1698 							pszParmValue, NULL);
1699 			if (new_list == NULL) {
1700 				break;
1701 			}
1702 
1703 			for (i=0; new_list[i]; i++) {
1704 				if (*(const char ***)parm_ptr != NULL &&
1705 				    new_list[i][0] == '+' &&
1706 				    new_list[i][1])
1707 				{
1708 					if (!str_list_check(*(const char ***)parm_ptr,
1709 							    &new_list[i][1])) {
1710 						*(const char ***)parm_ptr = str_list_add(*(const char ***)parm_ptr,
1711 											 &new_list[i][1]);
1712 					}
1713 				} else if (*(const char ***)parm_ptr != NULL &&
1714 					   new_list[i][0] == '-' &&
1715 					   new_list[i][1])
1716 				{
1717 					str_list_remove(*(const char ***)parm_ptr,
1718 							&new_list[i][1]);
1719 				} else {
1720 					if (i != 0) {
1721 						DEBUG(0, ("Unsupported list syntax for: %s = %s\n",
1722 							  pszParmName, pszParmValue));
1723 						return false;
1724 					}
1725 					*(char ***)parm_ptr = new_list;
1726 					break;
1727 				}
1728 			}
1729 			break;
1730 		}
1731 
1732 		case P_STRING:
1733 			lpcfg_string_set(mem_ctx, (char **)parm_ptr, pszParmValue);
1734 			break;
1735 
1736 		case P_USTRING:
1737 			lpcfg_string_set_upper(mem_ctx, (char **)parm_ptr, pszParmValue);
1738 			break;
1739 
1740 		case P_ENUM:
1741 			if (!lp_set_enum_parm(&parm_table[parmnum], pszParmValue, (int*)parm_ptr)) {
1742 				return false;
1743 			}
1744 			break;
1745 
1746 	}
1747 
1748 	return true;
1749 
1750 }
1751 
handle_name_resolve_order(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmValue,char ** ptr)1752 bool handle_name_resolve_order(struct loadparm_context *lp_ctx,
1753 			       struct loadparm_service *service,
1754 			       const char *pszParmValue, char **ptr)
1755 {
1756 	const char **valid_values = NULL;
1757 	const char **values_to_set = NULL;
1758 	int i;
1759 	bool value_is_valid = false;
1760 	valid_values = str_list_make_v3_const(NULL,
1761 					      DEFAULT_NAME_RESOLVE_ORDER,
1762 					      NULL);
1763 	if (valid_values == NULL) {
1764 		DBG_ERR("OOM: failed to make string list from %s\n",
1765 			DEFAULT_NAME_RESOLVE_ORDER);
1766 		goto out;
1767 	}
1768 	values_to_set = str_list_make_v3_const(lp_ctx->globals->ctx,
1769 					       pszParmValue,
1770 					       NULL);
1771 	if (values_to_set == NULL) {
1772 		DBG_ERR("OOM: failed to make string list from %s\n",
1773 			pszParmValue);
1774 		goto out;
1775 	}
1776 	TALLOC_FREE(lp_ctx->globals->name_resolve_order);
1777 	for (i = 0; values_to_set[i] != NULL; i++) {
1778 		value_is_valid = str_list_check(valid_values, values_to_set[i]);
1779 		if (!value_is_valid) {
1780 			DBG_ERR("WARNING: Ignoring invalid list value '%s' "
1781 				"for parameter 'name resolve order'\n",
1782 				values_to_set[i]);
1783 			break;
1784 		}
1785 	}
1786 out:
1787 	if (value_is_valid) {
1788 		lp_ctx->globals->name_resolve_order = values_to_set;
1789 	} else {
1790 		TALLOC_FREE(values_to_set);
1791 	}
1792 	TALLOC_FREE(valid_values);
1793 	return value_is_valid;
1794 }
1795 
set_variable(TALLOC_CTX * mem_ctx,struct loadparm_service * service,int parmnum,void * parm_ptr,const char * pszParmName,const char * pszParmValue,struct loadparm_context * lp_ctx,bool on_globals)1796 static bool set_variable(TALLOC_CTX *mem_ctx, struct loadparm_service *service,
1797 			 int parmnum, void *parm_ptr,
1798 			 const char *pszParmName, const char *pszParmValue,
1799 			 struct loadparm_context *lp_ctx, bool on_globals)
1800 {
1801 	int i;
1802 	bool ok;
1803 
1804 	/* if it is a special case then go ahead */
1805 	if (parm_table[parmnum].special) {
1806 		ok = parm_table[parmnum].special(lp_ctx, service, pszParmValue,
1807 						  (char **)parm_ptr);
1808 	} else {
1809 		ok = set_variable_helper(mem_ctx, parmnum, parm_ptr,
1810 					 pszParmName, pszParmValue);
1811 	}
1812 
1813 	if (!ok) {
1814 		return false;
1815 	}
1816 
1817 	if (on_globals && (lp_ctx->flags[parmnum] & FLAG_DEFAULT)) {
1818 		lp_ctx->flags[parmnum] &= ~FLAG_DEFAULT;
1819 		/* we have to also unset FLAG_DEFAULT on aliases */
1820 		for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
1821 			lp_ctx->flags[i] &= ~FLAG_DEFAULT;
1822 		}
1823 		for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset;i++) {
1824 			lp_ctx->flags[i] &= ~FLAG_DEFAULT;
1825 		}
1826 	}
1827 	return true;
1828 }
1829 
1830 
lpcfg_do_global_parameter(struct loadparm_context * lp_ctx,const char * pszParmName,const char * pszParmValue)1831 bool lpcfg_do_global_parameter(struct loadparm_context *lp_ctx,
1832 			       const char *pszParmName, const char *pszParmValue)
1833 {
1834 	int parmnum = lpcfg_map_parameter(pszParmName);
1835 	void *parm_ptr;
1836 
1837 	if (parmnum < 0) {
1838 		if (strchr(pszParmName, ':')) {
1839 			return lp_do_parameter_parametric(lp_ctx, NULL, pszParmName, pszParmValue, 0);
1840 		}
1841 		DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1842 		return true;
1843 	}
1844 
1845 	/* if the flag has been set on the command line, then don't allow override,
1846 	   but don't report an error */
1847 	if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
1848 		return true;
1849 	}
1850 
1851 	if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1852 		DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1853 			  pszParmName));
1854 	}
1855 
1856 	parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[parmnum]);
1857 
1858 	return set_variable(lp_ctx->globals->ctx, NULL, parmnum, parm_ptr,
1859 			    pszParmName, pszParmValue, lp_ctx, true);
1860 }
1861 
lpcfg_do_service_parameter(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * pszParmName,const char * pszParmValue)1862 bool lpcfg_do_service_parameter(struct loadparm_context *lp_ctx,
1863 				struct loadparm_service *service,
1864 				const char *pszParmName, const char *pszParmValue)
1865 {
1866 	void *parm_ptr;
1867 	int i;
1868 	int parmnum = lpcfg_map_parameter(pszParmName);
1869 
1870 	if (parmnum < 0) {
1871 		if (strchr(pszParmName, ':')) {
1872 			return lp_do_parameter_parametric(lp_ctx, service, pszParmName, pszParmValue, 0);
1873 		}
1874 		DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
1875 		return true;
1876 	}
1877 
1878 	/* if the flag has been set on the command line, then don't allow override,
1879 	   but don't report an error */
1880 	if (lp_ctx->flags[parmnum] & FLAG_CMDLINE) {
1881 		return true;
1882 	}
1883 
1884 	if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
1885 		DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
1886 			  pszParmName));
1887 	}
1888 
1889 	if (parm_table[parmnum].p_class == P_GLOBAL) {
1890 		DEBUG(0,
1891 		      ("Global parameter %s found in service section!\n",
1892 		       pszParmName));
1893 		return true;
1894 	}
1895 	parm_ptr = ((char *)service) + parm_table[parmnum].offset;
1896 
1897 	if (!service->copymap)
1898 		init_copymap(service);
1899 
1900 	/* this handles the aliases - set the copymap for other
1901 	 * entries with the same data pointer */
1902 	for (i = 0; parm_table[i].label; i++)
1903 		if (parm_table[i].offset == parm_table[parmnum].offset &&
1904 		    parm_table[i].p_class == parm_table[parmnum].p_class)
1905 			bitmap_clear(service->copymap, i);
1906 
1907 	return set_variable(service, service, parmnum, parm_ptr, pszParmName,
1908 			    pszParmValue, lp_ctx, false);
1909 }
1910 
1911 /**
1912  * Process a parameter.
1913  */
1914 
lpcfg_do_parameter(const char * pszParmName,const char * pszParmValue,void * userdata)1915 bool lpcfg_do_parameter(const char *pszParmName, const char *pszParmValue,
1916 			 void *userdata)
1917 {
1918 	struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
1919 
1920 	if (lp_ctx->bInGlobalSection)
1921 		return lpcfg_do_global_parameter(lp_ctx, pszParmName,
1922 					      pszParmValue);
1923 	else
1924 		return lpcfg_do_service_parameter(lp_ctx, lp_ctx->currentService,
1925 						  pszParmName, pszParmValue);
1926 }
1927 
1928 /*
1929   variable argument do parameter
1930 */
1931 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx, const char *pszParmName, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
lpcfg_do_global_parameter_var(struct loadparm_context * lp_ctx,const char * pszParmName,const char * fmt,...)1932 bool lpcfg_do_global_parameter_var(struct loadparm_context *lp_ctx,
1933 				const char *pszParmName, const char *fmt, ...)
1934 {
1935 	char *s;
1936 	bool ret;
1937 	va_list ap;
1938 
1939 	va_start(ap, fmt);
1940 	s = talloc_vasprintf(NULL, fmt, ap);
1941 	va_end(ap);
1942 	ret = lpcfg_do_global_parameter(lp_ctx, pszParmName, s);
1943 	talloc_free(s);
1944 	return ret;
1945 }
1946 
1947 
1948 /*
1949   set a parameter from the commandline - this is called from command line parameter
1950   parsing code. It sets the parameter then marks the parameter as unable to be modified
1951   by smb.conf processing
1952 */
lpcfg_set_cmdline(struct loadparm_context * lp_ctx,const char * pszParmName,const char * pszParmValue)1953 bool lpcfg_set_cmdline(struct loadparm_context *lp_ctx, const char *pszParmName,
1954 		       const char *pszParmValue)
1955 {
1956 	int parmnum;
1957 	int i;
1958 
1959 	while (isspace((unsigned char)*pszParmValue)) pszParmValue++;
1960 
1961 	parmnum = lpcfg_map_parameter(pszParmName);
1962 
1963 	if (parmnum < 0 && strchr(pszParmName, ':')) {
1964 		/* set a parametric option */
1965 		bool ok;
1966 		ok = lp_do_parameter_parametric(lp_ctx, NULL, pszParmName,
1967 						pszParmValue, FLAG_CMDLINE);
1968 		if (lp_ctx->s3_fns != NULL) {
1969 			if (ok) {
1970 				lp_ctx->s3_fns->store_cmdline(pszParmName, pszParmValue);
1971 			}
1972 		}
1973 		return ok;
1974 	}
1975 
1976 	if (parmnum < 0) {
1977 		DEBUG(0,("Unknown option '%s'\n", pszParmName));
1978 		return false;
1979 	}
1980 
1981 	/* reset the CMDLINE flag in case this has been called before */
1982 	lp_ctx->flags[parmnum] &= ~FLAG_CMDLINE;
1983 
1984 	if (!lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue)) {
1985 		return false;
1986 	}
1987 
1988 	lp_ctx->flags[parmnum] |= FLAG_CMDLINE;
1989 
1990 	/* we have to also set FLAG_CMDLINE on aliases */
1991 	for (i=parmnum-1;
1992 	     i>=0 && parm_table[i].p_class == parm_table[parmnum].p_class &&
1993 	     parm_table[i].offset == parm_table[parmnum].offset;
1994 	     i--) {
1995 		lp_ctx->flags[i] |= FLAG_CMDLINE;
1996 	}
1997 	for (i=parmnum+1;
1998 	     i<num_parameters() &&
1999 	     parm_table[i].p_class == parm_table[parmnum].p_class &&
2000 	     parm_table[i].offset == parm_table[parmnum].offset;
2001 	     i++) {
2002 		lp_ctx->flags[i] |= FLAG_CMDLINE;
2003 	}
2004 
2005 	if (lp_ctx->s3_fns != NULL) {
2006 		lp_ctx->s3_fns->store_cmdline(pszParmName, pszParmValue);
2007 	}
2008 
2009 	return true;
2010 }
2011 
2012 /*
2013   set a option from the commandline in 'a=b' format. Use to support --option
2014 */
lpcfg_set_option(struct loadparm_context * lp_ctx,const char * option)2015 bool lpcfg_set_option(struct loadparm_context *lp_ctx, const char *option)
2016 {
2017 	char *p, *s;
2018 	bool ret;
2019 
2020 	s = talloc_strdup(NULL, option);
2021 	if (!s) {
2022 		return false;
2023 	}
2024 
2025 	p = strchr(s, '=');
2026 	if (!p) {
2027 		talloc_free(s);
2028 		return false;
2029 	}
2030 
2031 	*p = 0;
2032 
2033 	ret = lpcfg_set_cmdline(lp_ctx, s, p+1);
2034 	talloc_free(s);
2035 	return ret;
2036 }
2037 
2038 
2039 #define BOOLSTR(b) ((b) ? "Yes" : "No")
2040 
2041 /**
2042  * Print a parameter of the specified type.
2043  */
2044 
lpcfg_print_parameter(struct parm_struct * p,void * ptr,FILE * f)2045 void lpcfg_print_parameter(struct parm_struct *p, void *ptr, FILE * f)
2046 {
2047 	/* For the seperation of lists values that we print below */
2048 	const char *list_sep = ", ";
2049 	int i;
2050 	switch (p->type)
2051 	{
2052 		case P_ENUM:
2053 			for (i = 0; p->enum_list[i].name; i++) {
2054 				if (*(int *)ptr == p->enum_list[i].value) {
2055 					fprintf(f, "%s",
2056 						p->enum_list[i].name);
2057 					break;
2058 				}
2059 			}
2060 			break;
2061 
2062 		case P_BOOL:
2063 			fprintf(f, "%s", BOOLSTR(*(bool *)ptr));
2064 			break;
2065 
2066 		case P_BOOLREV:
2067 			fprintf(f, "%s", BOOLSTR(!*(bool *)ptr));
2068 			break;
2069 
2070 		case P_INTEGER:
2071 		case P_BYTES:
2072 			fprintf(f, "%d", *(int *)ptr);
2073 			break;
2074 
2075 		case P_CHAR:
2076 			fprintf(f, "%c", *(char *)ptr);
2077 			break;
2078 
2079 		case P_OCTAL: {
2080 			int val = *(int *)ptr;
2081 			if (val == -1) {
2082 				fprintf(f, "-1");
2083 			} else {
2084 				fprintf(f, "0%03o", val);
2085 			}
2086 			break;
2087 		}
2088 
2089 		case P_CMDLIST:
2090 			list_sep = " ";
2091 
2092 			FALL_THROUGH;
2093 		case P_LIST:
2094 			if ((char ***)ptr && *(char ***)ptr) {
2095 				char **list = *(char ***)ptr;
2096 				for (; *list; list++) {
2097 					/* surround strings with whitespace in double quotes */
2098 					if (*(list+1) == NULL) {
2099 						/* last item, no extra separator */
2100 						list_sep = "";
2101 					}
2102 					if ( strchr_m( *list, ' ' ) ) {
2103 						fprintf(f, "\"%s\"%s", *list, list_sep);
2104 					} else {
2105 						fprintf(f, "%s%s", *list, list_sep);
2106 					}
2107 				}
2108 			}
2109 			break;
2110 
2111 		case P_STRING:
2112 		case P_USTRING:
2113 			if (*(char **)ptr) {
2114 				fprintf(f, "%s", *(char **)ptr);
2115 			}
2116 			break;
2117 	}
2118 }
2119 
2120 /**
2121  * Check if two parameters are equal.
2122  */
2123 
lpcfg_equal_parameter(parm_type type,void * ptr1,void * ptr2)2124 static bool lpcfg_equal_parameter(parm_type type, void *ptr1, void *ptr2)
2125 {
2126 	switch (type) {
2127 		case P_BOOL:
2128 		case P_BOOLREV:
2129 			return (*((bool *)ptr1) == *((bool *)ptr2));
2130 
2131 		case P_INTEGER:
2132 		case P_ENUM:
2133 		case P_OCTAL:
2134 		case P_BYTES:
2135 			return (*((int *)ptr1) == *((int *)ptr2));
2136 
2137 		case P_CHAR:
2138 			return (*((char *)ptr1) == *((char *)ptr2));
2139 
2140 		case P_LIST:
2141 		case P_CMDLIST:
2142 			return str_list_equal(*(const char ***)ptr1, *(const char ***)ptr2);
2143 
2144 		case P_STRING:
2145 		case P_USTRING:
2146 		{
2147 			char *p1 = *(char **)ptr1, *p2 = *(char **)ptr2;
2148 			if (p1 && !*p1)
2149 				p1 = NULL;
2150 			if (p2 && !*p2)
2151 				p2 = NULL;
2152 			return (p1 == p2 || strequal(p1, p2));
2153 		}
2154 	}
2155 	return false;
2156 }
2157 
2158 /**
2159  * Process a new section (service).
2160  *
2161  * At this stage all sections are services.
2162  * Later we'll have special sections that permit server parameters to be set.
2163  * Returns True on success, False on failure.
2164  */
2165 
do_section(const char * pszSectionName,void * userdata)2166 static bool do_section(const char *pszSectionName, void *userdata)
2167 {
2168 	struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
2169 	bool bRetval;
2170 	bool isglobal;
2171 
2172 	if (lp_ctx->s3_fns != NULL) {
2173 		return lp_ctx->s3_fns->do_section(pszSectionName, lp_ctx);
2174 	}
2175 
2176 	isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
2177 			 (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
2178 
2179 	/* if we've just struck a global section, note the fact. */
2180 	lp_ctx->bInGlobalSection = isglobal;
2181 
2182 	/* check for multiple global sections */
2183 	if (lp_ctx->bInGlobalSection) {
2184 		DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
2185 		bRetval = true;
2186 		goto out;
2187 	}
2188 
2189 	/* if we have a current service, tidy it up before moving on */
2190 	bRetval = true;
2191 
2192 	if (lp_ctx->currentService != NULL)
2193 		bRetval = lpcfg_service_ok(lp_ctx->currentService);
2194 
2195 	/* if all is still well, move to the next record in the services array */
2196 	if (bRetval) {
2197 		/* We put this here to avoid an odd message order if messages are */
2198 		/* issued by the post-processing of a previous section. */
2199 		DEBUG(4, ("Processing section \"[%s]\"\n", pszSectionName));
2200 
2201 		if ((lp_ctx->currentService = lpcfg_add_service(lp_ctx, lp_ctx->sDefault,
2202 								   pszSectionName))
2203 		    == NULL) {
2204 			DEBUG(0, ("Failed to add a new service\n"));
2205 			bRetval = false;
2206 			goto out;
2207 		}
2208 	}
2209 out:
2210 	return bRetval;
2211 }
2212 
2213 
2214 /**
2215  * Determine if a particular base parameter is currently set to the default value.
2216  */
2217 
is_default(void * base_structure,int i)2218 static bool is_default(void *base_structure, int i)
2219 {
2220 	void *def_ptr = ((char *)base_structure) + parm_table[i].offset;
2221 	switch (parm_table[i].type) {
2222 		case P_CMDLIST:
2223 		case P_LIST:
2224 			return str_list_equal((const char * const *)parm_table[i].def.lvalue,
2225 					      *(const char * const **)def_ptr);
2226 		case P_STRING:
2227 		case P_USTRING:
2228 			return strequal(parm_table[i].def.svalue,
2229 					*(char **)def_ptr);
2230 		case P_BOOL:
2231 		case P_BOOLREV:
2232 			return parm_table[i].def.bvalue ==
2233 				*(bool *)def_ptr;
2234 		case P_INTEGER:
2235 		case P_CHAR:
2236 		case P_OCTAL:
2237 		case P_BYTES:
2238 		case P_ENUM:
2239 			return parm_table[i].def.ivalue ==
2240 				*(int *)def_ptr;
2241 	}
2242 	return false;
2243 }
2244 
2245 /**
2246  *Display the contents of the global structure.
2247  */
2248 
lpcfg_dump_globals(struct loadparm_context * lp_ctx,FILE * f,bool show_defaults)2249 void lpcfg_dump_globals(struct loadparm_context *lp_ctx, FILE *f,
2250 			 bool show_defaults)
2251 {
2252 	int i;
2253 	struct parmlist_entry *data;
2254 
2255 	fprintf(f, "# Global parameters\n[global]\n");
2256 
2257 	for (i = 0; parm_table[i].label; i++) {
2258 		if (parm_table[i].p_class != P_GLOBAL) {
2259 			continue;
2260 		}
2261 
2262 		if (parm_table[i].flags & FLAG_SYNONYM) {
2263 			continue;
2264 		}
2265 
2266 		if (!show_defaults) {
2267 			if (lp_ctx->flags && (lp_ctx->flags[i] & FLAG_DEFAULT)) {
2268 				continue;
2269 			}
2270 
2271 			if (is_default(lp_ctx->globals, i)) {
2272 				continue;
2273 			}
2274 		}
2275 
2276 		fprintf(f, "\t%s = ", parm_table[i].label);
2277 		lpcfg_print_parameter(&parm_table[i], lpcfg_parm_ptr(lp_ctx, NULL, &parm_table[i]), f);
2278 		fprintf(f, "\n");
2279 	}
2280 	if (lp_ctx->globals->param_opt != NULL) {
2281 		for (data = lp_ctx->globals->param_opt; data;
2282 		     data = data->next) {
2283 			if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
2284 				continue;
2285 			}
2286 			fprintf(f, "\t%s = %s\n", data->key, data->value);
2287 		}
2288         }
2289 
2290 }
2291 
2292 /**
2293  * Display the contents of a single services record.
2294  */
2295 
lpcfg_dump_a_service(struct loadparm_service * pService,struct loadparm_service * sDefault,FILE * f,unsigned int * flags,bool show_defaults)2296 void lpcfg_dump_a_service(struct loadparm_service * pService, struct loadparm_service *sDefault, FILE * f,
2297 			  unsigned int *flags, bool show_defaults)
2298 {
2299 	int i;
2300 	struct parmlist_entry *data;
2301 
2302 	if (pService != sDefault)
2303 		fprintf(f, "\n[%s]\n", pService->szService);
2304 
2305 	for (i = 0; parm_table[i].label; i++) {
2306 		if (parm_table[i].p_class != P_LOCAL) {
2307 			continue;
2308 		}
2309 
2310 		if (parm_table[i].flags & FLAG_SYNONYM) {
2311 			continue;
2312 		}
2313 
2314 		if (*parm_table[i].label == '-') {
2315 			continue;
2316 		}
2317 
2318 		if (pService == sDefault) {
2319 			if (!show_defaults) {
2320 				if (flags && (flags[i] & FLAG_DEFAULT)) {
2321 					continue;
2322 				}
2323 
2324 				if (is_default(sDefault, i)) {
2325 					continue;
2326 				}
2327 			}
2328 		} else {
2329 			bool equal;
2330 
2331 			equal = lpcfg_equal_parameter(parm_table[i].type,
2332 						      ((char *)pService) +
2333 						      parm_table[i].offset,
2334 						      ((char *)sDefault) +
2335 						      parm_table[i].offset);
2336 			if (equal) {
2337 				continue;
2338 			}
2339 		}
2340 
2341 		fprintf(f, "\t%s = ", parm_table[i].label);
2342 		lpcfg_print_parameter(&parm_table[i],
2343 				((char *)pService) + parm_table[i].offset, f);
2344 		fprintf(f, "\n");
2345 	}
2346 	if (pService->param_opt != NULL) {
2347 		for (data = pService->param_opt; data; data = data->next) {
2348 			if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
2349 				continue;
2350 			}
2351 			fprintf(f, "\t%s = %s\n", data->key, data->value);
2352 		}
2353         }
2354 }
2355 
lpcfg_dump_a_parameter(struct loadparm_context * lp_ctx,struct loadparm_service * service,const char * parm_name,FILE * f)2356 bool lpcfg_dump_a_parameter(struct loadparm_context *lp_ctx,
2357 			    struct loadparm_service *service,
2358 			    const char *parm_name, FILE * f)
2359 {
2360 	struct parm_struct *parm;
2361 	void *ptr;
2362 	char *local_parm_name;
2363 	char *parm_opt;
2364 	const char *parm_opt_value;
2365 
2366 	/* check for parametrical option */
2367 	local_parm_name = talloc_strdup(lp_ctx, parm_name);
2368 	if (local_parm_name == NULL) {
2369 		return false;
2370 	}
2371 
2372 	parm_opt = strchr( local_parm_name, ':');
2373 
2374 	if (parm_opt) {
2375 		*parm_opt = '\0';
2376 		parm_opt++;
2377 		if (strlen(parm_opt)) {
2378 			parm_opt_value = lpcfg_parm_string(lp_ctx, service,
2379 				local_parm_name, parm_opt);
2380 			if (parm_opt_value) {
2381 				fprintf(f, "%s\n", parm_opt_value);
2382 				return true;
2383 			}
2384 		}
2385 		return false;
2386 	}
2387 
2388 	/* parameter is not parametric, search the table */
2389 	parm = lpcfg_parm_struct(lp_ctx, parm_name);
2390 	if (!parm) {
2391 		return false;
2392 	}
2393 
2394 	if (service != NULL && parm->p_class == P_GLOBAL) {
2395 		return false;
2396 	}
2397 
2398 	ptr = lpcfg_parm_ptr(lp_ctx, service,parm);
2399 
2400 	lpcfg_print_parameter(parm, ptr, f);
2401 	fprintf(f, "\n");
2402 	return true;
2403 }
2404 
2405 /**
2406  * Auto-load some home services.
2407  */
lpcfg_add_auto_services(struct loadparm_context * lp_ctx,const char * str)2408 static void lpcfg_add_auto_services(struct loadparm_context *lp_ctx,
2409 				    const char *str)
2410 {
2411 	return;
2412 }
2413 
2414 /***************************************************************************
2415  Initialise the sDefault parameter structure for the printer values.
2416 ***************************************************************************/
2417 
init_printer_values(struct loadparm_context * lp_ctx,TALLOC_CTX * ctx,struct loadparm_service * pService)2418 void init_printer_values(struct loadparm_context *lp_ctx, TALLOC_CTX *ctx,
2419 			 struct loadparm_service *pService)
2420 {
2421 	/* choose defaults depending on the type of printing */
2422 	switch (pService->printing) {
2423 		case PRINT_BSD:
2424 		case PRINT_AIX:
2425 		case PRINT_LPRNT:
2426 		case PRINT_LPROS2:
2427 			lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
2428 			lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
2429 			lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
2430 			break;
2431 
2432 		case PRINT_LPRNG:
2433 		case PRINT_PLP:
2434 			lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
2435 			lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
2436 			lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
2437 			lpcfg_string_set(ctx, &pService->queuepause_command, "lpc stop '%p'");
2438 			lpcfg_string_set(ctx, &pService->queueresume_command, "lpc start '%p'");
2439 			lpcfg_string_set(ctx, &pService->lppause_command, "lpc hold '%p' %j");
2440 			lpcfg_string_set(ctx, &pService->lpresume_command, "lpc release '%p' %j");
2441 			break;
2442 
2443 		case PRINT_CUPS:
2444 		case PRINT_IPRINT:
2445 			/* set the lpq command to contain the destination printer
2446 			   name only.  This is used by cups_queue_get() */
2447 			lpcfg_string_set(ctx, &pService->lpq_command, "%p");
2448 			lpcfg_string_set(ctx, &pService->lprm_command, "");
2449 			lpcfg_string_set(ctx, &pService->print_command, "");
2450 			lpcfg_string_set(ctx, &pService->lppause_command, "");
2451 			lpcfg_string_set(ctx, &pService->lpresume_command, "");
2452 			lpcfg_string_set(ctx, &pService->queuepause_command, "");
2453 			lpcfg_string_set(ctx, &pService->queueresume_command, "");
2454 			break;
2455 
2456 		case PRINT_SYSV:
2457 		case PRINT_HPUX:
2458 			lpcfg_string_set(ctx, &pService->lpq_command, "lpstat -o%p");
2459 			lpcfg_string_set(ctx, &pService->lprm_command, "cancel %p-%j");
2460 			lpcfg_string_set(ctx, &pService->print_command, "lp -c -d%p %s; rm %s");
2461 			lpcfg_string_set(ctx, &pService->queuepause_command, "disable %p");
2462 			lpcfg_string_set(ctx, &pService->queueresume_command, "enable %p");
2463 #ifndef HPUX
2464 			lpcfg_string_set(ctx, &pService->lppause_command, "lp -i %p-%j -H hold");
2465 			lpcfg_string_set(ctx, &pService->lpresume_command, "lp -i %p-%j -H resume");
2466 #endif /* HPUX */
2467 			break;
2468 
2469 		case PRINT_QNX:
2470 			lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P%p");
2471 			lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P%p %j");
2472 			lpcfg_string_set(ctx, &pService->print_command, "lp -r -P%p %s");
2473 			break;
2474 
2475 #if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
2476 
2477 	case PRINT_TEST:
2478 	case PRINT_VLP: {
2479 		const char *tdbfile;
2480 		TALLOC_CTX *tmp_ctx = talloc_new(ctx);
2481 		const char *tmp;
2482 
2483 		tmp = lpcfg_parm_string(lp_ctx, NULL, "vlp", "tdbfile");
2484 		if (tmp == NULL) {
2485 			tmp = "/tmp/vlp.tdb";
2486 		}
2487 
2488 		tdbfile = talloc_asprintf(tmp_ctx, "tdbfile=%s", tmp);
2489 		if (tdbfile == NULL) {
2490 			tdbfile="tdbfile=/tmp/vlp.tdb";
2491 		}
2492 
2493 		tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
2494 				      tdbfile);
2495 		lpcfg_string_set(ctx, &pService->print_command,
2496 			   tmp ? tmp : "vlp print %p %s");
2497 
2498 		tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
2499 				      tdbfile);
2500 		lpcfg_string_set(ctx, &pService->lpq_command,
2501 			   tmp ? tmp : "vlp lpq %p");
2502 
2503 		tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
2504 				      tdbfile);
2505 		lpcfg_string_set(ctx, &pService->lprm_command,
2506 			   tmp ? tmp : "vlp lprm %p %j");
2507 
2508 		tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
2509 				      tdbfile);
2510 		lpcfg_string_set(ctx, &pService->lppause_command,
2511 			   tmp ? tmp : "vlp lppause %p %j");
2512 
2513 		tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
2514 				      tdbfile);
2515 		lpcfg_string_set(ctx, &pService->lpresume_command,
2516 			   tmp ? tmp : "vlp lpresume %p %j");
2517 
2518 		tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
2519 				      tdbfile);
2520 		lpcfg_string_set(ctx, &pService->queuepause_command,
2521 			   tmp ? tmp : "vlp queuepause %p");
2522 
2523 		tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
2524 				      tdbfile);
2525 		lpcfg_string_set(ctx, &pService->queueresume_command,
2526 			   tmp ? tmp : "vlp queueresume %p");
2527 		TALLOC_FREE(tmp_ctx);
2528 
2529 		break;
2530 	}
2531 #endif /* DEVELOPER */
2532 
2533 	}
2534 }
2535 
2536 /**
2537  * Unload unused services.
2538  */
2539 
lpcfg_killunused(struct loadparm_context * lp_ctx,struct smbsrv_connection * smb,bool (* snumused)(struct smbsrv_connection *,int))2540 void lpcfg_killunused(struct loadparm_context *lp_ctx,
2541 		   struct smbsrv_connection *smb,
2542 		   bool (*snumused) (struct smbsrv_connection *, int))
2543 {
2544 	int i;
2545 
2546 	if (lp_ctx->s3_fns != NULL) {
2547 		smb_panic("Cannot be used from an s3 loadparm ctx");
2548 	}
2549 
2550 	for (i = 0; i < lp_ctx->iNumServices; i++) {
2551 		if (lp_ctx->services[i] == NULL)
2552 			continue;
2553 
2554 		if (!snumused || !snumused(smb, i)) {
2555 			talloc_free(lp_ctx->services[i]);
2556 			lp_ctx->services[i] = NULL;
2557 		}
2558 	}
2559 }
2560 
2561 
lpcfg_destructor(struct loadparm_context * lp_ctx)2562 static int lpcfg_destructor(struct loadparm_context *lp_ctx)
2563 {
2564 	struct parmlist_entry *data;
2565 
2566 	if (lp_ctx->refuse_free) {
2567 		/* someone is trying to free the
2568 		   global_loadparm_context.
2569 		   We can't allow that. */
2570 		return -1;
2571 	}
2572 
2573 	if (lp_ctx->globals->param_opt != NULL) {
2574 		struct parmlist_entry *next;
2575 		for (data = lp_ctx->globals->param_opt; data; data=next) {
2576 			next = data->next;
2577 			if (data->priority & FLAG_CMDLINE) continue;
2578 			DLIST_REMOVE(lp_ctx->globals->param_opt, data);
2579 			talloc_free(data);
2580 		}
2581 	}
2582 
2583 	return 0;
2584 }
2585 
2586 /**
2587  * Initialise the global parameter structure.
2588  *
2589  * Note that most callers should use loadparm_init_global() instead
2590  */
loadparm_init(TALLOC_CTX * mem_ctx)2591 struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
2592 {
2593 	int i;
2594 	char *myname;
2595 	struct loadparm_context *lp_ctx;
2596 	struct parmlist_entry *parm;
2597 	char *logfile;
2598 
2599 	lp_ctx = talloc_zero(mem_ctx, struct loadparm_context);
2600 	if (lp_ctx == NULL)
2601 		return NULL;
2602 
2603 	talloc_set_destructor(lp_ctx, lpcfg_destructor);
2604 	lp_ctx->bInGlobalSection = true;
2605 	lp_ctx->globals = talloc_zero(lp_ctx, struct loadparm_global);
2606 	/* This appears odd, but globals in s3 isn't a pointer */
2607 	lp_ctx->globals->ctx = lp_ctx->globals;
2608 	lp_ctx->globals->rpc_low_port = SERVER_TCP_LOW_PORT;
2609 	lp_ctx->globals->rpc_high_port = SERVER_TCP_HIGH_PORT;
2610 	lp_ctx->sDefault = talloc_zero(lp_ctx, struct loadparm_service);
2611 	lp_ctx->flags = talloc_zero_array(lp_ctx, unsigned int, num_parameters());
2612 
2613 	lp_ctx->sDefault->max_print_jobs = 1000;
2614 	lp_ctx->sDefault->available = true;
2615 	lp_ctx->sDefault->browseable = true;
2616 	lp_ctx->sDefault->read_only = true;
2617 	lp_ctx->sDefault->map_archive = true;
2618 	lp_ctx->sDefault->strict_locking = true;
2619 	lp_ctx->sDefault->oplocks = true;
2620 	lp_ctx->sDefault->create_mask = 0744;
2621 	lp_ctx->sDefault->force_create_mode = 0000;
2622 	lp_ctx->sDefault->directory_mask = 0755;
2623 	lp_ctx->sDefault->force_directory_mode = 0000;
2624 	lp_ctx->sDefault->aio_read_size = 1;
2625 	lp_ctx->sDefault->aio_write_size = 1;
2626 	lp_ctx->sDefault->smbd_search_ask_sharemode = true;
2627 	lp_ctx->sDefault->smbd_getinfo_ask_sharemode = true;
2628 
2629 	DEBUG(3, ("Initialising global parameters\n"));
2630 
2631 	for (i = 0; parm_table[i].label; i++) {
2632 		if ((parm_table[i].type == P_STRING ||
2633 		     parm_table[i].type == P_USTRING) &&
2634 		    !(lp_ctx->flags[i] & FLAG_CMDLINE)) {
2635 			TALLOC_CTX *parent_mem;
2636 			char **r;
2637 			if (parm_table[i].p_class == P_LOCAL) {
2638 				parent_mem = lp_ctx->sDefault;
2639 				r = (char **)(((char *)lp_ctx->sDefault) + parm_table[i].offset);
2640 			} else {
2641 				parent_mem = lp_ctx->globals;
2642 				r = (char **)(((char *)lp_ctx->globals) + parm_table[i].offset);
2643 			}
2644 			lpcfg_string_set(parent_mem, r, "");
2645 		}
2646 	}
2647 
2648 	logfile = talloc_asprintf(lp_ctx, "%s/log.samba", dyn_LOGFILEBASE);
2649 	lpcfg_do_global_parameter(lp_ctx, "log file", logfile);
2650 	talloc_free(logfile);
2651 
2652 	lpcfg_do_global_parameter(lp_ctx, "log level", "0");
2653 
2654 	lpcfg_do_global_parameter(lp_ctx, "syslog", "1");
2655 	lpcfg_do_global_parameter(lp_ctx, "syslog only", "No");
2656 	lpcfg_do_global_parameter(lp_ctx, "debug timestamp", "Yes");
2657 	lpcfg_do_global_parameter(lp_ctx, "debug prefix timestamp", "No");
2658 	lpcfg_do_global_parameter(lp_ctx, "debug hires timestamp", "Yes");
2659 	lpcfg_do_global_parameter(lp_ctx, "debug pid", "No");
2660 	lpcfg_do_global_parameter(lp_ctx, "debug uid", "No");
2661 	lpcfg_do_global_parameter(lp_ctx, "debug class", "No");
2662 
2663 	lpcfg_do_global_parameter(lp_ctx, "share backend", "classic");
2664 
2665 	lpcfg_do_global_parameter(lp_ctx, "server role", "auto");
2666 	lpcfg_do_global_parameter(lp_ctx, "domain logons", "No");
2667 	lpcfg_do_global_parameter(lp_ctx, "domain master", "Auto");
2668 
2669 	/* options that can be set on the command line must be initialised via
2670 	   the slower lpcfg_do_global_parameter() to ensure that FLAG_CMDLINE is obeyed */
2671 #ifdef TCP_NODELAY
2672 	lpcfg_do_global_parameter(lp_ctx, "socket options", "TCP_NODELAY");
2673 #endif
2674 	lpcfg_do_global_parameter(lp_ctx, "workgroup", DEFAULT_WORKGROUP);
2675 	myname = get_myname(lp_ctx);
2676 	lpcfg_do_global_parameter(lp_ctx, "netbios name", myname);
2677 	talloc_free(myname);
2678 	lpcfg_do_global_parameter(lp_ctx,
2679 				  "name resolve order",
2680 				  DEFAULT_NAME_RESOLVE_ORDER);
2681 
2682 	lpcfg_do_global_parameter(lp_ctx, "fstype", "NTFS");
2683 
2684 	lpcfg_do_global_parameter(lp_ctx, "ntvfs handler", "unixuid default");
2685 	lpcfg_do_global_parameter(lp_ctx, "max connections", "0");
2686 
2687 	lpcfg_do_global_parameter(lp_ctx, "dcerpc endpoint servers", "epmapper wkssvc rpcecho samr netlogon lsarpc drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver");
2688 	lpcfg_do_global_parameter(lp_ctx, "server services", "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns");
2689 	lpcfg_do_global_parameter(lp_ctx, "kccsrv:samba_kcc", "true");
2690 	/* the winbind method for domain controllers is for both RODC
2691 	   auth forwarding and for trusted domains */
2692 	lpcfg_do_global_parameter(lp_ctx, "private dir", dyn_PRIVATE_DIR);
2693 	lpcfg_do_global_parameter(lp_ctx, "binddns dir", dyn_BINDDNS_DIR);
2694 	lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_LOCAL_MACHINE", "hklm.ldb");
2695 
2696 	/* This hive should be dynamically generated by Samba using
2697 	   data from the sam, but for the moment leave it in a tdb to
2698 	   keep regedt32 from popping up an annoying dialog. */
2699 	lpcfg_do_global_parameter(lp_ctx, "registry:HKEY_USERS", "hku.ldb");
2700 
2701 	/* using UTF8 by default allows us to support all chars */
2702 	lpcfg_do_global_parameter(lp_ctx, "unix charset", "UTF-8");
2703 
2704 	/* Use codepage 850 as a default for the dos character set */
2705 	lpcfg_do_global_parameter(lp_ctx, "dos charset", "CP850");
2706 
2707 	/*
2708 	 * Allow the default PASSWD_CHAT to be overridden in local.h.
2709 	 */
2710 	lpcfg_do_global_parameter(lp_ctx, "passwd chat", DEFAULT_PASSWD_CHAT);
2711 
2712 	lpcfg_do_global_parameter(lp_ctx, "pid directory", dyn_PIDDIR);
2713 	lpcfg_do_global_parameter(lp_ctx, "lock dir", dyn_LOCKDIR);
2714 	lpcfg_do_global_parameter(lp_ctx, "state directory", dyn_STATEDIR);
2715 	lpcfg_do_global_parameter(lp_ctx, "cache directory", dyn_CACHEDIR);
2716 	lpcfg_do_global_parameter(lp_ctx, "ncalrpc dir", dyn_NCALRPCDIR);
2717 
2718 	lpcfg_do_global_parameter(lp_ctx, "nbt client socket address", "0.0.0.0");
2719 	lpcfg_do_global_parameter_var(lp_ctx, "server string",
2720 				   "Samba %s", SAMBA_VERSION_STRING);
2721 
2722 	lpcfg_do_global_parameter(lp_ctx, "password server", "*");
2723 
2724 	lpcfg_do_global_parameter(lp_ctx, "max mux", "50");
2725 	lpcfg_do_global_parameter(lp_ctx, "max xmit", "16644");
2726 	lpcfg_do_global_parameter(lp_ctx, "host msdfs", "true");
2727 
2728 	lpcfg_do_global_parameter(lp_ctx, "LargeReadwrite", "True");
2729 	lpcfg_do_global_parameter(lp_ctx, "server min protocol", "SMB2_02");
2730 	lpcfg_do_global_parameter(lp_ctx, "server max protocol", "SMB3");
2731 	lpcfg_do_global_parameter(lp_ctx, "client min protocol", "SMB2_02");
2732 	lpcfg_do_global_parameter(lp_ctx, "client max protocol", "default");
2733 	lpcfg_do_global_parameter(lp_ctx, "client ipc min protocol", "default");
2734 	lpcfg_do_global_parameter(lp_ctx, "client ipc max protocol", "default");
2735 	lpcfg_do_global_parameter(lp_ctx, "security", "AUTO");
2736 	lpcfg_do_global_parameter(lp_ctx, "EncryptPasswords", "True");
2737 	lpcfg_do_global_parameter(lp_ctx, "ReadRaw", "True");
2738 	lpcfg_do_global_parameter(lp_ctx, "WriteRaw", "True");
2739 	lpcfg_do_global_parameter(lp_ctx, "NullPasswords", "False");
2740 	lpcfg_do_global_parameter(lp_ctx, "old password allowed period", "60");
2741 	lpcfg_do_global_parameter(lp_ctx, "ObeyPamRestrictions", "False");
2742 
2743 	lpcfg_do_global_parameter(lp_ctx, "TimeServer", "False");
2744 	lpcfg_do_global_parameter(lp_ctx, "BindInterfacesOnly", "False");
2745 	lpcfg_do_global_parameter(lp_ctx, "Unicode", "True");
2746 	lpcfg_do_global_parameter(lp_ctx, "ClientLanManAuth", "False");
2747 	lpcfg_do_global_parameter(lp_ctx, "ClientNTLMv2Auth", "True");
2748 	lpcfg_do_global_parameter(lp_ctx, "LanmanAuth", "False");
2749 	lpcfg_do_global_parameter(lp_ctx, "NTLMAuth", "ntlmv2-only");
2750 	lpcfg_do_global_parameter(lp_ctx, "RawNTLMv2Auth", "False");
2751 	lpcfg_do_global_parameter(lp_ctx, "client use spnego principal", "False");
2752 
2753 	lpcfg_do_global_parameter(lp_ctx, "allow dcerpc auth level connect", "False");
2754 
2755 	lpcfg_do_global_parameter(lp_ctx, "UnixExtensions", "True");
2756 
2757 	lpcfg_do_global_parameter(lp_ctx, "PreferredMaster", "Auto");
2758 	lpcfg_do_global_parameter(lp_ctx, "LocalMaster", "True");
2759 
2760 	lpcfg_do_global_parameter(lp_ctx, "wins support", "False");
2761 	lpcfg_do_global_parameter(lp_ctx, "dns proxy", "True");
2762 
2763 	lpcfg_do_global_parameter(lp_ctx, "winbind separator", "\\");
2764 	lpcfg_do_global_parameter(lp_ctx, "winbind sealed pipes", "True");
2765 	lpcfg_do_global_parameter(lp_ctx, "winbind scan trusted domains", "True");
2766 	lpcfg_do_global_parameter(lp_ctx, "require strong key", "True");
2767 	lpcfg_do_global_parameter(lp_ctx, "winbindd socket directory", dyn_WINBINDD_SOCKET_DIR);
2768 	lpcfg_do_global_parameter(lp_ctx, "ntp signd socket directory", dyn_NTP_SIGND_SOCKET_DIR);
2769 	lpcfg_do_global_parameter_var(lp_ctx, "gpo update command", "%s/samba-gpupdate", dyn_SCRIPTSBINDIR);
2770 	lpcfg_do_global_parameter_var(lp_ctx, "apply group policies", "False");
2771 	lpcfg_do_global_parameter_var(lp_ctx, "dns update command", "%s/samba_dnsupdate", dyn_SCRIPTSBINDIR);
2772 	lpcfg_do_global_parameter_var(lp_ctx, "spn update command", "%s/samba_spnupdate", dyn_SCRIPTSBINDIR);
2773 	lpcfg_do_global_parameter_var(lp_ctx, "samba kcc command",
2774 					"%s/samba_kcc", dyn_SCRIPTSBINDIR);
2775 #ifdef MIT_KDC_PATH
2776 	lpcfg_do_global_parameter_var(lp_ctx,
2777 				      "mit kdc command",
2778 				      MIT_KDC_PATH);
2779 #endif
2780 	lpcfg_do_global_parameter(lp_ctx, "template shell", "/bin/false");
2781 	lpcfg_do_global_parameter(lp_ctx, "template homedir", "/home/%D/%U");
2782 
2783 	lpcfg_do_global_parameter(lp_ctx, "client signing", "default");
2784 	lpcfg_do_global_parameter(lp_ctx, "client ipc signing", "default");
2785 	lpcfg_do_global_parameter(lp_ctx, "server signing", "default");
2786 
2787 	lpcfg_do_global_parameter(lp_ctx, "use mmap", "True");
2788 
2789 	lpcfg_do_global_parameter(lp_ctx, "smb ports", "445 139");
2790 	lpcfg_do_global_parameter_var(lp_ctx, "nbt port", "%d", NBT_NAME_SERVICE_PORT);
2791 	lpcfg_do_global_parameter_var(lp_ctx, "dgram port", "%d", NBT_DGRAM_SERVICE_PORT);
2792 	lpcfg_do_global_parameter(lp_ctx, "cldap port", "389");
2793 	lpcfg_do_global_parameter(lp_ctx, "krb5 port", "88");
2794 	lpcfg_do_global_parameter(lp_ctx, "kpasswd port", "464");
2795 
2796 	lpcfg_do_global_parameter(lp_ctx, "nt status support", "True");
2797 
2798 	lpcfg_do_global_parameter(lp_ctx, "max wins ttl", "518400"); /* 6 days */
2799 	lpcfg_do_global_parameter(lp_ctx, "min wins ttl", "21600");
2800 
2801 	lpcfg_do_global_parameter(lp_ctx, "tls enabled", "True");
2802 	lpcfg_do_global_parameter(lp_ctx, "tls verify peer", "as_strict_as_possible");
2803 	lpcfg_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
2804 	lpcfg_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
2805 	lpcfg_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
2806 	lpcfg_do_global_parameter(lp_ctx, "tls priority", "NORMAL:-VERS-SSL3.0");
2807 
2808 	lpcfg_do_global_parameter(lp_ctx, "nsupdate command", "/usr/bin/nsupdate -g");
2809 
2810         lpcfg_do_global_parameter(lp_ctx, "allow dns updates", "secure only");
2811 	lpcfg_do_global_parameter(lp_ctx, "dns zone scavenging", "False");
2812         lpcfg_do_global_parameter(lp_ctx, "dns forwarder", "");
2813 
2814 	lpcfg_do_global_parameter(lp_ctx, "algorithmic rid base", "1000");
2815 
2816 	lpcfg_do_global_parameter(lp_ctx, "enhanced browsing", "True");
2817 
2818 	lpcfg_do_global_parameter(lp_ctx, "winbind nss info", "template");
2819 
2820 	lpcfg_do_global_parameter(lp_ctx, "server schannel", "True");
2821 
2822 	lpcfg_do_global_parameter(lp_ctx, "short preserve case", "True");
2823 
2824 	lpcfg_do_global_parameter(lp_ctx, "max open files", "16384");
2825 
2826 	lpcfg_do_global_parameter(lp_ctx, "cups connection timeout", "30");
2827 
2828 	lpcfg_do_global_parameter(lp_ctx, "locking", "True");
2829 
2830 	lpcfg_do_global_parameter(lp_ctx, "block size", "1024");
2831 
2832 	lpcfg_do_global_parameter(lp_ctx, "client use spnego", "True");
2833 
2834 	lpcfg_do_global_parameter(lp_ctx, "change notify", "True");
2835 
2836 	lpcfg_do_global_parameter(lp_ctx, "name cache timeout", "660");
2837 
2838 	lpcfg_do_global_parameter(lp_ctx, "defer sharing violations", "True");
2839 
2840 	lpcfg_do_global_parameter(lp_ctx, "ldap replication sleep", "1000");
2841 
2842 	lpcfg_do_global_parameter(lp_ctx, "idmap backend", "tdb");
2843 
2844 	lpcfg_do_global_parameter(lp_ctx, "enable privileges", "True");
2845 
2846 	lpcfg_do_global_parameter_var(lp_ctx, "smb2 max write", "%u", DEFAULT_SMB2_MAX_WRITE);
2847 
2848 	lpcfg_do_global_parameter(lp_ctx, "passdb backend", "tdbsam");
2849 
2850 	lpcfg_do_global_parameter(lp_ctx, "deadtime", "10080");
2851 
2852 	lpcfg_do_global_parameter(lp_ctx, "getwd cache", "True");
2853 
2854 	lpcfg_do_global_parameter(lp_ctx, "winbind nested groups", "True");
2855 
2856 	lpcfg_do_global_parameter(lp_ctx, "mangled names", "illegal");
2857 
2858 	lpcfg_do_global_parameter_var(lp_ctx, "smb2 max credits", "%u", DEFAULT_SMB2_MAX_CREDITS);
2859 
2860 	lpcfg_do_global_parameter(lp_ctx, "ldap ssl", "start tls");
2861 
2862 	lpcfg_do_global_parameter(lp_ctx, "ldap deref", "auto");
2863 
2864 	lpcfg_do_global_parameter(lp_ctx, "lm interval", "60");
2865 
2866 	lpcfg_do_global_parameter(lp_ctx, "mangling method", "hash2");
2867 
2868 	lpcfg_do_global_parameter(lp_ctx, "hide dot files", "True");
2869 
2870 	lpcfg_do_global_parameter(lp_ctx, "browse list", "True");
2871 
2872 	lpcfg_do_global_parameter(lp_ctx, "passwd chat timeout", "2");
2873 
2874 	lpcfg_do_global_parameter(lp_ctx, "guest account", GUEST_ACCOUNT);
2875 
2876 	lpcfg_do_global_parameter(lp_ctx, "client schannel", "True");
2877 
2878 	lpcfg_do_global_parameter(lp_ctx, "smb encrypt", "default");
2879 
2880 	lpcfg_do_global_parameter(lp_ctx, "max log size", "5000");
2881 
2882 	lpcfg_do_global_parameter(lp_ctx, "idmap negative cache time", "120");
2883 
2884 	lpcfg_do_global_parameter(lp_ctx, "ldap follow referral", "auto");
2885 
2886 	lpcfg_do_global_parameter(lp_ctx, "multicast dns register", "yes");
2887 
2888 	lpcfg_do_global_parameter(lp_ctx, "winbind reconnect delay", "30");
2889 
2890 	lpcfg_do_global_parameter(lp_ctx, "winbind request timeout", "60");
2891 
2892 	lpcfg_do_global_parameter(lp_ctx, "nt acl support", "yes");
2893 
2894 	lpcfg_do_global_parameter(lp_ctx, "acl check permissions", "yes");
2895 
2896 	lpcfg_do_global_parameter(lp_ctx, "keepalive", "300");
2897 
2898 	lpcfg_do_global_parameter(lp_ctx, "smbd profiling level", "off");
2899 
2900 	lpcfg_do_global_parameter(lp_ctx, "winbind cache time", "300");
2901 
2902 	lpcfg_do_global_parameter(lp_ctx, "level2 oplocks", "yes");
2903 
2904 	lpcfg_do_global_parameter(lp_ctx, "show add printer wizard", "yes");
2905 
2906 	lpcfg_do_global_parameter(lp_ctx, "ldap page size", "1000");
2907 
2908 	lpcfg_do_global_parameter(lp_ctx, "kernel share modes", "yes");
2909 
2910 	lpcfg_do_global_parameter(lp_ctx, "strict locking", "Auto");
2911 
2912 	lpcfg_do_global_parameter(lp_ctx, "strict sync", "yes");
2913 
2914 	lpcfg_do_global_parameter(lp_ctx, "map readonly", "no");
2915 
2916 	lpcfg_do_global_parameter(lp_ctx, "allow trusted domains", "yes");
2917 
2918 	lpcfg_do_global_parameter(lp_ctx, "default devmode", "yes");
2919 
2920 	lpcfg_do_global_parameter(lp_ctx, "os level", "20");
2921 
2922 	lpcfg_do_global_parameter(lp_ctx, "dos filetimes", "yes");
2923 
2924 	lpcfg_do_global_parameter(lp_ctx, "mangling char", "~");
2925 
2926 	lpcfg_do_global_parameter(lp_ctx, "printcap cache time", "750");
2927 
2928 	lpcfg_do_global_parameter(lp_ctx, "create krb5 conf", "yes");
2929 
2930 	lpcfg_do_global_parameter(lp_ctx, "winbind max clients", "200");
2931 
2932 	lpcfg_do_global_parameter(lp_ctx, "acl map full control", "yes");
2933 
2934 	lpcfg_do_global_parameter(lp_ctx, "nt pipe support", "yes");
2935 
2936 	lpcfg_do_global_parameter(lp_ctx, "ldap debug threshold", "10");
2937 
2938 	lpcfg_do_global_parameter(lp_ctx, "client ldap sasl wrapping", "sign");
2939 
2940 	lpcfg_do_global_parameter(lp_ctx, "mdns name", "netbios");
2941 
2942 	lpcfg_do_global_parameter(lp_ctx, "ldap server require strong auth", "yes");
2943 
2944 	lpcfg_do_global_parameter(lp_ctx, "follow symlinks", "yes");
2945 
2946 	lpcfg_do_global_parameter(lp_ctx, "machine password timeout", "604800");
2947 
2948 	lpcfg_do_global_parameter(lp_ctx, "ldap connection timeout", "2");
2949 
2950 	lpcfg_do_global_parameter(lp_ctx, "winbind expand groups", "0");
2951 
2952 	lpcfg_do_global_parameter(lp_ctx, "stat cache", "yes");
2953 
2954 	lpcfg_do_global_parameter(lp_ctx, "lpq cache time", "30");
2955 
2956 	lpcfg_do_global_parameter_var(lp_ctx, "smb2 max trans", "%u", DEFAULT_SMB2_MAX_TRANSACT);
2957 
2958 	lpcfg_do_global_parameter_var(lp_ctx, "smb2 max read", "%u", DEFAULT_SMB2_MAX_READ);
2959 
2960 	lpcfg_do_global_parameter(lp_ctx, "durable handles", "yes");
2961 
2962 	lpcfg_do_global_parameter(lp_ctx, "max stat cache size", "512");
2963 
2964 	lpcfg_do_global_parameter(lp_ctx, "ldap passwd sync", "no");
2965 
2966 	lpcfg_do_global_parameter(lp_ctx, "kernel change notify", "yes");
2967 
2968 	lpcfg_do_global_parameter(lp_ctx, "max ttl", "259200");
2969 
2970 	lpcfg_do_global_parameter(lp_ctx, "blocking locks", "yes");
2971 
2972 	lpcfg_do_global_parameter(lp_ctx, "load printers", "yes");
2973 
2974 	lpcfg_do_global_parameter(lp_ctx, "idmap cache time", "604800");
2975 
2976 	lpcfg_do_global_parameter(lp_ctx, "preserve case", "yes");
2977 
2978 	lpcfg_do_global_parameter(lp_ctx, "lm announce", "auto");
2979 
2980 	lpcfg_do_global_parameter(lp_ctx, "afs token lifetime", "604800");
2981 
2982 	lpcfg_do_global_parameter(lp_ctx, "enable core files", "yes");
2983 
2984 	lpcfg_do_global_parameter(lp_ctx, "winbind max domain connections", "1");
2985 
2986 	lpcfg_do_global_parameter(lp_ctx, "case sensitive", "auto");
2987 
2988 	lpcfg_do_global_parameter(lp_ctx, "ldap timeout", "15");
2989 
2990 	lpcfg_do_global_parameter(lp_ctx, "mangle prefix", "1");
2991 
2992 	lpcfg_do_global_parameter(lp_ctx, "posix locking", "yes");
2993 
2994 	lpcfg_do_global_parameter(lp_ctx, "lock spin time", "200");
2995 
2996 	lpcfg_do_global_parameter(lp_ctx, "directory name cache size", "100");
2997 
2998 	lpcfg_do_global_parameter(lp_ctx, "nmbd bind explicit broadcast", "yes");
2999 
3000 	lpcfg_do_global_parameter(lp_ctx, "init logon delay", "100");
3001 
3002 	lpcfg_do_global_parameter(lp_ctx, "usershare owner only", "yes");
3003 
3004 	lpcfg_do_global_parameter(lp_ctx, "-valid", "yes");
3005 
3006 	lpcfg_do_global_parameter_var(lp_ctx, "usershare path", "%s/usershares", get_dyn_STATEDIR());
3007 
3008 #ifdef DEVELOPER
3009 	lpcfg_do_global_parameter_var(lp_ctx, "panic action", "/bin/sleep 999999999");
3010 #endif
3011 
3012 	lpcfg_do_global_parameter(lp_ctx, "smb passwd file", get_dyn_SMB_PASSWD_FILE());
3013 
3014 	lpcfg_do_global_parameter(lp_ctx, "logon home", "\\\\%N\\%U");
3015 
3016 	lpcfg_do_global_parameter(lp_ctx, "logon path", "\\\\%N\\%U\\profile");
3017 
3018 	lpcfg_do_global_parameter(lp_ctx, "printjob username", "%U");
3019 
3020 	lpcfg_do_global_parameter(lp_ctx, "aio max threads", "100");
3021 
3022 	lpcfg_do_global_parameter(lp_ctx, "smb2 leases", "yes");
3023 
3024 	lpcfg_do_global_parameter(lp_ctx, "kerberos encryption types", "all");
3025 
3026 	lpcfg_do_global_parameter(lp_ctx,
3027 				  "rpc server dynamic port range",
3028 				  "49152-65535");
3029 
3030 	lpcfg_do_global_parameter(lp_ctx, "prefork children", "4");
3031 	lpcfg_do_global_parameter(lp_ctx, "prefork backoff increment", "10");
3032 	lpcfg_do_global_parameter(lp_ctx, "prefork maximum backoff", "120");
3033 
3034 	lpcfg_do_global_parameter(lp_ctx, "check parent directory delete on close", "no");
3035 
3036 	lpcfg_do_global_parameter(lp_ctx, "ea support", "yes");
3037 
3038 	lpcfg_do_global_parameter(lp_ctx, "store dos attributes", "yes");
3039 
3040 	lpcfg_do_global_parameter(lp_ctx, "debug encryption", "no");
3041 
3042 	lpcfg_do_global_parameter(lp_ctx, "spotlight backend", "noindex");
3043 
3044 	lpcfg_do_global_parameter(
3045 		lp_ctx, "ldap max anonymous request size", "256000");
3046 	lpcfg_do_global_parameter(
3047 		lp_ctx, "ldap max authenticated request size", "16777216");
3048 	lpcfg_do_global_parameter(
3049 		lp_ctx, "ldap max search request size", "256000");
3050 
3051 	for (i = 0; parm_table[i].label; i++) {
3052 		if (!(lp_ctx->flags[i] & FLAG_CMDLINE)) {
3053 			lp_ctx->flags[i] |= FLAG_DEFAULT;
3054 		}
3055 	}
3056 
3057 	for (parm=lp_ctx->globals->param_opt; parm; parm=parm->next) {
3058 		if (!(parm->priority & FLAG_CMDLINE)) {
3059 			parm->priority |= FLAG_DEFAULT;
3060 		}
3061 	}
3062 
3063 	for (parm=lp_ctx->sDefault->param_opt; parm; parm=parm->next) {
3064 		if (!(parm->priority & FLAG_CMDLINE)) {
3065 			parm->priority |= FLAG_DEFAULT;
3066 		}
3067 	}
3068 
3069 	return lp_ctx;
3070 }
3071 
3072 /**
3073  * Initialise the global parameter structure.
3074  */
loadparm_init_global(bool load_default)3075 struct loadparm_context *loadparm_init_global(bool load_default)
3076 {
3077 	if (global_loadparm_context == NULL) {
3078 		global_loadparm_context = loadparm_init(NULL);
3079 	}
3080 	if (global_loadparm_context == NULL) {
3081 		return NULL;
3082 	}
3083 	global_loadparm_context->global = true;
3084 	if (load_default && !global_loadparm_context->loaded) {
3085 		lpcfg_load_default(global_loadparm_context);
3086 	}
3087 	global_loadparm_context->refuse_free = true;
3088 	return global_loadparm_context;
3089 }
3090 
3091 /**
3092  * Initialise the global parameter structure.
3093  */
loadparm_init_s3(TALLOC_CTX * mem_ctx,const struct loadparm_s3_helpers * s3_fns)3094 struct loadparm_context *loadparm_init_s3(TALLOC_CTX *mem_ctx,
3095 					  const struct loadparm_s3_helpers *s3_fns)
3096 {
3097 	struct loadparm_context *loadparm_context = talloc_zero(mem_ctx, struct loadparm_context);
3098 	if (!loadparm_context) {
3099 		return NULL;
3100 	}
3101 	loadparm_context->s3_fns = s3_fns;
3102 	loadparm_context->globals = s3_fns->globals;
3103 	loadparm_context->flags = s3_fns->flags;
3104 
3105 	return loadparm_context;
3106 }
3107 
lpcfg_configfile(struct loadparm_context * lp_ctx)3108 const char *lpcfg_configfile(struct loadparm_context *lp_ctx)
3109 {
3110 	return lp_ctx->szConfigFile;
3111 }
3112 
lp_default_path(void)3113 const char *lp_default_path(void)
3114 {
3115     if (getenv("SMB_CONF_PATH"))
3116         return getenv("SMB_CONF_PATH");
3117     else
3118         return dyn_CONFIGFILE;
3119 }
3120 
3121 /**
3122  * Update the internal state of a loadparm context after settings
3123  * have changed.
3124  */
lpcfg_update(struct loadparm_context * lp_ctx)3125 static bool lpcfg_update(struct loadparm_context *lp_ctx)
3126 {
3127 	struct debug_settings settings;
3128 	int max_protocol, min_protocol;
3129 	TALLOC_CTX *tmp_ctx;
3130 	const struct loadparm_substitution *lp_sub =
3131 		lpcfg_noop_substitution();
3132 
3133 	tmp_ctx = talloc_new(lp_ctx);
3134 	if (tmp_ctx == NULL) {
3135 		return false;
3136 	}
3137 
3138 	lpcfg_add_auto_services(lp_ctx, lpcfg_auto_services(lp_ctx, lp_sub, tmp_ctx));
3139 
3140 	if (!lp_ctx->globals->wins_server_list && lp_ctx->globals->we_are_a_wins_server) {
3141 		lpcfg_do_global_parameter(lp_ctx, "wins server", "127.0.0.1");
3142 	}
3143 
3144 	if (!lp_ctx->global) {
3145 		TALLOC_FREE(tmp_ctx);
3146 		return true;
3147 	}
3148 
3149 	panic_action = lp_ctx->globals->panic_action;
3150 
3151 	reload_charcnv(lp_ctx);
3152 
3153 	ZERO_STRUCT(settings);
3154 	/* Add any more debug-related smb.conf parameters created in
3155 	 * future here */
3156 	settings.timestamp_logs = lp_ctx->globals->timestamp_logs;
3157 	settings.debug_prefix_timestamp = lp_ctx->globals->debug_prefix_timestamp;
3158 	settings.debug_hires_timestamp = lp_ctx->globals->debug_hires_timestamp;
3159 	settings.debug_pid = lp_ctx->globals->debug_pid;
3160 	settings.debug_uid = lp_ctx->globals->debug_uid;
3161 	settings.debug_class = lp_ctx->globals->debug_class;
3162 	settings.max_log_size = lp_ctx->globals->max_log_size;
3163 	debug_set_settings(&settings, lp_ctx->globals->logging,
3164 			   lp_ctx->globals->syslog,
3165 			   lp_ctx->globals->syslog_only);
3166 
3167 	/* FIXME: This is a bit of a hack, but we can't use a global, since
3168 	 * not everything that uses lp also uses the socket library */
3169 	if (lpcfg_parm_bool(lp_ctx, NULL, "socket", "testnonblock", false)) {
3170 		setenv("SOCKET_TESTNONBLOCK", "1", 1);
3171 	} else {
3172 		unsetenv("SOCKET_TESTNONBLOCK");
3173 	}
3174 
3175 	/* Check if command line max protocol < min protocol, if so
3176 	 * report a warning to the user.
3177 	 */
3178 	max_protocol = lpcfg_client_max_protocol(lp_ctx);
3179 	min_protocol = lpcfg_client_min_protocol(lp_ctx);
3180 	if (lpcfg_client_max_protocol(lp_ctx) < lpcfg_client_min_protocol(lp_ctx)) {
3181 		const char *max_protocolp, *min_protocolp;
3182 		max_protocolp = lpcfg_get_smb_protocol(max_protocol);
3183 		min_protocolp = lpcfg_get_smb_protocol(min_protocol);
3184 		DBG_ERR("Max protocol %s is less than min protocol %s.\n",
3185 			max_protocolp, min_protocolp);
3186 	}
3187 
3188 	TALLOC_FREE(tmp_ctx);
3189 	return true;
3190 }
3191 
lpcfg_load_default(struct loadparm_context * lp_ctx)3192 bool lpcfg_load_default(struct loadparm_context *lp_ctx)
3193 {
3194     const char *path;
3195 
3196     path = lp_default_path();
3197 
3198     if (!file_exist(path)) {
3199 	    /* We allow the default smb.conf file to not exist,
3200 	     * basically the equivalent of an empty file. */
3201 	    return lpcfg_update(lp_ctx);
3202     }
3203 
3204     return lpcfg_load(lp_ctx, path);
3205 }
3206 
3207 /**
3208  * Load the services array from the services file.
3209  *
3210  * Return True on success, False on failure.
3211  */
lpcfg_load_internal(struct loadparm_context * lp_ctx,const char * filename,bool set_global)3212 static bool lpcfg_load_internal(struct loadparm_context *lp_ctx,
3213 				const char *filename, bool set_global)
3214 {
3215 	char *n2;
3216 	bool bRetval;
3217 
3218 	filename = talloc_strdup(lp_ctx, filename);
3219 
3220 	lp_ctx->szConfigFile = filename;
3221 
3222 	if (lp_ctx->s3_fns) {
3223 		return lp_ctx->s3_fns->load(filename);
3224 	}
3225 
3226 	lp_ctx->bInGlobalSection = true;
3227 	n2 = standard_sub_basic(lp_ctx, lp_ctx->szConfigFile);
3228 	DEBUG(2, ("lpcfg_load: refreshing parameters from %s\n", n2));
3229 
3230 	add_to_file_list(lp_ctx, &lp_ctx->file_lists, lp_ctx->szConfigFile, n2);
3231 
3232 	/* We get sections first, so have to start 'behind' to make up */
3233 	lp_ctx->currentService = NULL;
3234 	bRetval = pm_process(n2, do_section, lpcfg_do_parameter, lp_ctx);
3235 
3236 	/* finish up the last section */
3237 	DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
3238 	if (bRetval)
3239 		if (lp_ctx->currentService != NULL)
3240 			bRetval = lpcfg_service_ok(lp_ctx->currentService);
3241 
3242 	bRetval = bRetval && lpcfg_update(lp_ctx);
3243 
3244 	/* we do this unconditionally, so that it happens even
3245 	   for a missing smb.conf */
3246 	reload_charcnv(lp_ctx);
3247 
3248 	if (bRetval == true && set_global) {
3249 		/* set this up so that any child python tasks will
3250 		   find the right smb.conf */
3251 		setenv("SMB_CONF_PATH", filename, 1);
3252 
3253 		/* set the context used by the lp_*() function
3254 		   varients */
3255 		global_loadparm_context = lp_ctx;
3256 		lp_ctx->loaded = true;
3257 	}
3258 
3259 	return bRetval;
3260 }
3261 
lpcfg_load_no_global(struct loadparm_context * lp_ctx,const char * filename)3262 bool lpcfg_load_no_global(struct loadparm_context *lp_ctx, const char *filename)
3263 {
3264     return lpcfg_load_internal(lp_ctx, filename, false);
3265 }
3266 
lpcfg_load(struct loadparm_context * lp_ctx,const char * filename)3267 bool lpcfg_load(struct loadparm_context *lp_ctx, const char *filename)
3268 {
3269     return lpcfg_load_internal(lp_ctx, filename, true);
3270 }
3271 
3272 /**
3273  * Return the max number of services.
3274  */
3275 
lpcfg_numservices(struct loadparm_context * lp_ctx)3276 int lpcfg_numservices(struct loadparm_context *lp_ctx)
3277 {
3278 	if (lp_ctx->s3_fns) {
3279 		return lp_ctx->s3_fns->get_numservices();
3280 	}
3281 
3282 	return lp_ctx->iNumServices;
3283 }
3284 
3285 /**
3286  * Display the contents of the services array in human-readable form.
3287  */
3288 
lpcfg_dump(struct loadparm_context * lp_ctx,FILE * f,bool show_defaults,int maxtoprint)3289 void lpcfg_dump(struct loadparm_context *lp_ctx, FILE *f, bool show_defaults,
3290 	     int maxtoprint)
3291 {
3292 	int iService;
3293 
3294 	if (lp_ctx->s3_fns) {
3295 		lp_ctx->s3_fns->dump(f, show_defaults, maxtoprint);
3296 		return;
3297 	}
3298 
3299 	lpcfg_dump_globals(lp_ctx, f, show_defaults);
3300 
3301 	lpcfg_dump_a_service(lp_ctx->sDefault, lp_ctx->sDefault, f, lp_ctx->flags, show_defaults);
3302 
3303 	for (iService = 0; iService < maxtoprint; iService++)
3304 		lpcfg_dump_one(f, show_defaults, lp_ctx->services[iService], lp_ctx->sDefault);
3305 }
3306 
3307 /**
3308  * Display the contents of one service in human-readable form.
3309  */
lpcfg_dump_one(FILE * f,bool show_defaults,struct loadparm_service * service,struct loadparm_service * sDefault)3310 void lpcfg_dump_one(FILE *f, bool show_defaults, struct loadparm_service *service, struct loadparm_service *sDefault)
3311 {
3312 	if (service != NULL) {
3313 		if (service->szService[0] == '\0')
3314 			return;
3315 		lpcfg_dump_a_service(service, sDefault, f, NULL, show_defaults);
3316 	}
3317 }
3318 
lpcfg_servicebynum(struct loadparm_context * lp_ctx,int snum)3319 struct loadparm_service *lpcfg_servicebynum(struct loadparm_context *lp_ctx,
3320 					    int snum)
3321 {
3322 	if (lp_ctx->s3_fns) {
3323 		return lp_ctx->s3_fns->get_servicebynum(snum);
3324 	}
3325 
3326 	return lp_ctx->services[snum];
3327 }
3328 
lpcfg_service(struct loadparm_context * lp_ctx,const char * service_name)3329 struct loadparm_service *lpcfg_service(struct loadparm_context *lp_ctx,
3330 				    const char *service_name)
3331 {
3332 	int iService;
3333         char *serviceName;
3334 
3335 	if (lp_ctx->s3_fns) {
3336 		return lp_ctx->s3_fns->get_service(service_name);
3337 	}
3338 
3339 	for (iService = lp_ctx->iNumServices - 1; iService >= 0; iService--) {
3340 		if (lp_ctx->services[iService] &&
3341 		    lp_ctx->services[iService]->szService) {
3342 			/*
3343 			 * The substitution here is used to support %U is
3344 			 * service names
3345 			 */
3346 			serviceName = standard_sub_basic(
3347 					lp_ctx->services[iService],
3348 					lp_ctx->services[iService]->szService);
3349 			if (strequal(serviceName, service_name)) {
3350 				talloc_free(serviceName);
3351 				return lp_ctx->services[iService];
3352 			}
3353 			talloc_free(serviceName);
3354 		}
3355 	}
3356 
3357 	DEBUG(7,("lpcfg_servicenumber: couldn't find %s\n", service_name));
3358 	return NULL;
3359 }
3360 
lpcfg_servicename(const struct loadparm_service * service)3361 const char *lpcfg_servicename(const struct loadparm_service *service)
3362 {
3363 	return service ? lpcfg_string((const char *)service->szService) : NULL;
3364 }
3365 
3366 /**
3367  * A useful volume label function.
3368  */
lpcfg_volume_label(struct loadparm_service * service,struct loadparm_service * sDefault)3369 const char *lpcfg_volume_label(struct loadparm_service *service, struct loadparm_service *sDefault)
3370 {
3371 	const char *ret;
3372 	ret = lpcfg_string((const char *)((service != NULL && service->volume != NULL) ?
3373 				       service->volume : sDefault->volume));
3374 	if (!*ret)
3375 		return lpcfg_servicename(service);
3376 	return ret;
3377 }
3378 
3379 /**
3380  * Return the correct printer name.
3381  */
lpcfg_printername(struct loadparm_service * service,struct loadparm_service * sDefault)3382 const char *lpcfg_printername(struct loadparm_service *service, struct loadparm_service *sDefault)
3383 {
3384 	const char *ret;
3385 	ret = lpcfg_string((const char *)((service != NULL && service->_printername != NULL) ?
3386 				       service->_printername : sDefault->_printername));
3387 	if (ret == NULL || (ret != NULL && *ret == '\0'))
3388 		ret = lpcfg_servicename(service);
3389 
3390 	return ret;
3391 }
3392 
3393 
3394 /**
3395  * Return the max print jobs per queue.
3396  */
lpcfg_maxprintjobs(struct loadparm_service * service,struct loadparm_service * sDefault)3397 int lpcfg_maxprintjobs(struct loadparm_service *service, struct loadparm_service *sDefault)
3398 {
3399 	int maxjobs = lpcfg_max_print_jobs(service, sDefault);
3400 
3401 	if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
3402 		maxjobs = PRINT_MAX_JOBID - 1;
3403 
3404 	return maxjobs;
3405 }
3406 
lpcfg_iconv_handle(struct loadparm_context * lp_ctx)3407 struct smb_iconv_handle *lpcfg_iconv_handle(struct loadparm_context *lp_ctx)
3408 {
3409 	if (lp_ctx == NULL) {
3410 		return get_iconv_handle();
3411 	}
3412 	return lp_ctx->iconv_handle;
3413 }
3414 
reload_charcnv(struct loadparm_context * lp_ctx)3415 _PUBLIC_ void reload_charcnv(struct loadparm_context *lp_ctx)
3416 {
3417 	if (!lp_ctx->global) {
3418 		return;
3419 	}
3420 
3421 	lp_ctx->iconv_handle =
3422 		reinit_iconv_handle(lp_ctx,
3423 				    lpcfg_dos_charset(lp_ctx),
3424 				    lpcfg_unix_charset(lp_ctx));
3425 	if (lp_ctx->iconv_handle == NULL) {
3426 		smb_panic("reinit_iconv_handle failed");
3427 	}
3428 }
3429 
lpcfg_tls_keyfile(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx)3430 _PUBLIC_ char *lpcfg_tls_keyfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
3431 {
3432 	return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_keyfile(lp_ctx));
3433 }
3434 
lpcfg_tls_certfile(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx)3435 _PUBLIC_ char *lpcfg_tls_certfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
3436 {
3437 	return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_certfile(lp_ctx));
3438 }
3439 
lpcfg_tls_cafile(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx)3440 _PUBLIC_ char *lpcfg_tls_cafile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
3441 {
3442 	return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_cafile(lp_ctx));
3443 }
3444 
lpcfg_tls_crlfile(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx)3445 _PUBLIC_ char *lpcfg_tls_crlfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
3446 {
3447 	return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_crlfile(lp_ctx));
3448 }
3449 
lpcfg_tls_dhpfile(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx)3450 _PUBLIC_ char *lpcfg_tls_dhpfile(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
3451 {
3452 	return lpcfg_private_path(mem_ctx, lp_ctx, lpcfg__tls_dhpfile(lp_ctx));
3453 }
3454 
lpcfg_gensec_settings(TALLOC_CTX * mem_ctx,struct loadparm_context * lp_ctx)3455 struct gensec_settings *lpcfg_gensec_settings(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx)
3456 {
3457 	struct gensec_settings *settings = talloc_zero(mem_ctx, struct gensec_settings);
3458 	if (settings == NULL)
3459 		return NULL;
3460 	SMB_ASSERT(lp_ctx != NULL);
3461 	settings->lp_ctx = talloc_reference(settings, lp_ctx);
3462 	settings->target_hostname = lpcfg_parm_string(lp_ctx, NULL, "gensec", "target_hostname");
3463 	return settings;
3464 }
3465 
lpcfg_server_role(struct loadparm_context * lp_ctx)3466 int lpcfg_server_role(struct loadparm_context *lp_ctx)
3467 {
3468 	int domain_master = lpcfg__domain_master(lp_ctx);
3469 
3470 	return lp_find_server_role(lpcfg__server_role(lp_ctx),
3471 				   lpcfg__security(lp_ctx),
3472 				   lpcfg__domain_logons(lp_ctx),
3473 				   (domain_master == true) ||
3474 				   (domain_master == Auto));
3475 }
3476 
lpcfg_security(struct loadparm_context * lp_ctx)3477 int lpcfg_security(struct loadparm_context *lp_ctx)
3478 {
3479 	return lp_find_security(lpcfg__server_role(lp_ctx),
3480 				lpcfg__security(lp_ctx));
3481 }
3482 
lpcfg_client_max_protocol(struct loadparm_context * lp_ctx)3483 int lpcfg_client_max_protocol(struct loadparm_context *lp_ctx)
3484 {
3485 	int client_max_protocol = lpcfg__client_max_protocol(lp_ctx);
3486 	if (client_max_protocol == PROTOCOL_DEFAULT) {
3487 		return PROTOCOL_LATEST;
3488 	}
3489 	return client_max_protocol;
3490 }
3491 
lpcfg_client_ipc_min_protocol(struct loadparm_context * lp_ctx)3492 int lpcfg_client_ipc_min_protocol(struct loadparm_context *lp_ctx)
3493 {
3494 	int client_ipc_min_protocol = lpcfg__client_ipc_min_protocol(lp_ctx);
3495 	if (client_ipc_min_protocol == PROTOCOL_DEFAULT) {
3496 		client_ipc_min_protocol = lpcfg_client_min_protocol(lp_ctx);
3497 	}
3498 	if (client_ipc_min_protocol < PROTOCOL_NT1) {
3499 		return PROTOCOL_NT1;
3500 	}
3501 	return client_ipc_min_protocol;
3502 }
3503 
lpcfg_client_ipc_max_protocol(struct loadparm_context * lp_ctx)3504 int lpcfg_client_ipc_max_protocol(struct loadparm_context *lp_ctx)
3505 {
3506 	int client_ipc_max_protocol = lpcfg__client_ipc_max_protocol(lp_ctx);
3507 	if (client_ipc_max_protocol == PROTOCOL_DEFAULT) {
3508 		return PROTOCOL_LATEST;
3509 	}
3510 	if (client_ipc_max_protocol < PROTOCOL_NT1) {
3511 		return PROTOCOL_NT1;
3512 	}
3513 	return client_ipc_max_protocol;
3514 }
3515 
lpcfg_client_ipc_signing(struct loadparm_context * lp_ctx)3516 int lpcfg_client_ipc_signing(struct loadparm_context *lp_ctx)
3517 {
3518 	int client_ipc_signing = lpcfg__client_ipc_signing(lp_ctx);
3519 	if (client_ipc_signing == SMB_SIGNING_DEFAULT) {
3520 		return SMB_SIGNING_REQUIRED;
3521 	}
3522 	return client_ipc_signing;
3523 }
3524 
lpcfg_server_signing_allowed(struct loadparm_context * lp_ctx,bool * mandatory)3525 bool lpcfg_server_signing_allowed(struct loadparm_context *lp_ctx, bool *mandatory)
3526 {
3527 	bool allowed = true;
3528 	enum smb_signing_setting signing_setting = lpcfg_server_signing(lp_ctx);
3529 
3530 	*mandatory = false;
3531 
3532 	if (signing_setting == SMB_SIGNING_DEFAULT) {
3533 		/*
3534 		 * If we are a domain controller, SMB signing is
3535 		 * really important, as it can prevent a number of
3536 		 * attacks on communications between us and the
3537 		 * clients
3538 		 *
3539 		 * However, it really sucks (no sendfile, CPU
3540 		 * overhead) performance-wise when used on a
3541 		 * file server, so disable it by default
3542 		 * on non-DCs
3543 		 */
3544 
3545 		if (lpcfg_server_role(lp_ctx) >= ROLE_ACTIVE_DIRECTORY_DC) {
3546 			signing_setting = SMB_SIGNING_REQUIRED;
3547 		} else {
3548 			signing_setting = SMB_SIGNING_OFF;
3549 		}
3550 	}
3551 
3552 	switch (signing_setting) {
3553 	case SMB_SIGNING_REQUIRED:
3554 		*mandatory = true;
3555 		break;
3556 	case SMB_SIGNING_DESIRED:
3557 	case SMB_SIGNING_IF_REQUIRED:
3558 		break;
3559 	case SMB_SIGNING_OFF:
3560 		allowed = false;
3561 		break;
3562 	case SMB_SIGNING_DEFAULT:
3563 	case SMB_SIGNING_IPC_DEFAULT:
3564 		smb_panic(__location__);
3565 		break;
3566 	}
3567 
3568 	return allowed;
3569 }
3570 
lpcfg_tdb_hash_size(struct loadparm_context * lp_ctx,const char * name)3571 int lpcfg_tdb_hash_size(struct loadparm_context *lp_ctx, const char *name)
3572 {
3573 	const char *base;
3574 
3575 	if (name == NULL) {
3576 		return 0;
3577 	}
3578 
3579 	base = strrchr_m(name, '/');
3580 	if (base != NULL) {
3581 		base += 1;
3582 	} else {
3583 		base = name;
3584 	}
3585 	return lpcfg_parm_int(lp_ctx, NULL, "tdb_hashsize", base, 0);
3586 
3587 }
3588 
lpcfg_tdb_flags(struct loadparm_context * lp_ctx,int tdb_flags)3589 int lpcfg_tdb_flags(struct loadparm_context *lp_ctx, int tdb_flags)
3590 {
3591 	if (!lpcfg_use_mmap(lp_ctx)) {
3592 		tdb_flags |= TDB_NOMMAP;
3593 	}
3594 	return tdb_flags;
3595 }
3596 
3597 /*
3598  * Do not allow LanMan auth if unless NTLMv1 is also allowed
3599  *
3600  * This also ensures it is disabled if NTLM is totally disabled
3601  */
lpcfg_lanman_auth(struct loadparm_context * lp_ctx)3602 bool lpcfg_lanman_auth(struct loadparm_context *lp_ctx)
3603 {
3604 	enum ntlm_auth_level ntlm_auth_level = lpcfg_ntlm_auth(lp_ctx);
3605 
3606 	if (ntlm_auth_level == NTLM_AUTH_ON) {
3607 		return lpcfg__lanman_auth(lp_ctx);
3608 	} else {
3609 		return false;
3610 	}
3611 }
3612 
lpcfg_noop_substitution_fn(TALLOC_CTX * mem_ctx,const struct loadparm_substitution * lp_sub,const char * raw_value,void * private_data)3613 static char *lpcfg_noop_substitution_fn(
3614 			TALLOC_CTX *mem_ctx,
3615 			const struct loadparm_substitution *lp_sub,
3616 			const char *raw_value,
3617 			void *private_data)
3618 {
3619 	return talloc_strdup(mem_ctx, raw_value);
3620 }
3621 
3622 static const struct loadparm_substitution global_noop_substitution = {
3623 	.substituted_string_fn = lpcfg_noop_substitution_fn,
3624 };
3625 
lpcfg_noop_substitution(void)3626 const struct loadparm_substitution *lpcfg_noop_substitution(void)
3627 {
3628 	return &global_noop_substitution;
3629 }
3630 
lpcfg_substituted_string(TALLOC_CTX * mem_ctx,const struct loadparm_substitution * lp_sub,const char * raw_value)3631 char *lpcfg_substituted_string(TALLOC_CTX *mem_ctx,
3632 			       const struct loadparm_substitution *lp_sub,
3633 			       const char *raw_value)
3634 {
3635 	return lp_sub->substituted_string_fn(mem_ctx,
3636 					     lp_sub,
3637 					     raw_value,
3638 					     lp_sub->private_data);
3639 }
3640