summaryrefslogtreecommitdiffstats
path: root/source4/param
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 17:47:29 +0000
commit4f5791ebd03eaec1c7da0865a383175b05102712 (patch)
tree8ce7b00f7a76baa386372422adebbe64510812d4 /source4/param
parentInitial commit. (diff)
downloadsamba-4f5791ebd03eaec1c7da0865a383175b05102712.tar.xz
samba-4f5791ebd03eaec1c7da0865a383175b05102712.zip
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--source4/param/loadparm.c77
-rw-r--r--source4/param/provision.c559
-rw-r--r--source4/param/provision.h72
-rw-r--r--source4/param/pyparam.c746
-rw-r--r--source4/param/pyparam.h28
-rw-r--r--source4/param/pyparam_util.c81
-rw-r--r--source4/param/secrets.c152
-rw-r--r--source4/param/secrets.h51
-rw-r--r--source4/param/share.c156
-rw-r--r--source4/param/share.h149
-rw-r--r--source4/param/share_classic.c385
-rw-r--r--source4/param/tests/loadparm.c271
-rw-r--r--source4/param/tests/share.c207
-rw-r--r--source4/param/wscript_build62
14 files changed, 2996 insertions, 0 deletions
diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c
new file mode 100644
index 0000000..7d3891d
--- /dev/null
+++ b/source4/param/loadparm.c
@@ -0,0 +1,77 @@
+/*
+ Unix SMB/CIFS implementation.
+ Parameter loading functions
+ Copyright (C) Karl Auer 1993-1998
+
+ Largely re-written by Andrew Tridgell, September 1994
+
+ Copyright (C) Simo Sorce 2001
+ Copyright (C) Alexander Bokovoy 2002
+ Copyright (C) Stefan (metze) Metzmacher 2002
+ Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003.
+ Copyright (C) James Myers 2003 <myersjj@samba.org>
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/param/param.h"
+#include "libcli/raw/libcliraw.h"
+#include "librpc/ndr/libndr.h"
+#include "libcli/smb/smb2_negotiate_context.h"
+
+void lpcfg_smbcli_options(struct loadparm_context *lp_ctx,
+ struct smbcli_options *options)
+{
+ struct GUID client_guid;
+ const char *str = NULL;
+
+ str = lpcfg_parm_string(lp_ctx, NULL, "libsmb", "client_guid");
+ if (str != NULL) {
+ GUID_from_string(str, &client_guid);
+ } else {
+ client_guid = GUID_random();
+ }
+ *options = (struct smbcli_options) {
+ .max_xmit = lpcfg_max_xmit(lp_ctx),
+ .max_mux = lpcfg_max_mux(lp_ctx),
+ .use_spnego = lpcfg_nt_status_support(lp_ctx) && lpcfg_client_use_spnego(lp_ctx),
+ .signing = lpcfg_client_signing(lp_ctx),
+ .request_timeout = SMB_REQUEST_TIMEOUT,
+ .ntstatus_support = lpcfg_nt_status_support(lp_ctx),
+ .min_protocol = lpcfg_client_min_protocol(lp_ctx),
+ .max_protocol = lpcfg__client_max_protocol(lp_ctx),
+ .unicode = lpcfg_unicode(lp_ctx),
+ .use_oplocks = true,
+ .use_level2_oplocks = true,
+ .smb2_capabilities = SMB2_CAP_ALL,
+ .client_guid = client_guid,
+ .max_credits = WINDOWS_CLIENT_PURE_SMB2_NEGPROT_INITIAL_CREDIT_ASK,
+ .smb3_capabilities = smb311_capabilities_parse("client",
+ lpcfg_client_smb3_signing_algorithms(lp_ctx),
+ lpcfg_client_smb3_encryption_algorithms(lp_ctx)),
+ };
+}
+
+void lpcfg_smbcli_session_options(struct loadparm_context *lp_ctx,
+ struct smbcli_session_options *options)
+{
+ *options = (struct smbcli_session_options) {
+ .lanman_auth = lpcfg_client_lanman_auth(lp_ctx),
+ .ntlmv2_auth = lpcfg_client_ntlmv2_auth(lp_ctx),
+ .plaintext_auth = lpcfg_client_plaintext_auth(lp_ctx),
+ };
+}
+
diff --git a/source4/param/provision.c b/source4/param/provision.c
new file mode 100644
index 0000000..e0b7c69
--- /dev/null
+++ b/source4/param/provision.c
@@ -0,0 +1,559 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008-2009
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include "python/py3compat.h"
+#include <ldb.h>
+#include <pyldb.h>
+#include "includes.h"
+#include "librpc/ndr/libndr.h"
+#include "param/provision.h"
+#include "param/secrets.h"
+#include <pytalloc.h>
+#include "python/modules.h"
+#include "param/pyparam.h"
+#include "dynconfig/dynconfig.h"
+
+static bool dict_insert(PyObject* dict,
+ const char* key,
+ PyObject* value)
+{
+ if (value == NULL) {
+ return false;
+ }
+ if (PyDict_SetItemString(dict, key, value) == -1) {
+ Py_XDECREF(value);
+ return false;
+ }
+ Py_XDECREF(value);
+ return true;
+}
+
+static PyObject *provision_module(void)
+{
+ PyObject *name = PyUnicode_FromString("samba.provision");
+ PyObject *mod = NULL;
+ if (name == NULL)
+ return NULL;
+ mod = PyImport_Import(name);
+ Py_CLEAR(name);
+ return mod;
+}
+
+static PyObject *schema_module(void)
+{
+ PyObject *name = PyUnicode_FromString("samba.schema");
+ PyObject *mod = NULL;
+ if (name == NULL)
+ return NULL;
+ mod = PyImport_Import(name);
+ Py_CLEAR(name);
+ return mod;
+}
+
+static PyObject *ldb_module(void)
+{
+ PyObject *name = PyUnicode_FromString("ldb");
+ PyObject *mod = NULL;
+ if (name == NULL)
+ return NULL;
+ mod = PyImport_Import(name);
+ Py_CLEAR(name);
+ return mod;
+}
+
+static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
+{
+ PyLdbObject *ret;
+ PyObject *ldb_mod = ldb_module();
+ PyTypeObject *ldb_ctx_type;
+ if (ldb_mod == NULL)
+ return NULL;
+
+ ldb_ctx_type = (PyTypeObject *)PyObject_GetAttrString(ldb_mod, "Ldb");
+
+ ret = (PyLdbObject *)ldb_ctx_type->tp_alloc(ldb_ctx_type, 0);
+ if (ret == NULL) {
+ PyErr_NoMemory();
+ Py_XDECREF(ldb_ctx_type);
+ return NULL;
+ }
+ ret->mem_ctx = talloc_new(NULL);
+ ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
+ Py_XDECREF(ldb_ctx_type);
+ return (PyObject *)ret;
+}
+
+NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx,
+ struct provision_settings *settings,
+ struct provision_result *result)
+{
+ const char *configfile;
+ PyObject *provision_mod = NULL, *provision_dict = NULL;
+ PyObject *provision_fn = NULL, *py_result = NULL;
+ PyObject *parameters = NULL, *py_lp_ctx = NULL, *py_domaindn = NULL;
+
+ struct ldb_context *samdb;
+ NTSTATUS status = NT_STATUS_OK;
+
+ DEBUG(0,("Provision for Become-DC test using python\n"));
+
+ Py_Initialize();
+ py_update_path(); /* Put the samba path at the start of sys.path */
+
+ provision_mod = provision_module();
+
+ if (provision_mod == NULL) {
+ PyErr_Print();
+ DEBUG(0, ("Unable to import provision Python module.\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ provision_dict = PyModule_GetDict(provision_mod);
+
+ if (provision_dict == NULL) {
+ DEBUG(0, ("Unable to get dictionary for provision module\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ provision_fn = PyDict_GetItemString(provision_dict, "provision_become_dc");
+ if (provision_fn == NULL) {
+ PyErr_Print();
+ DEBUG(0, ("Unable to get provision_become_dc function\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ DEBUG(0,("New Server in Site[%s]\n",
+ settings->site_name));
+
+ DEBUG(0,("DSA Instance [%s]\n"
+ "\tinvocationId[%s]\n",
+ settings->ntds_dn_str,
+ settings->invocation_id == NULL?"None":GUID_string(mem_ctx, settings->invocation_id)));
+
+ DEBUG(0,("Paths under targetdir[%s]\n",
+ settings->targetdir));
+ parameters = PyDict_New();
+
+ configfile = lpcfg_configfile(lp_ctx);
+ if (configfile != NULL) {
+ if (!dict_insert(parameters, "smbconf",
+ PyUnicode_FromString(configfile))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ }
+
+ if (!dict_insert(parameters,
+ "rootdn",
+ PyUnicode_FromString(settings->root_dn_str))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ if (settings->targetdir != NULL) {
+ if (!dict_insert(parameters,
+ "targetdir",
+ PyUnicode_FromString(settings->targetdir))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ }
+ if (!dict_insert(parameters,
+ "hostname",
+ PyUnicode_FromString(settings->netbios_name))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ if (!dict_insert(parameters,
+ "domain",
+ PyUnicode_FromString(settings->domain))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ if (!dict_insert(parameters,
+ "realm",
+ PyUnicode_FromString(settings->realm))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ if (settings->root_dn_str) {
+ if (!dict_insert(parameters,
+ "rootdn",
+ PyUnicode_FromString(settings->root_dn_str))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ }
+
+ if (settings->domain_dn_str) {
+ if (!dict_insert(parameters,
+ "domaindn",
+ PyUnicode_FromString(settings->domain_dn_str))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ }
+
+ if (settings->schema_dn_str) {
+ if (!dict_insert(parameters,
+ "schemadn",
+ PyUnicode_FromString(settings->schema_dn_str))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ }
+ if (settings->config_dn_str) {
+ if (!dict_insert(parameters,
+ "configdn",
+ PyUnicode_FromString(settings->config_dn_str))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ }
+ if (settings->server_dn_str) {
+ if (!dict_insert(parameters,
+ "serverdn",
+ PyUnicode_FromString(settings->server_dn_str))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ }
+ if (settings->site_name) {
+ if (!dict_insert(parameters,
+ "sitename",
+ PyUnicode_FromString(settings->site_name))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ }
+
+ if (!dict_insert(parameters,
+ "machinepass",
+ PyUnicode_FromString(settings->machine_password))){
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ if (!dict_insert(parameters,
+ "debuglevel",
+ PyLong_FromLong(DEBUGLEVEL))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ if (!dict_insert(parameters,
+ "use_ntvfs",
+ PyLong_FromLong(settings->use_ntvfs))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters);
+
+ if (py_result == NULL) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ py_domaindn = PyObject_GetAttrString(py_result, "domaindn");
+ result->domaindn = talloc_strdup(mem_ctx, PyUnicode_AsUTF8(py_domaindn));
+
+ /* FIXME paths */
+ py_lp_ctx = PyObject_GetAttrString(py_result, "lp");
+ if (py_lp_ctx == NULL) {
+ DEBUG(0, ("Missing 'lp' attribute"));
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ result->lp_ctx = lpcfg_from_py_object(mem_ctx, py_lp_ctx);
+
+ samdb = pyldb_Ldb_AsLdbContext(PyObject_GetAttrString(py_result, "samdb"));
+ if (samdb == NULL) {
+ DEBUG(0, ("Missing 'samdb' attribute"));
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ result->samdb = samdb;
+ status = NT_STATUS_OK;
+out:
+ Py_CLEAR(parameters);
+ Py_CLEAR(provision_mod);
+ Py_CLEAR(provision_fn);
+ Py_CLEAR(provision_dict);
+ Py_CLEAR(py_result);
+ Py_CLEAR(py_lp_ctx);
+ Py_CLEAR(py_domaindn);
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ return status;
+}
+
+static PyObject *py_dom_sid_FromSid(struct dom_sid *sid)
+{
+ PyObject *mod_security = NULL, *dom_sid_Type = NULL, *result = NULL;
+
+ mod_security = PyImport_ImportModule("samba.dcerpc.security");
+ if (mod_security == NULL) {
+ return NULL;
+ }
+
+ dom_sid_Type = PyObject_GetAttrString(mod_security, "dom_sid");
+ if (dom_sid_Type == NULL) {
+ Py_DECREF(mod_security);
+ return NULL;
+ }
+
+ result = pytalloc_reference((PyTypeObject *)dom_sid_Type, sid);
+ Py_DECREF(mod_security);
+ Py_DECREF(dom_sid_Type);
+ return result;
+}
+
+NTSTATUS provision_store_self_join(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx,
+ struct tevent_context *event_ctx,
+ struct provision_store_self_join_settings *settings,
+ const char **error_string)
+{
+ int ret;
+ PyObject *provision_mod = NULL, *provision_dict = NULL;
+ PyObject *provision_fn = NULL, *py_result = NULL;
+ PyObject *parameters = NULL;
+ struct ldb_context *ldb = NULL;
+ TALLOC_CTX *tmp_mem = talloc_new(mem_ctx);
+
+ NTSTATUS status = NT_STATUS_OK;
+ *error_string = NULL;
+
+ if (!tmp_mem) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ /* Create/Open the secrets database */
+ ldb = secrets_db_create(tmp_mem, lp_ctx);
+ if (!ldb) {
+ *error_string
+ = talloc_asprintf(mem_ctx,
+ "Could not open secrets database");
+ status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ goto out;
+ }
+
+ ret = ldb_transaction_start(ldb);
+
+ if (ret != LDB_SUCCESS) {
+ *error_string
+ = talloc_asprintf(mem_ctx,
+ "Could not start transaction on secrets database: %s", ldb_errstring(ldb));
+ status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ goto out;
+ }
+
+ Py_Initialize();
+ py_update_path(); /* Put the samba path at the start of sys.path */
+ provision_mod = provision_module();
+
+ if (provision_mod == NULL) {
+ *error_string
+ = talloc_asprintf(mem_ctx, "Unable to import provision Python module.");
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ provision_dict = PyModule_GetDict(provision_mod);
+
+ if (provision_dict == NULL) {
+ *error_string
+ = talloc_asprintf(mem_ctx, "Unable to get dictionary for provision module");
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ provision_fn = PyDict_GetItemString(provision_dict, "secretsdb_self_join");
+ if (provision_fn == NULL) {
+ *error_string
+ = talloc_asprintf(mem_ctx, "Unable to get provision_become_dc function");
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ parameters = PyDict_New();
+
+ if(!dict_insert(parameters,
+ "secretsdb",
+ PyLdb_FromLdbContext(ldb))){
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ if (!dict_insert(parameters,
+ "domain",
+ PyUnicode_FromString(settings->domain_name))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ if (settings->realm != NULL) {
+ if (!dict_insert(parameters,
+ "realm",
+ PyUnicode_FromString(settings->realm))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ }
+ if (!dict_insert(parameters,
+ "machinepass",
+ PyUnicode_FromString(settings->machine_password))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+ if (!dict_insert(parameters,
+ "netbiosname",
+ PyUnicode_FromString(settings->netbios_name))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+
+ if (!dict_insert(parameters,
+ "domainsid",
+ py_dom_sid_FromSid(settings->domain_sid))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ if (!dict_insert(parameters,
+ "secure_channel_type",
+ PyLong_FromLong(settings->secure_channel_type))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ if (!dict_insert(parameters,
+ "key_version_number",
+ PyLong_FromLong(settings->key_version_number))) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters);
+
+ if (py_result == NULL) {
+ ldb_transaction_cancel(ldb);
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
+
+ ret = ldb_transaction_commit(ldb);
+ if (ret != LDB_SUCCESS) {
+ *error_string
+ = talloc_asprintf(mem_ctx,
+ "Could not commit transaction on secrets database: %s", ldb_errstring(ldb));
+ status = NT_STATUS_INTERNAL_DB_ERROR;
+ goto out;
+ }
+
+ status = NT_STATUS_OK;
+out:
+ talloc_free(tmp_mem);
+ Py_CLEAR(parameters);
+ Py_CLEAR(provision_mod);
+ Py_CLEAR(provision_dict);
+ Py_CLEAR(py_result);
+ if (!NT_STATUS_IS_OK(status)) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ return status;
+}
+
+
+struct ldb_context *provision_get_schema(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ const char *schema_dn,
+ DATA_BLOB *override_prefixmap)
+{
+ PyObject *schema_mod, *schema_dict, *schema_fn, *py_result, *parameters;
+ PyObject *py_ldb = NULL;
+ struct ldb_context *ldb_result = NULL;
+ Py_Initialize();
+ py_update_path(); /* Put the samba path at the start of sys.path */
+
+ schema_mod = schema_module();
+
+ if (schema_mod == NULL) {
+ PyErr_Print();
+ DEBUG(0, ("Unable to import schema Python module.\n"));
+ return NULL;
+ }
+
+ schema_dict = PyModule_GetDict(schema_mod);
+
+ if (schema_dict == NULL) {
+ DEBUG(0, ("Unable to get dictionary for schema module\n"));
+ return NULL;
+ }
+
+ schema_fn = PyDict_GetItemString(schema_dict, "ldb_with_schema");
+ if (schema_fn == NULL) {
+ PyErr_Print();
+ DEBUG(0, ("Unable to get schema_get_ldb function\n"));
+ return NULL;
+ }
+
+ parameters = PyDict_New();
+
+ if (schema_dn) {
+ if (!dict_insert(parameters,
+ "schemadn",
+ PyUnicode_FromString(schema_dn))) {
+ return NULL;
+ }
+ }
+
+ if (override_prefixmap) {
+ if (!dict_insert(parameters,
+ "override_prefixmap",
+ PyBytes_FromStringAndSize(
+ (const char *)override_prefixmap->data,
+ override_prefixmap->length))) {
+ return NULL;
+ }
+ }
+
+ py_result = PyEval_CallObjectWithKeywords(schema_fn, NULL, parameters);
+
+ Py_DECREF(parameters);
+
+ if (py_result == NULL) {
+ PyErr_Print();
+ PyErr_Clear();
+ return NULL;
+ }
+
+ py_ldb = PyObject_GetAttrString(py_result, "ldb");
+ Py_DECREF(py_result);
+ ldb_result = pyldb_Ldb_AsLdbContext(py_ldb);
+ if (talloc_reference(mem_ctx, ldb_result) == NULL) {
+ ldb_result = NULL;
+ }
+ Py_DECREF(py_ldb);
+ return ldb_result;
+}
diff --git a/source4/param/provision.h b/source4/param/provision.h
new file mode 100644
index 0000000..2f6f582
--- /dev/null
+++ b/source4/param/provision.h
@@ -0,0 +1,72 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _PROVISION_H_
+#define _PROVISION_H_
+
+struct provision_settings {
+ const char *site_name;
+ const char *root_dn_str;
+ const char *domain_dn_str;
+ const char *config_dn_str;
+ const char *schema_dn_str;
+ const char *server_dn_str;
+ const struct GUID *invocation_id;
+ const char *netbios_name;
+ const char *host_ip;
+ const char *realm;
+ const char *domain;
+ const char *ntds_dn_str;
+ const char *machine_password;
+ const char *targetdir;
+ bool use_ntvfs;
+};
+
+/* FIXME: Rename this to hostconfig ? */
+struct provision_result {
+ const char *domaindn;
+ struct ldb_context *samdb;
+ struct loadparm_context *lp_ctx;
+};
+
+struct provision_store_self_join_settings {
+ const char *domain_name;
+ const char *realm;
+ const char *netbios_name;
+ enum netr_SchannelType secure_channel_type;
+ const char *machine_password;
+ int key_version_number;
+ struct dom_sid *domain_sid;
+};
+
+NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx,
+ struct provision_settings *settings,
+ struct provision_result *result);
+
+NTSTATUS provision_store_self_join(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx,
+ struct tevent_context *ev_ctx,
+ struct provision_store_self_join_settings *settings,
+ const char **error_string);
+
+struct ldb_context *provision_get_schema(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ const char *schema_dn,
+ DATA_BLOB *override_prefixmap);
+
+#endif /* _PROVISION_H_ */
diff --git a/source4/param/pyparam.c b/source4/param/pyparam.c
new file mode 100644
index 0000000..8f28083
--- /dev/null
+++ b/source4/param/pyparam.c
@@ -0,0 +1,746 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include "python/py3compat.h"
+#include "includes.h"
+#include "param/param.h"
+#include "param/loadparm.h"
+#include <pytalloc.h>
+#include "dynconfig/dynconfig.h"
+
+#define PyLoadparmContext_AsLoadparmContext(obj) pytalloc_get_type(obj, struct loadparm_context)
+#define PyLoadparmService_AsLoadparmService(obj) pytalloc_get_type(obj, struct loadparm_service)
+
+extern PyTypeObject PyLoadparmContext;
+extern PyTypeObject PyLoadparmService;
+
+static PyObject *PyLoadparmService_FromService(struct loadparm_service *service)
+{
+ return pytalloc_reference(&PyLoadparmService, service);
+}
+
+static PyObject *py_lp_ctx_get_helper(struct loadparm_context *lp_ctx, const char *service_name, const char *param_name)
+{
+ struct parm_struct *parm = NULL;
+ void *parm_ptr = NULL;
+ int i;
+
+ if (service_name != NULL && strwicmp(service_name, GLOBAL_NAME) &&
+ strwicmp(service_name, GLOBAL_NAME2)) {
+ struct loadparm_service *service;
+ /* its a share parameter */
+ service = lpcfg_service(lp_ctx, service_name);
+ if (service == NULL) {
+ return NULL;
+ }
+ if (strchr(param_name, ':')) {
+ /* its a parametric option on a share */
+ const char *type = talloc_strndup(lp_ctx, param_name,
+ strcspn(param_name, ":"));
+ const char *option = strchr(param_name, ':') + 1;
+ const char *value;
+ if (type == NULL || option == NULL) {
+ return NULL;
+ }
+ value = lpcfg_get_parametric(lp_ctx, service, type, option);
+ if (value == NULL) {
+ return NULL;
+ }
+ return PyUnicode_FromString(value);
+ }
+
+ parm = lpcfg_parm_struct(lp_ctx, param_name);
+ if (parm == NULL || parm->p_class == P_GLOBAL) {
+ return NULL;
+ }
+ parm_ptr = lpcfg_parm_ptr(lp_ctx, service, parm);
+ } else if (strchr(param_name, ':')) {
+ /* its a global parametric option */
+ const char *type = talloc_strndup(lp_ctx,
+ param_name, strcspn(param_name, ":"));
+ const char *option = strchr(param_name, ':') + 1;
+ const char *value;
+ if (type == NULL || option == NULL) {
+ return NULL;
+ }
+ value = lpcfg_get_parametric(lp_ctx, NULL, type, option);
+ if (value == NULL)
+ return NULL;
+ return PyUnicode_FromString(value);
+ } else {
+ /* its a global parameter */
+ parm = lpcfg_parm_struct(lp_ctx, param_name);
+ if (parm == NULL) {
+ return NULL;
+ }
+ parm_ptr = lpcfg_parm_ptr(lp_ctx, NULL, parm);
+ }
+
+ if (parm == NULL || parm_ptr == NULL) {
+ return NULL;
+ }
+
+ /* construct and return the right type of python object */
+ switch (parm->type) {
+ case P_CHAR:
+ return PyUnicode_FromFormat("%c", *(char *)parm_ptr);
+ case P_STRING:
+ case P_USTRING:
+ return PyUnicode_FromString(*(char **)parm_ptr);
+ case P_BOOL:
+ return PyBool_FromLong(*(bool *)parm_ptr);
+ case P_BOOLREV:
+ return PyBool_FromLong(!(*(bool *)parm_ptr));
+ case P_INTEGER:
+ case P_OCTAL:
+ case P_BYTES:
+ return PyLong_FromLong(*(int *)parm_ptr);
+ case P_ENUM:
+ for (i=0; parm->enum_list[i].name; i++) {
+ if (*(int *)parm_ptr == parm->enum_list[i].value) {
+ return PyUnicode_FromString(parm->enum_list[i].name);
+ }
+ }
+ return NULL;
+ case P_CMDLIST:
+ case P_LIST:
+ {
+ int j;
+ const char **strlist = *(const char ***)parm_ptr;
+ PyObject *pylist;
+
+ if(strlist == NULL) {
+ return PyList_New(0);
+ }
+
+ pylist = PyList_New(str_list_length(strlist));
+ for (j = 0; strlist[j]; j++)
+ PyList_SetItem(pylist, j,
+ PyUnicode_FromString(strlist[j]));
+ return pylist;
+ }
+ }
+ return NULL;
+
+}
+
+static PyObject *py_lp_ctx_load(PyObject *self, PyObject *args)
+{
+ char *filename;
+ bool ret;
+ if (!PyArg_ParseTuple(args, "s", &filename))
+ return NULL;
+
+ ret = lpcfg_load(PyLoadparmContext_AsLoadparmContext(self), filename);
+
+ if (!ret) {
+ PyErr_Format(PyExc_RuntimeError, "Unable to load file %s", filename);
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_lp_ctx_load_default(PyObject *self, PyObject *unused)
+{
+ bool ret;
+ ret = lpcfg_load_default(PyLoadparmContext_AsLoadparmContext(self));
+
+ if (!ret) {
+ PyErr_SetString(PyExc_RuntimeError, "Unable to load default file");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_lp_ctx_get(PyObject *self, PyObject *args)
+{
+ char *param_name;
+ char *section_name = NULL;
+ PyObject *ret;
+ if (!PyArg_ParseTuple(args, "s|z", &param_name, &section_name))
+ return NULL;
+
+ ret = py_lp_ctx_get_helper(PyLoadparmContext_AsLoadparmContext(self), section_name, param_name);
+ if (ret == NULL)
+ Py_RETURN_NONE;
+ return ret;
+}
+
+static PyObject *py_lp_ctx_is_myname(PyObject *self, PyObject *args)
+{
+ char *name;
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+
+ return PyBool_FromLong(lpcfg_is_myname(PyLoadparmContext_AsLoadparmContext(self), name));
+}
+
+static PyObject *py_lp_ctx_is_mydomain(PyObject *self, PyObject *args)
+{
+ char *name;
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+
+ return PyBool_FromLong(lpcfg_is_mydomain(PyLoadparmContext_AsLoadparmContext(self), name));
+}
+
+static PyObject *py_lp_ctx_set(PyObject *self, PyObject *args)
+{
+ char *name, *value;
+ bool ret;
+ if (!PyArg_ParseTuple(args, "ss", &name, &value))
+ return NULL;
+
+ ret = lpcfg_set_cmdline(PyLoadparmContext_AsLoadparmContext(self), name, value);
+ if (!ret) {
+ PyErr_SetString(PyExc_RuntimeError, "Unable to set parameter");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_lp_ctx_private_path(PyObject *self, PyObject *args)
+{
+ char *name, *path;
+ PyObject *ret;
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+
+ path = lpcfg_private_path(NULL, PyLoadparmContext_AsLoadparmContext(self), name);
+ ret = PyUnicode_FromString(path);
+ talloc_free(path);
+
+ return ret;
+}
+
+static PyObject *py_lp_ctx_services(PyObject *self, PyObject *unused)
+{
+ struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+ PyObject *ret;
+ int i;
+ ret = PyList_New(lpcfg_numservices(lp_ctx));
+ for (i = 0; i < lpcfg_numservices(lp_ctx); i++) {
+ struct loadparm_service *service = lpcfg_servicebynum(lp_ctx, i);
+ if (service != NULL) {
+ PyList_SetItem(ret, i, PyUnicode_FromString(lpcfg_servicename(service)));
+ }
+ }
+ return ret;
+}
+
+static PyObject *py_lp_ctx_server_role(PyObject *self, PyObject *unused)
+{
+ struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+ uint32_t role;
+ const char *role_str;
+
+ role = lpcfg_server_role(lp_ctx);
+ role_str = server_role_str(role);
+
+ return PyUnicode_FromString(role_str);
+}
+
+static PyObject *py_lp_dump(PyObject *self, PyObject *args)
+{
+ bool show_defaults = false;
+ const char *file_name = "";
+ const char *mode = "w";
+ FILE *f;
+ struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+
+ if (!PyArg_ParseTuple(args, "|bss", &show_defaults, &file_name, &mode))
+ return NULL;
+
+ if (file_name[0] == '\0') {
+ f = stdout;
+ } else {
+ f = fopen(file_name, mode);
+ }
+
+ if (f == NULL) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;
+ }
+
+ lpcfg_dump(lp_ctx, f, show_defaults, lpcfg_numservices(lp_ctx));
+
+ if (f != stdout) {
+ fclose(f);
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_lp_dump_globals(PyObject *self, PyObject *args)
+{
+ bool show_defaults = false;
+ const char *file_name = "";
+ const char *mode = "w";
+ FILE *f;
+ struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+
+ if (!PyArg_ParseTuple(args, "|bss", &show_defaults, &file_name, &mode))
+ return NULL;
+
+ if (file_name[0] == '\0') {
+ f = stdout;
+ } else {
+ f = fopen(file_name, mode);
+ }
+
+ if (f == NULL) {
+ PyErr_SetFromErrno(PyExc_IOError);
+ return NULL;
+ }
+
+ lpcfg_dump_globals(lp_ctx, f, show_defaults);
+
+ if (f != stdout) {
+ fclose(f);
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *py_lp_dump_a_parameter(PyObject *self, PyObject *args)
+{
+ char *param_name;
+ const char *section_name = NULL;
+ const char *file_name = "";
+ const char *mode = "w";
+ FILE *f;
+ struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+ struct loadparm_service *service;
+ bool ret;
+
+ if (!PyArg_ParseTuple(args, "s|zss", &param_name, &section_name, &file_name, &mode))
+ return NULL;
+
+ if (file_name[0] == '\0') {
+ f = stdout;
+ } else {
+ f = fopen(file_name, mode);
+ }
+
+ if (f == NULL) {
+ return NULL;
+ }
+
+ if (section_name != NULL && strwicmp(section_name, GLOBAL_NAME) &&
+ strwicmp(section_name, GLOBAL_NAME2)) {
+ /* it's a share parameter */
+ service = lpcfg_service(lp_ctx, section_name);
+ if (service == NULL) {
+ PyErr_Format(PyExc_RuntimeError, "Unknown section %s", section_name);
+ return NULL;
+ }
+ } else {
+ /* it's global */
+ service = NULL;
+ section_name = "global";
+ }
+
+ ret = lpcfg_dump_a_parameter(lp_ctx, service, param_name, f);
+
+ if (!ret) {
+ PyErr_Format(PyExc_RuntimeError, "Parameter %s unknown for section %s", param_name, section_name);
+ if (f != stdout) {
+ fclose(f);
+ }
+ return NULL;
+ }
+
+ if (f != stdout) {
+ fclose(f);
+ }
+
+ Py_RETURN_NONE;
+
+}
+
+static PyObject *py_lp_log_level(PyObject *self, PyObject *unused)
+{
+ int ret = debuglevel_get();
+ return PyLong_FromLong(ret);
+}
+
+
+static PyObject *py_samdb_url(PyObject *self, PyObject *unused)
+{
+ struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+ return PyUnicode_FromFormat("tdb://%s/sam.ldb", lpcfg_private_dir(lp_ctx));
+}
+
+static PyObject *py_cache_path(PyObject *self, PyObject *args)
+{
+ struct loadparm_context *lp_ctx = PyLoadparmContext_AsLoadparmContext(self);
+ char *name = NULL;
+ char *path = NULL;
+ PyObject *ret = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name)) {
+ return NULL;
+ }
+
+ path = lpcfg_cache_path(NULL, lp_ctx, name);
+ if (!path) {
+ PyErr_Format(PyExc_RuntimeError,
+ "Unable to access cache %s", name);
+ return NULL;
+ }
+ ret = PyUnicode_FromString(path);
+ talloc_free(path);
+
+ return ret;
+}
+
+static PyObject *py_state_path(PyObject *self, PyObject *args)
+{
+ struct loadparm_context *lp_ctx =
+ PyLoadparmContext_AsLoadparmContext(self);
+ char *name = NULL;
+ char *path = NULL;
+ PyObject *ret = NULL;
+
+ if (!PyArg_ParseTuple(args, "s", &name)) {
+ return NULL;
+ }
+
+ path = lpcfg_state_path(NULL, lp_ctx, name);
+ if (!path) {
+ PyErr_Format(PyExc_RuntimeError,
+ "Unable to access cache %s", name);
+ return NULL;
+ }
+ ret = PyUnicode_FromString(path);
+ talloc_free(path);
+
+ return ret;
+}
+
+static PyMethodDef py_lp_ctx_methods[] = {
+ { "load", py_lp_ctx_load, METH_VARARGS,
+ "S.load(filename) -> None\n"
+ "Load specified file." },
+ { "load_default", py_lp_ctx_load_default, METH_NOARGS,
+ "S.load_default() -> None\n"
+ "Load default smb.conf file." },
+ { "is_myname", py_lp_ctx_is_myname, METH_VARARGS,
+ "S.is_myname(name) -> bool\n"
+ "Check whether the specified name matches one of our netbios names." },
+ { "is_mydomain", py_lp_ctx_is_mydomain, METH_VARARGS,
+ "S.is_mydomain(name) -> bool\n"
+ "Check whether the specified name matches our domain name." },
+ { "get", py_lp_ctx_get, METH_VARARGS,
+ "S.get(name, service_name) -> value\n"
+ "Find specified parameter." },
+ { "set", py_lp_ctx_set, METH_VARARGS,
+ "S.set(name, value) -> bool\n"
+ "Change a parameter." },
+ { "private_path", py_lp_ctx_private_path, METH_VARARGS,
+ "S.private_path(name) -> path\n" },
+ { "services", py_lp_ctx_services, METH_NOARGS,
+ "S.services() -> list" },
+ { "server_role", py_lp_ctx_server_role, METH_NOARGS,
+ "S.server_role() -> value\n"
+ "Get the server role." },
+ { "dump", py_lp_dump, METH_VARARGS,
+ "S.dump(show_defaults=False, file_name='', mode='w')" },
+ { "dump_globals", py_lp_dump_globals, METH_VARARGS,
+ "S.dump_globals(show_defaults=False, file_name='', mode='w')" },
+ { "dump_a_parameter", py_lp_dump_a_parameter, METH_VARARGS,
+ "S.dump_a_parameter(name, service_name, file_name='', mode='w')" },
+ { "log_level", py_lp_log_level, METH_NOARGS,
+ "S.log_level() -> int\n Get the active log level" },
+ { "samdb_url", py_samdb_url, METH_NOARGS,
+ "S.samdb_url() -> string\n"
+ "Returns the current URL for sam.ldb." },
+ { "cache_path", py_cache_path, METH_VARARGS,
+ "S.cache_path(name) -> string\n"
+ "Returns a path in the Samba cache directory." },
+ { "state_path", py_state_path, METH_VARARGS,
+ "S.state_path(name) -> string\n"
+ "Returns a path in the Samba state directory." },
+ {0}
+};
+
+static PyObject *py_lp_ctx_default_service(PyObject *self, void *closure)
+{
+ return PyLoadparmService_FromService(lpcfg_default_service(PyLoadparmContext_AsLoadparmContext(self)));
+}
+
+static PyObject *py_lp_ctx_config_file(PyObject *self, void *closure)
+{
+ const char *configfile = lpcfg_configfile(PyLoadparmContext_AsLoadparmContext(self));
+ if (configfile == NULL)
+ Py_RETURN_NONE;
+ else
+ return PyUnicode_FromString(configfile);
+}
+
+static PyObject *py_lp_ctx_weak_crypto(PyObject *self, void *closure)
+{
+ enum samba_weak_crypto weak_crypto =
+ lpcfg_weak_crypto(PyLoadparmContext_AsLoadparmContext(self));
+
+ switch(weak_crypto) {
+ case SAMBA_WEAK_CRYPTO_UNKNOWN:
+ Py_RETURN_NONE;
+ case SAMBA_WEAK_CRYPTO_ALLOWED:
+ return PyUnicode_FromString("allowed");
+ case SAMBA_WEAK_CRYPTO_DISALLOWED:
+ return PyUnicode_FromString("disallowed");
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyGetSetDef py_lp_ctx_getset[] = {
+ {
+ .name = discard_const_p(char, "default_service"),
+ .get = (getter)py_lp_ctx_default_service,
+ },
+ {
+ .name = discard_const_p(char, "configfile"),
+ .get = (getter)py_lp_ctx_config_file,
+ .doc = discard_const_p(char, "Name of last config file that was loaded.")
+ },
+ {
+ .name = discard_const_p(char, "weak_crypto"),
+ .get = (getter)py_lp_ctx_weak_crypto,
+ .doc = discard_const_p(char, "If weak crypto is allowed.")
+ },
+ { .name = NULL }
+};
+
+static PyObject *py_lp_ctx_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ const char *kwnames[] = {"filename_for_non_global_lp", NULL};
+ PyObject *lp_ctx;
+ const char *non_global_conf = NULL;
+ struct loadparm_context *ctx;
+
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "|s",
+ discard_const_p(char *,
+ kwnames),
+ &non_global_conf)) {
+ return NULL;
+ }
+
+ /*
+ * by default, any LoadParm python objects map to a single global
+ * underlying object. The filename_for_non_global_lp arg overrides this
+ * default behaviour and creates a separate underlying LoadParm object.
+ */
+ if (non_global_conf != NULL) {
+ bool ok;
+ ctx = loadparm_init(NULL);
+ if (ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ lp_ctx = pytalloc_reference(type, ctx);
+ if (lp_ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ ok = lpcfg_load_no_global(
+ PyLoadparmContext_AsLoadparmContext(lp_ctx),
+ non_global_conf);
+ if (!ok) {
+ PyErr_Format(PyExc_ValueError,
+ "Could not load non-global conf %s",
+ non_global_conf);
+ return NULL;
+ }
+ return lp_ctx;
+ } else{
+ return pytalloc_reference(type, loadparm_init_global(false));
+ }
+}
+
+static Py_ssize_t py_lp_ctx_len(PyObject *self)
+{
+ return lpcfg_numservices(PyLoadparmContext_AsLoadparmContext(self));
+}
+
+static PyObject *py_lp_ctx_getitem(PyObject *self, PyObject *name)
+{
+ struct loadparm_service *service;
+ if (!PyUnicode_Check(name)) {
+ PyErr_SetString(PyExc_TypeError, "Only string subscripts are supported");
+ return NULL;
+ }
+ service = lpcfg_service(PyLoadparmContext_AsLoadparmContext(self), PyUnicode_AsUTF8(name));
+ if (service == NULL) {
+ PyErr_SetString(PyExc_KeyError, "No such section");
+ return NULL;
+ }
+ return PyLoadparmService_FromService(service);
+}
+
+static PyMappingMethods py_lp_ctx_mapping = {
+ .mp_length = (lenfunc)py_lp_ctx_len,
+ .mp_subscript = (binaryfunc)py_lp_ctx_getitem,
+};
+
+PyTypeObject PyLoadparmContext = {
+ .tp_name = "param.LoadParm",
+ .tp_getset = py_lp_ctx_getset,
+ .tp_methods = py_lp_ctx_methods,
+ .tp_new = py_lp_ctx_new,
+ .tp_as_mapping = &py_lp_ctx_mapping,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+};
+
+static PyObject *py_lp_service_dump(PyObject *self, PyObject *args)
+{
+ bool show_defaults = false;
+ FILE *f;
+ const char *file_name = "";
+ const char *mode = "w";
+ struct loadparm_service *service = PyLoadparmService_AsLoadparmService(self);
+ struct loadparm_service *default_service;
+ PyObject *py_default_service;
+
+ if (!PyArg_ParseTuple(args, "O|bss", &py_default_service, &show_defaults, &file_name, &mode))
+ return NULL;
+
+ if (file_name[0] == '\0') {
+ f = stdout;
+ } else {
+ f = fopen(file_name, mode);
+ }
+
+ if (f == NULL) {
+ return NULL;
+ }
+
+ if (!PyObject_TypeCheck(py_default_service, &PyLoadparmService)) {
+ PyErr_SetNone(PyExc_TypeError);
+ if (f != stdout) {
+ fclose(f);
+ }
+ return NULL;
+ }
+
+ default_service = PyLoadparmService_AsLoadparmService(py_default_service);
+
+ lpcfg_dump_one(f, show_defaults, service, default_service);
+
+ if (f != stdout) {
+ fclose(f);
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef py_lp_service_methods[] = {
+ { "dump", (PyCFunction)py_lp_service_dump, METH_VARARGS,
+ "S.dump(default_service, show_defaults=False, file_name='', mode='w')" },
+ {0}
+};
+
+PyTypeObject PyLoadparmService = {
+ .tp_name = "param.LoadparmService",
+ .tp_methods = py_lp_service_methods,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+};
+
+static PyObject *py_data_dir(PyObject *self)
+{
+ return PyUnicode_FromString(dyn_DATADIR);
+}
+
+static PyObject *py_default_path(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return PyUnicode_FromString(lp_default_path());
+}
+
+static PyObject *py_setup_dir(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return PyUnicode_FromString(dyn_SETUPDIR);
+}
+
+static PyObject *py_modules_dir(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return PyUnicode_FromString(dyn_MODULESDIR);
+}
+
+static PyObject *py_bin_dir(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return PyUnicode_FromString(dyn_BINDIR);
+}
+
+static PyObject *py_sbin_dir(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return PyUnicode_FromString(dyn_SBINDIR);
+}
+
+static PyMethodDef pyparam_methods[] = {
+ { "data_dir", (PyCFunction)py_data_dir, METH_NOARGS,
+ "Returns the compiled in location of data directory." },
+ { "default_path", (PyCFunction)py_default_path, METH_NOARGS,
+ "Returns the default smb.conf path." },
+ { "setup_dir", (PyCFunction)py_setup_dir, METH_NOARGS,
+ "Returns the compiled in location of provision templates." },
+ { "modules_dir", (PyCFunction)py_modules_dir, METH_NOARGS,
+ "Returns the compiled in location of modules." },
+ { "bin_dir", (PyCFunction)py_bin_dir, METH_NOARGS,
+ "Returns the compiled in BINDIR." },
+ { "sbin_dir", (PyCFunction)py_sbin_dir, METH_NOARGS,
+ "Returns the compiled in SBINDIR." },
+ {0}
+};
+
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "param",
+ .m_doc = "Parsing and writing Samba configuration files.",
+ .m_size = -1,
+ .m_methods = pyparam_methods,
+};
+
+MODULE_INIT_FUNC(param)
+{
+ PyObject *m;
+ PyTypeObject *talloc_type = pytalloc_GetObjectType();
+ if (talloc_type == NULL)
+ return NULL;
+
+ if (pytalloc_BaseObject_PyType_Ready(&PyLoadparmContext) < 0)
+ return NULL;
+
+ if (pytalloc_BaseObject_PyType_Ready(&PyLoadparmService) < 0)
+ return NULL;
+
+ m = PyModule_Create(&moduledef);
+ if (m == NULL)
+ return NULL;
+
+ Py_INCREF(&PyLoadparmContext);
+ PyModule_AddObject(m, "LoadParm", (PyObject *)&PyLoadparmContext);
+ return m;
+}
diff --git a/source4/param/pyparam.h b/source4/param/pyparam.h
new file mode 100644
index 0000000..e8944f5
--- /dev/null
+++ b/source4/param/pyparam.h
@@ -0,0 +1,28 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _PYPARAM_H_
+#define _PYPARAM_H_
+
+#include "param/param.h"
+
+_PUBLIC_ struct loadparm_context *lpcfg_from_py_object(TALLOC_CTX *mem_ctx, PyObject *py_obj);
+_PUBLIC_ struct loadparm_context *py_default_loadparm_context(TALLOC_CTX *mem_ctx);
+
+#endif /* _PYPARAM_H_ */
diff --git a/source4/param/pyparam_util.c b/source4/param/pyparam_util.c
new file mode 100644
index 0000000..9b9dcd2
--- /dev/null
+++ b/source4/param/pyparam_util.c
@@ -0,0 +1,81 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include "py3compat.h"
+#include "includes.h"
+#include "param/param.h"
+#include "param/pyparam.h"
+#include "param/loadparm.h"
+#include <pytalloc.h>
+
+#define PyLoadparmContext_AsLoadparmContext(obj) pytalloc_get_type(obj, struct loadparm_context)
+
+_PUBLIC_ struct loadparm_context *lpcfg_from_py_object(TALLOC_CTX *mem_ctx, PyObject *py_obj)
+{
+ struct loadparm_context *lp_ctx;
+ PyObject *param_mod;
+ PyTypeObject *lp_type;
+ bool is_lpobj;
+
+ if (PyUnicode_Check(py_obj)) {
+ lp_ctx = loadparm_init_global(false);
+ if (lp_ctx == NULL) {
+ return NULL;
+ }
+ if (!lpcfg_load(lp_ctx, PyUnicode_AsUTF8(py_obj))) {
+ PyErr_Format(PyExc_RuntimeError, "Unable to load %s",
+ PyUnicode_AsUTF8(py_obj));
+ return NULL;
+ }
+ return lp_ctx;
+ }
+
+ if (py_obj == Py_None) {
+ return loadparm_init_global(true);
+ }
+
+ param_mod = PyImport_ImportModule("samba.param");
+ if (param_mod == NULL) {
+ return NULL;
+ }
+
+ lp_type = (PyTypeObject *)PyObject_GetAttrString(param_mod, "LoadParm");
+ Py_DECREF(param_mod);
+ if (lp_type == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "Unable to import LoadParm");
+ return NULL;
+ }
+
+ is_lpobj = PyObject_TypeCheck(py_obj, lp_type);
+ Py_DECREF(lp_type);
+ if (is_lpobj) {
+ return talloc_reference(mem_ctx, PyLoadparmContext_AsLoadparmContext(py_obj));
+ }
+
+ PyErr_SetNone(PyExc_TypeError);
+ return NULL;
+}
+
+struct loadparm_context *py_default_loadparm_context(TALLOC_CTX *mem_ctx)
+{
+ return loadparm_init_global(true);
+}
+
+
diff --git a/source4/param/secrets.c b/source4/param/secrets.c
new file mode 100644
index 0000000..1df8620
--- /dev/null
+++ b/source4/param/secrets.c
@@ -0,0 +1,152 @@
+/*
+ Unix SMB/CIFS implementation.
+ Copyright (C) Andrew Tridgell 1992-2001
+ Copyright (C) Andrew Bartlett 2002
+ Copyright (C) Rafal Szczesniak 2002
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* the Samba secrets database stores any generated, private information
+ such as the local SID and machine trust password */
+
+#include "includes.h"
+#include "secrets.h"
+#include "param/param.h"
+#include "system/filesys.h"
+#include "lib/tdb_wrap/tdb_wrap.h"
+#include "lib/ldb-samba/ldb_wrap.h"
+#include <ldb.h>
+#include "../lib/util/util_tdb.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "dsdb/samdb/samdb.h"
+
+/**
+ create or connect to the secrets ldb
+*/
+struct ldb_context *secrets_db_create(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx)
+{
+ return ldb_wrap_connect(mem_ctx, NULL, lp_ctx, "secrets.ldb",
+ NULL, NULL, 0);
+}
+
+/**
+ connect to the secrets ldb
+*/
+struct ldb_context *secrets_db_connect(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx)
+{
+ return ldb_wrap_connect(mem_ctx, NULL, lp_ctx, "secrets.ldb",
+ NULL, NULL, LDB_FLG_DONT_CREATE_DB);
+}
+
+/**
+ * Retrieve the domain SID from the secrets database.
+ * @return pointer to a SID object if the SID could be obtained, NULL otherwise
+ */
+struct dom_sid *secrets_get_domain_sid(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ const char *domain,
+ enum netr_SchannelType *sec_channel_type,
+ char **errstring)
+{
+ struct ldb_context *ldb;
+ struct ldb_message *msg;
+ int ldb_ret;
+ const char *attrs[] = { "objectSid", "secureChannelType", NULL };
+ struct dom_sid *result = NULL;
+ const struct ldb_val *v;
+ enum ndr_err_code ndr_err;
+
+ *errstring = NULL;
+
+ ldb = secrets_db_connect(mem_ctx, lp_ctx);
+ if (ldb == NULL) {
+ DEBUG(5, ("secrets_db_connect failed\n"));
+ return NULL;
+ }
+
+ ldb_ret = dsdb_search_one(ldb, ldb, &msg,
+ ldb_dn_new(mem_ctx, ldb, SECRETS_PRIMARY_DOMAIN_DN),
+ LDB_SCOPE_ONELEVEL,
+ attrs, 0, SECRETS_PRIMARY_DOMAIN_FILTER, domain);
+
+ if (ldb_ret != LDB_SUCCESS) {
+ *errstring = talloc_asprintf(mem_ctx, "Failed to find record for %s in %s: %s: %s",
+ domain, (char *) ldb_get_opaque(ldb, "ldb_url"),
+ ldb_strerror(ldb_ret), ldb_errstring(ldb));
+ return NULL;
+ }
+ v = ldb_msg_find_ldb_val(msg, "objectSid");
+ if (v == NULL) {
+ *errstring = talloc_asprintf(mem_ctx, "Failed to find a SID on record for %s in %s",
+ domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
+ return NULL;
+ }
+
+ if (sec_channel_type) {
+ int t;
+ t = ldb_msg_find_attr_as_int(msg, "secureChannelType", -1);
+ if (t == -1) {
+ *errstring = talloc_asprintf(mem_ctx, "Failed to find secureChannelType for %s in %s",
+ domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
+ return NULL;
+ }
+ *sec_channel_type = t;
+ }
+
+ result = talloc(mem_ctx, struct dom_sid);
+ if (result == NULL) {
+ talloc_free(ldb);
+ return NULL;
+ }
+
+ ndr_err = ndr_pull_struct_blob(v, result, result,
+ (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ *errstring = talloc_asprintf(mem_ctx, "Failed to parse SID on record for %s in %s",
+ domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
+ talloc_free(result);
+ talloc_free(ldb);
+ return NULL;
+ }
+
+ return result;
+}
+
+char *keytab_name_from_msg(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_message *msg)
+{
+ const char *krb5keytab = ldb_msg_find_attr_as_string(msg, "krb5Keytab", NULL);
+ if (krb5keytab) {
+ return talloc_strdup(mem_ctx, krb5keytab);
+ } else {
+ char *file_keytab;
+ char *relative_path;
+ const char *privateKeytab = ldb_msg_find_attr_as_string(msg, "privateKeytab", NULL);
+ if (!privateKeytab) {
+ return NULL;
+ }
+
+ relative_path = ldb_relative_path(ldb, mem_ctx, privateKeytab);
+ if (!relative_path) {
+ return NULL;
+ }
+ file_keytab = talloc_asprintf(mem_ctx, "FILE:%s", relative_path);
+ talloc_free(relative_path);
+ return file_keytab;
+ }
+ return NULL;
+}
+
diff --git a/source4/param/secrets.h b/source4/param/secrets.h
new file mode 100644
index 0000000..1d2dc2b
--- /dev/null
+++ b/source4/param/secrets.h
@@ -0,0 +1,51 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * secrets.tdb file format info
+ * Copyright (C) Andrew Tridgell 2000
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _SOURCE4_PARAM_SECRETS_H
+#define _SOURCE4_PARAM_SECRETS_H
+
+#define SECRETS_PRIMARY_DOMAIN_DN "cn=Primary Domains"
+#define SECRETS_PRINCIPALS_DN "cn=Principals"
+#define SECRETS_PRIMARY_DOMAIN_FILTER "(&(flatname=%s)(objectclass=primaryDomain))"
+#define SECRETS_PRIMARY_REALM_FILTER "(&(realm=%s)(objectclass=primaryDomain))"
+#define SECRETS_KRBTGT_SEARCH "(&((|(realm=%s)(flatname=%s))(samAccountName=krbtgt)))"
+#define SECRETS_PRINCIPAL_SEARCH "(&(|(realm=%s)(flatname=%s))(servicePrincipalName=%s))"
+#define SECRETS_LDAP_FILTER "(&(objectclass=ldapSecret)(cn=SAMDB Credentials))"
+
+struct loadparm_context;
+struct tevent_context;
+struct ldb_message;
+struct ldb_context;
+
+#include "librpc/gen_ndr/misc.h"
+
+bool randseed_init(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx);
+
+struct ldb_context *secrets_db_create(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx);
+struct ldb_context *secrets_db_connect(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx);
+struct dom_sid *secrets_get_domain_sid(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ const char *domain,
+ enum netr_SchannelType *sec_channel_type,
+ char **errstring);
+char *keytab_name_from_msg(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_message *msg);
+
+
+#endif /* _SOURCE4_PARAM_SECRETS_H */
diff --git a/source4/param/share.c b/source4/param/share.c
new file mode 100644
index 0000000..aa477c7
--- /dev/null
+++ b/source4/param/share.c
@@ -0,0 +1,156 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Modular shares configuration system
+
+ Copyright (C) Simo Sorce 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "param/share.h"
+#include "param/param.h"
+#include "lib/util/samba_modules.h"
+
+char *share_string_option(TALLOC_CTX *mem_ctx, struct share_config *scfg, const char *opt_name, const char *defval)
+{
+ return scfg->ctx->ops->string_option(mem_ctx, scfg, opt_name, defval);
+}
+
+int share_int_option(struct share_config *scfg, const char *opt_name, int defval)
+{
+ return scfg->ctx->ops->int_option(scfg, opt_name, defval);
+}
+
+bool share_bool_option(struct share_config *scfg, const char *opt_name, bool defval)
+{
+ return scfg->ctx->ops->bool_option(scfg, opt_name, defval);
+}
+
+const char **share_string_list_option(TALLOC_CTX *mem_ctx, struct share_config *scfg, const char *opt_name)
+{
+ return scfg->ctx->ops->string_list_option(mem_ctx, scfg, opt_name);
+}
+
+NTSTATUS share_list_all(TALLOC_CTX *mem_ctx, struct share_context *sctx, int *count, const char ***names)
+{
+ return sctx->ops->list_all(mem_ctx, sctx, count, names);
+}
+
+NTSTATUS share_get_config(TALLOC_CTX *mem_ctx, struct share_context *sctx, const char *name, struct share_config **scfg)
+{
+ return sctx->ops->get_config(mem_ctx, sctx, name, scfg);
+}
+
+NTSTATUS share_create(struct share_context *sctx, const char *name, struct share_info *info, int count)
+{
+ if (sctx->ops->create) {
+ return sctx->ops->create(sctx, name, info, count);
+ }
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS share_set(struct share_context *sctx, const char *name, struct share_info *info, int count)
+{
+ if (sctx->ops->set) {
+ return sctx->ops->set(sctx, name, info, count);
+ }
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS share_remove(struct share_context *sctx, const char *name)
+{
+ if (sctx->ops->remove) {
+ return sctx->ops->remove(sctx, name);
+ }
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/* List of currently available share backends */
+static struct share_ops **backends = NULL;
+
+static const struct share_ops *share_backend_by_name(const char *name)
+{
+ int i;
+
+ for (i = 0; backends && backends[i]; i++) {
+ if (strcmp(backends[i]->name, name) == 0) {
+ return backends[i];
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ Register the share backend
+*/
+NTSTATUS share_register(const struct share_ops *ops)
+{
+ int i;
+
+ if (share_backend_by_name(ops->name) != NULL) {
+ DEBUG(0,("SHARE backend [%s] already registered\n", ops->name));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ i = 0;
+ while (backends && backends[i]) {
+ i++;
+ }
+
+ backends = realloc_p(backends, struct share_ops *, i + 2);
+ if (!backends) {
+ smb_panic("out of memory in share_register");
+ }
+
+ backends[i] = (struct share_ops *)smb_xmemdup(ops, sizeof(*ops));
+ backends[i]->name = smb_xstrdup(ops->name);
+
+ backends[i + 1] = NULL;
+
+ DEBUG(3, ("SHARE backend [%s] registered.\n", ops->name));
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS share_get_context(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ struct share_context **ctx)
+{
+ const struct share_ops *ops;
+
+ ops = share_backend_by_name("classic");
+ if (!ops) {
+ DEBUG(0, ("share_init_connection: share backend [classic] not found!\n"));
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ return ops->init(mem_ctx, ops, lp_ctx, ctx);
+}
+
+/*
+ initialise the SHARE subsystem
+*/
+NTSTATUS share_init(void)
+{
+#define _MODULE_PROTO(init) extern NTSTATUS init(TALLOC_CTX *);
+ STATIC_share_MODULES_PROTO;
+ init_module_fn static_init[] = { STATIC_share_MODULES };
+
+ run_init_functions(NULL, static_init);
+
+ return NT_STATUS_OK;
+}
diff --git a/source4/param/share.h b/source4/param/share.h
new file mode 100644
index 0000000..087697a
--- /dev/null
+++ b/source4/param/share.h
@@ -0,0 +1,149 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Modular services configuration
+
+ Copyright (C) Simo Sorce 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _SHARE_H
+#define _SHARE_H
+
+struct share_ops;
+
+struct share_context {
+ const struct share_ops *ops;
+ void *priv_data;
+};
+
+struct share_config {
+ const char *name;
+ struct share_context *ctx;
+ void *opaque;
+};
+
+enum share_info_type {
+ SHARE_INFO_STRING,
+ SHARE_INFO_INT,
+ SHARE_INFO_BLOB
+};
+
+struct share_info {
+ enum share_info_type type;
+ const char *name;
+ void *value;
+};
+
+struct tevent_context;
+
+struct share_ops {
+ const char *name;
+ NTSTATUS (*init)(TALLOC_CTX *, const struct share_ops*,
+ struct loadparm_context *lp_ctx,
+ struct share_context **);
+ char *(*string_option)(TALLOC_CTX *, struct share_config *, const char *, const char *);
+ int (*int_option)(struct share_config *, const char *, int);
+ bool (*bool_option)(struct share_config *, const char *, bool);
+ const char **(*string_list_option)(TALLOC_CTX *, struct share_config *, const char *);
+ NTSTATUS (*list_all)(TALLOC_CTX *, struct share_context *, int *, const char ***);
+ NTSTATUS (*get_config)(TALLOC_CTX *, struct share_context *, const char *, struct share_config **);
+ NTSTATUS (*create)(struct share_context *, const char *, struct share_info *, int);
+ NTSTATUS (*set)(struct share_context *, const char *, struct share_info *, int);
+ NTSTATUS (*remove)(struct share_context *, const char *);
+};
+
+struct loadparm_context;
+
+char *share_string_option(TALLOC_CTX *mem_ctx, struct share_config *scfg, const char *opt_name, const char *defval);
+int share_int_option(struct share_config *scfg, const char *opt_name, int defval);
+bool share_bool_option(struct share_config *scfg, const char *opt_name, bool defval);
+const char **share_string_list_option(TALLOC_CTX *mem_ctx, struct share_config *scfg, const char *opt_name);
+NTSTATUS share_list_all(TALLOC_CTX *mem_ctx, struct share_context *sctx, int *count, const char ***names);
+NTSTATUS share_get_config(TALLOC_CTX *mem_ctx, struct share_context *sctx, const char *name, struct share_config **scfg);
+NTSTATUS share_create(struct share_context *sctx, const char *name, struct share_info *info, int count);
+NTSTATUS share_set(struct share_context *sctx, const char *name, struct share_info *info, int count);
+NTSTATUS share_remove(struct share_context *sctx, const char *name);
+NTSTATUS share_register(const struct share_ops *ops);
+NTSTATUS share_get_context(TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ struct share_context **ctx);
+NTSTATUS share_init(void);
+
+/* list of shares options */
+
+#define SHARE_NAME "name"
+#define SHARE_PATH "path"
+#define SHARE_COMMENT "comment"
+#define SHARE_PASSWORD "password"
+#define SHARE_HOSTS_ALLOW "hosts-allow"
+#define SHARE_HOSTS_DENY "hosts-deny"
+#define SHARE_NTVFS_HANDLER "ntvfs-handler"
+#define SHARE_TYPE "type"
+#define SHARE_CSC_POLICY "csc-policy"
+#define SHARE_AVAILABLE "available"
+#define SHARE_BROWSEABLE "browseable"
+#define SHARE_MAX_CONNECTIONS "max-connections"
+
+/* I'd like to see the following options go away
+ * and always use EAs and SECDESCs */
+#define SHARE_READONLY "readonly"
+#define SHARE_MAP_SYSTEM "map-system"
+#define SHARE_MAP_HIDDEN "map-hidden"
+#define SHARE_MAP_ARCHIVE "map-archive"
+
+#define SHARE_STRICT_LOCKING "strict-locking"
+#define SHARE_OPLOCKS "oplocks"
+#define SHARE_STRICT_SYNC "strict-sync"
+#define SHARE_MSDFS_ROOT "msdfs-root"
+#define SHARE_CI_FILESYSTEM "ci-filesystem"
+
+#define SHARE_DIR_MASK "directory mask"
+#define SHARE_CREATE_MASK "create mask"
+#define SHARE_FORCE_CREATE_MODE "force create mode"
+#define SHARE_FORCE_DIR_MODE "force directory mode"
+
+/* defaults */
+
+#define SHARE_HOST_ALLOW_DEFAULT NULL
+#define SHARE_HOST_DENY_DEFAULT NULL
+#define SHARE_VOLUME_DEFAULT NULL
+#define SHARE_TYPE_DEFAULT "DISK"
+#define SHARE_CSC_POLICY_DEFAULT 0
+#define SHARE_AVAILABLE_DEFAULT true
+#define SHARE_BROWSEABLE_DEFAULT true
+#define SHARE_MAX_CONNECTIONS_DEFAULT 0
+
+#define SHARE_DIR_MASK_DEFAULT 0755
+#define SHARE_CREATE_MASK_DEFAULT 0744
+#define SHARE_FORCE_CREATE_MODE_DEFAULT 0000
+#define SHARE_FORCE_DIR_MODE_DEFAULT 0000
+
+
+
+/* I'd like to see the following options go away
+ * and always use EAs and SECDESCs */
+#define SHARE_READONLY_DEFAULT true
+#define SHARE_MAP_SYSTEM_DEFAULT false
+#define SHARE_MAP_HIDDEN_DEFAULT false
+#define SHARE_MAP_ARCHIVE_DEFAULT true
+
+#define SHARE_STRICT_LOCKING_DEFAULT true
+#define SHARE_OPLOCKS_DEFAULT true
+#define SHARE_STRICT_SYNC_DEFAULT false
+#define SHARE_MSDFS_ROOT_DEFAULT false
+#define SHARE_CI_FILESYSTEM_DEFAULT false
+
+#endif /* _SHARE_H */
diff --git a/source4/param/share_classic.c b/source4/param/share_classic.c
new file mode 100644
index 0000000..d03558d
--- /dev/null
+++ b/source4/param/share_classic.c
@@ -0,0 +1,385 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Classic file based shares configuration
+
+ Copyright (C) Simo Sorce 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "param/share.h"
+#include "param/param.h"
+
+NTSTATUS share_classic_init(TALLOC_CTX *);
+
+static NTSTATUS sclassic_init(TALLOC_CTX *mem_ctx,
+ const struct share_ops *ops,
+ struct loadparm_context *lp_ctx,
+ struct share_context **ctx)
+{
+ *ctx = talloc(mem_ctx, struct share_context);
+ if (!*ctx) {
+ DEBUG(0, ("ERROR: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ (*ctx)->ops = ops;
+ (*ctx)->priv_data = lp_ctx;
+
+ return NT_STATUS_OK;
+}
+
+static char *sclassic_string_option(TALLOC_CTX *mem_ctx,
+ struct share_config *scfg,
+ const char *opt_name,
+ const char *defval)
+{
+ struct loadparm_service *s = talloc_get_type(scfg->opaque,
+ struct loadparm_service);
+ struct loadparm_context *lp_ctx = talloc_get_type(scfg->ctx->priv_data,
+ struct loadparm_context);
+ char *parm, *val;
+ const char *ret;
+
+ if (strchr(opt_name, ':')) {
+ parm = talloc_strdup(scfg, opt_name);
+ if (!parm) {
+ return NULL;
+ }
+ val = strchr(parm, ':');
+ *val = '\0';
+ val++;
+
+ ret = lpcfg_parm_string(lp_ctx, s, parm, val);
+ if (!ret) {
+ ret = defval;
+ }
+ talloc_free(parm);
+ return talloc_strdup(mem_ctx, ret);
+ }
+
+ if (strcmp(opt_name, SHARE_NAME) == 0) {
+ return talloc_strdup(mem_ctx, scfg->name);
+ }
+
+ if (strcmp(opt_name, SHARE_PATH) == 0) {
+ return lpcfg_path(s, lpcfg_default_service(lp_ctx), mem_ctx);
+ }
+
+ if (strcmp(opt_name, SHARE_COMMENT) == 0) {
+ return lpcfg_comment(s, lpcfg_default_service(lp_ctx), mem_ctx);
+ }
+
+ if (strcmp(opt_name, SHARE_TYPE) == 0) {
+ if (lpcfg_printable(s, lpcfg_default_service(lp_ctx))) {
+ return talloc_strdup(mem_ctx, "PRINTER");
+ }
+ if (strcmp("NTFS", lpcfg_fstype(s, lpcfg_default_service(lp_ctx))) == 0) {
+ return talloc_strdup(mem_ctx, "DISK");
+ }
+ return talloc_strdup(mem_ctx, lpcfg_fstype(s, lpcfg_default_service(lp_ctx)));
+ }
+
+ if (strcmp(opt_name, SHARE_PASSWORD) == 0) {
+ return talloc_strdup(mem_ctx, defval);
+ }
+
+ DEBUG(0,("request for unknown share string option '%s'\n",
+ opt_name));
+
+ return talloc_strdup(mem_ctx, defval);
+}
+
+static int sclassic_int_option(struct share_config *scfg, const char *opt_name, int defval)
+{
+ struct loadparm_service *s = talloc_get_type(scfg->opaque,
+ struct loadparm_service);
+ struct loadparm_context *lp_ctx = talloc_get_type(scfg->ctx->priv_data,
+ struct loadparm_context);
+ char *parm, *val;
+ int ret;
+
+ if (strchr(opt_name, ':')) {
+ parm = talloc_strdup(scfg, opt_name);
+ if (!parm) {
+ return -1;
+ }
+ val = strchr(parm, ':');
+ *val = '\0';
+ val++;
+
+ ret = lpcfg_parm_int(lp_ctx, s, parm, val, defval);
+ if (!ret) {
+ ret = defval;
+ }
+ talloc_free(parm);
+ return ret;
+ }
+
+ if (strcmp(opt_name, SHARE_CSC_POLICY) == 0) {
+ return lpcfg_csc_policy(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_MAX_CONNECTIONS) == 0) {
+ return lpcfg_max_connections(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_CREATE_MASK) == 0) {
+ return lpcfg_create_mask(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_DIR_MASK) == 0) {
+ return lpcfg_directory_mask(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_FORCE_DIR_MODE) == 0) {
+ return lpcfg_force_directory_mode(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_FORCE_CREATE_MODE) == 0) {
+ return lpcfg_force_create_mode(s, lpcfg_default_service(lp_ctx));
+ }
+
+
+ DEBUG(0,("request for unknown share int option '%s'\n",
+ opt_name));
+
+ return defval;
+}
+
+static bool sclassic_bool_option(struct share_config *scfg, const char *opt_name,
+ bool defval)
+{
+ struct loadparm_service *s = talloc_get_type(scfg->opaque,
+ struct loadparm_service);
+ struct loadparm_context *lp_ctx = talloc_get_type(scfg->ctx->priv_data,
+ struct loadparm_context);
+ char *parm, *val;
+ bool ret;
+
+ if (strchr(opt_name, ':')) {
+ parm = talloc_strdup(scfg, opt_name);
+ if(!parm) {
+ return false;
+ }
+ val = strchr(parm, ':');
+ *val = '\0';
+ val++;
+
+ ret = lpcfg_parm_bool(lp_ctx, s, parm, val, defval);
+ talloc_free(parm);
+ return ret;
+ }
+
+ if (strcmp(opt_name, SHARE_AVAILABLE) == 0) {
+ return s != NULL;
+ }
+
+ if (strcmp(opt_name, SHARE_BROWSEABLE) == 0) {
+ return lpcfg_browseable(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_READONLY) == 0) {
+ return lpcfg_read_only(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_MAP_SYSTEM) == 0) {
+ return lpcfg_map_system(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_MAP_HIDDEN) == 0) {
+ return lpcfg_map_hidden(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_MAP_ARCHIVE) == 0) {
+ return lpcfg_map_archive(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_STRICT_LOCKING) == 0) {
+ return lpcfg_strict_locking(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_OPLOCKS) == 0) {
+ return lpcfg_oplocks(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_STRICT_SYNC) == 0) {
+ return lpcfg_strict_sync(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_MSDFS_ROOT) == 0) {
+ return lpcfg_msdfs_root(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_CI_FILESYSTEM) == 0) {
+ int case_sensitive = lpcfg_case_sensitive(s, lpcfg_default_service(lp_ctx));
+ /*
+ * Yes, this confusingly named option means Samba acts
+ * case sensitive, so that the filesystem can act case
+ * insensitive.
+ *
+ */
+ if (case_sensitive == Auto) {
+ /* Auto is for unix extensions and unix
+ * clients, which we don't support here.
+ * Samba needs to do the case changing,
+ * because the filesystem is case
+ * sensitive */
+ return false;
+ } else if (case_sensitive) {
+ /* True means that Samba won't do anything to
+ * change the case of incoming requests.
+ * Essentially this means we trust the file
+ * system to be case insensitive */
+ return true;
+ } else {
+ /* False means that Smaba needs to do the case
+ * changing, because the filesystem is case
+ * sensitive */
+ return false;
+ }
+ }
+
+ DEBUG(0,("request for unknown share bool option '%s'\n",
+ opt_name));
+
+ return defval;
+}
+
+static const char **sclassic_string_list_option(TALLOC_CTX *mem_ctx, struct share_config *scfg, const char *opt_name)
+{
+ struct loadparm_service *s = talloc_get_type(scfg->opaque,
+ struct loadparm_service);
+ struct loadparm_context *lp_ctx = talloc_get_type(scfg->ctx->priv_data,
+ struct loadparm_context);
+ char *parm, *val;
+ const char **ret;
+
+ if (strchr(opt_name, ':')) {
+ parm = talloc_strdup(scfg, opt_name);
+ if (!parm) {
+ return NULL;
+ }
+ val = strchr(parm, ':');
+ *val = '\0';
+ val++;
+
+ ret = lpcfg_parm_string_list(mem_ctx, lp_ctx, s, parm, val, ",;");
+ talloc_free(parm);
+ return ret;
+ }
+
+ if (strcmp(opt_name, SHARE_HOSTS_ALLOW) == 0) {
+ return lpcfg_hosts_allow(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_HOSTS_DENY) == 0) {
+ return lpcfg_hosts_deny(s, lpcfg_default_service(lp_ctx));
+ }
+
+ if (strcmp(opt_name, SHARE_NTVFS_HANDLER) == 0) {
+ return lpcfg_ntvfs_handler(s, lpcfg_default_service(lp_ctx));
+ }
+
+ DEBUG(0,("request for unknown share list option '%s'\n",
+ opt_name));
+
+ return NULL;
+}
+
+static NTSTATUS sclassic_list_all(TALLOC_CTX *mem_ctx,
+ struct share_context *ctx,
+ int *count,
+ const char ***names)
+{
+ int i;
+ int num_services;
+ const char **n;
+
+ num_services = lpcfg_numservices((struct loadparm_context *)ctx->priv_data);
+
+ n = talloc_array(mem_ctx, const char *, num_services);
+ if (!n) {
+ DEBUG(0,("ERROR: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; i < num_services; i++) {
+ n[i] = talloc_strdup(n, lpcfg_servicename(lpcfg_servicebynum((struct loadparm_context *)ctx->priv_data, i)));
+ if (!n[i]) {
+ DEBUG(0,("ERROR: Out of memory!\n"));
+ talloc_free(n);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ *names = n;
+ *count = num_services;
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS sclassic_get_config(TALLOC_CTX *mem_ctx,
+ struct share_context *ctx,
+ const char *name,
+ struct share_config **scfg)
+{
+ struct share_config *s;
+ struct loadparm_service *service;
+
+ service = lpcfg_service((struct loadparm_context *)ctx->priv_data, name);
+
+ if (service == NULL) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ s = talloc(mem_ctx, struct share_config);
+ if (!s) {
+ DEBUG(0,("ERROR: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ s->name = talloc_strdup(s, lpcfg_servicename(service));
+ if (!s->name) {
+ DEBUG(0,("ERROR: Out of memory!\n"));
+ talloc_free(s);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ s->opaque = (void *)service;
+ s->ctx = ctx;
+
+ *scfg = s;
+
+ return NT_STATUS_OK;
+}
+
+static const struct share_ops ops = {
+ .name = "classic",
+ .init = sclassic_init,
+ .string_option = sclassic_string_option,
+ .int_option = sclassic_int_option,
+ .bool_option = sclassic_bool_option,
+ .string_list_option = sclassic_string_list_option,
+ .list_all = sclassic_list_all,
+ .get_config = sclassic_get_config
+};
+
+NTSTATUS share_classic_init(TALLOC_CTX *ctx)
+{
+ return share_register(&ops);
+}
+
diff --git a/source4/param/tests/loadparm.c b/source4/param/tests/loadparm.c
new file mode 100644
index 0000000..6a6e33e
--- /dev/null
+++ b/source4/param/tests/loadparm.c
@@ -0,0 +1,271 @@
+/*
+ Unix SMB/CIFS implementation.
+ Samba utility functions
+ Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "param/share.h"
+#include "param/param.h"
+#include "torture/torture.h"
+#include "torture/local/proto.h"
+#include "libds/common/roles.h"
+
+static bool test_create(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lp_ctx != NULL, "lp_ctx");
+ return true;
+}
+
+static bool test_set_option(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "workgroup=werkgroep"), "lpcfg_set_option failed");
+ torture_assert_str_equal(tctx, "WERKGROEP", lpcfg_workgroup(lp_ctx), "workgroup");
+ return true;
+}
+
+static bool test_set_cmdline(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_cmdline(lp_ctx, "workgroup", "werkgroep"), "lpcfg_set_cmdline failed");
+ torture_assert(tctx, lpcfg_do_global_parameter(lp_ctx, "workgroup", "barbla"), "lpcfg_set_option failed");
+ torture_assert_str_equal(tctx, "WERKGROEP", lpcfg_workgroup(lp_ctx), "workgroup");
+ return true;
+}
+
+static bool test_do_global_parameter(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_do_global_parameter(lp_ctx, "workgroup", "werkgroep42"),
+ "lpcfg_set_cmdline failed");
+ torture_assert_str_equal(tctx, lpcfg_workgroup(lp_ctx), "WERKGROEP42", "workgroup");
+ return true;
+}
+
+
+static bool test_do_global_parameter_var(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_do_global_parameter_var(lp_ctx, "workgroup", "werk%s%d", "groep", 42),
+ "lpcfg_set_cmdline failed");
+ torture_assert_str_equal(tctx, lpcfg_workgroup(lp_ctx), "WERKGROEP42", "workgroup");
+ return true;
+}
+
+
+static bool test_set_option_invalid(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, !lpcfg_set_option(lp_ctx, "workgroup"), "lpcfg_set_option succeeded");
+ return true;
+}
+
+static bool test_set_option_parametric(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "some:thing=blaat"), "lpcfg_set_option failed");
+ torture_assert_str_equal(tctx, lpcfg_parm_string(lp_ctx, NULL, "some", "thing"), "blaat",
+ "invalid parametric option");
+ return true;
+}
+
+static bool test_lp_parm_double(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "some:thing=3.4"), "lpcfg_set_option failed");
+ torture_assert(tctx, lpcfg_parm_double(lp_ctx, NULL, "some", "thing", 2.0) == 3.4,
+ "invalid parametric option");
+ torture_assert(tctx, lpcfg_parm_double(lp_ctx, NULL, "some", "bla", 2.0) == 2.0,
+ "invalid parametric option");
+ return true;
+}
+
+static bool test_lp_parm_bool(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "some:thing=true"), "lpcfg_set_option failed");
+ torture_assert(tctx, lpcfg_parm_bool(lp_ctx, NULL, "some", "thing", false) == true,
+ "invalid parametric option");
+ torture_assert(tctx, lpcfg_parm_bool(lp_ctx, NULL, "some", "bla", true) == true,
+ "invalid parametric option");
+ return true;
+}
+
+static bool test_lp_parm_int(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "some:thing=34"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_parm_int(lp_ctx, NULL, "some", "thing", 20), 34,
+ "invalid parametric option");
+ torture_assert_int_equal(tctx, lpcfg_parm_int(lp_ctx, NULL, "some", "bla", 42), 42,
+ "invalid parametric option");
+ return true;
+}
+
+static bool test_lp_parm_bytes(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "some:thing=16K"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_parm_bytes(lp_ctx, NULL, "some", "thing", 20), 16 * 1024,
+ "invalid parametric option");
+ torture_assert_int_equal(tctx, lpcfg_parm_bytes(lp_ctx, NULL, "some", "bla", 42), 42,
+ "invalid parametric option");
+ return true;
+}
+
+static bool test_lp_do_service_parameter(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ struct loadparm_service *service = lpcfg_add_service(lp_ctx, lpcfg_default_service(lp_ctx), "foo");
+ torture_assert(tctx, lpcfg_do_service_parameter(lp_ctx, service,
+ "some:thing", "foo"), "lpcfg_set_option failed");
+ torture_assert_str_equal(tctx, lpcfg_parm_string(lp_ctx, service, "some", "thing"), "foo",
+ "invalid parametric option");
+ return true;
+}
+
+static bool test_lp_service(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ struct loadparm_service *service = lpcfg_add_service(lp_ctx, lpcfg_default_service(lp_ctx), "foo");
+ torture_assert(tctx, service == lpcfg_service(lp_ctx, "foo"), "invalid service");
+ return true;
+}
+
+static bool test_server_role_default(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_STANDALONE, "ROLE should be standalone by default");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_USER, "security should be user");
+ return true;
+}
+
+static bool test_server_role_dc_specified(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "server role=domain controller"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_ACTIVE_DIRECTORY_DC, "ROLE should be DC");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_USER, "security should be USER");
+ return true;
+}
+
+static bool test_server_role_member_specified(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "server role=member"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_DOMAIN_MEMBER, "ROLE should be member");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_ADS, "security should be ADS");
+ return true;
+}
+
+static bool test_server_role_member_specified2(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "server role=member"), "lpcfg_set_option failed");
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "security=domain"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_DOMAIN_MEMBER, "ROLE should be member");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_DOMAIN, "security should be domain");
+ return true;
+}
+
+static bool test_server_role_member_specified3(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "server role=member"), "lpcfg_set_option failed");
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "security=ads"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_DOMAIN_MEMBER, "ROLE should be member");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_ADS, "security should be ads");
+ return true;
+}
+
+static bool test_server_role_standalone_specified(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "server role=standalone"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_STANDALONE, "ROLE should be standalone");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_USER, "security should be USER");
+ return true;
+}
+
+static bool test_server_role_dc_domain_logons(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "domain logons=true"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_DOMAIN_PDC, "ROLE should be PDC");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_USER, "security should be user");
+ return true;
+}
+
+static bool test_server_role_dc_domain_logons_and_not_master(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "domain logons=true"), "lpcfg_set_option failed");
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "domain master=false"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_DOMAIN_BDC, "ROLE should be BDC");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_USER, "security should be user");
+ return true;
+}
+
+static bool test_server_role_security_ads(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "security=ads"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_DOMAIN_MEMBER, "ROLE should be MEMBER");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_ADS, "security should be ads");
+ return true;
+}
+
+static bool test_server_role_security_domain(struct torture_context *tctx)
+{
+ struct loadparm_context *lp_ctx = loadparm_init(tctx);
+ torture_assert(tctx, lpcfg_set_option(lp_ctx, "security=domain"), "lpcfg_set_option failed");
+ torture_assert_int_equal(tctx, lpcfg_server_role(lp_ctx), ROLE_DOMAIN_MEMBER, "ROLE should be MEMBER");
+ torture_assert_int_equal(tctx, lpcfg_security(lp_ctx), SEC_DOMAIN, "security should be domain");
+ return true;
+}
+
+struct torture_suite *torture_local_loadparm(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *suite = torture_suite_create(mem_ctx, "loadparm");
+
+ torture_suite_add_simple_test(suite, "create", test_create);
+ torture_suite_add_simple_test(suite, "set_option", test_set_option);
+ torture_suite_add_simple_test(suite, "set_cmdline", test_set_cmdline);
+ torture_suite_add_simple_test(suite, "set_option_invalid", test_set_option_invalid);
+ torture_suite_add_simple_test(suite, "set_option_parametric", test_set_option_parametric);
+ torture_suite_add_simple_test(suite, "set_lp_parm_double", test_lp_parm_double);
+ torture_suite_add_simple_test(suite, "set_lp_parm_bool", test_lp_parm_bool);
+ torture_suite_add_simple_test(suite, "set_lp_parm_int", test_lp_parm_int);
+ torture_suite_add_simple_test(suite, "set_lp_parm_bytes", test_lp_parm_bytes);
+ torture_suite_add_simple_test(suite, "service_parameter", test_lp_do_service_parameter);
+ torture_suite_add_simple_test(suite, "lpcfg_service", test_lp_service);
+ torture_suite_add_simple_test(suite, "do_global_parameter_var", test_do_global_parameter_var);
+ torture_suite_add_simple_test(suite, "do_global_parameter", test_do_global_parameter);
+ torture_suite_add_simple_test(suite, "test_server_role_default", test_server_role_default);
+ torture_suite_add_simple_test(suite, "test_server_role_dc_specified", test_server_role_dc_specified);
+ torture_suite_add_simple_test(suite, "test_server_role_member_specified", test_server_role_member_specified);
+ torture_suite_add_simple_test(suite, "test_server_role_member_specified2", test_server_role_member_specified2);
+ torture_suite_add_simple_test(suite, "test_server_role_member_specified3", test_server_role_member_specified3);
+ torture_suite_add_simple_test(suite, "test_server_role_standalone_specified", test_server_role_standalone_specified);
+ torture_suite_add_simple_test(suite, "test_server_role_dc_domain_logons", test_server_role_dc_domain_logons);
+ torture_suite_add_simple_test(suite, "test_server_role_dc_domain_logons_and_not_master", test_server_role_dc_domain_logons_and_not_master);
+ torture_suite_add_simple_test(suite, "test_server_role_security_ads", test_server_role_security_ads);
+ torture_suite_add_simple_test(suite, "test_server_role_security_domain", test_server_role_security_domain);
+
+ return suite;
+}
diff --git a/source4/param/tests/share.c b/source4/param/tests/share.c
new file mode 100644
index 0000000..9ac43ba
--- /dev/null
+++ b/source4/param/tests/share.c
@@ -0,0 +1,207 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ local testing of share code
+
+ Copyright (C) Jelmer Vernooij 2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "param/share.h"
+#include "param/param.h"
+#include "torture/torture.h"
+#include "torture/local/proto.h"
+
+static bool test_list_empty(struct torture_context *tctx,
+ const void *tcase_data,
+ const void *test_data)
+{
+ struct share_context *ctx = (struct share_context *)discard_const(tcase_data);
+ int count;
+ const char **names;
+
+ torture_assert_ntstatus_ok(tctx, share_list_all(tctx, ctx, &count, &names),
+ "share_list_all failed");
+
+ return true;
+}
+
+static bool test_create(struct torture_context *tctx,
+ const void *tcase_data,
+ const void *test_data)
+{
+ struct share_context *ctx = (struct share_context *)discard_const(tcase_data);
+ int count;
+ const char **names;
+ int i;
+ bool found = false;
+ struct share_info inf[] = {
+ { SHARE_INFO_STRING, SHARE_TYPE, discard_const_p(void *, "IPC$") },
+ { SHARE_INFO_STRING, SHARE_PATH, discard_const_p(void *, "/tmp/bla") }
+ };
+ NTSTATUS status;
+
+ status = share_create(ctx, "bloe", inf, 2);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED))
+ torture_skip(tctx, "Not supported by backend");
+
+ torture_assert_ntstatus_ok(tctx, status, "create_share failed");
+
+ torture_assert_ntstatus_ok(tctx, share_list_all(tctx, ctx, &count, &names),
+ "share_list_all failed");
+
+ torture_assert(tctx, count >= 1, "creating share failed");
+
+
+ for (i = 0; i < count; i++) {
+ found |= strcmp(names[i], "bloe") == 0;
+ }
+
+ torture_assert(tctx, found, "created share found");
+
+ return true;
+}
+
+
+static bool test_create_invalid(struct torture_context *tctx,
+ const void *tcase_data,
+ const void *test_data)
+{
+ struct share_context *ctx = (struct share_context *)discard_const(tcase_data);
+ NTSTATUS status;
+
+ status = share_create(ctx, "bla", NULL, 0);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED))
+ torture_skip(tctx, "Not supported by backend");
+
+ torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER,
+ status,
+ "create_share failed");
+
+ torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER,
+ share_create(ctx, NULL, NULL, 0),
+ "create_share failed");
+
+ return true;
+}
+
+static bool test_share_remove_invalid(struct torture_context *tctx,
+ const void *tcase_data,
+ const void *test_data)
+{
+ struct share_context *ctx = (struct share_context *)discard_const(tcase_data);
+ NTSTATUS status;
+
+ status = share_remove(ctx, "nonexistent");
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED))
+ torture_skip(tctx, "Not supported by backend");
+
+ torture_assert_ntstatus_equal(tctx, status, NT_STATUS_UNSUCCESSFUL, "remove fails");
+
+ return true;
+}
+
+
+
+static bool test_share_remove(struct torture_context *tctx,
+ const void *tcase_data,
+ const void *test_data)
+{
+ struct share_context *ctx = (struct share_context *)discard_const(tcase_data);
+ struct share_info inf[] = {
+ { SHARE_INFO_STRING, SHARE_TYPE, discard_const_p(void *, "IPC$") },
+ { SHARE_INFO_STRING, SHARE_PATH, discard_const_p(void *, "/tmp/bla") }
+ };
+ NTSTATUS status;
+
+ status = share_create(ctx, "blie", inf, 2);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED))
+ torture_skip(tctx, "Not supported by backend");
+
+ torture_assert_ntstatus_ok(tctx, status, "create_share failed");
+
+ torture_assert_ntstatus_ok(tctx, share_remove(ctx, "blie"), "remove failed");
+
+ return true;
+}
+
+static bool test_double_create(struct torture_context *tctx,
+ const void *tcase_data,
+ const void *test_data)
+{
+ struct share_context *ctx = (struct share_context *)discard_const(tcase_data);
+ struct share_info inf[] = {
+ { SHARE_INFO_STRING, SHARE_TYPE, discard_const_p(void *, "IPC$") },
+ { SHARE_INFO_STRING, SHARE_PATH, discard_const_p(void *, "/tmp/bla") }
+ };
+ NTSTATUS status;
+
+ status = share_create(ctx, "bla", inf, 2);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED))
+ torture_skip(tctx, "Not supported by backend");
+
+ torture_assert_ntstatus_ok(tctx, status, "create_share failed");
+
+ torture_assert_ntstatus_equal(tctx, NT_STATUS_OBJECT_NAME_COLLISION,
+ share_create(ctx, "bla", inf, 2),
+ "create_share failed");
+
+ return true;
+}
+
+static void tcase_add_share_tests(struct torture_tcase *tcase)
+{
+ torture_tcase_add_test_const(tcase, "list_empty", test_list_empty,NULL);
+ torture_tcase_add_test_const(tcase, "share_create", test_create, NULL);
+ torture_tcase_add_test_const(tcase, "share_remove", test_share_remove,
+ NULL);
+ torture_tcase_add_test_const(tcase, "share_remove_invalid",
+ test_share_remove_invalid, NULL);
+ torture_tcase_add_test_const(tcase, "share_create_invalid",
+ test_create_invalid, NULL);
+ torture_tcase_add_test_const(tcase, "share_double_create",
+ test_double_create, NULL);
+}
+
+static bool setup_classic(struct torture_context *tctx, void **data)
+{
+ return NT_STATUS_IS_OK(share_get_context(tctx, tctx->lp_ctx, (struct share_context **)data));
+}
+
+static bool teardown(struct torture_context *tctx, void *data)
+{
+ talloc_free(data);
+ return true;
+}
+
+struct torture_suite *torture_local_share(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *suite = torture_suite_create(mem_ctx, "share");
+ struct torture_tcase *tcase;
+
+ share_init();
+
+ tcase = torture_suite_add_tcase(suite, "classic");
+ torture_tcase_set_fixture(tcase, setup_classic, teardown);
+ tcase_add_share_tests(tcase);
+
+ return suite;
+}
diff --git a/source4/param/wscript_build b/source4/param/wscript_build
new file mode 100644
index 0000000..d1b852c
--- /dev/null
+++ b/source4/param/wscript_build
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+name = bld.pyembed_libname('PROVISION')
+pytalloc_util = bld.pyembed_libname('pytalloc-util')
+pyparam_util = bld.pyembed_libname('pyparam_util')
+libpython = bld.pyembed_libname('LIBPYTHON')
+
+pyldb_util = bld.pyembed_libname('pyldb-util')
+bld.SAMBA_SUBSYSTEM(name,
+ source='provision.c pyparam.c',
+ deps='%s %s ldb %s %s' % (libpython, pyparam_util, pytalloc_util, pyldb_util),
+ pyext=True,
+ enabled=bld.PYTHON_BUILD_IS_ENABLED(),
+)
+
+
+bld.SAMBA_SUBSYSTEM('share',
+ source='share.c',
+ public_headers='share.h',
+ deps='samba-util samba-modules'
+ )
+
+
+bld.SAMBA_MODULE('share_classic',
+ source='share_classic.c',
+ subsystem='share',
+ init_function='share_classic_init',
+ deps='samba-util samba-hostconfig'
+ )
+
+
+bld.SAMBA_SUBSYSTEM('SECRETS',
+ source='secrets.c',
+ deps='ldb tdb-wrap util_tdb NDR_SECURITY tevent ldbwrap'
+ )
+
+pytalloc_util = bld.pyembed_libname('pytalloc-util')
+pyparam_util = bld.pyembed_libname('pyparam_util')
+libpython = bld.pyembed_libname('LIBPYTHON')
+
+bld.SAMBA_PYTHON('pyparam',
+ source='pyparam.c',
+ deps='samba-hostconfig %s' % pytalloc_util,
+ realname='samba/param.so'
+ )
+
+bld.SAMBA_SUBSYSTEM(pyparam_util,
+ source='pyparam_util.c',
+ deps='%s samba-hostconfig %s' % (libpython, pytalloc_util),
+ pyext=True,
+ enabled=bld.PYTHON_BUILD_IS_ENABLED()
+ )
+
+bld.SAMBA_SUBSYSTEM('param_options',
+ source='loadparm.c',
+ deps='samba-hostconfig')
+
+
+bld.SAMBA_LIBRARY('shares',
+ source=[],
+ deps='share',
+ grouping_library=True,
+ private_library=True)