2 Unix SMB/CIFS implementation.
3 Parameter loading functions
4 Copyright (C) Karl Auer 1993-1998
6 Largely re-written by Andrew Tridgell, September 1994
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
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.
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.
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/>.
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.
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
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
57 #include "system/filesys.h"
59 #include "lib/param/loadparm.h"
61 #include "lib/smbconf/smbconf.h"
62 #include "lib/smbconf/smbconf_init.h"
65 #include "../librpc/gen_ndr/svcctl.h"
67 #include "../libcli/smb/smb_signing.h"
68 #include "dbwrap/dbwrap.h"
69 #include "dbwrap/dbwrap_rbt.h"
70 #include "../lib/util/bitmap.h"
71 #include "../source4/dns_server/dns_update.h"
73 #ifdef HAVE_SYS_SYSCTL_H
74 #include <sys/sysctl.h>
77 #ifdef HAVE_HTTPCONNECTENCRYPT
78 #include <cups/http.h>
81 #ifdef CLUSTER_SUPPORT
82 #include "ctdb_private.h"
87 extern userdom_struct current_user_info
;
89 /* the special value for the include parameter
90 * to be interpreted not as a file name but to
91 * trigger loading of the global smb.conf options
93 #ifndef INCLUDE_REGISTRY_NAME
94 #define INCLUDE_REGISTRY_NAME "registry"
97 static bool in_client
= false; /* Not in the client by default */
98 static struct smbconf_csn conf_last_csn
;
100 static int config_backend
= CONFIG_BACKEND_FILE
;
102 /* some helpful bits */
103 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
104 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
106 #define USERSHARE_VALID 1
107 #define USERSHARE_PENDING_DELETE 2
109 static bool defaults_saved
= false;
111 #define LOADPARM_EXTRA_GLOBALS \
112 struct parmlist_entry *param_opt; \
115 int iminreceivefile; \
116 char *szPrintcapname; \
118 int iPreferredMaster; \
119 char *szLdapMachineSuffix; \
120 char *szLdapUserSuffix; \
121 char *szLdapIdmapSuffix; \
122 char *szLdapGroupSuffix; \
125 char *szSocketAddress; \
126 char *szUsershareTemplateShare; \
129 int winbindMaxDomainConnections; \
130 int ismb2_max_credits; \
132 char *tls_certfile; \
136 char *panic_action; \
137 int bPreferredMaster;
139 #include "param/param_global.h"
141 static struct loadparm_global Globals
;
143 /* This is a default service used to prime a services structure */
144 static struct loadparm_service sDefault
=
149 .usershare_last_mod
= {0, 0},
153 .szInvalidUsers
= NULL
,
154 .szValidUsers
= NULL
,
155 .szAdminUsers
= NULL
,
160 .szRootPreExec
= NULL
,
161 .szRootPostExec
= NULL
,
162 .szCupsOptions
= NULL
,
163 .szPrintcommand
= NULL
,
164 .szLpqcommand
= NULL
,
165 .szLprmcommand
= NULL
,
166 .szLppausecommand
= NULL
,
167 .szLpresumecommand
= NULL
,
168 .szQueuepausecommand
= NULL
,
169 .szQueueresumecommand
= NULL
,
170 .szPrintername
= NULL
,
171 .szPrintjobUsername
= NULL
,
172 .szDontdescend
= NULL
,
173 .szHostsallow
= NULL
,
175 .szMagicScript
= NULL
,
176 .szMagicOutput
= NULL
,
179 .szVetoOplockFiles
= NULL
,
187 .szVfsObjects
= NULL
,
188 .szMSDfsProxy
= NULL
,
189 .szAioWriteBehind
= NULL
,
192 .iMaxPrintJobs
= 1000,
193 .iMaxReportedPrintJobs
= 0,
194 .iWriteCacheSize
= 0,
195 .iCreate_mask
= 0744,
196 .iCreate_force_mode
= 0,
197 .iSecurity_mask
= 0777,
198 .iSecurity_force_mode
= 0,
200 .iDir_force_mode
= 0,
201 .iDir_Security_mask
= 0777,
202 .iDir_Security_force_mode
= 0,
203 .iMaxConnections
= 0,
204 .iDefaultCase
= CASE_LOWER
,
205 .iPrinting
= DEFAULT_PRINTING
,
206 .iOplockContentionLimit
= 2,
209 .iDfreeCacheTime
= 0,
210 .bPreexecClose
= false,
211 .bRootpreexecClose
= false,
212 .iCaseSensitive
= Auto
,
213 .bCasePreserve
= true,
214 .bShortCasePreserve
= true,
215 .bHideDotFiles
= true,
216 .bHideSpecialFiles
= false,
217 .bHideUnReadable
= false,
218 .bHideUnWriteableFiles
= false,
220 .bAccessBasedShareEnum
= false,
224 .bGuest_only
= false,
225 .bAdministrative_share
= false,
228 .bPrintNotifyBackchannel
= true,
229 .bMap_system
= false,
230 .bMap_hidden
= false,
231 .bMap_archive
= true,
232 .bStoreDosAttributes
= false,
233 .bDmapiSupport
= false,
235 .iStrictLocking
= Auto
,
236 .bPosixLocking
= true,
239 .bKernelOplocks
= false,
240 .bLevel2OpLocks
= true,
242 .bMangledNames
= true,
245 .bSyncAlways
= false,
246 .bStrictAllocate
= false,
247 .bStrictSync
= false,
250 .bDeleteReadonly
= false,
251 .bFakeOplocks
= false,
252 .bDeleteVetoFiles
= false,
253 .bDosFilemode
= false,
254 .bDosFiletimes
= true,
255 .bDosFiletimeResolution
= false,
256 .bFakeDirCreateTimes
= false,
257 .bBlockingLocks
= true,
258 .bInheritPerms
= false,
259 .bInheritACLS
= false,
260 .bInheritOwner
= false,
262 .bUseClientDriver
= false,
263 .bDefaultDevmode
= true,
264 .bForcePrintername
= false,
265 .bNTAclSupport
= true,
266 .bForceUnknownAclUser
= false,
267 .bUseSendfile
= false,
268 .bProfileAcls
= false,
269 .bMap_acl_inherit
= false,
272 .bAclCheckPermissions
= true,
273 .bAclMapFullControl
= true,
274 .bAclGroupControl
= false,
275 .bChangeNotify
= true,
276 .bKernelChangeNotify
= true,
277 .iallocation_roundup_size
= SMB_ROUNDUP_ALLOCATION_SIZE
,
280 .iMap_readonly
= MAP_READONLY_YES
,
281 #ifdef BROKEN_DIRECTORY_HANDLING
282 .iDirectoryNameCacheSize
= 0,
284 .iDirectoryNameCacheSize
= 100,
286 .ismb_encrypt
= Auto
,
291 /* local variables */
292 static struct loadparm_service
**ServicePtrs
= NULL
;
293 static int iNumServices
= 0;
294 static int iServiceIndex
= 0;
295 static struct db_context
*ServiceHash
;
296 static int *invalid_services
= NULL
;
297 static int num_invalid_services
= 0;
298 static bool bInGlobalSection
= true;
299 static bool bGlobalOnly
= false;
301 #define NUMPARAMETERS (sizeof(parm_table) / sizeof(struct parm_struct))
303 /* prototypes for the special type handlers */
304 static bool handle_include(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
305 static bool handle_copy(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
306 static bool handle_idmap_backend(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
307 static bool handle_idmap_uid(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
308 static bool handle_idmap_gid(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
309 static bool handle_debug_list(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
310 static bool handle_realm(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
311 static bool handle_netbios_aliases(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
312 static bool handle_charset(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
313 static bool handle_dos_charset(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
314 static bool handle_printing(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
315 static bool handle_ldap_debug_level(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
);
317 /* these are parameter handlers which are not needed in the
321 #define handle_logfile NULL
323 static void set_allowed_client_auth(void);
325 static void add_to_file_list(const char *fname
, const char *subfname
);
326 static bool lp_set_cmdline_helper(const char *pszParmName
, const char *pszParmValue
, bool store_values
);
327 static void free_param_opts(struct parmlist_entry
**popts
);
329 #include "lib/param/param_table.c"
331 /***************************************************************************
332 Initialise the sDefault parameter structure for the printer values.
333 ***************************************************************************/
335 static void init_printer_values(struct loadparm_service
*pService
)
337 /* choose defaults depending on the type of printing */
338 switch (pService
->iPrinting
) {
343 string_set(&pService
->szLpqcommand
, "lpq -P'%p'");
344 string_set(&pService
->szLprmcommand
, "lprm -P'%p' %j");
345 string_set(&pService
->szPrintcommand
, "lpr -r -P'%p' %s");
350 string_set(&pService
->szLpqcommand
, "lpq -P'%p'");
351 string_set(&pService
->szLprmcommand
, "lprm -P'%p' %j");
352 string_set(&pService
->szPrintcommand
, "lpr -r -P'%p' %s");
353 string_set(&pService
->szQueuepausecommand
, "lpc stop '%p'");
354 string_set(&pService
->szQueueresumecommand
, "lpc start '%p'");
355 string_set(&pService
->szLppausecommand
, "lpc hold '%p' %j");
356 string_set(&pService
->szLpresumecommand
, "lpc release '%p' %j");
362 /* set the lpq command to contain the destination printer
363 name only. This is used by cups_queue_get() */
364 string_set(&pService
->szLpqcommand
, "%p");
365 string_set(&pService
->szLprmcommand
, "");
366 string_set(&pService
->szPrintcommand
, "");
367 string_set(&pService
->szLppausecommand
, "");
368 string_set(&pService
->szLpresumecommand
, "");
369 string_set(&pService
->szQueuepausecommand
, "");
370 string_set(&pService
->szQueueresumecommand
, "");
372 string_set(&pService
->szLpqcommand
, "lpq -P'%p'");
373 string_set(&pService
->szLprmcommand
, "lprm -P'%p' %j");
374 string_set(&pService
->szPrintcommand
, "lpr -P'%p' %s; rm %s");
375 string_set(&pService
->szLppausecommand
, "lp -i '%p-%j' -H hold");
376 string_set(&pService
->szLpresumecommand
, "lp -i '%p-%j' -H resume");
377 string_set(&pService
->szQueuepausecommand
, "disable '%p'");
378 string_set(&pService
->szQueueresumecommand
, "enable '%p'");
379 #endif /* HAVE_CUPS */
384 string_set(&pService
->szLpqcommand
, "lpstat -o%p");
385 string_set(&pService
->szLprmcommand
, "cancel %p-%j");
386 string_set(&pService
->szPrintcommand
, "lp -c -d%p %s; rm %s");
387 string_set(&pService
->szQueuepausecommand
, "disable %p");
388 string_set(&pService
->szQueueresumecommand
, "enable %p");
390 string_set(&pService
->szLppausecommand
, "lp -i %p-%j -H hold");
391 string_set(&pService
->szLpresumecommand
, "lp -i %p-%j -H resume");
396 string_set(&pService
->szLpqcommand
, "lpq -P%p");
397 string_set(&pService
->szLprmcommand
, "lprm -P%p %j");
398 string_set(&pService
->szPrintcommand
, "lp -r -P%p %s");
401 #if defined(DEVELOPER) || defined(ENABLE_BUILD_FARM_HACKS)
406 TALLOC_CTX
*tmp_ctx
= talloc_stackframe();
409 tdbfile
= talloc_asprintf(
410 tmp_ctx
, "tdbfile=%s",
411 lp_parm_const_string(-1, "vlp", "tdbfile",
413 if (tdbfile
== NULL
) {
414 tdbfile
="tdbfile=/tmp/vlp.tdb";
417 tmp
= talloc_asprintf(tmp_ctx
, "vlp %s print %%p %%s",
419 string_set(&pService
->szPrintcommand
,
420 tmp
? tmp
: "vlp print %p %s");
422 tmp
= talloc_asprintf(tmp_ctx
, "vlp %s lpq %%p",
424 string_set(&pService
->szLpqcommand
,
425 tmp
? tmp
: "vlp lpq %p");
427 tmp
= talloc_asprintf(tmp_ctx
, "vlp %s lprm %%p %%j",
429 string_set(&pService
->szLprmcommand
,
430 tmp
? tmp
: "vlp lprm %p %j");
432 tmp
= talloc_asprintf(tmp_ctx
, "vlp %s lppause %%p %%j",
434 string_set(&pService
->szLppausecommand
,
435 tmp
? tmp
: "vlp lppause %p %j");
437 tmp
= talloc_asprintf(tmp_ctx
, "vlp %s lpresume %%p %%j",
439 string_set(&pService
->szLpresumecommand
,
440 tmp
? tmp
: "vlp lpresume %p %j");
442 tmp
= talloc_asprintf(tmp_ctx
, "vlp %s queuepause %%p",
444 string_set(&pService
->szQueuepausecommand
,
445 tmp
? tmp
: "vlp queuepause %p");
447 tmp
= talloc_asprintf(tmp_ctx
, "vlp %s queueresume %%p",
449 string_set(&pService
->szQueueresumecommand
,
450 tmp
? tmp
: "vlp queueresume %p");
451 TALLOC_FREE(tmp_ctx
);
455 #endif /* DEVELOPER */
460 * Function to return the default value for the maximum number of open
461 * file descriptors permitted. This function tries to consult the
462 * kernel-level (sysctl) and ulimit (getrlimit()) values and goes
463 * the smaller of those.
465 static int max_open_files(void)
467 int sysctl_max
= MAX_OPEN_FILES
;
468 int rlimit_max
= MAX_OPEN_FILES
;
470 #ifdef HAVE_SYSCTLBYNAME
472 size_t size
= sizeof(sysctl_max
);
473 sysctlbyname("kern.maxfilesperproc", &sysctl_max
, &size
, NULL
,
478 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
484 if (getrlimit(RLIMIT_NOFILE
, &rl
) == 0)
485 rlimit_max
= rl
.rlim_cur
;
487 #if defined(RLIM_INFINITY)
488 if(rl
.rlim_cur
== RLIM_INFINITY
)
489 rlimit_max
= MAX_OPEN_FILES
;
494 if (sysctl_max
< MIN_OPEN_FILES_WINDOWS
) {
495 DEBUG(2,("max_open_files: increasing sysctl_max (%d) to "
496 "minimum Windows limit (%d)\n",
498 MIN_OPEN_FILES_WINDOWS
));
499 sysctl_max
= MIN_OPEN_FILES_WINDOWS
;
502 if (rlimit_max
< MIN_OPEN_FILES_WINDOWS
) {
503 DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to "
504 "minimum Windows limit (%d)\n",
506 MIN_OPEN_FILES_WINDOWS
));
507 rlimit_max
= MIN_OPEN_FILES_WINDOWS
;
510 return MIN(sysctl_max
, rlimit_max
);
514 * Common part of freeing allocated data for one parameter.
516 static void free_one_parameter_common(void *parm_ptr
,
517 struct parm_struct parm
)
519 if ((parm
.type
== P_STRING
) ||
520 (parm
.type
== P_USTRING
))
522 string_free((char**)parm_ptr
);
523 } else if (parm
.type
== P_LIST
) {
524 TALLOC_FREE(*((char***)parm_ptr
));
529 * Free the allocated data for one parameter for a share
530 * given as a service struct.
532 static void free_one_parameter(struct loadparm_service
*service
,
533 struct parm_struct parm
)
537 if (parm
.p_class
!= P_LOCAL
) {
541 parm_ptr
= lp_parm_ptr(service
, &parm
);
543 free_one_parameter_common(parm_ptr
, parm
);
547 * Free the allocated parameter data of a share given
548 * as a service struct.
550 static void free_parameters(struct loadparm_service
*service
)
554 for (i
=0; parm_table
[i
].label
; i
++) {
555 free_one_parameter(service
, parm_table
[i
]);
560 * Free the allocated data for one parameter for a given share
561 * specified by an snum.
563 static void free_one_parameter_by_snum(int snum
, struct parm_struct parm
)
568 parm_ptr
= lp_parm_ptr(NULL
, &parm
);
569 } else if (parm
.p_class
!= P_LOCAL
) {
572 parm_ptr
= lp_local_ptr_by_snum(snum
, &parm
);
575 free_one_parameter_common(parm_ptr
, parm
);
579 * Free the allocated parameter data for a share specified
582 static void free_parameters_by_snum(int snum
)
586 for (i
=0; parm_table
[i
].label
; i
++) {
587 free_one_parameter_by_snum(snum
, parm_table
[i
]);
592 * Free the allocated global parameters.
594 static void free_global_parameters(void)
596 free_param_opts(&Globals
.param_opt
);
597 free_parameters_by_snum(GLOBAL_SECTION_SNUM
);
600 static int map_parameter(const char *pszParmName
);
602 struct lp_stored_option
{
603 struct lp_stored_option
*prev
, *next
;
608 static struct lp_stored_option
*stored_options
;
611 save options set by lp_set_cmdline() into a list. This list is
612 re-applied when we do a globals reset, so that cmdline set options
613 are sticky across reloads of smb.conf
615 static bool store_lp_set_cmdline(const char *pszParmName
, const char *pszParmValue
)
617 struct lp_stored_option
*entry
, *entry_next
;
618 for (entry
= stored_options
; entry
!= NULL
; entry
= entry_next
) {
619 entry_next
= entry
->next
;
620 if (strcmp(pszParmName
, entry
->label
) == 0) {
621 DLIST_REMOVE(stored_options
, entry
);
627 entry
= talloc(NULL
, struct lp_stored_option
);
632 entry
->label
= talloc_strdup(entry
, pszParmName
);
638 entry
->value
= talloc_strdup(entry
, pszParmValue
);
644 DLIST_ADD_END(stored_options
, entry
, struct lp_stored_option
);
649 static bool apply_lp_set_cmdline(void)
651 struct lp_stored_option
*entry
= NULL
;
652 for (entry
= stored_options
; entry
!= NULL
; entry
= entry
->next
) {
653 if (!lp_set_cmdline_helper(entry
->label
, entry
->value
, false)) {
654 DEBUG(0, ("Failed to re-apply cmdline parameter %s = %s\n",
655 entry
->label
, entry
->value
));
662 /***************************************************************************
663 Initialise the global parameter structure.
664 ***************************************************************************/
666 static void init_globals(bool reinit_globals
)
668 static bool done_init
= false;
672 /* If requested to initialize only once and we've already done it... */
673 if (!reinit_globals
&& done_init
) {
674 /* ... then we have nothing more to do */
679 /* The logfile can be set before this is invoked. Free it if so. */
680 if (Globals
.logfile
!= NULL
) {
681 string_free(&Globals
.logfile
);
682 Globals
.logfile
= NULL
;
686 free_global_parameters();
689 /* This memset and the free_global_parameters() above will
690 * wipe out smb.conf options set with lp_set_cmdline(). The
691 * apply_lp_set_cmdline() call puts these values back in the
692 * table once the defaults are set */
693 ZERO_STRUCT(Globals
);
695 for (i
= 0; parm_table
[i
].label
; i
++) {
696 if ((parm_table
[i
].type
== P_STRING
||
697 parm_table
[i
].type
== P_USTRING
))
699 string_set((char **)lp_parm_ptr(NULL
, &parm_table
[i
]), "");
704 string_set(&sDefault
.fstype
, FSTYPE_STRING
);
705 string_set(&sDefault
.szPrintjobUsername
, "%U");
707 init_printer_values(&sDefault
);
710 DEBUG(3, ("Initialising global parameters\n"));
712 /* Must manually force to upper case here, as this does not go via the handler */
713 string_set(&Globals
.szNetbiosName
, myhostname_upper());
715 string_set(&Globals
.szSMBPasswdFile
, get_dyn_SMB_PASSWD_FILE());
716 string_set(&Globals
.szPrivateDir
, get_dyn_PRIVATE_DIR());
718 /* use the new 'hash2' method by default, with a prefix of 1 */
719 string_set(&Globals
.szManglingMethod
, "hash2");
720 Globals
.mangle_prefix
= 1;
722 string_set(&Globals
.szGuestaccount
, GUEST_ACCOUNT
);
724 /* using UTF8 by default allows us to support all chars */
725 string_set(&Globals
.unix_charset
, DEFAULT_UNIX_CHARSET
);
727 /* Use codepage 850 as a default for the dos character set */
728 string_set(&Globals
.dos_charset
, DEFAULT_DOS_CHARSET
);
731 * Allow the default PASSWD_CHAT to be overridden in local.h.
733 string_set(&Globals
.szPasswdChat
, DEFAULT_PASSWD_CHAT
);
735 string_set(&Globals
.szWorkgroup
, DEFAULT_WORKGROUP
);
737 string_set(&Globals
.szPasswdProgram
, "");
738 string_set(&Globals
.szLockDir
, get_dyn_LOCKDIR());
739 string_set(&Globals
.szStateDir
, get_dyn_STATEDIR());
740 string_set(&Globals
.szCacheDir
, get_dyn_CACHEDIR());
741 string_set(&Globals
.szPidDir
, get_dyn_PIDDIR());
742 string_set(&Globals
.szSocketAddress
, "0.0.0.0");
744 * By default support explicit binding to broadcast
747 Globals
.bNmbdBindExplicitBroadcast
= true;
749 if (asprintf(&s
, "Samba %s", samba_version_string()) < 0) {
750 smb_panic("init_globals: ENOMEM");
752 string_set(&Globals
.szServerString
, s
);
755 string_set(&Globals
.szPanicAction
, "/bin/sleep 999999999");
758 string_set(&Globals
.socket_options
, DEFAULT_SOCKET_OPTIONS
);
760 string_set(&Globals
.szLogonDrive
, "");
761 /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
762 string_set(&Globals
.szLogonHome
, "\\\\%N\\%U");
763 string_set(&Globals
.szLogonPath
, "\\\\%N\\%U\\profile");
765 Globals
.szNameResolveOrder
= (const char **)str_list_make_v3(NULL
, "lmhosts wins host bcast", NULL
);
766 string_set(&Globals
.szPasswordServer
, "*");
768 Globals
.AlgorithmicRidBase
= BASE_RID
;
770 Globals
.bLoadPrinters
= true;
771 Globals
.PrintcapCacheTime
= 750; /* 12.5 minutes */
773 Globals
.ConfigBackend
= config_backend
;
774 Globals
.server_role
= ROLE_AUTO
;
776 /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
777 /* Discovered by 2 days of pain by Don McCall @ HP :-). */
778 Globals
.max_xmit
= 0x4104;
779 Globals
.max_mux
= 50; /* This is *needed* for profile support. */
780 Globals
.lpqcachetime
= 30; /* changed to handle large print servers better -- jerry */
781 Globals
.bDisableSpoolss
= false;
782 Globals
.iMaxSmbdProcesses
= 0;/* no limit specified */
783 Globals
.pwordlevel
= 0;
784 Globals
.unamelevel
= 0;
785 Globals
.deadtime
= 0;
786 Globals
.getwd_cache
= true;
787 Globals
.bLargeReadwrite
= true;
788 Globals
.max_log_size
= 5000;
789 Globals
.max_open_files
= max_open_files();
790 Globals
.open_files_db_hash_size
= SMB_OPEN_DATABASE_TDB_HASH_SIZE
;
791 Globals
.srv_maxprotocol
= PROTOCOL_SMB2_10
;
792 Globals
.srv_minprotocol
= PROTOCOL_LANMAN1
;
793 Globals
.security
= SEC_USER
;
794 Globals
.paranoid_server_security
= true;
795 Globals
.bEncryptPasswords
= true;
796 Globals
.clientSchannel
= Auto
;
797 Globals
.serverSchannel
= Auto
;
798 Globals
.bReadRaw
= true;
799 Globals
.bWriteRaw
= true;
800 Globals
.bNullPasswords
= false;
801 Globals
.bObeyPamRestrictions
= false;
803 Globals
.bSyslogOnly
= false;
804 Globals
.bTimestampLogs
= true;
805 string_set(&Globals
.loglevel
, "0");
806 Globals
.bDebugPrefixTimestamp
= false;
807 Globals
.bDebugHiresTimestamp
= true;
808 Globals
.bDebugPid
= false;
809 Globals
.bDebugUid
= false;
810 Globals
.bDebugClass
= false;
811 Globals
.bEnableCoreFiles
= true;
812 Globals
.max_ttl
= 60 * 60 * 24 * 3; /* 3 days default. */
813 Globals
.max_wins_ttl
= 60 * 60 * 24 * 6; /* 6 days default. */
814 Globals
.min_wins_ttl
= 60 * 60 * 6; /* 6 hours default. */
815 Globals
.machine_password_timeout
= 60 * 60 * 24 * 7; /* 7 days default. */
816 Globals
.lm_announce
= Auto
; /* = Auto: send only if LM clients found */
817 Globals
.lm_interval
= 60;
818 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
819 Globals
.bNISHomeMap
= false;
820 #ifdef WITH_NISPLUS_HOME
821 string_set(&Globals
.szNISHomeMapName
, "auto_home.org_dir");
823 string_set(&Globals
.szNISHomeMapName
, "auto.home");
826 Globals
.bTimeServer
= false;
827 Globals
.bBindInterfacesOnly
= false;
828 Globals
.bUnixPasswdSync
= false;
829 Globals
.bPamPasswordChange
= false;
830 Globals
.bPasswdChatDebug
= false;
831 Globals
.iPasswdChatTimeout
= 2; /* 2 second default. */
832 Globals
.bNTPipeSupport
= true; /* Do NT pipes by default. */
833 Globals
.bNTStatusSupport
= true; /* Use NT status by default. */
834 Globals
.bStatCache
= true; /* use stat cache by default */
835 Globals
.iMaxStatCacheSize
= 256; /* 256k by default */
836 Globals
.restrict_anonymous
= 0;
837 Globals
.bClientLanManAuth
= false; /* Do NOT use the LanMan hash if it is available */
838 Globals
.bClientPlaintextAuth
= false; /* Do NOT use a plaintext password even if is requested by the server */
839 Globals
.bLanmanAuth
= false; /* Do NOT use the LanMan hash, even if it is supplied */
840 Globals
.bNTLMAuth
= true; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
841 Globals
.bClientNTLMv2Auth
= true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
842 /* Note, that we will also use NTLM2 session security (which is different), if it is available */
844 Globals
.map_to_guest
= 0; /* By Default, "Never" */
845 Globals
.oplock_break_wait_time
= 0; /* By Default, 0 msecs. */
846 Globals
.enhanced_browsing
= true;
847 Globals
.iLockSpinTime
= WINDOWS_MINIMUM_LOCK_TIMEOUT_MS
; /* msec. */
848 #ifdef MMAP_BLACKLIST
849 Globals
.bUseMmap
= false;
851 Globals
.bUseMmap
= true;
853 Globals
.bUnicode
= true;
854 Globals
.bUnixExtensions
= true;
855 Globals
.bResetOnZeroVC
= false;
856 Globals
.bLogWriteableFilesOnExit
= false;
857 Globals
.bCreateKrb5Conf
= true;
858 Globals
.winbindMaxDomainConnections
= 1;
860 /* hostname lookups can be very expensive and are broken on
861 a large number of sites (tridge) */
862 Globals
.bHostnameLookups
= false;
864 string_set(&Globals
.passdb_backend
, "tdbsam");
865 string_set(&Globals
.szLdapSuffix
, "");
866 string_set(&Globals
.szLdapMachineSuffix
, "");
867 string_set(&Globals
.szLdapUserSuffix
, "");
868 string_set(&Globals
.szLdapGroupSuffix
, "");
869 string_set(&Globals
.szLdapIdmapSuffix
, "");
871 string_set(&Globals
.szLdapAdminDn
, "");
872 Globals
.ldap_ssl
= LDAP_SSL_START_TLS
;
873 Globals
.ldap_ssl_ads
= false;
874 Globals
.ldap_deref
= -1;
875 Globals
.ldap_passwd_sync
= LDAP_PASSWD_SYNC_OFF
;
876 Globals
.ldap_delete_dn
= false;
877 Globals
.ldap_replication_sleep
= 1000; /* wait 1 sec for replication */
878 Globals
.ldap_follow_referral
= Auto
;
879 Globals
.ldap_timeout
= LDAP_DEFAULT_TIMEOUT
;
880 Globals
.ldap_connection_timeout
= LDAP_CONNECTION_DEFAULT_TIMEOUT
;
881 Globals
.ldap_page_size
= LDAP_PAGE_SIZE
;
883 Globals
.ldap_debug_level
= 0;
884 Globals
.ldap_debug_threshold
= 10;
886 /* This is what we tell the afs client. in reality we set the token
887 * to never expire, though, when this runs out the afs client will
888 * forget the token. Set to 0 to get NEVERDATE.*/
889 Globals
.iAfsTokenLifetime
= 604800;
890 Globals
.cups_connection_timeout
= CUPS_DEFAULT_CONNECTION_TIMEOUT
;
892 /* these parameters are set to defaults that are more appropriate
893 for the increasing samba install base:
895 as a member of the workgroup, that will possibly become a
896 _local_ master browser (lm = true). this is opposed to a forced
897 local master browser startup (pm = true).
899 doesn't provide WINS server service by default (wsupp = false),
900 and doesn't provide domain master browser services by default, either.
904 Globals
.bMsAddPrinterWizard
= true;
905 Globals
.os_level
= 20;
906 Globals
.bLocalMaster
= true;
907 Globals
.domain_master
= Auto
; /* depending on bDomainLogons */
908 Globals
.bDomainLogons
= false;
909 Globals
.bBrowseList
= true;
910 Globals
.bWINSsupport
= false;
911 Globals
.bWINSproxy
= false;
913 TALLOC_FREE(Globals
.szInitLogonDelayedHosts
);
914 Globals
.InitLogonDelay
= 100; /* 100 ms default delay */
916 Globals
.bWINSdnsProxy
= true;
918 Globals
.bAllowTrustedDomains
= true;
919 string_set(&Globals
.szIdmapBackend
, "tdb");
921 string_set(&Globals
.szTemplateShell
, "/bin/false");
922 string_set(&Globals
.szTemplateHomedir
, "/home/%D/%U");
923 string_set(&Globals
.szWinbindSeparator
, "\\");
925 string_set(&Globals
.szCupsServer
, "");
926 string_set(&Globals
.szIPrintServer
, "");
928 #ifdef CLUSTER_SUPPORT
929 string_set(&Globals
.ctdbdSocket
, CTDB_PATH
);
931 string_set(&Globals
.ctdbdSocket
, "");
934 Globals
.szClusterAddresses
= NULL
;
935 Globals
.clustering
= false;
936 Globals
.ctdb_timeout
= 0;
937 Globals
.ctdb_locktime_warn_threshold
= 0;
939 Globals
.winbind_cache_time
= 300; /* 5 minutes */
940 Globals
.winbind_reconnect_delay
= 30; /* 30 seconds */
941 Globals
.winbind_max_clients
= 200;
942 Globals
.bWinbindEnumUsers
= false;
943 Globals
.bWinbindEnumGroups
= false;
944 Globals
.bWinbindUseDefaultDomain
= false;
945 Globals
.bWinbindTrustedDomainsOnly
= false;
946 Globals
.bWinbindNestedGroups
= true;
947 Globals
.winbind_expand_groups
= 1;
948 Globals
.szWinbindNssInfo
= (const char **)str_list_make_v3(NULL
, "template", NULL
);
949 Globals
.bWinbindRefreshTickets
= false;
950 Globals
.bWinbindOfflineLogon
= false;
952 Globals
.iIdmapCacheTime
= 86400 * 7; /* a week by default */
953 Globals
.iIdmapNegativeCacheTime
= 120; /* 2 minutes by default */
955 Globals
.bPassdbExpandExplicit
= false;
957 Globals
.name_cache_timeout
= 660; /* In seconds */
959 Globals
.bUseSpnego
= true;
960 Globals
.bClientUseSpnego
= true;
962 Globals
.client_signing
= SMB_SIGNING_DEFAULT
;
963 Globals
.server_signing
= SMB_SIGNING_DEFAULT
;
965 Globals
.bDeferSharingViolations
= true;
966 Globals
.smb_ports
= (const char **)str_list_make_v3(NULL
, SMB_PORTS
, NULL
);
968 Globals
.bEnablePrivileges
= true;
969 Globals
.bHostMSDfs
= true;
970 Globals
.bASUSupport
= false;
972 /* User defined shares. */
973 if (asprintf(&s
, "%s/usershares", get_dyn_STATEDIR()) < 0) {
974 smb_panic("init_globals: ENOMEM");
976 string_set(&Globals
.szUsersharePath
, s
);
978 string_set(&Globals
.szUsershareTemplateShare
, "");
979 Globals
.iUsershareMaxShares
= 0;
980 /* By default disallow sharing of directories not owned by the sharer. */
981 Globals
.bUsershareOwnerOnly
= true;
982 /* By default disallow guest access to usershares. */
983 Globals
.bUsershareAllowGuests
= false;
985 Globals
.iKeepalive
= DEFAULT_KEEPALIVE
;
987 /* By default no shares out of the registry */
988 Globals
.bRegistryShares
= false;
990 Globals
.iminreceivefile
= 0;
992 Globals
.bMapUntrustedToDomain
= false;
993 Globals
.bMulticastDnsRegister
= true;
995 Globals
.ismb2_max_read
= DEFAULT_SMB2_MAX_READ
;
996 Globals
.ismb2_max_write
= DEFAULT_SMB2_MAX_WRITE
;
997 Globals
.ismb2_max_trans
= DEFAULT_SMB2_MAX_TRANSACT
;
998 Globals
.ismb2_max_credits
= DEFAULT_SMB2_MAX_CREDITS
;
1000 string_set(&Globals
.ncalrpc_dir
, get_dyn_NCALRPCDIR());
1002 /* Now put back the settings that were set with lp_set_cmdline() */
1003 apply_lp_set_cmdline();
1006 /*******************************************************************
1007 Convenience routine to grab string parameters into talloced memory
1008 and run standard_sub_basic on them. The buffers can be written to by
1009 callers without affecting the source string.
1010 ********************************************************************/
1012 static char *lp_string(TALLOC_CTX
*ctx
, const char *s
)
1016 /* The follow debug is useful for tracking down memory problems
1017 especially if you have an inner loop that is calling a lp_*()
1018 function that returns a string. Perhaps this debug should be
1019 present all the time? */
1022 DEBUG(10, ("lp_string(%s)\n", s
));
1028 ret
= talloc_sub_basic(ctx
,
1029 get_current_username(),
1030 current_user_info
.domain
,
1032 if (trim_char(ret
, '\"', '\"')) {
1033 if (strchr(ret
,'\"') != NULL
) {
1035 ret
= talloc_sub_basic(ctx
,
1036 get_current_username(),
1037 current_user_info
.domain
,
1045 In this section all the functions that are used to access the
1046 parameters from the rest of the program are defined
1049 #define FN_GLOBAL_STRING(fn_name,ptr) \
1050 char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
1051 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
1052 const char *lp_ ## fn_name(void) {return(*(const char **)(&Globals.ptr) ? *(const char **)(&Globals.ptr) : "");}
1053 #define FN_GLOBAL_LIST(fn_name,ptr) \
1054 const char **lp_ ## fn_name(void) {return(*(const char ***)(&Globals.ptr));}
1055 #define FN_GLOBAL_BOOL(fn_name,ptr) \
1056 bool lp_ ## fn_name(void) {return(*(bool *)(&Globals.ptr));}
1057 #define FN_GLOBAL_CHAR(fn_name,ptr) \
1058 char lp_ ## fn_name(void) {return(*(char *)(&Globals.ptr));}
1059 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
1060 int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
1062 #define FN_LOCAL_STRING(fn_name,val) \
1063 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));}
1064 #define FN_LOCAL_CONST_STRING(fn_name,val) \
1065 const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
1066 #define FN_LOCAL_LIST(fn_name,val) \
1067 const char **lp_ ## fn_name(int i) {return(const char **)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1068 #define FN_LOCAL_BOOL(fn_name,val) \
1069 bool lp_ ## fn_name(int i) {return(bool)(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1070 #define FN_LOCAL_INTEGER(fn_name,val) \
1071 int lp_ ## fn_name(int i) {return(LP_SNUM_OK(i)? ServicePtrs[(i)]->val : sDefault.val);}
1073 #define FN_LOCAL_PARM_BOOL(fn_name,val) \
1074 bool lp_ ## fn_name(const struct share_params *p) {return(bool)(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1075 #define FN_LOCAL_PARM_INTEGER(fn_name,val) \
1076 int lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1077 #define FN_LOCAL_CHAR(fn_name,val) \
1078 char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
1081 static FN_GLOBAL_BOOL(_readraw
, bReadRaw
)
1082 static FN_GLOBAL_BOOL(_writeraw
, bWriteRaw
)
1084 /* If lp_statedir() and lp_cachedir() are explicitely set during the
1085 * build process or in smb.conf, we use that value. Otherwise they
1086 * default to the value of lp_lockdir(). */
1087 const char *lp_statedir(void) {
1088 if ((strcmp(get_dyn_STATEDIR(), get_dyn_LOCKDIR()) != 0) ||
1089 (strcmp(get_dyn_STATEDIR(), Globals
.szStateDir
) != 0))
1090 return(*(char **)(&Globals
.szStateDir
) ?
1091 *(char **)(&Globals
.szStateDir
) : "");
1093 return(*(char **)(&Globals
.szLockDir
) ?
1094 *(char **)(&Globals
.szLockDir
) : "");
1096 const char *lp_cachedir(void) {
1097 if ((strcmp(get_dyn_CACHEDIR(), get_dyn_LOCKDIR()) != 0) ||
1098 (strcmp(get_dyn_CACHEDIR(), Globals
.szCacheDir
) != 0))
1099 return(*(char **)(&Globals
.szCacheDir
) ?
1100 *(char **)(&Globals
.szCacheDir
) : "");
1102 return(*(char **)(&Globals
.szLockDir
) ?
1103 *(char **)(&Globals
.szLockDir
) : "");
1105 static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int
,
1106 winbindMaxDomainConnections
)
1108 int lp_winbind_max_domain_connections(void)
1110 if (lp_winbind_offline_logon() &&
1111 lp_winbind_max_domain_connections_int() > 1) {
1112 DEBUG(1, ("offline logons active, restricting max domain "
1113 "connections to 1\n"));
1116 return MAX(1, lp_winbind_max_domain_connections_int());
1119 int lp_smb2_max_credits(void)
1121 if (Globals
.ismb2_max_credits
== 0) {
1122 Globals
.ismb2_max_credits
= DEFAULT_SMB2_MAX_CREDITS
;
1124 return Globals
.ismb2_max_credits
;
1126 int lp_cups_encrypt(void)
1129 #ifdef HAVE_HTTPCONNECTENCRYPT
1130 switch (Globals
.CupsEncrypt
) {
1132 result
= HTTP_ENCRYPT_REQUIRED
;
1135 result
= HTTP_ENCRYPT_ALWAYS
;
1138 result
= HTTP_ENCRYPT_NEVER
;
1145 /* These functions remain in source3/param for now */
1147 FN_GLOBAL_STRING(configfile
, szConfigFile
)
1149 #include "lib/param/param_functions.c"
1151 FN_LOCAL_STRING(servicename
, szService
)
1152 FN_LOCAL_CONST_STRING(const_servicename
, szService
)
1154 /* local prototypes */
1156 static int map_parameter_canonical(const char *pszParmName
, bool *inverse
);
1157 static const char *get_boolean(bool bool_value
);
1158 static int getservicebyname(const char *pszServiceName
,
1159 struct loadparm_service
*pserviceDest
);
1160 static void copy_service(struct loadparm_service
*pserviceDest
,
1161 struct loadparm_service
*pserviceSource
,
1162 struct bitmap
*pcopymapDest
);
1163 static bool do_parameter(const char *pszParmName
, const char *pszParmValue
,
1165 static bool do_section(const char *pszSectionName
, void *userdata
);
1166 static void init_copymap(struct loadparm_service
*pservice
);
1167 static bool hash_a_service(const char *name
, int number
);
1168 static void free_service_byindex(int iService
);
1169 static void show_parameter(int parmIndex
);
1170 static bool is_synonym_of(int parm1
, int parm2
, bool *inverse
);
1173 * This is a helper function for parametrical options support. It returns a
1174 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1175 * parametrical functions are quite simple
1177 static struct parmlist_entry
*get_parametrics_by_service(struct loadparm_service
*service
, const char *type
,
1180 bool global_section
= false;
1182 struct parmlist_entry
*data
;
1184 if (service
== NULL
) {
1185 data
= Globals
.param_opt
;
1186 global_section
= true;
1188 data
= service
->param_opt
;
1191 if (asprintf(¶m_key
, "%s:%s", type
, option
) == -1) {
1192 DEBUG(0,("asprintf failed!\n"));
1197 if (strwicmp(data
->key
, param_key
) == 0) {
1198 string_free(¶m_key
);
1204 if (!global_section
) {
1205 /* Try to fetch the same option but from globals */
1206 /* but only if we are not already working with Globals */
1207 data
= Globals
.param_opt
;
1209 if (strwicmp(data
->key
, param_key
) == 0) {
1210 string_free(¶m_key
);
1217 string_free(¶m_key
);
1223 * This is a helper function for parametrical options support. It returns a
1224 * pointer to parametrical option value if it exists or NULL otherwise. Actual
1225 * parametrical functions are quite simple
1227 static struct parmlist_entry
*get_parametrics(int snum
, const char *type
,
1230 if (snum
>= iNumServices
) return NULL
;
1233 return get_parametrics_by_service(NULL
, type
, option
);
1235 return get_parametrics_by_service(ServicePtrs
[snum
], type
, option
);
1240 #define MISSING_PARAMETER(name) \
1241 DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
1243 /*******************************************************************
1244 convenience routine to return int parameters.
1245 ********************************************************************/
1246 static int lp_int(const char *s
)
1250 MISSING_PARAMETER(lp_int
);
1254 return (int)strtol(s
, NULL
, 0);
1257 /*******************************************************************
1258 convenience routine to return unsigned long parameters.
1259 ********************************************************************/
1260 static unsigned long lp_ulong(const char *s
)
1264 MISSING_PARAMETER(lp_ulong
);
1268 return strtoul(s
, NULL
, 0);
1271 /*******************************************************************
1272 convenience routine to return boolean parameters.
1273 ********************************************************************/
1274 static bool lp_bool(const char *s
)
1279 MISSING_PARAMETER(lp_bool
);
1283 if (!set_boolean(s
, &ret
)) {
1284 DEBUG(0,("lp_bool(%s): value is not boolean!\n",s
));
1291 /*******************************************************************
1292 convenience routine to return enum parameters.
1293 ********************************************************************/
1294 static int lp_enum(const char *s
,const struct enum_list
*_enum
)
1298 if (!s
|| !*s
|| !_enum
) {
1299 MISSING_PARAMETER(lp_enum
);
1303 for (i
=0; _enum
[i
].name
; i
++) {
1304 if (strequal(_enum
[i
].name
,s
))
1305 return _enum
[i
].value
;
1308 DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s
));
1312 #undef MISSING_PARAMETER
1314 /* Return parametric option from a given service. Type is a part of option before ':' */
1315 /* Parametric option has following syntax: 'Type: option = value' */
1316 char *lp_parm_talloc_string(TALLOC_CTX
*ctx
, int snum
, const char *type
, const char *option
, const char *def
)
1318 struct parmlist_entry
*data
= get_parametrics(snum
, type
, option
);
1320 if (data
== NULL
||data
->value
==NULL
) {
1322 return lp_string(ctx
, def
);
1328 return lp_string(ctx
, data
->value
);
1331 /* Return parametric option from a given service. Type is a part of option before ':' */
1332 /* Parametric option has following syntax: 'Type: option = value' */
1333 const char *lp_parm_const_string(int snum
, const char *type
, const char *option
, const char *def
)
1335 struct parmlist_entry
*data
= get_parametrics(snum
, type
, option
);
1337 if (data
== NULL
||data
->value
==NULL
)
1343 const char *lp_parm_const_string_service(struct loadparm_service
*service
, const char *type
, const char *option
)
1345 struct parmlist_entry
*data
= get_parametrics_by_service(service
, type
, option
);
1347 if (data
== NULL
||data
->value
==NULL
)
1354 /* Return parametric option from a given service. Type is a part of option before ':' */
1355 /* Parametric option has following syntax: 'Type: option = value' */
1357 const char **lp_parm_string_list(int snum
, const char *type
, const char *option
, const char **def
)
1359 struct parmlist_entry
*data
= get_parametrics(snum
, type
, option
);
1361 if (data
== NULL
||data
->value
==NULL
)
1362 return (const char **)def
;
1364 if (data
->list
==NULL
) {
1365 data
->list
= str_list_make_v3(NULL
, data
->value
, NULL
);
1368 return (const char **)data
->list
;
1371 /* Return parametric option from a given service. Type is a part of option before ':' */
1372 /* Parametric option has following syntax: 'Type: option = value' */
1374 int lp_parm_int(int snum
, const char *type
, const char *option
, int def
)
1376 struct parmlist_entry
*data
= get_parametrics(snum
, type
, option
);
1378 if (data
&& data
->value
&& *data
->value
)
1379 return lp_int(data
->value
);
1384 /* Return parametric option from a given service. Type is a part of option before ':' */
1385 /* Parametric option has following syntax: 'Type: option = value' */
1387 unsigned long lp_parm_ulong(int snum
, const char *type
, const char *option
, unsigned long def
)
1389 struct parmlist_entry
*data
= get_parametrics(snum
, type
, option
);
1391 if (data
&& data
->value
&& *data
->value
)
1392 return lp_ulong(data
->value
);
1397 /* Return parametric option from a given service. Type is a part of option before ':' */
1398 /* Parametric option has following syntax: 'Type: option = value' */
1400 bool lp_parm_bool(int snum
, const char *type
, const char *option
, bool def
)
1402 struct parmlist_entry
*data
= get_parametrics(snum
, type
, option
);
1404 if (data
&& data
->value
&& *data
->value
)
1405 return lp_bool(data
->value
);
1410 /* Return parametric option from a given service. Type is a part of option before ':' */
1411 /* Parametric option has following syntax: 'Type: option = value' */
1413 int lp_parm_enum(int snum
, const char *type
, const char *option
,
1414 const struct enum_list
*_enum
, int def
)
1416 struct parmlist_entry
*data
= get_parametrics(snum
, type
, option
);
1418 if (data
&& data
->value
&& *data
->value
&& _enum
)
1419 return lp_enum(data
->value
, _enum
);
1425 /***************************************************************************
1426 Initialise a service to the defaults.
1427 ***************************************************************************/
1429 static void init_service(struct loadparm_service
*pservice
)
1431 memset((char *)pservice
, '\0', sizeof(struct loadparm_service
));
1432 copy_service(pservice
, &sDefault
, NULL
);
1437 * free a param_opts structure.
1438 * param_opts handling should be moved to talloc;
1439 * then this whole functions reduces to a TALLOC_FREE().
1442 static void free_param_opts(struct parmlist_entry
**popts
)
1444 struct parmlist_entry
*opt
, *next_opt
;
1446 if (popts
== NULL
) {
1450 if (*popts
!= NULL
) {
1451 DEBUG(5, ("Freeing parametrics:\n"));
1454 while (opt
!= NULL
) {
1455 string_free(&opt
->key
);
1456 string_free(&opt
->value
);
1457 TALLOC_FREE(opt
->list
);
1458 next_opt
= opt
->next
;
1465 /***************************************************************************
1466 Free the dynamically allocated parts of a service struct.
1467 ***************************************************************************/
1469 static void free_service(struct loadparm_service
*pservice
)
1474 if (pservice
->szService
)
1475 DEBUG(5, ("free_service: Freeing service %s\n",
1476 pservice
->szService
));
1478 free_parameters(pservice
);
1480 string_free(&pservice
->szService
);
1481 TALLOC_FREE(pservice
->copymap
);
1483 free_param_opts(&pservice
->param_opt
);
1485 ZERO_STRUCTP(pservice
);
1489 /***************************************************************************
1490 remove a service indexed in the ServicePtrs array from the ServiceHash
1491 and free the dynamically allocated parts
1492 ***************************************************************************/
1494 static void free_service_byindex(int idx
)
1496 if ( !LP_SNUM_OK(idx
) )
1499 ServicePtrs
[idx
]->valid
= false;
1500 invalid_services
[num_invalid_services
++] = idx
;
1502 /* we have to cleanup the hash record */
1504 if (ServicePtrs
[idx
]->szService
) {
1505 char *canon_name
= canonicalize_servicename(
1507 ServicePtrs
[idx
]->szService
);
1509 dbwrap_delete_bystring(ServiceHash
, canon_name
);
1510 TALLOC_FREE(canon_name
);
1513 free_service(ServicePtrs
[idx
]);
1516 /***************************************************************************
1517 Add a new service to the services array initialising it with the given
1519 ***************************************************************************/
1521 static int add_a_service(const struct loadparm_service
*pservice
, const char *name
)
1524 struct loadparm_service tservice
;
1525 int num_to_alloc
= iNumServices
+ 1;
1527 tservice
= *pservice
;
1529 /* it might already exist */
1531 i
= getservicebyname(name
, NULL
);
1537 /* find an invalid one */
1539 if (num_invalid_services
> 0) {
1540 i
= invalid_services
[--num_invalid_services
];
1543 /* if not, then create one */
1544 if (i
== iNumServices
) {
1545 struct loadparm_service
**tsp
;
1548 tsp
= SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(ServicePtrs
, struct loadparm_service
*, num_to_alloc
);
1550 DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
1554 ServicePtrs
[iNumServices
] = SMB_MALLOC_P(struct loadparm_service
);
1555 if (!ServicePtrs
[iNumServices
]) {
1556 DEBUG(0,("add_a_service: out of memory!\n"));
1561 /* enlarge invalid_services here for now... */
1562 tinvalid
= SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(invalid_services
, int,
1564 if (tinvalid
== NULL
) {
1565 DEBUG(0,("add_a_service: failed to enlarge "
1566 "invalid_services!\n"));
1569 invalid_services
= tinvalid
;
1571 free_service_byindex(i
);
1574 ServicePtrs
[i
]->valid
= true;
1576 init_service(ServicePtrs
[i
]);
1577 copy_service(ServicePtrs
[i
], &tservice
, NULL
);
1579 string_set(&ServicePtrs
[i
]->szService
, name
);
1581 DEBUG(8,("add_a_service: Creating snum = %d for %s\n",
1582 i
, ServicePtrs
[i
]->szService
));
1584 if (!hash_a_service(ServicePtrs
[i
]->szService
, i
)) {
1591 /***************************************************************************
1592 Convert a string to uppercase and remove whitespaces.
1593 ***************************************************************************/
1595 char *canonicalize_servicename(TALLOC_CTX
*ctx
, const char *src
)
1600 DEBUG(0,("canonicalize_servicename: NULL source name!\n"));
1604 result
= talloc_strdup(ctx
, src
);
1605 SMB_ASSERT(result
!= NULL
);
1611 /***************************************************************************
1612 Add a name/index pair for the services array to the hash table.
1613 ***************************************************************************/
1615 static bool hash_a_service(const char *name
, int idx
)
1619 if ( !ServiceHash
) {
1620 DEBUG(10,("hash_a_service: creating servicehash\n"));
1621 ServiceHash
= db_open_rbt(NULL
);
1622 if ( !ServiceHash
) {
1623 DEBUG(0,("hash_a_service: open tdb servicehash failed!\n"));
1628 DEBUG(10,("hash_a_service: hashing index %d for service name %s\n",
1631 canon_name
= canonicalize_servicename(talloc_tos(), name
);
1633 dbwrap_store_bystring(ServiceHash
, canon_name
,
1634 make_tdb_data((uint8
*)&idx
, sizeof(idx
)),
1637 TALLOC_FREE(canon_name
);
1642 /***************************************************************************
1643 Add a new home service, with the specified home directory, defaults coming
1645 ***************************************************************************/
1647 bool lp_add_home(const char *pszHomename
, int iDefaultService
,
1648 const char *user
, const char *pszHomedir
)
1652 if (pszHomename
== NULL
|| user
== NULL
|| pszHomedir
== NULL
||
1653 pszHomedir
[0] == '\0') {
1657 i
= add_a_service(ServicePtrs
[iDefaultService
], pszHomename
);
1662 if (!(*(ServicePtrs
[iDefaultService
]->szPath
))
1663 || strequal(ServicePtrs
[iDefaultService
]->szPath
,
1664 lp_pathname(talloc_tos(), GLOBAL_SECTION_SNUM
))) {
1665 string_set(&ServicePtrs
[i
]->szPath
, pszHomedir
);
1668 if (!(*(ServicePtrs
[i
]->comment
))) {
1669 char *comment
= NULL
;
1670 if (asprintf(&comment
, "Home directory of %s", user
) < 0) {
1673 string_set(&ServicePtrs
[i
]->comment
, comment
);
1677 /* set the browseable flag from the global default */
1679 ServicePtrs
[i
]->bBrowseable
= sDefault
.bBrowseable
;
1680 ServicePtrs
[i
]->bAccessBasedShareEnum
= sDefault
.bAccessBasedShareEnum
;
1682 ServicePtrs
[i
]->autoloaded
= true;
1684 DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename
,
1685 user
, ServicePtrs
[i
]->szPath
));
1690 /***************************************************************************
1691 Add a new service, based on an old one.
1692 ***************************************************************************/
1694 int lp_add_service(const char *pszService
, int iDefaultService
)
1696 if (iDefaultService
< 0) {
1697 return add_a_service(&sDefault
, pszService
);
1700 return (add_a_service(ServicePtrs
[iDefaultService
], pszService
));
1703 /***************************************************************************
1704 Add the IPC service.
1705 ***************************************************************************/
1707 static bool lp_add_ipc(const char *ipc_name
, bool guest_ok
)
1709 char *comment
= NULL
;
1710 int i
= add_a_service(&sDefault
, ipc_name
);
1715 if (asprintf(&comment
, "IPC Service (%s)",
1716 Globals
.szServerString
) < 0) {
1720 string_set(&ServicePtrs
[i
]->szPath
, tmpdir());
1721 string_set(&ServicePtrs
[i
]->szUsername
, "");
1722 string_set(&ServicePtrs
[i
]->comment
, comment
);
1723 string_set(&ServicePtrs
[i
]->fstype
, "IPC");
1724 ServicePtrs
[i
]->iMaxConnections
= 0;
1725 ServicePtrs
[i
]->bAvailable
= true;
1726 ServicePtrs
[i
]->bRead_only
= true;
1727 ServicePtrs
[i
]->bGuest_only
= false;
1728 ServicePtrs
[i
]->bAdministrative_share
= true;
1729 ServicePtrs
[i
]->bGuest_ok
= guest_ok
;
1730 ServicePtrs
[i
]->bPrint_ok
= false;
1731 ServicePtrs
[i
]->bBrowseable
= sDefault
.bBrowseable
;
1733 DEBUG(3, ("adding IPC service\n"));
1739 /***************************************************************************
1740 Add a new printer service, with defaults coming from service iFrom.
1741 ***************************************************************************/
1743 bool lp_add_printer(const char *pszPrintername
, int iDefaultService
)
1745 const char *comment
= "From Printcap";
1746 int i
= add_a_service(ServicePtrs
[iDefaultService
], pszPrintername
);
1751 /* note that we do NOT default the availability flag to true - */
1752 /* we take it from the default service passed. This allows all */
1753 /* dynamic printers to be disabled by disabling the [printers] */
1754 /* entry (if/when the 'available' keyword is implemented!). */
1756 /* the printer name is set to the service name. */
1757 string_set(&ServicePtrs
[i
]->szPrintername
, pszPrintername
);
1758 string_set(&ServicePtrs
[i
]->comment
, comment
);
1760 /* set the browseable flag from the gloabl default */
1761 ServicePtrs
[i
]->bBrowseable
= sDefault
.bBrowseable
;
1763 /* Printers cannot be read_only. */
1764 ServicePtrs
[i
]->bRead_only
= false;
1765 /* No share modes on printer services. */
1766 ServicePtrs
[i
]->bShareModes
= false;
1767 /* No oplocks on printer services. */
1768 ServicePtrs
[i
]->bOpLocks
= false;
1769 /* Printer services must be printable. */
1770 ServicePtrs
[i
]->bPrint_ok
= true;
1772 DEBUG(3, ("adding printer service %s\n", pszPrintername
));
1778 /***************************************************************************
1779 Check whether the given parameter name is valid.
1780 Parametric options (names containing a colon) are considered valid.
1781 ***************************************************************************/
1783 bool lp_parameter_is_valid(const char *pszParmName
)
1785 return ((map_parameter(pszParmName
) != -1) ||
1786 (strchr(pszParmName
, ':') != NULL
));
1789 /***************************************************************************
1790 Check whether the given name is the name of a global parameter.
1791 Returns true for strings belonging to parameters of class
1792 P_GLOBAL, false for all other strings, also for parametric options
1793 and strings not belonging to any option.
1794 ***************************************************************************/
1796 bool lp_parameter_is_global(const char *pszParmName
)
1798 int num
= map_parameter(pszParmName
);
1801 return (parm_table
[num
].p_class
== P_GLOBAL
);
1807 /**************************************************************************
1808 Check whether the given name is the canonical name of a parameter.
1809 Returns false if it is not a valid parameter Name.
1810 For parametric options, true is returned.
1811 **************************************************************************/
1813 bool lp_parameter_is_canonical(const char *parm_name
)
1815 if (!lp_parameter_is_valid(parm_name
)) {
1819 return (map_parameter(parm_name
) ==
1820 map_parameter_canonical(parm_name
, NULL
));
1823 /**************************************************************************
1824 Determine the canonical name for a parameter.
1825 Indicate when it is an inverse (boolean) synonym instead of a
1827 **************************************************************************/
1829 bool lp_canonicalize_parameter(const char *parm_name
, const char **canon_parm
,
1834 if (!lp_parameter_is_valid(parm_name
)) {
1839 num
= map_parameter_canonical(parm_name
, inverse
);
1841 /* parametric option */
1842 *canon_parm
= parm_name
;
1844 *canon_parm
= parm_table
[num
].label
;
1851 /**************************************************************************
1852 Determine the canonical name for a parameter.
1853 Turn the value given into the inverse boolean expression when
1854 the synonym is an invers boolean synonym.
1856 Return true if parm_name is a valid parameter name and
1857 in case it is an invers boolean synonym, if the val string could
1858 successfully be converted to the reverse bool.
1859 Return false in all other cases.
1860 **************************************************************************/
1862 bool lp_canonicalize_parameter_with_value(const char *parm_name
,
1864 const char **canon_parm
,
1865 const char **canon_val
)
1870 if (!lp_parameter_is_valid(parm_name
)) {
1876 num
= map_parameter_canonical(parm_name
, &inverse
);
1878 /* parametric option */
1879 *canon_parm
= parm_name
;
1882 *canon_parm
= parm_table
[num
].label
;
1884 if (!lp_invert_boolean(val
, canon_val
)) {
1896 /***************************************************************************
1897 Map a parameter's string representation to something we can use.
1898 Returns false if the parameter string is not recognised, else TRUE.
1899 ***************************************************************************/
1901 static int map_parameter(const char *pszParmName
)
1905 if (*pszParmName
== '-' && !strequal(pszParmName
, "-valid"))
1908 for (iIndex
= 0; parm_table
[iIndex
].label
; iIndex
++)
1909 if (strwicmp(parm_table
[iIndex
].label
, pszParmName
) == 0)
1912 /* Warn only if it isn't parametric option */
1913 if (strchr(pszParmName
, ':') == NULL
)
1914 DEBUG(1, ("Unknown parameter encountered: \"%s\"\n", pszParmName
));
1915 /* We do return 'fail' for parametric options as well because they are
1916 stored in different storage
1921 /***************************************************************************
1922 Map a parameter's string representation to the index of the canonical
1923 form of the parameter (it might be a synonym).
1924 Returns -1 if the parameter string is not recognised.
1925 ***************************************************************************/
1927 static int map_parameter_canonical(const char *pszParmName
, bool *inverse
)
1929 int parm_num
, canon_num
;
1930 bool loc_inverse
= false;
1932 parm_num
= map_parameter(pszParmName
);
1933 if ((parm_num
< 0) || !(parm_table
[parm_num
].flags
& FLAG_HIDE
)) {
1934 /* invalid, parametric or no canidate for synonyms ... */
1938 for (canon_num
= 0; parm_table
[canon_num
].label
; canon_num
++) {
1939 if (is_synonym_of(parm_num
, canon_num
, &loc_inverse
)) {
1940 parm_num
= canon_num
;
1946 if (inverse
!= NULL
) {
1947 *inverse
= loc_inverse
;
1952 /***************************************************************************
1953 return true if parameter number parm1 is a synonym of parameter
1954 number parm2 (parm2 being the principal name).
1955 set inverse to true if parm1 is P_BOOLREV and parm2 is P_BOOL,
1957 ***************************************************************************/
1959 static bool is_synonym_of(int parm1
, int parm2
, bool *inverse
)
1961 if ((parm_table
[parm1
].offset
== parm_table
[parm2
].offset
) &&
1962 (parm_table
[parm1
].p_class
== parm_table
[parm2
].p_class
) &&
1963 (parm_table
[parm1
].flags
& FLAG_HIDE
) &&
1964 !(parm_table
[parm2
].flags
& FLAG_HIDE
))
1966 if (inverse
!= NULL
) {
1967 if ((parm_table
[parm1
].type
== P_BOOLREV
) &&
1968 (parm_table
[parm2
].type
== P_BOOL
))
1980 /***************************************************************************
1981 Show one parameter's name, type, [values,] and flags.
1982 (helper functions for show_parameter_list)
1983 ***************************************************************************/
1985 static void show_parameter(int parmIndex
)
1987 int enumIndex
, flagIndex
;
1992 const char *type
[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
1993 "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
1995 unsigned flags
[] = { FLAG_BASIC
, FLAG_SHARE
, FLAG_PRINT
, FLAG_GLOBAL
,
1996 FLAG_WIZARD
, FLAG_ADVANCED
, FLAG_DEVELOPER
, FLAG_DEPRECATED
,
1998 const char *flag_names
[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
1999 "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
2000 "FLAG_DEPRECATED", "FLAG_HIDE", NULL
};
2002 printf("%s=%s", parm_table
[parmIndex
].label
,
2003 type
[parm_table
[parmIndex
].type
]);
2004 if (parm_table
[parmIndex
].type
== P_ENUM
) {
2007 parm_table
[parmIndex
].enum_list
[enumIndex
].name
;
2011 enumIndex
? "|" : "",
2012 parm_table
[parmIndex
].enum_list
[enumIndex
].name
);
2017 for (flagIndex
=0; flag_names
[flagIndex
]; flagIndex
++) {
2018 if (parm_table
[parmIndex
].flags
& flags
[flagIndex
]) {
2021 flag_names
[flagIndex
]);
2026 /* output synonyms */
2028 for (parmIndex2
=0; parm_table
[parmIndex2
].label
; parmIndex2
++) {
2029 if (is_synonym_of(parmIndex
, parmIndex2
, &inverse
)) {
2030 printf(" (%ssynonym of %s)", inverse
? "inverse " : "",
2031 parm_table
[parmIndex2
].label
);
2032 } else if (is_synonym_of(parmIndex2
, parmIndex
, &inverse
)) {
2034 printf(" (synonyms: ");
2039 printf("%s%s", parm_table
[parmIndex2
].label
,
2040 inverse
? "[i]" : "");
2050 /***************************************************************************
2051 Show all parameter's name, type, [values,] and flags.
2052 ***************************************************************************/
2054 void show_parameter_list(void)
2056 int classIndex
, parmIndex
;
2057 const char *section_names
[] = { "local", "global", NULL
};
2059 for (classIndex
=0; section_names
[classIndex
]; classIndex
++) {
2060 printf("[%s]\n", section_names
[classIndex
]);
2061 for (parmIndex
= 0; parm_table
[parmIndex
].label
; parmIndex
++) {
2062 if (parm_table
[parmIndex
].p_class
== classIndex
) {
2063 show_parameter(parmIndex
);
2069 /***************************************************************************
2070 Check if a given string correctly represents a boolean value.
2071 ***************************************************************************/
2073 bool lp_string_is_valid_boolean(const char *parm_value
)
2075 return set_boolean(parm_value
, NULL
);
2078 /***************************************************************************
2079 Get the standard string representation of a boolean value ("yes" or "no")
2080 ***************************************************************************/
2082 static const char *get_boolean(bool bool_value
)
2084 static const char *yes_str
= "yes";
2085 static const char *no_str
= "no";
2087 return (bool_value
? yes_str
: no_str
);
2090 /***************************************************************************
2091 Provide the string of the negated boolean value associated to the boolean
2092 given as a string. Returns false if the passed string does not correctly
2093 represent a boolean.
2094 ***************************************************************************/
2096 bool lp_invert_boolean(const char *str
, const char **inverse_str
)
2100 if (!set_boolean(str
, &val
)) {
2104 *inverse_str
= get_boolean(!val
);
2108 /***************************************************************************
2109 Provide the canonical string representation of a boolean value given
2110 as a string. Return true on success, false if the string given does
2111 not correctly represent a boolean.
2112 ***************************************************************************/
2114 bool lp_canonicalize_boolean(const char *str
, const char**canon_str
)
2118 if (!set_boolean(str
, &val
)) {
2122 *canon_str
= get_boolean(val
);
2126 /***************************************************************************
2127 Find a service by name. Otherwise works like get_service.
2128 ***************************************************************************/
2130 static int getservicebyname(const char *pszServiceName
, struct loadparm_service
*pserviceDest
)
2137 if (ServiceHash
== NULL
) {
2141 canon_name
= canonicalize_servicename(talloc_tos(), pszServiceName
);
2143 status
= dbwrap_fetch_bystring(ServiceHash
, canon_name
, canon_name
,
2146 if (NT_STATUS_IS_OK(status
) &&
2147 (data
.dptr
!= NULL
) &&
2148 (data
.dsize
== sizeof(iService
)))
2150 iService
= *(int *)data
.dptr
;
2153 TALLOC_FREE(canon_name
);
2155 if ((iService
!= -1) && (LP_SNUM_OK(iService
))
2156 && (pserviceDest
!= NULL
)) {
2157 copy_service(pserviceDest
, ServicePtrs
[iService
], NULL
);
2163 /* Return a pointer to a service by name. Unlike getservicebyname, it does not copy the service */
2164 struct loadparm_service
*lp_service(const char *pszServiceName
)
2166 int iService
= getservicebyname(pszServiceName
, NULL
);
2167 if (iService
== -1 || !LP_SNUM_OK(iService
)) {
2170 return ServicePtrs
[iService
];
2173 struct loadparm_service
*lp_servicebynum(int snum
)
2175 if ((snum
== -1) || !LP_SNUM_OK(snum
)) {
2178 return ServicePtrs
[snum
];
2181 struct loadparm_service
*lp_default_loadparm_service()
2187 /***************************************************************************
2188 Copy a service structure to another.
2189 If pcopymapDest is NULL then copy all fields
2190 ***************************************************************************/
2193 * Add a parametric option to a parmlist_entry,
2194 * replacing old value, if already present.
2196 static void set_param_opt(struct parmlist_entry
**opt_list
,
2197 const char *opt_name
,
2198 const char *opt_value
,
2201 struct parmlist_entry
*new_opt
, *opt
;
2204 if (opt_list
== NULL
) {
2211 /* Traverse destination */
2213 /* If we already have same option, override it */
2214 if (strwicmp(opt
->key
, opt_name
) == 0) {
2215 if ((opt
->priority
& FLAG_CMDLINE
) &&
2216 !(priority
& FLAG_CMDLINE
)) {
2217 /* it's been marked as not to be
2221 string_free(&opt
->value
);
2222 TALLOC_FREE(opt
->list
);
2223 opt
->value
= SMB_STRDUP(opt_value
);
2224 opt
->priority
= priority
;
2231 new_opt
= SMB_XMALLOC_P(struct parmlist_entry
);
2232 new_opt
->key
= SMB_STRDUP(opt_name
);
2233 new_opt
->value
= SMB_STRDUP(opt_value
);
2234 new_opt
->list
= NULL
;
2235 new_opt
->priority
= priority
;
2236 DLIST_ADD(*opt_list
, new_opt
);
2240 static void copy_service(struct loadparm_service
*pserviceDest
, struct loadparm_service
*pserviceSource
,
2241 struct bitmap
*pcopymapDest
)
2244 bool bcopyall
= (pcopymapDest
== NULL
);
2245 struct parmlist_entry
*data
;
2247 for (i
= 0; parm_table
[i
].label
; i
++)
2248 if (parm_table
[i
].p_class
== P_LOCAL
&&
2249 (bcopyall
|| bitmap_query(pcopymapDest
,i
))) {
2250 void *src_ptr
= lp_parm_ptr(pserviceSource
, &parm_table
[i
]);
2251 void *dest_ptr
= lp_parm_ptr(pserviceDest
, &parm_table
[i
]);
2253 switch (parm_table
[i
].type
) {
2256 *(bool *)dest_ptr
= *(bool *)src_ptr
;
2263 *(int *)dest_ptr
= *(int *)src_ptr
;
2267 *(char *)dest_ptr
= *(char *)src_ptr
;
2271 string_set((char **)dest_ptr
,
2277 char *upper_string
= strupper_talloc(talloc_tos(),
2279 string_set((char **)dest_ptr
,
2281 TALLOC_FREE(upper_string
);
2285 TALLOC_FREE(*((char ***)dest_ptr
));
2286 *((char ***)dest_ptr
) = str_list_copy(NULL
,
2287 *(const char ***)src_ptr
);
2295 init_copymap(pserviceDest
);
2296 if (pserviceSource
->copymap
)
2297 bitmap_copy(pserviceDest
->copymap
,
2298 pserviceSource
->copymap
);
2301 data
= pserviceSource
->param_opt
;
2303 set_param_opt(&pserviceDest
->param_opt
, data
->key
, data
->value
, data
->priority
);
2308 /***************************************************************************
2309 Check a service for consistency. Return false if the service is in any way
2310 incomplete or faulty, else true.
2311 ***************************************************************************/
2313 bool service_ok(int iService
)
2318 if (ServicePtrs
[iService
]->szService
[0] == '\0') {
2319 DEBUG(0, ("The following message indicates an internal error:\n"));
2320 DEBUG(0, ("No service name in service entry.\n"));
2324 /* The [printers] entry MUST be printable. I'm all for flexibility, but */
2325 /* I can't see why you'd want a non-printable printer service... */
2326 if (strwicmp(ServicePtrs
[iService
]->szService
, PRINTERS_NAME
) == 0) {
2327 if (!ServicePtrs
[iService
]->bPrint_ok
) {
2328 DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
2329 ServicePtrs
[iService
]->szService
));
2330 ServicePtrs
[iService
]->bPrint_ok
= true;
2332 /* [printers] service must also be non-browsable. */
2333 if (ServicePtrs
[iService
]->bBrowseable
)
2334 ServicePtrs
[iService
]->bBrowseable
= false;
2337 if (ServicePtrs
[iService
]->szPath
[0] == '\0' &&
2338 strwicmp(ServicePtrs
[iService
]->szService
, HOMES_NAME
) != 0 &&
2339 ServicePtrs
[iService
]->szMSDfsProxy
[0] == '\0'
2341 DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
2342 ServicePtrs
[iService
]->szService
));
2343 ServicePtrs
[iService
]->bAvailable
= false;
2346 /* If a service is flagged unavailable, log the fact at level 1. */
2347 if (!ServicePtrs
[iService
]->bAvailable
)
2348 DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
2349 ServicePtrs
[iService
]->szService
));
2354 static struct smbconf_ctx
*lp_smbconf_ctx(void)
2357 static struct smbconf_ctx
*conf_ctx
= NULL
;
2359 if (conf_ctx
== NULL
) {
2360 err
= smbconf_init(NULL
, &conf_ctx
, "registry:");
2361 if (!SBC_ERROR_IS_OK(err
)) {
2362 DEBUG(1, ("error initializing registry configuration: "
2363 "%s\n", sbcErrorString(err
)));
2371 static bool process_smbconf_service(struct smbconf_service
*service
)
2376 if (service
== NULL
) {
2380 ret
= do_section(service
->name
, NULL
);
2384 for (count
= 0; count
< service
->num_params
; count
++) {
2385 ret
= do_parameter(service
->param_names
[count
],
2386 service
->param_values
[count
],
2392 if (iServiceIndex
>= 0) {
2393 return service_ok(iServiceIndex
);
2399 * load a service from registry and activate it
2401 bool process_registry_service(const char *service_name
)
2404 struct smbconf_service
*service
= NULL
;
2405 TALLOC_CTX
*mem_ctx
= talloc_stackframe();
2406 struct smbconf_ctx
*conf_ctx
= lp_smbconf_ctx();
2409 if (conf_ctx
== NULL
) {
2413 DEBUG(5, ("process_registry_service: service name %s\n", service_name
));
2415 if (!smbconf_share_exists(conf_ctx
, service_name
)) {
2417 * Registry does not contain data for this service (yet),
2418 * but make sure lp_load doesn't return false.
2424 err
= smbconf_get_share(conf_ctx
, mem_ctx
, service_name
, &service
);
2425 if (!SBC_ERROR_IS_OK(err
)) {
2429 ret
= process_smbconf_service(service
);
2435 smbconf_changed(conf_ctx
, &conf_last_csn
, NULL
, NULL
);
2438 TALLOC_FREE(mem_ctx
);
2443 * process_registry_globals
2445 static bool process_registry_globals(void)
2449 add_to_file_list(INCLUDE_REGISTRY_NAME
, INCLUDE_REGISTRY_NAME
);
2451 ret
= do_parameter("registry shares", "yes", NULL
);
2456 return process_registry_service(GLOBAL_NAME
);
2459 bool process_registry_shares(void)
2463 struct smbconf_service
**service
= NULL
;
2464 uint32_t num_shares
= 0;
2465 TALLOC_CTX
*mem_ctx
= talloc_stackframe();
2466 struct smbconf_ctx
*conf_ctx
= lp_smbconf_ctx();
2469 if (conf_ctx
== NULL
) {
2473 err
= smbconf_get_config(conf_ctx
, mem_ctx
, &num_shares
, &service
);
2474 if (!SBC_ERROR_IS_OK(err
)) {
2480 for (count
= 0; count
< num_shares
; count
++) {
2481 if (strequal(service
[count
]->name
, GLOBAL_NAME
)) {
2484 ret
= process_smbconf_service(service
[count
]);
2491 smbconf_changed(conf_ctx
, &conf_last_csn
, NULL
, NULL
);
2494 TALLOC_FREE(mem_ctx
);
2499 * reload those shares from registry that are already
2500 * activated in the services array.
2502 static bool reload_registry_shares(void)
2507 for (i
= 0; i
< iNumServices
; i
++) {
2512 if (ServicePtrs
[i
]->usershare
== USERSHARE_VALID
) {
2516 ret
= process_registry_service(ServicePtrs
[i
]->szService
);
2527 #define MAX_INCLUDE_DEPTH 100
2529 static uint8_t include_depth
;
2531 static struct file_lists
{
2532 struct file_lists
*next
;
2536 } *file_lists
= NULL
;
2538 /*******************************************************************
2539 Keep a linked list of all config files so we know when one has changed
2540 it's date and needs to be reloaded.
2541 ********************************************************************/
2543 static void add_to_file_list(const char *fname
, const char *subfname
)
2545 struct file_lists
*f
= file_lists
;
2548 if (f
->name
&& !strcmp(f
->name
, fname
))
2554 f
= SMB_MALLOC_P(struct file_lists
);
2557 f
->next
= file_lists
;
2558 f
->name
= SMB_STRDUP(fname
);
2563 f
->subfname
= SMB_STRDUP(subfname
);
2570 f
->modtime
= file_modtime(subfname
);
2572 time_t t
= file_modtime(subfname
);
2580 * Free the file lists
2582 static void free_file_list(void)
2584 struct file_lists
*f
;
2585 struct file_lists
*next
;
2590 SAFE_FREE( f
->name
);
2591 SAFE_FREE( f
->subfname
);
2600 * Utility function for outsiders to check if we're running on registry.
2602 bool lp_config_backend_is_registry(void)
2604 return (lp_config_backend() == CONFIG_BACKEND_REGISTRY
);
2608 * Utility function to check if the config backend is FILE.
2610 bool lp_config_backend_is_file(void)
2612 return (lp_config_backend() == CONFIG_BACKEND_FILE
);
2615 /*******************************************************************
2616 Check if a config file has changed date.
2617 ********************************************************************/
2619 bool lp_file_list_changed(void)
2621 struct file_lists
*f
= file_lists
;
2623 DEBUG(6, ("lp_file_list_changed()\n"));
2628 if (strequal(f
->name
, INCLUDE_REGISTRY_NAME
)) {
2629 struct smbconf_ctx
*conf_ctx
= lp_smbconf_ctx();
2631 if (conf_ctx
== NULL
) {
2634 if (smbconf_changed(conf_ctx
, &conf_last_csn
, NULL
,
2637 DEBUGADD(6, ("registry config changed\n"));
2642 n2
= talloc_sub_basic(talloc_tos(),
2643 get_current_username(),
2644 current_user_info
.domain
,
2649 DEBUGADD(6, ("file %s -> %s last mod_time: %s\n",
2650 f
->name
, n2
, ctime(&f
->modtime
)));
2652 mod_time
= file_modtime(n2
);
2655 ((f
->modtime
!= mod_time
) ||
2656 (f
->subfname
== NULL
) ||
2657 (strcmp(n2
, f
->subfname
) != 0)))
2660 ("file %s modified: %s\n", n2
,
2662 f
->modtime
= mod_time
;
2663 SAFE_FREE(f
->subfname
);
2664 f
->subfname
= SMB_STRDUP(n2
);
2677 * Initialize iconv conversion descriptors.
2679 * This is called the first time it is needed, and also called again
2680 * every time the configuration is reloaded, because the charset or
2681 * codepage might have changed.
2683 static void init_iconv(void)
2685 global_iconv_handle
= smb_iconv_handle_reinit(NULL
, lp_dos_charset(),
2687 true, global_iconv_handle
);
2690 static bool handle_charset(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2692 if (strcmp(*ptr
, pszParmValue
) != 0) {
2693 string_set(ptr
, pszParmValue
);
2699 static bool handle_dos_charset(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2701 bool is_utf8
= false;
2702 size_t len
= strlen(pszParmValue
);
2704 if (len
== 4 || len
== 5) {
2705 /* Don't use StrCaseCmp here as we don't want to
2706 initialize iconv. */
2707 if ((toupper_m(pszParmValue
[0]) == 'U') &&
2708 (toupper_m(pszParmValue
[1]) == 'T') &&
2709 (toupper_m(pszParmValue
[2]) == 'F')) {
2711 if (pszParmValue
[3] == '8') {
2715 if (pszParmValue
[3] == '-' &&
2716 pszParmValue
[4] == '8') {
2723 if (strcmp(*ptr
, pszParmValue
) != 0) {
2725 DEBUG(0,("ERROR: invalid DOS charset: 'dos charset' must not "
2726 "be UTF8, using (default value) %s instead.\n",
2727 DEFAULT_DOS_CHARSET
));
2728 pszParmValue
= DEFAULT_DOS_CHARSET
;
2730 string_set(ptr
, pszParmValue
);
2736 static bool handle_realm(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2739 char *realm
= strupper_talloc(talloc_tos(), pszParmValue
);
2740 char *dnsdomain
= strlower_talloc(realm
, pszParmValue
);
2742 ret
&= string_set(&Globals
.szRealm
, pszParmValue
);
2743 ret
&= string_set(&Globals
.szRealm_upper
, realm
);
2744 ret
&= string_set(&Globals
.szRealm_lower
, dnsdomain
);
2750 static bool handle_netbios_aliases(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2752 TALLOC_FREE(Globals
.szNetbiosAliases
);
2753 Globals
.szNetbiosAliases
= (const char **)str_list_make_v3(NULL
, pszParmValue
, NULL
);
2754 return set_netbios_aliases(Globals
.szNetbiosAliases
);
2757 /***************************************************************************
2758 Handle the include operation.
2759 ***************************************************************************/
2760 static bool bAllowIncludeRegistry
= true;
2762 static bool handle_include(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2766 if (include_depth
>= MAX_INCLUDE_DEPTH
) {
2767 DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n",
2772 if (strequal(pszParmValue
, INCLUDE_REGISTRY_NAME
)) {
2773 if (!bAllowIncludeRegistry
) {
2776 if (bInGlobalSection
) {
2779 ret
= process_registry_globals();
2783 DEBUG(1, ("\"include = registry\" only effective "
2784 "in %s section\n", GLOBAL_NAME
));
2789 fname
= talloc_sub_basic(talloc_tos(), get_current_username(),
2790 current_user_info
.domain
,
2793 add_to_file_list(pszParmValue
, fname
);
2795 string_set(ptr
, fname
);
2797 if (file_exist(fname
)) {
2800 ret
= pm_process(fname
, do_section
, do_parameter
, NULL
);
2806 DEBUG(2, ("Can't find include file %s\n", fname
));
2811 /***************************************************************************
2812 Handle the interpretation of the copy parameter.
2813 ***************************************************************************/
2815 static bool handle_copy(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2819 struct loadparm_service serviceTemp
;
2821 string_set(ptr
, pszParmValue
);
2823 init_service(&serviceTemp
);
2827 DEBUG(3, ("Copying service from service %s\n", pszParmValue
));
2829 if ((iTemp
= getservicebyname(pszParmValue
, &serviceTemp
)) >= 0) {
2830 if (iTemp
== iServiceIndex
) {
2831 DEBUG(0, ("Can't copy service %s - unable to copy self!\n", pszParmValue
));
2833 copy_service(ServicePtrs
[iServiceIndex
],
2835 ServicePtrs
[iServiceIndex
]->copymap
);
2839 DEBUG(0, ("Unable to copy service - source not found: %s\n", pszParmValue
));
2843 free_service(&serviceTemp
);
2847 static bool handle_ldap_debug_level(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2849 Globals
.ldap_debug_level
= lp_int(pszParmValue
);
2850 init_ldap_debugging();
2854 /***************************************************************************
2855 Handle idmap/non unix account uid and gid allocation parameters. The format of these
2860 idmap uid = 1000-1999
2863 We only do simple parsing checks here. The strings are parsed into useful
2864 structures in the idmap daemon code.
2866 ***************************************************************************/
2868 /* Some lp_ routines to return idmap [ug]id information */
2870 static uid_t idmap_uid_low
, idmap_uid_high
;
2871 static gid_t idmap_gid_low
, idmap_gid_high
;
2873 bool lp_idmap_uid(uid_t
*low
, uid_t
*high
)
2875 if (idmap_uid_low
== 0 || idmap_uid_high
== 0)
2879 *low
= idmap_uid_low
;
2882 *high
= idmap_uid_high
;
2887 bool lp_idmap_gid(gid_t
*low
, gid_t
*high
)
2889 if (idmap_gid_low
== 0 || idmap_gid_high
== 0)
2893 *low
= idmap_gid_low
;
2896 *high
= idmap_gid_high
;
2901 static bool handle_idmap_backend(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2903 lp_do_parameter(snum
, "idmap config * : backend", pszParmValue
);
2908 /* Do some simple checks on "idmap [ug]id" parameter values */
2910 static bool handle_idmap_uid(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2912 lp_do_parameter(snum
, "idmap config * : range", pszParmValue
);
2917 static bool handle_idmap_gid(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
2919 lp_do_parameter(snum
, "idmap config * : range", pszParmValue
);
2924 /***************************************************************************
2925 Handle the DEBUG level list.
2926 ***************************************************************************/
2928 static bool handle_debug_list(struct loadparm_context
*unused
, int snum
, const char *pszParmValueIn
, char **ptr
)
2930 string_set(ptr
, pszParmValueIn
);
2931 return debug_parse_levels(pszParmValueIn
);
2934 /***************************************************************************
2935 Handle ldap suffixes - default to ldapsuffix if sub-suffixes are not defined.
2936 ***************************************************************************/
2938 static const char *append_ldap_suffix(TALLOC_CTX
*ctx
, const char *str
)
2940 const char *suffix_string
;
2942 suffix_string
= talloc_asprintf(ctx
, "%s,%s", str
,
2943 Globals
.szLdapSuffix
);
2944 if ( !suffix_string
) {
2945 DEBUG(0,("append_ldap_suffix: talloc_asprintf() failed!\n"));
2949 return suffix_string
;
2952 const char *lp_ldap_machine_suffix(TALLOC_CTX
*ctx
)
2954 if (Globals
.szLdapMachineSuffix
[0])
2955 return append_ldap_suffix(ctx
, Globals
.szLdapMachineSuffix
);
2957 return lp_string(ctx
, Globals
.szLdapSuffix
);
2960 const char *lp_ldap_user_suffix(TALLOC_CTX
*ctx
)
2962 if (Globals
.szLdapUserSuffix
[0])
2963 return append_ldap_suffix(ctx
, Globals
.szLdapUserSuffix
);
2965 return lp_string(ctx
, Globals
.szLdapSuffix
);
2968 const char *lp_ldap_group_suffix(TALLOC_CTX
*ctx
)
2970 if (Globals
.szLdapGroupSuffix
[0])
2971 return append_ldap_suffix(ctx
, Globals
.szLdapGroupSuffix
);
2973 return lp_string(ctx
, Globals
.szLdapSuffix
);
2976 const char *lp_ldap_idmap_suffix(TALLOC_CTX
*ctx
)
2978 if (Globals
.szLdapIdmapSuffix
[0])
2979 return append_ldap_suffix(ctx
, Globals
.szLdapIdmapSuffix
);
2981 return lp_string(ctx
, Globals
.szLdapSuffix
);
2984 /****************************************************************************
2985 set the value for a P_ENUM
2986 ***************************************************************************/
2988 static void lp_set_enum_parm( struct parm_struct
*parm
, const char *pszParmValue
,
2993 for (i
= 0; parm
->enum_list
[i
].name
; i
++) {
2994 if ( strequal(pszParmValue
, parm
->enum_list
[i
].name
)) {
2995 *ptr
= parm
->enum_list
[i
].value
;
2999 DEBUG(0, ("WARNING: Ignoring invalid value '%s' for parameter '%s'\n",
3000 pszParmValue
, parm
->label
));
3003 /***************************************************************************
3004 ***************************************************************************/
3006 static bool handle_printing(struct loadparm_context
*unused
, int snum
, const char *pszParmValue
, char **ptr
)
3008 static int parm_num
= -1;
3009 struct loadparm_service
*s
;
3011 if ( parm_num
== -1 )
3012 parm_num
= map_parameter( "printing" );
3014 lp_set_enum_parm( &parm_table
[parm_num
], pszParmValue
, (int*)ptr
);
3019 s
= ServicePtrs
[snum
];
3021 init_printer_values( s
);
3027 /***************************************************************************
3028 Initialise a copymap.
3029 ***************************************************************************/
3031 static void init_copymap(struct loadparm_service
*pservice
)
3035 TALLOC_FREE(pservice
->copymap
);
3037 pservice
->copymap
= bitmap_talloc(NULL
, NUMPARAMETERS
);
3038 if (!pservice
->copymap
)
3040 ("Couldn't allocate copymap!! (size %d)\n",
3041 (int)NUMPARAMETERS
));
3043 for (i
= 0; i
< NUMPARAMETERS
; i
++)
3044 bitmap_set(pservice
->copymap
, i
);
3048 return the parameter pointer for a parameter
3050 void *lp_parm_ptr(struct loadparm_service
*service
, struct parm_struct
*parm
)
3052 if (service
== NULL
) {
3053 if (parm
->p_class
== P_LOCAL
)
3054 return (void *)(((char *)&sDefault
)+parm
->offset
);
3055 else if (parm
->p_class
== P_GLOBAL
)
3056 return (void *)(((char *)&Globals
)+parm
->offset
);
3059 return (void *)(((char *)service
) + parm
->offset
);
3063 /***************************************************************************
3064 Return the local pointer to a parameter given the service number and parameter
3065 ***************************************************************************/
3067 void *lp_local_ptr_by_snum(int snum
, struct parm_struct
*parm
)
3069 return lp_parm_ptr(ServicePtrs
[snum
], parm
);
3072 /***************************************************************************
3073 Process a parameter for a particular service number. If snum < 0
3074 then assume we are in the globals.
3075 ***************************************************************************/
3077 bool lp_do_parameter(int snum
, const char *pszParmName
, const char *pszParmValue
)
3080 void *parm_ptr
= NULL
; /* where we are going to store the result */
3081 struct parmlist_entry
**opt_list
;
3083 parmnum
= map_parameter(pszParmName
);
3086 if (strchr(pszParmName
, ':') == NULL
) {
3087 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
3093 * We've got a parametric option
3096 opt_list
= (snum
< 0)
3097 ? &Globals
.param_opt
: &ServicePtrs
[snum
]->param_opt
;
3098 set_param_opt(opt_list
, pszParmName
, pszParmValue
, 0);
3103 /* if it's already been set by the command line, then we don't
3105 if (parm_table
[parmnum
].flags
& FLAG_CMDLINE
) {
3109 if (parm_table
[parmnum
].flags
& FLAG_DEPRECATED
) {
3110 DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
3114 /* we might point at a service, the default service or a global */
3116 parm_ptr
= lp_parm_ptr(NULL
, &parm_table
[parmnum
]);
3118 if (parm_table
[parmnum
].p_class
== P_GLOBAL
) {
3120 ("Global parameter %s found in service section!\n",
3124 parm_ptr
= lp_local_ptr_by_snum(snum
, &parm_table
[parmnum
]);
3128 if (!ServicePtrs
[snum
]->copymap
)
3129 init_copymap(ServicePtrs
[snum
]);
3131 /* this handles the aliases - set the copymap for other entries with
3132 the same data pointer */
3133 for (i
= 0; parm_table
[i
].label
; i
++) {
3134 if ((parm_table
[i
].offset
== parm_table
[parmnum
].offset
)
3135 && (parm_table
[i
].p_class
== parm_table
[parmnum
].p_class
)) {
3136 bitmap_clear(ServicePtrs
[snum
]->copymap
, i
);
3141 /* if it is a special case then go ahead */
3142 if (parm_table
[parmnum
].special
) {
3143 return parm_table
[parmnum
].special(NULL
, snum
, pszParmValue
,
3147 /* now switch on the type of variable it is */
3148 switch (parm_table
[parmnum
].type
)
3151 *(bool *)parm_ptr
= lp_bool(pszParmValue
);
3155 *(bool *)parm_ptr
= !lp_bool(pszParmValue
);
3159 *(int *)parm_ptr
= lp_int(pszParmValue
);
3163 *(char *)parm_ptr
= *pszParmValue
;
3167 i
= sscanf(pszParmValue
, "%o", (int *)parm_ptr
);
3169 DEBUG ( 0, ("Invalid octal number %s\n", pszParmName
));
3176 if (conv_str_size_error(pszParmValue
, &val
)) {
3177 if (val
<= INT_MAX
) {
3178 *(int *)parm_ptr
= (int)val
;
3183 DEBUG(0,("lp_do_parameter(%s): value is not "
3184 "a valid size specifier!\n", pszParmValue
));
3190 TALLOC_FREE(*((char ***)parm_ptr
));
3191 *(char ***)parm_ptr
= str_list_make_v3(
3192 NULL
, pszParmValue
, NULL
);
3196 string_set((char **)parm_ptr
, pszParmValue
);
3201 char *upper_string
= strupper_talloc(talloc_tos(),
3203 string_set((char **)parm_ptr
, upper_string
);
3204 TALLOC_FREE(upper_string
);
3208 lp_set_enum_parm( &parm_table
[parmnum
], pszParmValue
, (int*)parm_ptr
);
3217 /***************************************************************************
3218 set a parameter, marking it with FLAG_CMDLINE. Parameters marked as
3219 FLAG_CMDLINE won't be overridden by loads from smb.conf.
3220 ***************************************************************************/
3222 static bool lp_set_cmdline_helper(const char *pszParmName
, const char *pszParmValue
, bool store_values
)
3225 parmnum
= map_parameter(pszParmName
);
3227 parm_table
[parmnum
].flags
&= ~FLAG_CMDLINE
;
3228 if (!lp_do_parameter(-1, pszParmName
, pszParmValue
)) {
3231 parm_table
[parmnum
].flags
|= FLAG_CMDLINE
;
3233 /* we have to also set FLAG_CMDLINE on aliases. Aliases must
3234 * be grouped in the table, so we don't have to search the
3237 i
>=0 && parm_table
[i
].offset
== parm_table
[parmnum
].offset
3238 && parm_table
[i
].p_class
== parm_table
[parmnum
].p_class
;
3240 parm_table
[i
].flags
|= FLAG_CMDLINE
;
3242 for (i
=parmnum
+1;i
<NUMPARAMETERS
&& parm_table
[i
].offset
== parm_table
[parmnum
].offset
3243 && parm_table
[i
].p_class
== parm_table
[parmnum
].p_class
;i
++) {
3244 parm_table
[i
].flags
|= FLAG_CMDLINE
;
3248 store_lp_set_cmdline(pszParmName
, pszParmValue
);
3253 /* it might be parametric */
3254 if (strchr(pszParmName
, ':') != NULL
) {
3255 set_param_opt(&Globals
.param_opt
, pszParmName
, pszParmValue
, FLAG_CMDLINE
);
3257 store_lp_set_cmdline(pszParmName
, pszParmValue
);
3262 DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName
));
3266 bool lp_set_cmdline(const char *pszParmName
, const char *pszParmValue
)
3268 return lp_set_cmdline_helper(pszParmName
, pszParmValue
, true);
3271 /***************************************************************************
3272 Process a parameter.
3273 ***************************************************************************/
3275 static bool do_parameter(const char *pszParmName
, const char *pszParmValue
,
3278 if (!bInGlobalSection
&& bGlobalOnly
)
3281 DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName
, pszParmValue
));
3283 return (lp_do_parameter(bInGlobalSection
? -2 : iServiceIndex
,
3284 pszParmName
, pszParmValue
));
3288 set a option from the commandline in 'a=b' format. Use to support --option
3290 bool lp_set_option(const char *option
)
3295 s
= talloc_strdup(NULL
, option
);
3308 /* skip white spaces after the = sign */
3311 } while (*p
== ' ');
3313 ret
= lp_set_cmdline(s
, p
);
3318 /**************************************************************************
3319 Print a parameter of the specified type.
3320 ***************************************************************************/
3322 static void print_parameter(struct parm_struct
*p
, void *ptr
, FILE * f
)
3324 /* For the seperation of lists values that we print below */
3325 const char *list_sep
= ", ";
3330 for (i
= 0; p
->enum_list
[i
].name
; i
++) {
3331 if (*(int *)ptr
== p
->enum_list
[i
].value
) {
3333 p
->enum_list
[i
].name
);
3340 fprintf(f
, "%s", BOOLSTR(*(bool *)ptr
));
3344 fprintf(f
, "%s", BOOLSTR(!*(bool *)ptr
));
3349 fprintf(f
, "%d", *(int *)ptr
);
3353 fprintf(f
, "%c", *(char *)ptr
);
3357 int val
= *(int *)ptr
;
3361 fprintf(f
, "0%o", val
);
3370 if ((char ***)ptr
&& *(char ***)ptr
) {
3371 char **list
= *(char ***)ptr
;
3372 for (; *list
; list
++) {
3373 /* surround strings with whitespace in double quotes */
3374 if (*(list
+1) == NULL
) {
3375 /* last item, no extra separator */
3378 if ( strchr_m( *list
, ' ' ) ) {
3379 fprintf(f
, "\"%s\"%s", *list
, list_sep
);
3381 fprintf(f
, "%s%s", *list
, list_sep
);
3389 if (*(char **)ptr
) {
3390 fprintf(f
, "%s", *(char **)ptr
);
3398 /***************************************************************************
3399 Check if two parameters are equal.
3400 ***************************************************************************/
3402 static bool equal_parameter(parm_type type
, void *ptr1
, void *ptr2
)
3407 return (*((bool *)ptr1
) == *((bool *)ptr2
));
3413 return (*((int *)ptr1
) == *((int *)ptr2
));
3416 return (*((char *)ptr1
) == *((char *)ptr2
));
3420 return str_list_equal(*(const char ***)ptr1
, *(const char ***)ptr2
);
3425 char *p1
= *(char **)ptr1
, *p2
= *(char **)ptr2
;
3430 return (p1
== p2
|| strequal(p1
, p2
));
3438 /***************************************************************************
3439 Initialize any local varients in the sDefault table.
3440 ***************************************************************************/
3442 void init_locals(void)
3447 /***************************************************************************
3448 Process a new section (service). At this stage all sections are services.
3449 Later we'll have special sections that permit server parameters to be set.
3450 Returns true on success, false on failure.
3451 ***************************************************************************/
3453 static bool do_section(const char *pszSectionName
, void *userdata
)
3456 bool isglobal
= ((strwicmp(pszSectionName
, GLOBAL_NAME
) == 0) ||
3457 (strwicmp(pszSectionName
, GLOBAL_NAME2
) == 0));
3460 /* if we were in a global section then do the local inits */
3461 if (bInGlobalSection
&& !isglobal
)
3464 /* if we've just struck a global section, note the fact. */
3465 bInGlobalSection
= isglobal
;
3467 /* check for multiple global sections */
3468 if (bInGlobalSection
) {
3469 DEBUG(3, ("Processing section \"[%s]\"\n", pszSectionName
));
3473 if (!bInGlobalSection
&& bGlobalOnly
)
3476 /* if we have a current service, tidy it up before moving on */
3479 if (iServiceIndex
>= 0)
3480 bRetval
= service_ok(iServiceIndex
);
3482 /* if all is still well, move to the next record in the services array */
3484 /* We put this here to avoid an odd message order if messages are */
3485 /* issued by the post-processing of a previous section. */
3486 DEBUG(2, ("Processing section \"[%s]\"\n", pszSectionName
));
3488 iServiceIndex
= add_a_service(&sDefault
, pszSectionName
);
3489 if (iServiceIndex
< 0) {
3490 DEBUG(0, ("Failed to add a new service\n"));
3493 /* Clean all parametric options for service */
3494 /* They will be added during parsing again */
3495 free_param_opts(&ServicePtrs
[iServiceIndex
]->param_opt
);
3502 /***************************************************************************
3503 Determine if a partcular base parameter is currentl set to the default value.
3504 ***************************************************************************/
3506 static bool is_default(int i
)
3508 if (!defaults_saved
)
3510 switch (parm_table
[i
].type
) {
3513 return str_list_equal((const char **)parm_table
[i
].def
.lvalue
,
3514 *(const char ***)lp_parm_ptr(NULL
,
3518 return strequal(parm_table
[i
].def
.svalue
,
3519 *(char **)lp_parm_ptr(NULL
,
3523 return parm_table
[i
].def
.bvalue
==
3524 *(bool *)lp_parm_ptr(NULL
,
3527 return parm_table
[i
].def
.cvalue
==
3528 *(char *)lp_parm_ptr(NULL
,
3534 return parm_table
[i
].def
.ivalue
==
3535 *(int *)lp_parm_ptr(NULL
,
3543 /***************************************************************************
3544 Display the contents of the global structure.
3545 ***************************************************************************/
3547 static void dump_globals(FILE *f
)
3550 struct parmlist_entry
*data
;
3552 fprintf(f
, "[global]\n");
3554 for (i
= 0; parm_table
[i
].label
; i
++)
3555 if (parm_table
[i
].p_class
== P_GLOBAL
&&
3556 !(parm_table
[i
].flags
& FLAG_META
) &&
3557 (i
== 0 || (parm_table
[i
].offset
!= parm_table
[i
- 1].offset
))) {
3558 if (defaults_saved
&& is_default(i
))
3560 fprintf(f
, "\t%s = ", parm_table
[i
].label
);
3561 print_parameter(&parm_table
[i
], lp_parm_ptr(NULL
,
3566 if (Globals
.param_opt
!= NULL
) {
3567 data
= Globals
.param_opt
;
3569 fprintf(f
, "\t%s = %s\n", data
->key
, data
->value
);
3576 /***************************************************************************
3577 Return true if a local parameter is currently set to the global default.
3578 ***************************************************************************/
3580 bool lp_is_default(int snum
, struct parm_struct
*parm
)
3582 return equal_parameter(parm
->type
,
3583 lp_parm_ptr(ServicePtrs
[snum
], parm
),
3584 lp_parm_ptr(NULL
, parm
));
3587 /***************************************************************************
3588 Display the contents of a single services record.
3589 ***************************************************************************/
3591 static void dump_a_service(struct loadparm_service
*pService
, FILE * f
)
3594 struct parmlist_entry
*data
;
3596 if (pService
!= &sDefault
)
3597 fprintf(f
, "[%s]\n", pService
->szService
);
3599 for (i
= 0; parm_table
[i
].label
; i
++) {
3601 if (parm_table
[i
].p_class
== P_LOCAL
&&
3602 !(parm_table
[i
].flags
& FLAG_META
) &&
3603 (*parm_table
[i
].label
!= '-') &&
3604 (i
== 0 || (parm_table
[i
].offset
!= parm_table
[i
- 1].offset
)))
3606 if (pService
== &sDefault
) {
3607 if (defaults_saved
&& is_default(i
))
3610 if (equal_parameter(parm_table
[i
].type
,
3611 lp_parm_ptr(pService
, &parm_table
[i
]),
3612 lp_parm_ptr(NULL
, &parm_table
[i
])))
3616 fprintf(f
, "\t%s = ", parm_table
[i
].label
);
3617 print_parameter(&parm_table
[i
],
3618 lp_parm_ptr(pService
, &parm_table
[i
]),
3624 if (pService
->param_opt
!= NULL
) {
3625 data
= pService
->param_opt
;
3627 fprintf(f
, "\t%s = %s\n", data
->key
, data
->value
);
3633 /***************************************************************************
3634 Display the contents of a parameter of a single services record.
3635 ***************************************************************************/
3637 bool dump_a_parameter(int snum
, char *parm_name
, FILE * f
, bool isGlobal
)
3640 bool result
= false;
3643 fstring local_parm_name
;
3645 const char *parm_opt_value
;
3647 /* check for parametrical option */
3648 fstrcpy( local_parm_name
, parm_name
);
3649 parm_opt
= strchr( local_parm_name
, ':');
3654 if (strlen(parm_opt
)) {
3655 parm_opt_value
= lp_parm_const_string( snum
,
3656 local_parm_name
, parm_opt
, NULL
);
3657 if (parm_opt_value
) {
3658 printf( "%s\n", parm_opt_value
);
3665 /* check for a key and print the value */
3672 for (i
= 0; parm_table
[i
].label
; i
++) {
3673 if (strwicmp(parm_table
[i
].label
, parm_name
) == 0 &&
3674 !(parm_table
[i
].flags
& FLAG_META
) &&
3675 (parm_table
[i
].p_class
== p_class
|| parm_table
[i
].flags
& flag
) &&
3676 (*parm_table
[i
].label
!= '-') &&
3677 (i
== 0 || (parm_table
[i
].offset
!= parm_table
[i
- 1].offset
)))
3682 ptr
= lp_parm_ptr(NULL
,
3685 ptr
= lp_parm_ptr(ServicePtrs
[snum
],
3689 print_parameter(&parm_table
[i
],
3700 /***************************************************************************
3701 Return info about the requested parameter (given as a string).
3702 Return NULL when the string is not a valid parameter name.
3703 ***************************************************************************/
3705 struct parm_struct
*lp_get_parameter(const char *param_name
)
3707 int num
= map_parameter(param_name
);
3713 return &parm_table
[num
];
3716 /***************************************************************************
3717 Return info about the next parameter in a service.
3718 snum==GLOBAL_SECTION_SNUM gives the globals.
3719 Return NULL when out of parameters.
3720 ***************************************************************************/
3722 struct parm_struct
*lp_next_parameter(int snum
, int *i
, int allparameters
)
3725 /* do the globals */
3726 for (; parm_table
[*i
].label
; (*i
)++) {
3727 if (parm_table
[*i
].p_class
== P_SEPARATOR
)
3728 return &parm_table
[(*i
)++];
3730 if ((*parm_table
[*i
].label
== '-'))
3734 && (parm_table
[*i
].offset
==
3735 parm_table
[(*i
) - 1].offset
)
3736 && (parm_table
[*i
].p_class
==
3737 parm_table
[(*i
) - 1].p_class
))
3740 if (is_default(*i
) && !allparameters
)
3743 return &parm_table
[(*i
)++];
3746 struct loadparm_service
*pService
= ServicePtrs
[snum
];
3748 for (; parm_table
[*i
].label
; (*i
)++) {
3749 if (parm_table
[*i
].p_class
== P_SEPARATOR
)
3750 return &parm_table
[(*i
)++];
3752 if (parm_table
[*i
].p_class
== P_LOCAL
&&
3753 (*parm_table
[*i
].label
!= '-') &&
3755 (parm_table
[*i
].offset
!=
3756 parm_table
[(*i
) - 1].offset
)))
3758 if (allparameters
||
3759 !equal_parameter(parm_table
[*i
].type
,
3760 lp_parm_ptr(pService
,
3765 return &parm_table
[(*i
)++];
3776 /***************************************************************************
3777 Display the contents of a single copy structure.
3778 ***************************************************************************/
3779 static void dump_copy_map(bool *pcopymap
)
3785 printf("\n\tNon-Copied parameters:\n");
3787 for (i
= 0; parm_table
[i
].label
; i
++)
3788 if (parm_table
[i
].p_class
== P_LOCAL
&&
3789 parm_table
[i
].ptr
&& !pcopymap
[i
] &&
3790 (i
== 0 || (parm_table
[i
].ptr
!= parm_table
[i
- 1].ptr
)))
3792 printf("\t\t%s\n", parm_table
[i
].label
);
3797 /***************************************************************************
3798 Return TRUE if the passed service number is within range.
3799 ***************************************************************************/
3801 bool lp_snum_ok(int iService
)
3803 return (LP_SNUM_OK(iService
) && ServicePtrs
[iService
]->bAvailable
);
3806 /***************************************************************************
3807 Auto-load some home services.
3808 ***************************************************************************/
3810 static void lp_add_auto_services(char *str
)
3820 s
= SMB_STRDUP(str
);
3824 homes
= lp_servicenumber(HOMES_NAME
);
3826 for (p
= strtok_r(s
, LIST_SEP
, &saveptr
); p
;
3827 p
= strtok_r(NULL
, LIST_SEP
, &saveptr
)) {
3830 if (lp_servicenumber(p
) >= 0)
3833 home
= get_user_home_dir(talloc_tos(), p
);
3835 if (home
&& home
[0] && homes
>= 0)
3836 lp_add_home(p
, homes
, p
, home
);
3843 /***************************************************************************
3844 Auto-load one printer.
3845 ***************************************************************************/
3847 void lp_add_one_printer(const char *name
, const char *comment
,
3848 const char *location
, void *pdata
)
3850 int printers
= lp_servicenumber(PRINTERS_NAME
);
3853 if (lp_servicenumber(name
) < 0) {
3854 lp_add_printer(name
, printers
);
3855 if ((i
= lp_servicenumber(name
)) >= 0) {
3856 string_set(&ServicePtrs
[i
]->comment
, comment
);
3857 ServicePtrs
[i
]->autoloaded
= true;
3862 /***************************************************************************
3863 Have we loaded a services file yet?
3864 ***************************************************************************/
3866 bool lp_loaded(void)
3871 /***************************************************************************
3872 Unload unused services.
3873 ***************************************************************************/
3875 void lp_killunused(struct smbd_server_connection
*sconn
,
3876 bool (*snumused
) (struct smbd_server_connection
*, int))
3879 for (i
= 0; i
< iNumServices
; i
++) {
3883 /* don't kill autoloaded or usershare services */
3884 if ( ServicePtrs
[i
]->autoloaded
||
3885 ServicePtrs
[i
]->usershare
== USERSHARE_VALID
) {
3889 if (!snumused
|| !snumused(sconn
, i
)) {
3890 free_service_byindex(i
);
3896 * Kill all except autoloaded and usershare services - convenience wrapper
3898 void lp_kill_all_services(void)
3900 lp_killunused(NULL
, NULL
);
3903 /***************************************************************************
3905 ***************************************************************************/
3907 void lp_killservice(int iServiceIn
)
3909 if (VALID(iServiceIn
)) {
3910 free_service_byindex(iServiceIn
);
3914 /***************************************************************************
3915 Save the curent values of all global and sDefault parameters into the
3916 defaults union. This allows swat and testparm to show only the
3917 changed (ie. non-default) parameters.
3918 ***************************************************************************/
3920 static void lp_save_defaults(void)
3923 for (i
= 0; parm_table
[i
].label
; i
++) {
3924 if (i
> 0 && parm_table
[i
].offset
== parm_table
[i
- 1].offset
3925 && parm_table
[i
].p_class
== parm_table
[i
- 1].p_class
)
3927 switch (parm_table
[i
].type
) {
3930 parm_table
[i
].def
.lvalue
= str_list_copy(
3931 NULL
, *(const char ***)lp_parm_ptr(NULL
, &parm_table
[i
]));
3935 parm_table
[i
].def
.svalue
= SMB_STRDUP(*(char **)lp_parm_ptr(NULL
, &parm_table
[i
]));
3939 parm_table
[i
].def
.bvalue
=
3940 *(bool *)lp_parm_ptr(NULL
, &parm_table
[i
]);
3943 parm_table
[i
].def
.cvalue
=
3944 *(char *)lp_parm_ptr(NULL
, &parm_table
[i
]);
3950 parm_table
[i
].def
.ivalue
=
3951 *(int *)lp_parm_ptr(NULL
, &parm_table
[i
]);
3957 defaults_saved
= true;
3960 /***********************************************************
3961 If we should send plaintext/LANMAN passwords in the clinet
3962 ************************************************************/
3964 static void set_allowed_client_auth(void)
3966 if (Globals
.bClientNTLMv2Auth
) {
3967 Globals
.bClientLanManAuth
= false;
3969 if (!Globals
.bClientLanManAuth
) {
3970 Globals
.bClientPlaintextAuth
= false;
3974 /***************************************************************************
3976 The following code allows smbd to read a user defined share file.
3977 Yes, this is my intent. Yes, I'm comfortable with that...
3979 THE FOLLOWING IS SECURITY CRITICAL CODE.
3981 It washes your clothes, it cleans your house, it guards you while you sleep...
3982 Do not f%^k with it....
3983 ***************************************************************************/
3985 #define MAX_USERSHARE_FILE_SIZE (10*1024)
3987 /***************************************************************************
3988 Check allowed stat state of a usershare file.
3989 Ensure we print out who is dicking with us so the admin can
3990 get their sorry ass fired.
3991 ***************************************************************************/
3993 static bool check_usershare_stat(const char *fname
,
3994 const SMB_STRUCT_STAT
*psbuf
)
3996 if (!S_ISREG(psbuf
->st_ex_mode
)) {
3997 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
3998 "not a regular file\n",
3999 fname
, (unsigned int)psbuf
->st_ex_uid
));
4003 /* Ensure this doesn't have the other write bit set. */
4004 if (psbuf
->st_ex_mode
& S_IWOTH
) {
4005 DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
4006 "public write. Refusing to allow as a usershare file.\n",
4007 fname
, (unsigned int)psbuf
->st_ex_uid
));
4011 /* Should be 10k or less. */
4012 if (psbuf
->st_ex_size
> MAX_USERSHARE_FILE_SIZE
) {
4013 DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
4014 "too large (%u) to be a user share file.\n",
4015 fname
, (unsigned int)psbuf
->st_ex_uid
,
4016 (unsigned int)psbuf
->st_ex_size
));
4023 /***************************************************************************
4024 Parse the contents of a usershare file.
4025 ***************************************************************************/
4027 enum usershare_err
parse_usershare_file(TALLOC_CTX
*ctx
,
4028 SMB_STRUCT_STAT
*psbuf
,
4029 const char *servicename
,
4033 char **pp_sharepath
,
4035 char **pp_cp_servicename
,
4036 struct security_descriptor
**ppsd
,
4039 const char **prefixallowlist
= lp_usershare_prefix_allow_list();
4040 const char **prefixdenylist
= lp_usershare_prefix_deny_list();
4043 SMB_STRUCT_STAT sbuf
;
4044 char *sharepath
= NULL
;
4045 char *comment
= NULL
;
4047 *pp_sharepath
= NULL
;
4050 *pallow_guest
= false;
4053 return USERSHARE_MALFORMED_FILE
;
4056 if (strcmp(lines
[0], "#VERSION 1") == 0) {
4058 } else if (strcmp(lines
[0], "#VERSION 2") == 0) {
4061 return USERSHARE_MALFORMED_FILE
;
4064 return USERSHARE_BAD_VERSION
;
4067 if (strncmp(lines
[1], "path=", 5) != 0) {
4068 return USERSHARE_MALFORMED_PATH
;
4071 sharepath
= talloc_strdup(ctx
, &lines
[1][5]);
4073 return USERSHARE_POSIX_ERR
;
4075 trim_string(sharepath
, " ", " ");
4077 if (strncmp(lines
[2], "comment=", 8) != 0) {
4078 return USERSHARE_MALFORMED_COMMENT_DEF
;
4081 comment
= talloc_strdup(ctx
, &lines
[2][8]);
4083 return USERSHARE_POSIX_ERR
;
4085 trim_string(comment
, " ", " ");
4086 trim_char(comment
, '"', '"');
4088 if (strncmp(lines
[3], "usershare_acl=", 14) != 0) {
4089 return USERSHARE_MALFORMED_ACL_DEF
;
4092 if (!parse_usershare_acl(ctx
, &lines
[3][14], ppsd
)) {
4093 return USERSHARE_ACL_ERR
;
4097 if (strncmp(lines
[4], "guest_ok=", 9) != 0) {
4098 return USERSHARE_MALFORMED_ACL_DEF
;
4100 if (lines
[4][9] == 'y') {
4101 *pallow_guest
= true;
4104 /* Backwards compatible extension to file version #2. */
4106 if (strncmp(lines
[5], "sharename=", 10) != 0) {
4107 return USERSHARE_MALFORMED_SHARENAME_DEF
;
4109 if (!strequal(&lines
[5][10], servicename
)) {
4110 return USERSHARE_BAD_SHARENAME
;
4112 *pp_cp_servicename
= talloc_strdup(ctx
, &lines
[5][10]);
4113 if (!*pp_cp_servicename
) {
4114 return USERSHARE_POSIX_ERR
;
4119 if (*pp_cp_servicename
== NULL
) {
4120 *pp_cp_servicename
= talloc_strdup(ctx
, servicename
);
4121 if (!*pp_cp_servicename
) {
4122 return USERSHARE_POSIX_ERR
;
4126 if (snum
!= -1 && (strcmp(sharepath
, ServicePtrs
[snum
]->szPath
) == 0)) {
4127 /* Path didn't change, no checks needed. */
4128 *pp_sharepath
= sharepath
;
4129 *pp_comment
= comment
;
4130 return USERSHARE_OK
;
4133 /* The path *must* be absolute. */
4134 if (sharepath
[0] != '/') {
4135 DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
4136 servicename
, sharepath
));
4137 return USERSHARE_PATH_NOT_ABSOLUTE
;
4140 /* If there is a usershare prefix deny list ensure one of these paths
4141 doesn't match the start of the user given path. */
4142 if (prefixdenylist
) {
4144 for ( i
=0; prefixdenylist
[i
]; i
++ ) {
4145 DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
4146 servicename
, i
, prefixdenylist
[i
], sharepath
));
4147 if (memcmp( sharepath
, prefixdenylist
[i
], strlen(prefixdenylist
[i
])) == 0) {
4148 DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
4149 "usershare prefix deny list entries.\n",
4150 servicename
, sharepath
));
4151 return USERSHARE_PATH_IS_DENIED
;
4156 /* If there is a usershare prefix allow list ensure one of these paths
4157 does match the start of the user given path. */
4159 if (prefixallowlist
) {
4161 for ( i
=0; prefixallowlist
[i
]; i
++ ) {
4162 DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
4163 servicename
, i
, prefixallowlist
[i
], sharepath
));
4164 if (memcmp( sharepath
, prefixallowlist
[i
], strlen(prefixallowlist
[i
])) == 0) {
4168 if (prefixallowlist
[i
] == NULL
) {
4169 DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
4170 "usershare prefix allow list entries.\n",
4171 servicename
, sharepath
));
4172 return USERSHARE_PATH_NOT_ALLOWED
;
4176 /* Ensure this is pointing to a directory. */
4177 dp
= opendir(sharepath
);
4180 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4181 servicename
, sharepath
));
4182 return USERSHARE_PATH_NOT_DIRECTORY
;
4185 /* Ensure the owner of the usershare file has permission to share
4188 if (sys_stat(sharepath
, &sbuf
, false) == -1) {
4189 DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
4190 servicename
, sharepath
, strerror(errno
) ));
4192 return USERSHARE_POSIX_ERR
;
4197 if (!S_ISDIR(sbuf
.st_ex_mode
)) {
4198 DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
4199 servicename
, sharepath
));
4200 return USERSHARE_PATH_NOT_DIRECTORY
;
4203 /* Check if sharing is restricted to owner-only. */
4204 /* psbuf is the stat of the usershare definition file,
4205 sbuf is the stat of the target directory to be shared. */
4207 if (lp_usershare_owner_only()) {
4208 /* root can share anything. */
4209 if ((psbuf
->st_ex_uid
!= 0) && (sbuf
.st_ex_uid
!= psbuf
->st_ex_uid
)) {
4210 return USERSHARE_PATH_NOT_ALLOWED
;
4214 *pp_sharepath
= sharepath
;
4215 *pp_comment
= comment
;
4216 return USERSHARE_OK
;
4219 /***************************************************************************
4220 Deal with a usershare file.
4223 -1 - Bad name, invalid contents.
4224 - service name already existed and not a usershare, problem
4225 with permissions to share directory etc.
4226 ***************************************************************************/
4228 static int process_usershare_file(const char *dir_name
, const char *file_name
, int snum_template
)
4230 SMB_STRUCT_STAT sbuf
;
4231 SMB_STRUCT_STAT lsbuf
;
4233 char *sharepath
= NULL
;
4234 char *comment
= NULL
;
4235 char *cp_service_name
= NULL
;
4236 char **lines
= NULL
;
4240 TALLOC_CTX
*ctx
= talloc_stackframe();
4241 struct security_descriptor
*psd
= NULL
;
4242 bool guest_ok
= false;
4243 char *canon_name
= NULL
;
4244 bool added_service
= false;
4247 /* Ensure share name doesn't contain invalid characters. */
4248 if (!validate_net_name(file_name
, INVALID_SHARENAME_CHARS
, strlen(file_name
))) {
4249 DEBUG(0,("process_usershare_file: share name %s contains "
4250 "invalid characters (any of %s)\n",
4251 file_name
, INVALID_SHARENAME_CHARS
));
4255 canon_name
= canonicalize_servicename(ctx
, file_name
);
4260 fname
= talloc_asprintf(ctx
, "%s/%s", dir_name
, file_name
);
4265 /* Minimize the race condition by doing an lstat before we
4266 open and fstat. Ensure this isn't a symlink link. */
4268 if (sys_lstat(fname
, &lsbuf
, false) != 0) {
4269 DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
4270 fname
, strerror(errno
) ));
4274 /* This must be a regular file, not a symlink, directory or
4275 other strange filetype. */
4276 if (!check_usershare_stat(fname
, &lsbuf
)) {
4284 status
= dbwrap_fetch_bystring(ServiceHash
, canon_name
,
4289 if (NT_STATUS_IS_OK(status
) &&
4290 (data
.dptr
!= NULL
) &&
4291 (data
.dsize
== sizeof(iService
))) {
4292 memcpy(&iService
, data
.dptr
, sizeof(iService
));
4296 if (iService
!= -1 &&
4297 timespec_compare(&ServicePtrs
[iService
]->usershare_last_mod
,
4298 &lsbuf
.st_ex_mtime
) == 0) {
4299 /* Nothing changed - Mark valid and return. */
4300 DEBUG(10,("process_usershare_file: service %s not changed.\n",
4302 ServicePtrs
[iService
]->usershare
= USERSHARE_VALID
;
4307 /* Try and open the file read only - no symlinks allowed. */
4309 fd
= open(fname
, O_RDONLY
|O_NOFOLLOW
, 0);
4311 fd
= open(fname
, O_RDONLY
, 0);
4315 DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
4316 fname
, strerror(errno
) ));
4320 /* Now fstat to be *SURE* it's a regular file. */
4321 if (sys_fstat(fd
, &sbuf
, false) != 0) {
4323 DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
4324 fname
, strerror(errno
) ));
4328 /* Is it the same dev/inode as was lstated ? */
4329 if (!check_same_stat(&lsbuf
, &sbuf
)) {
4331 DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
4332 "Symlink spoofing going on ?\n", fname
));
4336 /* This must be a regular file, not a symlink, directory or
4337 other strange filetype. */
4338 if (!check_usershare_stat(fname
, &sbuf
)) {
4342 lines
= fd_lines_load(fd
, &numlines
, MAX_USERSHARE_FILE_SIZE
, NULL
);
4345 if (lines
== NULL
) {
4346 DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
4347 fname
, (unsigned int)sbuf
.st_ex_uid
));
4351 if (parse_usershare_file(ctx
, &sbuf
, file_name
,
4352 iService
, lines
, numlines
, &sharepath
,
4353 &comment
, &cp_service_name
,
4354 &psd
, &guest_ok
) != USERSHARE_OK
) {
4358 /* Everything ok - add the service possibly using a template. */
4360 const struct loadparm_service
*sp
= &sDefault
;
4361 if (snum_template
!= -1) {
4362 sp
= ServicePtrs
[snum_template
];
4365 if ((iService
= add_a_service(sp
, cp_service_name
)) < 0) {
4366 DEBUG(0, ("process_usershare_file: Failed to add "
4367 "new service %s\n", cp_service_name
));
4371 added_service
= true;
4373 /* Read only is controlled by usershare ACL below. */
4374 ServicePtrs
[iService
]->bRead_only
= false;
4377 /* Write the ACL of the new/modified share. */
4378 if (!set_share_security(canon_name
, psd
)) {
4379 DEBUG(0, ("process_usershare_file: Failed to set share "
4380 "security for user share %s\n",
4385 /* If from a template it may be marked invalid. */
4386 ServicePtrs
[iService
]->valid
= true;
4388 /* Set the service as a valid usershare. */
4389 ServicePtrs
[iService
]->usershare
= USERSHARE_VALID
;
4391 /* Set guest access. */
4392 if (lp_usershare_allow_guests()) {
4393 ServicePtrs
[iService
]->bGuest_ok
= guest_ok
;
4396 /* And note when it was loaded. */
4397 ServicePtrs
[iService
]->usershare_last_mod
= sbuf
.st_ex_mtime
;
4398 string_set(&ServicePtrs
[iService
]->szPath
, sharepath
);
4399 string_set(&ServicePtrs
[iService
]->comment
, comment
);
4405 if (ret
== -1 && iService
!= -1 && added_service
) {
4406 lp_remove_service(iService
);
4414 /***************************************************************************
4415 Checks if a usershare entry has been modified since last load.
4416 ***************************************************************************/
4418 static bool usershare_exists(int iService
, struct timespec
*last_mod
)
4420 SMB_STRUCT_STAT lsbuf
;
4421 const char *usersharepath
= Globals
.szUsersharePath
;
4424 if (asprintf(&fname
, "%s/%s",
4426 ServicePtrs
[iService
]->szService
) < 0) {
4430 if (sys_lstat(fname
, &lsbuf
, false) != 0) {
4435 if (!S_ISREG(lsbuf
.st_ex_mode
)) {
4441 *last_mod
= lsbuf
.st_ex_mtime
;
4445 /***************************************************************************
4446 Load a usershare service by name. Returns a valid servicenumber or -1.
4447 ***************************************************************************/
4449 int load_usershare_service(const char *servicename
)
4451 SMB_STRUCT_STAT sbuf
;
4452 const char *usersharepath
= Globals
.szUsersharePath
;
4453 int max_user_shares
= Globals
.iUsershareMaxShares
;
4454 int snum_template
= -1;
4456 if (*usersharepath
== 0 || max_user_shares
== 0) {
4460 if (sys_stat(usersharepath
, &sbuf
, false) != 0) {
4461 DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
4462 usersharepath
, strerror(errno
) ));
4466 if (!S_ISDIR(sbuf
.st_ex_mode
)) {
4467 DEBUG(0,("load_usershare_service: %s is not a directory.\n",
4473 * This directory must be owned by root, and have the 't' bit set.
4474 * It also must not be writable by "other".
4478 if (sbuf
.st_ex_uid
!= 0 || !(sbuf
.st_ex_mode
& S_ISVTX
) || (sbuf
.st_ex_mode
& S_IWOTH
)) {
4480 if (sbuf
.st_ex_uid
!= 0 || (sbuf
.st_ex_mode
& S_IWOTH
)) {
4482 DEBUG(0,("load_usershare_service: directory %s is not owned by root "
4483 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4488 /* Ensure the template share exists if it's set. */
4489 if (Globals
.szUsershareTemplateShare
[0]) {
4490 /* We can't use lp_servicenumber here as we are recommending that
4491 template shares have -valid=false set. */
4492 for (snum_template
= iNumServices
- 1; snum_template
>= 0; snum_template
--) {
4493 if (ServicePtrs
[snum_template
]->szService
&&
4494 strequal(ServicePtrs
[snum_template
]->szService
,
4495 Globals
.szUsershareTemplateShare
)) {
4500 if (snum_template
== -1) {
4501 DEBUG(0,("load_usershare_service: usershare template share %s "
4502 "does not exist.\n",
4503 Globals
.szUsershareTemplateShare
));
4508 return process_usershare_file(usersharepath
, servicename
, snum_template
);
4511 /***************************************************************************
4512 Load all user defined shares from the user share directory.
4513 We only do this if we're enumerating the share list.
4514 This is the function that can delete usershares that have
4516 ***************************************************************************/
4518 int load_usershare_shares(struct smbd_server_connection
*sconn
,
4519 bool (*snumused
) (struct smbd_server_connection
*, int))
4522 SMB_STRUCT_STAT sbuf
;
4524 int num_usershares
= 0;
4525 int max_user_shares
= Globals
.iUsershareMaxShares
;
4526 unsigned int num_dir_entries
, num_bad_dir_entries
, num_tmp_dir_entries
;
4527 unsigned int allowed_bad_entries
= ((2*max_user_shares
)/10);
4528 unsigned int allowed_tmp_entries
= ((2*max_user_shares
)/10);
4530 int snum_template
= -1;
4531 const char *usersharepath
= Globals
.szUsersharePath
;
4532 int ret
= lp_numservices();
4533 TALLOC_CTX
*tmp_ctx
;
4535 if (max_user_shares
== 0 || *usersharepath
== '\0') {
4536 return lp_numservices();
4539 if (sys_stat(usersharepath
, &sbuf
, false) != 0) {
4540 DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
4541 usersharepath
, strerror(errno
) ));
4546 * This directory must be owned by root, and have the 't' bit set.
4547 * It also must not be writable by "other".
4551 if (sbuf
.st_ex_uid
!= 0 || !(sbuf
.st_ex_mode
& S_ISVTX
) || (sbuf
.st_ex_mode
& S_IWOTH
)) {
4553 if (sbuf
.st_ex_uid
!= 0 || (sbuf
.st_ex_mode
& S_IWOTH
)) {
4555 DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
4556 "or does not have the sticky bit 't' set or is writable by anyone.\n",
4561 /* Ensure the template share exists if it's set. */
4562 if (Globals
.szUsershareTemplateShare
[0]) {
4563 /* We can't use lp_servicenumber here as we are recommending that
4564 template shares have -valid=false set. */
4565 for (snum_template
= iNumServices
- 1; snum_template
>= 0; snum_template
--) {
4566 if (ServicePtrs
[snum_template
]->szService
&&
4567 strequal(ServicePtrs
[snum_template
]->szService
,
4568 Globals
.szUsershareTemplateShare
)) {
4573 if (snum_template
== -1) {
4574 DEBUG(0,("load_usershare_shares: usershare template share %s "
4575 "does not exist.\n",
4576 Globals
.szUsershareTemplateShare
));
4581 /* Mark all existing usershares as pending delete. */
4582 for (iService
= iNumServices
- 1; iService
>= 0; iService
--) {
4583 if (VALID(iService
) && ServicePtrs
[iService
]->usershare
) {
4584 ServicePtrs
[iService
]->usershare
= USERSHARE_PENDING_DELETE
;
4588 dp
= opendir(usersharepath
);
4590 DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
4591 usersharepath
, strerror(errno
) ));
4595 for (num_dir_entries
= 0, num_bad_dir_entries
= 0, num_tmp_dir_entries
= 0;
4597 num_dir_entries
++ ) {
4599 const char *n
= de
->d_name
;
4601 /* Ignore . and .. */
4603 if ((n
[1] == '\0') || (n
[1] == '.' && n
[2] == '\0')) {
4609 /* Temporary file used when creating a share. */
4610 num_tmp_dir_entries
++;
4613 /* Allow 20% tmp entries. */
4614 if (num_tmp_dir_entries
> allowed_tmp_entries
) {
4615 DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
4616 "in directory %s\n",
4617 num_tmp_dir_entries
, usersharepath
));
4621 r
= process_usershare_file(usersharepath
, n
, snum_template
);
4623 /* Update the services count. */
4625 if (num_usershares
>= max_user_shares
) {
4626 DEBUG(0,("load_usershare_shares: max user shares reached "
4627 "on file %s in directory %s\n",
4628 n
, usersharepath
));
4631 } else if (r
== -1) {
4632 num_bad_dir_entries
++;
4635 /* Allow 20% bad entries. */
4636 if (num_bad_dir_entries
> allowed_bad_entries
) {
4637 DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
4638 "in directory %s\n",
4639 num_bad_dir_entries
, usersharepath
));
4643 /* Allow 20% bad entries. */
4644 if (num_dir_entries
> max_user_shares
+ allowed_bad_entries
) {
4645 DEBUG(0,("load_usershare_shares: too many total entries (%u) "
4646 "in directory %s\n",
4647 num_dir_entries
, usersharepath
));
4654 /* Sweep through and delete any non-refreshed usershares that are
4655 not currently in use. */
4656 tmp_ctx
= talloc_stackframe();
4657 for (iService
= iNumServices
- 1; iService
>= 0; iService
--) {
4658 if (VALID(iService
) && (ServicePtrs
[iService
]->usershare
== USERSHARE_PENDING_DELETE
)) {
4661 if (snumused
&& snumused(sconn
, iService
)) {
4665 servname
= lp_servicename(tmp_ctx
, iService
);
4667 /* Remove from the share ACL db. */
4668 DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
4670 delete_share_security(servname
);
4671 free_service_byindex(iService
);
4674 talloc_free(tmp_ctx
);
4676 return lp_numservices();
4679 /********************************************************
4680 Destroy global resources allocated in this file
4681 ********************************************************/
4683 void gfree_loadparm(void)
4689 /* Free resources allocated to services */
4691 for ( i
= 0; i
< iNumServices
; i
++ ) {
4693 free_service_byindex(i
);
4697 SAFE_FREE( ServicePtrs
);
4700 /* Now release all resources allocated to global
4701 parameters and the default service */
4703 free_global_parameters();
4707 /***************************************************************************
4708 Allow client apps to specify that they are a client
4709 ***************************************************************************/
4710 static void lp_set_in_client(bool b
)
4716 /***************************************************************************
4717 Determine if we're running in a client app
4718 ***************************************************************************/
4719 static bool lp_is_in_client(void)
4724 /***************************************************************************
4725 Load the services array from the services file. Return true on success,
4727 ***************************************************************************/
4729 static bool lp_load_ex(const char *pszFname
,
4733 bool initialize_globals
,
4734 bool allow_include_registry
,
4735 bool load_all_shares
)
4742 DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
4744 bInGlobalSection
= true;
4745 bGlobalOnly
= global_only
;
4746 bAllowIncludeRegistry
= allow_include_registry
;
4748 init_globals(initialize_globals
);
4752 if (save_defaults
) {
4757 if (!initialize_globals
) {
4758 free_param_opts(&Globals
.param_opt
);
4759 apply_lp_set_cmdline();
4762 lp_do_parameter(-1, "idmap config * : backend", Globals
.szIdmapBackend
);
4764 /* We get sections first, so have to start 'behind' to make up */
4767 if (lp_config_backend_is_file()) {
4768 n2
= talloc_sub_basic(talloc_tos(), get_current_username(),
4769 current_user_info
.domain
,
4772 smb_panic("lp_load_ex: out of memory");
4775 add_to_file_list(pszFname
, n2
);
4777 bRetval
= pm_process(n2
, do_section
, do_parameter
, NULL
);
4780 /* finish up the last section */
4781 DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval
)));
4783 if (iServiceIndex
>= 0) {
4784 bRetval
= service_ok(iServiceIndex
);
4788 if (lp_config_backend_is_registry()) {
4789 /* config backend changed to registry in config file */
4791 * We need to use this extra global variable here to
4792 * survive restart: init_globals uses this as a default
4793 * for ConfigBackend. Otherwise, init_globals would
4794 * send us into an endless loop here.
4796 config_backend
= CONFIG_BACKEND_REGISTRY
;
4798 DEBUG(1, ("lp_load_ex: changing to config backend "
4801 lp_kill_all_services();
4802 return lp_load_ex(pszFname
, global_only
, save_defaults
,
4803 add_ipc
, initialize_globals
,
4804 allow_include_registry
,
4807 } else if (lp_config_backend_is_registry()) {
4808 bRetval
= process_registry_globals();
4810 DEBUG(0, ("Illegal config backend given: %d\n",
4811 lp_config_backend()));
4815 if (bRetval
&& lp_registry_shares()) {
4816 if (load_all_shares
) {
4817 bRetval
= process_registry_shares();
4819 bRetval
= reload_registry_shares();
4824 char *serv
= lp_auto_services(talloc_tos());
4825 lp_add_auto_services(serv
);
4830 /* When 'restrict anonymous = 2' guest connections to ipc$
4832 lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
4833 if ( lp_enable_asu_support() ) {
4834 lp_add_ipc("ADMIN$", false);
4838 set_allowed_client_auth();
4840 if (lp_security() == SEC_ADS
&& strchr(lp_passwordserver(), ':')) {
4841 DEBUG(1, ("WARNING: The optional ':port' in password server = %s is deprecated\n",
4842 lp_passwordserver()));
4847 /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */
4848 /* if bWINSsupport is true and we are in the client */
4849 if (lp_is_in_client() && Globals
.bWINSsupport
) {
4850 lp_do_parameter(GLOBAL_SECTION_SNUM
, "wins server", "127.0.0.1");
4855 fault_configure(smb_panic_s3
);
4857 bAllowIncludeRegistry
= true;
4862 bool lp_load(const char *pszFname
,
4866 bool initialize_globals
)
4868 return lp_load_ex(pszFname
,
4873 true, /* allow_include_registry */
4874 false); /* load_all_shares*/
4877 bool lp_load_initial_only(const char *pszFname
)
4879 return lp_load_ex(pszFname
,
4880 true, /* global only */
4881 false, /* save_defaults */
4882 false, /* add_ipc */
4883 true, /* initialize_globals */
4884 false, /* allow_include_registry */
4885 false); /* load_all_shares*/
4889 * most common lp_load wrapper, loading only the globals
4891 bool lp_load_global(const char *file_name
)
4893 return lp_load_ex(file_name
,
4894 true, /* global_only */
4895 false, /* save_defaults */
4896 false, /* add_ipc */
4897 true, /* initialize_globals */
4898 true, /* allow_include_registry */
4899 false); /* load_all_shares*/
4903 * lp_load wrapper, especially for clients
4905 bool lp_load_client(const char *file_name
)
4907 lp_set_in_client(true);
4909 return lp_load_global(file_name
);
4913 * lp_load wrapper, loading only globals, but intended
4914 * for subsequent calls, not reinitializing the globals
4917 bool lp_load_global_no_reinit(const char *file_name
)
4919 return lp_load_ex(file_name
,
4920 true, /* global_only */
4921 false, /* save_defaults */
4922 false, /* add_ipc */
4923 false, /* initialize_globals */
4924 true, /* allow_include_registry */
4925 false); /* load_all_shares*/
4929 * lp_load wrapper, especially for clients, no reinitialization
4931 bool lp_load_client_no_reinit(const char *file_name
)
4933 lp_set_in_client(true);
4935 return lp_load_global_no_reinit(file_name
);
4938 bool lp_load_with_registry_shares(const char *pszFname
,
4942 bool initialize_globals
)
4944 return lp_load_ex(pszFname
,
4949 true, /* allow_include_registry */
4950 true); /* load_all_shares*/
4953 /***************************************************************************
4954 Return the max number of services.
4955 ***************************************************************************/
4957 int lp_numservices(void)
4959 return (iNumServices
);
4962 /***************************************************************************
4963 Display the contents of the services array in human-readable form.
4964 ***************************************************************************/
4966 void lp_dump(FILE *f
, bool show_defaults
, int maxtoprint
)
4971 defaults_saved
= false;
4975 dump_a_service(&sDefault
, f
);
4977 for (iService
= 0; iService
< maxtoprint
; iService
++) {
4979 lp_dump_one(f
, show_defaults
, iService
);
4983 /***************************************************************************
4984 Display the contents of one service in human-readable form.
4985 ***************************************************************************/
4987 void lp_dump_one(FILE * f
, bool show_defaults
, int snum
)
4990 if (ServicePtrs
[snum
]->szService
[0] == '\0')
4992 dump_a_service(ServicePtrs
[snum
], f
);
4996 /***************************************************************************
4997 Return the number of the service with the given name, or -1 if it doesn't
4998 exist. Note that this is a DIFFERENT ANIMAL from the internal function
4999 getservicebyname()! This works ONLY if all services have been loaded, and
5000 does not copy the found service.
5001 ***************************************************************************/
5003 int lp_servicenumber(const char *pszServiceName
)
5006 fstring serviceName
;
5008 if (!pszServiceName
) {
5009 return GLOBAL_SECTION_SNUM
;
5012 for (iService
= iNumServices
- 1; iService
>= 0; iService
--) {
5013 if (VALID(iService
) && ServicePtrs
[iService
]->szService
) {
5015 * The substitution here is used to support %U is
5018 fstrcpy(serviceName
, ServicePtrs
[iService
]->szService
);
5019 standard_sub_basic(get_current_username(),
5020 current_user_info
.domain
,
5021 serviceName
,sizeof(serviceName
));
5022 if (strequal(serviceName
, pszServiceName
)) {
5028 if (iService
>= 0 && ServicePtrs
[iService
]->usershare
== USERSHARE_VALID
) {
5029 struct timespec last_mod
;
5031 if (!usershare_exists(iService
, &last_mod
)) {
5032 /* Remove the share security tdb entry for it. */
5033 delete_share_security(lp_servicename(talloc_tos(), iService
));
5034 /* Remove it from the array. */
5035 free_service_byindex(iService
);
5036 /* Doesn't exist anymore. */
5037 return GLOBAL_SECTION_SNUM
;
5040 /* Has it been modified ? If so delete and reload. */
5041 if (timespec_compare(&ServicePtrs
[iService
]->usershare_last_mod
,
5043 /* Remove it from the array. */
5044 free_service_byindex(iService
);
5045 /* and now reload it. */
5046 iService
= load_usershare_service(pszServiceName
);
5051 DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName
));
5052 return GLOBAL_SECTION_SNUM
;
5058 /*******************************************************************
5059 A useful volume label function.
5060 ********************************************************************/
5062 const char *volume_label(TALLOC_CTX
*ctx
, int snum
)
5065 const char *label
= lp_volume(ctx
, snum
);
5067 label
= lp_servicename(ctx
, snum
);
5070 /* This returns a 33 byte guarenteed null terminated string. */
5071 ret
= talloc_strndup(ctx
, label
, 32);
5078 /*******************************************************************
5079 Get the default server type we will announce as via nmbd.
5080 ********************************************************************/
5082 int lp_default_server_announce(void)
5084 int default_server_announce
= 0;
5085 default_server_announce
|= SV_TYPE_WORKSTATION
;
5086 default_server_announce
|= SV_TYPE_SERVER
;
5087 default_server_announce
|= SV_TYPE_SERVER_UNIX
;
5089 /* note that the flag should be set only if we have a
5090 printer service but nmbd doesn't actually load the
5091 services so we can't tell --jerry */
5093 default_server_announce
|= SV_TYPE_PRINTQ_SERVER
;
5095 default_server_announce
|= SV_TYPE_SERVER_NT
;
5096 default_server_announce
|= SV_TYPE_NT
;
5098 switch (lp_server_role()) {
5099 case ROLE_DOMAIN_MEMBER
:
5100 default_server_announce
|= SV_TYPE_DOMAIN_MEMBER
;
5102 case ROLE_DOMAIN_PDC
:
5103 default_server_announce
|= SV_TYPE_DOMAIN_CTRL
;
5105 case ROLE_DOMAIN_BDC
:
5106 default_server_announce
|= SV_TYPE_DOMAIN_BAKCTRL
;
5108 case ROLE_STANDALONE
:
5112 if (lp_time_server())
5113 default_server_announce
|= SV_TYPE_TIME_SOURCE
;
5115 if (lp_host_msdfs())
5116 default_server_announce
|= SV_TYPE_DFS_SERVER
;
5118 return default_server_announce
;
5121 /***********************************************************
5122 If we are PDC then prefer us as DMB
5123 ************************************************************/
5125 bool lp_domain_master(void)
5127 if (Globals
.domain_master
== Auto
)
5128 return (lp_server_role() == ROLE_DOMAIN_PDC
);
5130 return (bool)Globals
.domain_master
;
5133 /***********************************************************
5134 If we are PDC then prefer us as DMB
5135 ************************************************************/
5137 static bool lp_domain_master_true_or_auto(void)
5139 if (Globals
.domain_master
) /* auto or yes */
5145 /***********************************************************
5146 If we are DMB then prefer us as LMB
5147 ************************************************************/
5149 bool lp_preferred_master(void)
5151 if (Globals
.iPreferredMaster
== Auto
)
5152 return (lp_local_master() && lp_domain_master());
5154 return (bool)Globals
.iPreferredMaster
;
5157 /*******************************************************************
5159 ********************************************************************/
5161 void lp_remove_service(int snum
)
5163 ServicePtrs
[snum
]->valid
= false;
5164 invalid_services
[num_invalid_services
++] = snum
;
5167 /*******************************************************************
5169 ********************************************************************/
5171 void lp_copy_service(int snum
, const char *new_name
)
5173 do_section(new_name
, NULL
);
5175 snum
= lp_servicenumber(new_name
);
5177 char *name
= lp_servicename(talloc_tos(), snum
);
5178 lp_do_parameter(snum
, "copy", name
);
5183 const char *lp_printername(TALLOC_CTX
*ctx
, int snum
)
5185 const char *ret
= lp__printername(talloc_tos(), snum
);
5186 if (ret
== NULL
|| *ret
== '\0') {
5187 ret
= lp_const_servicename(snum
);
5194 /***********************************************************
5195 Allow daemons such as winbindd to fix their logfile name.
5196 ************************************************************/
5198 void lp_set_logfile(const char *name
)
5200 string_set(&Globals
.logfile
, name
);
5201 debug_set_logfile(name
);
5204 /*******************************************************************
5205 Return the max print jobs per queue.
5206 ********************************************************************/
5208 int lp_maxprintjobs(int snum
)
5210 int maxjobs
= LP_SNUM_OK(snum
) ? ServicePtrs
[snum
]->iMaxPrintJobs
: sDefault
.iMaxPrintJobs
;
5211 if (maxjobs
<= 0 || maxjobs
>= PRINT_MAX_JOBID
)
5212 maxjobs
= PRINT_MAX_JOBID
- 1;
5217 const char *lp_printcapname(void)
5219 if ((Globals
.szPrintcapname
!= NULL
) &&
5220 (Globals
.szPrintcapname
[0] != '\0'))
5221 return Globals
.szPrintcapname
;
5223 if (sDefault
.iPrinting
== PRINT_CUPS
) {
5231 if (sDefault
.iPrinting
== PRINT_BSD
)
5232 return "/etc/printcap";
5234 return PRINTCAP_NAME
;
5237 static uint32 spoolss_state
;
5239 bool lp_disable_spoolss( void )
5241 if ( spoolss_state
== SVCCTL_STATE_UNKNOWN
)
5242 spoolss_state
= lp__disable_spoolss() ? SVCCTL_STOPPED
: SVCCTL_RUNNING
;
5244 return spoolss_state
== SVCCTL_STOPPED
? true : false;
5247 void lp_set_spoolss_state( uint32 state
)
5249 SMB_ASSERT( (state
== SVCCTL_STOPPED
) || (state
== SVCCTL_RUNNING
) );
5251 spoolss_state
= state
;
5254 uint32
lp_get_spoolss_state( void )
5256 return lp_disable_spoolss() ? SVCCTL_STOPPED
: SVCCTL_RUNNING
;
5259 /*******************************************************************
5260 Ensure we don't use sendfile if server smb signing is active.
5261 ********************************************************************/
5263 bool lp_use_sendfile(int snum
, struct smb_signing_state
*signing_state
)
5265 bool sign_active
= false;
5267 /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
5268 if (get_Protocol() < PROTOCOL_NT1
) {
5271 if (signing_state
) {
5272 sign_active
= smb_signing_is_active(signing_state
);
5274 return (lp__use_sendfile(snum
) &&
5275 (get_remote_arch() != RA_WIN95
) &&
5279 /*******************************************************************
5280 Turn off sendfile if we find the underlying OS doesn't support it.
5281 ********************************************************************/
5283 void set_use_sendfile(int snum
, bool val
)
5285 if (LP_SNUM_OK(snum
))
5286 ServicePtrs
[snum
]->bUseSendfile
= val
;
5288 sDefault
.bUseSendfile
= val
;
5291 /*******************************************************************
5292 Turn off storing DOS attributes if this share doesn't support it.
5293 ********************************************************************/
5295 void set_store_dos_attributes(int snum
, bool val
)
5297 if (!LP_SNUM_OK(snum
))
5299 ServicePtrs
[(snum
)]->bStoreDosAttributes
= val
;
5302 void lp_set_mangling_method(const char *new_method
)
5304 string_set(&Globals
.szManglingMethod
, new_method
);
5307 /*******************************************************************
5308 Global state for POSIX pathname processing.
5309 ********************************************************************/
5311 static bool posix_pathnames
;
5313 bool lp_posix_pathnames(void)
5315 return posix_pathnames
;
5318 /*******************************************************************
5319 Change everything needed to ensure POSIX pathname processing (currently
5321 ********************************************************************/
5323 void lp_set_posix_pathnames(void)
5325 posix_pathnames
= true;
5328 /*******************************************************************
5329 Global state for POSIX lock processing - CIFS unix extensions.
5330 ********************************************************************/
5332 bool posix_default_lock_was_set
;
5333 static enum brl_flavour posix_cifsx_locktype
; /* By default 0 == WINDOWS_LOCK */
5335 enum brl_flavour
lp_posix_cifsu_locktype(files_struct
*fsp
)
5337 if (posix_default_lock_was_set
) {
5338 return posix_cifsx_locktype
;
5340 return fsp
->posix_open
? POSIX_LOCK
: WINDOWS_LOCK
;
5344 /*******************************************************************
5345 ********************************************************************/
5347 void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val
)
5349 posix_default_lock_was_set
= true;
5350 posix_cifsx_locktype
= val
;
5353 int lp_min_receive_file_size(void)
5355 if (Globals
.iminreceivefile
< 0) {
5358 return MIN(Globals
.iminreceivefile
, BUFFER_SIZE
);
5361 /*******************************************************************
5362 If socket address is an empty character string, it is necessary to
5363 define it as "0.0.0.0".
5364 ********************************************************************/
5366 const char *lp_socket_address(void)
5368 char *sock_addr
= Globals
.szSocketAddress
;
5370 if (sock_addr
[0] == '\0'){
5371 string_set(&Globals
.szSocketAddress
, "0.0.0.0");
5373 return Globals
.szSocketAddress
;
5376 /*******************************************************************
5377 Safe wide links checks.
5378 This helper function always verify the validity of wide links,
5379 even after a configuration file reload.
5380 ********************************************************************/
5382 static bool lp_widelinks_internal(int snum
)
5384 return (bool)(LP_SNUM_OK(snum
)? ServicePtrs
[(snum
)]->bWidelinks
:
5385 sDefault
.bWidelinks
);
5388 void widelinks_warning(int snum
)
5390 if (lp_allow_insecure_widelinks()) {
5394 if (lp_unix_extensions() && lp_widelinks_internal(snum
)) {
5395 DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
5396 "These parameters are incompatible. "
5397 "Wide links will be disabled for this share.\n",
5398 lp_servicename(talloc_tos(), snum
) ));
5402 bool lp_widelinks(int snum
)
5404 /* wide links is always incompatible with unix extensions */
5405 if (lp_unix_extensions()) {
5407 * Unless we have "allow insecure widelinks"
5410 if (!lp_allow_insecure_widelinks()) {
5415 return lp_widelinks_internal(snum
);
5418 bool lp_writeraw(void)
5420 if (lp_async_smb_echo_handler()) {
5423 return lp__writeraw();
5426 bool lp_readraw(void)
5428 if (lp_async_smb_echo_handler()) {
5431 return lp__readraw();
5434 int lp_server_role(void)
5436 return lp_find_server_role(lp__server_role(),
5438 lp__domain_logons(),
5439 lp_domain_master_true_or_auto());
5442 int lp_security(void)
5444 return lp_find_security(lp__server_role(),