CVE-2016-2112: docs-xml: add "ldap server require strong auth" option
[samba.git] / source3 / param / loadparm.c
index f906dd956b2fad66cb057ad6cec00e04ec6869e9..14c3c5e0515b8d3cb00f37eca286209a30c21d27 100644 (file)
 #include "dbwrap/dbwrap.h"
 #include "dbwrap/dbwrap_rbt.h"
 #include "../lib/util/bitmap.h"
+#include "librpc/gen_ndr/nbt.h"
 
 #ifdef HAVE_SYS_SYSCTL_H
 #include <sys/sysctl.h>
 #endif
 
-#ifdef HAVE_HTTPCONNECTENCRYPT
-#include <cups/http.h>
-#endif
-
 bool bLoaded = false;
 
 extern userdom_struct current_user_info;
@@ -96,8 +93,11 @@ static struct smbconf_csn conf_last_csn;
 static int config_backend = CONFIG_BACKEND_FILE;
 
 /* some helpful bits */
-#define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
-#define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
+#define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && \
+                       (ServicePtrs != NULL) && \
+                      (ServicePtrs[(i)] != NULL) && ServicePtrs[(i)]->valid)
+#define VALID(i) ((ServicePtrs != NULL) && (ServicePtrs[i]!= NULL) && \
+                  ServicePtrs[i]->valid)
 
 #define USERSHARE_VALID 1
 #define USERSHARE_PENDING_DELETE 2
@@ -121,8 +121,8 @@ static struct loadparm_service sDefault =
        .invalid_users = NULL,
        .valid_users = NULL,
        .admin_users = NULL,
-       .szCopy = NULL,
-       .szInclude = NULL,
+       .copy = NULL,
+       .include = NULL,
        .preexec = NULL,
        .postexec = NULL,
        .root_preexec = NULL,
@@ -157,7 +157,7 @@ static struct loadparm_service sDefault =
        .aio_write_behind = NULL,
        .dfree_command = NULL,
        .min_print_space = 0,
-       .iMaxPrintJobs = 1000,
+       .max_print_jobs = 1000,
        .max_reported_print_jobs = 0,
        .write_cache_size = 0,
        .create_mask = 0744,
@@ -182,8 +182,9 @@ static struct loadparm_service sDefault =
        .hide_unwriteable_files = false,
        .browseable = true,
        .access_based_share_enum = false,
-       .bAvailable = true,
+       .available = true,
        .read_only = true,
+       .spotlight = false,
        .guest_only = false,
        .administrative_share = false,
        .guest_ok = false,
@@ -202,10 +203,11 @@ static struct loadparm_service sDefault =
        .level2_oplocks = true,
        .only_user = false,
        .mangled_names = true,
-       .bWidelinks = false,
+       .wide_links = false,
        .follow_symlinks = true,
        .sync_always = false,
        .strict_allocate = false,
+       .strict_rename = false,
        .strict_sync = false,
        .mangling_char = '~',
        .copymap = NULL,
@@ -221,6 +223,7 @@ static struct loadparm_service sDefault =
        .inherit_acls = false,
        .inherit_owner = false,
        .msdfs_root = false,
+       .msdfs_shuffle_referrals = false,
        .use_client_driver = false,
        .default_devmode = true,
        .force_printername = false,
@@ -235,8 +238,6 @@ static struct loadparm_service sDefault =
        .acl_map_full_control = true,
        .acl_group_control = false,
        .acl_allow_execute_always = false,
-       .change_notify = true,
-       .kernel_change_notify = true,
        .allocation_roundup_size = SMB_ROUNDUP_ALLOCATION_SIZE,
        .aio_read_size = 0,
        .aio_write_size = 0,
@@ -264,166 +265,6 @@ static void set_allowed_client_auth(void);
 static bool lp_set_cmdline_helper(const char *pszParmName, const char *pszParmValue);
 static void free_param_opts(struct parmlist_entry **popts);
 
-/* this is used to prevent lots of mallocs of size 1 */
-static const char null_string[] = "";
-
-/**
- Free a string value.
-**/
-
-static void string_free(char **s)
-{
-       if (!s || !(*s))
-               return;
-       if (*s == null_string)
-               *s = NULL;
-       TALLOC_FREE(*s);
-}
-
-/**
- Set a string value, deallocating any existing space, and allocing the space
- for the string
-**/
-
-static bool string_set(TALLOC_CTX *mem_ctx, char **dest,const char *src)
-{
-       string_free(dest);
-
-       if (!src) {
-               src = "";
-       }
-
-       (*dest) = talloc_strdup(mem_ctx, src);
-       if ((*dest) == NULL) {
-               DEBUG(0,("Out of memory in string_init\n"));
-               return false;
-       }
-
-       return true;
-}
-
-bool lp_string_set(char **dest, const char *src) {
-       return string_set(Globals.ctx, dest, src);
-}
-
-/***************************************************************************
- Initialise the sDefault parameter structure for the printer values.
-***************************************************************************/
-
-void init_printer_values(TALLOC_CTX *ctx, struct loadparm_service *pService)
-{
-       /* choose defaults depending on the type of printing */
-       switch (pService->printing) {
-               case PRINT_BSD:
-               case PRINT_AIX:
-               case PRINT_LPRNT:
-               case PRINT_LPROS2:
-                       lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
-                       lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
-                       lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
-                       break;
-
-               case PRINT_LPRNG:
-               case PRINT_PLP:
-                       lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P'%p'");
-                       lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P'%p' %j");
-                       lpcfg_string_set(ctx, &pService->print_command, "lpr -r -P'%p' %s");
-                       lpcfg_string_set(ctx, &pService->queuepause_command, "lpc stop '%p'");
-                       lpcfg_string_set(ctx, &pService->queueresume_command, "lpc start '%p'");
-                       lpcfg_string_set(ctx, &pService->lppause_command, "lpc hold '%p' %j");
-                       lpcfg_string_set(ctx, &pService->lpresume_command, "lpc release '%p' %j");
-                       break;
-
-               case PRINT_CUPS:
-               case PRINT_IPRINT:
-                       /* set the lpq command to contain the destination printer
-                          name only.  This is used by cups_queue_get() */
-                       lpcfg_string_set(ctx, &pService->lpq_command, "%p");
-                       lpcfg_string_set(ctx, &pService->lprm_command, "");
-                       lpcfg_string_set(ctx, &pService->print_command, "");
-                       lpcfg_string_set(ctx, &pService->lppause_command, "");
-                       lpcfg_string_set(ctx, &pService->lpresume_command, "");
-                       lpcfg_string_set(ctx, &pService->queuepause_command, "");
-                       lpcfg_string_set(ctx, &pService->queueresume_command, "");
-                       break;
-
-               case PRINT_SYSV:
-               case PRINT_HPUX:
-                       lpcfg_string_set(ctx, &pService->lpq_command, "lpstat -o%p");
-                       lpcfg_string_set(ctx, &pService->lprm_command, "cancel %p-%j");
-                       lpcfg_string_set(ctx, &pService->print_command, "lp -c -d%p %s; rm %s");
-                       lpcfg_string_set(ctx, &pService->queuepause_command, "disable %p");
-                       lpcfg_string_set(ctx, &pService->queueresume_command, "enable %p");
-#ifndef HPUX
-                       lpcfg_string_set(ctx, &pService->lppause_command, "lp -i %p-%j -H hold");
-                       lpcfg_string_set(ctx, &pService->lpresume_command, "lp -i %p-%j -H resume");
-#endif /* HPUX */
-                       break;
-
-               case PRINT_QNX:
-                       lpcfg_string_set(ctx, &pService->lpq_command, "lpq -P%p");
-                       lpcfg_string_set(ctx, &pService->lprm_command, "lprm -P%p %j");
-                       lpcfg_string_set(ctx, &pService->print_command, "lp -r -P%p %s");
-                       break;
-
-#if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
-
-       case PRINT_TEST:
-       case PRINT_VLP: {
-               const char *tdbfile;
-               TALLOC_CTX *tmp_ctx = talloc_new(ctx);
-               char *tmp;
-
-               tdbfile = talloc_asprintf(
-                       tmp_ctx, "tdbfile=%s",
-                       lp_parm_const_string(-1, "vlp", "tdbfile",
-                                            "/tmp/vlp.tdb"));
-               if (tdbfile == NULL) {
-                       tdbfile="tdbfile=/tmp/vlp.tdb";
-               }
-
-               tmp = talloc_asprintf(tmp_ctx, "vlp %s print %%p %%s",
-                                     tdbfile);
-               lpcfg_string_set(ctx, &pService->print_command,
-                          tmp ? tmp : "vlp print %p %s");
-
-               tmp = talloc_asprintf(tmp_ctx, "vlp %s lpq %%p",
-                                     tdbfile);
-               lpcfg_string_set(ctx, &pService->lpq_command,
-                          tmp ? tmp : "vlp lpq %p");
-
-               tmp = talloc_asprintf(tmp_ctx, "vlp %s lprm %%p %%j",
-                                     tdbfile);
-               lpcfg_string_set(ctx, &pService->lprm_command,
-                          tmp ? tmp : "vlp lprm %p %j");
-
-               tmp = talloc_asprintf(tmp_ctx, "vlp %s lppause %%p %%j",
-                                     tdbfile);
-               lpcfg_string_set(ctx, &pService->lppause_command,
-                          tmp ? tmp : "vlp lppause %p %j");
-
-               tmp = talloc_asprintf(tmp_ctx, "vlp %s lpresume %%p %%j",
-                                     tdbfile);
-               lpcfg_string_set(ctx, &pService->lpresume_command,
-                          tmp ? tmp : "vlp lpresume %p %j");
-
-               tmp = talloc_asprintf(tmp_ctx, "vlp %s queuepause %%p",
-                                     tdbfile);
-               lpcfg_string_set(ctx, &pService->queuepause_command,
-                          tmp ? tmp : "vlp queuepause %p");
-
-               tmp = talloc_asprintf(tmp_ctx, "vlp %s queueresume %%p",
-                                     tdbfile);
-               lpcfg_string_set(ctx, &pService->queueresume_command,
-                          tmp ? tmp : "vlp queueresume %p");
-               TALLOC_FREE(tmp_ctx);
-
-               break;
-       }
-#endif /* DEVELOPER */
-
-       }
-}
 /**
  *  Function to return the default value for the maximum number of open
  *  file descriptors permitted.  This function tries to consult the
@@ -487,7 +328,7 @@ static void free_one_parameter_common(void *parm_ptr,
        if ((parm.type == P_STRING) ||
            (parm.type == P_USTRING))
        {
-               string_free((char**)parm_ptr);
+               lpcfg_string_free((char**)parm_ptr);
        } else if (parm.type == P_LIST || parm.type == P_CMDLIST) {
                TALLOC_FREE(*((char***)parm_ptr));
        }
@@ -561,8 +402,25 @@ static void free_parameters_by_snum(int snum)
  */
 static void free_global_parameters(void)
 {
+       uint32_t i;
+       struct parm_struct *parm;
+
        free_param_opts(&Globals.param_opt);
        free_parameters_by_snum(GLOBAL_SECTION_SNUM);
+
+       /* Reset references in the defaults because the context is going to be freed */
+       for (i=0; parm_table[i].label; i++) {
+               parm = &parm_table[i];
+               if ((parm->type == P_STRING) ||
+                   (parm->type == P_USTRING)) {
+                       if ((parm->def.svalue != NULL) &&
+                           (*(parm->def.svalue) != '\0')) {
+                               if (talloc_parent(parm->def.svalue) == Globals.ctx) {
+                                       parm->def.svalue = NULL;
+                               }
+                       }
+               }
+       }
        TALLOC_FREE(Globals.ctx);
 }
 
