s3:smbd - support streams larger than 64 KiB
[samba.git] / source3 / param / loadparm.c
index 8f2f26a4d76e6cf3641a669f218e5c63a7edf1dd..85e578eda9eb9cd2fa9229fcf3609cfaf50fb6e9 100644 (file)
@@ -53,6 +53,7 @@
  *
  */
 
+#define LOADPARM_SUBSTITUTION_INTERNALS 1
 #include "includes.h"
 #include "system/filesys.h"
 #include "util_tdb.h"
@@ -72,6 +73,9 @@
 #include "librpc/gen_ndr/nbt.h"
 #include "source4/lib/tls/tls.h"
 #include "libcli/auth/ntlm_check.h"
+#include "lib/crypto/gnutls_helpers.h"
+#include "lib/util/string_wrappers.h"
+#include "auth/credentials/credentials.h"
 
 #ifdef HAVE_SYS_SYSCTL_H
 #include <sys/sysctl.h>
@@ -160,7 +164,6 @@ static const struct loadparm_service _sDefault =
        .min_print_space = 0,
        .max_print_jobs = 1000,
        .max_reported_print_jobs = 0,
-       .write_cache_size = 0,
        .create_mask = 0744,
        .force_create_mode = 0,
        .directory_mask = 0755,
@@ -194,6 +197,7 @@ static const struct loadparm_service _sDefault =
        .map_hidden = false,
        .map_archive = true,
        .store_dos_attributes = true,
+       .smbd_max_xattr_size = 65536,
        .dmapi_support = false,
        .locking = true,
        .strict_locking = Auto,
@@ -201,7 +205,7 @@ static const struct loadparm_service _sDefault =
        .oplocks = true,
        .kernel_oplocks = false,
        .level2_oplocks = true,
-       .mangled_names = MANGLED_NAMES_YES,
+       .mangled_names = MANGLED_NAMES_ILLEGAL,
        .wide_links = false,
        .follow_symlinks = true,
        .sync_always = false,
@@ -236,16 +240,19 @@ static const struct loadparm_service _sDefault =
        .acl_map_full_control = true,
        .acl_group_control = false,
        .acl_allow_execute_always = false,
-       .allocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
        .aio_read_size = 1,
        .aio_write_size = 1,
        .map_readonly = MAP_READONLY_NO,
        .directory_name_cache_size = 100,
-       .smb_encrypt = SMB_SIGNING_DEFAULT,
+       .server_smb_encrypt = SMB_ENCRYPTION_DEFAULT,
        .kernel_share_modes = true,
        .durable_handles = true,
        .check_parent_directory_delete_on_close = false,
        .param_opt = NULL,
+       .smbd_search_ask_sharemode = true,
+       .smbd_getinfo_ask_sharemode = true,
+       .spotlight_backend = SPOTLIGHT_BACKEND_NOINDEX,
+       .honor_change_notify_privilege = false,
        .dummy = ""
 };
 
@@ -543,7 +550,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
        init_printer_values(lp_ctx, Globals.ctx, &sDefault);
 
-       sDefault.ntvfs_handler = str_list_make_v3_const(NULL, "unixuid default", NULL);
+       sDefault.ntvfs_handler = str_list_make_v3_const(Globals.ctx, "unixuid default", NULL);
 
        DEBUG(3, ("Initialising global parameters\n"));
 
@@ -639,15 +646,15 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
        Globals._disable_spoolss = false;
        Globals.max_smbd_processes = 0;/* no limit specified */
        Globals.username_level = 0;
-       Globals.deadtime = 0;
+       Globals.deadtime = 10080;
        Globals.getwd_cache = true;
        Globals.large_readwrite = true;
        Globals.max_log_size = 5000;
        Globals.max_open_files = max_open_files();
        Globals.server_max_protocol = PROTOCOL_SMB3_11;
-       Globals.server_min_protocol = PROTOCOL_LANMAN1;
+       Globals.server_min_protocol = PROTOCOL_SMB2_02;
        Globals._client_max_protocol = PROTOCOL_DEFAULT;
