OpenSSH LDAP PUBLIC KEY PATCH 
Copyright (c) 2003 Eric AUGE (eau@phear.org)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

purposes of this patch:

This patch would help to have authentication centralization policy
using ssh public key authentication.
This patch could be an alternative to other "secure" authentication system
working in a similar way (Kerberos, SecurID, etc...), except the fact 
that it's based on OpenSSH and its public key abilities.

>> FYI: <<
'uid': means unix accounts existing on the current server
'lpkServerGroup:' mean server group configured on the current server ('lpkServerGroup' in sshd_config)

example schema:


                                  server1 (uid: eau,rival,toto) (lpkServerGroup: unix)
                ___________      /
               /           \ --- - server3 (uid: eau, titi) (lpkServerGroup: unix)
              | LDAP Server |    \
	      | eau  ,rival |     server2 (uid: rival, eau) (lpkServerGroup: unix)
	      | titi ,toto  |
	      | userx,....  |         server5 (uid: eau)  (lpkServerGroup: mail)
               \___________/ \       /
	                       ----- - server4 (uid: eau, rival)  (no group configured)
			             \
				        etc...

- WHAT WE NEED :

  * configured LDAP server somewhere on the network (i.e. OpenLDAP)
  * patched sshd (with this patch ;)
  * LDAP user(/group) entry (look at users.ldif (& groups.ldif)):
        User entry:
	- attached to the 'ldapPublicKey' objectclass
	- attached to the 'posixAccount' objectclass
	- with a filled 'sshPublicKey' attribute 
	Example:
		dn: uid=eau,ou=users,dc=cuckoos,dc=net
		objectclass: top
		objectclass: person
		objectclass: organizationalPerson
		objectclass: posixAccount
		objectclass: ldapPublicKey
		description: Eric AUGE Account
		userPassword: blah
		cn: Eric AUGE
		sn: Eric AUGE
		uid: eau
		uidNumber: 1034
		gidNumber: 1
		homeDirectory: /export/home/eau
		sshPublicKey: ssh-dss AAAAB3...
		sshPublicKey: ssh-dss AAAAM5...

	Group entry:
	- attached to the 'posixGroup' objectclass
	- with a 'cn' groupname attribute
	- with multiple 'memberUid' attributes filled with usernames allowed in this group
	Example:
		# few members
		dn: cn=unix,ou=groups,dc=cuckoos,dc=net
		objectclass: top
		objectclass: posixGroup
		description: Unix based servers group
		cn: unix
		gidNumber: 1002
		memberUid: eau
		memberUid: user1
		memberUid: user2


- HOW IT WORKS :

  * without patch
  If a user wants to authenticate to log in a server the sshd, will first look for authentication method allowed (RSAauth,kerberos,etc..)
  and if RSAauth and tickets based auth fails, it will fallback to standard password authentication (if enabled).

  * with the patch
  If a user want to authenticate to log in a server, the sshd will first look for auth method including LDAP pubkey, if the ldappubkey options is enabled.
  It will do an ldapsearch to get the public key directly from the LDAP instead of reading it from the server filesystem. 
  (usually in $HOME/.ssh/authorized_keys)

  If groups are enabled, it will also check if the user that wants to login is in the group of the server he is trying to log into.
  If it fails, it falls back on RSA auth files ($HOME/.ssh/authorized_keys), etc.. and finally to standard password authentication (if enabled).

  7 tokens are added to sshd_config :
  # here is the new patched ldap related tokens
  # entries in your LDAP must be posixAccount & strongAuthenticationUser & posixGroup
  UseLPK yes								# look the pub key into LDAP
  LpkServers ldap://10.31.32.5/ ldap://10.31.32.4 ldap://10.31.32.3	# which LDAP server for users ? (URL format)
  LpkUserDN  ou=users,dc=foobar,dc=net					# which base DN for users ?
  LpkGroupDN ou=groups,dc=foobar,dc=net					# which base DN for groups ? 
  LpkBindDN cn=manager,dc=foobar,dc=net					# which bind DN ?
  LpkBindPw asecret							# bind DN credidentials
  LpkServerGroup agroupname						# the group the server is part of

  Right now i'm using anonymous binding to get public keys, because getting public keys of someone doesn't impersonate him¸ but there is some
  flaws you have to take care of.

- HOW TO INSERT A USER/KEY INTO AN LDAP ENTRY

  * my way (there is plenty :)
  - create ldif file (i.e. users.ldif)
  - cat ~/.ssh/id_dsa.pub OR cat ~/.ssh/id_rsa.pub OR cat ~/.ssh/identity.pub
  - my way in 4 steps :
  Example:

  # you add this to the user entry in the LDIF file :
  [...]
  objectclass: posixAccount
  objectclass: ldapPublicKey
  [...]
  sshPubliKey: ssh-dss AAAABDh12DDUR2...
  [...]

  # insert your entry and you're done :)
  ldapadd -D balblabla -w bleh < file.ldif 
  
  all standard options can be present in the 'sshPublicKey' attribute.

