PEP8: fix E222: multiple spaces after operator
[amitay/samba.git] / python / samba / netcmd / delegation.py
1 # delegation management
2 #
3 # Copyright Matthieu Patou mat@samba.org 2010
4 # Copyright Stefan Metzmacher metze@samba.org 2011
5 # Copyright Bjoern Baumbach bb@sernet.de 2011
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20
21 import samba.getopt as options
22 import ldb
23 from samba import provision
24 from samba import dsdb
25 from samba.samdb import SamDB
26 from samba.auth import system_session
27 from samba.netcmd.common import _get_user_realm_domain
28 from samba.netcmd import (
29     Command,
30     CommandError,
31     SuperCommand,
32     Option
33 )
34
35
36 class cmd_delegation_show(Command):
37     """Show the delegation setting of an account."""
38
39     synopsis = "%prog <accountname> [options]"
40
41     takes_optiongroups = {
42         "sambaopts": options.SambaOptions,
43         "credopts": options.CredentialsOptions,
44         "versionopts": options.VersionOptions,
45     }
46
47     takes_options = [
48         Option("-H", "--URL", help="LDB URL for database or target server", type=str,
49                metavar="URL", dest="H"),
50     ]
51
52     takes_args = ["accountname"]
53
54     def run(self, accountname, H=None, credopts=None, sambaopts=None, versionopts=None):
55         lp = sambaopts.get_loadparm()
56         creds = credopts.get_credentials(lp)
57         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
58
59         if H == None:
60             path = paths.samdb
61         else:
62             path = H
63
64         sam = SamDB(path, session_info=system_session(),
65                     credentials=creds, lp=lp)
66         # TODO once I understand how, use the domain info to naildown
67         # to the correct domain
68         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
69
70         res = sam.search(expression="sAMAccountName=%s" %
71                          ldb.binary_encode(cleanedaccount),
72                          scope=ldb.SCOPE_SUBTREE,
73                          attrs=["userAccountControl", "msDS-AllowedToDelegateTo"])
74         if len(res) == 0:
75             raise CommandError("Unable to find account name '%s'" % accountname)
76         assert(len(res) == 1)
77
78         uac = int(res[0].get("userAccountControl")[0])
79         allowed = res[0].get("msDS-AllowedToDelegateTo")
80
81         self.outf.write("Account-DN: %s\n" % str(res[0].dn))
82         self.outf.write("UF_TRUSTED_FOR_DELEGATION: %s\n"
83                         % bool(uac & dsdb.UF_TRUSTED_FOR_DELEGATION))
84         self.outf.write("UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: %s\n" %
85                         bool(uac & dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION))
86
87         if allowed is not None:
88             for a in allowed:
89                 self.outf.write("msDS-AllowedToDelegateTo: %s\n" % a)
90
91
92 class cmd_delegation_for_any_service(Command):
93     """Set/unset UF_TRUSTED_FOR_DELEGATION for an account."""
94
95     synopsis = "%prog <accountname> [(on|off)] [options]"
96
97     takes_optiongroups = {
98         "sambaopts": options.SambaOptions,
99         "credopts": options.CredentialsOptions,
100         "versionopts": options.VersionOptions,
101     }
102
103     takes_options = [
104         Option("-H", "--URL", help="LDB URL for database or target server", type=str,
105                metavar="URL", dest="H"),
106     ]
107
108     takes_args = ["accountname", "onoff"]
109
110     def run(self, accountname, onoff, H=None, credopts=None, sambaopts=None,
111             versionopts=None):
112
113         on = False
114         if onoff == "on":
115             on = True
116         elif onoff == "off":
117             on = False
118         else:
119             raise CommandError("invalid argument: '%s' (choose from 'on', 'off')" % onoff)
120
121         lp = sambaopts.get_loadparm()
122         creds = credopts.get_credentials(lp)
123         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
124         if H == None:
125             path = paths.samdb
126         else:
127             path = H
128
129         sam = SamDB(path, session_info=system_session(),
130                     credentials=creds, lp=lp)
131         # TODO once I understand how, use the domain info to naildown
132         # to the correct domain
133         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
134
135         search_filter = "sAMAccountName=%s" % ldb.binary_encode(cleanedaccount)
136         flag = dsdb.UF_TRUSTED_FOR_DELEGATION
137         try:
138             sam.toggle_userAccountFlags(search_filter, flag,
139                                         flags_str="Trusted-for-Delegation",
140                                         on=on, strict=True)
141         except Exception as err:
142             raise CommandError(err)
143
144
145 class cmd_delegation_for_any_protocol(Command):
146     """Set/unset UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION (S4U2Proxy) for an account."""
147
148     synopsis = "%prog <accountname> [(on|off)] [options]"
149
150     takes_optiongroups = {
151         "sambaopts": options.SambaOptions,
152         "credopts": options.CredentialsOptions,
153         "versionopts": options.VersionOptions,
154     }
155
156     takes_options = [
157         Option("-H", "--URL", help="LDB URL for database or target server", type=str,
158                metavar="URL", dest="H"),
159     ]
160
161
162     takes_args = ["accountname", "onoff"]
163
164     def run(self, accountname, onoff, H=None, credopts=None, sambaopts=None,
165             versionopts=None):
166
167         on = False
168         if onoff == "on":
169             on = True
170         elif onoff == "off":
171             on = False
172         else:
173             raise CommandError("invalid argument: '%s' (choose from 'on', 'off')" % onoff)
174
175         lp = sambaopts.get_loadparm()
176         creds = credopts.get_credentials(lp, fallback_machine=True)
177         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
178         if H == None:
179             path = paths.samdb
180         else:
181             path = H
182
183         sam = SamDB(path, session_info=system_session(),
184                     credentials=creds, lp=lp)
185         # TODO once I understand how, use the domain info to naildown
186         # to the correct domain
187         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
188
189         search_filter = "sAMAccountName=%s" % ldb.binary_encode(cleanedaccount)
190         flag = dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
191         try:
192             sam.toggle_userAccountFlags(search_filter, flag,
193                                         flags_str="Trusted-to-Authenticate-for-Delegation",
194                                         on=on, strict=True)
195         except Exception as err:
196             raise CommandError(err)
197
198
199 class cmd_delegation_add_service(Command):
200     """Add a service principal as msDS-AllowedToDelegateTo."""
201
202     synopsis = "%prog <accountname> <principal> [options]"
203
204     takes_optiongroups = {
205         "sambaopts": options.SambaOptions,
206         "credopts": options.CredentialsOptions,
207         "versionopts": options.VersionOptions,
208     }
209
210     takes_options = [
211         Option("-H", "--URL", help="LDB URL for database or target server", type=str,
212                metavar="URL", dest="H"),
213     ]
214
215     takes_args = ["accountname", "principal"]
216
217     def run(self, accountname, principal, H=None, credopts=None, sambaopts=None,
218             versionopts=None):
219
220         lp = sambaopts.get_loadparm()
221         creds = credopts.get_credentials(lp)
222         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
223         if H == None:
224             path = paths.samdb
225         else:
226             path = H
227
228         sam = SamDB(path, session_info=system_session(),
229                     credentials=creds, lp=lp)
230         # TODO once I understand how, use the domain info to naildown
231         # to the correct domain
232         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
233
234         res = sam.search(expression="sAMAccountName=%s" %
235                          ldb.binary_encode(cleanedaccount),
236                          scope=ldb.SCOPE_SUBTREE,
237                          attrs=["msDS-AllowedToDelegateTo"])
238         if len(res) == 0:
239             raise CommandError("Unable to find account name '%s'" % accountname)
240         assert(len(res) == 1)
241
242         msg = ldb.Message()
243         msg.dn = res[0].dn
244         msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
245                                                              ldb.FLAG_MOD_ADD,
246                                                              "msDS-AllowedToDelegateTo")
247         try:
248             sam.modify(msg)
249         except Exception as err:
250             raise CommandError(err)
251
252
253 class cmd_delegation_del_service(Command):
254     """Delete a service principal as msDS-AllowedToDelegateTo."""
255
256     synopsis = "%prog <accountname> <principal> [options]"
257
258     takes_optiongroups = {
259         "sambaopts": options.SambaOptions,
260         "credopts": options.CredentialsOptions,
261         "versionopts": options.VersionOptions,
262     }
263
264     takes_options = [
265         Option("-H", "--URL", help="LDB URL for database or target server", type=str,
266                metavar="URL", dest="H"),
267     ]
268
269     takes_args = ["accountname", "principal"]
270
271     def run(self, accountname, principal, H=None, credopts=None, sambaopts=None,
272             versionopts=None):
273
274         lp = sambaopts.get_loadparm()
275         creds = credopts.get_credentials(lp)
276         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
277         if H == None:
278             path = paths.samdb
279         else:
280             path = H
281
282         sam = SamDB(path, session_info=system_session(),
283                     credentials=creds, lp=lp)
284         # TODO once I understand how, use the domain info to naildown
285         # to the correct domain
286         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
287
288         res = sam.search(expression="sAMAccountName=%s" %
289                          ldb.binary_encode(cleanedaccount),
290                          scope=ldb.SCOPE_SUBTREE,
291                          attrs=["msDS-AllowedToDelegateTo"])
292         if len(res) == 0:
293             raise CommandError("Unable to find account name '%s'" % accountname)
294         assert(len(res) == 1)
295
296         msg = ldb.Message()
297         msg.dn = res[0].dn
298         msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
299                                                              ldb.FLAG_MOD_DELETE,
300                                                              "msDS-AllowedToDelegateTo")
301         try:
302             sam.modify(msg)
303         except Exception as err:
304             raise CommandError(err)
305
306
307 class cmd_delegation(SuperCommand):
308     """Delegation management."""
309
310     subcommands = {}
311     subcommands["show"] = cmd_delegation_show()
312     subcommands["for-any-service"] = cmd_delegation_for_any_service()
313     subcommands["for-any-protocol"] = cmd_delegation_for_any_protocol()
314     subcommands["add-service"] = cmd_delegation_add_service()
315     subcommands["del-service"] = cmd_delegation_del_service()