1 # delegation management
3 # Copyright Matthieu Patou mat@samba.org 2010
4 # Copyright Stefan Metzmacher metze@samba.org 2011
5 # Copyright Bjoern Baumbach bb@sernet.de 2011
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.
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.
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/>.
21 import samba
.getopt
as options
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 (
36 class cmd_delegation_show(Command
):
37 """Show the delegation setting of an account."""
39 synopsis
= "%prog <accountname> [options]"
41 takes_optiongroups
= {
42 "sambaopts": options
.SambaOptions
,
43 "credopts": options
.CredentialsOptions
,
44 "versionopts": options
.VersionOptions
,
47 takes_args
= ["accountname"]
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
)
59 res
= sam
.search(expression
="sAMAccountName=%s" %
60 ldb
.binary_encode(cleanedaccount
),
61 scope
=ldb
.SCOPE_SUBTREE
,
62 attrs
=["userAccountControl", "msDS-AllowedToDelegateTo"])
64 raise CommandError("Unable to find account name '%s'" % accountname
)
67 uac
= int(res
[0].get("userAccountControl")[0])
68 allowed
= res
[0].get("msDS-AllowedToDelegateTo")
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
))
76 if allowed
is not None:
78 self
.outf
.write("msDS-AllowedToDelegateTo: %s\n" % a
)
81 class cmd_delegation_for_any_service(Command
):
82 """Set/unset UF_TRUSTED_FOR_DELEGATION for an account."""
84 synopsis
= "%prog <accountname> [(on|off)] [options]"
86 takes_optiongroups
= {
87 "sambaopts": options
.SambaOptions
,
88 "credopts": options
.CredentialsOptions
,
89 "versionopts": options
.VersionOptions
,
92 takes_args
= ["accountname", "onoff"]
94 def run(self
, accountname
, onoff
, credopts
=None, sambaopts
=None,
103 raise CommandError("invalid argument: '%s' (choose from 'on', 'off')" % onoff
)
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
)
114 search_filter
= "sAMAccountName=%s" % ldb
.binary_encode(cleanedaccount
)
115 flag
= dsdb
.UF_TRUSTED_FOR_DELEGATION
117 sam
.toggle_userAccountFlags(search_filter
, flag
,
118 flags_str
="Trusted-for-Delegation",
120 except Exception, err
:
121 raise CommandError(err
)
124 class cmd_delegation_for_any_protocol(Command
):
125 """Set/unset UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION (S4U2Proxy) for an account."""
127 synopsis
= "%prog <accountname> [(on|off)] [options]"
129 takes_optiongroups
= {
130 "sambaopts": options
.SambaOptions
,
131 "credopts": options
.CredentialsOptions
,
132 "versionopts": options
.VersionOptions
,
135 takes_args
= ["accountname", "onoff"]
137 def run(self
, accountname
, onoff
, credopts
=None, sambaopts
=None,
146 raise CommandError("invalid argument: '%s' (choose from 'on', 'off')" % onoff
)
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
)
157 search_filter
= "sAMAccountName=%s" % ldb
.binary_encode(cleanedaccount
)
158 flag
= dsdb
.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
160 sam
.toggle_userAccountFlags(search_filter
, flag
,
161 flags_str
="Trusted-to-Authenticate-for-Delegation",
163 except Exception, err
:
164 raise CommandError(err
)
167 class cmd_delegation_add_service(Command
):
168 """Add a service principal as msDS-AllowedToDelegateTo."""
170 synopsis
= "%prog <accountname> <principal> [options]"
172 takes_optiongroups
= {
173 "sambaopts": options
.SambaOptions
,
174 "credopts": options
.CredentialsOptions
,
175 "versionopts": options
.VersionOptions
,
178 takes_args
= ["accountname", "principal"]
180 def run(self
, accountname
, principal
, credopts
=None, sambaopts
=None,
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
)
192 res
= sam
.search(expression
="sAMAccountName=%s" %
193 ldb
.binary_encode(cleanedaccount
),
194 scope
=ldb
.SCOPE_SUBTREE
,
195 attrs
=["msDS-AllowedToDelegateTo"])
197 raise CommandError("Unable to find account name '%s'" % accountname
)
198 assert(len(res
) == 1)
202 msg
["msDS-AllowedToDelegateTo"] = ldb
.MessageElement([principal
],
204 "msDS-AllowedToDelegateTo")
207 except Exception, err
:
208 raise CommandError(err
)
211 class cmd_delegation_del_service(Command
):
212 """Delete a service principal as msDS-AllowedToDelegateTo."""
214 synopsis
= "%prog <accountname> <principal> [options]"
216 takes_optiongroups
= {
217 "sambaopts": options
.SambaOptions
,
218 "credopts": options
.CredentialsOptions
,
219 "versionopts": options
.VersionOptions
,
222 takes_args
= ["accountname", "principal"]
224 def run(self
, accountname
, principal
, credopts
=None, sambaopts
=None,
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
)
236 res
= sam
.search(expression
="sAMAccountName=%s" %
237 ldb
.binary_encode(cleanedaccount
),
238 scope
=ldb
.SCOPE_SUBTREE
,
239 attrs
=["msDS-AllowedToDelegateTo"])
241 raise CommandError("Unable to find account name '%s'" % accountname
)
242 assert(len(res
) == 1)
246 msg
["msDS-AllowedToDelegateTo"] = ldb
.MessageElement([principal
],
248 "msDS-AllowedToDelegateTo")
251 except Exception, err
:
252 raise CommandError(err
)
255 class cmd_delegation(SuperCommand
):
256 """Delegation management"""
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()