]>
Commit | Line | Data |
---|---|---|
9a6dd2b6 JR |
1 | This is a forward-port of the OpenSSH LPK support patch. |
2 | ||
3 | It adds support for storing OpenSSH public keys in LDAP. It also supports | |
4 | grouping of machines in the LDAP data to limit users to specific machines. | |
5 | ||
6 | The latest homepage for the LPK project is: | |
7 | http://code.google.com/p/openssh-lpk/ | |
8 | ||
9 | The 0.3.10 version of the patch includes a fix for 64-bit platforms, as | |
10 | discovered by Gentoo, where the bind timeout and search timeout values were not | |
11 | being parsed correctly: http://bugs.gentoo.org/210110 | |
12 | ||
13 | Forward-ported-from: openssh-lpk-5.1p1-0.3.9.patch | |
14 | Signed-off-by: Robin H. Johnson <robbat2@gentoo.org> | |
15 | ||
16 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/auth2-pubkey.c openssh-5.1p1+lpk/auth2-pubkey.c | |
17 | --- openssh-5.1p1.orig/auth2-pubkey.c 2008-07-03 19:54:25.000000000 -0700 | |
18 | +++ openssh-5.1p1+lpk/auth2-pubkey.c 2008-08-23 15:02:47.000000000 -0700 | |
19 | @@ -55,6 +55,10 @@ | |
20 | #include "monitor_wrap.h" | |
21 | #include "misc.h" | |
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 |
128 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/auth-rsa.c openssh-5.1p1+lpk/auth-rsa.c |
129 | --- openssh-5.1p1.orig/auth-rsa.c 2008-07-02 05:37:30.000000000 -0700 | |
130 | +++ openssh-5.1p1+lpk/auth-rsa.c 2008-08-23 15:02:47.000000000 -0700 | |
131 | @@ -174,10 +174,96 @@ | |
132 | FILE *f; | |
133 | u_long linenum = 0; | |
134 | Key *key; | |
135 | +#ifdef WITH_LDAP_PUBKEY | |
136 | + ldap_key_t * k; | |
137 | + unsigned int i = 0; | |
138 | +#endif | |
139 | ||
140 | /* Temporarily use the user's uid. */ | |
141 | temporarily_use_uid(pw); | |
142 | ||
143 | +#ifdef WITH_LDAP_PUBKEY | |
144 | + /* here is the job */ | |
145 | + key = key_new(KEY_RSA1); | |
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); | |
228 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/config.h.in openssh-5.1p1+lpk/config.h.in | |
229 | --- openssh-5.1p1.orig/config.h.in 2008-07-21 01:30:49.000000000 -0700 | |
230 | +++ openssh-5.1p1+lpk/config.h.in 2008-08-23 15:02:47.000000000 -0700 | |
231 | @@ -560,6 +560,9 @@ | |
232 | /* Define to 1 if you have the <linux/if_tun.h> header file. */ | |
233 | #undef HAVE_LINUX_IF_TUN_H | |
234 | ||
235 | +/* Define if you want LDAP support */ | |
236 | +#undef WITH_LDAP_PUBKEY | |
237 | + | |
238 | /* Define if your libraries define login() */ | |
239 | #undef HAVE_LOGIN | |
240 | ||
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" | |
345 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/configure.ac openssh-5.1p1+lpk/configure.ac | |
346 | --- openssh-5.1p1.orig/configure.ac 2008-07-09 04:07:19.000000000 -0700 | |
347 | +++ openssh-5.1p1+lpk/configure.ac 2008-08-23 15:02:47.000000000 -0700 | |
348 | @@ -1299,6 +1299,37 @@ | |
349 | esac ] | |
350 | ) | |
351 | ||
352 | +# Check whether user wants LDAP support | |
353 | +LDAP_MSG="no" | |
354 | +AC_ARG_WITH(ldap, | |
355 | + [ --with-ldap[[=PATH]] Enable LDAP pubkey support (optionally in PATH)], | |
356 | + [ | |
357 | + if test "x$withval" != "xno" ; then | |
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" | |
394 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/ldapauth.c openssh-5.1p1+lpk/ldapauth.c | |
395 | --- openssh-5.1p1.orig/ldapauth.c 1969-12-31 16:00:00.000000000 -0800 | |
396 | +++ openssh-5.1p1+lpk/ldapauth.c 2008-08-23 15:02:47.000000000 -0700 | |
397 | @@ -0,0 +1,575 @@ | |
398 | +/* | |
399 | + * $Id$ | |
400 | + */ | |
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 */ |
973 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/ldapauth.h openssh-5.1p1+lpk/ldapauth.h | |
974 | --- openssh-5.1p1.orig/ldapauth.h 1969-12-31 16:00:00.000000000 -0800 | |
975 | +++ openssh-5.1p1+lpk/ldapauth.h 2008-08-23 15:02:47.000000000 -0700 | |
976 | @@ -0,0 +1,124 @@ | |
977 | +/* | |
978 | + * $Id$ | |
979 | + */ | |
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 |
1101 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/lpk-user-example.txt openssh-5.1p1+lpk/lpk-user-example.txt | |
1102 | --- openssh-5.1p1.orig/lpk-user-example.txt 1969-12-31 16:00:00.000000000 -0800 | |
1103 | +++ openssh-5.1p1+lpk/lpk-user-example.txt 2008-08-23 15:02:47.000000000 -0700 | |
1104 | @@ -0,0 +1,117 @@ | |
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 |
1233 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/openssh-lpk_openldap.schema openssh-5.1p1+lpk/openssh-lpk_openldap.schema |
1234 | --- openssh-5.1p1.orig/openssh-lpk_openldap.schema 1969-12-31 16:00:00.000000000 -0800 | |
1235 | +++ openssh-5.1p1+lpk/openssh-lpk_openldap.schema 2008-08-23 15:02:47.000000000 -0700 | |
1236 | @@ -0,0 +1,19 @@ | |
1237 | +# | |
1238 | +# LDAP Public Key Patch schema for use with openssh-ldappubkey | |
1239 | +# Author: Eric AUGE <eau@phear.org> | |
1240 | +# | |
1241 | +# Based on the proposal of : Mark Ruijter | |
1242 | +# | |
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 | + ) | |
1256 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/openssh-lpk_sun.schema openssh-5.1p1+lpk/openssh-lpk_sun.schema | |
1257 | --- openssh-5.1p1.orig/openssh-lpk_sun.schema 1969-12-31 16:00:00.000000000 -0800 | |
1258 | +++ openssh-5.1p1+lpk/openssh-lpk_sun.schema 2008-08-23 15:02:47.000000000 -0700 | |
1259 | @@ -0,0 +1,21 @@ | |
1260 | +# | |
1261 | +# LDAP Public Key Patch schema for use with openssh-ldappubkey | |
1262 | +# Author: Eric AUGE <eau@phear.org> | |
1263 | +# | |
1264 | +# Schema for Sun Directory Server. | |
1265 | +# Based on the original schema, modified by Stefan Fischer. | |
1266 | +# | |
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 | + ) | |
1281 | diff -Nuar --exclude '*.orig' --exclude '*.rej' openssh-5.1p1.orig/README.lpk openssh-5.1p1+lpk/README.lpk | |
1282 | --- openssh-5.1p1.orig/README.lpk 1969-12-31 16:00:00.000000000 -0800 | |
1283 | +++ openssh-5.1p1+lpk/README.lpk 2008-08-23 15:02:47.000000000 -0700 | |
1284 | @@ -0,0 +1,267 @@ | |
1285 | +OpenSSH LDAP PUBLIC KEY PATCH | |
1286 | +Copyright (c) 2003 Eric AUGE (eau@phear.org) | |
1287 | +All rights reserved. | |
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 | Content-type: text/html ]>