X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fparam%2Floadparm.c;h=eaff9e6ec4c51b1429fbf4f12e8b82f117fe319f;hb=429133f5ad716019995f2ae6407ce563e1b6872b;hp=cb568256c7e06a398663de13e1f36074822d964d;hpb=d9a842b26f306a6328e0fb4f226ed8292a8c221a;p=samba.git diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index cb568256c7e..eaff9e6ec4c 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -54,9 +54,16 @@ #include "includes.h" #include "printing.h" +#ifdef HAVE_SYS_SYSCTL_H +#include +#endif + +#ifdef HAVE_HTTPCONNECTENCRYPT +#include +#endif + bool bLoaded = False; -extern enum protocol_types Protocol; extern userdom_struct current_user_info; #ifndef GLOBAL_NAME @@ -144,7 +151,6 @@ struct global { int iAfsTokenLifetime; char *szLogNtTokenCommand; char *szUsernameMap; - bool bForceUsernameMap; char *szLogonScript; char *szLogonPath; char *szLogonDrive; @@ -154,6 +160,7 @@ struct global { char *szRemoteAnnounce; char *szRemoteBrowseSync; char *szSocketAddress; + bool bNmbdBindExplicitBroadcast; char *szNISHomeMapName; char *szAnnounceVersion; /* This is initialised in init_globals */ char *szWorkgroup; @@ -196,6 +203,7 @@ struct global { bool bWinbindOfflineLogon; bool bWinbindNormalizeNames; bool bWinbindRpcOnly; + bool bCreateKrb5Conf; char *szIdmapBackend; char *szIdmapAllocBackend; char *szAddShareCommand; @@ -243,7 +251,7 @@ struct global { int oplock_break_wait_time; int winbind_cache_time; int winbind_reconnect_delay; - int winbind_max_idle_children; + int winbind_max_clients; char **szWinbindNssInfo; int iLockSpinTime; char *szLdapMachineSuffix; @@ -252,16 +260,20 @@ struct global { char *szLdapGroupSuffix; int ldap_ssl; bool ldap_ssl_ads; + int ldap_deref; + int ldap_follow_referral; char *szLdapSuffix; char *szLdapAdminDn; int ldap_debug_level; int ldap_debug_threshold; int iAclCompat; char *szCupsServer; + int CupsEncrypt; char *szIPrintServer; char *ctdbdSocket; char **szClusterAddresses; bool clustering; + int ctdb_timeout; int ldap_passwd_sync; int ldap_replication_sleep; int ldap_timeout; /* This is initialised in init_globals */ @@ -313,6 +325,7 @@ struct global { bool bClientNTLMv2Auth; bool bClientPlaintextAuth; bool bClientUseSpnego; + bool client_use_spnego_principal; bool bDebugPrefixTimestamp; bool bDebugHiresTimestamp; bool bDebugPid; @@ -358,7 +371,7 @@ struct service { bool valid; bool autoloaded; int usershare; - time_t usershare_last_mod; + struct timespec usershare_last_mod; char *szService; char *szPath; char *szUsername; @@ -502,7 +515,7 @@ static struct service sDefault = { True, /* valid */ False, /* not autoloaded */ 0, /* not a usershare */ - (time_t)0, /* No last mod time */ + {0, }, /* No last mod time */ NULL, /* szService */ NULL, /* szPath */ NULL, /* szUsername */ @@ -595,7 +608,7 @@ static struct service sDefault = { True, /* bLevel2OpLocks */ False, /* bOnlyUser */ True, /* bMangledNames */ - True, /* bWidelinks */ + false, /* bWidelinks */ True, /* bSymlinks */ False, /* bSyncAlways */ False, /* bStrictAllocate */ @@ -678,7 +691,10 @@ static void set_allowed_client_auth(void); static void *lp_local_ptr(struct service *service, void *ptr); +static void add_to_file_list(const char *fname, const char *subfname); + static const struct enum_list enum_protocol[] = { + {PROTOCOL_SMB2, "SMB2"}, {PROTOCOL_NT1, "NT1"}, {PROTOCOL_LANMAN2, "LANMAN2"}, {PROTOCOL_LANMAN1, "LANMAN1"}, @@ -733,6 +749,20 @@ static const struct enum_list enum_ldap_ssl[] = { {-1, NULL} }; +/* LDAP Dereferencing Alias types */ +#define SAMBA_LDAP_DEREF_NEVER 0 +#define SAMBA_LDAP_DEREF_SEARCHING 1 +#define SAMBA_LDAP_DEREF_FINDING 2 +#define SAMBA_LDAP_DEREF_ALWAYS 3 + +static const struct enum_list enum_ldap_deref[] = { + {SAMBA_LDAP_DEREF_NEVER, "never"}, + {SAMBA_LDAP_DEREF_SEARCHING, "searching"}, + {SAMBA_LDAP_DEREF_FINDING, "finding"}, + {SAMBA_LDAP_DEREF_ALWAYS, "always"}, + {-1, "auto"} +}; + static const struct enum_list enum_ldap_passwd_sync[] = { {LDAP_PASSWD_SYNC_OFF, "no"}, {LDAP_PASSWD_SYNC_OFF, "off"}, @@ -775,6 +805,8 @@ static const struct enum_list enum_case[] = { {-1, NULL} }; + + static const struct enum_list enum_bool_auto[] = { {False, "No"}, {False, "False"}, @@ -879,7 +911,7 @@ static const struct enum_list enum_kerberos_method[] = { /* Note: We do not initialise the defaults union - it is not allowed in ANSI C * - * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit + * The FLAG_HIDE is explicit. Parameters set this way do NOT appear in any edit * screen in SWAT. This is used to exclude parameters as well as to squash all * parameters that have been duplicated by pseudonyms. * @@ -888,7 +920,7 @@ static const struct enum_list enum_kerberos_method[] = { * Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in * respective views. * - * NOTE2: Handling of duplicated (synonym) paramters: + * NOTE2: Handling of duplicated (synonym) parameters: * Only the first occurance of a parameter should be enabled by FLAG_BASIC * and/or FLAG_ADVANCED. All duplicates following the first mention should be * set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred @@ -1033,7 +1065,7 @@ static struct parm_struct parm_table[] = { .ptr = &Globals.ConfigBackend, .special = NULL, .enum_list = enum_config_backend, - .flags = FLAG_ADVANCED, + .flags = FLAG_HIDE|FLAG_ADVANCED|FLAG_META, }, {N_("Security Options"), P_SEP, P_SEPARATOR}, @@ -1282,15 +1314,6 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, - { - .label = "force username map", - .type = P_BOOL, - .p_class = P_GLOBAL, - .ptr = &Globals.bForceUsernameMap, - .special = NULL, - .enum_list = NULL, - .flags = FLAG_ADVANCED, - }, { .label = "password level", .type = P_INTEGER, @@ -1372,6 +1395,15 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "client use spnego principal", + .type = P_BOOL, + .p_class = P_GLOBAL, + .ptr = &Globals.client_use_spnego_principal, + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, { .label = "username", .type = P_STRING, @@ -2497,7 +2529,7 @@ static struct parm_struct parm_table[] = { .ptr = &sDefault.iWriteCacheSize, .special = NULL, .enum_list = NULL, - .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_DEPRECATED, + .flags = FLAG_ADVANCED | FLAG_SHARE, }, { .label = "name cache timeout", @@ -2535,6 +2567,15 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED | FLAG_GLOBAL, }, + { + .label = "ctdb timeout", + .type = P_INTEGER, + .p_class = P_GLOBAL, + .ptr = &Globals.ctdb_timeout, + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED | FLAG_GLOBAL, + }, {N_("Printing Options"), P_SEP, P_SEPARATOR}, @@ -2638,6 +2679,16 @@ static struct parm_struct parm_table[] = { .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL, }, { + .label = "cups encrypt", + .type = P_ENUM, + .p_class = P_GLOBAL, + .ptr = &Globals.CupsEncrypt, + .special = NULL, + .enum_list = enum_bool_auto, + .flags = FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL, + }, + { + .label = "cups connection timeout", .type = P_INTEGER, .p_class = P_GLOBAL, @@ -3249,6 +3300,8 @@ static struct parm_struct parm_table[] = { .type = P_LIST, .p_class = P_GLOBAL, .ptr = &Globals.szInitLogonDelayedHosts, + .special = NULL, + .enum_list = NULL, .flags = FLAG_ADVANCED, }, @@ -3257,6 +3310,8 @@ static struct parm_struct parm_table[] = { .type = P_INTEGER, .p_class = P_GLOBAL, .ptr = &Globals.InitLogonDelay, + .special = NULL, + .enum_list = NULL, .flags = FLAG_ADVANCED, }, @@ -3345,22 +3400,22 @@ static struct parm_struct parm_table[] = { .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT, }, { - .label = "access based share enum", + .label = "browsable", .type = P_BOOL, .p_class = P_LOCAL, - .ptr = &sDefault.bAccessBasedShareEnum, + .ptr = &sDefault.bBrowseable, .special = NULL, .enum_list = NULL, - .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE + .flags = FLAG_HIDE, }, { - .label = "browsable", + .label = "access based share enum", .type = P_BOOL, .p_class = P_LOCAL, - .ptr = &sDefault.bBrowseable, + .ptr = &sDefault.bAccessBasedShareEnum, .special = NULL, .enum_list = NULL, - .flags = FLAG_HIDE, + .flags = FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE }, { .label = "enhanced browsing", @@ -3641,6 +3696,24 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "ldap deref", + .type = P_ENUM, + .p_class = P_GLOBAL, + .ptr = &Globals.ldap_deref, + .special = NULL, + .enum_list = enum_ldap_deref, + .flags = FLAG_ADVANCED, + }, + { + .label = "ldap follow referral", + .type = P_ENUM, + .p_class = P_GLOBAL, + .ptr = &Globals.ldap_follow_referral, + .special = NULL, + .enum_list = enum_bool_auto, + .flags = FLAG_ADVANCED, + }, { .label = "ldap timeout", .type = P_INTEGER, @@ -3744,7 +3817,7 @@ static struct parm_struct parm_table[] = { .ptr = &Globals.szConfigFile, .special = NULL, .enum_list = NULL, - .flags = FLAG_HIDE, + .flags = FLAG_HIDE|FLAG_META, }, { .label = "preload", @@ -3928,6 +4001,15 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "nmbd bind explicit broadcast", + .type = P_BOOL, + .p_class = P_GLOBAL, + .ptr = &Globals.bNmbdBindExplicitBroadcast, + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, { .label = "homedir map", .type = P_STRING, @@ -4007,7 +4089,7 @@ static struct parm_struct parm_table[] = { .ptr = &sDefault.szInclude, .special = handle_include, .enum_list = NULL, - .flags = FLAG_HIDE, + .flags = FLAG_HIDE|FLAG_META, }, { .label = "preexec", @@ -4268,7 +4350,7 @@ static struct parm_struct parm_table[] = { .ptr = &sDefault.bFakeDirCreateTimes, .special = NULL, .enum_list = NULL, - .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL, + .flags = FLAG_ADVANCED | FLAG_GLOBAL, }, { .label = "panic action", @@ -4469,6 +4551,15 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "winbind max clients", + .type = P_INTEGER, + .p_class = P_GLOBAL, + .ptr = &Globals.winbind_max_clients, + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, { .label = "winbind enum users", .type = P_BOOL, @@ -4568,6 +4659,15 @@ static struct parm_struct parm_table[] = { .enum_list = NULL, .flags = FLAG_ADVANCED, }, + { + .label = "create krb5 conf", + .type = P_BOOL, + .p_class = P_GLOBAL, + .ptr = &Globals.bCreateKrb5Conf, + .special = NULL, + .enum_list = NULL, + .flags = FLAG_ADVANCED, + }, {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0} }; @@ -4649,7 +4749,7 @@ static void init_printer_values(struct service *pService) string_set(&pService->szLpqcommand, "vlp lpq %p"); string_set(&pService->szLprmcommand, "vlp lprm %p %j"); string_set(&pService->szLppausecommand, "vlp lppause %p %j"); - string_set(&pService->szLpresumecommand, "vlp lpresum %p %j"); + string_set(&pService->szLpresumecommand, "vlp lpresume %p %j"); string_set(&pService->szQueuepausecommand, "vlp queuepause %p"); string_set(&pService->szQueueresumecommand, "vlp queueresume %p"); break; @@ -4665,33 +4765,50 @@ static void init_printer_values(struct service *pService) */ static int max_open_files(void) { - int sysctl_max; - struct rlimit rl; - bool sysctl_worked = false, rlimit_worked = false; + int sysctl_max = MAX_OPEN_FILES; + int rlimit_max = MAX_OPEN_FILES; #ifdef HAVE_SYSCTLBYNAME - size_t size = sizeof(sysctl_max); - if (sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL,0)==0) - sysctl_worked = true; + { + size_t size = sizeof(sysctl_max); + sysctlbyname("kern.maxfilesperproc", &sysctl_max, &size, NULL, + 0); + } #endif - if (getrlimit(RLIMIT_NOFILE, &rl) == 0) - rlimit_worked = true; +#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)) + { + struct rlimit rl; + + ZERO_STRUCT(rl); - if (sysctl_worked) { - if ((!rlimit_worked) || - (rl.rlim_cur == RLIM_INFINITY) || - (rl.rlim_cur > sysctl_max)) - return sysctl_max; - else - return rl.rlim_cur; - } else { - if ((!rlimit_worked) || - (rl.rlim_cur == RLIM_INFINITY)) - return MAX_OPEN_FILES; - else - return rl.rlim_cur; + if (getrlimit(RLIMIT_NOFILE, &rl) == 0) + rlimit_max = rl.rlim_cur; + +#if defined(RLIM_INFINITY) + if(rl.rlim_cur == RLIM_INFINITY) + rlimit_max = MAX_OPEN_FILES; + } +#endif +#endif + + if (sysctl_max < MIN_OPEN_FILES_WINDOWS) { + DEBUG(2,("max_open_files: increasing sysctl_max (%d) to " + "minimum Windows limit (%d)\n", + sysctl_max, + MIN_OPEN_FILES_WINDOWS)); + sysctl_max = MIN_OPEN_FILES_WINDOWS; + } + + if (rlimit_max < MIN_OPEN_FILES_WINDOWS) { + DEBUG(2,("rlimit_max: increasing rlimit_max (%d) to " + "minimum Windows limit (%d)\n", + rlimit_max, + MIN_OPEN_FILES_WINDOWS)); + rlimit_max = MIN_OPEN_FILES_WINDOWS; } + + return MIN(sysctl_max, rlimit_max); } /** @@ -4870,6 +4987,11 @@ static void init_globals(bool first_time_only) string_set(&Globals.szCacheDir, get_dyn_CACHEDIR()); string_set(&Globals.szPidDir, get_dyn_PIDDIR()); string_set(&Globals.szSocketAddress, "0.0.0.0"); + /* + * By default support explicit binding to broadcast + * addresses. + */ + Globals.bNmbdBindExplicitBroadcast = true; if (asprintf(&s, "Samba %s", samba_version_string()) < 0) { smb_panic("init_globals: ENOMEM"); @@ -4935,7 +5057,7 @@ static void init_globals(bool first_time_only) Globals.bTimestampLogs = True; string_set(&Globals.szLogLevel, "0"); Globals.bDebugPrefixTimestamp = False; - Globals.bDebugHiresTimestamp = False; + Globals.bDebugHiresTimestamp = true; Globals.bDebugPid = False; Globals.bDebugUid = False; Globals.bDebugClass = False; @@ -4984,12 +5106,13 @@ static void init_globals(bool first_time_only) #endif Globals.bUnixExtensions = True; Globals.bResetOnZeroVC = False; + Globals.bCreateKrb5Conf = true; /* hostname lookups can be very expensive and are broken on a large number of sites (tridge) */ Globals.bHostnameLookups = False; - string_set(&Globals.szPassdbBackend, "smbpasswd"); + string_set(&Globals.szPassdbBackend, "tdbsam"); string_set(&Globals.szLdapSuffix, ""); string_set(&Globals.szLdapMachineSuffix, ""); string_set(&Globals.szLdapUserSuffix, ""); @@ -4999,9 +5122,11 @@ static void init_globals(bool first_time_only) string_set(&Globals.szLdapAdminDn, ""); Globals.ldap_ssl = LDAP_SSL_START_TLS; Globals.ldap_ssl_ads = False; + Globals.ldap_deref = -1; Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF; Globals.ldap_delete_dn = False; Globals.ldap_replication_sleep = 1000; /* wait 1 sec for replication */ + Globals.ldap_follow_referral = Auto; Globals.ldap_timeout = LDAP_DEFAULT_TIMEOUT; Globals.ldap_connection_timeout = LDAP_CONNECTION_DEFAULT_TIMEOUT; Globals.ldap_page_size = LDAP_PAGE_SIZE; @@ -5057,9 +5182,11 @@ static void init_globals(bool first_time_only) string_set(&Globals.ctdbdSocket, ""); Globals.szClusterAddresses = NULL; Globals.clustering = False; + Globals.ctdb_timeout = 0; Globals.winbind_cache_time = 300; /* 5 minutes */ Globals.winbind_reconnect_delay = 30; /* 30 seconds */ + Globals.winbind_max_clients = 200; Globals.bWinbindEnumUsers = False; Globals.bWinbindEnumGroups = False; Globals.bWinbindUseDefaultDomain = False; @@ -5132,6 +5259,9 @@ static char *lp_string(const char *s) #if 0 DEBUG(10, ("lp_string(%s)\n", s)); #endif + if (!s) { + return NULL; + } ret = talloc_sub_basic(ctx, get_current_username(), @@ -5188,9 +5318,9 @@ static char *lp_string(const char *s) char fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);} FN_GLOBAL_STRING(lp_smb_ports, &Globals.smb_ports) -FN_GLOBAL_STRING(lp_dos_charset, &Globals.dos_charset) -FN_GLOBAL_STRING(lp_unix_charset, &Globals.unix_charset) -FN_GLOBAL_STRING(lp_display_charset, &Globals.display_charset) +FN_GLOBAL_CONST_STRING(lp_dos_charset, &Globals.dos_charset) +FN_GLOBAL_CONST_STRING(lp_unix_charset, &Globals.unix_charset) +FN_GLOBAL_CONST_STRING(lp_display_charset, &Globals.display_charset) FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile) FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile) FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile) @@ -5246,13 +5376,13 @@ FN_GLOBAL_CONST_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap) FN_GLOBAL_INTEGER(lp_afs_token_lifetime, &Globals.iAfsTokenLifetime) FN_GLOBAL_STRING(lp_log_nt_token_command, &Globals.szLogNtTokenCommand) FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap) -FN_GLOBAL_BOOL(lp_force_username_map, &Globals.bForceUsernameMap) FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript) FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath) FN_GLOBAL_CONST_STRING(lp_logon_drive, &Globals.szLogonDrive) FN_GLOBAL_CONST_STRING(lp_logon_home, &Globals.szLogonHome) FN_GLOBAL_STRING(lp_remote_announce, &Globals.szRemoteAnnounce) FN_GLOBAL_STRING(lp_remote_browse_sync, &Globals.szRemoteBrowseSync) +FN_GLOBAL_BOOL(lp_nmbd_bind_explicit_broadcast, &Globals.bNmbdBindExplicitBroadcast) FN_GLOBAL_LIST(lp_wins_server_list, &Globals.szWINSservers) FN_GLOBAL_LIST(lp_interfaces, &Globals.szInterfaces) FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName) @@ -5336,6 +5466,7 @@ FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets) FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon) FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames) FN_GLOBAL_BOOL(lp_winbind_rpc_only, &Globals.bWinbindRpcOnly) +FN_GLOBAL_BOOL(lp_create_krb5_conf, &Globals.bCreateKrb5Conf) FN_GLOBAL_CONST_STRING(lp_idmap_backend, &Globals.szIdmapBackend) FN_GLOBAL_STRING(lp_idmap_alloc_backend, &Globals.szIdmapAllocBackend) @@ -5348,6 +5479,8 @@ FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix) FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn) FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl) FN_GLOBAL_BOOL(lp_ldap_ssl_ads, &Globals.ldap_ssl_ads) +FN_GLOBAL_INTEGER(lp_ldap_deref, &Globals.ldap_deref) +FN_GLOBAL_INTEGER(lp_ldap_follow_referral, &Globals.ldap_follow_referral) FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync) FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn) FN_GLOBAL_INTEGER(lp_ldap_replication_sleep, &Globals.ldap_replication_sleep) @@ -5424,6 +5557,7 @@ FN_GLOBAL_BOOL(lp_use_mmap, &Globals.bUseMmap) FN_GLOBAL_BOOL(lp_unix_extensions, &Globals.bUnixExtensions) FN_GLOBAL_BOOL(lp_use_spnego, &Globals.bUseSpnego) FN_GLOBAL_BOOL(lp_client_use_spnego, &Globals.bClientUseSpnego) +FN_GLOBAL_BOOL(lp_client_use_spnego_principal, &Globals.client_use_spnego_principal) FN_GLOBAL_BOOL(lp_hostname_lookups, &Globals.bHostnameLookups) FN_LOCAL_PARM_BOOL(lp_change_notify, bChangeNotify) FN_LOCAL_PARM_BOOL(lp_kernel_change_notify, bKernelChangeNotify) @@ -5481,11 +5615,30 @@ FN_LOCAL_LIST(lp_admin_users, szAdminUsers) FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList) FN_LOCAL_STRING(lp_cups_options, szCupsOptions) FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer) +int lp_cups_encrypt(void) +{ + int result = 0; +#ifdef HAVE_HTTPCONNECTENCRYPT + switch (Globals.CupsEncrypt) { + case Auto: + result = HTTP_ENCRYPT_REQUIRED; + break; + case True: + result = HTTP_ENCRYPT_ALWAYS; + break; + case False: + result = HTTP_ENCRYPT_NEVER; + break; + } +#endif + return result; +} FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer) FN_GLOBAL_INTEGER(lp_cups_connection_timeout, &Globals.cups_connection_timeout) FN_GLOBAL_CONST_STRING(lp_ctdbd_socket, &Globals.ctdbdSocket) FN_GLOBAL_LIST(lp_cluster_addresses, &Globals.szClusterAddresses) FN_GLOBAL_BOOL(lp_clustering, &Globals.clustering) +FN_GLOBAL_INTEGER(lp_ctdb_timeout, &Globals.ctdb_timeout) FN_LOCAL_STRING(lp_printcommand, szPrintcommand) FN_LOCAL_STRING(lp_lpqcommand, szLpqcommand) FN_LOCAL_STRING(lp_lprmcommand, szLprmcommand) @@ -5545,7 +5698,6 @@ FN_LOCAL_BOOL(lp_oplocks, bOpLocks) FN_LOCAL_BOOL(lp_level2_oplocks, bLevel2OpLocks) FN_LOCAL_BOOL(lp_onlyuser, bOnlyUser) FN_LOCAL_PARM_BOOL(lp_manglednames, bMangledNames) -FN_LOCAL_BOOL(lp_widelinks, bWidelinks) FN_LOCAL_BOOL(lp_symlinks, bSymlinks) FN_LOCAL_BOOL(lp_syncalways, bSyncAlways) FN_LOCAL_BOOL(lp_strict_allocate, bStrictAllocate) @@ -5602,6 +5754,7 @@ FN_LOCAL_INTEGER(lp_smb_encrypt, ismb_encrypt) FN_LOCAL_CHAR(lp_magicchar, magic_char) FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time) FN_GLOBAL_INTEGER(lp_winbind_reconnect_delay, &Globals.winbind_reconnect_delay) +FN_GLOBAL_INTEGER(lp_winbind_max_clients, &Globals.winbind_max_clients) FN_GLOBAL_LIST(lp_winbind_nss_info, &Globals.szWinbindNssInfo) FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase) FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout) @@ -6099,6 +6252,11 @@ bool lp_add_home(const char *pszHomename, int iDefaultService, { int i; + if (pszHomename == NULL || user == NULL || pszHomedir == NULL || + pszHomedir[0] == '\0') { + return false; + } + i = add_a_service(ServicePtrs[iDefaultService], pszHomename); if (i < 0) @@ -6794,13 +6952,16 @@ static bool process_smbconf_service(struct smbconf_service *service) return false; } } + if (iServiceIndex >= 0) { + return service_ok(iServiceIndex); + } return true; } -/* - * process_registry_globals +/** + * load a service from registry and activate it */ -static bool process_registry_globals(void) +bool process_registry_service(const char *service_name) { WERROR werr; struct smbconf_service *service = NULL; @@ -6812,19 +6973,18 @@ static bool process_registry_globals(void) goto done; } - ret = do_parameter("registry shares", "yes", NULL); - if (!ret) { - goto done; - } + DEBUG(5, ("process_registry_service: service name %s\n", service_name)); - if (!smbconf_share_exists(conf_ctx, GLOBAL_NAME)) { - /* nothing to read from the registry yet but make sure lp_load - * doesn't return false */ + if (!smbconf_share_exists(conf_ctx, service_name)) { + /* + * Registry does not contain data for this service (yet), + * but make sure lp_load doesn't return false. + */ ret = true; goto done; } - werr = smbconf_get_share(conf_ctx, mem_ctx, GLOBAL_NAME, &service); + werr = smbconf_get_share(conf_ctx, mem_ctx, service_name, &service); if (!W_ERROR_IS_OK(werr)) { goto done; } @@ -6842,7 +7002,24 @@ done: return ret; } -static bool process_registry_shares(void) +/* + * process_registry_globals + */ +static bool process_registry_globals(void) +{ + bool ret; + + add_to_file_list(INCLUDE_REGISTRY_NAME, INCLUDE_REGISTRY_NAME); + + ret = do_parameter("registry shares", "yes", NULL); + if (!ret) { + return ret; + } + + return process_registry_service(GLOBAL_NAME); +} + +bool process_registry_shares(void) { WERROR werr; uint32_t count; @@ -6881,6 +7058,39 @@ done: return ret; } +/** + * reload those shares from registry that are already + * activated in the services array. + */ +static bool reload_registry_shares(void) +{ + int i; + bool ret = true; + + for (i = 0; i < iNumServices; i++) { + if (!VALID(i)) { + continue; + } + + if (ServicePtrs[i]->usershare == USERSHARE_VALID) { + continue; + } + + ret = process_registry_service(ServicePtrs[i]->szService); + if (!ret) { + goto done; + } + } + +done: + return ret; +} + + +#define MAX_INCLUDE_DEPTH 100 + +static uint8_t include_depth; + static struct file_lists { struct file_lists *next; char *name; @@ -6927,6 +7137,26 @@ static void add_to_file_list(const char *fname, const char *subfname) } } +/** + * Free the file lists + */ +static void free_file_list(void) +{ + struct file_lists *f; + struct file_lists *next; + + f = file_lists; + while( f ) { + next = f->next; + SAFE_FREE( f->name ); + SAFE_FREE( f->subfname ); + SAFE_FREE( f ); + f = next; + } + file_lists = NULL; +} + + /** * Utility function for outsiders to check if we're running on registry. */ @@ -6953,45 +7183,51 @@ bool lp_file_list_changed(void) DEBUG(6, ("lp_file_list_changed()\n")); - if (lp_config_backend_is_registry()) { - struct smbconf_ctx *conf_ctx = lp_smbconf_ctx(); - - if (conf_ctx == NULL) { - return false; - } - if (smbconf_changed(conf_ctx, &conf_last_csn, NULL, NULL)) { - DEBUGADD(6, ("registry config changed\n")); - return true; - } - } - while (f) { char *n2 = NULL; time_t mod_time; - n2 = alloc_sub_basic(get_current_username(), - current_user_info.domain, - f->name); - if (!n2) { - return false; - } - DEBUGADD(6, ("file %s -> %s last mod_time: %s\n", - f->name, n2, ctime(&f->modtime))); - - mod_time = file_modtime(n2); - - if (mod_time && ((f->modtime != mod_time) || (f->subfname == NULL) || (strcmp(n2, f->subfname) != 0))) { - DEBUGADD(6, - ("file %s modified: %s\n", n2, - ctime(&mod_time))); - f->modtime = mod_time; - SAFE_FREE(f->subfname); - f->subfname = n2; /* Passing ownership of - return from alloc_sub_basic - above. */ - return true; + if (strequal(f->name, INCLUDE_REGISTRY_NAME)) { + struct smbconf_ctx *conf_ctx = lp_smbconf_ctx(); + + if (conf_ctx == NULL) { + return false; + } + if (smbconf_changed(conf_ctx, &conf_last_csn, NULL, + NULL)) + { + DEBUGADD(6, ("registry config changed\n")); + return true; + } + } else { + n2 = alloc_sub_basic(get_current_username(), + current_user_info.domain, + f->name); + if (!n2) { + return false; + } + DEBUGADD(6, ("file %s -> %s last mod_time: %s\n", + f->name, n2, ctime(&f->modtime))); + + mod_time = file_modtime(n2); + + if (mod_time && + ((f->modtime != mod_time) || + (f->subfname == NULL) || + (strcmp(n2, f->subfname) != 0))) + { + DEBUGADD(6, + ("file %s modified: %s\n", n2, + ctime(&mod_time))); + f->modtime = mod_time; + SAFE_FREE(f->subfname); + f->subfname = n2; /* Passing ownership of + return from alloc_sub_basic + above. */ + return true; + } + SAFE_FREE(n2); } - SAFE_FREE(n2); f = f->next; } return (False); @@ -7068,12 +7304,22 @@ static bool handle_include(int snum, const char *pszParmValue, char **ptr) { char *fname; + if (include_depth >= MAX_INCLUDE_DEPTH) { + DEBUG(0, ("Error: Maximum include depth (%u) exceeded!\n", + include_depth)); + return false; + } + if (strequal(pszParmValue, INCLUDE_REGISTRY_NAME)) { if (!bAllowIncludeRegistry) { return true; } if (bInGlobalSection) { - return process_registry_globals(); + bool ret; + include_depth++; + ret = process_registry_globals(); + include_depth--; + return ret; } else { DEBUG(1, ("\"include = registry\" only effective " "in %s section\n", GLOBAL_NAME)); @@ -7090,7 +7336,10 @@ static bool handle_include(int snum, const char *pszParmValue, char **ptr) string_set(ptr, fname); if (file_exist(fname)) { - bool ret = pm_process(fname, do_section, do_parameter, NULL); + bool ret; + include_depth++; + ret = pm_process(fname, do_section, do_parameter, NULL); + include_depth--; SAFE_FREE(fname); return ret; } @@ -7718,6 +7967,7 @@ static void dump_globals(FILE *f) for (i = 0; parm_table[i].label; i++) if (parm_table[i].p_class == P_GLOBAL && + !(parm_table[i].flags & FLAG_META) && parm_table[i].ptr && (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) { if (defaults_saved && is_default(i)) @@ -7764,6 +8014,7 @@ static void dump_a_service(struct service *pService, FILE * f) for (i = 0; parm_table[i].label; i++) { if (parm_table[i].p_class == P_LOCAL && + !(parm_table[i].flags & FLAG_META) && parm_table[i].ptr && (*parm_table[i].label != '-') && (i == 0 || (parm_table[i].ptr != parm_table[i - 1].ptr))) @@ -7840,6 +8091,7 @@ bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal) for (i = 0; parm_table[i].label; i++) { if (strwicmp(parm_table[i].label, parm_name) == 0 && + !(parm_table[i].flags & FLAG_META) && (parm_table[i].p_class == p_class || parm_table[i].flags & flag) && parm_table[i].ptr && (*parm_table[i].label != '-') && @@ -8005,7 +8257,7 @@ static void lp_add_auto_services(char *str) home = get_user_home_dir(talloc_tos(), p); - if (home && homes >= 0) + if (home && home[0] && homes >= 0) lp_add_home(p, homes, p, home); TALLOC_FREE(home); @@ -8235,29 +8487,30 @@ static void set_allowed_client_auth(void) get their sorry ass fired. ***************************************************************************/ -static bool check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf) +static bool check_usershare_stat(const char *fname, + const SMB_STRUCT_STAT *psbuf) { - if (!S_ISREG(psbuf->st_mode)) { + if (!S_ISREG(psbuf->st_ex_mode)) { DEBUG(0,("check_usershare_stat: file %s owned by uid %u is " "not a regular file\n", - fname, (unsigned int)psbuf->st_uid )); + fname, (unsigned int)psbuf->st_ex_uid )); return False; } /* Ensure this doesn't have the other write bit set. */ - if (psbuf->st_mode & S_IWOTH) { + if (psbuf->st_ex_mode & S_IWOTH) { DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows " "public write. Refusing to allow as a usershare file.\n", - fname, (unsigned int)psbuf->st_uid )); + fname, (unsigned int)psbuf->st_ex_uid )); return False; } /* Should be 10k or less. */ - if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) { + if (psbuf->st_ex_size > MAX_USERSHARE_FILE_SIZE) { DEBUG(0,("check_usershare_stat: file %s owned by uid %u is " "too large (%u) to be a user share file.\n", - fname, (unsigned int)psbuf->st_uid, - (unsigned int)psbuf->st_size )); + fname, (unsigned int)psbuf->st_ex_uid, + (unsigned int)psbuf->st_ex_size )); return False; } @@ -8407,7 +8660,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, /* Ensure the owner of the usershare file has permission to share this directory. */ - if (sys_stat(sharepath, &sbuf) == -1) { + if (sys_stat(sharepath, &sbuf, false) == -1) { DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n", servicename, sharepath, strerror(errno) )); sys_closedir(dp); @@ -8416,7 +8669,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, sys_closedir(dp); - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n", servicename, sharepath )); return USERSHARE_PATH_NOT_DIRECTORY; @@ -8428,7 +8681,7 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, if (lp_usershare_owner_only()) { /* root can share anything. */ - if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) { + if ((psbuf->st_ex_uid != 0) && (sbuf.st_ex_uid != psbuf->st_ex_uid)) { return USERSHARE_PATH_NOT_ALLOWED; } } @@ -8479,7 +8732,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i /* Minimize the race condition by doing an lstat before we open and fstat. Ensure this isn't a symlink link. */ - if (sys_lstat(fname, &lsbuf) != 0) { + if (sys_lstat(fname, &lsbuf, false) != 0) { DEBUG(0,("process_usershare_file: stat of %s failed. %s\n", fname, strerror(errno) )); SAFE_FREE(fname); @@ -8506,7 +8759,9 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i TALLOC_FREE(canon_name); } - if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) { + if (iService != -1 && + timespec_compare(&ServicePtrs[iService]->usershare_last_mod, + &lsbuf.st_ex_mtime) == 0) { /* Nothing changed - Mark valid and return. */ DEBUG(10,("process_usershare_file: service %s not changed.\n", service_name )); @@ -8530,7 +8785,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i } /* Now fstat to be *SURE* it's a regular file. */ - if (sys_fstat(fd, &sbuf) != 0) { + if (sys_fstat(fd, &sbuf, false) != 0) { close(fd); DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n", fname, strerror(errno) )); @@ -8539,7 +8794,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i } /* Is it the same dev/inode as was lstated ? */ - if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) { + if (lsbuf.st_ex_dev != sbuf.st_ex_dev || lsbuf.st_ex_ino != sbuf.st_ex_ino) { close(fd); DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. " "Symlink spoofing going on ?\n", fname )); @@ -8559,7 +8814,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i close(fd); if (lines == NULL) { DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n", - fname, (unsigned int)sbuf.st_uid )); + fname, (unsigned int)sbuf.st_ex_uid )); SAFE_FREE(fname); return -1; } @@ -8623,7 +8878,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i } /* And note when it was loaded. */ - ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime; + ServicePtrs[iService]->usershare_last_mod = sbuf.st_ex_mtime; string_set(&ServicePtrs[iService]->szPath, sharepath); string_set(&ServicePtrs[iService]->comment, comment); @@ -8636,7 +8891,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i Checks if a usershare entry has been modified since last load. ***************************************************************************/ -static bool usershare_exists(int iService, time_t *last_mod) +static bool usershare_exists(int iService, struct timespec *last_mod) { SMB_STRUCT_STAT lsbuf; const char *usersharepath = Globals.szUsersharePath; @@ -8648,18 +8903,18 @@ static bool usershare_exists(int iService, time_t *last_mod) return false; } - if (sys_lstat(fname, &lsbuf) != 0) { + if (sys_lstat(fname, &lsbuf, false) != 0) { SAFE_FREE(fname); return false; } - if (!S_ISREG(lsbuf.st_mode)) { + if (!S_ISREG(lsbuf.st_ex_mode)) { SAFE_FREE(fname); return false; } SAFE_FREE(fname); - *last_mod = lsbuf.st_mtime; + *last_mod = lsbuf.st_ex_mtime; return true; } @@ -8678,13 +8933,13 @@ int load_usershare_service(const char *servicename) return -1; } - if (sys_stat(usersharepath, &sbuf) != 0) { + if (sys_stat(usersharepath, &sbuf, false) != 0) { DEBUG(0,("load_usershare_service: stat of %s failed. %s\n", usersharepath, strerror(errno) )); return -1; } - if (!S_ISDIR(sbuf.st_mode)) { + if (!S_ISDIR(sbuf.st_ex_mode)) { DEBUG(0,("load_usershare_service: %s is not a directory.\n", usersharepath )); return -1; @@ -8696,9 +8951,9 @@ int load_usershare_service(const char *servicename) */ #ifdef S_ISVTX - if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) { + if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) { #else - if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) { + if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) { #endif DEBUG(0,("load_usershare_service: directory %s is not owned by root " "or does not have the sticky bit 't' set or is writable by anyone.\n", @@ -8755,7 +9010,7 @@ int load_usershare_shares(void) return lp_numservices(); } - if (sys_stat(usersharepath, &sbuf) != 0) { + if (sys_stat(usersharepath, &sbuf, false) != 0) { DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n", usersharepath, strerror(errno) )); return ret; @@ -8767,9 +9022,9 @@ int load_usershare_shares(void) */ #ifdef S_ISVTX - if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) { + if (sbuf.st_ex_uid != 0 || !(sbuf.st_ex_mode & S_ISVTX) || (sbuf.st_ex_mode & S_IWOTH)) { #else - if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) { + if (sbuf.st_ex_uid != 0 || (sbuf.st_ex_mode & S_IWOTH)) { #endif DEBUG(0,("load_usershare_shares: directory %s is not owned by root " "or does not have the sticky bit 't' set or is writable by anyone.\n", @@ -8894,21 +9149,9 @@ int load_usershare_shares(void) void gfree_loadparm(void) { - struct file_lists *f; - struct file_lists *next; int i; - /* Free the file lists */ - - f = file_lists; - while( f ) { - next = f->next; - SAFE_FREE( f->name ); - SAFE_FREE( f->subfname ); - SAFE_FREE( f ); - f = next; - } - file_lists = NULL; + free_file_list(); /* Free resources allocated to services */ @@ -8972,6 +9215,8 @@ bool lp_load_ex(const char *pszFname, init_globals(! initialize_globals); debug_init(); + free_file_list(); + if (save_defaults) { init_locals(); lp_save_defaults(); @@ -9030,11 +9275,19 @@ bool lp_load_ex(const char *pszFname, bRetval = false; } - if (bRetval && lp_registry_shares() && allow_registry_shares) { - bRetval = process_registry_shares(); + if (bRetval && lp_registry_shares()) { + if (allow_registry_shares) { + bRetval = process_registry_shares(); + } else { + bRetval = reload_registry_shares(); + } } - lp_add_auto_services(lp_auto_services()); + { + char *serv = lp_auto_services(); + lp_add_auto_services(serv); + TALLOC_FREE(serv); + } if (add_ipc) { /* When 'restrict anonymous = 2' guest connections to ipc$ @@ -9180,7 +9433,7 @@ int lp_servicenumber(const char *pszServiceName) } if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) { - time_t last_mod; + struct timespec last_mod; if (!usershare_exists(iService, &last_mod)) { /* Remove the share security tdb entry for it. */ @@ -9192,7 +9445,8 @@ int lp_servicenumber(const char *pszServiceName) } /* Has it been modified ? If so delete and reload. */ - if (ServicePtrs[iService]->usershare_last_mod < last_mod) { + if (timespec_compare(&ServicePtrs[iService]->usershare_last_mod, + &last_mod) < 0) { /* Remove it from the array. */ free_service_byindex(iService); /* and now reload it. */ @@ -9217,15 +9471,10 @@ struct share_params *get_share_params(TALLOC_CTX *mem_ctx, const char *sharename) { struct share_params *result; - char *sname; + fstring sname; int snum; - if (!(sname = SMB_STRDUP(sharename))) { - return NULL; - } - - snum = find_service(sname); - SAFE_FREE(sname); + snum = find_service(sharename, sname); if (snum < 0) { return NULL; @@ -9552,10 +9801,6 @@ const char *lp_printcapname(void) return PRINTCAP_NAME; } -/******************************************************************* - Ensure we don't use sendfile if server smb signing is active. -********************************************************************/ - static uint32 spoolss_state; bool lp_disable_spoolss( void ) @@ -9582,15 +9827,20 @@ uint32 lp_get_spoolss_state( void ) Ensure we don't use sendfile if server smb signing is active. ********************************************************************/ -bool lp_use_sendfile(int snum) +bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state) { + bool sign_active = false; + /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */ - if (Protocol < PROTOCOL_NT1) { - return False; + if (get_Protocol() < PROTOCOL_NT1) { + return false; + } + if (signing_state) { + sign_active = smb_signing_is_active(signing_state); } return (_lp_use_sendfile(snum) && (get_remote_arch() != RA_WIN95) && - !srv_is_signing_active()); + !sign_active); } /******************************************************************* @@ -9689,3 +9939,40 @@ const char *lp_socket_address(void) } return Globals.szSocketAddress; } + +void lp_set_passdb_backend(const char *backend) +{ + string_set(&Globals.szPassdbBackend, backend); +} + +/******************************************************************* + Safe wide links checks. + This helper function always verify the validity of wide links, + even after a configuration file reload. +********************************************************************/ + +static bool lp_widelinks_internal(int snum) +{ + return (bool)(LP_SNUM_OK(snum)? ServicePtrs[(snum)]->bWidelinks : + sDefault.bWidelinks); +} + +void widelinks_warning(int snum) +{ + if (lp_unix_extensions() && lp_widelinks_internal(snum)) { + DEBUG(0,("Share '%s' has wide links and unix extensions enabled. " + "These parameters are incompatible. " + "Wide links will be disabled for this share.\n", + lp_servicename(snum) )); + } +} + +bool lp_widelinks(int snum) +{ + /* wide links is always incompatible with unix extensions */ + if (lp_unix_extensions()) { + return false; + } + + return lp_widelinks_internal(snum); +}