[PATCH] Add Unix attributes to a user or group in AD

Rowland Penny repenny241155 at gmail.com
Tue Oct 27 16:01:43 UTC 2015


Hi, the attached patches allow for the adding of Unix attributes to an 
already created user or group, they work much in the same way as 
'samba-tool user create' does except it requires a user or group that 
already exists.

The first patch allows to get an AD objects DN from its samaccountname
The second allows samba-tool to update a user
The third allows samba-tool to update a group

I think this is going to be required now that ADUC on win10 doesn't come 
with the UNIX Attributes tab.

Rowland
-------------- next part --------------
From 513ba85fe934bc2c7203c310a798eb45456bcf11 Mon Sep 17 00:00:00 2001
From: Rowland Penny <repenny241155 at gmail.com>
Date: Tue, 27 Oct 2015 15:36:45 +0000
Subject: [PATCH 1/3] samdb.py: get object dn from samaccountname
 Signed-off-by: Rowland Penny <repenny241155 at gmail.com>

---
 python/samba/samdb.py |   16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/python/samba/samdb.py b/python/samba/samdb.py
index 5750291..155d0df 100644
--- a/python/samba/samdb.py
+++ b/python/samba/samdb.py
@@ -944,3 +944,19 @@ accountExpires: %u
         is removed, this routine will put a tombstone in the record.
         '''
         return dsdb_dns.replace_by_dn(self, dn, new_records)
+
+    def get_object_dn(self, search_filter):
+        """Gets an objects DN
+
+        :param search_filter: LDAP filter to find the object (eg
+            samaccountname=name)
+        """
+        res = self.search(base=self.domain_dn(), 
+                          scope=ldb.SCOPE_SUBTREE,
+                          expression=search_filter,
+                          attrs=["dn", "sAMAccountName"])
+        if len(res) == 0:
+            raise Exception('Unable to find object "%s"' % 
+                            search_filter)
+        assert(len(res) == 1)
+        return res[0].dn
-- 
1.7.10.4

-------------- next part --------------
From 3897fff2e9cac43cb3d70d731aa30ffd9d660975 Mon Sep 17 00:00:00 2001
From: Rowland Penny <repenny241155 at gmail.com>
Date: Tue, 27 Oct 2015 15:44:16 +0000
Subject: [PATCH 2/3] user.py: update user with nis attributes Signed-off-by:
 Rowland Penny <repenny241155 at gmail.com>

---
 python/samba/netcmd/user.py |  156 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 156 insertions(+)

diff --git a/python/samba/netcmd/user.py b/python/samba/netcmd/user.py
index 2bc5522..7d39818 100644
--- a/python/samba/netcmd/user.py
+++ b/python/samba/netcmd/user.py
@@ -611,6 +611,161 @@ Example3 shows how an administrator would reset TestUser3 user's password to pas
         self.outf.write("Changed password OK\n")
 
 
+class cmd_user_nis_add(Command):
+    """Add NIS attributes to a user.
+
+This command adds NIS info to a user account in the Active 
+Directory domain.  
+The username specified on the command is the sAMaccountName.
+
+Unix (RFC2307) attributes will be added to the user account. 
+Add 'idmap_ldb:use rfc2307 = Yes' to smb.conf to use these 
+attributes for UID/GID mapping.
+
+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.
+
+Example:
+samba-tool user nisadd User1 --nis-domain=samdom --uid-number=10005 \
+--unix-home=/home/User1 --login-shell=/bin/false [--group-name=unixgroup]
+
+The example shows how to add RFC2307/NIS attributes to a domain 
+enabled user account. 
+The first four parameters are mandatory. 
+
+if the parameter '--group-name' is given, then the groups 'gidNumber' 
+will be obtained and used for the users 'gidNumber' attribute, this 
+does of course mean that the group MUST have a 'gidNumber.
+
+If the last parameter, '--group-name' & is omitted, the users gidNumber 
+will be  set to the gidNumber found in Domain Users. 
+This means that 'Domain Users' MUST  have a gidNumber.
+"""
+    synopsis = "%prog <username> [options]"
+
+    takes_options = [
+        Option("-H", "--URL", help="LDB URL for database or target server", 
+                type=str, metavar="URL", dest="H"),
+        Option("--nis-domain", help="User's Unix/RFC2307 NIS domain",
+                type=str),
+        Option("--unix-home", help="User's Unix/RFC2307 home directory", 
+                type=str),
+        Option("--group-name", help="A Unix/RFC2307 enabled AD group", 
+                type=str), 
+        Option("--login-shell", help="User's Unix/RFC2307 login shell", 
+                type=str),
+        Option("--uid-number", help="User's Unix/RFC2307 numeric UID",
+                type=str),
+        Option("--gid-number", help="User's Unix/RFC2307 numeric GID number",
+                type=str),
+
+    ]
+
+    takes_args = ["username"]
+
+    takes_optiongroups = {
+        "sambaopts": options.SambaOptions,
+        "credopts": options.CredentialsOptions,
+        "versionopts": options.VersionOptions,
+        }
+
+    def run(self, username, credopts=None, sambaopts=None, versionopts=None, 
+            H=None, nis_domain=None, unix_home=None, uid_number=None, 
+            gid_number=None, group_name=None, login_shell=None):
+
+        lp = sambaopts.get_loadparm()
+        creds = credopts.get_credentials(lp)
+
+        samdb = SamDB(url=H, session_info=system_session(), credentials=creds, 
+                      lp=lp)
+
+        if None in (nis_domain, uid_number, login_shell, unix_home):
+            raise CommandError('Missing parameters. To enable NIS features, '
+                               'the following options have to be given: '
+                               '--nis-domain=, --uid-number, --login-shell=,'
+                               ' --unix-home=, Operation cancelled.')
+
+        domain_dn = samdb.domain_dn()
+        search_filter = "(samaccountname=%s)" % username
+        user_dn = samdb.get_object_dn(search_filter)
+ 
+        # what if user already is a NIS user??
+        res = samdb.search(user_dn,
+                          scope=ldb.SCOPE_BASE, 
+                          attrs=["uidNumber"])
+        if "uidNumber" in res[0]:
+            raise CommandError("User %s already is a NIS user." % username) 
+
+        if group_name is not None:
+            # get users primary GID from group_name
+            search_filter = "samaccountname=%s" % group_name
+            group_dn = samdb.get_object_dn(search_filter)
+            try:
+                res = samdb.search(group_dn,
+                                   scope=ldb.SCOPE_SUBTREE, 
+                                   attrs=["gidNumber"])
+                assert len(res) == 1
+                gid_number = res[0]["gidNumber"][0]
+            except:
+                raise CommandError("Group %s does not have a gidNumber" % 
+                                    group_name)
+
+        if group_name is None:
+            # set users primary GID to the one from Domain Users
+            du_dn = "CN=Domain Users,CN=Users," + domain_dn
+            try:
+                res = samdb.search(du_dn,
+                                   scope=ldb.SCOPE_SUBTREE, 
+                                   attrs=["gidNumber"])
+                assert len(res) == 1
+                gid_number = res[0]["gidNumber"][0]
+            except:
+                raise CommandError("Domain Users Group does \
+not have a gidNumber attribute")
+
+        if not lp.get("idmap_ldb:use rfc2307"):
+            self.outf.write("You are setting a Unix/RFC2307 UID or GID. \
+You may want to set 'idmap_ldb:use rfc2307 = Yes' in smb.conf to use those \
+attributes for XID/SID-mapping.\n")
+
+        update_user = """
+dn: %s
+changetype: modify
+add: uid
+uid: %s
+-
+add: msSFU30Name
+msSFU30Name: %s
+-
+add: msSFU30NisDomain
+msSFU30NisDomain: %s
+-
+add: uidNumber
+uidNumber: %s
+-
+add: gidNumber
+gidNumber: %s
+-
+add: loginShell
+loginShell: %s
+-
+add: unixHomeDirectory
+unixHomeDirectory: %s
+-
+add: unixUserPassword
+unixUserPassword: ABCD!efgh12345$67890
+""" % (user_dn, username, username, nis_domain, uid_number, gid_number, 
+       login_shell, unix_home)
+
+        try:
+            samdb.modify_ldif(update_user)
+        except Exception, e:
+            raise CommandError("Failed to update user '%s': " % username, e)
+
+        self.outf.write("User '%s' updated successfully\n" % username)
+
+
 class cmd_user(SuperCommand):
     """User management."""
 
@@ -624,3 +779,4 @@ class cmd_user(SuperCommand):
     subcommands["setexpiry"] = cmd_user_setexpiry()
     subcommands["password"] = cmd_user_password()
     subcommands["setpassword"] = cmd_user_setpassword()
+    subcommands["nisadd"] = cmd_user_nis_add()
-- 
1.7.10.4

-------------- next part --------------
From 40ed888f97538b2f90b1a7a134e74a1946f92266 Mon Sep 17 00:00:00 2001
From: Rowland Penny <repenny241155 at gmail.com>
Date: Tue, 27 Oct 2015 15:48:31 +0000
Subject: [PATCH 3/3] group.py: update group with nis attributes
 Signed-off-by: Rowland Penny <repenny241155 at gmail.com>

---
 python/samba/netcmd/group.py |   94 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 94 insertions(+)

diff --git a/python/samba/netcmd/group.py b/python/samba/netcmd/group.py
index 722bcc4..efb819a 100644
--- a/python/samba/netcmd/group.py
+++ b/python/samba/netcmd/group.py
@@ -408,6 +408,99 @@ samba-tool group listmembers \"Domain Users\" -H ldap://samba.samdom.example.com
             raise CommandError('Failed to list members of "%s" group ' % groupname, e)
 
 
+class cmd_group_nis_add(Command):
+    """Add NIS attributes to a group.
+
+This command adds NIS info to a group account in the Active Directory domain.  
+The groupname specified on the command is the sAMaccountName.
+
+Unix (RFC2307) attributes will be added to the group account. 
+Configure 'idmap_ldb:use rfc2307 = Yes' in smb.conf to use these GID mapping 
+attributes.
+
+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.
+
+Example:
+samba-tool group nisadd Group1 --nis-domain=samdom --gid-number=12345
+
+The example shows how to add RFC2307/NIS attributes to a domain enabled group 
+account. The groups gidNumber will be set to '12345' 
+
+"""
+    synopsis = "%prog <groupname> [options]"
+
+    takes_optiongroups = {
+        "sambaopts": options.SambaOptions,
+        "credopts": options.CredentialsOptions,
+        "versionopts": options.VersionOptions,
+    }
+
+    takes_options = [
+        Option("-H", "--URL", help="LDB URL for database or target server", 
+               type=str, metavar="URL", dest="H"),
+        Option("--gid-number", help="Group's Unix/RFC2307 GID number", type=int),
+        Option("--nis-domain", help="Group's Unix/RFC2307 NIS domain", 
+               type=str),
+    ]
+
+    takes_args = ["groupname"]
+
+
+    def run(self, groupname, credopts=None, sambaopts=None, versionopts=None, 
+            H=None, nis_domain=None, gid_number=None):
+
+        lp = sambaopts.get_loadparm()
+        creds = credopts.get_credentials(lp)
+
+        samdb = SamDB(url=H, session_info=system_session(),
+                      credentials=creds, lp=lp)
+
+        if (gid_number is None and nis_domain is not None) or \
+           (gid_number is not None and nis_domain is None):
+            raise CommandError('Both --gid-number and --nis-domain'
+                               ' have to be set for a RFC2307-enabled group.'
+                               'Operation cancelled.')
+
+        domain_dn = samdb.domain_dn()
+        search_filter = "(samaccountname=%s)" % groupname
+        group_dn = samdb.get_object_dn(search_filter)
+
+        # what if group already is a NIS group??
+        res = samdb.search(group_dn,
+                           scope=ldb.SCOPE_BASE, 
+                           attrs=["gidNumber"])
+        if "gidNumber" in res[0]:
+            raise CommandError("Group %s already is a NIS group." % groupname) 
+
+        if not lp.get("idmap_ldb:use rfc2307"):
+            self.outf.write("You are setting a Unix/RFC2307 GID. \
+You may want to set 'idmap_ldb:use rfc2307 = Yes' in smb.conf to \
+use this attribute for XID/SID-mapping.\n")
+
+        update_group = """
+dn: %s
+changetype: modify
+add: msSFU30NisDomain
+msSFU30NisDomain: %s
+-
+add: msSFU30Name
+msSFU30Name: %s
+-
+add: gidNumber
+gidNumber: %s
+-
+""" % (group_dn, nis_domain, groupname,  gid_number)
+
+        try:
+            samdb.modify_ldif(update_group)
+        except Exception, e:
+            raise CommandError("Failed to update group '%s': " % groupname, e)
+
+        self.outf.write("Group '%s' updated successfully\n" % groupname)
+
+
 class cmd_group(SuperCommand):
     """Group management."""
 
@@ -418,3 +511,4 @@ class cmd_group(SuperCommand):
     subcommands["removemembers"] = cmd_group_remove_members()
     subcommands["list"] = cmd_group_list()
     subcommands["listmembers"] = cmd_group_list_members()
+    subcommands["nisadd"] = cmd_group_nis_add()
-- 
1.7.10.4



More information about the samba-technical mailing list