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
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 (
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"])
61 raise CommandError("Unable to find account name '%s'" % accountname
)
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:
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):
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
107 sam
.toggle_userAccountFlags(search_filter
, flag
,
108 flags_str
="Trusted-for-Delegation",
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):
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
143 sam
.toggle_userAccountFlags(search_filter
, flag
,
144 flags_str
="Trusted-to-Authenticate-for-Delegation",
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"])
173 raise CommandError("Unable to find account name '%s'" % accountname
)
174 assert(len(res
) == 1)
178 msg
["msDS-AllowedToDelegateTo"] = ldb
.MessageElement([principal
],
180 "msDS-AllowedToDelegateTo")
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"])
210 raise CommandError("Unable to find account name '%s'" % accountname
)
211 assert(len(res
) == 1)
215 msg
["msDS-AllowedToDelegateTo"] = ldb
.MessageElement([principal
],
217 "msDS-AllowedToDelegateTo")
220 except Exception, err
:
221 raise CommandError(err
)
224 class cmd_delegation(SuperCommand
):
225 """Delegation management"""
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()