diff options
author | Stefan Metzmacher <metze@samba.org> | 2011-06-24 16:59:24 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2011-06-24 19:06:44 +0200 |
commit | dee41bcdf20d54ca2c323c154b4f212065d0de0e (patch) | |
tree | 3bb76fd81587733ee93dc29c29cf2e59b24b1439 | |
parent | 4b26fc098087579018a2817906c140fa9cb8887e (diff) | |
download | samba-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
-rw-r--r-- | source4/scripting/python/samba/netcmd/__init__.py | 2 | ||||
-rw-r--r-- | source4/scripting/python/samba/netcmd/delegation.py | 267 |
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() |