Back to index

openldap  2.4.31
dn.c
Go to the documentation of this file.
00001 /* dn.c - routines for dealing with distinguished names */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
00017  * All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms are permitted
00020  * provided that this notice is preserved and that due credit is given
00021  * to the University of Michigan at Ann Arbor. The name of the University
00022  * may not be used to endorse or promote products derived from this
00023  * software without specific prior written permission. This software
00024  * is provided ``as is'' without express or implied warranty.
00025  */
00026 
00027 #include "portable.h"
00028 
00029 #include <stdio.h>
00030 
00031 #include <ac/ctype.h>
00032 #include <ac/socket.h>
00033 #include <ac/string.h>
00034 #include <ac/time.h>
00035 
00036 #include "slap.h"
00037 #include "lutil.h"
00038 
00039 /*
00040  * The DN syntax-related functions take advantage of the dn representation
00041  * handling functions ldap_str2dn/ldap_dn2str.  The latter are not schema-
00042  * aware, so the attributes and their values need be validated (and possibly
00043  * normalized).  In the current implementation the required validation/nor-
00044  * malization/"pretty"ing are done on newly created DN structural represen-
00045  * tations; however the idea is to move towards DN handling in structural
00046  * representation instead of the current string representation.  To this
00047  * purpose, we need to do only the required operations and keep track of
00048  * what has been done to minimize their impact on performances.
00049  *
00050  * Developers are strongly encouraged to use this feature, to speed-up
00051  * its stabilization.
00052  */
00053 
00054 #define       AVA_PRIVATE( ava ) ( ( AttributeDescription * )(ava)->la_private )
00055 
00056 int slap_DN_strict = SLAP_AD_NOINSERT;
00057 
00058 static int
00059 LDAPRDN_validate( LDAPRDN rdn )
00060 {
00061        int           iAVA;
00062        int           rc;
00063 
00064        assert( rdn != NULL );
00065 
00066        for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
00067               LDAPAVA                     *ava = rdn[ iAVA ];
00068               AttributeDescription *ad;
00069               slap_syntax_validate_func *validate = NULL;
00070 
00071               assert( ava != NULL );
00072               
00073               if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
00074                      const char    *text = NULL;
00075 
00076                      rc = slap_bv2ad( &ava->la_attr, &ad, &text );
00077                      if ( rc != LDAP_SUCCESS ) {
00078                             rc = slap_bv2undef_ad( &ava->la_attr,
00079                                    &ad, &text,
00080                                    SLAP_AD_PROXIED|slap_DN_strict );
00081                             if ( rc != LDAP_SUCCESS ) {
00082                                    return LDAP_INVALID_SYNTAX;
00083                             }
00084                      }
00085 
00086                      ava->la_private = ( void * )ad;
00087               }
00088 
00089               /*
00090                * Do not allow X-ORDERED 'VALUES' naming attributes
00091                */
00092               if ( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) {
00093                      return LDAP_INVALID_SYNTAX;
00094               }
00095 
00096               /* 
00097                * Replace attr oid/name with the canonical name
00098                */
00099               ava->la_attr = ad->ad_cname;
00100 
00101               validate = ad->ad_type->sat_syntax->ssyn_validate;
00102 
00103               if ( validate ) {
00104                      /*
00105                       * validate value by validate function
00106                       */
00107                      rc = ( *validate )( ad->ad_type->sat_syntax,
00108                             &ava->la_value );
00109                      
00110                      if ( rc != LDAP_SUCCESS ) {
00111                             return LDAP_INVALID_SYNTAX;
00112                      }
00113               }
00114        }
00115 
00116        return LDAP_SUCCESS;
00117 }
00118 
00119 /*
00120  * In-place, schema-aware validation of the
00121  * structural representation of a distinguished name.
00122  */
00123 static int
00124 LDAPDN_validate( LDAPDN dn )
00125 {
00126        int           iRDN;
00127        int           rc;
00128 
00129        assert( dn != NULL );
00130 
00131        for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
00132               rc = LDAPRDN_validate( dn[ iRDN ] );
00133               if ( rc != LDAP_SUCCESS ) {
00134                      return rc;
00135               }
00136        }
00137 
00138        return LDAP_SUCCESS;
00139 }
00140 
00141 /*
00142  * dn validate routine
00143  */
00144 int
00145 dnValidate(
00146        Syntax *syntax,
00147        struct berval *in )
00148 {
00149        int           rc;
00150        LDAPDN        dn = NULL;
00151 
00152        assert( in != NULL );
00153 
00154        if ( in->bv_len == 0 ) {
00155               return LDAP_SUCCESS;
00156 
00157        } else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) {
00158               return LDAP_INVALID_SYNTAX;
00159        }
00160 
00161        rc = ldap_bv2dn( in, &dn, LDAP_DN_FORMAT_LDAP );
00162        if ( rc != LDAP_SUCCESS ) {
00163               return LDAP_INVALID_SYNTAX;
00164        }
00165 
00166        assert( strlen( in->bv_val ) == in->bv_len );
00167 
00168        /*
00169         * Schema-aware validate
00170         */
00171        rc = LDAPDN_validate( dn );
00172        ldap_dnfree( dn );
00173 
00174        if ( rc != LDAP_SUCCESS ) {
00175               return LDAP_INVALID_SYNTAX;
00176        }
00177 
00178        return LDAP_SUCCESS;
00179 }
00180 
00181 int
00182 rdnValidate(
00183        Syntax *syntax,
00184        struct berval *in )
00185 {
00186        int           rc;
00187        LDAPRDN              rdn;
00188        char*         p;
00189 
00190        assert( in != NULL );
00191        if ( in->bv_len == 0 ) {
00192               return LDAP_SUCCESS;
00193 
00194        } else if ( in->bv_len > SLAP_LDAPDN_MAXLEN ) {
00195               return LDAP_INVALID_SYNTAX;
00196        }
00197 
00198        rc = ldap_bv2rdn_x( in , &rdn, (char **) &p,
00199                             LDAP_DN_FORMAT_LDAP, NULL);
00200        if ( rc != LDAP_SUCCESS ) {
00201               return LDAP_INVALID_SYNTAX;
00202        }
00203 
00204        assert( strlen( in->bv_val ) == in->bv_len );
00205 
00206        /*
00207         * Schema-aware validate
00208         */
00209        rc = LDAPRDN_validate( rdn );
00210        ldap_rdnfree( rdn );
00211 
00212        if ( rc != LDAP_SUCCESS ) {
00213               return LDAP_INVALID_SYNTAX;
00214        }
00215 
00216        return LDAP_SUCCESS;
00217 }
00218 
00219 
00220 /*
00221  * AVA sorting inside a RDN
00222  *
00223  * Rule: sort attributeTypes in alphabetical order.
00224  *
00225  * Note: the sorting can be slightly improved by sorting first
00226  * by attribute type length, then by alphabetical order.
00227  *
00228  * uses an insertion sort; should be fine since the number of AVAs in
00229  * a RDN should be limited.
00230  */
00231 static int
00232 AVA_Sort( LDAPRDN rdn, int nAVAs )
00233 {
00234        LDAPAVA       *ava_i;
00235        int           i;
00236 
00237        assert( rdn != NULL );
00238 
00239        for ( i = 1; i < nAVAs; i++ ) {
00240               LDAPAVA *ava_j;
00241               int j;
00242 
00243               ava_i = rdn[ i ];
00244               for ( j = i-1; j >=0; j-- ) {
00245                      int a;
00246 
00247                      ava_j = rdn[ j ];
00248                      a = strcmp( ava_i->la_attr.bv_val, ava_j->la_attr.bv_val );
00249 
00250                      /* RFC4512 does not allow multiple AVAs
00251                       * with the same attribute type in RDN (ITS#5968) */
00252                      if ( a == 0 )
00253                             return LDAP_INVALID_DN_SYNTAX;
00254 
00255                      if ( a > 0 )
00256                             break;
00257 
00258                      rdn[ j+1 ] = rdn[ j ];
00259               }
00260               rdn[ j+1 ] = ava_i;
00261        }
00262        return LDAP_SUCCESS;
00263 }
00264 
00265 static int
00266 LDAPRDN_rewrite( LDAPRDN rdn, unsigned flags, void *ctx )
00267 {
00268 
00269        int rc, iAVA, do_sort = 0;
00270 
00271        for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
00272               LDAPAVA                     *ava = rdn[ iAVA ];
00273               AttributeDescription *ad;
00274               slap_syntax_validate_func *validf = NULL;
00275               slap_mr_normalize_func *normf = NULL;
00276               slap_syntax_transform_func *transf = NULL;
00277               MatchingRule *mr = NULL;
00278               struct berval        bv = BER_BVNULL;
00279 
00280               assert( ava != NULL );
00281 
00282               if ( ( ad = AVA_PRIVATE( ava ) ) == NULL ) {
00283                      const char    *text = NULL;
00284 
00285                      rc = slap_bv2ad( &ava->la_attr, &ad, &text );
00286                      if ( rc != LDAP_SUCCESS ) {
00287                             rc = slap_bv2undef_ad( &ava->la_attr,
00288                                    &ad, &text,
00289                                    SLAP_AD_PROXIED|slap_DN_strict );
00290                             if ( rc != LDAP_SUCCESS ) {
00291                                    return LDAP_INVALID_SYNTAX;
00292                             }
00293                      }
00294                      
00295                      ava->la_private = ( void * )ad;
00296                      do_sort = 1;
00297               }
00298 
00299               /* 
00300                * Replace attr oid/name with the canonical name
00301                */
00302               ava->la_attr = ad->ad_cname;
00303 
00304               if( ava->la_flags & LDAP_AVA_BINARY ) {
00305                      /* AVA is binary encoded, not supported */
00306                      return LDAP_INVALID_SYNTAX;
00307 
00308                      /* Do not allow X-ORDERED 'VALUES' naming attributes */
00309               } else if( ad->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) {
00310                      return LDAP_INVALID_SYNTAX;
00311 
00312               } else if( flags & SLAP_LDAPDN_PRETTY ) {
00313                      transf = ad->ad_type->sat_syntax->ssyn_pretty;
00314                      if( !transf ) {
00315                             validf = ad->ad_type->sat_syntax->ssyn_validate;
00316                      }
00317               } else { /* normalization */
00318                      validf = ad->ad_type->sat_syntax->ssyn_validate;
00319                      mr = ad->ad_type->sat_equality;
00320                      if( mr && (!( mr->smr_usage & SLAP_MR_MUTATION_NORMALIZER ))) {
00321                             normf = mr->smr_normalize;
00322                      }
00323               }
00324 
00325               if ( validf ) {
00326                      /* validate value before normalization */
00327                      rc = ( *validf )( ad->ad_type->sat_syntax,
00328                             ava->la_value.bv_len
00329                                    ? &ava->la_value
00330                                    : (struct berval *) &slap_empty_bv );
00331 
00332                      if ( rc != LDAP_SUCCESS ) {
00333                             return LDAP_INVALID_SYNTAX;
00334                      }
00335               }
00336 
00337               if ( transf ) {
00338                      /*
00339                       * transform value by pretty function
00340                       *     if value is empty, use empty_bv
00341                       */
00342                      rc = ( *transf )( ad->ad_type->sat_syntax,
00343                             ava->la_value.bv_len
00344                                    ? &ava->la_value
00345                                    : (struct berval *) &slap_empty_bv,
00346                             &bv, ctx );
00347               
00348                      if ( rc != LDAP_SUCCESS ) {
00349                             return LDAP_INVALID_SYNTAX;
00350                      }
00351               }
00352 
00353               if ( normf ) {
00354                      /*
00355                       * normalize value
00356                       *     if value is empty, use empty_bv
00357                       */
00358                      rc = ( *normf )(
00359                             SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
00360                             ad->ad_type->sat_syntax,
00361                             mr,
00362                             ava->la_value.bv_len
00363                                    ? &ava->la_value
00364                                    : (struct berval *) &slap_empty_bv,
00365                             &bv, ctx );
00366               
00367                      if ( rc != LDAP_SUCCESS ) {
00368                             return LDAP_INVALID_SYNTAX;
00369                      }
00370               }
00371 
00372 
00373               if( bv.bv_val ) {
00374                      if ( ava->la_flags & LDAP_AVA_FREE_VALUE )
00375                             ber_memfree_x( ava->la_value.bv_val, ctx );
00376                      ava->la_value = bv;
00377                      ava->la_flags |= LDAP_AVA_FREE_VALUE;
00378               }
00379               /* reject empty values */
00380               if (!ava->la_value.bv_len) {
00381                      return LDAP_INVALID_SYNTAX;
00382               }
00383        }
00384        rc = LDAP_SUCCESS;
00385 
00386        if ( do_sort ) {
00387               rc = AVA_Sort( rdn, iAVA );
00388        }
00389 
00390        return rc;
00391 }
00392 
00393 /*
00394  * In-place, schema-aware normalization / "pretty"ing of the
00395  * structural representation of a distinguished name.
00396  */
00397 static int
00398 LDAPDN_rewrite( LDAPDN dn, unsigned flags, void *ctx )
00399 {
00400        int           iRDN;
00401        int           rc;
00402 
00403        assert( dn != NULL );
00404 
00405        for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
00406               rc = LDAPRDN_rewrite( dn[ iRDN ], flags, ctx );
00407               if ( rc != LDAP_SUCCESS ) {
00408                      return rc;
00409               }
00410        }
00411 
00412        return LDAP_SUCCESS;
00413 }
00414 
00415 int
00416 dnNormalize(
00417     slap_mask_t use,
00418     Syntax *syntax,
00419     MatchingRule *mr,
00420     struct berval *val,
00421     struct berval *out,
00422     void *ctx)
00423 {
00424        assert( val != NULL );
00425        assert( out != NULL );
00426 
00427        Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 );
00428 
00429        if ( val->bv_len != 0 ) {
00430               LDAPDN        dn = NULL;
00431               int           rc;
00432 
00433               /*
00434                * Go to structural representation
00435                */
00436               rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
00437               if ( rc != LDAP_SUCCESS ) {
00438                      return LDAP_INVALID_SYNTAX;
00439               }
00440 
00441               assert( strlen( val->bv_val ) == val->bv_len );
00442 
00443               /*
00444                * Schema-aware rewrite
00445                */
00446               if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
00447                      ldap_dnfree_x( dn, ctx );
00448                      return LDAP_INVALID_SYNTAX;
00449               }
00450 
00451               /*
00452                * Back to string representation
00453                */
00454               rc = ldap_dn2bv_x( dn, out,
00455                      LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
00456 
00457               ldap_dnfree_x( dn, ctx );
00458 
00459               if ( rc != LDAP_SUCCESS ) {
00460                      return LDAP_INVALID_SYNTAX;
00461               }
00462        } else {
00463               ber_dupbv_x( out, val, ctx );
00464        }
00465 
00466        Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val ? out->bv_val : "", 0, 0 );
00467 
00468        return LDAP_SUCCESS;
00469 }
00470 
00471 int
00472 rdnNormalize(
00473     slap_mask_t use,
00474     Syntax *syntax,
00475     MatchingRule *mr,
00476     struct berval *val,
00477     struct berval *out,
00478     void *ctx)
00479 {
00480        assert( val != NULL );
00481        assert( out != NULL );
00482 
00483        Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 );
00484        if ( val->bv_len != 0 ) {
00485               LDAPRDN              rdn = NULL;
00486               int           rc;
00487               char*         p;
00488 
00489               /*
00490                * Go to structural representation
00491                */
00492               rc = ldap_bv2rdn_x( val , &rdn, (char **) &p,
00493                                    LDAP_DN_FORMAT_LDAP, ctx);
00494 
00495               if ( rc != LDAP_SUCCESS ) {
00496                      return LDAP_INVALID_SYNTAX;
00497               }
00498 
00499               assert( strlen( val->bv_val ) == val->bv_len );
00500 
00501               /*
00502                * Schema-aware rewrite
00503                */
00504               if ( LDAPRDN_rewrite( rdn, 0, ctx ) != LDAP_SUCCESS ) {
00505                      ldap_rdnfree_x( rdn, ctx );
00506                      return LDAP_INVALID_SYNTAX;
00507               }
00508 
00509               /*
00510                * Back to string representation
00511                */
00512               rc = ldap_rdn2bv_x( rdn, out,
00513                      LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
00514 
00515               ldap_rdnfree_x( rdn, ctx );
00516 
00517               if ( rc != LDAP_SUCCESS ) {
00518                      return LDAP_INVALID_SYNTAX;
00519               }
00520        } else {
00521               ber_dupbv_x( out, val, ctx );
00522        }
00523 
00524        Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val ? out->bv_val : "", 0, 0 );
00525 
00526        return LDAP_SUCCESS;
00527 }
00528 
00529 int
00530 dnPretty(
00531        Syntax *syntax,
00532        struct berval *val,
00533        struct berval *out,
00534        void *ctx)
00535 {
00536        assert( val != NULL );
00537        assert( out != NULL );
00538 
00539        Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 );
00540 
00541        if ( val->bv_len == 0 ) {
00542               ber_dupbv_x( out, val, ctx );
00543 
00544        } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
00545               return LDAP_INVALID_SYNTAX;
00546 
00547        } else {
00548               LDAPDN        dn = NULL;
00549               int           rc;
00550 
00551               /* FIXME: should be liberal in what we accept */
00552               rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
00553               if ( rc != LDAP_SUCCESS ) {
00554                      return LDAP_INVALID_SYNTAX;
00555               }
00556 
00557               assert( strlen( val->bv_val ) == val->bv_len );
00558 
00559               /*
00560                * Schema-aware rewrite
00561                */
00562               if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
00563                      ldap_dnfree_x( dn, ctx );
00564                      return LDAP_INVALID_SYNTAX;
00565               }
00566 
00567               /* FIXME: not sure why the default isn't pretty */
00568               /* RE: the default is the form that is used as
00569                * an internal representation; the pretty form
00570                * is a variant */
00571               rc = ldap_dn2bv_x( dn, out,
00572                      LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
00573 
00574               ldap_dnfree_x( dn, ctx );
00575 
00576               if ( rc != LDAP_SUCCESS ) {
00577                      return LDAP_INVALID_SYNTAX;
00578               }
00579        }
00580 
00581        Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val ? out->bv_val : "", 0, 0 );
00582 
00583        return LDAP_SUCCESS;
00584 }
00585 
00586 int
00587 rdnPretty(
00588        Syntax *syntax,
00589        struct berval *val,
00590        struct berval *out,
00591        void *ctx)
00592 {
00593        assert( val != NULL );
00594        assert( out != NULL );
00595 
00596        Debug( LDAP_DEBUG_TRACE, ">>> rdnPretty: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 );
00597 
00598        if ( val->bv_len == 0 ) {
00599               ber_dupbv_x( out, val, ctx );
00600 
00601        } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
00602               return LDAP_INVALID_SYNTAX;
00603 
00604        } else {
00605               LDAPRDN              rdn = NULL;
00606               int           rc;
00607               char*         p;
00608 
00609               /* FIXME: should be liberal in what we accept */
00610               rc = ldap_bv2rdn_x( val , &rdn, (char **) &p,
00611                                    LDAP_DN_FORMAT_LDAP, ctx);
00612               if ( rc != LDAP_SUCCESS ) {
00613                      return LDAP_INVALID_SYNTAX;
00614               }
00615 
00616               assert( strlen( val->bv_val ) == val->bv_len );
00617 
00618               /*
00619                * Schema-aware rewrite
00620                */
00621               if ( LDAPRDN_rewrite( rdn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
00622                      ldap_rdnfree_x( rdn, ctx );
00623                      return LDAP_INVALID_SYNTAX;
00624               }
00625 
00626               /* FIXME: not sure why the default isn't pretty */
00627               /* RE: the default is the form that is used as
00628                * an internal representation; the pretty form
00629                * is a variant */
00630               rc = ldap_rdn2bv_x( rdn, out,
00631                      LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
00632 
00633               ldap_rdnfree_x( rdn, ctx );
00634 
00635               if ( rc != LDAP_SUCCESS ) {
00636                      return LDAP_INVALID_SYNTAX;
00637               }
00638        }
00639 
00640        Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val ? out->bv_val : "", 0, 0 );
00641 
00642        return LDAP_SUCCESS;
00643 }
00644 
00645 
00646 int
00647 dnPrettyNormalDN(
00648        Syntax *syntax,
00649        struct berval *val,
00650        LDAPDN *dn,
00651        int flags,
00652        void *ctx )
00653 {
00654        assert( val != NULL );
00655        assert( dn != NULL );
00656 
00657        Debug( LDAP_DEBUG_TRACE, ">>> dn%sDN: <%s>\n", 
00658                      flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal", 
00659                      val->bv_val ? val->bv_val : "", 0 );
00660 
00661        if ( val->bv_len == 0 ) {
00662               return LDAP_SUCCESS;
00663 
00664        } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
00665               return LDAP_INVALID_SYNTAX;
00666 
00667        } else {
00668               int           rc;
00669 
00670               /* FIXME: should be liberal in what we accept */
00671               rc = ldap_bv2dn_x( val, dn, LDAP_DN_FORMAT_LDAP, ctx );
00672               if ( rc != LDAP_SUCCESS ) {
00673                      return LDAP_INVALID_SYNTAX;
00674               }
00675 
00676               assert( strlen( val->bv_val ) == val->bv_len );
00677 
00678               /*
00679                * Schema-aware rewrite
00680                */
00681               if ( LDAPDN_rewrite( *dn, flags, ctx ) != LDAP_SUCCESS ) {
00682                      ldap_dnfree_x( *dn, ctx );
00683                      *dn = NULL;
00684                      return LDAP_INVALID_SYNTAX;
00685               }
00686        }
00687 
00688        Debug( LDAP_DEBUG_TRACE, "<<< dn%sDN\n", 
00689                      flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
00690                      0, 0 );
00691 
00692        return LDAP_SUCCESS;
00693 }
00694 
00695 /*
00696  * Combination of both dnPretty and dnNormalize
00697  */
00698 int
00699 dnPrettyNormal(
00700        Syntax *syntax,
00701        struct berval *val,
00702        struct berval *pretty,
00703        struct berval *normal,
00704        void *ctx)
00705 {
00706        assert( val != NULL );
00707        assert( pretty != NULL );
00708        assert( normal != NULL );
00709        Debug( LDAP_DEBUG_TRACE, ">>> dnPrettyNormal: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 );
00710 
00711        if ( val->bv_len == 0 ) {
00712               ber_dupbv_x( pretty, val, ctx );
00713               ber_dupbv_x( normal, val, ctx );
00714 
00715        } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
00716               /* too big */
00717               return LDAP_INVALID_SYNTAX;
00718 
00719        } else {
00720               LDAPDN        dn = NULL;
00721               int           rc;
00722 
00723               pretty->bv_val = NULL;
00724               normal->bv_val = NULL;
00725               pretty->bv_len = 0;
00726               normal->bv_len = 0;
00727 
00728               /* FIXME: should be liberal in what we accept */
00729               rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx );
00730               if ( rc != LDAP_SUCCESS ) {
00731                      return LDAP_INVALID_SYNTAX;
00732               }
00733 
00734               assert( strlen( val->bv_val ) == val->bv_len );
00735 
00736               /*
00737                * Schema-aware rewrite
00738                */
00739               if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) {
00740                      ldap_dnfree_x( dn, ctx );
00741                      return LDAP_INVALID_SYNTAX;
00742               }
00743 
00744               rc = ldap_dn2bv_x( dn, pretty,
00745                      LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
00746 
00747               if ( rc != LDAP_SUCCESS ) {
00748                      ldap_dnfree_x( dn, ctx );
00749                      return LDAP_INVALID_SYNTAX;
00750               }
00751 
00752               if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) {
00753                      ldap_dnfree_x( dn, ctx );
00754                      ber_memfree_x( pretty->bv_val, ctx );
00755                      pretty->bv_val = NULL;
00756                      pretty->bv_len = 0;
00757                      return LDAP_INVALID_SYNTAX;
00758               }
00759 
00760               rc = ldap_dn2bv_x( dn, normal,
00761                      LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx );
00762 
00763               ldap_dnfree_x( dn, ctx );
00764               if ( rc != LDAP_SUCCESS ) {
00765                      ber_memfree_x( pretty->bv_val, ctx );
00766                      pretty->bv_val = NULL;
00767                      pretty->bv_len = 0;
00768                      return LDAP_INVALID_SYNTAX;
00769               }
00770        }
00771 
00772        Debug( LDAP_DEBUG_TRACE, "<<< dnPrettyNormal: <%s>, <%s>\n",
00773               pretty->bv_val ? pretty->bv_val : "",
00774               normal->bv_val ? normal->bv_val : "", 0 );
00775 
00776        return LDAP_SUCCESS;
00777 }
00778 
00779 /*
00780  * dnMatch routine
00781  */
00782 int
00783 dnMatch(
00784        int *matchp,
00785        slap_mask_t flags,
00786        Syntax *syntax,
00787        MatchingRule *mr,
00788        struct berval *value,
00789        void *assertedValue )
00790 {
00791        int match;
00792        struct berval *asserted = (struct berval *) assertedValue;
00793 
00794        assert( matchp != NULL );
00795        assert( value != NULL );
00796        assert( assertedValue != NULL );
00797        assert( !BER_BVISNULL( value ) );
00798        assert( !BER_BVISNULL( asserted ) );
00799        
00800        match = value->bv_len - asserted->bv_len;
00801 
00802        if ( match == 0 ) {
00803               match = memcmp( value->bv_val, asserted->bv_val, 
00804                             value->bv_len );
00805        }
00806 
00807        Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
00808               match, value->bv_val, asserted->bv_val );
00809 
00810        *matchp = match;
00811        return LDAP_SUCCESS;
00812 }
00813 
00814 /*
00815  * dnRelativeMatch routine
00816  */
00817 int
00818 dnRelativeMatch(
00819        int *matchp,
00820        slap_mask_t flags,
00821        Syntax *syntax,
00822        MatchingRule *mr,
00823        struct berval *value,
00824        void *assertedValue )
00825 {
00826        int match;
00827        struct berval *asserted = (struct berval *) assertedValue;
00828 
00829        assert( matchp != NULL );
00830        assert( value != NULL );
00831        assert( assertedValue != NULL );
00832        assert( !BER_BVISNULL( value ) );
00833        assert( !BER_BVISNULL( asserted ) );
00834 
00835        if( mr == slap_schema.si_mr_dnSubtreeMatch ) {
00836               if( asserted->bv_len > value->bv_len ) {
00837                      match = -1;
00838               } else if ( asserted->bv_len == value->bv_len ) {
00839                      match = memcmp( value->bv_val, asserted->bv_val, 
00840                             value->bv_len );
00841               } else {
00842                      if( DN_SEPARATOR(
00843                             value->bv_val[value->bv_len - asserted->bv_len - 1] ))
00844                      {
00845                             match = memcmp(
00846                                    &value->bv_val[value->bv_len - asserted->bv_len],
00847                                    asserted->bv_val, 
00848                                    asserted->bv_len );
00849                      } else {
00850                             match = 1;
00851                      }
00852               }
00853 
00854               *matchp = match;
00855               return LDAP_SUCCESS;
00856        }
00857 
00858        if( mr == slap_schema.si_mr_dnSuperiorMatch ) {
00859               asserted = value;
00860               value = (struct berval *) assertedValue;
00861               mr = slap_schema.si_mr_dnSubordinateMatch;
00862        }
00863 
00864        if( mr == slap_schema.si_mr_dnSubordinateMatch ) {
00865               if( asserted->bv_len >= value->bv_len ) {
00866                      match = -1;
00867               } else {
00868                      if( DN_SEPARATOR(
00869                             value->bv_val[value->bv_len - asserted->bv_len - 1] ))
00870                      {
00871                             match = memcmp(
00872                                    &value->bv_val[value->bv_len - asserted->bv_len],
00873                                    asserted->bv_val, 
00874                                    asserted->bv_len );
00875                      } else {
00876                             match = 1;
00877                      }
00878               }
00879 
00880               *matchp = match;
00881               return LDAP_SUCCESS;
00882        }
00883 
00884        if( mr == slap_schema.si_mr_dnOneLevelMatch ) {
00885               if( asserted->bv_len >= value->bv_len ) {
00886                      match = -1;
00887               } else {
00888                      if( DN_SEPARATOR(
00889                             value->bv_val[value->bv_len - asserted->bv_len - 1] ))
00890                      {
00891                             match = memcmp(
00892                                    &value->bv_val[value->bv_len - asserted->bv_len],
00893                                    asserted->bv_val, 
00894                                    asserted->bv_len );
00895 
00896                             if( !match ) {
00897                                    struct berval rdn;
00898                                    rdn.bv_val = value->bv_val;
00899                                    rdn.bv_len = value->bv_len - asserted->bv_len - 1;
00900                                    match = dnIsOneLevelRDN( &rdn ) ? 0 : 1;
00901                             }
00902                      } else {
00903                             match = 1;
00904                      }
00905               }
00906 
00907               *matchp = match;
00908               return LDAP_SUCCESS;
00909        }
00910 
00911        /* should not be reachable */
00912        assert( 0 );
00913        return LDAP_OTHER;
00914 }
00915 
00916 int
00917 rdnMatch(
00918        int *matchp,
00919        slap_mask_t flags,
00920        Syntax *syntax,
00921        MatchingRule *mr,
00922        struct berval *value,
00923        void *assertedValue )
00924 {
00925        int match;
00926        struct berval *asserted = (struct berval *) assertedValue;
00927 
00928        assert( matchp != NULL );
00929        assert( value != NULL );
00930        assert( assertedValue != NULL );
00931        
00932        match = value->bv_len - asserted->bv_len;
00933 
00934        if ( match == 0 ) {
00935               match = memcmp( value->bv_val, asserted->bv_val, 
00936                             value->bv_len );
00937        }
00938 
00939        Debug( LDAP_DEBUG_ARGS, "rdnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
00940               match, value->bv_val, asserted->bv_val );
00941 
00942        *matchp = match;
00943        return LDAP_SUCCESS;
00944 }
00945 
00946 
00947 /*
00948  * dnParent - dn's parent, in-place
00949  * note: the incoming dn is assumed to be normalized/prettyfied,
00950  * so that escaped rdn/ava separators are in '\'+hexpair form
00951  *
00952  * note: "dn" and "pdn" can point to the same berval;
00953  * beware that, in this case, the pointer to the original buffer
00954  * will get lost.
00955  */
00956 void
00957 dnParent( 
00958        struct berval *dn, 
00959        struct berval *pdn )
00960 {
00961        char   *p;
00962 
00963        p = ber_bvchr( dn, ',' );
00964 
00965        /* one-level dn */
00966        if ( p == NULL ) {
00967               pdn->bv_val = dn->bv_val + dn->bv_len;
00968               pdn->bv_len = 0;
00969               return;
00970        }
00971 
00972        assert( DN_SEPARATOR( p[ 0 ] ) );
00973        p++;
00974 
00975        assert( ATTR_LEADCHAR( p[ 0 ] ) );
00976        pdn->bv_len = dn->bv_len - (p - dn->bv_val);
00977        pdn->bv_val = p;
00978 
00979        return;
00980 }
00981 
00982 /*
00983  * dnRdn - dn's rdn, in-place
00984  * note: the incoming dn is assumed to be normalized/prettyfied,
00985  * so that escaped rdn/ava separators are in '\'+hexpair form
00986  */
00987 void
00988 dnRdn( 
00989        struct berval *dn, 
00990        struct berval *rdn )
00991 {
00992        char   *p;
00993 
00994        *rdn = *dn;
00995        p = ber_bvchr( dn, ',' );
00996 
00997        /* one-level dn */
00998        if ( p == NULL ) {
00999               return;
01000        }
01001 
01002        assert( DN_SEPARATOR( p[ 0 ] ) );
01003        assert( ATTR_LEADCHAR( p[ 1 ] ) );
01004        rdn->bv_len = p - dn->bv_val;
01005 
01006        return;
01007 }
01008 
01009 int
01010 dnExtractRdn( 
01011        struct berval *dn, 
01012        struct berval        *rdn,
01013        void *ctx )
01014 {
01015        LDAPRDN              tmpRDN;
01016        const char    *p;
01017        int           rc;
01018 
01019        assert( dn != NULL );
01020        assert( rdn != NULL );
01021 
01022        if( dn->bv_len == 0 ) {
01023               return LDAP_OTHER;
01024        }
01025 
01026        rc = ldap_bv2rdn_x( dn, &tmpRDN, (char **)&p, LDAP_DN_FORMAT_LDAP, ctx );
01027        if ( rc != LDAP_SUCCESS ) {
01028               return rc;
01029        }
01030 
01031        rc = ldap_rdn2bv_x( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY,
01032               ctx );
01033 
01034        ldap_rdnfree_x( tmpRDN, ctx );
01035        return rc;
01036 }
01037 
01038 /*
01039  * We can assume the input is a prettied or normalized DN
01040  */
01041 ber_len_t
01042 dn_rdnlen(
01043        Backend              *be,
01044        struct berval *dn_in )
01045 {
01046        const char    *p;
01047 
01048        assert( dn_in != NULL );
01049 
01050        if ( dn_in == NULL ) {
01051               return 0;
01052        }
01053 
01054        if ( !dn_in->bv_len ) {
01055               return 0;
01056        }
01057 
01058        if ( be != NULL && be_issuffix( be, dn_in ) ) {
01059               return 0;
01060        }
01061 
01062        p = ber_bvchr( dn_in, ',' );
01063 
01064        return p ? (ber_len_t) (p - dn_in->bv_val) : dn_in->bv_len;
01065 }
01066 
01067 
01068 /* rdnValidate:
01069  *
01070  * LDAP_SUCCESS if rdn is a legal rdn;
01071  * LDAP_INVALID_SYNTAX otherwise (including a sequence of rdns)
01072  */
01073 int
01074 rdn_validate( struct berval *rdn )
01075 {
01076 #if 1
01077        /* Major cheat!
01078         * input is a pretty or normalized DN
01079         * hence, we can just search for ','
01080         */
01081        if( rdn == NULL || rdn->bv_len == 0 ||
01082               rdn->bv_len > SLAP_LDAPDN_MAXLEN )
01083        {
01084               return LDAP_INVALID_SYNTAX;
01085        }
01086        return ber_bvchr( rdn, ',' ) == NULL
01087               ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX;
01088 
01089 #else
01090        LDAPRDN              *RDN, **DN[ 2 ] = { &RDN, NULL };
01091        const char    *p;
01092        int           rc;
01093 
01094        /*
01095         * must be non-empty
01096         */
01097        if ( rdn == NULL || rdn == '\0' ) {
01098               return 0;
01099        }
01100 
01101        /*
01102         * must be parsable
01103         */
01104        rc = ldap_bv2rdn( rdn, &RDN, (char **)&p, LDAP_DN_FORMAT_LDAP );
01105        if ( rc != LDAP_SUCCESS ) {
01106               return 0;
01107        }
01108 
01109        /*
01110         * Must be one-level
01111         */
01112        if ( p[ 0 ] != '\0' ) {
01113               return 0;
01114        }
01115 
01116        /*
01117         * Schema-aware validate
01118         */
01119        if ( rc == LDAP_SUCCESS ) {
01120               rc = LDAPDN_validate( DN );
01121        }
01122        ldap_rdnfree( RDN );
01123 
01124        /*
01125         * Must validate (there's a repeated parsing ...)
01126         */
01127        return ( rc == LDAP_SUCCESS );
01128 #endif
01129 }
01130 
01131 
01132 /* build_new_dn:
01133  *
01134  * Used by back-bdb back_modrdn to create the new dn of entries being
01135  * renamed.
01136  *
01137  * new_dn = parent (p_dn) + separator + rdn (newrdn) + null.
01138  */
01139 
01140 void
01141 build_new_dn( struct berval * new_dn,
01142        struct berval * parent_dn,
01143        struct berval * newrdn,
01144        void *memctx )
01145 {
01146        char *ptr;
01147 
01148        if ( parent_dn == NULL || parent_dn->bv_len == 0 ) {
01149               ber_dupbv_x( new_dn, newrdn, memctx );
01150               return;
01151        }
01152 
01153        new_dn->bv_len = parent_dn->bv_len + newrdn->bv_len + 1;
01154        new_dn->bv_val = (char *) slap_sl_malloc( new_dn->bv_len + 1, memctx );
01155 
01156        ptr = lutil_strncopy( new_dn->bv_val, newrdn->bv_val, newrdn->bv_len );
01157        *ptr++ = ',';
01158        strcpy( ptr, parent_dn->bv_val );
01159 }
01160 
01161 
01162 /*
01163  * dnIsSuffix - tells whether suffix is a suffix of dn.
01164  * Both dn and suffix must be normalized.
01165  */
01166 int
01167 dnIsSuffix(
01168        const struct berval *dn,
01169        const struct berval *suffix )
01170 {
01171        int    d;
01172 
01173        assert( dn != NULL );
01174        assert( suffix != NULL );
01175 
01176        d = dn->bv_len - suffix->bv_len;
01177 
01178        /* empty suffix matches any dn */
01179        if ( suffix->bv_len == 0 ) {
01180               return 1;
01181        }
01182 
01183        /* suffix longer than dn */
01184        if ( d < 0 ) {
01185               return 0;
01186        }
01187 
01188        /* no rdn separator or escaped rdn separator */
01189        if ( d > 1 && !DN_SEPARATOR( dn->bv_val[ d - 1 ] ) ) {
01190               return 0;
01191        }
01192 
01193        /* no possible match or malformed dn */
01194        if ( d == 1 ) {
01195               return 0;
01196        }
01197 
01198        /* compare */
01199        return( strncmp( dn->bv_val + d, suffix->bv_val, suffix->bv_len ) == 0 );
01200 }
01201 
01202 /*
01203  * In place; assumes:
01204  * - ndn is normalized
01205  * - nbase is normalized
01206  * - dnIsSuffix( ndn, nbase ) == TRUE
01207  * - LDAP_SCOPE_DEFAULT == LDAP_SCOPE_SUBTREE
01208  */
01209 int
01210 dnIsWithinScope( struct berval *ndn, struct berval *nbase, int scope )
01211 {
01212        assert( ndn != NULL );
01213        assert( nbase != NULL );
01214        assert( !BER_BVISNULL( ndn ) );
01215        assert( !BER_BVISNULL( nbase ) );
01216 
01217        switch ( scope ) {
01218        case LDAP_SCOPE_DEFAULT:
01219        case LDAP_SCOPE_SUBTREE:
01220               break;
01221 
01222        case LDAP_SCOPE_BASE:
01223               if ( ndn->bv_len != nbase->bv_len ) {
01224                      return 0;
01225               }
01226               break;
01227 
01228        case LDAP_SCOPE_ONELEVEL: {
01229               struct berval pndn;
01230               dnParent( ndn, &pndn );
01231               if ( pndn.bv_len != nbase->bv_len ) {
01232                      return 0;
01233               }
01234               } break;
01235 
01236        case LDAP_SCOPE_SUBORDINATE:
01237               if ( ndn->bv_len == nbase->bv_len ) {
01238                      return 0;
01239               }
01240               break;
01241 
01242        /* unknown scope */
01243        default:
01244               return -1;
01245        }
01246 
01247        return 1;
01248 }
01249 
01250 /*
01251  * In place; assumes:
01252  * - ndn is normalized
01253  * - nbase is normalized
01254  * - LDAP_SCOPE_DEFAULT == LDAP_SCOPE_SUBTREE
01255  */
01256 int
01257 dnIsSuffixScope( struct berval *ndn, struct berval *nbase, int scope )
01258 {
01259        if ( !dnIsSuffix( ndn, nbase ) ) {
01260               return 0;
01261        }
01262 
01263        return dnIsWithinScope( ndn, nbase, scope );
01264 }
01265 
01266 int
01267 dnIsOneLevelRDN( struct berval *rdn )
01268 {
01269        ber_len_t     len = rdn->bv_len;
01270        for ( ; len--; ) {
01271               if ( DN_SEPARATOR( rdn->bv_val[ len ] ) ) {
01272                      return 0;
01273               }
01274        }
01275 
01276        return 1;
01277 }
01278 
01279 #ifdef HAVE_TLS
01280 static SLAP_CERT_MAP_FN *DNX509PeerNormalizeCertMap = NULL;
01281 #endif
01282 
01283 int register_certificate_map_function(SLAP_CERT_MAP_FN *fn)
01284 {
01285 #ifdef HAVE_TLS
01286        if ( DNX509PeerNormalizeCertMap == NULL ) {
01287               DNX509PeerNormalizeCertMap = fn;
01288               return 0;
01289        }
01290 #endif
01291 
01292        return -1;
01293 }
01294 
01295 /*
01296  * Convert an X.509 DN into a normalized LDAP DN
01297  */
01298 int
01299 dnX509normalize( void *x509_name, struct berval *out )
01300 {
01301        /* Invoke the LDAP library's converter with our schema-rewriter */
01302        int rc = ldap_X509dn2bv( x509_name, out, LDAPDN_rewrite, 0 );
01303 
01304        Debug( LDAP_DEBUG_TRACE,
01305               "dnX509Normalize: <%s> (%d)\n",
01306               BER_BVISNULL( out ) ? "(null)" : out->bv_val, rc, 0 );
01307 
01308        return rc;
01309 }
01310 
01311 #ifdef HAVE_TLS
01312 /*
01313  * Get the TLS session's peer's DN into a normalized LDAP DN
01314  */
01315 int
01316 dnX509peerNormalize( void *ssl, struct berval *dn )
01317 {
01318        int rc = LDAP_INVALID_CREDENTIALS;
01319 
01320        if ( DNX509PeerNormalizeCertMap != NULL )
01321               rc = (*DNX509PeerNormalizeCertMap)( ssl, dn );
01322 
01323        if ( rc != LDAP_SUCCESS ) {
01324               rc = ldap_pvt_tls_get_peer_dn( ssl, dn,
01325                      (LDAPDN_rewrite_dummy *)LDAPDN_rewrite, 0 );
01326        }
01327 
01328        return rc;
01329 }
01330 #endif