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