From: Björn Baumbach Date: Wed, 16 May 2018 08:19:16 +0000 (+0200) Subject: samba-tool: implement user setprimary group command (set primaryGroupID) X-Git-Tag: ldb-2.1.0~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8403527bbd132ee639fdd3926bf55d15bd8dea56;p=thirdparty%2Fsamba.git samba-tool: implement user setprimary group command (set primaryGroupID) Introduce an option to set the primaryGroupID attribute of a user account. Pair-programmed-with: Stefan Metzmacher Signed-off-by: Björn Baumbach Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- diff --git a/docs-xml/manpages/samba-tool.8.xml b/docs-xml/manpages/samba-tool.8.xml index 9664bb9cd56..d242d13ad6c 100644 --- a/docs-xml/manpages/samba-tool.8.xml +++ b/docs-xml/manpages/samba-tool.8.xml @@ -1192,6 +1192,11 @@ List all users. + + user setprimarygroup <replaceable>username</replaceable> <replaceable>primarygroupname</replaceable> + Set the primary group a user account. + + user show <replaceable>username</replaceable> [options] Display a user AD object. diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py index 86a7a45b24e..8e07e99b71b 100644 --- a/python/samba/netcmd/user.py +++ b/python/samba/netcmd/user.py @@ -736,6 +736,116 @@ class cmd_user_password(Command): self.outf.write("Changed password OK\n") +class cmd_user_setprimarygroup(Command): + """Set the primary group a user account. + +This command sets the primary group a user account. The username specified on +the command is the sAMAccountName. The primarygroupname is the sAMAccountName +of the new primary group. The user must be a member of the group. + +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 against a remote server. + +Example1: +samba-tool user setprimarygroup TestUser1 newPrimaryGroup --URL=ldap://samba.samdom.example.com -Uadministrator%passw1rd + +Example1 shows how to set the primary group for TestUser1 on a remote LDAP +server. The --URL parameter is used to specify the remote target server. The +-U option is used to pass the username and password of a user that exists on +the remote server and is authorized to update the server. +""" + synopsis = "%prog [options]" + + takes_optiongroups = { + "sambaopts": options.SambaOptions, + "versionopts": options.VersionOptions, + "credopts": options.CredentialsOptions, + } + + takes_options = [ + Option("-H", "--URL", help="LDB URL for database or target server", type=str, + metavar="URL", dest="H"), + ] + + takes_args = ["username", "primarygroupname"] + + def run(self, username, primarygroupname, credopts=None, sambaopts=None, + versionopts=None, H=None): + + lp = sambaopts.get_loadparm() + creds = credopts.get_credentials(lp) + + samdb = SamDB(url=H, session_info=system_session(), + credentials=creds, lp=lp) + + filter = ("(&(sAMAccountName=%s)(objectClass=user))" % + ldb.binary_encode(username)) + try: + res = samdb.search(base=samdb.domain_dn(), + expression=filter, + scope=ldb.SCOPE_SUBTREE, + controls=["extended_dn:1:1"], + attrs=["objectSid", + "memberOf", + "primaryGroupID"]) + user_sid_binary = res[0].get('objectSid', idx=0) + user_sid = ndr_unpack(security.dom_sid, user_sid_binary) + (user_dom_sid, user_rid) = user_sid.split() + user_sid_dn = "" % user_sid + user_pgid = int(res[0].get('primaryGroupID', idx=0)) + user_groups = res[0].get('memberOf') + if user_groups is None: + user_groups = [] + except IndexError: + raise CommandError("Unable to find user '%s'" % (username)) + + user_group_sids = [] + for user_group in user_groups: + user_group_dn = ldb.Dn(samdb, str(user_group)) + user_group_binary_sid = user_group_dn.get_extended_component("SID") + user_group_sid = ndr_unpack(security.dom_sid, user_group_binary_sid) + user_group_sids.append(user_group_sid) + + filter = ("(&(sAMAccountName=%s)(objectClass=group))" % + ldb.binary_encode(primarygroupname)) + try: + res = samdb.search(base=samdb.domain_dn(), + expression=filter, + scope=ldb.SCOPE_SUBTREE, + attrs=["objectSid"]) + group_sid_binary = res[0].get('objectSid', idx=0) + except IndexError: + raise CommandError("Unable to find group '%s'" % (primarygroupname)) + + primarygroup_sid = ndr_unpack(security.dom_sid, group_sid_binary) + (primarygroup_dom_sid, primarygroup_rid) = primarygroup_sid.split() + + if user_dom_sid != primarygroup_dom_sid: + raise CommandError("Group '%s' does not belong to the user's " + "domain" % primarygroupname) + + if primarygroup_rid != user_pgid and primarygroup_sid not in user_group_sids: + raise CommandError("User '%s' is not member of group '%s'" % + (username, primarygroupname)) + + setprimarygroup_ldif = """ +dn: %s +changetype: modify +delete: primaryGroupID +primaryGroupID: %u +add: primaryGroupID +primaryGroupID: %u +""" % (user_sid_dn, user_pgid, primarygroup_rid) + + try: + samdb.modify_ldif(setprimarygroup_ldif) + except Exception as msg: + raise CommandError("Failed to set primary group '%s' " + "for user '%s': %s" % + (primarygroupname, username, msg)) + self.outf.write("Changed primary group to '%s'\n" % primarygroupname) + + class cmd_user_setpassword(Command): """Set or reset the password of a user account. @@ -2894,6 +3004,7 @@ class cmd_user(SuperCommand): subcommands["list"] = cmd_user_list() subcommands["setexpiry"] = cmd_user_setexpiry() subcommands["password"] = cmd_user_password() + subcommands["setprimarygroup"] = cmd_user_setprimarygroup() subcommands["setpassword"] = cmd_user_setpassword() subcommands["getpassword"] = cmd_user_getpassword() subcommands["syncpasswords"] = cmd_user_syncpasswords()