47dffb07d51900539b7c3d4ef78e1532083bd5c3
[nivanova/samba-autobuild/.git] / source4 / scripting / 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_args = ["accountname"]
48
49     def run(self, accountname, credopts=None, sambaopts=None, versionopts=None):
50         lp = sambaopts.get_loadparm()
51         creds = credopts.get_credentials(lp)
52         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
53         sam = SamDB(paths.samdb, session_info=system_session(),
54                     credentials=creds, lp=lp)
55         # TODO once I understand how, use the domain info to naildown
56         # to the correct domain
57         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
58
59         res = sam.search(expression="sAMAccountName=%s" %
60                     ldb.binary_encode(cleanedaccount),
61                     scope=ldb.SCOPE_SUBTREE,
62                     attrs=["userAccountControl", "msDS-AllowedToDelegateTo"])
63         if len(res) == 0:
64             raise CommandError("Unable to find account name '%s'" % accountname)
65         assert(len(res) == 1)
66
67         uac = int(res[0].get("userAccountControl")[0])
68         allowed = res[0].get("msDS-AllowedToDelegateTo")
69
70         self.outf.write("Account-DN: %s\n" %  str(res[0].dn))
71         self.outf.write("UF_TRUSTED_FOR_DELEGATION: %s\n"
72             % bool(uac & dsdb.UF_TRUSTED_FOR_DELEGATION))
73         self.outf.write("UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: %s\n" %
74               bool(uac & dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION))
75
76         if allowed is not None:
77             for a in allowed:
78                 self.outf.write("msDS-AllowedToDelegateTo: %s\n" % a)
79
80
81 class cmd_delegation_for_any_service(Command):
82     """Set/unset UF_TRUSTED_FOR_DELEGATION for an account."""
83
84     synopsis = "%prog <accountname> [(on|off)] [options]"
85
86     takes_optiongroups = {
87         "sambaopts": options.SambaOptions,
88         "credopts": options.CredentialsOptions,
89         "versionopts": options.VersionOptions,
90         }
91
92     takes_args = ["accountname", "onoff"]
93
94     def run(self, accountname, onoff, credopts=None, sambaopts=None,
95             versionopts=None):
96
97         on = False
98         if onoff == "on":
99             on = True
100         elif onoff == "off":
101             on = False
102         else:
103             raise CommandError("invalid argument: '%s' (choose from 'on', 'off')" % onoff)
104
105         lp = sambaopts.get_loadparm()
106         creds = credopts.get_credentials(lp)
107         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
108         sam = SamDB(paths.samdb, session_info=system_session(),
109                     credentials=creds, lp=lp)
110         # TODO once I understand how, use the domain info to naildown
111         # to the correct domain
112         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
113
114         search_filter = "sAMAccountName=%s" % ldb.binary_encode(cleanedaccount)
115         flag = dsdb.UF_TRUSTED_FOR_DELEGATION
116         try:
117             sam.toggle_userAccountFlags(search_filter, flag,
118                                         flags_str="Trusted-for-Delegation",
119                                         on=on, strict=True)
120         except Exception, err:
121             raise CommandError(err)
122
123
124 class cmd_delegation_for_any_protocol(Command):
125     """Set/unset UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION (S4U2Proxy) for an account."""
126
127     synopsis = "%prog <accountname> [(on|off)] [options]"
128
129     takes_optiongroups = {
130         "sambaopts": options.SambaOptions,
131         "credopts": options.CredentialsOptions,
132         "versionopts": options.VersionOptions,
133         }
134
135     takes_args = ["accountname", "onoff"]
136
137     def run(self, accountname, onoff, credopts=None, sambaopts=None,
138             versionopts=None):
139
140         on = False
141         if onoff == "on":
142             on = True
143         elif onoff == "off":
144             on = False
145         else:
146             raise CommandError("invalid argument: '%s' (choose from 'on', 'off')" % onoff)
147
148         lp = sambaopts.get_loadparm()
149         creds = credopts.get_credentials(lp)
150         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
151         sam = SamDB(paths.samdb, session_info=system_session(),
152                     credentials=creds, lp=lp)
153         # TODO once I understand how, use the domain info to naildown
154         # to the correct domain
155         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
156
157         search_filter = "sAMAccountName=%s" % ldb.binary_encode(cleanedaccount)
158         flag = dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
159         try:
160             sam.toggle_userAccountFlags(search_filter, flag,
161                         flags_str="Trusted-to-Authenticate-for-Delegation",
162                         on=on, strict=True)
163         except Exception, err:
164             raise CommandError(err)
165
166
167 class cmd_delegation_add_service(Command):
168     """Add a service principal as msDS-AllowedToDelegateTo."""
169
170     synopsis = "%prog <accountname> <principal> [options]"
171
172     takes_optiongroups = {
173         "sambaopts": options.SambaOptions,
174         "credopts": options.CredentialsOptions,
175         "versionopts": options.VersionOptions,
176         }
177
178     takes_args = ["accountname", "principal"]
179
180     def run(self, accountname, principal, credopts=None, sambaopts=None,
181             versionopts=None):
182
183         lp = sambaopts.get_loadparm()
184         creds = credopts.get_credentials(lp)
185         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
186         sam = SamDB(paths.samdb, session_info=system_session(),
187                     credentials=creds, lp=lp)
188         # TODO once I understand how, use the domain info to naildown
189         # to the correct domain
190         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
191
192         res = sam.search(expression="sAMAccountName=%s" %
193                          ldb.binary_encode(cleanedaccount),
194                          scope=ldb.SCOPE_SUBTREE,
195                          attrs=["msDS-AllowedToDelegateTo"])
196         if len(res) == 0:
197             raise CommandError("Unable to find account name '%s'" % accountname)
198         assert(len(res) == 1)
199
200         msg = ldb.Message()
201         msg.dn = res[0].dn
202         msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
203                                           ldb.FLAG_MOD_ADD,
204                                           "msDS-AllowedToDelegateTo")
205         try:
206             sam.modify(msg)
207         except Exception, err:
208             raise CommandError(err)
209
210
211 class cmd_delegation_del_service(Command):
212     """Delete a service principal as msDS-AllowedToDelegateTo."""
213
214     synopsis = "%prog <accountname> <principal> [options]"
215
216     takes_optiongroups = {
217         "sambaopts": options.SambaOptions,
218         "credopts": options.CredentialsOptions,
219         "versionopts": options.VersionOptions,
220         }
221
222     takes_args = ["accountname", "principal"]
223
224     def run(self, accountname, principal, credopts=None, sambaopts=None,
225             versionopts=None):
226
227         lp = sambaopts.get_loadparm()
228         creds = credopts.get_credentials(lp)
229         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
230         sam = SamDB(paths.samdb, session_info=system_session(),
231                     credentials=creds, lp=lp)
232         # TODO once I understand how, use the domain info to naildown
233         # to the correct domain
234         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
235
236         res = sam.search(expression="sAMAccountName=%s" %
237                          ldb.binary_encode(cleanedaccount),
238                          scope=ldb.SCOPE_SUBTREE,
239                          attrs=["msDS-AllowedToDelegateTo"])
240         if len(res) == 0:
241             raise CommandError("Unable to find account name '%s'" % accountname)
242         assert(len(res) == 1)
243
244         msg = ldb.Message()
245         msg.dn = res[0].dn
246         msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
247                                           ldb.FLAG_MOD_DELETE,
248                                           "msDS-AllowedToDelegateTo")
249         try:
250             sam.modify(msg)
251         except Exception, err:
252             raise CommandError(err)
253
254
255 class cmd_delegation(SuperCommand):
256     """Delegation management."""
257
258     subcommands = {}
259     subcommands["show"] = cmd_delegation_show()
260     subcommands["for-any-service"] = cmd_delegation_for_any_service()
261     subcommands["for-any-protocol"] = cmd_delegation_for_any_protocol()
262     subcommands["add-service"] = cmd_delegation_add_service()
263     subcommands["del-service"] = cmd_delegation_del_service()