5 # Copyright Matthieu Patou mat@samba.org 2010
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
24 from samba
import provision
25 from samba
.samdb
import SamDB
26 from samba
.auth
import system_session
27 from samba
.netcmd
import (
34 def _get_user_realm_domain(user
):
35 """ get the realm or the domain and the base user
44 m
= re
.match(r
"(\w+)\\(\w+$)", user
)
48 return (baseuser
.lower(), domain
.upper(), realm
)
49 m
= re
.match(r
"(\w+)@(\w+)", user
)
53 return (baseuser
.lower(), domain
, realm
.upper())
55 class cmd_spn_list(Command
):
56 """List spns of a given user."""
57 synopsis
= "%prog spn list <user>"
59 takes_optiongroups
= {
60 "sambaopts": options
.SambaOptions
,
61 "credopts": options
.CredentialsOptions
,
62 "versionopts": options
.VersionOptions
,
67 def run(self
, user
, credopts
=None, sambaopts
=None, versionopts
=None):
68 lp
= sambaopts
.get_loadparm()
69 creds
= credopts
.get_credentials(lp
)
70 paths
= provision
.provision_paths_from_lp(lp
, lp
.get("realm"))
71 sam
= SamDB(paths
.samdb
, session_info
=system_session(),
72 credentials
=creds
, lp
=lp
)
73 # TODO once I understand how, use the domain info to naildown
74 # to the correct domain
75 (cleaneduser
, realm
, domain
) = _get_user_realm_domain(user
)
77 res
= sam
.search(expression
="samaccountname=%s" % cleaneduser
,
78 scope
=ldb
.SCOPE_SUBTREE
,
79 attrs
=["servicePrincipalName"])
81 spns
= res
[0].get("servicePrincipalName")
83 flag
= ldb
.FLAG_MOD_ADD
85 print "User %s has the following servicePrincipalName: " % str(res
[0].dn
)
87 print "\t %s" % (str(e
))
90 print "User %s has no servicePrincipalName" % str(res
[0].dn
)
92 raise CommandError("User %s not found" % user
)
94 class cmd_spn_add(Command
):
95 """Create a new spn."""
96 synopsis
= "%prog spn add [--force] <name> <user>"
98 takes_optiongroups
= {
99 "sambaopts": options
.SambaOptions
,
100 "credopts": options
.CredentialsOptions
,
101 "versionopts": options
.VersionOptions
,
104 Option("--force", help="Force the addition of the spn"\
105 " even it exists already", action
="store_true"),
107 takes_args
= ["name", "user"]
109 def run(self
, name
, user
, force
=False, credopts
=None, sambaopts
=None, versionopts
=None):
110 lp
= sambaopts
.get_loadparm()
111 creds
= credopts
.get_credentials(lp
)
112 paths
= provision
.provision_paths_from_lp(lp
, lp
.get("realm"))
113 sam
= SamDB(paths
.samdb
, session_info
=system_session(),
114 credentials
=creds
, lp
=lp
)
115 res
= sam
.search(expression
="servicePrincipalName=%s" % name
,
116 scope
=ldb
.SCOPE_SUBTREE
,
118 if len(res
) != 0 and not force
:
119 raise CommandError("Service principal %s already"
120 " affected to another user" % name
)
122 (cleaneduser
, realm
, domain
) = _get_user_realm_domain(user
)
123 res
= sam
.search(expression
="samaccountname=%s" % cleaneduser
,
124 scope
=ldb
.SCOPE_SUBTREE
,
125 attrs
=["servicePrincipalName"])
129 spns
= res
[0].get("servicePrincipalName")
132 flag
= ldb
.FLAG_MOD_ADD
138 flag
= ldb
.FLAG_MOD_REPLACE
141 msg
["servicePrincipalName"] = ldb
.MessageElement(tab
, flag
,
142 "servicePrincipalName")
146 raise CommandError("Service principal %s already"
147 " affected to %s" % (name
, user
))
149 raise CommandError("User %s not found" % user
)
152 class cmd_spn_delete(Command
):
154 synopsis
= "%prog spn delete <name> [user]"
156 takes_optiongroups
= {
157 "sambaopts": options
.SambaOptions
,
158 "credopts": options
.CredentialsOptions
,
159 "versionopts": options
.VersionOptions
,
162 takes_args
= ["name", "user?"]
164 def run(self
, name
, user
=None, credopts
=None, sambaopts
=None, versionopts
=None):
165 lp
= sambaopts
.get_loadparm()
166 creds
= credopts
.get_credentials(lp
)
167 paths
= provision
.provision_paths_from_lp(lp
, lp
.get("realm"))
168 sam
= SamDB(paths
.samdb
, session_info
=system_session(),
169 credentials
=creds
, lp
=lp
)
170 res
= sam
.search(expression
="servicePrincipalName=%s" % name
,
171 scope
=ldb
.SCOPE_SUBTREE
,
172 attrs
=["servicePrincipalName", "samAccountName"])
176 (cleaneduser
, realm
, domain
) = _get_user_realm_domain(user
)
178 if str(elem
["samAccountName"]).lower() == cleaneduser
:
181 raise CommandError("Unable to find user %s with"
182 " spn %s" % (user
, name
))
187 listUser
= "%s\n%s" % (listUser
, str(r
.dn
))
188 raise CommandError("More than one user has the spn %s "\
189 "and no specific user was specified, list of users"\
190 " with this spn:%s" % (name
, listUser
))
196 spns
= result
.get("servicePrincipalName")
202 flag
= ldb
.FLAG_MOD_REPLACE
204 msg
["servicePrincipalName"] = ldb
.MessageElement(tab
, flag
,
205 "servicePrincipalName")
208 raise CommandError("Service principal %s not affected" % name
)
210 class cmd_spn(SuperCommand
):
211 """User management [server connection needed]"""
214 subcommands
["add"] = cmd_spn_add()
215 subcommands
["list"] = cmd_spn_list()
216 subcommands
["delete"] = cmd_spn_delete()