@@ -608,7 +466,7 @@ bool store_lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
                return false;
        }
 
-       DLIST_ADD_END(stored_options, entry, struct lp_stored_option);
+       DLIST_ADD_END(stored_options, entry);
 
        return true;
 }
@@ -630,7 +488,7 @@ static bool apply_lp_set_cmdline(void)
  Initialise the global parameter structure.
 ***************************************************************************/
 
-static void init_globals(bool reinit_globals)
+static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
 {
        static bool done_init = false;
        char *s = NULL;
@@ -644,10 +502,7 @@ static void init_globals(bool reinit_globals)
 
        if (!done_init) {
                /* The logfile can be set before this is invoked. Free it if so. */
-               if (Globals.logfile != NULL) {
-                       string_free(&Globals.logfile);
-                       Globals.logfile = NULL;
-               }
+               lpcfg_string_free(&Globals.logfile);
                done_init = true;
        } else {
                free_global_parameters();
@@ -670,51 +525,65 @@ static void init_globals(bool reinit_globals)
                if ((parm_table[i].type == P_STRING ||
                     parm_table[i].type == P_USTRING))
                {
-                       string_set(Globals.ctx, (char **)lp_parm_ptr(NULL, &parm_table[i]), "");
+                       lpcfg_string_set(
+                               Globals.ctx,
+                               (char **)lp_parm_ptr(NULL, &parm_table[i]),
+                               "");
                }
        }
 
 
-       string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
-       string_set(Globals.ctx, &sDefault.printjob_username, "%U");
+       lpcfg_string_set(Globals.ctx, &sDefault.fstype, FSTYPE_STRING);
+       lpcfg_string_set(Globals.ctx, &sDefault.printjob_username, "%U");
 
-       init_printer_values(Globals.ctx, &sDefault);
+       init_printer_values(lp_ctx, Globals.ctx, &sDefault);
 
-       sDefault.ntvfs_handler = (const char **)str_list_make_v3(NULL, "unixuid default", NULL);
+       sDefault.ntvfs_handler = str_list_make_v3_const(NULL, "unixuid default", NULL);
 
        DEBUG(3, ("Initialising global parameters\n"));
 
        /* Must manually force to upper case here, as this does not go via the handler */
-       string_set(Globals.ctx, &Globals.netbios_name, myhostname_upper());
+       lpcfg_string_set(Globals.ctx, &Globals.netbios_name,
+                        myhostname_upper());
 
-       string_set(Globals.ctx, &Globals.smb_passwd_file, get_dyn_SMB_PASSWD_FILE());
-       string_set(Globals.ctx, &Globals.private_dir, get_dyn_PRIVATE_DIR());
+       lpcfg_string_set(Globals.ctx, &Globals.smb_passwd_file,
+                        get_dyn_SMB_PASSWD_FILE());
+       lpcfg_string_set(Globals.ctx, &Globals.private_dir,
+                        get_dyn_PRIVATE_DIR());
 
        /* use the new 'hash2' method by default, with a prefix of 1 */
-       string_set(Globals.ctx, &Globals.mangling_method, "hash2");
+       lpcfg_string_set(Globals.ctx, &Globals.mangling_method, "hash2");
        Globals.mangle_prefix = 1;
 
-       string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
+       lpcfg_string_set(Globals.ctx, &Globals.guest_account, GUEST_ACCOUNT);
 
        /* using UTF8 by default allows us to support all chars */
-       string_set(Globals.ctx, &Globals.unix_charset, DEFAULT_UNIX_CHARSET);
+       lpcfg_string_set(Globals.ctx, &Globals.unix_charset,
+                        DEFAULT_UNIX_CHARSET);
 
        /* Use codepage 850 as a default for the dos character set */
-       string_set(Globals.ctx, &Globals.dos_charset, DEFAULT_DOS_CHARSET);
+       lpcfg_string_set(Globals.ctx, &Globals.dos_charset,
+                        DEFAULT_DOS_CHARSET);
 
        /*
         * Allow the default PASSWD_CHAT to be overridden in local.h.
         */
-       string_set(Globals.ctx, &Globals.passwd_chat, DEFAULT_PASSWD_CHAT);
-
-       string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
-
-       string_set(Globals.ctx, &Globals.passwd_program, "");
-       string_set(Globals.ctx, &Globals.lock_directory, get_dyn_LOCKDIR());
-       string_set(Globals.ctx, &Globals.state_directory, get_dyn_STATEDIR());
-       string_set(Globals.ctx, &Globals.cache_directory, get_dyn_CACHEDIR());
-       string_set(Globals.ctx, &Globals.pid_directory, get_dyn_PIDDIR());
-       string_set(Globals.ctx, &Globals.nbt_client_socket_address, "0.0.0.0");
+       lpcfg_string_set(Globals.ctx, &Globals.passwd_chat,
+                        DEFAULT_PASSWD_CHAT);
+
+       lpcfg_string_set(Globals.ctx, &Globals.workgroup, DEFAULT_WORKGROUP);
+
+       lpcfg_string_set(Globals.ctx, &Globals.passwd_program, "");
+       lpcfg_string_set(Globals.ctx, &Globals.lock_directory,
+                        get_dyn_LOCKDIR());
+       lpcfg_string_set(Globals.ctx, &Globals.state_directory,
+                        get_dyn_STATEDIR());
+       lpcfg_string_set(Globals.ctx, &Globals.cache_directory,
+                        get_dyn_CACHEDIR());
+       lpcfg_string_set(Globals.ctx, &Globals.pid_directory,
+                        get_dyn_PIDDIR());
+       lpcfg_string_set(Globals.ctx, &Globals.nbt_client_socket_address,
+                        "0.0.0.0");
        /*
         * By default support explicit binding to broadcast
         * addresses.
@@ -725,21 +594,24 @@ static void init_globals(bool reinit_globals)
        if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
-       string_set(Globals.ctx, &Globals.server_string, s);
+       lpcfg_string_set(Globals.ctx, &Globals.server_string, s);
        TALLOC_FREE(s);
 #ifdef DEVELOPER
-       string_set(Globals.ctx, &Globals.panic_action, "/bin/sleep 999999999");
+       lpcfg_string_set(Globals.ctx, &Globals.panic_action,
+                        "/bin/sleep 999999999");
 #endif
 
-       string_set(Globals.ctx, &Globals.socket_options, DEFAULT_SOCKET_OPTIONS);
+       lpcfg_string_set(Globals.ctx, &Globals.socket_options,
+                        DEFAULT_SOCKET_OPTIONS);
 
-       string_set(Globals.ctx, &Globals.logon_drive, "");
+       lpcfg_string_set(Globals.ctx, &Globals.logon_drive, "");
        /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
-       string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
-       string_set(Globals.ctx, &Globals.logon_path, "\\\\%N\\%U\\profile");
+       lpcfg_string_set(Globals.ctx, &Globals.logon_home, "\\\\%N\\%U");
+       lpcfg_string_set(Globals.ctx, &Globals.logon_path,
+                        "\\\\%N\\%U\\profile");
 
-       Globals.name_resolve_order = (const char **)str_list_make_v3(NULL, "lmhosts wins host bcast", NULL);
-       string_set(Globals.ctx, &Globals.password_server, "*");
+       Globals.name_resolve_order = str_list_make_v3_const(NULL, "lmhosts wins host bcast", NULL);
+       lpcfg_string_set(Globals.ctx, &Globals.password_server, "*");
 
        Globals.algorithmic_rid_base = BASE_RID;
 
@@ -762,9 +634,9 @@ static void init_globals(bool reinit_globals)
        Globals.large_readwrite = true;
        Globals.max_log_size = 5000;
        Globals.max_open_files = max_open_files();
-       Globals.server_max_protocol = PROTOCOL_SMB3_00;
+       Globals.server_max_protocol = PROTOCOL_SMB3_11;
        Globals.server_min_protocol = PROTOCOL_LANMAN1;
-       Globals.client_max_protocol = PROTOCOL_NT1;
+       Globals._client_max_protocol = PROTOCOL_DEFAULT;
        Globals.client_min_protocol = PROTOCOL_CORE;
        Globals._security = SEC_AUTO;
        Globals.encrypt_passwords = true;
@@ -780,7 +652,7 @@ static void init_globals(bool reinit_globals)
        Globals.syslog = 1;
        Globals.syslog_only = false;
        Globals.timestamp_logs = true;
-       string_set(Globals.ctx, &Globals.log_level, "0");
+       lpcfg_string_set(Globals.ctx, &Globals.log_level, "0");
        Globals.debug_prefix_timestamp = false;
        Globals.debug_hires_timestamp = true;
        Globals.debug_pid = false;
@@ -796,9 +668,10 @@ static void init_globals(bool reinit_globals)
 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
        Globals.nis_homedir = false;
 #ifdef WITH_NISPLUS_HOME
-       string_set(Globals.ctx, &Globals.homedir_map, "auto_home.org_dir");
+       lpcfg_string_set(Globals.ctx, &Globals.homedir_map,
+                        "auto_home.org_dir");
 #else
-       string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
+       lpcfg_string_set(Globals.ctx, &Globals.homedir_map, "auto.home");
 #endif
 #endif
        Globals.time_server = false;
@@ -809,6 +682,7 @@ static void init_globals(bool reinit_globals)
        Globals.passwd_chat_timeout = 2; /* 2 second default. */
        Globals.nt_pipe_support = true; /* Do NT pipes by default. */
        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.restrict_anonymous = 0;
@@ -816,6 +690,7 @@ static void init_globals(bool reinit_globals)
        Globals.client_plaintext_auth = false;  /* Do NOT use a plaintext password even if is requested by the server */
        Globals.lanman_auth = false;    /* Do NOT use the LanMan hash, even if it is supplied */
        Globals.ntlm_auth = true;       /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */
+       Globals.raw_ntlmv2_auth = false; /* Reject NTLMv2 without NTLMSSP */
        Globals.client_ntlmv2_auth = true; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */
        /* Note, that we will also use NTLM2 session security (which is different), if it is available */
 
@@ -833,20 +708,23 @@ static void init_globals(bool reinit_globals)
        Globals.reset_on_zero_vc = false;
        Globals.log_writeable_files_on_exit = false;
        Globals.create_krb5_conf = true;
-       Globals.winbindMaxDomainConnections = 1;
+       Globals._winbind_max_domain_connections = 1;
 
        /* hostname lookups can be very expensive and are broken on
           a large number of sites (tridge) */
        Globals.hostname_lookups = false;
 
-       string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
-       string_set(Globals.ctx, &Globals.ldap_suffix, "");
-       string_set(Globals.ctx, &Globals.szLdapMachineSuffix, "");
-       string_set(Globals.ctx, &Globals.szLdapUserSuffix, "");
-       string_set(Globals.ctx, &Globals.szLdapGroupSuffix, "");
-       string_set(Globals.ctx, &Globals.szLdapIdmapSuffix, "");
+       Globals.change_notify = true,
+       Globals.kernel_change_notify = true,
+
+       lpcfg_string_set(Globals.ctx, &Globals.passdb_backend, "tdbsam");
+       lpcfg_string_set(Globals.ctx, &Globals.ldap_suffix, "");
+       lpcfg_string_set(Globals.ctx, &Globals._ldap_machine_suffix, "");
+       lpcfg_string_set(Globals.ctx, &Globals._ldap_user_suffix, "");
+       lpcfg_string_set(Globals.ctx, &Globals._ldap_group_suffix, "");
+       lpcfg_string_set(Globals.ctx, &Globals._ldap_idmap_suffix, "");
 
-       string_set(Globals.ctx, &Globals.ldap_admin_dn, "");
+       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;
@@ -861,6 +739,11 @@ static void init_globals(bool reinit_globals)
        Globals.ldap_debug_level = 0;
        Globals.ldap_debug_threshold = 10;
 
+       Globals.client_ldap_sasl_wrapping = ADS_AUTH_SASL_SIGN;
+
+       Globals.ldap_server_require_strong_auth =
+               LDAP_SERVER_REQUIRE_STRONG_AUTH_NO;
+
        /* This is what we tell the afs client. in reality we set the token 
         * to never expire, though, when this runs out the afs client will 
         * forget the token. Set to 0 to get NEVERDATE.*/
@@ -894,17 +777,19 @@ static void init_globals(bool reinit_globals)
        Globals.wins_dns_proxy = true;
 
        Globals.allow_trusted_domains = true;
-       string_set(Globals.ctx, &Globals.szIdmapBackend, "tdb");
+       lpcfg_string_set(Globals.ctx, &Globals.idmap_backend, "tdb");
 
-       string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
-       string_set(Globals.ctx, &Globals.template_homedir, "/home/%D/%U");
-       string_set(Globals.ctx, &Globals.winbind_separator, "\\");
-       string_set(Globals.ctx, &Globals.winbindd_socket_directory, dyn_WINBINDD_SOCKET_DIR);
+       lpcfg_string_set(Globals.ctx, &Globals.template_shell, "/bin/false");
+       lpcfg_string_set(Globals.ctx, &Globals.template_homedir,
+                        "/home/%D/%U");
+       lpcfg_string_set(Globals.ctx, &Globals.winbind_separator, "\\");
+       lpcfg_string_set(Globals.ctx, &Globals.winbindd_socket_directory,
+                        dyn_WINBINDD_SOCKET_DIR);
 
-       string_set(Globals.ctx, &Globals.cups_server, "");
-       string_set(Globals.ctx, &Globals.iprint_server, "");
+       lpcfg_string_set(Globals.ctx, &Globals.cups_server, "");
+       lpcfg_string_set(Globals.ctx, &Globals.iprint_server, "");
 
-       string_set(Globals.ctx, &Globals._ctdbd_socket, "");
+       lpcfg_string_set(Globals.ctx, &Globals._ctdbd_socket, "");
 
        Globals.cluster_addresses = NULL;
        Globals.clustering = false;
@@ -913,14 +798,15 @@ static void init_globals(bool reinit_globals)
 
        Globals.winbind_cache_time = 300;       /* 5 minutes */
        Globals.winbind_reconnect_delay = 30;   /* 30 seconds */
+       Globals.winbind_request_timeout = 60;   /* 60 seconds */
        Globals.winbind_max_clients = 200;
        Globals.winbind_enum_users = false;
        Globals.winbind_enum_groups = false;
        Globals.winbind_use_default_domain = false;
        Globals.winbind_trusted_domains_only = false;
        Globals.winbind_nested_groups = true;
-       Globals.winbind_expand_groups = 1;
-       Globals.winbind_nss_info = (const char **)str_list_make_v3(NULL, "template", NULL);
+       Globals.winbind_expand_groups = 0;
+       Globals.winbind_nss_info = str_list_make_v3_const(NULL, "template", NULL);
        Globals.winbind_refresh_tickets = false;
        Globals.winbind_offline_logon = false;
 
@@ -938,7 +824,7 @@ static void init_globals(bool reinit_globals)
        Globals.server_signing = SMB_SIGNING_DEFAULT;
 
        Globals.defer_sharing_violations = true;
-       Globals.smb_ports = (const char **)str_list_make_v3(NULL, SMB_PORTS, NULL);
+       Globals.smb_ports = str_list_make_v3_const(NULL, SMB_PORTS, NULL);
 
        Globals.enable_privileges = true;
        Globals.host_msdfs        = true;
@@ -949,9 +835,9 @@ static void init_globals(bool reinit_globals)
        if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
-       string_set(Globals.ctx, &Globals.usershare_path, s);
+       lpcfg_string_set(Globals.ctx, &Globals.usershare_path, s);
        TALLOC_FREE(s);
-       string_set(Globals.ctx, &Globals.usershare_template_share, "");
+       lpcfg_string_set(Globals.ctx, &Globals.usershare_template_share, "");
        Globals.usershare_max_shares = 0;
        /* By default disallow sharing of directories not owned by the sharer. */
        Globals.usershare_owner_only = true;
@@ -963,7 +849,7 @@ static void init_globals(bool reinit_globals)
        /* By default no shares out of the registry */
        Globals.registry_shares = false;
 
-       Globals.iminreceivefile = 0;
+       Globals.min_receivefile_size = 0;
 
        Globals.map_untrusted_to_domain = false;
        Globals.multicast_dns_register = true;
@@ -971,60 +857,67 @@ static void init_globals(bool reinit_globals)
        Globals.smb2_max_read = DEFAULT_SMB2_MAX_READ;
        Globals.smb2_max_write = DEFAULT_SMB2_MAX_WRITE;
        Globals.smb2_max_trans = DEFAULT_SMB2_MAX_TRANSACT;
-       Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
+       Globals.smb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
+       Globals.smb2_leases = false;
 
-       string_set(Globals.ctx, &Globals.ncalrpc_dir, get_dyn_NCALRPCDIR());
+       lpcfg_string_set(Globals.ctx, &Globals.ncalrpc_dir,
+                        get_dyn_NCALRPCDIR());
 
-       Globals.server_services = (const char **)str_list_make_v3(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL);
+       Globals.server_services = str_list_make_v3_const(NULL, "s3fs rpc nbt wrepl ldap cldap kdc drepl winbindd ntp_signd kcc dnsupdate dns", NULL);
 
-       Globals.dcerpc_endpoint_servers = (const char **)str_list_make_v3(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
+       Globals.dcerpc_endpoint_servers = str_list_make_v3_const(NULL, "epmapper wkssvc rpcecho samr netlogon lsarpc spoolss drsuapi dssetup unixinfo browser eventlog6 backupkey dnsserver", NULL);
 
        Globals.tls_enabled = true;
 
-       string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
-       string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
-       string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
+       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,
+                        "NORMAL:-VERS-SSL3.0");
 
-       string_set(Globals.ctx, &Globals.share_backend, "classic");
+       lpcfg_string_set(Globals.ctx, &Globals.share_backend, "classic");
 
-       Globals.iPreferredMaster = Auto;
+       Globals._preferred_master = Auto;
 
        Globals.allow_dns_updates = DNS_UPDATE_SIGNED;
 
-       string_set(Globals.ctx, &Globals.ntp_signd_socket_directory, get_dyn_NTP_SIGND_SOCKET_DIR());
+       lpcfg_string_set(Globals.ctx, &Globals.ntp_signd_socket_directory,
+                        get_dyn_NTP_SIGND_SOCKET_DIR());
 
-       string_set(Globals.ctx, &Globals.winbindd_privileged_socket_directory, get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
+       lpcfg_string_set(Globals.ctx,
+                        &Globals.winbindd_privileged_socket_directory,
+                        get_dyn_WINBINDD_PRIVILEGED_SOCKET_DIR());
 
        s = talloc_asprintf(talloc_tos(), "%s/samba_kcc", get_dyn_SCRIPTSBINDIR());
        if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
-       Globals.samba_kcc_command = (const char **)str_list_make_v3(NULL, s, NULL);
+       Globals.samba_kcc_command = str_list_make_v3_const(NULL, s, NULL);
        TALLOC_FREE(s);
 
        s = talloc_asprintf(talloc_tos(), "%s/samba_dnsupdate", get_dyn_SCRIPTSBINDIR());
        if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
-       Globals.dns_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
+       Globals.dns_update_command = str_list_make_v3_const(NULL, s, NULL);
        TALLOC_FREE(s);
 
        s = talloc_asprintf(talloc_tos(), "%s/samba_spnupdate", get_dyn_SCRIPTSBINDIR());
        if (s == NULL) {
                smb_panic("init_globals: ENOMEM");
        }
-       Globals.spn_update_command = (const char **)str_list_make_v3(NULL, s, NULL);
+       Globals.spn_update_command = str_list_make_v3_const(NULL, s, NULL);
        TALLOC_FREE(s);
 
-       Globals.nsupdate_command = (const char **)str_list_make_v3(NULL, "/usr/bin/nsupdate -g", NULL);
+       Globals.nsupdate_command = str_list_make_v3_const(NULL, "/usr/bin/nsupdate -g", NULL);
 
-       Globals.rndc_command = (const char **)str_list_make_v3(NULL, "/usr/sbin/rndc", NULL);
+       Globals.rndc_command = str_list_make_v3_const(NULL, "/usr/sbin/rndc", NULL);
 
        Globals.cldap_port = 389;
 
-       Globals.dgram_port = 138;
+       Globals.dgram_port = NBT_DGRAM_SERVICE_PORT;
 
-       Globals.nbt_port = 137;
+       Globals.nbt_port = NBT_NAME_SERVICE_PORT;
 
        Globals.krb5_port = 88;
 
@@ -1032,10 +925,32 @@ static void init_globals(bool reinit_globals)
 
        Globals.web_port = 901;
 
+       Globals.aio_max_threads = 100;
+
        /* Now put back the settings that were set with lp_set_cmdline() */
        apply_lp_set_cmdline();
 }
 
+/* Convenience routine to setup an lp_context with additional s3 variables */
+static struct loadparm_context *setup_lp_context(TALLOC_CTX *mem_ctx)
+{
+       struct loadparm_context *lp_ctx;
+
+       lp_ctx = loadparm_init_s3(mem_ctx,
+                                 loadparm_s3_helpers());
+       if (lp_ctx == NULL) {
+               DEBUG(0, ("loadparm_init_s3 failed\n"));
+               return NULL;
+       }
+
+       lp_ctx->sDefault = &sDefault;
+       lp_ctx->services = NULL; /* We do not want to access this directly */
+       lp_ctx->bInGlobalSection = bInGlobalSection;
+       lp_ctx->flags = flags_list;
+
+       return lp_ctx;
+}
+
 /*******************************************************************
  Convenience routine to grab string parameters into talloced memory
  and run standard_sub_basic on them. The buffers can be written to by
@@ -1110,44 +1025,15 @@ char *lp_ ## fn_name(TALLOC_CTX *ctx,int i) {return(lp_string((ctx), (LP_SNUM_OK
 #define FN_LOCAL_PARM_CHAR(fn_name,val) \
  char lp_ ## fn_name(const struct share_params *p) {return(LP_SNUM_OK(p->service)? ServicePtrs[(p->service)]->val : sDefault.val);}
 
-static FN_GLOBAL_INTEGER(winbind_max_domain_connections_int,
-                 winbindMaxDomainConnections)
-
 int lp_winbind_max_domain_connections(void)
 {
        if (lp_winbind_offline_logon() &&
-           lp_winbind_max_domain_connections_int() > 1) {
+           lp__winbind_max_domain_connections() > 1) {
                DEBUG(1, ("offline logons active, restricting max domain "
                          "connections to 1\n"));
                return 1;
        }
-       return MAX(1, lp_winbind_max_domain_connections_int());
-}
-
-int lp_smb2_max_credits(void)
-{
-       if (Globals.ismb2_max_credits == 0) {
-               Globals.ismb2_max_credits = DEFAULT_SMB2_MAX_CREDITS;
-       }
-       return Globals.ismb2_max_credits;
-}
-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;
+       return MAX(1, lp__winbind_max_domain_connections());
 }
 
 /* These functions remain in source3/param for now */
@@ -1190,6 +1076,79 @@ static struct parmlist_entry *get_parametrics(int snum, const char *type,
        }
 }
 
