Hello all together, all about I talk in this mail isn't really an OpenLDAP problem because OpenLDAP makes use of SASL implementations to support GSSAPI stuff for authentiation, signing and encryption. It does not provide its own GSSAPI implementation. Cyrus SASL GSSAPI is mostly used to provide that GSSAPI (or GSS-SPNEGO) feature. OpenLDAP client library stuff is often used to communicate to LDAP servers of different vendors. And one really often used LDAP server is Active Directory from Microsoft to manage computing environments and user (or computer) identities. If Services For Unix (SFU) or at least Win2k3R2 is used on Domain Controllers UNIX UIDs/GIDs are manageable by AD too. But now comes the problem for UNIX/Linux clients. Normally you get only connected to an AD as non-Windows client when using SSL/TLS over LDAPS or turn of LDAP server signing requirements. This will be done via group policy object -> GPO: Domain controller (GPO in OU=Domain Controllers,DC=...) -> Computer configuration -> Windows Settings -> Security Settings -> Domain controller: LDAP server signing requirements where value is set to "None". But then (unless the client requests data signing and the server supports it) LDAP communication is plain and the client could not be sure that it comes from the server. For UIDs/GIDs this is a great problem and the use of LDAP is then not better than the use of NIS. Thats why most AD infrastructures setting the value of that GPO to "Require signature". That isn't a problem for Windows clients because they use Kerberos session key for signing. But for OpenLDAP clients this is a problem. They could not talk to that AD-DC anymore. Only authentication works but LDAP communication signing not. So here (at the end of this mail) is a code snip set for Cyrus SASL GSSAPI plugin that solve this problem. description ----------- A client which talks to an AD-DC (tested with Win2k3R2, Win2k8 or Win2k8R2 as AD-DC and GPO "Domain controller: LDAP server signing requirements" is set to "Require signature") gets the following requirements for SSF --->>> line 1620 cyrus-sasl-2.1.24/plugins/gssapi.c) (allowed == 214748647 && need == 0 && (serverhas == 7) This means for AD: the LDAP-GPO is on, so we should say we do signing (but in real we do encryption) and say both. Another point in case of GSSAPI is the SSF isn't really relevant. GSSAPI code negotiate the encryption and signing algorithm depending on Kerberos session keys of involved server and client. So our solution should be an additional case where we choose oparams->encode = &gssapi_privacy_encode; and answer to the server we can do what he can do mychoice = (severhas & 7); Now GSSAPI(/Kerberos) based communication to AD-DC works. Thats it. Hope this little patch gets into Cyrus SASL code. annotation ---------- Nevertheless we should provide the correct SSF based on established GSS context not K5_MAX_SSF. A function like static sasl_ssf_t sasl_gss_get_current_ssf_from_ctx( context_t *context) { /* FIX ME: * Need to extract the proper value from context. */ return(K5_MAX_SSF); } should do that. Best regards and Merry Christmas Mike Becher
--- cyrus-sasl-2.1.24/plugins/gssapi.c.orig 2009-08-13 14:36:46.000000000 +0200 +++ cyrus-sasl-2.1.24/plugins/gssapi.c 2009-12-21 21:23:48.631598700 +0100 @@ -1616,8 +1616,18 @@ /* bit mask of server support */ serverhas = ((char *)output_token->value)[0]; + if (allowed >= K5_MAX_SSF && need == 0 && (serverhas & 6)) { + /* May be server wants as answer signing and encryption. + * This is a special case for MS AD-DCs where client should + * answer it can do what server can do but chooses encryption. + */ + oparams->encode = &gssapi_privacy_encode; + oparams->decode = &gssapi_decode; + /* FIX ME: Need to extract the proper value here */ + oparams->mech_ssf = K5_MAX_SSF; + mychoice = (serverhas & 7); /* if client didn't set use strongest layer available */ - if (allowed >= K5_MAX_SSF && need <= K5_MAX_SSF && (serverhas & 4)) { + } else if (allowed >= K5_MAX_SSF && need <= K5_MAX_SSF && (serverhas & 4)) { /* encryption */ oparams->encode = &gssapi_privacy_encode; oparams->decode = &gssapi_decode;