nfs4acls: Use talloc_realloc()
[Samba.git] / python / samba / netcmd / group.py
blob722bcc4887fcc15bab7cf8a9eb56e3f1e45d3145
1 # Copyright Jelmer Vernooij 2008
3 # Based on the original in EJS:
4 # Copyright Andrew Tridgell 2005
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 import samba.getopt as options
20 from samba.netcmd import Command, SuperCommand, CommandError, Option
21 import ldb
22 from samba.ndr import ndr_unpack
23 from samba.dcerpc import security
25 from getpass import getpass
26 from samba.auth import system_session
27 from samba.samdb import SamDB
28 from samba.dsdb import (
29 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
30 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP,
31 GTYPE_SECURITY_GLOBAL_GROUP,
32 GTYPE_SECURITY_UNIVERSAL_GROUP,
33 GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP,
34 GTYPE_DISTRIBUTION_GLOBAL_GROUP,
35 GTYPE_DISTRIBUTION_UNIVERSAL_GROUP,
38 security_group = dict({"Builtin": GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
39 "Domain": GTYPE_SECURITY_DOMAIN_LOCAL_GROUP,
40 "Global": GTYPE_SECURITY_GLOBAL_GROUP,
41 "Universal": GTYPE_SECURITY_UNIVERSAL_GROUP})
42 distribution_group = dict({"Domain": GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP,
43 "Global": GTYPE_DISTRIBUTION_GLOBAL_GROUP,
44 "Universal": GTYPE_DISTRIBUTION_UNIVERSAL_GROUP})
47 class cmd_group_add(Command):
48 """Creates a new AD group.
50 This command creates a new Active Directory group. The groupname specified on the command is a unique sAMAccountName.
52 An Active Directory group may contain user and computer accounts as well as other groups. An administrator creates a group and adds members to that group so they can be managed as a single entity. This helps to simplify security and system administration.
54 Groups may also be used to establish email distribution lists, using --group-type=Distribution.
56 Groups are located in domains in organizational units (OUs). The group's scope is a characteristic of the group that designates the extent to which the group is applied within the domain tree or forest.
58 The group location (OU), type (security or distribution) and scope may all be specified on the samba-tool command when the group is created.
60 The command may be run from the root userid or another authorized userid. The
61 -H or --URL= option can be used to execute the command on a remote server.
63 Example1:
64 samba-tool group add Group1 -H ldap://samba.samdom.example.com --description='Simple group'
66 Example1 adds a new group with the name Group1 added to the Users container on a remote LDAP server. The -U parameter is used to pass the userid and password of a user that exists on the remote server and is authorized to issue the command on that server. It defaults to the security type and global scope.
68 Example2:
69 sudo samba-tool group add Group2 --group-type=Distribution
71 Example2 adds a new distribution group to the local server. The command is run under root using the sudo command.
73 Example3:
74 samba-tool group add Group3 --nis-domain=samdom --gid-number=12345
76 Example3 adds a new RFC2307 enabled group for NIS domain samdom and GID 12345 (both options are required to enable this feature).
77 """
79 synopsis = "%prog <groupname> [options]"
81 takes_optiongroups = {
82 "sambaopts": options.SambaOptions,
83 "versionopts": options.VersionOptions,
84 "credopts": options.CredentialsOptions,
87 takes_options = [
88 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
89 metavar="URL", dest="H"),
90 Option("--groupou",
91 help="Alternative location (without domainDN counterpart) to default CN=Users in which new user object will be created",
92 type=str),
93 Option("--group-scope", type="choice", choices=["Domain", "Global", "Universal"],
94 help="Group scope (Domain | Global | Universal)"),
95 Option("--group-type", type="choice", choices=["Security", "Distribution"],
96 help="Group type (Security | Distribution)"),
97 Option("--description", help="Group's description", type=str),
98 Option("--mail-address", help="Group's email address", type=str),
99 Option("--notes", help="Groups's notes", type=str),
100 Option("--gid-number", help="Group's Unix/RFC2307 GID number", type=int),
101 Option("--nis-domain", help="SFU30 NIS Domain", type=str),
104 takes_args = ["groupname"]
106 def run(self, groupname, credopts=None, sambaopts=None,
107 versionopts=None, H=None, groupou=None, group_scope=None,
108 group_type=None, description=None, mail_address=None, notes=None, gid_number=None, nis_domain=None):
110 if (group_type or "Security") == "Security":
111 gtype = security_group.get(group_scope, GTYPE_SECURITY_GLOBAL_GROUP)
112 else:
113 gtype = distribution_group.get(group_scope, GTYPE_DISTRIBUTION_GLOBAL_GROUP)
115 if (gid_number is None and nis_domain is not None) or (gid_number is not None and nis_domain is None):
116 raise CommandError('Both --gid-number and --nis-domain have to be set for a RFC2307-enabled group. Operation cancelled.')
118 lp = sambaopts.get_loadparm()
119 creds = credopts.get_credentials(lp, fallback_machine=True)
121 try:
122 samdb = SamDB(url=H, session_info=system_session(),
123 credentials=creds, lp=lp)
124 samdb.newgroup(groupname, groupou=groupou, grouptype = gtype,
125 description=description, mailaddress=mail_address, notes=notes,
126 gidnumber=gid_number, nisdomain=nis_domain)
127 except Exception, e:
128 # FIXME: catch more specific exception
129 raise CommandError('Failed to create group "%s"' % groupname, e)
130 self.outf.write("Added group %s\n" % groupname)
133 class cmd_group_delete(Command):
134 """Deletes an AD group.
136 The command deletes an existing AD group from the Active Directory domain. The groupname specified on the command is the sAMAccountName.
138 Deleting a group is a permanent operation. When a group is deleted, all permissions and rights that users in the group had inherited from the group account are deleted as well.
140 The command may be run from the root userid or another authorized userid. The -H or --URL option can be used to execute the command on a remote server.
142 Example1:
143 samba-tool group delete Group1 -H ldap://samba.samdom.example.com -Uadministrator%passw0rd
145 Example1 shows how to delete an AD group from a remote LDAP server. The -U parameter is used to pass the userid and password of a user that exists on the remote server and is authorized to issue the command on that server.
147 Example2:
148 sudo samba-tool group delete Group2
150 Example2 deletes group Group2 from the local server. The command is run under root using the sudo command.
153 synopsis = "%prog <groupname> [options]"
155 takes_optiongroups = {
156 "sambaopts": options.SambaOptions,
157 "versionopts": options.VersionOptions,
158 "credopts": options.CredentialsOptions,
161 takes_options = [
162 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
163 metavar="URL", dest="H"),
166 takes_args = ["groupname"]
168 def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=None):
170 lp = sambaopts.get_loadparm()
171 creds = credopts.get_credentials(lp, fallback_machine=True)
173 try:
174 samdb = SamDB(url=H, session_info=system_session(),
175 credentials=creds, lp=lp)
176 samdb.deletegroup(groupname)
177 except Exception, e:
178 # FIXME: catch more specific exception
179 raise CommandError('Failed to remove group "%s"' % groupname, e)
180 self.outf.write("Deleted group %s\n" % groupname)
183 class cmd_group_add_members(Command):
184 """Add members to an AD group.
186 This command adds one or more members to an existing Active Directory group. The command accepts one or more group member names separated by commas. A group member may be a user or computer account or another Active Directory group.
188 When a member is added to a group the member may inherit permissions and rights from the group. Likewise, when permission or rights of a group are changed, the changes may reflect in the members through inheritance.
190 Example1:
191 samba-tool group addmembers supergroup Group1,Group2,User1 -H ldap://samba.samdom.example.com -Uadministrator%passw0rd
193 Example1 shows how to add two groups, Group1 and Group2 and one user account, User1, to the existing AD group named supergroup. The command will be run on a remote server specified with the -H. The -U parameter is used to pass the userid and password of a user authorized to issue the command on the remote server.
195 Example2:
196 sudo samba-tool group addmembers supergroup User2
198 Example2 shows how to add a single user account, User2, to the supergroup AD group. It uses the sudo command to run as root when issuing the command.
201 synopsis = "%prog <groupname> <listofmembers> [options]"
203 takes_optiongroups = {
204 "sambaopts": options.SambaOptions,
205 "versionopts": options.VersionOptions,
206 "credopts": options.CredentialsOptions,
209 takes_options = [
210 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
211 metavar="URL", dest="H"),
214 takes_args = ["groupname", "listofmembers"]
216 def run(self, groupname, listofmembers, credopts=None, sambaopts=None,
217 versionopts=None, H=None):
219 lp = sambaopts.get_loadparm()
220 creds = credopts.get_credentials(lp, fallback_machine=True)
222 try:
223 samdb = SamDB(url=H, session_info=system_session(),
224 credentials=creds, lp=lp)
225 groupmembers = listofmembers.split(',')
226 samdb.add_remove_group_members(groupname, groupmembers,
227 add_members_operation=True)
228 except Exception, e:
229 # FIXME: catch more specific exception
230 raise CommandError('Failed to add members "%s" to group "%s"' % (
231 listofmembers, groupname), e)
232 self.outf.write("Added members to group %s\n" % groupname)
235 class cmd_group_remove_members(Command):
236 """Remove members from an AD group.
238 This command removes one or more members from an existing Active Directory group. The command accepts one or more group member names separated by commas. A group member may be a user or computer account or another Active Directory group that is a member of the group specified on the command.
240 When a member is removed from a group, inherited permissions and rights will no longer apply to the member.
242 Example1:
243 samba-tool group removemembers supergroup Group1 -H ldap://samba.samdom.example.com -Uadministrator%passw0rd
245 Example1 shows how to remove Group1 from supergroup. The command will run on the remote server specified on the -H parameter. The -U parameter is used to pass the userid and password of a user authorized to issue the command on the remote server.
247 Example2:
248 sudo samba-tool group removemembers supergroup User1
250 Example2 shows how to remove a single user account, User2, from the supergroup AD group. It uses the sudo command to run as root when issuing the command.
253 synopsis = "%prog <groupname> <listofmembers> [options]"
255 takes_optiongroups = {
256 "sambaopts": options.SambaOptions,
257 "versionopts": options.VersionOptions,
258 "credopts": options.CredentialsOptions,
261 takes_options = [
262 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
263 metavar="URL", dest="H"),
266 takes_args = ["groupname", "listofmembers"]
268 def run(self, groupname, listofmembers, credopts=None, sambaopts=None,
269 versionopts=None, H=None):
271 lp = sambaopts.get_loadparm()
272 creds = credopts.get_credentials(lp, fallback_machine=True)
274 try:
275 samdb = SamDB(url=H, session_info=system_session(),
276 credentials=creds, lp=lp)
277 samdb.add_remove_group_members(groupname, listofmembers.split(","),
278 add_members_operation=False)
279 except Exception, e:
280 # FIXME: Catch more specific exception
281 raise CommandError('Failed to remove members "%s" from group "%s"' % (listofmembers, groupname), e)
282 self.outf.write("Removed members from group %s\n" % groupname)
285 class cmd_group_list(Command):
286 """List all groups."""
288 synopsis = "%prog [options]"
290 takes_options = [
291 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
292 metavar="URL", dest="H"),
293 Option("-v", "--verbose",
294 help="Verbose output, showing group type and group scope.",
295 action="store_true"),
299 takes_optiongroups = {
300 "sambaopts": options.SambaOptions,
301 "credopts": options.CredentialsOptions,
302 "versionopts": options.VersionOptions,
305 def run(self, sambaopts=None, credopts=None, versionopts=None, H=None,
306 verbose=False):
307 lp = sambaopts.get_loadparm()
308 creds = credopts.get_credentials(lp, fallback_machine=True)
310 samdb = SamDB(url=H, session_info=system_session(),
311 credentials=creds, lp=lp)
313 domain_dn = samdb.domain_dn()
314 res = samdb.search(domain_dn, scope=ldb.SCOPE_SUBTREE,
315 expression=("(objectClass=group)"),
316 attrs=["samaccountname", "grouptype"])
317 if (len(res) == 0):
318 return
320 if verbose:
321 self.outf.write("Group Name Group Type Group Scope\n")
322 self.outf.write("-----------------------------------------------------------------------------\n")
324 for msg in res:
325 self.outf.write("%-44s" % msg.get("samaccountname", idx=0))
326 hgtype = hex(int("%s" % msg["grouptype"]) & 0x00000000FFFFFFFF)
327 if (hgtype == hex(int(security_group.get("Builtin")))):
328 self.outf.write("Security Builtin\n")
329 elif (hgtype == hex(int(security_group.get("Domain")))):
330 self.outf.write("Security Domain\n")
331 elif (hgtype == hex(int(security_group.get("Global")))):
332 self.outf.write("Security Global\n")
333 elif (hgtype == hex(int(security_group.get("Universal")))):
334 self.outf.write("Security Universal\n")
335 elif (hgtype == hex(int(distribution_group.get("Global")))):
336 self.outf.write("Distribution Global\n")
337 elif (hgtype == hex(int(distribution_group.get("Domain")))):
338 self.outf.write("Distribution Domain\n")
339 elif (hgtype == hex(int(distribution_group.get("Universal")))):
340 self.outf.write("Distribution Universal\n")
341 else:
342 self.outf.write("\n")
343 else:
344 for msg in res:
345 self.outf.write("%s\n" % msg.get("samaccountname", idx=0))
347 class cmd_group_list_members(Command):
348 """List all members of an AD group.
350 This command lists members from an existing Active Directory group. The command accepts one group name.
352 Example1:
353 samba-tool group listmembers \"Domain Users\" -H ldap://samba.samdom.example.com -Uadministrator%passw0rd
356 synopsis = "%prog <groupname> [options]"
358 takes_options = [
359 Option("-H", "--URL", help="LDB URL for database or target server", type=str,
360 metavar="URL", dest="H"),
363 takes_optiongroups = {
364 "sambaopts": options.SambaOptions,
365 "credopts": options.CredentialsOptions,
366 "versionopts": options.VersionOptions,
369 takes_args = ["groupname"]
371 def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, H=None):
372 lp = sambaopts.get_loadparm()
373 creds = credopts.get_credentials(lp, fallback_machine=True)
375 try:
376 samdb = SamDB(url=H, session_info=system_session(),
377 credentials=creds, lp=lp)
379 search_filter = "(&(objectClass=group)(samaccountname=%s))" % groupname
380 res = samdb.search(samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE,
381 expression=(search_filter),
382 attrs=["objectSid"])
384 if (len(res) != 1):
385 return
387 group_dn = res[0].get('dn', idx=0)
388 object_sid = res[0].get('objectSid', idx=0)
390 object_sid = ndr_unpack(security.dom_sid, object_sid)
391 (group_dom_sid, rid) = object_sid.split()
393 search_filter = "(|(primaryGroupID=%s)(memberOf=%s))" % (rid, group_dn)
394 res = samdb.search(samdb.domain_dn(), scope=ldb.SCOPE_SUBTREE,
395 expression=(search_filter),
396 attrs=["samAccountName", "cn"])
398 if (len(res) == 0):
399 return
401 for msg in res:
402 member_name = msg.get("samAccountName", idx=0)
403 if member_name is None:
404 member_name = msg.get("cn", idx=0)
405 self.outf.write("%s\n" % member_name)
407 except Exception, e:
408 raise CommandError('Failed to list members of "%s" group ' % groupname, e)
411 class cmd_group(SuperCommand):
412 """Group management."""
414 subcommands = {}
415 subcommands["add"] = cmd_group_add()
416 subcommands["delete"] = cmd_group_delete()
417 subcommands["addmembers"] = cmd_group_add_members()
418 subcommands["removemembers"] = cmd_group_remove_members()
419 subcommands["list"] = cmd_group_list()
420 subcommands["listmembers"] = cmd_group_list_members()