|
From: Dick Davies <rasputnik <at> hellooperator.net>
Subject: chase up - Re: couple of questions on ldap auth Newsgroups: gmane.comp.web.lighttpd Date: 2005-03-18 15:30:06 GMT (4 years, 15 weeks, 2 days, 18 hours and 44 minutes ago)
No ones' sent me hate mail regarding this yet - is it ok,
or do I need to start over?
* Dick Davies <rasputnik <at> hellooperator.net> [0332 00:32]:
> * Jan Kneschke <jan <at> kneschke.de> [0353 14:53]:
> > On Wed, Mar 09, 2005 at 02:47:05PM +0000, Dick Davies wrote:
> > >
> > > Hi there, loving lighttpd, just wanted a sanity check.
> > >
> > > 1. does lighttpd support secure connections to an LDAP server (startTLS or SSL)?
> >
> > It does nothing explicit. I have to look into the ldap/ssl part to give
> > you an answer.
>
> Here's a patch (against trunk) to enable startTLS - I haven't done SSL because
>
> a) it's deprecated
> b) it requires more changes to the source, different ports, etc.
> b) I'm trying to migrate away from it :)
>
> Let me know if it sucks, because I'd like to add some more features:
>
> * decent debugging - in particular, ldap_set_option() doesn't fail
> if the ca certificate isn't there or is a jpeg of your dog -
> you just get a 'Connect failed' from the bind.
>
> * LDAP URI support and multiple servers (one thing apaches mod_auth_ldap
> does well)
>
> * reuse of connections - an ldap auth cache is pretty complicated, but
> just rebinding on an existing connection with each pair of credentials
> would probably help almost as much (I'd have to benchmark to see if
> that's worth the hassle, and understand the code a little better to keep
> it secure first).
>
> > > 2. how do I say 'require valid-user'?
> >
> > This is a todo.
>
> Been thinking about this one too - would it make sense to default to 'any
> user in the backend' if require is unset?
> (That's the simplest way I can think of and would work for me, with LDAP
> the search filter is ludicrously flexible anyway)
>
> --
> 'common sense is what tells you that the world is flat.'
> -- Principia Discordia
> Rasputin :: Jack of All Trades - Master of Nuns
> Index: src/http_auth.c
> ===================================================================
> --- src/http_auth.c (revision 109)
> +++ src/http_auth.c (working copy)
> @@ -568,7 +568,17 @@
> return -1;
> }
>
> + if (p->conf.auth_ldap_starttls == 1) {
> + if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL, NULL))) {
> + log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
>
> + ldap_unbind_s(ldap);
> +
> + return -1;
> + }
> + }
> +
> +
> if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
> log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
>
> Index: src/http_auth.h
> ===================================================================
> --- src/http_auth.h (revision 109)
> +++ src/http_auth.h (working copy)
> @@ -28,6 +28,8 @@
> buffer *auth_ldap_hostname;
> buffer *auth_ldap_basedn;
> buffer *auth_ldap_filter;
> + buffer *auth_ldap_cafile;
> + unsigned short auth_ldap_starttls;
>
> unsigned short auth_debug;
>
> Index: src/mod_auth.c
> ===================================================================
> --- src/mod_auth.c (revision 109)
> +++ src/mod_auth.c (working copy)
> @@ -68,6 +68,7 @@
> buffer_free(s->auth_ldap_hostname);
> buffer_free(s->auth_ldap_basedn);
> buffer_free(s->auth_ldap_filter);
> + buffer_free(s->auth_ldap_cafile);
>
> #ifdef USE_LDAP
> buffer_free(s->ldap_filter_pre);
> @@ -131,6 +132,10 @@
> PATCH(auth_ldap_basedn);
> } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
> PATCH(auth_ldap_filter);
> + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.cafile"))) {
> + PATCH(auth_ldap_cafile);
> + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
> + PATCH(auth_ldap_starttls);
> }
> }
> }
> @@ -153,6 +158,8 @@
> PATCH(auth_ldap_hostname);
> PATCH(auth_ldap_basedn);
> PATCH(auth_ldap_filter);
> + PATCH(auth_ldap_cafile);
> + PATCH(auth_ldap_starttls);
> #ifdef USE_LDAP
> PATCH(ldap);
> PATCH(ldap_filter_pre);
> @@ -297,9 +304,11 @@
> { "auth.backend.ldap.hostname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
> { "auth.backend.ldap.base-dn", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
> { "auth.backend.ldap.filter", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
> + { "auth.backend.ldap.cafile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
> + { "auth.backend.ldap.starttls", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
> { "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
> { "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
> - { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
> + { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
> { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
> };
>
> @@ -321,6 +330,8 @@
> s->auth_ldap_hostname = buffer_init();
> s->auth_ldap_basedn = buffer_init();
> s->auth_ldap_filter = buffer_init();
> + s->auth_ldap_cafile = buffer_init();
> + s->auth_ldap_starttls = 0;
> s->auth_debug = 0;
>
> s->auth_require = array_init();
> @@ -338,9 +349,11 @@
> cv[4].destination = s->auth_ldap_hostname;
> cv[5].destination = s->auth_ldap_basedn;
> cv[6].destination = s->auth_ldap_filter;
> - cv[7].destination = s->auth_htdigest_userfile;
> - cv[8].destination = s->auth_htpasswd_userfile;
> - cv[9].destination = &(s->auth_debug);
> + cv[7].destination = s->auth_ldap_cafile;
> + cv[8].destination = &(s->auth_ldap_starttls);
> + cv[9].destination = s->auth_htdigest_userfile;
> + cv[10].destination = s->auth_htpasswd_userfile;
> + cv[11].destination = &(s->auth_debug);
>
> p->config_storage[i] = s;
> ca = ((data_config *)srv->config_context->data[i])->value;
> @@ -526,9 +539,23 @@
> ret = LDAP_VERSION3;
> if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
> log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
> -
> +
> return HANDLER_ERROR;
> }
> +
> + if (s->auth_ldap_starttls == 1 ) {
> + if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
s->auth_ldap_cafile->ptr))) {
> + log_error_write(srv, __FILE__, __LINE__, "ss", "Loading CA certificate failed:", ldap_err2string(ret));
> +
> + return HANDLER_ERROR;
> + }
> +
> + if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL, NULL))) {
> + log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
> +
> + return HANDLER_ERROR;
> + }
> + }
>
>
> /* 1. */
> Index: doc/authentification.txt
> ===================================================================
> --- doc/authentification.txt (revision 109)
> +++ doc/authentification.txt (working copy)
> @@ -39,7 +39,7 @@
> ``````
>
> The Digest method only transfers a hashed value over the
> -network which is performes a lot of work to harden the
> +network which performs a lot of work to harden the
> authentification process in insecure networks.
>
> Backends
> @@ -112,7 +112,7 @@
> ldap
> ````
>
> -the ldap backend is basicly performing the following steps
> +the ldap backend is basically performing the following steps
> to authenticate a user
>
> 1. connect anonymously (at plugin init)
> @@ -120,7 +120,7 @@
> 3. auth against ldap server
> 4. disconnect
>
> -if step 4 is performs without any error the user is
> +if all 4 steps are performed without any error the user is
> authenticated
>
> Configuration
> @@ -152,6 +152,10 @@
> auth.backend.ldap.hostname = "localhost"
> auth.backend.ldap.base-dn = "dc=my-domain,dc=com"
> auth.backend.ldap.filter = "(uid=$)"
> + # if enabled, startTLS needs a valid (base64-encoded) CA
> + # certificate
> + auth.backend.ldap.starttls = "enable"
> + auth.backend.ldap.cafile = "/etc/CAcertificate.pem"
>
> ## restrictions
> # set restrictions:
> @@ -162,7 +166,7 @@
> # "require" => "user=<username>" )
> # )
> #
> - # <realm> is a string that is should be display in the dialog
> + # <realm> is a string to display in the dialog
> # presented to the user and is also used for the
> # digest-algorithm and has to match the realm in the
> # htdigest file (if used)
> @@ -182,10 +186,10 @@
> )
> )
>
> -Limitiations
> +Limitations
> ============
>
> - The implementation of digest method is currently not
> - completely conforming to the standard as it is still allowing
> + completely compliant with the standard as it still allows
> a replay attack.
>
--
'Yeah, well I'm gonna build my own themepark! With blackjack aaand Hookers!
Actually, forget the park. And the blackjack.'
-- Bender
Rasputin :: Jack of All Trades - Master of Nuns
|
|
|