]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-ldap/search.c
Happy New Year
[openldap] / servers / slapd / back-ldap / search.c
index eeab466a568a229bc0eee54d1b014874d8ab9469..3fad39c62b33761639842293fef0964ead92a854 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1999-2014 The OpenLDAP Foundation.
+ * Copyright 1999-2018 The OpenLDAP Foundation.
  * Portions Copyright 1999-2003 Howard Chu.
  * Portions Copyright 2000-2003 Pierangelo Masarati.
  * All rights reserved.
 
 static int
 ldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent,
-        struct berval *bdn );
+        struct berval *bdn, int remove_unknown_schema );
+
+
+static ObjectClass *
+oc_bvfind_undef_ex( struct berval *ocname, int flag )
+{
+       ObjectClass     *oc     = oc_bvfind( ocname );
+
+       if ( oc || flag ) {
+               /* oc defined or remove-unknown-schema flag set */
+               return oc;
+       }
+
+       return oc_bvfind_undef( ocname );
+}
+
 
 /*
  * replaces (&) with (objectClass=*) and (|) with (!(objectClass=*))
@@ -147,6 +162,8 @@ ldap_back_search(
        int             do_retry = 1, dont_retry = 0;
        LDAPControl     **ctrls = NULL;
        char            **references = NULL;
+       int             remove_unknown_schema =
+                                LDAP_BACK_OMIT_UNKNOWN_SCHEMA (li);
 
        rs_assert_ready( rs );
        rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */
@@ -338,7 +355,7 @@ retry:
 
                } else {
                        /* only touch when activity actually took place... */
-                       if ( li->li_idle_timeout && lc ) {
+                       if ( li->li_idle_timeout ) {
                                lc->lc_time = op->o_time;
                        }
 
@@ -354,7 +371,8 @@ retry:
                        do_retry = 0;
 
                        e = ldap_first_entry( lc->lc_ld, res );
-                       rc = ldap_build_entry( op, e, &ent, &bdn );
+                       rc = ldap_build_entry( op, e, &ent, &bdn,
+                                               remove_unknown_schema);
                        if ( rc == LDAP_SUCCESS ) {
                                ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls );
                                rs->sr_entry = &ent;
@@ -645,6 +663,13 @@ finish:;
                ldap_back_release_conn( li, lc );
        }
 
+       if ( rs->sr_err == LDAP_UNAVAILABLE &&
+               /* if we originally bound and wanted rebind-as-user, must drop
+                * the connection now because we just discarded the credentials.
+                * ITS#7464, #8142
+                */
+               LDAP_BACK_SAVECRED( li ) && SLAP_IS_AUTHZ_BACKEND( op ) )
+               rs->sr_err = SLAPD_DISCONNECT;
        return rs->sr_err;
 }
 