-       Globals.client_min_protocol = PROTOCOL_CORE;
+       Globals.client_min_protocol = PROTOCOL_SMB2_02;
        Globals._client_ipc_max_protocol = PROTOCOL_DEFAULT;
        Globals._client_ipc_min_protocol = PROTOCOL_DEFAULT;
        Globals._security = SEC_AUTO;
@@ -677,15 +684,6 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
        Globals.machine_password_timeout = 60 * 60 * 24 * 7;    /* 7 days default. */
        Globals.lm_announce = Auto;     /* = Auto: send only if LM clients found */
        Globals.lm_interval = 60;
-#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
-       Globals.nis_homedir = false;
-#ifdef WITH_NISPLUS_HOME
-       lpcfg_string_set(Globals.ctx, &Globals.homedir_map,
-                        "auto_home.org_dir");
-#else
-       lpcfg_string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
-#endif
-#endif
        Globals.time_server = false;
        Globals.bind_interfaces_only = false;
        Globals.unix_password_sync = false;
@@ -696,7 +694,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
        Globals.nt_status_support = true; /* Use NT status by default. */
        Globals.smbd_profiling_level = 0;
        Globals.stat_cache = true;      /* use stat cache by default */
-       Globals.max_stat_cache_size = 256; /* 256k by default */
+       Globals.max_stat_cache_size = 512; /* 512k by default */
        Globals.restrict_anonymous = 0;
        Globals.client_lanman_auth = false;     /* Do NOT use the LanMan hash if it is available */
        Globals.client_plaintext_auth = false;  /* Do NOT use a plaintext password even if is requested by the server */
@@ -712,11 +710,7 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
        Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
        Globals.enhanced_browsing = true;
        Globals.lock_spin_time = WINDOWS_MINIMUM_LOCK_TIMEOUT_MS; /* msec. */
-#ifdef MMAP_BLACKLIST
-       Globals.use_mmap = false;
-#else
        Globals.use_mmap = true;
-#endif
        Globals.unicode = true;
        Globals.unix_extensions = true;
        Globals.reset_on_zero_vc = false;
@@ -741,7 +735,6 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
        lpcfg_string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
        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;
@@ -887,14 +880,14 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
        lpcfg_string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
        lpcfg_string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
        lpcfg_string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