+static void discard_whitespace(char *str)
+{
+       size_t len = strlen(str);
+       size_t i = 0;
+
+       while (i < len) {
+               if (isspace(str[i])) {
+                       memmove(&str[i], &str[i+1], len-i);
+                       len -= 1;
+                       continue;
+               }
+               i += 1;
+       }
+}
+
+/**
+ * @brief Go through all global parametric parameters
+ *
+ * @param regex_str    A regular expression to scan param for
+ * @param max_matches   Max number of submatches the regexp expects
+ * @param cb           Function to call on match. Should return true
+ *                      when it wants wi_scan_global_parametrics to stop
+ *                      scanning
+ * @param private_data  Anonymous pointer passed to cb
+ *
+ * @return              0: success, regcomp/regexec return value on error.
+ *                      See "man regexec" for possible errors
+ */
+
+int lp_wi_scan_global_parametrics(
+       const char *regex_str, size_t max_matches,
+       bool (*cb)(const char *string, regmatch_t matches[],
+                  void *private_data),
+       void *private_data)
+{
+       struct parmlist_entry *data;
+       regex_t regex;
+       int ret;
+
+       ret = regcomp(&regex, regex_str, REG_ICASE);
+       if (ret != 0) {
+               return ret;
+       }
+
+       for (data = Globals.param_opt; data != NULL; data = data->next) {
+               size_t keylen = strlen(data->key);
+               char key[keylen+1];
+               regmatch_t matches[max_matches];
+               bool stop;
+
+               memcpy(key, data->key, sizeof(key));
+               discard_whitespace(key);
+
+               ret = regexec(&regex, key, max_matches, matches, 0);
+               if (ret == REG_NOMATCH) {
+                       continue;
+               }
+               if (ret != 0) {
+                       goto fail;
+               }
+
+               stop = cb(key, matches, private_data);
+               if (stop) {
+                       break;
+               }
+       }
+
+       ret = 0;
+fail:
+       regfree(&regex);
+       return ret;
+}
+
 
 #define MISSING_PARAMETER(name) \
     DEBUG(0, ("%s(): value is NULL or empty!\n", #name))
@@ -1261,7 +1220,7 @@ const char **lp_parm_string_list(int snum, const char *type, const char *option,
                data->list = str_list_make_v3(NULL, data->value, NULL);
        }
 
-       return (const char **)data->list;
+       return discard_const_p(const char *, data->list);
 }
 
 /* Return parametric option from a given service. Type is a part of option before ':' */
@@ -1293,6 +1252,22 @@ unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsi
 /* Return parametric option from a given service. Type is a part of option before ':' */
 /* Parametric option has following syntax: 'Type: option = value' */
 
+unsigned long long lp_parm_ulonglong(int snum, const char *type,
+                                    const char *option, unsigned long long def)
+{
+       struct parmlist_entry *data = get_parametrics(snum, type, option);
+
+       if (data && data->value && *data->value) {
+               return lp_ulonglong(data->value);
+       }
+
+       return def;
+}
+
+/* Return parametric option from a given service. Type is a part of option
+ * before ':' */
+/* Parametric option has following syntax: 'Type: option = value' */
+
 bool lp_parm_bool(int snum, const char *type, const char *option, bool def)
 {
        struct parmlist_entry *data = get_parametrics(snum, type, option);
@@ -1332,8 +1307,8 @@ static void free_param_opts(struct parmlist_entry **popts)
        }
        opt = *popts;
        while (opt != NULL) {
-               string_free(&opt->key);
-               string_free(&opt->value);
+               lpcfg_string_free(&opt->key);
+               lpcfg_string_free(&opt->value);
                TALLOC_FREE(opt->list);
                next_opt = opt->next;
                TALLOC_FREE(opt);
@@ -1357,7 +1332,7 @@ static void free_service(struct loadparm_service *pservice)
 
        free_parameters(pservice);
 
-       string_free(&pservice->szService);
+       lpcfg_string_free(&pservice->szService);
        TALLOC_FREE(pservice->copymap);
 
        free_param_opts(&pservice->param_opt);
@@ -1390,7 +1365,7 @@ static void free_service_byindex(int idx)
        }
 
        free_service(ServicePtrs[idx]);
-       talloc_free_children(ServicePtrs[idx]);
+       TALLOC_FREE(ServicePtrs[idx]);
 }
 
 /***************************************************************************
@@ -1401,7 +1376,6 @@ static void free_service_byindex(int idx)
 static int add_a_service(const struct loadparm_service *pservice, const char *name)
 {
        int i;
-       int num_to_alloc = iNumServices + 1;
        struct loadparm_service **tsp = NULL;
 
        /* it might already exist */
