I was thinking more about what would be required to provide the necessary hook in the main code. Here is a sketch of following the idea through.

I have maintained all the existing entry points and their current semantics in case any modules out there call them. I would be the first to admit this looks ugly. It also occurred to me that it doesn't make much sense. If it were possible to add a hook to the core slapd code, it would be simpler to just add another callback to validate the client cert.

But yeah, allowing modules to call back into the core without the discipline of a formal API _really_ ossifies the core quickly!

  Sean.

==========================================================================================
--- proto-slap.h.orig
+++ proto-slap.h
@@ -994,6 +994,7 @@
 LDAP_SLAPD_F (int) dnX509normalize LDAP_P(( void *x509_name, struct berval *out ));
 
 LDAP_SLAPD_F (int) dnX509peerNormalize LDAP_P(( void *ssl, struct berval *dn ));
+LDAP_SLAPD_F (int) dnX509peerNormalize3 LDAP_P(( void *ssl, struct berval *dn, int *aliencert ));
 
 LDAP_SLAPD_F (int) dnPrettyNormalDN LDAP_P(( Syntax *syntax, struct berval *val, LDAPDN *dn, int flags, void *ctx ));
 #define dnPrettyDN(syntax, val, dn, ctx) \
@@ -1003,6 +1004,9 @@
 
 typedef int (SLAP_CERT_MAP_FN) LDAP_P(( void *ssl, struct berval *dn ));
 LDAP_SLAPD_F (int) register_certificate_map_function LDAP_P(( SLAP_CERT_MAP_FN *fn ));
+
+typedef int (SLAP_CERT_MAP_FN3) LDAP_P(( void *ssl, struct berval *dn, int *alientcert ));
+LDAP_SLAPD_F (int) register_certificate_map_function3 LDAP_P(( SLAP_CERT_MAP_FN3 *fn ));
 
 /*
  * entry.c
==========================================================================================
--- connection.c.orig
+++ connection.c
@@ -1369,7 +1369,17 @@
                                c->c_ssf = c->c_tls_ssf;
                        }
 
-                       rc = dnX509peerNormalize( ssl, &authid );
+                       int aliencert = 0;
+                       rc = dnX509peerNormalize3( ssl, &authid, &aliencert );
+                       if ( alientcert ) {
+                                Debug( LDAP_DEBUG_TRACE, "connection_read(%d): "         
+                                        "TLS client certificate looks alien, error=%d id=%lu\n",
+                                        s, rc, c->c_connid );
+                               connection_closing( c, "TLS alien client certificate rejected" );     
+                               connection_close( c );
+                               connection_return( c );
+                               return 0;                                
+                       }                                                            
                        if ( rc != LDAP_SUCCESS ) {
                                Debug( LDAP_DEBUG_TRACE, "connection_read(%d): "
                                        "unable to get TLS client DN, error=%d id=%lu\n",

==========================================================================================
--- dn.c.orig
+++ dn.c
@@ -1295,6 +1295,11 @@
        return -1;
 }
 
+int register_certificate_map_function3(SLAP_CERT_MAP_FN3 *fn)
+{
+       return register_certificate_map_function((SLAP_CERT_MAP_FN *)fn);
+}
+
 /*
  * Convert an X.509 DN into a normalized LDAP DN
  */
@@ -1318,16 +1323,32 @@
 int
 dnX509peerNormalize( void *ssl, struct berval *dn )
 {
-       int rc = LDAP_INVALID_CREDENTIALS;
+       int alientcert = 0;
 
-       if ( DNX509PeerNormalizeCertMap != NULL )
-               rc = (*DNX509PeerNormalizeCertMap)( ssl, dn );
+       int rc = dnX509peerNormalize3( ssl, dn, &alientcert )
 
-       if ( rc != LDAP_SUCCESS ) {
-               rc = ldap_pvt_tls_get_peer_dn( ssl, dn,
-                       (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 );
-       }
+       /* mimic behaviour of original 2-parameter fn */
+       if ( aliencert && rc != LDAP_SUCCESS ) {
+                rc = ldap_pvt_tls_get_peer_dn( ssl, dn,
+                        (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 );
+        }
 
-       return rc;
+        return rc;
+}
+
+int
+dnX509peerNormalize3( void *ssl, struct berval *dn, int *alientcert )
+{
+        int rc = LDAP_INVALID_CREDENTIALS;
+
+        if ( DNX509PeerNormalizeCertMap != NULL )
+                rc = (*DNX509PeerNormalizeCertMap)( ssl, dn, alientcert );
+
+        if ( !alientcert && rc != LDAP_SUCCESS ) {
+                rc = ldap_pvt_tls_get_peer_dn( ssl, dn,
+                        (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 );
+        }
+
+        return rc;
 }
 #endif
==========================================================================================



Virus-free.www.avg.com