int dnExtractRdn( struct berval *dn, struct berval *rdn ) { LDAPRDN *tmpRDN; const char *p; int rc; assert( dn ); assert( rdn ); if( dn->bv_len == 0 ) { return LDAP_OTHER; } rc = ldap_bv2rdn( dn, &tmpRDN, (char **)&p, LDAP_DN_FORMAT_LDAP ); if ( rc != LDAP_SUCCESS ) { return rc; } rc = ldap_rdn2bv( tmpRDN, rdn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY ); ldap_rdnfree( tmpRDN ); if ( rc != LDAP_SUCCESS ) { return rc; } return LDAP_SUCCESS; }
/* rdnValidate: * * LDAP_SUCCESS if rdn is a legal rdn; * LDAP_INVALID_SYNTAX otherwise (including a sequence of rdns) */ int rdnValidate( 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 strchr( rdn->bv_val, ',' ) == 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 slapi_int_rdn_explode( Slapi_RDN *rdn ) { char *next; if ( rdn->rdn != NULL ) { return LDAP_SUCCESS; } return ldap_bv2rdn( &rdn->bv, &rdn->rdn, &next, LDAP_DN_FORMAT_LDAP ); }
static int create_baseObject( BackendDB *be, const char *fname, int lineno ) { backsql_info *bi = (backsql_info *)be->be_private; LDAPRDN rdn; char *p; int rc, iAVA; char buf[1024]; snprintf( buf, sizeof(buf), "dn: %s\n" "objectClass: extensibleObject\n" "description: builtin baseObject for back-sql\n" "description: all entries mapped " "in table \"ldap_entries\" " "must have " "\"" BACKSQL_BASEOBJECT_IDSTR "\" " "in the \"parent\" column", be->be_suffix[0].bv_val ); bi->sql_baseObject = str2entry( buf ); if ( bi->sql_baseObject == NULL ) { Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): " "unable to parse baseObject entry\n", fname, lineno, 0 ); return 1; } if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) { return 0; } rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **)&p, LDAP_DN_FORMAT_LDAP ); if ( rc != LDAP_SUCCESS ) { snprintf( buf, sizeof(buf), "unable to extract RDN " "from baseObject DN \"%s\" (%d: %s)", be->be_suffix[ 0 ].bv_val, rc, ldap_err2string( rc ) ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): %s\n", fname, lineno, buf ); return 1; } for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; AttributeDescription *ad = NULL; slap_syntax_transform_func *transf = NULL; struct berval bv = BER_BVNULL; const char *text = NULL; assert( ava != NULL ); rc = slap_bv2ad( &ava->la_attr, &ad, &text ); if ( rc != LDAP_SUCCESS ) { snprintf( buf, sizeof(buf), "AttributeDescription of naming " "attribute #%d from baseObject " "DN \"%s\": %d: %s", iAVA, be->be_suffix[ 0 ].bv_val, rc, ldap_err2string( rc ) ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): %s\n", fname, lineno, buf ); return 1; } transf = ad->ad_type->sat_syntax->ssyn_pretty; if ( transf ) { /* * transform value by pretty function * if value is empty, use empty_bv */ rc = ( *transf )( ad->ad_type->sat_syntax, ava->la_value.bv_len ? &ava->la_value : (struct berval *) &slap_empty_bv, &bv, NULL ); if ( rc != LDAP_SUCCESS ) { snprintf( buf, sizeof(buf), "prettying of attribute #%d " "from baseObject " "DN \"%s\" failed: %d: %s", iAVA, be->be_suffix[ 0 ].bv_val, rc, ldap_err2string( rc ) ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config (%s line %d): " "%s\n", fname, lineno, buf ); return 1; } } if ( !BER_BVISNULL( &bv ) ) { if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) { ber_memfree( ava->la_value.bv_val ); } ava->la_value = bv; ava->la_flags |= LDAP_AVA_FREE_VALUE; } attr_merge_normalize_one( bi->sql_baseObject, ad, &ava->la_value, NULL ); } ldap_rdnfree( rdn ); return 0; }
static int retcode_db_open( BackendDB *be, ConfigReply *cr) { slap_overinst *on = (slap_overinst *)be->bd_info; retcode_t *rd = (retcode_t *)on->on_bi.bi_private; retcode_item_t *rdi; for ( rdi = rd->rd_item; rdi; rdi = rdi->rdi_next ) { LDAPRDN rdn = NULL; int rc, j; char* p; struct berval val[ 3 ]; char buf[ SLAP_TEXT_BUFLEN ]; /* DN */ rdi->rdi_e.e_name = rdi->rdi_dn; rdi->rdi_e.e_nname = rdi->rdi_ndn; /* objectClass */ val[ 0 ] = oc_errObject->soc_cname; val[ 1 ] = slap_schema.si_oc_extensibleObject->soc_cname; BER_BVZERO( &val[ 2 ] ); attr_merge( &rdi->rdi_e, slap_schema.si_ad_objectClass, val, NULL ); /* RDN avas */ rc = ldap_bv2rdn( &rdi->rdi_dn, &rdn, (char **) &p, LDAP_DN_FORMAT_LDAP ); assert( rc == LDAP_SUCCESS ); for ( j = 0; rdn[ j ]; j++ ) { LDAPAVA *ava = rdn[ j ]; AttributeDescription *ad = NULL; const char *text; rc = slap_bv2ad( &ava->la_attr, &ad, &text ); assert( rc == LDAP_SUCCESS ); attr_merge_normalize_one( &rdi->rdi_e, ad, &ava->la_value, NULL ); } ldap_rdnfree( rdn ); /* error code */ snprintf( buf, sizeof( buf ), "%d", rdi->rdi_err ); ber_str2bv( buf, 0, 0, &val[ 0 ] ); attr_merge_one( &rdi->rdi_e, ad_errCode, &val[ 0 ], NULL ); if ( rdi->rdi_ref != NULL ) { attr_merge_normalize( &rdi->rdi_e, slap_schema.si_ad_ref, rdi->rdi_ref, NULL ); } /* text */ if ( !BER_BVISNULL( &rdi->rdi_text ) ) { val[ 0 ] = rdi->rdi_text; attr_merge_normalize_one( &rdi->rdi_e, ad_errText, &val[ 0 ], NULL ); } /* matched */ if ( !BER_BVISNULL( &rdi->rdi_matched ) ) { val[ 0 ] = rdi->rdi_matched; attr_merge_normalize_one( &rdi->rdi_e, ad_errMatchedDN, &val[ 0 ], NULL ); } /* sleep time */ if ( rdi->rdi_sleeptime ) { snprintf( buf, sizeof( buf ), "%d", rdi->rdi_sleeptime ); ber_str2bv( buf, 0, 0, &val[ 0 ] ); attr_merge_one( &rdi->rdi_e, ad_errSleepTime, &val[ 0 ], NULL ); } /* operations */ if ( rdi->rdi_mask & SN_DG_OP_ADD ) { BER_BVSTR( &val[ 0 ], "add" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_BIND ) { BER_BVSTR( &val[ 0 ], "bind" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_COMPARE ) { BER_BVSTR( &val[ 0 ], "compare" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_DELETE ) { BER_BVSTR( &val[ 0 ], "delete" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_EXTENDED ) { BER_BVSTR( &val[ 0 ], "extended" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_MODIFY ) { BER_BVSTR( &val[ 0 ], "modify" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_RENAME ) { BER_BVSTR( &val[ 0 ], "rename" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } if ( rdi->rdi_mask & SN_DG_OP_SEARCH ) { BER_BVSTR( &val[ 0 ], "search" ); attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL ); } } return 0; }
int passwd_back_search( Operation *op, SlapReply *rs ) { struct passwd *pw; time_t stoptime = (time_t)-1; LDAPRDN rdn = NULL; struct berval parent = BER_BVNULL; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; if ( op->ors_tlimit != SLAP_NO_LIMIT ) { stoptime = op->o_time + op->ors_tlimit; } /* Handle a query for the base of this backend */ if ( be_issuffix( op->o_bd, &op->o_req_ndn ) ) { struct berval val; rs->sr_matched = op->o_req_dn.bv_val; if( op->ors_scope != LDAP_SCOPE_ONELEVEL ) { AttributeDescription *desc = NULL; char *next; Entry e = { 0 }; /* Create an entry corresponding to the base DN */ e.e_name.bv_val = ch_strdup( op->o_req_dn.bv_val ); e.e_name.bv_len = op->o_req_dn.bv_len; e.e_nname.bv_val = ch_strdup( op->o_req_ndn.bv_val ); e.e_nname.bv_len = op->o_req_ndn.bv_len; /* Use the first attribute of the DN * as an attribute within the entry itself. */ if( ldap_bv2rdn( &op->o_req_dn, &rdn, &next, LDAP_DN_FORMAT_LDAP ) ) { rs->sr_err = LDAP_INVALID_DN_SYNTAX; goto done; } if( slap_bv2ad( &rdn[0]->la_attr, &desc, &rs->sr_text )) { rs->sr_err = LDAP_NO_SUCH_OBJECT; ldap_rdnfree(rdn); goto done; } attr_merge_normalize_one( &e, desc, &rdn[0]->la_value, NULL ); ldap_rdnfree(rdn); rdn = NULL; /* Every entry needs an objectclass. We don't really * know if our hardcoded choice here agrees with the * DN that was configured for this backend, but it's * better than nothing. * * should be a configuratable item */ BER_BVSTR( &val, "organizationalUnit" ); attr_merge_one( &e, ad_objectClass, &val, NULL ); if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { rs->sr_entry = &e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_flags = 0; rs->sr_attrs = NULL; } entry_clean( &e ); } if ( op->ors_scope != LDAP_SCOPE_BASE ) { /* check all our "children" */ ldap_pvt_thread_mutex_lock( &passwd_mutex ); pw_start( op->o_bd ); for ( pw = getpwent(); pw != NULL; pw = getpwent() ) { Entry e = { 0 }; /* check for abandon */ if ( op->o_abandon ) { endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); return( SLAPD_ABANDON ); } /* check time limit */ if ( op->ors_tlimit != SLAP_NO_LIMIT && slap_get_time() > stoptime ) { send_ldap_error( op, rs, LDAP_TIMELIMIT_EXCEEDED, NULL ); endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); return( 0 ); } if ( pw2entry( op->o_bd, pw, &e ) ) { rs->sr_err = LDAP_OTHER; endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); goto done; } if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { /* check size limit */ if ( --op->ors_slimit == -1 ) { send_ldap_error( op, rs, LDAP_SIZELIMIT_EXCEEDED, NULL ); endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); return( 0 ); } rs->sr_entry = &e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_flags = 0; rs->sr_entry = NULL; } entry_clean( &e ); } endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); } } else { char *next; Entry e = { 0 }; int rc; if (! be_issuffix( op->o_bd, &op->o_req_ndn ) ) { dnParent( &op->o_req_ndn, &parent ); } /* This backend is only one layer deep. Don't answer requests for * anything deeper than that. */ if( !be_issuffix( op->o_bd, &parent ) ) { int i; for( i=0; op->o_bd->be_nsuffix[i].bv_val != NULL; i++ ) { if( dnIsSuffix( &op->o_req_ndn, &op->o_bd->be_nsuffix[i] ) ) { rs->sr_matched = op->o_bd->be_suffix[i].bv_val; break; } } rs->sr_err = LDAP_NO_SUCH_OBJECT; goto done; } if( op->ors_scope == LDAP_SCOPE_ONELEVEL ) { goto done; } if ( ldap_bv2rdn( &op->o_req_dn, &rdn, &next, LDAP_DN_FORMAT_LDAP )) { rs->sr_err = LDAP_OTHER; goto done; } ldap_pvt_thread_mutex_lock( &passwd_mutex ); pw_start( op->o_bd ); pw = getpwnam( rdn[0]->la_value.bv_val ); if ( pw == NULL ) { rs->sr_matched = parent.bv_val; rs->sr_err = LDAP_NO_SUCH_OBJECT; ldap_pvt_thread_mutex_unlock( &passwd_mutex ); goto done; } rc = pw2entry( op->o_bd, pw, &e ); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); if ( rc ) { rs->sr_err = LDAP_OTHER; goto done; } if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { rs->sr_entry = &e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_flags = 0; rs->sr_entry = NULL; rs->sr_attrs = NULL; } entry_clean( &e ); } done: if( rs->sr_err != LDAP_NO_SUCH_OBJECT ) rs->sr_matched = NULL; send_ldap_result( op, rs ); if( rdn != NULL ) ldap_rdnfree( rdn ); return( 0 ); }
static int entry_naming_check( Entry *e, int manage, int add_naming, const char** text, char *textbuf, size_t textlen ) { /* naming check */ LDAPRDN rdn = NULL; const char *p = NULL; ber_len_t cnt; int rc = LDAP_SUCCESS; if ( BER_BVISEMPTY( &e->e_name )) { return LDAP_SUCCESS; } /* * Get attribute type(s) and attribute value(s) of our RDN */ if ( ldap_bv2rdn( &e->e_name, &rdn, (char **)&p, LDAP_DN_FORMAT_LDAP ) ) { *text = "unrecognized attribute type(s) in RDN"; return LDAP_INVALID_DN_SYNTAX; } /* Check that each AVA of the RDN is present in the entry */ /* FIXME: Should also check that each AVA lists a distinct type */ for ( cnt = 0; rdn[cnt]; cnt++ ) { LDAPAVA *ava = rdn[cnt]; AttributeDescription *desc = NULL; Attribute *attr; const char *errtext; int add = 0; if( ava->la_flags & LDAP_AVA_BINARY ) { snprintf( textbuf, textlen, "value of naming attribute '%s' in unsupported BER form", ava->la_attr.bv_val ); rc = LDAP_NAMING_VIOLATION; break; } rc = slap_bv2ad( &ava->la_attr, &desc, &errtext ); if ( rc != LDAP_SUCCESS ) { snprintf( textbuf, textlen, "%s (in RDN)", errtext ); break; } if( desc->ad_type->sat_usage ) { snprintf( textbuf, textlen, "naming attribute '%s' is operational", ava->la_attr.bv_val ); rc = LDAP_NAMING_VIOLATION; break; } if( desc->ad_type->sat_collective ) { snprintf( textbuf, textlen, "naming attribute '%s' is collective", ava->la_attr.bv_val ); rc = LDAP_NAMING_VIOLATION; break; } if( !manage && desc->ad_type->sat_obsolete ) { snprintf( textbuf, textlen, "naming attribute '%s' is obsolete", ava->la_attr.bv_val ); rc = LDAP_NAMING_VIOLATION; break; } if( !desc->ad_type->sat_equality ) { snprintf( textbuf, textlen, "naming attribute '%s' has no equality matching rule", ava->la_attr.bv_val ); rc = LDAP_NAMING_VIOLATION; break; } if( !desc->ad_type->sat_equality->smr_match ) { snprintf( textbuf, textlen, "naming attribute '%s' has unsupported equality matching rule", ava->la_attr.bv_val ); rc = LDAP_NAMING_VIOLATION; break; } /* find the naming attribute */ attr = attr_find( e->e_attrs, desc ); if ( attr == NULL ) { snprintf( textbuf, textlen, "naming attribute '%s' is not present in entry", ava->la_attr.bv_val ); if ( add_naming ) { add = 1; } else { rc = LDAP_NAMING_VIOLATION; } } else { rc = attr_valfind( attr, SLAP_MR_VALUE_OF_ASSERTION_SYNTAX| SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, &ava->la_value, NULL, NULL ); if ( rc != 0 ) { switch( rc ) { case LDAP_INAPPROPRIATE_MATCHING: snprintf( textbuf, textlen, "inappropriate matching for naming attribute '%s'", ava->la_attr.bv_val ); break; case LDAP_INVALID_SYNTAX: snprintf( textbuf, textlen, "value of naming attribute '%s' is invalid", ava->la_attr.bv_val ); break; case LDAP_NO_SUCH_ATTRIBUTE: if ( add_naming ) { if ( is_at_single_value( desc->ad_type ) ) { snprintf( textbuf, textlen, "value of single-valued naming attribute '%s' conflicts with value present in entry", ava->la_attr.bv_val ); } else { add = 1; rc = LDAP_SUCCESS; } } else { snprintf( textbuf, textlen, "value of naming attribute '%s' is not present in entry", ava->la_attr.bv_val ); } break; default: snprintf( textbuf, textlen, "naming attribute '%s' is inappropriate", ava->la_attr.bv_val ); } if ( !add ) { rc = LDAP_NAMING_VIOLATION; } } } if ( add ) { attr_merge_normalize_one( e, desc, &ava->la_value, NULL ); } else if ( rc != LDAP_SUCCESS ) { break; } } ldap_rdnfree( rdn ); return rc; }