@@ -1412,26 +1386,37 @@ static int add_a_service(const struct loadparm_service *pservice, const char *na
                }
        }
 
-       /* if not, then create one */
-       i = iNumServices;
-       tsp = talloc_realloc(NULL, ServicePtrs, struct loadparm_service *, num_to_alloc);
-       if (tsp == NULL) {
-               DEBUG(0,("add_a_service: failed to enlarge ServicePtrs!\n"));
-               return (-1);
+       /* Re use empty slots if any before allocating new one.*/
+       for (i=0; i < iNumServices; i++) {
+               if (ServicePtrs[i] == NULL) {
+                       break;
+               }
+       }
+       if (i == iNumServices) {
+               /* if not, then create one */
+               tsp = talloc_realloc(NULL, ServicePtrs,
+                                    struct loadparm_service *,
+                                    iNumServices + 1);
+               if (tsp == NULL) {
+                       DEBUG(0, ("add_a_service: failed to enlarge "
+                                 "ServicePtrs!\n"));
+                       return (-1);
+               }
+               ServicePtrs = tsp;
+               iNumServices++;
        }
-       ServicePtrs = tsp;
-       ServicePtrs[iNumServices] = talloc_zero(NULL, struct loadparm_service);
-       if (!ServicePtrs[iNumServices]) {
+       ServicePtrs[i] = talloc_zero(ServicePtrs, struct loadparm_service);
+       if (!ServicePtrs[i]) {
                DEBUG(0,("add_a_service: out of memory!\n"));
                return (-1);
        }
-       iNumServices++;
 
        ServicePtrs[i]->valid = true;
 
        copy_service(ServicePtrs[i], pservice, NULL);
        if (name)
-               string_set(ServicePtrs[i], &ServicePtrs[i]->szService, name);
+               lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->szService,
+                                name);
 
        DEBUG(8,("add_a_service: Creating snum = %d for %s\n", 
                i, ServicePtrs[i]->szService));
@@ -1489,7 +1474,7 @@ static bool hash_a_service(const char *name, int idx)
        canon_name = canonicalize_servicename(talloc_tos(), name );
 
        dbwrap_store_bystring(ServiceHash, canon_name,
-                             make_tdb_data((uint8 *)&idx, sizeof(idx)),
+                             make_tdb_data((uint8_t *)&idx, sizeof(idx)),
                              TDB_REPLACE);
 
        TALLOC_FREE(canon_name);
@@ -1520,7 +1505,8 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
        if (!(*(ServicePtrs[iDefaultService]->path))
            || strequal(ServicePtrs[iDefaultService]->path,
                        lp_path(talloc_tos(), GLOBAL_SECTION_SNUM))) {
-               string_set(ServicePtrs[i], &ServicePtrs[i]->path, pszHomedir);
+               lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path,
+                                pszHomedir);
        }
 
        if (!(*(ServicePtrs[i]->comment))) {
@@ -1528,7 +1514,8 @@ bool lp_add_home(const char *pszHomename, int iDefaultService,
                if (comment == NULL) {
                        return false;
                }
-               string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+               lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment,
+                                comment);
                TALLOC_FREE(comment);
        }
 
