/* * Ensure rs->sr_entry is modifiable, by duplicating it if necessary. * Obey sr_flags. Set REP_ENTRY_<MODIFIABLE, and MUSTBEFREED if duplicated>. * Return nonzero if rs->sr_entry was replaced. */ int rs_ensure_entry_modifiable( Operation *op, SlapReply *rs, slap_overinst *on ) { if ( rs->sr_flags & REP_ENTRY_MODIFIABLE ) { RS_ASSERT((rs->sr_flags & REP_ENTRY_MUSTFLUSH)==REP_ENTRY_MUSTBEFREED); return 0; } rs_replace_entry( op, rs, on, entry_dup( rs->sr_entry )); rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; return 1; }
/* * Ensure rs->sr_entry is modifiable, by duplicating it if necessary. * Obey sr_flags. Set REP_ENTRY_<MODIFIABLE, and MUSTBEFREED if duplicated>. * Return nonzero if rs->sr_entry was replaced. */ int rs_entry2modifiable( Operation *op, SlapReply *rs, slap_overinst *on ) { if ( rs->sr_flags & REP_ENTRY_MODIFIABLE ) { rs_assert_ok( rs ); return 0; } rs_replace_entry( op, rs, on, entry_dup( rs->sr_entry )); rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; return 1; }
static gboolean mk_link(struct rdup *e, char *p, GHashTable * uidhash, GHashTable * gidhash) { struct stat *st; gchar *t; gchar *parent; if (opt_dry) return TRUE; if (!rm(e->f_name)) return FALSE; /* symlink */ if (S_ISLNK(e->f_mode)) { if (symlink(e->f_target, e->f_name) == -1) { if (errno == EACCES) { parent = dir_parent(e->f_name); st = dir_write(parent); if (symlink(e->f_target, e->f_name) == -1) { msgd(__func__, __LINE__, _ ("Failed to make symlink `%s -> %s\': %s"), e->f_name, e->f_target, strerror(errno)); dir_restore(parent, st); g_free(parent); return FALSE; } dir_restore(parent, st); g_free(parent); } else { msgd(__func__, __LINE__, _ ("Failed to make symlink `%s -> %s\': %s"), e->f_name, e->f_target, strerror(errno)); return FALSE; } } mk_chown(e, uidhash, gidhash); return TRUE; } /* hardlink */ /* target must also fall in backup dir */ t = g_strdup_printf("%s%s", p, e->f_target); e->f_target = t; hlink_list = g_slist_append(hlink_list, entry_dup(e)); return TRUE; }
int testDup() { char *key = strdup("123abc"); struct data_t *value = data_create2(strlen("1234567890abc")+1,strdup("1234567890abc")); struct entry_t *entry = entry_create(key,value); struct entry_t *entry2 = entry_dup(entry); int result = (entry->key != entry2->key) && (strcmp(entry->key,entry2->key) == 0) && (entry->value != entry2->value) && (entry->value->datasize == entry2->value->datasize) && (memcmp(entry->value->data, entry2->value->data, entry->value->datasize) == 0); entry_destroy(entry); entry_destroy(entry2); printf("Modulo entry -> teste entry_dup: %s\n",result?"passou":"não passou"); return result; }
static int valsort_response( Operation *op, SlapReply *rs ) { slap_overinst *on; valsort_info *vi; Attribute *a; /* If this is not a search response, or it is a syncrepl response, * or the valsort control wants raw results, pass thru unmodified. */ if ( rs->sr_type != REP_SEARCH || ( _SCM(op->o_sync) > SLAP_CONTROL_IGNORED ) || ( op->o_ctrlflag[valsort_cid] & SLAP_CONTROL_DATA0)) return SLAP_CB_CONTINUE; on = (slap_overinst *) op->o_bd->bd_info; vi = on->on_bi.bi_private; /* And we must have something configured */ if ( !vi ) return SLAP_CB_CONTINUE; /* Find a rule whose baseDN matches this entry */ for (; vi; vi = vi->vi_next ) { int i, n; if ( !dnIsSuffix( &rs->sr_entry->e_nname, &vi->vi_dn )) continue; /* Find attr that this rule affects */ a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad ); if ( !a ) continue; if (( rs->sr_flags & ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) ) != ( REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED ) ) { Entry *e; e = entry_dup( rs->sr_entry ); if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) { overlay_entry_release_ov( op, rs->sr_entry, 0, on ); rs->sr_flags &= ~REP_ENTRY_MUSTRELEASE; } else if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) { entry_free( rs->sr_entry ); } rs->sr_entry = e; rs->sr_flags |= REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED; a = attr_find( rs->sr_entry->e_attrs, vi->vi_ad ); } n = a->a_numvals; if ( vi->vi_sort & VALSORT_WEIGHTED ) { int j, gotnvals; long *index = op->o_tmpalloc( n * sizeof(long), op->o_tmpmemctx ); gotnvals = (a->a_vals != a->a_nvals ); for (i=0; i<n; i++) { char *ptr = ber_bvchr( &a->a_nvals[i], '{' ); char *end = NULL; if ( !ptr ) { Debug(LDAP_DEBUG_TRACE, "weights missing from attr %s " "in entry %s\n", vi->vi_ad->ad_cname.bv_val, rs->sr_entry->e_name.bv_val, 0 ); break; } index[i] = strtol( ptr+1, &end, 0 ); if ( *end != '}' ) { Debug(LDAP_DEBUG_TRACE, "weights misformatted " "in entry %s\n", rs->sr_entry->e_name.bv_val, 0, 0 ); break; } /* Strip out weights */ ptr = a->a_nvals[i].bv_val; end++; for (;*end;) *ptr++ = *end++; *ptr = '\0'; a->a_nvals[i].bv_len = ptr - a->a_nvals[i].bv_val; if ( a->a_vals != a->a_nvals ) { ptr = a->a_vals[i].bv_val; end = ber_bvchr( &a->a_vals[i], '}' ); assert( end != NULL ); end++; for (;*end;) *ptr++ = *end++; *ptr = '\0'; a->a_vals[i].bv_len = ptr - a->a_vals[i].bv_val; } } /* An attr was missing weights here, ignore it */ if ( i<n ) { op->o_tmpfree( index, op->o_tmpmemctx ); continue; } /* Insertion sort */ for ( i=1; i<n; i++) { long idx = index[i]; struct berval tmp = a->a_vals[i], ntmp; if ( gotnvals ) ntmp = a->a_nvals[i]; j = i; while (( j>0 ) && (index[j-1] > idx )) { index[j] = index[j-1]; a->a_vals[j] = a->a_vals[j-1]; if ( gotnvals ) a->a_nvals[j] = a->a_nvals[j-1]; j--; } index[j] = idx; a->a_vals[j] = tmp; if ( gotnvals ) a->a_nvals[j] = ntmp; } /* Check for secondary sort */ if ( vi->vi_sort ^ VALSORT_WEIGHTED ) { for ( i=0; i<n;) { for (j=i+1; j<n; j++) { if (index[i] != index[j]) break; } if( j-i > 1 ) do_sort( op, a, i, j-i, vi->vi_sort ); i = j; } } op->o_tmpfree( index, op->o_tmpmemctx ); } else { do_sort( op, a, 0, n, vi->vi_sort ); } } return SLAP_CB_CONTINUE; }
static int autoca_op_response( Operation *op, SlapReply *rs ) { slap_overinst *on = op->o_callback->sc_private; autoca_info *ai = on->on_bi.bi_private; Attribute *a; int isusr = 0; if (rs->sr_type != REP_SEARCH) return SLAP_CB_CONTINUE; /* If root or self */ if ( !be_isroot( op ) && !dn_match( &rs->sr_entry->e_nname, &op->o_ndn )) return SLAP_CB_CONTINUE; isusr = is_entry_objectclass( rs->sr_entry, ai->ai_usrclass, SLAP_OCF_CHECK_SUP ); if ( !isusr ) { if (!is_entry_objectclass( rs->sr_entry, ai->ai_srvclass, SLAP_OCF_CHECK_SUP )) return SLAP_CB_CONTINUE; } a = attr_find( rs->sr_entry->e_attrs, ad_usrPkey ); if ( !a ) { Operation op2; genargs args; saveargs arg2; myext extras[2]; int rc; args.issuer_cert = ai->ai_cert; args.issuer_pkey = ai->ai_pkey; args.subjectDN = &rs->sr_entry->e_name; args.more_exts = NULL; if ( isusr ) { args.cert_exts = usrExts; args.keybits = ai->ai_usrkeybits; args.days = ai->ai_usrdays; a = attr_find( rs->sr_entry->e_attrs, ad_mail ); if ( a ) { extras[0].name = "subjectAltName"; extras[1].name = NULL; extras[0].value = op->o_tmpalloc( sizeof("email:") + a->a_vals[0].bv_len, op->o_tmpmemctx ); sprintf(extras[0].value, "email:%s", a->a_vals[0].bv_val); args.more_exts = extras; } } else { args.cert_exts = srvExts; args.keybits = ai->ai_srvkeybits; args.days = ai->ai_srvdays; if ( ad_ipaddr && (a = attr_find( rs->sr_entry->e_attrs, ad_ipaddr ))) { extras[0].name = "subjectAltName"; extras[1].name = NULL; extras[0].value = op->o_tmpalloc( sizeof("IP:") + a->a_vals[0].bv_len, op->o_tmpmemctx ); sprintf(extras[0].value, "IP:%s", a->a_vals[0].bv_val); args.more_exts = extras; } } rc = autoca_gencert( op, &args ); if ( rc ) return SLAP_CB_CONTINUE; X509_free( args.newcert ); EVP_PKEY_free( args.newpkey ); if ( is_entry_objectclass( rs->sr_entry, oc_usrObj, 0 )) arg2.oc = NULL; else arg2.oc = oc_usrObj; if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE )) { Entry *e = entry_dup( rs->sr_entry ); rs_replace_entry( op, rs, on, e ); rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; } arg2.dercert = &args.dercert; arg2.derpkey = &args.derpkey; arg2.on = on; arg2.dn = &rs->sr_entry->e_name; arg2.ndn = &rs->sr_entry->e_nname; arg2.isca = 0; op2 = *op; rc = autoca_savecert( &op2, &arg2 ); if ( !rc ) { /* If this is our cert DN, configure it */ if ( dn_match( &rs->sr_entry->e_nname, &ai->ai_localndn )) autoca_setlocal( &op2, &args.dercert, &args.derpkey ); attr_merge_one( rs->sr_entry, ad_usrCert, &args.dercert, NULL ); attr_merge_one( rs->sr_entry, ad_usrPkey, &args.derpkey, NULL ); } op->o_tmpfree( args.dercert.bv_val, op->o_tmpmemctx ); op->o_tmpfree( args.derpkey.bv_val, op->o_tmpmemctx ); } return SLAP_CB_CONTINUE; }
int list_add(struct list_t *list, struct entry_t *entry){ if (list == NULL || entry == NULL) return -1; struct node_t *node = (struct node_t *) malloc(sizeof(struct node_t)); if (node == NULL) return -1; // preparar node a ser inserido na lista node->entry = entry_dup(entry); node->next = NULL; struct node_t *current = list->head; struct node_t *previous = current; int str_cmp; // lista vazia if (list->head == NULL) { list->head = node; list->size++; } // adicionar no ao inicio da lista se nao existe else if (strcmp(entry->key, list->head->entry->key) < 0) { node->next = list->head; list->head = node; list->size++; } else { str_cmp = strcmp(entry->key, current->entry->key); // encontrar posicao que a key excede while( str_cmp > 0 && current->next != NULL ) { previous = current; current = current->next; str_cmp = strcmp( entry->key, current->entry->key ); } // key jah presente na lista if ( str_cmp == 0 ){ entry_destroy(node->entry); free(node); return -1; } // adicionar no antes do no encontrado else if (str_cmp < 0) { previous->next = node; node->next = current; list->size++; } // adicionar no depois do no encontrado // str_cmp > 0 else { // current nao eh no final if (current->next != NULL) node->next = current->next; current->next = node; list->size++; } } return 0; }
static int dynlist_prepare_entry( Operation *op, SlapReply *rs, dynlist_info_t *dli ) { Attribute *a, *id = NULL; slap_callback cb = { 0 }; Operation o = *op; struct berval *url; Entry *e; int opattrs, userattrs; dynlist_sc_t dlc = { 0 }; dynlist_map_t *dlm; a = attrs_find( rs->sr_entry->e_attrs, dli->dli_ad ); if ( a == NULL ) { /* FIXME: error? */ return SLAP_CB_CONTINUE; } opattrs = SLAP_OPATTRS( rs->sr_attr_flags ); userattrs = SLAP_USERATTRS( rs->sr_attr_flags ); /* Don't generate member list if it wasn't requested */ for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { AttributeDescription *ad = dlm->dlm_mapped_ad ? dlm->dlm_mapped_ad : dlm->dlm_member_ad; if ( userattrs || ad_inlist( ad, rs->sr_attrs ) ) break; } if ( dli->dli_dlm && !dlm ) return SLAP_CB_CONTINUE; if ( ad_dgIdentity && ( id = attrs_find( rs->sr_entry->e_attrs, ad_dgIdentity ))) { Attribute *authz = NULL; /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op ) && ( authz = attrs_find( rs->sr_entry->e_attrs, ad_dgAuthz ) ) ) { if ( slap_sasl_matches( op, authz->a_nvals, &o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS ) { return SLAP_CB_CONTINUE; } } o.o_dn = id->a_vals[0]; o.o_ndn = id->a_nvals[0]; o.o_groups = NULL; } e = rs->sr_entry; /* ensure e is modifiable, but do not replace * sr_entry yet since we have pointers into it */ if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) { e = entry_dup( rs->sr_entry ); } dlc.dlc_e = e; dlc.dlc_dli = dli; cb.sc_private = &dlc; cb.sc_response = dynlist_sc_update; o.o_callback = &cb; o.ors_deref = LDAP_DEREF_NEVER; o.ors_limit = NULL; o.ors_tlimit = SLAP_NO_LIMIT; o.ors_slimit = SLAP_NO_LIMIT; for ( url = a->a_nvals; !BER_BVISNULL( url ); url++ ) { LDAPURLDesc *lud = NULL; int i, j; struct berval dn; int rc; BER_BVZERO( &o.o_req_dn ); BER_BVZERO( &o.o_req_ndn ); o.ors_filter = NULL; o.ors_attrs = NULL; BER_BVZERO( &o.ors_filterstr ); if ( ldap_url_parse( url->bv_val, &lud ) != LDAP_URL_SUCCESS ) { /* FIXME: error? */ continue; } if ( lud->lud_host != NULL ) { /* FIXME: host not allowed; reject as illegal? */ Debug( LDAP_DEBUG_ANY, "dynlist_prepare_entry(\"%s\"): " "illegal URI \"%s\"\n", e->e_name.bv_val, url->bv_val, 0 ); goto cleanup; } if ( lud->lud_dn == NULL ) { /* note that an empty base is not honored in terms * of defaultSearchBase, because select_backend() * is not aware of the defaultSearchBase option; * this can be useful in case of a database serving * the empty suffix */ BER_BVSTR( &dn, "" ); } else { ber_str2bv( lud->lud_dn, 0, 0, &dn ); } rc = dnPrettyNormal( NULL, &dn, &o.o_req_dn, &o.o_req_ndn, op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { /* FIXME: error? */ goto cleanup; } o.ors_scope = lud->lud_scope; for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { if ( dlm->dlm_mapped_ad != NULL ) { break; } } if ( dli->dli_dlm && !dlm ) { /* if ( lud->lud_attrs != NULL ), * the URL should be ignored */ o.ors_attrs = slap_anlist_no_attrs; } else if ( lud->lud_attrs == NULL ) { o.ors_attrs = rs->sr_attrs; } else { for ( i = 0; lud->lud_attrs[i]; i++) /* just count */ ; o.ors_attrs = op->o_tmpcalloc( i + 1, sizeof( AttributeName ), op->o_tmpmemctx ); for ( i = 0, j = 0; lud->lud_attrs[i]; i++) { const char *text = NULL; ber_str2bv( lud->lud_attrs[i], 0, 0, &o.ors_attrs[j].an_name ); o.ors_attrs[j].an_desc = NULL; (void)slap_bv2ad( &o.ors_attrs[j].an_name, &o.ors_attrs[j].an_desc, &text ); /* FIXME: ignore errors... */ if ( rs->sr_attrs == NULL ) { if ( o.ors_attrs[j].an_desc != NULL && is_at_operational( o.ors_attrs[j].an_desc->ad_type ) ) { continue; } } else { if ( o.ors_attrs[j].an_desc != NULL && is_at_operational( o.ors_attrs[j].an_desc->ad_type ) ) { if ( !opattrs ) { continue; } if ( !ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) ) { /* lookup if mapped -- linear search, * not very efficient unless list * is very short */ for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) { break; } } if ( dlm == NULL ) { continue; } } } else { if ( !userattrs && o.ors_attrs[j].an_desc != NULL && !ad_inlist( o.ors_attrs[j].an_desc, rs->sr_attrs ) ) { /* lookup if mapped -- linear search, * not very efficient unless list * is very short */ for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) { if ( dlm->dlm_member_ad == o.ors_attrs[j].an_desc ) { break; } } if ( dlm == NULL ) { continue; } } } } j++; } if ( j == 0 ) { goto cleanup; } BER_BVZERO( &o.ors_attrs[j].an_name ); } if ( lud->lud_filter == NULL ) { ber_dupbv_x( &o.ors_filterstr, &dli->dli_default_filter, op->o_tmpmemctx ); } else { struct berval flt; ber_str2bv( lud->lud_filter, 0, 0, &flt ); if ( dynlist_make_filter( op, rs->sr_entry, url->bv_val, &flt, &o.ors_filterstr ) ) { /* error */ goto cleanup; } } o.ors_filter = str2filter_x( op, o.ors_filterstr.bv_val ); if ( o.ors_filter == NULL ) { goto cleanup; } o.o_bd = select_backend( &o.o_req_ndn, 1 ); if ( o.o_bd && o.o_bd->be_search ) { SlapReply r = { REP_SEARCH }; r.sr_attr_flags = slap_attr_flags( o.ors_attrs ); (void)o.o_bd->be_search( &o, &r ); } cleanup:; if ( id ) { slap_op_groups_free( &o ); } if ( o.ors_filter ) { filter_free_x( &o, o.ors_filter, 1 ); } if ( o.ors_attrs && o.ors_attrs != rs->sr_attrs && o.ors_attrs != slap_anlist_no_attrs ) { op->o_tmpfree( o.ors_attrs, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &o.o_req_dn ) ) { op->o_tmpfree( o.o_req_dn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &o.o_req_ndn ) ) { op->o_tmpfree( o.o_req_ndn.bv_val, op->o_tmpmemctx ); } assert( BER_BVISNULL( &o.ors_filterstr ) || o.ors_filterstr.bv_val != lud->lud_filter ); op->o_tmpfree( o.ors_filterstr.bv_val, op->o_tmpmemctx ); ldap_free_urldesc( lud ); } if ( e != rs->sr_entry ) { rs_replace_entry( op, rs, (slap_overinst *)op->o_bd->bd_info, e ); rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; } return SLAP_CB_CONTINUE; }
static int translucent_search_cb(Operation *op, SlapReply *rs) { trans_ctx *tc; BackendDB *db; slap_overinst *on; translucent_info *ov; Entry *le, *re; Attribute *a, *ax, *an, *as = NULL; int rc; int test_f = 0; tc = op->o_callback->sc_private; /* Don't let the op complete while we're gathering data */ if ( rs->sr_type == REP_RESULT && ( tc->step & USE_LIST )) return 0; if(rs->sr_type != REP_SEARCH || !rs->sr_entry) return(SLAP_CB_CONTINUE); Debug(LDAP_DEBUG_TRACE, "==> translucent_search_cb: %s\n", rs->sr_entry->e_name.bv_val, 0, 0); op->ors_slimit = tc->slimit + ( tc->slimit > 0 ? 1 : 0 ); if ( op->ors_attrs == slap_anlist_all_attributes ) { op->ors_attrs = tc->attrs; rs->sr_attrs = tc->attrs; rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs ); } on = tc->on; ov = on->on_bi.bi_private; db = op->o_bd; re = NULL; /* If we have local, get remote */ if ( tc->step & LCL_SIDE ) { le = rs->sr_entry; /* If entry is already on list, use it */ if ( tc->step & USE_LIST ) { re = tavl_delete( &tc->list, le, entry_dn_cmp ); if ( re ) { rs_flush_entry( op, rs, on ); rc = test_filter( op, re, tc->orig ); if ( rc == LDAP_COMPARE_TRUE ) { rs->sr_flags |= REP_ENTRY_MUSTBEFREED; rs->sr_entry = re; if ( tc->slimit >= 0 && rs->sr_nentries >= tc->slimit ) { return LDAP_SIZELIMIT_EXCEEDED; } return SLAP_CB_CONTINUE; } else { entry_free( re ); rs->sr_entry = NULL; return 0; } } } op->o_bd = &ov->db; rc = be_entry_get_rw( op, &rs->sr_entry->e_nname, NULL, NULL, 0, &re ); if ( rc == LDAP_SUCCESS && re ) { Entry *tmp = entry_dup( re ); be_entry_release_r( op, re ); re = tmp; test_f = 1; } } else { /* Else we have remote, get local */ op->o_bd = tc->db; le = NULL; rc = overlay_entry_get_ov(op, &rs->sr_entry->e_nname, NULL, NULL, 0, &le, on); if ( rc == LDAP_SUCCESS && le ) { re = entry_dup( rs->sr_entry ); rs_flush_entry( op, rs, on ); } else { le = NULL; } } /* ** if we got remote and local entry: ** foreach local attr: ** foreach remote attr: ** if match, remote attr with local attr; ** if new local, add to list; ** append new local attrs to remote; ** */ if ( re && le ) { for(ax = le->e_attrs; ax; ax = ax->a_next) { for(a = re->e_attrs; a; a = a->a_next) { if(a->a_desc == ax->a_desc) { test_f = 1; if(a->a_vals != a->a_nvals) ber_bvarray_free(a->a_nvals); ber_bvarray_free(a->a_vals); ber_bvarray_dup_x( &a->a_vals, ax->a_vals, NULL ); if ( ax->a_vals == ax->a_nvals ) { a->a_nvals = a->a_vals; } else { ber_bvarray_dup_x( &a->a_nvals, ax->a_nvals, NULL ); } break; } } if(a) continue; an = attr_dup(ax); an->a_next = as; as = an; } /* Dispose of local entry */ if ( tc->step & LCL_SIDE ) { rs_flush_entry(op, rs, on); } else { overlay_entry_release_ov(op, le, 0, on); } /* literally append, so locals are always last */ if(as) { if(re->e_attrs) { for(ax = re->e_attrs; ax->a_next; ax = ax->a_next); ax->a_next = as; } else { re->e_attrs = as; } } /* If both filters, save entry for later */ if ( tc->step == (USE_LIST|RMT_SIDE) ) { tavl_insert( &tc->list, re, entry_dn_cmp, avl_dup_error ); rs->sr_entry = NULL; rc = 0; } else { /* send it now */ rs->sr_entry = re; rs->sr_flags |= REP_ENTRY_MUSTBEFREED; if ( test_f ) { rc = test_filter( op, rs->sr_entry, tc->orig ); if ( rc == LDAP_COMPARE_TRUE ) { rc = SLAP_CB_CONTINUE; } else { rc = 0; } } else { rc = SLAP_CB_CONTINUE; } } } else if ( le ) { /* Only a local entry: remote was deleted * Ought to delete the local too... */ rc = 0; } else if ( tc->step & USE_LIST ) { /* Only a remote entry, but both filters: * Test the complete filter */ rc = test_filter( op, rs->sr_entry, tc->orig ); if ( rc == LDAP_COMPARE_TRUE ) { rc = SLAP_CB_CONTINUE; } else { rc = 0; } } else { /* Only a remote entry, only remote filter: * just pass thru */ rc = SLAP_CB_CONTINUE; } op->o_bd = db; if ( rc == SLAP_CB_CONTINUE && tc->slimit >= 0 && rs->sr_nentries >= tc->slimit ) { return LDAP_SIZELIMIT_EXCEEDED; } return rc; }
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 ) ) { Entry *e; e = entry_dup( bi->sql_baseObject ); if ( e == NULL ) { return LDAP_NO_MEMORY; } *bsi->bsi_e = *e; free( e ); goto done; } 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 ); 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 ); } bsi->bsi_oc = eid->eid_oc; bsi->bsi_c_eid = eid; #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; }
static int constraint_update( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; Backend *be = op->o_bd; constraint *c = on->on_bi.bi_private, *cp; Entry *target_entry = NULL, *target_entry_copy = NULL; Modifications *modlist, *m; BerVarray b = NULL; int i; struct berval rsv = BER_BVC("modify breaks constraint"); int rc; char *msg = NULL; if (get_relax(op)) { return SLAP_CB_CONTINUE; } switch ( op->o_tag ) { case LDAP_REQ_MODIFY: modlist = op->orm_modlist; break; case LDAP_REQ_MODRDN: modlist = op->orr_modlist; break; default: /* impossible! assert? */ return LDAP_OTHER; } Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "constraint_update()\n", 0,0,0); if ((m = modlist) == NULL) { op->o_bd->bd_info = (BackendInfo *)(on->on_info); send_ldap_error(op, rs, LDAP_INVALID_SYNTAX, "constraint_update() got null modlist"); return(rs->sr_err); } /* Do we need to count attributes? */ for(cp = c; cp; cp = cp->ap_next) { if (cp->count != 0 || cp->set || cp->restrict_lud != 0) { op->o_bd = on->on_info->oi_origdb; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &target_entry ); op->o_bd = be; if (rc != 0 || target_entry == NULL) { Debug(LDAP_DEBUG_TRACE, "==> constraint_update rc = %d DN=\"%s\"%s\n", rc, op->o_req_ndn.bv_val, target_entry ? "" : " not found" ); if ( rc == 0 ) rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; } break; } } rc = LDAP_CONSTRAINT_VIOLATION; for(;m; m = m->sml_next) { unsigned ce = 0; if (is_at_operational( m->sml_desc->ad_type )) continue; if ((( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_ADD) && (( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_REPLACE) && (( m->sml_op & LDAP_MOD_OP ) != LDAP_MOD_DELETE)) continue; /* we only care about ADD and REPLACE modifications */ /* and DELETE are used to track attribute count */ if ((( b = m->sml_values ) == NULL ) || (b[0].bv_val == NULL)) continue; /* Get this attribute count, if needed */ if (target_entry) ce = constraint_count_attr(target_entry, m->sml_desc); for(cp = c; cp; cp = cp->ap_next) { int j; for (j = 0; cp->ap[j]; j++) { if (cp->ap[j] == m->sml_desc) { break; } } if (cp->ap[j] == NULL) continue; if (cp->restrict_lud != NULL && constraint_check_restrict(op, cp, target_entry) == 0) { continue; } if (cp->count != 0) { unsigned ca; if (m->sml_op == LDAP_MOD_DELETE) ce = 0; for (ca = 0; b[ca].bv_val; ++ca); Debug(LDAP_DEBUG_TRACE, "==> constraint_update ce = %u, " "ca = %u, cp->count = %lu\n", ce, ca, (unsigned long) cp->count); if (m->sml_op == LDAP_MOD_ADD) { if (ca + ce > cp->count) { rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; } } if (m->sml_op == LDAP_MOD_REPLACE) { if (ca > cp->count) { rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; } ce = ca; } } /* DELETE are to be ignored beyond this point */ if (( m->sml_op & LDAP_MOD_OP ) == LDAP_MOD_DELETE) continue; for ( i = 0; b[i].bv_val; i++ ) { rc = constraint_violation( cp, &b[i], op, rs ); if ( rc ) { goto mod_violation; } } if (cp->set && target_entry) { if (target_entry_copy == NULL) { Modifications *ml; target_entry_copy = entry_dup(target_entry); /* if rename, set the new entry's name * (in normalized form only) */ if ( op->o_tag == LDAP_REQ_MODRDN ) { struct berval pdn, ndn = BER_BVNULL; if ( op->orr_nnewSup ) { pdn = *op->orr_nnewSup; } else { dnParent( &target_entry_copy->e_nname, &pdn ); } build_new_dn( &ndn, &pdn, &op->orr_nnewrdn, NULL ); ber_memfree( target_entry_copy->e_nname.bv_val ); target_entry_copy->e_nname = ndn; ber_bvreplace( &target_entry_copy->e_name, &ndn ); } /* apply modifications, in an attempt * to estimate what the entry would * look like in case all modifications * pass */ for ( ml = modlist; ml; ml = ml->sml_next ) { Modification *mod = &ml->sml_mod; const char *text; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof(textbuf); int err; switch ( mod->sm_op ) { case LDAP_MOD_ADD: err = modify_add_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); break; case LDAP_MOD_DELETE: err = modify_delete_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); break; case LDAP_MOD_REPLACE: err = modify_replace_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); break; case LDAP_MOD_INCREMENT: err = modify_increment_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); break; case SLAP_MOD_SOFTADD: mod->sm_op = LDAP_MOD_ADD; err = modify_add_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); mod->sm_op = SLAP_MOD_SOFTADD; if ( err == LDAP_TYPE_OR_VALUE_EXISTS ) { err = LDAP_SUCCESS; } break; case SLAP_MOD_SOFTDEL: mod->sm_op = LDAP_MOD_ADD; err = modify_delete_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); mod->sm_op = SLAP_MOD_SOFTDEL; if ( err == LDAP_NO_SUCH_ATTRIBUTE ) { err = LDAP_SUCCESS; } break; case SLAP_MOD_ADD_IF_NOT_PRESENT: if ( attr_find( target_entry_copy->e_attrs, mod->sm_desc ) ) { err = LDAP_SUCCESS; break; } mod->sm_op = LDAP_MOD_ADD; err = modify_add_values( target_entry_copy, mod, get_permissiveModify(op), &text, textbuf, textlen ); mod->sm_op = SLAP_MOD_ADD_IF_NOT_PRESENT; break; default: err = LDAP_OTHER; break; } if ( err != LDAP_SUCCESS ) { rc = err; goto mod_violation; } } } if ( acl_match_set(&cp->val, op, target_entry_copy, NULL) == 0) { rc = LDAP_CONSTRAINT_VIOLATION; goto mod_violation; } } } } if (target_entry) { op->o_bd = on->on_info->oi_origdb; be_entry_release_r(op, target_entry); op->o_bd = be; } if (target_entry_copy) { entry_free(target_entry_copy); } return SLAP_CB_CONTINUE; mod_violation: /* violation */ if (target_entry) { op->o_bd = on->on_info->oi_origdb; be_entry_release_r(op, target_entry); op->o_bd = be; } if (target_entry_copy) { entry_free(target_entry_copy); } op->o_bd->bd_info = (BackendInfo *)(on->on_info); if ( rc == LDAP_CONSTRAINT_VIOLATION ) { msg = print_message( &rsv, m->sml_desc ); } send_ldap_error( op, rs, LDAP_CONSTRAINT_VIOLATION, msg ); ch_free(msg); return (rs->sr_err); }
int slapadd( int argc, char **argv ) { char *buf = NULL; const char *text; char textbuf[SLAP_TEXT_BUFLEN] = { '\0' }; size_t textlen = sizeof textbuf; const char *progname = "slapadd"; struct berval csn; struct berval maxcsn[ SLAP_SYNC_SID_MAX + 1 ]; unsigned long sid; struct berval bvtext; Attribute *attr; Entry *ctxcsn_e; ID ctxcsn_id, id; OperationBuffer opbuf; Operation *op; int match; int checkvals; int lineno, nextline; int lmax; int rc = EXIT_SUCCESS; int manage = 0; /* default "000" */ csnsid = 0; slap_tool_init( progname, SLAPADD, argc, argv ); memset( &opbuf, 0, sizeof(opbuf) ); op = &opbuf.ob_op; op->o_hdr = &opbuf.ob_hdr; if( !be->be_entry_open || !be->be_entry_close || !be->be_entry_put || (update_ctxcsn && (!be->be_dn2id_get || !be->be_entry_get || !be->be_entry_modify)) ) { fprintf( stderr, "%s: database doesn't support necessary operations.\n", progname ); if ( dryrun ) { fprintf( stderr, "\t(dry) continuing...\n" ); } else { exit( EXIT_FAILURE ); } } checkvals = (slapMode & SLAP_TOOL_QUICK) ? 0 : 1; lmax = 0; nextline = 0; /* enforce schema checking unless not disabled */ if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) { SLAP_DBFLAGS(be) &= ~(SLAP_DBFLAG_NO_SCHEMA_CHECK); } if( !dryrun && be->be_entry_open( be, 1 ) != 0 ) { fprintf( stderr, "%s: could not open database.\n", progname ); exit( EXIT_FAILURE ); } if ( update_ctxcsn ) { maxcsn[ 0 ].bv_val = maxcsnbuf; for ( sid = 1; sid <= SLAP_SYNC_SID_MAX; sid++ ) { maxcsn[ sid ].bv_val = maxcsn[ sid - 1 ].bv_val + LDAP_LUTIL_CSNSTR_BUFSIZE; maxcsn[ sid ].bv_len = 0; } } /* nextline is the line number of the end of the current entry */ for( lineno=1; ldif_read_record( ldiffp, &nextline, &buf, &lmax ); lineno=nextline+1 ) { Entry *e; if ( lineno < jumpline ) continue; e = str2entry2( buf, checkvals ); /* * Initialize text buffer */ bvtext.bv_len = textlen; bvtext.bv_val = textbuf; bvtext.bv_val[0] = '\0'; if( e == NULL ) { fprintf( stderr, "%s: could not parse entry (line=%d)\n", progname, lineno ); rc = EXIT_FAILURE; if( continuemode ) continue; break; } /* make sure the DN is not empty */ if( BER_BVISEMPTY( &e->e_nname ) && !BER_BVISEMPTY( be->be_nsuffix )) { fprintf( stderr, "%s: empty dn=\"%s\" (line=%d)\n", progname, e->e_dn, lineno ); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } /* check backend */ if( select_backend( &e->e_nname, nosubordinates ) != be ) { fprintf( stderr, "%s: line %d: " "database (%s) not configured to hold \"%s\"\n", progname, lineno, be ? be->be_suffix[0].bv_val : "<none>", e->e_dn ); fprintf( stderr, "%s: line %d: " "database (%s) not configured to hold \"%s\"\n", progname, lineno, be ? be->be_nsuffix[0].bv_val : "<none>", e->e_ndn ); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } { Attribute *oc = attr_find( e->e_attrs, slap_schema.si_ad_objectClass ); if( oc == NULL ) { fprintf( stderr, "%s: dn=\"%s\" (line=%d): %s\n", progname, e->e_dn, lineno, "no objectClass attribute"); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } /* check schema */ op->o_bd = be; if ( (slapMode & SLAP_TOOL_NO_SCHEMA_CHECK) == 0) { rc = entry_schema_check( op, e, NULL, manage, 1, &text, textbuf, textlen ); if( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s: dn=\"%s\" (line=%d): (%d) %s\n", progname, e->e_dn, lineno, rc, text ); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } textbuf[ 0 ] = '\0'; } } if ( SLAP_LASTMOD(be) ) { time_t now = slap_get_time(); char uuidbuf[ LDAP_LUTIL_UUIDSTR_BUFSIZE ]; struct berval vals[ 2 ]; struct berval name, timestamp; struct berval nvals[ 2 ]; struct berval nname; char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; vals[1].bv_len = 0; vals[1].bv_val = NULL; nvals[1].bv_len = 0; nvals[1].bv_val = NULL; csn.bv_len = lutil_csnstr( csnbuf, sizeof( csnbuf ), csnsid, 0 ); csn.bv_val = csnbuf; timestamp.bv_val = timebuf; timestamp.bv_len = sizeof(timebuf); slap_timestamp( &now, ×tamp ); if ( BER_BVISEMPTY( &be->be_rootndn ) ) { BER_BVSTR( &name, SLAPD_ANONYMOUS ); nname = name; } else { name = be->be_rootdn; nname = be->be_rootndn; } if( attr_find( e->e_attrs, slap_schema.si_ad_entryUUID ) == NULL ) { vals[0].bv_len = lutil_uuidstr( uuidbuf, sizeof( uuidbuf ) ); vals[0].bv_val = uuidbuf; attr_merge_normalize_one( e, slap_schema.si_ad_entryUUID, vals, NULL ); } if( attr_find( e->e_attrs, slap_schema.si_ad_creatorsName ) == NULL ) { vals[0] = name; nvals[0] = nname; attr_merge( e, slap_schema.si_ad_creatorsName, vals, nvals ); } if( attr_find( e->e_attrs, slap_schema.si_ad_createTimestamp ) == NULL ) { vals[0] = timestamp; attr_merge( e, slap_schema.si_ad_createTimestamp, vals, NULL ); } if( attr_find( e->e_attrs, slap_schema.si_ad_entryCSN ) == NULL ) { vals[0] = csn; attr_merge( e, slap_schema.si_ad_entryCSN, vals, NULL ); } if( attr_find( e->e_attrs, slap_schema.si_ad_modifiersName ) == NULL ) { vals[0] = name; nvals[0] = nname; attr_merge( e, slap_schema.si_ad_modifiersName, vals, nvals ); } if( attr_find( e->e_attrs, slap_schema.si_ad_modifyTimestamp ) == NULL ) { vals[0] = timestamp; attr_merge( e, slap_schema.si_ad_modifyTimestamp, vals, NULL ); } if ( update_ctxcsn ) { int rc_sid; attr = attr_find( e->e_attrs, slap_schema.si_ad_entryCSN ); assert( attr != NULL ); rc_sid = slap_parse_csn_sid( &attr->a_nvals[ 0 ] ); if ( rc_sid < 0 ) { Debug( LDAP_DEBUG_ANY, "%s: could not " "extract SID from entryCSN=%s\n", progname, attr->a_nvals[ 0 ].bv_val, 0 ); } else { assert( rc_sid <= SLAP_SYNC_SID_MAX ); sid = (unsigned)rc_sid; if ( maxcsn[ sid ].bv_len != 0 ) { match = 0; value_match( &match, slap_schema.si_ad_entryCSN, slap_schema.si_ad_entryCSN->ad_type->sat_ordering, SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, &maxcsn[ sid ], &attr->a_nvals[0], &text ); } else { match = -1; } if ( match < 0 ) { strcpy( maxcsn[ sid ].bv_val, attr->a_nvals[0].bv_val ); maxcsn[ sid ].bv_len = attr->a_nvals[0].bv_len; } } } } if ( !dryrun ) { id = be->be_entry_put( be, e, &bvtext ); if( id == NOID ) { fprintf( stderr, "%s: could not add entry dn=\"%s\" " "(line=%d): %s\n", progname, e->e_dn, lineno, bvtext.bv_val ); rc = EXIT_FAILURE; entry_free( e ); if( continuemode ) continue; break; } if ( verbose ) fprintf( stderr, "added: \"%s\" (%08lx)\n", e->e_dn, (long) id ); } else { if ( verbose ) fprintf( stderr, "added: \"%s\"\n", e->e_dn ); } entry_free( e ); } bvtext.bv_len = textlen; bvtext.bv_val = textbuf; bvtext.bv_val[0] = '\0'; if ( rc == EXIT_SUCCESS && update_ctxcsn && !dryrun && sid != SLAP_SYNC_SID_MAX + 1 ) { ctxcsn_id = be->be_dn2id_get( be, be->be_nsuffix ); if ( ctxcsn_id == NOID ) { fprintf( stderr, "%s: context entry is missing\n", progname ); rc = EXIT_FAILURE; } else { ctxcsn_e = be->be_entry_get( be, ctxcsn_id ); if ( ctxcsn_e != NULL ) { Entry *e = entry_dup( ctxcsn_e ); int change; attr = attr_find( e->e_attrs, slap_schema.si_ad_contextCSN ); if ( attr ) { int i; change = 0; for ( i = 0; !BER_BVISNULL( &attr->a_nvals[ i ] ); i++ ) { int rc_sid; rc_sid = slap_parse_csn_sid( &attr->a_nvals[ i ] ); if ( rc_sid < 0 ) { Debug( LDAP_DEBUG_ANY, "%s: unable to extract SID " "from #%d contextCSN=%s\n", progname, i, attr->a_nvals[ i ].bv_val ); continue; } assert( rc_sid <= SLAP_SYNC_SID_MAX ); sid = (unsigned)rc_sid; if ( maxcsn[ sid ].bv_len == 0 ) { match = -1; } else { value_match( &match, slap_schema.si_ad_entryCSN, slap_schema.si_ad_entryCSN->ad_type->sat_ordering, SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, &maxcsn[ sid ], &attr->a_nvals[i], &text ); } if ( match > 0 ) { change = 1; } else { AC_MEMCPY( maxcsn[ sid ].bv_val, attr->a_nvals[ i ].bv_val, attr->a_nvals[ i ].bv_len ); maxcsn[ sid ].bv_val[ attr->a_nvals[ i ].bv_len ] = '\0'; maxcsn[ sid ].bv_len = attr->a_nvals[ i ].bv_len; } } if ( change ) { if ( attr->a_nvals != attr->a_vals ) { ber_bvarray_free( attr->a_nvals ); } attr->a_nvals = NULL; ber_bvarray_free( attr->a_vals ); attr->a_vals = NULL; attr->a_numvals = 0; } } else { change = 1; } if ( change ) { for ( sid = 0; sid <= SLAP_SYNC_SID_MAX; sid++ ) { if ( maxcsn[ sid ].bv_len ) { attr_merge_one( e, slap_schema.si_ad_contextCSN, &maxcsn[ sid], NULL ); } } ctxcsn_id = be->be_entry_modify( be, e, &bvtext ); if( ctxcsn_id == NOID ) { fprintf( stderr, "%s: could not modify ctxcsn\n", progname); rc = EXIT_FAILURE; } else if ( verbose ) { fprintf( stderr, "modified: \"%s\" (%08lx)\n", e->e_dn, (long) ctxcsn_id ); } } entry_free( e ); } } } ch_free( buf ); if ( !dryrun ) { if( be->be_entry_close( be ) ) { rc = EXIT_FAILURE; } if( be->be_sync ) { be->be_sync( be ); } } slap_tool_destroy(); return rc; }
static int cloak_search_cb( Operation *op, SlapReply *rs ) { slap_callback *sc; cloak_info_t *ci; Entry *e = NULL; Entry *me = NULL; assert( op && op->o_callback && rs ); if ( rs->sr_type != REP_SEARCH || !rs->sr_entry ) { slap_freeself_cb( op, rs ); return ( SLAP_CB_CONTINUE ); } sc = op->o_callback; e = rs->sr_entry; /* * First perform a quick scan for an attribute to cloak */ for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) { Attribute *a; if ( ci->ci_oc != NULL && !is_entry_objectclass_or_sub( e, ci->ci_oc ) ) continue; for ( a = e->e_attrs; a; a = a->a_next ) if ( a->a_desc == ci->ci_ad ) break; if ( a != NULL ) break; } /* * Nothing found to cloak */ if ( ci == NULL ) return ( SLAP_CB_CONTINUE ); /* * We are now committed to cloak an attribute. */ if ( rs->sr_flags & REP_ENTRY_MODIFIABLE ) me = e; else me = entry_dup( e ); for ( ci = (cloak_info_t *)sc->sc_private; ci; ci = ci->ci_next ) { Attribute *a; Attribute *pa; for ( pa = NULL, a = me->e_attrs; a; pa = a, a = a->a_next ) { if ( a->a_desc != ci->ci_ad ) continue; Debug( LDAP_DEBUG_TRACE, "cloak_search_cb: cloak %s\n", a->a_desc->ad_cname.bv_val, 0, 0 ); if ( pa != NULL ) pa->a_next = a->a_next; else me->e_attrs = a->a_next; attr_clean( a ); } } if ( me != e ) { if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) entry_free( e ); rs->sr_entry = me; rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED; } return ( SLAP_CB_CONTINUE ); }
static int adremap_search_resp( Operation *op, SlapReply *rs ) { adremap_ctx *ctx = op->o_callback->sc_private; slap_overinst *on = ctx->on; adremap_info *ai = on->on_bi.bi_private; adremap_case *ac; adremap_dnv *ad; Attribute *a; Entry *e; if (rs->sr_type != REP_SEARCH) return SLAP_CB_CONTINUE; /* we munged the attr list, restore it to original */ if (ctx->an_swap) { int i; ctx->an_swap = 0; for (i=0; rs->sr_attrs[i].an_name.bv_val; i++) { if (rs->sr_attrs[i].an_desc == ctx->ad) { rs->sr_attrs[i] = ctx->an; break; } } /* Usually rs->sr_attrs is just op->ors_attrs, but * overlays like rwm may make a new copy. Fix both * if needed. */ if (op->ors_attrs != rs->sr_attrs) { for (i=0; op->ors_attrs[i].an_name.bv_val; i++) { if (op->ors_attrs[i].an_desc == ctx->ad) { op->ors_attrs[i] = ctx->an; break; } } } } e = rs->sr_entry; for (ac = ai->ai_case; ac; ac = ac->ac_next) { a = attr_find(e->e_attrs, ac->ac_attr); if (a) { int i, j; if (!(rs->sr_flags & REP_ENTRY_MODIFIABLE)) { e = entry_dup(e); rs_replace_entry(op, rs, on, e); rs->sr_flags |= REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED; a = attr_find(e->e_attrs, ac->ac_attr); } for (i=0; i<a->a_numvals; i++) { unsigned char *c = a->a_vals[i].bv_val; for (j=0; j<a->a_vals[i].bv_len; j++) if (isupper(c[j])) c[j] = tolower(c[j]); } } } for (ad = ai->ai_dnv; ad; ad = ad->ad_next) { a = attr_find(e->e_attrs, ad->ad_dnattr); if (a) { Entry *n; Attribute *dr; int i, rc; if (!(rs->sr_flags & REP_ENTRY_MODIFIABLE)) { e = entry_dup(e); rs_replace_entry(op, rs, on, e); rs->sr_flags |= REP_ENTRY_MODIFIABLE|REP_ENTRY_MUSTBEFREED; a = attr_find(e->e_attrs, ad->ad_dnattr); } for (i=0; i<a->a_numvals; i++) { struct berval dv; dv = ad->ad_deref->ad_cname; /* If the RDN uses the deref attr, just use it directly */ if (a->a_nvals[i].bv_val[dv.bv_len] == '=' && !memcmp(a->a_nvals[i].bv_val, dv.bv_val, dv.bv_len)) { struct berval bv, nv; char *ptr; bv = a->a_vals[i]; nv = a->a_nvals[i]; bv.bv_val += dv.bv_len + 1; ptr = strchr(bv.bv_val, ','); if (ptr) bv.bv_len = ptr - bv.bv_val; else bv.bv_len -= dv.bv_len+1; nv.bv_val += dv.bv_len + 1; ptr = strchr(nv.bv_val, ','); if (ptr) nv.bv_len = ptr - nv.bv_val; else nv.bv_len -= dv.bv_len+1; attr_merge_one(e, ad->ad_newattr, &bv, &nv); } else { /* otherwise look up the deref attr */ n = NULL; rc = be_entry_get_rw(op, &a->a_nvals[i], NULL, ad->ad_deref, 0, &n); if (!rc && n) { dr = attr_find(n->e_attrs, ad->ad_deref); if (dr) attr_merge_one(e, ad->ad_newattr, dr->a_vals, dr->a_nvals); be_entry_release_r(op, n); } } } } } return SLAP_CB_CONTINUE; }
void dir_crawl(GTree *t, GHashTable *linkhash, GHashTable *userhash, GHashTable *grouphash, char *path) { DIR *dir; struct dirent *dent; struct rdup *directory; struct chown_pack *cp; char *curpath; gchar *lnk; struct stat s; struct rdup pop; struct remove_path rp; dev_t current_dev; size_t curpath_len; /* dir stack */ gint32 d = 0; gint32 dstack_cnt = 1; struct rdup **dirstack = g_malloc(dstack_cnt * D_STACKSIZE * sizeof(struct rdup *)); if (!(dir = opendir(path))) { /* non-dirs are also allowed, check for this, if it isn't give the error */ if (access(path, R_OK) == 0) { g_free(dirstack); return; } msg(_("Cannot enter directory `%s\': %s"), path, strerror(errno)); g_free(dirstack); return; } /* get device */ #ifdef HAVE_DIRFD if (fstat(dirfd(dir), &s) != 0) { #else if (fstat(rdup_dirfd(dir), &s) != 0) { #endif msg(_("Cannot determine holding device of the directory `%s\': %s"), path, strerror(errno)); closedir(dir); g_free(dirstack); return; } current_dev = s.st_dev; while((dent = readdir(dir))) { if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; if (opt_chown) { if ( !strncmp(dent->d_name, USRGRPINFO, LEN_USRGRPINFO) ) { continue; } } if (strcmp(path, "/") == 0) { curpath = g_strdup_printf("/%s", dent->d_name); curpath_len = strlen(curpath); } else { curpath = g_strdup_printf("%s/%s", path, dent->d_name); curpath_len = strlen(curpath); } if (lstat(curpath, &s) != 0) { msg(_("Could not stat path `%s\': %s"), curpath, strerror(errno)); g_free(curpath); continue; } if (strchr(curpath, '\n')) { msg(_("Newline (\\n) found in path `%s\', skipping"), curpath); g_free(curpath); continue; } if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode) || S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode) || S_ISFIFO(s.st_mode) || S_ISSOCK(s.st_mode) ) { pop.f_name = curpath; pop.f_target = NULL; pop.f_name_size = curpath_len; pop.f_uid = s.st_uid; pop.f_user = lookup_user(userhash, pop.f_uid); pop.f_gid = s.st_gid; pop.f_group = lookup_group(grouphash, pop.f_gid); pop.f_ctime = s.st_ctime; pop.f_mtime = s.st_mtime; pop.f_atime = s.st_atime; pop.f_mode = s.st_mode; pop.f_size = s.st_size; pop.f_dev = s.st_dev; pop.f_rdev = s.st_rdev; pop.f_ino = s.st_ino; pop.f_lnk = 0; if (gfunc_regexp(pregex_list, curpath, curpath_len)) { g_free(curpath); continue; } if (opt_nobackup && !strcmp(dent->d_name, NOBACKUP)) { /* return after seeing .nobackup */ if (opt_verbose > 0) { msg(_("%s found in '%s\'"), NOBACKUP, path); } /* remove all files found in this path */ rp.tree = t; rp.len = strlen(path); rp.path = path; g_tree_foreach(t, gfunc_remove_path, (gpointer)&rp); /* add .nobackup back in */ g_tree_insert(t, (gpointer) entry_dup(&pop), VALUE); g_free(dirstack); closedir(dir); return; } /* hardlinks */ if (s.st_nlink > 1) { if ((lnk = hlink(linkhash, &pop))) { pop.f_target = lnk; pop.f_lnk = 1; } } if (S_ISLNK(s.st_mode)) pop.f_target = slink(&pop); if (S_ISLNK(s.st_mode) || pop.f_lnk) { /* fix the name and the sizes */ pop.f_size = pop.f_name_size; pop.f_name_size += 4 + strlen(pop.f_target); } /* check for USRGRPINFO file */ if ( opt_chown && (cp = chown_parse(path, dent->d_name)) != NULL ) { pop.f_uid = cp->u; pop.f_gid = cp->g; pop.f_user = cp->user; pop.f_group = cp->group; } g_tree_insert(t, (gpointer) entry_dup(&pop), VALUE); if (pop.f_target != NULL) g_free(pop.f_target); g_free(curpath); continue; } else if(S_ISDIR(s.st_mode)) { /* one filesystem */ if (opt_onefilesystem && s.st_dev != current_dev) { msg(_("Not walking into different filesystem `%s\'"), curpath); g_free(curpath); continue; } /* Exclude list */ if (gfunc_regexp(pregex_list, curpath, curpath_len)) { g_free(curpath); continue; } dirstack[d] = g_malloc(sizeof(struct rdup)); dirstack[d]->f_name = g_strdup(curpath); dirstack[d]->f_target = NULL; dirstack[d]->f_name_size = curpath_len; dirstack[d]->f_uid = s.st_uid; dirstack[d]->f_user = lookup_user(userhash, s.st_uid); dirstack[d]->f_gid = s.st_gid; dirstack[d]->f_group = lookup_group(grouphash, s.st_gid); dirstack[d]->f_ctime = s.st_ctime; dirstack[d]->f_mtime = s.st_mtime; dirstack[d]->f_atime = s.st_atime; dirstack[d]->f_mode = s.st_mode; dirstack[d]->f_size = s.st_size; dirstack[d]->f_dev = s.st_dev; dirstack[d]->f_rdev = s.st_rdev; dirstack[d]->f_ino = s.st_ino; dirstack[d]->f_lnk = 0; /* check for USRGRPINFO file */ if ( opt_chown && (cp = chown_parse(curpath, NULL)) != NULL ) { dirstack[d]->f_uid = cp->u; dirstack[d]->f_gid = cp->g; dirstack[d]->f_user = cp->user; dirstack[d]->f_group = cp->group; } if (d++ % D_STACKSIZE == 0) { dirstack = g_realloc(dirstack, ++dstack_cnt * D_STACKSIZE * sizeof(struct rdup *)); } g_free(curpath); continue; } else { if (opt_verbose > 0) { msg(_("Neither file nor directory `%s\'"), curpath); } g_free(curpath); } } closedir(dir); if (opt_atime) { /* reset dirs atime */ if (d > 0 && opt_atime) { struct utimbuf ut; ut.actime = dirstack[d - 1]->f_atime; ut.modtime = dirstack[d - 1]->f_mtime; if (utime(dirstack[d - 1]->f_name, &ut) == -1) msg(_("Failed to reset atime: '%s\': %s"), dirstack[d - 1]->f_name, strerror(errno)); } } while (d > 0) { directory = dirstack[--d]; g_tree_insert(t, (gpointer) entry_dup(directory), VALUE); /* recurse */ /* potentially expensive operation. Better would be to when we hit * .nobackup to go up the tree and delete some nodes.... or not */ dir_crawl(t, linkhash, userhash, grouphash, directory->f_name); entry_free(directory); } g_free(dirstack); return; }
/** * prepend path leading up to backup directory to the tree */ gboolean dir_prepend(GTree *t, char *path, GHashTable *u, GHashTable *g) { char *c; char *p; char *path2; size_t len; struct stat s; struct rdup e; path2 = g_strdup(path); len = strlen(path); /* add closing / */ if (path2[len - 1] != '/') { path2 = g_realloc(path2, len + 2); path2[len] = '/'; path2[len + 1] = '\0'; } for (p = path2 + 1; (c = strchr(p, '/')); p++) { *c = '\0'; if (lstat(path2, &s) != 0) { msg(_("Could not stat path `%s\': %s"), path2, strerror(errno)); g_free(path2); return FALSE; } e.f_name = path2; e.f_target = NULL; e.f_name_size = strlen(path2); e.f_uid = s.st_uid; e.f_user = lookup_user(u, e.f_uid); e.f_gid = s.st_gid; e.f_group = lookup_group(g, e.f_gid); e.f_ctime = s.st_ctime; e.f_mtime = s.st_mtime; e.f_atime = s.st_atime; e.f_mode = s.st_mode; e.f_size = s.st_size; e.f_dev = s.st_dev; e.f_rdev = s.st_rdev; e.f_ino = s.st_ino; e.f_lnk = 0; /* symlinks; also set the target */ if (S_ISLNK(s.st_mode)) { e.f_target = slink(&e); e.f_size = e.f_name_size; e.f_name_size += 4 + strlen(e.f_target); /* When we encounter a symlink on this level, it is very hard to make this * backup work, because the target may fall out of the backup. If this * is the case the entire backup fails. Gnu tar only show the symlink * and then stops. We do now the same, heance the return FALSE */ g_tree_insert(t, (gpointer) entry_dup(&e), VALUE); g_free(e.f_target); g_free(path2); return FALSE; } g_tree_insert(t, (gpointer) entry_dup(&e), VALUE); *c = '/'; p = c++; } g_free(path2); return TRUE; }