[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: Certificate authentication and back-ldap proxy



Thank you very much.

We have followed your instructions and we have fixed the back-ldap proxy
slapd.conf file:

#
# Security SSL
#
TLSCipherSuite HIGH:MEDIUM:+SSLv3
TLSCACertificatePath /etc/ssl/cacerts/
TLSCertificateFile /etc/ssl/certs/proxy-server1.example.com.pem
TLSCertificateKeyFile /etc/ssl/private/proxy-server1.example.com.key
TLSVerifyClient demand

# Log level
loglevel 256

#######################################################################
# Database definitions
#######################################################################
database        ldap

rebind-as-user  true

suffix          "dc=example,dc=com"

uri             "ldaps://server1.example.com"

idassert-bind   bindmethod=simple
                binddn="cn=proxy_id,dc=example,dc=com"
                credentials="secret"
                mode=self

-------------------------
-------------------------

In the master server we have included the authz-policy and authz-regexp
sentences:

access to dn.base=""                                    
        by * read                                       

access to dn.base="cn=Subschema"
        by * read              

access to attrs=userPassword,userPKCS12
        by self write                 
        by dn.exact="cn=admin_w_cert,ou=admins,dc=example,dc=com" read
        by * auth                                                    

access to attrs=shadowLastChange
        by self write          
        by * read              

access to *
        by * read

#
# Security SSL
#
TLSCipherSuite HIGH:MEDIUM:+SSLv3
TLSCertificateFile /etc/ssl/certs/server1.example.com.pem
TLSCertificateKeyFile /etc/ssl/private/server1.example.com.key
TLSCACertificatePath /etc/ssl/cacerts/
TLSVerifyClient demand

#
#Log level
#
loglevel -1

# Require authentication
require authc

#
# Authz
#
authz-policy to
authz-regexp "CN=([^,]*),O=Internet Widgits Pty Ltd,ST=Some-State,C=AU"
CN=$1,ou=admins,dc=example,dc=com

#######################################################################
# HDB database definitions
#######################################################################

database        hdb
suffix          "dc=example,dc=com"
checkpoint      1024    5
cachesize       10000
rootdn          "cn=Manager,dc=example,dc=com"

rootpw          secret

# Indices to maintain
index   objectClass     eq

#
# Overlay ppolicy
#
overlay ppolicy

-------------------------
-------------------------

Also we have included some entries in the tree:

dn: ou=admins,dc=example,dc=com        
objectclass: top                       
objectclass: organizationalUnit        
ou: admins                             

dn: cn=admin_w_cert,ou=admins,dc=example,dc=com
cn: Admin with Cert Mapping                   
cn: admin_w_cert                              
objectclass: top
objectclass: person
sn: Admin with Cert Mapping

dn: cn=proxy_id,dc=example,dc=com
cn: Proxy ID
cn: proxy_id
objectclass: top
objectclass: person
sn: Proxy ID
userpassword: {SSHA}vPXnQ9g0JzITK3+SczbcDq/fwaDRAewf
authzTo: ldap:///ou=admins,dc=example,dc=com??sub?(objectClass=person)

-------------------------
-------------------------

Now the search works:

ldapsearch -LLL -b 'uid=user_w_pass,ou=people,dc=example,dc=com' -H
ldaps://proxy-server1.example.com:1636 userPassword

SASL/EXTERNAL authentication started
SASL username: CN=admin_w_cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=AU
SASL SSF: 0
dn: uid=user_w_pass,ou=people,dc=example,dc=com
userPassword:: e2NyeXB0fTcyMXpQbU4waWdKaU0=


Thanks again.

>> Hi,
>>
>>    We have some problems with certificate authentication when the master
>> server is behind a back-ldap proxy.
>>
>>    We have openldap 2.4.21 on Suse Linux Enterprise Server  10 SP3 and
>> these are the details of our scenario:
>>
>>    The master server: server1.example.com has the following slapd.conf
>> file:
>>
>> access to dn.base=""
>>         by * read
>>
>> access to dn.base="cn=Subschema"
>>         by * read
>>
>> access to attrs=userPassword,userPKCS12
>>         by self write
>>         by dn.exact="CN=admin_w_cert,O=Internet Widgits Pty
>> Ltd,ST=Some-State,C=AU" read
>>         by *
>> auth
>>
>> access to attrs=shadowLastChange
>>         by self write
>>         by * read
>>
>> access to *
>>         by * read
>>
>> #
>> # Security SSL
>> #
>> TLSCipherSuite HIGH:MEDIUM:+SSLv3
>> TLSCertificateFile /etc/ssl/certs/server1.example.com.pem
>> TLSCertificateKeyFile /etc/ssl/private/server1.example.com.key
>> TLSCACertificatePath /etc/ssl/cacerts/
>> TLSVerifyClient demand
>>
>> #
>> #Log level
>> #
>> loglevel 256
>>
>> # Require authentication
>> require authc
>>
>> #######################################################################
>> # HDB database definitions
>> #######################################################################
>>
>> database        hdb
>> suffix          "dc=example,dc=com"
>> checkpoint      1024    5
>> cachesize       10000
>> rootdn          "cn=Manager,dc=example,dc=com"
>>
>> rootpw          secret
>>
>> # Indices to maintain
>> index   objectClass     eq
>>
>> # Overlay ppolicy
>> overlay ppolicy
>>
>> ----------------------
>>
>>    Authentication is required, and we give access to the user passwords
>> for the dn of a certificate.
>>
>>    When we search for passwords using the certificate we get the
>> following:
>>
>> root# ldapsearch -LLL -b 'uid=user_w_pass,ou=people,dc=example,dc=com'
>> -H ldaps://server1.example.com userPassword
>>
>> SASL/EXTERNAL authentication started
>> SASL username: CN=admin_w_cert,O=Internet Widgits Pty
>> Ltd,ST=Some-State,C=AU
>> SASL SSF: 0
>> dn: uid=user_w_pass,ou=people,dc=example,dc=com
>> userPassword:: e2NyeXB0fTcyMXpQbU4waWdKaU0=
>>
>> -----------------------
>>
>>   The root user (ldap client) has a ~/.ldaprc file with:
>> TLS_CACERTDIR /etc/ssl/cacerts/
>> TLS_CERT /etc/ssl/certs/admin_w_cert.pem
>> TLS_KEY /etc/ssl/private/admin_w_cert.key
>> TLS_REQCERT demand
>> SASL_MECH EXTERNAL
>>
>>    In /var/log/messages we get:
>> ldap-master[22358]: conn=1000 fd=11 ACCEPT from
>> IP=server1.example.com:40899 (IP=server1.example.com:636)
>> ldap-master[22358]: conn=1000 fd=11 TLS established tls_ssf=256 ssf=256
>> ldap-master[22358]: conn=1000 op=0 BIND dn="" method=163
>> ldap-master[22358]: conn=1000 op=0 BIND
>> authcid="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> authzid="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> ldap-master[22358]: conn=1000 op=0 BIND dn="cn=admin_w_cert,o=internet
>> widgits pty ltd,st=some-state,c=au" mech=EXTERNAL sasl_ssf=0 ssf=256
>> ldap-master[22358]: conn=1000 op=0 RESULT tag=97 err=0 text=
>> ldap-master[22358]: conn=1000 op=1 SRCH
>> base="uid=user_w_pass,ou=people,dc=example,dc=com" scope=2 deref=0
>> filter="(objectClass=*)"
>> ldap-master[22358]: conn=1000 op=1 SRCH attr=userPassword
>> ldap-master[22358]: conn=1000 op=1 SEARCH RESULT tag=101 err=0
>> nentries=1 text=
>> ldap-master[22358]: conn=1000 op=2 UNBIND
>> ldap-master[22358]: conn=1000 fd=11 closed
>>
>>    This is the correct behavior for us. The problem appears when we
>> introduce a back-ldap proxy between the client and the master.
>>    The proxy server (proxy-server1.example.com) is listening in port
>> 1636 and its slapd.conf file is:
>>
>> #
>> # Security SSL
>> #
>> TLSCipherSuite HIGH:MEDIUM:+SSLv3
>> TLSCACertificatePath /etc/ssl/cacerts/
>> TLSCertificateFile /etc/ssl/certs/proxy-server1.example.com.pem
>> TLSCertificateKeyFile /etc/ssl/private/proxy-server1.example.com.key
>> TLSVerifyClient demand
>>
>> # Log level
>> loglevel 256
>>
>> #######################################################################
>> # Database definitions
>> #######################################################################
>> database        ldap
>>
>> rebind-as-user  true
>>
>> suffix          "dc=example,dc=com"
>>
>> uri             "ldaps://server1.example.com"
>> tls             ldaps
>>                 tls_cert=/etc/ssl/certs/proxy-server1.example.com.pem
>>                 tls_key=/etc/ssl/private/proxy-server1.example.com.key
>>                 tls_cacertdir=/etc/ssl/cacerts/
>>
>> ----------------------
>>
>>    If we search for passwords through the proxy we get:
>> root # ldapsearch -LLL -b 'uid=user_w_pass,ou=people,dc=example,dc=com'
>> -H ldaps://proxy-server1.example.com:1636 userPassword
>>
>> SASL/EXTERNAL authentication started
>> SASL username: CN=admin_w_cert,O=Internet Widgits Pty
>> Ltd,ST=Some-State,C=AU
>> SASL SSF: 0
>> Server is unwilling to perform (53)
>> Additional information: authentication required
>>
>>     In the /var/log/messages the following messages appear:
>> ldap-proxy[22802]: conn=1001 fd=8 ACCEPT from
>> IP=proxy-server1.example.com:60712 (IP=proxy-server1.example.com:1636)
>> ldap-proxy[22802]: conn=1001 fd=8 TLS established tls_ssf=256 ssf=256
>> ldap-proxy[22802]: conn=1001 op=0 BIND dn="" method=163
>> ldap-proxy[22802]: conn=1001 op=0 BIND
>> authcid="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> authzid="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> ldap-proxy[22802]: conn=1001 op=0 BIND dn="cn=admin_w_cert,o=internet
>> widgits pty ltd,st=some-state,c=au" mech=EXTERNAL sasl_ssf=0 ssf=256
>> ldap-proxy[22802]: conn=1001 op=0 RESULT tag=97 err=0 text=
>> ldap-proxy[22802]: conn=1001 op=1 SRCH
>> base="uid=user_w_pass,ou=people,dc=example,dc=com" scope=2 deref=0
>> filter="(objectClass=*)"
>> ldap-proxy[22802]: conn=1001 op=1 SRCH attr=userPassword
>>
>> ldap-master[22358]: conn=1008 op=2 SRCH
>> base="uid=user_w_pass,ou=people,dc=example,dc=com" scope=2 deref=0
>> filter="(objectClass=*)"
>> ldap-master[22358]: conn=1008 op=2 SRCH attr=userPassword
>> ldap-master[22358]: conn=1008 op=2 SEARCH RESULT tag=101 err=53
>> nentries=0 text=authentication required
>>
>> ldap-proxy[22802]: conn=1001 op=1 SEARCH RESULT tag=101 err=53
>> nentries=0 text=authentication required
>> ldap-proxy[22802]: conn=1001 op=2 UNBIND
>> ldap-proxy[22802]: conn=1001 fd=8 closed
>>
>>    The /root/.ldaprc file is the same than the previous one.
>>
>>    When we increase the logging level we discover this:
>> ....
>> ldap-proxy[23008]: conn=1000 op=0 do_bind
>> ldap-proxy[23008]: >>> dnPrettyNormal: <>
>> ldap-proxy[23008]: <<< dnPrettyNormal: <>, <>
>> ldap-proxy[23008]: conn=1000 op=0 BIND dn="" method=163
>> ldap-proxy[23008]: do_bind: dn () SASL mech EXTERNAL
>> ldap-proxy[23008]: ==> sasl_bind: dn="" mech=EXTERNAL datalen=0
>> ldap-proxy[23008]: SASL Canonicalize [conn=1000]:
>> authcid="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> ldap-proxy[23008]: slap_sasl_getdn: conn 1000
>> id=cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au [len=61]
>> ldap-proxy[23008]: ==>slap_sasl2dn: converting SASL name
>> cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au to a DN
>> ldap-proxy[23008]: <==slap_sasl2dn: Converted SASL name to <nothing>
>> ldap-proxy[23008]: SASL Canonicalize [conn=1000]:
>> slapAuthcDN="cn=admin_w_cert,o=internet widgits pty
>> ltd,st=some-state,c=au"
>> ldap-proxy[23008]: SASL proxy authorize [conn=1000]:
>> authcid="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> authzid="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> ldap-proxy[23008]: conn=1000 op=0 BIND
>> authcid="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> authzid="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> ldap-proxy[23008]: SASL Authorize [conn=1000]:  proxy authorization
>> allowed authzDN=""
>> ldap-proxy[23008]: send_ldap_sasl: err=0 len=-1
>> ldap-proxy[23008]: conn=1000 op=0 BIND dn="cn=admin_w_cert,o=internet
>> widgits pty ltd,st=some-state,c=au" mech=EXTERNAL sasl_ssf=0 ssf=256
>> ldap-proxy[23008]: do_bind: SASL/EXTERNAL bind:
>> dn="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> sasl_ssf=0
>> ldap-proxy[23008]: send_ldap_response: msgid=1 tag=97 err=0
>> ldap-proxy[23008]: conn=1000 op=0 RESULT tag=97 err=0 text=
>> ldap-proxy[23008]: <== slap_sasl_bind: rc=0
>> ....
>> ldap-proxy[23008]: conn=1000 op=1 SRCH
>> base="uid=user_w_pass,ou=people,dc=example,dc=com" scope=2 deref=0
>> filter="(objectClass=*)"
>> ldap-proxy[23008]: conn=1000 op=1 SRCH attr=userPassword
>> ldap-proxy[23008]: ==> limits_get: conn=1000 op=1
>> self="cn=admin_w_cert,o=internet widgits pty ltd,st=some-state,c=au"
>> this="uid=user_w_pass,ou=people,dc=example,dc=com"
>> ldap-master[22983]: daemon: activity on 1 descriptor
>> ldap-master[22983]: daemon: activity on:
>> ldap-master[22983]:
>> ldap-master[22983]: slap_listener_activate(7):
>> ldap-master[22983]: daemon: epoll: listen=7 busy
>> ldap-master[22983]: >>> slap_listener(ldaps://server1.example.com)
>> .....
>> ldap-master[22983]: conn=1000 op=0 do_bind
>> ldap-master[22983]: >>> dnPrettyNormal: <>
>> ldap-master[22983]: <<< dnPrettyNormal: <>, <>
>> ldap-master[22983]: conn=1000 op=0 BIND dn="" method=128
>> ldap-master[22983]: do_bind: version=3 dn="" method=128
>> ldap-master[22983]: send_ldap_result: conn=1000 op=0 p=3
>> ldap-master[22983]: send_ldap_result: err=0 matched="" text=""
>> ldap-master[22983]: send_ldap_response: msgid=1 tag=97 err=0
>> ldap-master[22983]: conn=1000 op=0 RESULT tag=97 err=0 text=
>> ldap-master[22983]: do_bind: v3 anonymous bind
>>
>> ----------------
>>
>> Therefore the proxy is binding anonymously in the master, instead of
>> using the dn of the certificate.
>>
>> Is there any  problem with the SASL EXTERNAL method?
>>
>> If we use SIMPLE authentication through the proxy, there is no problem:
>> root # ldapsearch -LLL -x -b
>> 'uid=user_w_pass,ou=people,dc=example,dc=com' -H
>> ldaps://proxy-server1.example.com:1636 -D
>> 'uid=user_w_pass,ou=people,dc=example,dc=com' -W  userPassword
>> Enter LDAP Password:
>>
>> dn: uid=user_w_pass,ou=people,dc=example,dc=com
>> userPassword:: e2NyeXB0fTcyMXpQbU4waWdKaU0=
>>     
>
> The problem is that you probably do not realize that the proxy cannot do a
> cert-based authentication on behalf of the client because it doesn't have
> the client's private key (which is correct).  You need the proxy perform
> an identity assertion: bind to the remote server with its own identity,
> and then assert the client's identity using proxy authorization.
>
> To do this, you need to:
>
> a) define some means for the proxy to bind to the remote server, e.g.
> using cert-based SASL EXTERNAL, or simple bind under TLS, or whatever;
>
> b) configure the remote server so that the proxy's identity defined in (a)
> is allowed to proxy authz as whatever client's identity you want to
> accept; this requires to use the directive "authz-policy"; you may need to
> use the "authz-regexp" if you intend to map the client's identity; and
> you'll need to populate the "authzTo" operational attribute of the entry
> corresponding to the proxy's identity.
>
> c) add to the proxy configuration the directive
>
> idassert-bind bindmethod=<what you chose for (a)>
>     <bind parameters for (a)>
>     mode=self
>
> This way, the proxy will:
>
> - authc the client locally
>
> - authc as itself with respect to the remote host
>
> - proxy operations adding the proxyAuthz control with the identity of the
> client
>
> See slapd-ldap(5) for details on the syntax of the idassert-* directives.
>
> p.
>
>   
---------------------------------------------------------------------------------------------
ADVERTENCIA: Sobre la privacidad y cumplimiento de la Ley de Protección de Datos, acceda a http://www.iac.es/disclaimer.php
WARNING: For more information on privacy and fulfilment of the Law concerning the Protection of Data, consult http://www.iac.es/disclaimer.php?lang=en