]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/dn.c
fix previous commit
[openldap] / servers / slapd / dn.c
index a74aa428326eab569c3bda3f14e67f33e905b075..5da22ac6a44a6f834e4c42eb5bbc03e8d93a3415 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2004 The OpenLDAP Foundation.
+ * Copyright 1998-2005 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,6 @@
 #include <ac/time.h>
 
 #include "slap.h"
-#include "ldap_pvt.h" /* must be after slap.h, to get ldap_bv2dn_x() & co */
 #include "lutil.h"
 
 /*
@@ -958,7 +957,109 @@ dnMatch(
                match, value->bv_val, asserted->bv_val );
 
        *matchp = match;
-       return( LDAP_SUCCESS );
+       return LDAP_SUCCESS;
+}
+
+/*
+ * dnRelativeMatch routine
+ */
+int
+dnRelativeMatch(
+       int *matchp,
+       slap_mask_t flags,
+       Syntax *syntax,
+       MatchingRule *mr,
+       struct berval *value,
+       void *assertedValue )
+{
+       int match;
+       struct berval *asserted = (struct berval *) assertedValue;
+
+       assert( matchp );
+       assert( value );
+       assert( assertedValue );
+       assert( !BER_BVISNULL( value ) );
+       assert( !BER_BVISNULL( asserted ) );
+
+       if( mr == slap_schema.si_mr_dnSubtreeMatch ) {
+               if( asserted->bv_len > value->bv_len ) {
+                       match = -1;
+               } else if ( asserted->bv_len == value->bv_len ) {
+                       match = memcmp( value->bv_val, asserted->bv_val, 
+                               value->bv_len );
+               } else {
+                       if( DN_SEPARATOR(
+                               value->bv_val[value->bv_len - asserted->bv_len - 1] ))
+                       {
+                               match = memcmp(
+                                       &value->bv_val[value->bv_len - asserted->bv_len],
+                                       asserted->bv_val, 
+                                       asserted->bv_len );
+                       } else {
+                               return 1;
+                       }
+               }
+
+               *matchp = match;
+               return LDAP_SUCCESS;
+       }
+
+       if( mr == slap_schema.si_mr_dnSuperiorMatch ) {
+               asserted = value;
+               value = (struct berval *) assertedValue;
+               mr = slap_schema.si_mr_dnSubordinateMatch;
+       }
+
+       if( mr == slap_schema.si_mr_dnSubordinateMatch ) {
+               if( asserted->bv_len >= value->bv_len ) {
+                       match = -1;
+               } else {
+                       if( DN_SEPARATOR(
+                               value->bv_val[value->bv_len - asserted->bv_len - 1] ))
+                       {
+                               match = memcmp(
+                                       &value->bv_val[value->bv_len - asserted->bv_len],
+                                       asserted->bv_val, 
+                                       asserted->bv_len );
+                       } else {
+                               return 1;
+                       }
+               }
+
+               *matchp = match;
+               return LDAP_SUCCESS;
+       }
+
+       if( mr == slap_schema.si_mr_dnOneLevelMatch ) {
+               if( asserted->bv_len >= value->bv_len ) {
+                       match = -1;
+               } else {
+                       if( DN_SEPARATOR(
+                               value->bv_val[value->bv_len - asserted->bv_len - 1] ))
+                       {
+                               match = memcmp(
+                                       &value->bv_val[value->bv_len - asserted->bv_len],
+                                       asserted->bv_val, 
+                                       asserted->bv_len );
+
+                               if( !match ) {
+                                       struct berval rdn;
+                                       rdn.bv_val = value->bv_val;
+                                       rdn.bv_len = value->bv_len - asserted->bv_len - 1;
+                                       match = dnIsOneLevelRDN( &rdn ) ? 0 : 1;
+                               }
+                       } else {
+                               return 1;
+                       }
+               }
+
+               *matchp = match;
+               return LDAP_SUCCESS;
+       }
+
+       /* should not be reachable */
+       assert( 0 );
+       return LDAP_OTHER;
 }
 
 int
