--- /dev/null
+diff -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/Makefile.in openssh-4.0p1-lpk/Makefile.in
+--- openssh-4.0p1/Makefile.in 2005-02-26 00:12:38.000000000 +0100
++++ openssh-4.0p1-lpk/Makefile.in 2005-03-12 00:38:11.000000000 +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
++ audit.o audit-bsm.o ldapauth.o
+
+ MANPAGES = 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 = 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 -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/auth-rsa.c openssh-4.0p1-lpk/auth-rsa.c
+--- openssh-4.0p1/auth-rsa.c 2004-12-11 03:39:50.000000000 +0100
++++ openssh-4.0p1-lpk/auth-rsa.c 2005-03-12 00:34:31.000000000 +0100
+@@ -160,10 +160,96 @@
+ u_long linenum = 0;
+ struct stat st;
+ Key *key;
++#ifdef WITH_LDAP_PUBKEY
++ ldap_key_t * k;
++ 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;
++
++ for (cp = k->keys[i]; *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 != 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 -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/auth2-pubkey.c openssh-4.0p1-lpk/auth2-pubkey.c
+--- openssh-4.0p1/auth2-pubkey.c 2004-12-11 03:39:50.000000000 +0100
++++ openssh-4.0p1-lpk/auth2-pubkey.c 2005-03-12 00:34:31.000000000 +0100
+@@ -43,6 +43,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;
+@@ -176,10 +180,77 @@
+ struct stat st;
+ Key *found;
+ char *fp;
++#ifdef WITH_LDAP_PUBKEY
++ ldap_key_t * k;
++ 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) {
++ char *cp, *options = NULL;
++ /* Skip leading whitespace, empty and comment lines. */
++ for (i = 0 ; i < k->num ; i++) {
++ for (cp = (char *)k->keys[i]; *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);
+
+ /* Fail quietly if file does not exist */
+diff -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/ldapauth.c openssh-4.0p1-lpk/ldapauth.c
+--- openssh-4.0p1/ldapauth.c 1970-01-01 01:00:00.000000000 +0100
++++ openssh-4.0p1-lpk/ldapauth.c 2005-03-12 00:34:31.000000000 +0100
+@@ -0,0 +1,290 @@
++/*
++ *
++ * Copyright (c) 2005, Eric AUGE <eau@phear.org>
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
++ *
++ * 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 <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++
++
++#include "ldapauth.h"
++
++static char *attrs[] = {
++ PUBKEYATTR,
++ NULL
++};
++
++/* just filter building stuff */
++#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)
++
++#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)
++
++/* some portable and working tokenizer, lame though */
++static int tokenize(char ** o, size_t size, char * input) {
++ unsigned int i = 0, num;
++ 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;
++}
++
++/* init && bind XXX TLS missing */
++int ldap_connect(ldap_opt_t * ldap) {
++ int version = LDAP_VERSION3;
++
++ if (!ldap->servers)
++ 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;
++ }
++
++ 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;
++}
++
++/* a bit dirty but leak free */
++char * ldap_parse_servers(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]) ) {
++ if (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) {
++ printf("ldap options:\n");
++ printf("servers: %s\n", ldap->servers);
++ printf("user basedn: %s\n", ldap->u_basedn);
++ printf("group basedn: %s\n", ldap->g_basedn);
++ printf("binddn: %s\n", ldap->binddn);
++ printf("bindpw: %s\n", ldap->bindpw);
++ printf("group: %s\n", ldap->sgroup);
++}
++
++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);
++ free(l);
++}
++
++/* free keys */
++void ldap_keys_free(ldap_key_t * k) {
++ ldap_value_free(k->keys);
++ free(k);
++ return;
++}
++
++ldap_key_t * ldap_getuserkey(ldap_opt_t *l, char * user) {
++ ldap_key_t * k = (ldap_key_t *) calloc (1, sizeof(ldap_key_t));
++ LDAPMessage *res, *e;
++ char * filter;
++ int i;
++
++ if (!k)
++ return NULL;
++
++ /* build filter for LDAP request */
++ REQUEST_USER(filter, user);
++
++ if ( ldap_search_s( l->ld,
++ l->u_basedn,
++ LDAP_SCOPE_SUBTREE,
++ filter,
++ attrs, 0, &res ) != LDAP_SUCCESS) {
++ ldap_perror(l->ld, "ldap_search_s()");
++
++ free(filter);
++ free(k);
++
++ 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)
++ printf("[LDAP] duplicate entries, using the FIRST entry returned\n");
++
++ e = ldap_first_entry(l->ld, res);
++ k->keys = ldap_get_values(l->ld, e, PUBKEYATTR);
++ k->num = ldap_count_values(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, char * user) {
++ LDAPMessage *res;
++ char * filter;
++
++ if ((!l->sgroup) || !(l->g_basedn))
++ return 1;
++
++ /* build filter for LDAP request */
++ REQUEST_GROUP(filter, user, l->sgroup);
++
++ if (ldap_search_s ( l->ld,
++ l->g_basedn,
++ LDAP_SCOPE_SUBTREE,
++ filter,
++ NULL, 0, &res) != LDAP_SUCCESS) {
++ ldap_perror(l->ld, "ldap_search_s()");
++
++ free(filter);
++ 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;
++}
+diff -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/ldapauth.h openssh-4.0p1-lpk/ldapauth.h
+--- openssh-4.0p1/ldapauth.h 1970-01-01 01:00:00.000000000 +0100
++++ openssh-4.0p1-lpk/ldapauth.h 2005-03-12 00:34:31.000000000 +0100
+@@ -0,0 +1,79 @@
++/*
++ *
++ * Copyright (c) 2005, Eric AUGE <eau@phear.org>
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
++ *
++ * 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
++
++#include <string.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"
++
++/* default options */
++#define _DEFAULT_LPK_ON 1
++#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
++
++/* defines */
++#define FAILURE -1
++#define SUCCESS 0
++#define PUBKEYATTR "sshPublicKey"
++
++/* 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 */
++} ldap_opt_t;
++
++typedef struct ldap_keys {
++ char ** keys; /* the public keys retrieved */
++ unsigned int num; /* number of keys */
++} ldap_key_t;
++
++
++/* function headers */
++int ldap_connect(ldap_opt_t *);
++char * ldap_parse_servers(char *);
++void ldap_options_print(ldap_opt_t *);
++void ldap_options_free(ldap_opt_t *);
++void ldap_keys_free(ldap_key_t *);
++ldap_key_t * ldap_getuserkey(ldap_opt_t *, char *);
++int ldap_ismember(ldap_opt_t *, char *);
++
++#endif
+diff -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/servconf.c openssh-4.0p1-lpk/servconf.c
+--- openssh-4.0p1/servconf.c 2005-03-01 11:24:33.000000000 +0100
++++ openssh-4.0p1-lpk/servconf.c 2005-03-12 00:34:31.000000000 +0100
+@@ -23,6 +23,10 @@
+ #include "kex.h"
+ #include "mac.h"
+
++#ifdef WITH_LDAP_PUBKEY
++#include "ldapauth.h"
++#endif
++
+ static void add_listen_addr(ServerOptions *, char *, u_short);
+ static void add_one_listen_addr(ServerOptions *, char *, u_short);
+
+@@ -101,7 +105,17 @@
+ options->authorized_keys_file = NULL;
+ options->authorized_keys_file2 = NULL;
+ options->num_accept_env = 0;
+-
++#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;
++#endif
+ /* Needs to be accessable in many places */
+ use_privsep = -1;
+ }
+@@ -229,7 +243,22 @@
+ }
+ if (options->authorized_keys_file == NULL)
+ options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
+-
++#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;
++#endif
+ /* Turn privilege separation on by default */
+ if (use_privsep == -1)
+ use_privsep = 1;
+@@ -273,6 +302,9 @@
+ sGssAuthentication, sGssCleanupCreds, sAcceptEnv,
+ sUsePrivilegeSeparation,
+ sDeprecated, sUnsupported
++#ifdef WITH_LDAP_PUBKEY
++ ,sLdapPublickey, sLdapServers, sLdapUserDN, sLdapGroupDN, sBindDN, sBindPw, sMyGroup
++#endif
+ } ServerOpCodes;
+
+ /* Textual representation of the tokens. */
+@@ -371,6 +403,15 @@
+ { "clientalivecountmax", sClientAliveCountMax },
+ { "authorizedkeysfile", sAuthorizedKeysFile },
+ { "authorizedkeysfile2", sAuthorizedKeysFile2 },
++#ifdef WITH_LDAP_PUBKEY
++ { _DEFAULT_LPK_TOKEN, sLdapPublickey },
++ { _DEFAULT_SRV_TOKEN, sLdapServers },
++ { _DEFAULT_USR_TOKEN, sLdapUserDN },
++ { _DEFAULT_GRP_TOKEN, sLdapGroupDN },
++ { _DEFAULT_BDN_TOKEN, sBindDN },
++ { _DEFAULT_BPW_TOKEN, sBindPw },
++ { _DEFAULT_MYG_TOKEN, sMyGroup },
++#endif
+ { "useprivilegeseparation", sUsePrivilegeSeparation},
+ { "acceptenv", sAcceptEnv },
+ { NULL, sBadOption }
+@@ -949,6 +990,77 @@
+ 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 = 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';
++ options->lpk.u_basedn = xstrdup(arg);
++ memset(arg,0,strlen(arg));
++ break;
++ case sLdapGroupDN:
++ /* 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';
++ options->lpk.g_basedn = xstrdup(arg);
++ memset(arg,0,strlen(arg));
++ break;
++ case sBindDN:
++ /* arg = strdelim(&cp); */
++ p = line;
++ while(*p++);
++ arg = p;
++ 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 = strdelim(&cp); */
++ p = line;
++ while(*p++);
++ arg = p;
++ 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:
++ p = line;
++ while (*p++);
++ arg = p;
++ if (!arg || *arg == '\0')
++ fatal("%s line %d: missing groupname",filename, linenum);
++ arg[strlen(arg)] = '\0';
++ options->lpk.sgroup = xstrdup(arg);
++ memset(arg,0,strlen(arg));
++ break;
++#endif
+
+ default:
+ fatal("%s line %d: Missing handler for opcode %s (%d)",
+diff -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/servconf.h openssh-4.0p1-lpk/servconf.h
+--- openssh-4.0p1/servconf.h 2005-01-20 00:57:56.000000000 +0100
++++ openssh-4.0p1-lpk/servconf.h 2005-03-12 00:34:31.000000000 +0100
+@@ -18,6 +18,10 @@
+
+ #include "buffer.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. */
+@@ -134,6 +138,9 @@
+ char *authorized_keys_file; /* File containing public keys */
+ char *authorized_keys_file2;
+ int use_pam; /* Enable auth via PAM */
++#ifdef WITH_LDAP_PUBKEY
++ ldap_opt_t lpk;
++#endif
+ } ServerOptions;
+
+ void initialize_server_options(ServerOptions *);
+diff -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/sshd.c openssh-4.0p1-lpk/sshd.c
+--- openssh-4.0p1/sshd.c 2005-03-06 12:38:52.000000000 +0100
++++ openssh-4.0p1-lpk/sshd.c 2005-03-12 00:37:33.000000000 +0100
+@@ -93,6 +93,10 @@
+ int deny_severity = LOG_WARNING;
+ #endif /* LIBWRAP */
+
++#ifdef WITH_LDAP_PUBKEY
++#include "ldapauth.h"
++#endif
++
+ #ifndef O_NOCTTY
+ #define O_NOCTTY 0
+ #endif
+@@ -1076,6 +1080,13 @@
+ exit(1);
+ }
+
++#ifdef WITH_LDAP_PUBKEY
++ ldap_options_print(&options.lpk);
++ /* XXX initialize/check ldap connection and set *LD */
++ if (options.lpk.on && ldap_connect(&options.lpk) < 0) {
++ error("[LDAP] Could not initialize ldap connections");
++ }
++#endif
+ debug("sshd version %.100s", SSH_RELEASE);
+
+ /* load private host keys */
+diff -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/sshd_config openssh-4.0p1-lpk/sshd_config
+--- openssh-4.0p1/sshd_config 2005-01-20 00:57:56.000000000 +0100
++++ openssh-4.0p1-lpk/sshd_config 2005-03-12 00:34:31.000000000 +0100
+@@ -38,8 +38,8 @@
+ #StrictModes yes
+ #MaxAuthTries 6
+
+-#RSAAuthentication yes
+-#PubkeyAuthentication yes
++RSAAuthentication yes
++PubkeyAuthentication yes
+ #AuthorizedKeysFile .ssh/authorized_keys
+
+ # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+@@ -53,11 +53,11 @@
+ #IgnoreRhosts yes
+
+ # To disable tunneled clear text passwords, change to no here!
+-#PasswordAuthentication yes
+-#PermitEmptyPasswords no
++PasswordAuthentication yes
++PermitEmptyPasswords no
+
+ # Change to no to disable s/key passwords
+-#ChallengeResponseAuthentication yes
++ChallengeResponseAuthentication no
+
+ # Kerberos options
+ #KerberosAuthentication no
+@@ -88,9 +88,9 @@
+ #PrintLastLog yes
+ #TCPKeepAlive yes
+ #UseLogin no
+-#UsePrivilegeSeparation yes
++UsePrivilegeSeparation no
+ #PermitUserEnvironment no
+-#Compression yes
++Compression no
+ #ClientAliveInterval 0
+ #ClientAliveCountMax 3
+ #UseDNS yes
+@@ -99,6 +99,16 @@
+
+ # no default banner path
+ #Banner /some/path
++
++# here is the new patched ldap related tokens
++# entries in your LDAP must have posixAccount & ldapPublicKey objectclass
++UseLPK yes
++LpkServers ldap://127.0.0.4 ldap://127.0.0.3 ldap://127.0.0.1/
++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
+
+ # override default of no subsystems
+ Subsystem sftp /usr/libexec/sftp-server
+diff -Nru -x 'config.*' -x Makefile -x 'buildpkg.*' -x opensshd.init -x 'ssh_prng_*' openssh-4.0p1/sshd_config.5 openssh-4.0p1-lpk/sshd_config.5
+--- openssh-4.0p1/sshd_config.5 2005-03-01 11:24:34.000000000 +0100
++++ openssh-4.0p1-lpk/sshd_config.5 2005-03-12 00:34:31.000000000 +0100
+@@ -760,6 +760,32 @@
+ program.
+ The default is
+ .Pa /usr/X11R6/bin/xauth .
++.It Cm UseLPK
++Enable LDAP public key resolution. The argument must be
++.Dq yes
++or
++.Dq no .
++.It Cm LpkServers
++Specifies LDAP one or more [:space:] separated server's url the following form may be used:
++.Pp
++.Bl -item -offset indent -compact
++.It
++.Cm LpkServers
++.Sm off
++.Ar LpkServers ldaps://127.0.0.1 ldap://127.0.0.2 ldap://127.0.0.3
++.Sm on
++.It Cm LpkUserDN/LpkGroupDN
++.Sm off
++.Ar LpkUserDN ou=groups,dc=phear,dc=org
++.Sm on
++.El
++.Pp
++.It Cm LpkBindDN
++Specifies a LDAP bind DN to use when doing ldap lookups.
++.It Cm LpkBindPw
++Specifies a LDAP bind Password associated to the previous token.
++.It Cm LpkServerGroup
++Specifies the group is the host is part of.
+ .El
+ .Ss Time Formats
+ .Nm sshd