wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
auth js library functions
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
get a list of domains for SWAT authentication
|
||||
*/
|
||||
function getDomainList()
|
||||
{
|
||||
var ret = new Array(2);
|
||||
var lp = loadparm_init();
|
||||
ret[0] = "System User";
|
||||
ret[1] = lp.get("workgroup");
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
base js library functions
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
if (global["HAVE_BASE_JS"] != undefined) {
|
||||
return;
|
||||
}
|
||||
HAVE_BASE_JS=1
|
||||
|
||||
/* bring the string functions into the global frame */
|
||||
string_init(global);
|
||||
|
||||
/*
|
||||
an essential function!
|
||||
*/
|
||||
function printf()
|
||||
{
|
||||
print(vsprintf(arguments));
|
||||
}
|
||||
|
||||
/*
|
||||
helper function to setup a rpc io object, ready for input
|
||||
*/
|
||||
function irpcObj()
|
||||
{
|
||||
var o = new Object();
|
||||
o.input = new Object();
|
||||
return o;
|
||||
}
|
||||
|
||||
/*
|
||||
check that a status result is OK
|
||||
*/
|
||||
function check_status_ok(status)
|
||||
{
|
||||
if (status.is_ok != true) {
|
||||
printVars(status);
|
||||
}
|
||||
assert(status.is_ok == true);
|
||||
}
|
||||
|
||||
/*
|
||||
check that two arrays are equal
|
||||
*/
|
||||
function check_array_equal(a1, a2)
|
||||
{
|
||||
assert(a1.length == a2.length);
|
||||
for (i=0; i<a1.length; i++) {
|
||||
assert(a1[i] == a2[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
check that an array is all zeros
|
||||
*/
|
||||
function check_array_zero(a)
|
||||
{
|
||||
for (i=0; i<a.length; i++) {
|
||||
assert(a[i] == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
substitute strings of the form ${NAME} in str, replacing
|
||||
with substitutions from subobj
|
||||
*/
|
||||
function substitute_var(str, subobj)
|
||||
{
|
||||
var list = split("${", str);
|
||||
var i;
|
||||
for (i=1;i<list.length;i++) {
|
||||
var list2 = split("}", list[i], 1);
|
||||
if ((list2.length < 2) && (list2[0] + "}" != list[i])) {
|
||||
return undefined;
|
||||
}
|
||||
var key = list2[0];
|
||||
var val;
|
||||
if (typeof(subobj[key]) == "undefined") {
|
||||
val = "${" + key + "}";
|
||||
} else if (typeof(subobj[key]) == "string") {
|
||||
val = subobj[key];
|
||||
} else {
|
||||
var fn = subobj[key];
|
||||
val = fn(key);
|
||||
}
|
||||
list2[0] = "" + val;
|
||||
list[i] = join("", list2);
|
||||
}
|
||||
return join("", list);
|
||||
}
|
||||
|
||||
/*
|
||||
return "s" if a number should be shown as plural
|
||||
*/
|
||||
function plural(n)
|
||||
{
|
||||
if (n == 1) {
|
||||
return "";
|
||||
}
|
||||
return "s";
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
server side js functions for encoding/decoding objects into linear strings
|
||||
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL Version 2 or later
|
||||
*/
|
||||
/*
|
||||
usage:
|
||||
|
||||
enc = encodeObject(obj);
|
||||
obj = decodeObject(enc);
|
||||
|
||||
The encoded format of the object is a string that is safe to
|
||||
use in URLs
|
||||
|
||||
Note that only data elements are encoded, not functions
|
||||
*/
|
||||
|
||||
function __count_members(o) {
|
||||
var i, count = 0;
|
||||
for (i in o) {
|
||||
count++;
|
||||
}
|
||||
if (o.length != undefined) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function __replace(str, old, rep) {
|
||||
var s = string_init();
|
||||
var a = s.split(old, str);
|
||||
var j = s.join(rep, a);
|
||||
return s.join(rep, a);
|
||||
}
|
||||
|
||||
function encodeElement(e, name) {
|
||||
var t = typeof(e);
|
||||
var r;
|
||||
var s = string_init();
|
||||
if (t == 'object' && e == null) {
|
||||
t = 'null';
|
||||
}
|
||||
if (t == 'object') {
|
||||
r = s.sprintf("%s:%s:%s", name, t, encodeObject(e));
|
||||
} else if (t == "string") {
|
||||
var enc = s.encodeURIComponent(e);
|
||||
var rep = __replace(enc, '%', '#');
|
||||
r = s.sprintf("%s:%s:%s:",
|
||||
name, t, __replace(s.encodeURIComponent(e),'%','#'));
|
||||
} else if (t == "boolean" || t == "number") {
|
||||
r = s.sprintf("%s:%s:%s:", name, t, "" + e);
|
||||
} else if (t == "undefined" || t == "null") {
|
||||
r = s.sprintf("%s:%s:", name, t);
|
||||
} else if (t == "pointer") {
|
||||
r = s.sprintf("%s:string:(POINTER):", name);
|
||||
} else {
|
||||
println("Unable to linearise type " + t);
|
||||
r = "";
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function encodeObject(o) {
|
||||
var s = string_init();
|
||||
var i, r = s.sprintf("%u:", __count_members(o));
|
||||
for (i in o) {
|
||||
r = r + encodeElement(o[i], i);
|
||||
}
|
||||
if (o.length != undefined) {
|
||||
r = r + encodeElement(o.length, 'length');
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function decodeObjectArray(a) {
|
||||
var s = string_init();
|
||||
var o = new Object();
|
||||
var i, count = a[a.i]; a.i++;
|
||||
for (i=0;i<count;i++) {
|
||||
var name = a[a.i]; a.i++;
|
||||
var type = a[a.i]; a.i++;
|
||||
var value;
|
||||
if (type == 'object') {
|
||||
o[name] = decodeObjectArray(a);
|
||||
} else if (type == "string") {
|
||||
value = s.decodeURIComponent(__replace(a[a.i],'#','%')); a.i++;
|
||||
o[name] = value;
|
||||
} else if (type == "boolean") {
|
||||
value = a[a.i]; a.i++;
|
||||
if (value == 'true') {
|
||||
o[name] = true;
|
||||
} else {
|
||||
o[name] = false;
|
||||
}
|
||||
} else if (type == "undefined") {
|
||||
o[name] = undefined;
|
||||
} else if (type == "null") {
|
||||
o[name] = null;
|
||||
} else if (type == "number") {
|
||||
value = a[a.i]; a.i++;
|
||||
o[name] = value + 0;
|
||||
} else {
|
||||
println("Unable to delinearise type " + t);
|
||||
assert(t == "supported type");
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
function decodeObject(str) {
|
||||
var s = string_init();
|
||||
var a = s.split(':', str);
|
||||
a.i = 0;
|
||||
return decodeObjectArray(a);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
backend code for Samba4 management
|
||||
Copyright Andrew Tridgell 2005
|
||||
Released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
return a list of current sessions
|
||||
*/
|
||||
function smbsrv_sessions()
|
||||
{
|
||||
var irpc = irpc_init();
|
||||
status = irpc.connect("smb_server");
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.level = irpc.SMBSRV_INFO_SESSIONS;
|
||||
status = irpc.smbsrv_information(io);
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* gather the results into a single array */
|
||||
var i, count=0, ret = new Array(0);
|
||||
for (i=0;i<io.results.length;i++) {
|
||||
var sessions = io.results[i].info.sessions.sessions;
|
||||
var j;
|
||||
for (j=0;j<sessions.length;j++) {
|
||||
ret[count] = sessions[j];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of current tree connects
|
||||
*/
|
||||
function smbsrv_tcons()
|
||||
{
|
||||
var irpc = irpc_init();
|
||||
status = irpc.connect("smb_server");
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.level = irpc.SMBSRV_INFO_TCONS;
|
||||
status = irpc.smbsrv_information(io);
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* gather the results into a single array */
|
||||
var i, count=0, ret = new Object();
|
||||
for (i=0;i<io.results.length;i++) {
|
||||
var tcons = io.results[i].info.tcons.tcons;
|
||||
var j;
|
||||
for (j=0;j<tcons.length;j++) {
|
||||
ret[count] = tcons[j];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
ret.length = count;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
return nbtd statistics
|
||||
*/
|
||||
function nbtd_statistics()
|
||||
{
|
||||
var irpc = irpc_init();
|
||||
status = irpc.connect("nbt_server");
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.level = irpc.NBTD_INFO_STATISTICS;
|
||||
status = irpc.nbtd_information(io);
|
||||
if (status.is_ok != true) {
|
||||
return undefined;
|
||||
}
|
||||
return io.results[0].info.stats;
|
||||
}
|
||||
|
||||
/*
|
||||
see if a service is enabled
|
||||
*/
|
||||
function service_enabled(name)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var services = lp.get("server services");
|
||||
var i;
|
||||
for (i=0;i<services.length;i++) {
|
||||
if (services[i] == name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
show status of a server
|
||||
*/
|
||||
function server_status(name)
|
||||
{
|
||||
var i;
|
||||
var io;
|
||||
var irpc = irpc_init();
|
||||
|
||||
if (!service_enabled(name)) {
|
||||
return "DISABLED";
|
||||
}
|
||||
|
||||
status = irpc.connect(name + "_server");
|
||||
if (status.is_ok != true) {
|
||||
return "DOWN";
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
status = irpc.irpc_uptime(io);
|
||||
if (status.is_ok != true) {
|
||||
return "NOT RESPONDING";
|
||||
}
|
||||
|
||||
return "RUNNING";
|
||||
}
|
||||
|
||||
/*
|
||||
show status of a stream server
|
||||
*/
|
||||
function stream_server_status(name)
|
||||
{
|
||||
var irpc = irpc_init();
|
||||
|
||||
if (!service_enabled(name)) {
|
||||
return "DISABLED";
|
||||
}
|
||||
status = irpc.connect(name + "_server");
|
||||
if (status.is_ok != true) {
|
||||
return "0 connections";
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
status = irpc.irpc_uptime(io);
|
||||
if (status.is_ok != true) {
|
||||
return "NOT RESPONDING";
|
||||
}
|
||||
|
||||
var n = io.results.length;
|
||||
return sprintf("%u connection%s", n, plural(n));
|
||||
}
|
||||
@@ -0,0 +1,870 @@
|
||||
/*
|
||||
backend code for provisioning a Samba4 server
|
||||
Copyright Andrew Tridgell 2005
|
||||
Released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
sys = sys_init();
|
||||
|
||||
/*
|
||||
return true if the current install seems to be OK
|
||||
*/
|
||||
function install_ok(session_info, credentials)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var ldb = ldb_init();
|
||||
ldb.session_info = session_info;
|
||||
ldb.credentials = credentials;
|
||||
if (lp.get("realm") == "") {
|
||||
return false;
|
||||
}
|
||||
var ok = ldb.connect(lp.get("sam database"));
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
var res = ldb.search("(cn=Administrator)");
|
||||
if (res.length != 1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
find a user or group from a list of possibilities
|
||||
*/
|
||||
function findnss()
|
||||
{
|
||||
var i;
|
||||
assert(arguments.length >= 2);
|
||||
var nssfn = arguments[0];
|
||||
for (i=1;i<arguments.length;i++) {
|
||||
if (nssfn(arguments[i]) != undefined) {
|
||||
return arguments[i];
|
||||
}
|
||||
}
|
||||
printf("Unable to find user/group for %s\n", arguments[1]);
|
||||
assert(i<arguments.length);
|
||||
}
|
||||
|
||||
/*
|
||||
add a foreign security principle
|
||||
*/
|
||||
function add_foreign(ldb, subobj, sid, desc)
|
||||
{
|
||||
var add = sprintf("
|
||||
dn: CN=%s,CN=ForeignSecurityPrincipals,%s
|
||||
objectClass: top
|
||||
objectClass: foreignSecurityPrincipal
|
||||
description: %s
|
||||
",
|
||||
sid, subobj.BASEDN, desc);
|
||||
/* deliberately ignore errors from this, as the records may
|
||||
already exist */
|
||||
ldb.add(add);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup a mapping between a sam name and a unix name
|
||||
*/
|
||||
function setup_name_mapping(info, ldb, sid, unixname)
|
||||
{
|
||||
var attrs = new Array("dn");
|
||||
var res = ldb.search(sprintf("objectSid=%s", sid),
|
||||
info.subobj.BASEDN, ldb.SCOPE_SUBTREE, attrs);
|
||||
if (res.length != 1) {
|
||||
info.message("Failed to find record for objectSid %s\n", sid);
|
||||
return false;
|
||||
}
|
||||
var mod = sprintf("
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: unixName
|
||||
unixName: %s
|
||||
",
|
||||
res[0].dn, unixname);
|
||||
var ok = ldb.modify(mod);
|
||||
if (!ok) {
|
||||
info.message("name mapping for %s failed - %s\n",
|
||||
sid, ldb.errstring());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
return current time as a nt time string
|
||||
*/
|
||||
function nttime()
|
||||
{
|
||||
return "" + sys.nttime();
|
||||
}
|
||||
|
||||
/*
|
||||
return current time as a ldap time string
|
||||
*/
|
||||
function ldaptime()
|
||||
{
|
||||
return sys.ldaptime(sys.nttime());
|
||||
}
|
||||
|
||||
/*
|
||||
return a date string suitable for a dns zone serial number
|
||||
*/
|
||||
function datestring()
|
||||
{
|
||||
var t = sys.ntgmtime(sys.nttime());
|
||||
return sprintf("%04u%02u%02u%02u",
|
||||
t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour);
|
||||
}
|
||||
|
||||
/*
|
||||
return first host IP
|
||||
*/
|
||||
function hostip()
|
||||
{
|
||||
var list = sys.interfaces();
|
||||
return list[0];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
return first part of hostname
|
||||
*/
|
||||
function hostname()
|
||||
{
|
||||
var s = split(".", sys.hostname());
|
||||
return s[0];
|
||||
}
|
||||
|
||||
/* the ldb is in bad shape, possibly due to being built from an
|
||||
incompatible previous version of the code, so delete it
|
||||
completely */
|
||||
function ldb_delete(ldb)
|
||||
{
|
||||
println("Deleting " + ldb.filename);
|
||||
var lp = loadparm_init();
|
||||
sys.unlink(sprintf("%s/%s", lp.get("private dir"), ldb.filename));
|
||||
ldb.transaction_cancel();
|
||||
ldb.close();
|
||||
var ok = ldb.connect(ldb.filename);
|
||||
ldb.transaction_start();
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
/*
|
||||
erase an ldb, removing all records
|
||||
*/
|
||||
function ldb_erase(ldb)
|
||||
{
|
||||
var res;
|
||||
|
||||
/* delete the specials */
|
||||
ldb.del("@INDEXLIST");
|
||||
ldb.del("@ATTRIBUTES");
|
||||
ldb.del("@SUBCLASSES");
|
||||
ldb.del("@MODULES");
|
||||
ldb.del("@PARTITION");
|
||||
ldb.del("@KLUDGEACL");
|
||||
|
||||
/* and the rest */
|
||||
attrs = new Array("dn");
|
||||
var basedn = "";
|
||||
var res = ldb.search("(&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO)))", basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
var i;
|
||||
if (typeof(res) == "undefined") {
|
||||
ldb_delete(ldb);
|
||||
return;
|
||||
}
|
||||
for (i=0;i<res.length;i++) {
|
||||
ldb.del(res[i].dn);
|
||||
}
|
||||
|
||||
|
||||
var res = ldb.search("(&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO)))", basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
if (res.length != 0) {
|
||||
ldb_delete(ldb);
|
||||
return;
|
||||
}
|
||||
assert(res.length == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
erase an ldb, removing all records
|
||||
*/
|
||||
function ldb_erase_partitions(info, ldb)
|
||||
{
|
||||
var rootDSE_attrs = new Array("namingContexts");
|
||||
var lp = loadparm_init();
|
||||
var j;
|
||||
|
||||
var res = ldb.search("(objectClass=*)", "", ldb.SCOPE_BASE, rootDSE_attrs);
|
||||
assert(typeof(res) != "undefined");
|
||||
assert(res.length == 1);
|
||||
if (typeof(res[0].namingContexts) == "undefined") {
|
||||
return;
|
||||
}
|
||||
for (j=0; j<res[0].namingContexts.length; j++) {
|
||||
var attrs = new Array("dn");
|
||||
var basedn = res[0].namingContexts[j];
|
||||
var k;
|
||||
var previous_remaining = 1;
|
||||
var current_remaining = 0;
|
||||
|
||||
for (k=0; k < 10 && (previous_remaining != current_remaining); k++) {
|
||||
/* and the rest */
|
||||
var res2 = ldb.search("(|(objectclass=*)(dn=*))", basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
var i;
|
||||
if (typeof(res2) == "undefined") {
|
||||
info.message("ldb search failed: " + ldb.errstring() + "\n");
|
||||
continue;
|
||||
}
|
||||
previous_remaining = current_remaining;
|
||||
current_remaining = res2.length;
|
||||
for (i=0;i<res2.length;i++) {
|
||||
ldb.del(res2[i].dn);
|
||||
}
|
||||
|
||||
var res3 = ldb.search("(|(objectclass=*)(dn=*))", basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
if (typeof(res3) == "undefined") {
|
||||
info.message("ldb search failed: " + ldb.errstring() + "\n");
|
||||
continue;
|
||||
}
|
||||
if (res3.length != 0) {
|
||||
info.message("Failed to delete all records under " + basedn + ", " + res3.length + " records remaining\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function open_ldb(info, dbname, erase)
|
||||
{
|
||||
var ldb = ldb_init();
|
||||
ldb.session_info = info.session_info;
|
||||
ldb.credentials = info.credentials;
|
||||
ldb.filename = dbname;
|
||||
|
||||
var connect_ok = ldb.connect(dbname);
|
||||
if (!connect_ok) {
|
||||
var lp = loadparm_init();
|
||||
sys.unlink(sprintf("%s/%s", lp.get("private dir"), dbname));
|
||||
connect_ok = ldb.connect(dbname);
|
||||
assert(connect_ok);
|
||||
}
|
||||
|
||||
ldb.transaction_start();
|
||||
|
||||
if (erase) {
|
||||
ldb_erase(ldb);
|
||||
}
|
||||
return ldb;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup a ldb in the private dir
|
||||
*/
|
||||
function setup_add_ldif(ldif, info, ldb, failok)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var src = lp.get("setup directory") + "/" + ldif;
|
||||
|
||||
var data = sys.file_load(src);
|
||||
data = substitute_var(data, info.subobj);
|
||||
|
||||
var add_ok = ldb.add(data);
|
||||
if (!add_ok) {
|
||||
info.message("ldb load failed: " + ldb.errstring() + "\n");
|
||||
if (!failok) {
|
||||
assert(add_ok);
|
||||
}
|
||||
}
|
||||
return add_ok;
|
||||
}
|
||||
|
||||
function setup_modify_ldif(ldif, info, ldb, failok)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var src = lp.get("setup directory") + "/" + ldif;
|
||||
|
||||
var data = sys.file_load(src);
|
||||
data = substitute_var(data, info.subobj);
|
||||
|
||||
var mod_ok = ldb.modify(data);
|
||||
if (!mod_ok) {
|
||||
info.message("ldb load failed: " + ldb.errstring() + "\n");
|
||||
if (!failok) {
|
||||
assert(mod_ok);
|
||||
}
|
||||
}
|
||||
return mod_ok;
|
||||
}
|
||||
|
||||
|
||||
function setup_ldb(ldif, info, dbname)
|
||||
{
|
||||
var erase = true;
|
||||
var failok = false;
|
||||
|
||||
if (arguments.length >= 4) {
|
||||
erase = arguments[3];
|
||||
}
|
||||
if (arguments.length == 5) {
|
||||
failok = arguments[4];
|
||||
}
|
||||
var ldb = open_ldb(info, dbname, erase);
|
||||
if (setup_add_ldif(ldif, info, ldb, failok)) {
|
||||
var commit_ok = ldb.transaction_commit();
|
||||
if (!commit_ok) {
|
||||
info.message("ldb commit failed: " + ldb.errstring() + "\n");
|
||||
assert(commit_ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
setup a ldb in the private dir
|
||||
*/
|
||||
function setup_ldb_modify(ldif, info, ldb)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
|
||||
var src = lp.get("setup directory") + "/" + ldif;
|
||||
|
||||
var data = sys.file_load(src);
|
||||
data = substitute_var(data, info.subobj);
|
||||
|
||||
var mod_ok = ldb.modify(data);
|
||||
if (!mod_ok) {
|
||||
info.message("ldb load failed: " + ldb.errstring() + "\n");
|
||||
return mod_ok;
|
||||
}
|
||||
return mod_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
setup a file in the private dir
|
||||
*/
|
||||
function setup_file(template, message, fname, subobj)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var f = fname;
|
||||
var src = lp.get("setup directory") + "/" + template;
|
||||
|
||||
sys.unlink(f);
|
||||
|
||||
var data = sys.file_load(src);
|
||||
data = substitute_var(data, subobj);
|
||||
|
||||
ok = sys.file_save(f, data);
|
||||
if (!ok) {
|
||||
message("failed to create file: " + f + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
}
|
||||
|
||||
function provision_default_paths(subobj)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var paths = new Object();
|
||||
paths.smbconf = lp.get("config file");
|
||||
paths.shareconf = lp.get("private dir") + "/" + "share.ldb";
|
||||
paths.hklm = "hklm.ldb";
|
||||
paths.hkcu = "hkcu.ldb";
|
||||
paths.hkcr = "hkcr.ldb";
|
||||
paths.hku = "hku.ldb";
|
||||
paths.hkpd = "hkpd.ldb";
|
||||
paths.hkpt = "hkpt.ldb";
|
||||
paths.samdb = lp.get("sam database");
|
||||
paths.secrets = "secrets.ldb";
|
||||
paths.dns = lp.get("private dir") + "/" + subobj.DNSDOMAIN + ".zone";
|
||||
paths.winsdb = "wins.ldb";
|
||||
paths.ldap_basedn_ldif = lp.get("private dir") + "/" + subobj.DNSDOMAIN + ".ldif";
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
setup reasonable name mappings for sam names to unix names
|
||||
*/
|
||||
function setup_name_mappings(info, ldb)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var attrs = new Array("objectSid");
|
||||
var subobj = info.subobj;
|
||||
|
||||
res = ldb.search("objectSid=*", subobj.BASEDN, ldb.SCOPE_BASE, attrs);
|
||||
assert(res.length == 1 && res[0].objectSid != undefined);
|
||||
var sid = res[0].objectSid;
|
||||
|
||||
/* add some foreign sids if they are not present already */
|
||||
add_foreign(ldb, subobj, "S-1-5-7", "Anonymous");
|
||||
add_foreign(ldb, subobj, "S-1-1-0", "World");
|
||||
add_foreign(ldb, subobj, "S-1-5-2", "Network");
|
||||
add_foreign(ldb, subobj, "S-1-5-18", "System");
|
||||
add_foreign(ldb, subobj, "S-1-5-11", "Authenticated Users");
|
||||
|
||||
/* some well known sids */
|
||||
setup_name_mapping(info, ldb, "S-1-5-7", subobj.NOBODY);
|
||||
setup_name_mapping(info, ldb, "S-1-1-0", subobj.NOGROUP);
|
||||
setup_name_mapping(info, ldb, "S-1-5-2", subobj.NOGROUP);
|
||||
setup_name_mapping(info, ldb, "S-1-5-18", subobj.ROOT);
|
||||
setup_name_mapping(info, ldb, "S-1-5-11", subobj.USERS);
|
||||
setup_name_mapping(info, ldb, "S-1-5-32-544", subobj.WHEEL);
|
||||
setup_name_mapping(info, ldb, "S-1-5-32-545", subobj.USERS);
|
||||
setup_name_mapping(info, ldb, "S-1-5-32-546", subobj.NOGROUP);
|
||||
setup_name_mapping(info, ldb, "S-1-5-32-551", subobj.BACKUP);
|
||||
|
||||
/* and some well known domain rids */
|
||||
setup_name_mapping(info, ldb, sid + "-500", subobj.ROOT);
|
||||
setup_name_mapping(info, ldb, sid + "-518", subobj.WHEEL);
|
||||
setup_name_mapping(info, ldb, sid + "-519", subobj.WHEEL);
|
||||
setup_name_mapping(info, ldb, sid + "-512", subobj.WHEEL);
|
||||
setup_name_mapping(info, ldb, sid + "-513", subobj.USERS);
|
||||
setup_name_mapping(info, ldb, sid + "-520", subobj.WHEEL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
provision samba4 - caution, this wipes all existing data!
|
||||
*/
|
||||
function provision(subobj, message, blank, paths, session_info, credentials)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var sys = sys_init();
|
||||
var info = new Object();
|
||||
|
||||
/*
|
||||
some options need to be upper/lower case
|
||||
*/
|
||||
subobj.REALM = strupper(subobj.REALM);
|
||||
subobj.HOSTNAME = strlower(subobj.HOSTNAME);
|
||||
subobj.DOMAIN = strupper(subobj.DOMAIN);
|
||||
assert(valid_netbios_name(subobj.DOMAIN));
|
||||
subobj.NETBIOSNAME = strupper(subobj.HOSTNAME);
|
||||
assert(valid_netbios_name(subobj.NETBIOSNAME));
|
||||
var rdns = split(",", subobj.BASEDN);
|
||||
subobj.RDN_DC = substr(rdns[0], strlen("DC="));
|
||||
|
||||
if (subobj.DOMAINGUID != undefined) {
|
||||
subobj.DOMAINGUID_MOD = sprintf("replace: objectGUID\nobjectGUID: %s\n-", subobj.DOMAINGUID);
|
||||
} else {
|
||||
subobj.DOMAINGUID_MOD = "";
|
||||
}
|
||||
|
||||
if (subobj.HOSTGUID != undefined) {
|
||||
subobj.HOSTGUID_ADD = sprintf("objectGUID: %s", subobj.HOSTGUID);
|
||||
} else {
|
||||
subobj.HOSTGUID_ADD = "";
|
||||
}
|
||||
|
||||
info.subobj = subobj;
|
||||
info.message = message;
|
||||
info.credentials = credentials;
|
||||
info.session_info = session_info;
|
||||
|
||||
/* only install a new smb.conf if there isn't one there already */
|
||||
var st = sys.stat(paths.smbconf);
|
||||
if (st == undefined) {
|
||||
message("Setting up smb.conf\n");
|
||||
setup_file("provision.smb.conf", info.message, paths.smbconf, subobj);
|
||||
lp.reload();
|
||||
}
|
||||
/* only install a new shares config db if there is none */
|
||||
st = sys.stat(paths.shareconf);
|
||||
if (st == undefined) {
|
||||
message("Setting up share.ldb\n");
|
||||
setup_ldb("share.ldif", info, paths.shareconf);
|
||||
}
|
||||
message("Setting up secrets.ldb\n");
|
||||
setup_ldb("secrets.ldif", info, paths.secrets);
|
||||
message("Setting up keytabs\n");
|
||||
var keytab_ok = credentials_update_all_keytabs();
|
||||
assert(keytab_ok);
|
||||
message("Setting up hklm.ldb\n");
|
||||
setup_ldb("hklm.ldif", info, paths.hklm);
|
||||
|
||||
message("Setting up sam.ldb partitions\n");
|
||||
/* Also wipes the database */
|
||||
setup_ldb("provision_partitions.ldif", info, paths.samdb);
|
||||
|
||||
var samdb = open_ldb(info, paths.samdb, false);
|
||||
|
||||
message("Setting up sam.ldb attributes\n");
|
||||
setup_add_ldif("provision_init.ldif", info, samdb, false);
|
||||
message("Erasing data from partitions\n");
|
||||
ldb_erase_partitions(info, samdb);
|
||||
|
||||
message("Adding baseDN: " + subobj.BASEDN + " (permitted to fail)\n");
|
||||
var add_ok = setup_add_ldif("provision_basedn.ldif", info, samdb, true);
|
||||
message("Modifying baseDN: " + subobj.BASEDN + "\n");
|
||||
var modify_ok = setup_ldb_modify("provision_basedn_modify.ldif", info, samdb);
|
||||
if (!modify_ok) {
|
||||
if (!add_ok) {
|
||||
message("Failed to both add and modify " + subobj.BASEDN + " in target " + subobj.LDAPBACKEND + "\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("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);
|
||||
|
||||
// (hack) Reload, now we have the schema loaded.
|
||||
var commit_ok = samdb.transaction_commit();
|
||||
if (!commit_ok) {
|
||||
info.message("samdb commit failed: " + samdb.errstring() + "\n");
|
||||
assert(commit_ok);
|
||||
}
|
||||
samdb.close();
|
||||
|
||||
samdb = open_ldb(info, paths.samdb, false);
|
||||
|
||||
message("Setting up display specifiers\n");
|
||||
setup_add_ldif("display_specifiers.ldif", info, samdb, false);
|
||||
message("Setting up sam.ldb templates\n");
|
||||
setup_add_ldif("provision_templates.ldif", info, samdb, false);
|
||||
message("Setting up sam.ldb data\n");
|
||||
setup_add_ldif("provision.ldif", info, samdb, false);
|
||||
|
||||
if (blank != false) {
|
||||
message("Setting up sam.ldb index\n");
|
||||
setup_add_ldif("provision_index.ldif", info, samdb, false);
|
||||
|
||||
var commit_ok = samdb.transaction_commit();
|
||||
if (!commit_ok) {
|
||||
info.message("ldb commit failed: " + samdb.errstring() + "\n");
|
||||
assert(commit_ok);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// message("Activate schema module");
|
||||
// setup_modify_ldif("schema_activation.ldif", info, samdb, false);
|
||||
//
|
||||
// // (hack) Reload, now we have the schema loaded.
|
||||
// var commit_ok = samdb.transaction_commit();
|
||||
// if (!commit_ok) {
|
||||
// info.message("samdb commit failed: " + samdb.errstring() + "\n");
|
||||
// assert(commit_ok);
|
||||
// }
|
||||
// samdb.close();
|
||||
//
|
||||
// samdb = open_ldb(info, paths.samdb, false);
|
||||
//
|
||||
message("Setting up sam.ldb users and groups\n");
|
||||
setup_add_ldif("provision_users.ldif", info, samdb, false);
|
||||
|
||||
if (setup_name_mappings(info, samdb) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
message("Setting up sam.ldb index\n");
|
||||
setup_add_ldif("provision_index.ldif", info, samdb, false);
|
||||
|
||||
var commit_ok = samdb.transaction_commit();
|
||||
if (!commit_ok) {
|
||||
info.message("samdb commit failed: " + samdb.errstring() + "\n");
|
||||
assert(commit_ok);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Write out a DNS zone file, from the info in the current database */
|
||||
function provision_dns(subobj, message, paths, session_info, credentials)
|
||||
{
|
||||
message("Setting up DNS zone: " + subobj.DNSDOMAIN + " \n");
|
||||
var ldb = ldb_init();
|
||||
ldb.session_info = session_info;
|
||||
ldb.credentials = credentials;
|
||||
|
||||
/* connect to the sam */
|
||||
var ok = ldb.connect(paths.samdb);
|
||||
assert(ok);
|
||||
|
||||
/* These values may have changed, due to an incoming SamSync,
|
||||
or may not have been specified, so fetch them from the database */
|
||||
|
||||
var attrs = new Array("objectGUID");
|
||||
res = ldb.search("objectGUID=*", subobj.BASEDN, ldb.SCOPE_BASE, attrs);
|
||||
assert(res.length == 1);
|
||||
assert(res[0].objectGUID != undefined);
|
||||
subobj.DOMAINGUID = res[0].objectGUID;
|
||||
|
||||
subobj.HOSTGUID = searchone(ldb, subobj.BASEDN, "(&(objectClass=computer)(cn=" + subobj.NETBIOSNAME + "))", "objectGUID");
|
||||
assert(subobj.HOSTGUID != undefined);
|
||||
|
||||
setup_file("provision.zone",
|
||||
message, paths.dns,
|
||||
subobj);
|
||||
|
||||
message("Please install the zone located in " + paths.dns + " into your DNS server\n");
|
||||
}
|
||||
|
||||
/* Write out a DNS zone file, from the info in the current database */
|
||||
function provision_ldapbase(subobj, message, paths)
|
||||
{
|
||||
message("Setting up LDAP base entry: " + subobj.BASEDN + " \n");
|
||||
var rdns = split(",", subobj.BASEDN);
|
||||
subobj.EXTENSIBLEOBJECT = "objectClass: extensibleObject";
|
||||
|
||||
subobj.RDN_DC = substr(rdns[0], strlen("DC="));
|
||||
|
||||
setup_file("provision_basedn.ldif",
|
||||
message, paths.ldap_basedn_ldif,
|
||||
subobj);
|
||||
|
||||
message("Please install the LDIF located in " + paths.ldap_basedn_ldif + " into your LDAP server, and re-run with --ldap-backend=ldap://my.ldap.server\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
guess reasonably default options for provisioning
|
||||
*/
|
||||
function provision_guess()
|
||||
{
|
||||
var subobj = new Object();
|
||||
var nss = nss_init();
|
||||
var lp = loadparm_init();
|
||||
var rdn_list;
|
||||
random_init(local);
|
||||
|
||||
subobj.REALM = strupper(lp.get("realm"));
|
||||
subobj.DOMAIN = lp.get("workgroup");
|
||||
subobj.HOSTNAME = hostname();
|
||||
|
||||
assert(subobj.REALM);
|
||||
assert(subobj.DOMAIN);
|
||||
assert(subobj.HOSTNAME);
|
||||
|
||||
subobj.VERSION = version();
|
||||
subobj.HOSTIP = hostip();
|
||||
subobj.DOMAINSID = randsid();
|
||||
subobj.INVOCATIONID = randguid();
|
||||
subobj.KRBTGTPASS = randpass(12);
|
||||
subobj.MACHINEPASS = randpass(12);
|
||||
subobj.ADMINPASS = randpass(12);
|
||||
subobj.DEFAULTSITE = "Default-First-Site-Name";
|
||||
subobj.NEWGUID = randguid;
|
||||
subobj.NTTIME = nttime;
|
||||
subobj.LDAPTIME = ldaptime;
|
||||
subobj.DATESTRING = datestring;
|
||||
subobj.ROOT = findnss(nss.getpwnam, "root");
|
||||
subobj.NOBODY = findnss(nss.getpwnam, "nobody");
|
||||
subobj.NOGROUP = findnss(nss.getgrnam, "nogroup", "nobody");
|
||||
subobj.WHEEL = findnss(nss.getgrnam, "wheel", "root", "staff", "adm");
|
||||
subobj.BACKUP = findnss(nss.getgrnam, "backup", "wheel", "root", "staff");
|
||||
subobj.USERS = findnss(nss.getgrnam, "users", "guest", "other", "unknown", "usr");
|
||||
subobj.DNSDOMAIN = strlower(subobj.REALM);
|
||||
subobj.DNSNAME = sprintf("%s.%s",
|
||||
strlower(subobj.HOSTNAME),
|
||||
subobj.DNSDOMAIN);
|
||||
rdn_list = split(".", subobj.DNSDOMAIN);
|
||||
subobj.BASEDN = "DC=" + join(",DC=", rdn_list);
|
||||
subobj.LDAPBACKEND = "users.ldb";
|
||||
subobj.LDAPMODULES = "objectguid";
|
||||
subobj.EXTENSIBLEOBJECT = "# no objectClass: extensibleObject for local ldb";
|
||||
return subobj;
|
||||
}
|
||||
|
||||
/*
|
||||
search for one attribute as a string
|
||||
*/
|
||||
function searchone(ldb, basedn, expression, attribute)
|
||||
{
|
||||
var attrs = new Array(attribute);
|
||||
res = ldb.search(expression, basedn, ldb.SCOPE_SUBTREE, attrs);
|
||||
if (res.length != 1 ||
|
||||
res[0][attribute] == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return res[0][attribute];
|
||||
}
|
||||
|
||||
/*
|
||||
modify an account to remove the
|
||||
*/
|
||||
function enable_account(ldb, user_dn)
|
||||
{
|
||||
var attrs = new Array("userAccountControl");
|
||||
var res = ldb.search(NULL, user_dn, ldb.SCOPE_ONELEVEL, attrs);
|
||||
assert(res.length == 1);
|
||||
var userAccountControl = res[0].userAccountControl;
|
||||
userAccountControl = userAccountControl - 2; /* remove disabled bit */
|
||||
var mod = sprintf("
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: userAccountControl
|
||||
userAccountControl: %u
|
||||
",
|
||||
user_dn, userAccountControl);
|
||||
var ok = ldb.modify(mod);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
add a new user record
|
||||
*/
|
||||
function newuser(username, unixname, password, message, session_info, credentials)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
var samdb = lp.get("sam database");
|
||||
var ldb = ldb_init();
|
||||
random_init(local);
|
||||
ldb.session_info = session_info;
|
||||
ldb.credentials = credentials;
|
||||
|
||||
/* connect to the sam */
|
||||
var ok = ldb.connect(samdb);
|
||||
assert(ok);
|
||||
|
||||
ldb.transaction_start();
|
||||
|
||||
/* find the DNs for the domain and the domain users group */
|
||||
var attrs = new Array("defaultNamingContext");
|
||||
res = ldb.search("defaultNamingContext=*", "", ldb.SCOPE_BASE, attrs);
|
||||
assert(res.length == 1 && res[0].defaultNamingContext != undefined);
|
||||
var domain_dn = res[0].defaultNamingContext;
|
||||
assert(domain_dn != undefined);
|
||||
var dom_users = searchone(ldb, domain_dn, "name=Domain Users", "dn");
|
||||
assert(dom_users != undefined);
|
||||
|
||||
var user_dn = sprintf("CN=%s,CN=Users,%s", username, domain_dn);
|
||||
|
||||
|
||||
/*
|
||||
the new user record. note the reliance on the samdb module to fill
|
||||
in a sid, guid etc
|
||||
*/
|
||||
var ldif = sprintf("
|
||||
dn: %s
|
||||
sAMAccountName: %s
|
||||
memberOf: %s
|
||||
unixName: %s
|
||||
sambaPassword: %s
|
||||
objectClass: user
|
||||
",
|
||||
user_dn, username, dom_users,
|
||||
unixname, password);
|
||||
/*
|
||||
add the user to the users group as well
|
||||
*/
|
||||
var modgroup = sprintf("
|
||||
dn: %s
|
||||
changetype: modify
|
||||
add: member
|
||||
member: %s
|
||||
",
|
||||
dom_users, user_dn);
|
||||
|
||||
|
||||
/*
|
||||
now the real work
|
||||
*/
|
||||
message("Adding user %s\n", user_dn);
|
||||
ok = ldb.add(ldif);
|
||||
if (ok != true) {
|
||||
message("Failed to add %s - %s\n", user_dn, ldb.errstring());
|
||||
return false;
|
||||
}
|
||||
|
||||
message("Modifying group %s\n", dom_users);
|
||||
ok = ldb.modify(modgroup);
|
||||
if (ok != true) {
|
||||
message("Failed to modify %s - %s\n", dom_users, ldb.errstring());
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
modify the userAccountControl to remove the disabled bit
|
||||
*/
|
||||
ok = enable_account(ldb, user_dn);
|
||||
if (ok) {
|
||||
ldb.transaction_commit();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Check whether a name is valid as a NetBIOS name.
|
||||
// FIXME: There are probably more constraints here.
|
||||
// crh has a paragraph on this in his book (1.4.1.1)
|
||||
function valid_netbios_name(name)
|
||||
{
|
||||
if (strlen(name) > 13) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function provision_validate(subobj, message)
|
||||
{
|
||||
var lp = loadparm_init();
|
||||
|
||||
if (!valid_netbios_name(subobj.DOMAIN)) {
|
||||
message("Invalid NetBIOS name for domain\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!valid_netbios_name(subobj.NETBIOSNAME)) {
|
||||
message("Invalid NetBIOS name for host\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (strupper(lp.get("workgroup")) != strupper(subobj.DOMAIN)) {
|
||||
message("workgroup '%s' in smb.conf must match chosen domain '%s'\n",
|
||||
lp.get("workgroup"), subobj.DOMAIN);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strupper(lp.get("realm")) != strupper(subobj.REALM)) {
|
||||
message("realm '%s' in smb.conf must match chosen realm '%s'\n",
|
||||
lp.get("realm"), subobj.REALM);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function join_domain(domain, netbios_name, join_type, creds, message)
|
||||
{
|
||||
var ctx = NetContext(creds);
|
||||
var joindom = new Object();
|
||||
joindom.domain = domain;
|
||||
joindom.join_type = join_type;
|
||||
joindom.netbios_name = netbios_name;
|
||||
if (!ctx.JoinDomain(joindom)) {
|
||||
message("Domain Join failed: " + joindom.error_string);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Vampire a remote domain. Session info and credentials are required for for
|
||||
* access to our local database (might be remote ldap)
|
||||
*/
|
||||
|
||||
function vampire(domain, session_info, credentials, message) {
|
||||
var ctx = NetContext(credentials);
|
||||
var vampire_ctx = new Object();
|
||||
var machine_creds = credentials_init();
|
||||
machine_creds.set_domain(form.DOMAIN);
|
||||
if (!machine_creds.set_machine_account()) {
|
||||
message("Failed to access domain join information!");
|
||||
return false;
|
||||
}
|
||||
vampire_ctx.machine_creds = machine_creds;
|
||||
vampire_ctx.session_info = session_info;
|
||||
if (!ctx.SamSyncLdb(vampire_ctx)) {
|
||||
message("Migration of remote domain to Samba failed: " + vampire_ctx.error_string);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
samr rpc utility functions
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
if (global["HAVE_SAMR_JS"] != undefined) {
|
||||
return;
|
||||
}
|
||||
HAVE_SAMR_JS=1
|
||||
|
||||
/*
|
||||
return a list of names and indexes from a samArray
|
||||
*/
|
||||
function samArray(output)
|
||||
{
|
||||
var list = new Array(output.num_entries);
|
||||
if (output.sam == NULL) {
|
||||
return list;
|
||||
}
|
||||
var i, entries = output.sam.entries;
|
||||
for (i=0;i<output.num_entries;i++) {
|
||||
list[i] = new Object();
|
||||
list[i].name = entries[i].name;
|
||||
list[i].idx = entries[i].idx;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
connect to the sam database
|
||||
*/
|
||||
function samrConnect(conn)
|
||||
{
|
||||
security_init(conn);
|
||||
var io = irpcObj();
|
||||
io.input.system_name = NULL;
|
||||
io.input.access_mask = conn.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
var status = conn.samr_Connect2(io);
|
||||
check_status_ok(status);
|
||||
return io.output.connect_handle;
|
||||
}
|
||||
|
||||
/*
|
||||
close a handle
|
||||
*/
|
||||
function samrClose(conn, handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
var status = conn.samr_Close(io);
|
||||
check_status_ok(status);
|
||||
}
|
||||
|
||||
/*
|
||||
get the sid for a domain
|
||||
*/
|
||||
function samrLookupDomain(conn, handle, domain)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.connect_handle = handle;
|
||||
io.input.domain_name = domain;
|
||||
var status = conn.samr_LookupDomain(io);
|
||||
check_status_ok(status);
|
||||
return io.output.sid;
|
||||
}
|
||||
|
||||
/*
|
||||
open a domain by sid
|
||||
*/
|
||||
function samrOpenDomain(conn, handle, sid)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.connect_handle = handle;
|
||||
io.input.access_mask = conn.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
io.input.sid = sid;
|
||||
var status = conn.samr_OpenDomain(io);
|
||||
check_status_ok(status);
|
||||
return io.output.domain_handle;
|
||||
}
|
||||
|
||||
/*
|
||||
open a user by rid
|
||||
*/
|
||||
function samrOpenUser(conn, handle, rid)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.domain_handle = handle;
|
||||
io.input.access_mask = conn.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
io.input.rid = rid;
|
||||
var status = conn.samr_OpenUser(io);
|
||||
check_status_ok(status);
|
||||
return io.output.user_handle;
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of all users
|
||||
*/
|
||||
function samrEnumDomainUsers(conn, dom_handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.domain_handle = dom_handle;
|
||||
io.input.resume_handle = 0;
|
||||
io.input.acct_flags = 0;
|
||||
io.input.max_size = -1;
|
||||
var status = conn.samr_EnumDomainUsers(io);
|
||||
check_status_ok(status);
|
||||
return samArray(io.output);
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of all groups
|
||||
*/
|
||||
function samrEnumDomainGroups(conn, dom_handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.domain_handle = dom_handle;
|
||||
io.input.resume_handle = 0;
|
||||
io.input.acct_flags = 0;
|
||||
io.input.max_size = -1;
|
||||
var status = conn.samr_EnumDomainGroups(io);
|
||||
check_status_ok(status);
|
||||
return samArray(io.output);
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of domains
|
||||
*/
|
||||
function samrEnumDomains(conn, handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.connect_handle = handle;
|
||||
io.input.resume_handle = 0;
|
||||
io.input.buf_size = -1;
|
||||
var status = conn.samr_EnumDomains(io);
|
||||
check_status_ok(status);
|
||||
return samArray(io.output);
|
||||
}
|
||||
|
||||
/*
|
||||
return information about a user
|
||||
*/
|
||||
function samrQueryUserInfo(conn, user_handle, level)
|
||||
{
|
||||
var r, io = irpcObj();
|
||||
io.input.user_handle = user_handle;
|
||||
io.input.level = level;
|
||||
var status = conn.samr_QueryUserInfo(io);
|
||||
check_status_ok(status);
|
||||
return io.output.info.info3;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
fill a user array with user information from samrQueryUserInfo
|
||||
*/
|
||||
function samrFillUserInfo(conn, dom_handle, users, level)
|
||||
{
|
||||
var i;
|
||||
for (i=0;i<users.length;i++) {
|
||||
var r, user_handle, info;
|
||||
user_handle = samrOpenUser(conn, dom_handle, users[i].idx);
|
||||
info = samrQueryUserInfo(conn, user_handle, level);
|
||||
info.name = users[i].name;
|
||||
info.idx = users[i].idx;
|
||||
users[i] = info;
|
||||
samrClose(conn, user_handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
server side js functions for handling async calls from js clients
|
||||
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL Version 2 or later
|
||||
*/
|
||||
|
||||
libinclude("encoder.js");
|
||||
|
||||
/*
|
||||
register a new call
|
||||
*/
|
||||
function __register_call(name, func)
|
||||
{
|
||||
var c = this;
|
||||
c.calls[name] = func;
|
||||
}
|
||||
|
||||
/*
|
||||
run a call sent from the client, and output the returned object (if any)
|
||||
*/
|
||||
function __run_call() {
|
||||
var c = this;
|
||||
var name = form['ajaj_func'];
|
||||
if (name == undefined) {
|
||||
/* no function to run */
|
||||
return;
|
||||
}
|
||||
var args = form['ajaj_args'];
|
||||
if (args == undefined) {
|
||||
println("no function arguments given in run_call");
|
||||
exit(0);
|
||||
}
|
||||
args = decodeObject(args);
|
||||
if (c.calls[name] == undefined) {
|
||||
println("undefined remote call " + name);
|
||||
exit(0);
|
||||
}
|
||||
var f = c.calls[name];
|
||||
var res;
|
||||
/* oh what a hack - should write a varargs ejs helper */
|
||||
if (args.length == 0) {
|
||||
res = f();
|
||||
} else if (args.length == 1) {
|
||||
res = f(args[0]);
|
||||
} else if (args.length == 2) {
|
||||
res = f(args[0], args[1]);
|
||||
} else if (args.length == 3) {
|
||||
res = f(args[0], args[1], args[2]);
|
||||
} else if (args.length == 4) {
|
||||
res = f(args[0], args[1], args[2], args[3]);
|
||||
} else if (args.length == 5) {
|
||||
res = f(args[0], args[1], args[2], args[3], args[4]);
|
||||
} else if (args.length == 6) {
|
||||
res = f(args[0], args[1], args[2], args[3], args[4], args[5]);
|
||||
} else if (args.length == 7) {
|
||||
res = f(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
|
||||
} else if (args.length == 8) {
|
||||
res = f(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
|
||||
} else {
|
||||
println("too many arguments for remote call: " + name);
|
||||
exit(0);
|
||||
}
|
||||
var repobj = new Object();
|
||||
repobj.res = res;
|
||||
write(encodeObject(repobj));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
initialise a server call object
|
||||
*/
|
||||
function servCallObj()
|
||||
{
|
||||
var c = new Object();
|
||||
c.add = __register_call;
|
||||
c.run = __run_call;
|
||||
c.calls = new Object();
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,674 @@
|
||||
/*
|
||||
backend code for upgrading from Samba3
|
||||
Copyright Jelmer Vernooij 2005
|
||||
Released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
libinclude("base.js");
|
||||
|
||||
function regkey_to_dn(name)
|
||||
{
|
||||
var dn = "hive=NONE";
|
||||
var i = 0;
|
||||
|
||||
var as = split("/", name);
|
||||
|
||||
for (i in as) {
|
||||
if (i > 0) {
|
||||
dn = sprintf("key=%s,", as[i]) + dn;
|
||||
}
|
||||
}
|
||||
|
||||
return dn;
|
||||
}
|
||||
|
||||
/* Where prefix is any of:
|
||||
* - HKLM
|
||||
* HKU
|
||||
* HKCR
|
||||
* HKPD
|
||||
* HKPT
|
||||
*/
|
||||
|
||||
function upgrade_registry(regdb,prefix,ldb)
|
||||
{
|
||||
assert(regdb != undefined);
|
||||
var prefix_up = strupper(prefix);
|
||||
var ldif = new Array();
|
||||
|
||||
for (var i in regdb.keys) {
|
||||
var rk = regdb.keys[i];
|
||||
var pts = split("/", rk.name);
|
||||
|
||||
/* Only handle selected hive */
|
||||
if (strupper(pts[0]) != prefix_up) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var keydn = regkey_to_dn(rk.name);
|
||||
|
||||
var pts = split("/", rk.name);
|
||||
|
||||
/* Convert key name to dn */
|
||||
ldif[rk.name] = sprintf("
|
||||
dn: %s
|
||||
name: %s
|
||||
|
||||
", keydn, pts[0]);
|
||||
|
||||
for (var j in rk.values) {
|
||||
var rv = rk.values[j];
|
||||
|
||||
ldif[rk.name + " (" + rv.name + ")"] = sprintf("
|
||||
dn: %s,value=%s
|
||||
value: %s
|
||||
type: %d
|
||||
data:: %s", keydn, rv.name, rv.name, rv.type, ldb.encode(rv.data));
|
||||
}
|
||||
}
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_sam_policy(samba3,dn)
|
||||
{
|
||||
var ldif = sprintf("
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: minPwdLength
|
||||
minPwdLength: %d
|
||||
pwdHistoryLength: %d
|
||||
minPwdAge: %d
|
||||
maxPwdAge: %d
|
||||
lockoutDuration: %d
|
||||
samba3ResetCountMinutes: %d
|
||||
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
|
||||
);
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_sam_account(ldb,acc,domaindn,domainsid)
|
||||
{
|
||||
if (acc.nt_username == undefined) {
|
||||
acc.nt_username = acc.username;
|
||||
}
|
||||
|
||||
if (acc.nt_username == "") {
|
||||
acc.nt_username = acc.username;
|
||||
}
|
||||
|
||||
if (acc.fullname == undefined) {
|
||||
var pw = nss.getpwnam(acc.fullname);
|
||||
acc.fullname = pw.pw_gecos;
|
||||
}
|
||||
|
||||
var pts = split(',', acc.fullname);
|
||||
acc.fullname = pts[0];
|
||||
|
||||
if (acc.fullname == undefined) {
|
||||
acc.fullname = acc.username;
|
||||
}
|
||||
|
||||
assert(acc.fullname != undefined);
|
||||
assert(acc.nt_username != undefined);
|
||||
|
||||
var ldif = sprintf(
|
||||
"dn: cn=%s,%s
|
||||
objectClass: top
|
||||
objectClass: user
|
||||
lastLogon: %d
|
||||
lastLogoff: %d
|
||||
unixName: %s
|
||||
sAMAccountName: %s
|
||||
cn: %s
|
||||
description: %s
|
||||
primaryGroupID: %d
|
||||
badPwdcount: %d
|
||||
logonCount: %d
|
||||
samba3Domain: %s
|
||||
samba3DirDrive: %s
|
||||
samba3MungedDial: %s
|
||||
samba3Homedir: %s
|
||||
samba3LogonScript: %s
|
||||
samba3ProfilePath: %s
|
||||
samba3Workstations: %s
|
||||
samba3KickOffTime: %d
|
||||
samba3BadPwdTime: %d
|
||||
samba3PassLastSetTime: %d
|
||||
samba3PassCanChangeTime: %d
|
||||
samba3PassMustChangeTime: %d
|
||||
objectSid: %s-%d
|
||||
lmPwdHash:: %s
|
||||
ntPwdHash:: %s
|
||||
|
||||
", ldb.dn_escape(acc.fullname), domaindn, acc.logon_time, acc.logoff_time, acc.username, acc.nt_username, acc.nt_username,
|
||||
|
||||
acc.acct_desc, acc.group_rid, acc.bad_password_count, acc.logon_count,
|
||||
acc.domain, acc.dir_drive, acc.munged_dial, acc.homedir, acc.logon_script,
|
||||
acc.profile_path, acc.workstations, acc.kickoff_time, acc.bad_password_time,
|
||||
acc.pass_last_set_time, acc.pass_can_change_time, acc.pass_must_change_time, domainsid, acc.user_rid,
|
||||
ldb.encode(acc.lm_pw), ldb.encode(acc.nt_pw));
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_sam_group(grp,domaindn)
|
||||
{
|
||||
var nss = nss_init();
|
||||
|
||||
var gr;
|
||||
if (grp.sid_name_use == 5) { // Well-known group
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (grp.nt_name == "Domain Guests" ||
|
||||
grp.nt_name == "Domain Users" ||
|
||||
grp.nt_name == "Domain Admins") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (grp.gid == -1) {
|
||||
gr = nss.getgrnam(grp.nt_name);
|
||||
} else {
|
||||
gr = nss.getgrgid(grp.gid);
|
||||
}
|
||||
|
||||
if (gr == undefined) {
|
||||
grp.unixname = "UNKNOWN";
|
||||
} else {
|
||||
grp.unixname = gr.gr_name;
|
||||
}
|
||||
|
||||
assert(grp.unixname != undefined);
|
||||
|
||||
var ldif = sprintf(
|
||||
"dn: cn=%s,%s
|
||||
objectClass: top
|
||||
objectClass: group
|
||||
description: %s
|
||||
cn: %s
|
||||
objectSid: %s
|
||||
unixName: %s
|
||||
samba3SidNameUse: %d
|
||||
", grp.nt_name, domaindn,
|
||||
grp.comment, grp.nt_name, grp.sid, grp.unixname, grp.sid_name_use);
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_winbind(samba3,domaindn)
|
||||
{
|
||||
var ldif = sprintf("
|
||||
|
||||
dn: dc=none
|
||||
userHwm: %d
|
||||
groupHwm: %d
|
||||
|
||||
", samba3.idmap.user_hwm, samba3.idmap.group_hwm);
|
||||
|
||||
for (var i in samba3.idmap.mappings) {
|
||||
var m = samba3.idmap.mappings[i];
|
||||
ldif = ldif + sprintf("
|
||||
dn: SID=%s,%s
|
||||
SID: %s
|
||||
type: %d
|
||||
unixID: %d", m.sid, domaindn, m.sid, m.type, m.unix_id);
|
||||
}
|
||||
|
||||
return ldif;
|
||||
}
|
||||
*/
|
||||
|
||||
function upgrade_wins(samba3)
|
||||
{
|
||||
var ldif = "";
|
||||
var version_id = 0;
|
||||
|
||||
for (i in samba3.winsentries) {
|
||||
var rType;
|
||||
var rState;
|
||||
var nType;
|
||||
var numIPs = 0;
|
||||
var e = samba3.winsentries[i];
|
||||
var now = sys.nttime();
|
||||
var ttl = sys.unix2nttime(e.ttl);
|
||||
|
||||
version_id++;
|
||||
|
||||
for (var i in e.ips) {
|
||||
numIPs++;
|
||||
}
|
||||
|
||||
if (e.type == 0x1C) {
|
||||
rType = 0x2;
|
||||
} else if (sys.bitAND(e.type, 0x80)) {
|
||||
if (numIPs > 1) {
|
||||
rType = 0x2;
|
||||
} else {
|
||||
rType = 0x1;
|
||||
}
|
||||
} else {
|
||||
if (numIPs > 1) {
|
||||
rType = 0x3;
|
||||
} else {
|
||||
rType = 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ttl > now) {
|
||||
rState = 0x0;/* active */
|
||||
} else {
|
||||
rState = 0x1;/* released */
|
||||
}
|
||||
|
||||
nType = (sys.bitAND(e.nb_flags,0x60)>>5);
|
||||
|
||||
ldif = ldif + sprintf("
|
||||
dn: name=%s,type=0x%02X
|
||||
type: 0x%02X
|
||||
name: %s
|
||||
objectClass: winsRecord
|
||||
recordType: %u
|
||||
recordState: %u
|
||||
nodeType: %u
|
||||
isStatic: 0
|
||||
expireTime: %s
|
||||
versionID: %llu
|
||||
", e.name, e.type, e.type, e.name,
|
||||
rType, rState, nType,
|
||||
sys.ldaptime(ttl), version_id);
|
||||
|
||||
for (var i in e.ips) {
|
||||
ldif = ldif + sprintf("address: %s\n", e.ips[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ldif = ldif + sprintf("
|
||||
dn: CN=VERSION
|
||||
objectClass: winsMaxVersion
|
||||
maxVersion: %llu
|
||||
", version_id);
|
||||
|
||||
return ldif;
|
||||
}
|
||||
|
||||
function upgrade_provision(samba3)
|
||||
{
|
||||
var subobj = new Object();
|
||||
var nss = nss_init();
|
||||
var lp = loadparm_init();
|
||||
var rdn_list;
|
||||
|
||||
var domainname = samba3.configuration.get("workgroup");
|
||||
|
||||
if (domainname == undefined) {
|
||||
domainname = samba3.secrets.domains[0].name;
|
||||
println("No domain specified in smb.conf file, assuming '" + domainname + "'");
|
||||
}
|
||||
|
||||
var domsec = samba3.find_domainsecrets(domainname);
|
||||
var hostsec = samba3.find_domainsecrets(hostname());
|
||||
var realm = samba3.configuration.get("realm");
|
||||
|
||||
if (realm == undefined) {
|
||||
realm = domainname;
|
||||
println("No realm specified in smb.conf file, assuming '" + realm + "'");
|
||||
}
|
||||
random_init(local);
|
||||
|
||||
subobj.REALM = realm;
|
||||
subobj.DOMAIN = domainname;
|
||||
subobj.HOSTNAME = hostname();
|
||||
|
||||
assert(subobj.REALM);
|
||||
assert(subobj.DOMAIN);
|
||||
assert(subobj.HOSTNAME);
|
||||
|
||||
subobj.HOSTIP = hostip();
|
||||
if (domsec != undefined) {
|
||||
subobj.DOMAINGUID = domsec.guid;
|
||||
subobj.DOMAINSID = domsec.sid;
|
||||
} else {
|
||||
println("Can't find domain secrets for '" + domainname + "'; using random SID and GUID");
|
||||
subobj.DOMAINGUID = randguid();
|
||||
subobj.DOMAINSID = randsid();
|
||||
}
|
||||
|
||||
if (hostsec) {
|
||||
subobj.HOSTGUID = hostsec.guid;
|
||||
} else {
|
||||
subobj.HOSTGUID = randguid();
|
||||
}
|
||||
subobj.INVOCATIONID = randguid();
|
||||
subobj.KRBTGTPASS = randpass(12);
|
||||
subobj.MACHINEPASS = randpass(12);
|
||||
subobj.ADMINPASS = randpass(12);
|
||||
subobj.DEFAULTSITE = "Default-First-Site-Name";
|
||||
subobj.NEWGUID = randguid;
|
||||
subobj.NTTIME = nttime;
|
||||
subobj.LDAPTIME = ldaptime;
|
||||
subobj.DATESTRING = datestring;
|
||||
subobj.USN = nextusn;
|
||||
subobj.ROOT = findnss(nss.getpwnam, "root");
|
||||
subobj.NOBODY = findnss(nss.getpwnam, "nobody");
|
||||
subobj.NOGROUP = findnss(nss.getgrnam, "nogroup", "nobody");
|
||||
subobj.WHEEL = findnss(nss.getgrnam, "wheel", "root");
|
||||
subobj.USERS = findnss(nss.getgrnam, "users", "guest", "other");
|
||||
subobj.DNSDOMAIN = strlower(subobj.REALM);
|
||||
subobj.DNSNAME = sprintf("%s.%s",
|
||||
strlower(subobj.HOSTNAME),
|
||||
subobj.DNSDOMAIN);
|
||||
subobj.BASEDN = "DC=" + join(",DC=", split(".", subobj.REALM));
|
||||
rdn_list = split(".", subobj.REALM);
|
||||
return subobj;
|
||||
}
|
||||
|
||||
smbconf_keep = new Array(
|
||||
"dos charset",
|
||||
"unix charset",
|
||||
"display charset",
|
||||
"comment",
|
||||
"path",
|
||||
"directory",
|
||||
"workgroup",
|
||||
"realm",
|
||||
"netbios name",
|
||||
"netbios aliases",
|
||||
"netbios scope",
|
||||
"server string",
|
||||
"interfaces",
|
||||
"bind interfaces only",
|
||||
"security",
|
||||
"auth methods",
|
||||
"encrypt passwords",
|
||||
"null passwords",
|
||||
"obey pam restrictions",
|
||||
"password server",
|
||||
"smb passwd file",
|
||||
"private dir",
|
||||
"passwd chat",
|
||||
"password level",
|
||||
"lanman auth",
|
||||
"ntlm auth",
|
||||
"client NTLMv2 auth",
|
||||
"client lanman auth",
|
||||
"client plaintext auth",
|
||||
"read only",
|
||||
"hosts allow",
|
||||
"hosts deny",
|
||||
"log level",
|
||||
"debuglevel",
|
||||
"log file",
|
||||
"smb ports",
|
||||
"large readwrite",
|
||||
"max protocol",
|
||||
"min protocol",
|
||||
"unicode",
|
||||
"read raw",
|
||||
"write raw",
|
||||
"disable netbios",
|
||||
"nt status support",
|
||||
"announce version",
|
||||
"announce as",
|
||||
"max mux",
|
||||
"max xmit",
|
||||
"name resolve order",
|
||||
"max wins ttl",
|
||||
"min wins ttl",
|
||||
"time server",
|
||||
"unix extensions",
|
||||
"use spnego",
|
||||
"server signing",
|
||||
"client signing",
|
||||
"max connections",
|
||||
"paranoid server security",
|
||||
"socket options",
|
||||
"strict sync",
|
||||
"max print jobs",
|
||||
"printable",
|
||||
"print ok",
|
||||
"printer name",
|
||||
"printer",
|
||||
"map system",
|
||||
"map hidden",
|
||||
"map archive",
|
||||
"preferred master",
|
||||
"prefered master",
|
||||
"local master",
|
||||
"browseable",
|
||||
"browsable",
|
||||
"wins server",
|
||||
"wins support",
|
||||
"csc policy",
|
||||
"strict locking",
|
||||
"config file",
|
||||
"preload",
|
||||
"auto services",
|
||||
"lock dir",
|
||||
"lock directory",
|
||||
"pid directory",
|
||||
"socket address",
|
||||
"copy",
|
||||
"include",
|
||||
"available",
|
||||
"volume",
|
||||
"fstype",
|
||||
"panic action",
|
||||
"msdfs root",
|
||||
"host msdfs",
|
||||
"winbind separator");
|
||||
|
||||
/*
|
||||
Remove configuration variables not present in Samba4
|
||||
oldconf: Old configuration structure
|
||||
mark: Whether removed configuration variables should be
|
||||
kept in the new configuration as "samba3:<name>"
|
||||
*/
|
||||
function upgrade_smbconf(oldconf,mark)
|
||||
{
|
||||
var data = oldconf.data();
|
||||
var newconf = param_init();
|
||||
|
||||
for (var s in data) {
|
||||
for (var p in data[s]) {
|
||||
var keep = false;
|
||||
for (var k in smbconf_keep) {
|
||||
if (smbconf_keep[k] == p) {
|
||||
keep = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (keep) {
|
||||
newconf.set(s, p, oldconf.get(s, p));
|
||||
} else if (mark) {
|
||||
newconf.set(s, "samba3:"+p, oldconf.get(s,p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (oldconf.get("domain logons") == "True") {
|
||||
if (oldconf.get("domain master") == "True") {
|
||||
newconf.set("server role", "pdc");
|
||||
} else {
|
||||
newconf.set("server role", "bdc");
|
||||
}
|
||||
} else {
|
||||
if (oldconf.get("domain master") == "True") {
|
||||
newconf.set("server role", "standalone");
|
||||
} else {
|
||||
newconf.set("server role", "member server");
|
||||
}
|
||||
}
|
||||
|
||||
return newconf;
|
||||
}
|
||||
|
||||
function upgrade(subobj, samba3, message, paths, session_info, credentials)
|
||||
{
|
||||
var ret = 0;
|
||||
var lp = loadparm_init();
|
||||
var samdb = ldb_init();
|
||||
samdb.session_info = session_info;
|
||||
samdb.credentials = credentials;
|
||||
var ok = samdb.connect(paths.samdb);
|
||||
if (!ok) {
|
||||
info.message("samdb connect failed: " + samdb.errstring() + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
message("Writing configuration\n");
|
||||
var newconf = upgrade_smbconf(samba3.configuration,true);
|
||||
newconf.save(paths.smbconf);
|
||||
|
||||
message("Importing account policies\n");
|
||||
var ldif = upgrade_sam_policy(samba3,subobj.BASEDN);
|
||||
ok = samdb.modify(ldif);
|
||||
if (!ok) {
|
||||
message("samdb load failed: " + samdb.errstring() + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
var regdb = ldb_init();
|
||||
ok = regdb.connect(paths.hklm);
|
||||
if (!ok) {
|
||||
message("registry connect: " + regdb.errstring() + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
ok = regdb.modify(sprintf("
|
||||
dn: value=RefusePasswordChange,key=Parameters,key=Netlogon,key=Services,key=CurrentControlSet,key=System,HIVE=NONE
|
||||
replace: type
|
||||
type: 4
|
||||
replace: data
|
||||
data: %d
|
||||
", samba3.policy.refuse_machine_password_change));
|
||||
if (!ok) {
|
||||
message("registry load failed: " + regdb.errstring() + "\n");
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
message("Importing users\n");
|
||||
for (var i in samba3.samaccounts) {
|
||||
var msg = "... " + samba3.samaccounts[i].username;
|
||||
var ldif = upgrade_sam_account(samdb,samba3.samaccounts[i],subobj.BASEDN,subobj.DOMAINSID);
|
||||
ok = samdb.add(ldif);
|
||||
if (!ok && samdb.errstring() != "Record exists") {
|
||||
msg = msg + "... error: " + samdb.errstring();
|
||||
ret = ret + 1;
|
||||
}
|
||||
message(msg + "\n");
|
||||
}
|
||||
|
||||
message("Importing groups\n");
|
||||
for (var i in samba3.groupmappings) {
|
||||
var msg = "... " + samba3.groupmappings[i].nt_name;
|
||||
var ldif = upgrade_sam_group(samba3.groupmappings[i],subobj.BASEDN);
|
||||
if (ldif != undefined) {
|
||||
ok = samdb.add(ldif);
|
||||
if (!ok && samdb.errstring() != "Record exists") {
|
||||
msg = msg + "... error: " + samdb.errstring();
|
||||
ret = ret + 1;
|
||||
}
|
||||
}
|
||||
message(msg + "\n");
|
||||
}
|
||||
|
||||
message("Importing registry data\n");
|
||||
var hives = new Array("hkcr","hkcu","hklm","hkpd","hku","hkpt");
|
||||
for (var i in hives) {
|
||||
var hn = hives[i];
|
||||
message("... " + hn + "\n");
|
||||
regdb = ldb_init();
|
||||
ok = regdb.connect(paths[hn]);
|
||||
assert(ok);
|
||||
var ldif = upgrade_registry(samba3.registry, hn, regdb);
|
||||
for (var j in ldif) {
|
||||
var msg = "... ... " + j;
|
||||
ok = regdb.add(ldif[j]);
|
||||
if (!ok && regdb.errstring() != "Record exists") {
|
||||
msg = msg + "... error: " + regdb.errstring();
|
||||
ret = ret + 1;
|
||||
}
|
||||
message(msg + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
message("Importing WINS data\n");
|
||||
var winsdb = ldb_init();
|
||||
ok = winsdb.connect(paths.winsdb);
|
||||
assert(ok);
|
||||
ldb_erase(winsdb);
|
||||
|
||||
var ldif = upgrade_wins(samba3);
|
||||
ok = winsdb.add(ldif);
|
||||
assert(ok);
|
||||
|
||||
// figure out ldapurl, if applicable
|
||||
var ldapurl = undefined;
|
||||
var pdb = samba3.configuration.get_list("passdb backend");
|
||||
if (pdb != undefined) {
|
||||
for (var b in pdb) {
|
||||
if (strlen(pdb[b]) >= 7) {
|
||||
if (substr(pdb[b], 0, 7) == "ldapsam") {
|
||||
ldapurl = substr(pdb[b], 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// URL was not specified in passdb backend but ldap /is/ used
|
||||
if (ldapurl == "") {
|
||||
ldapurl = "ldap://" + samba3.configuration.get("ldap server");
|
||||
}
|
||||
|
||||
// Enable samba3sam module if original passdb backend was ldap
|
||||
if (ldapurl != undefined) {
|
||||
message("Enabling Samba3 LDAP mappings for SAM database\n");
|
||||
|
||||
ok = samdb.modify("
|
||||
dn: @MODULES
|
||||
changetype: modify
|
||||
replace: @LIST
|
||||
@LIST: samldb,operational,objectguid,rdn_name,samba3sam
|
||||
");
|
||||
if (!ok) {
|
||||
message("Error enabling samba3sam module: " + samdb.errstring() + "\n");
|
||||
ret = ret + 1;
|
||||
}
|
||||
|
||||
ok = samdb.add(sprintf("
|
||||
dn: @MAP=samba3sam
|
||||
@MAP_URL: %s", ldapurl));
|
||||
assert(ok);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function upgrade_verify(subobj, samba3,paths,message)
|
||||
{
|
||||
message("Verifying account policies\n");
|
||||
var samldb = ldb_init();
|
||||
var ne = 0;
|
||||
|
||||
var ok = samldb.connect(paths.samdb);
|
||||
assert(ok);
|
||||
|
||||
for (var i in samba3.samaccounts) {
|
||||
var msg = samldb.search("(&(sAMAccountName=" + samba3.samaccounts[i].nt_username + ")(objectclass=user))");
|
||||
assert(msg.length >= 1);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
winreg rpc utility functions
|
||||
Copyright Andrew Tridgell 2005
|
||||
released under the GNU GPL v2 or later
|
||||
*/
|
||||
|
||||
libinclude("base.js");
|
||||
|
||||
/*
|
||||
close a handle
|
||||
*/
|
||||
function __winreg_close(handle)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
this.winreg_CloseKey(io);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
open a hive
|
||||
*/
|
||||
function __winreg_open_hive(hive)
|
||||
{
|
||||
var io = irpcObj();
|
||||
io.input.system_name = NULL;
|
||||
io.input.access_mask = this.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
var status;
|
||||
if (hive == "HKLM") {
|
||||
status = this.winreg_OpenHKLM(io);
|
||||
} else if (hive == "HKCR") {
|
||||
status = this.winreg_OpenHKCR(io);
|
||||
} else if (hive == "HKPD") {
|
||||
status = this.winreg_OpenHKPD(io);
|
||||
} else if (hive == "HKU") {
|
||||
status = this.winreg_OpenHKU(io);
|
||||
} else {
|
||||
this._last_error = "Unknown hive " + hive;
|
||||
return undefined;
|
||||
}
|
||||
if (!status.is_ok) {
|
||||
return undefined;
|
||||
}
|
||||
return io.output.handle;
|
||||
}
|
||||
|
||||
/*
|
||||
open a handle to a path
|
||||
*/
|
||||
function __winreg_open_path(path)
|
||||
{
|
||||
var s = string_init();
|
||||
var i, components = s.split('\\', path);
|
||||
|
||||
/* cope with a leading slash */
|
||||
if (components[0] == '') {
|
||||
for (i=0;i<(components.length-1);i++) {
|
||||
components[i] = components[i+1];
|
||||
}
|
||||
delete(components[i]);
|
||||
}
|
||||
|
||||
if (components.length == 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var handle = this.open_hive(components[0]);
|
||||
if (handle == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (components.length == 1) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
var hpath = components[1];
|
||||
|
||||
for (i=2;i<components.length;i++) {
|
||||
hpath = hpath + "\\" + components[i];
|
||||
}
|
||||
|
||||
io = irpcObj();
|
||||
io.input.parent_handle = handle;
|
||||
io.input.keyname = hpath;
|
||||
io.input.unknown = 0;
|
||||
io.input.access_mask = this.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
var status = this.winreg_OpenKey(io);
|
||||
|
||||
this.close(handle);
|
||||
|
||||
if (!status.is_ok) {
|
||||
return undefined;
|
||||
}
|
||||
if (io.output.result != "WERR_OK") {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return io.output.handle;
|
||||
}
|
||||
|
||||
/*
|
||||
return a list of keys for a winreg server given a path
|
||||
usage:
|
||||
list = reg.enum_path(path);
|
||||
*/
|
||||
function __winreg_enum_path(path)
|
||||
{
|
||||
var list = new Array(0);
|
||||
|
||||
if (path == null || path == "\\" || path == "") {
|
||||
return new Array("HKLM", "HKU");
|
||||
}
|
||||
|
||||
var handle = this.open_path(path);
|
||||
if (handle == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
io.input.name = new Object();
|
||||
io.input.name.length = 0;
|
||||
io.input.name.size = 32;
|
||||
io.input.name.name = NULL;
|
||||
io.input.keyclass = new Object();
|
||||
io.input.keyclass.length = 0;
|
||||
io.input.keyclass.size = 1024;
|
||||
io.input.keyclass.name = NULL;
|
||||
io.input.last_changed_time = 0;
|
||||
|
||||
var idx = 0;
|
||||
for (idx=0;idx >= 0;idx++) {
|
||||
io.input.enum_index = idx;
|
||||
var status = this.winreg_EnumKey(io);
|
||||
if (!status.is_ok) {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
var out = io.output;
|
||||
if (out.result == "WERR_MORE_DATA") {
|
||||
io.input.name.size = io.input.name.size * 2;
|
||||
idx--;
|
||||
if (io.input.name.size > 32000) {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (out.result != "WERR_OK") {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
list[list.length] = out.name.name;
|
||||
}
|
||||
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
return a list of values for a winreg server given a path
|
||||
usage:
|
||||
list = reg.enum_values(path);
|
||||
|
||||
each returned list element is an object containing a name, a
|
||||
type and a value
|
||||
*/
|
||||
function __winreg_enum_values(path)
|
||||
{
|
||||
var data = datablob_init();
|
||||
var list = new Array(0);
|
||||
|
||||
var handle = this.open_path(path);
|
||||
if (handle == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
io.input.name = new Object();
|
||||
io.input.name.length = 0;
|
||||
io.input.name.size = 128;
|
||||
io.input.name.name = "";
|
||||
io.input.type = 0;
|
||||
io.input.value = new Array(0);
|
||||
io.input.size = 1024;
|
||||
io.input.length = 0;
|
||||
|
||||
var idx;
|
||||
for (idx=0;idx >= 0;idx++) {
|
||||
io.input.enum_index = idx;
|
||||
var status = this.winreg_EnumValue(io);
|
||||
if (!status.is_ok) {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
var out = io.output;
|
||||
if (out.result == "WERR_MORE_DATA") {
|
||||
io.input.size = io.input.size * 2;
|
||||
io.input.name.size = io.input.name.size * 2;
|
||||
idx--;
|
||||
/* limit blobs to 1M */
|
||||
if (io.input.size > 1000000) {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (out.result != "WERR_OK") {
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
var el = new Object();
|
||||
el.name = out.name.name;
|
||||
el.type = out.type;
|
||||
el.rawvalue = out.value;
|
||||
el.value = data.regToVar(el.rawvalue, el.type);
|
||||
el.size = out.size;
|
||||
list[list.length] = el;
|
||||
}
|
||||
|
||||
this.close(handle);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
create a new key
|
||||
ok = reg.create_key(path, key);
|
||||
*/
|
||||
function __winreg_create_key(path, key)
|
||||
{
|
||||
var handle = this.open_path(path);
|
||||
if (handle == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var io = irpcObj();
|
||||
io.input.handle = handle;
|
||||
io.input.name = key;
|
||||
io.input.keyclass = NULL;
|
||||
io.input.options = 0;
|
||||
io.input.access_mask = this.SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
io.input.secdesc = NULL;
|
||||
io.input.action_taken = 0;
|
||||
|
||||
var status = this.winreg_CreateKey(io);
|
||||
this.close(handle);
|
||||
if (!status.is_ok) {
|
||||
return false;
|
||||
}
|
||||
if (io.output.result != "WERR_OK") {
|
||||
return false;
|
||||
}
|
||||
this.close(io.output.new_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
return a string for a winreg type
|
||||
*/
|
||||
function __winreg_typestring(type)
|
||||
{
|
||||
return this.typenames[type];
|
||||
}
|
||||
|
||||
/*
|
||||
initialise the winreg lib, returning an object
|
||||
*/
|
||||
function winregObj()
|
||||
{
|
||||
var reg = winreg_init();
|
||||
security_init(reg);
|
||||
|
||||
reg.typenames = new Array("REG_NONE", "REG_SZ", "REG_EXPAND_SZ", "REG_BINARY",
|
||||
"REG_DWORD", "REG_DWORD_BIG_ENDIAN", "REG_LINK", "REG_MULTI_SZ",
|
||||
"REG_RESOURCE_LIST", "REG_FULL_RESOURCE_DESCRIPTOR",
|
||||
"REG_RESOURCE_REQUIREMENTS_LIST", "REG_QWORD");
|
||||
|
||||
reg.close = __winreg_close;
|
||||
reg.open_hive = __winreg_open_hive;
|
||||
reg.open_path = __winreg_open_path;
|
||||
reg.enum_path = __winreg_enum_path;
|
||||
reg.enum_values = __winreg_enum_values;
|
||||
reg.create_key = __winreg_create_key;
|
||||
reg.typestring = __winreg_typestring;
|
||||
|
||||
return reg;
|
||||
}
|
||||
Reference in New Issue
Block a user