summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2011-06-24 16:59:24 +0200
committerStefan Metzmacher <metze@samba.org>2011-06-24 19:06:44 +0200
commitdee41bcdf20d54ca2c323c154b4f212065d0de0e (patch)
tree3bb76fd81587733ee93dc29c29cf2e59b24b1439 /source4
parent4b26fc098087579018a2817906c140fa9cb8887e (diff)
downloadsamba-dee41bcdf20d54ca2c323c154b4f212065d0de0e.tar.gz
samba-dee41bcdf20d54ca2c323c154b4f212065d0de0e.tar.bz2
samba-dee41bcdf20d54ca2c323c154b4f212065d0de0e.zip
s4:samba-tool: add "delegation" subcommands for S4U2Proxy and related stuff
For now this only works on the local sam.ldb, but it shouldn't be hard to improve it to talk to remove servers. Pair-Programmed-With: Björn Baumbach <bb@sernet.de> metze
Diffstat (limited to 'source4')
-rw-r--r--source4/scripting/python/samba/netcmd/__init__.py2
-rw-r--r--source4/scripting/python/samba/netcmd/delegation.py267
2 files changed, 269 insertions, 0 deletions
diff --git a/source4/scripting/python/samba/netcmd/__init__.py b/source4/scripting/python/samba/netcmd/__init__.py
index 1373cb289b..bc5b0f67ae 100644
--- a/source4/scripting/python/samba/netcmd/__init__.py
+++ b/source4/scripting/python/samba/netcmd/__init__.py
@@ -214,3 +214,5 @@ from samba.netcmd.testparm import cmd_testparm
commands["testparm"] = cmd_testparm()
from samba.netcmd.dbcheck import cmd_dbcheck
commands["dbcheck"] = cmd_dbcheck()
+from samba.netcmd.delegation import cmd_delegation
+commands["delegation"] = cmd_delegation()
diff --git a/source4/scripting/python/samba/netcmd/delegation.py b/source4/scripting/python/samba/netcmd/delegation.py
new file mode 100644
index 0000000000..1307c14cda
--- /dev/null
+++ b/source4/scripting/python/samba/netcmd/delegation.py
@@ -0,0 +1,267 @@
+#!/usr/bin/env python
+#
+# delegation management
+#
+# Copyright Matthieu Patou mat@samba.org 2010
+# Copyright Stefan Metzmacher metze@samba.org 2011
+# Copyright Bjoern Baumbach bb@sernet.de 2011
+#
+# 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.getopt as options
+import ldb
+import re
+from samba import provision
+from samba import dsdb
+from samba.samdb import SamDB
+from samba.auth import system_session
+from samba.netcmd import (
+ Command,
+ CommandError,
+ SuperCommand,
+ Option
+ )
+
+def _get_user_realm_domain(user):
+ """ get the realm or the domain and the base user
+ from user like:
+ * username
+ * DOMAIN\username
+ * username@REALM
+ """
+ baseuser = user
+ realm = ""
+ domain = ""
+ m = re.match(r"(\w+)\\(\w+$)", user)
+ if m:
+ domain = m.group(1)
+ baseuser = m.group(2)
+ return (baseuser.lower(), domain.upper(), realm)
+ m = re.match(r"(\w+)@(\w+)", user)
+ if m:
+ baseuser = m.group(1)
+ realm = m.group(2)
+ return (baseuser.lower(), domain, realm.upper())
+
+class cmd_delegation_show(Command):
+ """Show the delegation setting of an account."""
+ synopsis = "%prog delegation show <accountname>"
+
+ takes_optiongroups = {
+ "sambaopts": options.SambaOptions,
+ "credopts": options.CredentialsOptions,
+ "versionopts": options.VersionOptions,
+ }
+
+ takes_args = ["accountname"]
+
+ def run(self, accountname, credopts=None, sambaopts=None, versionopts=None):
+ lp = sambaopts.get_loadparm()
+ creds = credopts.get_credentials(lp)
+ paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
+ sam = SamDB(paths.samdb, session_info=system_session(),
+ credentials=creds, lp=lp)
+ # TODO once I understand how, use the domain info to naildown
+ # to the correct domain
+ (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
+ print "Searching for: %s" % (cleanedaccount)
+ res = sam.search(expression="sAMAccountName=%s" % cleanedaccount,
+ scope=ldb.SCOPE_SUBTREE,
+ attrs=["userAccountControl", "msDS-AllowedToDelegateTo"])
+ if len(res) != 1:
+ raise CommandError("Account %s found %d times" % (accountname, len(res)))
+
+ uac = int(res[0].get("userAccountControl")[0])
+ allowed = res[0].get("msDS-AllowedToDelegateTo")
+
+ print "Account-DN: %s" % str(res[0].dn)
+
+ if uac & dsdb.UF_TRUSTED_FOR_DELEGATION:
+ print "UF_TRUSTED_FOR_DELEGATION: 1"
+ else:
+ print "UF_TRUSTED_FOR_DELEGATION: 0"
+
+ if uac & dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION:
+ print "UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: 1"
+ else:
+ print "UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: 0"
+
+ if allowed != None:
+ for a in allowed:
+ print "msDS-AllowedToDelegateTo: %s" % (str(a))
+
+class cmd_delegation_for_any_service(Command):
+ """Set/unset UF_TRUSTED_FOR_DELEGATION for an account."""
+ synopsis = "%prog delegation for-any-service <accountname> on|off"
+
+ takes_optiongroups = {
+ "sambaopts": options.SambaOptions,
+ "credopts": options.CredentialsOptions,
+ "versionopts": options.VersionOptions,
+ }
+
+ takes_args = ["accountname", "onoff"]
+
+ def run(self, accountname, onoff, credopts=None, sambaopts=None, versionopts=None):
+
+ on = False
+ if onoff == "on":
+ on = True
+ elif onoff == "off":
+ on = False
+ else:
+ raise CommandError("Invalid argument [%s]" % onoff)
+
+ lp = sambaopts.get_loadparm()
+ creds = credopts.get_credentials(lp)
+ paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
+ sam = SamDB(paths.samdb, session_info=system_session(),
+ credentials=creds, lp=lp)
+ # TODO once I understand how, use the domain info to naildown
+ # to the correct domain
+ (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
+
+ search_filter = "sAMAccountName=%s" % cleanedaccount
+ flag = dsdb.UF_TRUSTED_FOR_DELEGATION
+ try:
+ sam.toggle_userAccountFlags(search_filter, flag, on=on, strict=True)
+ except Exception, err:
+ raise CommandError(err)
+
+class cmd_delegation_for_any_protocol(Command):
+ """Set/unset UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION (S4U2Proxy) for an account."""
+ synopsis = "%prog delegation for-any-protocol <accountname> on|off"
+
+ takes_optiongroups = {
+ "sambaopts": options.SambaOptions,
+ "credopts": options.CredentialsOptions,
+ "versionopts": options.VersionOptions,
+ }
+
+ takes_args = ["accountname", "onoff"]
+
+ def run(self, accountname, onoff, credopts=None, sambaopts=None, versionopts=None):
+
+ on = False
+ if onoff == "on":
+ on = True
+ elif onoff == "off":
+ on = False
+ else:
+ raise CommandError("Invalid argument [%s]" % onoff)
+
+ lp = sambaopts.get_loadparm()
+ creds = credopts.get_credentials(lp)
+ paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
+ sam = SamDB(paths.samdb, session_info=system_session(),
+ credentials=creds, lp=lp)
+ # TODO once I understand how, use the domain info to naildown
+ # to the correct domain
+ (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
+
+ search_filter = "sAMAccountName=%s" % cleanedaccount
+ flag = dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
+ try:
+ sam.toggle_userAccountFlags(search_filter, flag, on=on, strict=True)
+ except Exception, err:
+ raise CommandError(err)
+
+class cmd_delegation_add_service(Command):
+ """Add a service principal as msDS-AllowedToDelegateTo"""
+ synopsis = "%prog delegation add-service <accountname> <principal>"
+
+ takes_optiongroups = {
+ "sambaopts": options.SambaOptions,
+ "credopts": options.CredentialsOptions,
+ "versionopts": options.VersionOptions,
+ }
+
+ takes_args = ["accountname", "principal"]
+
+ def run(self, accountname, principal, credopts=None, sambaopts=None, versionopts=None):
+
+ lp = sambaopts.get_loadparm()
+ creds = credopts.get_credentials(lp)
+ paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
+ sam = SamDB(paths.samdb, session_info=system_session(),
+ credentials=creds, lp=lp)
+ # TODO once I understand how, use the domain info to naildown
+ # to the correct domain
+ (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
+
+ res = sam.search(expression="sAMAccountName=%s" % cleanedaccount,
+ scope=ldb.SCOPE_SUBTREE,
+ attrs=["msDS-AllowedToDelegateTo"])
+ if len(res) != 1:
+ raise CommandError("Account %s found %d times" % (accountname, len(res)))
+
+ msg = ldb.Message()
+ msg.dn = res[0].dn
+ msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
+ ldb.FLAG_MOD_ADD,
+ "msDS-AllowedToDelegateTo")
+ try:
+ sam.modify(msg)
+ except Exception, err:
+ raise CommandError(err)
+
+class cmd_delegation_del_service(Command):
+ """Add a service principal as msDS-AllowedToDelegateTo"""
+ synopsis = "%prog delegation del-service <accountname> <principal>"
+
+ takes_optiongroups = {
+ "sambaopts": options.SambaOptions,
+ "credopts": options.CredentialsOptions,
+ "versionopts": options.VersionOptions,
+ }
+
+ takes_args = ["accountname", "principal"]
+
+ def run(self, accountname, principal, credopts=None, sambaopts=None, versionopts=None):
+
+ lp = sambaopts.get_loadparm()
+ creds = credopts.get_credentials(lp)
+ paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
+ sam = SamDB(paths.samdb, session_info=system_session(),
+ credentials=creds, lp=lp)
+ # TODO once I understand how, use the domain info to naildown
+ # to the correct domain
+ (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
+
+ res = sam.search(expression="sAMAccountName=%s" % cleanedaccount,
+ scope=ldb.SCOPE_SUBTREE,
+ attrs=["msDS-AllowedToDelegateTo"])
+ if len(res) != 1:
+ raise CommandError("Account %s found %d times" % (accountname, len(res)))
+
+ msg = ldb.Message()
+ msg.dn = res[0].dn
+ msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
+ ldb.FLAG_MOD_DELETE,
+ "msDS-AllowedToDelegateTo")
+ try:
+ sam.modify(msg)
+ except Exception, err:
+ raise CommandError(err)
+
+class cmd_delegation(SuperCommand):
+ """Delegation management [server connection needed]"""
+
+ subcommands = {}
+ subcommands["show"] = cmd_delegation_show()
+ subcommands["for-any-service"] = cmd_delegation_for_any_service()
+ subcommands["for-any-protocol"] = cmd_delegation_for_any_protocol()
+ subcommands["add-service"] = cmd_delegation_add_service()
+ subcommands["del-service"] = cmd_delegation_del_service()