samba-tool delegation: Use self.outf, simplify some code.
[obnox/samba/samba-obnox.git] / source4 / scripting / python / samba / netcmd / delegation.py
1 #!/usr/bin/env python
2 #
3 # delegation management
4 #
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>
9 #
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.
14 #
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.
19 #
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/>.
22 #
23
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
36     )
37
38
39
40 class cmd_delegation_show(Command):
41     """Show the delegation setting of an account."""
42     
43     synopsis = "%prog delegation show <accountname> [options]"
44
45     takes_args = ["accountname"]
46
47     def run(self, accountname, credopts=None, sambaopts=None, versionopts=None):
48         lp = sambaopts.get_loadparm()
49         creds = credopts.get_credentials(lp)
50         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
51         sam = SamDB(paths.samdb, session_info=system_session(),
52                     credentials=creds, lp=lp)
53         # TODO once I understand how, use the domain info to naildown
54         # to the correct domain
55         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
56         self.outf.write("Searching for: %s\n" % (cleanedaccount))
57         res = sam.search(expression="sAMAccountName=%s" % ldb.binary_encode(cleanedaccount),
58                             scope=ldb.SCOPE_SUBTREE,
59                             attrs=["userAccountControl", "msDS-AllowedToDelegateTo"])
60         if len(res) != 1:
61             raise CommandError("Account %s found %d times" % (accountname, len(res)))
62
63         uac = int(res[0].get("userAccountControl")[0])
64         allowed = res[0].get("msDS-AllowedToDelegateTo")
65
66         self.outf.write("Account-DN: %s\n" %  str(res[0].dn))
67         self.outf.write("UF_TRUSTED_FOR_DELEGATION: %s\n"
68             % bool(uac & dsdb.UF_TRUSTED_FOR_DELEGATION))
69         self.outf.write("UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION: %s\n" %
70               bool(uac & dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION))
71
72         if allowed is not None:
73             for a in allowed:
74                 self.outf.write("msDS-AllowedToDelegateTo: %s\n" % a)
75
76
77
78 class cmd_delegation_for_any_service(Command):
79     """Set/unset UF_TRUSTED_FOR_DELEGATION for an account."""
80
81     synopsis = "%prog delegation for-any-service <accountname> [(on|off)] [options]"
82
83     takes_args = ["accountname", "onoff"]
84
85     def run(self, accountname, onoff, credopts=None, sambaopts=None, versionopts=None):
86
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]" % onoff)
94
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)
103
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, on=on, strict=True)
108         except Exception, err:
109             raise CommandError(err)
110
111
112
113 class cmd_delegation_for_any_protocol(Command):
114     """Set/unset UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION (S4U2Proxy) for an account."""
115
116     synopsis = "%prog delegation for-any-protocol <accountname> [(on|off)] [options]"
117
118     takes_args = ["accountname", "onoff"]
119
120     def run(self, accountname, onoff, credopts=None, sambaopts=None, versionopts=None):
121
122         on = False
123         if onoff == "on":
124             on = True
125         elif onoff == "off":
126             on = False
127         else:
128             raise CommandError("Invalid argument [%s]" % onoff)
129
130         lp = sambaopts.get_loadparm()
131         creds = credopts.get_credentials(lp)
132         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
133         sam = SamDB(paths.samdb, session_info=system_session(),
134                     credentials=creds, lp=lp)
135         # TODO once I understand how, use the domain info to naildown
136         # to the correct domain
137         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
138
139         search_filter = "sAMAccountName=%s" % ldb.binary_encode(cleanedaccount)
140         flag = dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
141         try:
142             sam.toggle_userAccountFlags(search_filter, flag, on=on, strict=True)
143         except Exception, err:
144             raise CommandError(err)
145
146
147
148 class cmd_delegation_add_service(Command):
149     """Add a service principal as msDS-AllowedToDelegateTo"""
150
151     synopsis = "%prog delegation add-service <accountname> <principal> [options]"
152
153     takes_args = ["accountname", "principal"]
154
155     def run(self, accountname, principal, credopts=None, sambaopts=None, versionopts=None):
156
157         lp = sambaopts.get_loadparm()
158         creds = credopts.get_credentials(lp)
159         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
160         sam = SamDB(paths.samdb, session_info=system_session(),
161                     credentials=creds, lp=lp)
162         # TODO once I understand how, use the domain info to naildown
163         # to the correct domain
164         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
165
166         res = sam.search(expression="sAMAccountName=%s" % ldb.binary_encode(cleanedaccount),
167                             scope=ldb.SCOPE_SUBTREE,
168                             attrs=["msDS-AllowedToDelegateTo"])
169         if len(res) != 1:
170             raise CommandError("Account %s found %d times" % (accountname, len(res)))
171
172         msg = ldb.Message()
173         msg.dn = res[0].dn
174         msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
175                                               ldb.FLAG_MOD_ADD,
176                                               "msDS-AllowedToDelegateTo")
177         try:
178             sam.modify(msg)
179         except Exception, err:
180             raise CommandError(err)
181
182
183
184 class cmd_delegation_del_service(Command):
185     """Delete a service principal as msDS-AllowedToDelegateTo"""
186
187     synopsis = "%prog delegation del-service <accountname> <principal> [options]"
188
189     takes_args = ["accountname", "principal"]
190
191     def run(self, accountname, principal, credopts=None, sambaopts=None, versionopts=None):
192
193         lp = sambaopts.get_loadparm()
194         creds = credopts.get_credentials(lp)
195         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
196         sam = SamDB(paths.samdb, session_info=system_session(),
197                     credentials=creds, lp=lp)
198         # TODO once I understand how, use the domain info to naildown
199         # to the correct domain
200         (cleanedaccount, realm, domain) = _get_user_realm_domain(accountname)
201
202         res = sam.search(expression="sAMAccountName=%s" % ldb.binary_encode(cleanedaccount),
203                             scope=ldb.SCOPE_SUBTREE,
204                             attrs=["msDS-AllowedToDelegateTo"])
205         if len(res) != 1:
206             raise CommandError("Account %s found %d times" % (accountname, len(res)))
207
208         msg = ldb.Message()
209         msg.dn = res[0].dn
210         msg["msDS-AllowedToDelegateTo"] = ldb.MessageElement([principal],
211                                               ldb.FLAG_MOD_DELETE,
212                                               "msDS-AllowedToDelegateTo")
213         try:
214             sam.modify(msg)
215         except Exception, err:
216             raise CommandError(err)
217
218
219
220 class cmd_delegation(SuperCommand):
221     """Delegation management"""
222
223     subcommands = {}
224     subcommands["show"] = cmd_delegation_show()
225     subcommands["for-any-service"] = cmd_delegation_for_any_service()
226     subcommands["for-any-protocol"] = cmd_delegation_for_any_protocol()
227     subcommands["add-service"] = cmd_delegation_add_service()
228     subcommands["del-service"] = cmd_delegation_del_service()