]> git.pld-linux.org Git - packages/openssh.git/blame - openssh-lpk.patch
- typo
[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 2821.
This page took 0.320004 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
f1344723
CM
223--- openssh-5.7p1/configure.orig 2011-01-22 11:29:11.000000000 +0200
224+++ openssh-5.7p1/configure 2011-01-24 16:33:06.271393457 +0200
225@@ -1348,6 +1348,7 @@
9a6dd2b6
JR
226 --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH)
227 --with-libedit[=PATH] Enable libedit support for sftp
f1344723 228 --with-audit=module Enable audit support (modules=debug,bsm,linux)
9a6dd2b6
JR
229+ --with-ldap[=PATH] Enable LDAP pubkey support (optionally in PATH)
230 --with-ssl-dir=PATH Specify path to OpenSSL installation
231 --without-openssl-header-check Disable OpenSSL version consistency check
232 --with-ssl-engine Enable OpenSSL (hardware) ENGINE support
f1344723 233@@ -12198,6 +12199,85 @@
9a6dd2b6
JR
234 fi
235
236
237+# Check whether user wants LDAP support
238+LDAP_MSG="no"
239+
240+# Check whether --with-ldap was given.
241+if test "${with_ldap+set}" = set; then
242+ withval=$with_ldap;
243+ if test "x$withval" != "xno" ; then
244+
245+ if test "x$withval" != "xyes" ; then
246+ CPPFLAGS="$CPPFLAGS -I${withval}/include"
247+ LDFLAGS="$LDFLAGS -L${withval}/lib"
248+ fi
249+
250+
251+cat >>confdefs.h <<\_ACEOF
252+#define WITH_LDAP_PUBKEY 1
253+_ACEOF
254+
255+ LIBS="-lldap $LIBS"
256+ LDAP_MSG="yes"
48dfc510 257+
9a6dd2b6
JR
258+ { echo "$as_me:$LINENO: checking for LDAP support" >&5
259+echo $ECHO_N "checking for LDAP support... $ECHO_C" >&6; }
260+ cat >conftest.$ac_ext <<_ACEOF
261+/* confdefs.h. */
262+_ACEOF
263+cat confdefs.h >>conftest.$ac_ext
264+cat >>conftest.$ac_ext <<_ACEOF
265+/* end confdefs.h. */
266+#include <sys/types.h>
267+ #include <ldap.h>
268+int
269+main ()
270+{
271+(void)ldap_init(0, 0);
272+ ;
273+ return 0;
274+}
275+_ACEOF
276+rm -f conftest.$ac_objext
277+if { (ac_try="$ac_compile"
278+case "(($ac_try" in
279+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
280+ *) ac_try_echo=$ac_try;;
281+esac
282+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
283+ (eval "$ac_compile") 2>conftest.er1
284+ ac_status=$?
285+ grep -v '^ *+' conftest.er1 >conftest.err
286+ rm -f conftest.er1
287+ cat conftest.err >&5
288+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
289+ (exit $ac_status); } && {
290+ test -z "$ac_c_werror_flag" ||
291+ test ! -s conftest.err
292+ } && test -s conftest.$ac_objext; then
293+ { echo "$as_me:$LINENO: result: yes" >&5
294+echo "${ECHO_T}yes" >&6; }
295+else
296+ echo "$as_me: failed program was:" >&5
297+sed 's/^/| /' conftest.$ac_ext >&5
48dfc510 298+
48dfc510 299+
9a6dd2b6
JR
300+ { echo "$as_me:$LINENO: result: no" >&5
301+echo "${ECHO_T}no" >&6; }
302+ { { echo "$as_me:$LINENO: error: ** Incomplete or missing ldap libraries **" >&5
303+echo "$as_me: error: ** Incomplete or missing ldap libraries **" >&2;}
304+ { (exit 1); exit 1; }; }
48dfc510 305+
48dfc510 306+
9a6dd2b6 307+fi
48dfc510 308+
9a6dd2b6
JR
309+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
310+ fi
48dfc510 311+
48dfc510 312+
9a6dd2b6 313+fi
48dfc510 314+
48dfc510 315+
9a6dd2b6
JR
316
317
318
f1344723 319@@ -31970,6 +32050,7 @@
9a6dd2b6
JR
320 echo " Smartcard support: $SCARD_MSG"
321 echo " S/KEY support: $SKEY_MSG"
322 echo " TCP Wrappers support: $TCPW_MSG"
323+echo " LDAP support: $LDAP_MSG"
324 echo " MD5 password support: $MD5_MSG"
325 echo " libedit support: $LIBEDIT_MSG"
326 echo " Solaris process contract support: $SPC_MSG"
327diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/configure.ac openssh-5.1p1+lpk/configure.ac
328--- openssh-5.1p1.orig/configure.ac 2008-07-09 04:07:19.000000000 -0700
329+++ openssh-5.1p1+lpk/configure.ac 2008-08-23 15:02:47.000000000 -0700
330@@ -1299,6 +1299,37 @@
331 esac ]
332 )
333
334+# Check whether user wants LDAP support
335+LDAP_MSG="no"
336+AC_ARG_WITH(ldap,
337+ [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)],
338+ [
339+ if test "x$withval" != "xno" ; then
48dfc510 340+
9a6dd2b6
JR
341+ if test "x$withval" != "xyes" ; then
342+ CPPFLAGS="$CPPFLAGS -I${withval}/include"
343+ LDFLAGS="$LDFLAGS -L${withval}/lib"
344+ fi
48dfc510 345+
9a6dd2b6
JR
346+ AC_DEFINE([WITH_LDAP_PUBKEY], 1, [Enable LDAP pubkey support])
347+ LIBS="-lldap $LIBS"
348+ LDAP_MSG="yes"
349+
350+ AC_MSG_CHECKING([for LDAP support])
351+ AC_TRY_COMPILE(
352+ [#include <sys/types.h>
353+ #include <ldap.h>],
354+ [(void)ldap_init(0, 0);],
355+ [AC_MSG_RESULT(yes)],
356+ [
357+ AC_MSG_RESULT(no)
358+ AC_MSG_ERROR([** Incomplete or missing ldap libraries **])
359+ ]
360+ )
361+ fi
362+ ]
363+)
48dfc510 364+
9a6dd2b6
JR
365 dnl Checks for library functions. Please keep in alphabetical order
366 AC_CHECK_FUNCS( \
367 arc4random \
368@@ -4137,6 +4168,7 @@
369 echo " Smartcard support: $SCARD_MSG"
370 echo " S/KEY support: $SKEY_MSG"
371 echo " TCP Wrappers support: $TCPW_MSG"
372+echo " LDAP support: $LDAP_MSG"
373 echo " MD5 password support: $MD5_MSG"
374 echo " libedit support: $LIBEDIT_MSG"
375 echo " Solaris process contract support: $SPC_MSG"
376diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/ldapauth.c openssh-5.1p1+lpk/ldapauth.c
377--- openssh-5.1p1.orig/ldapauth.c 1969-12-31 16:00:00.000000000 -0800
378+++ openssh-5.1p1+lpk/ldapauth.c 2008-08-23 15:02:47.000000000 -0700
379@@ -0,0 +1,575 @@
380+/*
381+ * $Id$
382+ */
48dfc510 383+
9a6dd2b6
JR
384+/*
385+ *
386+ * Copyright (c) 2005, Eric AUGE <eau@phear.org>
387+ * All rights reserved.
388+ *
389+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
390+ *
391+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
392+ * 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.
393+ * 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.
394+ *
395+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
396+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
397+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
398+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
399+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
400+ * 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.
401+ *
402+ *
403+ */
48dfc510 404+
9a6dd2b6 405+#include "includes.h"
48dfc510 406+
9a6dd2b6 407+#ifdef WITH_LDAP_PUBKEY
48dfc510 408+
9a6dd2b6
JR
409+#include <stdio.h>
410+#include <stdlib.h>
411+#include <unistd.h>
412+#include <string.h>
48dfc510 413+
9a6dd2b6
JR
414+#include "ldapauth.h"
415+#include "log.h"
48dfc510 416+
9a6dd2b6
JR
417+static char *attrs[] = {
418+ PUBKEYATTR,
419+ NULL
420+};
48dfc510 421+
9a6dd2b6
JR
422+/* filter building infos */
423+#define FILTER_GROUP_PREFIX "(&(objectclass=posixGroup)"
424+#define FILTER_OR_PREFIX "(|"
425+#define FILTER_OR_SUFFIX ")"
426+#define FILTER_CN_PREFIX "(cn="
427+#define FILTER_CN_SUFFIX ")"
428+#define FILTER_UID_FORMAT "(memberUid=%s)"
429+#define FILTER_GROUP_SUFFIX ")"
430+#define FILTER_GROUP_SIZE(group) (size_t) (strlen(group)+(ldap_count_group(group)*5)+52)
48dfc510 431+
9a6dd2b6
JR
432+/* just filter building stuff */
433+#define REQUEST_GROUP_SIZE(filter, uid) (size_t) (strlen(filter)+strlen(uid)+1)
434+#define REQUEST_GROUP(buffer, prefilter, pwname) \
435+ buffer = (char *) calloc(REQUEST_GROUP_SIZE(prefilter, pwname), sizeof(char)); \
436+ if (!buffer) { \
437+ perror("calloc()"); \
438+ return FAILURE; \
439+ } \
440+ snprintf(buffer, REQUEST_GROUP_SIZE(prefilter,pwname), prefilter, pwname)
441+/*
442+XXX OLD group building macros
443+#define REQUEST_GROUP_SIZE(grp, uid) (size_t) (strlen(grp)+strlen(uid)+46)
444+#define REQUEST_GROUP(buffer,pwname,grp) \
445+ buffer = (char *) calloc(REQUEST_GROUP_SIZE(grp, pwname), sizeof(char)); \
446+ if (!buffer) { \
447+ perror("calloc()"); \
448+ return FAILURE; \
449+ } \
450+ snprintf(buffer,REQUEST_GROUP_SIZE(grp,pwname),"(&(objectclass=posixGroup)(cn=%s)(memberUid=%s))",grp,pwname)
451+ */
48dfc510 452+
9a6dd2b6
JR
453+/*
454+XXX stock upstream version without extra filter support
455+#define REQUEST_USER_SIZE(uid) (size_t) (strlen(uid)+64)
456+#define REQUEST_USER(buffer, pwname) \
457+ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname), sizeof(char)); \
458+ if (!buffer) { \
459+ perror("calloc()"); \
460+ return NULL; \
461+ } \
462+ snprintf(buffer,REQUEST_USER_SIZE(pwname),"(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s))",pwname)
463+ */
48dfc510 464+
9a6dd2b6
JR
465+#define REQUEST_USER_SIZE(uid, filter) (size_t) (strlen(uid)+64+(filter != NULL ? strlen(filter) : 0))
466+#define REQUEST_USER(buffer, pwname, customfilter) \
467+ buffer = (char *) calloc(REQUEST_USER_SIZE(pwname, customfilter), sizeof(char)); \
468+ if (!buffer) { \
469+ perror("calloc()"); \
470+ return NULL; \
471+ } \
472+ snprintf(buffer, REQUEST_USER_SIZE(pwname, customfilter), \
473+ "(&(objectclass=posixAccount)(objectclass=ldapPublicKey)(uid=%s)%s)", \
474+ pwname, (customfilter != NULL ? customfilter : ""))
48dfc510 475+
9a6dd2b6
JR
476+/* some portable and working tokenizer, lame though */
477+static int tokenize(char ** o, size_t size, char * input) {
478+ unsigned int i = 0, num;
479+ const char * charset = " \t";
480+ char * ptr = input;
48dfc510 481+
9a6dd2b6
JR
482+ /* leading white spaces are ignored */
483+ num = strspn(ptr, charset);
484+ ptr += num;
48dfc510 485+
9a6dd2b6
JR
486+ while ((num = strcspn(ptr, charset))) {
487+ if (i < size-1) {
488+ o[i++] = ptr;
489+ ptr += num;
490+ if (*ptr)
491+ *ptr++ = '\0';
492+ }
493+ }
494+ o[i] = NULL;
495+ return SUCCESS;
496+}
48dfc510 497+
9a6dd2b6 498+void ldap_close(ldap_opt_t * ldap) {
48dfc510 499+
9a6dd2b6
JR
500+ if (!ldap)
501+ return;
48dfc510 502+
9a6dd2b6
JR
503+ if ( ldap_unbind_ext(ldap->ld, NULL, NULL) < 0)
504+ ldap_perror(ldap->ld, "ldap_unbind()");
48dfc510 505+
9a6dd2b6
JR
506+ ldap->ld = NULL;
507+ FLAG_SET_DISCONNECTED(ldap->flags);
48dfc510 508+
9a6dd2b6
JR
509+ return;
510+}
48dfc510 511+
9a6dd2b6
JR
512+/* init && bind */
513+int ldap_connect(ldap_opt_t * ldap) {
514+ int version = LDAP_VERSION3;
48dfc510 515+
9a6dd2b6
JR
516+ if (!ldap->servers)
517+ return FAILURE;
48dfc510 518+
9a6dd2b6
JR
519+ /* Connection Init and setup */
520+ ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
521+ if (!ldap->ld) {
522+ ldap_perror(ldap->ld, "ldap_init()");
523+ return FAILURE;
524+ }
48dfc510 525+
9a6dd2b6
JR
526+ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
527+ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_PROTOCOL_VERSION)");
528+ return FAILURE;
529+ }
48dfc510 530+
9a6dd2b6
JR
531+ /* Timeouts setup */
532+ if (ldap_set_option(ldap->ld, LDAP_OPT_NETWORK_TIMEOUT, &ldap->b_timeout) != LDAP_SUCCESS) {
533+ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_NETWORK_TIMEOUT)");
534+ }
535+ if (ldap_set_option(ldap->ld, LDAP_OPT_TIMEOUT, &ldap->s_timeout) != LDAP_SUCCESS) {
536+ ldap_perror(ldap->ld, "ldap_set_option(LDAP_OPT_TIMEOUT)");
537+ }
48dfc510 538+
9a6dd2b6
JR
539+ /* TLS support */
540+ if ( (ldap->tls == -1) || (ldap->tls == 1) ) {
541+ if (ldap_start_tls_s(ldap->ld, NULL, NULL ) != LDAP_SUCCESS) {
542+ /* failed then reinit the initial connect */
543+ ldap_perror(ldap->ld, "ldap_connect: (TLS) ldap_start_tls()");
544+ if (ldap->tls == 1)
545+ return FAILURE;
48dfc510 546+
9a6dd2b6
JR
547+ ldap->ld = ldap_init(ldap->servers, LDAP_PORT);
548+ if (!ldap->ld) {
549+ ldap_perror(ldap->ld, "ldap_init()");
550+ return FAILURE;
551+ }
48dfc510 552+
9a6dd2b6
JR
553+ if ( ldap_set_option(ldap->ld, LDAP_OPT_PROTOCOL_VERSION, &version) != LDAP_OPT_SUCCESS) {
554+ ldap_perror(ldap->ld, "ldap_set_option()");
555+ return FAILURE;
556+ }
557+ }
558+ }
48dfc510 559+
48dfc510 560+
9a6dd2b6
JR
561+ if ( ldap_simple_bind_s(ldap->ld, ldap->binddn, ldap->bindpw) != LDAP_SUCCESS) {
562+ ldap_perror(ldap->ld, "ldap_simple_bind_s()");
563+ return FAILURE;
564+ }
48dfc510 565+
9a6dd2b6
JR
566+ /* says it is connected */
567+ FLAG_SET_CONNECTED(ldap->flags);
48dfc510 568+
9a6dd2b6
JR
569+ return SUCCESS;
570+}
48dfc510 571+
9a6dd2b6
JR
572+/* must free allocated ressource */
573+static char * ldap_build_host(char *host, int port) {
574+ unsigned int size = strlen(host)+11;
575+ char * h = (char *) calloc (size, sizeof(char));
576+ int rc;
577+ if (!h)
578+ return NULL;
48dfc510 579+
9a6dd2b6
JR
580+ rc = snprintf(h, size, "%s:%d ", host, port);
581+ if (rc == -1)
582+ return NULL;
583+ return h;
584+}
48dfc510 585+
9a6dd2b6
JR
586+static int ldap_count_group(const char * input) {
587+ const char * charset = " \t";
588+ const char * ptr = input;
589+ unsigned int count = 0;
590+ unsigned int num;
48dfc510 591+
9a6dd2b6
JR
592+ num = strspn(ptr, charset);
593+ ptr += num;
48dfc510 594+
9a6dd2b6
JR
595+ while ((num = strcspn(ptr, charset))) {
596+ count++;
597+ ptr += num;
598+ ptr++;
599+ }
48dfc510 600+
9a6dd2b6
JR
601+ return count;
602+}
48dfc510 603+
9a6dd2b6
JR
604+/* format filter */
605+char * ldap_parse_groups(const char * groups) {
606+ unsigned int buffer_size = FILTER_GROUP_SIZE(groups);
607+ char * buffer = (char *) calloc(buffer_size, sizeof(char));
608+ char * g = NULL;
609+ char * garray[32];
610+ unsigned int i = 0;
48dfc510 611+
9a6dd2b6
JR
612+ if ((!groups)||(!buffer))
613+ return NULL;
48dfc510 614+
9a6dd2b6
JR
615+ g = strdup(groups);
616+ if (!g) {
617+ free(buffer);
618+ return NULL;
619+ }
48dfc510 620+
9a6dd2b6
JR
621+ /* first separate into n tokens */
622+ if ( tokenize(garray, sizeof(garray)/sizeof(*garray), g) < 0) {
623+ free(g);
624+ free(buffer);
625+ return NULL;
626+ }
48dfc510 627+
9a6dd2b6
JR
628+ /* build the final filter format */
629+ strlcat(buffer, FILTER_GROUP_PREFIX, buffer_size);
630+ strlcat(buffer, FILTER_OR_PREFIX, buffer_size);
631+ i = 0;
632+ while (garray[i]) {
633+ strlcat(buffer, FILTER_CN_PREFIX, buffer_size);
634+ strlcat(buffer, garray[i], buffer_size);
635+ strlcat(buffer, FILTER_CN_SUFFIX, buffer_size);
636+ i++;
637+ }
638+ strlcat(buffer, FILTER_OR_SUFFIX, buffer_size);
639+ strlcat(buffer, FILTER_UID_FORMAT, buffer_size);
640+ strlcat(buffer, FILTER_GROUP_SUFFIX, buffer_size);
641+
642+ free(g);
643+ return buffer;
48dfc510 644+}
48dfc510 645+
9a6dd2b6
JR
646+/* a bit dirty but leak free */
647+char * ldap_parse_servers(const char * servers) {
648+ char * s = NULL;
649+ char * tmp = NULL, *urls[32];
650+ unsigned int num = 0 , i = 0 , asize = 0;
651+ LDAPURLDesc *urld[32];
652+
653+ if (!servers)
654+ return NULL;
48dfc510 655+
9a6dd2b6
JR
656+ /* local copy of the arg */
657+ s = strdup(servers);
658+ if (!s)
659+ return NULL;
48dfc510 660+
9a6dd2b6
JR
661+ /* first separate into URL tokens */
662+ if ( tokenize(urls, sizeof(urls)/sizeof(*urls), s) < 0)
663+ return NULL;
48dfc510 664+
9a6dd2b6
JR
665+ i = 0;
666+ while (urls[i]) {
667+ if (! ldap_is_ldap_url(urls[i]) ||
668+ (ldap_url_parse(urls[i], &urld[i]) != 0)) {
669+ return NULL;
670+ }
671+ i++;
672+ }
48dfc510 673+
9a6dd2b6
JR
674+ /* now free(s) */
675+ free (s);
48dfc510 676+
9a6dd2b6
JR
677+ /* how much memory do we need */
678+ num = i;
679+ for (i = 0 ; i < num ; i++)
680+ asize += strlen(urld[i]->lud_host)+11;
48dfc510 681+
9a6dd2b6
JR
682+ /* alloc */
683+ s = (char *) calloc( asize+1 , sizeof(char));
684+ if (!s) {
685+ for (i = 0 ; i < num ; i++)
686+ ldap_free_urldesc(urld[i]);
687+ return NULL;
688+ }
48dfc510 689+
9a6dd2b6
JR
690+ /* then build the final host string */
691+ for (i = 0 ; i < num ; i++) {
692+ /* built host part */
693+ tmp = ldap_build_host(urld[i]->lud_host, urld[i]->lud_port);
694+ strncat(s, tmp, strlen(tmp));
695+ ldap_free_urldesc(urld[i]);
696+ free(tmp);
697+ }
48dfc510 698+
9a6dd2b6
JR
699+ return s;
700+}
48dfc510 701+
9a6dd2b6
JR
702+void ldap_options_print(ldap_opt_t * ldap) {
703+ debug("ldap options:");
704+ debug("servers: %s", ldap->servers);
705+ if (ldap->u_basedn)
706+ debug("user basedn: %s", ldap->u_basedn);
707+ if (ldap->g_basedn)
708+ debug("group basedn: %s", ldap->g_basedn);
709+ if (ldap->binddn)
710+ debug("binddn: %s", ldap->binddn);
711+ if (ldap->bindpw)
712+ debug("bindpw: %s", ldap->bindpw);
713+ if (ldap->sgroup)
714+ debug("group: %s", ldap->sgroup);
715+ if (ldap->filter)
716+ debug("filter: %s", ldap->filter);
717+}
48dfc510 718+
9a6dd2b6
JR
719+void ldap_options_free(ldap_opt_t * l) {
720+ if (!l)
721+ return;
722+ if (l->servers)
723+ free(l->servers);
724+ if (l->u_basedn)
725+ free(l->u_basedn);
726+ if (l->g_basedn)
727+ free(l->g_basedn);
728+ if (l->binddn)
729+ free(l->binddn);
730+ if (l->bindpw)
731+ free(l->bindpw);
732+ if (l->sgroup)
733+ free(l->sgroup);
734+ if (l->fgroup)
735+ free(l->fgroup);
736+ if (l->filter)
737+ free(l->filter);
738+ if (l->l_conf)
739+ free(l->l_conf);
740+ free(l);
741+}
48dfc510 742+
9a6dd2b6
JR
743+/* free keys */
744+void ldap_keys_free(ldap_key_t * k) {
745+ ldap_value_free_len(k->keys);
746+ free(k);
747+ return;
748+}
48dfc510 749+
9a6dd2b6
JR
750+ldap_key_t * ldap_getuserkey(ldap_opt_t *l, const char * user) {
751+ ldap_key_t * k = (ldap_key_t *) calloc (1, sizeof(ldap_key_t));
752+ LDAPMessage *res, *e;
753+ char * filter;
754+ int i;
48dfc510 755+
9a6dd2b6
JR
756+ if ((!k) || (!l))
757+ return NULL;
48dfc510 758+
9a6dd2b6
JR
759+ /* Am i still connected ? RETRY n times */
760+ /* XXX TODO: setup some conf value for retrying */
761+ if (!(l->flags & FLAG_CONNECTED))
762+ for (i = 0 ; i < 2 ; i++)
763+ if (ldap_connect(l) == 0)
764+ break;
48dfc510 765+
9a6dd2b6
JR
766+ /* quick check for attempts to be evil */
767+ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) ||
768+ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL))
769+ return NULL;
48dfc510 770+
9a6dd2b6
JR
771+ /* build filter for LDAP request */
772+ REQUEST_USER(filter, user, l->filter);
48dfc510 773+
9a6dd2b6
JR
774+ if ( ldap_search_st( l->ld,
775+ l->u_basedn,
776+ LDAP_SCOPE_SUBTREE,
777+ filter,
778+ attrs, 0, &l->s_timeout, &res ) != LDAP_SUCCESS) {
779+
780+ ldap_perror(l->ld, "ldap_search_st()");
48dfc510 781+
9a6dd2b6
JR
782+ free(filter);
783+ free(k);
48dfc510 784+
9a6dd2b6
JR
785+ /* XXX error on search, timeout etc.. close ask for reconnect */
786+ ldap_close(l);
48dfc510 787+
9a6dd2b6
JR
788+ return NULL;
789+ }
48dfc510 790+
9a6dd2b6
JR
791+ /* free */
792+ free(filter);
793+
794+ /* check if any results */
795+ i = ldap_count_entries(l->ld,res);
796+ if (i <= 0) {
797+ ldap_msgfree(res);
798+ free(k);
799+ return NULL;
48dfc510 800+ }
48dfc510 801+
9a6dd2b6
JR
802+ if (i > 1)
803+ debug("[LDAP] duplicate entries, using the FIRST entry returned");
48dfc510 804+
9a6dd2b6
JR
805+ e = ldap_first_entry(l->ld, res);
806+ k->keys = ldap_get_values_len(l->ld, e, PUBKEYATTR);
807+ k->num = ldap_count_values_len(k->keys);
48dfc510 808+
9a6dd2b6
JR
809+ ldap_msgfree(res);
810+ return k;
811+}
48dfc510 812+
48dfc510 813+
9a6dd2b6
JR
814+/* -1 if trouble
815+ 0 if user is NOT member of current server group
816+ 1 if user IS MEMBER of current server group
817+ */
818+int ldap_ismember(ldap_opt_t * l, const char * user) {
819+ LDAPMessage *res;
820+ char * filter;
821+ int i;
48dfc510 822+
9a6dd2b6
JR
823+ if ((!l->sgroup) || !(l->g_basedn))
824+ return 1;
48dfc510 825+
9a6dd2b6
JR
826+ /* Am i still connected ? RETRY n times */
827+ /* XXX TODO: setup some conf value for retrying */
828+ if (!(l->flags & FLAG_CONNECTED))
829+ for (i = 0 ; i < 2 ; i++)
830+ if (ldap_connect(l) == 0)
831+ break;
48dfc510 832+
9a6dd2b6
JR
833+ /* quick check for attempts to be evil */
834+ if ((strchr(user, '(') != NULL) || (strchr(user, ')') != NULL) ||
835+ (strchr(user, '*') != NULL) || (strchr(user, '\\') != NULL))
48dfc510 836+ return FAILURE;
48dfc510 837+
9a6dd2b6
JR
838+ /* build filter for LDAP request */
839+ REQUEST_GROUP(filter, l->fgroup, user);
48dfc510 840+
9a6dd2b6
JR
841+ if (ldap_search_st( l->ld,
842+ l->g_basedn,
843+ LDAP_SCOPE_SUBTREE,
844+ filter,
845+ NULL, 0, &l->s_timeout, &res) != LDAP_SUCCESS) {
846+
847+ ldap_perror(l->ld, "ldap_search_st()");
48dfc510 848+
9a6dd2b6 849+ free(filter);
48dfc510 850+
9a6dd2b6
JR
851+ /* XXX error on search, timeout etc.. close ask for reconnect */
852+ ldap_close(l);
48dfc510 853+
9a6dd2b6 854+ return FAILURE;
48dfc510 855+ }
856+
9a6dd2b6 857+ free(filter);
48dfc510 858+
9a6dd2b6
JR
859+ /* check if any results */
860+ if (ldap_count_entries(l->ld, res) > 0) {
861+ ldap_msgfree(res);
862+ return 1;
48dfc510 863+ }
864+
9a6dd2b6
JR
865+ ldap_msgfree(res);
866+ return 0;
48dfc510 867+}
868+
9a6dd2b6
JR
869+/*
870+ * ldap.conf simple parser
871+ * XXX TODO: sanity checks
872+ * must either
873+ * - free the previous ldap_opt_before replacing entries
874+ * - free each necessary previously parsed elements
875+ * ret:
876+ * -1 on FAILURE, 0 on SUCCESS
877+ */
878+int ldap_parse_lconf(ldap_opt_t * l) {
879+ FILE * lcd; /* ldap.conf descriptor */
880+ char buf[BUFSIZ];
881+ char * s = NULL, * k = NULL, * v = NULL;
882+ int li, len;
48dfc510 883+
9a6dd2b6
JR
884+ lcd = fopen (l->l_conf, "r");
885+ if (lcd == NULL) {
886+ /* debug("Cannot open %s", l->l_conf); */
887+ perror("ldap_parse_lconf()");
888+ return FAILURE;
889+ }
890+
891+ while (fgets (buf, sizeof (buf), lcd) != NULL) {
48dfc510 892+
9a6dd2b6
JR
893+ if (*buf == '\n' || *buf == '#')
894+ continue;
48dfc510 895+
9a6dd2b6
JR
896+ k = buf;
897+ v = k;
898+ while (*v != '\0' && *v != ' ' && *v != '\t')
899+ v++;
48dfc510 900+
9a6dd2b6
JR
901+ if (*v == '\0')
902+ continue;
48dfc510 903+
9a6dd2b6 904+ *(v++) = '\0';
48dfc510 905+
9a6dd2b6
JR
906+ while (*v == ' ' || *v == '\t')
907+ v++;
48dfc510 908+
9a6dd2b6
JR
909+ li = strlen (v) - 1;
910+ while (v[li] == ' ' || v[li] == '\t' || v[li] == '\n')
911+ --li;
912+ v[li + 1] = '\0';
48dfc510 913+
9a6dd2b6
JR
914+ if (!strcasecmp (k, "uri")) {
915+ if ((l->servers = ldap_parse_servers(v)) == NULL) {
916+ fatal("error in ldap servers");
917+ return FAILURE;
918+ }
48dfc510 919+
9a6dd2b6
JR
920+ }
921+ else if (!strcasecmp (k, "base")) {
922+ s = strchr (v, '?');
923+ if (s != NULL) {
924+ len = s - v;
925+ l->u_basedn = malloc (len + 1);
926+ strncpy (l->u_basedn, v, len);
927+ l->u_basedn[len] = '\0';
928+ } else {
929+ l->u_basedn = strdup (v);
930+ }
931+ }
932+ else if (!strcasecmp (k, "binddn")) {
933+ l->binddn = strdup (v);
934+ }
935+ else if (!strcasecmp (k, "bindpw")) {
936+ l->bindpw = strdup (v);
937+ }
938+ else if (!strcasecmp (k, "timelimit")) {
939+ l->s_timeout.tv_sec = atoi (v);
940+ }
941+ else if (!strcasecmp (k, "bind_timelimit")) {
942+ l->b_timeout.tv_sec = atoi (v);
943+ }
944+ else if (!strcasecmp (k, "ssl")) {
945+ if (!strcasecmp (v, "start_tls"))
946+ l->tls = 1;
947+ }
48dfc510 948+ }
48dfc510 949+
9a6dd2b6
JR
950+ fclose (lcd);
951+ return SUCCESS;
48dfc510 952+}
953+
9a6dd2b6
JR
954+#endif /* WITH_LDAP_PUBKEY */
955diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/ldapauth.h openssh-5.1p1+lpk/ldapauth.h
956--- openssh-5.1p1.orig/ldapauth.h 1969-12-31 16:00:00.000000000 -0800
957+++ openssh-5.1p1+lpk/ldapauth.h 2008-08-23 15:02:47.000000000 -0700
958@@ -0,0 +1,124 @@
959+/*
960+ * $Id$
961+ */
48dfc510 962+
9a6dd2b6
JR
963+/*
964+ *
965+ * Copyright (c) 2005, Eric AUGE <eau@phear.org>
966+ * All rights reserved.
967+ *
968+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
969+ *
970+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
971+ * 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.
972+ * 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.
973+ *
974+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
975+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
976+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
977+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
978+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
979+ * 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.
980+ *
981+ *
982+ */
48dfc510 983+
9a6dd2b6
JR
984+#ifndef LDAPAUTH_H
985+#define LDAPAUTH_H
48dfc510 986+
9a6dd2b6 987+#define LDAP_DEPRECATED 1
48dfc510 988+
9a6dd2b6
JR
989+#include <string.h>
990+#include <time.h>
991+#include <ldap.h>
992+#include <lber.h>
48dfc510 993+
9a6dd2b6
JR
994+/* tokens in use for config */
995+#define _DEFAULT_LPK_TOKEN "UseLPK"
996+#define _DEFAULT_SRV_TOKEN "LpkServers"
997+#define _DEFAULT_USR_TOKEN "LpkUserDN"
998+#define _DEFAULT_GRP_TOKEN "LpkGroupDN"
999+#define _DEFAULT_BDN_TOKEN "LpkBindDN"
1000+#define _DEFAULT_BPW_TOKEN "LpkBindPw"
1001+#define _DEFAULT_MYG_TOKEN "LpkServerGroup"
1002+#define _DEFAULT_FIL_TOKEN "LpkFilter"
1003+#define _DEFAULT_TLS_TOKEN "LpkForceTLS"
1004+#define _DEFAULT_BTI_TOKEN "LpkBindTimelimit"
1005+#define _DEFAULT_STI_TOKEN "LpkSearchTimelimit"
1006+#define _DEFAULT_LDP_TOKEN "LpkLdapConf"
48dfc510 1007+
9a6dd2b6
JR
1008+/* default options */
1009+#define _DEFAULT_LPK_ON 0
1010+#define _DEFAULT_LPK_SERVERS NULL
1011+#define _DEFAULT_LPK_UDN NULL
1012+#define _DEFAULT_LPK_GDN NULL
1013+#define _DEFAULT_LPK_BINDDN NULL
1014+#define _DEFAULT_LPK_BINDPW NULL
1015+#define _DEFAULT_LPK_SGROUP NULL
1016+#define _DEFAULT_LPK_FILTER NULL
1017+#define _DEFAULT_LPK_TLS -1
1018+#define _DEFAULT_LPK_BTIMEOUT 10
1019+#define _DEFAULT_LPK_STIMEOUT 10
1020+#define _DEFAULT_LPK_LDP NULL
48dfc510 1021+
9a6dd2b6
JR
1022+/* flags */
1023+#define FLAG_EMPTY 0x00000000
1024+#define FLAG_CONNECTED 0x00000001
48dfc510 1025+
9a6dd2b6
JR
1026+/* flag macros */
1027+#define FLAG_SET_EMPTY(x) x&=(FLAG_EMPTY)
1028+#define FLAG_SET_CONNECTED(x) x|=(FLAG_CONNECTED)
1029+#define FLAG_SET_DISCONNECTED(x) x&=~(FLAG_CONNECTED)
48dfc510 1030+
9a6dd2b6
JR
1031+/* defines */
1032+#define FAILURE -1
1033+#define SUCCESS 0
1034+#define PUBKEYATTR "sshPublicKey"
48dfc510 1035+
9a6dd2b6
JR
1036+/*
1037+ *
1038+ * defined files path
1039+ * (should be relocated to pathnames.h,
1040+ * if one day it's included within the tree)
1041+ *
1042+ */
1043+#define _PATH_LDAP_CONFIG_FILE "/etc/ldap.conf"
48dfc510 1044+
9a6dd2b6
JR
1045+/* structures */
1046+typedef struct ldap_options {
1047+ int on; /* Use it or NOT */
1048+ LDAP * ld; /* LDAP file desc */
1049+ char * servers; /* parsed servers for ldaplib failover handling */
1050+ char * u_basedn; /* user basedn */
1051+ char * g_basedn; /* group basedn */
1052+ char * binddn; /* binddn */
1053+ char * bindpw; /* bind password */
1054+ char * sgroup; /* server group */
1055+ char * fgroup; /* group filter */
1056+ char * filter; /* additional filter */
1057+ char * l_conf; /* use ldap.conf */
1058+ int tls; /* TLS only */
1059+ struct timeval b_timeout; /* bind timeout */
1060+ struct timeval s_timeout; /* search timeout */
1061+ unsigned int flags; /* misc flags (reconnection, future use?) */
1062+} ldap_opt_t;
48dfc510 1063+
9a6dd2b6
JR
1064+typedef struct ldap_keys {
1065+ struct berval ** keys; /* the public keys retrieved */
1066+ unsigned int num; /* number of keys */
1067+} ldap_key_t;
48dfc510 1068+
48dfc510 1069+
9a6dd2b6
JR
1070+/* function headers */
1071+void ldap_close(ldap_opt_t *);
1072+int ldap_connect(ldap_opt_t *);
1073+char * ldap_parse_groups(const char *);
1074+char * ldap_parse_servers(const char *);
1075+void ldap_options_print(ldap_opt_t *);
1076+void ldap_options_free(ldap_opt_t *);
1077+void ldap_keys_free(ldap_key_t *);
1078+int ldap_parse_lconf(ldap_opt_t *);
1079+ldap_key_t * ldap_getuserkey(ldap_opt_t *, const char *);
1080+int ldap_ismember(ldap_opt_t *, const char *);
48dfc510 1081+
9a6dd2b6
JR
1082+#endif
1083diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/lpk-user-example.txt openssh-5.1p1+lpk/lpk-user-example.txt
1084--- openssh-5.1p1.orig/lpk-user-example.txt 1969-12-31 16:00:00.000000000 -0800
1085+++ openssh-5.1p1+lpk/lpk-user-example.txt 2008-08-23 15:02:47.000000000 -0700
1086@@ -0,0 +1,117 @@
48dfc510 1087+
9a6dd2b6
JR
1088+Post to ML -> User Made Quick Install Doc.
1089+Contribution from John Lane <john@lane.uk.net>
48dfc510 1090+
9a6dd2b6 1091+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48dfc510 1092+
9a6dd2b6
JR
1093+OpenSSH LDAP keystore Patch
1094+===========================
48dfc510 1095+
9a6dd2b6
JR
1096+NOTE: these notes are a transcript of a specific installation
1097+ they work for me, your specifics may be different!
1098+ from John Lane March 17th 2005 john@lane.uk.net
48dfc510 1099+
9a6dd2b6
JR
1100+This is a patch to OpenSSH 4.0p1 to allow it to obtain users' public keys
1101+from their LDAP record as an alternative to ~/.ssh/authorized_keys.
48dfc510 1102+
9a6dd2b6 1103+(Assuming here that necessary build stuff is in $BUILD)
48dfc510 1104+
9a6dd2b6
JR
1105+cd $BUILD/openssh-4.0p1
1106+patch -Np1 -i $BUILD/openssh-lpk-4.0p1-0.3.patch
1107+mkdir -p /var/empty &&
1108+./configure --prefix=/usr --sysconfdir=/etc/ssh \
1109+ --libexecdir=/usr/sbin --with-md5-passwords --with-pam \
1110+ --with-libs="-lldap" --with-cppflags="-DWITH_LDAP_PUBKEY"
1111+Now do.
1112+make &&
1113+make install
48dfc510 1114+
9a6dd2b6
JR
1115+Add the following config to /etc/ssh/ssh_config
1116+UseLPK yes
1117+LpkServers ldap://myhost.mydomain.com
1118+LpkUserDN ou=People,dc=mydomain,dc=com
48dfc510 1119+
9a6dd2b6
JR
1120+We need to tell sshd about the SSL keys during boot, as root's
1121+environment does not exist at that time. Edit /etc/rc.d/init.d/sshd.
1122+Change the startup code from this:
1123+ echo "Starting SSH Server..."
1124+ loadproc /usr/sbin/sshd
1125+ ;;
1126+to this:
1127+ echo "Starting SSH Server..."
1128+ LDAPRC="/root/.ldaprc" loadproc /usr/sbin/sshd
1129+ ;;
48dfc510 1130+
9a6dd2b6
JR
1131+Re-start the sshd daemon:
1132+/etc/rc.d/init.d/sshd restart
48dfc510 1133+
9a6dd2b6
JR
1134+Install the additional LDAP schema
1135+cp $BUILD/openssh-lpk-0.2.schema /etc/openldap/schema/openssh.schema
48dfc510 1136+
9a6dd2b6
JR
1137+Now add the openSSH LDAP schema to /etc/openldap/slapd.conf:
1138+Add the following to the end of the existing block of schema includes
1139+include /etc/openldap/schema/openssh.schema
48dfc510 1140+
9a6dd2b6
JR
1141+Re-start the LDAP server:
1142+/etc/rc.d/init.d/slapd restart
48dfc510 1143+
9a6dd2b6
JR
1144+To add one or more public keys to a user, eg "testuser" :
1145+ldapsearch -x -W -Z -LLL -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D
1146+"uid=testuser,ou=People,dc=mydomain,dc=com" > /tmp/testuser
48dfc510 1147+
9a6dd2b6
JR
1148+append the following to this /tmp/testuser file
1149+objectclass: ldapPublicKey
1150+sshPublicKey: ssh-rsa
1151+AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KS
1152+qIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z8XwSsuAoR1t86t+5dlI
1153+7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key
48dfc510 1154+
9a6dd2b6
JR
1155+Then do a modify:
1156+ldapmodify -x -D "uid=testuser,ou=People,dc=mydomain,dc=com" -W -f
1157+/tmp/testuser -Z
1158+Enter LDAP Password:
1159+modifying entry "uid=testuser,ou=People,dc=mydomain,dc=com"
1160+And check the modify is ok:
1161+ldapsearch -x -W -Z -b "uid=testuser,ou=People,dc=mydomain,dc=com" -D
1162+"uid=testuser,ou=People,dc=mydomain,dc=com"
1163+Enter LDAP Password:
1164+# extended LDIF
1165+#
1166+# LDAPv3
1167+# base <uid=testuser,ou=People,dc=mydomain,dc=com> with scope sub
1168+# filter: (objectclass=*)
1169+# requesting: ALL
1170+#
48dfc510 1171+
9a6dd2b6
JR
1172+# testuser, People, mydomain.com
1173+dn: uid=testuser,ou=People,dc=mydomain,dc=com
1174+uid: testuser
1175+cn: testuser
1176+objectClass: account
1177+objectClass: posixAccount
1178+objectClass: top
1179+objectClass: shadowAccount
1180+objectClass: ldapPublicKey
1181+shadowLastChange: 12757
1182+shadowMax: 99999
1183+shadowWarning: 7
1184+loginShell: /bin/bash
1185+uidNumber: 9999
1186+gidNumber: 501
1187+homeDirectory: /home/testuser
1188+userPassword:: e1NTSEF9UDgwV1hnM1VjUDRJK0k1YnFiL1d4ZUJObXlZZ3Z3UTU=
1189+sshPublicKey: ssh-rsa
1190+AAAAB3NzaC1yc2EAAAABJQAAAIB3dsrwqXqD7E4zYYrxwdDKBUQxKMioXy9pxFVai64kAPxjU9KSqIo7QfkjslfsjflksjfldfkjsldfjLX/5zkzRmT28I5piGzunPv17S89z
1191+8XwSsuAoR1t86t+5dlI7eZE/gVbn2UQkQq7+kdDTS2yXV6VnC52N/kKLG3ciBkBAw== General Purpose RSA Key
48dfc510 1192+
9a6dd2b6
JR
1193+# search result
1194+search: 3
1195+result: 0 Success
48dfc510 1196+
9a6dd2b6
JR
1197+# numResponses: 2
1198+# numEntries: 1
48dfc510 1199+
9a6dd2b6
JR
1200+Now start a ssh session to user "testuser" from usual ssh client (e.g.
1201+puTTY). Login should succeed.
48dfc510 1202+
9a6dd2b6 1203+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
f1344723
CM
1204--- openssh-5.7p1/Makefile.in.orig 2011-01-17 12:15:29.000000000 +0200
1205+++ openssh-5.7p1/Makefile.in 2011-01-24 16:35:51.174726790 +0200
1206@@ -93,7 +93,7 @@
28ece7ce
AM
1207 auth2-gss.o gss-serv.o gss-serv-krb5.o \
1208 loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
f1344723 1209 sftp-server.o sftp-common.o \
28ece7ce
AM
1210- roaming_common.o roaming_serv.o
1211+ roaming_common.o roaming_serv.o ldapauth.o
9a6dd2b6 1212
28ece7ce
AM
1213 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
1214 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
1215diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/openssh-lpk_openldap.schema openssh-5.1p1+lpk/openssh-lpk_openldap.schema
1216--- openssh-5.1p1.orig/openssh-lpk_openldap.schema 1969-12-31 16:00:00.000000000 -0800
1217+++ openssh-5.1p1+lpk/openssh-lpk_openldap.schema 2008-08-23 15:02:47.000000000 -0700
1218@@ -0,0 +1,19 @@
1219+#
1220+# LDAP Public Key Patch schema for use with openssh-ldappubkey
1221+# Author: Eric AUGE <eau@phear.org>
1222+#
1223+# Based on the proposal of : Mark Ruijter
1224+#
48dfc510 1225+
48dfc510 1226+
9a6dd2b6
JR
1227+# octetString SYNTAX
1228+attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
1229+ DESC 'MANDATORY: OpenSSH Public key'
1230+ EQUALITY octetStringMatch
1231+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
48dfc510 1232+
9a6dd2b6
JR
1233+# printableString SYNTAX yes|no
1234+objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
1235+ DESC 'MANDATORY: OpenSSH LPK objectclass'
1236+ MUST ( sshPublicKey $ uid )
1237+ )
1238diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/openssh-lpk_sun.schema openssh-5.1p1+lpk/openssh-lpk_sun.schema
1239--- openssh-5.1p1.orig/openssh-lpk_sun.schema 1969-12-31 16:00:00.000000000 -0800
1240+++ openssh-5.1p1+lpk/openssh-lpk_sun.schema 2008-08-23 15:02:47.000000000 -0700
1241@@ -0,0 +1,21 @@
1242+#
1243+# LDAP Public Key Patch schema for use with openssh-ldappubkey
1244+# Author: Eric AUGE <eau@phear.org>
1245+#
1246+# Schema for Sun Directory Server.
1247+# Based on the original schema, modified by Stefan Fischer.
1248+#
48dfc510 1249+
9a6dd2b6 1250+dn: cn=schema
48dfc510 1251+
9a6dd2b6
JR
1252+# octetString SYNTAX
1253+attributeTypes: ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
1254+ DESC 'MANDATORY: OpenSSH Public key'
1255+ EQUALITY octetStringMatch
1256+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
48dfc510 1257+
9a6dd2b6
JR
1258+# printableString SYNTAX yes|no
1259+objectClasses: ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP top AUXILIARY
1260+ DESC 'MANDATORY: OpenSSH LPK objectclass'
1261+ MUST ( sshPublicKey $ uid )
1262+ )
1263diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/README.lpk openssh-5.1p1+lpk/README.lpk
1264--- openssh-5.1p1.orig/README.lpk 1969-12-31 16:00:00.000000000 -0800
1265+++ openssh-5.1p1+lpk/README.lpk 2008-08-23 15:02:47.000000000 -0700
1266@@ -0,0 +1,267 @@
1267+OpenSSH LDAP PUBLIC KEY PATCH
1268+Copyright (c) 2003 Eric AUGE (eau@phear.org)
1269+All rights reserved.
48dfc510 1270+
9a6dd2b6
JR
1271+Redistribution and use in source and binary forms, with or without
1272+modification, are permitted provided that the following conditions
1273+are met:
1274+1. Redistributions of source code must retain the above copyright
1275+ notice, this list of conditions and the following disclaimer.
1276+2. Redistributions in binary form must reproduce the above copyright
1277+ notice, this list of conditions and the following disclaimer in the
1278+ documentation and/or other materials provided with the distribution.
1279+3. The name of the author may not be used to endorse or promote products
1280+ derived from this software without specific prior written permission.
48dfc510 1281+
9a6dd2b6
JR
1282+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1283+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1284+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1285+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1286+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1287+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1288+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1289+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1290+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1291+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48dfc510 1292+
9a6dd2b6 1293+purposes of this patch:
48dfc510 1294+
9a6dd2b6
JR
1295+This patch would help to have authentication centralization policy
1296+using ssh public key authentication.
1297+This patch could be an alternative to other "secure" authentication system
1298+working in a similar way (Kerberos, SecurID, etc...), except the fact
1299+that it's based on OpenSSH and its public key abilities.
48dfc510 1300+
9a6dd2b6
JR
1301+>> FYI: <<
1302+'uid': means unix accounts existing on the current server
1303+'lpkServerGroup:' mean server group configured on the current server ('lpkServerGroup' in sshd_config)
48dfc510 1304+
9a6dd2b6 1305+example schema:
48dfc510 1306+
48dfc510 1307+
9a6dd2b6
JR
1308+ server1 (uid: eau,rival,toto) (lpkServerGroup: unix)
1309+ ___________ /
1310+ / \ --- - server3 (uid: eau, titi) (lpkServerGroup: unix)
1311+ | LDAP Server | \
1312+ | eau ,rival | server2 (uid: rival, eau) (lpkServerGroup: unix)
1313+ | titi ,toto |
1314+ | userx,.... | server5 (uid: eau) (lpkServerGroup: mail)
1315+ \___________/ \ /
1316+ ----- - server4 (uid: eau, rival) (no group configured)
1317+ \
1318+ etc...
48dfc510 1319+
9a6dd2b6 1320+- WHAT WE NEED :
48dfc510 1321+
9a6dd2b6
JR
1322+ * configured LDAP server somewhere on the network (i.e. OpenLDAP)
1323+ * patched sshd (with this patch ;)
1324+ * LDAP user(/group) entry (look at users.ldif (& groups.ldif)):
1325+ User entry:
1326+ - attached to the 'ldapPublicKey' objectclass
1327+ - attached to the 'posixAccount' objectclass
1328+ - with a filled 'sshPublicKey' attribute
1329+ Example:
1330+ dn: uid=eau,ou=users,dc=cuckoos,dc=net
1331+ objectclass: top
1332+ objectclass: person
1333+ objectclass: organizationalPerson
1334+ objectclass: posixAccount
1335+ objectclass: ldapPublicKey
1336+ description: Eric AUGE Account
1337+ userPassword: blah
1338+ cn: Eric AUGE
1339+ sn: Eric AUGE
1340+ uid: eau
1341+ uidNumber: 1034
1342+ gidNumber: 1
1343+ homeDirectory: /export/home/eau
1344+ sshPublicKey: ssh-dss AAAAB3...
1345+ sshPublicKey: ssh-dss AAAAM5...
48dfc510 1346+
9a6dd2b6
JR
1347+ Group entry:
1348+ - attached to the 'posixGroup' objectclass
1349+ - with a 'cn' groupname attribute
1350+ - with multiple 'memberUid' attributes filled with usernames allowed in this group
1351+ Example:
1352+ # few members
1353+ dn: cn=unix,ou=groups,dc=cuckoos,dc=net
1354+ objectclass: top
1355+ objectclass: posixGroup
1356+ description: Unix based servers group
1357+ cn: unix
1358+ gidNumber: 1002
1359+ memberUid: eau
1360+ memberUid: user1
1361+ memberUid: user2
48dfc510 1362+
48dfc510 1363+
9a6dd2b6 1364+- HOW IT WORKS :
48dfc510 1365+
9a6dd2b6
JR
1366+ * without patch
1367+ If a user wants to authenticate to log in a server the sshd, will first look for authentication method allowed (RSAauth,kerberos,etc..)
1368+ and if RSAauth and tickets based auth fails, it will fallback to standard password authentication (if enabled).
48dfc510 1369+
9a6dd2b6
JR
1370+ * with the patch
1371+ 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.
1372+ It will do an ldapsearch to get the public key directly from the LDAP instead of reading it from the server filesystem.
1373+ (usually in $HOME/.ssh/authorized_keys)
48dfc510 1374+
9a6dd2b6
JR
1375+ 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.
1376+ If it fails, it falls back on RSA auth files ($HOME/.ssh/authorized_keys), etc.. and finally to standard password authentication (if enabled).
48dfc510 1377+
9a6dd2b6
JR
1378+ 7 tokens are added to sshd_config :
1379+ # here is the new patched ldap related tokens
1380+ # entries in your LDAP must be posixAccount & strongAuthenticationUser & posixGroup
1381+ UseLPK yes # look the pub key into LDAP
1382+ LpkServers ldap://10.31.32.5/ ldap://10.31.32.4 ldap://10.31.32.3 # which LDAP server for users ? (URL format)
1383+ LpkUserDN ou=users,dc=foobar,dc=net # which base DN for users ?
1384+ LpkGroupDN ou=groups,dc=foobar,dc=net # which base DN for groups ?
1385+ LpkBindDN cn=manager,dc=foobar,dc=net # which bind DN ?
1386+ LpkBindPw asecret # bind DN credidentials
1387+ LpkServerGroup agroupname # the group the server is part of
48dfc510 1388+
9a6dd2b6
JR
1389