3 # delegation management
5 # Copyright Matthieu Patou mat@samba.org 2010
6 # Copyright Stefan Metzmacher metze@samba.org 2011
7 # Copyright Bjoern Baumbach bb@sernet.de 2011
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 import samba.getopt as options
26 from samba import provision
27 from samba import dsdb
28 from samba.samdb import SamDB
29 from samba.auth import system_session
30 from samba.netcmd import (
37 def _get_user_realm_domain(user):
38 """ get the realm or the domain and the base user
47 m = re.match(r"(\w+)\\(\w+$)", user)
51 return (baseuser.lower(), domain.upper(), realm)
52 m = re.match(r"(\w+)@(\w+)", user)
56 return (baseuser.lower(), domain, realm.upper())
58 class cmd_delegation_show(Command):
59 """Show the delegation setting of an account."""
60 synopsis = "%prog delegation show <accountname>"
62 takes_optiongroups = {
63 "sambaopts": options.SambaOptions,
64 "credopts": options.CredentialsOptions,
65 "versionopts": options.VersionOptions,
68 takes_args = ["accountname"]
70 def run(self, accountname, credopts=None, sambaopts=None, versionopts=None):
71 lp = sambaopts.get_loadparm()
72 creds = credopts.get_credentials(lp)
73 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
74 sam = SamDB(paths.samdb, session_info=system_session(),
75 credentials=creds, lp=lp)
76 # TODO once I understand how, use the domain info to naildown
77 # to the correct domain
78 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
79 print "Searching for: %s" % (cleanedaccount)
80 res = sam.search(expression="sAMAccountName=%s" % cleanedaccount,
81 scope=ldb.SCOPE_SUBTREE,
82 attrs=["userAccountControl", "msDS-AllowedToDelegateTo"])
84 raise CommandError("Account %s found %d times" % (accountname, len(res)))
86 uac = int(res[0].get("userAccountControl")[0])
87 allowed = res[0].get("msDS-AllowedToDelegateTo")
89 print "Account-DN: %s" % str(res[0].dn)
91 if uac & dsdb.UF_TRUSTED_FOR_DELEGATION:
92 print "UF_TRUSTED_FOR_DELEGATION: 1"
94 print "UF_TRUSTED_FOR_DELEGATION: 0"
96 if uac & dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION:
97 print "UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: 1"
99 print "UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: 0"
103 print "msDS-AllowedToDelegateTo: %s" % (str(a))
105 class cmd_delegation_for_any_service(Command):
106 """Set/unset UF_TRUSTED_FOR_DELEGATION for an account."""
107 synopsis = "%prog delegation for-any-service <accountname> on|off"
109 takes_optiongroups = {
110 "sambaopts": options.SambaOptions,
111 "credopts": options.CredentialsOptions,
112 "versionopts": options.VersionOptions,
115 takes_args = ["accountname", "onoff"]
117 def run(self, accountname, onoff, credopts=None, sambaopts=None, versionopts=None):
125 raise CommandError("Invalid argument [%s]" % onoff)
127 lp = sambaopts.get_loadparm()
128 creds = credopts.get_credentials(lp)
129 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
130 sam = SamDB(paths.samdb, session_info=system_session(),
131 credentials=creds, lp=lp)
132 # TODO once I understand how, use the domain info to naildown
133 # to the correct domain
134 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
136 search_filter = "sAMAccountName=%s" % cleanedaccount
137 flag = dsdb.UF_TRUSTED_FOR_DELEGATION
139 sam.toggle_userAccountFlags(search_filter, flag, on=on, strict=True)
140 except Exception, err:
141 raise CommandError(err)
143 class cmd_delegation_for_any_protocol(Command):
144 """Set/unset UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION (S4U2Proxy) for an account."""
145 synopsis = "%prog delegation for-any-protocol <accountname> on|off"
147 takes_optiongroups = {
148 "sambaopts": options.SambaOptions,
149 "credopts": options.CredentialsOptions,
150 "versionopts": options.VersionOptions,
153 takes_args = ["accountname", "onoff"]
155 def run(self, accountname, onoff, credopts=None, sambaopts=None, versionopts=None):
163 raise CommandError("Invalid argument [%s]" % onoff)
165 lp = sambaopts.get_loadparm()
166 creds = credopts.get_credentials(lp)
167 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
168 sam = SamDB(paths.samdb, session_info=system_session(),
169 credentials=creds, lp=lp)
170 # TODO once I understand how, use the domain info to naildown
171 # to the correct domain
172 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
174 search_filter = "sAMAccountName=%s" % cleanedaccount
175 flag = dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
177 sam.toggle_userAccountFlags(search_filter, flag, on=on, strict=True)
178 except Exception, err:
179 raise CommandError(err)
181 class cmd_delegation_add_service(Command):
182 """Add a service principal as msDS-AllowedToDelegateTo"""
183 synopsis = "%prog delegation add-service <accountname> <principal>"
185 takes_optiongroups = {
186 "sambaopts": options.SambaOptions,
187 "credopts": options.CredentialsOptions,
188 "versionopts": options.VersionOptions,
191 takes_args = ["accountname", "principal"]
193 def run(self, accountname, principal, credopts=None, sambaopts=None, versionopts=None):
195 lp = sambaopts.get_loadparm()
196 creds = credopts.get_credentials(lp)
197 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
198 sam = SamDB(paths.samdb, session_info=system_session(),
199 credentials=creds, lp=lp)
200 # TODO once I understand how, use the domain info to naildown
201 # to the correct domain
202 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
204 res = sam.search(expression="sAMAccountName=%s" % cleanedaccount,
205 scope=ldb.SCOPE_SUBTREE,
206 attrs=["msDS-AllowedToDelegateTo"])
208 raise CommandError("Account %s found %d times" % (accountname, len(res)))
212 msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
214 "msDS-AllowedToDelegateTo")
217 except Exception, err:
218 raise CommandError(err)
220 class cmd_delegation_del_service(Command):
221 """Add a service principal as msDS-AllowedToDelegateTo"""
222 synopsis = "%prog delegation del-service <accountname> <principal>"
224 takes_optiongroups = {
225 "sambaopts": options.SambaOptions,
226 "credopts": options.CredentialsOptions,
227 "versionopts": options.VersionOptions,
230 takes_args = ["accountname", "principal"]
232 def run(self, accountname, principal, credopts=None, sambaopts=None, versionopts=None):
234 lp = sambaopts.get_loadparm()
235 creds = credopts.get_credentials(lp)
236 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
237 sam = SamDB(paths.samdb, session_info=system_session(),
238 credentials=creds, lp=lp)
239 # TODO once I understand how, use the domain info to naildown
240 # to the correct domain
241 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
243 res = sam.search(expression="sAMAccountName=%s" % cleanedaccount,
244 scope=ldb.SCOPE_SUBTREE,
245 attrs=["msDS-AllowedToDelegateTo"])
247 raise CommandError("Account %s found %d times" % (accountname, len(res)))
251 msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
253 "msDS-AllowedToDelegateTo")
256 except Exception, err:
257 raise CommandError(err)
259 class cmd_delegation(SuperCommand):
260 """Delegation management [server connection needed]"""
263 subcommands["show"] = cmd_delegation_show()
264 subcommands["for-any-service"] = cmd_delegation_for_any_service()
265 subcommands["for-any-protocol"] = cmd_delegation_for_any_protocol()
266 subcommands["add-service"] = cmd_delegation_add_service()
267 subcommands["del-service"] = cmd_delegation_del_service()