- WHY :

  Simply because, i was looking for a way to centralize all sysadmins authentication, easily,  without completely using LDAP 
  as authentication method (like pam_ldap etc..).  
  
  After looking into Kerberos, SecurID, and other centralized secure authentications systems, the use of RSA and LDAP to get 
  public key for authentication allows us to control who has access to which server (the user needs an account and to be in 'strongAuthenticationUser'
  objectclass within LDAP and part of the group the SSH server is in). 

  Passwords update are no longer a nightmare for a server farm (key pair passphrase is stored on each user's box and private key is locally encrypted using his passphrase 
  so each user can change it as much as he wants). 

  Blocking a user account can be done directly from the LDAP (if sshd is using RSAAuth + ldap only).

- RULES :  
  Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey' which are defined in core.schema. 
  and the additionnal lpk.schema.

  This patch could allow a smooth transition between standard auth (/etc/passwd) and complete LDAP based authentication 
  (pamldap, nss_ldap, etc..).

  This can be an alternative to other (old?/expensive?) authentication methods (Kerberos/SecurID/..).
  
  Referring to schema at the beginning of this file if user 'eau' is only in group 'unix'
  'eau' would ONLY access 'server1', 'server2', 'server3' AND 'server4' BUT NOT 'server5'.
  If you then modify the LDAP 'mail' group entry to add 'memberUid: eau' THEN user 'eau' would be able
  to log in 'server5' (i hope you got the idea, my english is bad :).

  Each server's sshd is patched and configured to ask the public key and the group infos in the LDAP
  server.
  When you want to allow a new user to have access to the server parc, you just add him an account on 
  your servers, you add his public key into his entry on the LDAP server, it's done. 

  Because sshds are looking public keys into the LDAP directly instead of a file ($HOME/.ssh/authorized_keys).

  When the user needs to change his passphrase he can do it directly from his workstation by changing 
  his own key set lock passphrase, and all servers are automatically aware.
 
  With a CAREFUL LDAP server configuration you could allow a user to add/delete/modify his own entry himself
  so he can add/modify/delete himself his public key when needed.

­ FLAWS :
  LDAP must be well configured, getting the public key of some user is not a problem, but if anonymous LDAP 
  allow write to users dn, somebody could replace someuser's public key by its own and impersonate some 
  of your users in all your server farm be VERY CAREFUL.
  
  MITM attack when sshd is requesting the public key, could lead to a compromise of your servers allowing login 
  as the impersonnated user.

  If LDAP server is down then, fallback on passwd auth.
  
  the ldap code part has not been well audited yet.

- LDAP USER ENTRY EXAMPLES (LDIF Format, look in users.ldif)
    --- CUT HERE ---
    dn: uid=jdoe,ou=users,dc=foobar,dc=net
    objectclass: top
    objectclass: person
    objectclass: organizationalPerson
    objectclass: posixAccount
    objectclass: ldapPublicKey
    description: My account
    cn: John Doe
    sn: John Doe
    uid: jdoe
    uidNumber: 100
    gidNumber: 100
    homeDirectory: /home/jdoe
    sshPublicKey: ssh-dss AAAAB3NzaC1kc3MAAAEBAOvL8pREUg9wSy/8+hQJ54YF3AXkB0OZrXB....
    [...]
    --- CUT HERE ---

- LDAP GROUP ENTRY EXAMPLES (LDIF Format, look in groups.ldif)
    --- CUT HERE ---
    dn: cn=unix,ou=groups,dc=cuckoos,dc=net
    objectclass: top
    objectclass: posixGroup
    description: Unix based servers group
    cn: unix
    gidNumber: 1002
    memberUid: jdoe
    memberUid: user1
    memberUid: user2
    [...]
    --- CUT HERE ---

>> FYI: << 
Multiple 'sshPublicKey' in a user entry are allowed, as well as multiple 'memberUid' attributes in a group entry

- COMPILING:
  1. Apply the patch
  2. ./configure --with-your-options --with-ldap=/prefix/to/ldap_libs_and_includes
  3. make
  4. it's done.

- BLA :
  I hope this could help, and i hope to be clear enough,, or give ideas.  questions/comments/improvements are welcome.
  
- TODO :
  Redesign differently.

- DOCS/LINK :
  http://pacsec.jp/core05/psj05-barisani-en.pdf
  http://fritz.potsdam.edu/projects/openssh-lpk/
  http://fritz.potsdam.edu/projects/sshgate/
  http://dev.inversepath.com/trac/openssh-lpk
  http://lam.sf.net/ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm )

- CONTRIBUTORS/IDEAS/GREETS :
  - Falk Siemonsmeier.
  - Jacob Rief.
  - Michael Durchgraf.
  - frederic peters.
  - Finlay dobbie.
  - Stefan Fisher.
  - Robin H. Johnson.
  - Adrian Bridgett.

- CONTACT :
  - Eric AUGE <eau@phear.org>
  - Andrea Barisani <andrea@inversepath.com>
