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) Michael Adam 2008
|
---|
13 | Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
|
---|
14 | Copyright (C) Andrew Bartlett 2011
|
---|
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 "system/filesys.h"
|
---|
58 | #include "util_tdb.h"
|
---|
59 | #include "lib/param/loadparm.h"
|
---|
60 | #include "lib/param/param.h"
|
---|
61 | #include "printing.h"
|
---|
62 | #include "lib/smbconf/smbconf.h"
|
---|
63 | #include "lib/smbconf/smbconf_init.h"
|
---|
64 |
|
---|
65 | #include "ads.h"
|
---|
66 | #include "../librpc/gen_ndr/svcctl.h"
|
---|
67 | #include "intl.h"
|
---|
68 | #include "../libcli/smb/smb_signing.h"
|
---|
69 | #include "dbwrap/dbwrap.h"
|
---|
70 | #include "dbwrap/dbwrap_rbt.h"
|
---|
71 | #include "../lib/util/bitmap.h"
|
---|
72 | #include "librpc/gen_ndr/nbt.h"
|
---|
73 | #include "source4/lib/tls/tls.h"
|
---|
74 |
|
---|
75 | #ifdef HAVE_SYS_SYSCTL_H
|
---|
76 | #include <sys/sysctl.h>
|
---|
77 | #endif
|
---|
78 |
|
---|
79 | bool bLoaded = false;
|
---|
80 |
|
---|
81 | extern userdom_struct current_user_info;
|
---|
82 |
|
---|
83 | /* the special value for the include parameter
|
---|
84 | * to be interpreted not as a file name but to
|
---|
85 | * trigger loading of the global smb.conf options
|
---|
86 | * from registry. */
|
---|
87 | #ifndef INCLUDE_REGISTRY_NAME
|
---|
88 | #define INCLUDE_REGISTRY_NAME "registry"
|
---|
89 | #endif
|
---|
90 |
|
---|
91 | static bool in_client = false; /* Not in the client by default */
|
---|
92 | static struct smbconf_csn conf_last_csn;
|
---|
93 |
|
---|
94 | static int config_backend = CONFIG_BACKEND_FILE;
|
---|
95 |
|
---|
96 | /* some helpful bits */
|
---|
97 | #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && \
|
---|
98 | (ServicePtrs != NULL) && \
|
---|
99 | (ServicePtrs[(i)] != NULL) && ServicePtrs[(i)]->valid)
|
---|
100 | #define VALID(i) ((ServicePtrs != NULL) && (ServicePtrs[i]!= NULL) && \
|
---|
101 | ServicePtrs[i]->valid)
|
---|
102 |
|
---|
103 | #define USERSHARE_VALID 1
|
---|
104 | #define USERSHARE_PENDING_DELETE 2
|
---|
105 |
|
---|
106 | static bool defaults_saved = false;
|
---|
107 |
|
---|
108 | #include "lib/param/param_global.h"
|
---|
109 |
|
---|
110 | static struct loadparm_global Globals;
|
---|
111 |
|
---|
112 | /* This is a default service used to prime a services structure */
|
---|
113 | static struct loadparm_service sDefault =
|
---|
114 | {
|
---|
115 | .valid = true,
|
---|
116 | .autoloaded = false,
|
---|
117 | .usershare = 0,
|
---|
118 | .usershare_last_mod = {0, 0},
|
---|
119 | .szService = NULL,
|
---|
120 | .path = NULL,
|
---|
121 | .username = NULL,
|
---|
122 | .invalid_users = NULL,
|
---|
123 | .valid_users = NULL,
|
---|
124 | .admin_users = NULL,
|
---|
125 | .copy = NULL,
|
---|
126 | .include = NULL,
|
---|
127 | .preexec = NULL,
|
---|
128 | .postexec = NULL,
|
---|
129 | .root_preexec = NULL,
|
---|
130 | .root_postexec = NULL,
|
---|
131 | .cups_options = NULL,
|
---|
132 | .print_command = NULL,
|
---|
133 | .lpq_command = NULL,
|
---|
134 | .lprm_command = NULL,
|
---|
135 | .lppause_command = NULL,
|
---|
136 | .lpresume_command = NULL,
|
---|
137 | .queuepause_command = NULL,
|
---|
138 | .queueresume_command = NULL,
|
---|
139 | ._printername = NULL,
|
---|
140 | .printjob_username = NULL,
|
---|
141 | .dont_descend = NULL,
|
---|
142 | .hosts_allow = NULL,
|
---|
143 | .hosts_deny = NULL,
|
---|
144 | .magic_script = NULL,
|
---|
145 | .magic_output = NULL,
|
---|
146 | .veto_files = NULL,
|
---|
147 | .hide_files = NULL,
|
---|
148 | .veto_oplock_files = NULL,
|
---|
149 | .comment = NULL,
|
---|
150 | .force_user = NULL,
|
---|
151 | .force_group = NULL,
|
---|
152 | .read_list = NULL,
|
---|
153 | .write_list = NULL,
|
---|
154 | .volume = NULL,
|
---|
155 | .fstype = NULL,
|
---|
156 | .vfs_objects = NULL,
|
---|
157 | .msdfs_proxy = NULL,
|
---|
158 | .aio_write_behind = NULL,
|
---|
159 | .dfree_command = NULL,
|
---|
160 | .min_print_space = 0,
|
---|
161 | .max_print_jobs = 1000,
|
---|
162 | .max_reported_print_jobs = 0,
|
---|
163 | .write_cache_size = 0,
|
---|
164 | .create_mask = 0744,
|
---|
165 | .force_create_mode = 0,
|
---|
166 | .directory_mask = 0755,
|
---|
167 | .force_directory_mode = 0,
|
---|
168 | .max_connections = 0,
|
---|
169 | .default_case = CASE_LOWER,
|
---|
170 | .printing = DEFAULT_PRINTING,
|
---|
171 | .oplock_contention_limit = 2,
|
---|
172 | .csc_policy = 0,
|
---|
173 | .block_size = 1024,
|
---|
174 | .dfree_cache_time = 0,
|
---|
175 | .preexec_close = false,
|
---|
176 | .root_preexec_close = false,
|
---|
177 | .case_sensitive = Auto,
|
---|
178 | .preserve_case = true,
|
---|
179 | .short_preserve_case = true,
|
---|
180 | .hide_dot_files = true,
|
---|
181 | .hide_special_files = false,
|
---|
182 | .hide_unreadable = false,
|
---|
183 | .hide_unwriteable_files = false,
|
---|
184 | .browseable = true,
|
---|
185 | .access_based_share_enum = false,
|
---|
186 | .available = true,
|
---|
187 | .read_only = true,
|
---|
188 | .spotlight = false,
|
---|
189 | .guest_only = false,
|
---|
190 | .administrative_share = false,
|
---|
191 | .guest_ok = false,
|
---|
192 | .printable = false,
|
---|
193 | .print_notify_backchannel = false,
|
---|
194 | .map_system = false,
|
---|
195 | .map_hidden = false,
|
---|
196 | .map_archive = true,
|
---|
197 | .store_dos_attributes = false,
|
---|
198 | .dmapi_support = false,
|
---|
199 | .locking = true,
|
---|
200 | .strict_locking = Auto,
|
---|
201 | .posix_locking = true,
|
---|
202 | .oplocks = true,
|
---|
203 | .kernel_oplocks = false,
|
---|
204 | .level2_oplocks = true,
|
---|
205 | .only_user = false,
|
---|
206 | .mangled_names = true,
|
---|
207 | .wide_links = false,
|
---|
208 | .follow_symlinks = true,
|
---|
209 | .sync_always = false,
|
---|
210 | .strict_allocate = false,
|
---|
211 | .strict_rename = false,
|
---|
212 | .strict_sync = false,
|
---|
213 | .mangling_char = '~',
|
---|
214 | .copymap = NULL,
|
---|
215 | .delete_readonly = false,
|
---|
216 | .fake_oplocks = false,
|
---|
217 | .delete_veto_files = false,
|
---|
218 | .dos_filemode = false,
|
---|
219 | .dos_filetimes = true,
|
---|
220 | .dos_filetime_resolution = false,
|
---|
221 | .fake_directory_create_times = false,
|
---|
222 | .blocking_locks = true,
|
---|
223 | .inherit_permissions = false,
|
---|
224 | .inherit_acls = false,
|
---|
225 | .inherit_owner = false,
|
---|
226 | .msdfs_root = false,
|
---|
227 | .msdfs_shuffle_referrals = false,
|
---|
228 | .use_client_driver = false,
|
---|
229 | .default_devmode = true,
|
---|
230 | .force_printername = false,
|
---|
231 | .nt_acl_support = true,
|
---|
232 | .force_unknown_acl_user = false,
|
---|
233 | ._use_sendfile = false,
|
---|
234 | .profile_acls = false,
|
---|
235 | .map_acl_inherit = false,
|
---|
236 | .afs_share = false,
|
---|
237 | .ea_support = false,
|
---|
238 | .acl_check_permissions = true,
|
---|
239 | .acl_map_full_control = true,
|
---|
240 | .acl_group_control = false,
|
---|
241 | .acl_allow_execute_always = false,
|
---|
242 | .allocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
|
---|
243 | .aio_read_size = 0,
|
---|
244 | .aio_write_size = 0,
|
---|
245 | .map_readonly = MAP_READONLY_YES,
|
---|
246 | .directory_name_cache_size = 100,
|
---|
247 | .smb_encrypt = SMB_SIGNING_DEFAULT,
|
---|
248 | .kernel_share_modes = true,
|
---|
249 | .durable_handles = true,
|
---|
250 | .param_opt = NULL,
|
---|
251 | .dummy = ""
|
---|
252 | };
|
---|
253 |
|
---|
254 | /* local variables */
|
---|
255 | static struct loadparm_service **ServicePtrs = NULL;
|
---|
256 | static int iNumServices = 0;
|
---|
257 | static int iServiceIndex = 0;
|
---|
258 | static struct db_context *ServiceHash;
|
---|
259 | static bool bInGlobalSection = true;
|
---|
260 | static bool bGlobalOnly = false;
|
---|
261 | static struct file_lists *file_lists = NULL;
|
---|
262 | static unsigned int *flags_list = NULL;
|
---|
263 |
|
---|
264 | static void set_allowed_client_auth(void);
|
---|
265 |
|
---|
266 | static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue);
|
---|
267 | static void free_param_opts(struct parmlist_entry **popts);
|
---|
268 |
|
---|
269 | /**
|
---|
270 | * Function to return the default value for the maximum number of open
|
---|
271 | * file descriptors permitted. This function tries to consult the
|
---|
272 | * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
|
---|
273 | * the smaller of those.
|
---|
274 | */
|
---|
275 | static int max_open_files(void)
|
---|
276 | {
|
---|
277 | int sysctl_max = MAX_OPEN_FILES;
|
---|
278 | int rlimit_max = MAX_OPEN_FILES;
|
---|
279 |
|
---|
280 | #ifdef HAVE_SYSCTLBYNAME
|
---|
281 | {
|
---|
282 | size_t size = sizeof(sysctl_max);
|
---|
283 | sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,
|
---|
284 | 0);
|
---|
285 | }
|
---|
286 | #endif
|
---|
287 |
|
---|
288 | #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
|
---|
289 | {
|
---|
290 | struct rlimit rl;
|
---|
291 |
|
---|
292 | ZERO_STRUCT(rl);
|
---|
293 |
|
---|
294 | if (getrlimit(RLIMIT_NOFILE, &rl) == 0)
|
---|
295 | rlimit_max = rl.rlim_cur;
|
---|
296 |
|
---|
297 | #if defined(RLIM_INFINITY)
|
---|
298 | if(rl.rlim_cur == RLIM_INFINITY)
|
---|
299 | rlimit_max = MAX_OPEN_FILES;
|
---|
300 | #endif
|
---|
301 | }
|
---|
302 | #endif
|
---|
303 |
|
---|
304 | if (sysctl_max < MIN_OPEN_FILES_WINDOWS) {
|
---|
305 | DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
|
---|
306 | "minimum Windows limit (%d)\n",
|
---|
307 | sysctl_max,
|
---|
308 | MIN_OPEN_FILES_WINDOWS));
|
---|
309 | sysctl_max = MIN_OPEN_FILES_WINDOWS;
|
---|
310 | }
|
---|
311 |
|
---|
312 | if (rlimit_max < MIN_OPEN_FILES_WINDOWS) {
|
---|
313 | DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
|
---|
314 | "minimum Windows limit (%d)\n",
|
---|
315 | rlimit_max,
|
---|
316 | MIN_OPEN_FILES_WINDOWS));
|
---|
317 | rlimit_max = MIN_OPEN_FILES_WINDOWS;
|
---|
318 | }
|
---|
319 |
|
---|
320 | return MIN(sysctl_max, rlimit_max);
|
---|
321 | }
|
---|
322 |
|
---|
323 | /**
|
---|
324 | * Common part of freeing allocated data for one parameter.
|
---|
325 | */
|
---|
326 | static void free_one_parameter_common(void *parm_ptr,
|
---|
327 | struct parm_struct parm)
|
---|
328 | {
|
---|
329 | if ((parm.type == P_STRING) ||
|
---|
330 | (parm.type == P_USTRING))
|
---|
331 | {
|
---|
332 | lpcfg_string_free((char**)parm_ptr);
|
---|
333 | } else if (parm.type == P_LIST || parm.type == P_CMDLIST) {
|
---|
334 | TALLOC_FREE(*((char***)parm_ptr));
|
---|
335 | }
|
---|
336 | }
|
---|
337 |
|
---|
338 | /**
|
---|
339 | * Free the allocated data for one parameter for a share
|
---|
340 | * given as a service struct.
|
---|
341 | */
|
---|
342 | static void free_one_parameter(struct loadparm_service *service,
|
---|
343 | struct parm_struct parm)
|
---|
344 | {
|
---|
345 | void *parm_ptr;
|
---|
346 |
|
---|
347 | if (parm.p_class != P_LOCAL) {
|
---|
348 | return;
|
---|
349 | }
|
---|
350 |
|
---|
351 | parm_ptr = lp_parm_ptr(service, &parm);
|
---|
352 |
|
---|
353 | free_one_parameter_common(parm_ptr, parm);
|
---|
354 | }
|
---|
355 |
|
---|
356 | /**
|
---|
357 | * Free the allocated parameter data of a share given
|
---|
358 | * as a service struct.
|
---|
359 | */
|
---|
360 | static void free_parameters(struct loadparm_service *service)
|
---|
361 | {
|
---|
362 | uint32_t i;
|
---|
363 |
|
---|
364 | for (i=0; parm_table[i].label; i++) {
|
---|
365 | free_one_parameter(service, parm_table[i]);
|
---|
366 | }
|
---|
367 | }
|
---|
368 |
|
---|
369 | /**
|
---|
370 | * Free the allocated data for one parameter for a given share
|
---|
371 | * specified by an snum.
|
---|
372 | */
|
---|
373 | static void free_one_parameter_by_snum(int snum, struct parm_struct parm)
|
---|
374 | {
|
---|
375 | void *parm_ptr;
|
---|
376 |
|
---|
377 | if (snum < 0) {
|
---|
378 | parm_ptr = lp_parm_ptr(NULL, &parm);
|
---|
379 | } else if (parm.p_class != P_LOCAL) {
|
---|
380 | return;
|
---|
381 | } else {
|
---|
382 | parm_ptr = lp_parm_ptr(ServicePtrs[snum], &parm);
|
---|
383 | }
|
---|
384 |
|
---|
385 | free_one_parameter_common(parm_ptr, parm);
|
---|
386 | }
|
---|
387 |
|
---|
388 | /**
|
---|
389 | * Free the allocated parameter data for a share specified
|
---|
390 | * by an snum.
|
---|
391 | */
|
---|
392 | static void free_parameters_by_snum(int snum)
|
---|
393 | {
|
---|
394 | uint32_t i;
|
---|
395 |
|
---|
396 | for (i=0; parm_table[i].label; i++) {
|
---|
397 | free_one_parameter_by_snum(snum, parm_table[i]);
|
---|
398 | }
|
---|
399 | }
|
---|
400 |
|
---|
401 | /**
|
---|
402 | * Free the allocated global parameters.
|
---|
403 | */
|
---|
404 | static void free_global_parameters(void)
|
---|
405 | {
|
---|
406 | uint32_t i;
|
---|
407 | struct parm_struct *parm;
|
---|
408 |
|
---|
409 | free_param_opts(&Globals.param_opt);
|
---|
410 | free_parameters_by_snum(GLOBAL_SECTION_SNUM);
|
---|
411 |
|
---|
412 | /* Reset references in the defaults because the context is going to be freed */
|
---|
413 | for (i=0; parm_table[i].label; i++) {
|
---|
414 | parm = &parm_table[i];
|
---|
415 | if ((parm->type == P_STRING) ||
|
---|
416 | (parm->type == P_USTRING)) {
|
---|
417 | if ((parm->def.svalue != NULL) &&
|
---|
418 | (*(parm->def.svalue) != '\0')) {
|
---|
419 | if (talloc_parent(parm->def.svalue) == Globals.ctx) {
|
---|
420 | parm->def.svalue = NULL;
|
---|
421 | }
|
---|
422 | }
|
---|
423 | }
|
---|
424 | }
|
---|
425 | TALLOC_FREE(Globals.ctx);
|
---|
426 | }
|
---|
427 |
|
---|
428 | struct lp_stored_option {
|
---|
429 | struct lp_stored_option *prev, *next;
|
---|
430 | const char *label;
|
---|
431 | const char *value;
|
---|
432 | };
|
---|
433 |
|
---|
434 | static struct lp_stored_option *stored_options;
|
---|
435 |
|
---|
436 | /*
|
---|
437 | save options set by lp_set_cmdline() into a list. This list is
|
---|
438 | re-applied when we do a globals reset, so that cmdline set options
|
---|
439 | are sticky across reloads of smb.conf
|
---|
440 | */
|
---|
441 | bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
|
---|
442 | {
|
---|
443 | struct lp_stored_option *entry, *entry_next;
|
---|
444 | for (entry = stored_options; entry != NULL; entry = entry_next) {
|
---|
445 | entry_next = entry->next;
|
---|
446 | if (strcmp(pszParmName, entry->label) == 0) {
|
---|
447 | DLIST_REMOVE(stored_options, entry);
|
---|
448 | talloc_free(entry);
|
---|
449 | break;
|
---|
450 | }
|
---|
451 | }
|
---|
452 |
|
---|
453 | entry = talloc(NULL, struct lp_stored_option);
|
---|
454 | if (!entry) {
|
---|
455 | return false;
|
---|
456 | }
|
---|
457 |
|
---|
458 | entry->label = talloc_strdup(entry, pszParmName);
|
---|
459 | if (!entry->label) {
|
---|
460 | talloc_free(entry);
|
---|
461 | return false;
|
---|
462 | }
|
---|
463 |
|
---|
464 | entry->value = talloc_strdup(entry, pszParmValue);
|
---|
465 | if (!entry->value) {
|
---|
466 | talloc_free(entry);
|
---|
467 | return false;
|
---|
468 | }
|
---|
469 |
|
---|
470 | DLIST_ADD_END(stored_options, entry);
|
---|
471 |
|
---|
472 | return true;
|
---|
473 | }
|
---|
474 |
|
---|
475 | static bool apply_lp_set_cmdline(void)
|
---|
476 | {
|
---|
477 | struct lp_stored_option *entry = NULL;
|
---|
478 | for (entry = stored_options; entry != NULL; entry = entry->next) {
|
---|
479 | if (!lp_set_cmdline_helper(entry->label, entry->value)) {
|
---|
480 | DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
|
---|
481 | entry->label, entry->value));
|
---|
482 | return false;
|
---|
483 | }
|
---|
484 | }
|
---|
485 | return true;
|
---|
486 | }
|
---|
487 |
|
---|
488 | /***************************************************************************
|
---|
489 | Initialise the global parameter structure.
|
---|
490 | ***************************************************************************/
|
---|
491 |
|
---|
492 | static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
|
---|
493 | {
|
---|
494 | static bool done_init = false;
|
---|
495 | char *s = NULL;
|
---|
496 | int i;
|
---|
497 |
|
---|
498 | /* If requested to initialize only once and we've already done it... */
|
---|
499 | if (!reinit_globals && done_init) {
|
---|
500 | /* ... then we have nothing more to do */
|
---|
501 | return;
|
---|
502 | }
|
---|
503 |
|
---|
504 | if (!done_init) {
|
---|
505 | /* The logfile can be set before this is invoked. Free it if so. */
|
---|
506 | lpcfg_string_free(&Globals.logfile);
|
---|
507 | done_init = true;
|
---|
508 | } else {
|
---|
509 | free_global_parameters();
|
---|
510 | }
|
---|
511 |
|
---|
512 | /* This memset and the free_global_parameters() above will
|
---|
513 | * wipe out smb.conf options set with lp_set_cmdline(). The
|
---|
514 | * apply_lp_set_cmdline() call puts these values back in the
|
---|
515 | * table once the defaults are set */
|
---|
516 | ZERO_STRUCT(Globals);
|
---|
517 |
|
---|
518 | Globals.ctx = talloc_pooled_object(NULL, char, 272, 2048);
|
---|
519 |
|
---|
520 | /* Initialize the flags list if necessary */
|
---|
521 | if (flags_list == NULL) {
|
---|
522 | get_flags();
|
---|
523 | }
|
---|
524 |
|
---|
525 | for (i = 0; parm_table[i].label; i++) {
|
---|
526 | if ((parm_table[i].type == P_STRING ||
|
---|
527 | parm_table[i].type == P_USTRING))
|
---|
528 | {
|
---|
529 | lpcfg_string_set(
|
---|
530 | Globals.ctx,
|
---|
531 | (char **)lp_parm_ptr(NULL, &parm_table[i]),
|
---|
532 | "");
|
---|
533 | }
|
---|
534 | }
|
---|
535 |
|
---|
536 |
|
---|
537 | lpcfg_string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
|
---|
538 | lpcfg_string_set(Globals.ctx, &sDefault.printjob_username, "%U");
|
---|
539 |
|
---|
540 | init_printer_values(lp_ctx, Globals.ctx, &sDefault);
|
---|
541 |
|
---|
542 | sDefault.ntvfs_handler = str_list_make_v3_const(NULL, "unixuid default", NULL);
|
---|
543 |
|
---|
544 | DEBUG(3, ("Initialising global parameters\n"));
|
---|
545 |
|
---|
546 | /* Must manually force to upper case here, as this does not go via the handler */
|
---|
547 | lpcfg_string_set(Globals.ctx, &Globals.netbios_name,
|
---|
548 | myhostname_upper());
|
---|
549 |
|
---|
550 | lpcfg_string_set(Globals.ctx, &Globals.smb_passwd_file,
|
---|
551 | get_dyn_SMB_PASSWD_FILE());
|
---|
552 | lpcfg_string_set(Globals.ctx, &Globals.private_dir,
|
---|
553 | get_dyn_PRIVATE_DIR());
|
---|
554 |
|
---|
555 | /* use the new 'hash2' method by default, with a prefix of 1 */
|
---|
556 | lpcfg_string_set(Globals.ctx, &Globals.mangling_method, "hash2");
|
---|
557 | Globals.mangle_prefix = 1;
|
---|
558 |
|
---|
559 | lpcfg_string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
|
---|
560 |
|
---|
561 | /* using UTF8 by default allows us to support all chars */
|
---|
562 | lpcfg_string_set(Globals.ctx, &Globals.unix_charset,
|
---|
563 | DEFAULT_UNIX_CHARSET);
|
---|
564 |
|
---|
565 | /* Use codepage 850 as a default for the dos character set */
|
---|
566 | lpcfg_string_set(Globals.ctx, &Globals.dos_charset,
|
---|
567 | DEFAULT_DOS_CHARSET);
|
---|
568 |
|
---|
569 | /*
|
---|
570 | * Allow the default PASSWD_CHAT to be overridden in local.h.
|
---|
571 | */
|
---|
572 | lpcfg_string_set(Globals.ctx, &Globals.passwd_chat,
|
---|
573 | DEFAULT_PASSWD_CHAT);
|
---|
574 |
|
---|
575 | lpcfg_string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
|
---|
576 |
|
---|
577 | lpcfg_string_set(Globals.ctx, &Globals.passwd_program, "");
|
---|
578 | lpcfg_string_set(Globals.ctx, &Globals.lock_directory,
|
---|
579 | get_dyn_LOCKDIR());
|
---|
580 | lpcfg_string_set(Globals.ctx, &Globals.state_directory,
|
---|
581 | get_dyn_STATEDIR());
|
---|
582 | lpcfg_string_set(Globals.ctx, &Globals.cache_directory,
|
---|
583 | get_dyn_CACHEDIR());
|
---|
584 | lpcfg_string_set(Globals.ctx, &Globals.pid_directory,
|
---|
585 | get_dyn_PIDDIR());
|
---|
586 | lpcfg_string_set(Globals.ctx, &Globals.nbt_client_socket_address,
|
---|
587 | "0.0.0.0");
|
---|
588 | /*
|
---|
589 | * By default support explicit binding to broadcast
|
---|
590 | * addresses.
|
---|
591 | */
|
---|
592 | Globals.nmbd_bind_explicit_broadcast = true;
|
---|
593 |
|
---|
594 | s = talloc_asprintf(talloc_tos(), "Samba %s", samba_version_string());
|
---|
595 | if (s == NULL) {
|
---|
596 | smb_panic("init_globals: ENOMEM");
|
---|
597 | }
|
---|
598 | lpcfg_string_set(Globals.ctx, &Globals.server_string, s);
|
---|
599 | TALLOC_FREE(s);
|
---|
600 | #ifdef DEVELOPER
|
---|
601 | lpcfg_string_set(Globals.ctx, &Globals.panic_action,
|
---|
602 | "/bin/sleep 999999999");
|
---|
603 | #endif
|
---|
604 |
|
---|
605 | lpcfg_string_set(Globals.ctx, &Globals.socket_options,
|
---|
606 | DEFAULT_SOCKET_OPTIONS);
|
---|
607 |
|
---|
608 | lpcfg_string_set(Globals.ctx, &Globals.logon_drive, "");
|
---|
609 | /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
|
---|
610 | lpcfg_string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
|
---|
611 | lpcfg_string_set(Globals.ctx, &Globals.logon_path,
|
---|
612 | "\\\\%N\\%U\\profile");
|
---|
613 |
|
---|
614 | Globals.name_resolve_order = str_list_make_v3_const(NULL, "lmhosts wins host bcast", NULL);
|
---|
615 | lpcfg_string_set(Globals.ctx, &Globals.password_server, "*");
|
---|
616 |
|
---|
617 | Globals.algorithmic_rid_base = BASE_RID;
|
---|
618 |
|
---|
619 | Globals.load_printers = true;
|
---|
620 | Globals.printcap_cache_time = 750; /* 12.5 minutes */
|
---|
621 |
|
---|
622 | Globals.config_backend = config_backend;
|
---|
623 | Globals._server_role = ROLE_AUTO;
|
---|
624 |
|
---|
625 | /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
|
---|
626 | /* Discovered by 2 days of pain by Don McCall @ HP :-). */
|
---|
627 | Globals.max_xmit = 0x4104;
|
---|
628 | Globals.max_mux = 50; /* This is *needed* for profile support. */
|
---|
629 | Globals.lpq_cache_time = 30; /* changed to handle large print servers better -- jerry */
|
---|
630 | Globals._disable_spoolss = false;
|
---|
631 | Globals.max_smbd_processes = 0;/* no limit specified */
|
---|
632 | Globals.username_level = 0;
|
---|
633 | Globals.deadtime = 0;
|
---|
634 | Globals.getwd_cache = true;
|
---|
635 | Globals.large_readwrite = true;
|
---|
636 | Globals.max_log_size = 5000;
|
---|
637 | Globals.max_open_files = max_open_files();
|
---|
638 | Globals.server_max_protocol = PROTOCOL_SMB3_11;
|
---|
639 | Globals.server_min_protocol = PROTOCOL_LANMAN1;
|
---|
640 | Globals._client_max_protocol = PROTOCOL_DEFAULT;
|
---|
641 | Globals.client_min_protocol = PROTOCOL_CORE;
|
---|
642 | Globals._client_ipc_max_protocol = PROTOCOL_DEFAULT;
|
---|
643 | Globals._client_ipc_min_protocol = PROTOCOL_DEFAULT;
|
---|
644 | Globals._security = SEC_AUTO;
|
---|
645 | Globals.encrypt_passwords = true;
|
---|
646 | Globals.client_schannel = Auto;
|
---|
647 | Globals.winbind_sealed_pipes = true;
|
---|
648 | Globals.require_strong_key = true;
|
---|
649 | Globals.server_schannel = Auto;
|
---|
650 | Globals.read_raw = true;
|
---|
651 | Globals.write_raw = true;
|
---|
652 | Globals.null_passwords = false;
|
---|
653 | Globals.old_password_allowed_period = 60;
|
---|
654 | Globals.obey_pam_restrictions = false;
|
---|
655 | Globals.syslog = 1;
|
---|
656 | Globals.syslog_only = false;
|
---|
657 | Globals.timestamp_logs = true;
|
---|
658 | lpcfg_string_set(Globals.ctx, &Globals.log_level, "0");
|
---|
659 | Globals.debug_prefix_timestamp = false;
|
---|
660 | Globals.debug_hires_timestamp = true;
|
---|
661 | Globals.debug_pid = false;
|
---|
662 | Globals.debug_uid = false;
|
---|
663 | Globals.debug_class = false;
|
---|
664 | Globals.enable_core_files = true;
|
---|
665 | Globals.max_ttl = 60 * 60 * 24 * 3; /* 3 days default. */
|
---|
666 | Globals.max_wins_ttl = 60 * 60 * 24 * 6; /* 6 days default. */
|
---|
667 | Globals.min_wins_ttl = 60 * 60 * 6; /* 6 hours default. */
|
---|
668 | Globals.machine_password_timeout = 60 * 60 * 24 * 7; /* 7 days default. */
|
---|
669 | Globals.lm_announce = Auto; /* = Auto: send only if LM clients found */
|
---|
670 | Globals.lm_interval = 60;
|
---|
671 | #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
|
---|
672 | Globals.nis_homedir = false;
|
---|
673 | #ifdef WITH_NISPLUS_HOME
|
---|
674 | lpcfg_string_set(Globals.ctx, &Globals.homedir_map,
|
---|
675 | "auto_home.org_dir");
|
---|
676 | #else
|
---|
677 | lpcfg_string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
|
---|
678 | #endif
|
---|
679 | #endif
|
---|
680 | Globals.time_server = false;
|
---|
681 | Globals.bind_interfaces_only = false;
|
---|
682 | Globals.unix_password_sync = false;
|
---|
683 | Globals.pam_password_change = false;
|
---|
684 | Globals.passwd_chat_debug = false;
|
---|
685 | Globals.passwd_chat_timeout = 2; /* 2 second default. */
|
---|
686 | Globals.nt_pipe_support = true; /* Do NT pipes by default. */
|
---|
687 | Globals.nt_status_support = true; /* Use NT status by default. */
|
---|
688 | Globals.smbd_profiling_level = 0;
|
---|
689 | Globals.stat_cache = true; /* use stat cache by default */
|
---|
690 | Globals.max_stat_cache_size = 256; /* 256k by default */
|
---|
691 | Globals.restrict_anonymous = 0;
|
---|
692 | Globals.client_lanman_auth = false; /* Do NOT use the LanMan hash if it is available */
|
---|
693 | Globals.client_plaintext_auth = false; /* Do NOT use a plaintext password even if is requested by the server */
|
---|
694 | Globals.lanman_auth = false; /* Do NOT use the LanMan hash, even if it is supplied */
|
---|
695 | Globals.ntlm_auth = true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
|
---|
696 | Globals.raw_ntlmv2_auth = false; /* Reject NTLMv2 without NTLMSSP */
|
---|
697 | Globals.client_ntlmv2_auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
|
---|
698 | /* Note, that we will also use NTLM2 session security (which is different), if it is available */
|
---|
699 |
|
---|
700 | Globals.allow_dcerpc_auth_level_connect = false; /* we don't allow this by default */
|
---|
701 |
|
---|
702 | Globals.map_to_guest = 0; /* By Default, "Never" */
|
---|
703 | Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */
|
---|
704 | Globals.enhanced_browsing = true;
|
---|
705 | Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
|
---|
706 | #ifdef MMAP_BLACKLIST
|
---|
707 | Globals.use_mmap = false;
|
---|
708 | #else
|
---|
709 | Globals.use_mmap = true;
|
---|
710 | #endif
|
---|
711 | Globals.unicode = true;
|
---|
712 | Globals.unix_extensions = true;
|
---|
713 | Globals.reset_on_zero_vc = false;
|
---|
714 | Globals.log_writeable_files_on_exit = false;
|
---|
715 | Globals.create_krb5_conf = true;
|
---|
716 | Globals._winbind_max_domain_connections = 1;
|
---|
717 |
|
---|
718 | /* hostname lookups can be very expensive and are broken on
|
---|
719 | a large number of sites (tridge) */
|
---|
720 | Globals.hostname_lookups = false;
|
---|
721 |
|
---|
722 | Globals.change_notify = true,
|
---|
723 | Globals.kernel_change_notify = true,
|
---|
724 |
|
---|
725 | lpcfg_string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
|
---|
726 | lpcfg_string_set(Globals.ctx, &Globals.ldap_suffix, "");
|
---|
727 | lpcfg_string_set(Globals.ctx, &Globals._ldap_machine_suffix, "");
|
---|
728 | lpcfg_string_set(Globals.ctx, &Globals._ldap_user_suffix, "");
|
---|
729 | lpcfg_string_set(Globals.ctx, &Globals._ldap_group_suffix, "");
|
---|
730 | lpcfg_string_set(Globals.ctx, &Globals._ldap_idmap_suffix, "");
|
---|
731 |
|
---|
732 | lpcfg_string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
|
---|
733 | Globals.ldap_ssl = LDAP_SSL_START_TLS;
|
---|
734 | Globals.ldap_ssl_ads = false;
|
---|
735 | Globals.ldap_deref = -1;
|
---|
736 | Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
|
---|
737 | Globals.ldap_delete_dn = false;
|
---|
738 | Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */
|
---|
739 | Globals.ldap_follow_referral = Auto;
|
---|
740 | Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT;
|
---|
741 | Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT;
|
---|
742 | Globals.ldap_page_size = LDAP_PAGE_SIZE;
|
---|
743 |
|
---|
744 | Globals.ldap_debug_level = 0;
|
---|
745 | Globals.ldap_debug_threshold = 10;
|
---|
746 |
|
---|
747 | Globals.client_ldap_sasl_wrapping = ADS_AUTH_SASL_SIGN;
|
---|
748 |
|
---|
749 | Globals.ldap_server_require_strong_auth =
|
---|
750 | LDAP_SERVER_REQUIRE_STRONG_AUTH_YES;
|
---|
751 |
|
---|
752 | /* This is what we tell the afs client. in reality we set the token
|
---|
753 | * to never expire, though, when this runs out the afs client will
|
---|
754 | * forget the token. Set to 0 to get NEVERDATE.*/
|
---|
755 | Globals.afs_token_lifetime = 604800;
|
---|
756 | Globals.cups_connection_timeout = CUPS_DEFAULT_CONNECTION_TIMEOUT;
|
---|
757 |
|
---|
758 | /* these parameters are set to defaults that are more appropriate
|
---|
759 | for the increasing samba install base:
|
---|
760 |
|
---|
761 | as a member of the workgroup, that will possibly become a
|
---|
762 | _local_ master browser (lm = true). this is opposed to a forced
|
---|
763 | local master browser startup (pm = true).
|
---|
764 |
|
---|
765 | doesn't provide WINS server service by default (wsupp = false),
|
---|
766 | and doesn't provide domain master browser services by default, either.
|
---|
767 |
|
---|
768 | */
|
---|
769 |
|
---|
770 | Globals.show_add_printer_wizard = true;
|
---|
771 | Globals.os_level = 20;
|
---|
772 | Globals.local_master = true;
|
---|
773 | Globals._domain_master = Auto; /* depending on _domain_logons */
|
---|
774 | Globals._domain_logons = false;
|
---|
775 | Globals.browse_list = true;
|
---|
776 | Globals.we_are_a_wins_server = false;
|
---|
777 | Globals.wins_proxy = false;
|
---|
778 |
|
---|
779 | TALLOC_FREE(Globals.init_logon_delayed_hosts);
|
---|
780 | Globals.init_logon_delay = 100; /* 100 ms default delay */
|
---|
781 |
|
---|
782 | Globals.wins_dns_proxy = true;
|
---|
783 |
|
---|
784 | Globals.allow_trusted_domains = true;
|
---|
785 | lpcfg_string_set(Globals.ctx, &Globals.idmap_backend, "tdb");
|
---|
786 |
|
---|
787 | lpcfg_string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
|
---|
788 | lpcfg_string_set(Globals.ctx, &Globals.template_homedir,
|
---|
789 | "/home/%D/%U");
|
---|
790 | lpcfg_string_set(Globals.ctx, &Globals.winbind_separator, "\\");
|
---|
791 | lpcfg_string_set(Globals.ctx, &Globals.winbindd_socket_directory,
|
---|
792 | dyn_WINBINDD_SOCKET_DIR);
|
---|
793 |
|
---|
794 | lpcfg_string_set(Globals.ctx, &Globals.cups_server, "");
|
---|
795 | lpcfg_string_set(Globals.ctx, &Globals.iprint_server, "");
|
---|
796 |
|
---|
797 | lpcfg_string_set(Globals.ctx, &Globals._ctdbd_socket, "");
|
---|
798 |
|
---|
799 | Globals.cluster_addresses = NULL;
|
---|
800 | Globals.clustering = false;
|
---|
801 | Globals.ctdb_timeout = 0;
|
---|
802 | Globals.ctdb_locktime_warn_threshold = 0;
|
---|
803 |
|
---|
804 | Globals.winbind_cache_time = 300; /* 5 minutes */
|
---|
805 | Globals.winbind_reconnect_delay = 30; /* 30 seconds */
|
---|
806 | Globals.winbind_request_timeout = 60; /* 60 seconds */
|
---|
807 | Globals.winbind_max_clients = 200;
|
---|
808 | Globals.winbind_enum_users = false;
|
---|
809 | Globals.winbind_enum_groups = false;
|
---|
810 | Globals.winbind_use_default_domain = false;
|
---|
811 | Globals.winbind_trusted_domains_only = false;
|
---|
812 | Globals.winbind_nested_groups = true;
|
---|
813 | Globals.winbind_expand_groups = 0;
|
---|
814 | Globals.winbind_nss_info = str_list_make_v3_const(NULL, "template", NULL);
|
---|
815 | Globals.winbind_refresh_tickets = false;
|
---|
816 | Globals.winbind_offline_logon = false;
|
---|
817 |
|
---|
818 | Globals.idmap_cache_time = 86400 * 7; /* a week by default */
|
---|
819 | Globals.idmap_negative_cache_time = 120; /* 2 minutes by default */
|
---|
820 |
|
---|
821 | Globals.passdb_expand_explicit = false;
|
---|
822 |
|
---|
823 | Globals.name_cache_timeout = 660; /* In seconds */
|
---|
824 |
|
---|
825 | Globals.use_spnego = true;
|
---|
826 | Globals.client_use_spnego = true;
|
---|
827 |
|
---|
828 | Globals.client_signing = SMB_SIGNING_DEFAULT;
|
---|
829 | Globals._client_ipc_signing = SMB_SIGNING_DEFAULT;
|
---|
830 | Globals.server_signing = SMB_SIGNING_DEFAULT;
|
---|
831 |
|
---|
832 | Globals.defer_sharing_violations = true;
|
---|
833 | Globals.smb_ports = str_list_make_v3_const(NULL, SMB_PORTS, NULL);
|
---|
834 |
|
---|
835 | Globals.enable_privileges = true;
|
---|
836 | Globals.host_msdfs = true;
|
---|
837 | Globals.enable_asu_support = false;
|
---|
838 |
|
---|
839 | /* User defined shares. */
|
---|
840 | s = talloc_asprintf(talloc_tos(), "%s/usershares", get_dyn_STATEDIR());
|
---|
841 | if (s == NULL) {
|
---|
842 | smb_panic("init_globals: ENOMEM");
|
---|
843 | }
|
---|
844 | lpcfg_string_set(Globals.ctx, &Globals.usershare_path, s);
|
---|
845 | TALLOC_FREE(s);
|
---|
846 | lpcfg_string_set(Globals.ctx, &Globals.usershare_template_share, "");
|
---|
847 | Globals.usershare_max_shares = 0;
|
---|
848 | /* By default disallow sharing of directories not owned by the sharer. */
|
---|
849 | Globals.usershare_owner_only = true;
|
---|
850 | /* By default disallow guest access to usershares. */
|
---|
851 | Globals.usershare_allow_guests = false;
|
---|
852 |
|
---|
853 | Globals.keepalive = DEFAULT_KEEPALIVE;
|
---|
854 |
|
---|
855 | /* By default no shares out of the registry */
|
---|
856 | Globals.registry_shares = false;
|
---|
857 |
|
---|
858 | Globals.min_receivefile_size = 0;
|
---|
859 |
|
---|
860 | Globals.map_untrusted_to_domain = false;
|
---|
861 | Globals.multicast_dns_register = true;
|
---|
862 |
|
---|
863 | Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
|
---|
864 | Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
|
---|
865 | Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
|
---|
866 | Globals.smb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
|
---|
867 | Globals.smb2_leases = false;
|
---|
868 |
|
---|
869 | lpcfg_string_set(Globals.ctx, &Globals.ncalrpc_dir,
|
---|
870 | get_dyn_NCALRPCDIR());
|
---|
871 |
|
---|
872 | Globals.server_services = str_list_make_v3_const(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL);
|
---|
873 |
|
---|
874 | Globals.dcerpc_endpoint_servers = str_list_make_v3_const(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
|
---|
875 |
|
---|
876 | Globals.tls_enabled = true;
|
---|
877 | Globals.tls_verify_peer = TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE;
|
---|
878 |
|
---|
879 | lpcfg_string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
|
---|
880 | lpcfg_string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
|
---|
881 | lpcfg_string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
|
---|
882 | lpcfg_string_set(Globals.ctx, &Globals.tls_priority,
|
---|
883 | "NORMAL:-VERS-SSL3.0");
|
---|
884 |
|
---|
885 | lpcfg_string_set(Globals.ctx, &Globals.share_backend, "classic");
|
---|
886 |
|
---|
887 | Globals._preferred_master = Auto;
|
---|
888 |
|
---|
889 | Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
|
---|
890 |
|
---|
891 | lpcfg_string_set(Globals.ctx, &Globals.ntp_signd_socket_directory,
|
---|
892 | get_dyn_NTP_SIGND_SOCKET_DIR());
|
---|
893 |
|
---|
894 | lpcfg_string_set(Globals.ctx,
|
---|
895 | &Globals.winbindd_privileged_socket_directory,
|
---|
896 | get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
|
---|
897 |
|
---|
898 | s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
|
---|
899 | if (s == NULL) {
|
---|
900 | smb_panic("init_globals: ENOMEM");
|
---|
901 | }
|
---|
902 | Globals.samba_kcc_command = str_list_make_v3_const(NULL, s, NULL);
|
---|
903 | TALLOC_FREE(s);
|
---|
904 |
|
---|
905 | s = talloc_asprintf(talloc_tos(), "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR());
|
---|
906 | if (s == NULL) {
|
---|
907 | smb_panic("init_globals: ENOMEM");
|
---|
908 | }
|
---|
909 | Globals.dns_update_command = str_list_make_v3_const(NULL, s, NULL);
|
---|
910 | TALLOC_FREE(s);
|
---|
911 |
|
---|
912 | s = talloc_asprintf(talloc_tos(), "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR());
|
---|
913 | if (s == NULL) {
|
---|
914 | smb_panic("init_globals: ENOMEM");
|
---|
915 | }
|
---|
916 | Globals.spn_update_command = str_list_make_v3_const(NULL, s, NULL);
|
---|
917 | TALLOC_FREE(s);
|
---|
918 |
|
---|
919 | Globals.nsupdate_command = str_list_make_v3_const(NULL, "/usr/bin/nsupdate -g", NULL);
|
---|
920 |
|
---|
921 | Globals.rndc_command = str_list_make_v3_const(NULL, "/usr/sbin/rndc", NULL);
|
---|
922 |
|
---|
923 | Globals.cldap_port = 389;
|
---|
924 |
|
---|
925 | Globals.dgram_port = NBT_DGRAM_SERVICE_PORT;
|
---|
926 |
|
---|
927 | Globals.nbt_port = NBT_NAME_SERVICE_PORT;
|
---|
928 |
|
---|
929 | Globals.krb5_port = 88;
|
---|
930 |
|
---|
931 | Globals.kpasswd_port = 464;
|
---|
932 |
|
---|
933 | Globals.web_port = 901;
|
---|
934 |
|
---|
935 | Globals.aio_max_threads = 100;
|
---|
936 |
|
---|
937 | /* Now put back the settings that were set with lp_set_cmdline() */
|
---|
938 | apply_lp_set_cmdline();
|
---|
939 | }
|
---|
940 |
|
---|
941 | /* Convenience routine to setup an lp_context with additional s3 variables */
|
---|
942 | static struct loadparm_context *setup_lp_context(TALLOC_CTX *mem_ctx)
|
---|
943 | {
|
---|
944 | struct loadparm_context *lp_ctx;
|
---|
945 |
|
---|
946 | lp_ctx = loadparm_init_s3(mem_ctx,
|
---|
947 | loadparm_s3_helpers());
|
---|
948 | if (lp_ctx == NULL) {
|
---|
949 | DEBUG(0, ("loadparm_init_s3 failed\n"));
|
---|
950 | return NULL;
|
---|
951 | }
|
---|
952 |
|
---|
953 | lp_ctx->sDefault = &sDefault;
|
---|
954 | lp_ctx->services = NULL; /* We do not want to access this directly */
|
---|
955 | lp_ctx->bInGlobalSection = bInGlobalSection;
|
---|
956 | lp_ctx->flags = flags_list;
|
---|
957 |
|
---|
958 | return lp_ctx;
|
---|
959 | }
|
---|
960 |
|
---|
961 | /*******************************************************************
|
---|
962 | Convenience routine to grab string parameters into talloced memory
|
---|
963 | and run standard_sub_basic on them. The buffers can be written to by
|
---|
964 | callers without affecting the source string.
|
---|
965 | ********************************************************************/
|
---|
966 |
|
---|
967 | char *lp_string(TALLOC_CTX *ctx, const char *s)
|
---|
968 | {
|
---|
969 | char *ret;
|
---|
970 |
|
---|
971 | /* The follow debug is useful for tracking down memory problems
|
---|
972 | especially if you have an inner loop that is calling a lp_*()
|
---|
973 | function that returns a string. Perhaps this debug should be
|
---|
974 | present all the time? */
|
---|
975 |
|
---|
976 | #if 0
|
---|
977 | DEBUG(10, ("lp_string(%s)\n", s));
|
---|
978 | #endif
|
---|
979 | if (!s) {
|
---|
980 | return NULL;
|
---|
981 | }
|
---|
982 |
|
---|
983 | ret = talloc_sub_basic(ctx,
|
---|
984 | get_current_username(),
|
---|
985 | current_user_info.domain,
|
---|
986 | s);
|
---|
987 | if (trim_char(ret, '\"', '\"')) {
|
---|
988 | if (strchr(ret,'\"') != NULL) {
|
---|
989 | TALLOC_FREE(ret);
|
---|
990 | ret = talloc_sub_basic(ctx,
|
---|
991 | get_current_username(),
|
---|
992 | current_user_info.domain,
|
---|
993 | s);
|
---|
994 | }
|
---|
995 | }
|
---|
996 | return ret;
|
---|
997 | }
|
---|
998 |
|
---|
999 | /*
|
---|
1000 | In this section all the functions that are used to access the
|
---|
1001 | parameters from the rest of the program are defined
|
---|
1002 | */
|
---|
1003 |
|
---|
1004 | #define FN_GLOBAL_STRING(fn_name,ptr) \
|
---|
1005 | char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
|
---|
1006 | #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
|
---|
1007 | const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
|
---|
1008 | #define FN_GLOBAL_LIST(fn_name,ptr) \
|
---|
1009 | const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
|
---|
1010 | #define FN_GLOBAL_BOOL(fn_name,ptr) \
|
---|
1011 | bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
|
---|
1012 | #define FN_GLOBAL_CHAR(fn_name,ptr) \
|
---|
1013 | char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
|
---|
1014 | #define FN_GLOBAL_INTEGER(fn_name,ptr) \
|
---|
1015 | int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
|
---|
1016 |
|
---|
1017 | #define FN_LOCAL_STRING(fn_name,val) \
|
---|
1018 | char *lp_ ## fn_name(TALLOC_CTX *ctx,int i) {return(lp_string((ctx), (LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val));}
|
---|
1019 | #define FN_LOCAL_CONST_STRING(fn_name,val) \
|
---|
1020 | const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
|
---|
1021 | #define FN_LOCAL_LIST(fn_name,val) \
|
---|
1022 | const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
|
---|
1023 | #define FN_LOCAL_BOOL(fn_name,val) \
|
---|
1024 | bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
|
---|
1025 | #define FN_LOCAL_INTEGER(fn_name,val) \
|
---|
1026 | int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
|
---|
1027 |
|
---|
1028 | #define FN_LOCAL_PARM_BOOL(fn_name,val) \
|
---|
1029 | bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
|
---|
1030 | #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
|
---|
1031 | int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
|
---|
1032 | #define FN_LOCAL_PARM_CHAR(fn_name,val) \
|
---|
1033 | char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
|
---|
1034 |
|
---|
1035 | int lp_winbind_max_domain_connections(void)
|
---|
1036 | {
|
---|
1037 | if (lp_winbind_offline_logon() &&
|
---|
1038 | lp__winbind_max_domain_connections() > 1) {
|
---|
1039 | DEBUG(1, ("offline logons active, restricting max domain "
|
---|
1040 | "connections to 1\n"));
|
---|
1041 | return 1;
|
---|
1042 | }
|
---|
1043 | return MAX(1, lp__winbind_max_domain_connections());
|
---|
1044 | }
|
---|
1045 |
|
---|
1046 | /* These functions remain in source3/param for now */
|
---|
1047 |
|
---|
1048 | #include "lib/param/param_functions.c"
|
---|
1049 |
|
---|
1050 | FN_LOCAL_STRING(servicename, szService)
|
---|
1051 | FN_LOCAL_CONST_STRING(const_servicename, szService)
|
---|
1052 |
|
---|
1053 | /* These functions cannot be auto-generated */
|
---|
1054 | FN_LOCAL_BOOL(autoloaded, autoloaded)
|
---|
1055 | FN_GLOBAL_CONST_STRING(dnsdomain, dnsdomain)
|
---|
1056 |
|
---|
1057 | /* local prototypes */
|
---|
1058 |
|
---|
1059 | static int map_parameter_canonical(const char *pszParmName, bool *inverse);
|
---|
1060 | static const char *get_boolean(bool bool_value);
|
---|
1061 | static bool do_parameter(const char *pszParmName, const char *pszParmValue,
|
---|
1062 | void *userdata);
|
---|
1063 | static bool hash_a_service(const char *name, int number);
|
---|
1064 | static void free_service_byindex(int iService);
|
---|
1065 | static void show_parameter(int parmIndex);
|
---|
1066 | static bool is_synonym_of(int parm1, int parm2, bool *inverse);
|
---|
1067 |
|
---|
1068 | /*
|
---|
1069 | * This is a helper function for parametrical options support. It returns a
|
---|
1070 | * pointer to parametrical option value if it exists or NULL otherwise. Actual
|
---|
1071 | * parametrical functions are quite simple
|
---|
1072 | */
|
---|
1073 | static struct parmlist_entry *get_parametrics(int snum, const char *type,
|
---|
1074 | const char *option)
|
---|
1075 | {
|
---|
1076 | if (snum >= iNumServices) return NULL;
|
---|
1077 |
|
---|
1078 | if (snum < 0) {
|
---|
1079 | return get_parametric_helper(NULL, type, option, Globals.param_opt);
|
---|
1080 | } else {
|
---|
1081 | return get_parametric_helper(ServicePtrs[snum],
|
---|
1082 | type, option, Globals.param_opt);
|
---|
1083 | }
|
---|
1084 | }
|
---|
1085 |
|
---|
1086 | static void discard_whitespace(char *str)
|
---|
1087 | {
|
---|
1088 | size_t len = strlen(str);
|
---|
1089 | size_t i = 0;
|
---|
1090 |
|
---|
1091 | while (i < len) {
|
---|
1092 | if (isspace(str[i])) {
|
---|
1093 | memmove(&str[i], &str[i+1], len-i);
|
---|
1094 | len -= 1;
|
---|
1095 | continue;
|
---|
1096 | }
|
---|
1097 | i += 1;
|
---|
1098 | }
|
---|
1099 | }
|
---|
1100 |
|
---|
1101 | /**
|
---|
1102 | * @brief Go through all global parametric parameters
|
---|
1103 | *
|
---|
1104 | * @param regex_str A regular expression to scan param for
|
---|
1105 | * @param max_matches Max number of submatches the regexp expects
|
---|
1106 | * @param cb Function to call on match. Should return true
|
---|
1107 | * when it wants wi_scan_global_parametrics to stop
|
---|
1108 | * scanning
|
---|
1109 | * @param private_data Anonymous pointer passed to cb
|
---|
1110 | *
|
---|
1111 | * @return 0: success, regcomp/regexec return value on error.
|
---|
1112 | * See "man regexec" for possible errors
|
---|
1113 | */
|
---|
1114 |
|
---|
1115 | int lp_wi_scan_global_parametrics(
|
---|
1116 | const char *regex_str, size_t max_matches,
|
---|
1117 | bool (*cb)(const char *string, regmatch_t matches[],
|
---|
1118 | void *private_data),
|
---|
1119 | void *private_data)
|
---|
1120 | {
|
---|
1121 | struct parmlist_entry *data;
|
---|
1122 | regex_t regex;
|
---|
1123 | int ret;
|
---|
1124 |
|
---|
1125 | ret = regcomp(®ex, regex_str, REG_ICASE);
|
---|
1126 | if (ret != 0) {
|
---|
1127 | return ret;
|
---|
1128 | }
|
---|
1129 |
|
---|
1130 | for (data = Globals.param_opt; data != NULL; data = data->next) {
|
---|
1131 | size_t keylen = strlen(data->key);
|
---|
1132 | char key[keylen+1];
|
---|
1133 | regmatch_t matches[max_matches];
|
---|
1134 | bool stop;
|
---|
1135 |
|
---|
1136 | memcpy(key, data->key, sizeof(key));
|
---|
1137 | discard_whitespace(key);
|
---|
1138 |
|
---|
1139 | ret = regexec(®ex, key, max_matches, matches, 0);
|
---|
1140 | if (ret == REG_NOMATCH) {
|
---|
1141 | continue;
|
---|
1142 | }
|
---|
1143 | if (ret != 0) {
|
---|
1144 | goto fail;
|
---|
1145 | }
|
---|
1146 |
|
---|
1147 | stop = cb(key, matches, private_data);
|
---|
1148 | if (stop) {
|
---|
1149 | break;
|
---|
1150 | }
|
---|
1151 | }
|
---|
1152 |
|
---|
1153 | ret = 0;
|
---|
1154 | fail:
|
---|
1155 | regfree(®ex);
|
---|
1156 | return ret;
|
---|
1157 | }
|
---|
1158 |
|
---|
1159 |
|
---|
1160 | #define MISSING_PARAMETER(name) \
|
---|
1161 | DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
|
---|
1162 |
|
---|
1163 | /*******************************************************************
|
---|
1164 | convenience routine to return enum parameters.
|
---|
1165 | ********************************************************************/
|
---|
1166 | static int lp_enum(const char *s,const struct enum_list *_enum)
|
---|
1167 | {
|
---|
1168 | int i;
|
---|
1169 |
|
---|
1170 | if (!s || !*s || !_enum) {
|
---|
1171 | MISSING_PARAMETER(lp_enum);
|
---|
1172 | return (-1);
|
---|
1173 | }
|
---|
1174 |
|
---|
1175 | for (i=0; _enum[i].name; i++) {
|
---|
1176 | if (strequal(_enum[i].name,s))
|
---|
1177 | return _enum[i].value;
|
---|
1178 | }
|
---|
1179 |
|
---|
1180 | DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s));
|
---|
1181 | return (-1);
|
---|
1182 | }
|
---|
1183 |
|
---|
1184 | #undef MISSING_PARAMETER
|
---|
1185 |
|
---|
1186 | /* Return parametric option from a given service. Type is a part of option before ':' */
|
---|
1187 | /* Parametric option has following syntax: 'Type: option = value' */
|
---|
1188 | char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
|
---|
1189 | {
|
---|
1190 | struct parmlist_entry *data = get_parametrics(snum, type, option);
|
---|
1191 |
|
---|
1192 | if (data == NULL||data->value==NULL) {
|
---|
1193 | if (def) {
|
---|
1194 | return lp_string(ctx, def);
|
---|
1195 | } else {
|
---|
1196 | return NULL;
|
---|
1197 | }
|
---|
1198 | }
|
---|
1199 |
|
---|
1200 | return lp_string(ctx, data->value);
|
---|
1201 | }
|
---|
1202 |
|
---|
1203 | /* Return parametric option from a given service. Type is a part of option before ':' */
|
---|
1204 | /* Parametric option has following syntax: 'Type: option = value' */
|
---|
1205 | const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def)
|
---|
1206 | {
|
---|
1207 | struct parmlist_entry *data = get_parametrics(snum, type, option);
|
---|
1208 |
|
---|
1209 | if (data == NULL||data->value==NULL)
|
---|
1210 | return def;
|
---|
1211 |
|
---|
1212 | return data->value;
|
---|
1213 | }
|
---|
1214 |
|
---|
1215 |
|
---|
1216 | /* Return parametric option from a given service. Type is a part of option before ':' */
|
---|
1217 | /* Parametric option has following syntax: 'Type: option = value' */
|
---|
1218 |
|
---|
1219 | const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def)
|
---|
1220 | {
|
---|
1221 | struct parmlist_entry *data = get_parametrics(snum, type, option);
|
---|
1222 |
|
---|
1223 | if (data == NULL||data->value==NULL)
|
---|
1224 | return (const char **)def;
|
---|
1225 |
|
---|
1226 | if (data->list==NULL) {
|
---|
1227 | data->list = str_list_make_v3(NULL, data->value, NULL);
|
---|
1228 | }
|
---|
1229 |
|
---|
1230 | return discard_const_p(const char *, data->list);
|
---|
1231 | }
|
---|
1232 |
|
---|
1233 | /* Return parametric option from a given service. Type is a part of option before ':' */
|
---|
1234 | /* Parametric option has following syntax: 'Type: option = value' */
|
---|
1235 |
|
---|
1236 | int lp_parm_int(int snum, const char *type, const char *option, int def)
|
---|
1237 | {
|
---|
1238 | struct parmlist_entry *data = get_parametrics(snum, type, option);
|
---|
1239 |
|
---|
1240 | if (data && data->value && *data->value)
|
---|
1241 | return lp_int(data->value);
|
---|
1242 |
|
---|
1243 | return def;
|
---|
1244 | }
|
---|
1245 |
|
---|
1246 | /* Return parametric option from a given service. Type is a part of option before ':' */
|
---|
1247 | /* Parametric option has following syntax: 'Type: option = value' */
|
---|
1248 |
|
---|
1249 | unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def)
|
---|
1250 | {
|
---|
1251 | struct parmlist_entry *data = get_parametrics(snum, type, option);
|
---|
1252 |
|
---|
1253 | if (data && data->value && *data->value)
|
---|
1254 | return lp_ulong(data->value);
|
---|
1255 |
|
---|
1256 | return def;
|
---|
1257 | }
|
---|
1258 |
|
---|
1259 | /* Return parametric option from a given service. Type is a part of option before ':' */
|
---|
1260 | /* Parametric option has following syntax: 'Type: option = value' */
|
---|
1261 |
|
---|
1262 | unsigned long long lp_parm_ulonglong(int snum, const char *type,
|
---|
1263 | const char *option, unsigned long long def)
|
---|
1264 | {
|
---|
1265 | struct parmlist_entry *data = get_parametrics(snum, type, option);
|
---|
1266 |
|
---|
1267 | if (data && data->value && *data->value) {
|
---|
1268 | return lp_ulonglong(data->value);
|
---|
1269 | }
|
---|
1270 |
|
---|
1271 | return def;
|
---|
1272 | }
|
---|
1273 |
|
---|
1274 | /* Return parametric option from a given service. Type is a part of option
|
---|
1275 | * before ':' */
|
---|
1276 | /* Parametric option has following syntax: 'Type: option = value' */
|
---|
1277 |
|
---|
1278 | bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
|
---|
1279 | {
|
---|
1280 | struct parmlist_entry *data = get_parametrics(snum, type, option);
|
---|
1281 |
|
---|
1282 | if (data && data->value && *data->value)
|
---|
1283 | return lp_bool(data->value);
|
---|
1284 |
|
---|
1285 | return def;
|
---|
1286 | }
|
---|
1287 |
|
---|
1288 | /* Return parametric option from a given service. Type is a part of option before ':' */
|
---|
1289 | /* Parametric option has following syntax: 'Type: option = value' */
|
---|
1290 |
|
---|
1291 | int lp_parm_enum(int snum, const char *type, const char *option,
|
---|
1292 | const struct enum_list *_enum, int def)
|
---|
1293 | {
|
---|
1294 | struct parmlist_entry *data = get_parametrics(snum, type, option);
|
---|
1295 |
|
---|
1296 | if (data && data->value && *data->value && _enum)
|
---|
1297 | return lp_enum(data->value, _enum);
|
---|
1298 |
|
---|
1299 | return def;
|
---|
1300 | }
|
---|
1301 |
|
---|
1302 | /**
|
---|
1303 | * free a param_opts structure.
|
---|
1304 | * param_opts handling should be moved to talloc;
|
---|
1305 | * then this whole functions reduces to a TALLOC_FREE().
|
---|
1306 | */
|
---|
1307 |
|
---|
1308 | static void free_param_opts(struct parmlist_entry **popts)
|
---|
1309 | {
|
---|
1310 | struct parmlist_entry *opt, *next_opt;
|
---|
1311 |
|
---|
1312 | if (*popts != NULL) {
|
---|
1313 | DEBUG(5, ("Freeing parametrics:\n"));
|
---|
1314 | }
|
---|
1315 | opt = *popts;
|
---|
1316 | while (opt != NULL) {
|
---|
1317 | lpcfg_string_free(&opt->key);
|
---|
1318 | lpcfg_string_free(&opt->value);
|
---|
1319 | TALLOC_FREE(opt->list);
|
---|
1320 | next_opt = opt->next;
|
---|
1321 | TALLOC_FREE(opt);
|
---|
1322 | opt = next_opt;
|
---|
1323 | }
|
---|
1324 | *popts = NULL;
|
---|
1325 | }
|
---|
1326 |
|
---|
1327 | /***************************************************************************
|
---|
1328 | Free the dynamically allocated parts of a service struct.
|
---|
1329 | ***************************************************************************/
|
---|
1330 |
|
---|
1331 | static void free_service(struct loadparm_service *pservice)
|
---|
1332 | {
|
---|
1333 | if (!pservice)
|
---|
1334 | return;
|
---|
1335 |
|
---|
1336 | if (pservice->szService)
|
---|
1337 | DEBUG(5, ("free_service: Freeing service %s\n",
|
---|
1338 | pservice->szService));
|
---|
1339 |
|
---|
1340 | free_parameters(pservice);
|
---|
1341 |
|
---|
1342 | lpcfg_string_free(&pservice->szService);
|
---|
1343 | TALLOC_FREE(pservice->copymap);
|
---|
1344 |
|
---|
1345 | free_param_opts(&pservice->param_opt);
|
---|
1346 |
|
---|
1347 | ZERO_STRUCTP(pservice);
|
---|
1348 | }
|
---|
1349 |
|
---|
1350 |
|
---|
1351 | /***************************************************************************
|
---|
1352 | remove a service indexed in the ServicePtrs array from the ServiceHash
|
---|
1353 | and free the dynamically allocated parts
|
---|
1354 | ***************************************************************************/
|
---|
1355 |
|
---|
1356 | static void free_service_byindex(int idx)
|
---|
1357 | {
|
---|
1358 | if ( !LP_SNUM_OK(idx) )
|
---|
1359 | return;
|
---|
1360 |
|
---|
1361 | ServicePtrs[idx]->valid = false;
|
---|
1362 |
|
---|
1363 | /* we have to cleanup the hash record */
|
---|
1364 |
|
---|
1365 | if (ServicePtrs[idx]->szService) {
|
---|
1366 | char *canon_name = canonicalize_servicename(
|
---|
1367 | talloc_tos(),
|
---|
1368 | ServicePtrs[idx]->szService );
|
---|
1369 |
|
---|
1370 | dbwrap_delete_bystring(ServiceHash, canon_name );
|
---|
1371 | TALLOC_FREE(canon_name);
|
---|
1372 | }
|
---|
1373 |
|
---|
1374 | free_service(ServicePtrs[idx]);
|
---|
1375 | TALLOC_FREE(ServicePtrs[idx]);
|
---|
1376 | }
|
---|
1377 |
|
---|
1378 | /***************************************************************************
|
---|
1379 | Add a new service to the services array initialising it with the given
|
---|
1380 | service.
|
---|
1381 | ***************************************************************************/
|
---|
1382 |
|
---|
1383 | static int add_a_service(const struct loadparm_service *pservice, const char *name)
|
---|
1384 | {
|
---|
1385 | int i;
|
---|
1386 | int num_to_alloc = iNumServices + 1;
|
---|
1387 | struct loadparm_service **tsp = NULL;
|
---|
1388 |
|
---|
1389 | /* it might already exist */
|
---|
1390 | if (name) {
|
---|
1391 | i = getservicebyname(name, NULL);
|
---|
1392 | if (i >= 0) {
|
---|
1393 | return (i);
|
---|
1394 | }
|
---|
1395 | }
|
---|
1396 |
|
---|
1397 | /* Re use empty slots if any before allocating new one.*/
|
---|
1398 | for (i=0; i < iNumServices; i++) {
|
---|
1399 | if (ServicePtrs[i] == NULL) {
|
---|
1400 | break;
|
---|
1401 | }
|
---|
1402 | }
|
---|
1403 | if (i == iNumServices) {
|
---|
1404 | /* if not, then create one */
|
---|
1405 | tsp = talloc_realloc(NULL, ServicePtrs,
|
---|
1406 | struct loadparm_service *,
|
---|
1407 | num_to_alloc);
|
---|
1408 | if (tsp == NULL) {
|
---|
1409 | DEBUG(0, ("add_a_service: failed to enlarge "
|
---|
1410 | "ServicePtrs!\n"));
|
---|
1411 | return (-1);
|
---|
1412 | }
|
---|
1413 | ServicePtrs = tsp;
|
---|
1414 | iNumServices++;
|
---|
1415 | }
|
---|
1416 | ServicePtrs[i] = talloc_zero(ServicePtrs, struct loadparm_service);
|
---|
1417 | if (!ServicePtrs[i]) {
|
---|
1418 | DEBUG(0,("add_a_service: out of memory!\n"));
|
---|
1419 | return (-1);
|
---|
1420 | }
|
---|
1421 |
|
---|
1422 | ServicePtrs[i]->valid = true;
|
---|
1423 |
|
---|
1424 | copy_service(ServicePtrs[i], pservice, NULL);
|
---|
1425 | if (name)
|
---|
1426 | lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->szService,
|
---|
1427 | name);
|
---|
1428 |
|
---|
1429 | DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
|
---|
1430 | i, ServicePtrs[i]->szService));
|
---|
1431 |
|
---|
1432 | if (!hash_a_service(ServicePtrs[i]->szService, i)) {
|
---|
1433 | return (-1);
|
---|
1434 | }
|
---|
1435 |
|
---|
1436 | return (i);
|
---|
1437 | }
|
---|
1438 |
|
---|
1439 | /***************************************************************************
|
---|
1440 | Convert a string to uppercase and remove whitespaces.
|
---|
1441 | ***************************************************************************/
|
---|
1442 |
|
---|
1443 | char *canonicalize_servicename(TALLOC_CTX *ctx, const char *src)
|
---|
1444 | {
|
---|
1445 | char *result;
|
---|
1446 |
|
---|
1447 | if ( !src ) {
|
---|
1448 | DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
|
---|
1449 | return NULL;
|
---|
1450 | }
|
---|
1451 |
|
---|
1452 | result = talloc_strdup(ctx, src);
|
---|
1453 | SMB_ASSERT(result != NULL);
|
---|
1454 |
|
---|
1455 | if (!strlower_m(result)) {
|
---|
1456 | TALLOC_FREE(result);
|
---|
1457 | return NULL;
|
---|
1458 | }
|
---|
1459 | return result;
|
---|
1460 | }
|
---|
1461 |
|
---|
1462 | /***************************************************************************
|
---|
1463 | Add a name/index pair for the services array to the hash table.
|
---|
1464 | ***************************************************************************/
|
---|
1465 |
|
---|
1466 | static bool hash_a_service(const char *name, int idx)
|
---|
1467 | {
|
---|
1468 | char *canon_name;
|
---|
1469 |
|
---|
1470 | if ( !ServiceHash ) {
|
---|
1471 | DEBUG(10,("hash_a_service: creating servicehash\n"));
|
---|
1472 | ServiceHash = db_open_rbt(NULL);
|
---|
1473 | if ( !ServiceHash ) {
|
---|
1474 | DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
|
---|
1475 | return false;
|
---|
1476 | }
|
---|
1477 | }
|
---|
1478 |
|
---|
1479 | DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
|
---|
1480 | idx, name));
|
---|
1481 |
|
---|
1482 | canon_name = canonicalize_servicename(talloc_tos(), name );
|
---|
1483 |
|
---|
1484 | dbwrap_store_bystring(ServiceHash, canon_name,
|
---|
1485 | make_tdb_data((uint8_t *)&idx, sizeof(idx)),
|
---|
1486 | TDB_REPLACE);
|
---|
1487 |
|
---|
1488 | TALLOC_FREE(canon_name);
|
---|
1489 |
|
---|
1490 | return true;
|
---|
1491 | }
|
---|
1492 |
|
---|
1493 | /***************************************************************************
|
---|
1494 | Add a new home service, with the specified home directory, defaults coming
|
---|
1495 | from service ifrom.
|
---|
1496 | ***************************************************************************/
|
---|
1497 |
|
---|
1498 | bool lp_add_home(const char *pszHomename, int iDefaultService,
|
---|
1499 | const char *user, const char *pszHomedir)
|
---|
1500 | {
|
---|
1501 | int i;
|
---|
1502 |
|
---|
1503 | if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
|
---|
1504 | pszHomedir[0] == '\0') {
|
---|
1505 | return false;
|
---|
1506 | }
|
---|
1507 |
|
---|
1508 | i = add_a_service(ServicePtrs[iDefaultService], pszHomename);
|
---|
1509 |
|
---|
1510 | if (i < 0)
|
---|
1511 | return false;
|
---|
1512 |
|
---|
1513 | if (!(*(ServicePtrs[iDefaultService]->path))
|
---|
1514 | || strequal(ServicePtrs[iDefaultService]->path,
|
---|
1515 | lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
|
---|
1516 | lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path,
|
---|
1517 | pszHomedir);
|
---|
1518 | }
|
---|
1519 |
|
---|
1520 | if (!(*(ServicePtrs[i]->comment))) {
|
---|
1521 | char *comment = talloc_asprintf(talloc_tos(), "Home directory of %s", user);
|
---|
1522 | if (comment == NULL) {
|
---|
1523 | return false;
|
---|
1524 | }
|
---|
1525 | lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment,
|
---|
1526 | comment);
|
---|
1527 | TALLOC_FREE(comment);
|
---|
1528 | }
|
---|
1529 |
|
---|
1530 | /* set the browseable flag from the global default */
|
---|
1531 |
|
---|
1532 | ServicePtrs[i]->browseable = sDefault.browseable;
|
---|
1533 | ServicePtrs[i]->access_based_share_enum = sDefault.access_based_share_enum;
|
---|
1534 |
|
---|
1535 | ServicePtrs[i]->autoloaded = true;
|
---|
1536 |
|
---|
1537 | DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename,
|
---|
1538 | user, ServicePtrs[i]->path ));
|
---|
1539 |
|
---|
1540 | return true;
|
---|
1541 | }
|
---|
1542 |
|
---|
1543 | /***************************************************************************
|
---|
1544 | Add a new service, based on an old one.
|
---|
1545 | ***************************************************************************/
|
---|
1546 |
|
---|
1547 | int lp_add_service(const char *pszService, int iDefaultService)
|
---|
1548 | {
|
---|
1549 | if (iDefaultService < 0) {
|
---|
1550 | return add_a_service(&sDefault, pszService);
|
---|
1551 | }
|
---|
1552 |
|
---|
1553 | return (add_a_service(ServicePtrs[iDefaultService], pszService));
|
---|
1554 | }
|
---|
1555 |
|
---|
1556 | /***************************************************************************
|
---|
1557 | Add the IPC service.
|
---|
1558 | ***************************************************************************/
|
---|
1559 |
|
---|
1560 | static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
|
---|
1561 | {
|
---|
1562 | char *comment = NULL;
|
---|
1563 | int i = add_a_service(&sDefault, ipc_name);
|
---|
1564 |
|
---|
1565 | if (i < 0)
|
---|
1566 | return false;
|
---|
1567 |
|
---|
1568 | comment = talloc_asprintf(talloc_tos(), "IPC Service (%s)",
|
---|
1569 | Globals.server_string);
|
---|
1570 | if (comment == NULL) {
|
---|
1571 | return false;
|
---|
1572 | }
|
---|
1573 |
|
---|
1574 | lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
|
---|
1575 | lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
|
---|
1576 | lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
|
---|
1577 | lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
|
---|
1578 | ServicePtrs[i]->max_connections = 0;
|
---|
1579 | ServicePtrs[i]->available = true;
|
---|
1580 | ServicePtrs[i]->read_only = true;
|
---|
1581 | ServicePtrs[i]->guest_only = false;
|
---|
1582 | ServicePtrs[i]->administrative_share = true;
|
---|
1583 | ServicePtrs[i]->guest_ok = guest_ok;
|
---|
1584 | ServicePtrs[i]->printable = false;
|
---|
1585 | ServicePtrs[i]->browseable = sDefault.browseable;
|
---|
1586 | ServicePtrs[i]->autoloaded = true;
|
---|
1587 |
|
---|
1588 | DEBUG(3, ("adding IPC service\n"));
|
---|
1589 |
|
---|
1590 | TALLOC_FREE(comment);
|
---|
1591 | return true;
|
---|
1592 | }
|
---|
1593 |
|
---|
1594 | /***************************************************************************
|
---|
1595 | Add a new printer service, with defaults coming from service iFrom.
|
---|
1596 | ***************************************************************************/
|
---|
1597 |
|
---|
1598 | bool lp_add_printer(const char *pszPrintername, int iDefaultService)
|
---|
1599 | {
|
---|
1600 | const char *comment = "From Printcap";
|
---|
1601 | int i = add_a_service(ServicePtrs[iDefaultService], pszPrintername);
|
---|
1602 |
|
---|
1603 | if (i < 0)
|
---|
1604 | return false;
|
---|
1605 |
|
---|
1606 | /* note that we do NOT default the availability flag to true - */
|
---|
1607 | /* we take it from the default service passed. This allows all */
|
---|
1608 | /* dynamic printers to be disabled by disabling the [printers] */
|
---|
1609 | /* entry (if/when the 'available' keyword is implemented!). */
|
---|
1610 |
|
---|
1611 | /* the printer name is set to the service name. */
|
---|
1612 | lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->_printername,
|
---|
1613 | pszPrintername);
|
---|
1614 | lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
|
---|
1615 |
|
---|
1616 | /* set the browseable flag from the gloabl default */
|
---|
1617 | ServicePtrs[i]->browseable = sDefault.browseable;
|
---|
1618 |
|
---|
1619 | /* Printers cannot be read_only. */
|
---|
1620 | ServicePtrs[i]->read_only = false;
|
---|
1621 | /* No oplocks on printer services. */
|
---|
1622 | ServicePtrs[i]->oplocks = false;
|
---|
1623 | /* Printer services must be printable. */
|
---|
1624 | ServicePtrs[i]->printable = true;
|
---|
1625 |
|
---|
1626 | DEBUG(3, ("adding printer service %s\n", pszPrintername));
|
---|
1627 |
|
---|
1628 | return true;
|
---|
1629 | }
|
---|
1630 |
|
---|
1631 |
|
---|
1632 | /***************************************************************************
|
---|
1633 | Check whether the given parameter name is valid.
|
---|
1634 | Parametric options (names containing a colon) are considered valid.
|
---|
1635 | ***************************************************************************/
|
---|
1636 |
|
---|
1637 | bool lp_parameter_is_valid(const char *pszParmName)
|
---|
1638 | {
|
---|
1639 | return ((lpcfg_map_parameter(pszParmName) != -1) ||
|
---|
1640 | (strchr(pszParmName, ':') != NULL));
|
---|
1641 | }
|
---|
1642 |
|
---|
1643 | /***************************************************************************
|
---|
1644 | Check whether the given name is the name of a global parameter.
|
---|
1645 | Returns true for strings belonging to parameters of class
|
---|
1646 | P_GLOBAL, false for all other strings, also for parametric options
|
---|
1647 | and strings not belonging to any option.
|
---|
1648 | ***************************************************************************/
|
---|
1649 |
|
---|
1650 | bool lp_parameter_is_global(const char *pszParmName)
|
---|
1651 | {
|
---|
1652 | int num = lpcfg_map_parameter(pszParmName);
|
---|
1653 |
|
---|
1654 | if (num >= 0) {
|
---|
1655 | return (parm_table[num].p_class == P_GLOBAL);
|
---|
1656 | }
|
---|
1657 |
|
---|
1658 | return false;
|
---|
1659 | }
|
---|
1660 |
|
---|
1661 | /**************************************************************************
|
---|
1662 | Determine the canonical name for a parameter.
|
---|
1663 | Indicate when it is an inverse (boolean) synonym instead of a
|
---|
1664 | "usual" synonym.
|
---|
1665 | **************************************************************************/
|
---|
1666 |
|
---|
1667 | bool lp_canonicalize_parameter(const char *parm_name, const char **canon_parm,
|
---|
1668 | bool *inverse)
|
---|
1669 | {
|
---|
1670 | int num;
|
---|
1671 |
|
---|
1672 | if (!lp_parameter_is_valid(parm_name)) {
|
---|
1673 | *canon_parm = NULL;
|
---|
1674 | return false;
|
---|
1675 | }
|
---|
1676 |
|
---|
1677 | num = map_parameter_canonical(parm_name, inverse);
|
---|
1678 | if (num < 0) {
|
---|
1679 | /* parametric option */
|
---|
1680 | *canon_parm = parm_name;
|
---|
1681 | } else {
|
---|
1682 | *canon_parm = parm_table[num].label;
|
---|
1683 | }
|
---|
1684 |
|
---|
1685 | return true;
|
---|
1686 |
|
---|
1687 | }
|
---|
1688 |
|
---|
1689 | /**************************************************************************
|
---|
1690 | Determine the canonical name for a parameter.
|
---|
1691 | Turn the value given into the inverse boolean expression when
|
---|
1692 | the synonym is an invers boolean synonym.
|
---|
1693 |
|
---|
1694 | Return true if parm_name is a valid parameter name and
|
---|
1695 | in case it is an invers boolean synonym, if the val string could
|
---|
1696 | successfully be converted to the reverse bool.
|
---|
1697 | Return false in all other cases.
|
---|
1698 | **************************************************************************/
|
---|
1699 |
|
---|
1700 | bool lp_canonicalize_parameter_with_value(const char *parm_name,
|
---|
1701 | const char *val,
|
---|
1702 | const char **canon_parm,
|
---|
1703 | const char **canon_val)
|
---|
1704 | {
|
---|
1705 | int num;
|
---|
1706 | bool inverse;
|
---|
1707 |
|
---|
1708 | if (!lp_parameter_is_valid(parm_name)) {
|
---|
1709 | *canon_parm = NULL;
|
---|
1710 | *canon_val = NULL;
|
---|
1711 | return false;
|
---|
1712 | }
|
---|
1713 |
|
---|
1714 | num = map_parameter_canonical(parm_name, &inverse);
|
---|
1715 | if (num < 0) {
|
---|
1716 | /* parametric option */
|
---|
1717 | *canon_parm = parm_name;
|
---|
1718 | *canon_val = val;
|
---|
1719 | } else {
|
---|
1720 | *canon_parm = parm_table[num].label;
|
---|
1721 | if (inverse) {
|
---|
1722 | if (!lp_invert_boolean(val, canon_val)) {
|
---|
1723 | *canon_val = NULL;
|
---|
1724 | return false;
|
---|
1725 | }
|
---|
1726 | } else {
|
---|
1727 | *canon_val = val;
|
---|
1728 | }
|
---|
1729 | }
|
---|
1730 |
|
---|
1731 | return true;
|
---|
1732 | }
|
---|
1733 |
|
---|
1734 | /***************************************************************************
|
---|
1735 | Map a parameter's string representation to the index of the canonical
|
---|
1736 | form of the parameter (it might be a synonym).
|
---|
1737 | Returns -1 if the parameter string is not recognised.
|
---|
1738 | ***************************************************************************/
|
---|
1739 |
|
---|
1740 | static int map_parameter_canonical(const char *pszParmName, bool *inverse)
|
---|
1741 | {
|
---|
1742 | int parm_num, canon_num;
|
---|
1743 | bool loc_inverse = false;
|
---|
1744 |
|
---|
1745 | parm_num = lpcfg_map_parameter(pszParmName);
|
---|
1746 | if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_SYNONYM)) {
|
---|
1747 | /* invalid, parametric or no canidate for synonyms ... */
|
---|
1748 | goto done;
|
---|
1749 | }
|
---|
1750 |
|
---|
1751 | for (canon_num = 0; parm_table[canon_num].label; canon_num++) {
|
---|
1752 | if (is_synonym_of(parm_num, canon_num, &loc_inverse)) {
|
---|
1753 | parm_num = canon_num;
|
---|
1754 | goto done;
|
---|
1755 | }
|
---|
1756 | }
|
---|
1757 |
|
---|
1758 | done:
|
---|
1759 | if (inverse != NULL) {
|
---|
1760 | *inverse = loc_inverse;
|
---|
1761 | }
|
---|
1762 | return parm_num;
|
---|
1763 | }
|
---|
1764 |
|
---|
1765 | /***************************************************************************
|
---|
1766 | return true if parameter number parm1 is a synonym of parameter
|
---|
1767 | number parm2 (parm2 being the principal name).
|
---|
1768 | set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
|
---|
1769 | false otherwise.
|
---|
1770 | ***************************************************************************/
|
---|
1771 |
|
---|
1772 | static bool is_synonym_of(int parm1, int parm2, bool *inverse)
|
---|
1773 | {
|
---|
1774 | if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
|
---|
1775 | (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
|
---|
1776 | (parm_table[parm1].flags & FLAG_SYNONYM) &&
|
---|
1777 | !(parm_table[parm2].flags & FLAG_SYNONYM))
|
---|
1778 | {
|
---|
1779 | if (inverse != NULL) {
|
---|
1780 | if ((parm_table[parm1].type == P_BOOLREV) &&
|
---|
1781 | (parm_table[parm2].type == P_BOOL))
|
---|
1782 | {
|
---|
1783 | *inverse = true;
|
---|
1784 | } else {
|
---|
1785 | *inverse = false;
|
---|
1786 | }
|
---|
1787 | }
|
---|
1788 | return true;
|
---|
1789 | }
|
---|
1790 | return false;
|
---|
1791 | }
|
---|
1792 |
|
---|
1793 | /***************************************************************************
|
---|
1794 | Show one parameter's name, type, [values,] and flags.
|
---|
1795 | (helper functions for show_parameter_list)
|
---|
1796 | ***************************************************************************/
|
---|
1797 |
|
---|
1798 | static void show_parameter(int parmIndex)
|
---|
1799 | {
|
---|
1800 | int enumIndex, flagIndex;
|
---|
1801 | int parmIndex2;
|
---|
1802 | bool hadFlag;
|
---|
1803 | bool hadSyn;
|
---|
1804 | bool inverse;
|
---|
1805 | const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
|
---|
1806 | "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
|
---|
1807 | "P_ENUM", "P_BYTES", "P_CMDLIST" };
|
---|
1808 | unsigned flags[] = { FLAG_DEPRECATED, FLAG_SYNONYM };
|
---|
1809 | const char *flag_names[] = { "FLAG_DEPRECATED", "FLAG_SYNONYM", NULL};
|
---|
1810 |
|
---|
1811 | printf("%s=%s", parm_table[parmIndex].label,
|
---|
1812 | type[parm_table[parmIndex].type]);
|
---|
1813 | if (parm_table[parmIndex].type == P_ENUM) {
|
---|
1814 | printf(",");
|
---|
1815 | for (enumIndex=0;
|
---|
1816 | parm_table[parmIndex].enum_list[enumIndex].name;
|
---|
1817 | enumIndex++)
|
---|
1818 | {
|
---|
1819 | printf("%s%s",
|
---|
1820 | enumIndex ? "|" : "",
|
---|
1821 | parm_table[parmIndex].enum_list[enumIndex].name);
|
---|
1822 | }
|
---|
1823 | }
|
---|
1824 | printf(",");
|
---|
1825 | hadFlag = false;
|
---|
1826 | for (flagIndex=0; flag_names[flagIndex]; flagIndex++) {
|
---|
1827 | if (parm_table[parmIndex].flags & flags[flagIndex]) {
|
---|
1828 | printf("%s%s",
|
---|
1829 | hadFlag ? "|" : "",
|
---|
1830 | flag_names[flagIndex]);
|
---|
1831 | hadFlag = true;
|
---|
1832 | }
|
---|
1833 | }
|
---|
1834 |
|
---|
1835 | /* output synonyms */
|
---|
1836 | hadSyn = false;
|
---|
1837 | for (parmIndex2=0; parm_table[parmIndex2].label; parmIndex2++) {
|
---|
1838 | if (is_synonym_of(parmIndex, parmIndex2, &inverse)) {
|
---|
1839 | printf(" (%ssynonym of %s)", inverse ? "inverse " : "",
|
---|
1840 | parm_table[parmIndex2].label);
|
---|
1841 | } else if (is_synonym_of(parmIndex2, parmIndex, &inverse)) {
|
---|
1842 | if (!hadSyn) {
|
---|
1843 | printf(" (synonyms: ");
|
---|
1844 | hadSyn = true;
|
---|
1845 | } else {
|
---|
1846 | printf(", ");
|
---|
1847 | }
|
---|
1848 | printf("%s%s", parm_table[parmIndex2].label,
|
---|
1849 | inverse ? "[i]" : "");
|
---|
1850 | }
|
---|
1851 | }
|
---|
1852 | if (hadSyn) {
|
---|
1853 | printf(")");
|
---|
1854 | }
|
---|
1855 |
|
---|
1856 | printf("\n");
|
---|
1857 | }
|
---|
1858 |
|
---|
1859 | /***************************************************************************
|
---|
1860 | Show all parameter's name, type, [values,] and flags.
|
---|
1861 | ***************************************************************************/
|
---|
1862 |
|
---|
1863 | void show_parameter_list(void)
|
---|
1864 | {
|
---|
1865 | int classIndex, parmIndex;
|
---|
1866 | const char *section_names[] = { "local", "global", NULL};
|
---|
1867 |
|
---|
1868 | for (classIndex=0; section_names[classIndex]; classIndex++) {
|
---|
1869 | printf("[%s]\n", section_names[classIndex]);
|
---|
1870 | for (parmIndex = 0; parm_table[parmIndex].label; parmIndex++) {
|
---|
1871 | if (parm_table[parmIndex].p_class == classIndex) {
|
---|
1872 | show_parameter(parmIndex);
|
---|
1873 | }
|
---|
1874 | }
|
---|
1875 | }
|
---|
1876 | }
|
---|
1877 |
|
---|
1878 | /***************************************************************************
|
---|
1879 | Get the standard string representation of a boolean value ("yes" or "no")
|
---|
1880 | ***************************************************************************/
|
---|
1881 |
|
---|
1882 | static const char *get_boolean(bool bool_value)
|
---|
1883 | {
|
---|
1884 | static const char *yes_str = "yes";
|
---|
1885 | static const char *no_str = "no";
|
---|
1886 |
|
---|
1887 | return (bool_value ? yes_str : no_str);
|
---|
1888 | }
|
---|
1889 |
|
---|
1890 | /***************************************************************************
|
---|
1891 | Provide the string of the negated boolean value associated to the boolean
|
---|
1892 | given as a string. Returns false if the passed string does not correctly
|
---|
1893 | represent a boolean.
|
---|
1894 | ***************************************************************************/
|
---|
1895 |
|
---|
1896 | bool lp_invert_boolean(const char *str, const char **inverse_str)
|
---|
1897 | {
|
---|
1898 | bool val;
|
---|
1899 |
|
---|
1900 | if (!set_boolean(str, &val)) {
|
---|
1901 | return false;
|
---|
1902 | }
|
---|
1903 |
|
---|
1904 | *inverse_str = get_boolean(!val);
|
---|
1905 | return true;
|
---|
1906 | }
|
---|
1907 |
|
---|
1908 | /***************************************************************************
|
---|
1909 | Provide the canonical string representation of a boolean value given
|
---|
1910 | as a string. Return true on success, false if the string given does
|
---|
1911 | not correctly represent a boolean.
|
---|
1912 | ***************************************************************************/
|
---|
1913 |
|
---|
1914 | bool lp_canonicalize_boolean(const char *str, const char**canon_str)
|
---|
1915 | {
|
---|
1916 | bool val;
|
---|
1917 |
|
---|
1918 | if (!set_boolean(str, &val)) {
|
---|
1919 | return false;
|
---|
1920 | }
|
---|
1921 |
|
---|
1922 | *canon_str = get_boolean(val);
|
---|
1923 | return true;
|
---|
1924 | }
|
---|
1925 |
|
---|
1926 | /***************************************************************************
|
---|
1927 | Find a service by name. Otherwise works like get_service.
|
---|
1928 | ***************************************************************************/
|
---|
1929 |
|
---|
1930 | int getservicebyname(const char *pszServiceName, struct loadparm_service *pserviceDest)
|
---|
1931 | {
|
---|
1932 | int iService = -1;
|
---|
1933 | char *canon_name;
|
---|
1934 | TDB_DATA data;
|
---|
1935 | NTSTATUS status;
|
---|
1936 |
|
---|
1937 | if (ServiceHash == NULL) {
|
---|
1938 | return -1;
|
---|
1939 | }
|
---|
1940 |
|
---|
1941 | canon_name = canonicalize_servicename(talloc_tos(), pszServiceName);
|
---|
1942 |
|
---|
1943 | status = dbwrap_fetch_bystring(ServiceHash, canon_name, canon_name,
|
---|
1944 | &data);
|
---|
1945 |
|
---|
1946 | if (NT_STATUS_IS_OK(status) &&
|
---|
1947 | (data.dptr != NULL) &&
|
---|
1948 | (data.dsize == sizeof(iService)))
|
---|
1949 | {
|
---|
1950 | iService = *(int *)data.dptr;
|
---|
1951 | }
|
---|
1952 |
|
---|
1953 | TALLOC_FREE(canon_name);
|
---|
1954 |
|
---|
1955 | if ((iService != -1) && (LP_SNUM_OK(iService))
|
---|
1956 | && (pserviceDest != NULL)) {
|
---|
1957 | copy_service(pserviceDest, ServicePtrs[iService], NULL);
|
---|
1958 | }
|
---|
1959 |
|
---|
1960 | return (iService);
|
---|
1961 | }
|
---|
1962 |
|
---|
1963 | /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
|
---|
1964 | struct loadparm_service *lp_service(const char *pszServiceName)
|
---|
1965 | {
|
---|
1966 | int iService = getservicebyname(pszServiceName, NULL);
|
---|
1967 | if (iService == -1 || !LP_SNUM_OK(iService)) {
|
---|
1968 | return NULL;
|
---|
1969 | }
|
---|
1970 | return ServicePtrs[iService];
|
---|
1971 | }
|
---|
1972 |
|
---|
1973 | struct loadparm_service *lp_servicebynum(int snum)
|
---|
1974 | {
|
---|
1975 | if ((snum == -1) || !LP_SNUM_OK(snum)) {
|
---|
1976 | return NULL;
|
---|
1977 | }
|
---|
1978 | return ServicePtrs[snum];
|
---|
1979 | }
|
---|
1980 |
|
---|
1981 | struct loadparm_service *lp_default_loadparm_service()
|
---|
1982 | {
|
---|
1983 | return &sDefault;
|
---|
1984 | }
|
---|
1985 |
|
---|
1986 | static struct smbconf_ctx *lp_smbconf_ctx(void)
|
---|
1987 | {
|
---|
1988 | sbcErr err;
|
---|
1989 | static struct smbconf_ctx *conf_ctx = NULL;
|
---|
1990 |
|
---|
1991 | if (conf_ctx == NULL) {
|
---|
1992 | err = smbconf_init(NULL, &conf_ctx, "registry:");
|
---|
1993 | if (!SBC_ERROR_IS_OK(err)) {
|
---|
1994 | DEBUG(1, ("error initializing registry configuration: "
|
---|
1995 | "%s\n", sbcErrorString(err)));
|
---|
1996 | conf_ctx = NULL;
|
---|
1997 | }
|
---|
1998 | }
|
---|
1999 |
|
---|
2000 | return conf_ctx;
|
---|
2001 | }
|
---|
2002 |
|
---|
2003 | static bool process_smbconf_service(struct smbconf_service *service)
|
---|
2004 | {
|
---|
2005 | uint32_t count;
|
---|
2006 | bool ret;
|
---|
2007 |
|
---|
2008 | if (service == NULL) {
|
---|
2009 | return false;
|
---|
2010 | }
|
---|
2011 |
|
---|
2012 | ret = lp_do_section(service->name, NULL);
|
---|
2013 | if (ret != true) {
|
---|
2014 | return false;
|
---|
2015 | }
|
---|
2016 | for (count = 0; count < service->num_params; count++) {
|
---|
2017 |
|
---|
2018 | if (!bInGlobalSection && bGlobalOnly) {
|
---|
2019 | ret = true;
|
---|
2020 | } else {
|
---|
2021 | const char *pszParmName = service->param_names[count];
|
---|
2022 | const char *pszParmValue = service->param_values[count];
|
---|
2023 |
|
---|
2024 | DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
|
---|
2025 |
|
---|
2026 | ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
|
---|
2027 | pszParmName, pszParmValue);
|
---|
2028 | }
|
---|
2029 |
|
---|
2030 | if (ret != true) {
|
---|
2031 | return false;
|
---|
2032 | }
|
---|
2033 | }
|
---|
2034 | if (iServiceIndex >= 0) {
|
---|
2035 | return lpcfg_service_ok(ServicePtrs[iServiceIndex]);
|
---|
2036 | }
|
---|
2037 | return true;
|
---|
2038 | }
|
---|
2039 |
|
---|
2040 | /**
|
---|
2041 | * load a service from registry and activate it
|
---|
2042 | */
|
---|
2043 | bool process_registry_service(const char *service_name)
|
---|
2044 | {
|
---|
2045 | sbcErr err;
|
---|
2046 | struct smbconf_service *service = NULL;
|
---|
2047 | TALLOC_CTX *mem_ctx = talloc_stackframe();
|
---|
2048 | struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
|
---|
2049 | bool ret = false;
|
---|
2050 |
|
---|
2051 | if (conf_ctx == NULL) {
|
---|
2052 | goto done;
|
---|
2053 | }
|
---|
2054 |
|
---|
2055 | DEBUG(5, ("process_registry_service: service name %s\n", service_name));
|
---|
2056 |
|
---|
2057 | if (!smbconf_share_exists(conf_ctx, service_name)) {
|
---|
2058 | /*
|
---|
2059 | * Registry does not contain data for this service (yet),
|
---|
2060 | * but make sure lp_load doesn't return false.
|
---|
2061 | */
|
---|
2062 | ret = true;
|
---|
2063 | goto done;
|
---|
2064 | }
|
---|
2065 |
|
---|
2066 | err = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service);
|
---|
2067 | if (!SBC_ERROR_IS_OK(err)) {
|
---|
2068 | goto done;
|
---|
2069 | }
|
---|
2070 |
|
---|
2071 | ret = process_smbconf_service(service);
|
---|
2072 | if (!ret) {
|
---|
2073 | goto done;
|
---|
2074 | }
|
---|
2075 |
|
---|
2076 | /* store the csn */
|
---|
2077 | smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
|
---|
2078 |
|
---|
2079 | done:
|
---|
2080 | TALLOC_FREE(mem_ctx);
|
---|
2081 | return ret;
|
---|
2082 | }
|
---|
2083 |
|
---|
2084 | /*
|
---|
2085 | * process_registry_globals
|
---|
2086 | */
|
---|
2087 | static bool process_registry_globals(void)
|
---|
2088 | {
|
---|
2089 | bool ret;
|
---|
2090 |
|
---|
2091 | add_to_file_list(NULL, &file_lists, INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME);
|
---|
2092 |
|
---|
2093 | if (!bInGlobalSection && bGlobalOnly) {
|
---|
2094 | ret = true;
|
---|
2095 | } else {
|
---|
2096 | const char *pszParmName = "registry shares";
|
---|
2097 | const char *pszParmValue = "yes";
|
---|
2098 |
|
---|
2099 | DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
|
---|
2100 |
|
---|
2101 | ret = lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
|
---|
2102 | pszParmName, pszParmValue);
|
---|
2103 | }
|
---|
2104 |
|
---|
2105 | if (!ret) {
|
---|
2106 | return ret;
|
---|
2107 | }
|
---|
2108 |
|
---|
2109 | return process_registry_service(GLOBAL_NAME);
|
---|
2110 | }
|
---|
2111 |
|
---|
2112 | bool process_registry_shares(void)
|
---|
2113 | {
|
---|
2114 | sbcErr err;
|
---|
2115 | uint32_t count;
|
---|
2116 | struct smbconf_service **service = NULL;
|
---|
2117 | uint32_t num_shares = 0;
|
---|
2118 | TALLOC_CTX *mem_ctx = talloc_stackframe();
|
---|
2119 | struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
|
---|
2120 | bool ret = false;
|
---|
2121 |
|
---|
2122 | if (conf_ctx == NULL) {
|
---|
2123 | goto done;
|
---|
2124 | }
|
---|
2125 |
|
---|
2126 | err = smbconf_get_config(conf_ctx, mem_ctx, &num_shares, &service);
|
---|
2127 | if (!SBC_ERROR_IS_OK(err)) {
|
---|
2128 | goto done;
|
---|
2129 | }
|
---|
2130 |
|
---|
2131 | ret = true;
|
---|
2132 |
|
---|
2133 | for (count = 0; count < num_shares; count++) {
|
---|
2134 | if (strequal(service[count]->name, GLOBAL_NAME)) {
|
---|
2135 | continue;
|
---|
2136 | }
|
---|
2137 | ret = process_smbconf_service(service[count]);
|
---|
2138 | if (!ret) {
|
---|
2139 | goto done;
|
---|
2140 | }
|
---|
2141 | }
|
---|
2142 |
|
---|
2143 | /* store the csn */
|
---|
2144 | smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL);
|
---|
2145 |
|
---|
2146 | done:
|
---|
2147 | TALLOC_FREE(mem_ctx);
|
---|
2148 | return ret;
|
---|
2149 | }
|
---|
2150 |
|
---|
2151 | /**
|
---|
2152 | * reload those shares from registry that are already
|
---|
2153 | * activated in the services array.
|
---|
2154 | */
|
---|
2155 | static bool reload_registry_shares(void)
|
---|
2156 | {
|
---|
2157 | int i;
|
---|
2158 | bool ret = true;
|
---|
2159 |
|
---|
2160 | for (i = 0; i < iNumServices; i++) {
|
---|
2161 | if (!VALID(i)) {
|
---|
2162 | continue;
|
---|
2163 | }
|
---|
2164 |
|
---|
2165 | if (ServicePtrs[i]->usershare == USERSHARE_VALID) {
|
---|
2166 | continue;
|
---|
2167 | }
|
---|
2168 |
|
---|
2169 | ret = process_registry_service(ServicePtrs[i]->szService);
|
---|
2170 | if (!ret) {
|
---|
2171 | goto done;
|
---|
2172 | }
|
---|
2173 | }
|
---|
2174 |
|
---|
2175 | done:
|
---|
2176 | return ret;
|
---|
2177 | }
|
---|
2178 |
|
---|
2179 |
|
---|
2180 | #define MAX_INCLUDE_DEPTH 100
|
---|
2181 |
|
---|
2182 | static uint8_t include_depth;
|
---|
2183 |
|
---|
2184 | /**
|
---|
2185 | * Free the file lists
|
---|
2186 | */
|
---|
2187 | static void free_file_list(void)
|
---|
2188 | {
|
---|
2189 | struct file_lists *f;
|
---|
2190 | struct file_lists *next;
|
---|
2191 |
|
---|
2192 | f = file_lists;
|
---|
2193 | while( f ) {
|
---|
2194 | next = f->next;
|
---|
2195 | TALLOC_FREE( f );
|
---|
2196 | f = next;
|
---|
2197 | }
|
---|
2198 | file_lists = NULL;
|
---|
2199 | }
|
---|
2200 |
|
---|
2201 |
|
---|
2202 | /**
|
---|
2203 | * Utility function for outsiders to check if we're running on registry.
|
---|
2204 | */
|
---|
2205 | bool lp_config_backend_is_registry(void)
|
---|
2206 | {
|
---|
2207 | return (lp_config_backend() == CONFIG_BACKEND_REGISTRY);
|
---|
2208 | }
|
---|
2209 |
|
---|
2210 | /**
|
---|
2211 | * Utility function to check if the config backend is FILE.
|
---|
2212 | */
|
---|
2213 | bool lp_config_backend_is_file(void)
|
---|
2214 | {
|
---|
2215 | return (lp_config_backend() == CONFIG_BACKEND_FILE);
|
---|
2216 | }
|
---|
2217 |
|
---|
2218 | /*******************************************************************
|
---|
2219 | Check if a config file has changed date.
|
---|
2220 | ********************************************************************/
|
---|
2221 |
|
---|
2222 | bool lp_file_list_changed(void)
|
---|
2223 | {
|
---|
2224 | struct file_lists *f = file_lists;
|
---|
2225 |
|
---|
2226 | DEBUG(6, ("lp_file_list_changed()\n"));
|
---|
2227 |
|
---|
2228 | while (f) {
|
---|
2229 | if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
|
---|
2230 | struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
|
---|
2231 |
|
---|
2232 | if (conf_ctx == NULL) {
|
---|
2233 | return false;
|
---|
2234 | }
|
---|
2235 | if (smbconf_changed(conf_ctx, &conf_last_csn, NULL,
|
---|
2236 | NULL))
|
---|
2237 | {
|
---|
2238 | DEBUGADD(6, ("registry config changed\n"));
|
---|
2239 | return true;
|
---|
2240 | }
|
---|
2241 | } else {
|
---|
2242 | time_t mod_time;
|
---|
2243 | char *n2 = NULL;
|
---|
2244 |
|
---|
2245 | n2 = talloc_sub_basic(talloc_tos(),
|
---|
2246 | get_current_username(),
|
---|
2247 | current_user_info.domain,
|
---|
2248 | f->name);
|
---|
2249 | if (!n2) {
|
---|
2250 | return false;
|
---|
2251 | }
|
---|
2252 | DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
|
---|
2253 | f->name, n2, ctime(&f->modtime)));
|
---|
2254 |
|
---|
2255 | mod_time = file_modtime(n2);
|
---|
2256 |
|
---|
2257 | if (mod_time &&
|
---|
2258 | ((f->modtime != mod_time) ||
|
---|
2259 | (f->subfname == NULL) ||
|
---|
2260 | (strcmp(n2, f->subfname) != 0)))
|
---|
2261 | {
|
---|
2262 | DEBUGADD(6,
|
---|
2263 | ("file %s modified: %s\n", n2,
|
---|
2264 | ctime(&mod_time)));
|
---|
2265 | f->modtime = mod_time;
|
---|
2266 | TALLOC_FREE(f->subfname);
|
---|
2267 | f->subfname = talloc_strdup(f, n2);
|
---|
2268 | if (f->subfname == NULL) {
|
---|
2269 | smb_panic("talloc_strdup failed");
|
---|
2270 | }
|
---|
2271 | TALLOC_FREE(n2);
|
---|
2272 | return true;
|
---|
2273 | }
|
---|
2274 | TALLOC_FREE(n2);
|
---|
2275 | }
|
---|
2276 | f = f->next;
|
---|
2277 | }
|
---|
2278 | return false;
|
---|
2279 | }
|
---|
2280 |
|
---|
2281 |
|
---|
2282 | /**
|
---|
2283 | * Initialize iconv conversion descriptors.
|
---|
2284 | *
|
---|
2285 | * This is called the first time it is needed, and also called again
|
---|
2286 | * every time the configuration is reloaded, because the charset or
|
---|
2287 | * codepage might have changed.
|
---|
2288 | **/
|
---|
2289 | static void init_iconv(void)
|
---|
2290 | {
|
---|
2291 | global_iconv_handle = smb_iconv_handle_reinit(NULL, lp_dos_charset(),
|
---|
2292 | lp_unix_charset(),
|
---|
2293 | true, global_iconv_handle);
|
---|
2294 | }
|
---|
2295 |
|
---|
2296 | /***************************************************************************
|
---|
2297 | Handle the include operation.
|
---|
2298 | ***************************************************************************/
|
---|
2299 | static bool bAllowIncludeRegistry = true;
|
---|
2300 |
|
---|
2301 | bool lp_include(struct loadparm_context *lp_ctx, struct loadparm_service *service,
|
---|
2302 | const char *pszParmValue, char **ptr)
|
---|
2303 | {
|
---|
2304 | char *fname;
|
---|
2305 |
|
---|
2306 | if (include_depth >= MAX_INCLUDE_DEPTH) {
|
---|
2307 | DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
|
---|
2308 | include_depth));
|
---|
2309 | return false;
|
---|
2310 | }
|
---|
2311 |
|
---|
2312 | if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) {
|
---|
2313 | if (!bAllowIncludeRegistry) {
|
---|
2314 | return true;
|
---|
2315 | }
|
---|
2316 | if (lp_ctx->bInGlobalSection) {
|
---|
2317 | bool ret;
|
---|
2318 | include_depth++;
|
---|
2319 | ret = process_registry_globals();
|
---|
2320 | include_depth--;
|
---|
2321 | return ret;
|
---|
2322 | } else {
|
---|
2323 | DEBUG(1, ("\"include = registry\" only effective "
|
---|
2324 | "in %s section\n", GLOBAL_NAME));
|
---|
2325 | return false;
|
---|
2326 | }
|
---|
2327 | }
|
---|
2328 |
|
---|
2329 | fname = talloc_sub_basic(talloc_tos(), get_current_username(),
|
---|
2330 | current_user_info.domain,
|
---|
2331 | pszParmValue);
|
---|
2332 |
|
---|
2333 | add_to_file_list(NULL, &file_lists, pszParmValue, fname);
|
---|
2334 |
|
---|
2335 | if (service == NULL) {
|
---|
2336 | lpcfg_string_set(Globals.ctx, ptr, fname);
|
---|
2337 | } else {
|
---|
2338 | lpcfg_string_set(service, ptr, fname);
|
---|
2339 | }
|
---|
2340 |
|
---|
2341 | if (file_exist(fname)) {
|
---|
2342 | bool ret;
|
---|
2343 | include_depth++;
|
---|
2344 | ret = pm_process(fname, lp_do_section, do_parameter, lp_ctx);
|
---|
2345 | include_depth--;
|
---|
2346 | TALLOC_FREE(fname);
|
---|
2347 | return ret;
|
---|
2348 | }
|
---|
2349 |
|
---|
2350 | DEBUG(2, ("Can't find include file %s\n", fname));
|
---|
2351 | TALLOC_FREE(fname);
|
---|
2352 | return true;
|
---|
2353 | }
|
---|
2354 |
|
---|
2355 | bool lp_idmap_range(const char *domain_name, uint32_t *low, uint32_t *high)
|
---|
2356 | {
|
---|
2357 | char *config_option = NULL;
|
---|
2358 | const char *range = NULL;
|
---|
2359 | bool ret = false;
|
---|
2360 |
|
---|
2361 | SMB_ASSERT(low != NULL);
|
---|
2362 | SMB_ASSERT(high != NULL);
|
---|
2363 |
|
---|
2364 | if ((domain_name == NULL) || (domain_name[0] == '\0')) {
|
---|
2365 | domain_name = "*";
|
---|
2366 | }
|
---|
2367 |
|
---|
2368 | config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
|
---|
2369 | domain_name);
|
---|
2370 | if (config_option == NULL) {
|
---|
2371 | DEBUG(0, ("out of memory\n"));
|
---|
2372 | return false;
|
---|
2373 | }
|
---|
2374 |
|
---|
2375 | range = lp_parm_const_string(-1, config_option, "range", NULL);
|
---|
2376 | if (range == NULL) {
|
---|
2377 | DEBUG(1, ("idmap range not specified for domain '%s'\n", domain_name));
|
---|
2378 | goto done;
|
---|
2379 | }
|
---|
2380 |
|
---|
2381 | if (sscanf(range, "%u - %u", low, high) != 2) {
|
---|
2382 | DEBUG(1, ("error parsing idmap range '%s' for domain '%s'\n",
|
---|
2383 | range, domain_name));
|
---|
2384 | goto done;
|
---|
2385 | }
|
---|
2386 |
|
---|
2387 | ret = true;
|
---|
2388 |
|
---|
2389 | done:
|
---|
2390 | talloc_free(config_option);
|
---|
2391 | return ret;
|
---|
2392 |
|
---|
2393 | }
|
---|
2394 |
|
---|
2395 | bool lp_idmap_default_range(uint32_t *low, uint32_t *high)
|
---|
2396 | {
|
---|
2397 | return lp_idmap_range("*", low, high);
|
---|
2398 | }
|
---|
2399 |
|
---|
2400 | const char *lp_idmap_backend(const char *domain_name)
|
---|
2401 | {
|
---|
2402 | char *config_option = NULL;
|
---|
2403 | const char *backend = NULL;
|
---|
2404 |
|
---|
2405 | if ((domain_name == NULL) || (domain_name[0] == '\0')) {
|
---|
2406 | domain_name = "*";
|
---|
2407 | }
|
---|
2408 |
|
---|
2409 | config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
|
---|
2410 | domain_name);
|
---|
2411 | if (config_option == NULL) {
|
---|
2412 | DEBUG(0, ("out of memory\n"));
|
---|
2413 | return false;
|
---|
2414 | }
|
---|
2415 |
|
---|
2416 | backend = lp_parm_const_string(-1, config_option, "backend", NULL);
|
---|
2417 | if (backend == NULL) {
|
---|
2418 | DEBUG(1, ("idmap backend not specified for domain '%s'\n", domain_name));
|
---|
2419 | goto done;
|
---|
2420 | }
|
---|
2421 |
|
---|
2422 | done:
|
---|
2423 | talloc_free(config_option);
|
---|
2424 | return backend;
|
---|
2425 | }
|
---|
2426 |
|
---|
2427 | const char *lp_idmap_default_backend(void)
|
---|
2428 | {
|
---|
2429 | return lp_idmap_backend("*");
|
---|
2430 | }
|
---|
2431 |
|
---|
2432 | /***************************************************************************
|
---|
2433 | Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
|
---|
2434 | ***************************************************************************/
|
---|
2435 |
|
---|
2436 | static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
|
---|
2437 | {
|
---|
2438 | const char *suffix_string;
|
---|
2439 |
|
---|
2440 | suffix_string = talloc_asprintf(ctx, "%s,%s", str,
|
---|
2441 | Globals.ldap_suffix );
|
---|
2442 | if ( !suffix_string ) {
|
---|
2443 | DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
|
---|
2444 | return "";
|
---|
2445 | }
|
---|
2446 |
|
---|
2447 | return suffix_string;
|
---|
2448 | }
|
---|
2449 |
|
---|
2450 | const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
|
---|
2451 | {
|
---|
2452 | if (Globals._ldap_machine_suffix[0])
|
---|
2453 | return append_ldap_suffix(ctx, Globals._ldap_machine_suffix);
|
---|
2454 |
|
---|
2455 | return lp_string(ctx, Globals.ldap_suffix);
|
---|
2456 | }
|
---|
2457 |
|
---|
2458 | const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
|
---|
2459 | {
|
---|
2460 | if (Globals._ldap_user_suffix[0])
|
---|
2461 | return append_ldap_suffix(ctx, Globals._ldap_user_suffix);
|
---|
2462 |
|
---|
2463 | return lp_string(ctx, Globals.ldap_suffix);
|
---|
2464 | }
|
---|
2465 |
|
---|
2466 | const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
|
---|
2467 | {
|
---|
2468 | if (Globals._ldap_group_suffix[0])
|
---|
2469 | return append_ldap_suffix(ctx, Globals._ldap_group_suffix);
|
---|
2470 |
|
---|
2471 | return lp_string(ctx, Globals.ldap_suffix);
|
---|
2472 | }
|
---|
2473 |
|
---|
2474 | const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
|
---|
2475 | {
|
---|
2476 | if (Globals._ldap_idmap_suffix[0])
|
---|
2477 | return append_ldap_suffix(ctx, Globals._ldap_idmap_suffix);
|
---|
2478 |
|
---|
2479 | return lp_string(ctx, Globals.ldap_suffix);
|
---|
2480 | }
|
---|
2481 |
|
---|
2482 | /**
|
---|
2483 | return the parameter pointer for a parameter
|
---|
2484 | */
|
---|
2485 | void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
|
---|
2486 | {
|
---|
2487 | if (service == NULL) {
|
---|
2488 | if (parm->p_class == P_LOCAL)
|
---|
2489 | return (void *)(((char *)&sDefault)+parm->offset);
|
---|
2490 | else if (parm->p_class == P_GLOBAL)
|
---|
2491 | return (void *)(((char *)&Globals)+parm->offset);
|
---|
2492 | else return NULL;
|
---|
2493 | } else {
|
---|
2494 | return (void *)(((char *)service) + parm->offset);
|
---|
2495 | }
|
---|
2496 | }
|
---|
2497 |
|
---|
2498 | /***************************************************************************
|
---|
2499 | Process a parameter for a particular service number. If snum < 0
|
---|
2500 | then assume we are in the globals.
|
---|
2501 | ***************************************************************************/
|
---|
2502 |
|
---|
2503 | bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
|
---|
2504 | {
|
---|
2505 | TALLOC_CTX *frame = talloc_stackframe();
|
---|
2506 | struct loadparm_context *lp_ctx;
|
---|
2507 | bool ok;
|
---|
2508 |
|
---|
2509 | lp_ctx = setup_lp_context(frame);
|
---|
2510 | if (lp_ctx == NULL) {
|
---|
2511 | TALLOC_FREE(frame);
|
---|
2512 | return false;
|
---|
2513 | }
|
---|
2514 |
|
---|
2515 | if (snum < 0) {
|
---|
2516 | ok = lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue);
|
---|
2517 | } else {
|
---|
2518 | ok = lpcfg_do_service_parameter(lp_ctx, ServicePtrs[snum],
|
---|
2519 | pszParmName, pszParmValue);
|
---|
2520 | }
|
---|
2521 |
|
---|
2522 | TALLOC_FREE(frame);
|
---|
2523 |
|
---|
2524 | return ok;
|
---|
2525 | }
|
---|
2526 |
|
---|
2527 | /***************************************************************************
|
---|
2528 | set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
|
---|
2529 | FLAG_CMDLINE won't be overridden by loads from smb.conf.
|
---|
2530 | ***************************************************************************/
|
---|
2531 |
|
---|
2532 | static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue)
|
---|
2533 | {
|
---|
2534 | int parmnum, i;
|
---|
2535 | parmnum = lpcfg_map_parameter(pszParmName);
|
---|
2536 | if (parmnum >= 0) {
|
---|
2537 | flags_list[parmnum] &= ~FLAG_CMDLINE;
|
---|
2538 | if (!lp_do_parameter(-1, pszParmName, pszParmValue)) {
|
---|
2539 | return false;
|
---|
2540 | }
|
---|
2541 | flags_list[parmnum] |= FLAG_CMDLINE;
|
---|
2542 |
|
---|
2543 | /* we have to also set FLAG_CMDLINE on aliases. Aliases must
|
---|
2544 | * be grouped in the table, so we don't have to search the
|
---|
2545 | * whole table */
|
---|
2546 | for (i=parmnum-1;
|
---|
2547 | i>=0 && parm_table[i].offset == parm_table[parmnum].offset
|
---|
2548 | && parm_table[i].p_class == parm_table[parmnum].p_class;
|
---|
2549 | i--) {
|
---|
2550 | flags_list[i] |= FLAG_CMDLINE;
|
---|
2551 | }
|
---|
2552 | for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset
|
---|
2553 | && parm_table[i].p_class == parm_table[parmnum].p_class;i++) {
|
---|
2554 | flags_list[i] |= FLAG_CMDLINE;
|
---|
2555 | }
|
---|
2556 |
|
---|
2557 | return true;
|
---|
2558 | }
|
---|
2559 |
|
---|
2560 | /* it might be parametric */
|
---|
2561 | if (strchr(pszParmName, ':') != NULL) {
|
---|
2562 | set_param_opt(NULL, &Globals.param_opt, pszParmName, pszParmValue, FLAG_CMDLINE);
|
---|
2563 | return true;
|
---|
2564 | }
|
---|
2565 |
|
---|
2566 | DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName));
|
---|
2567 | return false;
|
---|
2568 | }
|
---|
2569 |
|
---|
2570 | bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
|
---|
2571 | {
|
---|
2572 | bool ret;
|
---|
2573 | TALLOC_CTX *frame = talloc_stackframe();
|
---|
2574 | struct loadparm_context *lp_ctx;
|
---|
2575 |
|
---|
2576 | lp_ctx = setup_lp_context(frame);
|
---|
2577 | if (lp_ctx == NULL) {
|
---|
2578 | TALLOC_FREE(frame);
|
---|
2579 | return false;
|
---|
2580 | }
|
---|
2581 |
|
---|
2582 | ret = lpcfg_set_cmdline(lp_ctx, pszParmName, pszParmValue);
|
---|
2583 |
|
---|
2584 | TALLOC_FREE(frame);
|
---|
2585 | return ret;
|
---|
2586 | }
|
---|
2587 |
|
---|
2588 | /***************************************************************************
|
---|
2589 | Process a parameter.
|
---|
2590 | ***************************************************************************/
|
---|
2591 |
|
---|
2592 | static bool do_parameter(const char *pszParmName, const char *pszParmValue,
|
---|
2593 | void *userdata)
|
---|
2594 | {
|
---|
2595 | if (!bInGlobalSection && bGlobalOnly)
|
---|
2596 | return true;
|
---|
2597 |
|
---|
2598 | DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
|
---|
2599 |
|
---|
2600 | if (bInGlobalSection) {
|
---|
2601 | return lpcfg_do_global_parameter(userdata, pszParmName, pszParmValue);
|
---|
2602 | } else {
|
---|
2603 | return lpcfg_do_service_parameter(userdata, ServicePtrs[iServiceIndex],
|
---|
2604 | pszParmName, pszParmValue);
|
---|
2605 | }
|
---|
2606 | }
|
---|
2607 |
|
---|
2608 | /***************************************************************************
|
---|
2609 | Initialize any local variables in the sDefault table, after parsing a
|
---|
2610 | [globals] section.
|
---|
2611 | ***************************************************************************/
|
---|
2612 |
|
---|
2613 | static void init_locals(void)
|
---|
2614 | {
|
---|
2615 | /*
|
---|
2616 | * We run this check once the [globals] is parsed, to force
|
---|
2617 | * the VFS objects and other per-share settings we need for
|
---|
2618 | * the standard way a AD DC is operated. We may change these
|
---|
2619 | * as our code evolves, which is why we force these settings.
|
---|
2620 | *
|
---|
2621 | * We can't do this at the end of lp_load_ex(), as by that
|
---|
2622 | * point the services have been loaded and they will already
|
---|
2623 | * have "" as their vfs objects.
|
---|
2624 | */
|
---|
2625 | if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
|
---|
2626 | const char **vfs_objects = lp_vfs_objects(-1);
|
---|
2627 | if (!vfs_objects || !vfs_objects[0]) {
|
---|
2628 | if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
|
---|
2629 | lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
|
---|
2630 | } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
|
---|
2631 | lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr posix_eadb");
|
---|
2632 | } else {
|
---|
2633 | lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr");
|
---|
2634 | }
|
---|
2635 | }
|
---|
2636 |
|
---|
2637 | lp_do_parameter(-1, "map hidden", "no");
|
---|
2638 | lp_do_parameter(-1, "map system", "no");
|
---|
2639 | lp_do_parameter(-1, "map readonly", "no");
|
---|
2640 | lp_do_parameter(-1, "map archive", "no");
|
---|
2641 | lp_do_parameter(-1, "store dos attributes", "yes");
|
---|
2642 | }
|
---|
2643 | }
|
---|
2644 |
|
---|
2645 | /***************************************************************************
|
---|
2646 | Process a new section (service). At this stage all sections are services.
|
---|
2647 | Later we'll have special sections that permit server parameters to be set.
|
---|
2648 | Returns true on success, false on failure.
|
---|
2649 | ***************************************************************************/
|
---|
2650 |
|
---|
2651 | bool lp_do_section(const char *pszSectionName, void *userdata)
|
---|
2652 | {
|
---|
2653 | struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
|
---|
2654 | bool bRetval;
|
---|
2655 | bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
|
---|
2656 | (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
|
---|
2657 | bRetval = false;
|
---|
2658 |
|
---|
2659 | /* if we were in a global section then do the local inits */
|
---|
2660 | if (bInGlobalSection && !isglobal)
|
---|
2661 | init_locals();
|
---|
2662 |
|
---|
2663 | /* if we've just struck a global section, note the fact. */
|
---|
2664 | bInGlobalSection = isglobal;
|
---|
2665 | if (lp_ctx != NULL) {
|
---|
2666 | lp_ctx->bInGlobalSection = isglobal;
|
---|
2667 | }
|
---|
2668 |
|
---|
2669 | /* check for multiple global sections */
|
---|
2670 | if (bInGlobalSection) {
|
---|
2671 | DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName));
|
---|
2672 | return true;
|
---|
2673 | }
|
---|
2674 |
|
---|
2675 | if (!bInGlobalSection && bGlobalOnly)
|
---|
2676 | return true;
|
---|
2677 |
|
---|
2678 | /* if we have a current service, tidy it up before moving on */
|
---|
2679 | bRetval = true;
|
---|
2680 |
|
---|
2681 | if (iServiceIndex >= 0)
|
---|
2682 | bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
|
---|
2683 |
|
---|
2684 | /* if all is still well, move to the next record in the services array */
|
---|
2685 | if (bRetval) {
|
---|
2686 | /* We put this here to avoid an odd message order if messages are */
|
---|
2687 | /* issued by the post-processing of a previous section. */
|
---|
2688 | DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName));
|
---|
2689 |
|
---|
2690 | iServiceIndex = add_a_service(&sDefault, pszSectionName);
|
---|
2691 | if (iServiceIndex < 0) {
|
---|
2692 | DEBUG(0, ("Failed to add a new service\n"));
|
---|
2693 | return false;
|
---|
2694 | }
|
---|
2695 | /* Clean all parametric options for service */
|
---|
2696 | /* They will be added during parsing again */
|
---|
2697 | free_param_opts(&ServicePtrs[iServiceIndex]->param_opt);
|
---|
2698 | }
|
---|
2699 |
|
---|
2700 | return bRetval;
|
---|
2701 | }
|
---|
2702 |
|
---|
2703 | /***************************************************************************
|
---|
2704 | Display the contents of a parameter of a single services record.
|
---|
2705 | ***************************************************************************/
|
---|
2706 |
|
---|
2707 | bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
|
---|
2708 | {
|
---|
2709 | bool result = false;
|
---|
2710 | struct loadparm_context *lp_ctx;
|
---|
2711 |
|
---|
2712 | lp_ctx = setup_lp_context(talloc_tos());
|
---|
2713 | if (lp_ctx == NULL) {
|
---|
2714 | return false;
|
---|
2715 | }
|
---|
2716 |
|
---|
2717 | if (isGlobal) {
|
---|
2718 | result = lpcfg_dump_a_parameter(lp_ctx, NULL, parm_name, f);
|
---|
2719 | } else {
|
---|
2720 | result = lpcfg_dump_a_parameter(lp_ctx, ServicePtrs[snum], parm_name, f);
|
---|
2721 | }
|
---|
2722 | TALLOC_FREE(lp_ctx);
|
---|
2723 | return result;
|
---|
2724 | }
|
---|
2725 |
|
---|
2726 | #if 0
|
---|
2727 | /***************************************************************************
|
---|
2728 | Display the contents of a single copy structure.
|
---|
2729 | ***************************************************************************/
|
---|
2730 | static void dump_copy_map(bool *pcopymap)
|
---|
2731 | {
|
---|
2732 | int i;
|
---|
2733 | if (!pcopymap)
|
---|
2734 | return;
|
---|
2735 |
|
---|
2736 | printf("\n\tNon-Copied parameters:\n");
|
---|
2737 |
|
---|
2738 | for (i = 0; parm_table[i].label; i++)
|
---|
2739 | if (parm_table[i].p_class == P_LOCAL &&
|
---|
2740 | parm_table[i].ptr && !pcopymap[i] &&
|
---|
2741 | (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr)))
|
---|
2742 | {
|
---|
2743 | printf("\t\t%s\n", parm_table[i].label);
|
---|
2744 | }
|
---|
2745 | }
|
---|
2746 | #endif
|
---|
2747 |
|
---|
2748 | /***************************************************************************
|
---|
2749 | Return TRUE if the passed service number is within range.
|
---|
2750 | ***************************************************************************/
|
---|
2751 |
|
---|
2752 | bool lp_snum_ok(int iService)
|
---|
2753 | {
|
---|
2754 | return (LP_SNUM_OK(iService) && ServicePtrs[iService]->available);
|
---|
2755 | }
|
---|
2756 |
|
---|
2757 | /***************************************************************************
|
---|
2758 | Auto-load some home services.
|
---|
2759 | ***************************************************************************/
|
---|
2760 |
|
---|
2761 | static void lp_add_auto_services(char *str)
|
---|
2762 | {
|
---|
2763 | char *s;
|
---|
2764 | char *p;
|
---|
2765 | int homes;
|
---|
2766 | char *saveptr;
|
---|
2767 |
|
---|
2768 | if (!str)
|
---|
2769 | return;
|
---|
2770 |
|
---|
2771 | s = talloc_strdup(talloc_tos(), str);
|
---|
2772 | if (!s) {
|
---|
2773 | smb_panic("talloc_strdup failed");
|
---|
2774 | return;
|
---|
2775 | }
|
---|
2776 |
|
---|
2777 | homes = lp_servicenumber(HOMES_NAME);
|
---|
2778 |
|
---|
2779 | for (p = strtok_r(s, LIST_SEP, &saveptr); p;
|
---|
2780 | p = strtok_r(NULL, LIST_SEP, &saveptr)) {
|
---|
2781 | char *home;
|
---|
2782 |
|
---|
2783 | if (lp_servicenumber(p) >= 0)
|
---|
2784 | continue;
|
---|
2785 |
|
---|
2786 | home = get_user_home_dir(talloc_tos(), p);
|
---|
2787 |
|
---|
2788 | if (home && home[0] && homes >= 0)
|
---|
2789 | lp_add_home(p, homes, p, home);
|
---|
2790 |
|
---|
2791 | TALLOC_FREE(home);
|
---|
2792 | }
|
---|
2793 | TALLOC_FREE(s);
|
---|
2794 | }
|
---|
2795 |
|
---|
2796 | /***************************************************************************
|
---|
2797 | Auto-load one printer.
|
---|
2798 | ***************************************************************************/
|
---|
2799 |
|
---|
2800 | void lp_add_one_printer(const char *name, const char *comment,
|
---|
2801 | const char *location, void *pdata)
|
---|
2802 | {
|
---|
2803 | int printers = lp_servicenumber(PRINTERS_NAME);
|
---|
2804 | int i;
|
---|
2805 |
|
---|
2806 | if (lp_servicenumber(name) < 0) {
|
---|
2807 | lp_add_printer(name, printers);
|
---|
2808 | if ((i = lp_servicenumber(name)) >= 0) {
|
---|
2809 | lpcfg_string_set(ServicePtrs[i],
|
---|
2810 | &ServicePtrs[i]->comment, comment);
|
---|
2811 | ServicePtrs[i]->autoloaded = true;
|
---|
2812 | }
|
---|
2813 | }
|
---|
2814 | }
|
---|
2815 |
|
---|
2816 | /***************************************************************************
|
---|
2817 | Have we loaded a services file yet?
|
---|
2818 | ***************************************************************************/
|
---|
2819 |
|
---|
2820 | bool lp_loaded(void)
|
---|
2821 | {
|
---|
2822 | return (bLoaded);
|
---|
2823 | }
|
---|
2824 |
|
---|
2825 | /***************************************************************************
|
---|
2826 | Unload unused services.
|
---|
2827 | ***************************************************************************/
|
---|
2828 |
|
---|
2829 | void lp_killunused(struct smbd_server_connection *sconn,
|
---|
2830 | bool (*snumused) (struct smbd_server_connection *, int))
|
---|
2831 | {
|
---|
2832 | int i;
|
---|
2833 | for (i = 0; i < iNumServices; i++) {
|
---|
2834 | if (!VALID(i))
|
---|
2835 | continue;
|
---|
2836 |
|
---|
2837 | /* don't kill autoloaded or usershare services */
|
---|
2838 | if ( ServicePtrs[i]->autoloaded ||
|
---|
2839 | ServicePtrs[i]->usershare == USERSHARE_VALID) {
|
---|
2840 | continue;
|
---|
2841 | }
|
---|
2842 |
|
---|
2843 | if (!snumused || !snumused(sconn, i)) {
|
---|
2844 | free_service_byindex(i);
|
---|
2845 | }
|
---|
2846 | }
|
---|
2847 | }
|
---|
2848 |
|
---|
2849 | /**
|
---|
2850 | * Kill all except autoloaded and usershare services - convenience wrapper
|
---|
2851 | */
|
---|
2852 | void lp_kill_all_services(void)
|
---|
2853 | {
|
---|
2854 | lp_killunused(NULL, NULL);
|
---|
2855 | }
|
---|
2856 |
|
---|
2857 | /***************************************************************************
|
---|
2858 | Unload a service.
|
---|
2859 | ***************************************************************************/
|
---|
2860 |
|
---|
2861 | void lp_killservice(int iServiceIn)
|
---|
2862 | {
|
---|
2863 | if (VALID(iServiceIn)) {
|
---|
2864 | free_service_byindex(iServiceIn);
|
---|
2865 | }
|
---|
2866 | }
|
---|
2867 |
|
---|
2868 | /***************************************************************************
|
---|
2869 | Save the curent values of all global and sDefault parameters into the
|
---|
2870 | defaults union. This allows testparm to show only the
|
---|
2871 | changed (ie. non-default) parameters.
|
---|
2872 | ***************************************************************************/
|
---|
2873 |
|
---|
2874 | static void lp_save_defaults(void)
|
---|
2875 | {
|
---|
2876 | int i;
|
---|
2877 | struct parmlist_entry * parm;
|
---|
2878 | for (i = 0; parm_table[i].label; i++) {
|
---|
2879 | if (!(flags_list[i] & FLAG_CMDLINE)) {
|
---|
2880 | flags_list[i] |= FLAG_DEFAULT;
|
---|
2881 | }
|
---|
2882 |
|
---|
2883 | if (i > 0 && parm_table[i].offset == parm_table[i - 1].offset
|
---|
2884 | && parm_table[i].p_class == parm_table[i - 1].p_class)
|
---|
2885 | continue;
|
---|
2886 | switch (parm_table[i].type) {
|
---|
2887 | case P_LIST:
|
---|
2888 | case P_CMDLIST:
|
---|
2889 | parm_table[i].def.lvalue = str_list_copy(
|
---|
2890 | NULL, *(const char ***)lp_parm_ptr(NULL, &parm_table[i]));
|
---|
2891 | break;
|
---|
2892 | case P_STRING:
|
---|
2893 | case P_USTRING:
|
---|
2894 | lpcfg_string_set(
|
---|
2895 | Globals.ctx,
|
---|
2896 | &parm_table[i].def.svalue,
|
---|
2897 | *(char **)lp_parm_ptr(
|
---|
2898 | NULL, &parm_table[i]));
|
---|
2899 | if (parm_table[i].def.svalue == NULL) {
|
---|
2900 | smb_panic("lpcfg_string_set() failed");
|
---|
2901 | }
|
---|
2902 | break;
|
---|
2903 | case P_BOOL:
|
---|
2904 | case P_BOOLREV:
|
---|
2905 | parm_table[i].def.bvalue =
|
---|
2906 | *(bool *)lp_parm_ptr(NULL, &parm_table[i]);
|
---|
2907 | break;
|
---|
2908 | case P_CHAR:
|
---|
2909 | parm_table[i].def.cvalue =
|
---|
2910 | *(char *)lp_parm_ptr(NULL, &parm_table[i]);
|
---|
2911 | break;
|
---|
2912 | case P_INTEGER:
|
---|
2913 | case P_OCTAL:
|
---|
2914 | case P_ENUM:
|
---|
2915 | case P_BYTES:
|
---|
2916 | parm_table[i].def.ivalue =
|
---|
2917 | *(int *)lp_parm_ptr(NULL, &parm_table[i]);
|
---|
2918 | break;
|
---|
2919 | }
|
---|
2920 | }
|
---|
2921 |
|
---|
2922 | for (parm=Globals.param_opt; parm; parm=parm->next) {
|
---|
2923 | if (!(parm->priority & FLAG_CMDLINE)) {
|
---|
2924 | parm->priority |= FLAG_DEFAULT;
|
---|
2925 | }
|
---|
2926 | }
|
---|
2927 |
|
---|
2928 | for (parm=sDefault.param_opt; parm; parm=parm->next) {
|
---|
2929 | if (!(parm->priority & FLAG_CMDLINE)) {
|
---|
2930 | parm->priority |= FLAG_DEFAULT;
|
---|
2931 | }
|
---|
2932 | }
|
---|
2933 |
|
---|
2934 | defaults_saved = true;
|
---|
2935 | }
|
---|
2936 |
|
---|
2937 | /***********************************************************
|
---|
2938 | If we should send plaintext/LANMAN passwords in the clinet
|
---|
2939 | ************************************************************/
|
---|
2940 |
|
---|
2941 | static void set_allowed_client_auth(void)
|
---|
2942 | {
|
---|
2943 | if (Globals.client_ntlmv2_auth) {
|
---|
2944 | Globals.client_lanman_auth = false;
|
---|
2945 | }
|
---|
2946 | if (!Globals.client_lanman_auth) {
|
---|
2947 | Globals.client_plaintext_auth = false;
|
---|
2948 | }
|
---|
2949 | }
|
---|
2950 |
|
---|
2951 | /***************************************************************************
|
---|
2952 | JRA.
|
---|
2953 | The following code allows smbd to read a user defined share file.
|
---|
2954 | Yes, this is my intent. Yes, I'm comfortable with that...
|
---|
2955 |
|
---|
2956 | THE FOLLOWING IS SECURITY CRITICAL CODE.
|
---|
2957 |
|
---|
2958 | It washes your clothes, it cleans your house, it guards you while you sleep...
|
---|
2959 | Do not f%^k with it....
|
---|
2960 | ***************************************************************************/
|
---|
2961 |
|
---|
2962 | #define MAX_USERSHARE_FILE_SIZE (10*1024)
|
---|
2963 |
|
---|
2964 | /***************************************************************************
|
---|
2965 | Check allowed stat state of a usershare file.
|
---|
2966 | Ensure we print out who is dicking with us so the admin can
|
---|
2967 | get their sorry ass fired.
|
---|
2968 | ***************************************************************************/
|
---|
2969 |
|
---|
2970 | static bool check_usershare_stat(const char *fname,
|
---|
2971 | const SMB_STRUCT_STAT *psbuf)
|
---|
2972 | {
|
---|
2973 | if (!S_ISREG(psbuf->st_ex_mode)) {
|
---|
2974 | DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
|
---|
2975 | "not a regular file\n",
|
---|
2976 | fname, (unsigned int)psbuf->st_ex_uid ));
|
---|
2977 | return false;
|
---|
2978 | }
|
---|
2979 |
|
---|
2980 | /* Ensure this doesn't have the other write bit set. */
|
---|
2981 | if (psbuf->st_ex_mode & S_IWOTH) {
|
---|
2982 | DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
|
---|
2983 | "public write. Refusing to allow as a usershare file.\n",
|
---|
2984 | fname, (unsigned int)psbuf->st_ex_uid ));
|
---|
2985 | return false;
|
---|
2986 | }
|
---|
2987 |
|
---|
2988 | /* Should be 10k or less. */
|
---|
2989 | if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) {
|
---|
2990 | DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
|
---|
2991 | "too large (%u) to be a user share file.\n",
|
---|
2992 | fname, (unsigned int)psbuf->st_ex_uid,
|
---|
2993 | (unsigned int)psbuf->st_ex_size ));
|
---|
2994 | return false;
|
---|
2995 | }
|
---|
2996 |
|
---|
2997 | return true;
|
---|
2998 | }
|
---|
2999 |
|
---|
3000 | /***************************************************************************
|
---|
3001 | Parse the contents of a usershare file.
|
---|
3002 | ***************************************************************************/
|
---|
3003 |
|
---|
3004 | enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
|
---|
3005 | SMB_STRUCT_STAT *psbuf,
|
---|
3006 | const char *servicename,
|
---|
3007 | int snum,
|
---|
3008 | char **lines,
|
---|
3009 | int numlines,
|
---|
3010 | char **pp_sharepath,
|
---|
3011 | char **pp_comment,
|
---|
3012 | char **pp_cp_servicename,
|
---|
3013 | struct security_descriptor **ppsd,
|
---|
3014 | bool *pallow_guest)
|
---|
3015 | {
|
---|
3016 | const char **prefixallowlist = lp_usershare_prefix_allow_list();
|
---|
3017 | const char **prefixdenylist = lp_usershare_prefix_deny_list();
|
---|
3018 | int us_vers;
|
---|
3019 | DIR *dp;
|
---|
3020 | SMB_STRUCT_STAT sbuf;
|
---|
3021 | char *sharepath = NULL;
|
---|
3022 | char *comment = NULL;
|
---|
3023 |
|
---|
3024 | *pp_sharepath = NULL;
|
---|
3025 | *pp_comment = NULL;
|
---|
3026 |
|
---|
3027 | *pallow_guest = false;
|
---|
3028 |
|
---|
3029 | if (numlines < 4) {
|
---|
3030 | return USERSHARE_MALFORMED_FILE;
|
---|
3031 | }
|
---|
3032 |
|
---|
3033 | if (strcmp(lines[0], "#VERSION 1") == 0) {
|
---|
3034 | us_vers = 1;
|
---|
3035 | } else if (strcmp(lines[0], "#VERSION 2") == 0) {
|
---|
3036 | us_vers = 2;
|
---|
3037 | if (numlines < 5) {
|
---|
3038 | return USERSHARE_MALFORMED_FILE;
|
---|
3039 | }
|
---|
3040 | } else {
|
---|
3041 | return USERSHARE_BAD_VERSION;
|
---|
3042 | }
|
---|
3043 |
|
---|
3044 | if (strncmp(lines[1], "path=", 5) != 0) {
|
---|
3045 | return USERSHARE_MALFORMED_PATH;
|
---|
3046 | }
|
---|
3047 |
|
---|
3048 | sharepath = talloc_strdup(ctx, &lines[1][5]);
|
---|
3049 | if (!sharepath) {
|
---|
3050 | return USERSHARE_POSIX_ERR;
|
---|
3051 | }
|
---|
3052 | trim_string(sharepath, " ", " ");
|
---|
3053 |
|
---|
3054 | if (strncmp(lines[2], "comment=", 8) != 0) {
|
---|
3055 | return USERSHARE_MALFORMED_COMMENT_DEF;
|
---|
3056 | }
|
---|
3057 |
|
---|
3058 | comment = talloc_strdup(ctx, &lines[2][8]);
|
---|
3059 | if (!comment) {
|
---|
3060 | return USERSHARE_POSIX_ERR;
|
---|
3061 | }
|
---|
3062 | trim_string(comment, " ", " ");
|
---|
3063 | trim_char(comment, '"', '"');
|
---|
3064 |
|
---|
3065 | if (strncmp(lines[3], "usershare_acl=", 14) != 0) {
|
---|
3066 | return USERSHARE_MALFORMED_ACL_DEF;
|
---|
3067 | }
|
---|
3068 |
|
---|
3069 | if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
|
---|
3070 | return USERSHARE_ACL_ERR;
|
---|
3071 | }
|
---|
3072 |
|
---|
3073 | if (us_vers == 2) {
|
---|
3074 | if (strncmp(lines[4], "guest_ok=", 9) != 0) {
|
---|
3075 | return USERSHARE_MALFORMED_ACL_DEF;
|
---|
3076 | }
|
---|
3077 | if (lines[4][9] == 'y') {
|
---|
3078 | *pallow_guest = true;
|
---|
3079 | }
|
---|
3080 |
|
---|
3081 | /* Backwards compatible extension to file version #2. */
|
---|
3082 | if (numlines > 5) {
|
---|
3083 | if (strncmp(lines[5], "sharename=", 10) != 0) {
|
---|
3084 | return USERSHARE_MALFORMED_SHARENAME_DEF;
|
---|
3085 | }
|
---|
3086 | if (!strequal(&lines[5][10], servicename)) {
|
---|
3087 | return USERSHARE_BAD_SHARENAME;
|
---|
3088 | }
|
---|
3089 | *pp_cp_servicename = talloc_strdup(ctx, &lines[5][10]);
|
---|
3090 | if (!*pp_cp_servicename) {
|
---|
3091 | return USERSHARE_POSIX_ERR;
|
---|
3092 | }
|
---|
3093 | }
|
---|
3094 | }
|
---|
3095 |
|
---|
3096 | if (*pp_cp_servicename == NULL) {
|
---|
3097 | *pp_cp_servicename = talloc_strdup(ctx, servicename);
|
---|
3098 | if (!*pp_cp_servicename) {
|
---|
3099 | return USERSHARE_POSIX_ERR;
|
---|
3100 | }
|
---|
3101 | }
|
---|
3102 |
|
---|
3103 | if (snum != -1 && (strcmp(sharepath, ServicePtrs[snum]->path) == 0)) {
|
---|
3104 | /* Path didn't change, no checks needed. */
|
---|
3105 | *pp_sharepath = sharepath;
|
---|
3106 | *pp_comment = comment;
|
---|
3107 | return USERSHARE_OK;
|
---|
3108 | }
|
---|
3109 |
|
---|
3110 | /* The path *must* be absolute. */
|
---|
3111 | if (sharepath[0] != '/') {
|
---|
3112 | DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
|
---|
3113 | servicename, sharepath));
|
---|
3114 | return USERSHARE_PATH_NOT_ABSOLUTE;
|
---|
3115 | }
|
---|
3116 |
|
---|
3117 | /* If there is a usershare prefix deny list ensure one of these paths
|
---|
3118 | doesn't match the start of the user given path. */
|
---|
3119 | if (prefixdenylist) {
|
---|
3120 | int i;
|
---|
3121 | for ( i=0; prefixdenylist[i]; i++ ) {
|
---|
3122 | DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
|
---|
3123 | servicename, i, prefixdenylist[i], sharepath ));
|
---|
3124 | if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
|
---|
3125 | DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
|
---|
3126 | "usershare prefix deny list entries.\n",
|
---|
3127 | servicename, sharepath));
|
---|
3128 | return USERSHARE_PATH_IS_DENIED;
|
---|
3129 | }
|
---|
3130 | }
|
---|
3131 | }
|
---|
3132 |
|
---|
3133 | /* If there is a usershare prefix allow list ensure one of these paths
|
---|
3134 | does match the start of the user given path. */
|
---|
3135 |
|
---|
3136 | if (prefixallowlist) {
|
---|
3137 | int i;
|
---|
3138 | for ( i=0; prefixallowlist[i]; i++ ) {
|
---|
3139 | DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
|
---|
3140 | servicename, i, prefixallowlist[i], sharepath ));
|
---|
3141 | if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
|
---|
3142 | break;
|
---|
3143 | }
|
---|
3144 | }
|
---|
3145 | if (prefixallowlist[i] == NULL) {
|
---|
3146 | DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
|
---|
3147 | "usershare prefix allow list entries.\n",
|
---|
3148 | servicename, sharepath));
|
---|
3149 | return USERSHARE_PATH_NOT_ALLOWED;
|
---|
3150 | }
|
---|
3151 | }
|
---|
3152 |
|
---|
3153 | /* Ensure this is pointing to a directory. */
|
---|
3154 | dp = opendir(sharepath);
|
---|
3155 |
|
---|
3156 | if (!dp) {
|
---|
3157 | DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
|
---|
3158 | servicename, sharepath));
|
---|
3159 | return USERSHARE_PATH_NOT_DIRECTORY;
|
---|
3160 | }
|
---|
3161 |
|
---|
3162 | /* Ensure the owner of the usershare file has permission to share
|
---|
3163 | this directory. */
|
---|
3164 |
|
---|
3165 | if (sys_stat(sharepath, &sbuf, false) == -1) {
|
---|
3166 | DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
|
---|
3167 | servicename, sharepath, strerror(errno) ));
|
---|
3168 | closedir(dp);
|
---|
3169 | return USERSHARE_POSIX_ERR;
|
---|
3170 | }
|
---|
3171 |
|
---|
3172 | closedir(dp);
|
---|
3173 |
|
---|
3174 | if (!S_ISDIR(sbuf.st_ex_mode)) {
|
---|
3175 | DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
|
---|
3176 | servicename, sharepath ));
|
---|
3177 | return USERSHARE_PATH_NOT_DIRECTORY;
|
---|
3178 | }
|
---|
3179 |
|
---|
3180 | /* Check if sharing is restricted to owner-only. */
|
---|
3181 | /* psbuf is the stat of the usershare definition file,
|
---|
3182 | sbuf is the stat of the target directory to be shared. */
|
---|
3183 |
|
---|
3184 | if (lp_usershare_owner_only()) {
|
---|
3185 | /* root can share anything. */
|
---|
3186 | if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) {
|
---|
3187 | return USERSHARE_PATH_NOT_ALLOWED;
|
---|
3188 | }
|
---|
3189 | }
|
---|
3190 |
|
---|
3191 | *pp_sharepath = sharepath;
|
---|
3192 | *pp_comment = comment;
|
---|
3193 | return USERSHARE_OK;
|
---|
3194 | }
|
---|
3195 |
|
---|
3196 | /***************************************************************************
|
---|
3197 | Deal with a usershare file.
|
---|
3198 | Returns:
|
---|
3199 | >= 0 - snum
|
---|
3200 | -1 - Bad name, invalid contents.
|
---|
3201 | - service name already existed and not a usershare, problem
|
---|
3202 | with permissions to share directory etc.
|
---|
3203 | ***************************************************************************/
|
---|
3204 |
|
---|
3205 | static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
|
---|
3206 | {
|
---|
3207 | SMB_STRUCT_STAT sbuf;
|
---|
3208 | SMB_STRUCT_STAT lsbuf;
|
---|
3209 | char *fname = NULL;
|
---|
3210 | char *sharepath = NULL;
|
---|
3211 | char *comment = NULL;
|
---|
3212 | char *cp_service_name = NULL;
|
---|
3213 | char **lines = NULL;
|
---|
3214 | int numlines = 0;
|
---|
3215 | int fd = -1;
|
---|
3216 | int iService = -1;
|
---|
3217 | TALLOC_CTX *ctx = talloc_stackframe();
|
---|
3218 | struct security_descriptor *psd = NULL;
|
---|
3219 | bool guest_ok = false;
|
---|
3220 | char *canon_name = NULL;
|
---|
3221 | bool added_service = false;
|
---|
3222 | int ret = -1;
|
---|
3223 |
|
---|
3224 | /* Ensure share name doesn't contain invalid characters. */
|
---|
3225 | if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
|
---|
3226 | DEBUG(0,("process_usershare_file: share name %s contains "
|
---|
3227 | "invalid characters (any of %s)\n",
|
---|
3228 | file_name, INVALID_SHARENAME_CHARS ));
|
---|
3229 | goto out;
|
---|
3230 | }
|
---|
3231 |
|
---|
3232 | canon_name = canonicalize_servicename(ctx, file_name);
|
---|
3233 | if (!canon_name) {
|
---|
3234 | goto out;
|
---|
3235 | }
|
---|
3236 |
|
---|
3237 | fname = talloc_asprintf(ctx, "%s/%s", dir_name, file_name);
|
---|
3238 | if (!fname) {
|
---|
3239 | goto out;
|
---|
3240 | }
|
---|
3241 |
|
---|
3242 | /* Minimize the race condition by doing an lstat before we
|
---|
3243 | open and fstat. Ensure this isn't a symlink link. */
|
---|
3244 |
|
---|
3245 | if (sys_lstat(fname, &lsbuf, false) != 0) {
|
---|
3246 | DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
|
---|
3247 | fname, strerror(errno) ));
|
---|
3248 | goto out;
|
---|
3249 | }
|
---|
3250 |
|
---|
3251 | /* This must be a regular file, not a symlink, directory or
|
---|
3252 | other strange filetype. */
|
---|
3253 | if (!check_usershare_stat(fname, &lsbuf)) {
|
---|
3254 | goto out;
|
---|
3255 | }
|
---|
3256 |
|
---|
3257 | {
|
---|
3258 | TDB_DATA data;
|
---|
3259 | NTSTATUS status;
|
---|
3260 |
|
---|
3261 | status = dbwrap_fetch_bystring(ServiceHash, canon_name,
|
---|
3262 | canon_name, &data);
|
---|
3263 |
|
---|
3264 | iService = -1;
|
---|
3265 |
|
---|
3266 | if (NT_STATUS_IS_OK(status) &&
|
---|
3267 | (data.dptr != NULL) &&
|
---|
3268 | (data.dsize == sizeof(iService))) {
|
---|
3269 | memcpy(&iService, data.dptr, sizeof(iService));
|
---|
3270 | }
|
---|
3271 | }
|
---|
3272 |
|
---|
3273 | if (iService != -1 &&
|
---|
3274 | timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
|
---|
3275 | &lsbuf.st_ex_mtime) == 0) {
|
---|
3276 | /* Nothing changed - Mark valid and return. */
|
---|
3277 | DEBUG(10,("process_usershare_file: service %s not changed.\n",
|
---|
3278 | canon_name ));
|
---|
3279 | ServicePtrs[iService]->usershare = USERSHARE_VALID;
|
---|
3280 | ret = iService;
|
---|
3281 | goto out;
|
---|
3282 | }
|
---|
3283 |
|
---|
3284 | /* Try and open the file read only - no symlinks allowed. */
|
---|
3285 | #ifdef O_NOFOLLOW
|
---|
3286 | fd = open(fname, O_RDONLY|O_NOFOLLOW, 0);
|
---|
3287 | #else
|
---|
3288 | fd = open(fname, O_RDONLY, 0);
|
---|
3289 | #endif
|
---|
3290 |
|
---|
3291 | if (fd == -1) {
|
---|
3292 | DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
|
---|
3293 | fname, strerror(errno) ));
|
---|
3294 | goto out;
|
---|
3295 | }
|
---|
3296 |
|
---|
3297 | /* Now fstat to be *SURE* it's a regular file. */
|
---|
3298 | if (sys_fstat(fd, &sbuf, false) != 0) {
|
---|
3299 | close(fd);
|
---|
3300 | DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
|
---|
3301 | fname, strerror(errno) ));
|
---|
3302 | goto out;
|
---|
3303 | }
|
---|
3304 |
|
---|
3305 | /* Is it the same dev/inode as was lstated ? */
|
---|
3306 | if (!check_same_stat(&lsbuf, &sbuf)) {
|
---|
3307 | close(fd);
|
---|
3308 | DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
|
---|
3309 | "Symlink spoofing going on ?\n", fname ));
|
---|
3310 | goto out;
|
---|
3311 | }
|
---|
3312 |
|
---|
3313 | /* This must be a regular file, not a symlink, directory or
|
---|
3314 | other strange filetype. */
|
---|
3315 | if (!check_usershare_stat(fname, &sbuf)) {
|
---|
3316 | close(fd);
|
---|
3317 | goto out;
|
---|
3318 | }
|
---|
3319 |
|
---|
3320 | lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE, NULL);
|
---|
3321 |
|
---|
3322 | close(fd);
|
---|
3323 | if (lines == NULL) {
|
---|
3324 | DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
|
---|
3325 | fname, (unsigned int)sbuf.st_ex_uid ));
|
---|
3326 | goto out;
|
---|
3327 | }
|
---|
3328 |
|
---|
3329 | if (parse_usershare_file(ctx, &sbuf, file_name,
|
---|
3330 | iService, lines, numlines, &sharepath,
|
---|
3331 | &comment, &cp_service_name,
|
---|
3332 | &psd, &guest_ok) != USERSHARE_OK) {
|
---|
3333 | goto out;
|
---|
3334 | }
|
---|
3335 |
|
---|
3336 | /* Everything ok - add the service possibly using a template. */
|
---|
3337 | if (iService < 0) {
|
---|
3338 | const struct loadparm_service *sp = &sDefault;
|
---|
3339 | if (snum_template != -1) {
|
---|
3340 | sp = ServicePtrs[snum_template];
|
---|
3341 | }
|
---|
3342 |
|
---|
3343 | if ((iService = add_a_service(sp, cp_service_name)) < 0) {
|
---|
3344 | DEBUG(0, ("process_usershare_file: Failed to add "
|
---|
3345 | "new service %s\n", cp_service_name));
|
---|
3346 | goto out;
|
---|
3347 | }
|
---|
3348 |
|
---|
3349 | added_service = true;
|
---|
3350 |
|
---|
3351 | /* Read only is controlled by usershare ACL below. */
|
---|
3352 | ServicePtrs[iService]->read_only = false;
|
---|
3353 | }
|
---|
3354 |
|
---|
3355 | /* Write the ACL of the new/modified share. */
|
---|
3356 | if (!set_share_security(canon_name, psd)) {
|
---|
3357 | DEBUG(0, ("process_usershare_file: Failed to set share "
|
---|
3358 | "security for user share %s\n",
|
---|
3359 | canon_name ));
|
---|
3360 | goto out;
|
---|
3361 | }
|
---|
3362 |
|
---|
3363 | /* If from a template it may be marked invalid. */
|
---|
3364 | ServicePtrs[iService]->valid = true;
|
---|
3365 |
|
---|
3366 | /* Set the service as a valid usershare. */
|
---|
3367 | ServicePtrs[iService]->usershare = USERSHARE_VALID;
|
---|
3368 |
|
---|
3369 | /* Set guest access. */
|
---|
3370 | if (lp_usershare_allow_guests()) {
|
---|
3371 | ServicePtrs[iService]->guest_ok = guest_ok;
|
---|
3372 | }
|
---|
3373 |
|
---|
3374 | /* And note when it was loaded. */
|
---|
3375 | ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime;
|
---|
3376 | lpcfg_string_set(ServicePtrs[iService], &ServicePtrs[iService]->path,
|
---|
3377 | sharepath);
|
---|
3378 | lpcfg_string_set(ServicePtrs[iService],
|
---|
3379 | &ServicePtrs[iService]->comment, comment);
|
---|
3380 |
|
---|
3381 | ret = iService;
|
---|
3382 |
|
---|
3383 | out:
|
---|
3384 |
|
---|
3385 | if (ret == -1 && iService != -1 && added_service) {
|
---|
3386 | lp_remove_service(iService);
|
---|
3387 | }
|
---|
3388 |
|
---|
3389 | TALLOC_FREE(lines);
|
---|
3390 | TALLOC_FREE(ctx);
|
---|
3391 | return ret;
|
---|
3392 | }
|
---|
3393 |
|
---|
3394 | /***************************************************************************
|
---|
3395 | Checks if a usershare entry has been modified since last load.
|
---|
3396 | ***************************************************************************/
|
---|
3397 |
|
---|
3398 | static bool usershare_exists(int iService, struct timespec *last_mod)
|
---|
3399 | {
|
---|
3400 | SMB_STRUCT_STAT lsbuf;
|
---|
3401 | const char *usersharepath = Globals.usershare_path;
|
---|
3402 | char *fname;
|
---|
3403 |
|
---|
3404 | fname = talloc_asprintf(talloc_tos(),
|
---|
3405 | "%s/%s",
|
---|
3406 | usersharepath,
|
---|
3407 | ServicePtrs[iService]->szService);
|
---|
3408 | if (fname == NULL) {
|
---|
3409 | return false;
|
---|
3410 | }
|
---|
3411 |
|
---|
3412 | if (sys_lstat(fname, &lsbuf, false) != 0) {
|
---|
3413 | TALLOC_FREE(fname);
|
---|
3414 | return false;
|
---|
3415 | }
|
---|
3416 |
|
---|
3417 | if (!S_ISREG(lsbuf.st_ex_mode)) {
|
---|
3418 | TALLOC_FREE(fname);
|
---|
3419 | return false;
|
---|
3420 | }
|
---|
3421 |
|
---|
3422 | TALLOC_FREE(fname);
|
---|
3423 | *last_mod = lsbuf.st_ex_mtime;
|
---|
3424 | return true;
|
---|
3425 | }
|
---|
3426 |
|
---|
3427 | /***************************************************************************
|
---|
3428 | Load a usershare service by name. Returns a valid servicenumber or -1.
|
---|
3429 | ***************************************************************************/
|
---|
3430 |
|
---|
3431 | int load_usershare_service(const char *servicename)
|
---|
3432 | {
|
---|
3433 | SMB_STRUCT_STAT sbuf;
|
---|
3434 | const char *usersharepath = Globals.usershare_path;
|
---|
3435 | int max_user_shares = Globals.usershare_max_shares;
|
---|
3436 | int snum_template = -1;
|
---|
3437 |
|
---|
3438 | if (*usersharepath == 0 || max_user_shares == 0) {
|
---|
3439 | return -1;
|
---|
3440 | }
|
---|
3441 |
|
---|
3442 | if (sys_stat(usersharepath, &sbuf, false) != 0) {
|
---|
3443 | DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
|
---|
3444 | usersharepath, strerror(errno) ));
|
---|
3445 | return -1;
|
---|
3446 | }
|
---|
3447 |
|
---|
3448 | if (!S_ISDIR(sbuf.st_ex_mode)) {
|
---|
3449 | DEBUG(0,("load_usershare_service: %s is not a directory.\n",
|
---|
3450 | usersharepath ));
|
---|
3451 | return -1;
|
---|
3452 | }
|
---|
3453 |
|
---|
3454 | /*
|
---|
3455 | * This directory must be owned by root, and have the 't' bit set.
|
---|
3456 | * It also must not be writable by "other".
|
---|
3457 | */
|
---|
3458 |
|
---|
3459 | #ifdef S_ISVTX
|
---|
3460 | if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
|
---|
3461 | #else
|
---|
3462 | if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
|
---|
3463 | #endif
|
---|
3464 | DEBUG(0,("load_usershare_service: directory %s is not owned by root "
|
---|
3465 | "or does not have the sticky bit 't' set or is writable by anyone.\n",
|
---|
3466 | usersharepath ));
|
---|
3467 | return -1;
|
---|
3468 | }
|
---|
3469 |
|
---|
3470 | /* Ensure the template share exists if it's set. */
|
---|
3471 | if (Globals.usershare_template_share[0]) {
|
---|
3472 | /* We can't use lp_servicenumber here as we are recommending that
|
---|
3473 | template shares have -valid=false set. */
|
---|
3474 | for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
|
---|
3475 | if (ServicePtrs[snum_template]->szService &&
|
---|
3476 | strequal(ServicePtrs[snum_template]->szService,
|
---|
3477 | Globals.usershare_template_share)) {
|
---|
3478 | break;
|
---|
3479 | }
|
---|
3480 | }
|
---|
3481 |
|
---|
3482 | if (snum_template == -1) {
|
---|
3483 | DEBUG(0,("load_usershare_service: usershare template share %s "
|
---|
3484 | "does not exist.\n",
|
---|
3485 | Globals.usershare_template_share ));
|
---|
3486 | return -1;
|
---|
3487 | }
|
---|
3488 | }
|
---|
3489 |
|
---|
3490 | return process_usershare_file(usersharepath, servicename, snum_template);
|
---|
3491 | }
|
---|
3492 |
|
---|
3493 | /***************************************************************************
|
---|
3494 | Load all user defined shares from the user share directory.
|
---|
3495 | We only do this if we're enumerating the share list.
|
---|
3496 | This is the function that can delete usershares that have
|
---|
3497 | been removed.
|
---|
3498 | ***************************************************************************/
|
---|
3499 |
|
---|
3500 | int load_usershare_shares(struct smbd_server_connection *sconn,
|
---|
3501 | bool (*snumused) (struct smbd_server_connection *, int))
|
---|
3502 | {
|
---|
3503 | DIR *dp;
|
---|
3504 | SMB_STRUCT_STAT sbuf;
|
---|
3505 | struct dirent *de;
|
---|
3506 | int num_usershares = 0;
|
---|
3507 | int max_user_shares = Globals.usershare_max_shares;
|
---|
3508 | unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
|
---|
3509 | unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
|
---|
3510 | unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
|
---|
3511 | int iService;
|
---|
3512 | int snum_template = -1;
|
---|
3513 | const char *usersharepath = Globals.usershare_path;
|
---|
3514 | int ret = lp_numservices();
|
---|
3515 | TALLOC_CTX *tmp_ctx;
|
---|
3516 |
|
---|
3517 | if (max_user_shares == 0 || *usersharepath == '\0') {
|
---|
3518 | return lp_numservices();
|
---|
3519 | }
|
---|
3520 |
|
---|
3521 | if (sys_stat(usersharepath, &sbuf, false) != 0) {
|
---|
3522 | DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
|
---|
3523 | usersharepath, strerror(errno) ));
|
---|
3524 | return ret;
|
---|
3525 | }
|
---|
3526 |
|
---|
3527 | /*
|
---|
3528 | * This directory must be owned by root, and have the 't' bit set.
|
---|
3529 | * It also must not be writable by "other".
|
---|
3530 | */
|
---|
3531 |
|
---|
3532 | #ifdef S_ISVTX
|
---|
3533 | if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) {
|
---|
3534 | #else
|
---|
3535 | if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) {
|
---|
3536 | #endif
|
---|
3537 | DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
|
---|
3538 | "or does not have the sticky bit 't' set or is writable by anyone.\n",
|
---|
3539 | usersharepath ));
|
---|
3540 | return ret;
|
---|
3541 | }
|
---|
3542 |
|
---|
3543 | /* Ensure the template share exists if it's set. */
|
---|
3544 | if (Globals.usershare_template_share[0]) {
|
---|
3545 | /* We can't use lp_servicenumber here as we are recommending that
|
---|
3546 | template shares have -valid=false set. */
|
---|
3547 | for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
|
---|
3548 | if (ServicePtrs[snum_template]->szService &&
|
---|
3549 | strequal(ServicePtrs[snum_template]->szService,
|
---|
3550 | Globals.usershare_template_share)) {
|
---|
3551 | break;
|
---|
3552 | }
|
---|
3553 | }
|
---|
3554 |
|
---|
3555 | if (snum_template == -1) {
|
---|
3556 | DEBUG(0,("load_usershare_shares: usershare template share %s "
|
---|
3557 | "does not exist.\n",
|
---|
3558 | Globals.usershare_template_share ));
|
---|
3559 | return ret;
|
---|
3560 | }
|
---|
3561 | }
|
---|
3562 |
|
---|
3563 | /* Mark all existing usershares as pending delete. */
|
---|
3564 | for (iService = iNumServices - 1; iService >= 0; iService--) {
|
---|
3565 | if (VALID(iService) && ServicePtrs[iService]->usershare) {
|
---|
3566 | ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
|
---|
3567 | }
|
---|
3568 | }
|
---|
3569 |
|
---|
3570 | dp = opendir(usersharepath);
|
---|
3571 | if (!dp) {
|
---|
3572 | DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
|
---|
3573 | usersharepath, strerror(errno) ));
|
---|
3574 | return ret;
|
---|
3575 | }
|
---|
3576 |
|
---|
3577 | for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
|
---|
3578 | (de = readdir(dp));
|
---|
3579 | num_dir_entries++ ) {
|
---|
3580 | int r;
|
---|
3581 | const char *n = de->d_name;
|
---|
3582 |
|
---|
3583 | /* Ignore . and .. */
|
---|
3584 | if (*n == '.') {
|
---|
3585 | if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
|
---|
3586 | continue;
|
---|
3587 | }
|
---|
3588 | }
|
---|
3589 |
|
---|
3590 | if (n[0] == ':') {
|
---|
3591 | /* Temporary file used when creating a share. */
|
---|
3592 | num_tmp_dir_entries++;
|
---|
3593 | }
|
---|
3594 |
|
---|
3595 | /* Allow 20% tmp entries. */
|
---|
3596 | if (num_tmp_dir_entries > allowed_tmp_entries) {
|
---|
3597 | DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
|
---|
3598 | "in directory %s\n",
|
---|
3599 | num_tmp_dir_entries, usersharepath));
|
---|
3600 | break;
|
---|
3601 | }
|
---|
3602 |
|
---|
3603 | r = process_usershare_file(usersharepath, n, snum_template);
|
---|
3604 | if (r == 0) {
|
---|
3605 | /* Update the services count. */
|
---|
3606 | num_usershares++;
|
---|
3607 | if (num_usershares >= max_user_shares) {
|
---|
3608 | DEBUG(0,("load_usershare_shares: max user shares reached "
|
---|
3609 | "on file %s in directory %s\n",
|
---|
3610 | n, usersharepath ));
|
---|
3611 | break;
|
---|
3612 | }
|
---|
3613 | } else if (r == -1) {
|
---|
3614 | num_bad_dir_entries++;
|
---|
3615 | }
|
---|
3616 |
|
---|
3617 | /* Allow 20% bad entries. */
|
---|
3618 | if (num_bad_dir_entries > allowed_bad_entries) {
|
---|
3619 | DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
|
---|
3620 | "in directory %s\n",
|
---|
3621 | num_bad_dir_entries, usersharepath));
|
---|
3622 | break;
|
---|
3623 | }
|
---|
3624 |
|
---|
3625 | /* Allow 20% bad entries. */
|
---|
3626 | if (num_dir_entries > max_user_shares + allowed_bad_entries) {
|
---|
3627 | DEBUG(0,("load_usershare_shares: too many total entries (%u) "
|
---|
3628 | "in directory %s\n",
|
---|
3629 | num_dir_entries, usersharepath));
|
---|
3630 | break;
|
---|
3631 | }
|
---|
3632 | }
|
---|
3633 |
|
---|
3634 | closedir(dp);
|
---|
3635 |
|
---|
3636 | /* Sweep through and delete any non-refreshed usershares that are
|
---|
3637 | not currently in use. */
|
---|
3638 | tmp_ctx = talloc_stackframe();
|
---|
3639 | for (iService = iNumServices - 1; iService >= 0; iService--) {
|
---|
3640 | if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
|
---|
3641 | char *servname;
|
---|
3642 |
|
---|
3643 | if (snumused && snumused(sconn, iService)) {
|
---|
3644 | continue;
|
---|
3645 | }
|
---|
3646 |
|
---|
3647 | servname = lp_servicename(tmp_ctx, iService);
|
---|
3648 |
|
---|
3649 | /* Remove from the share ACL db. */
|
---|
3650 | DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
|
---|
3651 | servname ));
|
---|
3652 | delete_share_security(servname);
|
---|
3653 | free_service_byindex(iService);
|
---|
3654 | }
|
---|
3655 | }
|
---|
3656 | talloc_free(tmp_ctx);
|
---|
3657 |
|
---|
3658 | return lp_numservices();
|
---|
3659 | }
|
---|
3660 |
|
---|
3661 | /********************************************************
|
---|
3662 | Destroy global resources allocated in this file
|
---|
3663 | ********************************************************/
|
---|
3664 |
|
---|
3665 | void gfree_loadparm(void)
|
---|
3666 | {
|
---|
3667 | int i;
|
---|
3668 |
|
---|
3669 | free_file_list();
|
---|
3670 |
|
---|
3671 | /* Free resources allocated to services */
|
---|
3672 |
|
---|
3673 | for ( i = 0; i < iNumServices; i++ ) {
|
---|
3674 | if ( VALID(i) ) {
|
---|
3675 | free_service_byindex(i);
|
---|
3676 | }
|
---|
3677 | }
|
---|
3678 |
|
---|
3679 | TALLOC_FREE( ServicePtrs );
|
---|
3680 | iNumServices = 0;
|
---|
3681 |
|
---|
3682 | /* Now release all resources allocated to global
|
---|
3683 | parameters and the default service */
|
---|
3684 |
|
---|
3685 | free_global_parameters();
|
---|
3686 | }
|
---|
3687 |
|
---|
3688 |
|
---|
3689 | /***************************************************************************
|
---|
3690 | Allow client apps to specify that they are a client
|
---|
3691 | ***************************************************************************/
|
---|
3692 | static void lp_set_in_client(bool b)
|
---|
3693 | {
|
---|
3694 | in_client = b;
|
---|
3695 | }
|
---|
3696 |
|
---|
3697 |
|
---|
3698 | /***************************************************************************
|
---|
3699 | Determine if we're running in a client app
|
---|
3700 | ***************************************************************************/
|
---|
3701 | static bool lp_is_in_client(void)
|
---|
3702 | {
|
---|
3703 | return in_client;
|
---|
3704 | }
|
---|
3705 |
|
---|
3706 | static void lp_enforce_ad_dc_settings(void)
|
---|
3707 | {
|
---|
3708 | lp_do_parameter(GLOBAL_SECTION_SNUM, "passdb backend", "samba_dsdb");
|
---|
3709 | lp_do_parameter(GLOBAL_SECTION_SNUM,
|
---|
3710 | "winbindd:use external pipes", "true");
|
---|
3711 | lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:default", "external");
|
---|
3712 | lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:svcctl", "embedded");
|
---|
3713 | lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:srvsvc", "embedded");
|
---|
3714 | lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:eventlog", "embedded");
|
---|
3715 | lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:ntsvcs", "embedded");
|
---|
3716 | lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:winreg", "embedded");
|
---|
3717 | lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:spoolss", "embedded");
|
---|
3718 | lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_daemon:spoolssd", "embedded");
|
---|
3719 | lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:tcpip", "no");
|
---|
3720 | }
|
---|
3721 |
|
---|
3722 | /***************************************************************************
|
---|
3723 | Load the services array from the services file. Return true on success,
|
---|
3724 | false on failure.
|
---|
3725 | ***************************************************************************/
|
---|
3726 |
|
---|
3727 | static bool lp_load_ex(const char *pszFname,
|
---|
3728 | bool global_only,
|
---|
3729 | bool save_defaults,
|
---|
3730 | bool add_ipc,
|
---|
3731 | bool reinit_globals,
|
---|
3732 | bool allow_include_registry,
|
---|
3733 | bool load_all_shares)
|
---|
3734 | {
|
---|
3735 | char *n2 = NULL;
|
---|
3736 | bool bRetval;
|
---|
3737 | TALLOC_CTX *frame = talloc_stackframe();
|
---|
3738 | struct loadparm_context *lp_ctx;
|
---|
3739 |
|
---|
3740 | bRetval = false;
|
---|
3741 |
|
---|
3742 | DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
|
---|
3743 |
|
---|
3744 | bInGlobalSection = true;
|
---|
3745 | bGlobalOnly = global_only;
|
---|
3746 | bAllowIncludeRegistry = allow_include_registry;
|
---|
3747 |
|
---|
3748 | lp_ctx = setup_lp_context(talloc_tos());
|
---|
3749 |
|
---|
3750 | init_globals(lp_ctx, reinit_globals);
|
---|
3751 |
|
---|
3752 | free_file_list();
|
---|
3753 |
|
---|
3754 | if (save_defaults) {
|
---|
3755 | init_locals();
|
---|
3756 | lp_save_defaults();
|
---|
3757 | }
|
---|
3758 |
|
---|
3759 | if (!reinit_globals) {
|
---|
3760 | free_param_opts(&Globals.param_opt);
|
---|
3761 | apply_lp_set_cmdline();
|
---|
3762 | }
|
---|
3763 |
|
---|
3764 | lp_do_parameter(-1, "idmap config * : backend", Globals.idmap_backend);
|
---|
3765 |
|
---|
3766 | /* We get sections first, so have to start 'behind' to make up */
|
---|
3767 | iServiceIndex = -1;
|
---|
3768 |
|
---|
3769 | if (lp_config_backend_is_file()) {
|
---|
3770 | n2 = talloc_sub_basic(talloc_tos(), get_current_username(),
|
---|
3771 | current_user_info.domain,
|
---|
3772 | pszFname);
|
---|
3773 | if (!n2) {
|
---|
3774 | smb_panic("lp_load_ex: out of memory");
|
---|
3775 | }
|
---|
3776 |
|
---|
3777 | add_to_file_list(NULL, &file_lists, pszFname, n2);
|
---|
3778 |
|
---|
3779 | bRetval = pm_process(n2, lp_do_section, do_parameter, lp_ctx);
|
---|
3780 | TALLOC_FREE(n2);
|
---|
3781 |
|
---|
3782 | /* finish up the last section */
|
---|
3783 | DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
|
---|
3784 | if (bRetval) {
|
---|
3785 | if (iServiceIndex >= 0) {
|
---|
3786 | bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
|
---|
3787 | }
|
---|
3788 | }
|
---|
3789 |
|
---|
3790 | if (lp_config_backend_is_registry()) {
|
---|
3791 | bool ok;
|
---|
3792 | /* config backend changed to registry in config file */
|
---|
3793 | /*
|
---|
3794 | * We need to use this extra global variable here to
|
---|
3795 | * survive restart: init_globals uses this as a default
|
---|
3796 | * for config_backend. Otherwise, init_globals would
|
---|
3797 | * send us into an endless loop here.
|
---|
3798 | */
|
---|
3799 |
|
---|
3800 | config_backend = CONFIG_BACKEND_REGISTRY;
|
---|
3801 | /* start over */
|
---|
3802 | DEBUG(1, ("lp_load_ex: changing to config backend "
|
---|
3803 | "registry\n"));
|
---|
3804 | init_globals(lp_ctx, true);
|
---|
3805 |
|
---|
3806 | TALLOC_FREE(lp_ctx);
|
---|
3807 |
|
---|
3808 | lp_kill_all_services();
|
---|
3809 | ok = lp_load_ex(pszFname, global_only, save_defaults,
|
---|
3810 | add_ipc, reinit_globals,
|
---|
3811 | allow_include_registry,
|
---|
3812 | load_all_shares);
|
---|
3813 | TALLOC_FREE(frame);
|
---|
3814 | return ok;
|
---|
3815 | }
|
---|
3816 | } else if (lp_config_backend_is_registry()) {
|
---|
3817 | bRetval = process_registry_globals();
|
---|
3818 | } else {
|
---|
3819 | DEBUG(0, ("Illegal config backend given: %d\n",
|
---|
3820 | lp_config_backend()));
|
---|
3821 | bRetval = false;
|
---|
3822 | }
|
---|
3823 |
|
---|
3824 | if (bRetval && lp_registry_shares()) {
|
---|
3825 | if (load_all_shares) {
|
---|
3826 | bRetval = process_registry_shares();
|
---|
3827 | } else {
|
---|
3828 | bRetval = reload_registry_shares();
|
---|
3829 | }
|
---|
3830 | }
|
---|
3831 |
|
---|
3832 | {
|
---|
3833 | char *serv = lp_auto_services(talloc_tos());
|
---|
3834 | lp_add_auto_services(serv);
|
---|
3835 | TALLOC_FREE(serv);
|
---|
3836 | }
|
---|
3837 |
|
---|
3838 | if (add_ipc) {
|
---|
3839 | /* When 'restrict anonymous = 2' guest connections to ipc$
|
---|
3840 | are denied */
|
---|
3841 | lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
|
---|
3842 | if ( lp_enable_asu_support() ) {
|
---|
3843 | lp_add_ipc("ADMIN$", false);
|
---|
3844 | }
|
---|
3845 | }
|
---|
3846 |
|
---|
3847 | set_allowed_client_auth();
|
---|
3848 |
|
---|
3849 | if (lp_security() == SEC_ADS && strchr(lp_password_server(), ':')) {
|
---|
3850 | DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
|
---|
3851 | lp_password_server()));
|
---|
3852 | }
|
---|
3853 |
|
---|
3854 | bLoaded = true;
|
---|
3855 |
|
---|
3856 | /* Now we check we_are_a_wins_server and set szWINSserver to 127.0.0.1 */
|
---|
3857 | /* if we_are_a_wins_server is true and we are in the client */
|
---|
3858 | if (lp_is_in_client() && Globals.we_are_a_wins_server) {
|
---|
3859 | lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1");
|
---|
3860 | }
|
---|
3861 |
|
---|
3862 | init_iconv();
|
---|
3863 |
|
---|
3864 | fault_configure(smb_panic_s3);
|
---|
3865 |
|
---|
3866 | /*
|
---|
3867 | * We run this check once the whole smb.conf is parsed, to
|
---|
3868 | * force some settings for the standard way a AD DC is
|
---|
3869 | * operated. We may change these as our code evolves, which
|
---|
3870 | * is why we force these settings.
|
---|
3871 | */
|
---|
3872 | if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
|
---|
3873 | lp_enforce_ad_dc_settings();
|
---|
3874 | }
|
---|
3875 |
|
---|
3876 | bAllowIncludeRegistry = true;
|
---|
3877 |
|
---|
3878 | TALLOC_FREE(frame);
|
---|
3879 | return (bRetval);
|
---|
3880 | }
|
---|
3881 |
|
---|
3882 | static bool lp_load(const char *pszFname,
|
---|
3883 | bool global_only,
|
---|
3884 | bool save_defaults,
|
---|
3885 | bool add_ipc,
|
---|
3886 | bool reinit_globals)
|
---|
3887 | {
|
---|
3888 | return lp_load_ex(pszFname,
|
---|
3889 | global_only,
|
---|
3890 | save_defaults,
|
---|
3891 | add_ipc,
|
---|
3892 | reinit_globals,
|
---|
3893 | true, /* allow_include_registry */
|
---|
3894 | false); /* load_all_shares*/
|
---|
3895 | }
|
---|
3896 |
|
---|
3897 | bool lp_load_initial_only(const char *pszFname)
|
---|
3898 | {
|
---|
3899 | return lp_load_ex(pszFname,
|
---|
3900 | true, /* global only */
|
---|
3901 | true, /* save_defaults */
|
---|
3902 | false, /* add_ipc */
|
---|
3903 | true, /* reinit_globals */
|
---|
3904 | false, /* allow_include_registry */
|
---|
3905 | false); /* load_all_shares*/
|
---|
3906 | }
|
---|
3907 |
|
---|
3908 | /**
|
---|
3909 | * most common lp_load wrapper, loading only the globals
|
---|
3910 | */
|
---|
3911 | bool lp_load_global(const char *file_name)
|
---|
3912 | {
|
---|
3913 | return lp_load(file_name,
|
---|
3914 | true, /* global_only */
|
---|
3915 | false, /* save_defaults */
|
---|
3916 | false, /* add_ipc */
|
---|
3917 | true); /* reinit_globals */
|
---|
3918 | }
|
---|
3919 |
|
---|
3920 | /**
|
---|
3921 | * The typical lp_load wrapper with shares, loads global and
|
---|
3922 | * shares, including IPC, but does not force immediate
|
---|
3923 | * loading of all shares from registry.
|
---|
3924 | */
|
---|
3925 | bool lp_load_with_shares(const char *file_name)
|
---|
3926 | {
|
---|
3927 | return lp_load(file_name,
|
---|
3928 | false, /* global_only */
|
---|
3929 | false, /* save_defaults */
|
---|
3930 | true, /* add_ipc */
|
---|
3931 | true); /* reinit_globals */
|
---|
3932 | }
|
---|
3933 |
|
---|
3934 | /**
|
---|
3935 | * lp_load wrapper, especially for clients
|
---|
3936 | */
|
---|
3937 | bool lp_load_client(const char *file_name)
|
---|
3938 | {
|
---|
3939 | lp_set_in_client(true);
|
---|
3940 |
|
---|
3941 | return lp_load_global(file_name);
|
---|
3942 | }
|
---|
3943 |
|
---|
3944 | /**
|
---|
3945 | * lp_load wrapper, loading only globals, but intended
|
---|
3946 | * for subsequent calls, not reinitializing the globals
|
---|
3947 | * to default values
|
---|
3948 | */
|
---|
3949 | bool lp_load_global_no_reinit(const char *file_name)
|
---|
3950 | {
|
---|
3951 | return lp_load(file_name,
|
---|
3952 | true, /* global_only */
|
---|
3953 | false, /* save_defaults */
|
---|
3954 | false, /* add_ipc */
|
---|
3955 | false); /* reinit_globals */
|
---|
3956 | }
|
---|
3957 |
|
---|
3958 | /**
|
---|
3959 | * lp_load wrapper, loading globals and shares,
|
---|
3960 | * intended for subsequent calls, i.e. not reinitializing
|
---|
3961 | * the globals to default values.
|
---|
3962 | */
|
---|
3963 | bool lp_load_no_reinit(const char *file_name)
|
---|
3964 | {
|
---|
3965 | return lp_load(file_name,
|
---|
3966 | false, /* global_only */
|
---|
3967 | false, /* save_defaults */
|
---|
3968 | false, /* add_ipc */
|
---|
3969 | false); /* reinit_globals */
|
---|
3970 | }
|
---|
3971 |
|
---|
3972 |
|
---|
3973 | /**
|
---|
3974 | * lp_load wrapper, especially for clients, no reinitialization
|
---|
3975 | */
|
---|
3976 | bool lp_load_client_no_reinit(const char *file_name)
|
---|
3977 | {
|
---|
3978 | lp_set_in_client(true);
|
---|
3979 |
|
---|
3980 | return lp_load_global_no_reinit(file_name);
|
---|
3981 | }
|
---|
3982 |
|
---|
3983 | bool lp_load_with_registry_shares(const char *pszFname)
|
---|
3984 | {
|
---|
3985 | return lp_load_ex(pszFname,
|
---|
3986 | false, /* global_only */
|
---|
3987 | true, /* save_defaults */
|
---|
3988 | false, /* add_ipc */
|
---|
3989 | false, /* reinit_globals */
|
---|
3990 | true, /* allow_include_registry */
|
---|
3991 | true); /* load_all_shares*/
|
---|
3992 | }
|
---|
3993 |
|
---|
3994 | /***************************************************************************
|
---|
3995 | Return the max number of services.
|
---|
3996 | ***************************************************************************/
|
---|
3997 |
|
---|
3998 | int lp_numservices(void)
|
---|
3999 | {
|
---|
4000 | return (iNumServices);
|
---|
4001 | }
|
---|
4002 |
|
---|
4003 | /***************************************************************************
|
---|
4004 | Display the contents of the services array in human-readable form.
|
---|
4005 | ***************************************************************************/
|
---|
4006 |
|
---|
4007 | void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
|
---|
4008 | {
|
---|
4009 | int iService;
|
---|
4010 | struct loadparm_context *lp_ctx;
|
---|
4011 |
|
---|
4012 | if (show_defaults)
|
---|
4013 | defaults_saved = false;
|
---|
4014 |
|
---|
4015 | lp_ctx = setup_lp_context(talloc_tos());
|
---|
4016 | if (lp_ctx == NULL) {
|
---|
4017 | return;
|
---|
4018 | }
|
---|
4019 |
|
---|
4020 | lpcfg_dump_globals(lp_ctx, f, !defaults_saved);
|
---|
4021 |
|
---|
4022 | lpcfg_dump_a_service(&sDefault, &sDefault, f, flags_list, show_defaults);
|
---|
4023 |
|
---|
4024 | for (iService = 0; iService < maxtoprint; iService++) {
|
---|
4025 | fprintf(f,"\n");
|
---|
4026 | lp_dump_one(f, show_defaults, iService);
|
---|
4027 | }
|
---|
4028 | }
|
---|
4029 |
|
---|
4030 | /***************************************************************************
|
---|
4031 | Display the contents of one service in human-readable form.
|
---|
4032 | ***************************************************************************/
|
---|
4033 |
|
---|
4034 | void lp_dump_one(FILE * f, bool show_defaults, int snum)
|
---|
4035 | {
|
---|
4036 | if (VALID(snum)) {
|
---|
4037 | if (ServicePtrs[snum]->szService[0] == '\0')
|
---|
4038 | return;
|
---|
4039 | lpcfg_dump_a_service(ServicePtrs[snum], &sDefault, f,
|
---|
4040 | flags_list, show_defaults);
|
---|
4041 | }
|
---|
4042 | }
|
---|
4043 |
|
---|
4044 | /***************************************************************************
|
---|
4045 | Return the number of the service with the given name, or -1 if it doesn't
|
---|
4046 | exist. Note that this is a DIFFERENT ANIMAL from the internal function
|
---|
4047 | getservicebyname()! This works ONLY if all services have been loaded, and
|
---|
4048 | does not copy the found service.
|
---|
4049 | ***************************************************************************/
|
---|
4050 |
|
---|
4051 | int lp_servicenumber(const char *pszServiceName)
|
---|
4052 | {
|
---|
4053 | int iService;
|
---|
4054 | fstring serviceName;
|
---|
4055 |
|
---|
4056 | if (!pszServiceName) {
|
---|
4057 | return GLOBAL_SECTION_SNUM;
|
---|
4058 | }
|
---|
4059 |
|
---|
4060 | for (iService = iNumServices - 1; iService >= 0; iService--) {
|
---|
4061 | if (VALID(iService) && ServicePtrs[iService]->szService) {
|
---|
4062 | /*
|
---|
4063 | * The substitution here is used to support %U in
|
---|
4064 | * service names
|
---|
4065 | */
|
---|
4066 | fstrcpy(serviceName, ServicePtrs[iService]->szService);
|
---|
4067 | standard_sub_basic(get_current_username(),
|
---|
4068 | current_user_info.domain,
|
---|
4069 | serviceName,sizeof(serviceName));
|
---|
4070 | if (strequal(serviceName, pszServiceName)) {
|
---|
4071 | break;
|
---|
4072 | }
|
---|
4073 | }
|
---|
4074 | }
|
---|
4075 |
|
---|
4076 | if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
|
---|
4077 | struct timespec last_mod;
|
---|
4078 |
|
---|
4079 | if (!usershare_exists(iService, &last_mod)) {
|
---|
4080 | /* Remove the share security tdb entry for it. */
|
---|
4081 | delete_share_security(lp_servicename(talloc_tos(), iService));
|
---|
4082 | /* Remove it from the array. */
|
---|
4083 | free_service_byindex(iService);
|
---|
4084 | /* Doesn't exist anymore. */
|
---|
4085 | return GLOBAL_SECTION_SNUM;
|
---|
4086 | }
|
---|
4087 |
|
---|
4088 | /* Has it been modified ? If so delete and reload. */
|
---|
4089 | if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod,
|
---|
4090 | &last_mod) < 0) {
|
---|
4091 | /* Remove it from the array. */
|
---|
4092 | free_service_byindex(iService);
|
---|
4093 | /* and now reload it. */
|
---|
4094 | iService = load_usershare_service(pszServiceName);
|
---|
4095 | }
|
---|
4096 | }
|
---|
4097 |
|
---|
4098 | if (iService < 0) {
|
---|
4099 | DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName));
|
---|
4100 | return GLOBAL_SECTION_SNUM;
|
---|
4101 | }
|
---|
4102 |
|
---|
4103 | return (iService);
|
---|
4104 | }
|
---|
4105 |
|
---|
4106 | /*******************************************************************
|
---|
4107 | A useful volume label function.
|
---|
4108 | ********************************************************************/
|
---|
4109 |
|
---|
4110 | const char *volume_label(TALLOC_CTX *ctx, int snum)
|
---|
4111 | {
|
---|
4112 | char *ret;
|
---|
4113 | const char *label = lp_volume(ctx, snum);
|
---|
4114 | if (!*label) {
|
---|
4115 | label = lp_servicename(ctx, snum);
|
---|
4116 | }
|
---|
4117 |
|
---|
4118 | /* This returns a 33 byte guarenteed null terminated string. */
|
---|
4119 | ret = talloc_strndup(ctx, label, 32);
|
---|
4120 | if (!ret) {
|
---|
4121 | return "";
|
---|
4122 | }
|
---|
4123 | return ret;
|
---|
4124 | }
|
---|
4125 |
|
---|
4126 | /*******************************************************************
|
---|
4127 | Get the default server type we will announce as via nmbd.
|
---|
4128 | ********************************************************************/
|
---|
4129 |
|
---|
4130 | int lp_default_server_announce(void)
|
---|
4131 | {
|
---|
4132 | int default_server_announce = 0;
|
---|
4133 | default_server_announce |= SV_TYPE_WORKSTATION;
|
---|
4134 | default_server_announce |= SV_TYPE_SERVER;
|
---|
4135 | default_server_announce |= SV_TYPE_SERVER_UNIX;
|
---|
4136 |
|
---|
4137 | /* note that the flag should be set only if we have a
|
---|
4138 | printer service but nmbd doesn't actually load the
|
---|
4139 | services so we can't tell --jerry */
|
---|
4140 |
|
---|
4141 | default_server_announce |= SV_TYPE_PRINTQ_SERVER;
|
---|
4142 |
|
---|
4143 | default_server_announce |= SV_TYPE_SERVER_NT;
|
---|
4144 | default_server_announce |= SV_TYPE_NT;
|
---|
4145 |
|
---|
4146 | switch (lp_server_role()) {
|
---|
4147 | case ROLE_DOMAIN_MEMBER:
|
---|
4148 | default_server_announce |= SV_TYPE_DOMAIN_MEMBER;
|
---|
4149 | break;
|
---|
4150 | case ROLE_DOMAIN_PDC:
|
---|
4151 | default_server_announce |= SV_TYPE_DOMAIN_CTRL;
|
---|
4152 | break;
|
---|
4153 | case ROLE_DOMAIN_BDC:
|
---|
4154 | default_server_announce |= SV_TYPE_DOMAIN_BAKCTRL;
|
---|
4155 | break;
|
---|
4156 | case ROLE_STANDALONE:
|
---|
4157 | default:
|
---|
4158 | break;
|
---|
4159 | }
|
---|
4160 | if (lp_time_server())
|
---|
4161 | default_server_announce |= SV_TYPE_TIME_SOURCE;
|
---|
4162 |
|
---|
4163 | if (lp_host_msdfs())
|
---|
4164 | default_server_announce |= SV_TYPE_DFS_SERVER;
|
---|
4165 |
|
---|
4166 | return default_server_announce;
|
---|
4167 | }
|
---|
4168 |
|
---|
4169 | /***********************************************************
|
---|
4170 | If we are PDC then prefer us as DMB
|
---|
4171 | ************************************************************/
|
---|
4172 |
|
---|
4173 | bool lp_domain_master(void)
|
---|
4174 | {
|
---|
4175 | if (Globals._domain_master == Auto)
|
---|
4176 | return (lp_server_role() == ROLE_DOMAIN_PDC);
|
---|
4177 |
|
---|
4178 | return (bool)Globals._domain_master;
|
---|
4179 | }
|
---|
4180 |
|
---|
4181 | /***********************************************************
|
---|
4182 | If we are PDC then prefer us as DMB
|
---|
4183 | ************************************************************/
|
---|
4184 |
|
---|
4185 | static bool lp_domain_master_true_or_auto(void)
|
---|
4186 | {
|
---|
4187 | if (Globals._domain_master) /* auto or yes */
|
---|
4188 | return true;
|
---|
4189 |
|
---|
4190 | return false;
|
---|
4191 | }
|
---|
4192 |
|
---|
4193 | /***********************************************************
|
---|
4194 | If we are DMB then prefer us as LMB
|
---|
4195 | ************************************************************/
|
---|
4196 |
|
---|
4197 | bool lp_preferred_master(void)
|
---|
4198 | {
|
---|
4199 | int preferred_master = lp__preferred_master();
|
---|
4200 |
|
---|
4201 | if (preferred_master == Auto)
|
---|
4202 | return (lp_local_master() && lp_domain_master());
|
---|
4203 |
|
---|
4204 | return (bool)preferred_master;
|
---|
4205 | }
|
---|
4206 |
|
---|
4207 | /*******************************************************************
|
---|
4208 | Remove a service.
|
---|
4209 | ********************************************************************/
|
---|
4210 |
|
---|
4211 | void lp_remove_service(int snum)
|
---|
4212 | {
|
---|
4213 | ServicePtrs[snum]->valid = false;
|
---|
4214 | }
|
---|
4215 |
|
---|
4216 | const char *lp_printername(TALLOC_CTX *ctx, int snum)
|
---|
4217 | {
|
---|
4218 | const char *ret = lp__printername(ctx, snum);
|
---|
4219 | if (ret == NULL || *ret == '\0') {
|
---|
4220 | ret = lp_const_servicename(snum);
|
---|
4221 | }
|
---|
4222 |
|
---|
4223 | return ret;
|
---|
4224 | }
|
---|
4225 |
|
---|
4226 |
|
---|
4227 | /***********************************************************
|
---|
4228 | Allow daemons such as winbindd to fix their logfile name.
|
---|
4229 | ************************************************************/
|
---|
4230 |
|
---|
4231 | void lp_set_logfile(const char *name)
|
---|
4232 | {
|
---|
4233 | lpcfg_string_set(Globals.ctx, &Globals.logfile, name);
|
---|
4234 | debug_set_logfile(name);
|
---|
4235 | }
|
---|
4236 |
|
---|
4237 | /*******************************************************************
|
---|
4238 | Return the max print jobs per queue.
|
---|
4239 | ********************************************************************/
|
---|
4240 |
|
---|
4241 | int lp_maxprintjobs(int snum)
|
---|
4242 | {
|
---|
4243 | int maxjobs = lp_max_print_jobs(snum);
|
---|
4244 |
|
---|
4245 | if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
|
---|
4246 | maxjobs = PRINT_MAX_JOBID - 1;
|
---|
4247 |
|
---|
4248 | return maxjobs;
|
---|
4249 | }
|
---|
4250 |
|
---|
4251 | const char *lp_printcapname(void)
|
---|
4252 | {
|
---|
4253 | const char *printcap_name = lp_printcap_name();
|
---|
4254 |
|
---|
4255 | if ((printcap_name != NULL) &&
|
---|
4256 | (printcap_name[0] != '\0'))
|
---|
4257 | return printcap_name;
|
---|
4258 |
|
---|
4259 | if (sDefault.printing == PRINT_CUPS) {
|
---|
4260 | return "cups";
|
---|
4261 | }
|
---|
4262 |
|
---|
4263 | if (sDefault.printing == PRINT_BSD)
|
---|
4264 | return "/etc/printcap";
|
---|
4265 |
|
---|
4266 | return PRINTCAP_NAME;
|
---|
4267 | }
|
---|
4268 |
|
---|
4269 | static uint32_t spoolss_state;
|
---|
4270 |
|
---|
4271 | bool lp_disable_spoolss( void )
|
---|
4272 | {
|
---|
4273 | if ( spoolss_state == SVCCTL_STATE_UNKNOWN )
|
---|
4274 | spoolss_state = lp__disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
|
---|
4275 |
|
---|
4276 | return spoolss_state == SVCCTL_STOPPED ? true : false;
|
---|
4277 | }
|
---|
4278 |
|
---|
4279 | void lp_set_spoolss_state( uint32_t state )
|
---|
4280 | {
|
---|
4281 | SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
|
---|
4282 |
|
---|
4283 | spoolss_state = state;
|
---|
4284 | }
|
---|
4285 |
|
---|
4286 | uint32_t lp_get_spoolss_state( void )
|
---|
4287 | {
|
---|
4288 | return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
|
---|
4289 | }
|
---|
4290 |
|
---|
4291 | /*******************************************************************
|
---|
4292 | Ensure we don't use sendfile if server smb signing is active.
|
---|
4293 | ********************************************************************/
|
---|
4294 |
|
---|
4295 | bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
|
---|
4296 | {
|
---|
4297 | bool sign_active = false;
|
---|
4298 |
|
---|
4299 | /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
|
---|
4300 | if (get_Protocol() < PROTOCOL_NT1) {
|
---|
4301 | return false;
|
---|
4302 | }
|
---|
4303 | if (signing_state) {
|
---|
4304 | sign_active = smb_signing_is_active(signing_state);
|
---|
4305 | }
|
---|
4306 | return (lp__use_sendfile(snum) &&
|
---|
4307 | (get_remote_arch() != RA_WIN95) &&
|
---|
4308 | !sign_active);
|
---|
4309 | }
|
---|
4310 |
|
---|
4311 | /*******************************************************************
|
---|
4312 | Turn off sendfile if we find the underlying OS doesn't support it.
|
---|
4313 | ********************************************************************/
|
---|
4314 |
|
---|
4315 | void set_use_sendfile(int snum, bool val)
|
---|
4316 | {
|
---|
4317 | if (LP_SNUM_OK(snum))
|
---|
4318 | ServicePtrs[snum]->_use_sendfile = val;
|
---|
4319 | else
|
---|
4320 | sDefault._use_sendfile = val;
|
---|
4321 | }
|
---|
4322 |
|
---|
4323 | void lp_set_mangling_method(const char *new_method)
|
---|
4324 | {
|
---|
4325 | lpcfg_string_set(Globals.ctx, &Globals.mangling_method, new_method);
|
---|
4326 | }
|
---|
4327 |
|
---|
4328 | /*******************************************************************
|
---|
4329 | Global state for POSIX pathname processing.
|
---|
4330 | ********************************************************************/
|
---|
4331 |
|
---|
4332 | static bool posix_pathnames;
|
---|
4333 |
|
---|
4334 | bool lp_posix_pathnames(void)
|
---|
4335 | {
|
---|
4336 | return posix_pathnames;
|
---|
4337 | }
|
---|
4338 |
|
---|
4339 | /*******************************************************************
|
---|
4340 | Set posix pathnames to new value. Returns old value.
|
---|
4341 | ********************************************************************/
|
---|
4342 |
|
---|
4343 | bool lp_set_posix_pathnames(bool newval)
|
---|
4344 | {
|
---|
4345 | bool oldval = posix_pathnames;
|
---|
4346 | posix_pathnames = newval;
|
---|
4347 | return oldval;
|
---|
4348 | }
|
---|
4349 |
|
---|
4350 | /*******************************************************************
|
---|
4351 | Global state for POSIX lock processing - CIFS unix extensions.
|
---|
4352 | ********************************************************************/
|
---|
4353 |
|
---|
4354 | bool posix_default_lock_was_set;
|
---|
4355 | static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
|
---|
4356 |
|
---|
4357 | enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
|
---|
4358 | {
|
---|
4359 | if (posix_default_lock_was_set) {
|
---|
4360 | return posix_cifsx_locktype;
|
---|
4361 | } else {
|
---|
4362 | return (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
|
---|
4363 | POSIX_LOCK : WINDOWS_LOCK;
|
---|
4364 | }
|
---|
4365 | }
|
---|
4366 |
|
---|
4367 | /*******************************************************************
|
---|
4368 | ********************************************************************/
|
---|
4369 |
|
---|
4370 | void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
|
---|
4371 | {
|
---|
4372 | posix_default_lock_was_set = true;
|
---|
4373 | posix_cifsx_locktype = val;
|
---|
4374 | }
|
---|
4375 |
|
---|
4376 | int lp_min_receive_file_size(void)
|
---|
4377 | {
|
---|
4378 | int min_receivefile_size = lp_min_receivefile_size();
|
---|
4379 |
|
---|
4380 | if (min_receivefile_size < 0) {
|
---|
4381 | return 0;
|
---|
4382 | }
|
---|
4383 | return min_receivefile_size;
|
---|
4384 | }
|
---|
4385 |
|
---|
4386 | /*******************************************************************
|
---|
4387 | Safe wide links checks.
|
---|
4388 | This helper function always verify the validity of wide links,
|
---|
4389 | even after a configuration file reload.
|
---|
4390 | ********************************************************************/
|
---|
4391 |
|
---|
4392 | void widelinks_warning(int snum)
|
---|
4393 | {
|
---|
4394 | if (lp_allow_insecure_wide_links()) {
|
---|
4395 | return;
|
---|
4396 | }
|
---|
4397 |
|
---|
4398 | if (lp_unix_extensions() && lp_wide_links(snum)) {
|
---|
4399 | DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
|
---|
4400 | "These parameters are incompatible. "
|
---|
4401 | "Wide links will be disabled for this share.\n",
|
---|
4402 | lp_servicename(talloc_tos(), snum) ));
|
---|
4403 | }
|
---|
4404 | }
|
---|
4405 |
|
---|
4406 | bool lp_widelinks(int snum)
|
---|
4407 | {
|
---|
4408 | /* wide links is always incompatible with unix extensions */
|
---|
4409 | if (lp_unix_extensions()) {
|
---|
4410 | /*
|
---|
4411 | * Unless we have "allow insecure widelinks"
|
---|
4412 | * turned on.
|
---|
4413 | */
|
---|
4414 | if (!lp_allow_insecure_wide_links()) {
|
---|
4415 | return false;
|
---|
4416 | }
|
---|
4417 | }
|
---|
4418 |
|
---|
4419 | return lp_wide_links(snum);
|
---|
4420 | }
|
---|
4421 |
|
---|
4422 | int lp_server_role(void)
|
---|
4423 | {
|
---|
4424 | return lp_find_server_role(lp__server_role(),
|
---|
4425 | lp__security(),
|
---|
4426 | lp__domain_logons(),
|
---|
4427 | lp_domain_master_true_or_auto());
|
---|
4428 | }
|
---|
4429 |
|
---|
4430 | int lp_security(void)
|
---|
4431 | {
|
---|
4432 | return lp_find_security(lp__server_role(),
|
---|
4433 | lp__security());
|
---|
4434 | }
|
---|
4435 |
|
---|
4436 | int lp_client_max_protocol(void)
|
---|
4437 | {
|
---|
4438 | int client_max_protocol = lp__client_max_protocol();
|
---|
4439 | if (client_max_protocol == PROTOCOL_DEFAULT) {
|
---|
4440 | return PROTOCOL_NT1;
|
---|
4441 | }
|
---|
4442 | return client_max_protocol;
|
---|
4443 | }
|
---|
4444 |
|
---|
4445 | int lp_client_ipc_min_protocol(void)
|
---|
4446 | {
|
---|
4447 | int client_ipc_min_protocol = lp__client_ipc_min_protocol();
|
---|
4448 | if (client_ipc_min_protocol == PROTOCOL_DEFAULT) {
|
---|
4449 | client_ipc_min_protocol = lp_client_min_protocol();
|
---|
4450 | }
|
---|
4451 | if (client_ipc_min_protocol < PROTOCOL_NT1) {
|
---|
4452 | return PROTOCOL_NT1;
|
---|
4453 | }
|
---|
4454 | return client_ipc_min_protocol;
|
---|
4455 | }
|
---|
4456 |
|
---|
4457 | int lp_client_ipc_max_protocol(void)
|
---|
4458 | {
|
---|
4459 | int client_ipc_max_protocol = lp__client_ipc_max_protocol();
|
---|
4460 | if (client_ipc_max_protocol == PROTOCOL_DEFAULT) {
|
---|
4461 | return PROTOCOL_LATEST;
|
---|
4462 | }
|
---|
4463 | if (client_ipc_max_protocol < PROTOCOL_NT1) {
|
---|
4464 | return PROTOCOL_NT1;
|
---|
4465 | }
|
---|
4466 | return client_ipc_max_protocol;
|
---|
4467 | }
|
---|
4468 |
|
---|
4469 | int lp_client_ipc_signing(void)
|
---|
4470 | {
|
---|
4471 | int client_ipc_signing = lp__client_ipc_signing();
|
---|
4472 | if (client_ipc_signing == SMB_SIGNING_DEFAULT) {
|
---|
4473 | return SMB_SIGNING_REQUIRED;
|
---|
4474 | }
|
---|
4475 | return client_ipc_signing;
|
---|
4476 | }
|
---|
4477 |
|
---|
4478 | struct loadparm_global * get_globals(void)
|
---|
4479 | {
|
---|
4480 | return &Globals;
|
---|
4481 | }
|
---|
4482 |
|
---|
4483 | unsigned int * get_flags(void)
|
---|
4484 | {
|
---|
4485 | if (flags_list == NULL) {
|
---|
4486 | flags_list = talloc_zero_array(NULL, unsigned int, num_parameters());
|
---|
4487 | }
|
---|
4488 |
|
---|
4489 | return flags_list;
|
---|
4490 | }
|
---|