@@ -1576,18 +1563,19 @@ static bool lp_add_ipc(const char *ipc_name, bool guest_ok)
                return false;
        }
 
-       string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
-       string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
-       string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
-       string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
+       lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->path, tmpdir());
+       lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->username, "");
+       lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+       lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->fstype, "IPC");
        ServicePtrs[i]->max_connections = 0;
-       ServicePtrs[i]->bAvailable = true;
+       ServicePtrs[i]->available = true;
        ServicePtrs[i]->read_only = true;
        ServicePtrs[i]->guest_only = false;
        ServicePtrs[i]->administrative_share = true;
        ServicePtrs[i]->guest_ok = guest_ok;
        ServicePtrs[i]->printable = false;
        ServicePtrs[i]->browseable = sDefault.browseable;
+       ServicePtrs[i]->autoloaded = true;
 
        DEBUG(3, ("adding IPC service\n"));
 
@@ -1613,8 +1601,9 @@ bool lp_add_printer(const char *pszPrintername, int iDefaultService)
        /* entry (if/when the 'available' keyword is implemented!).    */
 
        /* the printer name is set to the service name. */
-       string_set(ServicePtrs[i], &ServicePtrs[i]->_printername, pszPrintername);
-       string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+       lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->_printername,
+                        pszPrintername);
+       lpcfg_string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
 
        /* set the browseable flag from the gloabl default */
        ServicePtrs[i]->browseable = sDefault.browseable;
@@ -1661,22 +1650,6 @@ bool lp_parameter_is_global(const char *pszParmName)
        return false;
 }
 
-/**************************************************************************
- Check whether the given name is the canonical name of a parameter.
- Returns false if it is not a valid parameter Name.
- For parametric options, true is returned.
-**************************************************************************/
-
-bool lp_parameter_is_canonical(const char *parm_name)
-{
-       if (!lp_parameter_is_valid(parm_name)) {
-               return false;
-       }
-
-       return (lpcfg_map_parameter(parm_name) ==
-               map_parameter_canonical(parm_name, NULL));
-}
-
 /**************************************************************************
  Determine the canonical name for a parameter.
  Indicate when it is an inverse (boolean) synonym instead of a
@@ -1762,7 +1735,7 @@ static int map_parameter_canonical(const char *pszParmName, bool *inverse)
        bool loc_inverse = false;
 
        parm_num = lpcfg_map_parameter(pszParmName);
-       if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_HIDE)) {
+       if ((parm_num < 0) || !(parm_table[parm_num].flags & FLAG_SYNONYM)) {
                /* invalid, parametric or no canidate for synonyms ... */
                goto done;
        }
@@ -1792,8 +1765,8 @@ static bool is_synonym_of(int parm1, int parm2, bool *inverse)
 {
        if ((parm_table[parm1].offset == parm_table[parm2].offset) &&
            (parm_table[parm1].p_class == parm_table[parm2].p_class) &&
-           (parm_table[parm1].flags & FLAG_HIDE) &&
-           !(parm_table[parm2].flags & FLAG_HIDE))
+           (parm_table[parm1].flags & FLAG_SYNONYM) &&
+           !(parm_table[parm2].flags & FLAG_SYNONYM))
        {
                if (inverse != NULL) {
                        if ((parm_table[parm1].type == P_BOOLREV) &&
@@ -1823,13 +1796,9 @@ static void show_parameter(int parmIndex)
        bool inverse;
        const char *type[] = { "P_BOOL", "P_BOOLREV", "P_CHAR", "P_INTEGER",
                "P_OCTAL", "P_LIST", "P_STRING", "P_USTRING",
-               "P_ENUM", "P_SEP"};
-       unsigned flags[] = { FLAG_BASIC, FLAG_SHARE, FLAG_PRINT, FLAG_GLOBAL,
-               FLAG_WIZARD, FLAG_ADVANCED, FLAG_DEVELOPER, FLAG_DEPRECATED,
-               FLAG_HIDE};
-       const char *flag_names[] = { "FLAG_BASIC", "FLAG_SHARE", "FLAG_PRINT",
-               "FLAG_GLOBAL", "FLAG_WIZARD", "FLAG_ADVANCED", "FLAG_DEVELOPER",
-               "FLAG_DEPRECATED", "FLAG_HIDE", NULL};
+               "P_ENUM", "P_BYTES", "P_CMDLIST" };
+       unsigned flags[] = { FLAG_DEPRECATED, FLAG_SYNONYM };
+       const char *flag_names[] = { "FLAG_DEPRECATED", "FLAG_SYNONYM", NULL};
 
        printf("%s=%s", parm_table[parmIndex].label,
               type[parm_table[parmIndex].type]);
@@ -2006,52 +1975,6 @@ struct loadparm_service *lp_default_loadparm_service()
        return &sDefault;
 }
 
-/***************************************************************************
-Check a service for consistency. Return false if the service is in any way
-incomplete or faulty, else true.
-***************************************************************************/
-
-bool service_ok(int iService)
-{
-       bool bRetval;
-
-       bRetval = true;
-       if (ServicePtrs[iService]->szService[0] == '\0') {
-               DEBUG(0, ("The following message indicates an internal error:\n"));
-               DEBUG(0, ("No service name in service entry.\n"));
-               bRetval = false;
-       }
-
-       /* The [printers] entry MUST be printable. I'm all for flexibility, but */
-       /* I can't see why you'd want a non-printable printer service...        */
-       if (strwicmp(ServicePtrs[iService]->szService, PRINTERS_NAME) == 0) {
-               if (!ServicePtrs[iService]->printable) {
-                       DEBUG(0, ("WARNING: [%s] service MUST be printable!\n",
-                              ServicePtrs[iService]->szService));
-                       ServicePtrs[iService]->printable = true;
-               }
-               /* [printers] service must also be non-browsable. */
-               if (ServicePtrs[iService]->browseable)
-                       ServicePtrs[iService]->browseable = false;
-       }
-
-       if (ServicePtrs[iService]->path[0] == '\0' &&
-           strwicmp(ServicePtrs[iService]->szService, HOMES_NAME) != 0 &&
-           ServicePtrs[iService]->msdfs_proxy[0] == '\0'
-           ) {
-               DEBUG(0, ("WARNING: No path in service %s - making it unavailable!\n",
-                       ServicePtrs[iService]->szService));
-               ServicePtrs[iService]->bAvailable = false;
-       }
-
-       /* If a service is flagged unavailable, log the fact at level 1. */
-       if (!ServicePtrs[iService]->bAvailable)
-               DEBUG(1, ("NOTE: Service %s is flagged unavailable.\n",
-                         ServicePtrs[iService]->szService));
-
-       return (bRetval);
-}
-
 static struct smbconf_ctx *lp_smbconf_ctx(void)
 {
        sbcErr err;
@@ -2101,7 +2024,7 @@ static bool process_smbconf_service(struct smbconf_service *service)
                }
        }
        if (iServiceIndex >= 0) {
-               return service_ok(iServiceIndex);
+               return lpcfg_service_ok(ServicePtrs[iServiceIndex]);
        }
        return true;
 }
