]> git.pld-linux.org Git - packages/openssh.git/blob - openssh-lpk.patch
6972dcb47951f9597e703713b2b0f56ed9b78e44
[packages/openssh.git] / openssh-lpk.patch
1 This is a forward-port of the OpenSSH LPK support patch.
2
3 It adds support for storing OpenSSH public keys in LDAP. It also supports
4 grouping of machines in the LDAP data to limit users to specific machines.
5
6 The latest homepage for the LPK project is:
7 http://code.google.com/p/openssh-lpk/
8
9 The 0.3.10 version of the patch includes a fix for 64-bit platforms, as
10 discovered by Gentoo, where the bind timeout and search timeout values were not
11 being parsed correctly: http://bugs.gentoo.org/210110
12
13 Forward-ported-from: openssh-lpk-5.1p1-0.3.9.patch
14 Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
15
16 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/auth2-pubkey.c openssh-5.1p1+lpk/auth2-pubkey.c
17 --- openssh-5.1p1.orig/auth2-pubkey.c   2008-07-03 19:54:25.000000000 -0700
18 +++ openssh-5.1p1+lpk/auth2-pubkey.c    2008-08-23 15:02:47.000000000 -0700
19 @@ -55,6 +55,10 @@
20  #include "monitor_wrap.h"
21  #include "misc.h"
22  
23 +#ifdef WITH_LDAP_PUBKEY
24 +#include "ldapauth.h"
25 +#endif
26 +
27  /* import */
28  extern ServerOptions options;
29  extern u_char *session_id2;
30 @@ -187,10 +191,79 @@
31         u_long linenum = 0;
32         Key *found;
33         char *fp;
34 +#ifdef WITH_LDAP_PUBKEY
35 +       ldap_key_t * k;
36 +       unsigned int i = 0;
37 +#endif
38  
39         /* Temporarily use the user's uid. */
40         temporarily_use_uid(pw);
41  
42 +#ifdef WITH_LDAP_PUBKEY
43 +       found_key = 0;
44 +       /* allocate a new key type */
45 +       found = key_new(key->type);
46
47 +       /* first check if the options is enabled, then try.. */
48 +       if (options.lpk.on) {
49 +           debug("[LDAP] trying LDAP first uid=%s",pw->pw_name);
50 +           if (ldap_ismember(&options.lpk, pw->pw_name) > 0) {
51 +               if ((k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) {
52 +                   /* Skip leading whitespace, empty and comment lines. */
53 +                   for (i = 0 ; i < k->num ; i++) {
54 +                       /* dont forget if multiple keys to reset options */
55 +                       char *cp, *options = NULL;
56 +
57 +                       for (cp = (char *)k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
58 +                           ;
59 +                       if (!*cp || *cp == '\n' || *cp == '#')
60 +                           continue;
61 +
62 +                       if (key_read(found, &cp) != 1) {
63 +                           /* no key?  check if there are options for this key */
64 +                           int quoted = 0;
65 +                           debug2("[LDAP] user_key_allowed: check options: '%s'", cp);
66 +                           options = cp;
67 +                           for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
68 +                               if (*cp == '\\' && cp[1] == '"')
69 +                                   cp++;       /* Skip both */
70 +                               else if (*cp == '"')
71 +                                   quoted = !quoted;
72 +                           }
73 +                           /* Skip remaining whitespace. */
74 +                           for (; *cp == ' ' || *cp == '\t'; cp++)
75 +                               ;
76 +                           if (key_read(found, &cp) != 1) {
77 +                               debug2("[LDAP] user_key_allowed: advance: '%s'", cp);
78 +                               /* still no key?  advance to next line*/
79 +                               continue;
80 +                           }
81 +                       }
82 +
83 +                       if (key_equal(found, key) &&
84 +                               auth_parse_options(pw, options, file, linenum) == 1) {
85 +                           found_key = 1;
86 +                           debug("[LDAP] matching key found");
87 +                           fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
88 +                           verbose("[LDAP] Found matching %s key: %s", key_type(found), fp);
89 +
90 +                           /* restoring memory */
91 +                           ldap_keys_free(k);
92 +                           xfree(fp);
93 +                           restore_uid();
94 +                           key_free(found);
95 +                           return found_key;
96 +                           break;
97 +                       }
98 +                   }/* end of LDAP for() */
99 +               } else {
100 +                   logit("[LDAP] no keys found for '%s'!", pw->pw_name);
101 +               }
102 +           } else {
103 +               logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup);
104 +           }
105 +       }
106 +#endif
107         debug("trying public key file %s", file);
108         f = auth_openkeyfile(file, pw, options.strict_modes);
109  
110 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/auth-rsa.c openssh-5.1p1+lpk/auth-rsa.c
111 --- openssh-5.1p1.orig/auth-rsa.c       2008-07-02 05:37:30.000000000 -0700
112 +++ openssh-5.1p1+lpk/auth-rsa.c        2008-08-23 15:02:47.000000000 -0700
113 @@ -174,10 +174,96 @@
114         FILE *f;
115         u_long linenum = 0;
116         Key *key;
117 +#ifdef WITH_LDAP_PUBKEY
118 +       ldap_key_t * k;
119 +       unsigned int i = 0;
120 +#endif
121  
122         /* Temporarily use the user's uid. */
123         temporarily_use_uid(pw);
124  
125 +#ifdef WITH_LDAP_PUBKEY
126 +       /* here is the job */
127 +       key = key_new(KEY_RSA1);
128 +
129 +       if (options.lpk.on) {
130 +           debug("[LDAP] trying LDAP first uid=%s", pw->pw_name);
131 +           if ( ldap_ismember(&options.lpk, pw->pw_name) > 0) {
132 +               if ( (k = ldap_getuserkey(&options.lpk, pw->pw_name)) != NULL) {
133 +                   for (i = 0 ; i < k->num ; i++) {
134 +                       char *cp, *options = NULL;
135 +
136 +                       for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
137 +                           ;
138 +                       if (!*cp || *cp == '\n' || *cp == '#')
139 +                           continue;
140 +
141 +                       /*
142 +                       * Check if there are options for this key, and if so,
143 +                       * save their starting address and skip the option part
144 +                       * for now.  If there are no options, set the starting
145 +                       * address to NULL.
146 +                        */
147 +                       if (*cp < '0' || *cp > '9') {
148 +                           int quoted = 0;
149 +                           options = cp;
150 +                           for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
151 +                               if (*cp == '\\' && cp[1] == '"')
152 +                                   cp++;       /* Skip both */
153 +                               else if (*cp == '"')
154 +                                   quoted = !quoted;
155 +                           }
156 +                       } else
157 +                           options = NULL;
158 +
159 +                       /* Parse the key from the line. */
160 +                       if (hostfile_read_key(&cp, &bits, key) == 0) {
161 +                           debug("[LDAP] line %d: non ssh1 key syntax", i);
162 +                           continue;
163 +                       }
164 +                       /* cp now points to the comment part. */
165 +
166 +                       /* Check if the we have found the desired key (identified by its modulus). */
167 +                       if (BN_cmp(key->rsa->n, client_n) != 0)
168 +                           continue;
169 +
170 +                       /* check the real bits  */
171 +                       if (bits != (unsigned int)BN_num_bits(key->rsa->n))
172 +                           logit("[LDAP] Warning: ldap, line %lu: keysize mismatch: "
173 +                                   "actual %d vs. announced %d.", (unsigned long)i, BN_num_bits(key->rsa->n), bits);
174 +
175 +                       /* We have found the desired key. */
176 +                       /*
177 +                       * If our options do not allow this key to be used,
178 +                       * do not send challenge.
179 +                        */
180 +                       if (!auth_parse_options(pw, options, "[LDAP]", (unsigned long) i))
181 +                           continue;
182 +
183 +                       /* break out, this key is allowed */
184 +                       allowed = 1;
185 +
186 +                       /* add the return stuff etc... */
187 +                       /* Restore the privileged uid. */
188 +                       restore_uid();
189 +
190 +                       /* return key if allowed */
191 +                       if (allowed && rkey != NULL)
192 +                           *rkey = key;
193 +                       else
194 +                           key_free(key);
195 +
196 +                       ldap_keys_free(k);
197 +                       return (allowed);
198 +                   }
199 +               } else {
200 +                   logit("[LDAP] no keys found for '%s'!", pw->pw_name);
201 +               }
202 +           } else {
203 +               logit("[LDAP] '%s' is not in '%s'", pw->pw_name, options.lpk.sgroup);
204 +           }
205 +       }
206 +#endif
207         /* The authorized keys. */
208         file = authorized_keys_file(pw);
209         debug("trying public RSA key file %s", file);
210 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/config.h.in openssh-5.1p1+lpk/config.h.in
211 --- openssh-5.1p1.orig/config.h.in      2008-07-21 01:30:49.000000000 -0700
212 +++ openssh-5.1p1+lpk/config.h.in       2008-08-23 15:02:47.000000000 -0700
213 @@ -560,6 +560,9 @@
214  /* Define to 1 if you have the <linux/if_tun.h> header file. */
215  #undef HAVE_LINUX_IF_TUN_H
216  
217 +/* Define if you want LDAP support */
218 +#undef WITH_LDAP_PUBKEY
219 +
220  /* Define if your libraries define login() */
221  #undef HAVE_LOGIN
222  
223 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/configure openssh-5.1p1+lpk/configure
224 --- openssh-5.1p1.orig/configure        2008-07-21 01:30:50.000000000 -0700
225 +++ openssh-5.1p1+lpk/configure 2008-08-23 15:02:47.000000000 -0700
226 @@ -1340,6 +1340,7 @@
227    --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH)
228    --with-libedit[=PATH]   Enable libedit support for sftp
229    --with-audit=module     Enable EXPERIMENTAL audit support (modules=debug,bsm)
230 +  --with-ldap[=PATH]      Enable LDAP pubkey support (optionally in PATH)
231    --with-ssl-dir=PATH     Specify path to OpenSSL installation
232    --without-openssl-header-check Disable OpenSSL version consistency check
233    --with-ssl-engine       Enable OpenSSL (hardware) ENGINE support
234 @@ -12568,6 +12569,85 @@
235  fi
236  
237  
238 +# Check whether user wants LDAP support
239 +LDAP_MSG="no"
240 +
241 +# Check whether --with-ldap was given.
242 +if test "${with_ldap+set}" = set; then
243 +  withval=$with_ldap;
244 +               if test "x$withval" != "xno" ; then
245 +
246 +                       if test "x$withval" != "xyes" ; then
247 +                               CPPFLAGS="$CPPFLAGS -I${withval}/include"
248 +                               LDFLAGS="$LDFLAGS -L${withval}/lib"
249 +                       fi
250 +
251 +
252 +cat >>confdefs.h <<\_ACEOF
253 +#define WITH_LDAP_PUBKEY 1
254 +_ACEOF
255 +
256 +                       LIBS="-lldap $LIBS"
257 +                       LDAP_MSG="yes"
258 +
259 +                       { echo "$as_me:$LINENO: checking for LDAP support" >&5
260 +echo $ECHO_N "checking for LDAP support... $ECHO_C" >&6; }
261 +                       cat >conftest.$ac_ext <<_ACEOF
262 +/* confdefs.h.  */
263 +_ACEOF
264 +cat confdefs.h >>conftest.$ac_ext
265 +cat >>conftest.$ac_ext <<_ACEOF
266 +/* end confdefs.h.  */
267 +#include <sys/types.h>
268 +                                #include <ldap.h>
269 +int
270 +main ()
271 +{
272 +(void)ldap_init(0, 0);
273 +  ;
274 +  return 0;
275 +}
276 +_ACEOF
277 +rm -f conftest.$ac_objext
278 +if { (ac_try="$ac_compile"
279 +case "(($ac_try" in
280 +  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
281 +  *) ac_try_echo=$ac_try;;
282 +esac
283 +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
284 +  (eval "$ac_compile") 2>conftest.er1
285 +  ac_status=$?
286 +  grep -v '^ *+' conftest.er1 >conftest.err
287 +  rm -f conftest.er1
288 +  cat conftest.err >&5
289 +  echo "$as_me:$LINENO: \$? = $ac_status" >&5
290 +  (exit $ac_status); } && {
291 +        test -z "$ac_c_werror_flag" ||
292 +        test ! -s conftest.err
293 +       } && test -s conftest.$ac_objext; then
294 +  { echo "$as_me:$LINENO: result: yes" >&5
295 +echo "${ECHO_T}yes" >&6; }
296 +else
297 +  echo "$as_me: failed program was:" >&5
298 +sed 's/^/| /' conftest.$ac_ext >&5
299 +
300 +
301 +                                   { echo "$as_me:$LINENO: result: no" >&5
302 +echo "${ECHO_T}no" >&6; }
303 +                                       { { echo "$as_me:$LINENO: error: ** Incomplete or missing ldap libraries **" >&5
304 +echo "$as_me: error: ** Incomplete or missing ldap libraries **" >&2;}
305 +   { (exit 1); exit 1; }; }
306 +
307 +
308 +fi
309 +
310 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
311 +               fi
312 +
313 +
314 +fi
315 +
316 +
317  
318  
319  
320 @@ -30135,6 +30215,7 @@
321  echo "                 Smartcard support: $SCARD_MSG"
322  echo "                     S/KEY support: $SKEY_MSG"
323  echo "              TCP Wrappers support: $TCPW_MSG"
324 +echo "                      LDAP support: $LDAP_MSG"
325  echo "              MD5 password support: $MD5_MSG"
326  echo "                   libedit support: $LIBEDIT_MSG"
327  echo "  Solaris process contract support: $SPC_MSG"
328 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/configure.ac openssh-5.1p1+lpk/configure.ac
329 --- openssh-5.1p1.orig/configure.ac     2008-07-09 04:07:19.000000000 -0700
330 +++ openssh-5.1p1+lpk/configure.ac      2008-08-23 15:02:47.000000000 -0700
331 @@ -1299,6 +1299,37 @@
332         esac ]
333  )
334  
335 +# Check whether user wants LDAP support
336 +LDAP_MSG="no"
337 +AC_ARG_WITH(ldap,
338 +       [  --with-ldap[[=PATH]]      Enable LDAP pubkey support (optionally in PATH)],
339 +       [
340 +               if test "x$withval" != "xno" ; then
341 +
342 +                       if test "x$withval" != "xyes" ; then
343 +                               CPPFLAGS="$CPPFLAGS -I${withval}/include"
344 +                               LDFLAGS="$LDFLAGS -L${withval}/lib"
345 +                       fi
346 +
347 +                       AC_DEFINE([WITH_LDAP_PUBKEY], 1, [Enable LDAP pubkey support])
348 +                       LIBS="-lldap $LIBS"
349 +                       LDAP_MSG="yes"
350 +       
351 +                       AC_MSG_CHECKING([for LDAP support])
352 +                       AC_TRY_COMPILE(
353 +                               [#include <sys/types.h>
354 +                                #include <ldap.h>],
355 +                               [(void)ldap_init(0, 0);],
356 +                               [AC_MSG_RESULT(yes)],
357 +                               [
358 +                                   AC_MSG_RESULT(no) 
359 +                                       AC_MSG_ERROR([** Incomplete or missing ldap libraries **])
360 +                               ]
361 +               )
362 +               fi
363 +       ]
364 +)
365 +
366  dnl    Checks for library functions. Please keep in alphabetical order
367  AC_CHECK_FUNCS( \
368         arc4random \
369 @@ -4137,6 +4168,7 @@
370  echo "                 Smartcard support: $SCARD_MSG"
371  echo "                     S/KEY support: $SKEY_MSG"
372  echo "              TCP Wrappers support: $TCPW_MSG"
373 +echo "                      LDAP support: $LDAP_MSG"
374  echo "              MD5 password support: $MD5_MSG"
375  echo "                   libedit support: $LIBEDIT_MSG"
376  echo "  Solaris process contract support: $SPC_MSG"
377 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/ldapauth.c openssh-5.1p1+lpk/ldapauth.c
378 --- openssh-5.1p1.orig/ldapauth.c       1969-12-31 16:00:00.000000000 -0800
379 +++ openssh-5.1p1+lpk/ldapauth.c        2008-08-23 15:02:47.000000000 -0700
380 @@ -0,0 +1,575 @@
381 +/* 
382 + * $Id$
383 + */
384 +
385 +/*
386 + *
387 + * Copyright (c) 2005, Eric AUGE <eau@phear.org>
388 + * All rights reserved.
389 + *
390 + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
391 + *
392 + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
393 + * 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.
394 + * 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.
395 + *
396 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
397 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
398 + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
399 + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
400 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
401 + * 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.
402 + *
403 + *
404 + */
405 +
406 +#include "includes.h"
407 +
408 +#ifdef WITH_LDAP_PUBKEY
409 +
410 +#include <stdio.h>
411 +#include <stdlib.h>
412 +#include <unistd.h>
413 +#include <string.h>
414 +
415 +#include "ldapauth.h"
416 +#include "log.h"
417 +
418 +static char *attrs[] = {
419 +    PUBKEYATTR,
420 +    NULL
421 +};
422 +
423 +/* filter building infos */
424 +#define FILTER_GROUP_PREFIX "(&(objectclass=posixGroup)"
425 +#define FILTER_OR_PREFIX "(|"
426 +#define FILTER_OR_SUFFIX ")"
427 +#define FILTER_CN_PREFIX "(cn="
428 +#define FILTER_CN_SUFFIX ")"
429 +#define FILTER_UID_FORMAT "(memberUid=%s)"
430 +#define FILTER_GROUP_SUFFIX ")"
431 +#define FILTER_GROUP_SIZE(group) (size_t) (strlen(group)+(ldap_count_group(group)*5)+52)
432 +
433 +/* just filter building stuff */
434 +#define REQUEST_GROUP_SIZE(filter, uid) (size_t) (strlen(filter)+strlen(uid)+1)
435 +#define REQUEST_GROUP(buffer, prefilter, pwname) \
436 +    buffer = (char *) calloc(REQUEST_GROUP_SIZE(prefilter, pwname), sizeof(char)); \
437 +    if (!buffer) { \
438 +        perror("calloc()"); \
439 +        return FAILURE; \
440 +    } \
441 +    snprintf(buffer, REQUEST_GROUP_SIZE(prefilter,pwname), prefilter, pwname)
442 +/*
443 +XXX OLD group building macros
444 +#define REQUEST_GROUP_SIZE(grp, uid) (size_t) (strlen(grp)+strlen(uid)+46)
445 +#define REQUEST_GROUP(buffer,pwname,grp) \
446 +    buffer = (char *) calloc(REQUEST_GROUP_SIZE(grp, pwname), sizeof(char)); \
447 +    if (!buffer) { \
448 +        perror("calloc()"); \
449 +        return FAILURE; \
450 +    } \
451 +    snprintf(buffer,REQUEST_GROUP_SIZE(grp,pwname),"(&(objectclass=posixGroup)(cn=%s)(memberUid=%s))",grp,pwname)
452 +    */
453 +
454 +/*
455 +XXX stock upstream version without extra filter support
456 +#define REQUEST_USER_SIZE(uid) (size_t) (strlen(uid)+64)
457 +#define REQUEST_USER(buffer, pwname) \
458 +    buffer = (char *) calloc(REQUEST_USER_SIZE(pwname), sizeof(char)); \
459 +    if (!buffer) { \
460 +        perror("calloc()"); \
461 +        return NULL; \
462 +    } \
463 +    snprintf(buffer,REQUEST_USER_SIZE(pwname),"(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s))",pwname)
464 +   */
465 +
466 +#define REQUEST_USER_SIZE(uid, filter) (size_t) (strlen(uid)+64+(filter != NULL ? strlen(filter) : 0))
467 +#define REQUEST_USER(buffer, pwname, customfilter) \
468 +    buffer = (char *) calloc(REQUEST_USER_SIZE(pwname, customfilter), sizeof(char)); \
469 +    if (!buffer) { \
470 +        perror("calloc()"); \
471 +        return NULL; \
472 +    } \
473 +    snprintf(buffer, REQUEST_USER_SIZE(pwname, customfilter), \
474 +       "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)", \
475 +       pwname, (customfilter != NULL ? customfilter : ""))
476 +
477 +/* some portable and working tokenizer, lame though */
478 +static int tokenize(char ** o, size_t size, char * input) {
479 +    unsigned int i = 0, num;
480 +    const char * charset = " \t";
481 +    char * ptr = input;
482 +
483 +    /* leading white spaces are ignored */
484 +    num = strspn(ptr, charset);
485 +    ptr += num;
486 +
487 +    while ((num = strcspn(ptr, charset))) {
488 +        if (i < size-1) {
489 +            o[i++] = ptr;
490 +            ptr += num;
491 +            if (*ptr)
492 +                *ptr++ = '\0';
493 +        }
494 +    }
495 +    o[i] = NULL;
496 +    return SUCCESS;
497 +}
498 +
499 +void ldap_close(ldap_opt_t * ldap) {
500 +
501 +    if (!ldap)
502 +        return;
503 +
504 +    if ( ldap_unbind_ext(ldap->ld, NULL, NULL) < 0)
505 +       ldap_perror(ldap->ld, "ldap_unbind()");
506 +
507 +    ldap->ld = NULL;
508 +    FLAG_SET_DISCONNECTED(ldap->flags);
509 +
510 +    return;
511 +}
512 +
513 +/* init && bind */
514 +int ldap_connect(ldap_opt_t * ldap) {
515 +    int version = LDAP_VERSION3;
516 +
517 +    if (!ldap->servers)
518 +        return FAILURE;
519 +
520 +    /* Connection Init and setup */
521 +    ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
522 +    if (!ldap->ld) {
523 +        ldap_perror(ldap->ld, "ldap_init()");
524 +        return FAILURE;
525 +    }
526 +
527 +    if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
528 +        ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_PROTOCOL_VERSION)");
529 +        return FAILURE;
530 +    }
531 +
532 +    /* Timeouts setup */
533 +    if (ldap_set_option(ldap->ld, LDAP_OPT_NETWORK_TIMEOUT, &ldap->b_timeout) != LDAP_SUCCESS) {
534 +        ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT)");
535 +    }
536 +    if (ldap_set_option(ldap->ld, LDAP_OPT_TIMEOUT, &ldap->s_timeout) != LDAP_SUCCESS) {
537 +        ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_TIMEOUT)");
538 +    }
539 +
540 +    /* TLS support */
541 +    if ( (ldap->tls == -1) || (ldap->tls == 1) ) {
542 +        if (ldap_start_tls_s(ldap->ld, NULL, NULL ) != LDAP_SUCCESS) {
543 +            /* failed then reinit the initial connect */
544 +            ldap_perror(ldap->ld, "ldap_connect: (TLS) ldap_start_tls()");
545 +            if (ldap->tls == 1)
546 +                return FAILURE;
547 +
548 +            ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
549 +            if (!ldap->ld) { 
550 +                ldap_perror(ldap->ld, "ldap_init()");
551 +                return FAILURE;
552 +            }
553 +
554 +            if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
555 +                 ldap_perror(ldap->ld, "ldap_set_option()");
556 +                 return FAILURE;
557 +            }
558 +        }
559 +    }
560 +
561 +
562 +    if ( ldap_simple_bind_s(ldap->ld, ldap->binddn, ldap->bindpw) != LDAP_SUCCESS) {
563 +        ldap_perror(ldap->ld, "ldap_simple_bind_s()");
564 +        return FAILURE;
565 +    }
566 +
567 +    /* says it is connected */
568 +    FLAG_SET_CONNECTED(ldap->flags);
569 +
570 +    return SUCCESS;
571 +}
572 +
573 +/* must free allocated ressource */
574 +static char * ldap_build_host(char *host, int port) {
575 +    unsigned int size = strlen(host)+11;
576 +    char * h = (char *) calloc (size, sizeof(char));
577 +    int rc;
578 +    if (!h)
579 +         return NULL;
580 +
581 +    rc = snprintf(h, size, "%s:%d ", host, port);
582 +    if (rc == -1)
583 +        return NULL;
584 +    return h;
585 +}
586 +
587 +static int ldap_count_group(const char * input) {
588 +    const char * charset = " \t";
589 +    const char * ptr = input;
590 +    unsigned int count = 0;
591 +    unsigned int num;
592 +
593 +    num = strspn(ptr, charset);
594 +    ptr += num;
595 +
596 +    while ((num = strcspn(ptr, charset))) {
597 +    count++;
598 +    ptr += num;
599 +    ptr++;
600 +    }
601 +
602 +    return count;
603 +}
604 +
605 +/* format filter */
606 +char * ldap_parse_groups(const char * groups) {
607 +    unsigned int buffer_size = FILTER_GROUP_SIZE(groups);
608 +    char * buffer = (char *) calloc(buffer_size, sizeof(char));
609 +    char * g = NULL;
610 +    char * garray[32];
611 +    unsigned int i = 0;
612 +
613 +    if ((!groups)||(!buffer))
614 +        return NULL;
615 +
616 +    g = strdup(groups);
617 +    if (!g) {
618 +        free(buffer);
619 +        return NULL;
620 +    }
621 +
622 +    /* first separate into n tokens */
623 +    if ( tokenize(garray, sizeof(garray)/sizeof(*garray), g) < 0) {
624 +        free(g);
625 +        free(buffer);
626 +        return NULL;
627 +    }
628 +
629 +    /* build the final filter format */
630 +    strlcat(buffer, FILTER_GROUP_PREFIX, buffer_size);
631 +    strlcat(buffer, FILTER_OR_PREFIX, buffer_size);
632 +    i = 0;
633 +    while (garray[i]) {
634 +        strlcat(buffer, FILTER_CN_PREFIX, buffer_size);
635 +        strlcat(buffer, garray[i], buffer_size);
636 +        strlcat(buffer, FILTER_CN_SUFFIX, buffer_size);
637 +        i++;
638 +    }
639 +    strlcat(buffer, FILTER_OR_SUFFIX, buffer_size);
640 +    strlcat(buffer, FILTER_UID_FORMAT, buffer_size);
641 +    strlcat(buffer, FILTER_GROUP_SUFFIX, buffer_size);
642 +
643 +    free(g);
644 +    return buffer;
645 +}
646 +
647 +/* a bit dirty but leak free  */
648 +char * ldap_parse_servers(const char * servers) {
649 +    char * s = NULL;
650 +    char * tmp = NULL, *urls[32];
651 +    unsigned int num = 0 , i = 0 , asize = 0;
652 +    LDAPURLDesc *urld[32];
653 +
654 +    if (!servers)
655 +        return NULL;
656 +
657 +    /* local copy of the arg */
658 +    s = strdup(servers);
659 +    if (!s)
660 +        return NULL;
661 +
662 +    /* first separate into URL tokens */
663 +    if ( tokenize(urls, sizeof(urls)/sizeof(*urls), s) < 0)
664 +        return NULL;
665 +
666 +    i = 0;
667 +    while (urls[i]) {
668 +        if (! ldap_is_ldap_url(urls[i]) ||
669 +           (ldap_url_parse(urls[i], &urld[i]) != 0)) {
670 +                return NULL;
671 +        }
672 +        i++;
673 +    }
674 +
675 +    /* now free(s) */
676 +    free (s);
677 +
678 +    /* how much memory do we need */
679 +    num = i;
680 +    for (i = 0 ; i < num ; i++)
681 +        asize += strlen(urld[i]->lud_host)+11;
682 +
683 +    /* alloc */
684 +    s = (char *) calloc( asize+1 , sizeof(char));
685 +    if (!s) {
686 +        for (i = 0 ; i < num ; i++)
687 +            ldap_free_urldesc(urld[i]);
688 +        return NULL;
689 +    }
690 +
691 +    /* then build the final host string */
692 +    for (i = 0 ; i < num ; i++) {
693 +        /* built host part */
694 +        tmp = ldap_build_host(urld[i]->lud_host, urld[i]->lud_port);
695 +        strncat(s, tmp, strlen(tmp));
696 +        ldap_free_urldesc(urld[i]);
697 +        free(tmp);
698 +    }
699 +
700 +    return s;
701 +}
702 +
703 +void ldap_options_print(ldap_opt_t * ldap) {
704 +    debug("ldap options:");
705 +    debug("servers: %s", ldap->servers);
706 +    if (ldap->u_basedn)
707 +        debug("user basedn: %s", ldap->u_basedn);
708 +    if (ldap->g_basedn)
709 +        debug("group basedn: %s", ldap->g_basedn);
710 +    if (ldap->binddn)
711 +        debug("binddn: %s", ldap->binddn);
712 +    if (ldap->bindpw)
713 +        debug("bindpw: %s", ldap->bindpw);
714 +    if (ldap->sgroup)
715 +        debug("group: %s", ldap->sgroup);
716 +    if (ldap->filter)
717 +        debug("filter: %s", ldap->filter);
718 +}
719 +
720 +void ldap_options_free(ldap_opt_t * l) {
721 +    if (!l)
722 +        return;
723 +    if (l->servers)
724 +        free(l->servers);
725 +    if (l->u_basedn)
726 +        free(l->u_basedn);
727 +    if (l->g_basedn)
728 +        free(l->g_basedn);
729 +    if (l->binddn)
730 +        free(l->binddn);
731 +    if (l->bindpw)
732 +        free(l->bindpw);
733 +    if (l->sgroup)
734 +        free(l->sgroup);
735 +    if (l->fgroup)
736 +        free(l->fgroup);
737 +    if (l->filter)
738 +        free(l->filter);
739 +    if (l->l_conf)
740 +        free(l->l_conf);
741 +    free(l);
742 +}
743 +
744 +/* free keys */
745 +void ldap_keys_free(ldap_key_t * k) {
746 +    ldap_value_free_len(k->keys);
747 +    free(k);
748 +    return;
749 +}
750 +
751 +ldap_key_t * ldap_getuserkey(ldap_opt_t *l, const char * user) {
752 +    ldap_key_t * k = (ldap_key_t *) calloc (1, sizeof(ldap_key_t));
753 +    LDAPMessage *res, *e;
754 +    char * filter;
755 +    int i;
756 +
757 +    if ((!k) || (!l))
758 +         return NULL;
759 +
760 +    /* Am i still connected ? RETRY n times */
761 +    /* XXX TODO: setup some conf value for retrying */
762 +    if (!(l->flags & FLAG_CONNECTED))
763 +        for (i = 0 ; i < 2 ; i++)
764 +            if (ldap_connect(l) == 0)
765 +                break;
766 +
767 +    /* quick check for attempts to be evil */
768 +    if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) ||
769 +        (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL))
770 +        return NULL;
771 +
772 +    /* build  filter for LDAP request */
773 +    REQUEST_USER(filter, user, l->filter);
774 +
775 +    if ( ldap_search_st( l->ld,
776 +        l->u_basedn,
777 +        LDAP_SCOPE_SUBTREE,
778 +        filter,
779 +        attrs, 0, &l->s_timeout, &res ) != LDAP_SUCCESS) {
780 +        
781 +        ldap_perror(l->ld, "ldap_search_st()");
782 +
783 +        free(filter);
784 +        free(k);
785 +
786 +        /* XXX error on search, timeout etc.. close ask for reconnect */
787 +        ldap_close(l);
788 +
789 +        return NULL;
790 +    } 
791 +
792 +    /* free */
793 +    free(filter);
794 +
795 +    /* check if any results */
796 +    i = ldap_count_entries(l->ld,res);
797 +    if (i <= 0) {
798 +        ldap_msgfree(res);
799 +        free(k);
800 +        return NULL;
801 +    }
802 +
803 +    if (i > 1)
804 +        debug("[LDAP] duplicate entries, using the FIRST entry returned");
805 +
806 +    e = ldap_first_entry(l->ld, res);
807 +    k->keys = ldap_get_values_len(l->ld, e, PUBKEYATTR);
808 +    k->num = ldap_count_values_len(k->keys);
809 +
810 +    ldap_msgfree(res);
811 +    return k;
812 +}
813 +
814 +
815 +/* -1 if trouble
816 +   0 if user is NOT member of current server group
817 +   1 if user IS MEMBER of current server group 
818 + */
819 +int ldap_ismember(ldap_opt_t * l, const char * user) {
820 +    LDAPMessage *res;
821 +    char * filter;
822 +    int i;
823 +
824 +    if ((!l->sgroup) || !(l->g_basedn))
825 +        return 1;
826 +
827 +    /* Am i still connected ? RETRY n times */
828 +    /* XXX TODO: setup some conf value for retrying */
829 +    if (!(l->flags & FLAG_CONNECTED)) 
830 +        for (i = 0 ; i < 2 ; i++)
831 +            if (ldap_connect(l) == 0)
832 +                 break;
833 +
834 +    /* quick check for attempts to be evil */
835 +    if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) ||
836 +        (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL))
837 +        return FAILURE;
838 +
839 +    /* build filter for LDAP request */
840 +    REQUEST_GROUP(filter, l->fgroup, user);
841 +
842 +    if (ldap_search_st( l->ld, 
843 +        l->g_basedn,
844 +        LDAP_SCOPE_SUBTREE,
845 +        filter,
846 +        NULL, 0, &l->s_timeout, &res) != LDAP_SUCCESS) {
847 +    
848 +        ldap_perror(l->ld, "ldap_search_st()");
849 +
850 +        free(filter);
851 +
852 +        /* XXX error on search, timeout etc.. close ask for reconnect */
853 +        ldap_close(l);
854 +
855 +        return FAILURE;
856 +    }
857 +
858 +    free(filter);
859 +
860 +    /* check if any results */
861 +    if (ldap_count_entries(l->ld, res) > 0) {
862 +        ldap_msgfree(res);
863 +        return 1;
864 +    }
865 +
866 +    ldap_msgfree(res);
867 +    return 0;
868 +}
869 +
870 +/*
871 + * ldap.conf simple parser
872 + * XXX TODO:  sanity checks
873 + * must either
874 + * - free the previous ldap_opt_before replacing entries
875 + * - free each necessary previously parsed elements
876 + * ret:
877 + * -1 on FAILURE, 0 on SUCCESS
878 + */
879 +int ldap_parse_lconf(ldap_opt_t * l) {
880 +    FILE * lcd; /* ldap.conf descriptor */
881 +    char buf[BUFSIZ];
882 +    char * s = NULL, * k = NULL, * v = NULL;
883 +    int li, len;
884 +
885 +    lcd = fopen (l->l_conf, "r");
886 +    if (lcd == NULL) {
887 +        /* debug("Cannot open %s", l->l_conf); */
888 +        perror("ldap_parse_lconf()");
889 +        return FAILURE;
890 +    }
891 +    
892 +    while (fgets (buf, sizeof (buf), lcd) != NULL) {
893 +
894 +        if (*buf == '\n' || *buf == '#')
895 +            continue;
896 +
897 +        k = buf;
898 +        v = k;
899 +        while (*v != '\0' && *v != ' ' && *v != '\t')
900 +            v++;
901 +
902 +        if (*v == '\0')
903 +            continue;
904 +
905 +        *(v++) = '\0';
906 +
907 +        while (*v == ' ' || *v == '\t')
908 +            v++;
909 +
910 +        li = strlen (v) - 1;
911 +        while (v[li] == ' ' || v[li] == '\t' || v[li] == '\n')
912 +            --li;
913 +        v[li + 1] = '\0';
914 +
915 +        if (!strcasecmp (k, "uri")) {
916 +            if ((l->servers = ldap_parse_servers(v)) == NULL) {
917 +                fatal("error in ldap servers");
918 +            return FAILURE;
919 +            }
920 +
921 +        }
922 +        else if (!strcasecmp (k, "base")) { 
923 +            s = strchr (v, '?');
924 +            if (s != NULL) {
925 +                len = s - v;
926 +                l->u_basedn = malloc (len + 1);
927 +                strncpy (l->u_basedn, v, len);
928 +                l->u_basedn[len] = '\0';
929 +            } else {
930 +                l->u_basedn = strdup (v);
931 +            }
932 +        }
933 +        else if (!strcasecmp (k, "binddn")) {
934 +            l->binddn = strdup (v);
935 +        }
936 +        else if (!strcasecmp (k, "bindpw")) {
937 +            l->bindpw = strdup (v);
938 +        }
939 +        else if (!strcasecmp (k, "timelimit")) {
940 +            l->s_timeout.tv_sec = atoi (v);
941 +                }
942 +        else if (!strcasecmp (k, "bind_timelimit")) {
943 +            l->b_timeout.tv_sec = atoi (v);
944 +        }
945 +        else if (!strcasecmp (k, "ssl")) {
946 +            if (!strcasecmp (v, "start_tls"))
947 +                l->tls = 1;
948 +        }
949 +    }
950 +
951 +    fclose (lcd);
952 +    return SUCCESS;
953 +}
954 +
955 +#endif /* WITH_LDAP_PUBKEY */
956 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/ldapauth.h openssh-5.1p1+lpk/ldapauth.h
957 --- openssh-5.1p1.orig/ldapauth.h       1969-12-31 16:00:00.000000000 -0800
958 +++ openssh-5.1p1+lpk/ldapauth.h        2008-08-23 15:02:47.000000000 -0700
959 @@ -0,0 +1,124 @@
960 +/*
961 + * $Id$ 
962 + */
963 +
964 +/*
965 + *
966 + * Copyright (c) 2005, Eric AUGE <eau@phear.org>
967 + * All rights reserved.
968 + *
969 + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
970 + *
971 + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
972 + * 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.
973 + * 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.
974 + *
975 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
976 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
977 + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 
978 + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
979 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
980 + * 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.
981 + *
982 + *
983 + */
984 +
985 +#ifndef LDAPAUTH_H
986 +#define LDAPAUTH_H
987 +
988 +#define LDAP_DEPRECATED 1
989 +
990 +#include <string.h>
991 +#include <time.h>
992 +#include <ldap.h>
993 +#include <lber.h>
994 +
995 +/* tokens in use for config */
996 +#define _DEFAULT_LPK_TOKEN "UseLPK"
997 +#define _DEFAULT_SRV_TOKEN "LpkServers"
998 +#define _DEFAULT_USR_TOKEN "LpkUserDN"
999 +#define _DEFAULT_GRP_TOKEN "LpkGroupDN"
1000 +#define _DEFAULT_BDN_TOKEN "LpkBindDN"
1001 +#define _DEFAULT_BPW_TOKEN "LpkBindPw"
1002 +#define _DEFAULT_MYG_TOKEN "LpkServerGroup"
1003 +#define _DEFAULT_FIL_TOKEN "LpkFilter"
1004 +#define _DEFAULT_TLS_TOKEN "LpkForceTLS"
1005 +#define _DEFAULT_BTI_TOKEN "LpkBindTimelimit"
1006 +#define _DEFAULT_STI_TOKEN "LpkSearchTimelimit"
1007 +#define _DEFAULT_LDP_TOKEN "LpkLdapConf"
1008 +
1009 +/* default options */
1010 +#define _DEFAULT_LPK_ON 0
1011 +#define _DEFAULT_LPK_SERVERS NULL
1012 +#define _DEFAULT_LPK_UDN NULL
1013 +#define _DEFAULT_LPK_GDN NULL
1014 +#define _DEFAULT_LPK_BINDDN NULL
1015 +#define _DEFAULT_LPK_BINDPW NULL
1016 +#define _DEFAULT_LPK_SGROUP NULL
1017 +#define _DEFAULT_LPK_FILTER NULL
1018 +#define _DEFAULT_LPK_TLS -1
1019 +#define _DEFAULT_LPK_BTIMEOUT 10
1020 +#define _DEFAULT_LPK_STIMEOUT 10
1021 +#define _DEFAULT_LPK_LDP NULL
1022 +
1023 +/* flags */
1024 +#define FLAG_EMPTY         0x00000000
1025 +#define FLAG_CONNECTED     0x00000001
1026 +
1027 +/* flag macros */
1028 +#define FLAG_SET_EMPTY(x)              x&=(FLAG_EMPTY)
1029 +#define FLAG_SET_CONNECTED(x)          x|=(FLAG_CONNECTED)
1030 +#define FLAG_SET_DISCONNECTED(x)       x&=~(FLAG_CONNECTED)
1031 +
1032 +/* defines */
1033 +#define FAILURE -1
1034 +#define SUCCESS 0
1035 +#define PUBKEYATTR "sshPublicKey"
1036 +
1037 +/* 
1038 + *
1039 + * defined files path 
1040 + * (should be relocated to pathnames.h,
1041 + * if one day it's included within the tree) 
1042 + *
1043 + */
1044 +#define _PATH_LDAP_CONFIG_FILE "/etc/ldap.conf"
1045 +
1046 +/* structures */
1047 +typedef struct ldap_options {
1048 +    int on;                    /* Use it or NOT */
1049 +    LDAP * ld;                 /* LDAP file desc */
1050 +    char * servers;            /* parsed servers for ldaplib failover handling */
1051 +    char * u_basedn;           /* user basedn */
1052 +    char * g_basedn;           /* group basedn */
1053 +    char * binddn;             /* binddn */
1054 +    char * bindpw;             /* bind password */
1055 +    char * sgroup;             /* server group */
1056 +    char * fgroup;             /* group filter */
1057 +    char * filter;             /* additional filter */
1058 +    char * l_conf;             /* use ldap.conf */
1059 +    int tls;                   /* TLS only */
1060 +    struct timeval b_timeout;   /* bind timeout */
1061 +    struct timeval s_timeout;   /* search timeout */
1062 +    unsigned int flags;                /* misc flags (reconnection, future use?) */
1063 +} ldap_opt_t;
1064 +
1065 +typedef struct ldap_keys {
1066 +    struct berval ** keys;     /* the public keys retrieved */
1067 +    unsigned int num;          /* number of keys */
1068 +} ldap_key_t;
1069 +
1070 +
1071 +/* function headers */
1072 +void ldap_close(ldap_opt_t *);
1073 +int ldap_connect(ldap_opt_t *);
1074 +char * ldap_parse_groups(const char *);
1075 +char * ldap_parse_servers(const char *);
1076 +void ldap_options_print(ldap_opt_t *);
1077 +void ldap_options_free(ldap_opt_t *);
1078 +void ldap_keys_free(ldap_key_t *);
1079 +int ldap_parse_lconf(ldap_opt_t *);
1080 +ldap_key_t * ldap_getuserkey(ldap_opt_t *, const char *);
1081 +int ldap_ismember(ldap_opt_t *, const char *);
1082 +
1083 +#endif
1084 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/lpk-user-example.txt openssh-5.1p1+lpk/lpk-user-example.txt
1085 --- openssh-5.1p1.orig/lpk-user-example.txt     1969-12-31 16:00:00.000000000 -0800
1086 +++ openssh-5.1p1+lpk/lpk-user-example.txt      2008-08-23 15:02:47.000000000 -0700
1087 @@ -0,0 +1,117 @@
1088 +
1089 +Post to ML -> User Made Quick Install Doc.
1090 +Contribution from John Lane <john@lane.uk.net>
1091 +
1092 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1093 +
1094 +OpenSSH LDAP keystore Patch
1095 +===========================
1096 +
1097 +NOTE: these notes are a transcript of a specific installation
1098 +      they work for me, your specifics may be different!
1099 +      from John Lane March 17th 2005         john@lane.uk.net
1100 +
1101 +This is a patch to OpenSSH 4.0p1 to allow it to obtain users' public keys
1102 +from their LDAP record as an alternative to ~/.ssh/authorized_keys.
1103 +
1104 +(Assuming here that necessary build stuff is in $BUILD)
1105 +
1106 +cd $BUILD/openssh-4.0p1
1107 +patch -Np1 -i $BUILD/openssh-lpk-4.0p1-0.3.patch
1108 +mkdir -p /var/empty &&
1109 +./configure --prefix=/usr --sysconfdir=/etc/ssh \
1110 +    --libexecdir=/usr/sbin --with-md5-passwords --with-pam \
1111 +    --with-libs="-lldap" --with-cppflags="-DWITH_LDAP_PUBKEY"
1112 +Now do.
1113 +make &&
1114 +make install
1115 +
1116 +Add the following config to /etc/ssh/ssh_config
1117 +UseLPK yes
1118 +LpkServers ldap://myhost.mydomain.com
1119 +LpkUserDN  ou=People,dc=mydomain,dc=com
1120 +
1121 +We need to tell sshd about the SSL keys during boot, as root's
1122 +environment does not exist at that time. Edit /etc/rc.d/init.d/sshd.
1123 +Change the startup code from this:
1124 +                echo "Starting SSH Server..."
1125 +                loadproc /usr/sbin/sshd
1126 +                ;;
1127 +to this:
1128 +                echo "Starting SSH Server..."
1129 +                LDAPRC="/root/.ldaprc" loadproc /usr/sbin/sshd
1130 +                ;;
1131 +
1132 +Re-start the sshd daemon:
1133 +/etc/rc.d/init.d/sshd restart
1134 +
1135 +Install the additional LDAP schema
1136 +cp $BUILD/openssh-lpk-0.2.schema  /etc/openldap/schema/openssh.schema
1137 +
1138 +Now add the openSSH LDAP schema to /etc/openldap/slapd.conf:
1139 +Add the following to the end of the existing block of schema includes
1140 +include         /etc/openldap/schema/openssh.schema
1141 +
1142 +Re-start the LDAP server:
1143 +/etc/rc.d/init.d/slapd restart
1144 +
1145 +To add one or more public keys to a user, eg "testuser" :
1146 +ldapsearch -x -W -Z -LLL -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D
1147 +"uid=testuser,ou=People,dc=mydomain,dc=com" > /tmp/testuser
1148 +
1149 +append the following to this /tmp/testuser file
1150 +objectclass: ldapPublicKey
1151 +sshPublicKey: ssh-rsa
1152 +AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KS
1153 +qIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z8XwSsuAoR1t86t+5dlI
1154 +7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key
1155 +
1156 +Then do a modify:
1157 +ldapmodify -x -D "uid=testuser,ou=People,dc=mydomain,dc=com" -W -f
1158 +/tmp/testuser -Z
1159 +Enter LDAP Password:
1160 +modifying entry "uid=testuser,ou=People,dc=mydomain,dc=com"
1161 +And check the modify is ok:
1162 +ldapsearch -x -W -Z -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D
1163 +"uid=testuser,ou=People,dc=mydomain,dc=com"
1164 +Enter LDAP Password:
1165 +# extended LDIF
1166 +#
1167 +# LDAPv3
1168 +# base <uid=testuser,ou=People,dc=mydomain,dc=com> with scope sub
1169 +# filter: (objectclass=*)
1170 +# requesting: ALL
1171 +#
1172 +
1173 +# testuser, People, mydomain.com
1174 +dn: uid=testuser,ou=People,dc=mydomain,dc=com
1175 +uid: testuser
1176 +cn: testuser
1177 +objectClass: account
1178 +objectClass: posixAccount
1179 +objectClass: top
1180 +objectClass: shadowAccount
1181 +objectClass: ldapPublicKey
1182 +shadowLastChange: 12757
1183 +shadowMax: 99999
1184 +shadowWarning: 7
1185 +loginShell: /bin/bash
1186 +uidNumber: 9999
1187 +gidNumber: 501
1188 +homeDirectory: /home/testuser
1189 +userPassword:: e1NTSEF9UDgwV1hnM1VjUDRJK0k1YnFiL1d4ZUJObXlZZ3Z3UTU=
1190 +sshPublicKey: ssh-rsa
1191 +AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KSqIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z
1192 +8XwSsuAoR1t86t+5dlI7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key
1193 +
1194 +# search result
1195 +search: 3
1196 +result: 0 Success
1197 +
1198 +# numResponses: 2
1199 +# numEntries: 1
1200 +
1201 +Now start a ssh session to user "testuser" from usual ssh client (e.g.
1202 +puTTY). Login should succeed.
1203 +
1204 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1205 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/Makefile.in openssh-5.1p1+lpk/Makefile.in
1206 --- openssh-5.1p1.orig/Makefile.in      2008-07-08 07:21:12.000000000 -0700
1207 +++ openssh-5.1p1+lpk/Makefile.in       2008-08-23 15:02:47.000000000 -0700
1208 @@ -78,7 +78,7 @@
1209  
1210  SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
1211         sshconnect.o sshconnect1.o sshconnect2.o mux.o \
1212 -       roaming_common.o roaming_client.o
1213 +       roaming_common.o roaming_client.o ldapauth.o
1214  
1215  SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
1216         sshpty.o sshlogin.o servconf.o serverloop.o \
1217 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/openssh-lpk_openldap.schema openssh-5.1p1+lpk/openssh-lpk_openldap.schema
1218 --- openssh-5.1p1.orig/openssh-lpk_openldap.schema      1969-12-31 16:00:00.000000000 -0800
1219 +++ openssh-5.1p1+lpk/openssh-lpk_openldap.schema       2008-08-23 15:02:47.000000000 -0700
1220 @@ -0,0 +1,19 @@
1221 +#
1222 +# LDAP Public Key Patch schema for use with openssh-ldappubkey
1223 +# Author: Eric AUGE <eau@phear.org>
1224 +# 
1225 +# Based on the proposal of : Mark Ruijter
1226 +#
1227 +
1228 +
1229 +# octetString SYNTAX
1230 +attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' 
1231 +       DESC 'MANDATORY: OpenSSH Public key' 
1232 +       EQUALITY octetStringMatch
1233 +       SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
1234 +
1235 +# printableString SYNTAX yes|no
1236 +objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
1237 +       DESC 'MANDATORY: OpenSSH LPK objectclass'
1238 +       MUST ( sshPublicKey $ uid ) 
1239 +       )
1240 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/openssh-lpk_sun.schema openssh-5.1p1+lpk/openssh-lpk_sun.schema
1241 --- openssh-5.1p1.orig/openssh-lpk_sun.schema   1969-12-31 16:00:00.000000000 -0800
1242 +++ openssh-5.1p1+lpk/openssh-lpk_sun.schema    2008-08-23 15:02:47.000000000 -0700
1243 @@ -0,0 +1,21 @@
1244 +#
1245 +# LDAP Public Key Patch schema for use with openssh-ldappubkey
1246 +# Author: Eric AUGE <eau@phear.org>
1247 +# 
1248 +# Schema for Sun Directory Server.
1249 +# Based on the original schema, modified by Stefan Fischer.
1250 +#
1251 +
1252 +dn: cn=schema
1253 +
1254 +# octetString SYNTAX
1255 +attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey' 
1256 +       DESC 'MANDATORY: OpenSSH Public key' 
1257 +       EQUALITY octetStringMatch
1258 +       SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
1259 +
1260 +# printableString SYNTAX yes|no
1261 +objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
1262 +       DESC 'MANDATORY: OpenSSH LPK objectclass'
1263 +       MUST ( sshPublicKey $ uid ) 
1264 +       )
1265 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/README.lpk openssh-5.1p1+lpk/README.lpk
1266 --- openssh-5.1p1.orig/README.lpk       1969-12-31 16:00:00.000000000 -0800
1267 +++ openssh-5.1p1+lpk/README.lpk        2008-08-23 15:02:47.000000000 -0700
1268 @@ -0,0 +1,267 @@
1269 +OpenSSH LDAP PUBLIC KEY PATCH 
1270 +Copyright (c) 2003 Eric AUGE (eau@phear.org)
1271 +All rights reserved.
1272 +
1273 +Redistribution and use in source and binary forms, with or without
1274 +modification, are permitted provided that the following conditions
1275 +are met:
1276 +1. Redistributions of source code must retain the above copyright
1277 +   notice, this list of conditions and the following disclaimer.
1278 +2. Redistributions in binary form must reproduce the above copyright
1279 +   notice, this list of conditions and the following disclaimer in the
1280 +   documentation and/or other materials provided with the distribution.
1281 +3. The name of the author may not be used to endorse or promote products
1282 +   derived from this software without specific prior written permission.
1283 +
1284 +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1285 +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1286 +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1287 +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1288 +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1289 +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1290 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1291 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1292 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1293 +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1294 +
1295 +purposes of this patch:
1296 +
1297 +This patch would help to have authentication centralization policy
1298 +using ssh public key authentication.
1299 +This patch could be an alternative to other "secure" authentication system
1300 +working in a similar way (Kerberos, SecurID, etc...), except the fact 
1301 +that it's based on OpenSSH and its public key abilities.
1302 +
1303 +>> FYI: <<
1304 +'uid': means unix accounts existing on the current server
1305 +'lpkServerGroup:' mean server group configured on the current server ('lpkServerGroup' in sshd_config)
1306 +
1307 +example schema:
1308 +
1309 +
1310 +                                  server1 (uid: eau,rival,toto) (lpkServerGroup: unix)
1311 +                ___________      /
1312 +               /           \ --- - server3 (uid: eau, titi) (lpkServerGroup: unix)
1313 +              | LDAP Server |    \
1314 +             | eau  ,rival |     server2 (uid: rival, eau) (lpkServerGroup: unix)
1315 +             | titi ,toto  |
1316 +             | userx,....  |         server5 (uid: eau)  (lpkServerGroup: mail)
1317 +               \___________/ \       /
1318 +                              ----- - server4 (uid: eau, rival)  (no group configured)
1319 +                                    \
1320 +                                       etc...
1321 +
1322 +- WHAT WE NEED :
1323 +
1324 +  * configured LDAP server somewhere on the network (i.e. OpenLDAP)
1325 +  * patched sshd (with this patch ;)
1326 +  * LDAP user(/group) entry (look at users.ldif (& groups.ldif)):
1327 +        User entry:
1328 +       - attached to the 'ldapPublicKey' objectclass
1329 +       - attached to the 'posixAccount' objectclass
1330 +       - with a filled 'sshPublicKey' attribute 
1331 +       Example:
1332 +               dn: uid=eau,ou=users,dc=cuckoos,dc=net
1333 +               objectclass: top
1334 +               objectclass: person
1335 +               objectclass: organizationalPerson
1336 +               objectclass: posixAccount
1337 +               objectclass: ldapPublicKey
1338 +               description: Eric AUGE Account
1339 +               userPassword: blah
1340 +               cn: Eric AUGE
1341 +               sn: Eric AUGE
1342 +               uid: eau
1343 +               uidNumber: 1034
1344 +               gidNumber: 1
1345 +               homeDirectory: /export/home/eau
1346 +               sshPublicKey: ssh-dss AAAAB3...
1347 +               sshPublicKey: ssh-dss AAAAM5...
1348 +
1349 +       Group entry:
1350 +       - attached to the 'posixGroup' objectclass
1351 +       - with a 'cn' groupname attribute
1352 +       - with multiple 'memberUid' attributes filled with usernames allowed in this group
1353 +       Example:
1354 +               # few members
1355 +               dn: cn=unix,ou=groups,dc=cuckoos,dc=net
1356 +               objectclass: top
1357 +               objectclass: posixGroup
1358 +               description: Unix based servers group
1359 +               cn: unix
1360 +               gidNumber: 1002
1361 +               memberUid: eau
1362 +               memberUid: user1
1363 +               memberUid: user2
1364 +
1365 +
1366 +- HOW IT WORKS :
1367 +
1368 +  * without patch
1369 +  If a user wants to authenticate to log in a server the sshd, will first look for authentication method allowed (RSAauth,kerberos,etc..)
1370 +  and if RSAauth and tickets based auth fails, it will fallback to standard password authentication (if enabled).
1371 +
1372 +  * with the patch
1373 +  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.
1374 +  It will do an ldapsearch to get the public key directly from the LDAP instead of reading it from the server filesystem. 
1375 +  (usually in $HOME/.ssh/authorized_keys)
1376 +
1377 +  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.
1378 +  If it fails, it falls back on RSA auth files ($HOME/.ssh/authorized_keys), etc.. and finally to standard password authentication (if enabled).
1379 +
1380 +  7 tokens are added to sshd_config :
1381 +  # here is the new patched ldap related tokens
1382 +  # entries in your LDAP must be posixAccount & strongAuthenticationUser & posixGroup
1383 +  UseLPK yes                                                           # look the pub key into LDAP
1384 +  LpkServers ldap://10.31.32.5/ ldap://10.31.32.4 ldap://10.31.32.3    # which LDAP server for users ? (URL format)
1385 +  LpkUserDN  ou=users,dc=foobar,dc=net                                 # which base DN for users ?
1386 +  LpkGroupDN ou=groups,dc=foobar,dc=net                                        # which base DN for groups ? 
1387 +  LpkBindDN cn=manager,dc=foobar,dc=net                                        # which bind DN ?
1388 +  LpkBindPw asecret                                                    # bind DN credidentials
1389 +  LpkServerGroup agroupname                                            # the group the server is part of
1390 +
1391 +  Right now i'm using anonymous binding to get public keys, because getting public keys of someone doesn't impersonate him¸ but there is some
1392 +  flaws you have to take care of.
1393 +
1394 +- HOW TO INSERT A USER/KEY INTO AN LDAP ENTRY
1395 +
1396 +  * my way (there is plenty :)
1397 +  - create ldif file (i.e. users.ldif)
1398 +  - cat ~/.ssh/id_dsa.pub OR cat ~/.ssh/id_rsa.pub OR cat ~/.ssh/identity.pub
1399 +  - my way in 4 steps :
1400 +  Example:
1401 +
1402 +  # you add this to the user entry in the LDIF file :
1403 +  [...]
1404 +  objectclass: posixAccount
1405 +  objectclass: ldapPublicKey
1406 +  [...]
1407 +  sshPubliKey: ssh-dss AAAABDh12DDUR2...
1408 +  [...]
1409 +
1410 +  # insert your entry and you're done :)
1411 +  ldapadd -D balblabla -w bleh < file.ldif 
1412 +  
1413 +  all standard options can be present in the 'sshPublicKey' attribute.
1414 +
1415 +- WHY :
1416 +
1417 +  Simply because, i was looking for a way to centralize all sysadmins authentication, easily,  without completely using LDAP 
1418 +  as authentication method (like pam_ldap etc..).  
1419 +  
1420 +  After looking into Kerberos, SecurID, and other centralized secure authentications systems, the use of RSA and LDAP to get 
1421 +  public key for authentication allows us to control who has access to which server (the user needs an account and to be in 'strongAuthenticationUser'
1422 +  objectclass within LDAP and part of the group the SSH server is in). 
1423 +
1424 +  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 
1425 +  so each user can change it as much as he wants). 
1426 +
1427 +  Blocking a user account can be done directly from the LDAP (if sshd is using RSAAuth + ldap only).
1428 +
1429 +- RULES :  
1430 +  Entry in the LDAP server must respect 'posixAccount' and 'ldapPublicKey' which are defined in core.schema. 
1431 +  and the additionnal lpk.schema.
1432 +
1433 +  This patch could allow a smooth transition between standard auth (/etc/passwd) and complete LDAP based authentication 
1434 +  (pamldap, nss_ldap, etc..).
1435 +
1436 +  This can be an alternative to other (old?/expensive?) authentication methods (Kerberos/SecurID/..).
1437 +  
1438 +  Referring to schema at the beginning of this file if user 'eau' is only in group 'unix'
1439 +  'eau' would ONLY access 'server1', 'server2', 'server3' AND 'server4' BUT NOT 'server5'.
1440 +  If you then modify the LDAP 'mail' group entry to add 'memberUid: eau' THEN user 'eau' would be able
1441 +  to log in 'server5' (i hope you got the idea, my english is bad :).
1442 +
1443 +  Each server's sshd is patched and configured to ask the public key and the group infos in the LDAP
1444 +  server.
1445 +  When you want to allow a new user to have access to the server parc, you just add him an account on 
1446 +  your servers, you add his public key into his entry on the LDAP server, it's done. 
1447 +
1448 +  Because sshds are looking public keys into the LDAP directly instead of a file ($HOME/.ssh/authorized_keys).
1449 +
1450 +  When the user needs to change his passphrase he can do it directly from his workstation by changing 
1451 +  his own key set lock passphrase, and all servers are automatically aware.
1452
1453 +  With a CAREFUL LDAP server configuration you could allow a user to add/delete/modify his own entry himself
1454 +  so he can add/modify/delete himself his public key when needed.
1455 +
1456 +­ FLAWS :
1457 +  LDAP must be well configured, getting the public key of some user is not a problem, but if anonymous LDAP 
1458 +  allow write to users dn, somebody could replace someuser's public key by its own and impersonate some 
1459 +  of your users in all your server farm be VERY CAREFUL.
1460 +  
1461 +  MITM attack when sshd is requesting the public key, could lead to a compromise of your servers allowing login 
1462 +  as the impersonnated user.
1463 +
1464 +  If LDAP server is down then, fallback on passwd auth.
1465 +  
1466 +  the ldap code part has not been well audited yet.
1467 +
1468 +- LDAP USER ENTRY EXAMPLES (LDIF Format, look in users.ldif)
1469 +    --- CUT HERE ---
1470 +    dn: uid=jdoe,ou=users,dc=foobar,dc=net
1471 +    objectclass: top
1472 +    objectclass: person
1473 +    objectclass: organizationalPerson
1474 +    objectclass: posixAccount
1475 +    objectclass: ldapPublicKey
1476 +    description: My account
1477 +    cn: John Doe
1478 +    sn: John Doe
1479 +    uid: jdoe
1480 +    uidNumber: 100
1481 +    gidNumber: 100
1482 +    homeDirectory: /home/jdoe
1483 +    sshPublicKey: ssh-dss AAAAB3NzaC1kc3MAAAEBAOvL8pREUg9wSy/8+hQJ54YF3AXkB0OZrXB....
1484 +    [...]
1485 +    --- CUT HERE ---
1486 +
1487 +- LDAP GROUP ENTRY EXAMPLES (LDIF Format, look in groups.ldif)
1488 +    --- CUT HERE ---
1489 +    dn: cn=unix,ou=groups,dc=cuckoos,dc=net
1490 +    objectclass: top
1491 +    objectclass: posixGroup
1492 +    description: Unix based servers group
1493 +    cn: unix
1494 +    gidNumber: 1002
1495 +    memberUid: jdoe
1496 +    memberUid: user1
1497 +    memberUid: user2
1498 +    [...]
1499 +    --- CUT HERE ---
1500 +
1501 +>> FYI: << 
1502 +Multiple 'sshPublicKey' in a user entry are allowed, as well as multiple 'memberUid' attributes in a group entry
1503 +
1504 +- COMPILING:
1505 +  1. Apply the patch
1506 +  2. ./configure --with-your-options --with-ldap=/prefix/to/ldap_libs_and_includes
1507 +  3. make
1508 +  4. it's done.
1509 +
1510 +- BLA :
1511 +  I hope this could help, and i hope to be clear enough,, or give ideas.  questions/comments/improvements are welcome.
1512 +  
1513 +- TODO :
1514 +  Redesign differently.
1515 +
1516 +- DOCS/LINK :
1517 +  http://pacsec.jp/core05/psj05-barisani-en.pdf
1518 +  http://fritz.potsdam.edu/projects/openssh-lpk/
1519 +  http://fritz.potsdam.edu/projects/sshgate/
1520 +  http://dev.inversepath.com/trac/openssh-lpk
1521 +  http://lam.sf.net/ ( http://lam.sourceforge.net/documentation/supportedSchemas.htm )
1522 +
1523 +- CONTRIBUTORS/IDEAS/GREETS :
1524 +  - Falk Siemonsmeier.
1525 +  - Jacob Rief.
1526 +  - Michael Durchgraf.
1527 +  - frederic peters.
1528 +  - Finlay dobbie.
1529 +  - Stefan Fisher.
1530 +  - Robin H. Johnson.
1531 +  - Adrian Bridgett.
1532 +
1533 +- CONTACT :
1534 +  - Eric AUGE <eau@phear.org>
1535 +  - Andrea Barisani <andrea@inversepath.com>
1536 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/servconf.c openssh-5.1p1+lpk/servconf.c
1537 --- openssh-5.1p1.orig/servconf.c       2008-07-03 20:51:12.000000000 -0700
1538 +++ openssh-5.1p1+lpk/servconf.c        2008-08-23 15:02:47.000000000 -0700
1539 @@ -42,6 +42,10 @@
1540  #include "channels.h"
1541  #include "groupaccess.h"
1542  
1543 +#ifdef WITH_LDAP_PUBKEY
1544 +#include "ldapauth.h"
1545 +#endif
1546 +
1547  static void add_listen_addr(ServerOptions *, char *, int);
1548  static void add_one_listen_addr(ServerOptions *, char *, int);
1549  
1550 @@ -127,6 +131,25 @@
1551         options->zero_knowledge_password_authentication = -1;
1552         options->revoked_keys_file = NULL;
1553         options->trusted_user_ca_keys = NULL;
1554 +#ifdef WITH_LDAP_PUBKEY
1555 +       /* XXX dirty */
1556 +       options->lpk.ld = NULL;
1557 +       options->lpk.on = -1;
1558 +       options->lpk.servers = NULL;
1559 +       options->lpk.u_basedn = NULL;
1560 +       options->lpk.g_basedn = NULL;
1561 +       options->lpk.binddn = NULL;
1562 +       options->lpk.bindpw = NULL;
1563 +       options->lpk.sgroup = NULL;
1564 +       options->lpk.filter = NULL;
1565 +       options->lpk.fgroup = NULL;
1566 +       options->lpk.l_conf = NULL;
1567 +       options->lpk.tls = -1;
1568 +       options->lpk.b_timeout.tv_sec = -1;
1569 +       options->lpk.s_timeout.tv_sec = -1;
1570 +       options->lpk.flags = FLAG_EMPTY;
1571 +#endif
1572 +
1573  }
1574  
1575  void
1576 @@ -258,6 +281,32 @@
1577                 options->permit_tun = SSH_TUNMODE_NO;
1578         if (options->zero_knowledge_password_authentication == -1)
1579                 options->zero_knowledge_password_authentication = 0;
1580 +#ifdef WITH_LDAP_PUBKEY
1581 +       if (options->lpk.on == -1)
1582 +           options->lpk.on = _DEFAULT_LPK_ON;
1583 +       if (options->lpk.servers == NULL)
1584 +           options->lpk.servers = _DEFAULT_LPK_SERVERS;
1585 +       if (options->lpk.u_basedn == NULL)
1586 +           options->lpk.u_basedn = _DEFAULT_LPK_UDN;
1587 +       if (options->lpk.g_basedn == NULL)
1588 +           options->lpk.g_basedn = _DEFAULT_LPK_GDN;
1589 +       if (options->lpk.binddn == NULL)
1590 +           options->lpk.binddn = _DEFAULT_LPK_BINDDN;
1591 +       if (options->lpk.bindpw == NULL)
1592 +           options->lpk.bindpw = _DEFAULT_LPK_BINDPW;
1593 +       if (options->lpk.sgroup == NULL)
1594 +           options->lpk.sgroup = _DEFAULT_LPK_SGROUP;
1595 +       if (options->lpk.filter == NULL)
1596 +           options->lpk.filter = _DEFAULT_LPK_FILTER;
1597 +       if (options->lpk.tls == -1)
1598 +           options->lpk.tls = _DEFAULT_LPK_TLS;
1599 +       if (options->lpk.b_timeout.tv_sec == -1)
1600 +           options->lpk.b_timeout.tv_sec = _DEFAULT_LPK_BTIMEOUT;
1601 +       if (options->lpk.s_timeout.tv_sec == -1)
1602 +           options->lpk.s_timeout.tv_sec = _DEFAULT_LPK_STIMEOUT;
1603 +       if (options->lpk.l_conf == NULL)
1604 +           options->lpk.l_conf = _DEFAULT_LPK_LDP;
1605 +#endif
1606  
1607         /* Turn privilege separation on by default */
1608         if (use_privsep == -1)
1609 @@ -303,6 +352,12 @@
1610         sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
1611         sUsePrivilegeSeparation, sAllowAgentForwarding,
1612         sDeprecated, sUnsupported
1613 +#ifdef WITH_LDAP_PUBKEY
1614 +       ,sLdapPublickey, sLdapServers, sLdapUserDN
1615 +       ,sLdapGroupDN, sBindDN, sBindPw, sMyGroup
1616 +       ,sLdapFilter, sForceTLS, sBindTimeout
1617 +       ,sSearchTimeout, sLdapConf
1618 +#endif
1619  } ServerOpCodes;
1620  
1621  #define SSHCFG_GLOBAL  0x01    /* allowed in main section of sshd_config */
1622 @@ -408,6 +463,20 @@
1623         { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
1624         { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
1625         { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
1626 +#ifdef WITH_LDAP_PUBKEY
1627 +       { _DEFAULT_LPK_TOKEN, sLdapPublickey, SSHCFG_GLOBAL },
1628 +       { _DEFAULT_SRV_TOKEN, sLdapServers, SSHCFG_GLOBAL },
1629 +       { _DEFAULT_USR_TOKEN, sLdapUserDN, SSHCFG_GLOBAL },
1630 +       { _DEFAULT_GRP_TOKEN, sLdapGroupDN, SSHCFG_GLOBAL },
1631 +       { _DEFAULT_BDN_TOKEN, sBindDN, SSHCFG_GLOBAL },
1632 +       { _DEFAULT_BPW_TOKEN, sBindPw, SSHCFG_GLOBAL },
1633 +       { _DEFAULT_MYG_TOKEN, sMyGroup, SSHCFG_GLOBAL },
1634 +       { _DEFAULT_FIL_TOKEN, sLdapFilter, SSHCFG_GLOBAL },
1635 +       { _DEFAULT_TLS_TOKEN, sForceTLS, SSHCFG_GLOBAL },
1636 +       { _DEFAULT_BTI_TOKEN, sBindTimeout, SSHCFG_GLOBAL },
1637 +       { _DEFAULT_STI_TOKEN, sSearchTimeout, SSHCFG_GLOBAL },
1638 +       { _DEFAULT_LDP_TOKEN, sLdapConf, SSHCFG_GLOBAL },
1639 +#endif
1640         { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
1641         { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
1642         { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
1643 @@ -1294,6 +1363,107 @@
1644                 while (arg)
1645                     arg = strdelim(&cp);
1646                 break;
1647 +#ifdef WITH_LDAP_PUBKEY
1648 +       case sLdapPublickey:
1649 +               intptr = &options->lpk.on;
1650 +               goto parse_flag;
1651 +       case sLdapServers:
1652 +               /* arg = strdelim(&cp); */
1653 +               p = line;
1654 +               while(*p++);
1655 +               arg = p;
1656 +               if (!arg || *arg == '\0')
1657 +                   fatal("%s line %d: missing ldap server",filename,linenum);
1658 +               arg[strlen(arg)] = '\0';
1659 +               if ((options->lpk.servers = ldap_parse_servers(arg)) == NULL)
1660 +                   fatal("%s line %d: error in ldap servers", filename, linenum);
1661 +               memset(arg,0,strlen(arg));
1662 +               break;
1663 +       case sLdapUserDN:
1664 +               arg = cp;
1665 +               if (!arg || *arg == '\0')
1666 +                   fatal("%s line %d: missing ldap server",filename,linenum);
1667 +               arg[strlen(arg)] = '\0';
1668 +               options->lpk.u_basedn = xstrdup(arg);
1669 +               memset(arg,0,strlen(arg));
1670 +               break;
1671 +       case sLdapGroupDN:
1672 +               arg = cp;
1673 +               if (!arg || *arg == '\0')
1674 +                   fatal("%s line %d: missing ldap server",filename,linenum);
1675 +               arg[strlen(arg)] = '\0';
1676 +               options->lpk.g_basedn = xstrdup(arg);
1677 +               memset(arg,0,strlen(arg));
1678 +               break;
1679 +       case sBindDN:
1680 +               arg = cp;
1681 +               if (!arg || *arg == '\0')
1682 +                   fatal("%s line %d: missing binddn",filename,linenum);
1683 +               arg[strlen(arg)] = '\0';
1684 +               options->lpk.binddn = xstrdup(arg);
1685 +               memset(arg,0,strlen(arg));
1686 +               break;
1687 +       case sBindPw:
1688 +               arg = cp;
1689 +               if (!arg || *arg == '\0')
1690 +                   fatal("%s line %d: missing bindpw",filename,linenum);
1691 +               arg[strlen(arg)] = '\0';
1692 +               options->lpk.bindpw = xstrdup(arg);
1693 +               memset(arg,0,strlen(arg));
1694 +               break;
1695 +       case sMyGroup:
1696 +               arg = cp;
1697 +               if (!arg || *arg == '\0')
1698 +                   fatal("%s line %d: missing groupname",filename, linenum);
1699 +               arg[strlen(arg)] = '\0';
1700 +               options->lpk.sgroup = xstrdup(arg);
1701 +               if (options->lpk.sgroup)
1702 +                   options->lpk.fgroup = ldap_parse_groups(options->lpk.sgroup);
1703 +               memset(arg,0,strlen(arg));
1704 +               break;
1705 +       case sLdapFilter:
1706 +               arg = cp;
1707 +               if (!arg || *arg == '\0')
1708 +                   fatal("%s line %d: missing filter",filename, linenum);
1709 +               arg[strlen(arg)] = '\0';
1710 +               options->lpk.filter = xstrdup(arg);
1711 +               memset(arg,0,strlen(arg));
1712 +               break;
1713 +       case sForceTLS:
1714 +               intptr = &options->lpk.tls;
1715 +               arg = strdelim(&cp);
1716 +               if (!arg || *arg == '\0')
1717 +                       fatal("%s line %d: missing yes/no argument.",
1718 +                           filename, linenum);
1719 +               value = 0;      /* silence compiler */
1720 +               if (strcmp(arg, "yes") == 0)
1721 +                       value = 1;
1722 +               else if (strcmp(arg, "no") == 0)
1723 +                       value = 0;
1724 +               else if (strcmp(arg, "try") == 0)
1725 +                       value = -1;
1726 +               else
1727 +                       fatal("%s line %d: Bad yes/no argument: %s",
1728 +                               filename, linenum, arg);
1729 +               if (*intptr == -1)
1730 +                       *intptr = value;
1731 +               break;
1732 +       case sBindTimeout:
1733 +               intptr = (int *) &options->lpk.b_timeout.tv_sec;
1734 +               goto parse_int;
1735 +       case sSearchTimeout:
1736 +               intptr = (int *) &options->lpk.s_timeout.tv_sec;
1737 +               goto parse_int;
1738 +               break;
1739 +       case sLdapConf:
1740 +               arg = cp;
1741 +               if (!arg || *arg == '\0')
1742 +                   fatal("%s line %d: missing LpkLdapConf", filename, linenum);
1743 +               arg[strlen(arg)] = '\0';
1744 +               options->lpk.l_conf = xstrdup(arg);
1745 +               memset(arg, 0, strlen(arg));
1746 +               break;
1747 +#endif
1748  
1749         default:
1750                 fatal("%s line %d: Missing handler for opcode %s (%d)",
1751 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/servconf.h openssh-5.1p1+lpk/servconf.h
1752 --- openssh-5.1p1.orig/servconf.h       2008-06-10 06:01:51.000000000 -0700
1753 +++ openssh-5.1p1+lpk/servconf.h        2008-08-23 15:02:47.000000000 -0700
1754 @@ -16,6 +16,10 @@
1755  #ifndef SERVCONF_H
1756  #define SERVCONF_H
1757  
1758 +#ifdef WITH_LDAP_PUBKEY
1759 +#include "ldapauth.h"
1760 +#endif
1761 +
1762  #define MAX_PORTS              256     /* Max # ports. */
1763  
1764  #define MAX_ALLOW_USERS                256     /* Max # users on allow list. */
1765 @@ -145,6 +149,9 @@
1766         int     use_pam;                /* Enable auth via PAM */
1767  
1768         int     permit_tun;
1769 +#ifdef WITH_LDAP_PUBKEY
1770 +        ldap_opt_t lpk;
1771 +#endif
1772  
1773         int     num_permitted_opens;
1774  
1775 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/sshd.c openssh-5.1p1+lpk/sshd.c
1776 --- openssh-5.1p1.orig/sshd.c   2008-07-11 00:36:49.000000000 -0700
1777 +++ openssh-5.1p1+lpk/sshd.c    2008-08-23 15:02:47.000000000 -0700
1778 @@ -127,6 +127,10 @@
1779  int deny_severity;
1780  #endif /* LIBWRAP */
1781  
1782 +#ifdef WITH_LDAP_PUBKEY
1783 +#include "ldapauth.h"
1784 +#endif
1785 +
1786  #ifndef O_NOCTTY
1787  #define O_NOCTTY       0
1788  #endif
1789 @@ -1484,6 +1488,16 @@
1790                 exit(1);
1791         }
1792  
1793 +#ifdef WITH_LDAP_PUBKEY
1794 +    /* ldap_options_print(&options.lpk); */
1795 +    /* XXX initialize/check ldap connection and set *LD */
1796 +    if (options.lpk.on) {
1797 +        if (options.lpk.l_conf && (ldap_parse_lconf(&options.lpk) < 0) )
1798 +            error("[LDAP] could not parse %s", options.lpk.l_conf);
1799 +        if (ldap_connect(&options.lpk) < 0)
1800 +            error("[LDAP] could not initialize ldap connection");
1801 +    }
1802 +#endif
1803         debug("sshd version %.100s", SSH_RELEASE);
1804  
1805         /* Store privilege separation user for later use if required. */
1806 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/sshd_config openssh-5.1p1+lpk/sshd_config
1807 --- openssh-5.1p1.orig/sshd_config      2008-07-02 05:35:43.000000000 -0700
1808 +++ openssh-5.1p1+lpk/sshd_config       2008-08-23 15:02:47.000000000 -0700
1809 @@ -109,6 +109,21 @@
1810  # no default banner path
1811  #Banner none
1812  
1813 +# here are the new patched ldap related tokens
1814 +# entries in your LDAP must have posixAccount & ldapPublicKey objectclass
1815 +#UseLPK yes
1816 +#LpkLdapConf /etc/ldap.conf
1817 +#LpkServers  ldap://10.1.7.1/ ldap://10.1.7.2/
1818 +#LpkUserDN   ou=users,dc=phear,dc=org
1819 +#LpkGroupDN  ou=groups,dc=phear,dc=org
1820 +#LpkBindDN cn=Manager,dc=phear,dc=org
1821 +#LpkBindPw secret
1822 +#LpkServerGroup mail
1823 +#LpkFilter (hostAccess=master.phear.org)
1824 +#LpkForceTLS no
1825 +#LpkSearchTimelimit 3
1826 +#LpkBindTimelimit 3
1827 +
1828  # override default of no subsystems
1829  Subsystem      sftp    /usr/libexec/sftp-server
1830  
1831 diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/sshd_config.5 openssh-5.1p1+lpk/sshd_config.5
1832 --- openssh-5.1p1.orig/sshd_config.5    2008-07-02 05:35:43.000000000 -0700
1833 +++ openssh-5.1p1+lpk/sshd_config.5     2008-08-23 15:02:47.000000000 -0700
1834 @@ -1003,6 +1003,62 @@
1835  program.
1836  The default is
1837  .Pa /usr/X11R6/bin/xauth .
1838 +.It Cm UseLPK
1839 +Specifies whether LDAP public key retrieval must be used or not. It allow
1840 +an easy centralisation of public keys within an LDAP directory. The argument must be
1841 +.Dq yes
1842 +or
1843 +.Dq no .
1844 +.It Cm LpkLdapConf
1845 +Specifies whether LDAP Public keys should parse the specified ldap.conf file
1846 +instead of sshd_config Tokens. The argument must be a valid path to an ldap.conf
1847 +file like
1848 +.Pa /etc/ldap.conf
1849 +.It Cm LpkServers
1850 +Specifies LDAP one or more [:space:] separated server's url the following form may be used:
1851 +.Pp
1852 +LpkServers ldaps://127.0.0.1 ldap://127.0.0.2 ldap://127.0.0.3
1853 +.It Cm LpkUserDN
1854 +Specifies the LDAP user DN.
1855 +.Pp
1856 +LpkUserDN ou=users,dc=phear,dc=org
1857 +.It Cm LpkGroupDN
1858 +Specifies the LDAP groups DN.
1859 +.Pp
1860 +LpkGroupDN ou=groups,dc=phear,dc=org
1861 +.It Cm LpkBindDN
1862 +Specifies the LDAP bind DN to use if necessary.
1863 +.Pp
1864 +LpkBindDN cn=Manager,dc=phear,dc=org
1865 +.It Cm LpkBindPw
1866 +Specifies the LDAP bind credential. 
1867 +.Pp
1868 +LpkBindPw secret
1869 +.It Cm LpkServerGroup
1870 +Specifies one or more [:space:] separated group the server is part of. 
1871 +.Pp
1872 +LpkServerGroup unix mail prod
1873 +.It Cm LpkFilter
1874 +Specifies an additional LDAP filter to use for finding SSH keys
1875 +.Pp
1876 +LpkFilter (hostAccess=master.phear.org)
1877 +.It Cm LpkForceTLS
1878 +Specifies if the LDAP server connection must be tried, forced or not used. The argument must be 
1879 +.Dq yes
1880 +or
1881 +.Dq no
1882 +or
1883 +.Dq try .
1884 +.It Cm LpkSearchTimelimit
1885 +Sepcifies the search time limit before the search is considered over. value is
1886 +in seconds.
1887 +.Pp
1888 +LpkSearchTimelimit 3
1889 +.It Cm LpkBindTimelimit
1890 +Sepcifies the bind time limit before the connection is considered dead. value is
1891 +in seconds.
1892 +.Pp
1893 +LpkBindTimelimit 3
1894  .El
1895  .Sh TIME FORMATS
1896  .Xr sshd 8
This page took 0.350339 seconds and 2 git commands to generate.