I've had a bit of a cold this weekend, which provided ample opportunity to do some coding (as I didn't feel too
guilty
about not practising or going out).
On the PADL front, I've added support for template users to pam_ldap. I'm not sure whether this works yet, though
:-) Template users are a (as far as I know) FreeBSD practice where the PAM host application refetches the
username from PAM after calling pam_authenticate(). This lets the module change the username under the
application's nose, which is ideal for ISP applications; for example, a user might logon as
lukeh@padl.com, and be mapped to the template user nobody. pam_ldap will either map users
to
a default template user, or read the template user from an attribute in the user's entry. (Both of these are
configurable.) You might stack pam_ldap and pam_ntdom, setting pam_login_attribute in /etc/ldap.conf
to
userPrincipalName, and pam_template_login_attribute to sAMAccountName; then, you could login as
lukeh@padl.com; pam_ldap will search for (userPrincipalName=lukeh@padl.com), and then set the username to
the value of the sAMAccountName attribute in the resulting entry (eg. lukeh). pam_ntdom would then retrieve the
username from PAM, and do an NT domain authentication against "lukeh". Finally, login would retrieve the
username from PAM, and call getpwnam("lukeh"). YMMV, this code is experimental! Code, as usual, is at ftp.padl.com.
My friend Joshua Reich has been working on some
interesting LDAP-related projects which I hope to help him with. Check out his homepage at www.i2pi.com. Josh is one of the DataServe clan.
On the Darwin front, I've done a little bit more work on the PAM port, not much though, I'm waiting on getting
MacOS X up and running first. A bit hard without any PPC hardware to speak of; still, Rhapsody DR2 is quite a
nice Intel Unix! Also looked at adding support for reentrant name resolution APIs to Darwin, for the moment just
those in the Single UNIX Specification (getpwnam_r(), getpwuid_r(), getgrnam_r(), getgrgid_r()). There seem to be
some issues with lookupd in getting this working (not architectural issues, it just doesn't work!). You can check
these out in the lukeh-SingleUNIXSpecificationV2 branch of Libraries/NeXT/libinfo. You will need a login to access this.
The final, and perhaps more interesting project, has been a NetInfo backend for OpenLDAP. The backend uses
Marc Majka's dsstore API, rather than the NetInfo client library. dsstore is a hierarchical
database
library with an information that's sort of a cross between NetInfo and LDAP. You get the good things about
NetInfo:
for example, entries' distinguished names are dynamically constructed, rather than being stored with entry; and
the
good things about LDAP, such as complex queries. The library will either talk directly to the database on disk
(and
indeed is used as the backend by the MacOS X NetInfo daemon) or to a remote NetInfo database. Anyway, the
OpenLDAP backend, back-netinfo, uses this API. It's quite a thin layer: most of the code is spent
mapping between slapd data structures, such as filters, and their analogues in dsstore. The
trickier code has to do with mapping information models, which could do with some work. For the moment,
dsstore meta-attributes are mapped to LDAP attributes with the ;x-meta tag, except for
objectClass, which is mapped to the LDAP objectClass attribute. objectClass is also special-cased so that it
always contains extensibleObject and top, and so that filters such as (objectClass=*) will succeed even though
the
NetInfo entry does not contain these attributes. I expect this code will be able to go away once dsstore
can deal with schema itself, and slapd lets backends handle their own schema. Attributes which
slapd doesn't know about (ie. haven't been defined in a schema anywhere) appear as operational
attributes, and are thus not user-modifiable. To make this useful with existing NetInfo deployments, we need to
map between well known NetInfo and X.500 attribute types.
Here is an example of searching for a user in NetInfo, and then in LDAP:
% niutil -read . /users/lukeh
name: lukeh
uid: 1002
passwd: *
realname: Luke Howard
gid: 1000
home: /home/lukeh
shell: /bin/tcsh
sn: Howard
modifiersName: NAME=ROOT,OU=PEOPLE
modifyTimestamp: 20000702234549Z
_writers_passwd: lukeh
_writers_change: lukeh
% ldapsearch -LLL -b "ou=People" name=lukeh '*' '+'
dn: name=lukeh,ou=People
name: lukeh
uid: 1002
passwd: *
realname: Luke Howard
gid: 1000
home: /home/lukeh
shell: /bin/tcsh
sn: Howard
modifiersName: NAME=ROOT,OU=PEOPLE
modifyTimestamp: 20000702234549Z
writers_passwd;x-meta: lukeh
writers_change;x-meta: lukeh
objectClass: top
objectClass: extensibleObject
subschemaSubentry: cn=Subschema