summaryrefslogtreecommitdiff
path: root/source4/scripting
diff options
context:
space:
mode:
Diffstat (limited to 'source4/scripting')
-rwxr-xr-xsource4/scripting/bin/samba3dump387
-rw-r--r--source4/scripting/bin/winreg.py93
-rw-r--r--source4/scripting/ejs/smbcalls_reg.c2
-rw-r--r--source4/scripting/python/misc_wrap.c73
-rw-r--r--source4/scripting/python/samba/__init__.py20
-rw-r--r--source4/scripting/python/samba/provision.py4
-rw-r--r--source4/scripting/python/samba/samba3.py224
-rw-r--r--source4/scripting/python/samba/tests/__init__.py1
-rw-r--r--source4/scripting/python/samba/tests/samba3.py57
-rw-r--r--source4/scripting/python/samba/upgrade.py16
10 files changed, 584 insertions, 293 deletions
diff --git a/source4/scripting/bin/samba3dump b/source4/scripting/bin/samba3dump
index 6b3d999803..44ffc6a861 100755
--- a/source4/scripting/bin/samba3dump
+++ b/source4/scripting/bin/samba3dump
@@ -1,234 +1,157 @@
-#!/bin/sh
-exec smbscript "$0" ${1+"$@"}
-/*
- Dump Samba3 data
- Copyright Jelmer Vernooij 2005
- Released under the GNU GPL v2 or later
-*/
-
-options = GetOptions(ARGV,
- "POPT_AUTOHELP",
- "POPT_COMMON_SAMBA",
- "POPT_COMMON_VERSION",
- 'format=s',
- 'quiet', 'blank');
-
-if (options == undefined) {
- println("Failed to parse options");
- return -1;
-}
-
-if (options.format == undefined) {
- options.format = "summary";
-}
-
-if (options.format != "summary" && options.format != "full") {
- printf("Unknown format %s\n", options.format);
- return -1;
-}
-
-libinclude("base.js");
-
-if (options.ARGV.length != 2) {
- println("Usage: samba3dump <libdir> <smb.conf>");
- return -1;
-}
-
-function print_header(txt)
-{
- printf("\n%s\n", txt);
- println("==========================================");
-}
-
-function print_samba3_policy(pol)
-{
- print_header("Account Policies");
- printf("Min password length: %d\n", pol.min_password_length);
- printf("Password history length: %d\n", pol.password_history);
- printf("User must logon to change password: %d\n", pol.user_must_logon_to_change_password);
- printf("Maximum password age: %d\n", pol.maximum_password_age);
- printf("Minimum password age: %d\n", pol.minimum_password_age);
- printf("Lockout duration: %d\n", pol.lockout_duration);
- printf("Reset Count Minutes: %d\n", pol.reset_count_minutes);
- printf("Bad Lockout Minutes: %d\n", pol.bad_lockout_minutes);
- printf("Disconnect Time: %d\n", pol.disconnect_time);
- printf("Refuse Machine Password Change: %d\n", pol.refuse_machine_password_change);
-}
-
-function print_samba3_sam(samba3)
-{
- var i;
- print_header("SAM Database");
+#!/usr/bin/python
+#
+# Dump Samba3 data
+# Copyright Jelmer Vernooij 2005-2007
+# Released under the GNU GPL v3 or later
+#
+
+import optparse
+import os, sys
+sys.path.append(os.path.join(os.path.dirname(__file__), "../python"))
+import samba
+import samba.samba3
+
+parser = optparse.OptionParser("provision <libdir> <smb.conf>")
+parser.add_option("--format", type="choice", metavar="FORMAT",
+ choices=["full", "summary"])
+
+opts, args = parser.parse_args()
+
+if opts.format is None:
+ opts.format = "summary"
+
+def print_header(txt):
+ print "\n%s" % txt
+ print "=========================================="
+
+def print_samba3_policy(pol):
+ print_header("Account Policies")
+ print "Min password length: %d" % pol.min_password_length
+ print "Password history length: %d" % pol.password_history
+ print "User must logon to change password: %d" % pol.user_must_logon_to_change_password
+ print "Maximum password age: %d" % pol.maximum_password_age
+ print "Minimum password age: %d" % pol.minimum_password_age
+ print "Lockout duration: %d" % pol.lockout_duration
+ print "Reset Count Minutes: %d" % pol.reset_count_minutes
+ print "Bad Lockout Minutes: %d" % pol.bad_lockout_minutes
+ print "Disconnect Time: %d" % pol.disconnect_time
+ print "Refuse Machine Password Change: %d" % pol.refuse_machine_password_change
+
+def print_samba3_sam(samba3):
+ print_header("SAM Database")
- for (i in samba3.samaccounts) {
- var a = samba3.samaccounts[i];
- printf("%d: %s\n", a.user_rid, a.username);
- }
-}
-
-function print_samba3_shares(samba3)
-{
- var i, j;
- print_header("Configured shares");
- for (i in samba3.shares) {
- var s = samba3.shares[i];
- printf("--- %s ---\n", s.name);
-
- for (j in s.parameters) {
- var p = s.parameters[j];
- printf("\t%s = %s\n", p.name, p.value);
- }
-
- println("");
- }
-}
-
-function print_samba3_secrets(secrets)
-{
- var i;
- print_header("Secrets");
-
- println("IPC Credentials:");
- if (secrets.ipc_cred.username_obtained)
- printf(" User: %s\n", secrets.ipc_cred.get_username);
- if (secrets.ipc_cred.password_obtained)
- printf(" Password: %s\n", secrets.ipc_cred.get_password);
-
- if (secrets.ipc_cred.domain_obtained)
- printf(" Domain: %s\n\n", secrets.ipc_cred.get_domain);
-
- println("LDAP passwords:");
- for (i in secrets.ldappws) {
- var pw = secrets.ldappws[i];
- printf("\t%s -> %s\n", pw.dn, pw.password);
- }
- println("");
-
- println("Domains:");
- for (i in secrets.domains) {
- var d = secrets.domains[i];
- printf("\t--- %s ---\n", d.name);
- printf("\tSID: %s\n", d.sid);
- printf("\tGUID: %s\n", d.guid);
- printf("\tPlaintext pwd: %s\n", d.plaintext_pw);
- printf("\tLast Changed: %lu\n", d.last_change_time);
- printf("\tSecure Channel Type: %d\n\n", d.sec_channel_type);
- }
-
- println("Trusted domains:");
- for (i in secrets.trusted_domains) {
- var td = secrets.trusted_domains[i];
- for (j = 0; j < td.uni_name_len; j++) {
- printf("\t--- %s ---\n", td.uni_name[j]);
- }
- printf("\tPassword: %s\n", td.pass);
- printf("\tModified: %lu\n", td.mod_time);
- printf("\tSID: %s\n", td.domain_sid);
- }
-}
-
-function print_samba3_regdb(regdb)
-{
- var i, j;
- print_header("Registry");
-
- for (i in regdb.keys) {
- var k = regdb.keys[i];
- printf("%s\n", k.name);
- for (j in k.values) {
- var v = k.values[j];
- printf("\t%s: type %d, length %d\n", v.name, v.type, v.data.length);
- }
- }
-}
-
-function print_samba3_winsdb(samba3)
-{
- var i;
- print_header("WINS Database");
-
- for (i in samba3.winsentries) {
- var e = samba3.winsentries[i];
- printf("%s, nb_flags: %x, type: %d, ttl: %lu, %d ips, fst: %s\n", e.name, e.nb_flags, e.type, e.ttl, e.ips.length, e.ips[0]);
- }
-}
-
-function print_samba3_groupmappings(groupdb)
-{
- print_header("Group Mappings");
+ for a in samba3.samaccounts:
+ print "%d: %s" % a.user_rid, a.username
+
+def print_samba3_shares(samba3):
+ print_header("Configured shares")
+ for s in samba3.shares:
+ print "--- %s ---" % s.name
+
+ for p in s.parameters:
+ print "\t%s = %s" % (p.name, p.value)
+
+ print ""
+
+def print_samba3_secrets(secrets):
+ print_header("Secrets")
+
+ print "IPC Credentials:"
+ if secrets.ipc_cred.username_obtained:
+ print " User: %s\n" % secrets.ipc_cred.get_username
+ if secrets.ipc_cred.password_obtained:
+ print " Password: %s\n" % secrets.ipc_cred.get_password
+
+ if secrets.ipc_cred.domain_obtained:
+ print " Domain: %s\n" % secrets.ipc_cred.get_domain
+
+ print "LDAP passwords:"
+ for pw in secrets.ldappws:
+ print "\t%s -> %s" % (pw.dn, pw.password)
+ print ""
+
+ print "Domains:"
+ for d in secrets.domains:
+ print "\t--- %s ---" % d.name
+ print "\tSID: %s" % d.sid
+ print "\tGUID: %s" % d.guid
+ print "\tPlaintext pwd: %s" % d.plaintext_pw
+ print "\tLast Changed: %lu" % d.last_change_time
+ print "\tSecure Channel Type: %d\n" % d.sec_channel_type
+
+ print "Trusted domains:"
+ for td in secrets.trusted_domains:
+ for n in td.uni_name:
+ print "\t--- %s ---" % n
+ print "\tPassword: %s" % td.password
+ print "\tModified: %lu" % td.mod_time
+ print "\tSID: %s" % td.domain_sid
+
+def print_samba3_regdb(regdb):
+ print_header("Registry")
+
+ for k in regdb.keys:
+ print "%s\n" % k.name
+ for v in regdb.values(k):
+ print "\t%s: type %d, length %d" % (v.name, v.type, v.data.length)
+
+def print_samba3_winsdb(samba3):
+ print_header("WINS Database")
+
+ for e in samba3.winsentries:
+ print "%s, nb_flags: %x, type: %d, ttl: %lu, %d ips, fst: %s" % (e.name, e.nb_flags, e.type, e.ttl, e.ips.length, e.ips[0])
+
+def print_samba3_groupmappings(groupdb):
+ print_header("Group Mappings")
- for (var i in groupdb.groupmappings) {
- var g = groupdb.groupmappings[i];
- printf("\t--- Group: %s ---\n", g.nt_name);
- printf("\tComment: %s\n", g.comment);
- printf("\tGID: %d\n", g.gid);
- printf("\tSID Name Use: %d\n", g.sid_name_use);
- printf("\tSID: %s\n\n", g.sid);
- }
-}
-
-function print_samba3_aliases(groupdb)
-{
- var i, j;
- for (i in groupdb.aliases) {
- var a = groupdb.aliases[i];
- printf("\t--- Alias: %s ---\n", a.sid);
- for (j in a.members) {
- printf("\t%s\n", a.members[j]);
- }
- }
-}
-
-function print_samba3_idmapdb(idmapdb)
-{
- var i;
- print_header("Winbindd SID<->GID/UID mappings");
-
- printf("User High Water Mark: %d\n", idmapdb.user_hwm);
- printf("Group High Water Mark: %d\n\n", idmapdb.group_hwm);
-
- for (i in idmapdb.mappings) {
- var e = idmapdb.mappings[i];
- printf("%s -> ", e.sid);
-
- if (e.type == e.IDMAP_GROUP) {
- printf("GID %d\n", e.unix_id);
- } else {
- printf("UID %d\n", e.unix_id);
- }
- }
-}
-
-function print_samba3(samba3)
-{
- print_samba3_sam(samba3);
- print_samba3_policy(samba3.policy);
- print_samba3_shares(samba3);
- print_samba3_winsdb(samba3);
- print_samba3_regdb(samba3.registry);
- print_samba3_secrets(samba3.secrets);
- print_samba3_groupmappings(samba3);
- print_samba3_aliases(samba3);
- print_samba3_idmapdb(samba3.idmapdb);
-}
-
-function print_samba3_summary(samba3)
-{
- printf("WINS db entries: %d\n", samba3.winsentries.length);
- printf("SAM Accounts: %d\n", samba3.samaccounts.length);
- printf("Registry key count: %d\n", samba3.registry.keys.length);
- printf("Shares (including [global]): %d\n", samba3.shares.length);
- printf("Groupmap count: %d\n", samba3.groupmappings.length);
- printf("Alias count: %d\n", samba3.aliases.length);
- printf("Idmap count: %d\n", samba3.idmapdb.mappings.length);
-}
-
-samba3 = samba3_read(options.ARGV[0], options.ARGV[1]);
-
-if (options.format == "summary") {
- print_samba3_summary(samba3);
-} else if (options.format == "full") {
- print_samba3(samba3);
-}
-
-return 0;
+ for g in groupdb.groupmappings:
+ print "\t--- Group: %s ---" % g.nt_name
+ print "\tComment: %s" % g.comment
+ print "\tGID: %d" % g.gid
+ print "\tSID Name Use: %d" % g.sid_name_use
+ print "\tSID: %s\n" % g.sid
+
+def print_samba3_aliases(groupdb):
+ for a in groupdb.aliases:
+ print "\t--- Alias: %s ---" % a.sid
+ for m in a.members:
+ print "\t%s" % m
+
+def print_samba3_idmapdb(idmapdb):
+ print_header("Winbindd SID<->GID/UID mappings")
+
+ print "User High Water Mark: %d" % idmapdb.user_hwm
+ print "Group High Water Mark: %d\n" % idmapdb.group_hwm
+
+ for e in idmapdb.mappings:
+ if e.type == e.IDMAP_GROUP:
+ print "%s -> GID %d" % (e.sid, e.unix_id)
+ else:
+ print "%s -> UID %d" % (e.sid, e.unix_id)
+
+def print_samba3(samba3):
+ print_samba3_sam(samba3)
+ print_samba3_policy(samba3.get_policy_db())
+ print_samba3_shares(samba3)
+ print_samba3_winsdb(samba3.get_wins_db())
+ print_samba3_regdb(samba3.get_registry())
+ print_samba3_secrets(samba3.get_secrets_db())
+ print_samba3_groupmappings(samba3.get_groupmapping_db())
+ print_samba3_aliases(samba3)
+ print_samba3_idmapdb(samba3.get_idmap_db())
+
+def print_samba3_summary(samba3):
+ print "WINS db entries: %d" % len(samba3.winsentries)
+ print "SAM Accounts: %d" % len(samba3.samaccounts)
+ print "Registry key count: %d" % len(samba3.registry.keys)
+ print "Shares (including [global]): %d" % len(samba3.shares)
+ print "Groupmap count: %d" % len(samba3.groupmappings)
+ print "Alias count: %d" % len(samba3.aliases)
+ print "Idmap count: %d" % len(samba3.idmapdb.mappings)
+
+samba3 = samba.samba3.Samba3(args[0], args[1])
+
+if opts.format == "summary":
+ print_samba3_summary(samba3)
+elif opts.format == "full":
+ print_samba3(samba3)
diff --git a/source4/scripting/bin/winreg.py b/source4/scripting/bin/winreg.py
new file mode 100644
index 0000000000..6cdc3a5898
--- /dev/null
+++ b/source4/scripting/bin/winreg.py
@@ -0,0 +1,93 @@
+#!/usr/bin/python
+#
+# tool to manipulate a remote registry
+# Copyright Andrew Tridgell 2005
+# Copyright Jelmer Vernooij 2007
+# Released under the GNU GPL v3 or later
+#
+
+import sys
+
+options = GetOptions(ARGV,
+ "POPT_AUTOHELP",
+ "POPT_COMMON_SAMBA",
+ "POPT_COMMON_CREDENTIALS",
+ "createkey=s")
+if (options == undefined) {
+ print "Failed to parse options"
+ sys.exit(-1)
+
+if len(sys.argv < 2:
+ print "Usage: %s <BINDING> [path]" % sys.argv[0]
+ sys.exit(-1)
+
+binding = options.ARGV[0]
+reg = winregObj()
+
+print "Connecting to " + binding
+status = reg.connect(binding)
+if (status.is_ok != true) {
+ print("Failed to connect to " + binding + " - " + status.errstr + "\n")
+ return -1
+}
+
+def list_values(path):
+ list = reg.enum_values(path)
+ if (list == undefined) {
+ return
+ }
+ for (i=0;i<list.length;i++) {
+ v = list[i]
+ printf("\ttype=%-30s size=%4d '%s'\n", reg.typestring(v.type), v.size, v.name)
+ if (v.type == reg.REG_SZ || v.type == reg.REG_EXPAND_SZ) {
+ printf("\t\t'%s'\n", v.value)
+ }
+ if (v.type == reg.REG_MULTI_SZ) {
+ for (j in v.value) {
+ printf("\t\t'%s'\n", v.value[j])
+ }
+ }
+ if (v.type == reg.REG_DWORD || v.type == reg.REG_DWORD_BIG_ENDIAN) {
+ printf("\t\t0x%08x (%d)\n", v.value, v.value)
+ }
+ if (v.type == reg.REG_QWORD) {
+ printf("\t\t0x%llx (%lld)\n", v.value, v.value)
+ }
+ }
+
+def list_path(path):
+ count = 0
+ list = reg.enum_path(path)
+ if (list == undefined) {
+ println("Unable to list " + path)
+ return 0
+ }
+ list_values(path)
+ count = count + list.length
+ for (i=0;i<list.length;i++) {
+ if (path) {
+ npath = path + "\\" + list[i]
+ } else {
+ npath = list[i]
+ }
+ println(npath)
+ count = count + list_path(npath)
+ }
+ return count
+
+if len(sys.argv) > 2:
+ root = sys.argv[2]
+else:
+ root = ''
+
+if options.createkey:
+ try:
+ reg.create_key("HKLM\\SOFTWARE", options.createkey)
+ except:
+ print "Failed to create key"
+else:
+ printf("Listing registry tree '%s'\n", root)
+ count = list_path(root)
+ if count == 0:
+ println("No entries found")
+ sys.exit(1)
diff --git a/source4/scripting/ejs/smbcalls_reg.c b/source4/scripting/ejs/smbcalls_reg.c
index fee11b66d9..30e5357cfb 100644
--- a/source4/scripting/ejs/smbcalls_reg.c
+++ b/source4/scripting/ejs/smbcalls_reg.c
@@ -54,7 +54,7 @@ static int ejs_apply_patchfile(MprVarHandle eid, int argc, struct MprVar **argv)
return -1;
}
- error = reg_diff_apply(mprToString(argv[0]), rctx);
+ error = reg_diff_apply(rctx, mprToString(argv[0]));
mpr_Return(eid, mprWERROR(error));
diff --git a/source4/scripting/python/misc_wrap.c b/source4/scripting/python/misc_wrap.c
index dc1203e2f0..0f36647487 100644
--- a/source4/scripting/python/misc_wrap.c
+++ b/source4/scripting/python/misc_wrap.c
@@ -2808,9 +2808,7 @@ SWIGINTERN PyObject *_wrap_random_password(PyObject *SWIGUNUSEDPARM(self), PyObj
(char *) "len", NULL
};
- {
- arg1 = NULL;
- }
+ arg1 = NULL;
if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:random_password",kwnames,&obj0)) SWIG_fail;
ecode2 = SWIG_AsVal_size_t(obj0, &val2);
if (!SWIG_IsOK(ecode2)) {
@@ -2855,11 +2853,9 @@ SWIGINTERN PyObject *_wrap_ldb_set_credentials(PyObject *SWIGUNUSEDPARM(self), P
}
arg2 = (struct cli_credentials *)(argp2);
}
- {
- if (arg1 == NULL)
- SWIG_exception(SWIG_ValueError,
- "ldb context must be non-NULL");
- }
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
ldb_set_credentials(arg1,arg2);
resultobj = SWIG_Py_Void();
return resultobj;
@@ -2893,11 +2889,9 @@ SWIGINTERN PyObject *_wrap_ldb_set_session_info(PyObject *SWIGUNUSEDPARM(self),
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_set_session_info" "', argument " "2"" of type '" "struct auth_session_info *""'");
}
arg2 = (struct auth_session_info *)(argp2);
- {
- if (arg1 == NULL)
- SWIG_exception(SWIG_ValueError,
- "ldb context must be non-NULL");
- }
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
ldb_set_session_info(arg1,arg2);
resultobj = SWIG_Py_Void();
return resultobj;
@@ -2936,11 +2930,9 @@ SWIGINTERN PyObject *_wrap_ldb_set_loadparm(PyObject *SWIGUNUSEDPARM(self), PyOb
}
arg2 = (struct loadparm_context *)(argp2);
}
- {
- if (arg1 == NULL)
- SWIG_exception(SWIG_ValueError,
- "ldb context must be non-NULL");
- }
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
ldb_set_loadparm(arg1,arg2);
resultobj = SWIG_Py_Void();
return resultobj;
@@ -2975,11 +2967,9 @@ SWIGINTERN PyObject *_wrap_samdb_set_domain_sid(PyObject *SWIGUNUSEDPARM(self),
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "samdb_set_domain_sid" "', argument " "2"" of type '" "struct dom_sid const *""'");
}
arg2 = (struct dom_sid *)(argp2);
- {
- if (arg1 == NULL)
- SWIG_exception(SWIG_ValueError,
- "ldb context must be non-NULL");
- }
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
result = (bool)samdb_set_domain_sid(arg1,(struct dom_sid const *)arg2);
resultobj = SWIG_From_bool((bool)(result));
return resultobj;
@@ -3025,19 +3015,16 @@ SWIGINTERN PyObject *_wrap_dsdb_attach_schema_from_ldif_file(PyObject *SWIGUNUSE
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "dsdb_attach_schema_from_ldif_file" "', argument " "3"" of type '" "char const *""'");
}
arg3 = (char *)(buf3);
- {
- if (arg1 == NULL)
- SWIG_exception(SWIG_ValueError,
- "ldb context must be non-NULL");
- }
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
result = dsdb_attach_schema_from_ldif_file(arg1,(char const *)arg2,(char const *)arg3);
- {
- if (!W_ERROR_IS_OK(result)) {
- PyObject *obj = Py_BuildValue("(i,s)", (&result)->v, win_errstr(result));
- PyErr_SetObject(PyExc_RuntimeError, obj);
- } else if (resultobj == NULL) {
- resultobj = Py_None;
- }
+ if (!W_ERROR_IS_OK(result)) {
+ PyObject *obj = Py_BuildValue("(i,s)", (&result)->v, win_errstr(result));
+ PyErr_SetObject(PyExc_RuntimeError, obj);
+ SWIG_fail;
+ } else if (resultobj == NULL) {
+ resultobj = Py_None;
}
if (alloc2 == SWIG_NEWOBJ) free((char*)buf2);
if (alloc3 == SWIG_NEWOBJ) free((char*)buf3);
@@ -3079,11 +3066,9 @@ SWIGINTERN PyObject *_wrap_dsdb_set_global_schema(PyObject *SWIGUNUSEDPARM(self)
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "dsdb_set_global_schema" "', argument " "1"" of type '" "struct ldb_context *""'");
}
arg1 = (struct ldb_context *)(argp1);
- {
- if (arg1 == NULL)
- SWIG_exception(SWIG_ValueError,
- "ldb context must be non-NULL");
- }
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
result = (int)dsdb_set_global_schema(arg1);
resultobj = SWIG_From_int((int)(result));
return resultobj;
@@ -3109,11 +3094,9 @@ SWIGINTERN PyObject *_wrap_ldb_register_samba_handlers(PyObject *SWIGUNUSEDPARM(
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_register_samba_handlers" "', argument " "1"" of type '" "struct ldb_context *""'");
}
arg1 = (struct ldb_context *)(argp1);
- {
- if (arg1 == NULL)
- SWIG_exception(SWIG_ValueError,
- "ldb context must be non-NULL");
- }
+ if (arg1 == NULL)
+ SWIG_exception(SWIG_ValueError,
+ "ldb context must be non-NULL");
result = (int)ldb_register_samba_handlers(arg1);
resultobj = SWIG_From_int((int)(result));
return resultobj;
diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py
index c735361353..5b34534133 100644
--- a/source4/scripting/python/samba/__init__.py
+++ b/source4/scripting/python/samba/__init__.py
@@ -91,7 +91,14 @@ class Ldb(ldb.Ldb):
def searchone(self, basedn, attribute, expression=None,
scope=ldb.SCOPE_BASE):
- """Search for one attribute as a string."""
+ """Search for one attribute as a string.
+
+ :param basedn: BaseDN for the search.
+ :param attribute: Name of the attribute
+ :param expression: Optional search expression.
+ :param scope: Search scope (defaults to base).
+ :return: Value of attribute as a string or None if it wasn't found.
+ """
res = self.search(basedn, scope, expression, [attribute])
if len(res) != 1 or res[0][attribute] is None:
return None
@@ -100,7 +107,7 @@ class Ldb(ldb.Ldb):
return values.pop()
def erase(self):
- """Erase an ldb, removing all records."""
+ """Erase this ldb, removing all records."""
# delete the specials
for attr in ["@INDEXLIST", "@ATTRIBUTES", "@SUBCLASSES", "@MODULES",
"@OPTIONS", "@PARTITION", "@KLUDGEACL"]:
@@ -149,13 +156,18 @@ class Ldb(ldb.Ldb):
:param ldif_path: Path to LDIF file.
"""
- self.load_ldif_add(open(ldif_path, 'r').read())
+ self.add_ldif(open(ldif_path, 'r').read())
- def load_ldif_add(self, ldif):
+ def add_ldif(self, ldif):
for changetype, msg in self.parse_ldif(ldif):
assert changetype == ldb.CHANGETYPE_NONE
self.add(msg)
+ def modify_ldif(self, ldif):
+ for (changetype, msg) in ldb.parse_ldif(data):
+ assert changetype == CHANGETYPE_MODIFY
+ ldb.modify(msg)
+
def substitute_var(text, values):
"""substitute strings of the form ${NAME} in str, replacing
diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py
index dcf567954a..a4e6c6a214 100644
--- a/source4/scripting/python/samba/provision.py
+++ b/source4/scripting/python/samba/provision.py
@@ -111,9 +111,7 @@ def setup_modify_ldif(ldb, ldif_path, substvars=None):
assert "${" not in data
- for (changetype, msg) in ldb.parse_ldif(data):
- assert changetype == CHANGETYPE_MODIFY
- ldb.modify(msg)
+ ldb.modify_ldif(data)
def setup_ldb(ldb, ldif_path, subst_vars):
diff --git a/source4/scripting/python/samba/samba3.py b/source4/scripting/python/samba/samba3.py
new file mode 100644
index 0000000000..d8289ae756
--- /dev/null
+++ b/source4/scripting/python/samba/samba3.py
@@ -0,0 +1,224 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# 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/>.
+#
+
+"""Support for reading Samba 3 data files."""
+
+REGISTRY_VALUE_PREFIX = "SAMBA_REGVAL"
+REGISTRY_DB_VERSION = 1
+
+import tdb
+
+class Registry:
+ """Simple read-only support for reading the Samba3 registry."""
+ def __init__(self, file):
+ self.tdb = tdb.Tdb(file)
+
+ def __len__(self):
+ """Return the number of keys."""
+ return len(self.keys())
+
+ def keys(self):
+ """Return list with all the keys."""
+ return [k.rstrip("\x00") for k in self.tdb.keys() if not k.startswith(REGISTRY_VALUE_PREFIX)]
+
+ def subkeys(self, key):
+ data = self.tdb.get(key)
+ if data is None:
+ return []
+ # FIXME: Parse data
+ return []
+
+ def values(self, key):
+ """Return a dictionary with the values set for a specific key."""
+ data = self.tdb.get("%s/%s" % (REGISTRY_VALUE_PREFIX, key))
+ if data is None:
+ return {}
+ # FIXME: Parse data
+ return {}
+
+
+class PolicyDatabase:
+ def __init__(self, file):
+ self.tdb = tdb.Tdb(file)
+ self.min_password_length = tdb.fetch_uint32("min password length")
+ self.user_must_logon_to_change_password = tdb.fetch_uint32("password history")
+ self.user_must_logon_to_change_password = tdb.fetch_uint32("user must logon to change pasword")
+ self.maximum_password_age = tdb.fetch_uint32("maximum password age")
+ self.minimum_password_age = tdb.fetch_uint32("minimum password age")
+ self.lockout_duration = tdb.fetch_uint32("lockout duration")
+ self.reset_count_minutes = tdb.fetch_uint32("reset count minutes")
+ self.bad_lockout_minutes = tdb.fetch_uint32("bad lockout minutes")
+ self.disconnect_time = tdb.fetch_uint32("disconnect time")
+ self.refuse_machine_password_change = tdb.fetch_uint32("refuse machine password change")
+
+ # FIXME: Read privileges as well
+
+
+GROUPDB_DATABASE_VERSION_V1 = 1 # native byte format.
+GROUPDB_DATABASE_VERSION_V2 = 2 # le format.
+
+GROUP_PREFIX = "UNIXGROUP/"
+
+# Alias memberships are stored reverse, as memberships. The performance
+# critical operation is to determine the aliases a SID is member of, not
+# listing alias members. So we store a list of alias SIDs a SID is member of
+# hanging of the member as key.
+MEMBEROF_PREFIX = "MEMBEROF/"
+
+class GroupMappingDatabase:
+ def __init__(self, file):
+ self.tdb = tdb.Tdb(file)
+
+
+# High water mark keys
+HWM_GROUP = "GROUP HWM"
+HWM_USER = "USER HWM"
+
+# idmap version determines auto-conversion
+IDMAP_VERSION = 2
+
+class IdmapDatabase:
+ def __init__(self, file):
+ self.tdb = tdb.Tdb(file)
+ assert self.tdb.fetch_int32("IDMAP_VERSION") == IDMAP_VERSION
+
+
+class SecretsDatabase:
+ def __init__(self, file):
+ self.tdb = tdb.Tdb(file)
+ self.domains = {}
+ for k, v in self.tdb.items():
+ if k == "SECRETS/AUTH_PASSWORD":
+ self.auth_password = v
+ elif k == "SECRETS/AUTH_DOMAIN":
+ self.auth_domain = v
+ elif k == "SECRETS/AUTH_USER":
+ self.auth_user = v
+ elif k.startswith("SECRETS/SID/"):
+ pass # FIXME
+ elif k.startswith("SECRETS/DOMGUID/"):
+ pass # FIXME
+ elif k.startswith("SECRETS/LDAP_BIND_PW/"):
+ pass # FIXME
+ elif k.startswith("SECRETS/AFS_KEYFILE/"):
+ pass # FIXME
+ elif k.startswith("SECRETS/MACHINE_SEC_CHANNEL_TYPE/"):
+ pass # FIXME
+ elif k.startswith("SECRETS/MACHINE_LAST_CHANGE_TIME/"):
+ pass # FIXME
+ elif k.startswith("SECRETS/MACHINE_PASSWORD/"):
+ pass # FIXME
+ elif k.startswith("SECRETS/$MACHINE.ACC/"):
+ pass # FIXME
+ elif k.startswith("SECRETS/$DOMTRUST.ACC/"):
+ pass # FIXME
+ elif k == "INFO/random_seed":
+ self.random_seed = v
+ else:
+ raise "Unknown key %s in secrets database" % k
+
+SHARE_DATABASE_VERSION_V1 = 1
+SHARE_DATABASE_VERSION_V2 = 2
+
+class ShareInfoDatabase:
+ def __init__(self, file):
+ self.tdb = tdb.Tdb(file)
+ assert self.tdb.fetch_int32("INFO/version") in (SHARE_DATABASE_VERSION_V1, SHARE_DATABASE_VERSION_V2)
+
+ def get_secdesc(self, name):
+ secdesc = self.tdb.get("SECDESC/%s" % name)
+ # FIXME: Run ndr_pull_security_descriptor
+
+
+ACB_DISABLED = 0x00000001
+ACB_HOMDIRREQ = 0x00000002
+ACB_PWNOTREQ = 0x00000004
+ACB_TEMPDUP = 0x00000008
+ACB_NORMAL = 0x00000010
+ACB_MNS = 0x00000020
+ACB_DOMTRUST = 0x00000040
+ACB_WSTRUST = 0x00000080
+ACB_SVRTRUST = 0x00000100
+ACB_PWNOEXP = 0x00000200
+ACB_AUTOLOCK = 0x00000400
+ACB_ENC_TXT_PWD_ALLOWED = 0x00000800
+ACB_SMARTCARD_REQUIRED = 0x00001000
+ACB_TRUSTED_FOR_DELEGATION = 0x00002000
+ACB_NOT_DELEGATED = 0x00004000
+ACB_USE_DES_KEY_ONLY = 0x00008000
+ACB_DONT_REQUIRE_PREAUTH = 0x00010000
+ACB_PW_EXPIRED = 0x00020000
+ACB_NO_AUTH_DATA_REQD = 0x00080000
+
+acb_info_mapping = {
+ 'N': ACB_PWNOTREQ, # 'N'o password.
+ 'D': ACB_DISABLED, # 'D'isabled.
+ 'H': ACB_HOMDIRREQ, # 'H'omedir required.
+ 'T': ACB_TEMPDUP, # 'T'emp account.
+ 'U': ACB_NORMAL, # 'U'ser account (normal).
+ 'M': ACB_MNS, # 'M'NS logon user account. What is this ?
+ 'W': ACB_WSTRUST, # 'W'orkstation account.
+ 'S': ACB_SVRTRUST, # 'S'erver account.
+ 'L': ACB_AUTOLOCK, # 'L'ocked account.
+ 'X': ACB_PWNOEXP, # No 'X'piry on password
+ 'I': ACB_DOMTRUST, # 'I'nterdomain trust account.
+ ' ': 0
+ }
+
+
+class Smbpasswd:
+ def __init__(self, file):
+ pass
+
+
+class TdbSam:
+ def __init__(self, file):
+ self.tdb = tdb.Tdb(file)
+
+
+class WinsDatabase:
+ def __init__(self, file):
+ pass
+
+
+class Samba3:
+ def __init__(self, smbconfpath, libdir):
+ self.smbconfpath = smbconfpath
+ self.libdir = libdir
+
+ def get_policy_db(self):
+ return PolicyDatabase(os.path.join(libdir, "account_policy.tdb"))
+
+ def get_registry(self):
+ return Registry(os.path.join(libdir, "registry.tdb"))
+
+ def get_secrets_db(self):
+ return SecretsDatabase(os.path.join(libdir, "secrets.tdb"))
+
+ def get_shares_db(self):
+ return ShareInfoDatabase(os.path.join(libdir, "share_info.tdb"))
+
+ def get_idmap_db(self):
+ return IdmapDatabase(os.path.join(libdir, "winbindd_idmap.tdb"))
+
+ def get_wins_db(self):
+ return WinsDatabase(os.path.join(libdir, "wins.dat"))
+
+ def get_groupmapping_db(self):
+ return GroupMappingDatabase(os.path.join(libdir, "group_mapping.tdb"))
diff --git a/source4/scripting/python/samba/tests/__init__.py b/source4/scripting/python/samba/tests/__init__.py
index e213c1cc1f..b01807c02f 100644
--- a/source4/scripting/python/samba/tests/__init__.py
+++ b/source4/scripting/python/samba/tests/__init__.py
@@ -43,6 +43,7 @@ class TestCaseInTempDir(unittest.TestCase):
def tearDown(self):
super(TestCaseInTempDir, self).tearDown()
+ # FIXME: Remove all files in self.tempdir
class SubstituteVarTestCase(unittest.TestCase):
diff --git a/source4/scripting/python/samba/tests/samba3.py b/source4/scripting/python/samba/tests/samba3.py
new file mode 100644
index 0000000000..c6b6281c60
--- /dev/null
+++ b/source4/scripting/python/samba/tests/samba3.py
@@ -0,0 +1,57 @@
+#!/usr/bin/python
+
+# Unix SMB/CIFS implementation.
+# 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/>.
+#
+
+import unittest
+from samba.samba3 import GroupMappingDatabase, Registry, PolicyDatabase
+import os
+
+DATADIR=os.path.join(os.path.dirname(__file__), "../../../../../testdata/samba3")
+
+class RegistryTestCase(unittest.TestCase):
+ def setUp(self):
+ self.registry = Registry(os.path.join(DATADIR, "registry.tdb"))
+
+ def test_length(self):
+ self.assertEquals(28, len(self.registry))
+
+ def test_keys(self):
+ self.assertEquals([], self.registry.keys())
+
+
+class PolicyTestCase(unittest.TestCase):
+ def setUp(self):
+ self.policy = PolicyDatabase(os.path.join(DATADIR, "account_policy.tdb"))
+
+ def test_policy(self):
+ self.assertEquals(self.policy.min_password_length, 5)
+ self.assertEquals(self.policy.minimum_password_age, 0)
+ self.assertEquals(self.policy.maximum_password_age, 999999999)
+ self.assertEquals(self.policy.refuse_machine_password_change, 0)
+ self.assertEquals(self.policy.reset_count_minutes, 0)
+ self.assertEquals(self.policy.disconnect_time, -1)
+ self.assertEquals(self.policy.user_must_logon_to_change_password, 0)
+ self.assertEquals(self.policy.password_history, 0)
+ self.assertEquals(self.policy.lockout_duration, 0)
+ self.assertEquals(self.policy.bad_lockout_minutes, 0)
+
+
+class GroupsTestCase(unittest.TestCase):
+ def setUp(self):
+ self.groupdb = GroupMappingDatabase(os.path.join(DATADIR, "group_mapping.tdb"))
+
diff --git a/source4/scripting/python/samba/upgrade.py b/source4/scripting/python/samba/upgrade.py
index 1c27f8ec25..3168fedf2d 100644
--- a/source4/scripting/python/samba/upgrade.py
+++ b/source4/scripting/python/samba/upgrade.py
@@ -7,7 +7,7 @@
"""Support code for upgrading from Samba 3 to Samba 4."""
-from provision import findnss
+from provision import findnss, provision
import provision
import grp
import pwd
@@ -69,7 +69,7 @@ data:: %s""" % (keydn, rv.name, rv.name, rv.type, ldb.encode(rv.data))
return ldif
-def upgrade_sam_policy(samba3,dn):
+def upgrade_sam_policy(policy,dn):
ldif = """
dn: %s
changetype: modify
@@ -84,11 +84,11 @@ samba3UserMustLogonToChangePassword: %d
samba3BadLockoutMinutes: %d
samba3DisconnectTime: %d
-""" % (dn, samba3.policy.min_password_length,
- samba3.policy.password_history, samba3.policy.minimum_password_age,
- samba3.policy.maximum_password_age, samba3.policy.lockout_duration,
- samba3.policy.reset_count_minutes, samba3.policy.user_must_logon_to_change_password,
- samba3.policy.bad_lockout_minutes, samba3.policy.disconnect_time)
+""" % (dn, policy.min_password_length,
+ policy.password_history, policy.minimum_password_age,
+ policy.maximum_password_age, policy.lockout_duration,
+ policy.reset_count_minutes, policy.user_must_logon_to_change_password,
+ policy.bad_lockout_minutes, policy.disconnect_time)
return ldif
@@ -465,7 +465,7 @@ replace: type
type: 4
replace: data
data: %d
-""" % samba3.policy.refuse_machine_password_change)
+""" % policy.refuse_machine_password_change)
message("Importing users")
for account in samba3.samaccounts: