diff options
Diffstat (limited to 'source4/scripting')
-rwxr-xr-x | source4/scripting/bin/samba3dump | 387 | ||||
-rw-r--r-- | source4/scripting/bin/winreg.py | 93 | ||||
-rw-r--r-- | source4/scripting/ejs/smbcalls_reg.c | 2 | ||||
-rw-r--r-- | source4/scripting/python/misc_wrap.c | 73 | ||||
-rw-r--r-- | source4/scripting/python/samba/__init__.py | 20 | ||||
-rw-r--r-- | source4/scripting/python/samba/provision.py | 4 | ||||
-rw-r--r-- | source4/scripting/python/samba/samba3.py | 224 | ||||
-rw-r--r-- | source4/scripting/python/samba/tests/__init__.py | 1 | ||||
-rw-r--r-- | source4/scripting/python/samba/tests/samba3.py | 57 | ||||
-rw-r--r-- | source4/scripting/python/samba/upgrade.py | 16 |
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: |