r23177: Add in a new provision-backend script. This helps set up the OpenLDAP or...
authorAndrew Bartlett <abartlet@samba.org>
Tue, 29 May 2007 01:20:47 +0000 (01:20 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:53:00 +0000 (14:53 -0500)
This required a new mkdir() call in ejs.

We can now provision just the schema for ad2oLschema to operate on
(with provision_schema(), without performing the whole provision, just
to wipe it again (adjustments to 'make test' to come soon).

Andrew Bartlett

source/lib/ldb/tools/ad2oLschema.c
source/script/installmisc.sh
source/scripting/ejs/smbcalls_sys.c
source/scripting/libjs/provision.js
source/setup/fedorads-partitions.ldif [new file with mode: 0644]
source/setup/fedorads.inf [new file with mode: 0644]
source/setup/provision-backend [new file with mode: 0755]
source/setup/slapd.conf [new file with mode: 0644]

index d04260103d6c414eeb4120fc61700aff2abfa392..4cc07a52d859ded674686e85f626253a37fd6f14 100644 (file)
@@ -195,9 +195,11 @@ static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *sche
 static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx) 
 {
        const char *rootdse_attrs[] = {"schemaNamingContext", NULL};
+       const char *no_attrs[] = { NULL };
        struct ldb_dn *schemadn;
        struct ldb_dn *basedn = ldb_dn_new(mem_ctx, ldb, NULL);
        struct ldb_result *rootdse_res;
+       struct ldb_result *schema_res;
        int ldb_ret;
        if (!basedn) {
                return NULL;
@@ -206,8 +208,25 @@ static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ct
        /* Search for rootdse */
        ldb_ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, NULL, rootdse_attrs, &rootdse_res);
        if (ldb_ret != LDB_SUCCESS) {
-               printf("Search failed: %s\n", ldb_errstring(ldb));
-               return NULL;
+               ldb_ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, 
+                                "(&(objectClass=dMD)(cn=Schema))", 
+                                no_attrs, &schema_res);
+               if (ldb_ret) {
+                       printf("cn=Schema Search failed: %s\n", ldb_errstring(ldb));
+                       return NULL;
+               }
+
+               talloc_steal(mem_ctx, schema_res);
+
+               if (schema_res->count != 1) {
+                       printf("Failed to find rootDSE");
+                       return NULL;
+               }
+               
+               schemadn = talloc_steal(mem_ctx, schema_res->msgs[0]->dn);
+               talloc_free(schema_res);
+               return schemadn;
+               
        }
        
        talloc_steal(mem_ctx, rootdse_res);
index 082a01eee96d81f8bfe2d1cd28523bf524fca050..a714783aecf3fa246530391e46aba9bc55ae6745 100755 (executable)
@@ -14,6 +14,8 @@ cp scripting/libjs/*.js $JSDIR || exit 1
 
 echo "Installing setup templates"
 mkdir -p $SETUPDIR || exit 1
+cp setup/schema-map-* $SETUPDIR || exit 1
+cp setup/*.inf $SETUPDIR || exit 1
 cp setup/*.ldif $SETUPDIR || exit 1
 cp setup/*.zone $SETUPDIR || exit 1
 cp setup/*.conf $SETUPDIR || exit 1
index ce3f3f5a98a437f5920148835bf0fe1f8de016dd..1b1affc80d6a21cad417b316643fe2967c78ab0d 100644 (file)
@@ -305,6 +305,33 @@ static int ejs_sys_file_save(MprVarHandle eid, int argc, char **argv)
        return 0;
 }
 
+/*
+  mkdir()
+  usage:
+     ok = sys.mkdir(dirname, mode);
+*/
+static int ejs_sys_mkdir(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+       BOOL ret;
+       char *name;
+       if (argc != 2) {
+               ejsSetErrorMsg(eid, "sys_mkdir invalid arguments, need mkdir(dirname, mode)");
+               return -1;
+       }
+       if (!mprVarIsString(argv[0]->type)) {
+               ejsSetErrorMsg(eid, "sys_mkdir dirname not a string");
+               return -1;
+       }
+       if (!mprVarIsNumber(argv[1]->type)) {
+               ejsSetErrorMsg(eid, "sys_mkdir mode not a number");
+               return -1;
+       }
+       mprVarToString(&name, 0, NULL, argv[0]);
+       ret = mkdir(name, mprVarToNumber(argv[1]));
+       mpr_Return(eid, mprCreateBoolVar(ret == 0));
+       return 0;
+}
+
 
 /*
   return fields of a stat() call
@@ -438,6 +465,7 @@ static int ejs_sys_init(MprVarHandle eid, int argc, struct MprVar **argv)
        mprSetCFunction(obj, "ntgmtime", ejs_sys_ntgmtime);
        mprSetCFunction(obj, "ldaptime", ejs_sys_ldaptime);
        mprSetCFunction(obj, "httptime", ejs_sys_httptime);
+       mprSetCFunction(obj, "mkdir", ejs_sys_mkdir);
        mprSetStringCFunction(obj, "unlink", ejs_sys_unlink);
        mprSetStringCFunction(obj, "file_load", ejs_sys_file_load);
        mprSetStringCFunction(obj, "file_save", ejs_sys_file_save);
index d9bdb3b16b4f2c729afbbf057ef5f100fc7b2f11..d25c0f38ebd269a41e3c4606aeccf9458c596323 100644 (file)
@@ -388,6 +388,7 @@ function provision_default_paths(subobj)
        paths.ldap_basedn_ldif = lp.get("private dir") + "/" + subobj.DNSDOMAIN + ".ldif";
        paths.ldap_config_basedn_ldif = lp.get("private dir") + "/" + subobj.DNSDOMAIN + "-config.ldif";
        paths.ldap_schema_basedn_ldif = lp.get("private dir") + "/" + subobj.DNSDOMAIN + "-schema.ldif";
+       paths.ldapdir = lp.get("private dir") + "/ldap";
        return paths;
 }
 
@@ -446,10 +447,11 @@ function provision_fix_subobj(subobj, message, paths)
        var rdns = split(",", subobj.DOMAINDN);
        subobj.RDN_DC = substr(rdns[0], strlen("DC="));
 
-       subobj.SAM_LDB          = paths.samdb;
-       subobj.SECRETS_LDB      = paths.secrets;
+       subobj.SAM_LDB          = "tdb://" + paths.samdb;
        subobj.SECRETS_KEYTAB   = paths.keytab;
 
+       subobj.LDAPDIR = paths.ldapdir;
+
        return true;
 }
 
@@ -703,6 +705,53 @@ function provision(subobj, message, blank, paths, session_info, credentials, lda
        return true;
 }
 
+/*
+  provision just the schema into a temporary ldb, so we can run ad2oLschema on it
+*/
+function provision_schema(subobj, message, tmp_schema_path, paths)
+{
+       var lp = loadparm_init();
+       var sys = sys_init();
+       var info = new Object();
+
+       var ok = provision_fix_subobj(subobj, message, paths);
+       assert(ok);
+
+       info.subobj = subobj;
+       info.message = message;
+
+       message("Setting up sam.ldb partitions\n");
+
+       /* This will erase anything in the tmp db */
+       var samdb = open_ldb(info, tmp_schema_path, true);
+
+       message("Adding schema container (permitted to fail)\n");
+       var add_ok = setup_add_ldif("provision_schema_basedn.ldif", info, samdb, true);
+       message("Modifying schema container\n");
+       var modify_ok = setup_ldb_modify("provision_schema_basedn_modify.ldif", info, samdb);
+       if (!modify_ok) {
+               if (!add_ok) {
+                       message("Failed to both add and modify schema dn: + samdb.errstring() + "\n");
+                       message("Perhaps you need to run the provision script with the --ldap-base-dn option, and add this record to the backend manually\n"); 
+                       assert(modify_ok);
+               }
+               message("Failed to modify the schema container: " + samdb.errstring() + "\n");
+               assert(modify_ok);
+       }
+
+       message("Setting up sam.ldb Samba4 schema\n");
+       setup_add_ldif("schema_samba4.ldif", info, samdb, false);
+       message("Setting up sam.ldb AD schema\n");
+       setup_add_ldif("schema.ldif", info, samdb, false);
+
+       var commit_ok = samdb.transaction_commit();
+       if (!commit_ok) {
+               info.message("samdb commit failed: " + samdb.errstring() + "\n");
+               assert(commit_ok);
+       }
+       samdb.close();
+}
+
 /* Write out a DNS zone file, from the info in the current database */
 function provision_dns(subobj, message, paths, session_info, credentials)
 {
@@ -787,6 +836,7 @@ function provision_guess()
        subobj.KRBTGTPASS   = randpass(12);
        subobj.MACHINEPASS  = randpass(12);
        subobj.ADMINPASS    = randpass(12);
+       subobj.LDAPMANAGERPASS     = randpass(12);
        subobj.DEFAULTSITE  = "Default-First-Site-Name";
        subobj.NEWGUID      = randguid;
        subobj.NTTIME       = nttime;
diff --git a/source/setup/fedorads-partitions.ldif b/source/setup/fedorads-partitions.ldif
new file mode 100644 (file)
index 0000000..7533b15
--- /dev/null
@@ -0,0 +1,28 @@
+dn: cn=\"${CONFIGDN}\",cn=mapping tree,cn=config
+objectclass: top
+objectclass: extensibleObject
+objectclass: nsMappingTree
+nsslapd-state: backend
+nsslapd-backend: configData
+cn: ${CONFIGDN}
+
+dn: cn=configData,cn=ldbm database,cn=plugins,cn=config
+objectclass: extensibleObject
+objectclass: nsBackendInstance
+nsslapd-suffix: ${CONFIGDN}
+cn: configData
+
+dn: cn=\"${SCHEMADN}\",cn=mapping tree,cn=config
+objectclass: top
+objectclass: extensibleObject
+objectclass: nsMappingTree
+nsslapd-state: backend
+nsslapd-backend: schemaData
+cn: ${SCHEMADN}
+
+dn: cn=schemaData,cn=ldbm database,cn=plugins,cn=config
+objectclass: extensibleObject
+objectclass: nsBackendInstance
+nsslapd-suffix: ${SCHEMADN}
+cn: schemaData
+
diff --git a/source/setup/fedorads.inf b/source/setup/fedorads.inf
new file mode 100644 (file)
index 0000000..a5d282d
--- /dev/null
@@ -0,0 +1,26 @@
+[General]
+SuiteSpotUserID = ${ROOT}
+FullMachineName=   ${HOSTNAME}.${DNSDOMAIN}
+ServerRoot=   ${LDAPDIR}
+
+[slapd]
+ldapifilepath=${LDAPDIR}/ldapi
+Suffix= ${DOMAINDN}
+RootDN= cn=Manager,${DOMAINDN}
+RootDNPwd= ${LDAPMANAGERPASS}
+ServerIdentifier= samba4
+
+inst_dir= ${LDAPDIR}/slapd-samba4
+config_dir= ${LDAPDIR}/slapd-samba4
+schema_dir= ${LDAPDIR}/slapd-samba4/schema
+lock_dir= ${LDAPDIR}/slapd-samba4/lock
+log_dir= ${LDAPDIR}/slapd-samba4/logs
+run_dir= ${LDAPDIR}/slapd-samba4/logs
+db_dir= ${LDAPDIR}/slapd-samba4/db
+bak_dir= ${LDAPDIR}/slapd-samba4/bak
+tmp_dir= ${LDAPDIR}/slapd-samba4/tmp
+ldif_dir= ${LDAPDIR}/slapd-samba4/ldif
+cert_dir= ${LDAPDIR}/slapd-samba4
+
+start_server= 0
+install_full_schema= 0
\ No newline at end of file
diff --git a/source/setup/provision-backend b/source/setup/provision-backend
new file mode 100755 (executable)
index 0000000..6a5ec3e
--- /dev/null
@@ -0,0 +1,114 @@
+#!/bin/sh
+exec smbscript "$0" ${1+"$@"}
+/*
+       provision a Samba4 server
+       Copyright Andrew Tridgell 2005
+       Released under the GNU GPL v2 or later
+*/
+
+options = GetOptions(ARGV,
+               "POPT_AUTOHELP",
+               "POPT_COMMON_SAMBA",
+               "POPT_COMMON_VERSION",
+               "POPT_COMMON_CREDENTIALS",
+               'realm=s',
+               'host-name=s',
+               'ldap-manager-pass=s',
+               'root=s',
+               'quiet',
+               'ldap-backend-type=s');
+
+if (options == undefined) {
+   println("Failed to parse options");
+   return -1;
+}
+
+sys = sys_init();
+
+libinclude("base.js");
+libinclude("provision.js");
+
+/*
+  print a message if quiet is not set
+*/
+function message()
+{
+       if (options["quiet"] == undefined) {
+               print(vsprintf(arguments));
+       }
+}
+
+/*
+ show some help
+*/
+function ShowHelp()
+{
+       print("
+Samba4 provisioning
+
+provision [options]
+ --realm       REALM           set realm
+ --host-name   HOSTNAME        set hostname
+ --ldap-manager-pass   PASSWORD        choose LDAP Manager password (otherwise random)
+ --root         USERNAME       choose 'root' unix username
+ --quiet                       Be quiet
+ --ldap-backend-type LDAPSERVER     Select either \"openldap\" or \"fedora-ds\" as a target to configure
+ --ldap-module= MODULE          LDB mapping module to use for the LDAP backend
+You must provide at least a realm and ldap-backend-type
+
+");
+       exit(1);
+}
+
+if (options['host-name'] == undefined) {
+       options['host-name'] = hostname();
+}
+
+/*
+   main program
+*/
+if (options["realm"] == undefined ||
+    options["ldap-backend-type"] == undefined ||
+    options["host-name"] == undefined) {
+       ShowHelp();
+}
+
+/* cope with an initially blank smb.conf */
+var lp = loadparm_init();
+lp.set("realm", options.realm);
+lp.reload();
+
+var subobj = provision_guess();
+for (r in options) {
+       var key = strupper(join("", split("-", r)));
+       subobj[key] = options[r];
+}
+
+var ldapbackend = (options["ldap-backend-type"] != undefined);
+
+var paths = provision_default_paths(subobj);
+provision_fix_subobj(subobj, message, paths);
+message("Provisioning LDAP backend for %s in realm %s into %s\n", subobj.HOSTNAME, subobj.REALM, subobj.LDAPDIR);
+message("Using LDAP Manager password: %s\n", subobj.LDAPMANAGERPASS);
+
+var tmp_schema_ldb = subobj.LDAPDIR + "/schema-tmp.ldb";
+sys.mkdir(subobj.LDAPDIR, 0700);
+
+provision_schema(subobj, message, tmp_schema_ldb, paths);
+
+var mapping;
+var ext;
+if (options["ldap-backend-type"] == "fedora-ds") {
+       mapping = "schema-map-fedora-ds-1.0";
+       ext = "ldif";
+       setup_file("fedorads.inf", message, subobj.LDAPDIR + "/fedorads.inf", subobj);
+       setup_file("fedorads-partitions.ldif", message, subobj.LDAPDIR + "/fedorads-partitions.ldif", subobj);
+} else if (options["ldap-backend-type"] == "openldap") {
+       mapping = "schema-map-openldap-2.3";
+       ext = "schema";
+       setup_file("slapd.conf", message, subobj.LDAPDIR + "/slapd.conf", subobj);
+}
+message("ad2oLschema --option=convert:target=" + options["ldap-backend-type"] + " -I " + lp.get("setup directory") + "/" + mapping + " -H tdb://" + tmp_schema_ldb + " -O " + subobj.LDAPDIR + "/backend-schema." + ext + "\n");
+
+message("All OK\n");
+return 0;
diff --git a/source/setup/slapd.conf b/source/setup/slapd.conf
new file mode 100644 (file)
index 0000000..a6fe73a
--- /dev/null
@@ -0,0 +1,73 @@
+loglevel 0
+
+include ${LDAPDIR}/backend-schema.schema
+
+pidfile                ${LDAPDIR}/slapd.pid
+argsfile       ${LDAPDIR}/slapd.args
+sasl-realm ${DNSDOMAIN}
+access to * by * write
+
+allow update_anon
+
+authz-regexp
+          uid=([^,]*),cn=${DNSDOMAIN},cn=digest-md5,cn=auth
+          ldap:///${DOMAINDN}??sub?(samAccountName=\$1)
+
+authz-regexp
+          uid=([^,]*),cn=([^,]*),cn=digest-md5,cn=auth
+          ldap:///${DOMAINDN}??sub?(samAccountName=\$1)
+
+include $modconf
+
+defaultsearchbase \"${DOMAINDN}\"
+
+backend                bdb
+database        bdb
+suffix         \"cn=Schema,cn=Configuration,${DOMAINDN}\"
+directory      ${LDAPDIR}/db/schema
+index           objectClass eq
+index           samAccountName eq
+index name eq
+index objectCategory eq
+index lDAPDisplayName eq
+index subClassOf eq
+
+database        bdb
+suffix         \"cn=Configuration,${DOMAINDN}\"
+directory      ${LDAPDIR}/db/config
+index           objectClass eq
+index           samAccountName eq
+index name eq
+index objectSid eq
+index objectCategory eq
+index nCName eq pres
+index subClassOf eq
+index dnsRoot eq
+index nETBIOSName eq pres
+
+database        bdb
+suffix         \"${DOMAINDN}\"
+rootdn          \"cn=Manager,${DOMAINDN}\"
+rootpw          ${LDAPMANAGERPASS}
+directory      ${LDAPDIR}/db/user
+index           objectClass eq
+index           samAccountName eq
+index name eq
+index objectSid eq
+index objectCategory eq
+index member eq
+index uidNumber eq
+index gidNumber eq
+index unixName eq
+index privilege eq
+index nCName eq pres
+index lDAPDisplayName eq
+index subClassOf eq
+index dnsRoot eq
+index nETBIOSName eq pres
+
+#syncprov is stable in OpenLDAP 2.3, and available in 2.2.  
+#We only need this for the contextCSN attribute anyway....
+overlay syncprov
+syncprov-checkpoint 100 10
+syncprov-sessionlog 100