-       lpcfg_string_set(Globals.ctx, &Globals.tls_priority,
+       lpcfg_string_set(Globals.ctx,
+                        &Globals.tls_priority,
                         "NORMAL:-VERS-SSL3.0");
 
-       lpcfg_string_set(Globals.ctx, &Globals.share_backend, "classic");
-
        Globals._preferred_master = Auto;
 
        Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
+       Globals.dns_zone_scavenging = false;
 
        lpcfg_string_set(Globals.ctx, &Globals.ntp_signd_socket_directory,
                         get_dyn_NTP_SIGND_SOCKET_DIR());
@@ -935,8 +928,6 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
        Globals.nsupdate_command = str_list_make_v3_const(NULL, "/usr/bin/nsupdate -g", NULL);
 
-       Globals.rndc_command = str_list_make_v3_const(NULL, "/usr/sbin/rndc", NULL);
-
        Globals.cldap_port = 389;
 
        Globals.dgram_port = NBT_DGRAM_SERVICE_PORT;
@@ -947,8 +938,6 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 
        Globals.kpasswd_port = 464;
 
-       Globals.web_port = 901;
-
        Globals.aio_max_threads = 100;
 
        lpcfg_string_set(Globals.ctx,
@@ -956,7 +945,22 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
                         "49152-65535");
        Globals.rpc_low_port = SERVER_TCP_LOW_PORT;
        Globals.rpc_high_port = SERVER_TCP_HIGH_PORT;
-       Globals.prefork_children = 1;
+       Globals.prefork_children = 4;
+       Globals.prefork_backoff_increment = 10;
+       Globals.prefork_maximum_backoff = 120;
+
+       Globals.ldap_max_anonymous_request_size = 256000;
+       Globals.ldap_max_authenticated_request_size = 16777216;
+       Globals.ldap_max_search_request_size = 256000;
+
+       /* Async DNS query timeout (in seconds). */
+       Globals.async_dns_timeout = 10;
+
+       Globals.client_smb_encrypt = SMB_ENCRYPTION_DEFAULT;
+
+       Globals._client_use_kerberos = CRED_USE_KERBEROS_DESIRED;
+
+       Globals.client_protection = CRED_CLIENT_PROTECTION_DEFAULT;
 
        /* Now put back the settings that were set with lp_set_cmdline() */
        apply_lp_set_cmdline();
@@ -995,7 +999,11 @@ static struct loadparm_context *setup_lp_context(TALLOC_CTX *mem_ctx)
  callers without affecting the source string.
 ********************************************************************/
 
-char *lp_string(TALLOC_CTX *ctx, const char *s)
+static char *loadparm_s3_global_substitution_fn(
+                       TALLOC_CTX *mem_ctx,
+                       const struct loadparm_substitution *lp_sub,
+                       const char *s,
+                       void *private_data)
 {
        char *ret;
 
@@ -1011,14 +1019,14 @@ char *lp_string(TALLOC_CTX *ctx, const char *s)
                return NULL;
        }
 
-       ret = talloc_sub_basic(ctx,
+       ret = talloc_sub_basic(mem_ctx,
                        get_current_username(),
                        current_user_info.domain,
                        s);
        if (trim_char(ret, '\"', '\"')) {
                if (strchr(ret,'\"') != NULL) {
                        TALLOC_FREE(ret);
-                       ret = talloc_sub_basic(ctx,
+                       ret = talloc_sub_basic(mem_ctx,
                                        get_current_username(),
                                        current_user_info.domain,
                                        s);
@@ -1027,13 +1035,23 @@ char *lp_string(TALLOC_CTX *ctx, const char *s)
        return ret;
 }
 
+static const struct loadparm_substitution s3_global_substitution = {
+       .substituted_string_fn = loadparm_s3_global_substitution_fn,
+};
+
+const struct loadparm_substitution *loadparm_s3_global_substitution(void)
+{
+       return &s3_global_substitution;
+}
+
 /*
    In this section all the functions that are used to access the
    parameters from the rest of the program are defined
 */
 
-#define FN_GLOBAL_STRING(fn_name,ptr) \
-char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : ""));}
+#define FN_GLOBAL_SUBSTITUTED_STRING(fn_name,ptr) \
+char *lp_ ## fn_name(TALLOC_CTX *ctx, const struct loadparm_substitution *lp_sub) \
+ {return lpcfg_substituted_string(ctx, lp_sub, *(char **)(&Globals.ptr) ? *(char **)(&Globals.ptr) : "");}
 #define FN_GLOBAL_CONST_STRING(fn_name,ptr) \
  const char *lp_ ## fn_name(void) {return(*(const char * const *)(&Globals.ptr) ? *(const char * const *)(&Globals.ptr) : "");}
 #define FN_GLOBAL_LIST(fn_name,ptr) \
@@ -1045,8 +1063,9 @@ char *lp_ ## fn_name(TALLOC_CTX *ctx) {return(lp_string((ctx), *(char **)(&Globa
 #define FN_GLOBAL_INTEGER(fn_name,ptr) \
  int lp_ ## fn_name(void) {return(*(int *)(&Globals.ptr));}
 
-#define FN_LOCAL_STRING(fn_name,val) \
-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));}
+#define FN_LOCAL_SUBSTITUTED_STRING(fn_name,val) \
+char *lp_ ## fn_name(TALLOC_CTX *ctx, const struct loadparm_substitution *lp_sub, int i) \
+ {return lpcfg_substituted_string((ctx), lp_sub, (LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
 #define FN_LOCAL_CONST_STRING(fn_name,val) \
  const char *lp_ ## fn_name(int i) {return (const char *)((LP_SNUM_OK(i) && ServicePtrs[(i)]->val) ? ServicePtrs[(i)]->val : sDefault.val);}
 #define FN_LOCAL_LIST(fn_name,val) \
@@ -1078,7 +1097,7 @@ int lp_winbind_max_domain_connections(void)
 
 #include "lib/param/param_functions.c"
 
-FN_LOCAL_STRING(servicename, szService)
+FN_LOCAL_SUBSTITUTED_STRING(servicename, szService)
 FN_LOCAL_CONST_STRING(const_servicename, szService)
 
 /* These functions cannot be auto-generated */
@@ -1217,19 +1236,26 @@ static int lp_enum(const char *s,const struct enum_list *_enum)
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
-char *lp_parm_talloc_string(TALLOC_CTX *ctx, int snum, const char *type, const char *option, const char *def)
+char *lp_parm_substituted_string(TALLOC_CTX *mem_ctx,
+                                const struct loadparm_substitution *lp_sub,
+                                int snum,
+                                const char *type,
+                                const char *option,
+                                const char *def)
 {
        struct parmlist_entry *data = get_parametrics(snum, type, option);
 
+       SMB_ASSERT(lp_sub != NULL);
+
        if (data == NULL||data->value==NULL) {
                if (def) {
-                       return lp_string(ctx, def);
+                       return lpcfg_substituted_string(mem_ctx, lp_sub, def);
                } else {
                        return NULL;
                }
        }
 
-       return lp_string(ctx, data->value);
+       return lpcfg_substituted_string(mem_ctx, lp_sub, data->value);
 }
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
@@ -1529,7 +1555,10 @@ static bool hash_a_service(const char *name, int idx)
 bool lp_add_home(const char *pszHomename, int iDefaultService,
                 const char *user, const char *pszHomedir)
 {
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
        int i;
+       char *global_path;
 
        if (pszHomename == NULL || user == NULL || pszHomedir == NULL ||
                        pszHomedir[0] == '\0') {
@@ -1541,12 +1570,13 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
        if (i < 0)
                return false;
 
+       global_path = lp_path(talloc_tos(), lp_sub, GLOBAL_SECTION_SNUM);
        if (!(*(ServicePtrs[iDefaultService]->path))
-           || strequal(ServicePtrs[iDefaultService]->path,
-                       lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
+           || strequal(ServicePtrs[iDefaultService]->path, global_path)) {
                lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path,
                                 pszHomedir);
        }
+       TALLOC_FREE(global_path);
 
        if (!(*(ServicePtrs[i]->comment))) {
                char *comment = talloc_asprintf(talloc_tos(), "Home directory of %s", user);
@@ -2564,7 +2594,7 @@ const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
        if (Globals._ldap_machine_suffix[0])
                return append_ldap_suffix(ctx, Globals._ldap_machine_suffix);
 
-       return lp_string(ctx, Globals.ldap_suffix);
+       return talloc_strdup(ctx, Globals.ldap_suffix);
 }
 
 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
@@ -2572,7 +2602,7 @@ const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
        if (Globals._ldap_user_suffix[0])
                return append_ldap_suffix(ctx, Globals._ldap_user_suffix);
 
-       return lp_string(ctx, Globals.ldap_suffix);
+       return talloc_strdup(ctx, Globals.ldap_suffix);
 }
 
 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
@@ -2580,7 +2610,7 @@ const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
        if (Globals._ldap_group_suffix[0])
                return append_ldap_suffix(ctx, Globals._ldap_group_suffix);
 
-       return lp_string(ctx, Globals.ldap_suffix);
+       return talloc_strdup(ctx, Globals.ldap_suffix);
 }
 
 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
@@ -2588,7 +2618,7 @@ const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
        if (Globals._ldap_idmap_suffix[0])
                return append_ldap_suffix(ctx, Globals._ldap_idmap_suffix);
 
-       return lp_string(ctx, Globals.ldap_suffix);
+       return talloc_strdup(ctx, Globals.ldap_suffix);
 }
 
 /**
@@ -2717,6 +2747,38 @@ static bool do_parameter(const char *pszParmName, const char *pszParmValue,
        }
 }
 
+
+static const char *ad_dc_req_vfs_mods[] = {"dfs_samba4", "acl_xattr", NULL};
+
+/*
+ * check that @vfs_objects includes all vfs modules required by an AD DC.
+ */
+static bool check_ad_dc_required_mods(const char **vfs_objects)
+{
+       int i;
+       int j;
+       int got_req;
+
+       for (i = 0; ad_dc_req_vfs_mods[i] != NULL; i++) {
+               got_req = false;
+               for (j = 0; vfs_objects[j] != NULL; j++) {
+                       if (!strwicmp(ad_dc_req_vfs_mods[i], vfs_objects[j])) {
+                               got_req = true;
+                               break;
+                       }
+               }
+               if (!got_req) {
+                       DEBUG(0, ("vfs objects specified without required AD "
+                                 "DC module: %s\n", ad_dc_req_vfs_mods[i]));
+                       return false;
+               }
+       }
+
+       DEBUG(6, ("vfs objects specified with all required AD DC modules\n"));
+       return true;
+}
+
+
 /***************************************************************************
  Initialize any local variables in the sDefault table, after parsing a
  [globals] section.
@@ -2736,7 +2798,10 @@ static void init_locals(void)
         */
        if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
                const char **vfs_objects = lp_vfs_objects(-1);
-               if (!vfs_objects || !vfs_objects[0]) {
+               if (vfs_objects != NULL) {
+                       /* ignore return, only warn if modules are missing */
+                       check_ad_dc_required_mods(vfs_objects);
+               } else {
                        if (lp_parm_const_string(-1, "xattr_tdb", "file", NULL)) {
                                lp_do_parameter(-1, "vfs objects", "dfs_samba4 acl_xattr xattr_tdb");
                        } else if (lp_parm_const_string(-1, "posix", "eadb", NULL)) {
@@ -2766,7 +2831,6 @@ bool lp_do_section(const char *pszSectionName, void *userdata)
        bool bRetval;
        bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
                         (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
-       bRetval = false;
 
        /* if we were in a global section then do the local inits */
        if (bInGlobalSection && !isglobal)
@@ -2870,7 +2934,7 @@ bool lp_snum_ok(int iService)
  Auto-load some home services.
 ***************************************************************************/
 
-static void lp_add_auto_services(char *str)
+static void lp_add_auto_services(const char *str)
 {
        char *s;
        char *p;
@@ -3332,6 +3396,7 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
        char *canon_name = NULL;
        bool added_service = false;
        int ret = -1;
+       NTSTATUS status;
 
        /* Ensure share name doesn't contain invalid characters. */
        if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
@@ -3355,6 +3420,11 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
           open and fstat. Ensure this isn't a symlink link. */
 
        if (sys_lstat(fname, &lsbuf, false) != 0) {
+               if (errno == ENOENT) {
+                       /* Unknown share requested. Just ignore. */
+                       goto out;
+               }
+               /* Only log messages for meaningful problems. */
                DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
                        fname, strerror(errno) ));
                goto out;
@@ -3368,7 +3438,6 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
 
        {
                TDB_DATA data;
-               NTSTATUS status;
 
                status = dbwrap_fetch_bystring(ServiceHash, canon_name,
                                               canon_name, &data);
@@ -3465,7 +3534,8 @@ static int process_usershare_file(const char *dir_name, const char *file_name, i
        }
 
        /* Write the ACL of the new/modified share. */
-       if (!set_share_security(canon_name, psd)) {
+       status = set_share_security(canon_name, psd);
+       if (!NT_STATUS_IS_OK(status)) {
                 DEBUG(0, ("process_usershare_file: Failed to set share "
                        "security for user share %s\n",
                        canon_name ));
@@ -3560,6 +3630,11 @@ int load_usershare_service(const char *servicename)
        int max_user_shares = Globals.usershare_max_shares;
        int snum_template = -1;
 
+       if (servicename[0] == '\0') {
+               /* Invalid service name. */
+               return -1;
+       }
+
        if (*usersharepath == 0 ||  max_user_shares == 0) {
                return -1;
        }
@@ -3765,13 +3840,15 @@ int load_usershare_shares(struct smbd_server_connection *sconn,
        tmp_ctx = talloc_stackframe();
        for (iService = iNumServices - 1; iService >= 0; iService--) {
                if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
+                       const struct loadparm_substitution *lp_sub =
+                               loadparm_s3_global_substitution();
                        char *servname;
 
                        if (snumused && snumused(sconn, iService)) {
                                continue;
                        }
 
-                       servname = lp_servicename(tmp_ctx, iService);
+                       servname = lp_servicename(tmp_ctx, lp_sub, iService);
 
                        /* Remove from the share ACL db. */
                        DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
@@ -3863,8 +3940,7 @@ static bool lp_load_ex(const char *pszFname,
        bool bRetval;
        TALLOC_CTX *frame = talloc_stackframe();
        struct loadparm_context *lp_ctx;
-
-       bRetval = false;
+       int max_protocol, min_protocol;
 
        DEBUG(3, ("lp_load_ex: refreshing parameters\n"));
 
@@ -3958,7 +4034,9 @@ static bool lp_load_ex(const char *pszFname,
        }
 
        {
-               char *serv = lp_auto_services(talloc_tos());
+               const struct loadparm_substitution *lp_sub =
+                       loadparm_s3_global_substitution();
+               char *serv = lp_auto_services(talloc_tos(), lp_sub);
                lp_add_auto_services(serv);
                TALLOC_FREE(serv);
        }
@@ -4003,6 +4081,19 @@ static bool lp_load_ex(const char *pszFname,
 
        bAllowIncludeRegistry = true;
 
+       /* Check if command line max protocol < min protocol, if so
+        * report a warning to the user.
+        */
+       max_protocol = lp_client_max_protocol();
+       min_protocol = lp_client_min_protocol();
+       if (max_protocol < min_protocol) {
+               const char *max_protocolp, *min_protocolp;
+               max_protocolp = lpcfg_get_smb_protocol(max_protocol);
+               min_protocolp = lpcfg_get_smb_protocol(min_protocol);
+               DBG_ERR("Max protocol %s is less than min protocol %s.\n",
+                       max_protocolp, min_protocolp);
+       }
+
        TALLOC_FREE(frame);
        return (bRetval);
 }
@@ -4117,7 +4208,7 @@ bool lp_load_with_registry_shares(const char *pszFname)
                          false, /* global_only */
                          true,  /* save_defaults */
                          false, /* add_ipc */
-                         false, /* reinit_globals */
+                         true, /* reinit_globals */
                          true,  /* allow_include_registry */
                          true); /* load_all_shares*/
 }
@@ -4156,6 +4247,7 @@ void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
                fprintf(f,"\n");
                lp_dump_one(f, show_defaults, iService);
        }
+       TALLOC_FREE(lp_ctx);
 }
 
 /***************************************************************************
@@ -4209,7 +4301,7 @@ int lp_servicenumber(const char *pszServiceName)
 
                if (!usershare_exists(iService, &last_mod)) {
                        /* Remove the share security tdb entry for it. */
-                       delete_share_security(lp_servicename(talloc_tos(), iService));
+                       delete_share_security(lp_const_servicename(iService));
                        /* Remove it from the array. */
                        free_service_byindex(iService);
                        /* Doesn't exist anymore. */
@@ -4240,17 +4332,51 @@ int lp_servicenumber(const char *pszServiceName)
 
 const char *volume_label(TALLOC_CTX *ctx, int snum)
 {
+       const struct loadparm_substitution *lp_sub =
+               loadparm_s3_global_substitution();
        char *ret;
-       const char *label = lp_volume(ctx, snum);
+       const char *label = lp_volume(ctx, lp_sub, snum);
+       size_t end = 32;
+
        if (!*label) {
-               label = lp_servicename(ctx, snum);
+               label = lp_servicename(ctx, lp_sub, snum);
        }
 
-       /* This returns a 33 byte guarenteed null terminated string. */
-       ret = talloc_strndup(ctx, label, 32);
+       /*
+        * Volume label can be a max of 32 bytes. Make sure to truncate
+        * it at a codepoint boundary if it's longer than 32 and contains
+        * multibyte characters. Windows insists on a volume label being
+        * a valid mb sequence, and errors out if not.
+        */
+       if (strlen(label) > 32) {
+               /*
+                * A MB char can be a max of 5 bytes, thus
+                * we should have a valid mb character at a
+                * minimum position of (32-5) = 27.
+                */
+               while (end >= 27) {
+                       /*
+                        * Check if a codepoint starting from next byte
+                        * is valid. If yes, then the current byte is the
+                        * end of a MB or ascii sequence and the label can
+                        * be safely truncated here. If not, keep going
+                        * backwards till a valid codepoint is found.
+                        */
+                       size_t len = 0;
+                       const char *s = &label[end];
+                       codepoint_t c = next_codepoint(s, &len);
+                       if (c != INVALID_CODEPOINT) {
+                               break;
+                       }
+                       end--;
+               }
+       }
+
+       /* This returns a max of 33 byte guarenteed null terminated string. */
+       ret = talloc_strndup(ctx, label, end);
        if (!ret) {
                return "";
-       }               
+       }
        return ret;
 }
 
@@ -4344,9 +4470,12 @@ void lp_remove_service(int snum)
        ServicePtrs[snum]->valid = false;
 }
 
-const char *lp_printername(TALLOC_CTX *ctx, int snum)
+const char *lp_printername(TALLOC_CTX *ctx,
+                          const struct loadparm_substitution *lp_sub,
+                          int snum)
 {
-       const char *ret = lp__printername(ctx, snum);
+       const char *ret = lp__printername(ctx, lp_sub, snum);
+
        if (ret == NULL || *ret == '\0') {
                ret = lp_const_servicename(snum);
        }
@@ -4419,26 +4548,6 @@ uint32_t lp_get_spoolss_state( void )
        return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
 }
 
-/*******************************************************************
- Ensure we don't use sendfile if server smb signing is active.
-********************************************************************/
-
-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 (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) &&
-                       !sign_active);
-}
-
 /*******************************************************************
  Turn off sendfile if we find the underlying OS doesn't support it.
 ********************************************************************/
@@ -4526,10 +4635,10 @@ void widelinks_warning(int snum)
        }
 
        if (lp_unix_extensions() && lp_wide_links(snum)) {
-               DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
+               DBG_ERR("Share '%s' has wide links and unix extensions enabled. "
                        "These parameters are incompatible. "
                        "Wide links will be disabled for this share.\n",
-                        lp_servicename(talloc_tos(), snum) ));
+                        lp_const_servicename(snum));
        }
 }
 
