Authenticate to LDAP with GSSAPI
Hi, I have researched this topic and am unable to find examples or previous mailing lists queries about this specific issue. My issue is NOT using GSSAPI/krb5 to authenticate users and LDAP for user details. I have LDAP for authentication and user details with EAP, but I wish for the radiusd ldap connections to authenticate to the ldap server with GSSAPI (IE keytab / service account). The equivalent commands in userspace is: ldapsearch -Y GSSAPI '(objectClass=*)' I am unable to find references in the documentation as to how to achieve this. For example my current setup is: mods-enabled/ldap ldap { # ... snip ... identity = "krbprincipalname=radius/example.com,cn=services,cn=accounts,dc=example ,dc=com" password = foo } I would hopefully aim to have something akin to: ldap { # ... snip ... identity = "krbprincipalname=radius/example.com,cn=services,cn=accounts,dc=example ,dc=com" krb5_keytab = /etc/raddb/krb5.keytab krb5_principal = radius/example.com } Or even a combination of the keytab settings in mods-enabled/krb5 and mods-enabled/ldap. Does anyone have any experience with such configuration or whether freeradius supports the behaviour I would like to achieve? Sincerely, William
On 06/13/2015 09:07 PM, William wrote:
Hi,
I have researched this topic and am unable to find examples or previous mailing lists queries about this specific issue.
My issue is NOT using GSSAPI/krb5 to authenticate users and LDAP for user details.
I have LDAP for authentication and user details with EAP, but I wish for the radiusd ldap connections to authenticate to the ldap server with GSSAPI (IE keytab / service account).
The equivalent commands in userspace is:
ldapsearch -Y GSSAPI '(objectClass=*)'
I am unable to find references in the documentation as to how to achieve this.
For example my current setup is:
mods-enabled/ldap
ldap { # ... snip ... identity = "krbprincipalname=radius/example.com,cn=services,cn=accounts,dc=example ,dc=com" password = foo
}
I would hopefully aim to have something akin to:
ldap { # ... snip ... identity = "krbprincipalname=radius/example.com,cn=services,cn=accounts,dc=example ,dc=com" krb5_keytab = /etc/raddb/krb5.keytab krb5_principal = radius/example.com }
Or even a combination of the keytab settings in mods-enabled/krb5 and mods-enabled/ldap.
Does anyone have any experience with such configuration or whether freeradius supports the behaviour I would like to achieve?
Sincerely,
William - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html i vote for this functionality, too.
On 13 Jun 2015, at 21:37, Alan DeKok <aland@deployingradius.com> wrote:
On Jun 13, 2015, at 9:27 PM, Brendan Kearney <bpk678@gmail.com> wrote:
i vote for this functionality, too.
You're free to write a patch and submit it.
It's already supported. I just backported it from v3.1.x as SASL non-interactive bind didn't seem to work for EXTERNAL binds (which was the main reason I added SASL bind support). Regarding setting the keytab... no idea. How do you do it for ldapsearch? Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
On 13 Jun 2015, at 22:08, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
On 13 Jun 2015, at 21:37, Alan DeKok <aland@deployingradius.com> wrote:
On Jun 13, 2015, at 9:27 PM, Brendan Kearney <bpk678@gmail.com> wrote:
i vote for this functionality, too.
You're free to write a patch and submit it.
It's already supported. I just backported it from v3.1.x as SASL non-interactive bind didn't seem to work for EXTERNAL binds (which was the main reason I added SASL bind support).
Regarding setting the keytab... no idea. How do you do it for ldapsearch?
Hmm, this explains the limitation: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=412017 Apparently it's KRB5_KTNAME, there are probably other environmental variables to set other things... -Arran
i vote for this functionality, too.
You're free to write a patch and submit it.
It's already supported. I just backported it from v3.1.x as SASL non-interactive bind didn't seem to work for EXTERNAL binds (which was the main reason I added SASL bind support).
Regarding setting the keytab... no idea. How do you do it for ldapsearch?
Hmm, this explains the limitation:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=412017
Apparently it's KRB5_KTNAME, there are probably other environmental variables to set other things...
You can specify it with KRB5_KTNAME if you want the LDAP library to actually do the ktinit and manage the ccache itself. Alternatively, you can do the ktinit from your own application (IE radiusd) and then because the ccache is already created at that point, you can then pass that to the ldap search routines and it will utilise the crendentials. bind-dyndb-ldap has a good simple example of this. So anyway, what I'm gathering from this response is: * It's not currently supported * It would be nice to have Thanks all for the fast response, Sincerely, William
On 13 Jun 2015, at 22:48, William <william@firstyear.id.au> wrote:
i vote for this functionality, too.
You're free to write a patch and submit it.
It's already supported. I just backported it from v3.1.x as SASL non-interactive bind didn't seem to work for EXTERNAL binds (which was the main reason I added SASL bind support).
Regarding setting the keytab... no idea. How do you do it for ldapsearch?
Hmm, this explains the limitation:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=412017
Apparently it's KRB5_KTNAME, there are probably other environmental variables to set other things...
You can specify it with KRB5_KTNAME if you want the LDAP library to actually do the ktinit and manage the ccache itself. Alternatively, you can do the ktinit from your own application (IE radiusd) and then because the ccache is already created at that point, you can then pass that to the ldap search routines
I guess you could call it passing... but thats a bit misleading. Looks like it sets the KRB5CCNAME environmental variable, which then must get picked up somewhere deep and dark inside cyrus-sasl/krb5. https://github.com/pspacek/bind-dyndb-ldap/blob/master/src/krb5_helper.c#L12... and that code is used like this: https://github.com/pspacek/bind-dyndb-ldap/blob/master/src/ldap_helper.c#L28... https://github.com/pspacek/bind-dyndb-ldap/blob/master/src/ldap_helper.c#L29... <https://github.com/pspacek/bind-dyndb-ldap/blob/master/src/ldap_helper.c#L2901> their interact function certainly doesn't do anything special: https://github.com/pspacek/bind-dyndb-ldap/blob/master/src/ldap_helper.c#L26... <https://github.com/pspacek/bind-dyndb-ldap/blob/master/src/ldap_helper.c#L2690> That'd mean you could only maintain one global credential cache for the server... I guess that works, it's a bit crap, because it means the CC would be highly contended, but I don't really see security issues with it (someone feel free to correct me on that).
So anyway, what I'm gathering from this response is:
* It's not currently supported
Well you've not really said what you're trying to do here... What's the authentication flow? You'd authenticate the users with rlm_krb5, cache the tgt, then use it to authenticate against LDAP via SASL/GSSAPI? Currently rlm_krb5 removes the cached credentials soon after they're added. So that'd need to be altered, then we'd need to add maybe a post-auth method to remove the credentials after they'd been used with rlm_ldap. Past experience has shown that if you just let credentials build up in the CC it eventually starts having a big impact on performance. Hopefully the krb5 MEMORY CC is threadsafe, else that'd be a complete PITA. All the code changes would be inside rlm_krb5. Possibly: * Have an option to set the CC for the kerberos module. If the CC is just MEMORY, then a temporary in-memory CC is created. * Add an option to set_global_cc = <bool>, which sets KRB5CCNAME to the CC value of the module instance. if when the module instance attempts to set it, it finds an existing value, and the existing value does not match the configured value (with the exception of MEMORY prefixed CC values) the server refuses to start. CC initialisation is done if an existing CC does not exist. * Setting the CC config item automatically disables cache removal at the end of authenticate, but enables removal in a rlm_krb5 post-auth method. The other option is to have a global mutex, which is held during binds, and makes sure KRB5CCNAME isn't swapped out. But that's pretty nasty. No idea if it'd even work.
* It would be nice to have
Sure, but please discuss its development if thats your intention. -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
Well you've not really said what you're trying to do here... What's the authentication flow? You'd authenticate the users with rlm_krb5, cache the tgt, then use it to authenticate against LDAP via SASL/GSSAPI?
No: I would still be using LDAP for all *user* authentications, I just want the freeradius process to bind to ldap via GSSAPI/SASL using a service keytab rather than simple with a password.
Currently rlm_krb5 removes the cached credentials soon after they're added. So that'd need to be altered, then we'd need to add maybe a post-auth method to remove the credentials after they'd been used with rlm_ldap. Past experience has shown that if you just let credentials build up in the CC it eventually starts having a big impact on performance.
Why not have rlm_krb5 use a seperate in-memory ccache rather than the same one as other users / processes? Or am I misreading. Again, I'm not using the users krb5 ccache to auth to LDAP here, I want a radiusd keytab to auth to ldap via gssapi. However, the ability to support this specific setup you mention could be useful for some other people no doubt.
Hopefully the krb5 MEMORY CC is threadsafe, else that'd be a complete PITA.
All the code changes would be inside rlm_krb5. Possibly:
* Have an option to set the CC for the kerberos module. If the CC is just MEMORY, then a temporary in-memory CC is created.
* Add an option to set_global_cc = <bool>, which sets KRB5CCNAME to the CC value of the module instance. if when the module instance attempts to set it, it finds an existing value, and the existing value does not match the configured value (with the exception of MEMORY prefixed CC values) the server refuses to start. CC initialisation is done if an existing CC does not exist.
* Setting the CC config item automatically disables cache removal at the end of authenticate, but enables removal in a rlm_krb5 post-auth method.
The other option is to have a global mutex, which is held during binds, and makes sure KRB5CCNAME isn't swapped out. But that's pretty nasty. No idea if it'd even work.
* It would be nice to have
Sure, but please discuss its development if thats your intention.
Sadly, my development abilities lay else where. The purpose of this email was to ascertain whether the functionality existed, rather than to ask for it to be developed. Sincerely, William
Why not have rlm_krb5 use a seperate in-memory ccache rather than the same one as other users / processes?
What other processes? What other users? FreeRADIUS is a single process running under the same user. It has multiple modules, each of which may have multiple instances, with different configurations. Yes krb5 does use a different in memory cache, in fact it uses serveral, one for each 'context'. Each MEMORY CC is only used by one thread at a time, to ensure there's no contention. The modifications I suggested would allow krb5 to work with a single MEMORY CC, and change the lifetime of the entries, so they could be used with other modules which implemented kerberos. Currently that's probably only ldap, but it could theoretically be the rest module as well. This would be where, for some reason, you wanted the server to have the same authorizational profile as the user connecting. The server essentially becomes the user's proxy. This is a different sort of setup to the one you're enquiring about.
Or am I misreading.
You're misunderstanding. There's a big long chain of libraries before we get to kerberos when using it with LDAP. It goes: rlm_ldap -> libldap -> cyrus-sasl -> libkrb5. Question: How do you configure the keytab in krb5 via API calls? Answer: You don't, because the cyrus-sasl guys never exposed that functionality. The only way to configure libkrb5 is via environmental variables. That's how the code you posted sets its custom credential cache. It doesn't 'pass' the CC to LDAP functions, it sets an environmental variable which libkrb5 picks up way down the line. You can set the CC in radiusd's environment too (to a FILE, KCM or KEYRING CC for example).
Again, I'm not using the users krb5 ccache to auth to LDAP here, I want a radiusd keytab to auth to ldap via gssapi.
Then the functionality exists today? Set the keytab/CC in radiusd's environment and it'll work. There is no way to configure keytabs in FreeRADIUS on a per LDAP module instance basis. It's not a limitation of FreeRADIUS, it's a limitation of cyrus-sasl. There is no way we could add this functionality with current versions of libldap/cyrus-sasl. If we wanted to write our own SASL implementation, we could add this functionality, but that's a hell of a lot of work, and for the vast majority of users there'd be no benefit.
However, the ability to support this specific setup you mention could be useful for some other people no doubt.
Maybe, if other people want that, could they speak up now? Or are other people wanting the same type of authentication as the OP described?
Sure, but please discuss its development if thats your intention.
Sadly, my development abilities lay else where. The purpose of this email was to ascertain whether the functionality existed
Well, it does. Just not quite in the form you suggested it should, and again, that's not a limitation of FreeRADIUS, it's a limitation of cyrus-sasl, and IMHO not one that we should waste time addressing. If you find the current interact function does not work for you (i.e. it's not responding correctly to one of the prompts), post the debug output, and i'll do my best to fix it. -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
On Jun 14, 2015 12:31 PM, "Arran Cudbard-Bell" <a.cudbardb@freeradius.org> wrote:
Maybe, if other people want that, could they speak up now? Or are other
people wanting the same type of authentication as the OP described?
Speaking up... While I would like the ability to have radius authenticate to ldap via kerberos ticketing / keytab / gssapi / sasl, my scenario would differ in that I am only using ldap for AuthZ. AuthN is handled by my kerberos instances. I see application of keytab usage also benefiting interactions with AD. Maybe its just me, but I see the use of a keytab as "more secure" or maybe "less insecure" than having a password in a config file. Granted file permissions and the use of a "throw away ID" are best practices for this kind of setup, I still would favor the keytab use in addition to those steps.
Hi, On Sun, Jun 14, 2015 at 8:13 PM, brendan kearney <bpk678@gmail.com> wrote:
On Jun 14, 2015 12:31 PM, "Arran Cudbard-Bell" <a.cudbardb@freeradius.org> wrote:
Maybe, if other people want that, could they speak up now? Or are other
people wanting the same type of authentication as the OP described?
Speaking up...
While I would like the ability to have radius authenticate to ldap via kerberos ticketing / keytab / gssapi / sasl, my scenario would differ in that I am only using ldap for AuthZ. AuthN is handled by my kerberos instances.
If I got Arran's comment correctly then setting KRB5_CLIENT_KTNAME could work for that (KRB5_KTNAME is for acceptors, not initiators AFAI understand: http://web.mit.edu/kerberos/krb5-1.13/doc/basic/keytab_def.html). Or you are concern it might impact on the AuthN modules? I haven't tested or actually looked at the code just thinking outloud.
I see application of keytab usage also benefiting interactions with AD.
Maybe its just me, but I see the use of a keytab as "more secure" or maybe "less insecure" than having a password in a config file. Granted file permissions and the use of a "throw away ID" are best practices for this kind of setup, I still would favor the keytab use in addition to those steps.
Well, keytab contains the key[s] (which may have been derived from user's secret) so AFAI understand they are password equivalent. Regards, Isaac B.
Well, keytab contains the key[s] (which may have been derived from user's secret) so AFAI understand they are password equivalent.
Regards, Isaac B.
agreed, hence my "less insecure" notion, but those Risk Management types can check their check box about passwords not being stored in the clear on the file system.
On Sun, Jun 14, 2015 at 10:19 PM, brendan kearney <bpk678@gmail.com> wrote:
Well, keytab contains the key[s] (which may have been derived from user's secret) so AFAI understand they are password equivalent.
Regards, Isaac B.
agreed, hence my "less insecure" notion, but those Risk Management types can check their check box about passwords not being stored in the clear on the file system.
To be more accurate it might depend on the key type. Generally RC4 keys are unsalted hash of the password (specifically nt-hash, see RFC 4757). Perhaps salted keys could be considered somewhat better.
On Jun 15, 2015, at 10:36 AM, Isaac Boukris <iboukris@gmail.com> wrote:
On Sun, Jun 14, 2015 at 10:19 PM, brendan kearney <bpk678@gmail.com> wrote:
Well, keytab contains the key[s] (which may have been derived from user's secret) so AFAI understand they are password equivalent.
Regards, Isaac B.
agreed, hence my "less insecure" notion, but those Risk Management types can check their check box about passwords not being stored in the clear on the file system.
To be more accurate it might depend on the key type. Generally RC4 keys are unsalted hash of the password (specifically nt-hash, see RFC 4757). Perhaps salted keys could be considered somewhat better.
Ok, well for service authentication, as Isaac quite rightly said, KRB5_CLIENT_KTNAME is the environmental variable you need to specify the keytab. Once you have that set, SASL/GSSAPI should just work in v3.0.x HEAD rlm_ldap. I got about 70% through writing the used auth/autz modifications last night, i'll try push those up today. They'll be v3.1.x only until someone tests them and verifies they work, and don't break other kerberos operations. -Arran
Hi Arran, On Mon, Jun 15, 2015 at 8:24 PM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
I got about 70% through writing the used auth/autz modifications last night, i'll try push those up today. They'll be v3.1.x only until someone tests them and verifies they work, and don't break other kerberos operations.
I thought it would be fun to test and fun it was. First I tried simple setup to authenticate users via ldap-bind using simple bind for admin searches as well. I had some crashes with v3.1 so I ran away to v3.0 where at first I got a linkage issue for which I had to add 'sasl.c' to the makefile and then I got the same first crashes. Not sure I understood it well but I managed to solve it with: diff --git a/src/modules/rlm_ldap/ldap.c b/src/modules/rlm_ldap/ldap.c index 416a122..7cf8cae 100644 --- a/src/modules/rlm_ldap/ldap.c +++ b/src/modules/rlm_ldap/ldap.c @@ -717,7 +717,7 @@ ldap_rcode_t rlm_ldap_bind(rlm_ldap_t const *inst, REQUEST *request, ldap_handle num = retry ? fr_connection_get_num(inst->pool) : 0; for (i = num; i >= 0; i--) { #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND - if (sasl->mech) { + if (sasl && sasl->mech) { status = rlm_ldap_sasl_interactive(inst, request, *pconn, dn, password, sasl, &error, &extra); } else Then it worked with simple-bind for admin auth so I tried to set: mech = 'GSSAPI' And then I got auth failure which - from the wireshark traces - I think was related to 'identity' directive being set with a DN so I comment it out (along with the 'password' directive) as it should not be necessary. But I got another crash which I worked around again by: diff --git a/src/modules/rlm_ldap/sasl.c b/src/modules/rlm_ldap/sasl.c index 0e58bba..f519483 100644 --- a/src/modules/rlm_ldap/sasl.c +++ b/src/modules/rlm_ldap/sasl.c @@ -63,7 +63,7 @@ static int _sasl_interact(UNUSED LDAP *handle, UNUSED unsigned flags, void *ctx, break; case SASL_CB_USER: - cb_p->result = this->extra->proxy ? this->extra->proxy : this->identity; + cb_p->result = (this->extra && this->extra->proxy) ? this->extra->proxy : this->identity; break; case SASL_CB_GETREALM: Now it works fine with Kerberos auth for admin searches using the KRB5_CLIENT_KTNAME but the fun part is when I set: mech = 'GSS-SPNEGO' It uses spnego and when KRB5_CLIENT_KTNAME is not available it fails-over to using my NTLM system credentials and works fine (lookup gss-ntlmssp for details). Regards, Isaac B.
On 15 Jun 2015, at 21:07, Isaac Boukris <iboukris@gmail.com> wrote:
Hi Arran,
On Mon, Jun 15, 2015 at 8:24 PM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
I got about 70% through writing the used auth/autz modifications last night, i'll try push those up today. They'll be v3.1.x only until someone tests them and verifies they work, and don't break other kerberos operations.
I thought it would be fun to test and fun it was.
First I tried simple setup to authenticate users via ldap-bind using simple bind for admin searches as well. I had some crashes with v3.1 so I ran away to v3.0 where at first I got a linkage issue for which I had to add 'sasl.c' to the makefile and then I got the same first crashes.
Ah, sorry about that. It was only previously tested with EXTERNAL and was waiting for further tests. Another guy was complaining about the non-interactive version not being useful, so I backported it, a little too hastily apparently.
Not sure I understood it well but I managed to solve it with:
diff --git a/src/modules/rlm_ldap/ldap.c b/src/modules/rlm_ldap/ldap.c index 416a122..7cf8cae 100644 --- a/src/modules/rlm_ldap/ldap.c +++ b/src/modules/rlm_ldap/ldap.c @@ -717,7 +717,7 @@ ldap_rcode_t rlm_ldap_bind(rlm_ldap_t const *inst, REQUEST *request, ldap_handle num = retry ? fr_connection_get_num(inst->pool) : 0; for (i = num; i >= 0; i--) { #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND - if (sasl->mech) { + if (sasl && sasl->mech) {
That's the correct fix.
Then it worked with simple-bind for admin auth so I tried to set: mech = 'GSSAPI' And then I got auth failure which - from the wireshark traces - I think was related to 'identity' directive being set with a DN so I comment it out (along with the 'password' directive) as it should not be necessary.
Well you control the value sent in identity. So if it was a DN that's what you had in the config file... I hope?
But I got another crash which I worked around again by:
diff --git a/src/modules/rlm_ldap/sasl.c b/src/modules/rlm_ldap/sasl.c index 0e58bba..f519483 100644 --- a/src/modules/rlm_ldap/sasl.c +++ b/src/modules/rlm_ldap/sasl.c @@ -63,7 +63,7 @@ static int _sasl_interact(UNUSED LDAP *handle, UNUSED unsigned flags, void *ctx, break;
case SASL_CB_USER: - cb_p->result = this->extra->proxy ? this->extra->proxy : this->identity; + cb_p->result = (this->extra && this->extra->proxy) ? this->extra->proxy : this->identity; break;
Not the correct fix. I've pushed another one.
case SASL_CB_GETREALM:
Now it works fine with Kerberos auth for admin searches using the KRB5_CLIENT_KTNAME but the fun part is when I set: mech = 'GSS-SPNEGO' It uses spnego and when KRB5_CLIENT_KTNAME is not available it fails-over to using my NTLM system credentials and works fine (lookup gss-ntlmssp for details).
Hehe, as it should I guess, that's neat. Thankyou very much for testing and providing feedback. I've pushed fixes for the issues you've encountered and updated the default ldap config file. -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
On Tue, Jun 16, 2015 at 5:55 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
On 15 Jun 2015, at 21:07, Isaac Boukris <iboukris@gmail.com> wrote: Then it worked with simple-bind for admin auth so I tried to set: mech = 'GSSAPI' And then I got auth failure which - from the wireshark traces - I think was related to 'identity' directive being set with a DN so I comment it out (along with the 'password' directive) as it should not be necessary.
Well you control the value sent in identity. So if it was a DN that's what you had in the config file... I hope?
Yea, it was the DN of the same user principle that's in the keytab. Perhaps specifying it implies simple-bind (no sasl).
Now it works fine with Kerberos auth for admin searches using the KRB5_CLIENT_KTNAME but the fun part is when I set: mech = 'GSS-SPNEGO' It uses spnego and when KRB5_CLIENT_KTNAME is not available it fails-over to using my NTLM system credentials and works fine (lookup gss-ntlmssp for details).
Hehe, as it should I guess, that's neat.
Yes, funny how many pseudo mechanism though - sasl(gssapi(spnego(actual_mech))) ;-) However, I just found out it doesn't fully work well yet :-( The bind succeed but later when radiusd makes a search query the LDAP (AD) simply does not respond (it does respond if simple-bind is used). It puzzled me for a while till I compared network traces with the equivalent "ldapsearch -Y GSSAPI" command. It appears that when GSSAPI is used then 'ldapsearch' will also use an encryption wrapping scheme to envelop the subsequent search requests to the server. My guess is that the server does not respond because it expect that (see attached capture - at the very end you can see the successful ldapsearch). Need to look into it, perhaps it's negotiable or some sasl library calls should be changed. I'll try to look into ldapsearch code and investigate further - ideas of solutions are welcome :)
Thankyou very much for testing and providing feedback. I've pushed fixes for the issues you've encountered and updated the default ldap config file.
I can confirm the crashes are gone and it works well. I still have the linkage run time issue unless I add 'sasl.c' to 'rlm_ldap/all.mk.in' with v3.0 (no build-tools expert). Thank you guys for this great and open source software.
Hi, On Wed, Jun 17, 2015 at 2:51 AM, Alan DeKok <aland@deployingradius.com> wrote:
On Jun 16, 2015, at 7:02 PM, Isaac Boukris <iboukris@gmail.com> wrote:
I can confirm the crashes are gone and it works well. I still have the linkage run time issue unless I add 'sasl.c' to 'rlm_ldap/all.mk.in' with v3.0 (no build-tools expert).
I've pushed a fix.
Thanks Alan! I've made some progress with my 'LDAP not responding problem'. If I set "SASL_SECPROPS maxssf=0" in my 'ldap.conf' file then both 'ldapsearch' and 'radiusd' won't encrypt the search request and - most importantly - the LDAP server answers to both of them! So I guess we can call that 'working' for now as the admin authentication use kerberos. I'll try however to investigate further why 'radiusd' won't encrypt like 'ldapsearch' does when I don't limit 'ssf'. Also interesting to understand how this is negotiated at sasl level (as I'm convinced now). Regards, Isaac B.
Hi Arran / all, On Wed, Jun 17, 2015 at 9:17 PM, Isaac Boukris <iboukris@gmail.com> wrote:
I've made some progress with my 'LDAP not responding problem'.
If I set "SASL_SECPROPS maxssf=0" in my 'ldap.conf' file then both 'ldapsearch' and 'radiusd' won't encrypt the search request and - most importantly - the LDAP server answers to both of them! So I guess we can call that 'working' for now as the admin authentication use kerberos.
I'll try however to investigate further why 'radiusd' won't encrypt like 'ldapsearch' does when I don't limit 'ssf'. Also interesting to understand how this is negotiated at sasl level (as I'm convinced now).
I've made some more progress. The difference between 'radiusd' and 'ldapsearch' seem to be at the 'bind' stage where 'ldapsearch' calls 'ldap_sasl_interactive_bind()' one more time compare to 'radiusd'. It seem that in this last call the ldap library checks the 'ssf' and sets the security layers (encoding and decoding callbacks, see in 'ldap_int_sasl_bind'). I notice that while 'ldapsearch' loops over the return value from 'ldap_sasl_interactive_bind()' call: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common.... We instead loop over the return value from 'rlm_ldap_result()' call: https://github.com/FreeRADIUS/freeradius-server/blob/v3.1.x/src/modules/rlm_... When I change the loop in 'radiusd' to 'while (ret != LDAP_SASL_BIND_IN_PROGRESS)' I can see that we go further in the flow since 'radiusd -X' prints more sasl related lines similar to what 'ldapsearch' prints (it used to print only the first line that starts with SASL). rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. rlm_ldap (ldap): Bind with (anonymous) to ldap://ms.frenche.cp:389 failed: Timed out while waiting for server to respond rlm_ldap (ldap): Opening connection failed (0) rlm_ldap (ldap): Removing connection pool /usr/local/etc/raddb/mods-enabled/ldap[8]: Instantiation failed for module "ldap" Of course it now fails (anonymous?) as I probably messed up the code logic but it seems the right direction. I'd like to investigate further but I could use some assistance and ideas ;-) Regards, Isaac B.
On Sun, Jun 21, 2015 at 7:31 PM, Isaac Boukris <iboukris@gmail.com> wrote:
Hi Arran / all,
On Wed, Jun 17, 2015 at 9:17 PM, Isaac Boukris <iboukris@gmail.com> wrote:
I've made some progress with my 'LDAP not responding problem'.
If I set "SASL_SECPROPS maxssf=0" in my 'ldap.conf' file then both 'ldapsearch' and 'radiusd' won't encrypt the search request and - most importantly - the LDAP server answers to both of them! So I guess we can call that 'working' for now as the admin authentication use kerberos.
I'll try however to investigate further why 'radiusd' won't encrypt like 'ldapsearch' does when I don't limit 'ssf'. Also interesting to understand how this is negotiated at sasl level (as I'm convinced now).
I've made some more progress. The difference between 'radiusd' and 'ldapsearch' seem to be at the 'bind' stage where 'ldapsearch' calls 'ldap_sasl_interactive_bind()' one more time compare to 'radiusd'. It seem that in this last call the ldap library checks the 'ssf' and sets the security layers (encoding and decoding callbacks, see in 'ldap_int_sasl_bind').
I notice that while 'ldapsearch' loops over the return value from 'ldap_sasl_interactive_bind()' call: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common....
We instead loop over the return value from 'rlm_ldap_result()' call: https://github.com/FreeRADIUS/freeradius-server/blob/v3.1.x/src/modules/rlm_...
When I change the loop in 'radiusd' to 'while (ret != LDAP_SASL_BIND_IN_PROGRESS)' I can see that we go further in the flow since 'radiusd -X' prints more sasl related lines similar to what 'ldapsearch' prints (it used to print only the first line that starts with SASL).
rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. rlm_ldap (ldap): Bind with (anonymous) to ldap://ms.frenche.cp:389 failed: Timed out while waiting for server to respond rlm_ldap (ldap): Opening connection failed (0) rlm_ldap (ldap): Removing connection pool /usr/local/etc/raddb/mods-enabled/ldap[8]: Instantiation failed for module "ldap"
Of course it now fails (anonymous?) as I probably messed up the code logic but it seems the right direction. I'd like to investigate further but I could use some assistance and ideas ;-)
Ok, I got it to actually work (including the encryption / sealing part). Here is the working diff (LDAP_SASL_BIND_IN_PROGRESS = 14): diff --git a/src/modules/rlm_ldap/sasl.c b/src/modules/rlm_ldap/sasl.c index 5686f2b..2d61107 100644 --- a/src/modules/rlm_ldap/sasl.c +++ b/src/modules/rlm_ldap/sasl.c @@ -125,6 +125,7 @@ ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request, NULL, NULL, LDAP_SASL_AUTOMATIC, _sasl_interact, &sasl_ctx, result, &mech, &msgid); + if(ret != 14) break; ldap_msgfree(result); /* We always need to free the old message */ if (ret >= 0) MOD_ROPTIONAL(RDEBUG3, DEBUG3, "Continuing SASL mech %s...", mech); @@ -145,7 +146,7 @@ ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request, ldap_memfree(srv_cred); } } - } while (status == LDAP_PROC_CONTINUE); + } while (ret == 14); ldap_msgfree(result); return status; Need some polishing etc but this works :) Regards, Isaac B.
Ok, I got it to actually work (including the encryption / sealing part). Here is the working diff (LDAP_SASL_BIND_IN_PROGRESS = 14):
diff --git a/src/modules/rlm_ldap/sasl.c b/src/modules/rlm_ldap/sasl.c index 5686f2b..2d61107 100644 --- a/src/modules/rlm_ldap/sasl.c +++ b/src/modules/rlm_ldap/sasl.c @@ -125,6 +125,7 @@ ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request, NULL, NULL, LDAP_SASL_AUTOMATIC, _sasl_interact, &sasl_ctx, result, &mech, &msgid); + if(ret != 14) break;
ldap_msgfree(result); /* We always need to free the old message */ if (ret >= 0) MOD_ROPTIONAL(RDEBUG3, DEBUG3, "Continuing SASL mech %s...", mech);
@@ -145,7 +146,7 @@ ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request, ldap_memfree(srv_cred); } } - } while (status == LDAP_PROC_CONTINUE); + } while (ret == 14); ldap_msgfree(result);
return status;
Need some polishing etc but this works :)
Not really correct, but does give a clue to what might be going on. With your patch status wouldn't get set on the final round of SASL auth, so rlm_ldap_sasl_interactive would return the wrong ldap_rcode_t value. rlm_ldap_result should be used to get the result via ldap_result, and check it for errors with ldap_parse_result. I can see that possibly ldap_parse_result is giving bad return codes, which is causing the loop to terminate. I can't really claim that, that's a bug in the libldap code, because the man pages don't explicitly mention ldap_result being able to parse SASL bind results. I'm guessing previously you were getting an error message starting with 'LDAP lib error:' could you post that to the list so we can see what ldap_parse_result was returning and determine if it was something innocuous being miscategorised as an error. I saw one potential issue and fixed it, so you may want to try with current v3.0.x HEAD. -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
On Sun, Jun 21, 2015 at 10:37 PM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Ok, I got it to actually work (including the encryption / sealing part). Here is the working diff (LDAP_SASL_BIND_IN_PROGRESS = 14):
diff --git a/src/modules/rlm_ldap/sasl.c b/src/modules/rlm_ldap/sasl.c index 5686f2b..2d61107 100644 --- a/src/modules/rlm_ldap/sasl.c +++ b/src/modules/rlm_ldap/sasl.c @@ -125,6 +125,7 @@ ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request, NULL, NULL, LDAP_SASL_AUTOMATIC, _sasl_interact, &sasl_ctx, result, &mech, &msgid); + if(ret != 14) break;
ldap_msgfree(result); /* We always need to free the old message */ if (ret >= 0) MOD_ROPTIONAL(RDEBUG3, DEBUG3, "Continuing SASL mech %s...", mech);
@@ -145,7 +146,7 @@ ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request, ldap_memfree(srv_cred); } } - } while (status == LDAP_PROC_CONTINUE); + } while (ret == 14); ldap_msgfree(result);
return status;
Need some polishing etc but this works :)
Not really correct, but does give a clue to what might be going on. With your patch status wouldn't get set on the final round of SASL auth, so rlm_ldap_sasl_interactive would return the wrong ldap_rcode_t value.
Admittedly, I am not familiar enough with ldap library to be confident about my patch. It was based on gdb'ing both 'ldapsearch' and 'radiusd' and comparing the library calls as mentioned.
rlm_ldap_result should be used to get the result via ldap_result, and check it for errors with ldap_parse_result. I can see that possibly ldap_parse_result is giving bad return codes, which is causing the loop to terminate.
Note that this is what 'ldapsearch' seem to be doing, it breaks from the loop before calling 'ldap_result()' once we aren't in 'progress', see: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common....
I can't really claim that, that's a bug in the libldap code, because the man pages don't explicitly mention ldap_result being able to parse SASL bind results.
I'm guessing previously you were getting an error message starting with 'LDAP lib error:' could you post that to the list so we can see what ldap_parse_result was returning and determine if it was something innocuous being miscategorised as an error.
Initially there was no error at binding stage but subsequents 'search' were sent and 'clear' and were not responded by the LDAP server (unless I limit 'ssf' as mentioned).
I saw one potential issue and fixed it, so you may want to try with current v3.0.x HEAD.
Now I get similar failure to the one I got with my initial 'patch' (which I've posted two emails ago). The server hangs right after it prints "SASL data security layer installed." then it fails. Pasting again: rlm_ldap: libldap vendor: OpenLDAP, version: 20440 accounting { reference = "%{tolower:type.%{Acct-Status-Type}}" } post-auth { reference = "." } rlm_ldap (ldap): Initialising connection pool pool { start = 5 min = 1 max = 1 spare = 10 uses = 0 lifetime = 0 cleanup_interval = 30 idle_timeout = 60 retry_delay = 30 spread = no } WARNING: Ignoring "start = 5", forcing to "start = 1" WARNING: Ignoring "spare = 10", forcing to "spare = 0" rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. rlm_ldap (ldap): Bind with (anonymous) to ldap://ms.frenche.cp:389 failed: Timed out while waiting for server to respond rlm_ldap (ldap): Opening connection failed (0) rlm_ldap (ldap): Removing connection pool /usr/local/etc/raddb/mods-enabled/ldap[8]: Instantiation failed for module "ldap" Regards.
Not really correct, but does give a clue to what might be going on. With your patch status wouldn't get set on the final round of SASL auth, so rlm_ldap_sasl_interactive would return the wrong ldap_rcode_t value.
Admittedly, I am not familiar enough with ldap library to be confident about my patch. It was based on gdb'ing both 'ldapsearch' and 'radiusd' and comparing the library calls as mentioned.
Sure.
rlm_ldap_result should be used to get the result via ldap_result, and check it for errors with ldap_parse_result. I can see that possibly ldap_parse_result is giving bad return codes, which is causing the loop to terminate.
Note that this is what 'ldapsearch' seem to be doing, it breaks from the loop before calling 'ldap_result()' once we aren't in 'progress', see: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common....
OK that helps. So my guess is that ldap_result will indicate that the bind was successful before ldap_sasl_interactive_bind indicates tells us that, and that on the final loop ldap_sasl_interactive_bind doesn't actually send anything to the server, it just indicates that the previous operation was successful. Slightly odd that it wouldn't set some kind of NULL/noop msgid that would indicate that, I guess that's a bug (or 'feature') of libldap. I've fudged rlm_ldap_result to take a -1 msgid, which causes it to skip attempting to retrieve the result, and just do error processing using the handle. I think that should fix everything.
I can't really claim that, that's a bug in the libldap code, because the man pages don't explicitly mention ldap_result being able to parse SASL bind results.
I'm guessing previously you were getting an error message starting with 'LDAP lib error:' could you post that to the list so we can see what ldap_parse_result was returning and determine if it was something innocuous being miscategorised as an error.
Initially there was no error at binding stage but subsequents 'search' were sent and 'clear' and were not responded by the LDAP server (unless I limit 'ssf' as mentioned).
OK.
I saw one potential issue and fixed it, so you may want to try with current v3.0.x HEAD.
Now I get similar failure to the one I got with my initial 'patch' (which I've posted two emails ago). The server hangs right after it prints "SASL data security layer installed." then it fails.
Yeah, that makes sense now... -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
On Mon, Jun 22, 2015 at 2:39 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Not really correct, but does give a clue to what might be going on. With your patch status wouldn't get set on the final round of SASL auth, so rlm_ldap_sasl_interactive would return the wrong ldap_rcode_t value.
Admittedly, I am not familiar enough with ldap library to be confident about my patch. It was based on gdb'ing both 'ldapsearch' and 'radiusd' and comparing the library calls as mentioned.
Sure.
rlm_ldap_result should be used to get the result via ldap_result, and check it for errors with ldap_parse_result. I can see that possibly ldap_parse_result is giving bad return codes, which is causing the loop to terminate.
Note that this is what 'ldapsearch' seem to be doing, it breaks from the loop before calling 'ldap_result()' once we aren't in 'progress', see: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common....
OK that helps.
So my guess is that ldap_result will indicate that the bind was successful before ldap_sasl_interactive_bind indicates tells us that, and that on the final loop ldap_sasl_interactive_bind doesn't actually send anything to the server, it just indicates that the previous operation was successful.
Yea, that what it looks like, I see on the wire that the server sent 'success' but ldap_sasl_interactive_bind still returns LDAP_SASL_BIND_IN_PROGRESS. Perhaps it just want to be called again in order to install the security layers (not to communicate with the server). I tried to read some doc, it isn't clear but it could match the behaviour we see.
Slightly odd that it wouldn't set some kind of NULL/noop msgid that would indicate that, I guess that's a bug (or 'feature') of libldap.
I've fudged rlm_ldap_result to take a -1 msgid, which causes it to skip attempting to retrieve the result, and just do error processing using the handle.
I think that should fix everything.
Not yet :( I now get (limiting 'ssf' doesn't make a diff): rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: error.c:255: ldap_parse_result: Assertion `r != ((void *)0)' failed. Aborted (core dumped) Let me know if you want the back-trace. Thanks for working with me on this.
On 21 Jun 2015, at 20:04, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 2:39 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Not really correct, but does give a clue to what might be going on. With your patch status wouldn't get set on the final round of SASL auth, so rlm_ldap_sasl_interactive would return the wrong ldap_rcode_t value.
Admittedly, I am not familiar enough with ldap library to be confident about my patch. It was based on gdb'ing both 'ldapsearch' and 'radiusd' and comparing the library calls as mentioned.
Sure.
rlm_ldap_result should be used to get the result via ldap_result, and check it for errors with ldap_parse_result. I can see that possibly ldap_parse_result is giving bad return codes, which is causing the loop to terminate.
Note that this is what 'ldapsearch' seem to be doing, it breaks from the loop before calling 'ldap_result()' once we aren't in 'progress', see: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common....
OK that helps.
So my guess is that ldap_result will indicate that the bind was successful before ldap_sasl_interactive_bind indicates tells us that, and that on the final loop ldap_sasl_interactive_bind doesn't actually send anything to the server, it just indicates that the previous operation was successful.
Yea, that what it looks like, I see on the wire that the server sent 'success' but ldap_sasl_interactive_bind still returns LDAP_SASL_BIND_IN_PROGRESS. Perhaps it just want to be called again in order to install the security layers (not to communicate with the server).
Ah possibly.
I tried to read some doc, it isn't clear but it could match the behaviour we see.
Slightly odd that it wouldn't set some kind of NULL/noop msgid that would indicate that, I guess that's a bug (or 'feature') of libldap.
I've fudged rlm_ldap_result to take a -1 msgid, which causes it to skip attempting to retrieve the result, and just do error processing using the handle.
I think that should fix everything.
Not yet :( I now get (limiting 'ssf' doesn't make a diff):
rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: error.c:255: ldap_parse_result: Assertion `r != ((void *)0)' failed. Aborted (core dumped)
Let me know if you want the back-trace.
Nah I see the problem.
Thanks for working with me on this.
No problem. Should work now (hopefully). -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
On Mon, Jun 22, 2015 at 3:52 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
On 21 Jun 2015, at 20:04, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 2:39 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Not really correct, but does give a clue to what might be going on. With your patch status wouldn't get set on the final round of SASL auth, so rlm_ldap_sasl_interactive would return the wrong ldap_rcode_t value.
Admittedly, I am not familiar enough with ldap library to be confident about my patch. It was based on gdb'ing both 'ldapsearch' and 'radiusd' and comparing the library calls as mentioned.
Sure.
rlm_ldap_result should be used to get the result via ldap_result, and check it for errors with ldap_parse_result. I can see that possibly ldap_parse_result is giving bad return codes, which is causing the loop to terminate.
Note that this is what 'ldapsearch' seem to be doing, it breaks from the loop before calling 'ldap_result()' once we aren't in 'progress', see: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common....
OK that helps.
So my guess is that ldap_result will indicate that the bind was successful before ldap_sasl_interactive_bind indicates tells us that, and that on the final loop ldap_sasl_interactive_bind doesn't actually send anything to the server, it just indicates that the previous operation was successful.
Yea, that what it looks like, I see on the wire that the server sent 'success' but ldap_sasl_interactive_bind still returns LDAP_SASL_BIND_IN_PROGRESS. Perhaps it just want to be called again in order to install the security layers (not to communicate with the server).
Ah possibly.
I tried to read some doc, it isn't clear but it could match the behaviour we see.
Slightly odd that it wouldn't set some kind of NULL/noop msgid that would indicate that, I guess that's a bug (or 'feature') of libldap.
I've fudged rlm_ldap_result to take a -1 msgid, which causes it to skip attempting to retrieve the result, and just do error processing using the handle.
I think that should fix everything.
Not yet :( I now get (limiting 'ssf' doesn't make a diff):
rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: error.c:255: ldap_parse_result: Assertion `r != ((void *)0)' failed. Aborted (core dumped)
Let me know if you want the back-trace.
Nah I see the problem.
Thanks for working with me on this.
No problem. Should work now (hopefully).
One more to go :) rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. Program received signal SIGSEGV, Segmentation fault. 0xb7773114 in rlm_ldap_result (inst=0x8277490, conn=0x82a23b0, msgid=-1, dn=0xb777b564 "", result=0x0, error=0xbffff2fc, extra=0xbffff2f8) at src/modules/rlm_ldap/ldap.c:480 480 *result = NULL; (gdb) bt #0 0xb7773114 in rlm_ldap_result (inst=0x8277490, conn=0x82a23b0, msgid=-1, dn=0xb777b564 "", result=0x0, error=0xbffff2fc, extra=0xbffff2f8) at src/modules/rlm_ldap/ldap.c:480 #1 0xb77789e4 in rlm_ldap_sasl_interactive (inst=0x8277490, request=0x0, conn=0x82a23b0, identity=0xb777b564 "", password=0x0, sasl=0x82774ac, error=0xbffff2fc, extra=0xbffff2f8) at src/modules/rlm_ldap/sasl.c:142 #2 0xb77736a0 in rlm_ldap_bind (inst=0x8277490, request=0x0, pconn=0xbffff350, dn=0xb777b564 "", password=0x0, sasl=0x82774ac, retry=false) at src/modules/rlm_ldap/ldap.c:717 Perhaps I could add dbg prints.
On 21 Jun 2015, at 21:01, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 3:52 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
On 21 Jun 2015, at 20:04, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 2:39 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Not really correct, but does give a clue to what might be going on. With your patch status wouldn't get set on the final round of SASL auth, so rlm_ldap_sasl_interactive would return the wrong ldap_rcode_t value.
Admittedly, I am not familiar enough with ldap library to be confident about my patch. It was based on gdb'ing both 'ldapsearch' and 'radiusd' and comparing the library calls as mentioned.
Sure.
rlm_ldap_result should be used to get the result via ldap_result, and check it for errors with ldap_parse_result. I can see that possibly ldap_parse_result is giving bad return codes, which is causing the loop to terminate.
Note that this is what 'ldapsearch' seem to be doing, it breaks from the loop before calling 'ldap_result()' once we aren't in 'progress', see: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common....
OK that helps.
So my guess is that ldap_result will indicate that the bind was successful before ldap_sasl_interactive_bind indicates tells us that, and that on the final loop ldap_sasl_interactive_bind doesn't actually send anything to the server, it just indicates that the previous operation was successful.
Yea, that what it looks like, I see on the wire that the server sent 'success' but ldap_sasl_interactive_bind still returns LDAP_SASL_BIND_IN_PROGRESS. Perhaps it just want to be called again in order to install the security layers (not to communicate with the server).
Ah possibly.
I tried to read some doc, it isn't clear but it could match the behaviour we see.
Slightly odd that it wouldn't set some kind of NULL/noop msgid that would indicate that, I guess that's a bug (or 'feature') of libldap.
I've fudged rlm_ldap_result to take a -1 msgid, which causes it to skip attempting to retrieve the result, and just do error processing using the handle.
I think that should fix everything.
Not yet :( I now get (limiting 'ssf' doesn't make a diff):
rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: error.c:255: ldap_parse_result: Assertion `r != ((void *)0)' failed. Aborted (core dumped)
Let me know if you want the back-trace.
Nah I see the problem.
Thanks for working with me on this.
No problem. Should work now (hopefully).
One more to go :)
done. Result can be null now *sigh*. -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
On Mon, Jun 22, 2015 at 4:05 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
On 21 Jun 2015, at 21:01, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 3:52 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
On 21 Jun 2015, at 20:04, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 2:39 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
> > Not really correct, but does give a clue to what might be going on. With your patch status wouldn't get set on the final round of SASL auth, so rlm_ldap_sasl_interactive would return the wrong ldap_rcode_t value.
Admittedly, I am not familiar enough with ldap library to be confident about my patch. It was based on gdb'ing both 'ldapsearch' and 'radiusd' and comparing the library calls as mentioned.
Sure.
> rlm_ldap_result should be used to get the result via ldap_result, and check it for errors with ldap_parse_result. I can see that possibly ldap_parse_result is giving bad return codes, which is causing the loop to terminate.
Note that this is what 'ldapsearch' seem to be doing, it breaks from the loop before calling 'ldap_result()' once we aren't in 'progress', see: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common....
OK that helps.
So my guess is that ldap_result will indicate that the bind was successful before ldap_sasl_interactive_bind indicates tells us that, and that on the final loop ldap_sasl_interactive_bind doesn't actually send anything to the server, it just indicates that the previous operation was successful.
Yea, that what it looks like, I see on the wire that the server sent 'success' but ldap_sasl_interactive_bind still returns LDAP_SASL_BIND_IN_PROGRESS. Perhaps it just want to be called again in order to install the security layers (not to communicate with the server).
Ah possibly.
I tried to read some doc, it isn't clear but it could match the behaviour we see.
Slightly odd that it wouldn't set some kind of NULL/noop msgid that would indicate that, I guess that's a bug (or 'feature') of libldap.
I've fudged rlm_ldap_result to take a -1 msgid, which causes it to skip attempting to retrieve the result, and just do error processing using the handle.
I think that should fix everything.
Not yet :( I now get (limiting 'ssf' doesn't make a diff):
rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: error.c:255: ldap_parse_result: Assertion `r != ((void *)0)' failed. Aborted (core dumped)
Let me know if you want the back-trace.
Nah I see the problem.
Thanks for working with me on this.
No problem. Should work now (hopefully).
One more to go :)
done.
Result can be null now *sigh*.
And one more assertion: rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed. Aborted (core dumped) Thanks!
Result can be null now *sigh*.
And one more assertion:
rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed. Aborted (core dumped)
and on to the next one... Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
On Mon, Jun 22, 2015 at 4:26 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Result can be null now *sigh*.
And one more assertion:
rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed. Aborted (core dumped)
and on to the next one...
Still (I'm testing with v3.0 btw). rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed. Program received signal SIGABRT, Aborted. 0xb7fdbbe0 in __kernel_vsyscall () (gdb) bt #0 0xb7fdbbe0 in __kernel_vsyscall () #1 0xb7a54297 in __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:55 #2 0xb7a55b69 in __GI_abort () at abort.c:89 #3 0xb7a4d297 in __assert_fail_base (fmt=0xb7b9e554 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0xb7703468 "((ber)->ber_opts.lbo_valid==0x2)", file=0xb7703a21 "io.c", line=186, function=0xb7703be9 <__PRETTY_FUNCTION__.6470> "ber_free_buf") at assert.c:92 #4 0xb7a4d31b in __GI___assert_fail (assertion=assertion@entry=0xb7703468 "((ber)->ber_opts.lbo_valid==0x2)", file=file@entry=0xb7703a21 "io.c", line=line@entry=186, function=function@entry=0xb7703be9 <__PRETTY_FUNCTION__.6470> "ber_free_buf") at assert.c:101 #5 0xb76fe8c5 in ber_free_buf (ber=0x82ae380) at io.c:186 #6 0xb76fe910 in ber_free (ber=0x82ae380, freebuf=freebuf@entry=1) at io.c:203 #7 0xb7715d09 in ldap_msgfree (lm=0x82ae868) at result.c:1279 #8 0xb7778bb0 in rlm_ldap_sasl_interactive (inst=0x8277490, request=0x0, conn=0x82a23b0, identity=0xb777b564 "", password=0x0, sasl=0x82774ac, error=0xbffff2fc, extra=0xbffff2f8) at src/modules/rlm_ldap/sasl.c:183 #9 0xb77736ad in rlm_ldap_bind (inst=0x8277490, request=0x0, pconn=0xbffff350, dn=0xb777b564 "", password=0x0, sasl=0x82774ac, retry=false) at src/modules/rlm_ldap/ldap.c:717
On Mon, Jun 22, 2015 at 4:37 AM, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 4:26 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Result can be null now *sigh*.
And one more assertion:
rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed. Aborted (core dumped)
and on to the next one...
Still (I'm testing with v3.0 btw).
rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed.
Program received signal SIGABRT, Aborted. 0xb7fdbbe0 in __kernel_vsyscall () (gdb) bt #0 0xb7fdbbe0 in __kernel_vsyscall () #1 0xb7a54297 in __GI_raise (sig=6) at ../sysdeps/unix/sysv/linux/raise.c:55 #2 0xb7a55b69 in __GI_abort () at abort.c:89 #3 0xb7a4d297 in __assert_fail_base (fmt=0xb7b9e554 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0xb7703468 "((ber)->ber_opts.lbo_valid==0x2)", file=0xb7703a21 "io.c", line=186, function=0xb7703be9 <__PRETTY_FUNCTION__.6470> "ber_free_buf") at assert.c:92 #4 0xb7a4d31b in __GI___assert_fail (assertion=assertion@entry=0xb7703468 "((ber)->ber_opts.lbo_valid==0x2)", file=file@entry=0xb7703a21 "io.c", line=line@entry=186, function=function@entry=0xb7703be9 <__PRETTY_FUNCTION__.6470> "ber_free_buf") at assert.c:101 #5 0xb76fe8c5 in ber_free_buf (ber=0x82ae380) at io.c:186 #6 0xb76fe910 in ber_free (ber=0x82ae380, freebuf=freebuf@entry=1) at io.c:203 #7 0xb7715d09 in ldap_msgfree (lm=0x82ae868) at result.c:1279 #8 0xb7778bb0 in rlm_ldap_sasl_interactive (inst=0x8277490, request=0x0, conn=0x82a23b0, identity=0xb777b564 "", password=0x0, sasl=0x82774ac, error=0xbffff2fc, extra=0xbffff2f8) at src/modules/rlm_ldap/sasl.c:183 #9 0xb77736ad in rlm_ldap_bind (inst=0x8277490, request=0x0, pconn=0xbffff350, dn=0xb777b564 "", password=0x0, sasl=0x82774ac, retry=false) at src/modules/rlm_ldap/ldap.c:717
I should put some work as well. I think it's the double free (had it at some stage). The following fixes it for me, see if ok (perhaps we can revert one of last changes as well). diff --git a/src/modules/rlm_ldap/sasl.c b/src/modules/rlm_ldap/sasl.c index c20b5af..a1df2bb 100644 --- a/src/modules/rlm_ldap/sasl.c +++ b/src/modules/rlm_ldap/sasl.c @@ -128,7 +128,6 @@ ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request, NULL, NULL, LDAP_SASL_AUTOMATIC, _sasl_interact, &sasl_ctx, result, &mech, &msgid); - ldap_msgfree(result); /* We always need to free the old message */ /* * If ldap_sasl_interactive_bind indicates it didn't want @@ -147,6 +146,7 @@ ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request, * If LDAP parse result indicates there was an error * then we're done. */ + ldap_msgfree(result); /* We always need to free the old message */ status = rlm_ldap_result(inst, conn, msgid, identity, &result, error, extra); switch (status) { case LDAP_PROC_SUCCESS: /* ldap_sasl_interactive_bind should have indicated success */
On 21 Jun 2015, at 21:48, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 4:37 AM, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 4:26 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Result can be null now *sigh*.
And one more assertion:
rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed. Aborted (core dumped)
and on to the next one...
Still (I'm testing with v3.0 btw).
rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed.
Yep, you're right double free. Done. -Arran Arran Cudbard-Bell <a.cudbardb@freeradius.org> FreeRADIUS development team FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2
Morning, On Mon, Jun 22, 2015 at 5:29 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
On 21 Jun 2015, at 21:48, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 4:37 AM, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 4:26 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Result can be null now *sigh*.
And one more assertion:
rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed. Aborted (core dumped)
and on to the next one...
Still (I'm testing with v3.0 btw).
rlm_ldap (ldap): Opening additional connection (0), 1 of 1 pending slots used rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: io.c:186: ber_free_buf: Assertion `((ber)->ber_opts.lbo_valid==0x2)' failed.
Yep, you're right double free.
Done.
Works perfect now. Thanks a lot. Regards, Isaac B.
On Mon, Jun 22, 2015 at 4:01 AM, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 3:52 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
On 21 Jun 2015, at 20:04, Isaac Boukris <iboukris@gmail.com> wrote:
On Mon, Jun 22, 2015 at 2:39 AM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
Not really correct, but does give a clue to what might be going on. With your patch status wouldn't get set on the final round of SASL auth, so rlm_ldap_sasl_interactive would return the wrong ldap_rcode_t value.
Admittedly, I am not familiar enough with ldap library to be confident about my patch. It was based on gdb'ing both 'ldapsearch' and 'radiusd' and comparing the library calls as mentioned.
Sure.
rlm_ldap_result should be used to get the result via ldap_result, and check it for errors with ldap_parse_result. I can see that possibly ldap_parse_result is giving bad return codes, which is causing the loop to terminate.
Note that this is what 'ldapsearch' seem to be doing, it breaks from the loop before calling 'ldap_result()' once we aren't in 'progress', see: https://github.com/osstech-jp/openldap/blob/wiredtiger/clients/tools/common....
OK that helps.
So my guess is that ldap_result will indicate that the bind was successful before ldap_sasl_interactive_bind indicates tells us that, and that on the final loop ldap_sasl_interactive_bind doesn't actually send anything to the server, it just indicates that the previous operation was successful.
Yea, that what it looks like, I see on the wire that the server sent 'success' but ldap_sasl_interactive_bind still returns LDAP_SASL_BIND_IN_PROGRESS. Perhaps it just want to be called again in order to install the security layers (not to communicate with the server).
Ah possibly.
I tried to read some doc, it isn't clear but it could match the behaviour we see.
Slightly odd that it wouldn't set some kind of NULL/noop msgid that would indicate that, I guess that's a bug (or 'feature') of libldap.
I've fudged rlm_ldap_result to take a -1 msgid, which causes it to skip attempting to retrieve the result, and just do error processing using the handle.
I think that should fix everything.
Not yet :( I now get (limiting 'ssf' doesn't make a diff):
rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed. radiusd: error.c:255: ldap_parse_result: Assertion `r != ((void *)0)' failed. Aborted (core dumped)
Let me know if you want the back-trace.
Nah I see the problem.
Thanks for working with me on this.
No problem. Should work now (hopefully).
One more to go :)
rlm_ldap (ldap): Connecting to ldap://ms.frenche.cp:389 rlm_ldap (ldap): Starting SASL mech(s): GSSAPI SASL/GSSAPI authentication started SASL username: anna@FRENCHE.CP SASL SSF: 56 SASL data security layer installed.
Program received signal SIGSEGV, Segmentation fault. 0xb7773114 in rlm_ldap_result (inst=0x8277490, conn=0x82a23b0, msgid=-1, dn=0xb777b564 "", result=0x0, error=0xbffff2fc, extra=0xbffff2f8) at src/modules/rlm_ldap/ldap.c:480 480 *result = NULL; (gdb) bt #0 0xb7773114 in rlm_ldap_result (inst=0x8277490, conn=0x82a23b0, msgid=-1, dn=0xb777b564 "", result=0x0, error=0xbffff2fc, extra=0xbffff2f8) at src/modules/rlm_ldap/ldap.c:480 #1 0xb77789e4 in rlm_ldap_sasl_interactive (inst=0x8277490, request=0x0, conn=0x82a23b0, identity=0xb777b564 "", password=0x0, sasl=0x82774ac, error=0xbffff2fc, extra=0xbffff2f8) at src/modules/rlm_ldap/sasl.c:142 #2 0xb77736a0 in rlm_ldap_bind (inst=0x8277490, request=0x0, pconn=0xbffff350, dn=0xb777b564 "", password=0x0, sasl=0x82774ac, retry=false) at src/modules/rlm_ldap/ldap.c:717
Perhaps I could add dbg prints.
BTW the ldapsearch example seem to verify the returned value from rlm_ldap_sasl_interactive to be eq to LDAP_SUCCESS in order to conclude success.
participants (6)
-
Alan DeKok -
Arran Cudbard-Bell -
Brendan Kearney -
brendan kearney -
Isaac Boukris -
William