Samba User Mapping
Introduction
This page shows you how to create Samba user mapping. The complete files are available in PENROSE_SERVER_HOME/samples/samba/partition.
Source Configuration
Define a source in sources.xml corresponding to the user table in your database. See the following example:
<source name="users"> <connection-name>Samba</connection-name> <field name="username" primaryKey="true"/> <field name="firstName"/> <field name="lastName"/> <field name="encPassword"/> <field name="uid"/> <field name="user_sid"/> <field name="gid"/> <field name="group_sid"/> <field name="lm_password"/> <field name="nt_password"/> ... <parameter> <param-name>tableName</param-name> <param-value>users</param-value> </parameter> </source>
In this example the password column contains the SHA-encrypted passwords.
Entry Mapping
Define a mapping for the users in mapping.xml, for instance: uid=...,ou=Users,dc=Samba,dc=Example,dc=com.
<entry dn="uid=...,ou=Users,dc=Samba,dc=Example,dc=com">
... object classes ...
... attribute mappings ...
... source/field mappings ...
</entry>
Object Classes
<oc>account</oc> <oc>posixAccount</oc> <oc>sambaSamAccount</oc>
Attribute Mappings
Most attribute mappings are quite straight forward:
<at name="uid" rdn="true"> <variable>u.username</variable> </at> <at name="cn"> <expression> if (u == void || u == null) return null; return u.firstName+" "+u.lastName; </expression> </at> <at name="uidNumber"> <variable>u.uid</variable> </at> <at name="sambaSID"> <variable>u.user_sid</variable> </at> <at name="gidNumber"> <variable>u.gid</variable> </at> <at name="sambaPrimaryGroupSID"> <variable>u.group_sid</variable> </at> <at name="sambaLMPassword"> <variable>u.lm_password</variable> </at> <at name="sambaNTPassword"> <variable>u.nt_password</variable> </at>
Since password is encrypted in the database, we need to convert it to the correct LDAP userPassword format.
<at name="userPassword"> <expression> import org.safehaus.penrose.util.*; if (u == void || u == null) return null; if (u.encPassword== void || u.encPassword== null) return null; byte[] bytes = BinaryUtil.decode("BigInteger", u.encPassword); return "{SHA}"+BinaryUtil.encode("Base64", bytes); </expression> </at>
Source/Field Mappings
Most field mappings are also quite straight forward:
<source name="u"> <source-name>users</source-name> <field name="username"> <variable>uid</variable> </field> <field name="firstName"> <expression> if (cn == void || cn == null) return null; int i = cn.lastIndexOf(" "); return cn.substring(0, i); </expression> </field> <field name="lastName"> <variable>sn</variable> </field> <field name="uid"> <variable>uidNumber</variable> </field> <field name="user_sid"> <variable>sambaSID</variable> </field> <field name="gid"> <variable>gidNumber</variable> </field> <field name="group_sid"> <variable>sambaPrimaryGroupSID</variable> </field> </source>
For the password field, first we check if the supplied userPassword is in plain text, that means it's a new password and we need to encrypt it. If it's already encrypted, we just need to convert it from the LDAP userPassword format into the format used in the database.
<field name="encPassword"> <expression>import org.safehaus.penrose.util.*; if (userPassword == void || userPassword == null) return null; String method = PasswordUtil.getEncryptionMethod(userPassword); byte[] bytes; if (method == null) { bytes = PasswordUtil.encrypt("SHA", userPassword); } else if ("SHA".equals(method)) { String password = PasswordUtil.getEncryptedPassword(userPassword); bytes = BinaryUtil.decode("Base64", password); } else { throw new Exception("Unsupported encryption: "+method); } return BinaryUtil.encode("BigInteger", bytes); </expression> </field>
The NT and LM passwords are computed from the plain text userPassword. So if the supplied userPassword is plain text, then we compute both NT and LM passwords. If the userPassword is already encrypted, we just accept the supplied NT and LM passwords.
<field name="nt_password"> <expression> import org.safehaus.penrose.util.*; if (userPassword == void || userPassword == null) return sambaNTPassword; String method = PasswordUtil.getEncryptionMethod(userPassword); byte[] bytes; if (method == null) { byte[] bytes = PasswordUtil.encryptNTPassword(userPassword); if (bytes == null) return null; return BinaryUtil.encode("BigInteger", bytes).toUpperCase(); } else if ("SHA".equals(method)) { return sambaNTPassword; } else { throw new Exception("Unsupported encryption: "+method); } </expression> </field> <field name="lm_password"> <expression> import org.safehaus.penrose.util.*; if (userPassword == void || userPassword == null) return sambaLMPassword; String method = PasswordUtil.getEncryptionMethod(userPassword); byte[] bytes; if (method == null) { byte[] bytes = PasswordUtil.encryptLMPassword(userPassword); if (bytes == null) return null; return BinaryUtil.encode("BigInteger", bytes).toUpperCase(); } else if ("SHA".equals(method)) { return sambaLMPassword; } else { throw new Exception("Unsupported encryption: "+method); } </expression> </field>