[csw-devel] SF.net SVN: gar:[9735] csw/mgar/pkg/openssh/branches
dmichelsen at users.sourceforge.net
dmichelsen at users.sourceforge.net
Wed Apr 21 14:02:41 CEST 2010
Revision: 9735
http://gar.svn.sourceforge.net/gar/?rev=9735&view=rev
Author: dmichelsen
Date: 2010-04-21 12:02:40 +0000 (Wed, 21 Apr 2010)
Log Message:
-----------
openssh: Make branch for 5.4p1-lpk
Modified Paths:
--------------
csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/Makefile
csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/checksums
csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/CSWosshlpk.prototype
Added Paths:
-----------
csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/
csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/0001-This-is-a-forward-port-of-the-OpenSSH-LPK-support-pa.patch
Removed Paths:
-------------
csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/contrib-openssh-lpk-5.2p1-0.3.9.patch
Modified: csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/Makefile
===================================================================
--- csw/mgar/pkg/openssh/trunk/Makefile 2010-04-20 15:47:18 UTC (rev 9732)
+++ csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/Makefile 2010-04-21 12:02:40 UTC (rev 9735)
@@ -83,7 +83,7 @@
# documentation files to install (not a gar variable)
DOCFILES = CREDITS ChangeLog ChangeLog.gssapi INSTALL LICENCE OVERVIEW README README.dns
-DOCFILES += README.platform README.privsep README.smartcard README.tun TODO WARNING.RNG
+DOCFILES += README.platform README.privsep README.tun TODO WARNING.RNG
# we're using conf handling class from the cswclassutils package
RUNTIME_DEP_PKGS += CSWcswclassutils
@@ -106,15 +106,19 @@
# we always register the lpk related files so checksum
# is the same with LPK enabled or not
-DISTFILES += contrib-openssh-lpk-5.2p1-0.3.9.patch
+# Patch taken from http://code.google.com/p/openssh-lpk/issues/detail?id=7
+# and modified with
+# perl -e 's/--- g/--- /; s/\+{3} g/+++ /' -pi
+# as all filenames seem to be prefixed with 'g' and redone patch for
+# patchdirlevel 1 instead of 0
+DISTFILES += 0001-This-is-a-forward-port-of-the-OpenSSH-LPK-support-pa.patch
ifdef LPK
PACKAGES = CSWosshlpk
CATALOGNAME_CSWosshlpk = openssh_lpk
SPKG_DESC_CSWosshlpk = $(SPKG_DESC_CSWossh) with ldap public key support
RUNTIME_DEP_PKGS_CSWosshlpk = $(RUNTIME_DEP_PKGS_CSWossh) CSWoldaprt
SPKG_CLASSES_CSWosshlpk = none cswpreserveconf cswinitsmf
- MASTER_SITES += http://openssh-lpk.googlecode.com/svn/trunk/patch/contrib/
- PATCHFILES += contrib-openssh-lpk-5.2p1-0.3.9.patch
+ PATCHFILES += 0001-This-is-a-forward-port-of-the-OpenSSH-LPK-support-pa.patch
CONFIGURE_ARGS += --with-ldap
DOCFILES += openssh-lpk_openldap.schema openssh-lpk_sun.schema lpk-user-example.txt README.lpk
@@ -122,6 +126,10 @@
SPKG_DESC_CSWosshclient =
endif
+CHECKPKG_OVERRIDES_CSWosshlpk += bad-rpath-entry|/opt/csw/lib/
+CHECKPKG_OVERRIDES_CSWosshlpk += bad-rpath-entry|/opt/csw/lib/
+CHECKPKG_OVERRIDES_CSWosshlpk += init-file-wrong-location|/etc/opt/csw/init.d/cswopenssh
+CHECKPKG_OVERRIDES_CSWosshlpk += surplus-dependency|CSWosshclient
include gar/category.mk
@@ -133,6 +141,7 @@
# adding documentation files
post-merge: merge-config-files merge-doc-files merge-init-files merge-contrib-files
+ @$(MAKECOOKIE)
merge-contrib-files:
ginstall -D "$(WORKSRC_FIRSTMOD)/contrib/ssh-copy-id" "$(PKGROOT)/$(bindir)/ssh-copy-id"
@@ -150,7 +159,6 @@
(cd $(WORKSRC_FIRSTMOD) && ginstall $(DOCFILES) $(PKGROOT)/$(docdir)/$$DOCDIR/); \
ginstall $(WORKDIR_FIRSTMOD)/changelog.CSW $(PKGROOT)/$(docdir)/$$DOCDIR/; \
done
- @$(MAKECOOKIE)
merge-config-files:
ginstall $(PKGROOT)/$(sysconfdir)/ssh/ssh_config $(PKGROOT)/$(sysconfdir)/ssh/ssh_config.CSW
@@ -161,6 +169,5 @@
-e 's,^ *# *UsePAM *.*,UsePAM yes,g' \
-e 's,^ *# *PrintMotd *.*,PrintMotd no,g' \
-e 's,^ *# *X11Forwarding *.*,X11Forwarding yes,g' "$(PKGROOT)/$(sysconfdir)/ssh/sshd_config" > "$(PKGROOT)/$(sysconfdir)/ssh/sshd_config.CSW
- @$(MAKECOOKIE)
Modified: csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/checksums
===================================================================
--- csw/mgar/pkg/openssh/trunk/checksums 2010-04-20 15:47:18 UTC (rev 9732)
+++ csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/checksums 2010-04-21 12:02:40 UTC (rev 9735)
@@ -1,3 +1,4 @@
+d0bdd7ebcbd41acd67dcf55e98c53dcb 0001-This-is-a-forward-port-of-the-OpenSSH-LPK-support-pa.patch
1d3d6d477c09e59c514e637fa3a2f7a4 CSWossh.checkinstall
0993813fa5c752215f892cb67c86816f CSWossh.preinstall
e00106f28a2aef529e097aa182906273 CSWossh.prototype
@@ -4,9 +5,8 @@
39259b734dc10d2b7eb82d2331254d4c CSWosshclient.prototype
1d3d6d477c09e59c514e637fa3a2f7a4 CSWosshlpk.checkinstall
0993813fa5c752215f892cb67c86816f CSWosshlpk.preinstall
-77b86c30c3257fdf014102c8166fab2d CSWosshlpk.prototype
+36aff9d761d77369ba97ce6508782ccd CSWosshlpk.prototype
3344f6f17e6d75e8e135b8366e64a7ee changelog.CSW
-9153031524651a18e7edaed4637aa769 contrib-openssh-lpk-5.2p1-0.3.9.patch
a5ebb2e3fdaa06c3c9edba55aac5f83b cswopenssh
8e765642349b6321d01b33e95304e113 cswopenssh.xml
704ad1d3216df8de4d44465006c64c39 derelativise_path_bugfix.patch
Added: csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/0001-This-is-a-forward-port-of-the-OpenSSH-LPK-support-pa.patch
===================================================================
--- csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/0001-This-is-a-forward-port-of-the-OpenSSH-LPK-support-pa.patch (rev 0)
+++ csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/0001-This-is-a-forward-port-of-the-OpenSSH-LPK-support-pa.patch 2010-04-21 12:02:40 UTC (rev 9735)
@@ -0,0 +1,1948 @@
+From bf2274fb19b2da6b8b3b6c51111d912e19b3128c Mon Sep 17 00:00:00 2001
+From: Dagobert Michelsen <dam at opencsw.org>
+Date: Wed, 21 Apr 2010 11:14:45 +0200
+Subject: [PATCH] This is a forward-port of the OpenSSH LPK support patch.
+
+It adds support for storing OpenSSH public keys in LDAP. It also supports
+grouping of machines in the LDAP data to limit users to specific machines.
+
+The latest homepage for the LPK project is:
+http://code.google.com/p/openssh-lpk/
+
+The 0.3.10 version of the patch includes a fix for 64-bit platforms, as
+discovered by Gentoo, where the bind timeout and search timeout values were not
+being parsed correctly: http://bugs.gentoo.org/210110
+
+Forward-ported-from: openssh-lpk-5.1p1-0.3.10.patch
+---
+ Makefile.in | 2 +-
+ README.lpk | 267 ++++++++++++++++++++
+ auth-rsa.c | 86 +++++++
+ auth2-pubkey.c | 73 ++++++
+ config.h.in | 3 +
+ configure | 81 ++++++
+ configure.ac | 32 +++
+ ldapauth.c | 575 +++++++++++++++++++++++++++++++++++++++++++
+ ldapauth.h | 124 ++++++++++
+ lpk-user-example.txt | 117 +++++++++
+ openssh-lpk_openldap.schema | 19 ++
+ openssh-lpk_sun.schema | 21 ++
+ servconf.c | 169 +++++++++++++
+ servconf.h | 7 +
+ sshd.c | 14 +
+ sshd_config | 15 ++
+ sshd_config.5 | 56 +++++
+ 17 files changed, 1660 insertions(+), 1 deletions(-)
+ create mode 100644 README.lpk
+ create mode 100644 ldapauth.c
+ create mode 100644 ldapauth.h
+ create mode 100644 lpk-user-example.txt
+ create mode 100644 openssh-lpk_openldap.schema
+ create mode 100644 openssh-lpk_sun.schema
+
+diff --git a/Makefile.in b/Makefile.in
+index 69e3567..b15d85d 100644
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -91,7 +91,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
+ auth2-gss.o gss-serv.o gss-serv-krb5.o \
+ loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
+ audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \
+- roaming_common.o roaming_serv.o
++ roaming_common.o roaming_serv.o ldapauth.o
+
+ MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
+ MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
+diff --git a/README.lpk b/README.lpk
+new file mode 100644
+index 0000000..d0b6de0
+--- /dev/null
++++ b/README.lpk
+@@ -0,0 +1,267 @@
++OpenSSH LDAP PUBLIC KEY PATCH
++Copyright (c) 2003 Eric AUGE (eau at 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\xB8 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.
++
++\xAD 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 at phear.org>
++ - Andrea Barisani <andrea at inversepath.com>
+diff --git a/auth-rsa.c b/auth-rsa.c
+index 65571a8..107fcaf 100644
+--- a/auth-rsa.c
++++ b/auth-rsa.c
+@@ -177,10 +177,96 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
+ FILE *f;
+ u_long linenum = 0;
+ Key *key;
++#ifdef WITH_LDAP_PUBKEY
++ ldap_key_t * k;
++ unsigned int i = 0;
++#endif
+
+ /* Temporarily use the user's uid. */
+ temporarily_use_uid(pw);
+
++#ifdef WITH_LDAP_PUBKEY
++ /* here is the job */
++ key = key_new(KEY_RSA1);
++
++ if (options.lpk.on) {
++ debug("[LDAP] trying LDAP first uid=%s", pw->pw_name);
++ if ( ldap_ismember(&options.lpk, pw->pw_name) > 0) {
++ if ( (k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) {
++ for (i = 0 ; i < k->num ; i++) {
++ char *cp, *options = NULL;
++
++ for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
++ ;
++ if (!*cp || *cp == '\n' || *cp == '#')
++ continue;
++
++ /*
++ * Check if there are options for this key, and if so,
++ * save their starting address and skip the option part
++ * for now. If there are no options, set the starting
++ * address to NULL.
++ */
++ if (*cp < '0' || *cp > '9') {
++ int quoted = 0;
++ options = cp;
++ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
++ if (*cp == '\\' && cp[1] == '"')
++ cp++; /* Skip both */
++ else if (*cp == '"')
++ quoted = !quoted;
++ }
++ } else
++ options = NULL;
++
++ /* Parse the key from the line. */
++ if (hostfile_read_key(&cp, &bits, key) == 0) {
++ debug("[LDAP] line %d: non ssh1 key syntax", i);
++ continue;
++ }
++ /* cp now points to the comment part. */
++
++ /* Check if the we have found the desired key (identified by its modulus). */
++ if (BN_cmp(key->rsa->n, client_n) != 0)
++ continue;
++
++ /* check the real bits */
++ if (bits != (unsigned int)BN_num_bits(key->rsa->n))
++ logit("[LDAP] Warning: ldap, line %lu: keysize mismatch: "
++ "actual %d vs. announced %d.", (unsigned long)i, BN_num_bits(key->rsa->n), bits);
++
++ /* We have found the desired key. */
++ /*
++ * If our options do not allow this key to be used,
++ * do not send challenge.
++ */
++ if (!auth_parse_options(pw, options, "[LDAP]", (unsigned long) i))
++ continue;
++
++ /* break out, this key is allowed */
++ allowed = 1;
++
++ /* add the return stuff etc... */
++ /* Restore the privileged uid. */
++ restore_uid();
++
++ /* return key if allowed */
++ if (allowed && rkey != NULL)
++ *rkey = key;
++ else
++ key_free(key);
++
++ ldap_keys_free(k);
++ return (allowed);
++ }
++ } else {
++ logit("[LDAP] no keys found for '%s'!", pw->pw_name);
++ }
++ } else {
++ logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup);
++ }
++ }
++#endif
+ /* The authorized keys. */
+ file = authorized_keys_file(pw);
+ debug("trying public RSA key file %s", file);
+diff --git a/auth2-pubkey.c b/auth2-pubkey.c
+index 51aa774..7a3a27b 100644
+--- a/auth2-pubkey.c
++++ b/auth2-pubkey.c
+@@ -58,6 +58,10 @@
+ #include "misc.h"
+ #include "authfile.h"
+
++#ifdef WITH_LDAP_PUBKEY
++#include "ldapauth.h"
++#endif
++
+ /* import */
+ extern ServerOptions options;
+ extern u_char *session_id2;
+@@ -187,10 +191,79 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file)
+ u_long linenum = 0;
+ Key *found;
+ char *fp;
++#ifdef WITH_LDAP_PUBKEY
++ ldap_key_t * k;
++ unsigned int i = 0;
++#endif
+
+ /* Temporarily use the user's uid. */
+ temporarily_use_uid(pw);
+
++#ifdef WITH_LDAP_PUBKEY
++ found_key = 0;
++ /* allocate a new key type */
++ found = key_new(key->type);
++
++ /* first check if the options is enabled, then try.. */
++ if (options.lpk.on) {
++ debug("[LDAP] trying LDAP first uid=%s",pw->pw_name);
++ if (ldap_ismember(&options.lpk, pw->pw_name) > 0) {
++ if ((k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) {
++ /* Skip leading whitespace, empty and comment lines. */
++ for (i = 0 ; i < k->num ; i++) {
++ /* dont forget if multiple keys to reset options */
++ char *cp, *options = NULL;
++
++ for (cp = (char *)k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
++ ;
++ if (!*cp || *cp == '\n' || *cp == '#')
++ continue;
++
++ if (key_read(found, &cp) != 1) {
++ /* no key? check if there are options for this key */
++ int quoted = 0;
++ debug2("[LDAP] user_key_allowed: check options: '%s'", cp);
++ options = cp;
++ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
++ if (*cp == '\\' && cp[1] == '"')
++ cp++; /* Skip both */
++ else if (*cp == '"')
++ quoted = !quoted;
++ }
++ /* Skip remaining whitespace. */
++ for (; *cp == ' ' || *cp == '\t'; cp++)
++ ;
++ if (key_read(found, &cp) != 1) {
++ debug2("[LDAP] user_key_allowed: advance: '%s'", cp);
++ /* still no key? advance to next line*/
++ continue;
++ }
++ }
++
++ if (key_equal(found, key) &&
++ auth_parse_options(pw, options, file, linenum) == 1) {
++ found_key = 1;
++ debug("[LDAP] matching key found");
++ fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
++ verbose("[LDAP] Found matching %s key: %s", key_type(found), fp);
++
++ /* restoring memory */
++ ldap_keys_free(k);
++ xfree(fp);
++ restore_uid();
++ key_free(found);
++ return found_key;
++ break;
++ }
++ }/* end of LDAP for() */
++ } else {
++ logit("[LDAP] no keys found for '%s'!", pw->pw_name);
++ }
++ } else {
++ logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup);
++ }
++ }
++#endif
+ debug("trying public key file %s", file);
+ f = auth_openkeyfile(file, pw, options.strict_modes);
+
+diff --git a/config.h.in b/config.h.in
+index a61dec6..eba6884 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -575,6 +575,9 @@
+ /* Define to 1 if you have the <linux/if_tun.h> header file. */
+ #undef HAVE_LINUX_IF_TUN_H
+
++/* Define if you want LDAP support */
++#undef WITH_LDAP_PUBKEY
++
+ /* Define if your libraries define login() */
+ #undef HAVE_LOGIN
+
+diff --git a/configure b/configure
+index 7c19fc2..8ebf2e1 100755
+--- a/configure
++++ b/configure
+@@ -1340,6 +1340,7 @@ Optional Packages:
+ --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH)
+ --with-libedit[=PATH] Enable libedit support for sftp
+ --with-audit=module Enable EXPERIMENTAL audit support (modules=debug,bsm)
++ --with-ldap[=PATH] Enable LDAP pubkey support (optionally in PATH)
+ --with-ssl-dir=PATH Specify path to OpenSSL installation
+ --without-openssl-header-check Disable OpenSSL version consistency check
+ --with-ssl-engine Enable OpenSSL (hardware) ENGINE support
+@@ -12845,6 +12846,85 @@ echo "$as_me: error: Unknown audit module $withval" >&2;}
+ fi
+
+
++# Check whether user wants LDAP support
++LDAP_MSG="no"
++
++# Check whether --with-ldap was given.
++if test "${with_ldap+set}" = set; then
++ withval=$with_ldap;
++ if test "x$withval" != "xno" ; then
++
++ if test "x$withval" != "xyes" ; then
++ CPPFLAGS="$CPPFLAGS -I${withval}/include"
++ LDFLAGS="$LDFLAGS -L${withval}/lib"
++ fi
++
++
++cat >>confdefs.h <<\_ACEOF
++#define WITH_LDAP_PUBKEY 1
++_ACEOF
++
++ LIBS="-lldap $LIBS"
++ LDAP_MSG="yes"
++
++ { echo "$as_me:$LINENO: checking for LDAP support" >&5
++echo $ECHO_N "checking for LDAP support... $ECHO_C" >&6; }
++ cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h. */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h. */
++#include <sys/types.h>
++ #include <ldap.h>
++int
++main ()
++{
++(void)ldap_init(0, 0);
++ ;
++ return 0;
++}
++_ACEOF
++rm -f conftest.$ac_objext
++if { (ac_try="$ac_compile"
++case "(($ac_try" in
++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++ *) ac_try_echo=$ac_try;;
++esac
++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
++ (eval "$ac_compile") 2>conftest.er1
++ ac_status=$?
++ grep -v '^ *+' conftest.er1 >conftest.err
++ rm -f conftest.er1
++ cat conftest.err >&5
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } && {
++ test -z "$ac_c_werror_flag" ||
++ test ! -s conftest.err
++ } && test -s conftest.$ac_objext; then
++ { echo "$as_me:$LINENO: result: yes" >&5
++echo "${ECHO_T}yes" >&6; }
++else
++ echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++
++ { echo "$as_me:$LINENO: result: no" >&5
++echo "${ECHO_T}no" >&6; }
++ { { echo "$as_me:$LINENO: error: ** Incomplete or missing ldap libraries **" >&5
++echo "$as_me: error: ** Incomplete or missing ldap libraries **" >&2;}
++ { (exit 1); exit 1; }; }
++
++
++fi
++
++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
++ fi
++
++
++fi
++
++
+
+
+
+@@ -30786,6 +30866,7 @@ echo " SELinux support: $SELINUX_MSG"
+ echo " Smartcard support: $SCARD_MSG"
+ echo " S/KEY support: $SKEY_MSG"
+ echo " TCP Wrappers support: $TCPW_MSG"
++echo " LDAP support: $LDAP_MSG"
+ echo " MD5 password support: $MD5_MSG"
+ echo " libedit support: $LIBEDIT_MSG"
+ echo " Solaris process contract support: $SPC_MSG"
+diff --git a/configure.ac b/configure.ac
+index a9960a7..d3d85ca 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1323,6 +1323,37 @@ AC_ARG_WITH(audit,
+ esac ]
+ )
+
++# Check whether user wants LDAP support
++LDAP_MSG="no"
++AC_ARG_WITH(ldap,
++ [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)],
++ [
++ if test "x$withval" != "xno" ; then
++
++ if test "x$withval" != "xyes" ; then
++ CPPFLAGS="$CPPFLAGS -I${withval}/include"
++ LDFLAGS="$LDFLAGS -L${withval}/lib"
++ fi
++
++ AC_DEFINE([WITH_LDAP_PUBKEY], 1, [Enable LDAP pubkey support])
++ LIBS="-lldap $LIBS"
++ LDAP_MSG="yes"
++
++ AC_MSG_CHECKING([for LDAP support])
++ AC_TRY_COMPILE(
++ [#include <sys/types.h>
++ #include <ldap.h>],
++ [(void)ldap_init(0, 0);],
++ [AC_MSG_RESULT(yes)],
++ [
++ AC_MSG_RESULT(no)
++ AC_MSG_ERROR([** Incomplete or missing ldap libraries **])
++ ]
++ )
++ fi
++ ]
++)
++
+ dnl Checks for library functions. Please keep in alphabetical order
+ AC_CHECK_FUNCS( \
+ arc4random \
+@@ -4185,6 +4216,7 @@ echo " SELinux support: $SELINUX_MSG"
+ echo " Smartcard support: $SCARD_MSG"
+ echo " S/KEY support: $SKEY_MSG"
+ echo " TCP Wrappers support: $TCPW_MSG"
++echo " LDAP support: $LDAP_MSG"
+ echo " MD5 password support: $MD5_MSG"
+ echo " libedit support: $LIBEDIT_MSG"
+ echo " Solaris process contract support: $SPC_MSG"
+diff --git a/ldapauth.c b/ldapauth.c
+new file mode 100644
+index 0000000..133483e
+--- /dev/null
++++ b/ldapauth.c
+@@ -0,0 +1,575 @@
++/*
++ * $Id: openssh-lpk-4.3p1-0.3.7.patch,v 1.3 2006/04/18 15:29:09 eau Exp $
++ */
++
++/*
++ *
++ * Copyright (c) 2005, Eric AUGE <eau at 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:
++ *
++ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
++ * 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.
++ * Neither the name of the phear.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
++ *
++ *
++ */
++
++#include "includes.h"
++
++#ifdef WITH_LDAP_PUBKEY
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++
++#include "ldapauth.h"
++#include "log.h"
++
++static char *attrs[] = {
++ PUBKEYATTR,
++ NULL
++};
++
++/* filter building infos */
++#define FILTER_GROUP_PREFIX "(&(objectclass=posixGroup)"
++#define FILTER_OR_PREFIX "(|"
++#define FILTER_OR_SUFFIX ")"
++#define FILTER_CN_PREFIX "(cn="
++#define FILTER_CN_SUFFIX ")"
++#define FILTER_UID_FORMAT "(memberUid=%s)"
++#define FILTER_GROUP_SUFFIX ")"
++#define FILTER_GROUP_SIZE(group) (size_t) (strlen(group)+(ldap_count_group(group)*5)+52)
++
++/* just filter building stuff */
++#define REQUEST_GROUP_SIZE(filter, uid) (size_t) (strlen(filter)+strlen(uid)+1)
++#define REQUEST_GROUP(buffer, prefilter, pwname) \
++ buffer = (char *) calloc(REQUEST_GROUP_SIZE(prefilter, pwname), sizeof(char)); \
++ if (!buffer) { \
++ perror("calloc()"); \
++ return FAILURE; \
++ } \
++ snprintf(buffer, REQUEST_GROUP_SIZE(prefilter,pwname), prefilter, pwname)
++/*
++XXX OLD group building macros
++#define REQUEST_GROUP_SIZE(grp, uid) (size_t) (strlen(grp)+strlen(uid)+46)
++#define REQUEST_GROUP(buffer,pwname,grp) \
++ buffer = (char *) calloc(REQUEST_GROUP_SIZE(grp, pwname), sizeof(char)); \
++ if (!buffer) { \
++ perror("calloc()"); \
++ return FAILURE; \
++ } \
++ snprintf(buffer,REQUEST_GROUP_SIZE(grp,pwname),"(&(objectclass=posixGroup)(cn=%s)(memberUid=%s))",grp,pwname)
++ */
++
++/*
++XXX stock upstream version without extra filter support
++#define REQUEST_USER_SIZE(uid) (size_t) (strlen(uid)+64)
++#define REQUEST_USER(buffer, pwname) \
++ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname), sizeof(char)); \
++ if (!buffer) { \
++ perror("calloc()"); \
++ return NULL; \
++ } \
++ snprintf(buffer,REQUEST_USER_SIZE(pwname),"(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s))",pwname)
++ */
++
++#define REQUEST_USER_SIZE(uid, filter) (size_t) (strlen(uid)+64+(filter != NULL ? strlen(filter) : 0))
++#define REQUEST_USER(buffer, pwname, customfilter) \
++ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname, customfilter), sizeof(char)); \
++ if (!buffer) { \
++ perror("calloc()"); \
++ return NULL; \
++ } \
++ snprintf(buffer, REQUEST_USER_SIZE(pwname, customfilter), \
++ "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)", \
++ pwname, (customfilter != NULL ? customfilter : ""))
++
++/* some portable and working tokenizer, lame though */
++static int tokenize(char ** o, size_t size, char * input) {
++ unsigned int i = 0, num;
++ const char * charset = " \t";
++ char * ptr = input;
++
++ /* leading white spaces are ignored */
++ num = strspn(ptr, charset);
++ ptr += num;
++
++ while ((num = strcspn(ptr, charset))) {
++ if (i < size-1) {
++ o[i++] = ptr;
++ ptr += num;
++ if (*ptr)
++ *ptr++ = '\0';
++ }
++ }
++ o[i] = NULL;
++ return SUCCESS;
++}
++
++void ldap_close(ldap_opt_t * ldap) {
++
++ if (!ldap)
++ return;
++
++ if ( ldap_unbind_ext(ldap->ld, NULL, NULL) < 0)
++ ldap_perror(ldap->ld, "ldap_unbind()");
++
++ ldap->ld = NULL;
++ FLAG_SET_DISCONNECTED(ldap->flags);
++
++ return;
++}
++
++/* init && bind */
++int ldap_connect(ldap_opt_t * ldap) {
++ int version = LDAP_VERSION3;
++
++ if (!ldap->servers)
++ return FAILURE;
++
++ /* Connection Init and setup */
++ ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
++ if (!ldap->ld) {
++ ldap_perror(ldap->ld, "ldap_init()");
++ return FAILURE;
++ }
++
++ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
++ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_PROTOCOL_VERSION)");
++ return FAILURE;
++ }
++
++ /* Timeouts setup */
++ if (ldap_set_option(ldap->ld, LDAP_OPT_NETWORK_TIMEOUT, &ldap->b_timeout) != LDAP_SUCCESS) {
++ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT)");
++ }
++ if (ldap_set_option(ldap->ld, LDAP_OPT_TIMEOUT, &ldap->s_timeout) != LDAP_SUCCESS) {
++ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_TIMEOUT)");
++ }
++
++ /* TLS support */
++ if ( (ldap->tls == -1) || (ldap->tls == 1) ) {
++ if (ldap_start_tls_s(ldap->ld, NULL, NULL ) != LDAP_SUCCESS) {
++ /* failed then reinit the initial connect */
++ ldap_perror(ldap->ld, "ldap_connect: (TLS) ldap_start_tls()");
++ if (ldap->tls == 1)
++ return FAILURE;
++
++ ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
++ if (!ldap->ld) {
++ ldap_perror(ldap->ld, "ldap_init()");
++ return FAILURE;
++ }
++
++ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
++ ldap_perror(ldap->ld, "ldap_set_option()");
++ return FAILURE;
++ }
++ }
++ }
++
++
++ if ( ldap_simple_bind_s(ldap->ld, ldap->binddn, ldap->bindpw) != LDAP_SUCCESS) {
++ ldap_perror(ldap->ld, "ldap_simple_bind_s()");
++ return FAILURE;
++ }
++
++ /* says it is connected */
++ FLAG_SET_CONNECTED(ldap->flags);
++
++ return SUCCESS;
++}
++
++/* must free allocated ressource */
++static char * ldap_build_host(char *host, int port) {
++ unsigned int size = strlen(host)+11;
++ char * h = (char *) calloc (size, sizeof(char));
++ int rc;
++ if (!h)
++ return NULL;
++
++ rc = snprintf(h, size, "%s:%d ", host, port);
++ if (rc == -1)
++ return NULL;
++ return h;
++}
++
++static int ldap_count_group(const char * input) {
++ const char * charset = " \t";
++ const char * ptr = input;
++ unsigned int count = 0;
++ unsigned int num;
++
++ num = strspn(ptr, charset);
++ ptr += num;
++
++ while ((num = strcspn(ptr, charset))) {
++ count++;
++ ptr += num;
++ ptr++;
++ }
++
++ return count;
++}
++
++/* format filter */
++char * ldap_parse_groups(const char * groups) {
++ unsigned int buffer_size = FILTER_GROUP_SIZE(groups);
++ char * buffer = (char *) calloc(buffer_size, sizeof(char));
++ char * g = NULL;
++ char * garray[32];
++ unsigned int i = 0;
++
++ if ((!groups)||(!buffer))
++ return NULL;
++
++ g = strdup(groups);
++ if (!g) {
++ free(buffer);
++ return NULL;
++ }
++
++ /* first separate into n tokens */
++ if ( tokenize(garray, sizeof(garray)/sizeof(*garray), g) < 0) {
++ free(g);
++ free(buffer);
++ return NULL;
++ }
++
++ /* build the final filter format */
++ strlcat(buffer, FILTER_GROUP_PREFIX, buffer_size);
++ strlcat(buffer, FILTER_OR_PREFIX, buffer_size);
++ i = 0;
++ while (garray[i]) {
++ strlcat(buffer, FILTER_CN_PREFIX, buffer_size);
++ strlcat(buffer, garray[i], buffer_size);
++ strlcat(buffer, FILTER_CN_SUFFIX, buffer_size);
++ i++;
++ }
++ strlcat(buffer, FILTER_OR_SUFFIX, buffer_size);
++ strlcat(buffer, FILTER_UID_FORMAT, buffer_size);
++ strlcat(buffer, FILTER_GROUP_SUFFIX, buffer_size);
++
++ free(g);
++ return buffer;
++}
++
++/* a bit dirty but leak free */
++char * ldap_parse_servers(const char * servers) {
++ char * s = NULL;
++ char * tmp = NULL, *urls[32];
++ unsigned int num = 0 , i = 0 , asize = 0;
++ LDAPURLDesc *urld[32];
++
++ if (!servers)
++ return NULL;
++
++ /* local copy of the arg */
++ s = strdup(servers);
++ if (!s)
++ return NULL;
++
++ /* first separate into URL tokens */
++ if ( tokenize(urls, sizeof(urls)/sizeof(*urls), s) < 0)
++ return NULL;
++
++ i = 0;
++ while (urls[i]) {
++ if (! ldap_is_ldap_url(urls[i]) ||
++ (ldap_url_parse(urls[i], &urld[i]) != 0)) {
++ return NULL;
++ }
++ i++;
++ }
++
++ /* now free(s) */
++ free (s);
++
++ /* how much memory do we need */
++ num = i;
++ for (i = 0 ; i < num ; i++)
++ asize += strlen(urld[i]->lud_host)+11;
++
++ /* alloc */
++ s = (char *) calloc( asize+1 , sizeof(char));
++ if (!s) {
++ for (i = 0 ; i < num ; i++)
++ ldap_free_urldesc(urld[i]);
++ return NULL;
++ }
++
++ /* then build the final host string */
++ for (i = 0 ; i < num ; i++) {
++ /* built host part */
++ tmp = ldap_build_host(urld[i]->lud_host, urld[i]->lud_port);
++ strncat(s, tmp, strlen(tmp));
++ ldap_free_urldesc(urld[i]);
++ free(tmp);
++ }
++
++ return s;
++}
++
++void ldap_options_print(ldap_opt_t * ldap) {
++ debug("ldap options:");
++ debug("servers: %s", ldap->servers);
++ if (ldap->u_basedn)
++ debug("user basedn: %s", ldap->u_basedn);
++ if (ldap->g_basedn)
++ debug("group basedn: %s", ldap->g_basedn);
++ if (ldap->binddn)
++ debug("binddn: %s", ldap->binddn);
++ if (ldap->bindpw)
++ debug("bindpw: %s", ldap->bindpw);
++ if (ldap->sgroup)
++ debug("group: %s", ldap->sgroup);
++ if (ldap->filter)
++ debug("filter: %s", ldap->filter);
++}
++
++void ldap_options_free(ldap_opt_t * l) {
++ if (!l)
++ return;
++ if (l->servers)
++ free(l->servers);
++ if (l->u_basedn)
++ free(l->u_basedn);
++ if (l->g_basedn)
++ free(l->g_basedn);
++ if (l->binddn)
++ free(l->binddn);
++ if (l->bindpw)
++ free(l->bindpw);
++ if (l->sgroup)
++ free(l->sgroup);
++ if (l->fgroup)
++ free(l->fgroup);
++ if (l->filter)
++ free(l->filter);
++ if (l->l_conf)
++ free(l->l_conf);
++ free(l);
++}
++
++/* free keys */
++void ldap_keys_free(ldap_key_t * k) {
++ ldap_value_free_len(k->keys);
++ free(k);
++ return;
++}
++
++ldap_key_t * ldap_getuserkey(ldap_opt_t *l, const char * user) {
++ ldap_key_t * k = (ldap_key_t *) calloc (1, sizeof(ldap_key_t));
++ LDAPMessage *res, *e;
++ char * filter;
++ int i;
++
++ if ((!k) || (!l))
++ return NULL;
++
++ /* Am i still connected ? RETRY n times */
++ /* XXX TODO: setup some conf value for retrying */
++ if (!(l->flags & FLAG_CONNECTED))
++ for (i = 0 ; i < 2 ; i++)
++ if (ldap_connect(l) == 0)
++ break;
++
++ /* quick check for attempts to be evil */
++ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) ||
++ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL))
++ return NULL;
++
++ /* build filter for LDAP request */
++ REQUEST_USER(filter, user, l->filter);
++
++ if ( ldap_search_st( l->ld,
++ l->u_basedn,
++ LDAP_SCOPE_SUBTREE,
++ filter,
++ attrs, 0, &l->s_timeout, &res ) != LDAP_SUCCESS) {
++
++ ldap_perror(l->ld, "ldap_search_st()");
++
++ free(filter);
++ free(k);
++
++ /* XXX error on search, timeout etc.. close ask for reconnect */
++ ldap_close(l);
++
++ return NULL;
++ }
++
++ /* free */
++ free(filter);
++
++ /* check if any results */
++ i = ldap_count_entries(l->ld,res);
++ if (i <= 0) {
++ ldap_msgfree(res);
++ free(k);
++ return NULL;
++ }
++
++ if (i > 1)
++ debug("[LDAP] duplicate entries, using the FIRST entry returned");
++
++ e = ldap_first_entry(l->ld, res);
++ k->keys = ldap_get_values_len(l->ld, e, PUBKEYATTR);
++ k->num = ldap_count_values_len(k->keys);
++
++ ldap_msgfree(res);
++ return k;
++}
++
++
++/* -1 if trouble
++ 0 if user is NOT member of current server group
++ 1 if user IS MEMBER of current server group
++ */
++int ldap_ismember(ldap_opt_t * l, const char * user) {
++ LDAPMessage *res;
++ char * filter;
++ int i;
++
++ if ((!l->sgroup) || !(l->g_basedn))
++ return 1;
++
++ /* Am i still connected ? RETRY n times */
++ /* XXX TODO: setup some conf value for retrying */
++ if (!(l->flags & FLAG_CONNECTED))
++ for (i = 0 ; i < 2 ; i++)
++ if (ldap_connect(l) == 0)
++ break;
++
++ /* quick check for attempts to be evil */
++ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) ||
++ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL))
++ return FAILURE;
++
++ /* build filter for LDAP request */
++ REQUEST_GROUP(filter, l->fgroup, user);
++
++ if (ldap_search_st( l->ld,
++ l->g_basedn,
++ LDAP_SCOPE_SUBTREE,
++ filter,
++ NULL, 0, &l->s_timeout, &res) != LDAP_SUCCESS) {
++
++ ldap_perror(l->ld, "ldap_search_st()");
++
++ free(filter);
++
++ /* XXX error on search, timeout etc.. close ask for reconnect */
++ ldap_close(l);
++
++ return FAILURE;
++ }
++
++ free(filter);
++
++ /* check if any results */
++ if (ldap_count_entries(l->ld, res) > 0) {
++ ldap_msgfree(res);
++ return 1;
++ }
++
++ ldap_msgfree(res);
++ return 0;
++}
++
++/*
++ * ldap.conf simple parser
++ * XXX TODO: sanity checks
++ * must either
++ * - free the previous ldap_opt_before replacing entries
++ * - free each necessary previously parsed elements
++ * ret:
++ * -1 on FAILURE, 0 on SUCCESS
++ */
++int ldap_parse_lconf(ldap_opt_t * l) {
++ FILE * lcd; /* ldap.conf descriptor */
++ char buf[BUFSIZ];
++ char * s = NULL, * k = NULL, * v = NULL;
++ int li, len;
++
++ lcd = fopen (l->l_conf, "r");
++ if (lcd == NULL) {
++ /* debug("Cannot open %s", l->l_conf); */
++ perror("ldap_parse_lconf()");
++ return FAILURE;
++ }
++
++ while (fgets (buf, sizeof (buf), lcd) != NULL) {
++
++ if (*buf == '\n' || *buf == '#')
++ continue;
++
++ k = buf;
++ v = k;
++ while (*v != '\0' && *v != ' ' && *v != '\t')
++ v++;
++
++ if (*v == '\0')
++ continue;
++
++ *(v++) = '\0';
++
++ while (*v == ' ' || *v == '\t')
++ v++;
++
++ li = strlen (v) - 1;
++ while (v[li] == ' ' || v[li] == '\t' || v[li] == '\n')
++ --li;
++ v[li + 1] = '\0';
++
++ if (!strcasecmp (k, "uri")) {
++ if ((l->servers = ldap_parse_servers(v)) == NULL) {
++ fatal("error in ldap servers");
++ return FAILURE;
++ }
++
++ }
++ else if (!strcasecmp (k, "base")) {
++ s = strchr (v, '?');
++ if (s != NULL) {
++ len = s - v;
++ l->u_basedn = malloc (len + 1);
++ strncpy (l->u_basedn, v, len);
++ l->u_basedn[len] = '\0';
++ } else {
++ l->u_basedn = strdup (v);
++ }
++ }
++ else if (!strcasecmp (k, "binddn")) {
++ l->binddn = strdup (v);
++ }
++ else if (!strcasecmp (k, "bindpw")) {
++ l->bindpw = strdup (v);
++ }
++ else if (!strcasecmp (k, "timelimit")) {
++ l->s_timeout.tv_sec = atoi (v);
++ }
++ else if (!strcasecmp (k, "bind_timelimit")) {
++ l->b_timeout.tv_sec = atoi (v);
++ }
++ else if (!strcasecmp (k, "ssl")) {
++ if (!strcasecmp (v, "start_tls"))
++ l->tls = 1;
++ }
++ }
++
++ fclose (lcd);
++ return SUCCESS;
++}
++
++#endif /* WITH_LDAP_PUBKEY */
+diff --git a/ldapauth.h b/ldapauth.h
+new file mode 100644
+index 0000000..ba70958
+--- /dev/null
++++ b/ldapauth.h
+@@ -0,0 +1,124 @@
++/*
++ * $Id: openssh-lpk-4.3p1-0.3.7.patch,v 1.3 2006/04/18 15:29:09 eau Exp $
++ */
++
++/*
++ *
++ * Copyright (c) 2005, Eric AUGE <eau at 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:
++ *
++ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
++ * 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.
++ * Neither the name of the phear.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
++ *
++ *
++ */
++
++#ifndef LDAPAUTH_H
++#define LDAPAUTH_H
++
++#define LDAP_DEPRECATED 1
++
++#include <string.h>
++#include <time.h>
++#include <ldap.h>
++#include <lber.h>
++
++/* tokens in use for config */
++#define _DEFAULT_LPK_TOKEN "UseLPK"
++#define _DEFAULT_SRV_TOKEN "LpkServers"
++#define _DEFAULT_USR_TOKEN "LpkUserDN"
++#define _DEFAULT_GRP_TOKEN "LpkGroupDN"
++#define _DEFAULT_BDN_TOKEN "LpkBindDN"
++#define _DEFAULT_BPW_TOKEN "LpkBindPw"
++#define _DEFAULT_MYG_TOKEN "LpkServerGroup"
++#define _DEFAULT_FIL_TOKEN "LpkFilter"
++#define _DEFAULT_TLS_TOKEN "LpkForceTLS"
++#define _DEFAULT_BTI_TOKEN "LpkBindTimelimit"
++#define _DEFAULT_STI_TOKEN "LpkSearchTimelimit"
++#define _DEFAULT_LDP_TOKEN "LpkLdapConf"
++
++/* default options */
++#define _DEFAULT_LPK_ON 0
++#define _DEFAULT_LPK_SERVERS NULL
++#define _DEFAULT_LPK_UDN NULL
++#define _DEFAULT_LPK_GDN NULL
++#define _DEFAULT_LPK_BINDDN NULL
++#define _DEFAULT_LPK_BINDPW NULL
++#define _DEFAULT_LPK_SGROUP NULL
++#define _DEFAULT_LPK_FILTER NULL
++#define _DEFAULT_LPK_TLS -1
++#define _DEFAULT_LPK_BTIMEOUT 10
++#define _DEFAULT_LPK_STIMEOUT 10
++#define _DEFAULT_LPK_LDP NULL
++
++/* flags */
++#define FLAG_EMPTY 0x00000000
++#define FLAG_CONNECTED 0x00000001
++
++/* flag macros */
++#define FLAG_SET_EMPTY(x) x&=(FLAG_EMPTY)
++#define FLAG_SET_CONNECTED(x) x|=(FLAG_CONNECTED)
++#define FLAG_SET_DISCONNECTED(x) x&=~(FLAG_CONNECTED)
++
++/* defines */
++#define FAILURE -1
++#define SUCCESS 0
++#define PUBKEYATTR "sshPublicKey"
++
++/*
++ *
++ * defined files path
++ * (should be relocated to pathnames.h,
++ * if one day it's included within the tree)
++ *
++ */
++#define _PATH_LDAP_CONFIG_FILE "/etc/ldap.conf"
++
++/* structures */
++typedef struct ldap_options {
++ int on; /* Use it or NOT */
++ LDAP * ld; /* LDAP file desc */
++ char * servers; /* parsed servers for ldaplib failover handling */
++ char * u_basedn; /* user basedn */
++ char * g_basedn; /* group basedn */
++ char * binddn; /* binddn */
++ char * bindpw; /* bind password */
++ char * sgroup; /* server group */
++ char * fgroup; /* group filter */
++ char * filter; /* additional filter */
++ char * l_conf; /* use ldap.conf */
++ int tls; /* TLS only */
++ struct timeval b_timeout; /* bind timeout */
++ struct timeval s_timeout; /* search timeout */
++ unsigned int flags; /* misc flags (reconnection, future use?) */
++} ldap_opt_t;
++
++typedef struct ldap_keys {
++ struct berval ** keys; /* the public keys retrieved */
++ unsigned int num; /* number of keys */
++} ldap_key_t;
++
++
++/* function headers */
++void ldap_close(ldap_opt_t *);
++int ldap_connect(ldap_opt_t *);
++char * ldap_parse_groups(const char *);
++char * ldap_parse_servers(const char *);
++void ldap_options_print(ldap_opt_t *);
++void ldap_options_free(ldap_opt_t *);
++void ldap_keys_free(ldap_key_t *);
++int ldap_parse_lconf(ldap_opt_t *);
++ldap_key_t * ldap_getuserkey(ldap_opt_t *, const char *);
++int ldap_ismember(ldap_opt_t *, const char *);
++
++#endif
+diff --git a/lpk-user-example.txt b/lpk-user-example.txt
+new file mode 100644
+index 0000000..1528fc0
+--- /dev/null
++++ b/lpk-user-example.txt
+@@ -0,0 +1,117 @@
++
++Post to ML -> User Made Quick Install Doc.
++Contribution from John Lane <john at lane.uk.net>
++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++
++OpenSSH LDAP keystore Patch
++===========================
++
++NOTE: these notes are a transcript of a specific installation
++ they work for me, your specifics may be different!
++ from John Lane March 17th 2005 john at lane.uk.net
++
++This is a patch to OpenSSH 4.0p1 to allow it to obtain users' public keys
++from their LDAP record as an alternative to ~/.ssh/authorized_keys.
++
++(Assuming here that necessary build stuff is in $BUILD)
++
++cd $BUILD/openssh-4.0p1
++patch -Np1 -i $BUILD/openssh-lpk-4.0p1-0.3.patch
++mkdir -p /var/empty &&
++./configure --prefix=/usr --sysconfdir=/etc/ssh \
++ --libexecdir=/usr/sbin --with-md5-passwords --with-pam \
++ --with-libs="-lldap" --with-cppflags="-DWITH_LDAP_PUBKEY"
++Now do.
++make &&
++make install
++
++Add the following config to /etc/ssh/ssh_config
++UseLPK yes
++LpkServers ldap://myhost.mydomain.com
++LpkUserDN ou=People,dc=mydomain,dc=com
++
++We need to tell sshd about the SSL keys during boot, as root's
++environment does not exist at that time. Edit /etc/rc.d/init.d/sshd.
++Change the startup code from this:
++ echo "Starting SSH Server..."
++ loadproc /usr/sbin/sshd
++ ;;
++to this:
++ echo "Starting SSH Server..."
++ LDAPRC="/root/.ldaprc" loadproc /usr/sbin/sshd
++ ;;
++
++Re-start the sshd daemon:
++/etc/rc.d/init.d/sshd restart
++
++Install the additional LDAP schema
++cp $BUILD/openssh-lpk-0.2.schema /etc/openldap/schema/openssh.schema
++
++Now add the openSSH LDAP schema to /etc/openldap/slapd.conf:
++Add the following to the end of the existing block of schema includes
++include /etc/openldap/schema/openssh.schema
++
++Re-start the LDAP server:
++/etc/rc.d/init.d/slapd restart
++
++To add one or more public keys to a user, eg "testuser" :
++ldapsearch -x -W -Z -LLL -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D
++"uid=testuser,ou=People,dc=mydomain,dc=com" > /tmp/testuser
++
++append the following to this /tmp/testuser file
++objectclass: ldapPublicKey
++sshPublicKey: ssh-rsa
++AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KS
++qIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z8XwSsuAoR1t86t+5dlI
++7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key
++
++Then do a modify:
++ldapmodify -x -D "uid=testuser,ou=People,dc=mydomain,dc=com" -W -f
++/tmp/testuser -Z
++Enter LDAP Password:
++modifying entry "uid=testuser,ou=People,dc=mydomain,dc=com"
++And check the modify is ok:
++ldapsearch -x -W -Z -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D
++"uid=testuser,ou=People,dc=mydomain,dc=com"
++Enter LDAP Password:
++# extended LDIF
++#
++# LDAPv3
++# base <uid=testuser,ou=People,dc=mydomain,dc=com> with scope sub
++# filter: (objectclass=*)
++# requesting: ALL
++#
++
++# testuser, People, mydomain.com
++dn: uid=testuser,ou=People,dc=mydomain,dc=com
++uid: testuser
++cn: testuser
++objectClass: account
++objectClass: posixAccount
++objectClass: top
++objectClass: shadowAccount
++objectClass: ldapPublicKey
++shadowLastChange: 12757
++shadowMax: 99999
++shadowWarning: 7
++loginShell: /bin/bash
++uidNumber: 9999
++gidNumber: 501
++homeDirectory: /home/testuser
++userPassword:: e1NTSEF9UDgwV1hnM1VjUDRJK0k1YnFiL1d4ZUJObXlZZ3Z3UTU=
++sshPublicKey: ssh-rsa
++AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KSqIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z
++8XwSsuAoR1t86t+5dlI7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key
++
++# search result
++search: 3
++result: 0 Success
++
++# numResponses: 2
++# numEntries: 1
++
++Now start a ssh session to user "testuser" from usual ssh client (e.g.
++puTTY). Login should succeed.
++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+diff --git a/openssh-lpk_openldap.schema b/openssh-lpk_openldap.schema
+new file mode 100644
+index 0000000..5f5512a
+--- /dev/null
++++ b/openssh-lpk_openldap.schema
+@@ -0,0 +1,19 @@
++#
++# LDAP Public Key Patch schema for use with openssh-ldappubkey
++# Author: Eric AUGE <eau at phear.org>
++#
++# Based on the proposal of : Mark Ruijter
++#
++
++
++# octetString SYNTAX
++attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
++ DESC 'MANDATORY: OpenSSH Public key'
++ EQUALITY octetStringMatch
++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
++
++# printableString SYNTAX yes|no
++objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
++ DESC 'MANDATORY: OpenSSH LPK objectclass'
++ MUST ( sshPublicKey $ uid )
++ )
+diff --git a/openssh-lpk_sun.schema b/openssh-lpk_sun.schema
+new file mode 100644
+index 0000000..c5e0214
+--- /dev/null
++++ b/openssh-lpk_sun.schema
+@@ -0,0 +1,21 @@
++#
++# LDAP Public Key Patch schema for use with openssh-ldappubkey
++# Author: Eric AUGE <eau at phear.org>
++#
++# Schema for Sun Directory Server.
++# Based on the original schema, modified by Stefan Fischer.
++#
++
++dn: cn=schema
++
++# octetString SYNTAX
++attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
++ DESC 'MANDATORY: OpenSSH Public key'
++ EQUALITY octetStringMatch
++ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
++
++# printableString SYNTAX yes|no
++objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
++ DESC 'MANDATORY: OpenSSH LPK objectclass'
++ MUST ( sshPublicKey $ uid )
++ )
+diff --git a/servconf.c b/servconf.c
+index f9e2f2d..078b581 100644
+--- a/servconf.c
++++ b/servconf.c
+@@ -42,6 +42,10 @@
+ #include "channels.h"
+ #include "groupaccess.h"
+
++#ifdef WITH_LDAP_PUBKEY
++#include "ldapauth.h"
++#endif
++
+ static void add_listen_addr(ServerOptions *, char *, int);
+ static void add_one_listen_addr(ServerOptions *, char *, int);
+
+@@ -131,6 +135,24 @@ initialize_server_options(ServerOptions *options)
+ options->zero_knowledge_password_authentication = -1;
+ options->revoked_keys_file = NULL;
+ options->trusted_user_ca_keys = NULL;
++#ifdef WITH_LDAP_PUBKEY
++ /* XXX dirty */
++ options->lpk.ld = NULL;
++ options->lpk.on = -1;
++ options->lpk.servers = NULL;
++ options->lpk.u_basedn = NULL;
++ options->lpk.g_basedn = NULL;
++ options->lpk.binddn = NULL;
++ options->lpk.bindpw = NULL;
++ options->lpk.sgroup = NULL;
++ options->lpk.filter = NULL;
++ options->lpk.fgroup = NULL;
++ options->lpk.l_conf = NULL;
++ options->lpk.tls = -1;
++ options->lpk.b_timeout.tv_sec = -1;
++ options->lpk.s_timeout.tv_sec = -1;
++ options->lpk.flags = FLAG_EMPTY;
++#endif
+ }
+
+ void
+@@ -265,6 +287,32 @@ fill_default_server_options(ServerOptions *options)
+ options->permit_tun = SSH_TUNMODE_NO;
+ if (options->zero_knowledge_password_authentication == -1)
+ options->zero_knowledge_password_authentication = 0;
++#ifdef WITH_LDAP_PUBKEY
++ if (options->lpk.on == -1)
++ options->lpk.on = _DEFAULT_LPK_ON;
++ if (options->lpk.servers == NULL)
++ options->lpk.servers = _DEFAULT_LPK_SERVERS;
++ if (options->lpk.u_basedn == NULL)
++ options->lpk.u_basedn = _DEFAULT_LPK_UDN;
++ if (options->lpk.g_basedn == NULL)
++ options->lpk.g_basedn = _DEFAULT_LPK_GDN;
++ if (options->lpk.binddn == NULL)
++ options->lpk.binddn = _DEFAULT_LPK_BINDDN;
++ if (options->lpk.bindpw == NULL)
++ options->lpk.bindpw = _DEFAULT_LPK_BINDPW;
++ if (options->lpk.sgroup == NULL)
++ options->lpk.sgroup = _DEFAULT_LPK_SGROUP;
++ if (options->lpk.filter == NULL)
++ options->lpk.filter = _DEFAULT_LPK_FILTER;
++ if (options->lpk.tls == -1)
++ options->lpk.tls = _DEFAULT_LPK_TLS;
++ if (options->lpk.b_timeout.tv_sec == -1)
++ options->lpk.b_timeout.tv_sec = _DEFAULT_LPK_BTIMEOUT;
++ if (options->lpk.s_timeout.tv_sec == -1)
++ options->lpk.s_timeout.tv_sec = _DEFAULT_LPK_STIMEOUT;
++ if (options->lpk.l_conf == NULL)
++ options->lpk.l_conf = _DEFAULT_LPK_LDP;
++#endif
+
+ /* Turn privilege separation on by default */
+ if (use_privsep == -1)
+@@ -312,6 +360,12 @@ typedef enum {
+ sZeroKnowledgePasswordAuthentication, sHostCertificate,
+ sRevokedKeys, sTrustedUserCAKeys,
+ sDeprecated, sUnsupported
++#ifdef WITH_LDAP_PUBKEY
++ ,sLdapPublickey, sLdapServers, sLdapUserDN
++ ,sLdapGroupDN, sBindDN, sBindPw, sMyGroup
++ ,sLdapFilter, sForceTLS, sBindTimeout
++ ,sSearchTimeout, sLdapConf
++#endif
+ } ServerOpCodes;
+
+ #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
+@@ -432,6 +486,20 @@ static struct {
+ { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
+ { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
+ { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
++#ifdef WITH_LDAP_PUBKEY
++ { _DEFAULT_LPK_TOKEN, sLdapPublickey, SSHCFG_GLOBAL },
++ { _DEFAULT_SRV_TOKEN, sLdapServers, SSHCFG_GLOBAL },
++ { _DEFAULT_USR_TOKEN, sLdapUserDN, SSHCFG_GLOBAL },
++ { _DEFAULT_GRP_TOKEN, sLdapGroupDN, SSHCFG_GLOBAL },
++ { _DEFAULT_BDN_TOKEN, sBindDN, SSHCFG_GLOBAL },
++ { _DEFAULT_BPW_TOKEN, sBindPw, SSHCFG_GLOBAL },
++ { _DEFAULT_MYG_TOKEN, sMyGroup, SSHCFG_GLOBAL },
++ { _DEFAULT_FIL_TOKEN, sLdapFilter, SSHCFG_GLOBAL },
++ { _DEFAULT_TLS_TOKEN, sForceTLS, SSHCFG_GLOBAL },
++ { _DEFAULT_BTI_TOKEN, sBindTimeout, SSHCFG_GLOBAL },
++ { _DEFAULT_STI_TOKEN, sSearchTimeout, SSHCFG_GLOBAL },
++ { _DEFAULT_LDP_TOKEN, sLdapConf, SSHCFG_GLOBAL },
++#endif
+ { NULL, sBadOption, 0 }
+ };
+
+@@ -1349,6 +1417,107 @@ process_server_config_line(ServerOptions *options, char *line,
+ while (arg)
+ arg = strdelim(&cp);
+ break;
++#ifdef WITH_LDAP_PUBKEY
++ case sLdapPublickey:
++ intptr = &options->lpk.on;
++ goto parse_flag;
++ case sLdapServers:
++ /* arg = strdelim(&cp); */
++ p = line;
++ while(*p++);
++ arg = p;
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing ldap server",filename,linenum);
++ arg[strlen(arg)] = '\0';
++ if ((options->lpk.servers = ldap_parse_servers(arg)) == NULL)
++ fatal("%s line %d: error in ldap servers", filename, linenum);
++ memset(arg,0,strlen(arg));
++ break;
++ case sLdapUserDN:
++ arg = cp;
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing ldap server",filename,linenum);
++ arg[strlen(arg)] = '\0';
++ options->lpk.u_basedn = xstrdup(arg);
++ memset(arg,0,strlen(arg));
++ break;
++ case sLdapGroupDN:
++ arg = cp;
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing ldap server",filename,linenum);
++ arg[strlen(arg)] = '\0';
++ options->lpk.g_basedn = xstrdup(arg);
++ memset(arg,0,strlen(arg));
++ break;
++ case sBindDN:
++ arg = cp;
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing binddn",filename,linenum);
++ arg[strlen(arg)] = '\0';
++ options->lpk.binddn = xstrdup(arg);
++ memset(arg,0,strlen(arg));
++ break;
++ case sBindPw:
++ arg = cp;
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing bindpw",filename,linenum);
++ arg[strlen(arg)] = '\0';
++ options->lpk.bindpw = xstrdup(arg);
++ memset(arg,0,strlen(arg));
++ break;
++ case sMyGroup:
++ arg = cp;
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing groupname",filename, linenum);
++ arg[strlen(arg)] = '\0';
++ options->lpk.sgroup = xstrdup(arg);
++ if (options->lpk.sgroup)
++ options->lpk.fgroup = ldap_parse_groups(options->lpk.sgroup);
++ memset(arg,0,strlen(arg));
++ break;
++ case sLdapFilter:
++ arg = cp;
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing filter",filename, linenum);
++ arg[strlen(arg)] = '\0';
++ options->lpk.filter = xstrdup(arg);
++ memset(arg,0,strlen(arg));
++ break;
++ case sForceTLS:
++ intptr = &options->lpk.tls;
++ arg = strdelim(&cp);
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing yes/no argument.",
++ filename, linenum);
++ value = 0; /* silence compiler */
++ if (strcmp(arg, "yes") == 0)
++ value = 1;
++ else if (strcmp(arg, "no") == 0)
++ value = 0;
++ else if (strcmp(arg, "try") == 0)
++ value = -1;
++ else
++ fatal("%s line %d: Bad yes/no argument: %s",
++ filename, linenum, arg);
++ if (*intptr == -1)
++ *intptr = value;
++ break;
++ case sBindTimeout:
++ intptr = (int *) &options->lpk.b_timeout.tv_sec;
++ goto parse_int;
++ case sSearchTimeout:
++ intptr = (int *) &options->lpk.s_timeout.tv_sec;
++ goto parse_int;
++ break;
++ case sLdapConf:
++ arg = cp;
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing LpkLdapConf", filename, linenum);
++ arg[strlen(arg)] = '\0';
++ options->lpk.l_conf = xstrdup(arg);
++ memset(arg, 0, strlen(arg));
++ break;
++#endif
+
+ default:
+ fatal("%s line %d: Missing handler for opcode %s (%d)",
+diff --git a/servconf.h b/servconf.h
+index 860009f..fd113c2 100644
+--- a/servconf.h
++++ b/servconf.h
+@@ -16,6 +16,10 @@
+ #ifndef SERVCONF_H
+ #define SERVCONF_H
+
++#ifdef WITH_LDAP_PUBKEY
++#include "ldapauth.h"
++#endif
++
+ #define MAX_PORTS 256 /* Max # ports. */
+
+ #define MAX_ALLOW_USERS 256 /* Max # users on allow list. */
+@@ -150,6 +154,9 @@ typedef struct {
+ int use_pam; /* Enable auth via PAM */
+
+ int permit_tun;
++#ifdef WITH_LDAP_PUBKEY
++ ldap_opt_t lpk;
++#endif
+
+ int num_permitted_opens;
+
+diff --git a/sshd.c b/sshd.c
+index bc0d275..e82e102 100644
+--- a/sshd.c
++++ b/sshd.c
+@@ -127,6 +127,10 @@ int allow_severity;
+ int deny_severity;
+ #endif /* LIBWRAP */
+
++#ifdef WITH_LDAP_PUBKEY
++#include "ldapauth.h"
++#endif
++
+ #ifndef O_NOCTTY
+ #define O_NOCTTY 0
+ #endif
+@@ -1530,6 +1534,16 @@ main(int ac, char **av)
+ exit(1);
+ }
+
++#ifdef WITH_LDAP_PUBKEY
++ /* ldap_options_print(&options.lpk); */
++ /* XXX initialize/check ldap connection and set *LD */
++ if (options.lpk.on) {
++ if (options.lpk.l_conf && (ldap_parse_lconf(&options.lpk) < 0) )
++ error("[LDAP] could not parse %s", options.lpk.l_conf);
++ if (ldap_connect(&options.lpk) < 0)
++ error("[LDAP] could not initialize ldap connection");
++ }
++#endif
+ debug("sshd version %.100s", SSH_RELEASE);
+
+ /* Store privilege separation user for later use if required. */
+diff --git a/sshd_config b/sshd_config
+index 72fbae3..381b390 100644
+--- a/sshd_config
++++ b/sshd_config
+@@ -107,6 +107,21 @@
+ # no default banner path
+ #Banner none
+
++# here are the new patched ldap related tokens
++# entries in your LDAP must have posixAccount & ldapPublicKey objectclass
++#UseLPK yes
++#LpkLdapConf /etc/ldap.conf
++#LpkServers ldap://10.1.7.1/ ldap://10.1.7.2/
++#LpkUserDN ou=users,dc=phear,dc=org
++#LpkGroupDN ou=groups,dc=phear,dc=org
++#LpkBindDN cn=Manager,dc=phear,dc=org
++#LpkBindPw secret
++#LpkServerGroup mail
++#LpkFilter (hostAccess=master.phear.org)
++#LpkForceTLS no
++#LpkSearchTimelimit 3
++#LpkBindTimelimit 3
++
+ # override default of no subsystems
+ Subsystem sftp /usr/libexec/sftp-server
+
+diff --git a/sshd_config.5 b/sshd_config.5
+index 2f54102..cb86374 100644
+--- a/sshd_config.5
++++ b/sshd_config.5
+@@ -1043,6 +1043,62 @@ Specifies the full pathname of the
+ program.
+ The default is
+ .Pa /usr/X11R6/bin/xauth .
++.It Cm UseLPK
++Specifies whether LDAP public key retrieval must be used or not. It allow
++an easy centralisation of public keys within an LDAP directory. The argument must be
++.Dq yes
++or
++.Dq no .
++.It Cm LpkLdapConf
++Specifies whether LDAP Public keys should parse the specified ldap.conf file
++instead of sshd_config Tokens. The argument must be a valid path to an ldap.conf
++file like
++.Pa /etc/ldap.conf
++.It Cm LpkServers
++Specifies LDAP one or more [:space:] separated server's url the following form may be used:
++.Pp
++LpkServers ldaps://127.0.0.1 ldap://127.0.0.2 ldap://127.0.0.3
++.It Cm LpkUserDN
++Specifies the LDAP user DN.
++.Pp
++LpkUserDN ou=users,dc=phear,dc=org
++.It Cm LpkGroupDN
++Specifies the LDAP groups DN.
++.Pp
++LpkGroupDN ou=groups,dc=phear,dc=org
++.It Cm LpkBindDN
++Specifies the LDAP bind DN to use if necessary.
++.Pp
++LpkBindDN cn=Manager,dc=phear,dc=org
++.It Cm LpkBindPw
++Specifies the LDAP bind credential.
++.Pp
++LpkBindPw secret
++.It Cm LpkServerGroup
++Specifies one or more [:space:] separated group the server is part of.
++.Pp
++LpkServerGroup unix mail prod
++.It Cm LpkFilter
++Specifies an additional LDAP filter to use for finding SSH keys
++.Pp
++LpkFilter (hostAccess=master.phear.org)
++.It Cm LpkForceTLS
++Specifies if the LDAP server connection must be tried, forced or not used. The argument must be
++.Dq yes
++or
++.Dq no
++or
++.Dq try .
++.It Cm LpkSearchTimelimit
++Sepcifies the search time limit before the search is considered over. value is
++in seconds.
++.Pp
++LpkSearchTimelimit 3
++.It Cm LpkBindTimelimit
++Sepcifies the bind time limit before the connection is considered dead. value is
++in seconds.
++.Pp
++LpkBindTimelimit 3
+ .El
+ .Sh TIME FORMATS
+ .Xr sshd 8
+--
+1.7.0
+
Modified: csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/CSWosshlpk.prototype
===================================================================
--- csw/mgar/pkg/openssh/trunk/files/CSWosshlpk.prototype 2010-04-20 15:47:18 UTC (rev 9732)
+++ csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/CSWosshlpk.prototype 2010-04-21 12:02:40 UTC (rev 9735)
@@ -6,7 +6,6 @@
f none /opt/csw/libexec/sftp-server 0755 root bin
f none /opt/csw/sbin/sshd 0755 root bin
f none /opt/csw/sbin/sshd.smf_wrapper 0755 root bin
-f none /opt/csw/share/Ssh.bin 0644 root bin
d none /opt/csw/share/doc/openssh_lpk 0755 root bin
f none /opt/csw/share/doc/openssh_lpk/changelog.CSW 0644 root bin
f none /opt/csw/share/doc/openssh_lpk/CREDITS 0644 root bin
@@ -20,7 +19,6 @@
f none /opt/csw/share/doc/openssh_lpk/README.dns 0644 root bin
f none /opt/csw/share/doc/openssh_lpk/README.platform 0644 root bin
f none /opt/csw/share/doc/openssh_lpk/README.privsep 0644 root bin
-f none /opt/csw/share/doc/openssh_lpk/README.smartcard 0644 root bin
f none /opt/csw/share/doc/openssh_lpk/README.tun 0644 root bin
f none /opt/csw/share/doc/openssh_lpk/TODO 0644 root bin
f none /opt/csw/share/doc/openssh_lpk/WARNING.RNG 0644 root bin
@@ -32,5 +30,8 @@
f none /opt/csw/share/man/man8/sftp-server.8 0644 root bin
f none /opt/csw/share/man/man8/sshd.8 0644 root bin
d none /opt/csw/share/openssh 0755 root bin
+d none /opt/csw/share/checkpkg 0755 root bin
+d none /opt/csw/share/checkpkg/overrides 0755 root bin
+f none /opt/csw/share/checkpkg/overrides/openssh_lpk 0644 root bin
d none /var/empty
f none /var/opt/csw/svc/manifest/network/cswopenssh.xml 0644 root sys
Deleted: csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/contrib-openssh-lpk-5.2p1-0.3.9.patch
===================================================================
--- csw/mgar/pkg/openssh/trunk/files/contrib-openssh-lpk-5.2p1-0.3.9.patch 2010-04-20 15:47:18 UTC (rev 9732)
+++ csw/mgar/pkg/openssh/branches/openssh-5.4p1+lpk/files/contrib-openssh-lpk-5.2p1-0.3.9.patch 2010-04-21 12:02:40 UTC (rev 9735)
@@ -1,1884 +0,0 @@
-diff -Nuar --exclude '*.rej' --exclude '*.orig' openssh-5.2p1.orig/Makefile.in openssh-5.2p1+lpk/Makefile.in
---- openssh-5.2p1.orig/Makefile.in 2008-11-05 06:20:46.000000000 +0100
-+++ openssh-5.2p1+lpk/Makefile.in 2009-03-22 15:59:08.607515800 +0100
-@@ -86,7 +86,7 @@
- auth-krb5.o \
- auth2-gss.o gss-serv.o gss-serv-krb5.o \
- loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
-- audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o
-+ audit.o audit-bsm.o platform.o ldapauth.o sftp-server.o sftp-common.o
-
- MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out sshd_config.5.out ssh_config.5.out
- MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 sshd_config.5 ssh_config.5
-diff -Nuar --exclude '*.rej' --exclude '*.orig' openssh-5.2p1.orig/README.lpk openssh-5.2p1+lpk/README.lpk
---- openssh-5.2p1.orig/README.lpk 1970-01-01 01:00:00.000000000 +0100
-+++ openssh-5.2p1+lpk/README.lpk 2009-03-22 15:59:08.672813997 +0100
-@@ -0,0 +1,267 @@
-+OpenSSH LDAP PUBLIC KEY PATCH
-+Copyright (c) 2003 Eric AUGE (eau at 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\xB8 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.
-+
-+\xAD 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 at phear.org>
-+ - Andrea Barisani <andrea at inversepath.com>
-diff -Nuar --exclude '*.rej' --exclude '*.orig' openssh-5.2p1.orig/auth-rsa.c openssh-5.2p1+lpk/auth-rsa.c
---- openssh-5.2p1.orig/auth-rsa.c 2008-07-02 14:37:30.000000000 +0200
-+++ openssh-5.2p1+lpk/auth-rsa.c 2009-03-22 15:59:08.132715250 +0100
-@@ -174,10 +174,96 @@
- FILE *f;
- u_long linenum = 0;
- Key *key;
-+#ifdef WITH_LDAP_PUBKEY
-+ ldap_key_t * k;
-+ unsigned int i = 0;
-+#endif
-
- /* Temporarily use the user's uid. */
- temporarily_use_uid(pw);
-
-+#ifdef WITH_LDAP_PUBKEY
-+ /* here is the job */
-+ key = key_new(KEY_RSA1);
-+
-+ if (options.lpk.on) {
-+ debug("[LDAP] trying LDAP first uid=%s", pw->pw_name);
-+ if ( ldap_ismember(&options.lpk, pw->pw_name) > 0) {
-+ if ( (k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) {
-+ for (i = 0 ; i < k->num ; i++) {
-+ char *cp, *options = NULL;
-+
-+ for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
-+ ;
-+ if (!*cp || *cp == '\n' || *cp == '#')
-+ continue;
-+
-+ /*
-+ * Check if there are options for this key, and if so,
-+ * save their starting address and skip the option part
-+ * for now. If there are no options, set the starting
-+ * address to NULL.
-+ */
-+ if (*cp < '0' || *cp > '9') {
-+ int quoted = 0;
-+ options = cp;
-+ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
-+ if (*cp == '\\' && cp[1] == '"')
-+ cp++; /* Skip both */
-+ else if (*cp == '"')
-+ quoted = !quoted;
-+ }
-+ } else
-+ options = NULL;
-+
-+ /* Parse the key from the line. */
-+ if (hostfile_read_key(&cp, &bits, key) == 0) {
-+ debug("[LDAP] line %d: non ssh1 key syntax", i);
-+ continue;
-+ }
-+ /* cp now points to the comment part. */
-+
-+ /* Check if the we have found the desired key (identified by its modulus). */
-+ if (BN_cmp(key->rsa->n, client_n) != 0)
-+ continue;
-+
-+ /* check the real bits */
-+ if (bits != (unsigned int)BN_num_bits(key->rsa->n))
-+ logit("[LDAP] Warning: ldap, line %lu: keysize mismatch: "
-+ "actual %d vs. announced %d.", (unsigned long)i, BN_num_bits(key->rsa->n), bits);
-+
-+ /* We have found the desired key. */
-+ /*
-+ * If our options do not allow this key to be used,
-+ * do not send challenge.
-+ */
-+ if (!auth_parse_options(pw, options, "[LDAP]", (unsigned long) i))
-+ continue;
-+
-+ /* break out, this key is allowed */
-+ allowed = 1;
-+
-+ /* add the return stuff etc... */
-+ /* Restore the privileged uid. */
-+ restore_uid();
-+
-+ /* return key if allowed */
-+ if (allowed && rkey != NULL)
-+ *rkey = key;
-+ else
-+ key_free(key);
-+
-+ ldap_keys_free(k);
-+ return (allowed);
-+ }
-+ } else {
-+ logit("[LDAP] no keys found for '%s'!", pw->pw_name);
-+ }
-+ } else {
-+ logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup);
-+ }
-+ }
-+#endif
- /* The authorized keys. */
- file = authorized_keys_file(pw);
- debug("trying public RSA key file %s", file);
-diff -Nuar --exclude '*.rej' --exclude '*.orig' openssh-5.2p1.orig/auth2-pubkey.c openssh-5.2p1+lpk/auth2-pubkey.c
---- openssh-5.2p1.orig/auth2-pubkey.c 2008-07-04 04:54:25.000000000 +0200
-+++ openssh-5.2p1+lpk/auth2-pubkey.c 2009-03-22 15:59:08.102307504 +0100
-@@ -55,6 +55,10 @@
- #include "monitor_wrap.h"
- #include "misc.h"
-
-+#ifdef WITH_LDAP_PUBKEY
-+#include "ldapauth.h"
-+#endif
-+
- /* import */
- extern ServerOptions options;
- extern u_char *session_id2;
-@@ -187,10 +191,79 @@
- u_long linenum = 0;
- Key *found;
- char *fp;
-+#ifdef WITH_LDAP_PUBKEY
-+ ldap_key_t * k;
-+ unsigned int i = 0;
-+#endif
-
- /* Temporarily use the user's uid. */
- temporarily_use_uid(pw);
-
-+#ifdef WITH_LDAP_PUBKEY
-+ found_key = 0;
-+ /* allocate a new key type */
-+ found = key_new(key->type);
-+
-+ /* first check if the options is enabled, then try.. */
-+ if (options.lpk.on) {
-+ debug("[LDAP] trying LDAP first uid=%s",pw->pw_name);
-+ if (ldap_ismember(&options.lpk, pw->pw_name) > 0) {
-+ if ((k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) {
-+ /* Skip leading whitespace, empty and comment lines. */
-+ for (i = 0 ; i < k->num ; i++) {
-+ /* dont forget if multiple keys to reset options */
-+ char *cp, *options = NULL;
-+
-+ for (cp = (char *)k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
-+ ;
-+ if (!*cp || *cp == '\n' || *cp == '#')
-+ continue;
-+
-+ if (key_read(found, &cp) != 1) {
-+ /* no key? check if there are options for this key */
-+ int quoted = 0;
-+ debug2("[LDAP] user_key_allowed: check options: '%s'", cp);
-+ options = cp;
-+ for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
-+ if (*cp == '\\' && cp[1] == '"')
-+ cp++; /* Skip both */
-+ else if (*cp == '"')
-+ quoted = !quoted;
-+ }
-+ /* Skip remaining whitespace. */
-+ for (; *cp == ' ' || *cp == '\t'; cp++)
-+ ;
-+ if (key_read(found, &cp) != 1) {
-+ debug2("[LDAP] user_key_allowed: advance: '%s'", cp);
-+ /* still no key? advance to next line*/
-+ continue;
-+ }
-+ }
-+
-+ if (key_equal(found, key) &&
-+ auth_parse_options(pw, options, file, linenum) == 1) {
-+ found_key = 1;
-+ debug("[LDAP] matching key found");
-+ fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
-+ verbose("[LDAP] Found matching %s key: %s", key_type(found), fp);
-+
-+ /* restoring memory */
-+ ldap_keys_free(k);
-+ xfree(fp);
-+ restore_uid();
-+ key_free(found);
-+ return found_key;
-+ break;
-+ }
-+ }/* end of LDAP for() */
-+ } else {
-+ logit("[LDAP] no keys found for '%s'!", pw->pw_name);
-+ }
-+ } else {
-+ logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup);
-+ }
-+ }
-+#endif
- debug("trying public key file %s", file);
- f = auth_openkeyfile(file, pw, options.strict_modes);
-
-diff -Nuar --exclude '*.rej' --exclude '*.orig' openssh-5.2p1.orig/config.h.in openssh-5.2p1+lpk/config.h.in
---- openssh-5.2p1.orig/config.h.in 2009-02-23 01:18:12.000000000 +0100
-+++ openssh-5.2p1+lpk/config.h.in 2009-03-22 15:59:08.195639244 +0100
-@@ -563,6 +563,9 @@
- /* Define to 1 if you have the <linux/if_tun.h> header file. */
- #undef HAVE_LINUX_IF_TUN_H
-
-+/* Define if you want LDAP support */
-+#undef WITH_LDAP_PUBKEY
-+
- /* Define if your libraries define login() */
- #undef HAVE_LOGIN
-
-diff -Nuar --exclude '*.rej' --exclude '*.orig' openssh-5.2p1.orig/configure openssh-5.2p1+lpk/configure
---- openssh-5.2p1.orig/configure 2009-02-23 01:18:14.000000000 +0100
-+++ openssh-5.2p1+lpk/configure 2009-03-22 15:59:08.400328912 +0100
-@@ -1340,6 +1340,7 @@
- --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH)
- --with-libedit[=PATH] Enable libedit support for sftp
- --with-audit=module Enable EXPERIMENTAL audit support (modules=debug,bsm)
-+ --with-ldap[=PATH] Enable LDAP pubkey support (optionally in PATH)
- --with-ssl-dir=PATH Specify path to OpenSSL installation
- --without-openssl-header-check Disable OpenSSL version consistency check
- --with-ssl-engine Enable OpenSSL (hardware) ENGINE support
-@@ -12767,6 +12768,85 @@
- fi
-
-
-+# Check whether user wants LDAP support
-+LDAP_MSG="no"
-+
-+# Check whether --with-ldap was given.
-+if test "${with_ldap+set}" = set; then
-+ withval=$with_ldap;
-+ if test "x$withval" != "xno" ; then
-+
-+ if test "x$withval" != "xyes" ; then
-+ CPPFLAGS="$CPPFLAGS -I${withval}/include"
-+ LDFLAGS="$LDFLAGS -L${withval}/lib"
-+ fi
-+
-+
-+cat >>confdefs.h <<\_ACEOF
-+#define WITH_LDAP_PUBKEY 1
-+_ACEOF
-+
-+ LIBS="-lldap $LIBS"
-+ LDAP_MSG="yes"
-+
-+ { echo "$as_me:$LINENO: checking for LDAP support" >&5
-+echo $ECHO_N "checking for LDAP support... $ECHO_C" >&6; }
-+ cat >conftest.$ac_ext <<_ACEOF
-+/* confdefs.h. */
-+_ACEOF
-+cat confdefs.h >>conftest.$ac_ext
-+cat >>conftest.$ac_ext <<_ACEOF
-+/* end confdefs.h. */
-+#include <sys/types.h>
-+ #include <ldap.h>
-+int
-+main ()
-+{
-+(void)ldap_init(0, 0);
-+ ;
-+ return 0;
-+}
-+_ACEOF
-+rm -f conftest.$ac_objext
-+if { (ac_try="$ac_compile"
-+case "(($ac_try" in
-+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-+ *) ac_try_echo=$ac_try;;
-+esac
-+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-+ (eval "$ac_compile") 2>conftest.er1
-+ ac_status=$?
-+ grep -v '^ *+' conftest.er1 >conftest.err
-+ rm -f conftest.er1
-+ cat conftest.err >&5
-+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
-+ (exit $ac_status); } && {
-+ test -z "$ac_c_werror_flag" ||
-+ test ! -s conftest.err
-+ } && test -s conftest.$ac_objext; then
-+ { echo "$as_me:$LINENO: result: yes" >&5
-+echo "${ECHO_T}yes" >&6; }
-+else
-+ echo "$as_me: failed program was:" >&5
-+sed 's/^/| /' conftest.$ac_ext >&5
-+
-+
-+ { echo "$as_me:$LINENO: result: no" >&5
-+echo "${ECHO_T}no" >&6; }
-+ { { echo "$as_me:$LINENO: error: ** Incomplete or missing ldap libraries **" >&5
-+echo "$as_me: error: ** Incomplete or missing ldap libraries **" >&2;}
-+ { (exit 1); exit 1; }; }
-+
-+
-+fi
-+
-+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-+ fi
-+
-+
-+fi
-+
-+
-
-
-
-@@ -30543,6 +30623,7 @@
- echo " Smartcard support: $SCARD_MSG"
- echo " S/KEY support: $SKEY_MSG"
- echo " TCP Wrappers support: $TCPW_MSG"
-+echo " LDAP support: $LDAP_MSG"
- echo " MD5 password support: $MD5_MSG"
- echo " libedit support: $LIBEDIT_MSG"
- echo " Solaris process contract support: $SPC_MSG"
-diff -Nuar --exclude '*.rej' --exclude '*.orig' openssh-5.2p1.orig/configure.ac openssh-5.2p1+lpk/configure.ac
---- openssh-5.2p1.orig/configure.ac 2009-02-16 05:37:03.000000000 +0100
-+++ openssh-5.2p1+lpk/configure.ac 2009-03-22 15:59:08.490709251 +0100
-@@ -1314,6 +1314,37 @@
- esac ]
- )
-
-+# Check whether user wants LDAP support
-+LDAP_MSG="no"
-+AC_ARG_WITH(ldap,
-+ [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)],
-+ [
-+ if test "x$withval" != "xno" ; then
-+
-+ if test "x$withval" != "xyes" ; then
-+ CPPFLAGS="$CPPFLAGS -I${withval}/include"
-+ LDFLAGS="$LDFLAGS -L${withval}/lib"
-+ fi
-+
-+ AC_DEFINE([WITH_LDAP_PUBKEY], 1, [Enable LDAP pubkey support])
-+ LIBS="-lldap $LIBS"
-+ LDAP_MSG="yes"
-+
-+ AC_MSG_CHECKING([for LDAP support])
-+ AC_TRY_COMPILE(
-+ [#include <sys/types.h>
-+ #include <ldap.h>],
-+ [(void)ldap_init(0, 0);],
-+ [AC_MSG_RESULT(yes)],
-+ [
-+ AC_MSG_RESULT(no)
-+ AC_MSG_ERROR([** Incomplete or missing ldap libraries **])
-+ ]
-+ )
-+ fi
-+ ]
-+)
-+
- dnl Checks for library functions. Please keep in alphabetical order
- AC_CHECK_FUNCS( \
- arc4random \
-@@ -4163,6 +4194,7 @@
- echo " Smartcard support: $SCARD_MSG"
- echo " S/KEY support: $SKEY_MSG"
- echo " TCP Wrappers support: $TCPW_MSG"
-+echo " LDAP support: $LDAP_MSG"
- echo " MD5 password support: $MD5_MSG"
- echo " libedit support: $LIBEDIT_MSG"
- echo " Solaris process contract support: $SPC_MSG"
-diff -Nuar --exclude '*.rej' --exclude '*.orig' openssh-5.2p1.orig/ldapauth.c openssh-5.2p1+lpk/ldapauth.c
---- openssh-5.2p1.orig/ldapauth.c 1970-01-01 01:00:00.000000000 +0100
-+++ openssh-5.2p1+lpk/ldapauth.c 2009-03-22 15:59:08.528655666 +0100
-@@ -0,0 +1,575 @@
-+/*
-+ * $Id: openssh-lpk-4.3p1-0.3.7.patch,v 1.3 2006/04/18 15:29:09 eau Exp $
-+ */
-+
-+/*
-+ *
-+ * Copyright (c) 2005, Eric AUGE <eau at 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:
-+ *
-+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-+ * 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.
-+ * Neither the name of the phear.org nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
-+ *
-+ *
-+ */
-+
-+#include "includes.h"
-+
-+#ifdef WITH_LDAP_PUBKEY
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <string.h>
-+
-+#include "ldapauth.h"
-+#include "log.h"
-+
-+static char *attrs[] = {
-+ PUBKEYATTR,
-+ NULL
-+};
-+
-+/* filter building infos */
-+#define FILTER_GROUP_PREFIX "(&(objectclass=posixGroup)"
-+#define FILTER_OR_PREFIX "(|"
-+#define FILTER_OR_SUFFIX ")"
-+#define FILTER_CN_PREFIX "(cn="
-+#define FILTER_CN_SUFFIX ")"
-+#define FILTER_UID_FORMAT "(memberUid=%s)"
-+#define FILTER_GROUP_SUFFIX ")"
-+#define FILTER_GROUP_SIZE(group) (size_t) (strlen(group)+(ldap_count_group(group)*5)+52)
-+
-+/* just filter building stuff */
-+#define REQUEST_GROUP_SIZE(filter, uid) (size_t) (strlen(filter)+strlen(uid)+1)
-+#define REQUEST_GROUP(buffer, prefilter, pwname) \
-+ buffer = (char *) calloc(REQUEST_GROUP_SIZE(prefilter, pwname), sizeof(char)); \
-+ if (!buffer) { \
-+ perror("calloc()"); \
-+ return FAILURE; \
-+ } \
-+ snprintf(buffer, REQUEST_GROUP_SIZE(prefilter,pwname), prefilter, pwname)
-+/*
-+XXX OLD group building macros
-+#define REQUEST_GROUP_SIZE(grp, uid) (size_t) (strlen(grp)+strlen(uid)+46)
-+#define REQUEST_GROUP(buffer,pwname,grp) \
-+ buffer = (char *) calloc(REQUEST_GROUP_SIZE(grp, pwname), sizeof(char)); \
-+ if (!buffer) { \
-+ perror("calloc()"); \
-+ return FAILURE; \
-+ } \
-+ snprintf(buffer,REQUEST_GROUP_SIZE(grp,pwname),"(&(objectclass=posixGroup)(cn=%s)(memberUid=%s))",grp,pwname)
-+ */
-+
-+/*
-+XXX stock upstream version without extra filter support
-+#define REQUEST_USER_SIZE(uid) (size_t) (strlen(uid)+64)
-+#define REQUEST_USER(buffer, pwname) \
-+ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname), sizeof(char)); \
-+ if (!buffer) { \
-+ perror("calloc()"); \
-+ return NULL; \
-+ } \
-+ snprintf(buffer,REQUEST_USER_SIZE(pwname),"(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s))",pwname)
-+ */
-+
-+#define REQUEST_USER_SIZE(uid, filter) (size_t) (strlen(uid)+64+(filter != NULL ? strlen(filter) : 0))
-+#define REQUEST_USER(buffer, pwname, customfilter) \
-+ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname, customfilter), sizeof(char)); \
-+ if (!buffer) { \
-+ perror("calloc()"); \
-+ return NULL; \
-+ } \
-+ snprintf(buffer, REQUEST_USER_SIZE(pwname, customfilter), \
-+ "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)", \
-+ pwname, (customfilter != NULL ? customfilter : ""))
-+
-+/* some portable and working tokenizer, lame though */
-+static int tokenize(char ** o, size_t size, char * input) {
-+ unsigned int i = 0, num;
-+ const char * charset = " \t";
-+ char * ptr = input;
-+
-+ /* leading white spaces are ignored */
-+ num = strspn(ptr, charset);
-+ ptr += num;
-+
-+ while ((num = strcspn(ptr, charset))) {
-+ if (i < size-1) {
-+ o[i++] = ptr;
-+ ptr += num;
-+ if (*ptr)
-+ *ptr++ = '\0';
-+ }
-+ }
-+ o[i] = NULL;
-+ return SUCCESS;
-+}
-+
-+void ldap_close(ldap_opt_t * ldap) {
-+
-+ if (!ldap)
-+ return;
-+
-+ if ( ldap_unbind_ext(ldap->ld, NULL, NULL) < 0)
-+ ldap_perror(ldap->ld, "ldap_unbind()");
-+
-+ ldap->ld = NULL;
-+ FLAG_SET_DISCONNECTED(ldap->flags);
-+
-+ return;
-+}
-+
-+/* init && bind */
-+int ldap_connect(ldap_opt_t * ldap) {
-+ int version = LDAP_VERSION3;
-+
-+ if (!ldap->servers)
-+ return FAILURE;
-+
-+ /* Connection Init and setup */
-+ ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
-+ if (!ldap->ld) {
-+ ldap_perror(ldap->ld, "ldap_init()");
-+ return FAILURE;
-+ }
-+
-+ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
-+ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_PROTOCOL_VERSION)");
-+ return FAILURE;
-+ }
-+
-+ /* Timeouts setup */
-+ if (ldap_set_option(ldap->ld, LDAP_OPT_NETWORK_TIMEOUT, &ldap->b_timeout) != LDAP_SUCCESS) {
-+ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT)");
-+ }
-+ if (ldap_set_option(ldap->ld, LDAP_OPT_TIMEOUT, &ldap->s_timeout) != LDAP_SUCCESS) {
-+ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_TIMEOUT)");
-+ }
-+
-+ /* TLS support */
-+ if ( (ldap->tls == -1) || (ldap->tls == 1) ) {
-+ if (ldap_start_tls_s(ldap->ld, NULL, NULL ) != LDAP_SUCCESS) {
-+ /* failed then reinit the initial connect */
-+ ldap_perror(ldap->ld, "ldap_connect: (TLS) ldap_start_tls()");
-+ if (ldap->tls == 1)
-+ return FAILURE;
-+
-+ ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
-+ if (!ldap->ld) {
-+ ldap_perror(ldap->ld, "ldap_init()");
-+ return FAILURE;
-+ }
-+
-+ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
-+ ldap_perror(ldap->ld, "ldap_set_option()");
-+ return FAILURE;
-+ }
-+ }
-+ }
-+
-+
-+ if ( ldap_simple_bind_s(ldap->ld, ldap->binddn, ldap->bindpw) != LDAP_SUCCESS) {
-+ ldap_perror(ldap->ld, "ldap_simple_bind_s()");
-+ return FAILURE;
-+ }
-+
-+ /* says it is connected */
-+ FLAG_SET_CONNECTED(ldap->flags);
-+
-+ return SUCCESS;
-+}
-+
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the devel
mailing list