@@ -2295,8 +2218,6 @@ bool lp_file_list_changed(void)
        DEBUG(6, ("lp_file_list_changed()\n"));
 
        while (f) {
-               time_t mod_time;
-
                if (strequal(f->name, INCLUDE_REGISTRY_NAME)) {
                        struct smbconf_ctx *conf_ctx = lp_smbconf_ctx();
 
@@ -2310,7 +2231,9 @@ bool lp_file_list_changed(void)
                                return true;
                        }
                } else {
+                       time_t mod_time;
                        char *n2 = NULL;
+
                        n2 = talloc_sub_basic(talloc_tos(),
                                              get_current_username(),
                                              current_user_info.domain,
@@ -2367,7 +2290,8 @@ static void init_iconv(void)
 ***************************************************************************/
 static bool bAllowIncludeRegistry = true;
 
-bool lp_include(struct loadparm_context *lp_ctx, int snum, const char *pszParmValue, char **ptr)
+bool lp_include(struct loadparm_context *lp_ctx, struct loadparm_service *service,
+               const char *pszParmValue, char **ptr)
 {
        char *fname;
 
@@ -2400,16 +2324,16 @@ bool lp_include(struct loadparm_context *lp_ctx, int snum, const char *pszParmVa
 
        add_to_file_list(NULL, &file_lists, pszParmValue, fname);
 
-       if (snum < 0) {
-               string_set(Globals.ctx, ptr, fname);
+       if (service == NULL) {
+               lpcfg_string_set(Globals.ctx, ptr, fname);
        } else {
-               string_set(ServicePtrs[snum], ptr, fname);
+               lpcfg_string_set(service, ptr, fname);
        }
 
        if (file_exist(fname)) {
                bool ret;
                include_depth++;
-               ret = pm_process(fname, lp_do_section, do_parameter, NULL);
+               ret = pm_process(fname, lp_do_section, do_parameter, lp_ctx);
                include_depth--;
                TALLOC_FREE(fname);
                return ret;
@@ -2517,32 +2441,32 @@ static const char *append_ldap_suffix(TALLOC_CTX *ctx, const char *str )
 
 const char *lp_ldap_machine_suffix(TALLOC_CTX *ctx)
 {
-       if (Globals.szLdapMachineSuffix[0])
-               return append_ldap_suffix(ctx, Globals.szLdapMachineSuffix);
+       if (Globals._ldap_machine_suffix[0])
+               return append_ldap_suffix(ctx, Globals._ldap_machine_suffix);
 
        return lp_string(ctx, Globals.ldap_suffix);
 }
 
 const char *lp_ldap_user_suffix(TALLOC_CTX *ctx)
 {
-       if (Globals.szLdapUserSuffix[0])
-               return append_ldap_suffix(ctx, Globals.szLdapUserSuffix);
+       if (Globals._ldap_user_suffix[0])
+               return append_ldap_suffix(ctx, Globals._ldap_user_suffix);
 
        return lp_string(ctx, Globals.ldap_suffix);
 }
 
 const char *lp_ldap_group_suffix(TALLOC_CTX *ctx)
 {
-       if (Globals.szLdapGroupSuffix[0])
-               return append_ldap_suffix(ctx, Globals.szLdapGroupSuffix);
+       if (Globals._ldap_group_suffix[0])
+               return append_ldap_suffix(ctx, Globals._ldap_group_suffix);
 
        return lp_string(ctx, Globals.ldap_suffix);
 }
 
 const char *lp_ldap_idmap_suffix(TALLOC_CTX *ctx)
 {
-       if (Globals.szLdapIdmapSuffix[0])
-               return append_ldap_suffix(ctx, Globals.szLdapIdmapSuffix);
+       if (Globals._ldap_idmap_suffix[0])
+               return append_ldap_suffix(ctx, Globals._ldap_idmap_suffix);
 
        return lp_string(ctx, Globals.ldap_suffix);
 }
@@ -2570,118 +2494,26 @@ void *lp_parm_ptr(struct loadparm_service *service, struct parm_struct *parm)
 
 bool lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue)
 {
-       int parmnum, i;
-       void *parm_ptr = NULL;  /* where we are going to store the result */
-       struct parmlist_entry **opt_list;
-       TALLOC_CTX *mem_ctx;
        TALLOC_CTX *frame = talloc_stackframe();
+       struct loadparm_context *lp_ctx;
        bool ok;
 
-       parmnum = lpcfg_map_parameter(pszParmName);
-
-       if (parmnum < 0) {
-               if (strchr(pszParmName, ':') == NULL) {
-                       DEBUG(0, ("Ignoring unknown parameter \"%s\"\n",
-                                 pszParmName));
-                       TALLOC_FREE(frame);
-                       return true;
-               }
-
-               /*
-                * We've got a parametric option
-                */
-
-               if (snum < 0) {
-                       opt_list = &Globals.param_opt;
-                       set_param_opt(NULL, opt_list, pszParmName, pszParmValue, 0);
-               } else {
-                       opt_list = &ServicePtrs[snum]->param_opt;
-                       set_param_opt(ServicePtrs[snum], opt_list, pszParmName, pszParmValue, 0);
-               }
-
-               TALLOC_FREE(frame);
-               return true;
-       }
-
-       /* if it's already been set by the command line, then we don't
-          override here */
-       if (flags_list[parmnum] & FLAG_CMDLINE) {
+       lp_ctx = setup_lp_context(frame);
+       if (lp_ctx == NULL) {
                TALLOC_FREE(frame);
-               return true;
-       }
-
-       if (parm_table[parmnum].flags & FLAG_DEPRECATED) {
-               DEBUG(1, ("WARNING: The \"%s\" option is deprecated\n",
-                         pszParmName));
+               return false;
        }
 
-       /* we might point at a service, the default service or a global */
        if (snum < 0) {
-               parm_ptr = lp_parm_ptr(NULL, &parm_table[parmnum]);
-               mem_ctx = Globals.ctx;
+               ok = lpcfg_do_global_parameter(lp_ctx, pszParmName, pszParmValue);
        } else {
-               if (parm_table[parmnum].p_class == P_GLOBAL) {
-                       DEBUG(0,
-                             ("Global parameter %s found in service section!\n",
-                              pszParmName));
-                       TALLOC_FREE(frame);
-                       return true;
-               }
-               parm_ptr = lp_parm_ptr(ServicePtrs[snum], &parm_table[parmnum]);
-
-               if (!ServicePtrs[snum]->copymap)
-                       init_copymap(ServicePtrs[snum]);
-
-               /* this handles the aliases - set the copymap for other entries with
-                  the same data pointer */
-               for (i = 0; parm_table[i].label; i++) {
-                       if ((parm_table[i].offset == parm_table[parmnum].offset)
-                           && (parm_table[i].p_class == parm_table[parmnum].p_class)) {
-                               bitmap_clear(ServicePtrs[snum]->copymap, i);
-                       }
-               }
-
-               mem_ctx = ServicePtrs[snum];
-       }
-
-       /* if it is a special case then go ahead */
-       if (parm_table[parmnum].special) {
-               struct loadparm_context *lp_ctx = loadparm_init_s3(frame,
-                                                                  loadparm_s3_helpers());
-               lp_ctx->sDefault = &sDefault;
-               lp_ctx->services = ServicePtrs;
-               lp_ctx->bInGlobalSection = bInGlobalSection;
-               lp_ctx->flags = flags_list;
-               ok = parm_table[parmnum].special(lp_ctx, snum, pszParmValue,
-                                                 (char **)parm_ptr);
-               TALLOC_FREE(frame);
-
-               if (!ok) {
-                       return false;
-               }
-               goto mark_non_default;
+               ok = lpcfg_do_service_parameter(lp_ctx, ServicePtrs[snum],
+                                               pszParmName, pszParmValue);
        }
 
        TALLOC_FREE(frame);
 
-       ok = set_variable_helper(mem_ctx, parmnum, parm_ptr, pszParmName, pszParmValue);
-
-       if (!ok) {
-               return false;
-       }
-
-mark_non_default:
-       if (snum < 0 && (flags_list[parmnum] & FLAG_DEFAULT)) {
-               flags_list[parmnum] &= ~FLAG_DEFAULT;
-               /* we have to also unset FLAG_DEFAULT on aliases */
-               for (i=parmnum-1;i>=0 && parm_table[i].offset == parm_table[parmnum].offset;i--) {
-                       flags_list[i] &= ~FLAG_DEFAULT;
-               }
-               for (i=parmnum+1;i<num_parameters() && parm_table[i].offset == parm_table[parmnum].offset;i++) {
-                       flags_list[i] &= ~FLAG_DEFAULT;
-               }
-       }
-       return true;
+       return ok;
 }
 
 /***************************************************************************
@@ -2733,9 +2565,9 @@ bool lp_set_cmdline(const char *pszParmName, const char *pszParmValue)
        TALLOC_CTX *frame = talloc_stackframe();
        struct loadparm_context *lp_ctx;
 
-       lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
+       lp_ctx = setup_lp_context(frame);
        if (lp_ctx == NULL) {
-               DEBUG(0, ("loadparm_init_s3 failed\n"));
+               TALLOC_FREE(frame);
                return false;
        }
 
@@ -2757,8 +2589,12 @@ static bool do_parameter(const char *pszParmName, const char *pszParmValue,
 
        DEBUGADD(4, ("doing parameter %s = %s\n", pszParmName, pszParmValue));
 
-       return (lp_do_parameter(bInGlobalSection ? -2 : iServiceIndex,
-                               pszParmName, pszParmValue));
+       if (bInGlobalSection) {
+               return lpcfg_do_global_parameter(userdata, pszParmName, pszParmValue);
+       } else {
+               return lpcfg_do_service_parameter(userdata, ServicePtrs[iServiceIndex],
+                                                 pszParmName, pszParmValue);
+       }
 }
 
 /***************************************************************************
@@ -2806,6 +2642,7 @@ static void init_locals(void)
 
 bool lp_do_section(const char *pszSectionName, void *userdata)
 {
+       struct loadparm_context *lp_ctx = (struct loadparm_context *)userdata;
        bool bRetval;
        bool isglobal = ((strwicmp(pszSectionName, GLOBAL_NAME) == 0) ||
                         (strwicmp(pszSectionName, GLOBAL_NAME2) == 0));
@@ -2817,6 +2654,9 @@ bool lp_do_section(const char *pszSectionName, void *userdata)
 
        /* if we've just struck a global section, note the fact. */
        bInGlobalSection = isglobal;
+       if (lp_ctx != NULL) {
+               lp_ctx->bInGlobalSection = isglobal;
+       }
 
        /* check for multiple global sections */
        if (bInGlobalSection) {
@@ -2831,7 +2671,7 @@ bool lp_do_section(const char *pszSectionName, void *userdata)
        bRetval = true;
 
        if (iServiceIndex >= 0)
-               bRetval = service_ok(iServiceIndex);
+               bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
 
        /* if all is still well, move to the next record in the services array */
        if (bRetval) {
@@ -2852,83 +2692,6 @@ bool lp_do_section(const char *pszSectionName, void *userdata)
        return bRetval;
 }
 
-
-/***************************************************************************
- Determine if a partcular base parameter is currentl set to the default value.
-***************************************************************************/
-
-static bool is_default(int i)
-{
-       switch (parm_table[i].type) {
-               case P_LIST:
-               case P_CMDLIST:
-                       return str_list_equal((const char * const *)parm_table[i].def.lvalue,
-                                             *(const char ***)lp_parm_ptr(NULL, 
-                                                                          &parm_table[i]));
-               case P_STRING:
-               case P_USTRING:
-                       return strequal(parm_table[i].def.svalue,
-                                       *(char **)lp_parm_ptr(NULL, 
-                                                             &parm_table[i]));
-               case P_BOOL:
-               case P_BOOLREV:
-                       return parm_table[i].def.bvalue ==
-                               *(bool *)lp_parm_ptr(NULL, 
-                                                    &parm_table[i]);
-               case P_CHAR:
-                       return parm_table[i].def.cvalue ==
-                               *(char *)lp_parm_ptr(NULL, 
-                                                    &parm_table[i]);
-               case P_INTEGER:
-               case P_OCTAL:
-               case P_ENUM:
-               case P_BYTES:
-                       return parm_table[i].def.ivalue ==
-                               *(int *)lp_parm_ptr(NULL, 
-                                                   &parm_table[i]);
-               case P_SEP:
-                       break;
-       }
-       return false;
-}
-
-/***************************************************************************
-Display the contents of the global structure.
-***************************************************************************/
-
-static void dump_globals(FILE *f, bool show_defaults)
-{
-       int i;
-       struct parmlist_entry *data;
-
-       fprintf(f, "[global]\n");
-
-       for (i = 0; parm_table[i].label; i++)
-               if (parm_table[i].p_class == P_GLOBAL &&
-                   !(parm_table[i].flags & FLAG_META) &&
-                   (i == 0 || (parm_table[i].offset != parm_table[i - 1].offset))) {
-                       if (show_defaults && is_default(i))
-                               continue;
-                       fprintf(f, "\t%s = ", parm_table[i].label);
-                       lpcfg_print_parameter(&parm_table[i], lp_parm_ptr(NULL,
-                                                                         &parm_table[i]),
-                                       f);
-                       fprintf(f, "\n");
-       }
-       if (Globals.param_opt != NULL) {
-               data = Globals.param_opt;
-               while(data) {
-                       if (!show_defaults && (data->priority & FLAG_DEFAULT)) {
-                               data = data->next;
-                               continue;
-                       }
-                       fprintf(f, "\t%s = %s\n", data->key, data->value);
-                       data = data->next;
-               }
-        }
-
-}
-
 /***************************************************************************
  Display the contents of a parameter of a single services record.
 ***************************************************************************/
@@ -2936,10 +2699,9 @@ static void dump_globals(FILE *f, bool show_defaults)
 bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
 {
        bool result = false;
-
        struct loadparm_context *lp_ctx;
 
-       lp_ctx = loadparm_init_s3(talloc_tos(), loadparm_s3_helpers());
+       lp_ctx = setup_lp_context(talloc_tos());
        if (lp_ctx == NULL) {
                return false;
        }
@@ -2953,22 +2715,6 @@ bool dump_a_parameter(int snum, char *parm_name, FILE * f, bool isGlobal)
        return result;
 }
 
-/***************************************************************************
- Return info about the requested parameter (given as a string).
- Return NULL when the string is not a valid parameter name.
-***************************************************************************/
-
-struct parm_struct *lp_get_parameter(const char *param_name)
-{
-       int num = lpcfg_map_parameter(param_name);
-
-       if (num < 0) {
-               return NULL;
-       }
-
-       return &parm_table[num];
-}
-
 #if 0
 /***************************************************************************
  Display the contents of a single copy structure.
@@ -2997,7 +2743,7 @@ static void dump_copy_map(bool *pcopymap)
 
 bool lp_snum_ok(int iService)
 {
-       return (LP_SNUM_OK(iService) && ServicePtrs[iService]->bAvailable);
+       return (LP_SNUM_OK(iService) && ServicePtrs[iService]->available);
 }
 
 /***************************************************************************
@@ -3052,7 +2798,8 @@ void lp_add_one_printer(const char *name, const char *comment,
        if (lp_servicenumber(name) < 0) {
                lp_add_printer(name, printers);
                if ((i = lp_servicenumber(name)) >= 0) {
-                       string_set(ServicePtrs[i], &ServicePtrs[i]->comment, comment);
+                       lpcfg_string_set(ServicePtrs[i],
+                                        &ServicePtrs[i]->comment, comment);
                        ServicePtrs[i]->autoloaded = true;
                }
        }
@@ -3136,9 +2883,13 @@ static void lp_save_defaults(void)
                                break;
                        case P_STRING:
                        case P_USTRING:
-                               parm_table[i].def.svalue = talloc_strdup(Globals.ctx, *(char **)lp_parm_ptr(NULL, &parm_table[i]));
+                               lpcfg_string_set(
+                                       Globals.ctx,
+                                       &parm_table[i].def.svalue,
+                                       *(char **)lp_parm_ptr(
+                                               NULL, &parm_table[i]));
                                if (parm_table[i].def.svalue == NULL) {
-                                       smb_panic("talloc_strdup failed");
+                                       smb_panic("lpcfg_string_set() failed");
                                }
                                break;
                        case P_BOOL:
@@ -3157,8 +2908,6 @@ static void lp_save_defaults(void)
                                parm_table[i].def.ivalue =
                                        *(int *)lp_parm_ptr(NULL, &parm_table[i]);
                                break;
-                       case P_SEP:
-                               break;
                }
        }
 
@@ -3616,8 +3365,10 @@ 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_ex_mtime;
-       string_set(ServicePtrs[iService], &ServicePtrs[iService]->path, sharepath);
-       string_set(ServicePtrs[iService], &ServicePtrs[iService]->comment, comment);
+       lpcfg_string_set(ServicePtrs[iService], &ServicePtrs[iService]->path,
+                        sharepath);
+       lpcfg_string_set(ServicePtrs[iService],
+                        &ServicePtrs[iService]->comment, comment);
 
        ret = iService;
 
@@ -3944,6 +3695,22 @@ static bool lp_is_in_client(void)
     return in_client;
 }
 
+static void lp_enforce_ad_dc_settings(void)
+{
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "passdb backend", "samba_dsdb");
+       lp_do_parameter(GLOBAL_SECTION_SNUM,
+                       "winbindd:use external pipes", "true");
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:default", "external");
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:svcctl", "embedded");
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:srvsvc", "embedded");
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:eventlog", "embedded");
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:ntsvcs", "embedded");
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:winreg", "embedded");
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:spoolss", "embedded");
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_daemon:spoolssd", "embedded");
+       lp_do_parameter(GLOBAL_SECTION_SNUM, "rpc_server:tcpip", "no");
+}
+
 /***************************************************************************
  Load the services array from the services file. Return true on success,
  false on failure.
@@ -3953,13 +3720,14 @@ static bool lp_load_ex(const char *pszFname,
                       bool global_only,
                       bool save_defaults,
                       bool add_ipc,
-                      bool initialize_globals,
+                      bool reinit_globals,
                       bool allow_include_registry,
                       bool load_all_shares)
 {
        char *n2 = NULL;
        bool bRetval;
        TALLOC_CTX *frame = talloc_stackframe();
+       struct loadparm_context *lp_ctx;
 
        bRetval = false;
 
@@ -3969,7 +3737,9 @@ static bool lp_load_ex(const char *pszFname,
        bGlobalOnly = global_only;
        bAllowIncludeRegistry = allow_include_registry;
 
-       init_globals(initialize_globals);
+       lp_ctx = setup_lp_context(talloc_tos());
+
+       init_globals(lp_ctx, reinit_globals);
 
        free_file_list();
 
@@ -3978,12 +3748,12 @@ static bool lp_load_ex(const char *pszFname,
                lp_save_defaults();
        }
 
-       if (!initialize_globals) {
+       if (!reinit_globals) {
                free_param_opts(&Globals.param_opt);
                apply_lp_set_cmdline();
        }
 
-       lp_do_parameter(-1, "idmap config * : backend", Globals.szIdmapBackend);
+       lp_do_parameter(-1, "idmap config * : backend", Globals.idmap_backend);
 
        /* We get sections first, so have to start 'behind' to make up */
        iServiceIndex = -1;
@@ -3998,14 +3768,14 @@ static bool lp_load_ex(const char *pszFname,
 
                add_to_file_list(NULL, &file_lists, pszFname, n2);
 
-               bRetval = pm_process(n2, lp_do_section, do_parameter, NULL);
+               bRetval = pm_process(n2, lp_do_section, do_parameter, lp_ctx);
                TALLOC_FREE(n2);
 
                /* finish up the last section */
                DEBUG(4, ("pm_process() returned %s\n", BOOLSTR(bRetval)));
                if (bRetval) {
                        if (iServiceIndex >= 0) {
-                               bRetval = service_ok(iServiceIndex);
+                               bRetval = lpcfg_service_ok(ServicePtrs[iServiceIndex]);
                        }
                }
 
@@ -4018,14 +3788,18 @@ static bool lp_load_ex(const char *pszFname,
                         * for config_backend. Otherwise, init_globals would
                         *  send us into an endless loop here.
                         */
+
                        config_backend = CONFIG_BACKEND_REGISTRY;
                        /* start over */
                        DEBUG(1, ("lp_load_ex: changing to config backend "
                                  "registry\n"));
-                       init_globals(true);
+                       init_globals(lp_ctx, true);
+
+                       TALLOC_FREE(lp_ctx);
+
                        lp_kill_all_services();
                        ok = lp_load_ex(pszFname, global_only, save_defaults,
-                                       add_ipc, initialize_globals,
+                                       add_ipc, reinit_globals,
                                        allow_include_registry,
                                        load_all_shares);
                        TALLOC_FREE(frame);
@@ -4084,23 +3858,11 @@ static bool lp_load_ex(const char *pszFname,
        /*
         * We run this check once the whole smb.conf is parsed, to
         * force some settings for the standard way a AD DC is
-        * operated.  We may changed these as our code evolves, which
+        * operated.  We may change these as our code evolves, which
         * is why we force these settings.
         */
        if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
-               lp_do_parameter(-1, "passdb backend", "samba_dsdb");
-
-               lp_do_parameter(-1, "winbindd:use external pipes", "true");
-
-               lp_do_parameter(-1, "rpc_server:default", "external");
-               lp_do_parameter(-1, "rpc_server:svcctl", "embedded");
-               lp_do_parameter(-1, "rpc_server:srvsvc", "embedded");
-               lp_do_parameter(-1, "rpc_server:eventlog", "embedded");
-               lp_do_parameter(-1, "rpc_server:ntsvcs", "embedded");
-               lp_do_parameter(-1, "rpc_server:winreg", "embedded");
-               lp_do_parameter(-1, "rpc_server:spoolss", "embedded");
-               lp_do_parameter(-1, "rpc_daemon:spoolssd", "embedded");
-               lp_do_parameter(-1, "rpc_server:tcpip", "no");
+               lp_enforce_ad_dc_settings();
        }
 
        bAllowIncludeRegistry = true;
@@ -4109,17 +3871,17 @@ static bool lp_load_ex(const char *pszFname,
        return (bRetval);
 }
 
-bool lp_load(const char *pszFname,
-            bool global_only,
-            bool save_defaults,
-            bool add_ipc,
-            bool initialize_globals)
+static bool lp_load(const char *pszFname,
+                   bool global_only,
+                   bool save_defaults,
+                   bool add_ipc,
+                   bool reinit_globals)
 {
        return lp_load_ex(pszFname,
                          global_only,
                          save_defaults,
                          add_ipc,
-                         initialize_globals,
+                         reinit_globals,
                          true,   /* allow_include_registry */
                          false); /* load_all_shares*/
 }
@@ -4128,9 +3890,9 @@ bool lp_load_initial_only(const char *pszFname)
 {
        return lp_load_ex(pszFname,
                          true,   /* global only */
-                         false,  /* save_defaults */
+                         true,   /* save_defaults */
                          false,  /* add_ipc */
-                         true,   /* initialize_globals */
+                         true,   /* reinit_globals */
                          false,  /* allow_include_registry */
                          false); /* load_all_shares*/
 }
@@ -4140,13 +3902,25 @@ bool lp_load_initial_only(const char *pszFname)
  */
 bool lp_load_global(const char *file_name)
 {
-       return lp_load_ex(file_name,
-                         true,   /* global_only */
-                         false,  /* save_defaults */
-                         false,  /* add_ipc */
-                         true,   /* initialize_globals */
-                         true,   /* allow_include_registry */
-                         false); /* load_all_shares*/
+       return lp_load(file_name,
+                      true,   /* global_only */
+                      false,  /* save_defaults */
+                      false,  /* add_ipc */
+                      true);  /* reinit_globals */
+}
+
+/**
+ * The typical lp_load wrapper with shares, loads global and
+ * shares, including IPC, but does not force immediate
+ * loading of all shares from registry.
+ */
+bool lp_load_with_shares(const char *file_name)
+{
+       return lp_load(file_name,
+                      false,  /* global_only */
+                      false,  /* save_defaults */
+                      true,   /* add_ipc */
+                      true);  /* reinit_globals */
 }
 
 /**
@@ -4166,15 +3940,28 @@ bool lp_load_client(const char *file_name)
  */
 bool lp_load_global_no_reinit(const char *file_name)
 {
-       return lp_load_ex(file_name,
-                         true,   /* global_only */
-                         false,  /* save_defaults */
-                         false,  /* add_ipc */
-                         false,  /* initialize_globals */
-                         true,   /* allow_include_registry */
-                         false); /* load_all_shares*/
+       return lp_load(file_name,
+                      true,   /* global_only */
+                      false,  /* save_defaults */
+                      false,  /* add_ipc */
+                      false); /* reinit_globals */
+}
+
+/**
+ * lp_load wrapper, loading globals and shares,
+ * intended for subsequent calls, i.e. not reinitializing
+ * the globals to default values.
+ */
+bool lp_load_no_reinit(const char *file_name)
+{
+       return lp_load(file_name,
+                      false,  /* global_only */
+                      false,  /* save_defaults */
+                      false,  /* add_ipc */
+                      false); /* reinit_globals */
 }
 
+
 /**
  * lp_load wrapper, especially for clients, no reinitialization
  */
@@ -4185,17 +3972,13 @@ bool lp_load_client_no_reinit(const char *file_name)
        return lp_load_global_no_reinit(file_name);
 }
 
-bool lp_load_with_registry_shares(const char *pszFname,
-                                 bool global_only,
-                                 bool save_defaults,
-                                 bool add_ipc,
-                                 bool initialize_globals)
+bool lp_load_with_registry_shares(const char *pszFname)
 {
        return lp_load_ex(pszFname,
-                         global_only,
-                         save_defaults,
-                         add_ipc,
-                         initialize_globals,
+                         false, /* global_only */
+                         true,  /* save_defaults */
+                         false, /* add_ipc */
+                         false, /* reinit_globals */
                          true,  /* allow_include_registry */
                          true); /* load_all_shares*/
 }
@@ -4216,11 +3999,17 @@ Display the contents of the services array in human-readable form.
 void lp_dump(FILE *f, bool show_defaults, int maxtoprint)
 {
        int iService;
+       struct loadparm_context *lp_ctx;
 
        if (show_defaults)
                defaults_saved = false;
 
-       dump_globals(f, defaults_saved);
+       lp_ctx = setup_lp_context(talloc_tos());
+       if (lp_ctx == NULL) {
+               return;
+       }
+
+       lpcfg_dump_globals(lp_ctx, f, !defaults_saved);
 
        lpcfg_dump_a_service(&sDefault, &sDefault, f, flags_list, show_defaults);
 
@@ -4263,7 +4052,7 @@ int lp_servicenumber(const char *pszServiceName)
        for (iService = iNumServices - 1; iService >= 0; iService--) {
                if (VALID(iService) && ServicePtrs[iService]->szService) {
                        /*
-                        * The substitution here is used to support %U is
+                        * The substitution here is used to support %U in
                         * service names
                         */
                        fstrcpy(serviceName, ServicePtrs[iService]->szService);
@@ -4399,10 +4188,12 @@ static bool lp_domain_master_true_or_auto(void)
 
 bool lp_preferred_master(void)
 {
-       if (Globals.iPreferredMaster == Auto)
+       int preferred_master = lp__preferred_master();
+
+       if (preferred_master == Auto)
                return (lp_local_master() && lp_domain_master());
 
-       return (bool)Globals.iPreferredMaster;
+       return (bool)preferred_master;
 }
 
 /*******************************************************************
@@ -4431,7 +4222,7 @@ const char *lp_printername(TALLOC_CTX *ctx, int snum)
 
 void lp_set_logfile(const char *name)
 {
-       string_set(Globals.ctx, &Globals.logfile, name);
+       lpcfg_string_set(Globals.ctx, &Globals.logfile, name);
        debug_set_logfile(name);
 }
 
@@ -4441,7 +4232,8 @@ void lp_set_logfile(const char *name)
 
 int lp_maxprintjobs(int snum)
 {
-       int maxjobs = LP_SNUM_OK(snum) ? ServicePtrs[snum]->iMaxPrintJobs : sDefault.iMaxPrintJobs;
+       int maxjobs = lp_max_print_jobs(snum);
+
        if (maxjobs <= 0 || maxjobs >= PRINT_MAX_JOBID)
                maxjobs = PRINT_MAX_JOBID - 1;
 
@@ -4450,9 +4242,11 @@ int lp_maxprintjobs(int snum)
 
 const char *lp_printcapname(void)
 {
-       if ((Globals.szPrintcapname != NULL) &&
-           (Globals.szPrintcapname[0] != '\0'))
-               return Globals.szPrintcapname;
+       const char *printcap_name = lp_printcap_name();
+
+       if ((printcap_name != NULL) &&
+           (printcap_name[0] != '\0'))
+               return printcap_name;
 
        if (sDefault.printing == PRINT_CUPS) {
                return "cups";
@@ -4464,7 +4258,7 @@ const char *lp_printcapname(void)
        return PRINTCAP_NAME;
 }
 
-static uint32 spoolss_state;
+static uint32_t spoolss_state;
 
 bool lp_disable_spoolss( void )
 {
@@ -4474,14 +4268,14 @@ bool lp_disable_spoolss( void )
        return spoolss_state == SVCCTL_STOPPED ? true : false;
 }
 
-void lp_set_spoolss_state( uint32 state )
+void lp_set_spoolss_state( uint32_t state )
 {
        SMB_ASSERT( (state == SVCCTL_STOPPED) || (state == SVCCTL_RUNNING) );
 
        spoolss_state = state;
 }
 
-uint32 lp_get_spoolss_state( void )
+uint32_t lp_get_spoolss_state( void )
 {
        return lp_disable_spoolss() ? SVCCTL_STOPPED : SVCCTL_RUNNING;
 }
@@ -4518,20 +4312,9 @@ void set_use_sendfile(int snum, bool val)
                sDefault._use_sendfile = val;
 }
 
-/*******************************************************************
- Turn off storing DOS attributes if this share doesn't support it.
-********************************************************************/
-
-void set_store_dos_attributes(int snum, bool val)
-{
-       if (!LP_SNUM_OK(snum))
-               return;
-       ServicePtrs[(snum)]->store_dos_attributes = val;
-}
-
 void lp_set_mangling_method(const char *new_method)
 {
-       string_set(Globals.ctx, &Globals.mangling_method, new_method);
+       lpcfg_string_set(Globals.ctx, &Globals.mangling_method, new_method);
 }
 
 /*******************************************************************
@@ -4567,7 +4350,8 @@ enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
        if (posix_default_lock_was_set) {
                return posix_cifsx_locktype;
        } else {
-               return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
+               return (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
+                       POSIX_LOCK : WINDOWS_LOCK;
        }
 }
 
@@ -4582,10 +4366,12 @@ void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
 
 int lp_min_receive_file_size(void)
 {
-       if (Globals.iminreceivefile < 0) {
+       int min_receivefile_size = lp_min_receivefile_size();
+
+       if (min_receivefile_size < 0) {
                return 0;
        }
-       return Globals.iminreceivefile;
+       return min_receivefile_size;
 }
 
 /*******************************************************************
@@ -4594,19 +4380,13 @@ int lp_min_receive_file_size(void)
  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_allow_insecure_wide_links()) {
                return;
        }
 
-       if (lp_unix_extensions() && lp_widelinks_internal(snum)) {
+       if (lp_unix_extensions() && lp_wide_links(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",
@@ -4627,7 +4407,7 @@ bool lp_widelinks(int snum)
                }
        }
 
-       return lp_widelinks_internal(snum);
+       return lp_wide_links(snum);
 }
 
 int lp_server_role(void)
@@ -4644,6 +4424,24 @@ int lp_security(void)
                                lp__security());
 }
 
+int lp_client_max_protocol(void)
+{
+       int client_max_protocol = lp__client_max_protocol();
+       if (client_max_protocol == PROTOCOL_DEFAULT) {
+               return PROTOCOL_NT1;
+       }
+       return client_max_protocol;
+}
+
+int lp_winbindd_max_protocol(void)
+{
+       int client_max_protocol = lp__client_max_protocol();
+       if (client_max_protocol == PROTOCOL_DEFAULT) {
+               return PROTOCOL_LATEST;
+       }
+       return client_max_protocol;
+}
+
 struct loadparm_global * get_globals(void)
 {
        return &Globals;