@@ -988,8 +1089,7 @@ rdnMatch(
                match, value->bv_val, asserted->bv_val );
 
        *matchp = match;
-
-       return( LDAP_SUCCESS );
+       return LDAP_SUCCESS;
 }
 
 
@@ -997,6 +1097,10 @@ rdnMatch(
  * dnParent - dn's parent, in-place
  * note: the incoming dn is assumed to be normalized/prettyfied,
  * so that escaped rdn/ava separators are in '\'+hexpair form
+ *
+ * note: "dn" and "pdn" can point to the same berval;
+ * beware that, in this case, the pointer to the original buffer
+ * will get lost.
  */
 void
 dnParent( 
@@ -1018,8 +1122,35 @@ dnParent(
        p++;
 
        assert( ATTR_LEADCHAR( p[ 0 ] ) );
-       pdn->bv_val = p;
        pdn->bv_len = dn->bv_len - (p - dn->bv_val);
+       pdn->bv_val = p;
+
+       return;
+}
+
+/*
+ * dnRdn - dn's rdn, in-place
+ * note: the incoming dn is assumed to be normalized/prettyfied,
+ * so that escaped rdn/ava separators are in '\'+hexpair form
+ */
+void
+dnRdn( 
+       struct berval   *dn, 
+       struct berval   *rdn )
+{
+       char    *p;
+
+       *rdn = *dn;
+       p = strchr( dn->bv_val, ',' );
+
+       /* one-level dn */
+       if ( p == NULL ) {
+               return;
+       }
+
+       assert( DN_SEPARATOR( p[ 0 ] ) );
+       assert( ATTR_LEADCHAR( p[ 1 ] ) );
+       rdn->bv_len = p - dn->bv_val;
 
        return;
 }
@@ -1046,14 +1177,11 @@ dnExtractRdn(
                return rc;
        }
 
-       rc = ldap_rdn2bv_x( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
+       rc = ldap_rdn2bv_x( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY,
+               ctx );
 
        ldap_rdnfree_x( tmpRDN, ctx );
-       if ( rc != LDAP_SUCCESS ) {
-               return rc;
-       }
-
-       return LDAP_SUCCESS;
+       return rc;
 }
 
 /*
@@ -1174,7 +1302,7 @@ build_new_dn( struct berval * new_dn,
        new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1;
        new_dn->bv_val = (char *) slap_sl_malloc( new_dn->bv_len + 1, memctx );
 
-       ptr = lutil_strcopy( new_dn->bv_val, newrdn->bv_val );
+       ptr = lutil_strncopy( new_dn->bv_val, newrdn->bv_val, newrdn->bv_len );
        *ptr++ = ',';
        strcpy( ptr, parent_dn->bv_val );
 }
@@ -1231,6 +1359,22 @@ dnIsOneLevelRDN( struct berval *rdn )
        return 1;
 }
 
+#ifdef HAVE_TLS
+static SLAP_CERT_MAP_FN *DNX509PeerNormalizeCertMap = NULL;
+#endif
+
+int register_certificate_map_function(SLAP_CERT_MAP_FN *fn)
+{
+#ifdef HAVE_TLS
+       if ( DNX509PeerNormalizeCertMap == NULL ) {
+               DNX509PeerNormalizeCertMap = fn;
+               return 0;
+       }
+#endif
+
+       return -1;
+}
+
 #ifdef HAVE_TLS
 /*
  * Convert an X.509 DN into a normalized LDAP DN
@@ -1253,8 +1397,16 @@ dnX509normalize( void *x509_name, struct berval *out )
 int
 dnX509peerNormalize( void *ssl, struct berval *dn )
 {
+       int rc = LDAP_INVALID_CREDENTIALS;
 
-       return ldap_pvt_tls_get_peer_dn( ssl, dn,
-               (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 );
+       if ( DNX509PeerNormalizeCertMap != NULL )
+               rc = (*DNX509PeerNormalizeCertMap)( ssl, dn );
+
+       if ( rc != LDAP_SUCCESS ) {
+               rc = ldap_pvt_tls_get_peer_dn( ssl, dn,
+                       (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 );
+       }
+
+       return rc;
 }
 #endif