samba-tool: Improve "delegation" command error handling
[Samba/gebeck_regimport.git] / source4 / scripting / python / samba / netcmd / delegation.py
blob469579e58c9c0b2c7f1410a41670a465d28f4180
1 #!/usr/bin/env python
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
8 # Copyright Giampaolo Lauria 2011 <lauria2@yahoo.com>
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 3 of the License, or
13 # (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 import samba.getopt as options
25 import ldb
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.common import _get_user_realm_domain
31 from samba.netcmd import (
32 Command,
33 CommandError,
34 SuperCommand,
35 Option
39 class cmd_delegation_show(Command):
40 """Show the delegation setting of an account."""
42 synopsis = "%prog <accountname> [options]"
44 takes_args = ["accountname"]
46 def run(self, accountname, credopts=None, sambaopts=None, versionopts=None):
47 lp = sambaopts.get_loadparm()
48 creds = credopts.get_credentials(lp)
49 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
50 sam = SamDB(paths.samdb, session_info=system_session(),
51 credentials=creds, lp=lp)
52 # TODO once I understand how, use the domain info to naildown
53 # to the correct domain
54 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
56 res = sam.search(expression="sAMAccountName=%s" %
57 ldb.binary_encode(cleanedaccount),
58 scope=ldb.SCOPE_SUBTREE,
59 attrs=["userAccountControl", "msDS-AllowedToDelegateTo"])
60 if len(res) == 0:
61 raise CommandError("Unable to find account name '%s'" % accountname)
62 assert(len(res) == 1)
64 uac = int(res[0].get("userAccountControl")[0])
65 allowed = res[0].get("msDS-AllowedToDelegateTo")
67 self.outf.write("Account-DN: %s\n" % str(res[0].dn))
68 self.outf.write("UF_TRUSTED_FOR_DELEGATION: %s\n"
69 % bool(uac & dsdb.UF_TRUSTED_FOR_DELEGATION))
70 self.outf.write("UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: %s\n" %
71 bool(uac & dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION))
73 if allowed is not None:
74 for a in allowed:
75 self.outf.write("msDS-AllowedToDelegateTo: %s\n" % a)
78 class cmd_delegation_for_any_service(Command):
79 """Set/unset UF_TRUSTED_FOR_DELEGATION for an account."""
81 synopsis = "%prog <accountname> [(on|off)] [options]"
83 takes_args = ["accountname", "onoff"]
85 def run(self, accountname, onoff, credopts=None, sambaopts=None, versionopts=None):
87 on = False
88 if onoff == "on":
89 on = True
90 elif onoff == "off":
91 on = False
92 else:
93 raise CommandError("invalid argument: '%s' (choose from 'on', 'off')" % onoff)
95 lp = sambaopts.get_loadparm()
96 creds = credopts.get_credentials(lp)
97 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
98 sam = SamDB(paths.samdb, session_info=system_session(),
99 credentials=creds, lp=lp)
100 # TODO once I understand how, use the domain info to naildown
101 # to the correct domain
102 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
104 search_filter = "sAMAccountName=%s" % ldb.binary_encode(cleanedaccount)
105 flag = dsdb.UF_TRUSTED_FOR_DELEGATION
106 try:
107 sam.toggle_userAccountFlags(search_filter, flag,
108 flags_str="Trusted-for-Delegation",
109 on=on, strict=True)
110 except Exception, err:
111 raise CommandError(err)
114 class cmd_delegation_for_any_protocol(Command):
115 """Set/unset UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION (S4U2Proxy) for an account."""
117 synopsis = "%prog <accountname> [(on|off)] [options]"
119 takes_args = ["accountname", "onoff"]
121 def run(self, accountname, onoff, credopts=None, sambaopts=None, versionopts=None):
123 on = False
124 if onoff == "on":
125 on = True
126 elif onoff == "off":
127 on = False
128 else:
129 raise CommandError("invalid argument: '%s' (choose from 'on', 'off')" % onoff)
131 lp = sambaopts.get_loadparm()
132 creds = credopts.get_credentials(lp)
133 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
134 sam = SamDB(paths.samdb, session_info=system_session(),
135 credentials=creds, lp=lp)
136 # TODO once I understand how, use the domain info to naildown
137 # to the correct domain
138 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
140 search_filter = "sAMAccountName=%s" % ldb.binary_encode(cleanedaccount)
141 flag = dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
142 try:
143 sam.toggle_userAccountFlags(search_filter, flag,
144 flags_str="Trusted-to-Authenticate-for-Delegation",
145 on=on, strict=True)
146 except Exception, err:
147 raise CommandError(err)
150 class cmd_delegation_add_service(Command):
151 """Add a service principal as msDS-AllowedToDelegateTo"""
153 synopsis = "%prog <accountname> <principal> [options]"
155 takes_args = ["accountname", "principal"]
157 def run(self, accountname, principal, credopts=None, sambaopts=None, versionopts=None):
159 lp = sambaopts.get_loadparm()
160 creds = credopts.get_credentials(lp)
161 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
162 sam = SamDB(paths.samdb, session_info=system_session(),
163 credentials=creds, lp=lp)
164 # TODO once I understand how, use the domain info to naildown
165 # to the correct domain
166 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
168 res = sam.search(expression="sAMAccountName=%s" %
169 ldb.binary_encode(cleanedaccount),
170 scope=ldb.SCOPE_SUBTREE,
171 attrs=["msDS-AllowedToDelegateTo"])
172 if len(res) == 0:
173 raise CommandError("Unable to find account name '%s'" % accountname)
174 assert(len(res) == 1)
176 msg = ldb.Message()
177 msg.dn = res[0].dn
178 msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
179 ldb.FLAG_MOD_ADD,
180 "msDS-AllowedToDelegateTo")
181 try:
182 sam.modify(msg)
183 except Exception, err:
184 raise CommandError(err)
187 class cmd_delegation_del_service(Command):
188 """Delete a service principal as msDS-AllowedToDelegateTo"""
190 synopsis = "%prog <accountname> <principal> [options]"
192 takes_args = ["accountname", "principal"]
194 def run(self, accountname, principal, credopts=None, sambaopts=None, versionopts=None):
196 lp = sambaopts.get_loadparm()
197 creds = credopts.get_credentials(lp)
198 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
199 sam = SamDB(paths.samdb, session_info=system_session(),
200 credentials=creds, lp=lp)
201 # TODO once I understand how, use the domain info to naildown
202 # to the correct domain
203 (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
205 res = sam.search(expression="sAMAccountName=%s" %
206 ldb.binary_encode(cleanedaccount),
207 scope=ldb.SCOPE_SUBTREE,
208 attrs=["msDS-AllowedToDelegateTo"])
209 if len(res) == 0:
210 raise CommandError("Unable to find account name '%s'" % accountname)
211 assert(len(res) == 1)
213 msg = ldb.Message()
214 msg.dn = res[0].dn
215 msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
216 ldb.FLAG_MOD_DELETE,
217 "msDS-AllowedToDelegateTo")
218 try:
219 sam.modify(msg)
220 except Exception, err:
221 raise CommandError(err)
224 class cmd_delegation(SuperCommand):
225 """Delegation management"""
227 subcommands = {}
228 subcommands["show"] = cmd_delegation_show()
229 subcommands["for-any-service"] = cmd_delegation_for_any_service()
230 subcommands["for-any-protocol"] = cmd_delegation_for_any_protocol()
231 subcommands["add-service"] = cmd_delegation_add_service()
232 subcommands["del-service"] = cmd_delegation_del_service()