void build_new_dn( struct berval * new_dn, struct berval * parent_dn, struct berval * newrdn, void *memctx ) { char *ptr; if ( parent_dn == NULL || parent_dn->bv_len == 0 ) { ber_dupbv_x( new_dn, newrdn, memctx ); return; } 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_strncopy( new_dn->bv_val, newrdn->bv_val, newrdn->bv_len ); *ptr++ = ','; strcpy( ptr, parent_dn->bv_val ); }
int slap_sort_vals( Modifications *ml, const char **text, int *dup, void *ctx ) { AttributeDescription *ad; MatchingRule *mr; int istack[sizeof(int)*16]; int i, j, k, l, ir, jstack, match, *ix, itmp, nvals, rc = LDAP_SUCCESS; int is_norm; struct berval a, *cv; #define SMALL 8 #define SWAP(a,b,tmp) tmp=(a);(a)=(b);(b)=tmp #define COMP(a,b) match=0; rc = ordered_value_match( &match, \ ad, mr, SLAP_MR_EQUALITY \ | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX \ | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH \ | SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, \ &(a), &(b), text ); #define IX(x) ix[x] #define EXCH(x,y) SWAP(ix[x],ix[y],itmp) #define SETA(x) itmp = ix[x]; a = cv[itmp] #define GETA(x) ix[x] = itmp; #define SET(x,y) ix[x] = ix[y] ad = ml->sml_desc; nvals = ml->sml_numvals; if ( nvals <= 1 ) goto ret; /* For Modifications, sml_nvalues is NULL if normalization wasn't needed. * For Attributes, sml_nvalues == sml_values when normalization isn't needed. */ if ( ml->sml_nvalues && ml->sml_nvalues != ml->sml_values ) { cv = ml->sml_nvalues; is_norm = 1; } else { cv = ml->sml_values; is_norm = 0; } if ( ad == slap_schema.si_ad_objectClass ) mr = NULL; /* shortcut matching */ else mr = ad->ad_type->sat_equality; /* record indices to preserve input ordering */ ix = slap_sl_malloc( nvals * sizeof(int), ctx ); for (i=0; i<nvals; i++) ix[i] = i; ir = nvals-1; l = 0; jstack = 0; for(;;) { if (ir - l < SMALL) { /* Insertion sort */ match=1; for (j=l+1;j<=ir;j++) { SETA(j); for (i=j-1;i>=0;i--) { COMP(cv[IX(i)], a); if ( match <= 0 ) break; SET(i+1,i); } GETA(i+1); if ( match == 0 ) goto done; } if ( jstack == 0 ) break; if ( match == 0 ) break; ir = istack[jstack--]; l = istack[jstack--]; } else { k = (l + ir) >> 1; /* Choose median of left, center, right */ EXCH(k, l+1); COMP( cv[IX(l)], cv[IX(ir)] ); if ( match > 0 ) { EXCH(l, ir); } else if ( match == 0 ) { i = ir; break; } COMP( cv[IX(l+1)], cv[IX(ir)] ); if ( match > 0 ) { EXCH(l+1, ir); } else if ( match == 0 ) { i = ir; break; } COMP( cv[IX(l)], cv[IX(l+1)] ); if ( match > 0 ) { EXCH(l, l+1); } else if ( match == 0 ) { i = l; break; } i = l+1; j = ir; a = cv[IX(i)]; for(;;) { do { i++; COMP( cv[IX(i)], a ); } while( match < 0 ); while( match > 0 ) { j--; COMP( cv[IX(j)], a ); } if (j < i) { match = 1; break; } if ( match == 0 ) { i = l+1; break; } EXCH(i,j); } if ( match == 0 ) break; EXCH(l+1,j); jstack += 2; if (ir-i+1 >= j) { istack[jstack] = ir; istack[jstack-1] = i; ir = j; } else { istack[jstack] = j; istack[jstack-1] = l; l = i; } } } done: if ( match == 0 && i >= 0 ) *dup = ix[i]; /* For sorted attributes, put the values in index order */ if ( rc == LDAP_SUCCESS && match && ( ad->ad_type->sat_flags & SLAP_AT_SORTED_VAL )) { BerVarray tmpv = slap_sl_malloc( sizeof( struct berval ) * nvals, ctx ); for ( i = 0; i<nvals; i++ ) tmpv[i] = cv[ix[i]]; for ( i = 0; i<nvals; i++ ) cv[i] = tmpv[i]; /* Check if the non-normalized array needs to move too */ if ( is_norm ) { cv = ml->sml_values; for ( i = 0; i<nvals; i++ ) tmpv[i] = cv[ix[i]]; for ( i = 0; i<nvals; i++ ) cv[i] = tmpv[i]; } slap_sl_free( tmpv, ctx ); } slap_sl_free( ix, ctx ); if ( rc == LDAP_SUCCESS && match == 0 ) { /* value exists already */ assert( i >= 0 ); assert( i < nvals ); rc = LDAP_TYPE_OR_VALUE_EXISTS; } ret: return rc; }
/* * meta_back_proxy_authz_cred() * * prepares credentials & method for meta_back_proxy_authz_bind(); * or, if method is SASL, performs the SASL bind directly. */ int meta_back_proxy_authz_cred( metaconn_t *mc, int candidate, Operation *op, SlapReply *rs, ldap_back_send_t sendok, struct berval *binddn, struct berval *bindcred, int *method ) { metainfo_t *mi = (metainfo_t *)op->o_bd->be_private; metatarget_t *mt = mi->mi_targets[ candidate ]; metasingleconn_t *msc = &mc->mc_conns[ candidate ]; struct berval ndn; int dobind = 0; /* don't proxyAuthz if protocol is not LDAPv3 */ switch ( mt->mt_version ) { case LDAP_VERSION3: break; case 0: if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { break; } /* fall thru */ default: rs->sr_err = LDAP_UNWILLING_TO_PERFORM; if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); } LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); goto done; } if ( op->o_tag == LDAP_REQ_BIND ) { ndn = op->o_req_ndn; } else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) { ndn = op->o_conn->c_ndn; } else { ndn = op->o_ndn; } rs->sr_err = LDAP_SUCCESS; /* * FIXME: we need to let clients use proxyAuthz * otherwise we cannot do symmetric pools of servers; * we have to live with the fact that a user can * authorize itself as any ID that is allowed * by the authzTo directive of the "proxyauthzdn". */ /* * NOTE: current Proxy Authorization specification * and implementation do not allow proxy authorization * control to be provided with Bind requests */ /* * if no bind took place yet, but the connection is bound * and the "proxyauthzdn" is set, then bind as * "proxyauthzdn" and explicitly add the proxyAuthz * control to every operation with the dn bound * to the connection as control value. */ /* bind as proxyauthzdn only if no idassert mode * is requested, or if the client's identity * is authorized */ switch ( mt->mt_idassert_mode ) { case LDAP_BACK_IDASSERT_LEGACY: if ( !BER_BVISNULL( &ndn ) && !BER_BVISEMPTY( &ndn ) ) { if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) && !BER_BVISEMPTY( &mt->mt_idassert_authcDN ) ) { *binddn = mt->mt_idassert_authcDN; *bindcred = mt->mt_idassert_passwd; dobind = 1; } } break; default: /* NOTE: rootdn can always idassert */ if ( BER_BVISNULL( &ndn ) && mt->mt_idassert_authz == NULL && !( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) { if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { rs->sr_err = LDAP_INAPPROPRIATE_AUTH; if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); } LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); goto done; } rs->sr_err = LDAP_SUCCESS; *binddn = slap_empty_bv; *bindcred = slap_empty_bv; break; } else if ( mt->mt_idassert_authz && !be_isroot( op ) ) { struct berval authcDN; if ( BER_BVISNULL( &ndn ) ) { authcDN = slap_empty_bv; } else { authcDN = ndn; } rs->sr_err = slap_sasl_matches( op, mt->mt_idassert_authz, &authcDN, &authcDN ); if ( rs->sr_err != LDAP_SUCCESS ) { if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); } LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); goto done; } rs->sr_err = LDAP_SUCCESS; *binddn = slap_empty_bv; *bindcred = slap_empty_bv; break; } } *binddn = mt->mt_idassert_authcDN; *bindcred = mt->mt_idassert_passwd; dobind = 1; break; } if ( dobind && mt->mt_idassert_authmethod == LDAP_AUTH_SASL ) { #ifdef HAVE_CYRUS_SASL void *defaults = NULL; struct berval authzID = BER_BVNULL; int freeauthz = 0; /* if SASL supports native authz, prepare for it */ if ( ( !op->o_do_not_cache || !op->o_is_auth_check ) && ( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) ) { switch ( mt->mt_idassert_mode ) { case LDAP_BACK_IDASSERT_OTHERID: case LDAP_BACK_IDASSERT_OTHERDN: authzID = mt->mt_idassert_authzID; break; case LDAP_BACK_IDASSERT_ANONYMOUS: BER_BVSTR( &authzID, "dn:" ); break; case LDAP_BACK_IDASSERT_SELF: if ( BER_BVISNULL( &ndn ) ) { /* connection is not authc'd, so don't idassert */ BER_BVSTR( &authzID, "dn:" ); break; } authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len; authzID.bv_val = slap_sl_malloc( authzID.bv_len + 1, op->o_tmpmemctx ); memcpy( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ); memcpy( authzID.bv_val + STRLENOF( "dn:" ), ndn.bv_val, ndn.bv_len + 1 ); freeauthz = 1; break; default: break; } } if ( mt->mt_idassert_secprops != NULL ) { rs->sr_err = ldap_set_option( msc->msc_ld, LDAP_OPT_X_SASL_SECPROPS, (void *)mt->mt_idassert_secprops ); if ( rs->sr_err != LDAP_OPT_SUCCESS ) { rs->sr_err = LDAP_OTHER; if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); } LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); goto done; } } defaults = lutil_sasl_defaults( msc->msc_ld, mt->mt_idassert_sasl_mech.bv_val, mt->mt_idassert_sasl_realm.bv_val, mt->mt_idassert_authcID.bv_val, mt->mt_idassert_passwd.bv_val, authzID.bv_val ); if ( defaults == NULL ) { rs->sr_err = LDAP_OTHER; LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); } goto done; } rs->sr_err = ldap_sasl_interactive_bind_s( msc->msc_ld, binddn->bv_val, mt->mt_idassert_sasl_mech.bv_val, NULL, NULL, LDAP_SASL_QUIET, lutil_sasl_interact, defaults ); rs->sr_err = slap_map_api2result( rs ); if ( rs->sr_err != LDAP_SUCCESS ) { LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); } } else { LDAP_BACK_CONN_ISBOUND_SET( msc ); } lutil_sasl_freedefs( defaults ); if ( freeauthz ) { slap_sl_free( authzID.bv_val, op->o_tmpmemctx ); } goto done; #endif /* HAVE_CYRUS_SASL */ } *method = mt->mt_idassert_authmethod; switch ( mt->mt_idassert_authmethod ) { case LDAP_AUTH_NONE: BER_BVSTR( binddn, "" ); BER_BVSTR( bindcred, "" ); /* fallthru */ case LDAP_AUTH_SIMPLE: break; default: /* unsupported! */ LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED; if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); } break; } done:; if ( !BER_BVISEMPTY( binddn ) ) { LDAP_BACK_CONN_ISIDASSERT_SET( msc ); } return rs->sr_err; }
/* * Determine the structural object class from a set of OIDs */ int structural_class( BerVarray ocs, ObjectClass **scp, ObjectClass ***socsp, const char **text, char *textbuf, size_t textlen, void *ctx ) { int i, nocs; ObjectClass *oc, **socs; ObjectClass *sc = NULL; int scn = -1; *text = "structural_class: internal error"; /* count them */ for( i=0; ocs[i].bv_val; i++ ) ; nocs = i; socs = slap_sl_malloc( (nocs+1) * sizeof(ObjectClass *), ctx ); for( i=0; ocs[i].bv_val; i++ ) { socs[i] = oc_bvfind( &ocs[i] ); if( socs[i] == NULL ) { snprintf( textbuf, textlen, "unrecognized objectClass '%s'", ocs[i].bv_val ); *text = textbuf; goto fail; } } socs[i] = NULL; for( i=0; ocs[i].bv_val; i++ ) { oc = socs[i]; if( oc->soc_kind == LDAP_SCHEMA_STRUCTURAL ) { if( sc == NULL || is_object_subclass( sc, oc ) ) { sc = oc; scn = i; } else if ( !is_object_subclass( oc, sc ) ) { int j; ObjectClass *xc = NULL; /* find common superior */ for( j=i+1; ocs[j].bv_val; j++ ) { xc = socs[j]; if( xc == NULL ) { snprintf( textbuf, textlen, "unrecognized objectClass '%s'", ocs[j].bv_val ); *text = textbuf; goto fail; } if( xc->soc_kind != LDAP_SCHEMA_STRUCTURAL ) { xc = NULL; continue; } if( is_object_subclass( sc, xc ) && is_object_subclass( oc, xc ) ) { /* found common subclass */ break; } xc = NULL; } if( xc == NULL ) { /* no common subclass */ snprintf( textbuf, textlen, "invalid structural object class chain (%s/%s)", ocs[scn].bv_val, ocs[i].bv_val ); *text = textbuf; goto fail; } } } } if( scp ) { *scp = sc; } if( sc == NULL ) { *text = "no structural object class provided"; goto fail; } if( scn < 0 ) { *text = "invalid structural object class"; goto fail; } if ( socsp ) { *socsp = socs; } else { slap_sl_free( socs, ctx ); } *text = NULL; return LDAP_SUCCESS; fail: slap_sl_free( socs, ctx ); return LDAP_OBJECT_CLASS_VIOLATION; }
static int objectSubClassIndexer( slap_mask_t use, slap_mask_t mask, Syntax *syntax, MatchingRule *mr, struct berval *prefix, BerVarray values, BerVarray *keysp, void *ctx ) { int rc, noc, i; BerVarray ocvalues; ObjectClass **socs; for( noc=0; values[noc].bv_val != NULL; noc++ ) { /* just count em */; } /* over allocate */ socs = slap_sl_malloc( (noc+16) * sizeof( ObjectClass * ), ctx ); /* initialize */ for( i=0; i<noc; i++ ) { socs[i] = oc_bvfind( &values[i] ); } /* expand values */ for( i=0; i<noc; i++ ) { int j; ObjectClass *oc = socs[i]; if( oc == NULL || oc->soc_sups == NULL ) continue; for( j=0; oc->soc_sups[j] != NULL; j++ ) { int found = 0; ObjectClass *sup = oc->soc_sups[j]; int k; for( k=0; k<noc; k++ ) { if( sup == socs[k] ) { found++; break; } } if( !found ) { socs = slap_sl_realloc( socs, sizeof( ObjectClass * ) * (noc+2), ctx ); assert( k == noc ); socs[noc++] = sup; } } } ocvalues = slap_sl_malloc( sizeof( struct berval ) * (noc+1), ctx ); /* copy values */ for( i=0; i<noc; i++ ) { if ( socs[i] ) ocvalues[i] = socs[i]->soc_cname; else ocvalues[i] = values[i]; } BER_BVZERO( &ocvalues[i] ); rc = octetStringIndexer( use, mask, syntax, mr, prefix, ocvalues, keysp, ctx ); slap_sl_free( ocvalues, ctx ); slap_sl_free( socs, ctx ); return rc; }