Coda File System

Re: Coda authentification & LDAP

From: Jan Harkes <jaharkes_at_cs.cmu.edu>
Date: Wed, 7 Mar 2007 15:38:10 -0500
On Wed, Mar 07, 2007 at 07:19:41PM +0100, S. Cance wrote:
> I'm working on a network where every services use LDAP to authenticate 
> users.
> That's why I am working on a LDAP based clog utility.

Ok, pause here for a second LDAP is a directory service, the list of
users, groups and membership information. Clog/auth2 perform
authentication which is quite different.

In the Active Directory environment LDAP handles membership and such,
but kerberos is used for authentication.

However...

Since LDAP has the mechanism that allows a user to authenticate with the
LDAP servers (possibly based on their kerberos identity), it is possible
to have the ldap directory provide authentication tokens for Coda.

(i.e. user proves his identity to kerberos which gives him a ticket that
proves the identity to ldap which then could return a Coda token which
is used to prove our identity to the Coda servers).

So the whole authentication/authorization/ACL system consists of several
parts,


1 - Coda tokens, the user somehow proves his identity to Coda's auth2
server, maybe through a shared secret (Coda password) or in the form of
a valid kerberos ticket.

2- This token is then used whenever the client connects to the servers.
If the token is valid the server associates the Coda user identity with
any request that is sent over this encrypted connection from the client.

3- When a client creates a new connection, the server does a lookup in
the protection database (pdb) and obtains a list of all groups that the
authenticated user is a member of. The user identity + all numeric group
identifiers are stored in a per-user (per-connection?) list.

4- Whenever an action is performed on any object, the server takes the
ACL and checks if the user is a member of any of the groups that would
allow the operation to complete.


So really LDAP wouldn't really be involved much in the token part of
this, but really would replace step 4 where we check if the current
users is a member of any of the groups listed in the ACL. However this
is probably too expensive, a single reintegration may touch several
hundred objects each of which may have a couple of groups listed in
their ACLs. To keep the number of LDAP queries within reason, it is
probably valuable to keep the existing model where we obtain the full
list of groups a user belongs to only when a new connection is set up.

Since the server stores ACLs as a (uid/gid, rights) tuple, the user and
group names when when an ACL is updated have to be mapped to numeric
group identifiers, but ACLs are not updated all that frequently.
However, nothing in LDAP actually is based on numeric ids, assigns them
or enforces their constistency.

Another problem is that the last time I looked at the openldap library,
which would have to be linked with the Coda server for most of the
described functionality, is using pthreads which have some issues when
mixed with Coda's userspace threading. It also was randomly using
blocking operations (I guess assuming that the calling application uses
kernel threads?) during which the Coda server is unable to send any
responses back to clients. And failure handling was problematic. If a
backend LDAP server fell over all queries would fail until the ldap
handle was closed and reopened. So this meant that we had to keep track
of all outstanding queries and resubmit them after failover happens.

Things may have improved though, most of this was with early openldap
releases probably about 6 years ago. Anything that has survived from
these early attempts should be at,

    /coda/coda.cs.cmu.edu/usr/pam/development/ldap-coda/

Not so long ago I revisited some bits, but approaching it more from the
user/management side. I imported a snapshot of our pdbtool user/group
databases into an LDAP repository and tried to see how we could move
pdbtool like functionality to an LDAP server.

    /coda/coda.cs.cmu.edu/usr/jaharkes/ldap/

The main program is 'codapts' which may seem familiar to anyone who has
worked with AFS as it implements a similar set of operations as the AFS
'pts' tool, some operations require system:administrator membership, but
users are allowed to create/manage their own groups and such.

    $ codapts help
    codapts: Commands are:
    adduser         add a user to a group
    chown           change ownership of a group
    chfn            change user name and information
    chsh            change login shell
    creategroup     create a new group
    createuser      create a new user
    delete          delete a user or group from database
    examine         examine an entry
    help            get help on commands
    listentries     list users/groups in the protection database
    listmax         list max id
    listowned       list groups owned by an entry
    membership      list membership of a user or group
    passwd          change user password
    removeuser      remove a user from a group
    rename          rename user or group
    setfields       set fields for an entry
    setmax          (re)set max id


There is also some code (tokens.py) that was intended to be used as an
LDAP server plugin to allow the ldap server to return a valid Coda
token. I guess I never figured out how to get the authenticated user
identity from the ldap server and ended up using it mostly as a testing
tool while I was implementing the new Coda token format that was
introduced around the same time as rpc2-2.0.

> Still, the source code is quite complicated and I could use a hand on 
> some of my questions :
>    - are ACLs checker(s) only based on tokens, or do they make 
> references to the user database ?
> what I mean here is : do I have to create a new user in pdbtool for each 
> of the users in the LDAP database ?
> If I do, is it possible to check if a user exists in the server database 
> without using any password ?

The server doesn't need passwords or anything to validate membership
(i.e. ACL rights) of a user that presented a valid token against the
pdbtool database. But it does need to know such information.

So this would either involve having the Coda server use LDAP to query
for group membership information, which may be somewhat complicated as I
described earlier.

Or have a way to synchronize the LDAP and pdbtool database contents,
(periodically) export all users and groups from LDAP and import them
into pdbtool.

>    - I see in U_BindToServer (line 325 of coda/coda-src/auth2/auser.c) 
> a loop on each of the auth servers. while using LDAP there is only one 
> LDAP server, do the tokens have to be registered to each servers or is 
> it that the tokens are stored on the client and sent to the servers at 
> each requests if needed ?

Tokens are generated by the auth2 daemon, but anyone who has access to
the shared authentication secret can in principle generate a valid token
(this is a secret that is shared between auth2 and codasrv, that way
codasrv can tell if the token came from auth2 and has not been tampered
with, etc.)

>    - I am not sure where the token is generated, I don't really get the 
> whole token system in fact, if it is generated by the client wouldn't 
> that be a security issue ? So if it generated by the server, LDAP auth 
> doesn't seems that easy :(
> 
> do you think it is usefull to create a whole new way to authenticate 
> users, or should I create a tool to synchronize coda user database with 
> the ldap ?

Synchronizing LDAP with the pdbtool database may be useful, because it
will allow the server to correctly test ACL/group membership. But it
won't solve your authentication issues. ldap uses hash+salt based
password authentication, while clog and auth2 depend on both sides
proving to each other that they know the same shared secret without
actually revealing the secret, so auth2 can't use the passwords as they
are stored in ldap. And LDAP probably can't be trusted to store the
(cleartext) passwords that auth2 would like to use.

Jan
Received on 2007-03-07 15:40:56