/* * lookup instance names by included suffixes and excluded suffixes. * * Get instance names associated with the given included suffixes * as well as the excluded suffixes. * Subtract the excluded instances from the included instance. * Assign the result to instances. */ int slapi_lookup_instance_name_by_suffixes(char **included, char **excluded, char ***instances) { char **incl_instances, **excl_instances; char **p; int rval = -1; if (instances == NULL) return rval; *instances = NULL; incl_instances = NULL; for (p = included; p && *p; p++) { if (slapi_lookup_instance_name_by_suffix(*p, NULL, &incl_instances, 0) < 0) return rval; } excl_instances = NULL; for (p = excluded; p && *p; p++) { /* okay to be empty */ slapi_lookup_instance_name_by_suffix(*p, NULL, &excl_instances, 0); } rval = 0; if (excl_instances) { charray_subtract(incl_instances, excl_instances, NULL); charray_free(excl_instances); } *instances = incl_instances; return rval; }
int _ger_generate_template_entry ( Slapi_PBlock *pb ) { Slapi_Entry *e = NULL; char **gerattrs = NULL; char **attrs = NULL; char **allowedattrs = NULL; char *templateentry = NULL; char *object = NULL; char *superior = NULL; char *p = NULL; const char *dn = NULL; Slapi_DN *sdn = NULL; char *dntype = NULL; int siz = 0; int len = 0; int i = 0; int notfirst = 0; int rc = LDAP_SUCCESS; slapi_pblock_get( pb, SLAPI_SEARCH_GERATTRS, &gerattrs ); if (NULL == gerattrs) { slapi_log_err(SLAPI_LOG_ERR, plugin_name, "_ger_generate_template_entry - Objectclass info is expected " "in the attr list, e.g., \"*@person\"\n"); rc = LDAP_SUCCESS; goto bailout; } for (i = 0; gerattrs && gerattrs[i]; i++) { object = strchr(gerattrs[i], '@'); if (NULL != object && '\0' != *(++object)) { break; } } if (NULL == object) { rc = LDAP_SUCCESS; /* no objectclass info; ok to return */ goto bailout; } /* * Either @objectclass or @objectclass:dntype is accepted. * If @objectclass, the first MUST attributetype (or the first MAY * attributetype if MUST does not exist) is used for the attribute * type in the leaf RDN. * If @objectclass:dntype, dntype is used for the attribute type in the * leaf RDN. */ dntype = strchr(object, ':'); if (dntype) { /* @objectclasse:dntype */ *dntype++ = '\0'; } attrs = slapi_schema_list_objectclass_attributes( (const char *)object, SLAPI_OC_FLAG_REQUIRED); allowedattrs = slapi_schema_list_objectclass_attributes( (const char *)object, SLAPI_OC_FLAG_ALLOWED); charray_merge(&attrs, allowedattrs, 0 /* no copy */); slapi_ch_free((void **)&allowedattrs); /* free just allowedattrs */ if (NULL == attrs) { rc = LDAP_SUCCESS; /* bogus objectclass info; ok to return */ goto bailout; } for (i = 0; attrs[i]; i++) { if (0 == strcasecmp(attrs[i], "objectclass")) { /* <*attrp>: <object>\n\0 */ siz += strlen(attrs[i]) + 4 + strlen(object); } else { /* <*attrp>: (template_attribute)\n\0 */ siz += strlen(attrs[i]) + 4 + 20; } } /* get the target dn where the template entry is located */ slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn ); dn = slapi_sdn_get_dn(sdn); if (dn) { /* dn: <attr>=<template_name>,<dn>\n\0 */ if (dntype) { siz += strlen(dntype) + 30 + strlen(object) + strlen(dn); } else { siz += strlen(attrs[0]) + 30 + strlen(object) + strlen(dn); } } else { /* dn: <attr>=<template_name>\n\0 */ if (dntype) { siz += strlen(dntype) + 30 + strlen(object); } else { siz += strlen(attrs[0]) + 30 + strlen(object); } } templateentry = (char *)slapi_ch_malloc(siz); if (NULL != dn && strlen(dn) > 0) { PR_snprintf(templateentry, siz, "dn: %s=template_%s_objectclass,%s\n", dntype?dntype:attrs[0], object, dn); } else { PR_snprintf(templateentry, siz, "dn: %s=template_%s_objectclass\n", dntype?dntype:attrs[0], object); } for (--i; i >= 0; i--) { len = strlen(templateentry); p = templateentry + len; if (0 == strcasecmp(attrs[i], "objectclass")) { PR_snprintf(p, siz - len, "%s: %s\n", attrs[i], object); } else { PR_snprintf(p, siz - len, "%s: (template_attribute)\n", attrs[i]); } } charray_free(attrs); while ((superior = slapi_schema_get_superior_name(object)) && (0 != strcasecmp(superior, "top"))) { if (notfirst) { slapi_ch_free_string(&object); } notfirst = 1; object = superior; attrs = slapi_schema_list_objectclass_attributes( (const char *)superior, SLAPI_OC_FLAG_REQUIRED); for (i = 0; attrs && attrs[i]; i++) { if (0 == strcasecmp(attrs[i], "objectclass")) { /* <*attrp>: <object>\n\0 */ siz += strlen(attrs[i]) + 4 + strlen(object); } } templateentry = (char *)slapi_ch_realloc(templateentry, siz); for (--i; i >= 0; i--) { len = strlen(templateentry); p = templateentry + len; if (0 == strcasecmp(attrs[i], "objectclass")) { PR_snprintf(p, siz - len, "%s: %s\n", attrs[i], object); } } charray_free(attrs); } if (notfirst) { slapi_ch_free_string(&object); } slapi_ch_free_string(&superior); siz += 18; /* objectclass: top\n\0 */ len = strlen(templateentry); templateentry = (char *)slapi_ch_realloc(templateentry, siz); p = templateentry + len; PR_snprintf(p, siz - len, "objectclass: top\n"); e = slapi_str2entry(templateentry, SLAPI_STR2ENTRY_NOT_WELL_FORMED_LDIF); /* set the template entry to send the result to clients */ slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, e); bailout: slapi_ch_free_string(&templateentry); return rc; }
void _ger_get_attrs_rights ( Slapi_PBlock *gerpb, Slapi_Entry *e, const char *subjectndn, char **attrs, char **gerstr, size_t *gerstrsize, size_t *gerstrcap, char **errbuf ) { int isfirstattr = 1; /* gerstr was initially allocated with enough space for one more line */ _append_gerstr(gerstr, gerstrsize, gerstrcap, "attributeLevelRights: ", NULL); /* * If it's stated attribute list is given, * the first attr in the list should not be empty. * Otherwise, it's considered the list is not given. */ if (attrs && *attrs && (strlen(*attrs) > 0)) { int i = 0; char **allattrs = NULL; char **opattrs = NULL; char **noexpattrs = NULL; /* attrs not to expose */ char **myattrs = NULL; char **thisattr = NULL; int hasstar = charray_inlist(attrs, "*"); int hasplus = charray_inlist(attrs, "+"); Slapi_Attr *objclasses = NULL; Slapi_ValueSet *objclassvals = NULL; int isextensibleobj = 0; /* get all attrs available for the entry */ slapi_entry_attr_find(e, "objectclass", &objclasses); if (NULL != objclasses) { Slapi_Value *v; slapi_attr_get_valueset(objclasses, &objclassvals); i = slapi_valueset_first_value(objclassvals, &v); if (-1 != i) { const char *ocname = NULL; allattrs = slapi_schema_list_objectclass_attributes( (const char *)v->bv.bv_val, SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); /* check if this entry is an extensble object or not */ ocname = slapi_value_get_string(v); if ( strcasecmp( ocname, "extensibleobject" ) == 0 ) { isextensibleobj = 1; } /* add "aci" to the allattrs to adjust to do_search */ charray_add(&allattrs, slapi_attr_syntax_normalize("aci")); while (-1 != i) { i = slapi_valueset_next_value(objclassvals, i, &v); if (-1 != i) { myattrs = slapi_schema_list_objectclass_attributes( (const char *)v->bv.bv_val, SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); /* check if this entry is an extensble object or not */ ocname = slapi_value_get_string(v); if ( strcasecmp( ocname, "extensibleobject" ) == 0 ) { isextensibleobj = 1; } charray_merge_nodup(&allattrs, myattrs, 1/*copy_strs*/); charray_free(myattrs); } } } slapi_valueset_free(objclassvals); } /* get operational attrs */ opattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_OPATTR); noexpattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_NOEXPOSE); /* subtract no expose attrs from opattrs (e.g., unhashed pw) */ charray_subtract(opattrs, noexpattrs, NULL); if (isextensibleobj) { for ( i = 0; attrs[i]; i++ ) { if ('\0' == *attrs[i]) { continue; /* skip an empty attr */ } _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } } else { if (hasstar && hasplus) { GER_GET_ATTR_RIGHTS(allattrs); GER_GET_ATTR_RIGHTS(opattrs); } else if (hasstar) { GER_GET_ATTR_RIGHTS(allattrs); GER_GET_ATTR_RIGHTA_EXT('*', opattrs, allattrs); } else if (hasplus) { GER_GET_ATTR_RIGHTS(opattrs); GER_GET_ATTR_RIGHTA_EXT('+', allattrs, opattrs); } else { for ( i = 0; attrs[i]; i++ ) { if ('\0' == *attrs[i]) { continue; /* skip an empty attr */ } if (charray_inlist(noexpattrs, attrs[i])) { continue; } else if (charray_inlist(allattrs, attrs[i]) || charray_inlist(opattrs, attrs[i]) || (0 == strcasecmp(attrs[i], "dn")) || (0 == strcasecmp(attrs[i], "distinguishedName"))) { _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } else { /* if the attr does not belong to the entry, "<attr>:none" is returned */ if (!isfirstattr) { _append_gerstr(gerstr, gerstrsize, gerstrcap, ", ", NULL); } _append_gerstr(gerstr, gerstrsize, gerstrcap, attrs[i], ":"); _append_gerstr(gerstr, gerstrsize, gerstrcap, "none", NULL); isfirstattr = 0; } } } } charray_free(allattrs); charray_free(opattrs); } else { Slapi_Attr *prevattr = NULL, *attr; char *type; while ( slapi_entry_next_attr ( e, prevattr, &attr ) == 0 ) { if ( ! slapi_attr_flag_is_set (attr, SLAPI_ATTR_FLAG_OPATTR) ) { slapi_attr_get_type ( attr, &type ); _ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } prevattr = attr; } } if ( isfirstattr ) { /* not a single attribute was retrived or specified */ _append_gerstr(gerstr, gerstrsize, gerstrcap, "*:none", NULL); } return; }
static int changelog4_create_be() { int i, dir_count = 5; Slapi_Backend *rbe; slapi_be_config config; char *cl_dir = changelog4_get_dir (); char *cl_suffix; if ( cl_dir == NULL ) { slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "Error: no directory specified for changelog database.\n"); return -1; } cl_suffix = changelog4_get_suffix (); if ( cl_suffix == NULL ) { slapi_ch_free ((void **)&cl_dir); slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "Error: no suffix specified for changelog database.\n"); return -1; } /* setup configuration parameters for backend initialization */ config.type = CHANGELOG_LDBM_TYPE; config.suffix = cl_suffix; config.is_private = 1; /* yes */ config.log_change = 0; /* no */ config.directives = (slapi_config_directive*)slapi_ch_calloc( dir_count, sizeof(slapi_config_directive)); config.dir_count = dir_count; for (i = 0; i < dir_count; i++) { config.directives[i].file_name = "(internal)"; config.directives[i].lineno = 0; } /* setup indexes */ config.directives[0].argv = NULL; config.directives[0].argc = 3; charray_add( &(config.directives[0].argv), slapi_ch_strdup( "index" )); charray_add( &(config.directives[0].argv), slapi_ch_strdup( attr_changenumber )); charray_add( &(config.directives[0].argv), slapi_ch_strdup( "eq" )); /* Set up the database directory */ config.directives[1].argv = NULL; config.directives[1].argc = 2; charray_add( &(config.directives[1].argv), slapi_ch_strdup( "directory" )); charray_add( &(config.directives[1].argv), slapi_ch_strdup( cl_dir )); /* Override the entry cache size */ config.directives[2].argv = NULL; config.directives[2].argc = 2; charray_add( &(config.directives[2].argv), slapi_ch_strdup( "cachesize" )); charray_add( &(config.directives[2].argv), slapi_ch_strdup( "10" )); /* Override the database cache size */ config.directives[3].argv = NULL; config.directives[3].argc = 2; charray_add( &(config.directives[3].argv), slapi_ch_strdup( "dbcachesize" )); charray_add( &(config.directives[3].argv), slapi_ch_strdup( "1000000" )); /* Override the allids threshold */ config.directives[4].argv = NULL; config.directives[4].argc = 2; charray_add( &(config.directives[4].argv), slapi_ch_strdup( "allidsthreshold" )); /* assumes sizeof(int) >= 32 bits */ charray_add( &(config.directives[4].argv), slapi_ch_strdup( "2147483647" )); /* rbe = slapi_be_create_instance(&config, LDBM_TYPE); */ rbe= NULL; /* free memory allocated to argv */ for (i = 0; i < dir_count; i++) { charray_free (config.directives[i].argv); } slapi_ch_free ((void **)&config.directives); slapi_ch_free ((void **)&cl_dir); slapi_ch_free ((void **)&cl_suffix); if (rbe == NULL) { slapi_log_err(SLAPI_LOG_ERR, repl_plugin_name, "Error: failed to create changelog backend. " "Replication disabled.\n"); return -1; } set_repl_backend (rbe); changelog4_init_trimming (); return 0; }
/* * Thread routine for sending search results to a client * which is persistently waiting for them. * * This routine will terminate when either (a) the ps_complete * flag is set, or (b) the associated operation is abandoned. * In any case, the thread won't notice until it wakes from * sleeping on the ps_list condition variable, so it needs * to be awakened. */ static void ps_send_results( void *arg ) { PSearch *ps = (PSearch *)arg; PSEQNode *peq, *peqnext; struct slapi_filter *filter = 0; char *base = NULL; Slapi_DN *sdn = NULL; char *fstr = NULL; char **pbattrs = NULL; int conn_acq_flag = 0; g_incr_active_threadcnt(); /* need to acquire a reference to this connection so that it will not be released or cleaned up out from under us */ PR_Lock( ps->ps_pblock->pb_conn->c_mutex ); conn_acq_flag = connection_acquire_nolock(ps->ps_pblock->pb_conn); PR_Unlock( ps->ps_pblock->pb_conn->c_mutex ); if (conn_acq_flag) { slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search", "conn=%" NSPRIu64 " op=%d Could not acquire the connection - psearch aborted\n", ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid); } PR_Lock( psearch_list->pl_cvarlock ); while ( (conn_acq_flag == 0) && !ps->ps_complete ) { /* Check for an abandoned operation */ if ( ps->ps_pblock->pb_op == NULL || slapi_op_abandoned( ps->ps_pblock ) ) { slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search", "conn=%" NSPRIu64 " op=%d The operation has been abandoned\n", ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid); break; } if ( NULL == ps->ps_eq_head ) { /* Nothing to do */ PR_WaitCondVar( psearch_list->pl_cvar, PR_INTERVAL_NO_TIMEOUT ); } else { /* dequeue the item */ int attrsonly; char **attrs; LDAPControl **ectrls; Slapi_Entry *ec; Slapi_Filter *f = NULL; PR_Lock( ps->ps_lock ); peq = ps->ps_eq_head; ps->ps_eq_head = peq->pe_next; if ( NULL == ps->ps_eq_head ) { ps->ps_eq_tail = NULL; } PR_Unlock( ps->ps_lock ); /* Get all the information we need to send the result */ ec = peq->pe_entry; slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_ATTRS, &attrs ); slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_ATTRSONLY, &attrsonly ); if ( !ps->ps_send_entchg_controls || peq->pe_ctrls[0] == NULL ) { ectrls = NULL; } else { ectrls = peq->pe_ctrls; } /* * Send the result. Since send_ldap_search_entry can block for * up to 30 minutes, we relinquish all locks before calling it. */ PR_Unlock(psearch_list->pl_cvarlock); /* * The entry is in the right scope and matches the filter * but we need to redo the filter test here to check access * controls. See the comments at the slapi_filter_test() * call in ps_service_persistent_searches(). */ slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_FILTER, &f ); /* See if the entry meets the filter and ACL criteria */ if ( slapi_vattr_filter_test( ps->ps_pblock, ec, f, 1 /* verify_access */ ) == 0 ) { int rc = 0; slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_RESULT_ENTRY, ec ); rc = send_ldap_search_entry( ps->ps_pblock, ec, ectrls, attrs, attrsonly ); if (rc) { slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search", "conn=%" NSPRIu64 " op=%d Error %d sending entry %s with op status %d\n", ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid, rc, slapi_entry_get_dn_const(ec), ps->ps_pblock->pb_op->o_status); } } PR_Lock(psearch_list->pl_cvarlock); /* Deallocate our wrapper for this entry */ pe_ch_free( &peq ); } } PR_Unlock( psearch_list->pl_cvarlock ); ps_remove( ps ); /* indicate the end of search */ plugin_call_plugins( ps->ps_pblock , SLAPI_PLUGIN_POST_SEARCH_FN ); /* free things from the pblock that were not free'd in do_search() */ /* we strdup'd this in search.c - need to free */ slapi_pblock_get( ps->ps_pblock, SLAPI_ORIGINAL_TARGET_DN, &base ); slapi_pblock_set( ps->ps_pblock, SLAPI_ORIGINAL_TARGET_DN, NULL ); slapi_ch_free_string(&base); /* Free SLAPI_SEARCH_* before deleting op since those are held by op */ slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, &sdn ); slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_TARGET_SDN, NULL ); slapi_sdn_free(&sdn); slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_STRFILTER, &fstr ); slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_STRFILTER, NULL ); slapi_ch_free_string(&fstr); slapi_pblock_get( ps->ps_pblock, SLAPI_SEARCH_ATTRS, &pbattrs ); slapi_pblock_set( ps->ps_pblock, SLAPI_SEARCH_ATTRS, NULL ); if ( pbattrs != NULL ) { charray_free( pbattrs ); } slapi_pblock_get(ps->ps_pblock, SLAPI_SEARCH_FILTER, &filter ); slapi_pblock_set(ps->ps_pblock, SLAPI_SEARCH_FILTER, NULL ); slapi_filter_free(filter, 1); /* Clean up the connection structure */ PR_Lock( ps->ps_pblock->pb_conn->c_mutex ); slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search", "conn=%" NSPRIu64 " op=%d Releasing the connection and operation\n", ps->ps_pblock->pb_conn->c_connid, ps->ps_pblock->pb_op->o_opid); /* Delete this op from the connection's list */ connection_remove_operation( ps->ps_pblock->pb_conn, ps->ps_pblock->pb_op ); operation_free(&(ps->ps_pblock->pb_op),ps->ps_pblock->pb_conn); ps->ps_pblock->pb_op=NULL; /* Decrement the connection refcnt */ if (conn_acq_flag == 0) { /* we acquired it, so release it */ connection_release_nolock (ps->ps_pblock->pb_conn); } PR_Unlock( ps->ps_pblock->pb_conn->c_mutex ); PR_DestroyLock ( ps->ps_lock ); ps->ps_lock = NULL; slapi_ch_free((void **) &ps->ps_pblock ); for ( peq = ps->ps_eq_head; peq; peq = peqnext) { peqnext = peq->pe_next; pe_ch_free( &peq ); } slapi_ch_free((void **) &ps ); g_decr_active_threadcnt(); }