NIS Users

Goal

We want to map the following entry in /etc/passwd:

jbond:x:507:507:James Bond:/home/jbond:/bin/bash

into the following LDAP entry in Penrose:

dn: uid=jbond,ou=Users,dc=NIS,dc=Example,dc=com
loginShell: /bin/bash
sn: Bond
objectClass: account
objectClass: posixAccount
gidNumber: 507
uid: jbond
uidNumber: 507
gecos: James Bond
cn: James Bond
userPassword:: e2NyeXB0fSQxJHBXZzl3RWxEJDJBVmtsUG1jbjRiWlRtcnYweVJoZDA=
homeDirectory: /home/jbond

Solution

First we define the source:

<source name="users">

    <connection-name>NIS</connection-name>

    <field name="cn"/>
    <field name="sn"/>
    <field name="uid" primaryKey="true"/>
    <field name="uidNumber"/>
    <field name="gidNumber"/>
    <field name="homeDirectory"/>
    <field name="userPassword"/>
    <field name="loginShell"/>
    <field name="gecos"/>
    <field name="description"/>

    <parameter>
      <param-name>objectClasses</param-name>
      <param-value>posixAccount</param-value>
    </parameter>
    <parameter>
      <param-name>base</param-name>
      <param-value>system/passwd.byname</param-value>
    </parameter>
    <parameter>
      <param-name>scope</param-name>
      <param-value>ONELEVEL</param-value>
    </parameter>

</source>

Then we define the mapping:

<entry dn="uid=...,ou=Users,dc=NIS,dc=Example,dc=com">

    <oc>account</oc>
    <oc>posixAccount</oc>

    <at name="cn">
      <variable>u.cn</variable>
    </at>
    <at name="sn">
      <variable>u.sn</variable>
    </at>
    <at name="uid" rdn="true">
      <variable>u.uid</variable>
    </at>
    <at name="uidNumber">
      <variable>u.uidNumber</variable>
    </at>
    <at name="gidNumber">
      <variable>u.gidNumber</variable>
    </at>
    <at name="homeDirectory">
      <variable>u.homeDirectory</variable>
    </at>
    <at name="userPassword">
      <expression>
import org.safehaus.penrose.util.*;

if (u == void || u == null) return;
if (u.userPassword == void || u.userPassword == null) return;

return "{crypt}"+u.userPassword;
      </expression>
    </at>
    <at name="loginShell">
      <variable>u.loginShell</variable>
    </at>
    <at name="gecos">
      <variable>u.gecos</variable>
    </at>
    <at name="description">
      <variable>u.description</variable>
    </at>

</entry>

In the same entry we also configure the reverse mapping:

<entry dn="uid=...,ou=Users,dc=NIS,dc=Example,dc=com">

    <source name="u">
      <source-name>users</source-name>
      <field name="cn">
        <variable>cn</variable>
      </field>
      <field name="sn">
        <variable>cn</variable>
      </field>
      <field name="uid" primaryKey="true">
        <variable>uid</variable>
      </field>
      <field name="uidNumber">
        <variable>uidNumber</variable>
      </field>
      <field name="gidNumber">
        <variable>gidNumber</variable>
      </field>
      <field name="homeDirectory">
        <variable>homeDirectory</variable>
      </field>
      <field name="userPassword">
        <expression>
import org.safehaus.penrose.util.*;

if (userPassword == void || userPassword == null) return;

String method = PasswordUtil.getEncryptionMethod(userPassword);

if (method == null) {
    return PasswordUtil.encrypt("crypt", userPassword);

} else if ("crypt".equals(method)) {
    return PasswordUtil.getEncryptedPassword(userPassword);

} else {
    throw new Exception("Unsupported encryption: "+method);
}

return bytes;
        </expression>
      </field>
      <field name="loginShell">
        <variable>loginShell</variable>
      </field>
      <field name="gecos">
        <variable>gecos</variable>
      </field>
      <field name="description">
        <variable>description</variable>
      </field>
    </source>

</entry>

Authentication

By default, Penrose will authenticate the user against the encrypted password returned by the NIS server. If the NIS server is configured not to return the encrypted password, you will need to use PAM authentication.

Make sure the /etc/nsswitch.conf is configured to authenticate using NIS. Then add the following parameter into the above source:

<source name="users">

    <parameter>
      <param-name>pam</param-name>
      <param-value>system-auth</param-value>
    </parameter>

</source>

The pam parameter indicates which PAM service will be used for authentication. The PAM service should be located in /etc/pam.d.