]> git.pld-linux.org Git - packages/openssh.git/blame - openssh-lpk.patch
- up to 5.9p1 (lpk patch needs update; builds --without ldap only for now)
[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 2868.
This page took 3.416477 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;
afde20c1
AM
30@@ -272,9 +272,97 @@
31 {
32 char *file;
33 u_int i, allowed = 0;
9a6dd2b6
JR
34+#ifdef WITH_LDAP_PUBKEY
35+ ldap_key_t * k;
36+ unsigned int i = 0;
37+#endif
38
9a6dd2b6
JR
39 temporarily_use_uid(pw);
40
41+#ifdef WITH_LDAP_PUBKEY
afde20c1
AM
42+ /* here is the job */
43+ key = key_new(KEY_RSA1);
44+
9a6dd2b6 45+ if (options.lpk.on) {
afde20c1
AM
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) {
9a6dd2b6 49+ for (i = 0 ; i < k->num ; i++) {
9a6dd2b6 50+ char *cp, *options = NULL;
48dfc510 51+
afde20c1 52+ for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
9a6dd2b6
JR
53+ ;
54+ if (!*cp || *cp == '\n' || *cp == '#')
55+ continue;
48dfc510 56+
afde20c1
AM
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') {
9a6dd2b6 64+ int quoted = 0;
9a6dd2b6
JR
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+ }
afde20c1
AM
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;
9a6dd2b6 79+ }
afde20c1 80+ /* cp now points to the comment part. */
48dfc510 81+
afde20c1
AM
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;
48dfc510 85+
afde20c1
AM
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+ }
9a6dd2b6
JR
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
afde20c1
AM
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);
9a6dd2b6
JR
128diff -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);
48dfc510 146+
9a6dd2b6
JR
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;
48dfc510 153+
9a6dd2b6
JR
154+ for (cp = k->keys[i]->bv_val; *cp == ' ' || *cp == '\t'; cp++)
155+ ;
156+ if (!*cp || *cp == '\n' || *cp == '#')
157+ continue;
48dfc510 158+
9a6dd2b6
JR
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;
48dfc510 176+
9a6dd2b6
JR
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. */
48dfc510 183+
9a6dd2b6
JR
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;
48dfc510 187+
9a6dd2b6
JR
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);
228diff -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
f1344723
CM
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 @@
9a6dd2b6
JR
244 --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH)
245 --with-libedit[=PATH] Enable libedit support for sftp
f1344723 246 --with-audit=module Enable audit support (modules=debug,bsm,linux)
9a6dd2b6
JR
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
f1344723 251@@ -12198,6 +12199,85 @@
9a6dd2b6
JR
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"
48dfc510 275+
9a6dd2b6
JR
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
48dfc510 316+
48dfc510 317+
9a6dd2b6
JR
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; }; }
48dfc510 323+
48dfc510 324+
9a6dd2b6 325+fi
48dfc510 326+
9a6dd2b6
JR
327+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
328+ fi
48dfc510 329+
48dfc510 330+
9a6dd2b6 331+fi
48dfc510 332+
48dfc510 333+
9a6dd2b6
JR
334
335
336
f1344723 337@@ -31970,6 +32050,7 @@
9a6dd2b6
JR
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"
345diff -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
48dfc510 358+
9a6dd2b6
JR
359+ if test "x$withval" != "xyes" ; then
360+ CPPFLAGS="$CPPFLAGS -I${withval}/include"
361+ LDFLAGS="$LDFLAGS -L${withval}/lib"
362+ fi
48dfc510 363+
9a6dd2b6
JR
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+)
48dfc510 382+
9a6dd2b6
JR
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"
394diff -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+ */
48dfc510 401+
9a6dd2b6
JR
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+ */
48dfc510 422+
9a6dd2b6 423+#include "includes.h"
48dfc510 424+
9a6dd2b6 425+#ifdef WITH_LDAP_PUBKEY
48dfc510 426+
9a6dd2b6
JR
427+#include <stdio.h>
428+#include <stdlib.h>
429+#include <unistd.h>
430+#include <string.h>
48dfc510 431+
9a6dd2b6
JR
432+#include "ldapauth.h"
433+#include "log.h"
48dfc510 434+
9a6dd2b6
JR
435+static char *attrs[] = {
436+ PUBKEYATTR,
437+ NULL
438+};
48dfc510 439+
9a6dd2b6
JR
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)
48dfc510 449+
9a6dd2b6
JR
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+ */
48dfc510 470+
9a6dd2b6
JR
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+ */
48dfc510 482+
9a6dd2b6
JR
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 : ""))
48dfc510 493+
9a6dd2b6
JR
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;
48dfc510 499+
9a6dd2b6
JR
500+ /* leading white spaces are ignored */
501+ num = strspn(ptr, charset);
502+ ptr += num;
48dfc510 503+
9a6dd2b6
JR
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+}
48dfc510 515+
9a6dd2b6 516+void ldap_close(ldap_opt_t * ldap) {
48dfc510 517+
9a6dd2b6
JR
518+ if (!ldap)
519+ return;
48dfc510 520+
9a6dd2b6
JR
521+ if ( ldap_unbind_ext(ldap->ld, NULL, NULL) < 0)
522+ ldap_perror(ldap->ld, "ldap_unbind()");
48dfc510 523+
9a6dd2b6
JR
524+ ldap->ld = NULL;
525+ FLAG_SET_DISCONNECTED(ldap->flags);
48dfc510 526+
9a6dd2b6
JR
527+ return;
528+}
48dfc510 529+
9a6dd2b6
JR
530+/* init && bind */
531+int ldap_connect(ldap_opt_t * ldap) {
532+ int version = LDAP_VERSION3;
48dfc510 533+
9a6dd2b6
JR
534+ if (!ldap->servers)
535+ return FAILURE;
48dfc510 536+
9a6dd2b6
JR
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+ }
48dfc510 543+
9a6dd2b6
JR
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+ }
48dfc510 548+
9a6dd2b6
JR
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+ }
48dfc510 556+
9a6dd2b6
JR
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;
48dfc510 564+
9a6dd2b6
JR
565+ ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
566+ if (!ldap->ld) {
567+ ldap_perror(ldap->ld, "ldap_init()");
568+ return FAILURE;
569+ }
48dfc510 570+
9a6dd2b6
JR
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+ }
48dfc510 577+
48dfc510 578+
9a6dd2b6
JR
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+ }
48dfc510 583+
9a6dd2b6
JR
584+ /* says it is connected */
585+ FLAG_SET_CONNECTED(ldap->flags);
48dfc510 586+
9a6dd2b6
JR
587+ return SUCCESS;
588+}
48dfc510 589+
9a6dd2b6
JR
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;
48dfc510 597+
9a6dd2b6
JR
598+ rc = snprintf(h, size, "%s:%d ", host, port);
599+ if (rc == -1)
600+ return NULL;
601+ return h;
602+}
48dfc510 603+
9a6dd2b6
JR
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;
48dfc510 609+
9a6dd2b6
JR
610+ num = strspn(ptr, charset);
611+ ptr += num;
48dfc510 612+
9a6dd2b6
JR
613+ while ((num = strcspn(ptr, charset))) {
614+ count++;
615+ ptr += num;
616+ ptr++;
617+ }
48dfc510 618+
9a6dd2b6
JR
619+ return count;
620+}
48dfc510 621+
9a6dd2b6
JR
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;
48dfc510 629+
9a6dd2b6
JR
630+ if ((!groups)||(!buffer))
631+ return NULL;
48dfc510 632+
9a6dd2b6
JR
633+ g = strdup(groups);
634+ if (!g) {
635+ free(buffer);
636+ return NULL;
637+ }
48dfc510 638+
9a6dd2b6
JR
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+ }
48dfc510 645+
9a6dd2b6
JR
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;
48dfc510 662+}
48dfc510 663+
9a6dd2b6
JR
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;
48dfc510 673+
9a6dd2b6
JR
674+ /* local copy of the arg */
675+ s = strdup(servers);
676+ if (!s)
677+ return NULL;
48dfc510 678+
9a6dd2b6
JR
679+ /* first separate into URL tokens */
680+ if ( tokenize(urls, sizeof(urls)/sizeof(*urls), s) < 0)
681+ return NULL;
48dfc510 682+
9a6dd2b6
JR
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+ }
48dfc510 691+
9a6dd2b6
JR
692+ /* now free(s) */
693+ free (s);
48dfc510 694+
9a6dd2b6
JR
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;
48dfc510 699+
9a6dd2b6
JR
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+ }
48dfc510 707+
9a6dd2b6
JR
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+ }
48dfc510 716+
9a6dd2b6
JR
717+ return s;
718+}
48dfc510 719+
9a6dd2b6
JR
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+}
48dfc510 736+
9a6dd2b6
JR
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+}
48dfc510 760+
9a6dd2b6
JR
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+}
48dfc510 767+
9a6dd2b6
JR
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;
48dfc510 773+
9a6dd2b6
JR
774+ if ((!k) || (!l))
775+ return NULL;
48dfc510 776+
9a6dd2b6
JR
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;
48dfc510 783+
9a6dd2b6
JR
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;
48dfc510 788+
9a6dd2b6
JR
789+ /* build filter for LDAP request */
790+ REQUEST_USER(filter, user, l->filter);
48dfc510 791+
9a6dd2b6
JR
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()");
48dfc510 799+
9a6dd2b6
JR
800+ free(filter);
801+ free(k);
48dfc510 802+
9a6dd2b6
JR
803+ /* XXX error on search, timeout etc.. close ask for reconnect */
804+ ldap_close(l);
48dfc510 805+
9a6dd2b6
JR
806+ return NULL;
807+ }
48dfc510 808+
9a6dd2b6
JR
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;
48dfc510 818+ }
48dfc510 819+
9a6dd2b6
JR
820+ if (i > 1)
821+ debug("[LDAP] duplicate entries, using the FIRST entry returned");
48dfc510 822+
9a6dd2b6
JR
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);
48dfc510 826+
9a6dd2b6
JR
827+ ldap_msgfree(res);
828+ return k;
829+}
48dfc510 830+
48dfc510 831+
9a6dd2b6
JR
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;
48dfc510 840+
9a6dd2b6
JR
841+ if ((!l->sgroup) || !(l->g_basedn))
842+ return 1;
48dfc510 843+
9a6dd2b6
JR
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;
48dfc510 850+
9a6dd2b6
JR
851+ /* quick check for attempts to be evil */
852+ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) ||
853+ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL))
48dfc510 854+ return FAILURE;
48dfc510 855+
9a6dd2b6
JR
856+ /* build filter for LDAP request */
857+ REQUEST_GROUP(filter, l->fgroup, user);
48dfc510 858+
9a6dd2b6
JR
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()");
48dfc510 866+
9a6dd2b6 867+ free(filter);
48dfc510 868+
9a6dd2b6
JR
869+ /* XXX error on search, timeout etc.. close ask for reconnect */
870+ ldap_close(l);
48dfc510 871+
9a6dd2b6 872+ return FAILURE;
48dfc510 873+ }
874+
9a6dd2b6 875+ free(filter);
48dfc510 876+
9a6dd2b6
JR
877+ /* check if any results */
878+ if (ldap_count_entries(l->ld, res) > 0) {
879+ ldap_msgfree(res);
880+ return 1;
48dfc510 881+ }
882+
9a6dd2b6
JR
883+ ldap_msgfree(res);
884+ return 0;
48dfc510 885+}
886+
9a6dd2b6
JR
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;
48dfc510 901+
9a6dd2b6
JR
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) {
48dfc510 910+
9a6dd2b6
JR
911+ if (*buf == '\n' || *buf == '#')
912+ continue;
48dfc510 913+
9a6dd2b6
JR
914+ k = buf;
915+ v = k;
916+ while (*v != '\0' && *v != ' ' && *v != '\t')
917+ v++;
48dfc510 918+
9a6dd2b6
JR
919+ if (*v == '\0')
920+ continue;
48dfc510 921+
9a6dd2b6 922+ *(v++) = '\0';
48dfc510 923+
9a6dd2b6
JR
924+ while (*v == ' ' || *v == '\t')
925+ v++;
48dfc510 926+
9a6dd2b6
JR
927+ li = strlen (v) - 1;
928+ while (v[li] == ' ' || v[li] == '\t' || v[li] == '\n')
929+ --li;
930+ v[li + 1] = '\0';
48dfc510 931+
9a6dd2b6
JR
932+ if (!strcasecmp (k, "uri")) {
933+ if ((l->servers = ldap_parse_servers(v)) == NULL) {
934+ fatal("error in ldap servers");
935+ return FAILURE;
936+ }
48dfc510 937+
9a6dd2b6
JR
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+ }
48dfc510 966+ }
48dfc510 967+
9a6dd2b6
JR
968+ fclose (lcd);
969+ return SUCCESS;
48dfc510 970+}
971+
9a6dd2b6
JR
972+#endif /* WITH_LDAP_PUBKEY */
973diff -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+ */
48dfc510 980+
9a6dd2b6
JR
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+ */
48dfc510 1001+
9a6dd2b6
JR
1002+#ifndef LDAPAUTH_H
1003+#define LDAPAUTH_H
48dfc510 1004+
9a6dd2b6 1005+#define LDAP_DEPRECATED 1
48dfc510 1006+
9a6dd2b6
JR
1007+#include <string.h>
1008+#include <time.h>
1009+#include <ldap.h>
1010+#include <lber.h>
48dfc510 1011+
9a6dd2b6
JR
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"
48dfc510 1025+
9a6dd2b6
JR
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
48dfc510 1039+
9a6dd2b6
JR
1040+/* flags */
1041+#define FLAG_EMPTY 0x00000000
1042+#define FLAG_CONNECTED 0x00000001
48dfc510 1043+
9a6dd2b6
JR
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)
48dfc510 1048+
9a6dd2b6
JR
1049+/* defines */
1050+#define FAILURE -1
1051+#define SUCCESS 0
1052+#define PUBKEYATTR "sshPublicKey"
48dfc510 1053+
9a6dd2b6
JR
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"
48dfc510 1062+
9a6dd2b6
JR
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;
48dfc510 1081+
9a6dd2b6
JR
1082+typedef struct ldap_keys {
1083+ struct berval ** keys; /* the public keys retrieved */
1084+ unsigned int num; /* number of keys */
1085+} ldap_key_t;
48dfc510 1086+
48dfc510 1087+
9a6dd2b6
JR
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 *);
48dfc510 1099+
9a6dd2b6
JR
1100+#endif
1101diff -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 @@
48dfc510 1105+
9a6dd2b6
JR
1106+Post to ML -> User Made Quick Install Doc.
1107+Contribution from John Lane <john@lane.uk.net>
48dfc510 1108+
9a6dd2b6 1109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48dfc510 1110+
9a6dd2b6
JR
1111+OpenSSH LDAP keystore Patch
1112+===========================
48dfc510 1113+
9a6dd2b6
JR
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
48dfc510 1117+
9a6dd2b6
JR
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.
48dfc510 1120+
9a6dd2b6 1121+(Assuming here that necessary build stuff is in $BUILD)
48dfc510 1122+
9a6dd2b6
JR
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
48dfc510 1132+
9a6dd2b6
JR
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
48dfc510 1137+
9a6dd2b6
JR
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+ ;;
48dfc510 1148+
9a6dd2b6
JR
1149+Re-start the sshd daemon:
1150+/etc/rc.d/init.d/sshd restart
48dfc510 1151+
9a6dd2b6
JR
1152+Install the additional LDAP schema
1153+cp $BUILD/openssh-lpk-0.2.schema /etc/openldap/schema/openssh.schema
48dfc510 1154+
9a6dd2b6
JR
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
48dfc510 1158+
9a6dd2b6
JR
1159+Re-start the LDAP server:
1160+/etc/rc.d/init.d/slapd restart
48dfc510 1161+
9a6dd2b6
JR
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
48dfc510 1165+
9a6dd2b6
JR
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
48dfc510 1172+
9a6dd2b6
JR
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+#
48dfc510 1189+
9a6dd2b6
JR
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
48dfc510 1210+
9a6dd2b6
JR
1211+# search result
1212+search: 3
1213+result: 0 Success
48dfc510 1214+
9a6dd2b6
JR
1215+# numResponses: 2
1216+# numEntries: 1
48dfc510 1217+
9a6dd2b6
JR
1218+Now start a ssh session to user "testuser" from usual ssh client (e.g.
1219+puTTY). Login should succeed.
48dfc510 1220+
9a6dd2b6 1221+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
f1344723
CM
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 @@
28ece7ce
AM
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 \
f1344723 1227 sftp-server.o sftp-common.o \
28ece7ce
AM
1228- roaming_common.o roaming_serv.o
1229+ roaming_common.o roaming_serv.o ldapauth.o
9a6dd2b6 1230
28ece7ce
AM
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
9a6dd2b6
JR
1233diff -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+#
48dfc510 1243+
48dfc510 1244+
9a6dd2b6
JR
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 )
48dfc510 1250+
9a6dd2b6
JR
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+ )
1256diff -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+#
48dfc510 1267+
9a6dd2b6 1268+dn: cn=schema
48dfc510 1269+
9a6dd2b6
JR
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 )
48dfc510 1275+
9a6dd2b6
JR
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+ )
1281diff -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.
48dfc510 1288+
9a6dd2b6
JR
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.
48dfc510 1299+
9a6dd2b6
JR
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.
48dfc510 1310+
9a6dd2b6 1311+purposes of this patch:
48dfc510 1312+
9a6dd2b6
JR
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.
48dfc510 1318+
9a6dd2b6
JR
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)
48dfc510 1322+
9a6dd2b6 1323+example schema:
48dfc510 1324+
48dfc510 1325+
9a6dd2b6
JR
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...
48dfc510 1337+
9a6dd2b6 1338+- WHAT WE NEED :
48dfc510 1339+
9a6dd2b6
JR
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...
48dfc510 1364+
9a6dd2b6
JR
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
48dfc510 1380+
48dfc510 1381+
9a6dd2b6 1382+- HOW IT WORKS :
48dfc510 1383+
9a6dd2b6
JR
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).
48dfc510 1387+
9a6dd2b6
JR
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)
48dfc510 1392+
9a6dd2b6
JR
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).
48dfc510 1395+
9a6dd2b6
JR
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
48dfc510 1406+
9a6dd2b6
JR
1407