@@ -653,7 +678,8 @@ ldap_build_entry(
                Operation       *op,
                LDAPMessage     *e,
                Entry           *ent,
-               struct berval   *bdn )
+               struct berval   *bdn,
+               int remove_unknown_schema)
 {
        struct berval   a;
        BerElement      ber = *ldap_get_message_ber( e );
@@ -707,7 +733,7 @@ ldap_build_entry(
                                != LDAP_SUCCESS )
                {
                        if ( slap_bv2undef_ad( &a, &attr->a_desc, &text,
-                               SLAP_AD_PROXIED ) != LDAP_SUCCESS )
+                                (remove_unknown_schema ? SLAP_AD_NOINSERT : SLAP_AD_PROXIED )) != LDAP_SUCCESS )
                        {
                                Debug( LDAP_DEBUG_ANY, 
                                        "%s ldap_build_entry: "
@@ -785,7 +811,8 @@ ldap_build_entry(
 
                                /* check if, by chance, it's an undefined objectClass */
                                if ( attr->a_desc == slap_schema.si_ad_objectClass &&
-                                               ( oc = oc_bvfind_undef( &attr->a_vals[i] ) ) != NULL )
+                                               ( oc = oc_bvfind_undef_ex( &attr->a_vals[i],
+                                                               remove_unknown_schema ) ) != NULL )
                                {
                                        ber_dupbv( &pval, &oc->soc_cname );
                                        rc = LDAP_SUCCESS;
@@ -900,9 +927,7 @@ ldap_back_entry_get(
        ldapinfo_t      *li = (ldapinfo_t *) op->o_bd->be_private;
 
        ldapconn_t      *lc = NULL;
-       int             rc,
-                       do_not_cache;
-       ber_tag_t       tag;
+       int             rc;
        struct berval   bdn;
        LDAPMessage     *result = NULL,
                        *e = NULL;
@@ -911,20 +936,22 @@ ldap_back_entry_get(
        SlapReply       rs;
        int             do_retry = 1;
        LDAPControl     **ctrls = NULL;
+       Operation op2 = *op;
 
+       int             remove_unknown_schema =
+                               LDAP_BACK_OMIT_UNKNOWN_SCHEMA (li);
        *ent = NULL;
 
        /* Tell getconn this is a privileged op */
-       do_not_cache = op->o_do_not_cache;
-       tag = op->o_tag;
-       /* do not cache */
-       op->o_do_not_cache = 1;
+       op2.o_do_not_cache = 1;
+       /* use rootdn to be doubly explicit this is privileged */
+       op2.o_dn = op->o_bd->be_rootdn;
+       op2.o_ndn = op->o_bd->be_rootndn;
        /* ldap_back_entry_get() is an entry lookup, so it does not need
         * to know what the entry is being looked up for */
-       op->o_tag = LDAP_REQ_SEARCH;
-       rc = ldap_back_dobind( &lc, op, &rs, LDAP_BACK_DONTSEND );
-       op->o_do_not_cache = do_not_cache;
-       op->o_tag = tag;
+       op2.o_tag = LDAP_REQ_SEARCH;
+       op2.o_ctrls = NULL;
+       rc = ldap_back_dobind( &lc, &op2, &rs, LDAP_BACK_DONTSEND );
        if ( !rc ) {
                return rs.sr_err;
        }
@@ -954,8 +981,8 @@ ldap_back_entry_get(
        }
 
 retry:
-       ctrls = op->o_ctrls;
-       rc = ldap_back_controls_add( op, &rs, lc, &ctrls );
+       ctrls = NULL;
+       rc = ldap_back_controls_add( &op2, &rs, lc, &ctrls );
        if ( rc != LDAP_SUCCESS ) {
                goto cleanup;
        }
@@ -967,9 +994,9 @@ retry:
        if ( rc != LDAP_SUCCESS ) {
                if ( rc == LDAP_SERVER_DOWN && do_retry ) {
                        do_retry = 0;
-                       if ( ldap_back_retry( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
+                       if ( ldap_back_retry( &lc, &op2, &rs, LDAP_BACK_DONTSEND ) ) {
                                /* if the identity changed, there might be need to re-authz */
-                               (void)ldap_back_controls_free( op, &rs, &ctrls );
+                               (void)ldap_back_controls_free( &op2, &rs, &ctrls );
                                goto retry;
                        }
                }
@@ -988,7 +1015,7 @@ retry:
                goto cleanup;
        }
 
-       rc = ldap_build_entry( op, e, *ent, &bdn );
+       rc = ldap_build_entry( op, e, *ent, &bdn, remove_unknown_schema );
 
        if ( rc != LDAP_SUCCESS ) {
                entry_free( *ent );
@@ -996,7 +1023,7 @@ retry:
        }
 
 cleanup:
-       (void)ldap_back_controls_free( op, &rs, &ctrls );
+       (void)ldap_back_controls_free( &op2, &rs, &ctrls );
 
        if ( result ) {
                ldap_msgfree( result );