]>
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; | |
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 | ||
110 | diff -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); | |
210 | diff -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" | |
327 | diff -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" | |
376 | diff -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 */ |
955 | diff -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 |
1083 | diff -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 |
1215 | diff -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 | + ) | |
1238 | diff -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 | + ) | |
1263 | diff -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 | Content-type: text/html ]>