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