diff options
Diffstat (limited to 'source4/scripting')
19 files changed, 727 insertions, 574 deletions
diff --git a/source4/scripting/bin/minschema.py b/source4/scripting/bin/minschema.py new file mode 100755 index 0000000000..fb9d7b05aa --- /dev/null +++ b/source4/scripting/bin/minschema.py @@ -0,0 +1,579 @@ +#!/usr/bin/python +# +# work out the minimal schema for a set of objectclasses +# + +import optparse +import samba +from samba import getopt as options +import sys + +parser = optparse.OptionParser("minschema <URL> <classfile>") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +parser.add_option_group(options.VersionOptions(parser)) +parser.add_option("--verbose", help="Be verbose", action="store_true") +parser.add_option("--dump-classes", action="store_true") +parser.add_option("--dump-attributes", action="store_true") +parser.add_option("--dump-subschema", action="store_true") +parser.add_option("--dump-subschema-auto", action="store_true") + +opts, args = parser.parse_args() +opts.dump_all = True + +if opts.dump_classes: + opts.dump_all = False +if opts.dump_attributes: + opts.dump_all = False +if opts.dump_subschema: + opts.dump_all = False +if opts.dump_subschema_auto: + opts.dump_all = False + opts.dump_subschema = True +if opts.dump_all: + opts.dump_classes = True + opts.dump_attributes = True + opts.dump_subschema = True + opts.dump_subschema_auto = True + +if len(args) != 2: + parser.print_usage() + sys.exit(1) + +(url, classfile) = args + +creds = credopts.get_credentials() +ldb = Ldb(url, credentials=creds) + +objectclasses = [] +attributes = [] + +objectclasses_expanded = set() + +# the attributes we need for objectclasses +class_attrs = ["objectClass", + "subClassOf", + "governsID", + "possSuperiors", + "possibleInferiors", + "mayContain", + "mustContain", + "auxiliaryClass", + "rDNAttID", + "showInAdvancedViewOnly", + "adminDisplayName", + "adminDescription", + "objectClassCategory", + "lDAPDisplayName", + "schemaIDGUID", + "systemOnly", + "systemPossSuperiors", + "systemMayContain", + "systemMustContain", + "systemAuxiliaryClass", + "defaultSecurityDescriptor", + "systemFlags", + "defaultHidingValue", + "objectCategory", + "defaultObjectCategory", + + # this attributes are not used by w2k3 + "schemaFlagsEx", + "msDs-IntId", + "msDs-Schema-Extensions", + "classDisplayName", + "isDefunct"] + +attrib_attrs = ["objectClass", + "attributeID", + "attributeSyntax", + "isSingleValued", + "rangeLower", + "rangeUpper", + "mAPIID", + "linkID", + "showInAdvancedViewOnly", + "adminDisplayName", + "oMObjectClass", + "adminDescription", + "oMSyntax", + "searchFlags", + "extendedCharsAllowed", + "lDAPDisplayName", + "schemaIDGUID", + "attributeSecurityGUID", + "systemOnly", + "systemFlags", + "isMemberOfPartialAttributeSet", + "objectCategory", + + # this attributes are not used by w2k3 + "schemaFlagsEx", + "msDs-IntId", + "msDs-Schema-Extensions", + "classDisplayName", + "isEphemeral", + "isDefunct"] + +# +# notes: +# +# objectClassCategory +# 1: structural +# 2: abstract +# 3: auxiliary + +# +# print only if verbose is set +# +def dprintf(text): + if verbose is not None: + print text + +def get_object_cn(ldb, name): + attrs = ["cn"] + + res = ldb.search("(ldapDisplayName=%s)" % name, rootDse["schemaNamingContext"], ldb.SCOPE_SUBTREE, attrs) + assert len(res) == 1 + + return res[0]["cn"] + +class Objectclass: + def __init__(self, ldb, name): + """create an objectclass object""" + self.name = name + self.cn = get_object_cn(ldb, name) + + +class Attribute: + def __init__(self, ldb, name): + """create an attribute object""" + self.name = name + self.cn = get_object_cn(ldb, name) + + +syntaxmap = dict() + +syntaxmap['2.5.5.1'] = '1.3.6.1.4.1.1466.115.121.1.12' +syntaxmap['2.5.5.2'] = '1.3.6.1.4.1.1466.115.121.1.38' +syntaxmap['2.5.5.3'] = '1.2.840.113556.1.4.1362' +syntaxmap['2.5.5.4'] = '1.2.840.113556.1.4.905' +syntaxmap['2.5.5.5'] = '1.3.6.1.4.1.1466.115.121.1.26' +syntaxmap['2.5.5.6'] = '1.3.6.1.4.1.1466.115.121.1.36' +syntaxmap['2.5.5.7'] = '1.2.840.113556.1.4.903' +syntaxmap['2.5.5.8'] = '1.3.6.1.4.1.1466.115.121.1.7' +syntaxmap['2.5.5.9'] = '1.3.6.1.4.1.1466.115.121.1.27' +syntaxmap['2.5.5.10'] = '1.3.6.1.4.1.1466.115.121.1.40' +syntaxmap['2.5.5.11'] = '1.3.6.1.4.1.1466.115.121.1.24' +syntaxmap['2.5.5.12'] = '1.3.6.1.4.1.1466.115.121.1.15' +syntaxmap['2.5.5.13'] = '1.3.6.1.4.1.1466.115.121.1.43' +syntaxmap['2.5.5.14'] = '1.2.840.113556.1.4.904' +syntaxmap['2.5.5.15'] = '1.2.840.113556.1.4.907' +syntaxmap['2.5.5.16'] = '1.2.840.113556.1.4.906' +syntaxmap['2.5.5.17'] = '1.3.6.1.4.1.1466.115.121.1.40' + + +def map_attribute_syntax(s): + """map some attribute syntaxes from some apparently MS specific + syntaxes to the standard syntaxes""" + if syntaxmap.has_key(s): + return syntaxmap[s] + return s + + +def fix_dn(dn): + """fix a string DN to use ${SCHEMADN}""" + return dn.replace(rootDse["schemaNamingContext"], "${SCHEMADN}") + + +def write_ldif_one(o, attrs): + """dump an object as ldif""" + print "dn: CN=%s,${SCHEMADN}\n" % o["cn"] + for a in attrs: + if not o.has_key(a): + continue + # special case for oMObjectClass, which is a binary object + if a == "oMObjectClass": + print "%s:: %s\n" % (a, o[a]) + continue + v = o[a] + if isinstance(v, str): + v = [v] + for j in v: + print "%s: %s\n" % (a, fix_dn(j)) + print "\n" + +def write_ldif(o, attrs): + """dump an array of objects as ldif""" + for i in o: + write_ldif_one(i, attrs) + + +def create_testdn(exampleDN): + """create a testDN based an an example DN + the idea is to ensure we obey any structural rules""" + a = exampleDN.split(",") + a[0] = "CN=TestDN" + return ",".join(a) + + +def find_objectclass_properties(ldb, o): + """the properties of an objectclass""" + res = ldb.search( + expression="(ldapDisplayName=%s)" % o.name, + basedn=rootDse["schemaNamingContext"], scope=ldb.SCOPE_SUBTREE, attrs=class_attrs) + assert(len(res) == 1) + msg = res[0] + for a in msg: + o[a] = msg[a] + +def find_attribute_properties(ldb, o): + """find the properties of an attribute""" + res = ldb.search( + expression="(ldapDisplayName=%s)" % o.name, + basedn=rootDse["schemaNamingContext"], scope=ldb.SCOPE_SUBTREE, + attrs=attrib_attrs) + assert(len(res) == 1) + msg = res[0] + for a in msg: + # special case for oMObjectClass, which is a binary object + if a == "oMObjectClass": + o[a] = ldb.encode(msg[a]) + continue + o[a] = msg[a] + + +def find_objectclass_auto(ldb, o): + """find the auto-created properties of an objectclass. Only works for + classes that can be created using just a DN and the objectclass""" + if not o.has_key("exampleDN"): + return + testdn = create_testdn(o.exampleDN) + + print "testdn is '%s'\n" % testdn + + ldif = "dn: " + testdn + ldif += "\nobjectClass: " + o.name + try: + ldb.add(ldif) + except LdbError, e: + print "error adding %s: %s\n" % (o.name, e) + print "%s\n" % ldif + return + + res = ldb.search("", testdn, ldb.SCOPE_BASE) + ldb.delete(testdn) + + for a in res.msgs[0]: + attributes[a].autocreate = True + + +def expand_objectclass(ldb, o): + """look at auxiliary information from a class to intuit the existance of + more classes needed for a minimal schema""" + attrs = ["auxiliaryClass", "systemAuxiliaryClass", + "possSuperiors", "systemPossSuperiors", + "subClassOf"] + res = ldb.search( + expression="(&(objectClass=classSchema)(ldapDisplayName=%s))" % o.name, + basedn=rootDse["schemaNamingContext"], scope=ldb.SCOPE_SUBTREE, + attrs=attrs) + print "Expanding class %s\n" % o.name + assert(len(res) == 1) + msg = res[0] + for a in attrs: + if not msg.has_key(aname): + continue + list = msg[aname] + if isinstance(list, str): + list = [msg[aname]] + for name in list: + if not objectclasses.has_key(name): + print "Found new objectclass '%s'\n" % name + objectclasses[name] = Objectclass(ldb, name) + + +def add_objectclass_attributes(ldb, objectclass): + """add the must and may attributes from an objectclass to the full list + of attributes""" + attrs = ["mustContain", "systemMustContain", + "mayContain", "systemMayContain"] + for aname in attrs: + if not objectclass.has_key(aname): + continue + alist = objectclass[aname] + if isinstance(alist, str): + alist = [alist] + for a in alist: + if not attributes.has_key(a): + attributes[a] = Attribute(ldb, a) + + +def walk_dn(ldb, dn): + """process an individual record, working out what attributes it has""" + # get a list of all possible attributes for this object + attrs = ["allowedAttributes"] + try: + res = ldb.search("objectClass=*", dn, ldb.SCOPE_BASE, attrs) + except LdbError, e: + print "Unable to fetch allowedAttributes for '%s' - %r\n" % (dn, e) + return + allattrs = res[0]["allowedAttributes"] + try: + res = ldb.search("objectClass=*", dn, ldb.SCOPE_BASE, allattrs) + except LdbError, e: + print "Unable to fetch all attributes for '%s' - %s\n" % (dn, e) + return + msg = res[0] + for a in msg: + if not attributes.has_key(a): + attributes[a] = Attribute(ldb, a) + +def walk_naming_context(ldb, namingContext): + """walk a naming context, looking for all records""" + try: + res = ldb.search("objectClass=*", namingContext, ldb.SCOPE_DEFAULT, + ["objectClass"]) + except LdbError, e: + print "Unable to fetch objectClasses for '%s' - %s\n" % (namingContext, e) + return + for msg in res: + msg = res.msgs[r]["objectClass"] + for objectClass in msg: + if not objectclasses.has_key(objectClass): + objectclasses[objectClass] = Objectclass(ldb, objectClass) + objectclasses[objectClass].exampleDN = res.msgs[r]["dn"] + walk_dn(ldb, res.msgs[r].dn) + +def trim_objectclass_attributes(ldb, objectclass): + """trim the may attributes for an objectClass""" + # trim possibleInferiors, + # include only the classes we extracted + if objectclass.has_key("possibleInferiors"): + possinf = objectclass["possibleInferiors"] + newpossinf = [] + if isinstance(possinf, str): + possinf = [possinf] + for x in possinf: + if objectclasses.has_key(x): + newpossinf[n] = x + n+=1 + objectclass["possibleInferiors"] = newpossinf + + # trim systemMayContain, + # remove duplicates + if objectclass.has_key("systemMayContain"): + sysmay = objectclass["systemMayContain"] + newsysmay = [] + if isinstance(sysmay, str): + sysmay = [sysmay] + for x in sysmay: + if not x in newsysmay: + newsysmay.append(x) + objectclass["systemMayContain"] = newsysmay + + # trim mayContain, + # remove duplicates + if not objectclass.has_key("mayContain"): + may = objectclass["mayContain"] + newmay = [] + if isinstance(may, str): + may = [may] + for x in may: + if not x in newmay: + newmay.append(x) + objectclass["mayContain"] = newmay + +def build_objectclass(ldb, name): + """load the basic attributes of an objectClass""" + attrs = ["name"] + try: + res = ldb.search( + expression="(&(objectClass=classSchema)(ldapDisplayName=%s))" % name, + basedn=rootDse["schemaNamingContext"], scope=ldb.SCOPE_SUBTREE, + attrs=attrs) + except LdbError, e: + print "unknown class '%s'\n" % name + return None + if len(res) == 0: + print "unknown class '%s'\n" % name + return None + return Objectclass(ldb, name) + +def attribute_list(objectclass, attr1, attr2): + """form a coalesced attribute list""" + a1 = objectclass[attr1] + a2 = objectclass[attr2] + if isinstance(a1, str): + a1 = [a1] + if isinstance(a2, str): + a2 = [a2] + return a1 + a2 + +def aggregate_list(name, list): + """write out a list in aggregate form""" + if list is None: + return + print "%s ( %s )" % (name, "$ ".join(list)) + +def write_aggregate_objectclass(objectclass): + """write the aggregate record for an objectclass""" + print "objectClasses: ( %s NAME '%s' " % (objectclass.governsID, objectclass.name) + if not objectclass.has_key('subClassOf'): + print "SUP %s " % objectclass['subClassOf'] + if objectclass.objectClassCategory == 1: + print "STRUCTURAL " + elif objectclass.objectClassCategory == 2: + print "ABSTRACT " + elif objectclass.objectClassCategory == 3: + print "AUXILIARY " + + list = attribute_list(objectclass, "systemMustContain", "mustContain") + aggregate_list("MUST", list) + + list = attribute_list(objectclass, "systemMayContain", "mayContain") + aggregate_list("MAY", list) + + print ")\n" + + +def write_aggregate_ditcontentrule(objectclass): + """write the aggregate record for an ditcontentrule""" + list = attribute_list(objectclass, "auxiliaryClass", "systemAuxiliaryClass") + if list is None: + return + + print "dITContentRules: ( %s NAME '%s' " % (objectclass.governsID, objectclass.name) + + aggregate_list("AUX", list) + + may_list = None + must_list = None + + for c in list: + list2 = attribute_list(objectclasses[c], + "mayContain", "systemMayContain") + may_list = may_list + list2 + list2 = attribute_list(objectclasses[c], + "mustContain", "systemMustContain") + must_list = must_list + list2 + + aggregate_list("MUST", must_list) + aggregate_list("MAY", may_list) + + print ")\n" + +def write_aggregate_attribute(attrib): + """write the aggregate record for an attribute""" + print "attributeTypes: ( %s NAME '%s' SYNTAX '%s' " % ( + attrib.attributeID, attrib.name, + map_attribute_syntax(attrib.attributeSyntax)) + if attrib['isSingleValued'] == "TRUE": + print "SINGLE-VALUE " + if attrib['systemOnly'] == "TRUE": + print "NO-USER-MODIFICATION " + + print ")\n" + + +def write_aggregate(): + """write the aggregate record""" + print "dn: CN=Aggregate,${SCHEMADN}\n" + print """objectClass: top +objectClass: subSchema +objectCategory: CN=SubSchema,${SCHEMADN} +""" + if not opts.dump_subschema_auto: + return + + for objectclass in objectclasses: + write_aggregate_objectclass(objectclass) + for attr in attributes: + write_aggregate_attribute(attr) + for objectclass in objectclasses: + write_aggregate_ditcontentrule(objectclass) + +def load_list(file): + """load a list from a file""" + return open(file, 'r').splitlines() + +# get the rootDSE +res = ldb.search("", "", ldb.SCOPE_BASE) +rootDse = res[0] + +# load the list of classes we are interested in +classes = load_list(classfile) +for classname in classes: + objectclass = build_objectclass(ldb, classname) + if objectclass is not None: + objectclasses[classname] = objectclass + + +# +# expand the objectclass list as needed +# +expanded = 0 + +# so EJS do not have while nor the break statement +# cannot find any other way than doing more loops +# than necessary to recursively expand all classes +# +for inf in range(500): + for n in objectclasses: + if not n in objectclasses_expanded: + expand_objectclass(ldb, objectclasses[i]) + objectclasses_expanded.add(n) + +# +# find objectclass properties +# +for objectclass in objectclasses: + find_objectclass_properties(ldb, objectclass) + + +# +# form the full list of attributes +# +for objectclass in objectclasses: + add_objectclass_attributes(ldb, objectclass) + +# and attribute properties +for attr in attributes: + find_attribute_properties(ldb, attr) + +# +# trim the 'may' attribute lists to those really needed +# +for objectclass in objectclasses: + trim_objectclass_attributes(ldb, objectclass) + +# +# dump an ldif form of the attributes and objectclasses +# +if opts.dump_attributes: + write_ldif(attributes, attrib_attrs) +if opts.dump_classes: + write_ldif(objectclasses, class_attrs) +if opts.dump_subschema: + write_aggregate() + +if not opts.verbose: + sys.exit(0) + +# +# dump list of objectclasses +# +print "objectClasses:\n" +for objectclass in objectclasses: + print "\t%s\n" % objectclass + +print "attributes:\n" +for attr in attributes: + print "\t%s\n" % attr + +print "autocreated attributes:\n" +for attr in attributes: + if attr.autocreate: + print "\t%s\n" % i diff --git a/source4/scripting/bin/subunitrun b/source4/scripting/bin/subunitrun index 7142abed85..11ac426589 100755 --- a/source4/scripting/bin/subunitrun +++ b/source4/scripting/bin/subunitrun @@ -21,6 +21,5 @@ from subunit import SubunitTestRunner import sys from unittest import TestProgram -program = TestProgram(module=None, argv=sys.argv, - testRunner=SubunitTestRunner()) -program.runTests() +runner = SubunitTestRunner() +TestProgram(module=None, argv=sys.argv, testRunner=runner) diff --git a/source4/scripting/ejs/config.mk b/source4/scripting/ejs/config.mk index 656ecdae16..c1f07367fb 100644 --- a/source4/scripting/ejs/config.mk +++ b/source4/scripting/ejs/config.mk @@ -4,13 +4,13 @@ OBJ_FILES = \ [MODULE::smbcalls_config] OBJ_FILES = smbcalls_config.o -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ SUBSYSTEM = smbcalls INIT_FUNCTION = smb_setup_ejs_config [MODULE::smbcalls_ldb] OBJ_FILES = smbcalls_ldb.o -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ SUBSYSTEM = smbcalls INIT_FUNCTION = smb_setup_ejs_ldb PRIVATE_DEPENDENCIES = LIBLDB SAMDB LIBNDR @@ -18,45 +18,38 @@ PRIVATE_DEPENDENCIES = LIBLDB SAMDB LIBNDR [MODULE::smbcalls_reg] OBJ_FILES = smbcalls_reg.o SUBSYSTEM = smbcalls -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ INIT_FUNCTION = smb_setup_ejs_reg PRIVATE_DEPENDENCIES = registry SAMDB LIBNDR [MODULE::smbcalls_nbt] OBJ_FILES = smbcalls_nbt.o SUBSYSTEM = smbcalls -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ INIT_FUNCTION = smb_setup_ejs_nbt -[MODULE::smbcalls_samba3] -OBJ_FILES = smbcalls_samba3.o -SUBSYSTEM = smbcalls -OUTPUT_TYPE = INTEGRATED -INIT_FUNCTION = smb_setup_ejs_samba3 -PRIVATE_DEPENDENCIES = LIBSAMBA3 - [MODULE::smbcalls_rand] OBJ_FILES = smbcalls_rand.o SUBSYSTEM = smbcalls -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ INIT_FUNCTION = smb_setup_ejs_random [MODULE::smbcalls_nss] OBJ_FILES = smbcalls_nss.o SUBSYSTEM = smbcalls -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ INIT_FUNCTION = smb_setup_ejs_nss PRIVATE_DEPENDENCIES = NSS_WRAPPER [MODULE::smbcalls_data] OBJ_FILES = smbcalls_data.o SUBSYSTEM = smbcalls -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ INIT_FUNCTION = smb_setup_ejs_datablob [MODULE::smbcalls_auth] OBJ_FILES = smbcalls_auth.o -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ SUBSYSTEM = smbcalls INIT_FUNCTION = smb_setup_ejs_auth PRIVATE_DEPENDENCIES = auth @@ -64,16 +57,16 @@ PRIVATE_DEPENDENCIES = auth [MODULE::smbcalls_string] OBJ_FILES = smbcalls_string.o SUBSYSTEM = smbcalls -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ INIT_FUNCTION = smb_setup_ejs_string [MODULE::smbcalls_sys] OBJ_FILES = smbcalls_sys.o SUBSYSTEM = smbcalls -OUTPUT_TYPE = INTEGRATED +OUTPUT_TYPE = MERGED_OBJ INIT_FUNCTION = smb_setup_ejs_system -include ejsnet/config.mk +mkinclude ejsnet/config.mk [SUBSYSTEM::smbcalls] PRIVATE_PROTO_HEADER = proto.h diff --git a/source4/scripting/ejs/smbcalls_samba3.c b/source4/scripting/ejs/smbcalls_samba3.c deleted file mode 100644 index 36ec2a54e4..0000000000 --- a/source4/scripting/ejs/smbcalls_samba3.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - provide hooks into smbd C calls from ejs scripts - - Copyright (C) Jelmer Vernooij 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 "includes.h" -#include "scripting/ejs/smbcalls.h" -#include "lib/appweb/ejs/ejs.h" -#include "lib/samba3/samba3.h" -#include "libcli/security/security.h" -#include "librpc/gen_ndr/ndr_misc.h" -#include "system/network.h" - - -static struct MprVar mprRegistry(struct samba3_regdb *reg) -{ - struct MprVar mpv = mprObject("registry"), ks, vs, k, v; - int i, j; - - ks = mprArray("array"); - - for (i = 0; i < reg->key_count; i++) { - k = mprObject("regkey"); - - mprSetVar(&k, "name", mprString(reg->keys[i].name)); - - vs = mprArray("array"); - - for (j = 0; j < reg->keys[i].value_count; j++) { - v = mprObject("regval"); - - mprSetVar(&v, "name", mprString(reg->keys[i].values[j].name)); - mprSetVar(&v, "type", mprCreateIntegerVar(reg->keys[i].values[j].type)); - mprSetVar(&v, "data", mprDataBlob(reg->keys[i].values[j].data)); - - mprAddArray(&vs, j, v); - } - - mprSetVar(&k, "values", vs); - - mprAddArray(&ks, i, k); - } - - if (i == 0) { - mprSetVar(&ks, "length", mprCreateIntegerVar(i)); - } - - mprSetVar(&mpv, "keys", ks); - - return mpv; -} - -static struct MprVar mprPolicy(struct samba3_policy *pol) -{ - struct MprVar mpv = mprObject("policy"); - - mprSetVar(&mpv, "min_password_length", mprCreateIntegerVar(pol->min_password_length)); - mprSetVar(&mpv, "password_history", mprCreateIntegerVar(pol->password_history)); - mprSetVar(&mpv, "user_must_logon_to_change_password", mprCreateIntegerVar(pol->user_must_logon_to_change_password)); - mprSetVar(&mpv, "maximum_password_age", mprCreateIntegerVar(pol->maximum_password_age)); - mprSetVar(&mpv, "minimum_password_age", mprCreateIntegerVar(pol->minimum_password_age)); - mprSetVar(&mpv, "lockout_duration", mprCreateIntegerVar(pol->lockout_duration)); - mprSetVar(&mpv, "reset_count_minutes", mprCreateIntegerVar(pol->reset_count_minutes)); - mprSetVar(&mpv, "bad_lockout_minutes", mprCreateIntegerVar(pol->bad_lockout_minutes)); - mprSetVar(&mpv, "disconnect_time", mprCreateIntegerVar(pol->disconnect_time)); - mprSetVar(&mpv, "refuse_machine_password_change", mprCreateIntegerVar(pol->refuse_machine_password_change)); - - return mpv; -} - -static struct MprVar mprIdmapDb(struct samba3_idmapdb *db) -{ - struct MprVar mpv = mprObject("idmapdb"), mps, mp; - int i; - - mprSetVar(&mpv, "user_hwm", mprCreateIntegerVar(db->user_hwm)); - mprSetVar(&mpv, "group_hwm", mprCreateIntegerVar(db->group_hwm)); - - mps = mprArray("array"); - - for (i = 0; i < db->mapping_count; i++) { - char *tmp; - mp = mprObject("idmap"); - - mprSetVar(&mp, "IDMAP_GROUP", mprCreateIntegerVar(IDMAP_GROUP)); - mprSetVar(&mp, "IDMAP_USER", mprCreateIntegerVar(IDMAP_USER)); - mprSetVar(&mp, "type", mprCreateIntegerVar(db->mappings[i].type)); - mprSetVar(&mp, "unix_id", mprCreateIntegerVar(db->mappings[i].unix_id)); - - tmp = dom_sid_string(NULL, db->mappings[i].sid); - mprSetVar(&mp, "sid", mprString(tmp)); - talloc_free(tmp); - - mprAddArray(&mps, i, mp); - } - - if (i == 0) { - mprSetVar(&mpv, "length", mprCreateIntegerVar(i)); - } - - - mprSetVar(&mpv, "mappings", mps); - - return mpv; -} - -static struct MprVar mprGroupMappings(struct samba3_groupdb *db) -{ - struct MprVar mpv = mprArray("array"), g; - int i; - - for (i = 0; i < db->groupmap_count; i++) { - char *tmp; - g = mprObject("group"); - - mprSetVar(&g, "gid", mprCreateIntegerVar(db->groupmappings[i].gid)); - - tmp = dom_sid_string(NULL, db->groupmappings[i].sid); - mprSetVar(&g, "sid", mprString(tmp)); - talloc_free(tmp); - - mprSetVar(&g, "sid_name_use", mprCreateIntegerVar(db->groupmappings[i].sid_name_use)); - mprSetVar(&g, "nt_name", mprString(db->groupmappings[i].nt_name)); - mprSetVar(&g, "comment", mprString(db->groupmappings[i].comment)); - - mprAddArray(&mpv, i, g); - } - - if (i == 0) { - mprSetVar(&mpv, "length", mprCreateIntegerVar(i)); - } - - - return mpv; -} - -static struct MprVar mprAliases(struct samba3_groupdb *db) -{ - struct MprVar mpv = mprObject("array"), a, am; - int i, j; - - for (i = 0; i < db->alias_count; i++) { - char *tmp; - a = mprObject("alias"); - - tmp = dom_sid_string(NULL, db->aliases[i].sid); - mprSetVar(&a, "sid", mprString(tmp)); - talloc_free(tmp); - - am = mprArray("array"); - - for (j = 0; j < db->aliases[i].member_count; j++) { - tmp = dom_sid_string(NULL, db->aliases[i].members[j]); - mprAddArray(&am, j, mprString(tmp)); - talloc_free(tmp); - } - - mprSetVar(&a, "members", am); - } - - if (i == 0) { - mprSetVar(&mpv, "length", mprCreateIntegerVar(i)); - } - - return mpv; -} - -static struct MprVar mprDomainSecrets(struct samba3_domainsecrets *ds) -{ - struct MprVar v, e = mprObject("domainsecrets"); - char *tmp; - DATA_BLOB blob; - - mprSetVar(&e, "name", mprString(ds->name)); - - tmp = dom_sid_string(NULL, &ds->sid); - mprSetVar(&e, "sid", mprString(tmp)); - talloc_free(tmp); - - tmp = GUID_string(NULL, &ds->guid); - mprSetVar(&e, "guid", mprString(tmp)); - talloc_free(tmp); - - mprSetVar(&e, "plaintext_pw", mprString(ds->plaintext_pw)); - - mprSetVar(&e, "last_change_time", mprCreateIntegerVar(ds->last_change_time)); - mprSetVar(&e, "sec_channel_type", mprCreateIntegerVar(ds->sec_channel_type)); - - v = mprObject("hash_pw"); - - blob.data = ds->hash_pw.hash; - blob.length = 16; - mprSetVar(&v, "hash", mprDataBlob(blob)); - - mprSetVar(&v, "mod_time", mprCreateIntegerVar(ds->hash_pw.mod_time)); - - mprSetVar(&e, "hash_pw", v); - - return e; -} - -static struct MprVar mprSecrets(struct samba3_secrets *sec) -{ - struct MprVar mpv = mprObject("samba3_secrets"), es, e; - int i; - - es = mprArray("array"); - - for (i = 0; i < sec->ldappw_count; i++) { - e = mprObject("ldappw"); - - mprSetVar(&e, "dn", mprString(sec->ldappws[i].dn)); - mprSetVar(&e, "password", mprString(sec->ldappws[i].password)); - - mprAddArray(&es, i, e); - } - - mprSetVar(&mpv, "ldappws", es); - - es = mprArray("array"); - - for (i = 0; i < sec->domain_count; i++) { - mprAddArray(&es, i, mprDomainSecrets(&sec->domains[i])); - } - - if (i == 0) { - mprSetVar(&es, "length", mprCreateIntegerVar(i)); - } - - mprSetVar(&mpv, "domains", es); - - es = mprArray("trusted_domains"); - - for (i = 0; i < sec->trusted_domain_count; i++) { - struct MprVar ns; - char *tmp; - int j; - e = mprObject("trusted_domain"); - - ns = mprArray("array"); - - for (j = 0; j < sec->trusted_domains[i].uni_name_len; j++) { - mprAddArray(&ns, j, mprString(sec->trusted_domains[i].uni_name[j])); - } - - mprSetVar(&e, "uni_name", ns); - - mprSetVar(&e, "pass", mprString(sec->trusted_domains[i].pass)); - mprSetVar(&e, "mod_time", mprCreateIntegerVar(sec->trusted_domains[i].mod_time)); - - tmp = dom_sid_string(NULL, &sec->trusted_domains[i].domain_sid); - mprSetVar(&e, "domains_sid", mprString(tmp)); - talloc_free(tmp); - - mprAddArray(&es, i, e); - } - - if (i == 0) { - mprSetVar(&es, "length", mprCreateIntegerVar(i)); - } - - mprSetVar(&mpv, "trusted_domains", es); - - es = mprArray("array"); - - for (i = 0; i < sec->afs_keyfile_count; i++) { - struct MprVar ks; - int j; - e = mprObject("afs_keyfile"); - - mprSetVar(&e, "cell", mprString(sec->afs_keyfiles[i].cell)); - - ks = mprArray("array"); - - for (j = 0; j < 8; j++) { - struct MprVar k = mprObject("entry"); - DATA_BLOB blob; - - mprSetVar(&k, "kvno", mprCreateIntegerVar(sec->afs_keyfiles[i].entry[j].kvno)); - blob.data = (uint8_t*)sec->afs_keyfiles[i].entry[j].key; - blob.length = 8; - mprSetVar(&k, "key", mprDataBlob(blob)); - - mprAddArray(&ks, j, k); - } - - mprSetVar(&e, "entry", ks); - - mprSetVar(&e, "nkeys", mprCreateIntegerVar(sec->afs_keyfiles[i].nkeys)); - - mprAddArray(&es, i, e); - } - - if (i == 0) { - mprSetVar(&es, "length", mprCreateIntegerVar(i)); - } - - mprSetVar(&mpv, "afs_keyfiles", es); - - mprSetVar(&mpv, "ipc_cred", mprCredentials(sec->ipc_cred)); - - return mpv; -} - -static struct MprVar mprShares(struct samba3 *samba3) -{ - struct MprVar mpv = mprArray("array"), s; - int i; - - for (i = 0; i < samba3->share_count; i++) { - s = mprObject("share"); - - mprSetVar(&s, "name", mprString(samba3->shares[i].name)); - - /* FIXME: secdesc */ - - mprAddArray(&mpv, i, s); - } - - if (i == 0) { - mprSetVar(&mpv, "length", mprCreateIntegerVar(i)); - } - - return mpv; -} - -static struct MprVar mprSamAccounts(struct samba3 *samba3) -{ - struct MprVar mpv = mprArray("array"), m; - int i; - - for (i = 0; i < samba3->samaccount_count; i++) { - struct samba3_samaccount *a = &samba3->samaccounts[i]; - DATA_BLOB blob; - - m = mprObject("samba3_samaccount"); - - mprSetVar(&m, "logon_time", mprCreateIntegerVar(a->logon_time)); - mprSetVar(&m, "logoff_time", mprCreateIntegerVar(a->logoff_time)); - mprSetVar(&m, "kickoff_time", mprCreateIntegerVar(a->kickoff_time)); - mprSetVar(&m, "bad_password_time", mprCreateIntegerVar(a->bad_password_time)); - mprSetVar(&m, "pass_last_set_time", mprCreateIntegerVar(a->pass_last_set_time)); - mprSetVar(&m, "pass_can_change_time", mprCreateIntegerVar(a->pass_can_change_time)); - mprSetVar(&m, "pass_must_change_time", mprCreateIntegerVar(a->pass_must_change_time)); - mprSetVar(&m, "user_rid", mprCreateIntegerVar(a->user_rid)); - mprSetVar(&m, "group_rid", mprCreateIntegerVar(a->group_rid)); - mprSetVar(&m, "acct_ctrl", mprCreateIntegerVar(a->acct_ctrl)); - mprSetVar(&m, "logon_divs", mprCreateIntegerVar(a->logon_divs)); - mprSetVar(&m, "bad_password_count", mprCreateIntegerVar(a->bad_password_count)); - mprSetVar(&m, "logon_count", mprCreateIntegerVar(a->logon_count)); - mprSetVar(&m, "username", mprString(a->username)); - mprSetVar(&m, "domain", mprString(a->domain)); - mprSetVar(&m, "nt_username", mprString(a->nt_username)); - mprSetVar(&m, "dir_drive", mprString(a->dir_drive)); - mprSetVar(&m, "munged_dial", mprString(a->munged_dial)); - mprSetVar(&m, "fullname", mprString(a->fullname)); - mprSetVar(&m, "homedir", mprString(a->homedir)); - mprSetVar(&m, "logon_script", mprString(a->logon_script)); - mprSetVar(&m, "profile_path", mprString(a->profile_path)); - mprSetVar(&m, "acct_desc", mprString(a->acct_desc)); - mprSetVar(&m, "workstations", mprString(a->workstations)); - blob.length = 16; - blob.data = a->lm_pw.hash; - mprSetVar(&m, "lm_pw", mprDataBlob(blob)); - blob.data = a->nt_pw.hash; - mprSetVar(&m, "nt_pw", mprDataBlob(blob)); - - mprAddArray(&mpv, i, m); - } - - if (i == 0) { - mprSetVar(&mpv, "length", mprCreateIntegerVar(i)); - } - - return mpv; -} - -static struct MprVar mprWinsEntries(struct samba3 *samba3) -{ - struct MprVar mpv = mprArray("array"); - int i, j; - - for (i = 0; i < samba3->winsdb_count; i++) { - struct MprVar w = mprObject("wins_entry"), ips; - - mprSetVar(&w, "name", mprString(samba3->winsdb_entries[i].name)); - mprSetVar(&w, "nb_flags", mprCreateIntegerVar(samba3->winsdb_entries[i].nb_flags)); - mprSetVar(&w, "type", mprCreateIntegerVar(samba3->winsdb_entries[i].type)); - mprSetVar(&w, "ttl", mprCreateIntegerVar(samba3->winsdb_entries[i].ttl)); - - ips = mprObject("array"); - - for (j = 0; j < samba3->winsdb_entries[i].ip_count; j++) { - const char *addr; - addr = inet_ntoa(samba3->winsdb_entries[i].ips[j]); - mprAddArray(&ips, j, mprString(addr)); - } - - mprSetVar(&w, "ips", ips); - - mprAddArray(&mpv, i, w); - } - - if (i == 0) { - mprSetVar(&mpv, "length", mprCreateIntegerVar(i)); - } - - return mpv; -} - -static int ejs_find_domainsecrets(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct samba3 *samba3 = NULL; - struct samba3_domainsecrets *sec; - - if (argc < 1) { - ejsSetErrorMsg(eid, "find_domainsecrets invalid arguments"); - return -1; - } - - samba3 = (struct samba3 *)mprGetThisPtr(eid, "samba3"); - mprAssert(samba3); - sec = samba3_find_domainsecrets(samba3, mprToString(argv[0])); - - if (sec == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - } else { - mpr_Return(eid, mprDomainSecrets(sec)); - } - - return 0; -} - -/* - initialise samba3 ejs subsystem - - samba3 = samba3_read(libdir,smbconf) -*/ -static int ejs_samba3_read(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct MprVar mpv = mprObject("samba3"); - struct samba3 *samba3; - NTSTATUS status; - - if (argc < 2) { - ejsSetErrorMsg(eid, "samba3_read invalid arguments"); - return -1; - } - - status = samba3_read(mprToString(argv[0]), mprToString(argv[1]), mprMemCtx(), &samba3); - - if (NT_STATUS_IS_ERR(status)) { - ejsSetErrorMsg(eid, "samba3_read: error"); - return -1; - } - - mprAssert(samba3); - - mprSetPtrChild(&mpv, "samba3", samba3); - mprSetVar(&mpv, "winsentries", mprWinsEntries(samba3)); - mprSetVar(&mpv, "samaccounts", mprSamAccounts(samba3)); - mprSetVar(&mpv, "shares", mprShares(samba3)); - mprSetVar(&mpv, "secrets", mprSecrets(&samba3->secrets)); - mprSetVar(&mpv, "groupmappings", mprGroupMappings(&samba3->group)); - mprSetVar(&mpv, "aliases", mprAliases(&samba3->group)); - mprSetVar(&mpv, "idmapdb", mprIdmapDb(&samba3->idmap)); - mprSetVar(&mpv, "policy", mprPolicy(&samba3->policy)); - mprSetVar(&mpv, "registry", mprRegistry(&samba3->registry)); - mprSetVar(&mpv, "configuration", mprParam(samba3->configuration)); - mprSetCFunction(&mpv, "find_domainsecrets", ejs_find_domainsecrets); - - mpr_Return(eid, mpv); - - return 0; -} - - -/* - setup C functions that be called from ejs -*/ -NTSTATUS smb_setup_ejs_samba3(void) -{ - ejsDefineCFunction(-1, "samba3_read", ejs_samba3_read, NULL, MPR_VAR_SCRIPT_HANDLE); - return NT_STATUS_OK; -} diff --git a/source4/scripting/ejs/smbscript.c b/source4/scripting/ejs/smbscript.c index a4f2e1cd43..9ed4aa490f 100644 --- a/source4/scripting/ejs/smbscript.c +++ b/source4/scripting/ejs/smbscript.c @@ -61,8 +61,6 @@ int main(int argc, const char **argv) lp_load(lp_ctx, dyn_CONFIGFILE); } - ldb_global_init(); - gensec_init(lp_ctx); mprSetCtx(mem_ctx); diff --git a/source4/scripting/libjs/provision.js b/source4/scripting/libjs/provision.js index e71498010c..dc9eae8e72 100644 --- a/source4/scripting/libjs/provision.js +++ b/source4/scripting/libjs/provision.js @@ -1124,7 +1124,7 @@ unixName: %s sambaPassword: %s objectClass: user ", - user_dn, username, dom_users, + user_dn, username, unixname, password); /* add the user to the users group as well @@ -1134,7 +1134,7 @@ dn: %s changetype: modify add: member member: %s -", +", dom_users, user_dn); diff --git a/source4/scripting/python/config.m4 b/source4/scripting/python/config.m4 index e4a34ece1e..2142cd9abd 100644 --- a/source4/scripting/python/config.m4 +++ b/source4/scripting/python/config.m4 @@ -54,7 +54,7 @@ fi if test x$PYTHON != x then - DISTUTILS_CFLAGS=`$PYTHON -c "from distutils import sysconfig; print '-I%s -I%s %s' % (sysconfig.get_python_inc(), sysconfig.get_python_inc(plat_specific=True), sysconfig.get_config_var('CFLAGS'))"` + DISTUTILS_CFLAGS=`$PYTHON -c "from distutils import sysconfig; print '-I%s -I%s %s' % (sysconfig.get_python_inc(), sysconfig.get_python_inc(plat_specific=1), sysconfig.get_config_var('CFLAGS'))"` DISTUTILS_LDFLAGS=`$PYTHON -c "from distutils import sysconfig; print '%s %s -lpython%s -L%s' % (sysconfig.get_config_var('LIBS'), sysconfig.get_config_var('SYSLIBS'), sysconfig.get_config_var('VERSION'), sysconfig.get_config_var('LIBPL'))"` TRY_LINK_PYTHON($DISTUTILS_LDFLAGS, $DISTUTILS_CFLAGS) fi @@ -66,12 +66,8 @@ if test $working_python = yes; then SMB_ENABLE(EXT_LIB_PYTHON,YES) SMB_ENABLE(smbpython,YES) SMB_ENABLE(LIBPYTHON,YES) - dnl AC_DEFINE(HAVE_WORKING_PYTHON, 1, [Whether we have working python support]) AC_MSG_RESULT([yes]) else - SMB_ENABLE(EXT_LIB_PYTHON,NO) - SMB_ENABLE(LIBPYTHONyy,NO) - SMB_ENABLE(smbpython,NO) - AC_MSG_RESULT([no]) + AC_MSG_ERROR([Python not found. Please install Python 2.x and its development headers/libraries.]) fi diff --git a/source4/scripting/python/config.mk b/source4/scripting/python/config.mk index 450da0e90a..b15e1fcda7 100644 --- a/source4/scripting/python/config.mk +++ b/source4/scripting/python/config.mk @@ -33,7 +33,7 @@ pythonmods:: $(PYTHON_DSOS) $(PYTHON_PYS) PYDOCTOR_MODULES=bin/python/ldb.py bin/python/auth.py bin/python/credentials.py bin/python/registry.py bin/python/tdb.py bin/python/security.py bin/python/events.py bin/python/net.py pydoctor:: pythonmods - LD_LIBRARY_PATH=bin/shared PYTHONPATH=bin/python pydoctor --make-html --docformat=restructuredtext --add-package scripting/python/samba/ $(addprefix --add-module , $(PYDOCTOR_MODULES)) + LD_LIBRARY_PATH=bin/shared PYTHONPATH=bin/python pydoctor --project-name=Samba --make-html --docformat=restructuredtext --add-package scripting/python/samba/ $(addprefix --add-module , $(PYDOCTOR_MODULES)) installpython:: pythonmods @$(SHELL) $(srcdir)/script/installpython.sh \ diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 7dd564fae1..3e88b68509 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -271,20 +271,19 @@ def setup_name_mappings(ldb, sid, domaindn, root, nobody, nogroup, users, def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, credentials, configdn, schemadn, domaindn, hostname, netbiosname, dnsdomain, realm, - rootdn, serverrole, ldap_backend=None, + rootdn, serverrole, sitename, ldap_backend=None, ldap_backend_type=None, erase=False): """Setup the partitions for the SAM database. Alternatively, provision() may call this, and then populate the database. :param erase: Remove the existing data present in the database. - :param :note: This will wipe the Sam Database! :note: This function always removes the local SAM LDB file. The erase - parameter controls whether to erase the existing data, which - may not be stored locally but in LDAP. + parameter controls whether to erase the existing data, which + may not be stored locally but in LDAP. """ assert session_info is not None @@ -333,13 +332,12 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, schemadn_ldb = "schema.ldb" if ldap_backend is not None: schema_ldb = ldap_backend - schemadn_ldb = ldap_backend if ldap_backend_type == "fedora-ds": - backend_modules = ["nsuniqueid","paged_searches"] + backend_modules = ["nsuniqueid", "paged_searches"] elif ldap_backend_type == "openldap": - backend_modules = ["normalise","entryuuid","paged_searches"] + backend_modules = ["normalise", "entryuuid", "paged_searches"] elif serverrole == "domain controller": backend_modules = ["repl_meta_data"] else: @@ -380,7 +378,8 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, message("Setting up sam.ldb rootDSE") setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname, - dnsdomain, realm, rootdn, configdn, netbiosname) + dnsdomain, realm, rootdn, configdn, netbiosname, + sitename) if erase: message("Erasing data from partitions") @@ -474,18 +473,18 @@ def setup_registry(path, setup_path, session_info, credentials, lp): def setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname, - dnsdomain, realm, rootdn, configdn, netbiosname): + dnsdomain, realm, rootdn, configdn, netbiosname, + sitename): """Setup the SamDB rootdse. :param samdb: Sam Database handle :param setup_path: Obtain setup path - ... """ setup_add_ldif(samdb, setup_path("provision_rootdse_add.ldif"), { "SCHEMADN": schemadn, "NETBIOSNAME": netbiosname, "DNSDOMAIN": dnsdomain, - "DEFAULTSITE": DEFAULTSITE, + "DEFAULTSITE": sitename, "REALM": realm, "DNSNAME": "%s.%s" % (hostname, dnsdomain), "DOMAINDN": domaindn, @@ -498,7 +497,7 @@ def setup_samdb_rootdse(samdb, setup_path, schemadn, domaindn, hostname, def setup_self_join(samdb, configdn, schemadn, domaindn, netbiosname, hostname, dnsdomain, machinepass, dnspass, realm, domainname, domainsid, invocationid, setup_path, - policyguid, hostguid=None): + policyguid, sitename, hostguid=None): """Join a host to its own domain.""" if hostguid is not None: hostguid_add = "objectGUID: %s" % hostguid @@ -511,7 +510,7 @@ def setup_self_join(samdb, configdn, schemadn, domaindn, "DOMAINDN": domaindn, "INVOCATIONID": invocationid, "NETBIOSNAME": netbiosname, - "DEFAULTSITE": DEFAULTSITE, + "DEFAULTSITE": sitename, "DNSNAME": "%s.%s" % (hostname, dnsdomain), "MACHINEPASS_B64": b64encode(machinepass), "DNSPASS_B64": b64encode(dnspass), @@ -532,12 +531,15 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, domainsid, aci, domainguid, policyguid, domainname, fill, adminpass, krbtgtpass, machinepass, hostguid, invocationid, dnspass, - serverrole, ldap_backend=None, ldap_backend_type=None): + serverrole, sitename, ldap_backend=None, + ldap_backend_type=None): """Setup a complete SAM Database. :note: This will wipe the main SAM database file! """ + assert serverrole in ("domain controller", "member server") + # Also wipes the database setup_samdb_partitions(path, setup_path, schemadn=schemadn, configdn=configdn, domaindn=domaindn, message=message, lp=lp, @@ -545,7 +547,8 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, hostname=hostname, netbiosname=netbiosname, dnsdomain=dnsdomain, realm=realm, rootdn=rootdn, ldap_backend=ldap_backend, serverrole=serverrole, - ldap_backend_type=ldap_backend_type, erase=erase) + ldap_backend_type=ldap_backend_type, erase=erase, + sitename=sitename) samdb = SamDB(path, session_info=session_info, credentials=credentials, lp=lp) @@ -563,7 +566,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, if lp.get("server role") == "domain controller": samdb.set_invocation_id(invocationid) - load_schema(setup_path, samdb, schemadn, netbiosname, configdn) + load_schema(setup_path, samdb, schemadn, netbiosname, configdn, sitename) samdb.transaction_start() @@ -585,7 +588,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, "DOMAINSID": str(domainsid), "SCHEMADN": schemadn, "NETBIOSNAME": netbiosname, - "DEFAULTSITE": DEFAULTSITE, + "DEFAULTSITE": sitename, "CONFIGDN": configdn, "POLICYGUID": policyguid, "DOMAINDN": domaindn, @@ -615,7 +618,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, setup_path("provision_schema_basedn_modify.ldif"), { "SCHEMADN": schemadn, "NETBIOSNAME": netbiosname, - "DEFAULTSITE": DEFAULTSITE, + "DEFAULTSITE": sitename, "CONFIGDN": configdn, }) @@ -630,7 +633,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, setup_add_ldif(samdb, setup_path("provision_configuration.ldif"), { "CONFIGDN": configdn, "NETBIOSNAME": netbiosname, - "DEFAULTSITE": DEFAULTSITE, + "DEFAULTSITE": sitename, "DNSDOMAIN": dnsdomain, "DOMAIN": domainname, "SCHEMADN": schemadn, @@ -657,7 +660,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, setup_add_ldif(samdb, setup_path("provision.ldif"), { "DOMAINDN": domaindn, "NETBIOSNAME": netbiosname, - "DEFAULTSITE": DEFAULTSITE, + "DEFAULTSITE": sitename, "CONFIGDN": configdn, }) @@ -680,7 +683,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, machinepass=machinepass, domainname=domainname, domainsid=domainsid, policyguid=policyguid, hostname=hostname, hostguid=hostguid, - setup_path=setup_path) + setup_path=setup_path, sitename=sitename) #We want to setup the index last, as adds are faster unindexed message("Setting up sam.ldb index") @@ -692,6 +695,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, samdb.transaction_commit() return samdb + FILL_FULL = "FULL" FILL_NT4SYNC = "NT4SYNC" FILL_DRS = "DRS" @@ -703,7 +707,7 @@ def provision(lp, setup_dir, message, paths, session_info, policyguid=None, invocationid=None, machinepass=None, dnspass=None, root=None, nobody=None, nogroup=None, users=None, wheel=None, backup=None, aci=None, serverrole=None, erase=False, - ldap_backend=None, ldap_backend_type=None): + ldap_backend=None, ldap_backend_type=None, sitename=DEFAULTSITE): """Provision samba4 :note: caution, this wipes all existing data! @@ -852,7 +856,7 @@ def provision(lp, setup_dir, message, paths, session_info, hostguid=hostguid, invocationid=invocationid, machinepass=machinepass, dnspass=dnspass, serverrole=serverrole, ldap_backend=ldap_backend, - ldap_backend_type=ldap_backend_type) + ldap_backend_type=ldap_backend_type, sitename=sitename) if lp.get("server role") == "domain controller": policy_path = os.path.join(paths.sysvol, dnsdomain, "Policies", @@ -946,7 +950,7 @@ def create_zone_file(path, setup_path, samdb, dnsdomain, domaindn, }) -def load_schema(setup_path, samdb, schemadn, netbiosname, configdn): +def load_schema(setup_path, samdb, schemadn, netbiosname, configdn, sitename): """Load schema for the SamDB. :param samdb: Load a schema into a SamDB. @@ -963,7 +967,7 @@ def load_schema(setup_path, samdb, schemadn, netbiosname, configdn): "SCHEMADN": schemadn, "NETBIOSNAME": netbiosname, "CONFIGDN": configdn, - "DEFAULTSITE": DEFAULTSITE + "DEFAULTSITE":sitename }) samdb.attach_schema_from_ldif(head_data, schema_data) diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index c11fabf553..3c6bb23c02 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -100,12 +100,14 @@ userAccountControl: %u self.transaction_start() # find the DNs for the domain and the domain users group - res = self.search("", SCOPE_BASE, "defaultNamingContext=*", - ["defaultNamingContext"]) + res = self.search("", scope=ldb.SCOPE_BASE, + expression="(defaultNamingContext=*)", + attrs=["defaultNamingContext"]) assert(len(res) == 1 and res[0].defaultNamingContext is not None) domain_dn = res[0]["defaultNamingContext"][0] assert(domain_dn is not None) - dom_users = self.searchone(basedn=domain_dn, attribute="dn", expression="name=Domain Users") + dom_users = self.searchone(basedn=domain_dn, attribute="dn", + expression="name=Domain Users") assert(dom_users is not None) user_dn = "CN=%s,CN=Users,%s" % (username, domain_dn) diff --git a/source4/scripting/python/samba/tests/__init__.py b/source4/scripting/python/samba/tests/__init__.py index 9402002674..c8673d3fae 100644 --- a/source4/scripting/python/samba/tests/__init__.py +++ b/source4/scripting/python/samba/tests/__init__.py @@ -84,3 +84,9 @@ class LdbExtensionTests(TestCaseInTempDir): del l os.unlink(path) + +def get_loadparm(): + import param + lp = param.LoadParm() + lp.load(os.getenv("SMB_CONF_PATH")) + return lp diff --git a/source4/scripting/python/samba/tests/dcerpc/registry.py b/source4/scripting/python/samba/tests/dcerpc/registry.py index f3f0b0fb1a..147acc5098 100644 --- a/source4/scripting/python/samba/tests/dcerpc/registry.py +++ b/source4/scripting/python/samba/tests/dcerpc/registry.py @@ -20,11 +20,11 @@ import winreg from param import LoadParm import unittest +from samba.tests import get_loadparm class WinregTests(unittest.TestCase): def setUp(self): - lp_ctx = LoadParm() - lp_ctx.load("st/client/client.conf") + lp_ctx = get_loadparm() self.conn = winreg.winreg("ncalrpc:", lp_ctx) def get_hklm(self): diff --git a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py index 52c2bb8c72..8c1a8bec71 100644 --- a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py +++ b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py @@ -18,13 +18,12 @@ # import echo -from param import LoadParm import unittest +from samba.tests import get_loadparm class RpcEchoTests(unittest.TestCase): def setUp(self): - lp_ctx = LoadParm() - lp_ctx.load("st/client/client.conf") + lp_ctx = get_loadparm() self.conn = echo.rpcecho("ncalrpc:", lp_ctx) def test_addone(self): diff --git a/source4/scripting/python/samba/tests/dcerpc/sam.py b/source4/scripting/python/samba/tests/dcerpc/sam.py index 50caaf2348..96348f2f69 100644 --- a/source4/scripting/python/samba/tests/dcerpc/sam.py +++ b/source4/scripting/python/samba/tests/dcerpc/sam.py @@ -19,10 +19,11 @@ import samr import unittest +from samba.tests import get_loadparm class SamrTests(unittest.TestCase): def setUp(self): - self.conn = samr.samr("ncalrpc:", "st/client/client.conf") + self.conn = samr.samr("ncalrpc:", get_loadparm()) def test_connect5(self): (level, info, handle) = self.conn.Connect5(None, 0, 1, samr.ConnectInfo1()) diff --git a/source4/scripting/python/samba/tests/provision.py b/source4/scripting/python/samba/tests/provision.py index eb49f7af83..514582cbe4 100644 --- a/source4/scripting/python/samba/tests/provision.py +++ b/source4/scripting/python/samba/tests/provision.py @@ -24,8 +24,7 @@ from ldb import Dn import param import unittest -lp = param.LoadParm() -lp.load("st/dc/etc/smb.conf") +lp = samba.tests.get_loadparm() setup_dir = "setup" def setup_path(file): @@ -33,6 +32,8 @@ def setup_path(file): class ProvisionTestCase(samba.tests.TestCaseInTempDir): + """Some simple tests for individual functions in the provisioning code. + """ def test_setup_secretsdb(self): path = os.path.join(self.tempdir, "secrets.ldb") ldb = setup_secretsdb(path, setup_path, None, None, lp=lp) diff --git a/source4/scripting/python/samba/tests/samdb.py b/source4/scripting/python/samba/tests/samdb.py new file mode 100644 index 0000000000..40e56bebb5 --- /dev/null +++ b/source4/scripting/python/samba/tests/samdb.py @@ -0,0 +1,55 @@ +#!/usr/bin/python + +# Unix SMB/CIFS implementation. Tests for SamDB +# 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/>. +# +from auth import system_session +from credentials import Credentials +import os +from samba.provision import setup_samdb +from samba.samdb import SamDB +from samba.tests import get_loadparm, TestCaseInTempDir +import security +from unittest import TestCase +import uuid + +class SamDBTestCase(TestCaseInTempDir): + def setUp(self): + super(SamDBTestCase, self).setUp() + invocationid = uuid.random() + domaindn = "DC=COM,DC=EXAMPLE" + self.domaindn = domaindn + configdn = "CN=Configuration," + domaindn + schemadn = "CN=Schema," + configdn + domainguid = uuid.random() + policyguid = uuid.random() + setup_path = lambda x: os.path.join("setup", x) + creds = Credentials() + domainsid = security.random_sid() + hostguid = uuid.random() + path = os.path.join(self.tempdir, "samdb.ldb") + self.samdb = setup_samdb(path, setup_path, system_session(), creds, + get_loadparm(), schemadn, configdn, + self.domaindn, "example.com", "EXAMPLE.COM", + "FOO", lambda x: None, "foo", domaindn, + False, domainsid, "# no aci", domainguid, + policyguid, "EXAMPLE", True, "secret", + "secret", "secret", hostguid, invocationid, + "secret", "domain controller") + + def test_add_foreign(self): + self.samdb.add_foreign(self.domaindn, "S-1-5-7", "Somedescription") + diff --git a/source4/scripting/python/samba/tests/upgrade.py b/source4/scripting/python/samba/tests/upgrade.py index ddafa00691..4dc86ace8a 100644 --- a/source4/scripting/python/samba/tests/upgrade.py +++ b/source4/scripting/python/samba/tests/upgrade.py @@ -17,6 +17,21 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -import samba.upgrade -from unittest import TestCase +from samba import Ldb +from samba.upgrade import import_wins +from samba.tests import LdbTestCase +class WinsUpgradeTests(LdbTestCase): + def test_upgrade(self): + winsdb = { + "FOO#20": (200, ["127.0.0.1", "127.0.0.2"], 0x60) + } + import_wins(self.ldb, winsdb) + + self.assertEquals(['name=FOO,type=0x20'], + [str(m.dn) for m in self.ldb.search(expression="(objectClass=winsRecord)")]) + + def test_version(self): + import_wins(self.ldb, {}) + self.assertEquals("VERSION", + self.ldb.search(expression="(objectClass=winsMaxVersion)")[0]["cn"]) diff --git a/source4/scripting/python/samba/upgrade.py b/source4/scripting/python/samba/upgrade.py index b332bb89ae..01b62ff984 100644 --- a/source4/scripting/python/samba/upgrade.py +++ b/source4/scripting/python/samba/upgrade.py @@ -10,6 +10,7 @@ from provision import findnss, provision, FILL_DRS import grp import ldb +import time import pwd import uuid import registry @@ -17,6 +18,7 @@ from samba import Ldb from samba.samdb import SamDB def import_sam_policy(samldb, samba3_policy, domaindn): + """Import a Samba 3 policy database.""" samldb.modify_ldif(""" dn: %s changetype: modify @@ -162,7 +164,6 @@ def import_wins(samba4_winsdb, samba3_winsdb): :param samba3_winsdb: WINS database to import from """ version_id = 0 - import time for (name, (ttl, ips, nb_flags)) in samba3_winsdb.items(): version_id+=1 @@ -201,7 +202,8 @@ def import_wins(samba4_winsdb, samba3_winsdb): "versionID": str(version_id), "address": ips}) - samba4_winsdb.add({"dn": "CN=VERSION", + samba4_winsdb.add({"dn": "cn=VERSION", + "cn": "VERSION", "objectClass": "winsMaxVersion", "maxVersion": str(version_id)}) diff --git a/source4/scripting/python/subunit/__init__.py b/source4/scripting/python/subunit/__init__.py index 4d3434a3ea..3abfbf522e 100644 --- a/source4/scripting/python/subunit/__init__.py +++ b/source4/scripting/python/subunit/__init__.py @@ -209,7 +209,7 @@ class TestProtocolClient(unittest.TestResult): """A class that looks like a TestResult and informs a TestProtocolServer.""" def __init__(self, stream): - unittest.TestResult.__init__(self) + super(TestProtocolClient, self).__init__() self._stream = stream def addError(self, test, error): @@ -218,6 +218,7 @@ class TestProtocolClient(unittest.TestResult): for line in self._exc_info_to_string(error, test).splitlines(): self._stream.write("%s\n" % line) self._stream.write("]\n") + super(TestProtocolClient, self).addError(test, error) def addFailure(self, test, error): """Report a failure in test test.""" @@ -225,14 +226,17 @@ class TestProtocolClient(unittest.TestResult): for line in self._exc_info_to_string(error, test).splitlines(): self._stream.write("%s\n" % line) self._stream.write("]\n") + super(TestProtocolClient, self).addFailure(test, error) def addSuccess(self, test): """Report a success in a test.""" self._stream.write("successful: %s\n" % (test.shortDescription() or str(test))) + super(TestProtocolClient, self).addSuccess(test) def startTest(self, test): """Mark a test as starting its test run.""" self._stream.write("test: %s\n" % (test.shortDescription() or str(test))) + super(TestProtocolClient, self).startTest(test) def RemoteError(description=""): |