/* * 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( struct berval *dn, struct berval *pdn ) { char *p; p = ber_bvchr( dn, ',' ); /* one-level dn */ if ( p == NULL ) { pdn->bv_val = dn->bv_val + dn->bv_len; pdn->bv_len = 0; return; } assert( DN_SEPARATOR( p[ 0 ] ) ); p++; assert( ATTR_LEADCHAR( p[ 0 ] ) ); pdn->bv_len = dn->bv_len - (p - dn->bv_val); pdn->bv_val = p; return; }
/* * We can assume the input is a prettied or normalized DN */ ber_len_t dn_rdnlen( Backend *be, struct berval *dn_in ) { const char *p; assert( dn_in != NULL ); if ( dn_in == NULL ) { return 0; } if ( !dn_in->bv_len ) { return 0; } if ( be != NULL && be_issuffix( be, dn_in ) ) { return 0; } p = ber_bvchr( dn_in, ',' ); return p ? (ber_len_t) (p - dn_in->bv_val) : dn_in->bv_len; }
/* rdnValidate: * * LDAP_SUCCESS if rdn is a legal rdn; * LDAP_INVALID_SYNTAX otherwise (including a sequence of rdns) */ int rdn_validate( struct berval *rdn ) { #if 1 /* Major cheat! * input is a pretty or normalized DN * hence, we can just search for ',' */ if( rdn == NULL || rdn->bv_len == 0 || rdn->bv_len > SLAP_LDAPDN_MAXLEN ) { return LDAP_INVALID_SYNTAX; } return ber_bvchr( rdn, ',' ) == NULL ? LDAP_SUCCESS : LDAP_INVALID_SYNTAX; #else LDAPRDN *RDN, **DN[ 2 ] = { &RDN, NULL }; const char *p; int rc; /* * must be non-empty */ if ( rdn == NULL || rdn == '\0' ) { return 0; } /* * must be parsable */ rc = ldap_bv2rdn( rdn, &RDN, (char **)&p, LDAP_DN_FORMAT_LDAP ); if ( rc != LDAP_SUCCESS ) { return 0; } /* * Must be one-level */ if ( p[ 0 ] != '\0' ) { return 0; } /* * Schema-aware validate */ if ( rc == LDAP_SUCCESS ) { rc = LDAPDN_validate( DN ); } ldap_rdnfree( RDN ); /* * Must validate (there's a repeated parsing ...) */ return ( rc == LDAP_SUCCESS ); #endif }
static int valsort_modify( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; valsort_info *vi = on->on_bi.bi_private; Modifications *ml; int i; char *ptr, *end; /* See if any weighted sorting applies to this entry */ for ( ;vi;vi=vi->vi_next ) { if ( !dnIsSuffix( &op->o_req_ndn, &vi->vi_dn )) continue; if ( !(vi->vi_sort & VALSORT_WEIGHTED )) continue; for (ml = op->orm_modlist; ml; ml=ml->sml_next ) { /* Must be a Delete Attr op, so no values to consider */ if ( !ml->sml_values ) continue; if ( ml->sml_desc == vi->vi_ad ) break; } if ( !ml ) continue; for (i=0; !BER_BVISNULL( &ml->sml_values[i] ); i++) { ptr = ber_bvchr(&ml->sml_values[i], '{' ); if ( !ptr ) { Debug(LDAP_DEBUG_TRACE, "weight missing from attribute %s\n", vi->vi_ad->ad_cname.bv_val, 0, 0); send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION, "weight missing from attribute" ); return rs->sr_err; } strtol( ptr+1, &end, 0 ); if ( *end != '}' ) { Debug(LDAP_DEBUG_TRACE, "weight is misformatted in %s\n", vi->vi_ad->ad_cname.bv_val, 0, 0); send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION, "weight is misformatted" ); return rs->sr_err; } } } return SLAP_CB_CONTINUE; }
/* * 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 = ber_bvchr( dn, ',' ); /* 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; }
static int valsort_add( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; valsort_info *vi = on->on_bi.bi_private; Attribute *a; int i; char *ptr, *end; /* See if any weighted sorting applies to this entry */ for ( ;vi;vi=vi->vi_next ) { if ( !dnIsSuffix( &op->o_req_ndn, &vi->vi_dn )) continue; if ( !(vi->vi_sort & VALSORT_WEIGHTED )) continue; a = attr_find( op->ora_e->e_attrs, vi->vi_ad ); if ( !a ) continue; for (i=0; !BER_BVISNULL( &a->a_vals[i] ); i++) { ptr = ber_bvchr(&a->a_vals[i], '{' ); if ( !ptr ) { Debug(LDAP_DEBUG_TRACE, "weight missing from attribute %s\n", vi->vi_ad->ad_cname.bv_val, 0, 0); send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION, "weight missing from attribute" ); return rs->sr_err; } strtol( ptr+1, &end, 0 ); if ( *end != '}' ) { Debug(LDAP_DEBUG_TRACE, "weight is misformatted in %s\n", vi->vi_ad->ad_cname.bv_val, 0, 0); send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION, "weight is misformatted" ); return rs->sr_err; } } } return SLAP_CB_CONTINUE; }
/* Find the given attribute's value in the RDN of the DN */ int nssov_find_rdnval(struct berval *dn, AttributeDescription *ad, struct berval *value) { struct berval rdn; char *next; BER_BVZERO(value); dnRdn( dn, &rdn ); do { next = ber_bvchr( &rdn, '+' ); if ( rdn.bv_val[ad->ad_cname.bv_len] == '=' && !ber_bvcmp( &rdn, &ad->ad_cname )) { if ( next ) rdn.bv_len = next - rdn.bv_val; value->bv_val = rdn.bv_val + ad->ad_cname.bv_len + 1; value->bv_len = rdn.bv_len - ad->ad_cname.bv_len - 1; break; } if ( !next ) break; next++; rdn.bv_len -= next - rdn.bv_val; rdn.bv_val = next; } while (1); }
static int OpenLDAPaciPrettyNormal( struct berval *val, struct berval *out, void *ctx, int normalize ) { struct berval oid = BER_BVNULL, scope = BER_BVNULL, rights = BER_BVNULL, nrights = BER_BVNULL, type = BER_BVNULL, ntype = BER_BVNULL, subject = BER_BVNULL, nsubject = BER_BVNULL; int idx, rc = LDAP_SUCCESS, freesubject = 0, freetype = 0; char *ptr; BER_BVZERO( out ); if ( BER_BVISEMPTY( val ) ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: value is empty\n" ); return LDAP_INVALID_SYNTAX; } /* oid: if valid, it's already normalized */ if ( acl_get_part( val, 0, '#', &oid ) < 0 || numericoidValidate( NULL, &oid ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid oid '%s'\n", oid.bv_val ); return LDAP_INVALID_SYNTAX; } /* scope: normalize by replacing with OpenLDAPaciscopes */ if ( acl_get_part( val, 1, '#', &scope ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing scope in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &scope, OpenLDAPaciscopes ); if ( idx == -1 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid scope '%s'\n", scope.bv_val ); return LDAP_INVALID_SYNTAX; } scope = *OpenLDAPaciscopes[ idx ]; /* rights */ if ( acl_get_part( val, 2, '#', &rights ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing rights in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } if ( OpenLDAPaciNormalizeRights( &rights, &nrights, ctx ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } /* type */ if ( acl_get_part( val, 3, '#', &type ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing type in '%s'\n", val->bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } idx = bv_getcaseidx( &type, OpenLDAPacitypes ); if ( idx == -1 ) { struct berval isgr; if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", type.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } idx = bv_getcaseidx( &isgr, OpenLDAPacitypes ); if ( idx == -1 || idx >= LAST_OPTIONAL ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid type '%s'\n", isgr.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } } ntype = *OpenLDAPacitypes[ idx ]; /* subject */ bv_get_tail( val, &type, &subject ); if ( BER_BVISEMPTY( &subject ) || subject.bv_val[ 0 ] != '#' ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: missing subject in '%s'\n", val->bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } subject.bv_val++; subject.bv_len--; if ( idx < LAST_DNVALUED ) { /* FIXME: pass DN syntax? */ if ( normalize ) { rc = dnNormalize( 0, NULL, NULL, &subject, &nsubject, ctx ); } else { rc = dnPretty( NULL, &subject, &nsubject, ctx ); } if ( rc == LDAP_SUCCESS ) { freesubject = 1; } else { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid subject dn '%s'\n", subject.bv_val ); goto cleanup; } if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] ) { /* do {group|role}/oc/at check */ struct berval ocbv = BER_BVNULL, atbv = BER_BVNULL; ocbv.bv_val = ber_bvchr( &type, '/' ); if ( ocbv.bv_val != NULL ) { ObjectClass *oc = NULL; AttributeDescription *ad = NULL; const char *text = NULL; int rc; struct berval bv; bv.bv_len = ntype.bv_len; ocbv.bv_val++; ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val ); atbv.bv_val = ber_bvchr( &ocbv, '/' ); if ( atbv.bv_val != NULL ) { atbv.bv_val++; atbv.bv_len = type.bv_len - ( atbv.bv_val - type.bv_val ); ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1; rc = slap_bv2ad( &atbv, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown group attribute '%s'\n", atbv.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } bv.bv_len += STRLENOF( "/" ) + ad->ad_cname.bv_len; } oc = oc_bvfind( &ocbv ); if ( oc == NULL ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: invalid group '%s'\n", ocbv.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } bv.bv_len += STRLENOF( "/" ) + oc->soc_cname.bv_len; bv.bv_val = ber_memalloc_x( bv.bv_len + 1, ctx ); ptr = bv.bv_val; ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len ); ptr[ 0 ] = '/'; ptr++; ptr = lutil_strncopy( ptr, oc->soc_cname.bv_val, oc->soc_cname.bv_len ); if ( ad != NULL ) { ptr[ 0 ] = '/'; ptr++; ptr = lutil_strncopy( ptr, ad->ad_cname.bv_val, ad->ad_cname.bv_len ); } ptr[ 0 ] = '\0'; ntype = bv; freetype = 1; } } } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) { AttributeDescription *ad = NULL; const char *text = NULL; int rc; rc = slap_bv2ad( &subject, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: unknown dn attribute '%s'\n", subject.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) { /* FIXME: allow nameAndOptionalUID? */ Debug( LDAP_DEBUG_ACL, "aciPrettyNormal: wrong syntax for dn attribute '%s'\n", subject.bv_val ); rc = LDAP_INVALID_SYNTAX; goto cleanup; } nsubject = ad->ad_cname; } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_SET_REF ] ) { /* NOTE: dunno how to normalize it... */ nsubject = subject; } out->bv_len = oid.bv_len + STRLENOF( "#" ) + scope.bv_len + STRLENOF( "#" ) + nrights.bv_len + STRLENOF( "#" ) + ntype.bv_len + STRLENOF( "#" ) + nsubject.bv_len; out->bv_val = ber_memalloc_x( out->bv_len + 1, ctx ); ptr = lutil_strncopy( out->bv_val, oid.bv_val, oid.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, scope.bv_val, scope.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, nrights.bv_val, nrights.bv_len ); ptr[ 0 ] = '#'; ptr++; ptr = lutil_strncopy( ptr, ntype.bv_val, ntype.bv_len ); ptr[ 0 ] = '#'; ptr++; if ( !BER_BVISNULL( &nsubject ) ) { ptr = lutil_strncopy( ptr, nsubject.bv_val, nsubject.bv_len ); } ptr[ 0 ] = '\0'; cleanup:; if ( freesubject ) { ber_memfree_x( nsubject.bv_val, ctx ); } if ( freetype ) { ber_memfree_x( ntype.bv_val, ctx ); } if ( !BER_BVISNULL( &nrights ) ) { ber_memfree_x( nrights.bv_val, ctx ); } return rc; }
static int OpenLDAPaciValidate( Syntax *syntax, struct berval *val ) { struct berval oid = BER_BVNULL, scope = BER_BVNULL, rights = BER_BVNULL, type = BER_BVNULL, subject = BER_BVNULL; int idx; int rc; if ( BER_BVISEMPTY( val ) ) { Debug( LDAP_DEBUG_ACL, "aciValidatet: value is empty\n" ); return LDAP_INVALID_SYNTAX; } /* oid */ if ( acl_get_part( val, 0, '#', &oid ) < 0 || numericoidValidate( NULL, &oid ) != LDAP_SUCCESS ) { /* NOTE: the numericoidValidate() is rather pedantic; * I'd replace it with X-ORDERED VALUES so that * it's guaranteed values are maintained and used * in the desired order */ Debug( LDAP_DEBUG_ACL, "aciValidate: invalid oid '%s'\n", oid.bv_val ); return LDAP_INVALID_SYNTAX; } /* scope */ if ( acl_get_part( val, 1, '#', &scope ) < 0 || bv_getcaseidx( &scope, OpenLDAPaciscopes ) == -1 ) { Debug( LDAP_DEBUG_ACL, "aciValidate: invalid scope '%s'\n", scope.bv_val ); return LDAP_INVALID_SYNTAX; } /* rights */ if ( acl_get_part( val, 2, '#', &rights ) < 0 || OpenLDAPaciValidateRights( &rights ) != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } /* type */ if ( acl_get_part( val, 3, '#', &type ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciValidate: missing type in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &type, OpenLDAPacitypes ); if ( idx == -1 ) { struct berval isgr; if ( acl_get_part( &type, 0, '/', &isgr ) < 0 ) { Debug( LDAP_DEBUG_ACL, "aciValidate: invalid type '%s'\n", type.bv_val ); return LDAP_INVALID_SYNTAX; } idx = bv_getcaseidx( &isgr, OpenLDAPacitypes ); if ( idx == -1 || idx >= LAST_OPTIONAL ) { Debug( LDAP_DEBUG_ACL, "aciValidate: invalid type '%s'\n", isgr.bv_val ); return LDAP_INVALID_SYNTAX; } } /* subject */ bv_get_tail( val, &type, &subject ); if ( subject.bv_val[ 0 ] != '#' ) { Debug( LDAP_DEBUG_ACL, "aciValidate: missing subject in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } if ( idx >= LAST_DNVALUED ) { if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_DNATTR ] ) { AttributeDescription *ad = NULL; const char *text = NULL; rc = slap_bv2ad( &subject, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciValidate: unknown dn attribute '%s'\n", subject.bv_val ); return LDAP_INVALID_SYNTAX; } if ( ad->ad_type->sat_syntax != slap_schema.si_syn_distinguishedName ) { /* FIXME: allow nameAndOptionalUID? */ Debug( LDAP_DEBUG_ACL, "aciValidate: wrong syntax for dn attribute '%s'\n", subject.bv_val ); return LDAP_INVALID_SYNTAX; } } /* not a DN */ return LDAP_SUCCESS; } else if ( OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_GROUP ] || OpenLDAPacitypes[ idx ] == &aci_bv[ ACI_BV_ROLE ] ) { /* do {group|role}/oc/at check */ struct berval ocbv = BER_BVNULL, atbv = BER_BVNULL; ocbv.bv_val = ber_bvchr( &type, '/' ); if ( ocbv.bv_val != NULL ) { ocbv.bv_val++; ocbv.bv_len = type.bv_len - ( ocbv.bv_val - type.bv_val ); atbv.bv_val = ber_bvchr( &ocbv, '/' ); if ( atbv.bv_val != NULL ) { AttributeDescription *ad = NULL; const char *text = NULL; int rc; atbv.bv_val++; atbv.bv_len = type.bv_len - ( atbv.bv_val - type.bv_val ); ocbv.bv_len = atbv.bv_val - ocbv.bv_val - 1; rc = slap_bv2ad( &atbv, &ad, &text ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciValidate: unknown group attribute '%s'\n", atbv.bv_val ); return LDAP_INVALID_SYNTAX; } } if ( oc_bvfind( &ocbv ) == NULL ) { Debug( LDAP_DEBUG_ACL, "aciValidate: unknown group '%s'\n", ocbv.bv_val ); return LDAP_INVALID_SYNTAX; } } } if ( BER_BVISEMPTY( &subject ) ) { /* empty DN invalid */ Debug( LDAP_DEBUG_ACL, "aciValidate: missing dn in '%s'\n", val->bv_val ); return LDAP_INVALID_SYNTAX; } subject.bv_val++; subject.bv_len--; /* FIXME: pass DN syntax? */ rc = dnValidate( NULL, &subject ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ACL, "aciValidate: invalid dn '%s'\n", subject.bv_val ); } return rc; }
static int do_base( char *uri, char *dn, struct berval *pass, char *base, char *filter, char *pwattr, int maxloop, int force, int chaserefs, int noinit, int delay, int action_type, void *action ) { LDAP *ld = NULL; int i = 0; int rc = LDAP_SUCCESS; ber_int_t msgid; LDAPMessage *res, *msg; char **dns = NULL; struct berval *creds = NULL; char *attrs[] = { LDAP_NO_ATTRS, NULL }; int ndns = 0; #ifdef _WIN32 DWORD beg, end; #else struct timeval beg, end; #endif int version = LDAP_VERSION3; char *nullstr = ""; ldap_initialize( &ld, uri ); if ( ld == NULL ) { tester_perror( "ldap_initialize", NULL ); exit( EXIT_FAILURE ); } (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); (void) ldap_set_option( ld, LDAP_OPT_REFERRALS, chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF ); rc = ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, pass, NULL, NULL, NULL ); if ( rc != LDAP_SUCCESS ) { tester_ldap_error( ld, "ldap_sasl_bind_s", NULL ); exit( EXIT_FAILURE ); } fprintf( stderr, "PID=%ld - Bind(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n", (long) pid, maxloop, base, filter, pwattr ); if ( pwattr != NULL ) { attrs[ 0 ] = pwattr; } rc = ldap_search_ext( ld, base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, 0, 0, &msgid ); if ( rc != LDAP_SUCCESS ) { tester_ldap_error( ld, "ldap_search_ext", NULL ); exit( EXIT_FAILURE ); } while ( ( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res ) ) > 0 ) { BerElement *ber; struct berval bv; int done = 0; for ( msg = ldap_first_message( ld, res ); msg; msg = ldap_next_message( ld, msg ) ) { switch ( ldap_msgtype( msg ) ) { case LDAP_RES_SEARCH_ENTRY: rc = ldap_get_dn_ber( ld, msg, &ber, &bv ); dns = realloc( dns, (ndns + 1)*sizeof(char *) ); dns[ndns] = ber_strdup( bv.bv_val ); if ( pwattr != NULL ) { struct berval **values = ldap_get_values_len( ld, msg, pwattr ); creds = realloc( creds, (ndns + 1)*sizeof(struct berval) ); if ( values == NULL ) { novals:; creds[ndns].bv_len = 0; creds[ndns].bv_val = nullstr; } else { static struct berval cleartext = BER_BVC( "{CLEARTEXT} " ); struct berval value = *values[ 0 ]; if ( value.bv_val[ 0 ] == '{' ) { char *end = ber_bvchr( &value, '}' ); if ( end ) { if ( ber_bvcmp( &value, &cleartext ) == 0 ) { value.bv_val += cleartext.bv_len; value.bv_len -= cleartext.bv_len; } else { ldap_value_free_len( values ); goto novals; } } } ber_dupbv( &creds[ndns], &value ); ldap_value_free_len( values ); } } ndns++; ber_free( ber, 0 ); break; case LDAP_RES_SEARCH_RESULT: done = 1; break; } if ( done ) break; } ldap_msgfree( res ); if ( done ) break; } #ifdef _WIN32 beg = GetTickCount(); #else gettimeofday( &beg, NULL ); #endif if ( ndns == 0 ) { tester_error( "No DNs" ); return 1; } fprintf( stderr, " PID=%ld - Bind base=\"%s\" filter=\"%s\" got %d values.\n", (long) pid, base, filter, ndns ); /* Ok, got list of DNs, now start binding to each */ for ( i = 0; i < maxloop; i++ ) { int j; struct berval cred = { 0, NULL }; #if 0 /* use high-order bits for better randomness (Numerical Recipes in "C") */ j = rand() % ndns; #endif j = ((double)ndns)*rand()/(RAND_MAX + 1.0); if ( creds && !BER_BVISEMPTY( &creds[j] ) ) { cred = creds[j]; } if ( do_bind( uri, dns[j], &cred, 1, force, chaserefs, noinit, &ld, action_type, action ) && !force ) { break; } if ( delay ) { sleep( delay ); } } if ( ld != NULL ) { ldap_unbind_ext( ld, NULL, NULL ); ld = NULL; } #ifdef _WIN32 end = GetTickCount(); end -= beg; fprintf( stderr, " PID=%ld - Bind done %d in %d.%03d seconds.\n", (long) pid, i, end / 1000, end % 1000 ); #else gettimeofday( &end, NULL ); end.tv_usec -= beg.tv_usec; if (end.tv_usec < 0 ) { end.tv_usec += 1000000; end.tv_sec -= 1; } end.tv_sec -= beg.tv_sec; fprintf( stderr, " PID=%ld - Bind done %d in %ld.%06ld seconds.\n", (long) pid, i, (long) end.tv_sec, (long) end.tv_usec ); #endif if ( dns ) { for ( i = 0; i < ndns; i++ ) { ber_memfree( dns[i] ); } free( dns ); } if ( creds ) { for ( i = 0; i < ndns; i++ ) { if ( creds[i].bv_val != nullstr ) { ber_memfree( creds[i].bv_val ); } } free( creds ); } return 0; }
static int pw2entry( Backend *be, struct passwd *pw, Entry *e ) { size_t pwlen; struct berval val; struct berval bv; int rc; /* * from pw we get pw_name and make it cn * give it an objectclass of person. */ pwlen = strlen( pw->pw_name ); val.bv_len = STRLENOF("uid=,") + ( pwlen + be->be_suffix[0].bv_len ); val.bv_val = ch_malloc( val.bv_len + 1 ); /* rdn attribute type should be a configuratable item */ sprintf( val.bv_val, "uid=%s,%s", pw->pw_name, be->be_suffix[0].bv_val ); rc = dnNormalize( 0, NULL, NULL, &val, &bv, NULL ); if( rc != LDAP_SUCCESS ) { free( val.bv_val ); return( -1 ); } e->e_name = val; e->e_nname = bv; e->e_attrs = NULL; /* objectclasses should be configurable items */ BER_BVSTR( &val, "person" ); attr_merge_one( e, slap_schema.si_ad_objectClass, &val, NULL ); BER_BVSTR( &val, "uidObject" ); attr_merge_one( e, slap_schema.si_ad_objectClass, &val, NULL ); val.bv_val = pw->pw_name; val.bv_len = pwlen; attr_merge_normalize_one( e, slap_schema.si_ad_uid, &val, NULL ); /* required by uidObject */ attr_merge_normalize_one( e, slap_schema.si_ad_cn, &val, NULL ); /* required by person */ attr_merge_normalize_one( e, ad_sn, &val, NULL ); /* required by person */ #ifdef HAVE_STRUCT_PASSWD_PW_GECOS /* * if gecos is present, add it as a cn. first process it * according to standard BSD usage. If the processed cn has * a space, use the tail as the surname. */ if (pw->pw_gecos[0]) { char *s; ber_str2bv( pw->pw_gecos, 0, 0, &val ); attr_merge_normalize_one( e, ad_desc, &val, NULL ); s = ber_bvchr( &val, ',' ); if ( s ) *s = '\0'; s = ber_bvchr( &val, '&' ); if ( s ) { char buf[1024]; if( val.bv_len + pwlen < sizeof(buf) ) { int i = s - val.bv_val; strncpy( buf, val.bv_val, i ); s = buf + i; strcpy( s, pw->pw_name ); *s = TOUPPER((unsigned char)*s); strcat( s, val.bv_val + i + 1 ); val.bv_val = buf; } } val.bv_len = strlen( val.bv_val ); if ( val.bv_len && strcasecmp( val.bv_val, pw->pw_name ) ) { attr_merge_normalize_one( e, slap_schema.si_ad_cn, &val, NULL ); } if ( ( s = strrchr(val.bv_val, ' ' ) ) ) { ber_str2bv( s + 1, 0, 0, &val ); attr_merge_normalize_one( e, ad_sn, &val, NULL ); } } #endif /* HAVE_STRUCT_PASSWD_PW_GECOS */ return( 0 ); }
int schema_info( Entry **entry, const char **text ) { AttributeDescription *ad_structuralObjectClass = slap_schema.si_ad_structuralObjectClass; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; AttributeDescription *ad_createTimestamp = slap_schema.si_ad_createTimestamp; AttributeDescription *ad_modifyTimestamp = slap_schema.si_ad_modifyTimestamp; Entry *e; struct berval vals[5]; struct berval nvals[5]; e = entry_alloc(); if( e == NULL ) { /* Out of memory, do something about it */ Debug( LDAP_DEBUG_ANY, "schema_info: entry_alloc failed - out of memory.\n", 0, 0, 0 ); *text = "out of memory"; return LDAP_OTHER; } e->e_attrs = NULL; /* backend-specific schema info should be created by the * backend itself */ ber_dupbv( &e->e_name, &frontendDB->be_schemadn ); ber_dupbv( &e->e_nname, &frontendDB->be_schemandn ); e->e_private = NULL; BER_BVSTR( &vals[0], "subentry" ); if( attr_merge_one( e, ad_structuralObjectClass, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } BER_BVSTR( &vals[0], "top" ); BER_BVSTR( &vals[1], "subentry" ); BER_BVSTR( &vals[2], "subschema" ); BER_BVSTR( &vals[3], "extensibleObject" ); BER_BVZERO( &vals[4] ); if ( attr_merge( e, ad_objectClass, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } { int rc; AttributeDescription *desc = NULL; struct berval rdn = frontendDB->be_schemadn; vals[0].bv_val = ber_bvchr( &rdn, '=' ); if( vals[0].bv_val == NULL ) { *text = "improperly configured subschema subentry"; return LDAP_OTHER; } vals[0].bv_val++; vals[0].bv_len = rdn.bv_len - (vals[0].bv_val - rdn.bv_val); rdn.bv_len -= vals[0].bv_len + 1; rc = slap_bv2ad( &rdn, &desc, text ); if( rc != LDAP_SUCCESS ) { entry_free( e ); *text = "improperly configured subschema subentry"; return LDAP_OTHER; } nvals[0].bv_val = ber_bvchr( &frontendDB->be_schemandn, '=' ); assert( nvals[0].bv_val != NULL ); nvals[0].bv_val++; nvals[0].bv_len = frontendDB->be_schemandn.bv_len - (nvals[0].bv_val - frontendDB->be_schemandn.bv_val); if ( attr_merge_one( e, desc, vals, nvals ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } } { char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; /* * According to RFC 4512: Servers SHOULD maintain the 'creatorsName', 'createTimestamp', 'modifiersName', and 'modifyTimestamp' attributes for all entries of the DIT. * to be conservative, we declare schema created * AND modified at server startup time ... */ vals[0].bv_val = timebuf; vals[0].bv_len = sizeof( timebuf ); slap_timestamp( &starttime, vals ); if( attr_merge_one( e, ad_createTimestamp, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } if( attr_merge_one( e, ad_modifyTimestamp, vals, NULL ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } } if ( syn_schema_info( e ) || mr_schema_info( e ) || mru_schema_info( e ) || at_schema_info( e ) || oc_schema_info( e ) || cr_schema_info( e ) ) { /* Out of memory, do something about it */ entry_free( e ); *text = "out of memory"; return LDAP_OTHER; } *entry = e; return LDAP_SUCCESS; }
/* Called for all modify and modrdn ops. If the current op was replicated * from elsewhere, all of the attrs should already be present. */ void slap_mods_opattrs( Operation *op, Modifications **modsp, int manage_ctxcsn ) { struct berval name, timestamp, csn = BER_BVNULL; struct berval nname; char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; char csnbuf[ LDAP_PVT_CSNSTR_BUFSIZE ]; Modifications *mod, **modtail, *modlast; int gotcsn = 0, gotmname = 0, gotmtime = 0; if ( SLAP_LASTMOD( op->o_bd ) && !op->orm_no_opattrs ) { char *ptr; timestamp.bv_val = timebuf; for ( modtail = modsp; *modtail; modtail = &(*modtail)->sml_next ) { if ( (*modtail)->sml_op != LDAP_MOD_ADD && (*modtail)->sml_op != SLAP_MOD_SOFTADD && (*modtail)->sml_op != SLAP_MOD_ADD_IF_NOT_PRESENT && (*modtail)->sml_op != LDAP_MOD_REPLACE ) { continue; } if ( (*modtail)->sml_desc == slap_schema.si_ad_entryCSN ) { csn = (*modtail)->sml_values[0]; gotcsn = 1; } else if ( (*modtail)->sml_desc == slap_schema.si_ad_modifiersName ) { gotmname = 1; } else if ( (*modtail)->sml_desc == slap_schema.si_ad_modifyTimestamp ) { gotmtime = 1; } } if ( BER_BVISEMPTY( &op->o_csn )) { if ( !gotcsn ) { csn.bv_val = csnbuf; csn.bv_len = sizeof( csnbuf ); slap_get_csn( op, &csn, manage_ctxcsn ); } else { if ( manage_ctxcsn ) { slap_queue_csn( op, &csn ); } } } else { csn = op->o_csn; } ptr = ber_bvchr( &csn, '#' ); if ( ptr ) { timestamp.bv_len = STRLENOF("YYYYMMDDHHMMSSZ"); AC_MEMCPY( timebuf, csn.bv_val, timestamp.bv_len ); timebuf[timestamp.bv_len-1] = 'Z'; timebuf[timestamp.bv_len] = '\0'; } else { time_t now = slap_get_time(); timestamp.bv_len = sizeof(timebuf); slap_timestamp( &now, ×tamp ); } if ( BER_BVISEMPTY( &op->o_dn ) ) { BER_BVSTR( &name, SLAPD_ANONYMOUS ); nname = name; } else { name = op->o_dn; nname = op->o_ndn; } if ( !gotcsn ) { mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); mod->sml_op = LDAP_MOD_REPLACE; mod->sml_flags = SLAP_MOD_INTERNAL; mod->sml_next = NULL; BER_BVZERO( &mod->sml_type ); mod->sml_desc = slap_schema.si_ad_entryCSN; mod->sml_numvals = 1; mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); ber_dupbv( &mod->sml_values[0], &csn ); BER_BVZERO( &mod->sml_values[1] ); assert( !BER_BVISNULL( &mod->sml_values[0] ) ); mod->sml_nvalues = NULL; *modtail = mod; modlast = mod; modtail = &mod->sml_next; } if ( !gotmname ) { mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); mod->sml_op = LDAP_MOD_REPLACE; mod->sml_flags = SLAP_MOD_INTERNAL; mod->sml_next = NULL; BER_BVZERO( &mod->sml_type ); mod->sml_desc = slap_schema.si_ad_modifiersName; mod->sml_numvals = 1; mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); ber_dupbv( &mod->sml_values[0], &name ); BER_BVZERO( &mod->sml_values[1] ); assert( !BER_BVISNULL( &mod->sml_values[0] ) ); mod->sml_nvalues = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); ber_dupbv( &mod->sml_nvalues[0], &nname ); BER_BVZERO( &mod->sml_nvalues[1] ); assert( !BER_BVISNULL( &mod->sml_nvalues[0] ) ); *modtail = mod; modtail = &mod->sml_next; } if ( !gotmtime ) { mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); mod->sml_op = LDAP_MOD_REPLACE; mod->sml_flags = SLAP_MOD_INTERNAL; mod->sml_next = NULL; BER_BVZERO( &mod->sml_type ); mod->sml_desc = slap_schema.si_ad_modifyTimestamp; mod->sml_numvals = 1; mod->sml_values = (BerVarray) ch_malloc( 2 * sizeof( struct berval ) ); ber_dupbv( &mod->sml_values[0], ×tamp ); BER_BVZERO( &mod->sml_values[1] ); assert( !BER_BVISNULL( &mod->sml_values[0] ) ); mod->sml_nvalues = NULL; *modtail = mod; modtail = &mod->sml_next; } } }
static int valsort_response( Operation *op, SlapReply *rs ) { slap_overinst *on; valsort_info *vi; Attribute *a; /* If this is not a search response, or it is a syncrepl response, * or the valsort control wants raw results, pass thru unmodified. */ if ( rs->sr_type != REP_SEARCH || ( _SCM(op->o_sync) > SLAP_CONTROL_IGNORED ) || ( op->o_ctrlflag[valsort_cid] & SLAP_CONTROL_DATA0)) return SLAP_CB_CONTINUE; on = (slap_overinst *) op->o_bd->bd_info; vi = on->on_bi.bi_private; /* And we must have something configured */ if ( !vi ) return SLAP_CB_CONTINUE; /* Find a rule whose baseDN matches this entry */ for (; vi; vi = vi->vi_next ) { int i, n; if ( !dnIsSuffix( &rs->sr_entry->e_nname, &vi->vi_dn )) continue; /* Find attr that this rule affects */ a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad ); if ( !a ) continue; if (( rs->sr_flags & ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) ) != ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) ) { Entry *e; e = entry_dup( rs->sr_entry ); if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { overlay_entry_release_ov( op, rs->sr_entry, 0, on ); rs->sr_flags &= ~REP_ENTRY_MUSTRELEASE; } else if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { entry_free( rs->sr_entry ); } rs->sr_entry = e; rs->sr_flags |= REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED; a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad ); } n = a->a_numvals; if ( vi->vi_sort & VALSORT_WEIGHTED ) { int j, gotnvals; long *index = op->o_tmpalloc( n * sizeof(long), op->o_tmpmemctx ); gotnvals = (a->a_vals != a->a_nvals ); for (i=0; i<n; i++) { char *ptr = ber_bvchr( &a->a_nvals[i], '{' ); char *end = NULL; if ( !ptr ) { Debug(LDAP_DEBUG_TRACE, "weights missing from attr %s " "in entry %s\n", vi->vi_ad->ad_cname.bv_val, rs->sr_entry->e_name.bv_val, 0 ); break; } index[i] = strtol( ptr+1, &end, 0 ); if ( *end != '}' ) { Debug(LDAP_DEBUG_TRACE, "weights misformatted " "in entry %s\n", rs->sr_entry->e_name.bv_val, 0, 0 ); break; } /* Strip out weights */ ptr = a->a_nvals[i].bv_val; end++; for (;*end;) *ptr++ = *end++; *ptr = '\0'; a->a_nvals[i].bv_len = ptr - a->a_nvals[i].bv_val; if ( a->a_vals != a->a_nvals ) { ptr = a->a_vals[i].bv_val; end = ber_bvchr( &a->a_vals[i], '}' ); assert( end != NULL ); end++; for (;*end;) *ptr++ = *end++; *ptr = '\0'; a->a_vals[i].bv_len = ptr - a->a_vals[i].bv_val; } } /* An attr was missing weights here, ignore it */ if ( i<n ) { op->o_tmpfree( index, op->o_tmpmemctx ); continue; } /* Insertion sort */ for ( i=1; i<n; i++) { long idx = index[i]; struct berval tmp = a->a_vals[i], ntmp; if ( gotnvals ) ntmp = a->a_nvals[i]; j = i; while (( j>0 ) && (index[j-1] > idx )) { index[j] = index[j-1]; a->a_vals[j] = a->a_vals[j-1]; if ( gotnvals ) a->a_nvals[j] = a->a_nvals[j-1]; j--; } index[j] = idx; a->a_vals[j] = tmp; if ( gotnvals ) a->a_nvals[j] = ntmp; } /* Check for secondary sort */ if ( vi->vi_sort ^ VALSORT_WEIGHTED ) { for ( i=0; i<n;) { for (j=i+1; j<n; j++) { if (index[i] != index[j]) break; } if( j-i > 1 ) do_sort( op, a, i, j-i, vi->vi_sort ); i = j; } } op->o_tmpfree( index, op->o_tmpmemctx ); } else { do_sort( op, a, 0, n, vi->vi_sort ); } } return SLAP_CB_CONTINUE; }
int slap_bv2ad( struct berval *bv, AttributeDescription **ad, const char **text ) { int rtn = LDAP_UNDEFINED_TYPE; AttributeDescription desc, *d2; char *name, *options, *optn; char *opt, *next; int ntags; int tagslen; /* hardcoded limits for speed */ #define MAX_TAGGING_OPTIONS 128 struct berval tags[MAX_TAGGING_OPTIONS+1]; #define MAX_TAGS_LEN 1024 char tagbuf[MAX_TAGS_LEN]; assert( ad != NULL ); assert( *ad == NULL ); /* temporary */ if( bv == NULL || BER_BVISNULL( bv ) || BER_BVISEMPTY( bv ) ) { *text = "empty AttributeDescription"; return rtn; } /* make sure description is IA5 */ if( ad_keystring( bv ) ) { *text = "AttributeDescription contains inappropriate characters"; return rtn; } /* find valid base attribute type; parse in place */ desc.ad_cname = *bv; desc.ad_flags = 0; BER_BVZERO( &desc.ad_tags ); name = bv->bv_val; options = ber_bvchr( bv, ';' ); if ( options != NULL && (unsigned) ( options - name ) < bv->bv_len ) { /* don't go past the end of the berval! */ desc.ad_cname.bv_len = options - name; } else { options = NULL; } desc.ad_type = at_bvfind( &desc.ad_cname ); if( desc.ad_type == NULL ) { *text = "attribute type undefined"; return rtn; } if( is_at_operational( desc.ad_type ) && options != NULL ) { *text = "operational attribute with options undefined"; return rtn; } /* * parse options in place */ ntags = 0; tagslen = 0; optn = bv->bv_val + bv->bv_len; for( opt=options; opt != NULL; opt=next ) { int optlen; opt++; next = strchrlen( opt, optn, ';', &optlen ); if( optlen == 0 ) { *text = "zero length option is invalid"; return rtn; } else if ( optlen == STRLENOF("binary") && strncasecmp( opt, "binary", STRLENOF("binary") ) == 0 ) { /* binary option */ if( slap_ad_is_binary( &desc ) ) { *text = "option \"binary\" specified multiple times"; return rtn; } if( !slap_syntax_is_binary( desc.ad_type->sat_syntax )) { /* not stored in binary, disallow option */ *text = "option \"binary\" not supported with type"; return rtn; } desc.ad_flags |= SLAP_DESC_BINARY; continue; } else if ( ad_find_option_definition( opt, optlen ) ) { int i; if( opt[optlen-1] == '-' || ( opt[optlen-1] == '=' && msad_range_hack )) { desc.ad_flags |= SLAP_DESC_TAG_RANGE; } if( ntags >= MAX_TAGGING_OPTIONS ) { *text = "too many tagging options"; return rtn; } /* * tags should be presented in sorted order, * so run the array in reverse. */ for( i=ntags-1; i>=0; i-- ) { int rc; rc = strncasecmp( opt, tags[i].bv_val, (unsigned) optlen < tags[i].bv_len ? (unsigned) optlen : tags[i].bv_len ); if( rc == 0 && (unsigned)optlen == tags[i].bv_len ) { /* duplicate (ignore) */ ntags--; goto done; } else if ( rc > 0 || ( rc == 0 && (unsigned)optlen > tags[i].bv_len )) { AC_MEMCPY( &tags[i+2], &tags[i+1], (ntags-i-1)*sizeof(struct berval) ); tags[i+1].bv_val = opt; tags[i+1].bv_len = optlen; goto done; } } if( ntags ) { AC_MEMCPY( &tags[1], &tags[0], ntags*sizeof(struct berval) ); } tags[0].bv_val = opt; tags[0].bv_len = optlen; done:; tagslen += optlen + 1; ntags++; } else { *text = "unrecognized option"; return rtn; } } if( ntags > 0 ) { int i; if( tagslen > MAX_TAGS_LEN ) { *text = "tagging options too long"; return rtn; } desc.ad_tags.bv_val = tagbuf; tagslen = 0; for( i=0; i<ntags; i++ ) { AC_MEMCPY( &desc.ad_tags.bv_val[tagslen], tags[i].bv_val, tags[i].bv_len ); tagslen += tags[i].bv_len; desc.ad_tags.bv_val[tagslen++] = ';'; } desc.ad_tags.bv_val[--tagslen] = '\0'; desc.ad_tags.bv_len = tagslen; } /* see if a matching description is already cached */ for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) { if( d2->ad_flags != desc.ad_flags ) { continue; } if( d2->ad_tags.bv_len != desc.ad_tags.bv_len ) { continue; } if( d2->ad_tags.bv_len == 0 ) { break; } if( strncasecmp( d2->ad_tags.bv_val, desc.ad_tags.bv_val, desc.ad_tags.bv_len ) == 0 ) { break; } } /* Not found, add new one */ while (d2 == NULL) { size_t dlen = 0; ldap_pvt_thread_mutex_lock( &desc.ad_type->sat_ad_mutex ); /* check again now that we've locked */ for (d2 = desc.ad_type->sat_ad; d2; d2=d2->ad_next) { if (d2->ad_flags != desc.ad_flags) continue; if (d2->ad_tags.bv_len != desc.ad_tags.bv_len) continue; if (d2->ad_tags.bv_len == 0) break; if (strncasecmp(d2->ad_tags.bv_val, desc.ad_tags.bv_val, desc.ad_tags.bv_len) == 0) break; } if (d2) { ldap_pvt_thread_mutex_unlock( &desc.ad_type->sat_ad_mutex ); break; } /* Allocate a single contiguous block. If there are no * options, we just need space for the AttrDesc structure. * Otherwise, we need to tack on the full name length + * options length, + maybe tagging options length again. */ if (desc.ad_tags.bv_len || desc.ad_flags != SLAP_DESC_NONE) { dlen = desc.ad_type->sat_cname.bv_len + 1; if (desc.ad_tags.bv_len) { dlen += 1 + desc.ad_tags.bv_len; } if ( slap_ad_is_binary( &desc ) ) { dlen += 1 + STRLENOF(";binary") + desc.ad_tags.bv_len; } } d2 = ch_malloc(sizeof(AttributeDescription) + dlen); d2->ad_next = NULL; d2->ad_type = desc.ad_type; d2->ad_flags = desc.ad_flags; d2->ad_cname.bv_len = desc.ad_type->sat_cname.bv_len; d2->ad_tags.bv_len = desc.ad_tags.bv_len; ldap_pvt_thread_mutex_lock( &ad_index_mutex ); d2->ad_index = ++ad_count; ldap_pvt_thread_mutex_unlock( &ad_index_mutex ); if (dlen == 0) { d2->ad_cname.bv_val = d2->ad_type->sat_cname.bv_val; d2->ad_tags.bv_val = NULL; } else { char *cp, *op, *lp; int j; d2->ad_cname.bv_val = (char *)(d2+1); strcpy(d2->ad_cname.bv_val, d2->ad_type->sat_cname.bv_val); cp = d2->ad_cname.bv_val + d2->ad_cname.bv_len; if( slap_ad_is_binary( &desc ) ) { op = cp; lp = NULL; if( desc.ad_tags.bv_len ) { lp = desc.ad_tags.bv_val; while( strncasecmp(lp, "binary", STRLENOF("binary")) < 0 && (lp = strchr( lp, ';' )) != NULL ) ++lp; if( lp != desc.ad_tags.bv_val ) { *cp++ = ';'; j = (lp ? (unsigned) (lp - desc.ad_tags.bv_val - 1) : strlen( desc.ad_tags.bv_val )); cp = lutil_strncopy(cp, desc.ad_tags.bv_val, j); } } cp = lutil_strcopy(cp, ";binary"); if( lp != NULL ) { *cp++ = ';'; cp = lutil_strcopy(cp, lp); } d2->ad_cname.bv_len = cp - d2->ad_cname.bv_val; if( desc.ad_tags.bv_len ) ldap_pvt_str2lower(op); j = 1; } else { j = 0; } if( desc.ad_tags.bv_len ) { lp = d2->ad_cname.bv_val + d2->ad_cname.bv_len + j; if ( j == 0 ) *lp++ = ';'; d2->ad_tags.bv_val = lp; strcpy(lp, desc.ad_tags.bv_val); ldap_pvt_str2lower(lp); if( j == 0 ) d2->ad_cname.bv_len += 1 + desc.ad_tags.bv_len; } } /* Add new desc to list. We always want the bare Desc with * no options to stay at the head of the list, assuming * that one will be used most frequently. */ if (desc.ad_type->sat_ad == NULL || dlen == 0) { d2->ad_next = desc.ad_type->sat_ad; desc.ad_type->sat_ad = d2; } else { d2->ad_next = desc.ad_type->sat_ad->ad_next; desc.ad_type->sat_ad->ad_next = d2; } ldap_pvt_thread_mutex_unlock( &desc.ad_type->sat_ad_mutex ); } if( *ad == NULL ) { *ad = d2; } else { **ad = *d2; } return LDAP_SUCCESS; }
/* * call from within ldap_back_db_open() */ int ldap_back_monitor_db_open( BackendDB *be ) { ldapinfo_t *li = (ldapinfo_t *) be->be_private; char buf[ BACKMONITOR_BUFSIZE ]; Entry *e = NULL; monitor_callback_t *cb = NULL; struct berval suffix, *filter, *base; char *ptr; time_t now; char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; struct berval timestamp; int rc = 0; BackendInfo *mi; monitor_extra_t *mbe; if ( !SLAP_DBMONITORING( be ) ) { return 0; } /* check if monitor is configured and usable */ mi = backend_info( "monitor" ); if ( !mi || !mi->bi_extra ) { SLAP_DBFLAGS( be ) ^= SLAP_DBFLAG_MONITORING; return 0; } mbe = mi->bi_extra; /* don't bother if monitor is not configured */ if ( !mbe->is_configured() ) { static int warning = 0; if ( warning++ == 0 ) { Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: " "monitoring disabled; " "configure monitor database to enable\n", 0, 0, 0 ); } return 0; } /* set up the fake subsystem that is used to create * the volatile connection entries */ li->li_monitor_info.lmi_mss.mss_name = "back-ldap"; li->li_monitor_info.lmi_mss.mss_flags = MONITOR_F_VOLATILE_CH; li->li_monitor_info.lmi_mss.mss_create = ldap_back_monitor_conn_create; li->li_monitor_info.lmi_li = li; li->li_monitor_info.lmi_scope = LDAP_SCOPE_SUBORDINATE; base = &li->li_monitor_info.lmi_base; BER_BVSTR( base, "cn=databases,cn=monitor" ); filter = &li->li_monitor_info.lmi_filter; BER_BVZERO( filter ); suffix.bv_len = ldap_bv2escaped_filter_value_len( &be->be_nsuffix[ 0 ] ); if ( suffix.bv_len == be->be_nsuffix[ 0 ].bv_len ) { suffix = be->be_nsuffix[ 0 ]; } else { ldap_bv2escaped_filter_value( &be->be_nsuffix[ 0 ], &suffix ); } filter->bv_len = STRLENOF( "(&" ) + li->li_monitor_info.lmi_more_filter.bv_len + STRLENOF( "(monitoredInfo=" ) + strlen( be->bd_info->bi_type ) + STRLENOF( ")(!(monitorOverlay=" ) + strlen( be->bd_info->bi_type ) + STRLENOF( "))(namingContexts:distinguishedNameMatch:=" ) + suffix.bv_len + STRLENOF( "))" ); ptr = filter->bv_val = ch_malloc( filter->bv_len + 1 ); ptr = lutil_strcopy( ptr, "(&" ); ptr = lutil_strncopy( ptr, li->li_monitor_info.lmi_more_filter.bv_val, li->li_monitor_info.lmi_more_filter.bv_len ); ptr = lutil_strcopy( ptr, "(monitoredInfo=" ); ptr = lutil_strcopy( ptr, be->bd_info->bi_type ); ptr = lutil_strcopy( ptr, ")(!(monitorOverlay=" ); ptr = lutil_strcopy( ptr, be->bd_info->bi_type ); ptr = lutil_strcopy( ptr, "))(namingContexts:distinguishedNameMatch:=" ); ptr = lutil_strncopy( ptr, suffix.bv_val, suffix.bv_len ); ptr = lutil_strcopy( ptr, "))" ); ptr[ 0 ] = '\0'; assert( ptr == &filter->bv_val[ filter->bv_len ] ); if ( suffix.bv_val != be->be_nsuffix[ 0 ].bv_val ) { ch_free( suffix.bv_val ); } now = slap_get_time(); timestamp.bv_val = timebuf; timestamp.bv_len = sizeof( timebuf ); slap_timestamp( &now, ×tamp ); /* caller (e.g. an overlay based on back-ldap) may want to use * a different RDN... */ if ( BER_BVISNULL( &li->li_monitor_info.lmi_rdn ) ) { ber_str2bv( "cn=Connections", 0, 1, &li->li_monitor_info.lmi_rdn ); } ptr = ber_bvchr( &li->li_monitor_info.lmi_rdn, '=' ); assert( ptr != NULL ); ptr[ 0 ] = '\0'; ptr++; snprintf( buf, sizeof( buf ), "dn: %s=%s\n" "objectClass: monitorContainer\n" "%s: %s\n" "creatorsName: %s\n" "createTimestamp: %s\n" "modifiersName: %s\n" "modifyTimestamp: %s\n", li->li_monitor_info.lmi_rdn.bv_val, ptr, li->li_monitor_info.lmi_rdn.bv_val, ptr, BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val, timestamp.bv_val, BER_BVISNULL( &be->be_rootdn ) ? SLAPD_ANONYMOUS : be->be_rootdn.bv_val, timestamp.bv_val ); e = str2entry( buf ); if ( e == NULL ) { rc = -1; goto cleanup; } ptr[ -1 ] = '='; /* add labeledURI and special, modifiable URI value */ if ( li->li_uri != NULL ) { struct berval bv; LDAPURLDesc *ludlist = NULL; int rc; rc = ldap_url_parselist_ext( &ludlist, li->li_uri, NULL, LDAP_PVT_URL_PARSE_NOEMPTY_HOST | LDAP_PVT_URL_PARSE_DEF_PORT ); if ( rc != LDAP_URL_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "ldap_back_monitor_db_open: " "unable to parse URI list (ignored)\n", 0, 0, 0 ); } else { for ( ; ludlist != NULL; ) { LDAPURLDesc *next = ludlist->lud_next; bv.bv_val = ldap_url_desc2str( ludlist ); assert( bv.bv_val != NULL ); ldap_free_urldesc( ludlist ); bv.bv_len = strlen( bv.bv_val ); attr_merge_normalize_one( e, slap_schema.si_ad_labeledURI, &bv, NULL ); ch_free( bv.bv_val ); ludlist = next; } } ber_str2bv( li->li_uri, 0, 0, &bv ); attr_merge_normalize_one( e, ad_olmDbURIList, &bv, NULL ); } ber_dupbv( &li->li_monitor_info.lmi_nrdn, &e->e_nname ); cb = ch_calloc( sizeof( monitor_callback_t ), 1 ); cb->mc_update = ldap_back_monitor_update; cb->mc_modify = ldap_back_monitor_modify; cb->mc_free = ldap_back_monitor_free; cb->mc_private = (void *)li; rc = mbe->register_entry_parent( e, cb, (monitor_subsys_t *)&li->li_monitor_info, MONITOR_F_VOLATILE_CH, base, LDAP_SCOPE_SUBORDINATE, filter ); cleanup:; if ( rc != 0 ) { if ( cb != NULL ) { ch_free( cb ); cb = NULL; } if ( e != NULL ) { entry_free( e ); e = NULL; } if ( !BER_BVISNULL( filter ) ) { ch_free( filter->bv_val ); BER_BVZERO( filter ); } } /* store for cleanup */ li->li_monitor_info.lmi_cb = (void *)cb; if ( e != NULL ) { entry_free( e ); } return rc; }