]> git.pld-linux.org Git - packages/openssh.git/blame - openssh-lpk.patch
- fixed
[packages/openssh.git] / openssh-lpk.patch
Content-type: text/html ]> git.pld-linux.org Git - packages/openssh.git/blame - openssh-lpk.patch


500 - Internal Server Error

Malformed UTF-8 character (fatal) at (eval 6) line 1, <$fd> line 2814.
This page took 0.305502 seconds and 4 git commands to generate.
CommitLineData
9a6dd2b6
JR
1This is a forward-port of the OpenSSH LPK support patch.
2
3It adds support for storing OpenSSH public keys in LDAP. It also supports
4grouping of machines in the LDAP data to limit users to specific machines.
5
6The latest homepage for the LPK project is:
7http://code.google.com/p/openssh-lpk/
8
9The 0.3.10 version of the patch includes a fix for 64-bit platforms, as
10discovered by Gentoo, where the bind timeout and search timeout values were not
11being parsed correctly: http://bugs.gentoo.org/210110
12
13Forward-ported-from: openssh-lpk-5.1p1-0.3.9.patch
14Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
15
16diff -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"
48dfc510 22
9a6dd2b6
JR
23+#ifdef WITH_LDAP_PUBKEY
24+#include "ldapauth.h"
25+#endif
48dfc510 26+
9a6dd2b6
JR
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;
48dfc510 56+
9a6dd2b6
JR
57+ for (cp = (char *)k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
58+ ;
59+ if (!*cp || *cp == '\n' || *cp == '#')
60+ continue;
48dfc510 61+
9a6dd2b6
JR
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+ }
48dfc510 82+
9a6dd2b6
JR
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);
48dfc510 89+
9a6dd2b6
JR
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
110diff -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);
48dfc510 128+
9a6dd2b6
JR
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;
48dfc510 135+
9a6dd2b6
JR
136+ for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
137+ ;
138+ if (!*cp || *cp == '\n' || *cp == '#')
139+ continue;
48dfc510 140+
9a6dd2b6
JR
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;
48dfc510 158+
9a6dd2b6
JR
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. */
48dfc510 165+
9a6dd2b6
JR
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;
48dfc510 169+
9a6dd2b6
JR
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);
210diff -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
223diff -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"
48dfc510 258+
9a6dd2b6
JR
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
48dfc510 299+
48dfc510 300+
9a6dd2b6
JR
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; }; }
48dfc510 306+
48dfc510 307+
9a6dd2b6 308+fi
48dfc510 309+
9a6dd2b6
JR
310+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
311+ fi
48dfc510 312+
48dfc510 313+
9a6dd2b6 314+fi
48dfc510 315+
48dfc510 316+
9a6dd2b6
JR
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"
328diff -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
48dfc510 341+
9a6dd2b6
JR
342+ if test "x$withval" != "xyes" ; then
343+ CPPFLAGS="$CPPFLAGS -I${withval}/include"
344+ LDFLAGS="$LDFLAGS -L${withval}/lib"
345+ fi
48dfc510 346+
9a6dd2b6
JR
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+)
48dfc510 365+
9a6dd2b6
JR
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"
377diff -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+ */
48dfc510 384+
9a6dd2b6
JR
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+ */
48dfc510 405+
9a6dd2b6 406+#include "includes.h"
48dfc510 407+
9a6dd2b6 408+#ifdef WITH_LDAP_PUBKEY
48dfc510 409+
9a6dd2b6
JR
410+#include <stdio.h>
411+#include <stdlib.h>
412+#include <unistd.h>
413+#include <string.h>
48dfc510 414+
9a6dd2b6
JR
415+#include "ldapauth.h"
416+#include "log.h"
48dfc510 417+
9a6dd2b6
JR
418+static char *attrs[] = {
419+ PUBKEYATTR,
420+ NULL
421+};
48dfc510 422+
9a6dd2b6
JR
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)
48dfc510 432+
9a6dd2b6
JR
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+ */
48dfc510 453+
9a6dd2b6
JR
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+ */
48dfc510 465+
9a6dd2b6
JR
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 : ""))
48dfc510 476+
9a6dd2b6
JR
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;
48dfc510 482+
9a6dd2b6
JR
483+ /* leading white spaces are ignored */
484+ num = strspn(ptr, charset);
485+ ptr += num;
48dfc510 486+
9a6dd2b6
JR
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+}
48dfc510 498+
9a6dd2b6 499+void ldap_close(ldap_opt_t * ldap) {
48dfc510 500+
9a6dd2b6
JR
501+ if (!ldap)
502+ return;
48dfc510 503+
9a6dd2b6
JR
504+ if ( ldap_unbind_ext(ldap->ld, NULL, NULL) < 0)
505+ ldap_perror(ldap->ld, "ldap_unbind()");
48dfc510 506+
9a6dd2b6
JR
507+ ldap->ld = NULL;
508+ FLAG_SET_DISCONNECTED(ldap->flags);
48dfc510 509+
9a6dd2b6
JR
510+ return;
511+}
48dfc510 512+
9a6dd2b6
JR
513+/* init && bind */
514+int ldap_connect(ldap_opt_t * ldap) {
515+ int version = LDAP_VERSION3;
48dfc510 516+
9a6dd2b6
JR
517+ if (!ldap->servers)
518+ return FAILURE;
48dfc510 519+
9a6dd2b6
JR
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+ }
48dfc510 526+
9a6dd2b6
JR
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+ }
48dfc510 531+
9a6dd2b6
JR
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+ }
48dfc510 539+
9a6dd2b6
JR
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;
48dfc510 547+
9a6dd2b6
JR
548+ ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
549+ if (!ldap->ld) {
550+ ldap_perror(ldap->ld, "ldap_init()");
551+ return FAILURE;
552+ }
48dfc510 553+
9a6dd2b6
JR
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+ }
48dfc510 560+
48dfc510 561+
9a6dd2b6
JR
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+ }
48dfc510 566+
9a6dd2b6
JR
567+ /* says it is connected */
568+ FLAG_SET_CONNECTED(ldap->flags);
48dfc510 569+
9a6dd2b6
JR
570+ return SUCCESS;
571+}
48dfc510 572+
9a6dd2b6
JR
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;
48dfc510 580+
9a6dd2b6
JR
581+ rc = snprintf(h, size, "%s:%d ", host, port);
582+ if (rc == -1)
583+ return NULL;
584+ return h;
585+}
48dfc510 586+
9a6dd2b6
JR
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;
48dfc510 592+
9a6dd2b6
JR
593+ num = strspn(ptr, charset);
594+ ptr += num;
48dfc510 595+
9a6dd2b6
JR
596+ while ((num = strcspn(ptr, charset))) {
597+ count++;
598+ ptr += num;
599+ ptr++;
600+ }
48dfc510 601+
9a6dd2b6
JR
602+ return count;
603+}
48dfc510 604+
9a6dd2b6
JR
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;
48dfc510 612+
9a6dd2b6
JR
613+ if ((!groups)||(!buffer))
614+ return NULL;
48dfc510 615+
9a6dd2b6
JR
616+ g = strdup(groups);
617+ if (!g) {
618+ free(buffer);
619+ return NULL;
620+ }
48dfc510 621+
9a6dd2b6
JR
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+ }
48dfc510 628+
9a6dd2b6
JR
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;
48dfc510 645+}
48dfc510 646+
9a6dd2b6
JR
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;
48dfc510 656+
9a6dd2b6
JR
657+ /* local copy of the arg */
658+ s = strdup(servers);
659+ if (!s)
660+ return NULL;
48dfc510 661+
9a6dd2b6
JR
662+ /* first separate into URL tokens */
663+ if ( tokenize(urls, sizeof(urls)/sizeof(*urls), s) < 0)
664+ return NULL;
48dfc510 665+
9a6dd2b6
JR
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+ }
48dfc510 674+
9a6dd2b6
JR
675+ /* now free(s) */
676+ free (s);
48dfc510 677+
9a6dd2b6
JR
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;
48dfc510 682+
9a6dd2b6
JR
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+ }
48dfc510 690+
9a6dd2b6
JR
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+ }
48dfc510 699+
9a6dd2b6
JR
700+ return s;
701+}
48dfc510 702+
9a6dd2b6
JR
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+}
48dfc510 719+
9a6dd2b6
JR
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+}
48dfc510 743+
9a6dd2b6
JR
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+}
48dfc510 750+
9a6dd2b6
JR
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;
48dfc510 756+
9a6dd2b6
JR
757+ if ((!k) || (!l))
758+ return NULL;
48dfc510 759+
9a6dd2b6
JR
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;
48dfc510 766+
9a6dd2b6
JR
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;
48dfc510 771+
9a6dd2b6
JR
772+ /* build filter for LDAP request */
773+ REQUEST_USER(filter, user, l->filter);
48dfc510 774+
9a6dd2b6
JR
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()");
48dfc510 782+
9a6dd2b6
JR
783+ free(filter);
784+ free(k);
48dfc510 785+
9a6dd2b6
JR
786+ /* XXX error on search, timeout etc.. close ask for reconnect */
787+ ldap_close(l);
48dfc510 788+
9a6dd2b6
JR
789+ return NULL;
790+ }
48dfc510 791+
9a6dd2b6
JR
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;
48dfc510 801+ }
48dfc510 802+
9a6dd2b6
JR
803+ if (i > 1)
804+ debug("[LDAP] duplicate entries, using the FIRST entry returned");
48dfc510 805+
9a6dd2b6
JR
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);
48dfc510 809+
9a6dd2b6
JR
810+ ldap_msgfree(res);
811+ return k;
812+}
48dfc510 813+
48dfc510 814+
9a6dd2b6
JR
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;
48dfc510 823+
9a6dd2b6
JR
824+ if ((!l->sgroup) || !(l->g_basedn))
825+ return 1;
48dfc510 826+
9a6dd2b6
JR
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;
48dfc510 833+
9a6dd2b6
JR
834+ /* quick check for attempts to be evil */
835+ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) ||
836+ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL))
48dfc510 837+ return FAILURE;
48dfc510 838+
9a6dd2b6
JR
839+ /* build filter for LDAP request */
840+ REQUEST_GROUP(filter, l->fgroup, user);
48dfc510 841+
9a6dd2b6
JR
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()");
48dfc510 849+
9a6dd2b6 850+ free(filter);
48dfc510 851+
9a6dd2b6
JR
852+ /* XXX error on search, timeout etc.. close ask for reconnect */
853+ ldap_close(l);
48dfc510 854+
9a6dd2b6 855+ return FAILURE;
48dfc510 856+ }
857+
9a6dd2b6 858+ free(filter);
48dfc510 859+
9a6dd2b6
JR
860+ /* check if any results */
861+ if (ldap_count_entries(l->ld, res) > 0) {
862+ ldap_msgfree(res);
863+ return 1;
48dfc510 864+ }
865+
9a6dd2b6
JR
866+ ldap_msgfree(res);
867+ return 0;
48dfc510 868+}
869+
9a6dd2b6
JR
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;
48dfc510 884+
9a6dd2b6
JR
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) {
48dfc510 893+
9a6dd2b6
JR
894+ if (*buf == '\n' || *buf == '#')
895+ continue;
48dfc510 896+
9a6dd2b6
JR
897+ k = buf;
898+ v = k;
899+ while (*v != '\0' && *v != ' ' && *v != '\t')
900+ v++;
48dfc510 901+
9a6dd2b6
JR
902+ if (*v == '\0')
903+ continue;
48dfc510 904+
9a6dd2b6 905+ *(v++) = '\0';
48dfc510 906+
9a6dd2b6
JR
907+ while (*v == ' ' || *v == '\t')
908+ v++;
48dfc510 909+
9a6dd2b6
JR
910+ li = strlen (v) - 1;
911+ while (v[li] == ' ' || v[li] == '\t' || v[li] == '\n')
912+ --li;
913+ v[li + 1] = '\0';
48dfc510 914+
9a6dd2b6
JR
915+ if (!strcasecmp (k, "uri")) {
916+ if ((l->servers = ldap_parse_servers(v)) == NULL) {
917+ fatal("error in ldap servers");
918+ return FAILURE;
919+ }
48dfc510 920+
9a6dd2b6
JR
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+ }
48dfc510 949+ }
48dfc510 950+
9a6dd2b6
JR
951+ fclose (lcd);
952+ return SUCCESS;
48dfc510 953+}
954+
9a6dd2b6
JR
955+#endif /* WITH_LDAP_PUBKEY */
956diff -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+ */
48dfc510 963+
9a6dd2b6
JR
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+ */
48dfc510 984+
9a6dd2b6
JR
985+#ifndef LDAPAUTH_H
986+#define LDAPAUTH_H
48dfc510 987+
9a6dd2b6 988+#define LDAP_DEPRECATED 1
48dfc510 989+
9a6dd2b6
JR
990+#include <string.h>
991+#include <time.h>
992+#include <ldap.h>
993+#include <lber.h>
48dfc510 994+
9a6dd2b6
JR
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"
48dfc510 1008+
9a6dd2b6
JR
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
48dfc510 1022+
9a6dd2b6
JR
1023+/* flags */
1024+#define FLAG_EMPTY 0x00000000
1025+#define FLAG_CONNECTED 0x00000001
48dfc510 1026+
9a6dd2b6
JR
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)
48dfc510 1031+
9a6dd2b6
JR
1032+/* defines */
1033+#define FAILURE -1
1034+#define SUCCESS 0
1035+#define PUBKEYATTR "sshPublicKey"
48dfc510 1036+
9a6dd2b6
JR
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"
48dfc510 1045+
9a6dd2b6
JR
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;
48dfc510 1064+
9a6dd2b6
JR
1065+typedef struct ldap_keys {
1066+ struct berval ** keys; /* the public keys retrieved */
1067+ unsigned int num; /* number of keys */
1068+} ldap_key_t;
48dfc510 1069+
48dfc510 1070+
9a6dd2b6
JR
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 *);
48dfc510 1082+
9a6dd2b6
JR
1083+#endif
1084diff -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 @@
48dfc510 1088+
9a6dd2b6
JR
1089+Post to ML -> User Made Quick Install Doc.
1090+Contribution from John Lane <john@lane.uk.net>
48dfc510 1091+
9a6dd2b6 1092+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48dfc510 1093+
9a6dd2b6
JR
1094+OpenSSH LDAP keystore Patch
1095+===========================
48dfc510 1096+
9a6dd2b6
JR
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
48dfc510 1100+
9a6dd2b6
JR
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.
48dfc510 1103+
9a6dd2b6 1104+(Assuming here that necessary build stuff is in $BUILD)
48dfc510 1105+
9a6dd2b6
JR
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
48dfc510 1115+
9a6dd2b6
JR
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
48dfc510 1120+
9a6dd2b6
JR
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+ ;;
48dfc510 1131+
9a6dd2b6
JR
1132+Re-start the sshd daemon:
1133+/etc/rc.d/init.d/sshd restart
48dfc510 1134+
9a6dd2b6
JR
1135+Install the additional LDAP schema
1136+cp $BUILD/openssh-lpk-0.2.schema /etc/openldap/schema/openssh.schema
48dfc510 1137+
9a6dd2b6
JR
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
48dfc510 1141+
9a6dd2b6
JR
1142+Re-start the LDAP server:
1143+/etc/rc.d/init.d/slapd restart
48dfc510 1144+
9a6dd2b6
JR
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
48dfc510 1148+
9a6dd2b6
JR
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
48dfc510 1155+
9a6dd2b6
JR
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+#
48dfc510 1172+
9a6dd2b6
JR
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
48dfc510 1193+
9a6dd2b6
JR
1194+# search result
1195+search: 3
1196+result: 0 Success
48dfc510 1197+
9a6dd2b6
JR
1198+# numResponses: 2
1199+# numEntries: 1
48dfc510 1200+
9a6dd2b6
JR
1201+Now start a ssh session to user "testuser" from usual ssh client (e.g.
1202+puTTY). Login should succeed.
48dfc510 1203+
9a6dd2b6
JR
1204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1205diff -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
28ece7ce
AM
1208@@ -91,7 +91,7 @@
1209 auth2-gss.o gss-serv.o gss-serv-krb5.o \
1210 loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
1211 audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \
1212- roaming_common.o roaming_serv.o
1213+ roaming_common.o roaming_serv.o ldapauth.o
9a6dd2b6 1214
28ece7ce
AM
1215 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
1216 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
9a6dd2b6
JR
1217diff -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+#
48dfc510 1227+
48dfc510 1228+
9a6dd2b6
JR
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 )
48dfc510 1234+
9a6dd2b6
JR
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+ )
1240diff -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+#
48dfc510 1251+
9a6dd2b6 1252+dn: cn=schema
48dfc510 1253+
9a6dd2b6
JR
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 )
48dfc510 1259+
9a6dd2b6
JR
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+ )
1265diff -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.
48dfc510 1272+
9a6dd2b6
JR
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.
48dfc510 1283+
9a6dd2b6
JR
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.
48dfc510 1294+
9a6dd2b6 1295+purposes of this patch:
48dfc510 1296+
9a6dd2b6
JR
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.
48dfc510 1302+
9a6dd2b6
JR
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)
48dfc510 1306+
9a6dd2b6 1307+example schema:
48dfc510 1308+
48dfc510 1309+
9a6dd2b6
JR
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...
48dfc510 1321+
9a6dd2b6 1322+- WHAT WE NEED :
48dfc510 1323+
9a6dd2b6
JR
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...
48dfc510 1348+
9a6dd2b6
JR
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
48dfc510 1364+
48dfc510 1365+
9a6dd2b6 1366+- HOW IT WORKS :
48dfc510 1367+
9a6dd2b6
JR
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).
48dfc510 1371+
9a6dd2b6
JR
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)
48dfc510 1376+
9a6dd2b6
JR
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).
48dfc510 1379+
9a6dd2b6
JR
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
48dfc510 1390+
9a6dd2b6
JR
1391