[Fedora-directory-users] Samba & Fedora Directory Server Integration

Mark McLoughlin markmc at redhat.com
Mon Jan 16 08:43:53 UTC 2006


On Sat, 2006-01-14 at 18:58 -0600, Oscar A. Valdez wrote:
> I've followed the Samba & Fedora Directory Server Integration How-To
> located at http://directory.fedora.redhat.com/wiki/Howto:Samba , and I'm
> about to upload my user accounts into the DS. I have two questions
> before I proceed, though:
> 
> 1) At the end of the How-To, a "testuser" is added to the Samba server
> with the "smbpasswd -a" command. Wouldn't the DS make the user accounts
> visible to the Samba server, making it unecessary to add them via
> smbpasswd? If it's really necessary to add the accounts via smbpasswd,
> then the DS isn't really a backend to the Samba Server: they would be
> acting in parallel.

	Yeah, it sucks.

	One of the main issues is that for SMB authentication each user's
password needs to be stored in LM and NT formats in the sambaNTPassword
and sambaLMPassword attributes. So, when the user set its password, some
code needs to have access to the plaintext password and translate it
into LM and NT format. The easiest way is to use smbpassword, but you
could use your own code to set the password in all formats at once ....
or, I'm sure you could right a fedora-ds plugin which would save the
password in those formats whenever it is set.

	But it doesn't end there. Even just for SMB authentication, there are
other attributes which smbpasswd manages and there's a lot of voodoo
involved.

	To give you idea of the kind of stuff you need to do in order to not
use smbpasswd, see the code below. I wish I could explain the code in
detail, but I've forgotten a lot of the details.

Cheers,
Mark.

...
#
# Copyright (C) 2006 Red Hat, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

SAMBA_RID_MULTIPLIER = 2
SAMBA_RID_BASE = 1000
SAMBA_USER_RID_TYPE = 0x0
SAMBA_USER_GID_TYPE = 0x1
SAMBA_LM_HASH_MAGIC = "KGS!@#$%"

...
    def _get_machine_sid (self):
        if not self.machine_sid is None:
            return self.machine_sid

        output = commands.getoutput ("net getlocalsid")
        for line in output.split ("\n"):
            if line.startswith ("SID for domain"):
                parts = line.split (":")
                if len (parts) >= 2:
                    self.machine_sid = parts[1].strip ()
                    break

        return self.machine_sid

    def _get_user_sid (self, uid):
        machine_sid = self._get_machine_sid ()

        user_rid = ((uid * SAMBA_RID_MULTIPLIER) + SAMBA_RID_BASE) | SAMBA_USER_RID_TYPE

        return machine_sid + "-" + str (user_rid)

    def _get_group_sid (self, gid):
        machine_sid = self._get_machine_sid ()

        group_rid = ((gid * SAMBA_RID_MULTIPLIER) + SAMBA_RID_BASE) | SAMBA_USER_GID_TYPE

        return machine_sid + "-" + str (group_rid)

    def add_user_attributes (self, username, uid, gid, password):
        def get_nt_password (plaintext):
            hash = MD4.new ()
            hash.update (plaintext.encode ("utf-16-le"))
            return hash.hexdigest ().upper ()

        def get_lm_password (plaintext):
            def lm_hash (pw7):
                a7 = array.array ("B", pw7.upper ().encode ("850"))

                while len (a7) < 7:
                    a7.append (0)

                a8 = array.array ("B")

                a8.append (                         a7[0] >> 1 )
                a8.append (((a7[0] & 0x01) << 6) | (a7[1] >> 2))
                a8.append (((a7[1] & 0x03) << 5) | (a7[2] >> 3))
                a8.append (((a7[2] & 0x07) << 4) | (a7[3] >> 4))
                a8.append (((a7[3] & 0x0F) << 3) | (a7[4] >> 5))
                a8.append (((a7[4] & 0x1F) << 2) | (a7[5] >> 6))
                a8.append (((a7[5] & 0x3F) << 1) | (a7[6] >> 7))
                a8.append (  a7[6] & 0x7F                      )

                for i in range (8):
                    a8[i] <<= 1

                ciph = DES.new (a8.tostring ()).encrypt (SAMBA_LM_HASH_MAGIC)

                return ciph.encode ("hex").upper ()

            return lm_hash (plaintext[0:7]) + lm_hash (plaintext[7:14])

        samba_user_sid  = self._get_user_sid  (uid)
        samba_group_sid = self._get_group_sid (gid)

        nt_password = get_nt_password (password)
        lm_password = get_lm_password (password)

        directory.add_samba_user_attributes (username,
                                             samba_user_sid,
                                             samba_group_sid,
                                             nt_password,
                                             lm_password)
...

    def add_samba_user_attributes (self, username, samba_user_sid, samba_group_sid, nt_password, lm_password):
        ldap_connection = self.get_ldap_connection ()
        user_suffix     = self.get_user_suffix ()

        ldap_connection.modify_s ("uid=%s,%s" % (username, user_suffix),
                                  [
                                    ( ldap.MOD_ADD, "objectClass",          [ "sambaSamAccount" ] ),
                                    ( ldap.MOD_ADD, "sambaSID",             [ samba_user_sid ] ),
                                    ( ldap.MOD_ADD, "sambaPrimaryGroupSID", [ samba_group_sid ] ),
                                    ( ldap.MOD_ADD, "sambaNTPassword",      [ nt_password ] ),
                                    ( ldap.MOD_ADD, "sambaLMPassword",      [ lm_password ] )
                                  ])
...




More information about the Fedora-directory-users mailing list