PEP8: fix E241: multiple spaces after ','
[samba.git] / python / samba / netcmd / spn.py
1 # spn management
2 #
3 # Copyright Matthieu Patou mat@samba.org 2010
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18
19 import samba.getopt as options
20 import ldb
21 from samba import provision
22 from samba.samdb import SamDB
23 from samba.auth import system_session
24 from samba.netcmd.common import _get_user_realm_domain
25 from samba.netcmd import (
26     Command,
27     CommandError,
28     SuperCommand,
29     Option
30 )
31
32
33 class cmd_spn_list(Command):
34     """List spns of a given user."""
35
36     synopsis = "%prog <user> [options]"
37
38     takes_optiongroups = {
39         "sambaopts": options.SambaOptions,
40         "credopts": options.CredentialsOptions,
41         "versionopts": options.VersionOptions,
42     }
43
44     takes_args = ["user"]
45
46     def run(self, user, 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         (cleaneduser, realm, domain) = _get_user_realm_domain(user)
55         self.outf.write(cleaneduser + "\n")
56         res = sam.search(
57             expression="samaccountname=%s" % ldb.binary_encode(cleaneduser),
58             scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"])
59         if len(res) > 0:
60             spns = res[0].get("servicePrincipalName")
61             found = False
62             flag = ldb.FLAG_MOD_ADD
63             if spns is not None:
64                 self.outf.write(
65                     "User %s has the following servicePrincipalName: \n" %
66                     res[0].dn)
67                 for e in spns:
68                     self.outf.write("\t %s\n" % e)
69             else:
70                 self.outf.write("User %s has no servicePrincipalName\n" %
71                                 res[0].dn)
72         else:
73             raise CommandError("User %s not found" % user)
74
75
76 class cmd_spn_add(Command):
77     """Create a new spn."""
78
79     synopsis = "%prog <name> <user> [options]"
80
81     takes_optiongroups = {
82         "sambaopts": options.SambaOptions,
83         "credopts": options.CredentialsOptions,
84         "versionopts": options.VersionOptions,
85     }
86     takes_options = [
87         Option("--force", help="Force the addition of the spn"
88                                " even it exists already", action="store_true"),
89             ]
90     takes_args = ["name", "user"]
91
92     def run(self, name, user, force=False, credopts=None, sambaopts=None,
93             versionopts=None):
94         lp = sambaopts.get_loadparm()
95         creds = credopts.get_credentials(lp)
96         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
97         sam = SamDB(paths.samdb, session_info=system_session(),
98                     credentials=creds, lp=lp)
99         res = sam.search(
100             expression="servicePrincipalName=%s" % ldb.binary_encode(name),
101             scope=ldb.SCOPE_SUBTREE)
102         if len(res) != 0 and not force:
103             raise CommandError("Service principal %s already"
104                                " affected to another user" % name)
105
106         (cleaneduser, realm, domain) = _get_user_realm_domain(user)
107         res = sam.search(
108             expression="samaccountname=%s" % ldb.binary_encode(cleaneduser),
109             scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"])
110         if len(res) > 0:
111             res[0].dn
112             msg = ldb.Message()
113             spns = res[0].get("servicePrincipalName")
114             tab = []
115             found = False
116             flag = ldb.FLAG_MOD_ADD
117             if spns is not None:
118                 for e in spns:
119                     if str(e) == name:
120                         found = True
121                     tab.append(str(e))
122                 flag = ldb.FLAG_MOD_REPLACE
123             tab.append(name)
124             msg.dn = res[0].dn
125             msg["servicePrincipalName"] = ldb.MessageElement(tab, flag,
126                                                              "servicePrincipalName")
127             if not found:
128                 sam.modify(msg)
129             else:
130                 raise CommandError("Service principal %s already"
131                                    " affected to %s" % (name, user))
132         else:
133             raise CommandError("User %s not found" % user)
134
135
136 class cmd_spn_delete(Command):
137     """Delete a spn."""
138
139     synopsis = "%prog <name> [user] [options]"
140
141     takes_optiongroups = {
142         "sambaopts": options.SambaOptions,
143         "credopts": options.CredentialsOptions,
144         "versionopts": options.VersionOptions,
145     }
146
147     takes_args = ["name", "user?"]
148
149     def run(self, name, user=None, credopts=None, sambaopts=None,
150             versionopts=None):
151         lp = sambaopts.get_loadparm()
152         creds = credopts.get_credentials(lp)
153         paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
154         sam = SamDB(paths.samdb, session_info=system_session(),
155                     credentials=creds, lp=lp)
156         res = sam.search(
157             expression="servicePrincipalName=%s" % ldb.binary_encode(name),
158             scope=ldb.SCOPE_SUBTREE,
159             attrs=["servicePrincipalName", "samAccountName"])
160         if len(res) > 0:
161             result = None
162             if user is not None:
163                 (cleaneduser, realm, domain) = _get_user_realm_domain(user)
164                 for elem in res:
165                     if str(elem["samAccountName"]).lower() == cleaneduser:
166                         result = elem
167                 if result is None:
168                     raise CommandError("Unable to find user %s with"
169                                        " spn %s" % (user, name))
170             else:
171                 if len(res) != 1:
172                     listUser = ""
173                     for r in res:
174                         listUser = "%s\n%s" % (listUser, str(r.dn))
175                     raise CommandError("More than one user has the spn %s "
176                                        "and no specific user was specified, list of users"
177                                        " with this spn:%s" % (name, listUser))
178                 else:
179                     result = res[0]
180
181
182             msg = ldb.Message()
183             spns = result.get("servicePrincipalName")
184             tab = []
185             if spns is not None:
186                 for e in spns:
187                     if str(e) != name:
188                         tab.append(str(e))
189                 flag = ldb.FLAG_MOD_REPLACE
190             msg.dn = result.dn
191             msg["servicePrincipalName"] = ldb.MessageElement(tab, flag,
192                                                              "servicePrincipalName")
193             sam.modify(msg)
194         else:
195             raise CommandError("Service principal %s not affected" % name)
196
197
198 class cmd_spn(SuperCommand):
199     """Service Principal Name (SPN) management."""
200
201     subcommands = {}
202     subcommands["add"] = cmd_spn_add()
203     subcommands["list"] = cmd_spn_list()
204     subcommands["delete"] = cmd_spn_delete()
205