static int ss_index_entry (Slapi_PBlock* pb) /* Compute substring index keys (when writing an entry). */ { auto int rc = LDAP_OPERATIONS_ERROR; auto size_t substringsLen = 0; struct berval** values; auto ss_indexer_t* ss = ss_indexer_get (pb); auto indexer_t* ix = ss ? ss->ss_indexer : NULL; if (ix != NULL && ix->ix_index != NULL && !slapi_pblock_get (pb, SLAPI_PLUGIN_MR_VALUES, &values)) { auto struct berval* substrings = NULL; auto struct berval** prefixes = NULL; auto struct berval** value; for (value = values; *value != NULL; ++value) { auto struct berval substring; substring.bv_val = (*value)->bv_val; substring.bv_len = (*value)->bv_len; if (long_enough (&substring, SS_INDEX_LENGTH-1)) { auto struct berval* prefix = &ss_index_initial; auto size_t offset; for (offset = 0; 1; ++offset) { ++substringsLen; substrings = (struct berval*) slapi_ch_realloc ((void*)substrings, substringsLen * sizeof(struct berval)); memcpy (&(substrings[substringsLen-1]), &substring, sizeof (struct berval)); prefixes = (struct berval**) slapi_ch_realloc ((void*)prefixes, substringsLen * sizeof(struct berval*)); prefixes[substringsLen-1] = prefix; if (offset != 0) LDAP_UTF8INC (substring.bv_val); substring.bv_len = (*value)->bv_len - (substring.bv_val - (*value)->bv_val); if (long_enough (&substring, SS_INDEX_LENGTH)) { prefix = &ss_index_middle; } else if (long_enough (&substring, SS_INDEX_LENGTH-1)) { prefix = &ss_index_final; } else { break; } } } } if (substrings != NULL) { auto struct berval** vector = (struct berval**) slapi_ch_malloc ((substringsLen+1) * sizeof(struct berval*)); auto size_t i; for (i = 0; i < substringsLen; ++i) vector[i] = &(substrings[i]); vector[substringsLen] = NULL; rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_KEYS, ix->ix_index (ix, vector, prefixes)); slapi_ch_free((void**)&vector); slapi_ch_free((void**)&substrings); slapi_ch_free((void**)&prefixes); } } slapi_log_err(SLAPI_LOG_FILTER, COLLATE_PLUGIN_SUBSYSTEM, "ss_index_entry - (%p) %i %lu substrings\n", (void*)ss, rc, (unsigned long)substringsLen); return rc; }
int slapi_register_object_extension( const char *pluginname, const char *objectname, slapi_extension_constructor_fnptr constructor, slapi_extension_destructor_fnptr destructor, int *objecttype, int *extensionhandle) { int rc; slapi_extension_t type; struct slapi_registered_extension *re; ldap_pvt_thread_mutex_lock( ®istered_extensions.mutex ); rc = map_extension_type( objectname, &type ); if ( rc != 0 ) { ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex ); return rc; } *objecttype = (int)type; re = ®istered_extensions.extensions[*objecttype]; *extensionhandle = re->count; if ( re->active ) { /* can't add new extensions after objects have been created */ ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex ); return -1; } re->count++; if ( re->constructors == NULL ) { re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_calloc( re->count, sizeof( slapi_extension_constructor_fnptr ) ); } else { re->constructors = (slapi_extension_constructor_fnptr *)slapi_ch_realloc( (char *)re->constructors, re->count * sizeof( slapi_extension_constructor_fnptr ) ); } re->constructors[*extensionhandle] = constructor; if ( re->destructors == NULL ) { re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_calloc( re->count, sizeof( slapi_extension_destructor_fnptr ) ); } else { re->destructors = (slapi_extension_destructor_fnptr *)slapi_ch_realloc( (char *)re->destructors, re->count * sizeof( slapi_extension_destructor_fnptr ) ); } re->destructors[*extensionhandle] = destructor; ldap_pvt_thread_mutex_unlock( ®istered_extensions.mutex ); return 0; }
Slapi_Backend * slapi_be_new( const char *type, const char *name, int isprivate, int logchanges ) { Slapi_Backend *be; int i; /* should add some locking here to prevent concurrent access */ if ( nbackends == maxbackends ) { int oldsize = maxbackends; maxbackends += BACKEND_GRAB_SIZE; backends = (Slapi_Backend **) slapi_ch_realloc( (char *) backends, maxbackends * sizeof(Slapi_Backend *) ); memset( &backends[oldsize], '\0', BACKEND_GRAB_SIZE * sizeof(Slapi_Backend *) ); } for (i=0; ((i<maxbackends) && (backends[i])); i++) ; PR_ASSERT(i<maxbackends); be = (Slapi_Backend *) slapi_ch_calloc(1, sizeof(Slapi_Backend)); be->be_lock = slapi_new_rwlock(); be_init( be, type, name, isprivate, logchanges, defsize, deftime ); backends[i] = be; nbackends++; slapi_log_err(SLAPI_LOG_TRACE, "slapi_be_new", "Added new backend name [%s] type [%s] nbackends [%d]\n", name, type, nbackends); return( be ); }
/* * vals - The existing values. * addval - The value to add. * nvals - The number of existing values. * maxvals - The number of elements in the existing values array. */ void bervalarray_add_berval_fast( struct berval ***vals, const struct berval *addval, int nvals, int *maxvals ) { int need = nvals + 2; if(need>*maxvals) { if (*maxvals==0) { *maxvals = 2; } while ( *maxvals < need ) { *maxvals *= 2; } if(*vals==NULL) { *vals = (struct berval **) slapi_ch_malloc( *maxvals * sizeof(struct berval *)); } else { *vals = (struct berval **) slapi_ch_realloc( (char *) *vals, *maxvals * sizeof(struct berval *)); } } (*vals)[nvals] = ber_bvdup( (struct berval *)addval ); (*vals)[nvals+1] = NULL; }
/* index == 1 : insert first */ void dl_add_index (DataList *dl, void *element, int index) { int i = 0; PR_ASSERT (dl); PR_ASSERT (element); if (dl->element_count == dl->alloc_count) { dl->alloc_count += ALLOC_INCREMENT; dl->elements = (void**)slapi_ch_realloc ((char*)dl->elements, dl->alloc_count * sizeof (void*)); } dl->element_count ++; for (i = dl->element_count-1; i >= index; i--) { dl->elements[i] = dl->elements[i-1]; } if ( dl->element_count < index ) { /* Means that we are adding the first element */ dl->elements[0] = element; } else { dl->elements[i] = element; } }
static void addMod(LDAPMod ***modary, int *capacity, int *nmods, LDAPMod *toadd) { if (*nmods == *capacity) { *capacity += 4; if (*modary) { *modary = (LDAPMod **)slapi_ch_realloc((char *)*modary, *capacity * sizeof(LDAPMod *)); } else { *modary = (LDAPMod **)slapi_ch_malloc(*capacity * sizeof(LDAPMod *)); } } (*modary)[*nmods] = toadd; (*nmods)++; }
void dl_add (DataList *dl, void *element) { PR_ASSERT (dl); PR_ASSERT (element); if (dl->element_count == dl->alloc_count) { dl->alloc_count += ALLOC_INCREMENT; dl->elements = (void**)slapi_ch_realloc ((char*)dl->elements, dl->alloc_count * sizeof (void*)); } dl->elements[dl->element_count] = element; dl->element_count ++; }
/* capacity is the capacity of the gerstr, size is the current length */ static void _append_gerstr( char **gerstr, size_t *capacity, size_t *size, const char *news, const char *news2 ) { size_t len; size_t increment = 128; size_t fornull; if (!news) { return; } /* find out how much space we need */ len = strlen(news); fornull = 1; if (news2) { len += strlen(news2); fornull++; } /* increase space if needed */ while ((*size + len + fornull) > *capacity) { if ((len + fornull) > increment) { *capacity += len + fornull; /* just go ahead and grow the string enough */ } else { *capacity += increment; /* rather than having lots of small increments */ } } if (!*gerstr) { *gerstr = slapi_ch_malloc(*capacity); **gerstr = 0; } else { *gerstr = slapi_ch_realloc(*gerstr, *capacity); } strcat(*gerstr, news); if (news2) { strcat(*gerstr, news2); } *size += len; return; }
static int convert_to_string(Slapi_DN *dn, void *arg) { struct list_to_string_data *data = (struct list_to_string_data *)arg; int newlen = slapi_sdn_get_ndn_len(dn) + strlen(data->delimiter) + 1; if (data->string) { newlen += strlen(data->string); data->string = slapi_ch_realloc(data->string, newlen); } else { data->string = slapi_ch_calloc(1, newlen); } strcat(data->string, slapi_sdn_get_dn(dn)); strcat(data->string, data->delimiter); return 1; }
static int slapi_int_search_entry_callback( Slapi_Entry *entry, void *callback_data ) { int nentries = 0, i = 0; Slapi_Entry **head = NULL, **tp; Slapi_PBlock *pb = (Slapi_PBlock *)callback_data; PBLOCK_ASSERT_INTOP( pb, LDAP_REQ_SEARCH ); entry = slapi_entry_dup( entry ); if ( entry == NULL ) { return LDAP_NO_MEMORY; } slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries ); slapi_pblock_get( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &head ); i = nentries + 1; if ( nentries == 0 ) { tp = (Slapi_Entry **)slapi_ch_malloc( 2 * sizeof(Slapi_Entry *) ); if ( tp == NULL ) { slapi_entry_free( entry ); return LDAP_NO_MEMORY; } tp[0] = entry; } else { tp = (Slapi_Entry **)slapi_ch_realloc( (char *)head, sizeof(Slapi_Entry *) * ( i + 1 ) ); if ( tp == NULL ) { slapi_entry_free( entry ); return LDAP_NO_MEMORY; } tp[i - 1] = entry; } tp[i] = NULL; slapi_pblock_set( pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, (void *)tp ); slapi_pblock_set( pb, SLAPI_NENTRIES, (void *)&i ); return LDAP_SUCCESS; }
static int pblock_add_control( Slapi_PBlock *pb, LDAPControl *control ) { LDAPControl **controls = NULL; size_t i; pblock_get_default( pb, SLAPI_RESCONTROLS, (void **)&controls ); if ( controls != NULL ) { for ( i = 0; controls[i] != NULL; i++ ) ; } else { i = 0; } controls = (LDAPControl **)slapi_ch_realloc( (char *)controls, ( i + 2 ) * sizeof(LDAPControl *)); controls[i++] = slapi_dup_control( control ); controls[i] = NULL; return pblock_set_default( pb, SLAPI_RESCONTROLS, (void *)controls ); }
/* Caller must ensure that U == NULL and Ulen == 0 the first time called */ static UErrorCode SetUnicodeStringFromUTF_8 (UChar** U, int32_t* Ulen, int *isAlloced, const struct berval* bv) /* Copy the UTF-8 string bv into the UnicodeString U, but remove leading and trailing whitespace, and convert consecutive whitespaces into a single space. Ulen is set to the number of UChars in the array (not necessarily the number of bytes!) */ { size_t n; int32_t len = 0; /* length of non-space string */ UErrorCode err = U_ZERO_ERROR; const char* s = bv->bv_val; const char* begin = NULL; /* will point to beginning of non-space in val */ const char* end = NULL; /* will point to the first space after the last non-space char in val */ int32_t nUchars = 0; if (!bv->bv_len) { /* no value? */ return U_INVALID_FORMAT_ERROR; /* don't know what else to use here */ } /* first, set s to the first non-space char in bv->bv_val */ for (n = 0; (n < bv->bv_len) && ldap_utf8isspace((char *)s); ) { /* cast away const */ const char *next = LDAP_UTF8NEXT((char *)s); /* cast away const */ n += (next - s); /* count bytes, not chars */ s = next; } begin = s; /* begin points to first non-space char in val */ if (n >= bv->bv_len) { /* value is all spaces? */ return U_INVALID_FORMAT_ERROR; /* don't know what else to use here */ } s = bv->bv_val + (bv->bv_len-1); /* move s to last char of bv_val */ end = s; /* end points at last char of bv_val - may change below */ /* find the last non-null and non-space char of val */ for (n = bv->bv_len; (n > 0) && (!*s || ldap_utf8isspace((char *)s));) { const char *prev = LDAP_UTF8PREV((char *)s); end = prev; n -= (s - prev); /* count bytes, not chars */ s = prev; } /* end now points at last non-null/non-space of val */ if (n == 0) { /* bogus */ return U_INVALID_FORMAT_ERROR; /* don't know what else to use here */ } len = LDAP_UTF8NEXT((char *)end) - begin; u_strFromUTF8(*U, *Ulen, &nUchars, begin, len, &err); if (nUchars > *Ulen) { /* need more space */ if (*isAlloced) { /* realloc space */ *U = (UChar *)slapi_ch_realloc((char *)*U, sizeof(UChar) * nUchars); } else { /* must use malloc */ *U = (UChar *)slapi_ch_malloc(sizeof(UChar) * nUchars); *isAlloced = 1; /* no longer using fixed buffer */ } *Ulen = nUchars; err = U_ZERO_ERROR; /* reset */ u_strFromUTF8(*U, *Ulen, NULL, begin, len, &err); } else { *Ulen = nUchars; } return err; }
/* * Parse the value from an LDAPv3 "Simple Paged Results" control. They look * like this: * * realSearchControlValue ::= SEQUENCE { * size INTEGER (0..maxInt), * -- requested page size from client * -- result set size estimate from server * cookie OCTET STRING * -- index for the pagedresults array in the connection * } * * Return an LDAP error code (LDAP_SUCCESS if all goes well). */ int pagedresults_parse_control_value( Slapi_PBlock *pb, struct berval *psbvp, ber_int_t *pagesize, int *index, Slapi_Backend *be ) { int rc = LDAP_SUCCESS; struct berval cookie = {0}; Connection *conn = pb->pb_conn; Operation *op = pb->pb_op; BerElement *ber = NULL; PagedResults *prp = NULL; time_t ctime = current_time(); int i; int maxreqs = config_get_maxsimplepaged_per_conn(); slapi_log_err(SLAPI_LOG_TRACE, "pagedresults_parse_control_value", "=>\n"); if ( NULL == conn || NULL == op || NULL == pagesize || NULL == index ) { slapi_log_err(SLAPI_LOG_ERR, "pagedresults_parse_control_value", "<= Error %d\n", LDAP_OPERATIONS_ERROR); return LDAP_OPERATIONS_ERROR; } *index = -1; if ( psbvp->bv_len == 0 || psbvp->bv_val == NULL ) { slapi_log_err(SLAPI_LOG_ERR, "pagedresults_parse_control_value", "<= no control value\n"); return LDAP_PROTOCOL_ERROR; } ber = ber_init( psbvp ); if ( ber == NULL ) { slapi_log_err(SLAPI_LOG_ERR, "pagedresults_parse_control_value", "<= no control value\n"); return LDAP_PROTOCOL_ERROR; } if ( ber_scanf( ber, "{io}", pagesize, &cookie ) == LBER_ERROR ) { slapi_log_err(SLAPI_LOG_ERR, "pagedresults_parse_control_value", "<= corrupted control value\n"); return LDAP_PROTOCOL_ERROR; } if (!maxreqs) { slapi_log_err(SLAPI_LOG_ERR, "pagedresults_parse_control_value", "Simple paged results requests per conn exceeded the limit: %d\n", maxreqs); return LDAP_UNWILLING_TO_PERFORM; } PR_EnterMonitor(conn->c_mutex); /* the ber encoding is no longer needed */ ber_free(ber, 1); if ( cookie.bv_len <= 0 ) { /* first time? */ int maxlen = conn->c_pagedresults.prl_maxlen; if (conn->c_pagedresults.prl_count == maxlen) { if (0 == maxlen) { /* first time */ conn->c_pagedresults.prl_maxlen = 1; conn->c_pagedresults.prl_list = (PagedResults *)slapi_ch_calloc(1, sizeof(PagedResults)); } else { /* new max length */ conn->c_pagedresults.prl_maxlen *= 2; conn->c_pagedresults.prl_list = (PagedResults *)slapi_ch_realloc( (char *)conn->c_pagedresults.prl_list, sizeof(PagedResults) * conn->c_pagedresults.prl_maxlen); /* initialze newly allocated area */ memset(conn->c_pagedresults.prl_list + maxlen, '\0', sizeof(PagedResults) * maxlen); } *index = maxlen; /* the first position in the new area */ prp = conn->c_pagedresults.prl_list + *index; prp->pr_current_be = be; } else { prp = conn->c_pagedresults.prl_list; for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++, prp++) { if (!prp->pr_current_be) { /* unused slot; take it */ _pr_cleanup_one_slot(prp); prp->pr_current_be = be; *index = i; break; } else if (((prp->pr_timelimit > 0) && (ctime > prp->pr_timelimit)) || /* timelimit exceeded */ (prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) /* abandoned */) { _pr_cleanup_one_slot(prp); conn->c_pagedresults.prl_count--; prp->pr_current_be = be; *index = i; break; } } } if ((maxreqs > 0) && (*index >= maxreqs)) { rc = LDAP_UNWILLING_TO_PERFORM; slapi_log_err(SLAPI_LOG_TRACE, "pagedresults_parse_control_value", "Simple paged results requests per conn exeeded the limit: %d\n", maxreqs); goto bail; } if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen) && !conn->c_pagedresults.prl_list[*index].pr_mutex) { conn->c_pagedresults.prl_list[*index].pr_mutex = PR_NewLock(); } conn->c_pagedresults.prl_count++; } else { /* Repeated paged results request. * PagedResults is already allocated. */ char *ptr = slapi_ch_malloc(cookie.bv_len + 1); memcpy(ptr, cookie.bv_val, cookie.bv_len); *(ptr+cookie.bv_len) = '\0'; *index = strtol(ptr, NULL, 10); slapi_ch_free_string(&ptr); if ((conn->c_pagedresults.prl_maxlen <= *index) || (*index < 0)){ rc = LDAP_PROTOCOL_ERROR; slapi_log_err(SLAPI_LOG_ERR, "pagedresults_parse_control_value", "Invalid cookie: %d\n", *index); *index = -1; /* index is invalid. reinitializing it. */ goto bail; } prp = conn->c_pagedresults.prl_list + *index; if (!(prp->pr_search_result_set)) { /* freed and reused for the next backend. */ conn->c_pagedresults.prl_count++; } } /* reset sizelimit */ op->o_pagedresults_sizelimit = -1; if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) { if (conn->c_pagedresults.prl_list[*index].pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) { /* repeated case? */ prp = conn->c_pagedresults.prl_list + *index; _pr_cleanup_one_slot(prp); rc = LDAP_CANCELLED; } else { /* Need to keep the latest msgid to prepare for the abandon. */ conn->c_pagedresults.prl_list[*index].pr_msgid = op->o_msgid; } } else { rc = LDAP_PROTOCOL_ERROR; slapi_log_err(SLAPI_LOG_ERR, "pagedresults_parse_control_value", "Invalid cookie: %d\n", *index); } bail: slapi_ch_free((void **)&cookie.bv_val); /* cleaning up the rest of the timedout or abandoned if any */ prp = conn->c_pagedresults.prl_list; for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++, prp++) { if (prp->pr_current_be && (((prp->pr_timelimit > 0) && (ctime > prp->pr_timelimit)) || /* timelimit exceeded */ (prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED)) /* abandoned */) { _pr_cleanup_one_slot(prp); conn->c_pagedresults.prl_count--; if (i == *index) { /* registered slot is expired and cleaned up. return cancelled. */ *index = -1; rc = LDAP_CANCELLED; } } } PR_ExitMonitor(conn->c_mutex); slapi_log_err(SLAPI_LOG_TRACE, "pagedresults_parse_control_value", "<= idx %d\n", *index); return rc; }
int collation_config (size_t cargc, char** cargv, const char* fname, size_t lineno) /* Process one line from a configuration file. Return 0 if it's OK, -1 if it's not recognized. Any other return value is a process exit code. */ { if (cargc <= 0) { /* Bizarre. Oh, well... */ } else if (!strcasecmp (cargv[0], "NLS")) { /* ignore - not needed anymore with ICU - was used to get path for NLS_Initialize */ } else if (!strcasecmp (cargv[0], "collation")) { if ( cargc < 7 ) { slapi_log_err(SLAPI_LOG_ERR, COLLATE_PLUGIN_SUBSYSTEM, "collation_config - %s: line %lu ignored: only %lu arguments (expected " "collation language country variant strength decomposition oid ...)\n", fname, (unsigned long)lineno, (unsigned long)cargc ); } else { auto size_t arg; auto coll_profile_t* profile = (coll_profile_t*) slapi_ch_calloc (1, sizeof (coll_profile_t)); if (*cargv[1]) profile->language = slapi_ch_strdup (cargv[1]); if (*cargv[2]) profile->country = slapi_ch_strdup (cargv[2]); if (*cargv[3]) profile->variant = slapi_ch_strdup (cargv[3]); switch (atoi(cargv[4])) { case 1: profile->strength = UCOL_PRIMARY; break; case 2: profile->strength = UCOL_SECONDARY; /* no break here? fall through? wtf? */ case 3: profile->strength = UCOL_TERTIARY; break; case 4: profile->strength = UCOL_IDENTICAL; break; default: profile->strength = UCOL_SECONDARY; slapi_log_err(SLAPI_LOG_ERR, COLLATE_PLUGIN_SUBSYSTEM, "collation_config - %s: line %lu: strength \"%s\" not supported (will use 2)\n", fname, (unsigned long)lineno, cargv[4]); break; } switch (atoi(cargv[5])) { case 1: profile->decomposition = UCOL_OFF; break; case 2: profile->decomposition = UCOL_DEFAULT; /* no break here? fall through? wtf? */ case 3: profile->decomposition = UCOL_ON; break; default: profile->decomposition = UCOL_DEFAULT; slapi_log_err(SLAPI_LOG_ERR, COLLATE_PLUGIN_SUBSYSTEM, "collation_config - %s: line %lu: decomposition \"%s\" not supported (will use 2)\n", fname, (unsigned long)lineno, cargv[5]); break; } { char descStr[256]; char nameOrder[256]; char nameSubstring[256]; char oidString[256]; char *tmpStr=NULL; Slapi_MatchingRuleEntry *mrentry=slapi_matchingrule_new(); if(UCOL_PRIMARY == profile->strength) { strcpy(nameOrder,"caseIgnoreOrderingMatch"); strcpy(nameSubstring,"caseIgnoreSubstringMatch"); } else { strcpy(nameOrder,"caseExactOrderingMatch"); strcpy(nameSubstring,"caseExactSubstringMatch"); } /* PAR: this looks broken the "extra" text based oids that are actually used to form the name and description are always derived from the language and country fields so there should be no need to have two separate code paths to set the name and description fields of the schema as language is always available, and if country is not, it is not in the name anyway. Is it safe to assume all matching rules will follow this convention? The answer, or lack of it, probably explains the reasoning for doing things the way they are currently. */ if(cargc > 7) { PL_strcatn(nameOrder,sizeof(nameOrder),"-"); PL_strcatn(nameOrder,sizeof(nameOrder),cargv[7]); PL_strcatn(nameSubstring,sizeof(nameSubstring),"-"); PL_strcatn(nameSubstring,sizeof(nameSubstring),cargv[7]); slapi_matchingrule_set(mrentry,SLAPI_MATCHINGRULE_NAME, (void *)slapi_ch_strdup(nameOrder)); } else { if(0 != cargv[1][0]) { PL_strcatn(nameOrder,sizeof(nameOrder),"-"); PL_strcatn(nameSubstring,sizeof(nameSubstring),"-"); } else { nameOrder[0] = 0; nameSubstring[0] = 0; } PL_strcatn(nameOrder,sizeof(nameOrder),cargv[1]); PL_strcatn(nameSubstring,sizeof(nameSubstring),cargv[1]); slapi_matchingrule_set(mrentry,SLAPI_MATCHINGRULE_NAME, (void *)slapi_ch_strdup(nameOrder)); } PL_strncpyz(oidString,cargv[6], sizeof(oidString)); slapi_matchingrule_set(mrentry,SLAPI_MATCHINGRULE_OID, (void *)slapi_ch_strdup(oidString)); if(0 != cargv[2][0]) { PR_snprintf(descStr, sizeof(descStr), "%s-%s",cargv[1],cargv[2]); } else { PL_strncpyz(descStr,cargv[1], sizeof(descStr)); } slapi_matchingrule_set(mrentry,SLAPI_MATCHINGRULE_DESC, (void *)slapi_ch_strdup(descStr)); slapi_matchingrule_set(mrentry,SLAPI_MATCHINGRULE_SYNTAX, (void *)slapi_ch_strdup(DIRSTRING_SYNTAX_OID)); slapi_matchingrule_register(mrentry); slapi_matchingrule_get(mrentry,SLAPI_MATCHINGRULE_NAME, (void *)&tmpStr); slapi_ch_free((void **)&tmpStr); slapi_matchingrule_get(mrentry,SLAPI_MATCHINGRULE_OID, (void *)&tmpStr); slapi_ch_free((void **)&tmpStr); slapi_matchingrule_set(mrentry,SLAPI_MATCHINGRULE_NAME, (void *)slapi_ch_strdup(nameSubstring)); PL_strcatn(oidString,sizeof(oidString),".6"); slapi_matchingrule_set(mrentry,SLAPI_MATCHINGRULE_OID, (void *)slapi_ch_strdup(oidString)); slapi_matchingrule_register(mrentry); slapi_matchingrule_free(&mrentry,1); } for (arg = 6; arg < cargc; ++arg) { auto coll_id_t* id = (coll_id_t*) slapi_ch_malloc (sizeof (coll_id_t)); id->oid = slapi_ch_strdup (cargv[arg]); id->profile = profile; if (collation_ids <= 0) { collation_id = (const coll_id_t**) slapi_ch_malloc (2 * sizeof (coll_id_t*)); } else { collation_id = (const coll_id_t**) slapi_ch_realloc ((void*)collation_id, (collation_ids + 2) * sizeof (coll_id_t*)); } collation_id [collation_ids++] = id; collation_id [collation_ids] = NULL; } } } else { return -1; /* unrecognized */ } return 0; /* success */ }
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 valuearray_add_valuearray_fast(Slapi_Value ***vals, Slapi_Value **addvals, int nvals, int naddvals, int *maxvals, int exact, /* Don't create an array bigger than needed */ int passin) /* The values are being passed in */ { int i, j; int allocate= 0; int need = nvals + naddvals + 1; if(exact) { /* Create an array exactly the right size. */ if(need>*maxvals) { allocate= need; } } else { if (*maxvals==0) /* empty; create with 4 by default */ { allocate= 4; } else if (need > *maxvals) { /* Exponentially expand the array */ allocate= *maxvals; while ( allocate < need ) { allocate *= 2; } } } if(allocate>0) { if(*vals==NULL) { *vals = (Slapi_Value **) slapi_ch_malloc( allocate * sizeof(Slapi_Value *)); } else { *vals = (Slapi_Value **) slapi_ch_realloc( (char *) *vals, allocate * sizeof(Slapi_Value *)); } *maxvals= allocate; } for ( i = 0, j = 0; i < naddvals; i++) { if ( addvals[i]!=NULL ) { if(passin) { /* We consume the values */ (*vals)[nvals + j] = addvals[i]; } else { /* We copy the values */ (*vals)[nvals + j] = slapi_value_dup(addvals[i]); } j++; } } (*vals)[nvals + j] = NULL; }
/* caller is responsible to release "valuearray" */ int get_values_from_string(const char *string, char *type, char ***valuearray) { int rc = -1; size_t typelen = 0; char *ptr = NULL; char *copy = NULL; char *tmpptr = NULL; char *startptr = NULL; struct berval tmptype = {0, NULL}; struct berval bvvalue = {0, NULL}; int freeval = 0; char *value = NULL; int idx = 0; #define get_values_INITIALMAXCNT 1 int maxcnt = get_values_INITIALMAXCNT; if (NULL == string || NULL == type || NULL == valuearray) { return rc; } *valuearray = NULL; tmpptr = (char *)string; ptr = PL_strcasestr(tmpptr, type); if (NULL == ptr) { return rc; } typelen = strlen(type); startptr = tmpptr; while (NULL != (ptr = ldif_getline(&tmpptr))) { if ((0 != PL_strncasecmp(ptr, type, typelen)) || (*(ptr + typelen) != ';' && *(ptr + typelen) != ':')) { /* did not match */ ldif_getline_fixline(startptr, tmpptr); startptr = tmpptr; continue; } /* matched */ copy = slapi_ch_strdup(ptr); ldif_getline_fixline(startptr, tmpptr); startptr = tmpptr; rc = slapi_ldif_parse_line(copy, &tmptype, &bvvalue, &freeval); if (0 > rc || NULL == bvvalue.bv_val || 0 >= bvvalue.bv_len) { continue; } if (0 != PL_strncasecmp(type, tmptype.bv_val, tmptype.bv_len)) { char *p = PL_strchr(tmptype.bv_val, ';'); /* subtype ? */ if (p) { if (0 != strncasecmp(type, tmptype.bv_val, p - tmptype.bv_val)) { slapi_log_error(SLAPI_LOG_FATAL, "get_values_from_string", "type does not match: %s != %s\n", type, tmptype.bv_val); if (freeval) { slapi_ch_free_string(&bvvalue.bv_val); } goto bail; } } else { slapi_log_error(SLAPI_LOG_FATAL, "get_values_from_string", "type does not match: %s != %s\n", type, tmptype.bv_val); if (freeval) { slapi_ch_free_string(&bvvalue.bv_val); } goto bail; } } if (freeval) { value = bvvalue.bv_val; /* just hand off memory */ bvvalue.bv_val = NULL; } else { /* copy */ value = (char *)slapi_ch_malloc(bvvalue.bv_len + 1); memcpy(value, bvvalue.bv_val, bvvalue.bv_len); *(value + bvvalue.bv_len) = '\0'; } if ((get_values_INITIALMAXCNT == maxcnt) || !valuearray || (idx + 1 >= maxcnt)) { maxcnt *= 2; *valuearray = (char **)slapi_ch_realloc((char *)*valuearray, sizeof(char *) * maxcnt); } (*valuearray)[idx++] = value; (*valuearray)[idx] = NULL; slapi_ch_free_string(©); } bail: slapi_ch_free_string(©); return rc; }
/* * memberof_apply_config() * * Apply the pending changes in the e entry to our config struct. * memberof_validate_config() must have already been called. */ int memberof_apply_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { Slapi_Entry *config_entry = NULL; Slapi_DN *config_sdn = NULL; char **groupattrs = NULL; char *memberof_attr = NULL; char *filter_str = NULL; int num_groupattrs = 0; int groupattr_name_len = 0; char *allBackends = NULL; char **entryScopes = NULL; char **entryScopeExcludeSubtrees = NULL; char *sharedcfg = NULL; char *skip_nested = NULL; char *auto_add_oc = NULL; int num_vals = 0; *returncode = LDAP_SUCCESS; /* * Check if this is a shared config entry */ sharedcfg = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA); if(sharedcfg){ if((config_sdn = slapi_sdn_new_dn_byval(sharedcfg))){ slapi_search_internal_get_entry(config_sdn, NULL, &config_entry, memberof_get_plugin_id()); if(config_entry){ /* Set the entry to be the shared config entry. Validation was done in preop */ e = config_entry; } else { /* This should of been checked in preop validation */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "memberof_apply_config - Failed to locate shared config entry (%s)", sharedcfg); slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM,"%s\n",returntext); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } } } /* * Apply the config settings */ groupattrs = slapi_entry_attr_get_charray(e, MEMBEROF_GROUP_ATTR); memberof_attr = slapi_entry_attr_get_charptr(e, MEMBEROF_ATTR); allBackends = slapi_entry_attr_get_charptr(e, MEMBEROF_BACKEND_ATTR); skip_nested = slapi_entry_attr_get_charptr(e, MEMBEROF_SKIP_NESTED_ATTR); auto_add_oc = slapi_entry_attr_get_charptr(e, MEMBEROF_AUTO_ADD_OC); /* * We want to be sure we don't change the config in the middle of * a memberOf operation, so we obtain an exclusive lock here */ memberof_wlock_config(); if (groupattrs) { int i = 0; slapi_ch_array_free(theConfig.groupattrs); theConfig.groupattrs = groupattrs; groupattrs = NULL; /* config now owns memory */ /* * We allocate a list of Slapi_Attr using the groupattrs for * convenience in our memberOf comparison functions */ for (i = 0; theConfig.group_slapiattrs && theConfig.group_slapiattrs[i]; i++) { slapi_attr_free(&theConfig.group_slapiattrs[i]); } /* Count the number of groupattrs. */ for (num_groupattrs = 0; theConfig.groupattrs && theConfig.groupattrs[num_groupattrs]; num_groupattrs++) { /* * Add up the total length of all attribute names. We need * to know this for building the group check filter later. */ groupattr_name_len += strlen(theConfig.groupattrs[num_groupattrs]); } /* Realloc the list of Slapi_Attr if necessary. */ if (i < num_groupattrs) { theConfig.group_slapiattrs = (Slapi_Attr **)slapi_ch_realloc((char *)theConfig.group_slapiattrs, sizeof(Slapi_Attr *) * (num_groupattrs + 1)); } /* Build the new list */ for (i = 0; theConfig.groupattrs[i]; i++) { theConfig.group_slapiattrs[i] = slapi_attr_new(); slapi_attr_init(theConfig.group_slapiattrs[i], theConfig.groupattrs[i]); } /* Terminate the list. */ theConfig.group_slapiattrs[i] = NULL; /* The filter is based off of the groupattr, so we update it here too. */ slapi_filter_free(theConfig.group_filter, 1); if (num_groupattrs > 1) { int bytes_out = 0; int filter_str_len = groupattr_name_len + (num_groupattrs * 4) + 4; /* Allocate enough space for the filter */ filter_str = slapi_ch_malloc(filter_str_len); /* Add beginning of filter. */ bytes_out = snprintf(filter_str, filter_str_len - bytes_out, "(|"); /* Add filter section for each groupattr. */ for (i = 0; theConfig.groupattrs[i]; i++) { bytes_out += snprintf(filter_str + bytes_out, filter_str_len - bytes_out, "(%s=*)", theConfig.groupattrs[i]); } /* Add end of filter. */ snprintf(filter_str + bytes_out, filter_str_len - bytes_out, ")"); } else { filter_str = slapi_ch_smprintf("(%s=*)", theConfig.groupattrs[0]); } /* * Log an error if we were unable to build the group filter for some * reason. If this happens, the memberOf plugin will not be able to * check if an entry is a group, causing it to not catch changes. This * shouldn't happen, but there may be some garbage configuration that * could trigger this. */ if ((theConfig.group_filter = slapi_str2filter(filter_str)) == NULL) { slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_apply_config - Unable to create the group check filter. The memberOf " "plug-in will not operate on changes to groups. Please check " "your %s configuration settings. (filter: %s)\n", MEMBEROF_GROUP_ATTR, filter_str ); } slapi_ch_free_string(&filter_str); } if (memberof_attr) { slapi_ch_free_string(&theConfig.memberof_attr); theConfig.memberof_attr = memberof_attr; memberof_attr = NULL; /* config now owns memory */ } if (skip_nested){ if(strcasecmp(skip_nested,"on") == 0){ theConfig.skip_nested = 1; } else { theConfig.skip_nested = 0; } } if (allBackends) { if(strcasecmp(allBackends,"on")==0){ theConfig.allBackends = 1; } else { theConfig.allBackends = 0; } } else { theConfig.allBackends = 0; } theConfig.auto_add_oc = auto_add_oc; /* * Check and process the entry scopes */ memberof_free_scope(theConfig.entryScopes, &theConfig.entryScopeCount); entryScopes = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_ATTR, &num_vals); if(entryScopes){ int i = 0; /* Validation has already been performed in preop, just build the DN's */ theConfig.entryScopes = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *), num_vals+1); for (i = 0;i < num_vals; i++){ theConfig.entryScopes[i] = slapi_sdn_new_dn_passin(entryScopes[i]); } theConfig.entryScopeCount = num_vals; /* shortcut for config copy */ } /* * Check and process the entry exclude scopes */ memberof_free_scope(theConfig.entryScopeExcludeSubtrees, &theConfig.entryExcludeScopeCount); entryScopeExcludeSubtrees = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE, &num_vals); if(entryScopeExcludeSubtrees){ int i = 0; /* Validation has already been performed in preop, just build the DN's */ theConfig.entryScopeExcludeSubtrees = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),num_vals+1); for (i = 0;i < num_vals; i++){ theConfig.entryScopeExcludeSubtrees[i] = slapi_sdn_new_dn_passin(entryScopeExcludeSubtrees[i]); } theConfig.entryExcludeScopeCount = num_vals; /* shortcut for config copy */ } /* release the lock */ memberof_unlock_config(); done: slapi_sdn_free(&config_sdn); slapi_entry_free(config_entry); slapi_ch_array_free(groupattrs); slapi_ch_free_string(&sharedcfg); slapi_ch_free_string(&memberof_attr); slapi_ch_free_string(&allBackends); slapi_ch_free_string(&skip_nested); slapi_ch_free((void **)&entryScopes); slapi_ch_free((void **)&entryScopeExcludeSubtrees); if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } }
static int ss_index_search (Slapi_PBlock* pb) /* Compute substring search keys (when searching for entries). */ { auto int rc = LDAP_OPERATIONS_ERROR; auto or_filter_t* or = or_filter_get (pb); if (or) { if (or->or_index_keys == NULL /* not yet computed */ && or->or_values && or->or_indexer && or->or_indexer->ix_index) { auto size_t substringsLen = 0; auto struct berval* substrings = NULL; auto struct berval** prefixes = NULL; auto struct berval** value; for (value = or->or_values; *value != NULL; ++value) { auto size_t offset; auto struct berval substring; substring.bv_val = (*value)->bv_val; for (offset = 0; 1; ++offset, LDAP_UTF8INC (substring.bv_val)) { auto struct berval* prefix = NULL; substring.bv_len = (*value)->bv_len - (substring.bv_val - (*value)->bv_val); if (offset == 0 && value == or->or_values) { if (long_enough (&substring, SS_INDEX_LENGTH - 1)) { prefix = &ss_index_initial; } } else if (value[1] != NULL) { if (long_enough (&substring, SS_INDEX_LENGTH)) { prefix = &ss_index_middle; } } else if (long_enough (&substring, SS_INDEX_LENGTH)) { prefix = &ss_index_middle; } else if (long_enough (&substring, SS_INDEX_LENGTH-1)) { prefix = &ss_index_final; } if (prefix == NULL) break; ++substringsLen; substrings = (struct berval*) slapi_ch_realloc ((void*)substrings, substringsLen * sizeof(struct berval)); memcpy (&(substrings[substringsLen-1]), &substring, sizeof (struct berval)); prefixes = (struct berval**) slapi_ch_realloc ((void*)prefixes, substringsLen * sizeof(struct berval*)); prefixes[substringsLen-1] = prefix; } } if (substrings != NULL) { auto indexer_t* ix = or->or_indexer; auto struct berval** vector = (struct berval**) slapi_ch_malloc ((substringsLen+1) * sizeof(struct berval*)); auto size_t i; for (i = 0; i < substringsLen; ++i) vector[i] = &(substrings[i]); vector[substringsLen] = NULL; or->or_index_keys = slapi_ch_bvecdup ( ix->ix_index (ix, vector, prefixes)); slapi_ch_free((void**)&vector); slapi_ch_free((void**)&substrings); slapi_ch_free((void**)&prefixes); } } if (or->or_index_keys) { rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_KEYS, or->or_index_keys); } } slapi_log_err(SLAPI_LOG_FILTER, COLLATE_PLUGIN_SUBSYSTEM, "ss_index_search - (%p) %i\n", (void*)or, rc); return rc; }
/* * memberof_copy_config() * * Makes a copy of the config in src. This function will free the * elements of dest if they already exist. This should only be called * if you hold the memberof config lock if src was obtained with * memberof_get_config(). */ void memberof_copy_config(MemberOfConfig *dest, MemberOfConfig *src) { if (dest && src) { /* Check if the copy is already up to date */ if (src->groupattrs) { int i = 0, j = 0; /* Copy group attributes string list. */ slapi_ch_array_free(dest->groupattrs); dest->groupattrs = slapi_ch_array_dup(src->groupattrs); /* Copy group check filter. */ slapi_filter_free(dest->group_filter, 1); dest->group_filter = slapi_filter_dup(src->group_filter); /* Copy group attributes Slapi_Attr list. * First free the old list. */ for (i = 0; dest->group_slapiattrs && dest->group_slapiattrs[i]; i++) { slapi_attr_free(&dest->group_slapiattrs[i]); } /* Count how many values we have in the source list. */ for (j = 0; src->group_slapiattrs[j]; j++) { /* Do nothing. */ } /* Realloc dest if necessary. */ if (i < j) { dest->group_slapiattrs = (Slapi_Attr **)slapi_ch_realloc((char *)dest->group_slapiattrs, sizeof(Slapi_Attr *) * (j + 1)); } /* Copy the attributes. */ for (i = 0; src->group_slapiattrs[i]; i++) { dest->group_slapiattrs[i] = slapi_attr_dup(src->group_slapiattrs[i]); } /* Terminate the array. */ dest->group_slapiattrs[i] = NULL; } if (src->memberof_attr) { slapi_ch_free_string(&dest->memberof_attr); dest->memberof_attr = slapi_ch_strdup(src->memberof_attr); } if(src->skip_nested){ dest->skip_nested = src->skip_nested; } if(src->allBackends) { dest->allBackends = src->allBackends; } slapi_ch_free_string(&dest->auto_add_oc); dest->auto_add_oc = slapi_ch_strdup(src->auto_add_oc); if(src->entryScopes){ int num_vals = 0; dest->entryScopes = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),src->entryScopeCount+1); for(num_vals = 0; src->entryScopes[num_vals]; num_vals++){ dest->entryScopes[num_vals] = slapi_sdn_dup(src->entryScopes[num_vals]); } } if(src->entryScopeExcludeSubtrees){ int num_vals = 0; dest->entryScopeExcludeSubtrees = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),src->entryExcludeScopeCount+1); for(num_vals = 0; src->entryScopeExcludeSubtrees[num_vals]; num_vals++){ dest->entryScopeExcludeSubtrees[num_vals] = slapi_sdn_dup(src->entryScopeExcludeSubtrees[num_vals]); } } } }
/* * usn_rootdse_search -- callback for the search on root DSN * add lastusn value per backend * * example: * ldapsearch -b "" -s base "(objectclass=*)" lastusn * dn: * lastusn;userroot: 72 * lastusn;testbackend: 15 */ static int usn_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg) { char *cookie = NULL; Slapi_Backend *be; struct berval *vals[2]; struct berval usn_berval; vals[0] = &usn_berval; vals[1] = NULL; char counter_buf[USN_COUNTER_BUF_LEN]; int attr_len = 64; /* length of lastusn;<backend_name> */ char *attr = (char *)slapi_ch_malloc(attr_len); char *attr_subp = NULL; int isglobal = config_get_entryusn_global(); slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "--> usn_rootdse_search\n"); usn_berval.bv_val = counter_buf; if (isglobal) { /* nsslapd-entryusn-global: on*/ /* root dse shows ... * lastusn: <num> */ PR_snprintf(attr, USN_LAST_USN_ATTR_CORE_LEN + 1, "%s", USN_LAST_USN); for (be = slapi_get_first_backend(&cookie); be; be = slapi_get_next_backend(cookie)) { if (be->be_usn_counter) { break; } } if (be && be->be_usn_counter) { /* get a next USN counter from be_usn_counter; * then minus 1 from it */ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRI64 "d", slapi_counter_get_value(be->be_usn_counter)-1); usn_berval.bv_len = strlen(usn_berval.bv_val); slapi_entry_attr_replace(e, attr, vals); } } else { /* nsslapd-entryusn-global: off (default) */ /* root dse shows ... * lastusn;<backend>: <num> */ PR_snprintf(attr, USN_LAST_USN_ATTR_CORE_LEN + 2, "%s;", USN_LAST_USN); attr_subp = attr + USN_LAST_USN_ATTR_CORE_LEN + 1; for (be = slapi_get_first_backend(&cookie); be; be = slapi_get_next_backend(cookie)) { if (NULL == be->be_usn_counter) { /* no counter == not a db backend */ continue; } /* get a next USN counter from be_usn_counter; * then minus 1 from it */ PR_snprintf(usn_berval.bv_val, USN_COUNTER_BUF_LEN, "%" NSPRI64 "d", slapi_counter_get_value(be->be_usn_counter)-1); usn_berval.bv_len = strlen(usn_berval.bv_val); if (USN_LAST_USN_ATTR_CORE_LEN+strlen(be->be_name)+2 > attr_len) { attr_len *= 2; attr = (char *)slapi_ch_realloc(attr, attr_len); attr_subp = attr + USN_LAST_USN_ATTR_CORE_LEN; } PR_snprintf(attr_subp, attr_len - USN_LAST_USN_ATTR_CORE_LEN, "%s", be->be_name); slapi_entry_attr_replace(e, attr, vals); } } slapi_ch_free_string(&cookie); slapi_ch_free_string(&attr); slapi_log_error(SLAPI_LOG_TRACE, USN_PLUGIN_SUBSYSTEM, "<-- usn_rootdse_search\n"); return SLAPI_DSE_CALLBACK_OK; }
/* * Parse the value from an LDAPv3 "Simple Paged Results" control. They look * like this: * * realSearchControlValue ::= SEQUENCE { * size INTEGER (0..maxInt), * -- requested page size from client * -- result set size estimate from server * cookie OCTET STRING * -- index for the pagedresults array in the connection * } * * Return an LDAP error code (LDAP_SUCCESS if all goes well). */ int pagedresults_parse_control_value( Slapi_PBlock *pb, struct berval *psbvp, ber_int_t *pagesize, int *index ) { int rc = LDAP_SUCCESS; struct berval cookie = {0}; Connection *conn = pb->pb_conn; Operation *op = pb->pb_op; LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_parse_control_value\n"); if ( NULL == conn || NULL == op || NULL == pagesize || NULL == index ) { LDAPDebug1Arg(LDAP_DEBUG_ANY, "<-- pagedresults_parse_control_value: %d\n", LDAP_OPERATIONS_ERROR); return LDAP_OPERATIONS_ERROR; } *index = -1; if ( psbvp->bv_len == 0 || psbvp->bv_val == NULL ) { rc = LDAP_PROTOCOL_ERROR; } else { BerElement *ber = ber_init( psbvp ); if ( ber == NULL ) { rc = LDAP_OPERATIONS_ERROR; } else { if ( ber_scanf( ber, "{io}", pagesize, &cookie ) == LBER_ERROR ) { rc = LDAP_PROTOCOL_ERROR; } /* the ber encoding is no longer needed */ ber_free(ber, 1); if ( cookie.bv_len <= 0 ) { int i; int maxlen; /* first time? */ PR_Lock(conn->c_mutex); maxlen = conn->c_pagedresults.prl_maxlen; if (conn->c_pagedresults.prl_count == maxlen) { if (0 == maxlen) { /* first time */ conn->c_pagedresults.prl_maxlen = 1; conn->c_pagedresults.prl_list = (PagedResults *)slapi_ch_calloc(1, sizeof(PagedResults)); } else { /* new max length */ conn->c_pagedresults.prl_maxlen *= 2; conn->c_pagedresults.prl_list = (PagedResults *)slapi_ch_realloc( (char *)conn->c_pagedresults.prl_list, sizeof(PagedResults) * conn->c_pagedresults.prl_maxlen); /* initialze newly allocated area */ memset(conn->c_pagedresults.prl_list + maxlen, '\0', sizeof(PagedResults) * maxlen); } *index = maxlen; /* the first position in the new area */ } else { for (i = 0; i < conn->c_pagedresults.prl_maxlen; i++) { if (!conn->c_pagedresults.prl_list[i].pr_current_be) { *index = i; break; } } } conn->c_pagedresults.prl_count++; PR_Unlock(conn->c_mutex); } else { /* Repeated paged results request. * PagedResults is already allocated. */ char *ptr = slapi_ch_malloc(cookie.bv_len + 1); memcpy(ptr, cookie.bv_val, cookie.bv_len); *(ptr+cookie.bv_len) = '\0'; *index = strtol(ptr, NULL, 10); slapi_ch_free_string(&ptr); } slapi_ch_free((void **)&cookie.bv_val); } } if ((*index > -1) && (*index < conn->c_pagedresults.prl_maxlen)) { /* Need to keep the latest msgid to prepare for the abandon. */ conn->c_pagedresults.prl_list[*index].pr_msgid = op->o_msgid; } else { rc = LDAP_PROTOCOL_ERROR; LDAPDebug1Arg(LDAP_DEBUG_ANY, "pagedresults_parse_control_value: invalid cookie: %d\n", *index); } LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_parse_control_value: idx %d\n", *index); return rc; }