static int nssov_db_open( BackendDB *be, ConfigReply *cr ) { slap_overinst *on = (slap_overinst *)be->bd_info; nssov_info *ni = on->on_bi.bi_private; nssov_mapinfo *mi; int i, sock; struct sockaddr_un addr; /* Set default bases */ for (i=0; i<NM_NONE; i++) { if ( BER_BVISNULL( &ni->ni_maps[i].mi_base )) { ber_dupbv( &ni->ni_maps[i].mi_base, &be->be_nsuffix[0] ); } if ( ni->ni_maps[i].mi_scope == LDAP_SCOPE_DEFAULT ) ni->ni_maps[i].mi_scope = LDAP_SCOPE_SUBTREE; } /* validate attribute maps */ mi = ni->ni_maps; for ( i=0; i<NM_NONE; i++,mi++) { const char *text; int j; for (j=0; !BER_BVISNULL(&mi->mi_attrkeys[j]); j++) { /* skip attrs we already validated */ if ( mi->mi_attrs[j].an_desc ) continue; if ( slap_bv2ad( &mi->mi_attrs[j].an_name, &mi->mi_attrs[j].an_desc, &text )) { Debug(LDAP_DEBUG_ANY,"nssov: invalid attr \"%s\": %s\n", mi->mi_attrs[j].an_name.bv_val, text, 0 ); return -1; } } BER_BVZERO(&mi->mi_attrs[j].an_name); mi->mi_attrs[j].an_desc = NULL; } /* Find host and authorizedService definitions */ if ((ni->ni_pam_opts & NI_PAM_USERHOST) && !nssov_pam_host_ad) { const char *text; i = slap_str2ad("host", &nssov_pam_host_ad, &text); if (i != LDAP_SUCCESS) { Debug(LDAP_DEBUG_ANY,"nssov: host attr unknown: %s\n", text, 0, 0 ); return -1; } } if ((ni->ni_pam_opts & (NI_PAM_USERSVC|NI_PAM_HOSTSVC)) && !nssov_pam_svc_ad) { const char *text; i = slap_str2ad("authorizedService", &nssov_pam_svc_ad, &text); if (i != LDAP_SUCCESS) { Debug(LDAP_DEBUG_ANY,"nssov: authorizedService attr unknown: %s\n", text, 0, 0 ); return -1; } } if ( slapMode & SLAP_SERVER_MODE ) { /* make sure /var/run/nslcd exists */ if (mkdir(NSLCD_PATH, (mode_t) 0555)) { Debug(LDAP_DEBUG_TRACE,"nssov: mkdir(%s) failed (ignored): %s\n", NSLCD_PATH,strerror(errno),0); } else { Debug(LDAP_DEBUG_TRACE,"nssov: created %s\n",NSLCD_PATH,0,0); } /* create a socket */ if ( (sock=socket(PF_UNIX,SOCK_STREAM,0))<0 ) { Debug(LDAP_DEBUG_ANY,"nssov: cannot create socket: %s\n",strerror(errno),0,0); return -1; } /* remove existing named socket */ if (unlink(NSLCD_SOCKET)<0) { Debug( LDAP_DEBUG_TRACE,"nssov: unlink() of "NSLCD_SOCKET" failed (ignored): %s\n", strerror(errno),0,0); } /* create socket address structure */ memset(&addr,0,sizeof(struct sockaddr_un)); addr.sun_family=AF_UNIX; strncpy(addr.sun_path,NSLCD_SOCKET,sizeof(addr.sun_path)); addr.sun_path[sizeof(addr.sun_path)-1]='\0'; /* bind to the named socket */ if (bind(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr_un))) { Debug( LDAP_DEBUG_ANY,"nssov: bind() to "NSLCD_SOCKET" failed: %s", strerror(errno),0,0); if (close(sock)) Debug( LDAP_DEBUG_ANY,"nssov: problem closing socket: %s",strerror(errno),0,0); return -1; } /* close the file descriptor on exit */ if (fcntl(sock,F_SETFD,FD_CLOEXEC)<0) { Debug( LDAP_DEBUG_ANY,"nssov: fcntl(F_SETFL,O_NONBLOCK) failed: %s",strerror(errno),0,0); if (close(sock)) Debug( LDAP_DEBUG_ANY,"nssov: problem closing socket: %s",strerror(errno),0,0); return -1; } /* set permissions of socket so anybody can do requests */ /* Note: we use chmod() here instead of fchmod() because fchmod does not work on sockets http://www.opengroup.org/onlinepubs/009695399/functions/fchmod.html http://lkml.org/lkml/2005/5/16/11 */ if (chmod(NSLCD_SOCKET,(mode_t)0666)) { Debug( LDAP_DEBUG_ANY,"nssov: chmod(0666) failed: %s",strerror(errno),0,0); if (close(sock)) Debug( LDAP_DEBUG_ANY,"nssov: problem closing socket: %s",strerror(errno),0,0); return -1; } /* start listening for connections */ if (listen(sock,SOMAXCONN)<0) { Debug( LDAP_DEBUG_ANY,"nssov: listen() failed: %s",strerror(errno),0,0); if (close(sock)) Debug( LDAP_DEBUG_ANY,"nssov: problem closing socket: %s",strerror(errno),0,0); return -1; } ni->ni_socket = sock; ni->ni_conn = connection_client_setup( sock, acceptconn, ni ); } return 0; }
int ldap_back_search( Operation *op, SlapReply *rs ) { ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = NULL; struct timeval tv; time_t stoptime = (time_t)(-1); LDAPMessage *res, *e; int rc = 0, msgid; struct berval match = BER_BVNULL, filter = BER_BVNULL; int i, x; char **attrs = NULL; int freetext = 0, filter_undef = 0; int do_retry = 1, dont_retry = 0; LDAPControl **ctrls = NULL; char **references = NULL; rs_assert_ready( rs ); rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */ if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { return rs->sr_err; } /* * FIXME: in case of values return filter, we might want * to map attrs and maybe rewrite value */ if ( op->ors_tlimit != SLAP_NO_LIMIT ) { tv.tv_sec = op->ors_tlimit; tv.tv_usec = 0; stoptime = op->o_time + op->ors_tlimit; } else { LDAP_BACK_TV_SET( &tv ); } i = 0; if ( op->ors_attrs ) { for ( ; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ ) /* just count attrs */ ; } x = 0; if ( op->o_bd->be_extra_anlist ) { for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) /* just count attrs */ ; } if ( i > 0 || x > 0 ) { int j = 0; attrs = op->o_tmpalloc( ( i + x + 1 )*sizeof( char * ), op->o_tmpmemctx ); if ( attrs == NULL ) { rs->sr_err = LDAP_NO_MEMORY; rc = -1; goto finish; } if ( i > 0 ) { for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++, j++ ) { attrs[ j ] = op->ors_attrs[i].an_name.bv_val; } } if ( x > 0 ) { for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++, j++ ) { if ( op->o_bd->be_extra_anlist[x].an_desc && ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, op->ors_attrs ) ) { continue; } attrs[ j ] = op->o_bd->be_extra_anlist[x].an_name.bv_val; } } attrs[ j ] = NULL; } ctrls = op->o_ctrls; rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { goto finish; } /* deal with <draft-zeilenga-ldap-t-f> filters */ filter = op->ors_filterstr; retry: /* this goes after retry because ldap_back_munge_filter() * optionally replaces RFC 4526 T-F filters (&) (|) * if already computed, they will be re-installed * by filter2bv_undef_x() later */ if ( !LDAP_BACK_T_F( li ) ) { ldap_back_munge_filter( op, &filter ); } rs->sr_err = ldap_pvt_search( lc->lc_ld, op->o_req_dn.bv_val, op->ors_scope, filter.bv_val, attrs, op->ors_attrsonly, ctrls, NULL, tv.tv_sec ? &tv : NULL, op->ors_slimit, op->ors_deref, &msgid ); ldap_pvt_thread_mutex_lock( &li->li_counter_mutex ); ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_SEARCH ], 1 ); ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex ); if ( rs->sr_err != LDAP_SUCCESS ) { switch ( rs->sr_err ) { case LDAP_SERVER_DOWN: if ( do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) { goto retry; } } if ( lc == NULL ) { /* reset by ldap_back_retry ... */ rs->sr_err = slap_map_api2result( rs ); } else { rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_DONTSEND ); } goto finish; case LDAP_FILTER_ERROR: /* first try? */ if ( !filter_undef && strstr( filter.bv_val, "(?" ) && !LDAP_BACK_NOUNDEFFILTER( li ) ) { BER_BVZERO( &filter ); filter2bv_undef_x( op, op->ors_filter, 1, &filter ); filter_undef = 1; goto retry; } /* invalid filters return success with no data */ rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; goto finish; default: rs->sr_err = slap_map_api2result( rs ); rs->sr_text = NULL; goto finish; } } /* if needed, initialize timeout */ if ( li->li_timeout[ SLAP_OP_SEARCH ] ) { if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) { tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ]; tv.tv_usec = 0; } } /* We pull apart the ber result, stuff it into a slapd entry, and * let send_search_entry stuff it back into ber format. Slow & ugly, * but this is necessary for version matching, and for ACL processing. */ for ( rc = -2; rc != -1; rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ONE, &tv, &res ) ) { /* check for abandon */ if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( lc ) ) { if ( rc > 0 ) { ldap_msgfree( res ); } (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); rc = SLAPD_ABANDON; goto finish; } if ( rc == 0 || rc == -2 ) { ldap_pvt_thread_yield(); /* check timeout */ if ( li->li_timeout[ SLAP_OP_SEARCH ] ) { if ( rc == 0 ) { (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); rs->sr_text = "Operation timed out"; rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ? LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER; goto finish; } } else { LDAP_BACK_TV_SET( &tv ); } /* check time limit */ if ( op->ors_tlimit != SLAP_NO_LIMIT && slap_get_time() > stoptime ) { (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; goto finish; } continue; } else { /* only touch when activity actually took place... */ if ( li->li_idle_timeout ) { lc->lc_time = op->o_time; } /* don't retry any more */ dont_retry = 1; } if ( rc == LDAP_RES_SEARCH_ENTRY ) { Entry ent = { 0 }; struct berval bdn = BER_BVNULL; do_retry = 0; e = ldap_first_entry( lc->lc_ld, res ); rc = ldap_build_entry( op, e, &ent, &bdn ); if ( rc == LDAP_SUCCESS ) { ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls ); rs->sr_entry = &ent; rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_flags = 0; rs->sr_err = LDAP_SUCCESS; rc = rs->sr_err = send_search_entry( op, rs ); if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } rs->sr_entry = NULL; rs->sr_flags = 0; if ( !BER_BVISNULL( &ent.e_name ) ) { assert( ent.e_name.bv_val != bdn.bv_val ); op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx ); BER_BVZERO( &ent.e_name ); } if ( !BER_BVISNULL( &ent.e_nname ) ) { op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx ); BER_BVZERO( &ent.e_nname ); } entry_clean( &ent ); } ldap_msgfree( res ); switch ( rc ) { case LDAP_SUCCESS: case LDAP_INSUFFICIENT_ACCESS: break; default: if ( rc == LDAP_UNAVAILABLE ) { rc = rs->sr_err = LDAP_OTHER; } else { (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); } goto finish; } } else if ( rc == LDAP_RES_SEARCH_REFERENCE ) { if ( LDAP_BACK_NOREFS( li ) ) { ldap_msgfree( res ); continue; } do_retry = 0; rc = ldap_parse_reference( lc->lc_ld, res, &references, &rs->sr_ctrls, 1 ); if ( rc != LDAP_SUCCESS ) { continue; } /* FIXME: there MUST be at least one */ if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) { int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) /* NO OP */ ; /* FIXME: there MUST be at least one */ rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] ); } BER_BVZERO( &rs->sr_ref[ cnt ] ); /* ignore return value by now */ RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); rs->sr_entry = NULL; ( void )send_search_reference( op, rs ); } else { Debug( LDAP_DEBUG_ANY, "%s ldap_back_search: " "got SEARCH_REFERENCE " "with no referrals\n", op->o_log_prefix, 0, 0 ); } /* cleanup */ if ( references ) { ber_memvfree( (void **)references ); op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx ); rs->sr_ref = NULL; references = NULL; } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } } else if ( rc == LDAP_RES_INTERMEDIATE ) { /* FIXME: response controls * are passed without checks */ rc = ldap_parse_intermediate( lc->lc_ld, res, (char **)&rs->sr_rspoid, &rs->sr_rspdata, &rs->sr_ctrls, 0 ); if ( rc != LDAP_SUCCESS ) { continue; } slap_send_ldap_intermediate( op, rs ); if ( rs->sr_rspoid != NULL ) { ber_memfree( (char *)rs->sr_rspoid ); rs->sr_rspoid = NULL; } if ( rs->sr_rspdata != NULL ) { ber_bvfree( rs->sr_rspdata ); rs->sr_rspdata = NULL; } if ( rs->sr_ctrls != NULL ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } } else { char *err = NULL; rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, &match.bv_val, &err, &references, &rs->sr_ctrls, 1 ); if ( rc == LDAP_SUCCESS ) { if ( err ) { rs->sr_text = err; freetext = 1; } } else { rs->sr_err = rc; } rs->sr_err = slap_map_api2result( rs ); /* RFC 4511: referrals can only appear * if result code is LDAP_REFERRAL */ if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) { if ( rs->sr_err != LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s ldap_back_search: " "got referrals with err=%d\n", op->o_log_prefix, rs->sr_err, 0 ); } else { int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) /* NO OP */ ; rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { /* duplicating ...*/ ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] ); } BER_BVZERO( &rs->sr_ref[ cnt ] ); } } else if ( rs->sr_err == LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s ldap_back_search: " "got err=%d with null " "or empty referrals\n", op->o_log_prefix, rs->sr_err, 0 ); rs->sr_err = LDAP_NO_SUCH_OBJECT; } if ( match.bv_val != NULL ) { match.bv_len = strlen( match.bv_val ); } rc = 0; break; } /* if needed, restore timeout */ if ( li->li_timeout[ SLAP_OP_SEARCH ] ) { if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) { tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ]; tv.tv_usec = 0; } } } if ( rc == -1 ) { if ( dont_retry == 0 ) { if ( do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) { goto retry; } } rs->sr_err = LDAP_SERVER_DOWN; rs->sr_err = slap_map_api2result( rs ); goto finish; } else if ( LDAP_BACK_ONERR_STOP( li ) ) { /* if onerr == STOP */ rs->sr_err = LDAP_SERVER_DOWN; rs->sr_err = slap_map_api2result( rs ); goto finish; } } /* * Rewrite the matched portion of the search base, if required */ if ( !BER_BVISNULL( &match ) && !BER_BVISEMPTY( &match ) ) { struct berval pmatch; if ( dnPretty( NULL, &match, &pmatch, op->o_tmpmemctx ) != LDAP_SUCCESS ) { pmatch.bv_val = match.bv_val; match.bv_val = NULL; } rs->sr_matched = pmatch.bv_val; rs->sr_flags |= REP_MATCHED_MUSTBEFREED; } finish:; if ( !BER_BVISNULL( &match ) ) { ber_memfree( match.bv_val ); } if ( rs->sr_v2ref ) { rs->sr_err = LDAP_REFERRAL; } if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } if ( filter.bv_val != op->ors_filterstr.bv_val ) { op->o_tmpfree( filter.bv_val, op->o_tmpmemctx ); } #if 0 /* let send_ldap_result play cleanup handlers (ITS#4645) */ if ( rc != SLAPD_ABANDON ) #endif { send_ldap_result( op, rs ); } (void)ldap_back_controls_free( op, rs, &ctrls ); if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } if ( rs->sr_text ) { if ( freetext ) { ber_memfree( (char *)rs->sr_text ); } rs->sr_text = NULL; } if ( rs->sr_ref ) { op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx ); rs->sr_ref = NULL; } if ( references ) { ber_memvfree( (void **)references ); } if ( attrs ) { op->o_tmpfree( attrs, op->o_tmpmemctx ); } if ( lc != NULL ) { 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; }
Entry * str2entry2( char *s, int checkvals, int *rc ) { int dummy; if (! rc) rc = &dummy; Entry *e; struct berval *type, *vals, *nvals; char *freeval; AttributeDescription *ad, *ad_prev; const char *text; char *next; int attr_cnt; int i, lines; Attribute ahead, *atail; /* * LDIF is used as the string format. * An entry looks like this: * * dn: <dn>\n * [<attr>:[:] <value>\n] * [<tab><continuedvalue>\n]* * ... * * If a double colon is used after a type, it means the * following value is encoded as a base 64 string. This * happens if the value contains a non-printing character * or newline. */ *rc = LDAP_OTHER; Debug( LDAP_DEBUG_TRACE, "=> str2entry: \"%s\"\n", s ? s : "NULL" ); e = entry_alloc(); if( e == NULL ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (entry allocation failed)\n" ); *rc = LDAP_NO_MEMORY; return NULL; } /* initialize entry */ e->e_id = NOID; /* dn + attributes */ atail = &ahead; ahead.a_next = NULL; ad = NULL; ad_prev = NULL; attr_cnt = 0; next = s; lines = ldif_countlines( s ); type = ch_calloc( 1, (lines+1)*3*sizeof(struct berval)+lines ); vals = type+lines+1; nvals = vals+lines+1; freeval = (char *)(nvals+lines+1); i = -1; /* parse into individual values, record DN */ while ( (s = ldif_getline( &next )) != NULL ) { int freev; if ( *s == '\n' || *s == '\0' ) { break; } i++; if (i >= lines) { Debug( LDAP_DEBUG_TRACE, "<= str2entry ran past end of entry\n" ); *rc = LDAP_INVALID_SYNTAX; goto fail; } int err = ldif_parse_line2( s, type+i, vals+i, &freev ); freeval[i] = freev; if ( err ) { Debug( LDAP_DEBUG_TRACE, "<= str2entry NULL (parse_line)\n" ); *rc = LDAP_OTHER; continue; } if ( bvcasematch( &type[i], &dn_bv ) ) { if ( e->e_dn != NULL ) { Debug( LDAP_DEBUG_ANY, "str2entry: " "entry %ld has multiple DNs \"%s\" and \"%s\"\n", (long) e->e_id, e->e_dn, vals[i].bv_val ); *rc = LDAP_INVALID_SYNTAX; goto fail; } *rc = dnPrettyNormal( NULL, &vals[i], &e->e_name, &e->e_nname, NULL ); if( *rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "str2entry: " "entry %ld has invalid DN \"%s\"\n", (long) e->e_id, vals[i].bv_val ); goto fail; } if ( freeval[i] ) free( vals[i].bv_val ); vals[i].bv_val = NULL; i--; continue; } } lines = i+1; /* check to make sure there was a dn: line */ if ( BER_BVISNULL( &e->e_name )) { Debug( LDAP_DEBUG_ANY, "str2entry: entry %ld has no dn\n", (long) e->e_id ); *rc = LDAP_INVALID_SYNTAX; goto fail; } /* Make sure all attributes with multiple values are contiguous */ if ( checkvals ) { int j, k; struct berval bv; int fv; for (i=0; i<lines; i++) { for ( j=i+1; j<lines; j++ ) { if ( bvcasematch( type+i, type+j )) { /* out of order, move intervening attributes down */ if ( j != i+1 ) { bv = vals[j]; fv = freeval[j]; for ( k=j; k>i; k-- ) { type[k] = type[k-1]; vals[k] = vals[k-1]; freeval[k] = freeval[k-1]; } k++; type[k] = type[i]; vals[k] = bv; freeval[k] = fv; } i++; } } } } if ( lines > 0 ) { for ( i=0; i<=lines; i++ ) { ad_prev = ad; if ( !ad || ( i<lines && !bvcasematch( type+i, &ad->ad_cname ))) { ad = NULL; *rc = slap_bv2ad( type+i, &ad, &text ); if( *rc != LDAP_SUCCESS ) { int wtool = ( slapMode & (SLAP_TOOL_MODE|SLAP_TOOL_READONLY) ) == SLAP_TOOL_MODE; Debug( wtool ? LDAP_DEBUG_ANY : LDAP_DEBUG_TRACE, "<= str2entry: str2ad(%s): %s\n", type[i].bv_val, text ); if( wtool ) { goto fail; } *rc = slap_bv2undef_ad( type+i, &ad, &text, 0 ); if( *rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "<= str2entry: slap_str2undef_ad(%s): %s\n", type[i].bv_val, text ); goto fail; } } /* require ';binary' when appropriate (ITS#5071) */ if ( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad ) ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s #%d: " "needs ';binary' transfer as per syntax %s\n", ad->ad_cname.bv_val, 0, ad->ad_type->sat_syntax->ssyn_oid ); *rc = LDAP_INVALID_SYNTAX; goto fail; } } if (( ad_prev && ad != ad_prev ) || ( i == lines )) { int j, k; atail->a_next = attr_alloc( NULL ); atail = atail->a_next; atail->a_flags = 0; atail->a_numvals = attr_cnt; atail->a_desc = ad_prev; atail->a_vals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); if( ad_prev->ad_type->sat_equality && ad_prev->ad_type->sat_equality->smr_normalize ) atail->a_nvals = ch_malloc( (attr_cnt + 1) * sizeof(struct berval)); else atail->a_nvals = NULL; k = i - attr_cnt; for ( j=0; j<attr_cnt; j++ ) { if ( freeval[k] ) atail->a_vals[j] = vals[k]; else ber_dupbv( atail->a_vals+j, &vals[k] ); vals[k].bv_val = NULL; if ( atail->a_nvals ) { atail->a_nvals[j] = nvals[k]; nvals[k].bv_val = NULL; } k++; } BER_BVZERO( &atail->a_vals[j] ); if ( atail->a_nvals ) { BER_BVZERO( &atail->a_nvals[j] ); } else { atail->a_nvals = atail->a_vals; } attr_cnt = 0; /* FIXME: we only need this when migrating from an unsorted DB */ if ( atail->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { *rc = slap_sort_vals( (Modifications *)atail, &text, &j, NULL ); if ( *rc == LDAP_SUCCESS ) { atail->a_flags |= SLAP_ATTR_SORTED_VALS; } else if ( *rc == LDAP_TYPE_OR_VALUE_EXISTS ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s value #%d provided more than once\n", atail->a_desc->ad_cname.bv_val, j ); goto fail; } } if ( i == lines ) break; } if ( BER_BVISNULL( &vals[i] ) ) { Debug( LDAP_DEBUG_ANY, "str2entry: attributeType %s #%d: " "no value\n", ad->ad_cname.bv_val, attr_cnt ); *rc = LDAP_INVALID_SYNTAX; goto fail; } if ( ad->ad_type->sat_equality && ad->ad_type->sat_equality->smr_normalize ) { *rc = ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, ad, ad->ad_type->sat_equality, &vals[i], &nvals[i], NULL ); if ( *rc ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (smr_normalize %s='%s' %d)\n", ad->ad_cname.bv_val, vals[i].bv_val, *rc ); goto fail; } } attr_cnt++; } } free( type ); atail->a_next = NULL; e->e_attrs = ahead.a_next; *rc = LDAP_SUCCESS; Debug(LDAP_DEBUG_TRACE, "<= str2entry(%s) -> 0x%lx\n", e->e_dn, (unsigned long) e ); return e; fail: for ( i=0; i<lines; i++ ) { if ( freeval[i] ) free( vals[i].bv_val ); free( nvals[i].bv_val ); } free( type ); entry_free( e ); return NULL; }
int load_extop2( const struct berval *ext_oid, slap_mask_t ext_flags, SLAP_EXTOP_MAIN_FN *ext_main, unsigned flags ) { struct berval oidm = BER_BVNULL; struct extop_list *ext; int insertme = 0; if ( !ext_main ) { return -1; } if ( ext_oid == NULL || BER_BVISNULL( ext_oid ) || BER_BVISEMPTY( ext_oid ) ) { return -1; } if ( numericoidValidate( NULL, (struct berval *)ext_oid ) != LDAP_SUCCESS ) { oidm.bv_val = oidm_find( ext_oid->bv_val ); if ( oidm.bv_val == NULL ) { return -1; } oidm.bv_len = strlen( oidm.bv_val ); ext_oid = &oidm; } for ( ext = supp_ext_list; ext; ext = ext->next ) { if ( bvmatch( ext_oid, &ext->oid ) ) { if ( flags == 1 ) { break; } return -1; } } if ( flags == 0 || ext == NULL ) { ext = ch_calloc( 1, sizeof(struct extop_list) + ext_oid->bv_len + 1 ); if ( ext == NULL ) { return(-1); } ext->oid.bv_val = (char *)(ext + 1); AC_MEMCPY( ext->oid.bv_val, ext_oid->bv_val, ext_oid->bv_len ); ext->oid.bv_len = ext_oid->bv_len; ext->oid.bv_val[ext->oid.bv_len] = '\0'; insertme = 1; } ext->flags = ext_flags; ext->ext_main = ext_main; if ( insertme ) { ext->next = supp_ext_list; supp_ext_list = ext; } return(0); }
int ndb_back_modrdn( Operation *op, SlapReply *rs ) { struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; AttributeDescription *children = slap_schema.si_ad_children; AttributeDescription *entry = slap_schema.si_ad_entry; struct berval new_dn = BER_BVNULL, new_ndn = BER_BVNULL; Entry e = {0}; Entry e2 = {0}; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; struct berval *np_dn = NULL; /* newSuperior dn */ struct berval *np_ndn = NULL; /* newSuperior ndn */ int manageDSAit = get_manageDSAit( op ); int num_retries = 0; NdbArgs NA, NA2; NdbRdns rdns, rdn2; struct berval matched; LDAPControl **preread_ctrl = NULL; LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; int rc; Debug( LDAP_DEBUG_ARGS, "==>" LDAP_XSTRING(ndb_back_modrdn) "(%s,%s,%s)\n", op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val, op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" ); ctrls[num_ctrls] = NULL; slap_mods_opattrs( op, &op->orr_modlist, 1 ); e.e_name = op->o_req_dn; e.e_nname = op->o_req_ndn; /* Get our NDB handle */ rs->sr_err = ndb_thread_handle( op, &NA.ndb ); rdns.nr_num = 0; NA.rdns = &rdns; NA.e = &e; NA2.ndb = NA.ndb; NA2.e = &e2; NA2.rdns = &rdn2; if( 0 ) { retry: /* transaction retry */ NA.txn->close(); NA.txn = NULL; if ( e.e_attrs ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(ndb_back_modrdn) ": retrying...\n", 0, 0, 0 ); if ( op->o_abandon ) { rs->sr_err = SLAPD_ABANDON; goto return_results; } if ( NA2.ocs ) { ber_bvarray_free_x( NA2.ocs, op->o_tmpmemctx ); } if ( NA.ocs ) { ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); } ndb_trans_backoff( ++num_retries ); } NA.ocs = NULL; NA2.ocs = NULL; /* begin transaction */ NA.txn = NA.ndb->startTransaction(); rs->sr_text = NULL; if( !NA.txn ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": startTransaction failed: %s (%d)\n", NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } NA2.txn = NA.txn; /* get entry */ rs->sr_err = ndb_entry_get_info( op, &NA, 1, &matched ); switch( rs->sr_err ) { case 0: break; case LDAP_NO_SUCH_OBJECT: Debug( LDAP_DEBUG_ARGS, "<=- ndb_back_modrdn: no such object %s\n", op->o_req_dn.bv_val, 0, 0 ); rs->sr_matched = matched.bv_val; if ( NA.ocs ) ndb_check_referral( op, rs, &NA ); goto return_results; #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; #endif case LDAP_BUSY: rs->sr_text = "ldap server busy"; goto return_results; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } /* acquire and lock entry */ rs->sr_err = ndb_entry_get_data( op, &NA, 1 ); if ( rs->sr_err ) goto return_results; if ( !manageDSAit && is_entry_glue( &e )) { rs->sr_err = LDAP_NO_SUCH_OBJECT; goto return_results; } if ( get_assert( op ) && ( test_filter( op, &e, (Filter *)get_assertion( op )) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED; goto return_results; } /* check write on old entry */ rs->sr_err = access_allowed( op, &e, entry, NULL, ACL_WRITE, NULL ); if ( ! rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0, 0, 0 ); rs->sr_text = "no write access to old entry"; rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } /* Can't do it if we have kids */ rs->sr_err = ndb_has_children( &NA, &rc ); if ( rs->sr_err ) { Debug(LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": has_children failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( rc == LDAP_COMPARE_TRUE ) { Debug(LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": non-leaf %s\n", op->o_req_dn.bv_val, 0, 0); rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; rs->sr_text = "subtree rename not supported"; goto return_results; } if (!manageDSAit && is_entry_referral( &e ) ) { /* entry is a referral, don't allow modrdn */ rs->sr_ref = get_entry_referrals( op, &e ); Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": entry %s is referral\n", e.e_dn, 0, 0 ); rs->sr_err = LDAP_REFERRAL, rs->sr_matched = op->o_req_dn.bv_val; rs->sr_flags = REP_REF_MUSTBEFREED; goto return_results; } if ( be_issuffix( op->o_bd, &e.e_nname ) ) { /* There can only be one suffix entry */ rs->sr_err = LDAP_NAMING_VIOLATION; rs->sr_text = "cannot rename suffix entry"; goto return_results; } else { dnParent( &e.e_nname, &e2.e_nname ); dnParent( &e.e_name, &e2.e_name ); } /* check parent for "children" acl */ rs->sr_err = access_allowed( op, &e2, children, NULL, op->oq_modrdn.rs_newSup == NULL ? ACL_WRITE : ACL_WDEL, NULL ); if ( ! rs->sr_err ) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 ); rs->sr_text = "no write access to old parent's children"; goto return_results; } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": wr to children " "of entry %s OK\n", e2.e_name.bv_val, 0, 0 ); if ( op->oq_modrdn.rs_newSup != NULL ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": new parent \"%s\" requested...\n", op->oq_modrdn.rs_newSup->bv_val, 0, 0 ); /* newSuperior == oldParent? */ if( dn_match( &e2.e_nname, op->oq_modrdn.rs_nnewSup ) ) { Debug( LDAP_DEBUG_TRACE, "bdb_back_modrdn: " "new parent \"%s\" same as the old parent \"%s\"\n", op->oq_modrdn.rs_newSup->bv_val, e2.e_name.bv_val, 0 ); op->oq_modrdn.rs_newSup = NULL; /* ignore newSuperior */ } } if ( op->oq_modrdn.rs_newSup != NULL ) { if ( op->oq_modrdn.rs_newSup->bv_len ) { rdn2.nr_num = 0; np_dn = op->oq_modrdn.rs_newSup; np_ndn = op->oq_modrdn.rs_nnewSup; /* newSuperior == oldParent? - checked above */ /* newSuperior == entry being moved?, if so ==> ERROR */ if ( dnIsSuffix( np_ndn, &e.e_nname )) { rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_text = "new superior not found"; goto return_results; } /* Get Entry with dn=newSuperior. Does newSuperior exist? */ e2.e_name = *np_dn; e2.e_nname = *np_ndn; rs->sr_err = ndb_entry_get_info( op, &NA2, 1, NULL ); switch( rs->sr_err ) { case 0: break; case LDAP_NO_SUCH_OBJECT: Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": newSup(ndn=%s) not here!\n", np_ndn->bv_val, 0, 0); rs->sr_text = "new superior not found"; goto return_results; #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; #endif case LDAP_BUSY: rs->sr_text = "ldap server busy"; goto return_results; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( NA2.ocs ) { Attribute a; int i; for ( i=0; !BER_BVISNULL( &NA2.ocs[i] ); i++); a.a_numvals = i; a.a_desc = slap_schema.si_ad_objectClass; a.a_vals = NA2.ocs; a.a_nvals = NA2.ocs; a.a_next = NULL; e2.e_attrs = &a; if ( is_entry_alias( &e2 )) { /* parent is an alias, don't allow move */ Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": entry is alias\n", 0, 0, 0 ); rs->sr_text = "new superior is an alias"; rs->sr_err = LDAP_ALIAS_PROBLEM; goto return_results; } if ( is_entry_referral( &e2 ) ) { /* parent is a referral, don't allow move */ Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": entry is referral\n", 0, 0, 0 ); rs->sr_text = "new superior is a referral"; rs->sr_err = LDAP_OTHER; goto return_results; } } } /* check newSuperior for "children" acl */ rs->sr_err = access_allowed( op, &e2, children, NULL, ACL_WADD, NULL ); if( ! rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": no wr to newSup children\n", 0, 0, 0 ); rs->sr_text = "no write access to new superior's children"; rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": wr to new parent OK id=%ld\n", (long) e2.e_id, 0, 0 ); } /* Build target dn and make sure target entry doesn't exist already. */ if (!new_dn.bv_val) { build_new_dn( &new_dn, &e2.e_name, &op->oq_modrdn.rs_newrdn, NULL ); } if (!new_ndn.bv_val) { build_new_dn( &new_ndn, &e2.e_nname, &op->oq_modrdn.rs_nnewrdn, NULL ); } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": new ndn=%s\n", new_ndn.bv_val, 0, 0 ); /* Allow rename to same DN */ if ( !bvmatch ( &new_ndn, &e.e_nname )) { rdn2.nr_num = 0; e2.e_name = new_dn; e2.e_nname = new_ndn; NA2.ocs = &matched; rs->sr_err = ndb_entry_get_info( op, &NA2, 1, NULL ); NA2.ocs = NULL; switch( rs->sr_err ) { #if 0 case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; #endif case LDAP_NO_SUCH_OBJECT: break; case 0: rs->sr_err = LDAP_ALREADY_EXISTS; goto return_results; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } } assert( op->orr_modlist != NULL ); if( op->o_preread ) { if( preread_ctrl == NULL ) { preread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if( slap_read_controls( op, rs, &e, &slap_pre_read_bv, preread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": pre-read failed!\n", 0, 0, 0 ); if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto return_results; } } } /* delete old DN */ rs->sr_err = ndb_entry_del_info( op->o_bd, &NA ); if ( rs->sr_err != 0 ) { Debug(LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": dn2id del failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); #if 0 switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } #endif rs->sr_err = LDAP_OTHER; rs->sr_text = "DN index delete fail"; goto return_results; } /* copy entry fields */ e2.e_attrs = e.e_attrs; e2.e_id = e.e_id; /* add new DN */ rs->sr_err = ndb_entry_put_info( op->o_bd, &NA2, 0 ); if ( rs->sr_err != 0 ) { Debug(LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": dn2id add failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); #if 0 switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } #endif rs->sr_err = LDAP_OTHER; rs->sr_text = "DN index add failed"; goto return_results; } /* modify entry */ rs->sr_err = ndb_modify_internal( op, &NA2, &rs->sr_text, textbuf, textlen ); if( rs->sr_err != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": modify failed: %s (%d)\n", NA.txn->getNdbError().message, NA.txn->getNdbError().code, 0 ); #if 0 switch( rs->sr_err ) { case DB_LOCK_DEADLOCK: case DB_LOCK_NOTGRANTED: goto retry; } #endif goto return_results; } e.e_attrs = e2.e_attrs; if( op->o_postread ) { if( postread_ctrl == NULL ) { postread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if( slap_read_controls( op, rs, &e2, &slap_post_read_bv, postread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(ndb_back_modrdn) ": post-read failed!\n", 0, 0, 0 ); if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto return_results; } } } if( op->o_noop ) { if (( rs->sr_err=NA.txn->execute( NdbTransaction::Rollback, NdbOperation::AbortOnError, 1 )) != 0 ) { rs->sr_text = "txn_abort (no-op) failed"; } else { rs->sr_err = LDAP_X_NO_OPERATION; } } else { if (( rs->sr_err=NA.txn->execute( NdbTransaction::Commit, NdbOperation::AbortOnError, 1 )) != 0 ) { rs->sr_text = "txn_commit failed"; } else { rs->sr_err = LDAP_SUCCESS; } } if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_X_NO_OPERATION ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": txn_%s failed: %s (%d)\n", op->o_noop ? "abort (no-op)" : "commit", NA.txn->getNdbError().message, NA.txn->getNdbError().code ); rs->sr_err = LDAP_OTHER; goto return_results; } NA.txn->close(); NA.txn = NULL; Debug(LDAP_DEBUG_TRACE, LDAP_XSTRING(ndb_back_modrdn) ": rdn modified%s id=%08lx dn=\"%s\"\n", op->o_noop ? " (no-op)" : "", e.e_id, op->o_req_dn.bv_val ); rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; if( num_ctrls ) rs->sr_ctrls = ctrls; return_results: if ( NA2.ocs ) { ber_bvarray_free_x( NA2.ocs, op->o_tmpmemctx ); NA2.ocs = NULL; } if ( NA.ocs ) { ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); NA.ocs = NULL; } if ( e.e_attrs ) { attrs_free( e.e_attrs ); e.e_attrs = NULL; } if( NA.txn != NULL ) { NA.txn->execute( Rollback ); NA.txn->close(); } send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); if( new_dn.bv_val != NULL ) free( new_dn.bv_val ); if( new_ndn.bv_val != NULL ) free( new_ndn.bv_val ); if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); } if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); } rs->sr_text = NULL; return rs->sr_err; }
/* * Do basic attribute type checking and syntax validation. */ int slap_mods_check( Operation *op, Modifications *ml, const char **text, char *textbuf, size_t textlen, void *ctx ) { int rc; for( ; ml != NULL; ml = ml->sml_next ) { AttributeDescription *ad = NULL; /* convert to attribute description */ if ( ml->sml_desc == NULL ) { rc = slap_bv2ad( &ml->sml_type, &ml->sml_desc, text ); if( rc != LDAP_SUCCESS ) { if ( get_no_schema_check( op )) { rc = slap_bv2undef_ad( &ml->sml_type, &ml->sml_desc, text, 0 ); } } if( rc != LDAP_SUCCESS ) { snprintf( textbuf, textlen, "%s: %s", ml->sml_type.bv_val, *text ); *text = textbuf; return rc; } } ad = ml->sml_desc; if( slap_syntax_is_binary( ad->ad_type->sat_syntax ) && !slap_ad_is_binary( ad )) { /* attribute requires binary transfer */ snprintf( textbuf, textlen, "%s: requires ;binary transfer", ml->sml_type.bv_val ); *text = textbuf; return LDAP_UNDEFINED_TYPE; } if( !slap_syntax_is_binary( ad->ad_type->sat_syntax ) && slap_ad_is_binary( ad )) { /* attribute does not require binary transfer */ snprintf( textbuf, textlen, "%s: disallows ;binary transfer", ml->sml_type.bv_val ); *text = textbuf; return LDAP_UNDEFINED_TYPE; } if( slap_ad_is_tag_range( ad )) { /* attribute requires binary transfer */ snprintf( textbuf, textlen, "%s: inappropriate use of tag range option", ml->sml_type.bv_val ); *text = textbuf; return LDAP_UNDEFINED_TYPE; } #if 0 if ( is_at_obsolete( ad->ad_type ) && (( ml->sml_op != LDAP_MOD_REPLACE && ml->sml_op != LDAP_MOD_DELETE ) || ml->sml_values != NULL )) { /* * attribute is obsolete, * only allow replace/delete with no values */ snprintf( textbuf, textlen, "%s: attribute is obsolete", ml->sml_type.bv_val ); *text = textbuf; return LDAP_CONSTRAINT_VIOLATION; } #endif if ( ml->sml_op == LDAP_MOD_INCREMENT && #ifdef SLAPD_REAL_SYNTAX !is_at_syntax( ad->ad_type, SLAPD_REAL_SYNTAX ) && #endif !is_at_syntax( ad->ad_type, SLAPD_INTEGER_SYNTAX ) ) { /* * attribute values must be INTEGER or REAL */ snprintf( textbuf, textlen, "%s: attribute syntax inappropriate for increment", ml->sml_type.bv_val ); *text = textbuf; return LDAP_CONSTRAINT_VIOLATION; } /* * check values */ if( ml->sml_values != NULL ) { ber_len_t nvals; slap_syntax_validate_func *validate = ad->ad_type->sat_syntax->ssyn_validate; slap_syntax_transform_func *pretty = ad->ad_type->sat_syntax->ssyn_pretty; if( !pretty && !validate ) { *text = "no validator for syntax"; snprintf( textbuf, textlen, "%s: no validator for syntax %s", ml->sml_type.bv_val, ad->ad_type->sat_syntax->ssyn_oid ); *text = textbuf; return LDAP_INVALID_SYNTAX; } /* * check that each value is valid per syntax * and pretty if appropriate */ for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) { struct berval pval; if ( pretty ) { rc = ordered_value_pretty( ad, &ml->sml_values[nvals], &pval, ctx ); } else { rc = ordered_value_validate( ad, &ml->sml_values[nvals], ml->sml_op ); } if( rc != 0 ) { snprintf( textbuf, textlen, "%s: value #%ld invalid per syntax", ml->sml_type.bv_val, (long) nvals ); *text = textbuf; return LDAP_INVALID_SYNTAX; } if( pretty ) { ber_memfree_x( ml->sml_values[nvals].bv_val, ctx ); ml->sml_values[nvals] = pval; } } ml->sml_values[nvals].bv_len = 0; ml->sml_numvals = nvals; /* * a rough single value check... an additional check is needed * to catch add of single value to existing single valued attribute */ if ((ml->sml_op == LDAP_MOD_ADD || ml->sml_op == LDAP_MOD_REPLACE) && nvals > 1 && is_at_single_value( ad->ad_type )) { snprintf( textbuf, textlen, "%s: multiple values provided", ml->sml_type.bv_val ); *text = textbuf; return LDAP_CONSTRAINT_VIOLATION; } /* if the type has a normalizer, generate the * normalized values. otherwise leave them NULL. * * this is different from the rule for attributes * in an entry - in an attribute list, the normalized * value is set equal to the non-normalized value * when there is no normalizer. */ if( nvals && ad->ad_type->sat_equality && ad->ad_type->sat_equality->smr_normalize ) { ml->sml_nvalues = ber_memalloc_x( (nvals+1)*sizeof(struct berval), ctx ); for ( nvals = 0; !BER_BVISNULL( &ml->sml_values[nvals] ); nvals++ ) { rc = ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, ad, ad->ad_type->sat_equality, &ml->sml_values[nvals], &ml->sml_nvalues[nvals], ctx ); if ( rc ) { Debug( LDAP_DEBUG_ANY, "<= str2entry NULL (ssyn_normalize %d)\n", rc, 0, 0 ); snprintf( textbuf, textlen, "%s: value #%ld normalization failed", ml->sml_type.bv_val, (long) nvals ); *text = textbuf; BER_BVZERO( &ml->sml_nvalues[nvals] ); return rc; } } BER_BVZERO( &ml->sml_nvalues[nvals] ); } /* check for duplicates, but ignore Deletes. */ if( nvals > 1 && ml->sml_op != LDAP_MOD_DELETE ) { int i; rc = slap_sort_vals( ml, text, &i, ctx ); if ( rc == LDAP_TYPE_OR_VALUE_EXISTS ) { /* value exists already */ snprintf( textbuf, textlen, "%s: value #%d provided more than once", ml->sml_desc->ad_cname.bv_val, i ); *text = textbuf; } if ( rc ) return rc; } } else { ml->sml_numvals = 0; } } return LDAP_SUCCESS; }
int do_search( Operation *op, /* info about the op to which we're responding */ SlapReply *rs /* all the response data we'll send */ ) { struct berval base = BER_BVNULL; ber_len_t siz, off, i; Debug( LDAP_DEBUG_TRACE, "%s do_search\n", op->o_log_prefix, 0, 0 ); /* * Parse the search request. It looks like this: * * SearchRequest := [APPLICATION 3] SEQUENCE { * baseObject DistinguishedName, * scope ENUMERATED { * baseObject (0), * singleLevel (1), * wholeSubtree (2), * subordinate (3) -- OpenLDAP extension * }, * derefAliases ENUMERATED { * neverDerefaliases (0), * derefInSearching (1), * derefFindingBaseObj (2), * alwaysDerefAliases (3) * }, * sizelimit INTEGER (0 .. 65535), * timelimit INTEGER (0 .. 65535), * attrsOnly BOOLEAN, * filter Filter, * attributes SEQUENCE OF AttributeType * } */ /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */ if ( ber_scanf( op->o_ber, "{miiiib" /*}*/, &base, &op->ors_scope, &op->ors_deref, &op->ors_slimit, &op->ors_tlimit, &op->ors_attrsonly ) == LBER_ERROR ) { send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto return_results; } if ( op->ors_tlimit < 0 || op->ors_tlimit > SLAP_MAX_LIMIT ) { send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid time limit" ); goto return_results; } if ( op->ors_slimit < 0 || op->ors_slimit > SLAP_MAX_LIMIT ) { send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid size limit" ); goto return_results; } switch( op->ors_scope ) { case LDAP_SCOPE_BASE: case LDAP_SCOPE_ONELEVEL: case LDAP_SCOPE_SUBTREE: case LDAP_SCOPE_SUBORDINATE: break; default: send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid scope" ); goto return_results; } switch( op->ors_deref ) { case LDAP_DEREF_NEVER: case LDAP_DEREF_FINDING: case LDAP_DEREF_SEARCHING: case LDAP_DEREF_ALWAYS: break; default: send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid deref" ); goto return_results; } rs->sr_err = dnPrettyNormal( NULL, &base, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_search: invalid dn: \"%s\"\n", op->o_log_prefix, base.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto return_results; } Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base.bv_val, op->ors_scope, op->ors_deref ); Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", op->ors_slimit, op->ors_tlimit, op->ors_attrsonly); /* filter - returns a "normalized" version */ rs->sr_err = get_filter( op, op->o_ber, &op->ors_filter, &rs->sr_text ); if( rs->sr_err != LDAP_SUCCESS ) { if( rs->sr_err == SLAPD_DISCONNECT ) { rs->sr_err = LDAP_PROTOCOL_ERROR; send_ldap_disconnect( op, rs ); rs->sr_err = SLAPD_DISCONNECT; } else { send_ldap_result( op, rs ); } goto return_results; } filter2bv_x( op, op->ors_filter, &op->ors_filterstr ); Debug( LDAP_DEBUG_ARGS, " filter: %s\n", !BER_BVISEMPTY( &op->ors_filterstr ) ? op->ors_filterstr.bv_val : "empty", 0, 0 ); /* attributes */ siz = sizeof(AttributeName); off = offsetof(AttributeName,an_name); if ( ber_scanf( op->o_ber, "{M}}", &op->ors_attrs, &siz, off ) == LBER_ERROR ) { send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding attrs error" ); rs->sr_err = SLAPD_DISCONNECT; goto return_results; } for ( i=0; i<siz; i++ ) { const char *dummy; /* ignore msgs from bv2ad */ op->ors_attrs[i].an_desc = NULL; op->ors_attrs[i].an_oc = NULL; op->ors_attrs[i].an_flags = 0; if ( slap_bv2ad( &op->ors_attrs[i].an_name, &op->ors_attrs[i].an_desc, &dummy ) != LDAP_SUCCESS ) { slap_bv2undef_ad( &op->ors_attrs[i].an_name, &op->ors_attrs[i].an_desc, &dummy, SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); }; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_search: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); goto return_results; } Debug( LDAP_DEBUG_ARGS, " attrs:", 0, 0, 0 ); if ( siz != 0 ) { for ( i = 0; i<siz; i++ ) { Debug( LDAP_DEBUG_ARGS, " %s", op->ors_attrs[i].an_name.bv_val, 0, 0 ); } } Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 ); if ( StatslogTest( LDAP_DEBUG_STATS ) ) { char abuf[BUFSIZ/2], *ptr = abuf; unsigned len = 0, alen; sprintf(abuf, "scope=%d deref=%d", op->ors_scope, op->ors_deref); Statslog( LDAP_DEBUG_STATS, "%s SRCH base=\"%s\" %s filter=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, abuf, op->ors_filterstr.bv_val, 0 ); for ( i = 0; i<siz; i++ ) { alen = op->ors_attrs[i].an_name.bv_len; if (alen >= sizeof(abuf)) { alen = sizeof(abuf)-1; } if (len && (len + 1 + alen >= sizeof(abuf))) { Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); len = 0; ptr = abuf; } if (len) { *ptr++ = ' '; len++; } ptr = lutil_strncopy(ptr, op->ors_attrs[i].an_name.bv_val, alen); len += alen; *ptr = '\0'; } if (len) { Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); } } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_search( op, rs ); return_results:; if ( !BER_BVISNULL( &op->o_req_dn ) ) { slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &op->o_req_ndn ) ) { slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &op->ors_filterstr ) ) { op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); } if ( op->ors_filter != NULL) { filter_free_x( op, op->ors_filter, 1 ); } if ( op->ors_attrs != NULL ) { op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); } return rs->sr_err; }
static int vlv_parseCtrl( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { BerElementBuffer berbuf; BerElement *ber; ber_tag_t tag; ber_len_t len; vlv_ctrl *vc, vc2; rs->sr_err = LDAP_PROTOCOL_ERROR; rs->sr_text = NULL; if ( op->o_ctrlflag[vlv_cid] > SLAP_CONTROL_IGNORED ) { rs->sr_text = "vlv control specified multiple times"; } else if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { rs->sr_text = "vlv control value is absent"; } else if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) { rs->sr_text = "vlv control value is empty"; } if ( rs->sr_text != NULL ) return rs->sr_err; op->o_ctrlflag[vlv_cid] = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; ber = (BerElement *)&berbuf; ber_init2( ber, &ctrl->ldctl_value, 0 ); rs->sr_err = LDAP_PROTOCOL_ERROR; tag = ber_scanf( ber, "{ii", &vc2.vc_before, &vc2.vc_after ); if ( tag == LBER_ERROR ) { return rs->sr_err; } tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_VLVBYINDEX_IDENTIFIER ) { tag = ber_scanf( ber, "{ii}", &vc2.vc_offset, &vc2.vc_count ); if ( tag == LBER_ERROR ) return rs->sr_err; BER_BVZERO( &vc2.vc_value ); } else if ( tag == LDAP_VLVBYVALUE_IDENTIFIER ) { tag = ber_scanf( ber, "m", &vc2.vc_value ); if ( tag == LBER_ERROR || BER_BVISNULL( &vc2.vc_value )) return rs->sr_err; } else { return rs->sr_err; } tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_VLVCONTEXT_IDENTIFIER ) { struct berval bv; tag = ber_scanf( ber, "m", &bv ); if ( tag == LBER_ERROR || bv.bv_len != sizeof(vc2.vc_context)) return rs->sr_err; memcpy( &vc2.vc_context, bv.bv_val, bv.bv_len ); } else { vc2.vc_context = 0; } vc = op->o_tmpalloc( sizeof(vlv_ctrl), op->o_tmpmemctx ); *vc = vc2; op->o_controls[vlv_cid] = vc; rs->sr_err = LDAP_SUCCESS; return rs->sr_err; }
static void send_list( Operation *op, SlapReply *rs, sort_op *so) { Avlnode *cur_node, *tmp_node; vlv_ctrl *vc = op->o_controls[vlv_cid]; int i, j, dir, rc; BackendDB *be; Entry *e; LDAPControl *ctrls[2]; rs->sr_attrs = op->ors_attrs; /* FIXME: it may be better to just flatten the tree into * an array before doing all of this... */ /* Are we just counting an offset? */ if ( BER_BVISNULL( &vc->vc_value )) { if ( vc->vc_offset == vc->vc_count ) { /* wants the last entry in the list */ cur_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT); so->so_vlv_target = so->so_nentries; } else if ( vc->vc_offset == 1 ) { /* wants the first entry in the list */ cur_node = tavl_end(so->so_tree, TAVL_DIR_LEFT); so->so_vlv_target = 1; } else { int target; /* Just iterate to the right spot */ if ( vc->vc_count && vc->vc_count != so->so_nentries ) { if ( vc->vc_offset > vc->vc_count ) goto range_err; target = so->so_nentries * vc->vc_offset / vc->vc_count; } else { if ( vc->vc_offset > so->so_nentries ) { range_err: so->so_vlv_rc = LDAP_VLV_RANGE_ERROR; pack_vlv_response_control( op, rs, so, ctrls ); ctrls[1] = NULL; slap_add_ctrls( op, rs, ctrls ); rs->sr_err = LDAP_VLV_ERROR; return; } target = vc->vc_offset; } so->so_vlv_target = target; /* Start at left and go right, or start at right and go left? */ if ( target < so->so_nentries / 2 ) { cur_node = tavl_end(so->so_tree, TAVL_DIR_LEFT); dir = TAVL_DIR_RIGHT; } else { cur_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT); dir = TAVL_DIR_LEFT; target = so->so_nentries - target + 1; } for ( i=1; i<target; i++ ) cur_node = tavl_next( cur_node, dir ); } } else { /* we're looking for a specific value */ sort_ctrl *sc = so->so_ctrl; MatchingRule *mr = sc->sc_keys[0].sk_ordering; sort_node *sn; struct berval bv; if ( mr->smr_normalize ) { rc = mr->smr_normalize( SLAP_MR_VALUE_OF_SYNTAX, mr->smr_syntax, mr, &vc->vc_value, &bv, op->o_tmpmemctx ); if ( rc ) { so->so_vlv_rc = LDAP_INAPPROPRIATE_MATCHING; pack_vlv_response_control( op, rs, so, ctrls ); ctrls[1] = NULL; slap_add_ctrls( op, rs, ctrls ); rs->sr_err = LDAP_VLV_ERROR; return; } } else { bv = vc->vc_value; } sn = op->o_tmpalloc( sizeof(sort_node) + sc->sc_nkeys * sizeof(struct berval), op->o_tmpmemctx ); sn->sn_vals = (struct berval *)(sn+1); sn->sn_conn = op->o_conn->c_conn_idx; sn->sn_session = find_session_by_so( so->so_info->svi_max_percon, op->o_conn->c_conn_idx, so ); sn->sn_vals[0] = bv; for (i=1; i<sc->sc_nkeys; i++) { BER_BVZERO( &sn->sn_vals[i] ); } cur_node = tavl_find3( so->so_tree, sn, node_cmp, &j ); /* didn't find >= match */ if ( j > 0 ) { if ( cur_node ) cur_node = tavl_next( cur_node, TAVL_DIR_RIGHT ); } op->o_tmpfree( sn, op->o_tmpmemctx ); if ( !cur_node ) { so->so_vlv_target = so->so_nentries + 1; } else { sort_node *sn = so->so_tree->avl_data; /* start from the left or the right side? */ mr->smr_match( &i, 0, mr->smr_syntax, mr, &bv, &sn->sn_vals[0] ); if ( i > 0 ) { tmp_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT); dir = TAVL_DIR_LEFT; } else { tmp_node = tavl_end(so->so_tree, TAVL_DIR_LEFT); dir = TAVL_DIR_RIGHT; } for (i=0; tmp_node != cur_node; tmp_node = tavl_next( tmp_node, dir ), i++); so->so_vlv_target = (dir == TAVL_DIR_RIGHT) ? i+1 : so->so_nentries - i; } if ( bv.bv_val != vc->vc_value.bv_val ) op->o_tmpfree( bv.bv_val, op->o_tmpmemctx ); } if ( !cur_node ) { i = 1; cur_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT); } else { i = 0; } for ( ; i<vc->vc_before; i++ ) { tmp_node = tavl_next( cur_node, TAVL_DIR_LEFT ); if ( !tmp_node ) break; cur_node = tmp_node; } j = i + vc->vc_after + 1; be = op->o_bd; for ( i=0; i<j; i++ ) { sort_node *sn = cur_node->avl_data; if ( slapd_shutdown ) break; op->o_bd = select_backend( &sn->sn_dn, 0 ); e = NULL; rc = be_entry_get_rw( op, &sn->sn_dn, NULL, NULL, 0, &e ); if ( e && rc == LDAP_SUCCESS ) { rs->sr_entry = e; rs->sr_flags = REP_ENTRY_MUSTRELEASE; rs->sr_err = send_search_entry( op, rs ); if ( rs->sr_err == LDAP_UNAVAILABLE ) break; } cur_node = tavl_next( cur_node, TAVL_DIR_RIGHT ); if ( !cur_node ) break; } so->so_vlv_rc = LDAP_SUCCESS; op->o_bd = be; }
int backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid ) { Operation *op = bsi->bsi_op; backsql_info *bi = (backsql_info *)op->o_bd->be_private; int i; int rc; Debug( LDAP_DEBUG_TRACE, "==>backsql_id2entry()\n", 0, 0, 0 ); assert( bsi->bsi_e != NULL ); memset( bsi->bsi_e, 0, sizeof( Entry ) ); if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) { (void)entry_dup2( bsi->bsi_e, bi->sql_baseObject ); goto done; } bsi->bsi_e->e_attrs = NULL; bsi->bsi_e->e_private = NULL; if ( eid->eid_oc == NULL ) { eid->eid_oc = backsql_id2oc( bsi->bsi_op->o_bd->be_private, eid->eid_oc_id ); if ( eid->eid_oc == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): unable to fetch objectClass with id=" BACKSQL_IDNUMFMT " for entry id=" BACKSQL_IDFMT " dn=\"%s\"\n", eid->eid_oc_id, BACKSQL_IDARG(eid->eid_id), eid->eid_dn.bv_val ); return LDAP_OTHER; } } bsi->bsi_oc = eid->eid_oc; bsi->bsi_c_eid = eid; ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, op->o_tmpmemctx ); ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, op->o_tmpmemctx ); #ifndef BACKSQL_ARBITRARY_KEY /* FIXME: unused */ bsi->bsi_e->e_id = eid->eid_id; #endif /* ! BACKSQL_ARBITRARY_KEY */ rc = attr_merge_normalize_one( bsi->bsi_e, slap_schema.si_ad_objectClass, &bsi->bsi_oc->bom_oc->soc_cname, bsi->bsi_op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { backsql_entry_clean( op, bsi->bsi_e ); return rc; } if ( bsi->bsi_attrs == NULL || ( bsi->bsi_flags & BSQL_SF_ALL_USER ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): " "retrieving all attributes\n", 0, 0, 0 ); avl_apply( bsi->bsi_oc->bom_attrs, backsql_get_attr_vals, bsi, 0, AVL_INORDER ); } else { Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): " "custom attribute list\n", 0, 0, 0 ); for ( i = 0; !BER_BVISNULL( &bsi->bsi_attrs[ i ].an_name ); i++ ) { backsql_at_map_rec **vat; AttributeName *an = &bsi->bsi_attrs[ i ]; int j; /* if one of the attributes listed here is * a subtype of another, it must be ignored, * because subtypes are already dealt with * by backsql_supad2at() */ for ( j = 0; !BER_BVISNULL( &bsi->bsi_attrs[ j ].an_name ); j++ ) { /* skip self */ if ( j == i ) { continue; } /* skip subtypes */ if ( is_at_subtype( an->an_desc->ad_type, bsi->bsi_attrs[ j ].an_desc->ad_type ) ) { goto next; } } rc = backsql_supad2at( bsi->bsi_oc, an->an_desc, &vat ); if ( rc != 0 || vat == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(): " "attribute \"%s\" is not defined " "for objectlass \"%s\"\n", an->an_name.bv_val, BACKSQL_OC_NAME( bsi->bsi_oc ), 0 ); continue; } for ( j = 0; vat[j]; j++ ) { backsql_get_attr_vals( vat[j], bsi ); } ch_free( vat ); next:; } } if ( bsi->bsi_flags & BSQL_SF_RETURN_ENTRYUUID ) { Attribute *a_entryUUID, **ap; a_entryUUID = backsql_operational_entryUUID( bi, eid ); if ( a_entryUUID != NULL ) { for ( ap = &bsi->bsi_e->e_attrs; *ap; ap = &(*ap)->a_next ); *ap = a_entryUUID; } } if ( ( bsi->bsi_flags & BSQL_SF_ALL_OPER ) || an_find( bsi->bsi_attrs, slap_bv_all_operational_attrs ) || an_find( bsi->bsi_attrs, &slap_schema.si_ad_structuralObjectClass->ad_cname ) ) { ObjectClass *soc = NULL; if ( BACKSQL_CHECK_SCHEMA( bi ) ) { Attribute *a; const char *text = NULL; char textbuf[ 1024 ]; size_t textlen = sizeof( textbuf ); struct berval bv[ 2 ], *nvals; int rc = LDAP_SUCCESS; a = attr_find( bsi->bsi_e->e_attrs, slap_schema.si_ad_objectClass ); if ( a != NULL ) { nvals = a->a_nvals; } else { bv[ 0 ] = bsi->bsi_oc->bom_oc->soc_cname; BER_BVZERO( &bv[ 1 ] ); nvals = bv; } rc = structural_class( nvals, &soc, NULL, &text, textbuf, textlen, op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): " "structural_class() failed %d (%s)\n", bsi->bsi_e->e_name.bv_val, rc, text ? text : "" ); backsql_entry_clean( op, bsi->bsi_e ); return rc; } if ( !bvmatch( &soc->soc_cname, &bsi->bsi_oc->bom_oc->soc_cname ) ) { if ( !is_object_subclass( bsi->bsi_oc->bom_oc, soc ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): " "computed structuralObjectClass %s " "does not match objectClass %s associated " "to entry\n", bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val, bsi->bsi_oc->bom_oc->soc_cname.bv_val ); backsql_entry_clean( op, bsi->bsi_e ); return rc; } Debug( LDAP_DEBUG_TRACE, "backsql_id2entry(%s): " "computed structuralObjectClass %s " "is subclass of objectClass %s associated " "to entry\n", bsi->bsi_e->e_name.bv_val, soc->soc_cname.bv_val, bsi->bsi_oc->bom_oc->soc_cname.bv_val ); } } else { soc = bsi->bsi_oc->bom_oc; } rc = attr_merge_normalize_one( bsi->bsi_e, slap_schema.si_ad_structuralObjectClass, &soc->soc_cname, bsi->bsi_op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { backsql_entry_clean( op, bsi->bsi_e ); return rc; } } done:; Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 ); return LDAP_SUCCESS; }
int ldap_back_modify( Operation *op, SlapReply *rs ) { ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; ldapconn_t *lc = NULL; LDAPMod **modv = NULL, *mods = NULL; Modifications *ml; int i, j, rc; ber_int_t msgid; int isupdate; ldap_back_send_t retrying = LDAP_BACK_RETRYING; LDAPControl **ctrls = NULL; if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { return rs->sr_err; } for ( i = 0, ml = op->orm_modlist; ml; i++, ml = ml->sml_next ) /* just count mods */ ; modv = (LDAPMod **)ch_malloc( ( i + 1 )*sizeof( LDAPMod * ) + i*sizeof( LDAPMod ) ); if ( modv == NULL ) { rc = LDAP_NO_MEMORY; goto cleanup; } mods = (LDAPMod *)&modv[ i + 1 ]; isupdate = be_shadow_update( op ); for ( i = 0, ml = op->orm_modlist; ml; ml = ml->sml_next ) { if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod ) { continue; } modv[ i ] = &mods[ i ]; mods[ i ].mod_op = ( ml->sml_op | LDAP_MOD_BVALUES ); mods[ i ].mod_type = ml->sml_desc->ad_cname.bv_val; if ( ml->sml_values != NULL ) { if ( ml->sml_values == NULL ) { continue; } for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) /* just count mods */ ; mods[ i ].mod_bvalues = (struct berval **)ch_malloc( ( j + 1 )*sizeof( struct berval * ) ); for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) { mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ]; } mods[ i ].mod_bvalues[ j ] = NULL; } else { mods[ i ].mod_bvalues = NULL; } i++; } modv[ i ] = 0; retry:; ctrls = op->o_ctrls; rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rc = -1; goto cleanup; } rs->sr_err = ldap_modify_ext( lc->lc_ld, op->o_req_dn.bv_val, modv, ctrls, NULL, &msgid ); rc = ldap_back_op_result( lc, op, rs, msgid, li->li_timeout[ SLAP_OP_MODIFY ], ( LDAP_BACK_SENDRESULT | retrying ) ); if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) { retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } ldap_pvt_thread_mutex_lock( &li->li_counter_mutex ); ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_MODIFY ], 1 ); ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex ); cleanup:; (void)ldap_back_controls_free( op, rs, &ctrls ); for ( i = 0; modv[ i ]; i++ ) { ch_free( modv[ i ]->mod_bvalues ); } ch_free( modv ); if ( lc != NULL ) { ldap_back_release_conn( li, lc ); } return rc; }
static int backsql_get_attr_vals( void *v_at, void *v_bsi ) { backsql_at_map_rec *at = v_at; backsql_srch_info *bsi = v_bsi; backsql_info *bi; RETCODE rc; SQLHSTMT sth = SQL_NULL_HSTMT; BACKSQL_ROW_NTS row; unsigned long i, k = 0, oldcount = 0, res = 0; #ifdef BACKSQL_COUNTQUERY unsigned count, j, append = 0; SQLLEN countsize = sizeof( count ); Attribute *attr = NULL; slap_mr_normalize_func *normfunc = NULL; #endif /* BACKSQL_COUNTQUERY */ #ifdef BACKSQL_PRETTY_VALIDATE slap_syntax_validate_func *validate = NULL; slap_syntax_transform_func *pretty = NULL; #endif /* BACKSQL_PRETTY_VALIDATE */ assert( at != NULL ); assert( bsi != NULL ); Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): " "oc=\"%s\" attr=\"%s\" keyval=" BACKSQL_IDFMT "\n", BACKSQL_OC_NAME( bsi->bsi_oc ), at->bam_ad->ad_cname.bv_val, BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval) ); bi = (backsql_info *)bsi->bsi_op->o_bd->be_private; #ifdef BACKSQL_PRETTY_VALIDATE validate = at->bam_true_ad->ad_type->sat_syntax->ssyn_validate; pretty = at->bam_true_ad->ad_type->sat_syntax->ssyn_pretty; if ( validate == NULL && pretty == NULL ) { return 1; } #endif /* BACKSQL_PRETTY_VALIDATE */ #ifdef BACKSQL_COUNTQUERY if ( at->bam_true_ad->ad_type->sat_equality ) { normfunc = at->bam_true_ad->ad_type->sat_equality->smr_normalize; } /* Count how many rows will be returned. This avoids memory * fragmentation that can result from loading the values in * one by one and using realloc() */ rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_countquery, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " "error preparing count query: %s\n", at->bam_countquery, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); return 1; } rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &bsi->bsi_c_eid->eid_keyval ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " "error binding key value parameter\n", 0, 0, 0 ); SQLFreeStmt( sth, SQL_DROP ); return 1; } rc = SQLExecute( sth ); if ( ! BACKSQL_SUCCESS( rc ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " "error executing attribute count query '%s'\n", at->bam_countquery, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); return 1; } SQLBindCol( sth, (SQLUSMALLINT)1, SQL_C_LONG, (SQLPOINTER)&count, (SQLINTEGER)sizeof( count ), &countsize ); rc = SQLFetch( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " "error fetch results of count query: %s\n", at->bam_countquery, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); return 1; } Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " "number of values in query: %u\n", count, 0, 0 ); SQLFreeStmt( sth, SQL_DROP ); if ( count == 0 ) { return 1; } attr = attr_find( bsi->bsi_e->e_attrs, at->bam_true_ad ); if ( attr != NULL ) { BerVarray tmp; if ( attr->a_vals != NULL ) { oldcount = attr->a_numvals; } tmp = ch_realloc( attr->a_vals, ( oldcount + count + 1 ) * sizeof( struct berval ) ); if ( tmp == NULL ) { return 1; } attr->a_vals = tmp; memset( &attr->a_vals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) ); if ( normfunc ) { tmp = ch_realloc( attr->a_nvals, ( oldcount + count + 1 ) * sizeof( struct berval ) ); if ( tmp == NULL ) { return 1; } attr->a_nvals = tmp; memset( &attr->a_nvals[ oldcount ], 0, ( count + 1 ) * sizeof( struct berval ) ); } else { attr->a_nvals = attr->a_vals; } attr->a_numvals += count; } else { append = 1; /* Make space for the array of values */ attr = attr_alloc( at->bam_true_ad ); attr->a_numvals = count; attr->a_vals = ch_calloc( count + 1, sizeof( struct berval ) ); if ( attr->a_vals == NULL ) { Debug( LDAP_DEBUG_TRACE, "Out of memory!\n", 0,0,0 ); ch_free( attr ); return 1; } if ( normfunc ) { attr->a_nvals = ch_calloc( count + 1, sizeof( struct berval ) ); if ( attr->a_nvals == NULL ) { ch_free( attr->a_vals ); ch_free( attr ); return 1; } } else { attr->a_nvals = attr->a_vals; } } #endif /* BACKSQL_COUNTQUERY */ rc = backsql_Prepare( bsi->bsi_dbh, &sth, at->bam_query, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " "error preparing query: %s\n", at->bam_query, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); #ifdef BACKSQL_COUNTQUERY if ( append ) { attr_free( attr ); } #endif /* BACKSQL_COUNTQUERY */ return 1; } rc = backsql_BindParamID( sth, 1, SQL_PARAM_INPUT, &bsi->bsi_c_eid->eid_keyval ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " "error binding key value parameter\n", 0, 0, 0 ); #ifdef BACKSQL_COUNTQUERY if ( append ) { attr_free( attr ); } #endif /* BACKSQL_COUNTQUERY */ return 1; } #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " "query=\"%s\" keyval=" BACKSQL_IDFMT "\n", at->bam_query, BACKSQL_IDARG(bsi->bsi_c_eid->eid_keyval), 0 ); #endif /* BACKSQL_TRACE */ rc = SQLExecute( sth ); if ( ! BACKSQL_SUCCESS( rc ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_get_attr_vals(): " "error executing attribute query \"%s\"\n", at->bam_query, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); #ifdef BACKSQL_COUNTQUERY if ( append ) { attr_free( attr ); } #endif /* BACKSQL_COUNTQUERY */ return 1; } backsql_BindRowAsStrings_x( sth, &row, bsi->bsi_op->o_tmpmemctx ); #ifdef BACKSQL_COUNTQUERY j = oldcount; #endif /* BACKSQL_COUNTQUERY */ for ( rc = SQLFetch( sth ), k = 0; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ), k++ ) { for ( i = 0; i < (unsigned long)row.ncols; i++ ) { if ( row.value_len[ i ] > 0 ) { struct berval bv; int retval; #ifdef BACKSQL_TRACE AttributeDescription *ad = NULL; const char *text; retval = slap_bv2ad( &row.col_names[ i ], &ad, &text ); if ( retval != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "==>backsql_get_attr_vals(\"%s\"): " "unable to find AttributeDescription %s " "in schema (%d)\n", bsi->bsi_e->e_name.bv_val, row.col_names[ i ].bv_val, retval ); res = 1; goto done; } if ( ad != at->bam_ad ) { Debug( LDAP_DEBUG_ANY, "==>backsql_get_attr_vals(\"%s\"): " "column name %s differs from " "AttributeDescription %s\n", bsi->bsi_e->e_name.bv_val, ad->ad_cname.bv_val, at->bam_ad->ad_cname.bv_val ); res = 1; goto done; } #endif /* BACKSQL_TRACE */ /* ITS#3386, ITS#3113 - 20070308 * If a binary is fetched? * must use the actual size read * from the database. */ if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) { #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_ANY, "==>backsql_get_attr_vals(\"%s\"): " "column name %s: data is binary; " "using database size %ld\n", bsi->bsi_e->e_name.bv_val, ad->ad_cname.bv_val, row.value_len[ i ] ); #endif /* BACKSQL_TRACE */ bv.bv_val = row.cols[ i ]; bv.bv_len = row.value_len[ i ]; } else { ber_str2bv( row.cols[ i ], 0, 0, &bv ); } #ifdef BACKSQL_PRETTY_VALIDATE if ( pretty ) { struct berval pbv; retval = pretty( at->bam_true_ad->ad_type->sat_syntax, &bv, &pbv, bsi->bsi_op->o_tmpmemctx ); bv = pbv; } else { retval = validate( at->bam_true_ad->ad_type->sat_syntax, &bv ); } if ( retval != LDAP_SUCCESS ) { char buf[ SLAP_TEXT_BUFLEN ]; /* FIXME: we're ignoring invalid values, * but we're accepting the attributes; * should we fail at all? */ snprintf( buf, sizeof( buf ), "unable to %s value #%lu " "of AttributeDescription %s", pretty ? "prettify" : "validate", k - oldcount, at->bam_ad->ad_cname.bv_val ); Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(\"%s\"): " "%s (%d)\n", bsi->bsi_e->e_name.bv_val, buf, retval ); continue; } #endif /* BACKSQL_PRETTY_VALIDATE */ #ifndef BACKSQL_COUNTQUERY (void)backsql_entry_addattr( bsi->bsi_e, at->bam_true_ad, &bv, bsi->bsi_op->o_tmpmemctx ); #else /* BACKSQL_COUNTQUERY */ if ( normfunc ) { struct berval nbv; retval = (*normfunc)( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, at->bam_true_ad->ad_type->sat_syntax, at->bam_true_ad->ad_type->sat_equality, &bv, &nbv, bsi->bsi_op->o_tmpmemctx ); if ( retval != LDAP_SUCCESS ) { char buf[ SLAP_TEXT_BUFLEN ]; /* FIXME: we're ignoring invalid values, * but we're accepting the attributes; * should we fail at all? */ snprintf( buf, sizeof( buf ), "unable to normalize value #%lu " "of AttributeDescription %s", k - oldcount, at->bam_ad->ad_cname.bv_val ); Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(\"%s\"): " "%s (%d)\n", bsi->bsi_e->e_name.bv_val, buf, retval ); #ifdef BACKSQL_PRETTY_VALIDATE if ( pretty ) { bsi->bsi_op->o_tmpfree( bv.bv_val, bsi->bsi_op->o_tmpmemctx ); } #endif /* BACKSQL_PRETTY_VALIDATE */ continue; } ber_dupbv( &attr->a_nvals[ j ], &nbv ); bsi->bsi_op->o_tmpfree( nbv.bv_val, bsi->bsi_op->o_tmpmemctx ); } ber_dupbv( &attr->a_vals[ j ], &bv ); assert( j < oldcount + count ); j++; #endif /* BACKSQL_COUNTQUERY */ #ifdef BACKSQL_PRETTY_VALIDATE if ( pretty ) { bsi->bsi_op->o_tmpfree( bv.bv_val, bsi->bsi_op->o_tmpmemctx ); } #endif /* BACKSQL_PRETTY_VALIDATE */ #ifdef BACKSQL_TRACE Debug( LDAP_DEBUG_TRACE, "prec=%d\n", (int)row.col_prec[ i ], 0, 0 ); } else { Debug( LDAP_DEBUG_TRACE, "NULL value " "in this row for attribute \"%s\"\n", row.col_names[ i ].bv_val, 0, 0 ); #endif /* BACKSQL_TRACE */ } } } #ifdef BACKSQL_COUNTQUERY if ( BER_BVISNULL( &attr->a_vals[ 0 ] ) ) { /* don't leave around attributes with no values */ attr_free( attr ); } else if ( append ) { Attribute **ap; for ( ap = &bsi->bsi_e->e_attrs; (*ap) != NULL; ap = &(*ap)->a_next ) /* goto last */ ; *ap = attr; } #endif /* BACKSQL_COUNTQUERY */ SQLFreeStmt( sth, SQL_DROP ); Debug( LDAP_DEBUG_TRACE, "<==backsql_get_attr_vals()\n", 0, 0, 0 ); if ( at->bam_next ) { res = backsql_get_attr_vals( at->bam_next, v_bsi ); } else { res = 1; } #ifdef BACKSQL_TRACE done:; #endif /* BACKSQL_TRACE */ backsql_FreeRow_x( &row, bsi->bsi_op->o_tmpmemctx ); return res; }
/* * NOTE: the dn must be normalized */ int backsql_dn2id( Operation *op, SlapReply *rs, SQLHDBC dbh, struct berval *ndn, backsql_entryID *id, int matched, int muck ) { backsql_info *bi = op->o_bd->be_private; SQLHSTMT sth = SQL_NULL_HSTMT; BACKSQL_ROW_NTS row = { 0 }; RETCODE rc; int res; struct berval realndn = BER_BVNULL; /* TimesTen */ char upperdn[ BACKSQL_MAX_DN_LEN + 1 ]; struct berval tbbDN; int i, j; /* * NOTE: id can be NULL; in this case, the function * simply checks whether the DN can be successfully * turned into an ID, returning LDAP_SUCCESS for * positive cases, or the most appropriate error */ Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(\"%s\")%s%s\n", ndn->bv_val, id == NULL ? " (no ID expected)" : "", matched ? " matched expected" : "" ); if ( id ) { /* NOTE: trap inconsistencies */ assert( BER_BVISNULL( &id->eid_ndn ) ); } if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): DN length=%ld " "exceeds max DN length %d:\n", ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN ); return LDAP_OTHER; } /* return baseObject if available and matches */ /* FIXME: if ndn is already mucked, we cannot check this */ if ( bi->sql_baseObject != NULL && dn_match( ndn, &bi->sql_baseObject->e_nname ) ) { if ( id != NULL ) { #ifdef BACKSQL_ARBITRARY_KEY ber_dupbv_x( &id->eid_id, &backsql_baseObject_bv, op->o_tmpmemctx ); ber_dupbv_x( &id->eid_keyval, &backsql_baseObject_bv, op->o_tmpmemctx ); #else /* ! BACKSQL_ARBITRARY_KEY */ id->eid_id = BACKSQL_BASEOBJECT_ID; id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL; #endif /* ! BACKSQL_ARBITRARY_KEY */ id->eid_oc_id = BACKSQL_BASEOBJECT_OC; ber_dupbv_x( &id->eid_ndn, &bi->sql_baseObject->e_nname, op->o_tmpmemctx ); ber_dupbv_x( &id->eid_dn, &bi->sql_baseObject->e_name, op->o_tmpmemctx ); id->eid_next = NULL; } return LDAP_SUCCESS; } /* begin TimesTen */ assert( bi->sql_id_query != NULL ); Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): id_query \"%s\"\n", ndn->bv_val, bi->sql_id_query, 0 ); rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "error preparing SQL:\n %s", ndn->bv_val, bi->sql_id_query, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); res = LDAP_OTHER; goto done; } realndn = *ndn; if ( muck ) { if ( backsql_api_dn2odbc( op, rs, &realndn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "backsql_api_dn2odbc(\"%s\") failed\n", ndn->bv_val, realndn.bv_val, 0 ); res = LDAP_OTHER; goto done; } } if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) { /* * Prepare an upper cased, byte reversed version * that can be searched using indexes */ for ( i = 0, j = realndn.bv_len - 1; realndn.bv_val[ i ]; i++, j--) { upperdn[ i ] = realndn.bv_val[ j ]; } upperdn[ i ] = '\0'; ldap_pvt_str2upper( upperdn ); Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "upperdn=\"%s\"\n", ndn->bv_val, upperdn, 0 ); ber_str2bv( upperdn, 0, 0, &tbbDN ); } else { if ( BACKSQL_USE_REVERSE_DN( bi ) ) { AC_MEMCPY( upperdn, realndn.bv_val, realndn.bv_len + 1 ); ldap_pvt_str2upper( upperdn ); Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "upperdn=\"%s\"\n", ndn->bv_val, upperdn, 0 ); ber_str2bv( upperdn, 0, 0, &tbbDN ); } else { tbbDN = realndn; } } rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN ); if ( rc != SQL_SUCCESS) { /* end TimesTen */ Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "error binding dn=\"%s\" parameter:\n", ndn->bv_val, tbbDN.bv_val, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); res = LDAP_OTHER; goto done; } rc = SQLExecute( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "error executing query (\"%s\", \"%s\"):\n", ndn->bv_val, bi->sql_id_query, tbbDN.bv_val ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); res = LDAP_OTHER; goto done; } backsql_BindRowAsStrings_x( sth, &row, op->o_tmpmemctx ); rc = SQLFetch( sth ); if ( BACKSQL_SUCCESS( rc ) ) { char buf[ SLAP_TEXT_BUFLEN ]; #ifdef LDAP_DEBUG snprintf( buf, sizeof(buf), "id=%s keyval=%s oc_id=%s dn=%s", row.cols[ 0 ], row.cols[ 1 ], row.cols[ 2 ], row.cols[ 3 ] ); Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): %s\n", ndn->bv_val, buf, 0 ); #endif /* LDAP_DEBUG */ res = LDAP_SUCCESS; if ( id != NULL ) { struct berval dn; id->eid_next = NULL; #ifdef BACKSQL_ARBITRARY_KEY ber_str2bv_x( row.cols[ 0 ], 0, 1, &id->eid_id, op->o_tmpmemctx ); ber_str2bv_x( row.cols[ 1 ], 0, 1, &id->eid_keyval, op->o_tmpmemctx ); #else /* ! BACKSQL_ARBITRARY_KEY */ if ( BACKSQL_STR2ID( &id->eid_id, row.cols[ 0 ], 0 ) != 0 ) { res = LDAP_OTHER; goto done; } if ( BACKSQL_STR2ID( &id->eid_keyval, row.cols[ 1 ], 0 ) != 0 ) { res = LDAP_OTHER; goto done; } #endif /* ! BACKSQL_ARBITRARY_KEY */ if ( BACKSQL_STR2ID( &id->eid_oc_id, row.cols[ 2 ], 0 ) != 0 ) { res = LDAP_OTHER; goto done; } ber_str2bv( row.cols[ 3 ], 0, 0, &dn ); if ( backsql_api_odbc2dn( op, rs, &dn ) ) { res = LDAP_OTHER; goto done; } res = dnPrettyNormal( NULL, &dn, &id->eid_dn, &id->eid_ndn, op->o_tmpmemctx ); if ( res != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_dn2id(\"%s\"): " "dnPrettyNormal failed (%d: %s)\n", realndn.bv_val, res, ldap_err2string( res ) ); /* cleanup... */ (void)backsql_free_entryID( id, 0, op->o_tmpmemctx ); } if ( dn.bv_val != row.cols[ 3 ] ) { free( dn.bv_val ); } } } else { res = LDAP_NO_SUCH_OBJECT; if ( matched ) { struct berval pdn = *ndn; /* * Look for matched */ rs->sr_matched = NULL; while ( !be_issuffix( op->o_bd, &pdn ) ) { char *matchedDN = NULL; dnParent( &pdn, &pdn ); /* * Empty DN ("") defaults to LDAP_SUCCESS */ rs->sr_err = backsql_dn2id( op, rs, dbh, &pdn, id, 0, 1 ); switch ( rs->sr_err ) { case LDAP_NO_SUCH_OBJECT: /* try another one */ break; case LDAP_SUCCESS: matchedDN = pdn.bv_val; /* fail over to next case */ default: rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_matched = matchedDN; goto done; } } } } done:; backsql_FreeRow_x( &row, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(\"%s\"): err=%d\n", ndn->bv_val, res, 0 ); if ( sth != SQL_NULL_HSTMT ) { SQLFreeStmt( sth, SQL_DROP ); } if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != ndn->bv_val ) { ch_free( realndn.bv_val ); } return res; }
int backsql_modrdn( Operation *op, SlapReply *rs ) { backsql_info *bi = (backsql_info*)op->o_bd->be_private; SQLHDBC dbh = SQL_NULL_HDBC; SQLHSTMT sth = SQL_NULL_HSTMT; RETCODE rc; backsql_entryID e_id = BACKSQL_ENTRYID_INIT, n_id = BACKSQL_ENTRYID_INIT; backsql_srch_info bsi = { 0 }; backsql_oc_map_rec *oc = NULL; struct berval pdn = BER_BVNULL, pndn = BER_BVNULL, *new_pdn = NULL, *new_npdn = NULL, new_dn = BER_BVNULL, new_ndn = BER_BVNULL, realnew_dn = BER_BVNULL; Entry r = { 0 }, p = { 0 }, n = { 0 }, *e = NULL; int manageDSAit = get_manageDSAit( op ); struct berval *newSuperior = op->oq_modrdn.rs_newSup; Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry \"%s\", " "newrdn=\"%s\", newSuperior=\"%s\"\n", op->o_req_dn.bv_val, op->oq_modrdn.rs_newrdn.bv_val, newSuperior ? newSuperior->bv_val : "(NULL)" ); rs->sr_err = backsql_get_db_conn( op, &dbh ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "could not get connection handle - exiting\n", 0, 0, 0 ); rs->sr_text = ( rs->sr_err == LDAP_OTHER ) ? "SQL-backend error" : NULL; e = NULL; goto done; } bsi.bsi_e = &r; rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_all_attributes, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) ); switch ( rs->sr_err ) { case LDAP_SUCCESS: break; case LDAP_REFERRAL: if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) && dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } break; } e = &r; /* fallthru */ default: Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): " "could not retrieve modrdnDN ID - no such entry\n", 0, 0, 0 ); if ( !BER_BVISNULL( &r.e_nname ) ) { /* FIXME: should always be true! */ e = &r; } else { e = NULL; } goto done; } #ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%s\n", e_id.eid_id.bv_val, 0, 0 ); #else /* ! BACKSQL_ARBITRARY_KEY */ Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=%ld\n", e_id.eid_id, 0, 0 ); #endif /* ! BACKSQL_ARBITRARY_KEY */ if ( get_assert( op ) && ( test_filter( op, &r, get_assertion( op ) ) != LDAP_COMPARE_TRUE ) ) { rs->sr_err = LDAP_ASSERTION_FAILED; e = &r; goto done; } if ( backsql_has_children( op, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "entry \"%s\" has children\n", op->o_req_dn.bv_val, 0, 0 ); rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; rs->sr_text = "subtree rename not supported"; e = &r; goto done; } /* * Check for entry access to target */ if ( !access_allowed( op, &r, slap_schema.si_ad_entry, NULL, ACL_WRITE, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " no access to entry\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto done; } dnParent( &op->o_req_dn, &pdn ); dnParent( &op->o_req_ndn, &pndn ); /* * namingContext "" is not supported */ if ( BER_BVISEMPTY( &pdn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "parent is \"\" - aborting\n", 0, 0, 0 ); rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "not allowed within namingContext"; e = NULL; goto done; } /* * Check for children access to parent */ bsi.bsi_e = &p; e_id = bsi.bsi_base_id; memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) ); rs->sr_err = backsql_init_search( &bsi, &pndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_all_attributes, BACKSQL_ISF_GET_ENTRY ); #ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "old parent entry id is %s\n", bsi.bsi_base_id.eid_id.bv_val, 0, 0 ); #else /* ! BACKSQL_ARBITRARY_KEY */ Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "old parent entry id is %ld\n", bsi.bsi_base_id.eid_id, 0, 0 ); #endif /* ! BACKSQL_ARBITRARY_KEY */ if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): " "could not retrieve renameDN ID - no such entry\n", 0, 0, 0 ); e = &p; goto done; } if ( !access_allowed( op, &p, slap_schema.si_ad_children, NULL, newSuperior ? ACL_WDEL : ACL_WRITE, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " no access to parent\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto done; } if ( newSuperior ) { (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); /* * namingContext "" is not supported */ if ( BER_BVISEMPTY( newSuperior ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "newSuperior is \"\" - aborting\n", 0, 0, 0 ); rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "not allowed within namingContext"; e = NULL; goto done; } new_pdn = newSuperior; new_npdn = op->oq_modrdn.rs_nnewSup; /* * Check for children access to new parent */ bsi.bsi_e = &n; rs->sr_err = backsql_init_search( &bsi, new_npdn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_all_attributes, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): " "could not retrieve renameDN ID - no such entry\n", 0, 0, 0 ); e = &n; goto done; } n_id = bsi.bsi_base_id; #ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "new parent entry id=%s\n", n_id.eid_id.bv_val, 0, 0 ); #else /* ! BACKSQL_ARBITRARY_KEY */ Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "new parent entry id=%ld\n", n_id.eid_id, 0, 0 ); #endif /* ! BACKSQL_ARBITRARY_KEY */ if ( !access_allowed( op, &n, slap_schema.si_ad_children, NULL, ACL_WADD, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "no access to new parent \"%s\"\n", new_pdn->bv_val, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; e = &n; goto done; } } else { n_id = bsi.bsi_base_id; new_pdn = &pdn; new_npdn = &pndn; } memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) ); if ( newSuperior && dn_match( &pndn, new_npdn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "newSuperior is equal to old parent - ignored\n", 0, 0, 0 ); newSuperior = NULL; } if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "newSuperior is equal to entry being moved " "- aborting\n", 0, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "newSuperior is equal to old DN"; e = &r; goto done; } build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn, op->o_tmpmemctx ); build_new_dn( &new_ndn, new_npdn, &op->oq_modrdn.rs_nnewrdn, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new entry dn is \"%s\"\n", new_dn.bv_val, 0, 0 ); realnew_dn = new_dn; if ( backsql_api_dn2odbc( op, rs, &realnew_dn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): " "backsql_api_dn2odbc(\"%s\") failed\n", op->o_req_dn.bv_val, realnew_dn.bv_val, 0 ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "executing renentry_stmt\n", 0, 0, 0 ); rc = backsql_Prepare( dbh, &sth, bi->sql_renentry_stmt, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "error preparing renentry_stmt\n", 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realnew_dn ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(): " "error binding DN parameter for objectClass %s\n", oc->bom_oc->soc_cname.bv_val, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = backsql_BindParamID( sth, 2, SQL_PARAM_INPUT, &n_id.eid_id ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(): " "error binding parent ID parameter for objectClass %s\n", oc->bom_oc->soc_cname.bv_val, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &e_id.eid_keyval ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(): " "error binding entry ID parameter for objectClass %s\n", oc->bom_oc->soc_cname.bv_val, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = backsql_BindParamID( sth, 4, SQL_PARAM_INPUT, &e_id.eid_id ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_add_attr(): " "error binding ID parameter for objectClass %s\n", oc->bom_oc->soc_cname.bv_val, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = SQLExecute( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "could not rename ldap_entries record\n", 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; e = NULL; goto done; } SQLFreeStmt( sth, SQL_DROP ); assert( op->orr_modlist != NULL ); slap_mods_opattrs( op, &op->orr_modlist, 1 ); assert( e_id.eid_oc != NULL ); oc = e_id.eid_oc; rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, op->orr_modlist ); slap_graduate_commit_csn( op ); if ( rs->sr_err != LDAP_SUCCESS ) { e = &r; goto done; } if ( BACKSQL_CHECK_SCHEMA( bi ) ) { char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' }; backsql_entry_clean( op, &r ); (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx ); bsi.bsi_e = &r; rs->sr_err = backsql_init_search( &bsi, &new_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_all_attributes, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) ); switch ( rs->sr_err ) { case LDAP_SUCCESS: break; case LDAP_REFERRAL: if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) && dn_match( &new_ndn, &bsi.bsi_e->e_nname ) ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } break; } e = &r; /* fallthru */ default: Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): " "could not retrieve modrdnDN ID - no such entry\n", 0, 0, 0 ); if ( !BER_BVISNULL( &r.e_nname ) ) { /* FIXME: should always be true! */ e = &r; } else { e = NULL; } goto done; } e_id = bsi.bsi_base_id; rs->sr_err = entry_schema_check( op, &r, NULL, 0, 0, &rs->sr_text, textbuf, sizeof( textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): " "entry failed schema check -- aborting\n", r.e_name.bv_val, 0, 0 ); e = NULL; goto done; } } done:; if ( e != NULL ) { if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } } /* * Commit only if all operations succeed */ if ( sth != SQL_NULL_HSTMT ) { SQLUSMALLINT CompletionType = SQL_ROLLBACK; if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { CompletionType = SQL_COMMIT; } SQLTransact( SQL_NULL_HENV, dbh, CompletionType ); } if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) { rs->sr_err = LDAP_X_NO_OPERATION; } send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); if ( !BER_BVISNULL( &realnew_dn ) && realnew_dn.bv_val != new_dn.bv_val ) { ch_free( realnew_dn.bv_val ); } if ( !BER_BVISNULL( &new_dn ) ) { slap_sl_free( new_dn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &new_ndn ) ) { slap_sl_free( new_ndn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &e_id.eid_ndn ) ) { (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &n_id.eid_ndn ) ) { (void)backsql_free_entryID( &n_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &r.e_nname ) ) { backsql_entry_clean( op, &r ); } if ( !BER_BVISNULL( &p.e_nname ) ) { backsql_entry_clean( op, &p ); } if ( !BER_BVISNULL( &n.e_nname ) ) { backsql_entry_clean( op, &n ); } if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n", 0, 0, 0 ); return rs->sr_err; }
int slap_parse_modlist( Operation *op, SlapReply *rs, BerElement *ber, req_modify_s *ms ) { ber_tag_t tag; ber_len_t len; char *last; Modifications **modtail = &ms->rs_mods.rs_modlist; ms->rs_mods.rs_modlist = NULL; ms->rs_increment = 0; rs->sr_err = LDAP_SUCCESS; /* collect modifications & save for later */ for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT; tag = ber_next_element( ber, &len, last ) ) { ber_int_t mop; Modifications tmp, *mod; tmp.sml_nvalues = NULL; if ( ber_scanf( ber, "{e{m[W]}}", &mop, &tmp.sml_type, &tmp.sml_values ) == LBER_ERROR ) { rs->sr_text = "decoding modlist error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } mod = (Modifications *) ch_malloc( sizeof(Modifications) ); mod->sml_op = mop; mod->sml_flags = 0; mod->sml_type = tmp.sml_type; mod->sml_values = tmp.sml_values; mod->sml_nvalues = NULL; mod->sml_desc = NULL; mod->sml_next = NULL; *modtail = mod; switch( mop ) { case LDAP_MOD_ADD: if ( mod->sml_values == NULL ) { rs->sr_text = "modify/add operation requires values"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } /* fall through */ case LDAP_MOD_DELETE: case LDAP_MOD_REPLACE: break; case LDAP_MOD_INCREMENT: if( op->o_protocol >= LDAP_VERSION3 ) { ms->rs_increment++; if ( mod->sml_values == NULL ) { rs->sr_text = "modify/increment operation requires value"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } if ( !BER_BVISNULL( &mod->sml_values[ 1 ] ) ) { rs->sr_text = "modify/increment operation requires single value"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } break; } /* fall thru */ default: rs->sr_text = "unrecognized modify operation"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } modtail = &mod->sml_next; } *modtail = NULL; done: if ( rs->sr_err != LDAP_SUCCESS ) { slap_mods_free( ms->rs_mods.rs_modlist, 1 ); ms->rs_mods.rs_modlist = NULL; ms->rs_increment = 0; } return rs->sr_err; }
static int sssvlv_op_response( Operation *op, SlapReply *rs ) { sort_ctrl *sc = op->o_controls[sss_cid]; sort_op *so = op->o_callback->sc_private; if ( rs->sr_type == REP_SEARCH ) { int i; size_t len; sort_node *sn, *sn2; struct berval *bv; char *ptr; len = sizeof(sort_node) + sc->sc_nkeys * sizeof(struct berval) + rs->sr_entry->e_nname.bv_len + 1; sn = op->o_tmpalloc( len, op->o_tmpmemctx ); sn->sn_vals = (struct berval *)(sn+1); /* Build tmp list of key values */ for ( i=0; i<sc->sc_nkeys; i++ ) { Attribute *a = attr_find( rs->sr_entry->e_attrs, sc->sc_keys[i].sk_ad ); if ( a ) { if ( a->a_numvals > 1 ) { bv = select_value( a, &sc->sc_keys[i] ); } else { bv = a->a_nvals; } sn->sn_vals[i] = *bv; len += bv->bv_len + 1; } else { BER_BVZERO( &sn->sn_vals[i] ); } } /* Now dup into regular memory */ sn2 = ch_malloc( len ); sn2->sn_vals = (struct berval *)(sn2+1); memcpy( sn2->sn_vals, sn->sn_vals, sc->sc_nkeys * sizeof(struct berval)); ptr = (char *)(sn2->sn_vals + sc->sc_nkeys); sn2->sn_dn.bv_val = ptr; sn2->sn_dn.bv_len = rs->sr_entry->e_nname.bv_len; memcpy( ptr, rs->sr_entry->e_nname.bv_val, rs->sr_entry->e_nname.bv_len ); ptr += rs->sr_entry->e_nname.bv_len; *ptr++ = '\0'; for ( i=0; i<sc->sc_nkeys; i++ ) { if ( !BER_BVISNULL( &sn2->sn_vals[i] )) { memcpy(ptr, sn2->sn_vals[i].bv_val, sn2->sn_vals[i].bv_len); sn2->sn_vals[i].bv_val = ptr; ptr += sn2->sn_vals[i].bv_len; *ptr++ = '\0'; } } op->o_tmpfree( sn, op->o_tmpmemctx ); sn = sn2; sn->sn_conn = op->o_conn->c_conn_idx; sn->sn_session = find_session_by_so( so->so_info->svi_max_percon, op->o_conn->c_conn_idx, so ); /* Insert into the AVL tree */ tavl_insert(&(so->so_tree), sn, node_insert, avl_dup_error); so->so_nentries++; /* Collected the keys so that they can be sorted. Thus, stop * the entry from propagating. */ rs->sr_err = LDAP_SUCCESS; } else if ( rs->sr_type == REP_RESULT ) { /* Remove serversort response callback. * We don't want the entries that we are about to send to be * processed by serversort response again. */ if ( op->o_callback->sc_response == sssvlv_op_response ) { op->o_callback = op->o_callback->sc_next; } send_entry( op, rs, so ); send_result( op, rs, so ); } return rs->sr_err; }
int do_modify( Operation *op, SlapReply *rs ) { struct berval dn = BER_BVNULL; char textbuf[ SLAP_TEXT_BUFLEN ]; size_t textlen = sizeof( textbuf ); #ifdef LDAP_DEBUG Modifications *tmp; #endif Debug( LDAP_DEBUG_TRACE, "%s do_modify\n", op->o_log_prefix, 0, 0 ); /* * Parse the modify request. It looks like this: * * ModifyRequest := [APPLICATION 6] SEQUENCE { * name DistinguishedName, * mods SEQUENCE OF SEQUENCE { * operation ENUMERATED { * add (0), * delete (1), * replace (2) * }, * modification SEQUENCE { * type AttributeType, * values SET OF AttributeValue * } * } * } */ if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); return SLAPD_DISCONNECT; } Debug( LDAP_DEBUG_ARGS, "%s do_modify: dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); rs->sr_err = slap_parse_modlist( op, rs, op->o_ber, &op->oq_modify ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: slap_parse_modlist failed err=%d msg=%s\n", op->o_log_prefix, rs->sr_err, rs->sr_text ); goto cleanup; } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); goto cleanup; } rs->sr_err = dnPrettyNormal( NULL, &dn, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx ); if( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_modify: invalid dn (%s)\n", op->o_log_prefix, dn.bv_val, 0 ); send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" ); goto cleanup; } op->orm_no_opattrs = 0; #ifdef LDAP_DEBUG Debug( LDAP_DEBUG_ARGS, "%s modifications:\n", op->o_log_prefix, 0, 0 ); for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) { Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n", tmp->sml_op == LDAP_MOD_ADD ? "add" : (tmp->sml_op == LDAP_MOD_INCREMENT ? "increment" : (tmp->sml_op == LDAP_MOD_DELETE ? "delete" : "replace")), tmp->sml_type.bv_val, 0 ); if ( tmp->sml_values == NULL ) { Debug( LDAP_DEBUG_ARGS, "%s\n", "\t\tno values", NULL, NULL ); } else if ( BER_BVISNULL( &tmp->sml_values[ 0 ] ) ) { Debug( LDAP_DEBUG_ARGS, "%s\n", "\t\tzero values", NULL, NULL ); } else if ( BER_BVISNULL( &tmp->sml_values[ 1 ] ) ) { Debug( LDAP_DEBUG_ARGS, "%s, length %ld\n", "\t\tone value", (long) tmp->sml_values[0].bv_len, NULL ); } else { Debug( LDAP_DEBUG_ARGS, "%s\n", "\t\tmultiple values", NULL, NULL ); } } if ( StatslogTest( LDAP_DEBUG_STATS ) ) { char abuf[BUFSIZ/2], *ptr = abuf; int len = 0; Statslog( LDAP_DEBUG_STATS, "%s MOD dn=\"%s\"\n", op->o_log_prefix, op->o_req_dn.bv_val, 0, 0, 0 ); for ( tmp = op->orm_modlist; tmp != NULL; tmp = tmp->sml_next ) { if (len + 1 + tmp->sml_type.bv_len > sizeof(abuf)) { Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); len = 0; ptr = abuf; if( 1 + tmp->sml_type.bv_len > sizeof(abuf)) { Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n", op->o_log_prefix, tmp->sml_type.bv_val, 0, 0, 0 ); continue; } } if (len) { *ptr++ = ' '; len++; } ptr = lutil_strcopy(ptr, tmp->sml_type.bv_val); len += tmp->sml_type.bv_len; } if (len) { Statslog( LDAP_DEBUG_STATS, "%s MOD attr=%s\n", op->o_log_prefix, abuf, 0, 0, 0 ); } } #endif /* LDAP_DEBUG */ rs->sr_err = slap_mods_check( op, op->orm_modlist, &rs->sr_text, textbuf, textlen, NULL ); if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_modify( op, rs ); #ifdef LDAP_X_TXN if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) { /* skip cleanup */ return rs->sr_err; } #endif cleanup: op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); if ( op->orm_modlist != NULL ) slap_mods_free( op->orm_modlist, 1 ); return rs->sr_err; }
void slapi_int_connection_done_pb( Slapi_PBlock *pb ) { Connection *conn; Operation *op; PBLOCK_ASSERT_INTOP( pb, 0 ); conn = pb->pb_conn; op = pb->pb_op; /* free allocated DNs */ if ( !BER_BVISNULL( &op->o_dn ) ) op->o_tmpfree( op->o_dn.bv_val, op->o_tmpmemctx ); if ( !BER_BVISNULL( &op->o_ndn ) ) op->o_tmpfree( op->o_ndn.bv_val, op->o_tmpmemctx ); if ( !BER_BVISNULL( &op->o_req_dn ) ) op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); if ( !BER_BVISNULL( &op->o_req_ndn ) ) op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); switch ( op->o_tag ) { case LDAP_REQ_MODRDN: if ( !BER_BVISNULL( &op->orr_newrdn )) op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx ); if ( !BER_BVISNULL( &op->orr_nnewrdn )) op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx ); if ( op->orr_newSup != NULL ) { assert( !BER_BVISNULL( op->orr_newSup ) ); op->o_tmpfree( op->orr_newSup->bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx ); } if ( op->orr_nnewSup != NULL ) { assert( !BER_BVISNULL( op->orr_nnewSup ) ); op->o_tmpfree( op->orr_nnewSup->bv_val, op->o_tmpmemctx ); op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx ); } slap_mods_free( op->orr_modlist, 1 ); break; case LDAP_REQ_ADD: slap_mods_free( op->ora_modlist, 0 ); break; case LDAP_REQ_MODIFY: slap_mods_free( op->orm_modlist, 1 ); break; case LDAP_REQ_SEARCH: if ( op->ors_attrs != NULL ) { op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx ); op->ors_attrs = NULL; } break; default: break; } slapi_ch_free_string( &conn->c_authmech.bv_val ); slapi_ch_free_string( &conn->c_dn.bv_val ); slapi_ch_free_string( &conn->c_ndn.bv_val ); slapi_ch_free_string( &conn->c_peer_domain.bv_val ); slapi_ch_free_string( &conn->c_peer_name.bv_val ); if ( conn->c_sb != NULL ) { ber_sockbuf_free( conn->c_sb ); } slapi_int_free_object_extensions( SLAPI_X_EXT_OPERATION, op ); slapi_int_free_object_extensions( SLAPI_X_EXT_CONNECTION, conn ); slapi_ch_free( (void **)&pb->pb_op->o_callback ); slapi_ch_free( (void **)&pb->pb_op ); slapi_ch_free( (void **)&pb->pb_conn ); slapi_ch_free( (void **)&pb->pb_rs ); }
/* 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_LUTIL_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 != 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; } } }
int slapi_add_internal_pb( Slapi_PBlock *pb ) { SlapReply *rs; Slapi_Entry *entry_orig = NULL; OpExtraDB oex; int rc; if ( pb == NULL ) { return -1; } PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_ADD ); rs = pb->pb_rs; entry_orig = pb->pb_op->ora_e; pb->pb_op->ora_e = NULL; /* * The caller can specify a new entry, or a target DN and set * of modifications, but not both. */ if ( entry_orig != NULL ) { if ( pb->pb_op->ora_modlist != NULL || !BER_BVISNULL( &pb->pb_op->o_req_ndn )) { rs->sr_err = LDAP_PARAM_ERROR; goto cleanup; } assert( BER_BVISNULL( &pb->pb_op->o_req_dn ) ); /* shouldn't get set */ ber_dupbv( &pb->pb_op->o_req_dn, &entry_orig->e_name ); ber_dupbv( &pb->pb_op->o_req_ndn, &entry_orig->e_nname ); } else if ( pb->pb_op->ora_modlist == NULL || BER_BVISNULL( &pb->pb_op->o_req_ndn )) { rs->sr_err = LDAP_PARAM_ERROR; goto cleanup; } pb->pb_op->ora_e = (Entry *)slapi_ch_calloc( 1, sizeof(Entry) ); ber_dupbv( &pb->pb_op->ora_e->e_name, &pb->pb_op->o_req_dn ); ber_dupbv( &pb->pb_op->ora_e->e_nname, &pb->pb_op->o_req_ndn ); if ( entry_orig != NULL ) { assert( pb->pb_op->ora_modlist == NULL ); rs->sr_err = slap_entry2mods( entry_orig, &pb->pb_op->ora_modlist, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { goto cleanup; } } else { assert( pb->pb_op->ora_modlist != NULL ); } rs->sr_err = slap_mods_check( pb->pb_op, pb->pb_op->ora_modlist, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ), NULL ); if ( rs->sr_err != LDAP_SUCCESS ) { goto cleanup; } /* Duplicate the values, because we may call slapi_entry_free() */ rs->sr_err = slap_mods2entry( pb->pb_op->ora_modlist, &pb->pb_op->ora_e, 1, 0, &rs->sr_text, pb->pb_textbuf, sizeof( pb->pb_textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { goto cleanup; } oex.oe.oe_key = (void *)do_add; oex.oe_db = NULL; LDAP_SLIST_INSERT_HEAD(&pb->pb_op->o_extra, &oex.oe, oe_next); rc = slapi_int_func_internal_pb( pb, op_add ); LDAP_SLIST_REMOVE(&pb->pb_op->o_extra, &oex.oe, OpExtra, oe_next); if ( !rc ) { if ( pb->pb_op->ora_e != NULL && oex.oe_db != NULL ) { BackendDB *bd = pb->pb_op->o_bd; pb->pb_op->o_bd = oex.oe_db; be_entry_release_w( pb->pb_op, pb->pb_op->ora_e ); pb->pb_op->ora_e = NULL; pb->pb_op->o_bd = bd; } } cleanup: if ( pb->pb_op->ora_e != NULL ) { slapi_entry_free( pb->pb_op->ora_e ); pb->pb_op->ora_e = NULL; } if ( entry_orig != NULL ) { pb->pb_op->ora_e = entry_orig; slap_mods_free( pb->pb_op->ora_modlist, 1 ); pb->pb_op->ora_modlist = NULL; } return 0; }
int do_extended( Operation *op, SlapReply *rs ) { struct berval reqdata = {0, NULL}; ber_len_t len; Debug( LDAP_DEBUG_TRACE, "%s do_extended\n", op->o_log_prefix, 0, 0 ); if( op->o_protocol < LDAP_VERSION3 ) { Debug( LDAP_DEBUG_ANY, "%s do_extended: protocol version (%d) too low\n", op->o_log_prefix, op->o_protocol, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "requires LDAPv3" ); rs->sr_err = SLAPD_DISCONNECT; goto done; } if ( ber_scanf( op->o_ber, "{m" /*}*/, &op->ore_reqoid ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_extended: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto done; } if( ber_peek_tag( op->o_ber, &len ) == LDAP_TAG_EXOP_REQ_VALUE ) { if( ber_scanf( op->o_ber, "m", &reqdata ) == LBER_ERROR ) { Debug( LDAP_DEBUG_ANY, "%s do_extended: ber_scanf failed\n", op->o_log_prefix, 0, 0 ); send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" ); rs->sr_err = SLAPD_DISCONNECT; goto done; } } if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s do_extended: get_ctrls failed\n", op->o_log_prefix, 0, 0 ); return rs->sr_err; } Statslog( LDAP_DEBUG_STATS, "%s EXT oid=%s\n", op->o_log_prefix, op->ore_reqoid.bv_val, 0, 0, 0 ); /* check for controls inappropriate for all extended operations */ if( get_manageDSAit( op ) == SLAP_CONTROL_CRITICAL ) { send_ldap_error( op, rs, LDAP_UNAVAILABLE_CRITICAL_EXTENSION, "manageDSAit control inappropriate" ); goto done; } /* FIXME: temporary? */ if ( reqdata.bv_val ) { op->ore_reqdata = &reqdata; } op->o_bd = frontendDB; rs->sr_err = frontendDB->be_extended( op, rs ); /* clean up in case some overlay set them? */ if ( !BER_BVISNULL( &op->o_req_ndn ) ) { if ( !BER_BVISNULL( &op->o_req_dn ) && op->o_req_ndn.bv_val != op->o_req_dn.bv_val ) { op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); } op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &op->o_req_dn ); BER_BVZERO( &op->o_req_ndn ); } done: return rs->sr_err; }
static int test_ava_vrFilter( Operation *op, Attribute *a, AttributeAssertion *ava, int type, char ***e_flags ) { int i, j; for ( i=0; a != NULL; a = a->a_next, i++ ) { MatchingRule *mr; struct berval *bv; if ( !is_ad_subtype( a->a_desc, ava->aa_desc ) ) { continue; } switch ( type ) { case LDAP_FILTER_APPROX: mr = a->a_desc->ad_type->sat_approx; if( mr != NULL ) break; /* use EQUALITY matching rule if no APPROX rule */ case LDAP_FILTER_EQUALITY: mr = a->a_desc->ad_type->sat_equality; break; case LDAP_FILTER_GE: case LDAP_FILTER_LE: mr = a->a_desc->ad_type->sat_ordering; break; default: mr = NULL; } if( mr == NULL ) continue; bv = a->a_nvals; for ( j=0; !BER_BVISNULL( bv ); bv++, j++ ) { int rc, match; const char *text; rc = value_match( &match, a->a_desc, mr, 0, bv, &ava->aa_value, &text ); if( rc != LDAP_SUCCESS ) return rc; switch ( type ) { case LDAP_FILTER_EQUALITY: case LDAP_FILTER_APPROX: if ( match == 0 ) { (*e_flags)[i][j] = 1; } break; case LDAP_FILTER_GE: if ( match >= 0 ) { (*e_flags)[i][j] = 1; } break; case LDAP_FILTER_LE: if ( match <= 0 ) { (*e_flags)[i][j] = 1; } break; } } } return LDAP_SUCCESS; }
static int dupent_parseCtrl ( Operation *op, SlapReply *rs, LDAPControl *ctrl ) { ber_tag_t tag; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_len_t len; BerVarray AttributeDescriptionList = NULL; ber_len_t cnt = sizeof(struct berval); ber_len_t off = 0; ber_int_t PartialApplicationAllowed = 1; dupent_t *ds = NULL; int i; if ( op->o_dupent != SLAP_CONTROL_NONE ) { rs->sr_text = "Dupent control specified multiple times"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISNULL( &ctrl->ldctl_value ) ) { rs->sr_text = "Dupent control value is absent"; return LDAP_PROTOCOL_ERROR; } if ( BER_BVISEMPTY( &ctrl->ldctl_value ) ) { rs->sr_text = "Dupent control value is empty"; return LDAP_PROTOCOL_ERROR; } ber_init2( ber, &ctrl->ldctl_value, 0 ); /* DuplicateEntryRequest ::= SEQUENCE { AttributeDescriptionList, -- from [RFC2251] PartialApplicationAllowed BOOLEAN DEFAULT TRUE } AttributeDescriptionList ::= SEQUENCE OF AttributeDescription AttributeDescription ::= LDAPString attributeDescription = AttributeType [ ";" <options> ] */ tag = ber_skip_tag( ber, &len ); if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; if ( ber_scanf( ber, "{M}", &AttributeDescriptionList, &cnt, off ) == LBER_ERROR ) { rs->sr_text = "Dupent control: dupentSpec decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_skip_tag( ber, &len ); if ( tag == LBER_BOOLEAN ) { /* NOTE: PartialApplicationAllowed is ignored, since the control * can always be honored */ if ( ber_scanf( ber, "b", &PartialApplicationAllowed ) == LBER_ERROR ) { rs->sr_text = "Dupent control: dupentSpec decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_skip_tag( ber, &len ); } if ( len || tag != LBER_DEFAULT ) { rs->sr_text = "Dupent control: dupentSpec decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } ds = (dupent_t *)op->o_tmpcalloc( 1, sizeof(dupent_t) + sizeof(AttributeName)*cnt, op->o_tmpmemctx ); ds->ds_paa = PartialApplicationAllowed; if ( cnt == 0 ) { ds->ds_flags |= SLAP_USERATTRS_YES; } else { int c; ds->ds_an = (AttributeName *)&ds[ 1 ]; for ( i = 0, c = 0; i < cnt; i++ ) { const char *text; int j; int rc; AttributeDescription *ad = NULL; if ( bvmatch( &AttributeDescriptionList[i], slap_bv_all_user_attrs ) ) { if ( ds->ds_flags & SLAP_USERATTRS_YES ) { rs->sr_text = "Dupent control: AttributeDescription decoding error"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } ds->ds_flags |= SLAP_USERATTRS_YES; continue; } rc = slap_bv2ad( &AttributeDescriptionList[i], &ad, &text ); if ( rc != LDAP_SUCCESS ) { continue; } ds->ds_an[c].an_desc = ad; ds->ds_an[c].an_name = ad->ad_cname; /* FIXME: not specified; consider this an error, just in case */ for ( j = 0; j < c; j++ ) { if ( ds->ds_an[c].an_desc == ds->ds_an[j].an_desc ) { rs->sr_text = "Dupent control: AttributeDescription must be unique within AttributeDescriptionList"; rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } c++; } ds->ds_nattrs = c; if ( ds->ds_flags & SLAP_USERATTRS_YES ) { /* purge user attrs */ for ( i = 0; i < ds->ds_nattrs; ) { if ( is_at_operational( ds->ds_an[i].an_desc->ad_type ) ) { i++; continue; } ds->ds_nattrs--; if ( i < ds->ds_nattrs ) { ds->ds_an[i] = ds->ds_an[ds->ds_nattrs]; } } } } op->o_ctrldupent = (void *)ds; op->o_dupent = ctrl->ldctl_iscritical ? SLAP_CONTROL_CRITICAL : SLAP_CONTROL_NONCRITICAL; rs->sr_err = LDAP_SUCCESS; done:; if ( rs->sr_err != LDAP_SUCCESS ) { op->o_tmpfree( ds, op->o_tmpmemctx ); } if ( AttributeDescriptionList != NULL ) { ber_memfree_x( AttributeDescriptionList, op->o_tmpmemctx ); } return rs->sr_err; }
static int test_mra_vrFilter( Operation *op, Attribute *a, MatchingRuleAssertion *mra, char ***e_flags ) { int i, j; for ( i = 0; a != NULL; a = a->a_next, i++ ) { struct berval *bv, assertedValue; int normalize_attribute = 0; if ( mra->ma_desc ) { if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) { continue; } assertedValue = mra->ma_value; } else { int rc; const char *text = NULL; /* check if matching is appropriate */ if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) { continue; } rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule, SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, &mra->ma_value, &assertedValue, &text, op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) continue; } /* check match */ if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) { bv = a->a_nvals; } else { bv = a->a_vals; normalize_attribute = 1; } for ( j = 0; !BER_BVISNULL( bv ); bv++, j++ ) { int rc, match; const char *text; struct berval nbv = BER_BVNULL; if ( normalize_attribute && mra->ma_rule->smr_normalize ) { /* see comment in filterentry.c */ if ( mra->ma_rule->smr_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, mra->ma_rule->smr_syntax, mra->ma_rule, bv, &nbv, op->o_tmpmemctx ) != LDAP_SUCCESS ) { /* FIXME: stop processing? */ continue; } } else { nbv = *bv; } rc = value_match( &match, a->a_desc, mra->ma_rule, 0, &nbv, &assertedValue, &text ); if ( nbv.bv_val != bv->bv_val ) { op->o_tmpfree( nbv.bv_val, op->o_tmpmemctx ); } if ( rc != LDAP_SUCCESS ) return rc; if ( match == 0 ) { (*e_flags)[i][j] = 1; } } } return LDAP_SUCCESS; }
static int constraint_cf_gen( ConfigArgs *c ) { slap_overinst *on = (slap_overinst *)(c->bi); constraint *cn = on->on_bi.bi_private, *cp; struct berval bv; int i, rc = 0; constraint ap = { NULL }; const char *text = NULL; switch ( c->op ) { case SLAP_CONFIG_EMIT: switch (c->type) { case CONSTRAINT_ATTRIBUTE: for (cp=cn; cp; cp=cp->ap_next) { char *s; char *tstr = NULL; int quotes = 0, numeric = 0; int j; size_t val = 0; char val_buf[SLAP_TEXT_BUFLEN] = { '\0' }; bv.bv_len = STRLENOF(" "); for (j = 0; cp->ap[j]; j++) { bv.bv_len += cp->ap[j]->ad_cname.bv_len; } /* room for commas */ bv.bv_len += j - 1; switch (cp->type) { case CONSTRAINT_COUNT: tstr = COUNT_STR; val = cp->count; numeric = 1; break; case CONSTRAINT_SIZE: tstr = SIZE_STR; val = cp->size; numeric = 1; break; case CONSTRAINT_REGEX: tstr = REGEX_STR; quotes = 1; break; case CONSTRAINT_SET: tstr = SET_STR; quotes = 1; break; case CONSTRAINT_URI: tstr = URI_STR; quotes = 1; break; default: abort(); } bv.bv_len += strlen(tstr); bv.bv_len += cp->val.bv_len + 2*quotes; if (cp->restrict_lud != NULL) { bv.bv_len += cp->restrict_val.bv_len + STRLENOF(" restrict=\"\""); } if (numeric) { int len = snprintf(val_buf, sizeof(val_buf), "%zu", val); if (len <= 0) { /* error */ return -1; } bv.bv_len += len; } s = bv.bv_val = ch_malloc(bv.bv_len + 1); s = lutil_strncopy( s, cp->ap[0]->ad_cname.bv_val, cp->ap[0]->ad_cname.bv_len ); for (j = 1; cp->ap[j]; j++) { *s++ = ','; s = lutil_strncopy( s, cp->ap[j]->ad_cname.bv_val, cp->ap[j]->ad_cname.bv_len ); } *s++ = ' '; s = lutil_strcopy( s, tstr ); *s++ = ' '; if (numeric) { s = lutil_strcopy( s, val_buf ); } else { if ( quotes ) *s++ = '"'; s = lutil_strncopy( s, cp->val.bv_val, cp->val.bv_len ); if ( quotes ) *s++ = '"'; } if (cp->restrict_lud != NULL) { s = lutil_strcopy( s, " restrict=\"" ); s = lutil_strncopy( s, cp->restrict_val.bv_val, cp->restrict_val.bv_len ); *s++ = '"'; } *s = '\0'; rc = value_add_one( &c->rvalue_vals, &bv ); if (rc == LDAP_SUCCESS) rc = value_add_one( &c->rvalue_nvals, &bv ); ch_free(bv.bv_val); if (rc) return rc; } break; default: abort(); break; } break; case LDAP_MOD_DELETE: switch (c->type) { case CONSTRAINT_ATTRIBUTE: if (!cn) break; /* nothing to do */ if (c->valx < 0) { /* zap all constraints */ while (cn) { cp = cn->ap_next; constraint_free( cn, 1 ); cn = cp; } on->on_bi.bi_private = NULL; } else { constraint **cpp; /* zap constraint numbered 'valx' */ for(i=0, cp = cn, cpp = &cn; (cp) && (i<c->valx); i++, cpp = &cp->ap_next, cp = *cpp); if (cp) { /* zap cp, and join cpp to cp->ap_next */ *cpp = cp->ap_next; constraint_free( cp, 1 ); } on->on_bi.bi_private = cn; } break; default: abort(); break; } break; case SLAP_CONFIG_ADD: case LDAP_MOD_ADD: switch (c->type) { case CONSTRAINT_ATTRIBUTE: { int j; char **attrs = ldap_str2charray( c->argv[1], "," ); for ( j = 0; attrs[j]; j++) /* just count */ ; ap.ap = ch_calloc( sizeof(AttributeDescription*), j + 1 ); for ( j = 0; attrs[j]; j++) { if ( slap_str2ad( attrs[j], &ap.ap[j], &text ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s\n", c->argv[0], attrs[j], text ); rc = ARG_BAD_CONF; goto done; } } if ( strcasecmp( c->argv[2], REGEX_STR ) == 0) { int err; ap.type = CONSTRAINT_REGEX; ap.re = ch_malloc( sizeof(regex_t) ); if ((err = regcomp( ap.re, c->argv[3], REG_EXTENDED )) != 0) { char errmsg[1024]; regerror( err, ap.re, errmsg, sizeof(errmsg) ); ch_free(ap.re); snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: Illegal regular expression \"%s\": Error %s", c->argv[0], c->argv[1], c->argv[3], errmsg); ap.re = NULL; rc = ARG_BAD_CONF; goto done; } ber_str2bv( c->argv[3], 0, 1, &ap.val ); } else if ( strcasecmp( c->argv[2], SIZE_STR ) == 0 ) { char *endptr; ap.type = CONSTRAINT_SIZE; ap.size = strtoull(c->argv[3], &endptr, 10); if ( *endptr ) rc = ARG_BAD_CONF; } else if ( strcasecmp( c->argv[2], COUNT_STR ) == 0 ) { char *endptr; ap.type = CONSTRAINT_COUNT; ap.count = strtoull(c->argv[3], &endptr, 10); if ( *endptr ) rc = ARG_BAD_CONF; } else if ( strcasecmp( c->argv[2], URI_STR ) == 0 ) { int err; ap.type = CONSTRAINT_URI; err = ldap_url_parse(c->argv[3], &ap.lud); if ( err != LDAP_URL_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: Invalid URI \"%s\"", c->argv[0], c->argv[1], c->argv[3]); rc = ARG_BAD_CONF; goto done; } if (ap.lud->lud_host != NULL) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: unsupported hostname in URI \"%s\"", c->argv[0], c->argv[1], c->argv[3]); ldap_free_urldesc(ap.lud); rc = ARG_BAD_CONF; goto done; } for ( i=0; ap.lud->lud_attrs[i]; i++); /* FIXME: This is worthless without at least one attr */ if ( i ) { ap.attrs = ch_malloc( (i+1)*sizeof(AttributeDescription *)); for ( i=0; ap.lud->lud_attrs[i]; i++) { ap.attrs[i] = NULL; if ( slap_str2ad( ap.lud->lud_attrs[i], &ap.attrs[i], &text ) ) { ch_free( ap.attrs ); snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s <%s>: %s\n", c->argv[0], ap.lud->lud_attrs[i], text ); rc = ARG_BAD_CONF; goto done; } } ap.attrs[i] = NULL; } if (ap.lud->lud_dn == NULL) { ap.lud->lud_dn = ch_strdup(""); } else { struct berval dn, ndn; ber_str2bv( ap.lud->lud_dn, 0, 0, &dn ); if (dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) ) { /* cleanup */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: URI %s DN normalization failed", c->argv[0], c->argv[1], c->argv[3] ); Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", c->log, c->cr_msg ); rc = ARG_BAD_CONF; goto done; } ldap_memfree( ap.lud->lud_dn ); ap.lud->lud_dn = ndn.bv_val; } if (ap.lud->lud_filter == NULL) { ap.lud->lud_filter = ch_strdup("objectClass=*"); } else if ( ap.lud->lud_filter[0] == '(' ) { ber_len_t len = strlen( ap.lud->lud_filter ); if ( ap.lud->lud_filter[len - 1] != ')' ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: invalid URI filter: %s", c->argv[0], c->argv[1], ap.lud->lud_filter ); rc = ARG_BAD_CONF; goto done; } memmove( &ap.lud->lud_filter[0], &ap.lud->lud_filter[1], len - 2 ); ap.lud->lud_filter[len - 2] = '\0'; } ber_str2bv( c->argv[3], 0, 1, &ap.val ); } else if ( strcasecmp( c->argv[2], SET_STR ) == 0 ) { ap.set = 1; ber_str2bv( c->argv[3], 0, 1, &ap.val ); ap.type = CONSTRAINT_SET; } else { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: Unknown constraint type: %s", c->argv[0], c->argv[1], c->argv[2] ); rc = ARG_BAD_CONF; goto done; } if ( c->argc > 4 ) { int argidx; for ( argidx = 4; argidx < c->argc; argidx++ ) { if ( strncasecmp( c->argv[argidx], "restrict=", STRLENOF("restrict=") ) == 0 ) { int err; char *arg = c->argv[argidx] + STRLENOF("restrict="); err = ldap_url_parse(arg, &ap.restrict_lud); if ( err != LDAP_URL_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: Invalid restrict URI \"%s\"", c->argv[0], c->argv[1], arg); rc = ARG_BAD_CONF; goto done; } if (ap.restrict_lud->lud_host != NULL) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: unsupported hostname in restrict URI \"%s\"", c->argv[0], c->argv[1], arg); rc = ARG_BAD_CONF; goto done; } if ( ap.restrict_lud->lud_attrs != NULL ) { if ( ap.restrict_lud->lud_attrs[0] != '\0' ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: attrs not allowed in restrict URI %s\n", c->argv[0], c->argv[1], arg); rc = ARG_BAD_CONF; goto done; } ldap_memvfree((void *)ap.restrict_lud->lud_attrs); ap.restrict_lud->lud_attrs = NULL; } if (ap.restrict_lud->lud_dn != NULL) { if (ap.restrict_lud->lud_dn[0] == '\0') { ldap_memfree(ap.restrict_lud->lud_dn); ap.restrict_lud->lud_dn = NULL; } else { struct berval dn, ndn; int j; ber_str2bv(ap.restrict_lud->lud_dn, 0, 0, &dn); if (dnNormalize(0, NULL, NULL, &dn, &ndn, NULL)) { /* cleanup */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: restrict URI %s DN normalization failed", c->argv[0], c->argv[1], arg ); rc = ARG_BAD_CONF; goto done; } assert(c->be != NULL); if (c->be->be_nsuffix == NULL) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: restrict URI requires suffix", c->argv[0], c->argv[1] ); rc = ARG_BAD_CONF; goto done; } for ( j = 0; !BER_BVISNULL(&c->be->be_nsuffix[j]); j++) { if (dnIsSuffix(&ndn, &c->be->be_nsuffix[j])) break; } if (BER_BVISNULL(&c->be->be_nsuffix[j])) { /* error */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: restrict URI DN %s not within database naming context(s)", c->argv[0], c->argv[1], dn.bv_val ); rc = ARG_BAD_CONF; goto done; } ap.restrict_ndn = ndn; } } if (ap.restrict_lud->lud_filter != NULL) { ap.restrict_filter = str2filter(ap.restrict_lud->lud_filter); if (ap.restrict_filter == NULL) { /* error */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: restrict URI filter %s invalid", c->argv[0], c->argv[1], ap.restrict_lud->lud_filter ); rc = ARG_BAD_CONF; goto done; } } ber_str2bv(c->argv[argidx] + STRLENOF("restrict="), 0, 1, &ap.restrict_val); } else { /* cleanup */ snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s %s: unrecognized arg #%d (%s)", c->argv[0], c->argv[1], argidx, c->argv[argidx] ); rc = ARG_BAD_CONF; goto done; } } } done:; if ( rc == LDAP_SUCCESS ) { constraint *a2 = ch_calloc( sizeof(constraint), 1 ); a2->ap_next = on->on_bi.bi_private; a2->ap = ap.ap; a2->type = ap.type; a2->re = ap.re; a2->val = ap.val; a2->lud = ap.lud; a2->set = ap.set; a2->size = ap.size; a2->count = ap.count; if ( a2->lud ) { ber_str2bv(a2->lud->lud_dn, 0, 0, &a2->dn); ber_str2bv(a2->lud->lud_filter, 0, 0, &a2->filter); } a2->attrs = ap.attrs; a2->restrict_lud = ap.restrict_lud; a2->restrict_ndn = ap.restrict_ndn; a2->restrict_filter = ap.restrict_filter; a2->restrict_val = ap.restrict_val; on->on_bi.bi_private = a2; } else { Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", c->log, c->cr_msg ); constraint_free( &ap, 0 ); } ldap_memvfree((void**)attrs); } break; default: abort(); break; } break; default: abort(); } return rc; }
static int aa_operational( Operation *op, SlapReply *rs ) { Attribute *a, **ap; AccessControlState acl_state = ACL_STATE_INIT; struct berval *v; AttributeType **atp = NULL; ObjectClass **ocp = NULL; #define GOT_NONE (0x0U) #define GOT_C (0x1U) #define GOT_CE (0x2U) #define GOT_A (0x4U) #define GOT_AE (0x8U) #define GOT_ALL (GOT_C|GOT_CE|GOT_A|GOT_AE) int got = GOT_NONE; /* only add if requested */ if ( SLAP_OPATTRS( rs->sr_attr_flags ) ) { got = GOT_ALL; } else { if ( ad_inlist( ad_allowedChildClasses, rs->sr_attrs ) ) { got |= GOT_C; } if ( ad_inlist( ad_allowedChildClassesEffective, rs->sr_attrs ) ) { got |= GOT_CE; } if ( ad_inlist( ad_allowedAttributes, rs->sr_attrs ) ) { got |= GOT_A; } if ( ad_inlist( ad_allowedAttributesEffective, rs->sr_attrs ) ) { got |= GOT_AE; } } if ( got == GOT_NONE ) { return SLAP_CB_CONTINUE; } /* shouldn't be called without an entry; please check */ assert( rs->sr_entry != NULL ); for ( ap = &rs->sr_operational_attrs; *ap != NULL; ap = &(*ap)->a_next ) /* go to last */ ; /* see caveats; this is not guaranteed for all backends */ a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_objectClass ); if ( a == NULL ) { goto do_oc; } /* if client has no access to objectClass attribute; don't compute */ if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass, NULL, ACL_READ, &acl_state ) ) { return SLAP_CB_CONTINUE; } for ( v = a->a_nvals; !BER_BVISNULL( v ); v++ ) { ObjectClass *oc = oc_bvfind( v ); assert( oc != NULL ); /* if client has no access to specific value, don't compute */ if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass, &oc->soc_cname, ACL_READ, &acl_state ) ) { continue; } aa_add_oc( oc, &ocp, &atp ); if ( oc->soc_sups ) { int i; for ( i = 0; oc->soc_sups[ i ] != NULL; i++ ) { aa_add_oc( oc->soc_sups[ i ], &ocp, &atp ); } } } ch_free( ocp ); if ( atp != NULL ) { BerVarray bv_allowed = NULL, bv_effective = NULL; int i, ja = 0, je = 0; for ( i = 0; atp[ i ] != NULL; i++ ) /* just count */ ; if ( got & GOT_A ) { bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) ); } if ( got & GOT_AE ) { bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) ); } for ( i = 0, ja = 0, je = 0; atp[ i ] != NULL; i++ ) { if ( got & GOT_A ) { ber_dupbv( &bv_allowed[ ja ], &atp[ i ]->sat_cname ); ja++; } if ( got & GOT_AE ) { AttributeDescription *ad = NULL; const char *text = NULL; if ( slap_bv2ad( &atp[ i ]->sat_cname, &ad, &text ) ) { /* log? */ continue; } if ( access_allowed( op, rs->sr_entry, ad, NULL, ACL_WRITE, NULL ) ) { ber_dupbv( &bv_effective[ je ], &atp[ i ]->sat_cname ); je++; } } } ch_free( atp ); if ( ( got & GOT_A ) && ja > 0 ) { BER_BVZERO( &bv_allowed[ ja ] ); *ap = attr_alloc( ad_allowedAttributes ); (*ap)->a_vals = bv_allowed; (*ap)->a_nvals = bv_allowed; (*ap)->a_numvals = ja; ap = &(*ap)->a_next; } if ( ( got & GOT_AE ) && je > 0 ) { BER_BVZERO( &bv_effective[ je ] ); *ap = attr_alloc( ad_allowedAttributesEffective ); (*ap)->a_vals = bv_effective; (*ap)->a_nvals = bv_effective; (*ap)->a_numvals = je; ap = &(*ap)->a_next; } *ap = NULL; } do_oc:; if ( ( got & GOT_C ) || ( got & GOT_CE ) ) { BerVarray bv_allowed = NULL, bv_effective = NULL; int i, ja = 0, je = 0; ObjectClass *oc; for ( oc_start( &oc ); oc != NULL; oc_next( &oc ) ) { /* we can only add AUXILIARY objectClasses */ if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) { continue; } i++; } if ( got & GOT_C ) { bv_allowed = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) ); } if ( got & GOT_CE ) { bv_effective = ber_memalloc( sizeof( struct berval ) * ( i + 1 ) ); } for ( oc_start( &oc ); oc != NULL; oc_next( &oc ) ) { /* we can only add AUXILIARY objectClasses */ if ( oc->soc_kind != LDAP_SCHEMA_AUXILIARY ) { continue; } if ( got & GOT_C ) { ber_dupbv( &bv_allowed[ ja ], &oc->soc_cname ); ja++; } if ( got & GOT_CE ) { if ( !access_allowed( op, rs->sr_entry, slap_schema.si_ad_objectClass, &oc->soc_cname, ACL_WRITE, NULL ) ) { goto done_ce; } if ( oc->soc_required ) { for ( i = 0; oc->soc_required[ i ] != NULL; i++ ) { AttributeDescription *ad = NULL; const char *text = NULL; if ( slap_bv2ad( &oc->soc_required[ i ]->sat_cname, &ad, &text ) ) { /* log? */ continue; } if ( !access_allowed( op, rs->sr_entry, ad, NULL, ACL_WRITE, NULL ) ) { goto done_ce; } } } ber_dupbv( &bv_effective[ je ], &oc->soc_cname ); je++; } done_ce:; } if ( ( got & GOT_C ) && ja > 0 ) { BER_BVZERO( &bv_allowed[ ja ] ); *ap = attr_alloc( ad_allowedChildClasses ); (*ap)->a_vals = bv_allowed; (*ap)->a_nvals = bv_allowed; (*ap)->a_numvals = ja; ap = &(*ap)->a_next; } if ( ( got & GOT_CE ) && je > 0 ) { BER_BVZERO( &bv_effective[ je ] ); *ap = attr_alloc( ad_allowedChildClassesEffective ); (*ap)->a_vals = bv_effective; (*ap)->a_nvals = bv_effective; (*ap)->a_numvals = je; ap = &(*ap)->a_next; } *ap = NULL; } return SLAP_CB_CONTINUE; }
static int ldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent, struct berval *bdn ) { struct berval a; BerElement ber = *ldap_get_message_ber( e ); Attribute *attr, **attrp; const char *text; int last; char *lastb; ber_len_t len; /* safe assumptions ... */ assert( ent != NULL ); BER_BVZERO( &ent->e_bv ); if ( ber_scanf( &ber, "{m", bdn ) == LBER_ERROR ) { return LDAP_DECODING_ERROR; } /* * Note: this may fail if the target host(s) schema differs * from the one known to the meta, and a DN with unknown * attributes is returned. * * FIXME: should we log anything, or delegate to dnNormalize? */ /* Note: if the distinguished values or the naming attributes * change, should we massage them as well? */ if ( dnPrettyNormal( NULL, bdn, &ent->e_name, &ent->e_nname, op->o_tmpmemctx ) != LDAP_SUCCESS ) { return LDAP_INVALID_DN_SYNTAX; } ent->e_attrs = NULL; if ( ber_first_element( &ber, &len, &lastb ) != LBER_SEQUENCE ) { return LDAP_SUCCESS; } attrp = &ent->e_attrs; while ( ber_next_element( &ber, &len, lastb ) == LBER_SEQUENCE && ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) { int i; slap_syntax_validate_func *validate; slap_syntax_transform_func *pretty; attr = attr_alloc( NULL ); if ( attr == NULL ) { return LDAP_OTHER; } if ( slap_bv2ad( &a, &attr->a_desc, &text ) != LDAP_SUCCESS ) { if ( slap_bv2undef_ad( &a, &attr->a_desc, &text, SLAP_AD_PROXIED ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "%s ldap_build_entry: " "slap_bv2undef_ad(%s): %s\n", op->o_log_prefix, a.bv_val, text ); ( void )ber_scanf( &ber, "x" /* [W] */ ); attr_free( attr ); continue; } } /* no subschemaSubentry */ if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry || attr->a_desc == slap_schema.si_ad_entryDN ) { /* * We eat target's subschemaSubentry because * a search for this value is likely not * to resolve to the appropriate backend; * later, the local subschemaSubentry is * added. * * We also eat entryDN because the frontend * will reattach it without checking if already * present... */ ( void )ber_scanf( &ber, "x" /* [W] */ ); attr_free( attr ); continue; } if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR || attr->a_vals == NULL ) { /* * Note: attr->a_vals can be null when using * values result filter */ attr->a_vals = (struct berval *)&slap_dummy_bv; } validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate; pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty; if ( !validate && !pretty ) { attr->a_nvals = NULL; attr_free( attr ); goto next_attr; } for ( i = 0; !BER_BVISNULL( &attr->a_vals[i] ); i++ ) ; last = i; /* * check that each value is valid per syntax * and pretty if appropriate */ for ( i = 0; i<last; i++ ) { struct berval pval; int rc; if ( pretty ) { rc = ordered_value_pretty( attr->a_desc, &attr->a_vals[i], &pval, NULL ); } else { rc = ordered_value_validate( attr->a_desc, &attr->a_vals[i], 0 ); } if ( rc != LDAP_SUCCESS ) { ObjectClass *oc; /* 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 ) { ber_dupbv( &pval, &oc->soc_cname ); rc = LDAP_SUCCESS; } else { ber_memfree( attr->a_vals[i].bv_val ); if ( --last == i ) { BER_BVZERO( &attr->a_vals[i] ); break; } attr->a_vals[i] = attr->a_vals[last]; BER_BVZERO( &attr->a_vals[last] ); i--; } } if ( rc == LDAP_SUCCESS && pretty ) { ber_memfree( attr->a_vals[i].bv_val ); attr->a_vals[i] = pval; } } attr->a_numvals = last = i; if ( last == 0 && attr->a_vals != &slap_dummy_bv ) { attr->a_nvals = NULL; attr_free( attr ); goto next_attr; } if ( last && attr->a_desc->ad_type->sat_equality && attr->a_desc->ad_type->sat_equality->smr_normalize ) { attr->a_nvals = ch_malloc( ( last + 1 )*sizeof( struct berval ) ); for ( i = 0; i < last; i++ ) { int rc; rc = ordered_value_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, attr->a_desc, attr->a_desc->ad_type->sat_equality, &attr->a_vals[i], &attr->a_nvals[i], NULL ); if ( rc != LDAP_SUCCESS ) { ber_memfree( attr->a_vals[i].bv_val ); if ( --last == i ) { BER_BVZERO( &attr->a_vals[i] ); break; } attr->a_vals[i] = attr->a_vals[last]; BER_BVZERO( &attr->a_vals[last] ); i--; } } BER_BVZERO( &attr->a_nvals[i] ); if ( last == 0 ) { attr_free( attr ); goto next_attr; } } else { attr->a_nvals = attr->a_vals; } attr->a_numvals = last; /* Handle sorted vals, strip dups but keep the attr */ if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { while ( attr->a_numvals > 1 ) { int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx ); if ( rc != LDAP_TYPE_OR_VALUE_EXISTS ) break; /* Strip duplicate values */ if ( attr->a_nvals != attr->a_vals ) ber_memfree( attr->a_nvals[i].bv_val ); ber_memfree( attr->a_vals[i].bv_val ); attr->a_numvals--; assert( i >= 0 ); if ( (unsigned)i < attr->a_numvals ) { attr->a_vals[i] = attr->a_vals[attr->a_numvals]; if ( attr->a_nvals != attr->a_vals ) attr->a_nvals[i] = attr->a_nvals[attr->a_numvals]; } BER_BVZERO(&attr->a_vals[attr->a_numvals]); if ( attr->a_nvals != attr->a_vals ) BER_BVZERO(&attr->a_nvals[attr->a_numvals]); } attr->a_flags |= SLAP_ATTR_SORTED_VALS; } *attrp = attr; attrp = &attr->a_next; next_attr:; } return LDAP_SUCCESS; }
int slap_send_search_reference( Operation *op, SlapReply *rs ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *) &berbuf; int rc = 0; int bytes; char *edn = rs->sr_entry ? rs->sr_entry->e_name.bv_val : "(null)"; AttributeDescription *ad_ref = slap_schema.si_ad_ref; AttributeDescription *ad_entry = slap_schema.si_ad_entry; rs->sr_type = REP_SEARCHREF; if ( op->o_callback ) { rc = slap_response_play( op, rs ); if ( rc != SLAP_CB_CONTINUE ) { goto rel; } } Debug( LDAP_DEBUG_TRACE, "=> send_search_reference: dn=\"%s\"\n", edn, 0, 0 ); if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, ad_entry, NULL, ACL_READ, NULL ) ) { Debug( LDAP_DEBUG_ACL, "send_search_reference: access to entry not allowed\n", 0, 0, 0 ); rc = 1; goto rel; } if ( rs->sr_entry && ! access_allowed( op, rs->sr_entry, ad_ref, NULL, ACL_READ, NULL ) ) { Debug( LDAP_DEBUG_ACL, "send_search_reference: access " "to reference not allowed\n", 0, 0, 0 ); rc = 1; goto rel; } if( op->o_domain_scope ) { Debug( LDAP_DEBUG_ANY, "send_search_reference: domainScope control in (%s)\n", edn, 0, 0 ); rc = 0; goto rel; } if( rs->sr_ref == NULL ) { Debug( LDAP_DEBUG_ANY, "send_search_reference: null ref in (%s)\n", edn, 0, 0 ); rc = 1; goto rel; } if( op->o_protocol < LDAP_VERSION3 ) { rc = 0; /* save the references for the result */ if( rs->sr_ref[0].bv_val != NULL ) { if( value_add( &rs->sr_v2ref, rs->sr_ref ) ) rc = LDAP_OTHER; } goto rel; } #ifdef LDAP_CONNECTIONLESS if( op->o_conn && op->o_conn->c_is_udp ) { ber = op->o_res_ber; } else #endif { ber_init_w_nullc( ber, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); } rc = ber_printf( ber, "{it{W}" /*"}"*/ , op->o_msgid, LDAP_RES_SEARCH_REFERENCE, rs->sr_ref ); if( rc != -1 ) { rc = send_ldap_controls( op, ber, rs->sr_ctrls ); } if( rc != -1 ) { rc = ber_printf( ber, /*"{"*/ "N}" ); } if ( rc == -1 ) { Debug( LDAP_DEBUG_ANY, "send_search_reference: ber_printf failed\n", 0, 0, 0 ); #ifdef LDAP_CONNECTIONLESS if (!op->o_conn || op->o_conn->c_is_udp == 0) #endif ber_free_buf( ber ); send_ldap_error( op, rs, LDAP_OTHER, "encode DN error" ); goto rel; } rc = 0; if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { assert( rs->sr_entry != NULL ); be_entry_release_rw( op, rs->sr_entry, 0 ); rs->sr_flags ^= REP_ENTRY_MUSTRELEASE; rs->sr_entry = NULL; } #ifdef LDAP_CONNECTIONLESS if (!op->o_conn || op->o_conn->c_is_udp == 0) { #endif bytes = send_ldap_ber( op, ber ); ber_free_buf( ber ); if ( bytes < 0 ) { rc = LDAP_UNAVAILABLE; } else { ldap_pvt_thread_mutex_lock( &op->o_counters->sc_mutex ); ldap_pvt_mp_add_ulong( op->o_counters->sc_bytes, (unsigned long)bytes ); ldap_pvt_mp_add_ulong( op->o_counters->sc_refs, 1 ); ldap_pvt_mp_add_ulong( op->o_counters->sc_pdu, 1 ); ldap_pvt_thread_mutex_unlock( &op->o_counters->sc_mutex ); } #ifdef LDAP_CONNECTIONLESS } #endif if ( rs->sr_ref != NULL ) { int r; for ( r = 0; !BER_BVISNULL( &rs->sr_ref[ r ] ); r++ ) { Statslog( LDAP_DEBUG_STATS2, "%s REF #%d \"%s\"\n", op->o_log_prefix, r, rs->sr_ref[0].bv_val, 0, 0 ); } } else { Statslog( LDAP_DEBUG_STATS2, "%s REF \"(null)\"\n", op->o_log_prefix, 0, 0, 0, 0 ); } Debug( LDAP_DEBUG_TRACE, "<= send_search_reference\n", 0, 0, 0 ); rel: if ( op->o_callback ) { (void)slap_cleanup_play( op, rs ); } return rc; }
int backsql_delete( Operation *op, SlapReply *rs ) { SQLHDBC dbh = SQL_NULL_HDBC; SQLHSTMT sth = SQL_NULL_HSTMT; backsql_oc_map_rec *oc = NULL; backsql_srch_info bsi = { 0 }; backsql_entryID e_id = { 0 }; Entry d = { 0 }, p = { 0 }, *e = NULL; struct berval pdn = BER_BVNULL; int manageDSAit = get_manageDSAit( op ); Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n", op->o_req_ndn.bv_val, 0, 0 ); rs->sr_err = backsql_get_db_conn( op, &dbh ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "could not get connection handle - exiting\n", 0, 0, 0 ); rs->sr_text = ( rs->sr_err == LDAP_OTHER ) ? "SQL-backend error" : NULL; e = NULL; goto done; } /* * Get the entry */ bsi.bsi_e = &d; rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) ); switch ( rs->sr_err ) { case LDAP_SUCCESS: break; case LDAP_REFERRAL: if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) && dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } break; } e = &d; /* fallthru */ default: Debug( LDAP_DEBUG_TRACE, "backsql_delete(): " "could not retrieve deleteDN ID - no such entry\n", 0, 0, 0 ); if ( !BER_BVISNULL( &d.e_nname ) ) { /* FIXME: should always be true! */ e = &d; } else { e = NULL; } goto done; } if ( get_assert( op ) && ( test_filter( op, &d, get_assertion( op ) ) != LDAP_COMPARE_TRUE ) ) { rs->sr_err = LDAP_ASSERTION_FAILED; e = &d; goto done; } if ( !access_allowed( op, &d, slap_schema.si_ad_entry, NULL, ACL_WDEL, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "no write access to entry\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; e = &d; goto done; } rs->sr_err = backsql_has_children( op, dbh, &op->o_req_ndn ); switch ( rs->sr_err ) { case LDAP_COMPARE_FALSE: rs->sr_err = LDAP_SUCCESS; break; case LDAP_COMPARE_TRUE: #ifdef SLAP_CONTROL_X_TREE_DELETE if ( get_treeDelete( op ) ) { rs->sr_err = LDAP_SUCCESS; break; } #endif /* SLAP_CONTROL_X_TREE_DELETE */ Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "entry \"%s\" has children\n", op->o_req_dn.bv_val, 0, 0 ); rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; rs->sr_text = "subordinate objects must be deleted first"; /* fallthru */ default: e = &d; goto done; } assert( bsi.bsi_base_id.eid_oc != NULL ); oc = bsi.bsi_base_id.eid_oc; if ( oc->bom_delete_proc == NULL ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "delete procedure is not defined " "for this objectclass - aborting\n", 0, 0, 0 ); rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "operation not permitted within namingContext"; e = NULL; goto done; } /* * Get the parent */ e_id = bsi.bsi_base_id; memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) ); if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) { dnParent( &op->o_req_ndn, &pdn ); bsi.bsi_e = &p; rs->sr_err = backsql_init_search( &bsi, &pdn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs, BACKSQL_ISF_GET_ENTRY ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_delete(): " "could not retrieve deleteDN ID " "- no such entry\n", 0, 0, 0 ); e = &p; goto done; } (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); /* check parent for "children" acl */ if ( !access_allowed( op, &p, slap_schema.si_ad_children, NULL, ACL_WDEL, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "no write access to parent\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; e = &p; goto done; } } e = &d; #ifdef SLAP_CONTROL_X_TREE_DELETE if ( get_treeDelete( op ) ) { backsql_tree_delete( op, rs, dbh, &sth ); if ( rs->sr_err == LDAP_OTHER || rs->sr_err == LDAP_SUCCESS ) { e = NULL; } } else #endif /* SLAP_CONTROL_X_TREE_DELETE */ { backsql_delete_int( op, rs, dbh, &sth, &e_id, &e ); } /* * Commit only if all operations succeed */ if ( sth != SQL_NULL_HSTMT ) { SQLUSMALLINT CompletionType = SQL_ROLLBACK; if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { assert( e == NULL ); CompletionType = SQL_COMMIT; } SQLTransact( SQL_NULL_HENV, dbh, CompletionType ); } done: ; if ( e != NULL ) { if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } } if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) { rs->sr_err = LDAP_X_NO_OPERATION; } send_ldap_result( op, rs ); Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 ); if ( !BER_BVISNULL( &e_id.eid_ndn ) ) { (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &d.e_nname ) ) { backsql_entry_clean( op, &d ); } if ( !BER_BVISNULL( &p.e_nname ) ) { backsql_entry_clean( op, &p ); } if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } return rs->sr_err; }
static int nss_cf_gen(ConfigArgs *c) { slap_overinst *on = (slap_overinst *)c->bi; nssov_info *ni = on->on_bi.bi_private; nssov_mapinfo *mi; int i, j, rc = 0; slap_mask_t m; if ( c->op == SLAP_CONFIG_EMIT ) { switch(c->type) { case NSS_SSD: rc = 1; for (i=NM_alias;i<NM_NONE;i++) { struct berval scope; struct berval ssd; struct berval base; mi = &ni->ni_maps[i]; /* ignore all-default services */ if ( mi->mi_scope == LDAP_SCOPE_DEFAULT && bvmatch( &mi->mi_filter, &mi->mi_filter0 ) && BER_BVISNULL( &mi->mi_base )) continue; if ( BER_BVISNULL( &mi->mi_base )) base = ni->ni_db->be_nsuffix[0]; else base = mi->mi_base; ldap_pvt_scope2bv(mi->mi_scope == LDAP_SCOPE_DEFAULT ? LDAP_SCOPE_SUBTREE : mi->mi_scope, &scope); ssd.bv_len = STRLENOF(" ldap:///???") + nss_svcs[i].word.bv_len + base.bv_len + scope.bv_len + mi->mi_filter.bv_len; ssd.bv_val = ch_malloc( ssd.bv_len + 1 ); sprintf(ssd.bv_val, "%s ldap:///%s??%s?%s", nss_svcs[i].word.bv_val, base.bv_val, scope.bv_val, mi->mi_filter.bv_val ); ber_bvarray_add( &c->rvalue_vals, &ssd ); rc = 0; } break; case NSS_MAP: rc = 1; for (i=NM_alias;i<NM_NONE;i++) { mi = &ni->ni_maps[i]; for (j=0;!BER_BVISNULL(&mi->mi_attrkeys[j]);j++) { if ( ber_bvstrcasecmp(&mi->mi_attrkeys[j], &mi->mi_attrs[j].an_name)) { struct berval map; map.bv_len = nss_svcs[i].word.bv_len + mi->mi_attrkeys[j].bv_len + mi->mi_attrs[j].an_desc->ad_cname.bv_len + 2; map.bv_val = ch_malloc(map.bv_len + 1); sprintf(map.bv_val, "%s %s %s", nss_svcs[i].word.bv_val, mi->mi_attrkeys[j].bv_val, mi->mi_attrs[j].an_desc->ad_cname.bv_val ); ber_bvarray_add( &c->rvalue_vals, &map ); rc = 0; } } } break; case NSS_PAM: rc = mask_to_verbs( pam_opts, ni->ni_pam_opts, &c->rvalue_vals ); break; case NSS_PAMGROUP: if (!BER_BVISEMPTY( &ni->ni_pam_group_dn )) { value_add_one( &c->rvalue_vals, &ni->ni_pam_group_dn ); value_add_one( &c->rvalue_nvals, &ni->ni_pam_group_dn ); } else { rc = 1; } break; case NSS_PAMSESS: if (ni->ni_pam_sessions) { ber_bvarray_dup_x( &c->rvalue_vals, ni->ni_pam_sessions, NULL ); } else { rc = 1; } break; } return rc; } else if ( c->op == LDAP_MOD_DELETE ) { /* FIXME */ return 1; } switch( c->type ) { case NSS_SSD: { LDAPURLDesc *lud; i = verb_to_mask(c->argv[1], nss_svcs); if ( i == NM_NONE ) return 1; mi = &ni->ni_maps[i]; rc = ldap_url_parse(c->argv[2], &lud); if ( rc ) return 1; do { struct berval base; /* Must be LDAP scheme */ if (strcasecmp(lud->lud_scheme,"ldap")) { rc = 1; break; } /* Host part, attrs, and extensions must be empty */ if (( lud->lud_host && *lud->lud_host ) || lud->lud_attrs || lud->lud_exts ) { rc = 1; break; } ber_str2bv( lud->lud_dn,0,0,&base); rc = dnNormalize( 0,NULL,NULL,&base,&mi->mi_base,NULL); if ( rc ) break; if ( lud->lud_filter ) { /* steal this */ ber_str2bv( lud->lud_filter,0,0,&mi->mi_filter); lud->lud_filter = NULL; } mi->mi_scope = lud->lud_scope; } while(0); ldap_free_urldesc( lud ); } break; case NSS_MAP: i = verb_to_mask(c->argv[1], nss_svcs); if ( i == NM_NONE ) return 1; rc = 1; mi = &ni->ni_maps[i]; for (j=0; !BER_BVISNULL(&mi->mi_attrkeys[j]); j++) { if (!strcasecmp(c->argv[2],mi->mi_attrkeys[j].bv_val)) { AttributeDescription *ad = NULL; const char *text; rc = slap_str2ad( c->argv[3], &ad, &text); if ( rc == 0 ) { mi->mi_attrs[j].an_desc = ad; mi->mi_attrs[j].an_name = ad->ad_cname; } break; } } break; case NSS_PAM: m = ni->ni_pam_opts; i = verbs_to_mask(c->argc, c->argv, pam_opts, &m); if (i == 0) { ni->ni_pam_opts = m; if ((m & NI_PAM_USERHOST) && !nssov_pam_host_ad) { const char *text; i = slap_str2ad("host", &nssov_pam_host_ad, &text); if (i != LDAP_SUCCESS) { snprintf(c->cr_msg, sizeof(c->cr_msg), "nssov: host attr unknown: %s", text); Debug(LDAP_DEBUG_ANY,"%s\n",c->cr_msg,0,0); rc = 1; break; } } if ((m & (NI_PAM_USERSVC|NI_PAM_HOSTSVC)) && !nssov_pam_svc_ad) { const char *text; i = slap_str2ad("authorizedService", &nssov_pam_svc_ad, &text); if (i != LDAP_SUCCESS) { snprintf(c->cr_msg, sizeof(c->cr_msg), "nssov: authorizedService attr unknown: %s", text); Debug(LDAP_DEBUG_ANY,"%s\n",c->cr_msg,0,0); rc = 1; break; } } } else { rc = 1; } break; case NSS_PAMGROUP: ni->ni_pam_group_dn = c->value_ndn; ch_free( c->value_dn.bv_val ); break; case NSS_PAMSESS: ber_str2bv( c->argv[1], 0, 1, &c->value_bv ); ber_bvarray_add( &ni->ni_pam_sessions, &c->value_bv ); break; } return rc; }