@@ -4605,6 +4714,16 @@ int lp_client_ipc_signing(void)
        return client_ipc_signing;
 }
 
+enum credentials_use_kerberos lp_client_use_kerberos(void)
+{
+       if (lp_weak_crypto() == SAMBA_WEAK_CRYPTO_DISALLOWED) {
+               return CRED_USE_KERBEROS_REQUIRED;
+       }
+
+       return lp__client_use_kerberos();
+}
+
+
 int lp_rpc_low_port(void)
 {
        return Globals.rpc_low_port;
@@ -4644,3 +4763,25 @@ unsigned int * get_flags(void)
 
        return flags_list;
 }
+
+enum samba_weak_crypto lp_weak_crypto()
+{
+       if (Globals.weak_crypto == SAMBA_WEAK_CRYPTO_UNKNOWN) {
+               Globals.weak_crypto = SAMBA_WEAK_CRYPTO_DISALLOWED;
+
+               if (samba_gnutls_weak_crypto_allowed()) {
+                       Globals.weak_crypto = SAMBA_WEAK_CRYPTO_ALLOWED;
+               }
+       }
+
+       return Globals.weak_crypto;
+}
+
+uint32_t lp_get_async_dns_timeout(void)
+{
+       /*
+        * Clamp minimum async dns timeout to 1 second
+        * as per the man page.
+        */
+       return MAX(Globals.async_dns_timeout, 1);
+}