+ new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1;
+ new_dn->bv_val = (char *) sl_malloc( new_dn->bv_len + 1, memctx );
+
+ ptr = lutil_strcopy( new_dn->bv_val, newrdn->bv_val );
+ *ptr++ = ',';
+ strcpy( ptr, parent_dn->bv_val );
+}
+
+
+/*
+ * dnIsSuffix - tells whether suffix is a suffix of dn.
+ * Both dn and suffix must be normalized.
+ */
+int
+dnIsSuffix(
+ const struct berval *dn,
+ const struct berval *suffix )
+{
+ int d = dn->bv_len - suffix->bv_len;
+
+ assert( dn );
+ assert( suffix );
+
+ /* empty suffix matches any dn */
+ if ( suffix->bv_len == 0 ) {
+ return 1;
+ }
+
+ /* suffix longer than dn */
+ if ( d < 0 ) {
+ return 0;
+ }
+
+ /* no rdn separator or escaped rdn separator */
+ if ( d > 1 && !DN_SEPARATOR( dn->bv_val[ d - 1 ] ) ) {
+ return 0;
+ }
+
+ /* no possible match or malformed dn */
+ if ( d == 1 ) {
+ return 0;
+ }
+
+ /* compare */
+ return( strcmp( dn->bv_val + d, suffix->bv_val ) == 0 );
+}
+
+#ifdef HAVE_TLS
+/*
+ * Convert an X.509 DN into a normalized LDAP DN
+ */
+int
+dnX509normalize( void *x509_name, struct berval *out )
+{
+ /* Invoke the LDAP library's converter with our schema-rewriter */
+ int rc = ldap_X509dn2bv( x509_name, out, LDAPDN_rewrite, 0 );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "dnX509Normalize: <%s>\n", out->bv_val, 0, 0 );