Revert "Fix bug #7781 (Samba transforms "ShareName" to lowercase when adding new...
[samba.git] / source3 / param / loadparm.c
index da3da632600b516a4d2fd798901b1866fc13c661..8c1cf0973b0729ac54c6d14aa1f2e8a0c96b1b85 100644 (file)
 #include "includes.h"
 #include "printing.h"
 
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
 #ifdef HAVE_HTTPCONNECTENCRYPT
 #include <cups/http.h>
 #endif
 
 bool bLoaded = False;
 
-extern enum protocol_types Protocol;
 extern userdom_struct current_user_info;
 
 #ifndef GLOBAL_NAME
@@ -157,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;
@@ -199,6 +203,7 @@ struct global {
        bool bWinbindOfflineLogon;
        bool bWinbindNormalizeNames;
        bool bWinbindRpcOnly;
+       bool bCreateKrb5Conf;
        char *szIdmapBackend;
        char *szIdmapAllocBackend;
        char *szAddShareCommand;
@@ -246,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;
@@ -255,6 +260,8 @@ 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;
@@ -266,6 +273,7 @@ struct global {
        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 */
@@ -317,6 +325,7 @@ struct global {
        bool bClientNTLMv2Auth;
        bool bClientPlaintextAuth;
        bool bClientUseSpnego;
+       bool client_use_spnego_principal;
        bool bDebugPrefixTimestamp;
        bool bDebugHiresTimestamp;
        bool bDebugPid;
@@ -362,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;
@@ -506,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 */
@@ -599,7 +608,7 @@ static struct service sDefault = {
        True,                   /* bLevel2OpLocks */
        False,                  /* bOnlyUser */
        True,                   /* bMangledNames */
-       True,                   /* bWidelinks */
+       false,                  /* bWidelinks */
        True,                   /* bSymlinks */
        False,                  /* bSyncAlways */
        False,                  /* bStrictAllocate */
@@ -685,6 +694,7 @@ 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"},
@@ -739,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"},
@@ -1371,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,
@@ -2496,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",
@@ -2534,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},
 
@@ -3258,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,
        },
 
@@ -3266,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,
 
        },
@@ -3650,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,
@@ -3937,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,
@@ -4277,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",
@@ -4478,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,
@@ -4577,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}
 };
@@ -4701,6 +4792,22 @@ static int max_open_files(void)
 #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);
 }
 
@@ -4880,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");
@@ -4945,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;
@@ -4994,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, "");
@@ -5009,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;
@@ -5067,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;
@@ -5142,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(),
@@ -5198,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)
@@ -5262,6 +5382,7 @@ 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)
@@ -5345,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)
@@ -5357,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)
@@ -5433,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)
@@ -5492,26 +5617,28 @@ 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:
-                       Globals.CupsEncrypt = HTTP_ENCRYPT_REQUIRED;
+                       result = HTTP_ENCRYPT_REQUIRED;
                        break;
                case True:
-                       Globals.CupsEncrypt = HTTP_ENCRYPT_ALWAYS;
+                       result = HTTP_ENCRYPT_ALWAYS;
                        break;
                case False:
-                       Globals.CupsEncrypt = HTTP_ENCRYPT_NEVER;
+                       result = HTTP_ENCRYPT_NEVER;
                        break;
        }
 #endif
-       return Globals.CupsEncrypt;
+       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)
@@ -5571,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)
@@ -5628,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)
@@ -6125,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)
@@ -6926,6 +7058,35 @@ 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;
@@ -8096,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);
@@ -8329,27 +8490,27 @@ static void set_allowed_client_auth(void)
 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;
        }
 
@@ -8499,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);
@@ -8508,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;
@@ -8520,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;
                }
        }
@@ -8571,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);
@@ -8598,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 ));
@@ -8622,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) ));
@@ -8631,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 ));
@@ -8651,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;
        }
@@ -8715,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);
 
@@ -8728,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;
@@ -8740,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;
 }
 
@@ -8770,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;
@@ -8788,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",
@@ -8847,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;
@@ -8859,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",
@@ -9112,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$
@@ -9262,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. */
@@ -9274,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. */
@@ -9665,7 +9837,7 @@ 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) {
+       if (get_Protocol() < PROTOCOL_NT1) {
                return false;
        }
        if (signing_state) {
@@ -9772,3 +9944,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);
+}