mirror of
https://github.com/samba-team/samba.git
synced 2025-11-25 00:23:52 +03:00
r26496: Move some provision functions to a new SamDB class, support setting session_info on a ldb context from python.
This commit is contained in:
committed by
Stefan Metzmacher
parent
c9e5a3078f
commit
75cfb0d609
@@ -40,12 +40,10 @@ void ldb_set_credentials(struct ldb_context *ldb, struct cli_credentials *creds)
|
||||
ldb_set_opaque(ldb, "credentials", creds);
|
||||
}
|
||||
|
||||
#if 0 /* Fails to link.. */
|
||||
void ldb_set_session_info(struct ldb_context *ldb, struct auth_session_info *session_info)
|
||||
{
|
||||
ldb_set_opaque(ldb, "sessionInfo", session_info);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ldb_set_loadparm(struct ldb_context *ldb, struct loadparm_context *lp_ctx)
|
||||
{
|
||||
|
||||
@@ -62,6 +62,7 @@ import credentials
|
||||
import param
|
||||
random_password = _misc.random_password
|
||||
ldb_set_credentials = _misc.ldb_set_credentials
|
||||
ldb_set_session_info = _misc.ldb_set_session_info
|
||||
ldb_set_loadparm = _misc.ldb_set_loadparm
|
||||
|
||||
|
||||
|
||||
@@ -2460,29 +2460,30 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags)
|
||||
/* -------- TYPES TABLE (BEGIN) -------- */
|
||||
|
||||
#define SWIGTYPE_p_TALLOC_CTX swig_types[0]
|
||||
#define SWIGTYPE_p_char swig_types[1]
|
||||
#define SWIGTYPE_p_cli_credentials swig_types[2]
|
||||
#define SWIGTYPE_p_int swig_types[3]
|
||||
#define SWIGTYPE_p_ldb_context swig_types[4]
|
||||
#define SWIGTYPE_p_ldb_dn swig_types[5]
|
||||
#define SWIGTYPE_p_ldb_ldif swig_types[6]
|
||||
#define SWIGTYPE_p_ldb_message swig_types[7]
|
||||
#define SWIGTYPE_p_ldb_message_element swig_types[8]
|
||||
#define SWIGTYPE_p_ldb_result swig_types[9]
|
||||
#define SWIGTYPE_p_loadparm_context swig_types[10]
|
||||
#define SWIGTYPE_p_loadparm_service swig_types[11]
|
||||
#define SWIGTYPE_p_long_long swig_types[12]
|
||||
#define SWIGTYPE_p_param_context swig_types[13]
|
||||
#define SWIGTYPE_p_param_section swig_types[14]
|
||||
#define SWIGTYPE_p_short swig_types[15]
|
||||
#define SWIGTYPE_p_signed_char swig_types[16]
|
||||
#define SWIGTYPE_p_unsigned_char swig_types[17]
|
||||
#define SWIGTYPE_p_unsigned_int swig_types[18]
|
||||
#define SWIGTYPE_p_unsigned_long swig_types[19]
|
||||
#define SWIGTYPE_p_unsigned_long_long swig_types[20]
|
||||
#define SWIGTYPE_p_unsigned_short swig_types[21]
|
||||
static swig_type_info *swig_types[23];
|
||||
static swig_module_info swig_module = {swig_types, 22, 0, 0, 0, 0};
|
||||
#define SWIGTYPE_p_auth_session_info swig_types[1]
|
||||
#define SWIGTYPE_p_char swig_types[2]
|
||||
#define SWIGTYPE_p_cli_credentials swig_types[3]
|
||||
#define SWIGTYPE_p_int swig_types[4]
|
||||
#define SWIGTYPE_p_ldb_context swig_types[5]
|
||||
#define SWIGTYPE_p_ldb_dn swig_types[6]
|
||||
#define SWIGTYPE_p_ldb_ldif swig_types[7]
|
||||
#define SWIGTYPE_p_ldb_message swig_types[8]
|
||||
#define SWIGTYPE_p_ldb_message_element swig_types[9]
|
||||
#define SWIGTYPE_p_ldb_result swig_types[10]
|
||||
#define SWIGTYPE_p_loadparm_context swig_types[11]
|
||||
#define SWIGTYPE_p_loadparm_service swig_types[12]
|
||||
#define SWIGTYPE_p_long_long swig_types[13]
|
||||
#define SWIGTYPE_p_param_context swig_types[14]
|
||||
#define SWIGTYPE_p_param_section swig_types[15]
|
||||
#define SWIGTYPE_p_short swig_types[16]
|
||||
#define SWIGTYPE_p_signed_char swig_types[17]
|
||||
#define SWIGTYPE_p_unsigned_char swig_types[18]
|
||||
#define SWIGTYPE_p_unsigned_int swig_types[19]
|
||||
#define SWIGTYPE_p_unsigned_long swig_types[20]
|
||||
#define SWIGTYPE_p_unsigned_long_long swig_types[21]
|
||||
#define SWIGTYPE_p_unsigned_short swig_types[22]
|
||||
static swig_type_info *swig_types[24];
|
||||
static swig_module_info swig_module = {swig_types, 23, 0, 0, 0, 0};
|
||||
#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
|
||||
#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
|
||||
|
||||
@@ -2703,12 +2704,10 @@ void ldb_set_credentials(struct ldb_context *ldb, struct cli_credentials *creds)
|
||||
ldb_set_opaque(ldb, "credentials", creds);
|
||||
}
|
||||
|
||||
#if 0 /* Fails to link.. */
|
||||
void ldb_set_session_info(struct ldb_context *ldb, struct auth_session_info *session_info)
|
||||
{
|
||||
ldb_set_opaque(ldb, "sessionInfo", session_info);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ldb_set_loadparm(struct ldb_context *ldb, struct loadparm_context *lp_ctx)
|
||||
{
|
||||
@@ -2758,7 +2757,7 @@ SWIGINTERN PyObject *_wrap_ldb_set_credentials(PyObject *SWIGUNUSEDPARM(self), P
|
||||
PyObject * obj0 = 0 ;
|
||||
PyObject * obj1 = 0 ;
|
||||
char * kwnames[] = {
|
||||
(char *) "Ldb",(char *) "creds", NULL
|
||||
(char *) "ldb",(char *) "creds", NULL
|
||||
};
|
||||
|
||||
{
|
||||
@@ -2790,6 +2789,44 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
SWIGINTERN PyObject *_wrap_ldb_set_session_info(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
|
||||
PyObject *resultobj = 0;
|
||||
struct ldb_context *arg1 = (struct ldb_context *) 0 ;
|
||||
struct auth_session_info *arg2 = (struct auth_session_info *) 0 ;
|
||||
void *argp1 = 0 ;
|
||||
int res1 = 0 ;
|
||||
void *argp2 = 0 ;
|
||||
int res2 = 0 ;
|
||||
PyObject * obj0 = 0 ;
|
||||
PyObject * obj1 = 0 ;
|
||||
char * kwnames[] = {
|
||||
(char *) "ldb",(char *) "session_info", NULL
|
||||
};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:ldb_set_session_info",kwnames,&obj0,&obj1)) SWIG_fail;
|
||||
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_context, 0 | 0 );
|
||||
if (!SWIG_IsOK(res1)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_set_session_info" "', argument " "1"" of type '" "struct ldb_context *""'");
|
||||
}
|
||||
arg1 = (struct ldb_context *)(argp1);
|
||||
res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_auth_session_info, 0 | 0 );
|
||||
if (!SWIG_IsOK(res2)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_set_session_info" "', argument " "2"" of type '" "struct auth_session_info *""'");
|
||||
}
|
||||
arg2 = (struct auth_session_info *)(argp2);
|
||||
{
|
||||
if (arg1 == NULL)
|
||||
SWIG_exception(SWIG_ValueError,
|
||||
"ldb context must be non-NULL");
|
||||
}
|
||||
ldb_set_session_info(arg1,arg2);
|
||||
resultobj = SWIG_Py_Void();
|
||||
return resultobj;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
SWIGINTERN PyObject *_wrap_ldb_set_loadparm(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
|
||||
PyObject *resultobj = 0;
|
||||
struct ldb_context *arg1 = (struct ldb_context *) 0 ;
|
||||
@@ -2801,7 +2838,7 @@ SWIGINTERN PyObject *_wrap_ldb_set_loadparm(PyObject *SWIGUNUSEDPARM(self), PyOb
|
||||
PyObject * obj0 = 0 ;
|
||||
PyObject * obj1 = 0 ;
|
||||
char * kwnames[] = {
|
||||
(char *) "Ldb",(char *) "lp_ctx", NULL
|
||||
(char *) "ldb",(char *) "lp_ctx", NULL
|
||||
};
|
||||
|
||||
{
|
||||
@@ -2836,6 +2873,7 @@ fail:
|
||||
static PyMethodDef SwigMethods[] = {
|
||||
{ (char *)"random_password", (PyCFunction) _wrap_random_password, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{ (char *)"ldb_set_credentials", (PyCFunction) _wrap_ldb_set_credentials, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{ (char *)"ldb_set_session_info", (PyCFunction) _wrap_ldb_set_session_info, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{ (char *)"ldb_set_loadparm", (PyCFunction) _wrap_ldb_set_loadparm, METH_VARARGS | METH_KEYWORDS, NULL},
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
@@ -2844,6 +2882,7 @@ static PyMethodDef SwigMethods[] = {
|
||||
/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
|
||||
|
||||
static swig_type_info _swigt__p_TALLOC_CTX = {"_p_TALLOC_CTX", "TALLOC_CTX *", 0, 0, (void*)0, 0};
|
||||
static swig_type_info _swigt__p_auth_session_info = {"_p_auth_session_info", "struct auth_session_info *", 0, 0, (void*)0, 0};
|
||||
static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
|
||||
static swig_type_info _swigt__p_cli_credentials = {"_p_cli_credentials", "struct cli_credentials *|cli_credentials *", 0, 0, (void*)0, 0};
|
||||
static swig_type_info _swigt__p_int = {"_p_int", "intptr_t *|int *|int_least32_t *|int_fast32_t *|int32_t *|int_fast16_t *", 0, 0, (void*)0, 0};
|
||||
@@ -2868,6 +2907,7 @@ static swig_type_info _swigt__p_unsigned_short = {"_p_unsigned_short", "unsigned
|
||||
|
||||
static swig_type_info *swig_type_initial[] = {
|
||||
&_swigt__p_TALLOC_CTX,
|
||||
&_swigt__p_auth_session_info,
|
||||
&_swigt__p_char,
|
||||
&_swigt__p_cli_credentials,
|
||||
&_swigt__p_int,
|
||||
@@ -2892,6 +2932,7 @@ static swig_type_info *swig_type_initial[] = {
|
||||
};
|
||||
|
||||
static swig_cast_info _swigc__p_TALLOC_CTX[] = { {&_swigt__p_TALLOC_CTX, 0, 0, 0},{0, 0, 0, 0}};
|
||||
static swig_cast_info _swigc__p_auth_session_info[] = { {&_swigt__p_auth_session_info, 0, 0, 0},{0, 0, 0, 0}};
|
||||
static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
|
||||
static swig_cast_info _swigc__p_cli_credentials[] = { {&_swigt__p_cli_credentials, 0, 0, 0},{0, 0, 0, 0}};
|
||||
static swig_cast_info _swigc__p_int[] = { {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
|
||||
@@ -2916,6 +2957,7 @@ static swig_cast_info _swigc__p_unsigned_short[] = { {&_swigt__p_unsigned_short
|
||||
|
||||
static swig_cast_info *swig_cast_initial[] = {
|
||||
_swigc__p_TALLOC_CTX,
|
||||
_swigc__p_auth_session_info,
|
||||
_swigc__p_char,
|
||||
_swigc__p_cli_credentials,
|
||||
_swigc__p_int,
|
||||
|
||||
@@ -35,40 +35,78 @@ if _in_source_tree():
|
||||
|
||||
import misc
|
||||
import ldb
|
||||
ldb.ldb.set_credentials = misc.ldb_set_credentials
|
||||
#FIXME: ldb.ldb.set_session_info = misc.ldb_set_session_info
|
||||
ldb.ldb.set_loadparm = misc.ldb_set_loadparm
|
||||
ldb.Ldb.set_credentials = misc.ldb_set_credentials
|
||||
ldb.Ldb.set_session_info = misc.ldb_set_session_info
|
||||
ldb.Ldb.set_loadparm = misc.ldb_set_loadparm
|
||||
|
||||
def Ldb(url, session_info=None, credentials=None, modules_dir=None, lp=None):
|
||||
"""Open a Samba Ldb file.
|
||||
|
||||
:param url: LDB Url to open
|
||||
:param session_info: Optional session information
|
||||
:param credentials: Optional credentials, defaults to anonymous.
|
||||
:param modules_dir: Modules directory, automatically set if not specified.
|
||||
:param lp: Loadparm object, optional.
|
||||
|
||||
This is different from a regular Ldb file in that the Samba-specific
|
||||
modules-dir is used by default and that credentials and session_info
|
||||
can be passed through (required by some modules).
|
||||
class Ldb(ldb.Ldb):
|
||||
"""Simple Samba-specific LDB subclass that takes care
|
||||
of setting up the modules dir, credentials pointers, etc.
|
||||
|
||||
Please note that this is intended to be for all Samba LDB files,
|
||||
not necessarily the Sam database. For Sam-specific helper
|
||||
functions see samdb.py.
|
||||
"""
|
||||
import ldb
|
||||
ret = ldb.Ldb()
|
||||
if modules_dir is None:
|
||||
modules_dir = default_ldb_modules_dir
|
||||
if modules_dir is not None:
|
||||
ret.set_modules_dir(modules_dir)
|
||||
def samba_debug(level,text):
|
||||
print "%d %s" % (level, text)
|
||||
if credentials is not None:
|
||||
ldb.set_credentials(credentials)
|
||||
if session_info is not None:
|
||||
ldb.set_session_info(session_info)
|
||||
if lp is not None:
|
||||
ldb.set_loadparm(lp)
|
||||
#ret.set_debug(samba_debug)
|
||||
ret.connect(url)
|
||||
return ret
|
||||
def __init__(url, session_info=None, credentials=None, modules_dir=None,
|
||||
lp=None):
|
||||
"""Open a Samba Ldb file.
|
||||
|
||||
:param url: LDB Url to open
|
||||
:param session_info: Optional session information
|
||||
:param credentials: Optional credentials, defaults to anonymous.
|
||||
:param modules_dir: Modules directory, automatically set if not specified.
|
||||
:param lp: Loadparm object, optional.
|
||||
|
||||
This is different from a regular Ldb file in that the Samba-specific
|
||||
modules-dir is used by default and that credentials and session_info
|
||||
can be passed through (required by some modules).
|
||||
"""
|
||||
super(self, Ldb).__init__()
|
||||
import ldb
|
||||
ret = ldb.Ldb()
|
||||
if modules_dir is None:
|
||||
modules_dir = default_ldb_modules_dir
|
||||
if modules_dir is not None:
|
||||
ret.set_modules_dir(modules_dir)
|
||||
def samba_debug(level,text):
|
||||
print "%d %s" % (level, text)
|
||||
if credentials is not None:
|
||||
ldb.set_credentials(credentials)
|
||||
if session_info is not None:
|
||||
ldb.set_session_info(session_info)
|
||||
if lp is not None:
|
||||
ldb.set_loadparm(lp)
|
||||
#ret.set_debug(samba_debug)
|
||||
ret.connect(url)
|
||||
return ret
|
||||
|
||||
def searchone(self, basedn, expression, attribute):
|
||||
"""Search for one attribute as a string."""
|
||||
res = self.search(basedn, SCOPE_SUBTREE, expression, [attribute])
|
||||
if len(res) != 1 or res[0][attribute] is None:
|
||||
return None
|
||||
return res[0][attribute]
|
||||
|
||||
def erase(self):
|
||||
"""Erase an ldb, removing all records."""
|
||||
# delete the specials
|
||||
for attr in ["@INDEXLIST", "@ATTRIBUTES", "@SUBCLASSES", "@MODULES",
|
||||
"@OPTIONS", "@PARTITION", "@KLUDGEACL"]:
|
||||
try:
|
||||
self.delete(Dn(self, attr))
|
||||
except LdbError, (LDB_ERR_NO_SUCH_OBJECT, _):
|
||||
# Ignore missing dn errors
|
||||
pass
|
||||
|
||||
basedn = Dn(self, "")
|
||||
# and the rest
|
||||
for msg in self.search(basedn, SCOPE_SUBTREE,
|
||||
"(&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO)))",
|
||||
["dn"]):
|
||||
self.delete(msg.dn)
|
||||
|
||||
res = self.search(basedn, SCOPE_SUBTREE, "(&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO)))", ["dn"])
|
||||
assert len(res) == 0
|
||||
|
||||
|
||||
def substitute_var(text, values):
|
||||
|
||||
@@ -15,6 +15,7 @@ from socket import gethostname, gethostbyname
|
||||
import param
|
||||
import registry
|
||||
from samba import Ldb, substitute_var, valid_netbios_name
|
||||
from samba.samdb import SamDB
|
||||
from ldb import Dn, SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, \
|
||||
LDB_ERR_NO_SUCH_OBJECT, timestring
|
||||
|
||||
@@ -164,32 +165,6 @@ def findnss(nssfn, *names):
|
||||
pass
|
||||
raise Exception("Unable to find user/group for %s" % arguments[1])
|
||||
|
||||
def add_foreign(ldb, subobj, sid, desc):
|
||||
"""Add a foreign security principle."""
|
||||
add = """
|
||||
dn: CN=%s,CN=ForeignSecurityPrincipals,%s
|
||||
objectClass: top
|
||||
objectClass: foreignSecurityPrincipal
|
||||
description: %s
|
||||
""" % (sid, subobj.domaindn, desc)
|
||||
# deliberately ignore errors from this, as the records may
|
||||
# already exist
|
||||
for msg in ldb.parse_ldif(add):
|
||||
ldb.add(msg[1])
|
||||
|
||||
def setup_name_mapping(subobj, ldb, sid, unixname):
|
||||
"""Setup a mapping between a sam name and a unix name."""
|
||||
res = ldb.search(Dn(ldb, subobj.domaindn), SCOPE_SUBTREE,
|
||||
"objectSid=%s" % sid, ["dn"])
|
||||
assert len(res) == 1, "Failed to find record for objectSid %s" % sid
|
||||
|
||||
mod = """
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: unixName
|
||||
unixName: %s
|
||||
""" % (res[0].dn, unixname)
|
||||
ldb.modify(ldb.parse_ldif(mod).next()[1])
|
||||
|
||||
|
||||
def hostip():
|
||||
@@ -214,57 +189,6 @@ def ldb_delete(ldb):
|
||||
ldb.connect(ldb.filename)
|
||||
|
||||
|
||||
def ldb_erase(ldb):
|
||||
"""Erase an ldb, removing all records."""
|
||||
# delete the specials
|
||||
for attr in ["@INDEXLIST", "@ATTRIBUTES", "@SUBCLASSES", "@MODULES",
|
||||
"@OPTIONS", "@PARTITION", "@KLUDGEACL"]:
|
||||
try:
|
||||
ldb.delete(Dn(ldb, attr))
|
||||
except LdbError, (LDB_ERR_NO_SUCH_OBJECT, _):
|
||||
# Ignore missing dn errors
|
||||
pass
|
||||
|
||||
basedn = Dn(ldb, "")
|
||||
# and the rest
|
||||
for msg in ldb.search(basedn, SCOPE_SUBTREE,
|
||||
"(&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO)))",
|
||||
["dn"]):
|
||||
ldb.delete(msg.dn)
|
||||
|
||||
res = ldb.search(basedn, SCOPE_SUBTREE, "(&(|(objectclass=*)(dn=*))(!(dn=@BASEINFO)))", ["dn"])
|
||||
assert len(res) == 0
|
||||
|
||||
|
||||
def ldb_erase_partitions(subobj, message, ldb, ldapbackend):
|
||||
"""Erase an ldb, removing all records."""
|
||||
assert ldb is not None
|
||||
res = ldb.search(Dn(ldb, ""), SCOPE_BASE, "(objectClass=*)",
|
||||
["namingContexts"])
|
||||
assert len(res) == 1
|
||||
if not "namingContexts" in res[0]:
|
||||
return
|
||||
for basedn in res[0]["namingContexts"]:
|
||||
anything = "(|(objectclass=*)(dn=*))"
|
||||
previous_remaining = 1
|
||||
current_remaining = 0
|
||||
|
||||
if ldapbackend and (basedn == subobj.domaindn):
|
||||
# Only delete objects that were created by provision
|
||||
anything = "(objectcategory=*)"
|
||||
|
||||
k = 0
|
||||
while ++k < 10 and (previous_remaining != current_remaining):
|
||||
# and the rest
|
||||
res2 = ldb.search(Dn(ldb, basedn), SCOPE_SUBTREE, anything, ["dn"])
|
||||
previous_remaining = current_remaining
|
||||
current_remaining = len(res2)
|
||||
for msg in res2:
|
||||
try:
|
||||
ldb.delete(msg.dn)
|
||||
except LdbError, (_, text):
|
||||
message("Unable to delete %s: %s" % (msg.dn, text))
|
||||
|
||||
|
||||
def open_ldb(session_info, credentials, dbname):
|
||||
assert session_info is not None
|
||||
@@ -374,30 +298,30 @@ def setup_name_mappings(subobj, ldb):
|
||||
sid = list(res[0]["objectSid"])[0]
|
||||
|
||||
# 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")
|
||||
ldb.add_foreign(subobj.domaindn, "S-1-5-7", "Anonymous")
|
||||
ldb.add_foreign(subobj.domaindn, "S-1-1-0", "World")
|
||||
ldb.add_foreign(subobj.domaindn, "S-1-5-2", "Network")
|
||||
ldb.add_foreign(subobj.domaindn, "S-1-5-18", "System")
|
||||
ldb.add_foreign(subobj.domaindn, "S-1-5-11", "Authenticated Users")
|
||||
|
||||
# some well known sids
|
||||
setup_name_mapping(subobj, ldb, "S-1-5-7", subobj.nobody)
|
||||
setup_name_mapping(subobj, ldb, "S-1-1-0", subobj.nogroup)
|
||||
setup_name_mapping(subobj, ldb, "S-1-5-2", subobj.nogroup)
|
||||
setup_name_mapping(subobj, ldb, "S-1-5-18", subobj.root)
|
||||
setup_name_mapping(subobj, ldb, "S-1-5-11", subobj.users)
|
||||
setup_name_mapping(subobj, ldb, "S-1-5-32-544", subobj.wheel)
|
||||
setup_name_mapping(subobj, ldb, "S-1-5-32-545", subobj.users)
|
||||
setup_name_mapping(subobj, ldb, "S-1-5-32-546", subobj.nogroup)
|
||||
setup_name_mapping(subobj, ldb, "S-1-5-32-551", subobj.backup)
|
||||
ldb.setup_name_mapping(subobj.domaindn, "S-1-5-7", subobj.nobody)
|
||||
ldb.setup_name_mapping(subobj.domaindn, "S-1-1-0", subobj.nogroup)
|
||||
ldb.setup_name_mapping(subobj.domaindn, "S-1-5-2", subobj.nogroup)
|
||||
ldb.setup_name_mapping(subobj.domaindn, "S-1-5-18", subobj.root)
|
||||
ldb.setup_name_mapping(subobj.domaindn, "S-1-5-11", subobj.users)
|
||||
ldb.setup_name_mapping(subobj.domaindn, "S-1-5-32-544", subobj.wheel)
|
||||
ldb.setup_name_mapping(subobj.domaindn, "S-1-5-32-545", subobj.users)
|
||||
ldb.setup_name_mapping(subobj.domaindn, "S-1-5-32-546", subobj.nogroup)
|
||||
ldb.setup_name_mapping(subobj.domaindn, "S-1-5-32-551", subobj.backup)
|
||||
|
||||
# and some well known domain rids
|
||||
setup_name_mapping(subobj, ldb, sid + "-500", subobj.root)
|
||||
setup_name_mapping(subobj, ldb, sid + "-518", subobj.wheel)
|
||||
setup_name_mapping(subobj, ldb, sid + "-519", subobj.wheel)
|
||||
setup_name_mapping(subobj, ldb, sid + "-512", subobj.wheel)
|
||||
setup_name_mapping(subobj, ldb, sid + "-513", subobj.users)
|
||||
setup_name_mapping(subobj, ldb, sid + "-520", subobj.wheel)
|
||||
ldb.setup_name_mapping(subobj.domaindn, sid + "-500", subobj.root)
|
||||
ldb.setup_name_mapping(subobj.domaindn, sid + "-518", subobj.wheel)
|
||||
ldb.setup_name_mapping(subobj.domaindn, sid + "-519", subobj.wheel)
|
||||
ldb.setup_name_mapping(subobj.domaindn, sid + "-512", subobj.wheel)
|
||||
ldb.setup_name_mapping(subobj.domaindn, sid + "-513", subobj.users)
|
||||
ldb.setup_name_mapping(subobj.domaindn, sid + "-520", subobj.wheel)
|
||||
|
||||
|
||||
def provision_become_dc(setup_dir, subobj, message, paths, session_info,
|
||||
@@ -414,7 +338,8 @@ def provision_become_dc(setup_dir, subobj, message, paths, session_info,
|
||||
setup_ldb(setup_dir, "provision_partitions.ldif", session_info,
|
||||
credentials, subobj, paths.samdb)
|
||||
|
||||
samdb = open_ldb(session_info, credentials, paths.samdb)
|
||||
samdb = SamDB(paths.samdb, session_info=session_info,
|
||||
credentials=credentials)
|
||||
ldb.transaction_start()
|
||||
try:
|
||||
message("Setting up %s attributes" % paths.samdb)
|
||||
@@ -424,7 +349,7 @@ def provision_become_dc(setup_dir, subobj, message, paths, session_info,
|
||||
setup_add_ldif(setup_dir, "provision_rootdse_add.ldif", subobj, samdb)
|
||||
|
||||
message("Erasing data from partitions")
|
||||
ldb_erase_partitions(subobj, message, samdb, undefined)
|
||||
ldb_erase_partitions(subobj, message, samdb, None)
|
||||
|
||||
message("Setting up %s indexes" % paths.samdb)
|
||||
setup_add_ldif(setup_dir, "provision_index.ldif", subobj, samdb)
|
||||
@@ -603,7 +528,7 @@ def provision_dns(setup_dir, subobj, message, paths, session_info, credentials):
|
||||
"""Write out a DNS zone file, from the info in the current database."""
|
||||
message("Setting up DNS zone: %s" % subobj.dnsdomain)
|
||||
# connect to the sam
|
||||
ldb = Ldb(paths.samdb, session_info=session_info, credentials=credentials)
|
||||
ldb = SamDB(paths.samdb, session_info=session_info, credentials=credentials)
|
||||
|
||||
# These values may have changed, due to an incoming SamSync,
|
||||
# or may not have been specified, so fetch them from the database
|
||||
@@ -614,7 +539,7 @@ def provision_dns(setup_dir, subobj, message, paths, session_info, credentials):
|
||||
assert(res[0]["objectGUID"] is not None)
|
||||
subobj.domainguid = res[0]["objectGUID"]
|
||||
|
||||
subobj.host_guid = searchone(ldb, subobj.domaindn,
|
||||
subobj.host_guid = ldb.searchone(subobj.domaindn,
|
||||
"(&(objectClass=computer)(cn=%s))" % subobj.netbiosname, "objectGUID")
|
||||
assert subobj.host_guid is not None
|
||||
|
||||
@@ -716,13 +641,6 @@ def provision_guess(lp):
|
||||
return subobj
|
||||
|
||||
|
||||
def searchone(ldb, basedn, expression, attribute):
|
||||
"""search for one attribute as a string."""
|
||||
res = ldb.search(basedn, SCOPE_SUBTREE, expression, [attribute])
|
||||
if len(res) != 1 or res[0][attribute] is None:
|
||||
return None
|
||||
return res[0][attribute]
|
||||
|
||||
|
||||
def load_schema(setup_dir, subobj, samdb):
|
||||
"""Load schema."""
|
||||
@@ -745,70 +663,6 @@ def load_schema(setup_dir, subobj, samdb):
|
||||
samdb.attach_dsdb_schema_from_ldif(head_data, schema_data)
|
||||
|
||||
|
||||
def enable_account(ldb, user_dn):
|
||||
"""enable the account."""
|
||||
res = ldb.search(user_dn, SCOPE_ONELEVEL, None, ["userAccountControl"])
|
||||
assert len(res) == 1
|
||||
userAccountControl = res[0].userAccountControl
|
||||
userAccountControl = userAccountControl - 2 # remove disabled bit
|
||||
mod = """
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: userAccountControl
|
||||
userAccountControl: %u
|
||||
""" % (user_dn, userAccountControl)
|
||||
ldb.modify(mod)
|
||||
|
||||
|
||||
def newuser(sam, username, unixname, password, message, session_info,
|
||||
credentials):
|
||||
"""add a new user record"""
|
||||
# connect to the sam
|
||||
ldb.transaction_start()
|
||||
|
||||
# find the DNs for the domain and the domain users group
|
||||
res = ldb.search("", SCOPE_BASE, "defaultNamingContext=*",
|
||||
["defaultNamingContext"])
|
||||
assert(len(res) == 1 and res[0].defaultNamingContext is not None)
|
||||
domain_dn = res[0].defaultNamingContext
|
||||
assert(domain_dn is not None)
|
||||
dom_users = searchone(ldb, domain_dn, "name=Domain Users", "dn")
|
||||
assert(dom_users is not None)
|
||||
|
||||
user_dn = "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
|
||||
#
|
||||
ldif = """
|
||||
dn: %s
|
||||
sAMAccountName: %s
|
||||
unixName: %s
|
||||
sambaPassword: %s
|
||||
objectClass: user
|
||||
""" % (user_dn, username, unixname, password)
|
||||
# add the user to the users group as well
|
||||
modgroup = """
|
||||
dn: %s
|
||||
changetype: modify
|
||||
add: member
|
||||
member: %s
|
||||
""" % (dom_users, user_dn)
|
||||
|
||||
|
||||
# now the real work
|
||||
message("Adding user %s" % user_dn)
|
||||
ldb.add(ldif)
|
||||
|
||||
message("Modifying group %s" % dom_users)
|
||||
ldb.modify(modgroup)
|
||||
|
||||
# modify the userAccountControl to remove the disabled bit
|
||||
enable_account(ldb, user_dn)
|
||||
ldb.transaction_commit()
|
||||
|
||||
|
||||
def join_domain(domain, netbios_name, join_type, creds, message):
|
||||
ctx = NetContext(creds)
|
||||
joindom = object()
|
||||
@@ -835,3 +689,35 @@ def vampire(domain, session_info, credentials, message):
|
||||
vampire_ctx.session_info = session_info
|
||||
if not ctx.SamSyncLdb(vampire_ctx):
|
||||
raise Exception("Migration of remote domain to Samba failed: %s " % vampire_ctx.error_string)
|
||||
|
||||
|
||||
def ldb_erase_partitions(subobj, message, ldb, ldapbackend):
|
||||
"""Erase an ldb, removing all records."""
|
||||
assert ldb is not None
|
||||
res = ldb.search(Dn(ldb, ""), SCOPE_BASE, "(objectClass=*)",
|
||||
["namingContexts"])
|
||||
assert len(res) == 1
|
||||
if not "namingContexts" in res[0]:
|
||||
return
|
||||
for basedn in res[0]["namingContexts"]:
|
||||
anything = "(|(objectclass=*)(dn=*))"
|
||||
previous_remaining = 1
|
||||
current_remaining = 0
|
||||
|
||||
if ldapbackend and (basedn == subobj.domaindn):
|
||||
# Only delete objects that were created by provision
|
||||
anything = "(objectcategory=*)"
|
||||
|
||||
k = 0
|
||||
while ++k < 10 and (previous_remaining != current_remaining):
|
||||
# and the rest
|
||||
res2 = ldb.search(Dn(ldb, basedn), SCOPE_SUBTREE, anything, ["dn"])
|
||||
previous_remaining = current_remaining
|
||||
current_remaining = len(res2)
|
||||
for msg in res2:
|
||||
try:
|
||||
ldb.delete(msg.dn)
|
||||
except LdbError, (_, text):
|
||||
message("Unable to delete %s: %s" % (msg.dn, text))
|
||||
|
||||
|
||||
|
||||
117
source/scripting/python/samba/samdb.py
Normal file
117
source/scripting/python/samba/samdb.py
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Unix SMB/CIFS implementation.
|
||||
# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007
|
||||
#
|
||||
# Based on the original in EJS:
|
||||
# Copyright (C) Andrew Tridgell 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/>.
|
||||
#
|
||||
|
||||
import samba
|
||||
|
||||
class SamDB(samba.Ldb):
|
||||
def add_foreign(self, domaindn, sid, desc):
|
||||
"""Add a foreign security principle."""
|
||||
add = """
|
||||
dn: CN=%s,CN=ForeignSecurityPrincipals,%s
|
||||
objectClass: top
|
||||
objectClass: foreignSecurityPrincipal
|
||||
description: %s
|
||||
""" % (sid, domaindn, desc)
|
||||
# deliberately ignore errors from this, as the records may
|
||||
# already exist
|
||||
for msg in self.parse_ldif(add):
|
||||
self.add(msg[1])
|
||||
|
||||
def setup_name_mapping(self, domaindn, sid, unixname):
|
||||
"""Setup a mapping between a sam name and a unix name."""
|
||||
res = self.search(Dn(ldb, domaindn), SCOPE_SUBTREE,
|
||||
"objectSid=%s" % sid, ["dn"])
|
||||
assert len(res) == 1, "Failed to find record for objectSid %s" % sid
|
||||
|
||||
mod = """
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: unixName
|
||||
unixName: %s
|
||||
""" % (res[0].dn, unixname)
|
||||
self.modify(self.parse_ldif(mod).next()[1])
|
||||
|
||||
def enable_account(self, user_dn):
|
||||
"""enable the account.
|
||||
|
||||
:param user_dn: Dn of the account to enable.
|
||||
"""
|
||||
res = self.search(user_dn, SCOPE_ONELEVEL, None, ["userAccountControl"])
|
||||
assert len(res) == 1
|
||||
userAccountControl = res[0].userAccountControl
|
||||
userAccountControl = userAccountControl - 2 # remove disabled bit
|
||||
mod = """
|
||||
dn: %s
|
||||
changetype: modify
|
||||
replace: userAccountControl
|
||||
userAccountControl: %u
|
||||
""" % (user_dn, userAccountControl)
|
||||
self.modify(mod)
|
||||
|
||||
def newuser(self, username, unixname, password, message):
|
||||
"""add a new user record"""
|
||||
# connect to the sam
|
||||
self.transaction_start()
|
||||
|
||||
# find the DNs for the domain and the domain users group
|
||||
res = self.search("", SCOPE_BASE, "defaultNamingContext=*",
|
||||
["defaultNamingContext"])
|
||||
assert(len(res) == 1 and res[0].defaultNamingContext is not None)
|
||||
domain_dn = res[0].defaultNamingContext
|
||||
assert(domain_dn is not None)
|
||||
dom_users = searchone(self, domain_dn, "name=Domain Users", "dn")
|
||||
assert(dom_users is not None)
|
||||
|
||||
user_dn = "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
|
||||
#
|
||||
ldif = """
|
||||
dn: %s
|
||||
sAMAccountName: %s
|
||||
unixName: %s
|
||||
sambaPassword: %s
|
||||
objectClass: user
|
||||
""" % (user_dn, username, unixname, password)
|
||||
# add the user to the users group as well
|
||||
modgroup = """
|
||||
dn: %s
|
||||
changetype: modify
|
||||
add: member
|
||||
member: %s
|
||||
""" % (dom_users, user_dn)
|
||||
|
||||
|
||||
# now the real work
|
||||
message("Adding user %s" % user_dn)
|
||||
self.add(ldif)
|
||||
|
||||
message("Modifying group %s" % dom_users)
|
||||
self.modify(modgroup)
|
||||
|
||||
# modify the userAccountControl to remove the disabled bit
|
||||
enable_account(self, user_dn)
|
||||
self.transaction_commit()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user