329
slapi_schema_get_repl_entries(char **repl_schema_top, char ** repl_schema_supplier, char **repl_schema_consumer, char **default_supplier_policy, char **default_consumer_policy)
331
*repl_schema_top = ENTRY_REPL_SCHEMA_TOP;
332
*repl_schema_supplier = ENTRY_REPL_SCHEMA_SUPPLIER;
333
*repl_schema_consumer = ENTRY_REPL_SCHEMA_CONSUMER;
334
*default_supplier_policy = DEFAULT_SUPPLIER_POLICY;
335
*default_consumer_policy = DEFAULT_CONSUMER_POLICY;
338
/* It gets the attributes (see attrName)values in the entry, and add
339
* the policies in the provided list
341
* Entry: Slapi_entry with DN being ENTRY_REPL_SCHEMA_SUPPLIER or ENTRY_REPL_SCHEMA_CONSUMER
342
* attrName: name defining the policy object (objectclass/attribute) and the action
343
* ATTR_SCHEMA_UPDATE_OBJECTCLASS_ACCEPT
344
* ATTR_SCHEMA_UPDATE_OBJECTCLASS_REJECT
345
* ATTR_SCHEMA_UPDATE_ATTRIBUTE_ACCEPT
346
* ATTR_SCHEMA_UPDATE_ATTRIBUTE_REJECT
347
* *list: is the list of schema_item_t containing the policies (it can be list of objectclasses or attributes)
351
void schema_policy_add_action(Slapi_Entry *entry, char *attrName, schema_item_t **list)
353
Slapi_Attr *attr = NULL;
354
schema_item_t *schema_item;
358
/* Retrieve the expected action from the attribute name */
359
if ((strcasecmp(attrName, ATTR_SCHEMA_UPDATE_OBJECTCLASS_ACCEPT) == 0) ||
360
(strcasecmp(attrName, ATTR_SCHEMA_UPDATE_ATTRIBUTE_ACCEPT) == 0)) {
361
action = REPL_SCHEMA_UPDATE_ACCEPT_VALUE;
363
action = REPL_SCHEMA_UPDATE_REJECT_VALUE;
366
/* Retrieve the given attribute from the entry */
367
slapi_entry_attr_find(entry, attrName, &attr);
369
Slapi_Value *sval = NULL;
370
const struct berval *attrVal = NULL;
371
int k = slapi_attr_first_value(attr, &sval);
373
/* For each value adds the policy in the list */
375
attrVal = slapi_value_get_berval(sval);
377
schema_item = (schema_item_t *) slapi_ch_calloc(1, sizeof(schema_item_t));
379
/* Get the schema name_or_oid */
380
value = (char *) slapi_ch_malloc(attrVal->bv_len + 1);
381
memcpy(value, attrVal->bv_val, attrVal->bv_len);
382
value[attrVal->bv_len] = '\0';
383
schema_item->name_or_oid = value;
385
/* Set the action on that item */
386
schema_item->action = action;
388
/* Add it on the head of the list */
389
schema_item->next = *list;
392
/* Get the next name_or_oid */
393
k = slapi_attr_next_value(attr, k, &sval);
398
/* Caller must hold schema_policy_lock in write */
400
schema_load_repl_policy(const char *dn, repl_schema_policy_t *replica)
403
Slapi_Entry *entry = NULL;
404
schema_item_t *schema_item, *next;
406
if (replica == NULL) {
410
/* Start to free the previous policy */
411
/* first the objectclasses policies */
412
for (schema_item = replica->objectclasses; schema_item; ) {
413
slapi_ch_free((void **) &schema_item->name_or_oid);
414
next = schema_item->next;
415
slapi_ch_free((void **) &schema_item);
418
replica->objectclasses = NULL;
419
/* second the attributes policies */
420
for (schema_item = replica->attributes; schema_item; ) {
421
slapi_ch_free((void **) &schema_item->name_or_oid);
422
next = schema_item->next;
423
slapi_ch_free((void **) &schema_item);
426
replica->attributes = NULL;
428
/* Load the replication policy of the schema */
429
slapi_sdn_init_dn_byref( &sdn, dn );
430
if (slapi_search_internal_get_entry(&sdn, NULL, &entry, plugin_get_default_component_id()) == LDAP_SUCCESS) {
432
/* fill the policies (accept/reject) regarding objectclass */
433
schema_policy_add_action(entry, ATTR_SCHEMA_UPDATE_OBJECTCLASS_ACCEPT, &replica->objectclasses);
434
schema_policy_add_action(entry, ATTR_SCHEMA_UPDATE_OBJECTCLASS_REJECT, &replica->objectclasses);
436
/* fill the policies (accept/reject) regarding attribute */
437
schema_policy_add_action(entry, ATTR_SCHEMA_UPDATE_ATTRIBUTE_ACCEPT, &replica->attributes);
438
schema_policy_add_action(entry, ATTR_SCHEMA_UPDATE_ATTRIBUTE_REJECT, &replica->attributes);
440
slapi_entry_free( entry );
442
slapi_sdn_done(&sdn);
445
/* It load the policies (if they are defined) regarding the replication of the schema
446
* depending if the instance behaves as a consumer or a supplier
447
* It returns 0 if success
450
slapi_schema_load_repl_policies()
452
if (schema_policy_lock == NULL) {
453
if (NULL == (schema_policy_lock = slapi_new_rwlock())) {
454
slapi_log_error(SLAPI_LOG_FATAL, "slapi_schema_load_repl_policies",
455
"slapi_new_rwlock() for schema replication policy lock failed\n");
459
slapi_rwlock_wrlock( schema_policy_lock );
461
schema_load_repl_policy((const char *) ENTRY_REPL_SCHEMA_SUPPLIER, &supplier_policy);
462
schema_load_repl_policy((const char *) ENTRY_REPL_SCHEMA_CONSUMER, &consumer_policy);
464
slapi_rwlock_unlock( schema_policy_lock );
470
* It checks if the name/oid of the provided schema item (objectclass/attribute)
471
* is defined in the schema replication policy.
472
* If the replica role is a supplier, it takes the policy from supplier_policy else
473
* it takes it from the consumer_policy.
474
* Then depending on the schema_item, it takes the objectclasses or attributes policies
476
* If it find the name/oid in the policies, it returns
477
* REPL_SCHEMA_UPDATE_ACCEPT_VALUE: This schema item is accepted and can not prevent schema update
478
* REPL_SCHEMA_UPDATE_REJECT_VALUE: This schema item is rejected and prevents the schema update
479
* REPL_SCHEMA_UPDATE_UNKNOWN_VALUE: This schema item as no defined policy
481
* Caller must hold schema_policy_lock in read
484
schema_check_policy(int replica_role, int schema_item, char *name, char *oid)
486
repl_schema_policy_t *repl_policy;
487
schema_item_t *policy;
489
/* depending on the role, we take the supplier or the consumer policy */
490
if (replica_role == REPL_SCHEMA_AS_SUPPLIER) {
491
repl_policy = &supplier_policy;
493
repl_policy = &consumer_policy;
496
/* Now take the correct schema item policy */
497
if (schema_item == REPL_SCHEMA_OBJECTCLASS) {
498
policy = repl_policy->objectclasses;
500
policy = repl_policy->attributes;
503
/* Try to find the name/oid in the defined policies */
505
if ((strcasecmp( name, policy->name_or_oid) == 0) || (strcasecmp( oid, policy->name_or_oid) == 0)) {
506
return policy->action;
508
policy = policy->next;
510
return REPL_SCHEMA_UPDATE_UNKNOWN_VALUE;
257
514
schema_dse_lock_read( void )
5869
6164
* If oc_list1 or oc_list2 is global_oc, the caller must hold the oc_lock
5872
schema_oc_superset_check(struct objclass *oc_list1, struct objclass *oc_list2, char *message) {
6167
schema_oc_superset_check(struct objclass *oc_list1, struct objclass *oc_list2, char *message, int replica_role) {
5873
6168
struct objclass *oc_1, *oc_2;
6169
const char *description;
6170
int debug_logging = 0;
6172
int repl_schema_policy;
5878
6174
if (message == NULL) {
6175
description = (const char *) "";
5881
description = message;
6177
description = (const char *) message;
5884
6180
/* by default assum oc_list1 == oc_list2 */
6183
/* Are we doing replication logging */
6184
if(slapi_is_loglevel_set(SLAPI_LOG_REPL)){
5887
6188
/* Check if all objectclass in oc_list1
5888
6189
* - exists in oc_list2
5889
6190
* - required attributes are also required in oc_2
5890
6191
* - allowed attributes are also allowed in oc_2
6193
slapi_rwlock_rdlock( schema_policy_lock );
5892
6194
for (oc_1 = oc_list1; oc_1 != NULL; oc_1 = oc_1->oc_next) {
6197
/* Check if there is a specific policy for that objectclass */
6198
repl_schema_policy = schema_check_policy(replica_role, REPL_SCHEMA_OBJECTCLASS, oc_1->oc_name, oc_1->oc_oid);
6199
if (repl_schema_policy == REPL_SCHEMA_UPDATE_ACCEPT_VALUE) {
6200
/* We are skipping the superset checking for that objectclass */
6201
slapi_log_error(SLAPI_LOG_REPL, "schema", "Do not check if this OBJECTCLASS is missing on local/remote schema [%s or %s]\n", oc_1->oc_name, oc_1->oc_oid);
6203
} else if (repl_schema_policy == REPL_SCHEMA_UPDATE_REJECT_VALUE) {
6204
/* This objectclass being present, we need to fail as if it was a superset
6205
* keep evaluating to have all the objectclass checking
6207
slapi_log_error(SLAPI_LOG_REPL, "schema", "%s objectclass prevents replication of the schema\n", oc_1->oc_name);
6210
/* we continue to check all the objectclasses so we log what is wrong */
5894
6217
/* Retrieve the remote objectclass in our local schema */
5895
6218
oc_2 = oc_find_nolock(oc_1->oc_oid, oc_list2, PR_TRUE);
5896
6219
if (oc_2 == NULL) {
5897
6220
/* try to retrieve it with the name*/
5898
6221
oc_2 = oc_find_nolock(oc_1->oc_name, oc_list2, PR_TRUE);
6224
if (schema_oc_compare(oc_1, oc_2, description) > 0) {
6226
if (debug_logging) {
6227
if (replica_role == REPL_SCHEMA_AS_CONSUMER) {
6228
slapi_log_error(SLAPI_LOG_REPL, "schema", "Local %s schema objectclasses is a superset of"
6229
" the received one.\n", oc_1->oc_name);
6231
slapi_log_error(SLAPI_LOG_REPL, "schema", "Remote %s schema objectclasses is a superset of"
6232
" the received one.\n", oc_1->oc_name);
5901
6240
slapi_log_error(SLAPI_LOG_REPL, "schema", "Fail to retrieve in the %s schema [%s or %s]\n",
5906
6245
/* The oc_1 objectclasses is supperset */
5909
continue; /* we continue to check all the objectclass */
5912
/* First check the MUST */
5913
if (oc_1->oc_orig_required) {
5914
for (i = 0; oc_1->oc_orig_required[i] != NULL; i++) {
5915
/* For each required attribute from the remote schema check that
5916
* it is also required in the local schema
5919
if (oc_2->oc_orig_required) {
5920
for (j = 0; oc_2->oc_orig_required[j] != NULL; j++) {
5921
if (strcasecmp(oc_2->oc_orig_required[j], oc_1->oc_orig_required[i]) == 0) {
6248
/* we continue to check all the objectclasses so we log what is wrong */
6255
slapi_rwlock_unlock( schema_policy_lock );
6259
/* call must hold oc_lock at least in read */
6260
static struct schema_mods_indexes *
6261
schema_list_oc2learn(struct objclass *oc_remote_list, struct objclass *oc_local_list, int replica_role) {
6262
struct objclass *oc_remote, *oc_local;
6263
struct schema_mods_indexes *head = NULL, *mods_index;
6265
int repl_schema_policy;
6266
const char *message;
6268
if (replica_role == REPL_SCHEMA_AS_SUPPLIER) {
6269
message = (const char *) "remote consumer";
6271
message = (const char *) "remote supplier";
6274
slapi_rwlock_rdlock( schema_policy_lock );
6275
for (oc_remote = oc_remote_list; oc_remote != NULL; oc_remote = oc_remote->oc_next, index++) {
6277
/* If this objectclass is not checked (accept) or rejects schema update */
6278
repl_schema_policy = schema_check_policy(replica_role, REPL_SCHEMA_OBJECTCLASS, oc_remote->oc_name, oc_remote->oc_oid);
6279
if ((repl_schema_policy == REPL_SCHEMA_UPDATE_ACCEPT_VALUE) || (repl_schema_policy == REPL_SCHEMA_UPDATE_REJECT_VALUE)) {
6284
oc_local = oc_find_nolock(oc_remote->oc_oid, oc_local_list, PR_TRUE);
6285
if (oc_local == NULL) {
6286
/* try to retrieve it with the name*/
6287
oc_local = oc_find_nolock(oc_remote->oc_name, oc_local_list, PR_TRUE);
6289
if ((oc_local == NULL) ||
6290
(schema_oc_compare(oc_local, oc_remote, message) < 0)) {
6291
/* This replica does not know this objectclass, It needs to be added */
6292
slapi_log_error(SLAPI_LOG_REPL, "schema", "Add that unknown/extended objectclass %s (%s)\n",
6296
if ((mods_index = (struct schema_mods_indexes *) slapi_ch_calloc(1, sizeof (struct schema_mods_indexes))) == NULL) {
6297
slapi_log_error(SLAPI_LOG_FATAL, "schema", "Fail to Add (no memory) objectclass %s (%s)\n",
6303
/* insert it in the list */
6304
mods_index->index = index;
6305
mods_index->next = head;
6306
mods_index->new_value = NULL;
6310
slapi_rwlock_unlock( schema_policy_lock );
6313
static struct schema_mods_indexes *
6314
schema_list_attr2learn(struct asyntaxinfo *at_list_local, struct asyntaxinfo *at_list_remote, int replica_role)
6316
struct asyntaxinfo *at_remote, *at_local;
6317
struct schema_mods_indexes *head = NULL, *mods_index;
6319
int repl_schema_policy;
6320
int debug_logging = 0;
6323
if (slapi_is_loglevel_set(SLAPI_LOG_REPL)) {
6327
if (replica_role == REPL_SCHEMA_AS_SUPPLIER) {
6328
message = "remote consumer";
6330
message = "remote supplier";
6333
slapi_rwlock_rdlock(schema_policy_lock);
6334
for (at_remote = at_list_remote; at_remote != NULL; at_remote = at_remote->asi_next, index++) {
6335
/* If this objectclass is not checked (accept) or rejects schema update */
6336
repl_schema_policy = schema_check_policy(replica_role, REPL_SCHEMA_ATTRIBUTE, at_remote->asi_name, at_remote->asi_oid);;
6337
if ((repl_schema_policy == REPL_SCHEMA_UPDATE_ACCEPT_VALUE) || (repl_schema_policy == REPL_SCHEMA_UPDATE_REJECT_VALUE)) {
6341
if (((at_local = attr_syntax_find(at_remote, at_list_local)) == NULL) ||
6342
(schema_at_compare(at_local, at_remote, message, debug_logging) < 0)) {
6343
/* This replica does not know this attribute, It needs to be added */
6344
slapi_log_error(SLAPI_LOG_REPL, "schema", "Add that unknown/extended attribute %s (%s)\n",
6345
at_remote->asi_name,
6346
at_remote->asi_oid);
6348
if ((mods_index = (struct schema_mods_indexes *) slapi_ch_calloc(1, sizeof (struct schema_mods_indexes))) == NULL) {
6349
slapi_log_error(SLAPI_LOG_FATAL, "schema", "Fail to Add (no memory) attribute %s (%s)\n",
6350
at_remote->asi_name,
6351
at_remote->asi_oid);
6355
/* insert it in the list */
6356
mods_index->index = index;
6357
mods_index->next = head;
6358
mods_index->new_value = NULL;
6363
slapi_rwlock_unlock(schema_policy_lock);
6367
/* If oc_1 > oc2 returns 1
6371
schema_oc_compare_strict(struct objclass *oc_1, struct objclass *oc_2, const char *description)
6375
PRBool moved_must_to_may;
6377
/* safety checking */
6385
/* First check the MUST */
6386
if (oc_1->oc_orig_required) {
6387
for (i = 0; oc_1->oc_orig_required[i] != NULL; i++) {
6388
/* For each required attribute from oc1 schema check that
6389
* it is also required in the oc2 schema
6392
if (oc_2->oc_orig_required) {
6393
for (j = 0; oc_2->oc_orig_required[j] != NULL; j++) {
6394
if (strcasecmp(oc_2->oc_orig_required[j], oc_1->oc_orig_required[i]) == 0) {
5928
/* The required attribute in the remote protocol (remote_oc->oc_orig_required[i])
5929
* is not required in the local protocol
5931
slapi_log_error(SLAPI_LOG_REPL, "schema", "Attribute %s is not required in '%s' of the %s schema\n",
5932
oc_1->oc_orig_required[i],
5936
/* The oc_1 objectclasses is supperset */
5939
continue; /* we continue to check all attributes */
5944
/* Second check the MAY */
5945
if (oc_1->oc_orig_allowed) {
5946
for (i = 0; oc_1->oc_orig_allowed[i] != NULL; i++) {
5947
/* For each required attribute from the remote schema check that
5948
* it is also required in the local schema
6401
/* Before stating that oc1 is a superset of oc2, we need to verify that the 'required'
6402
* attribute (from oc1) is missing in 'required' oc2 because it is
6403
* now 'allowed' in oc2
6405
moved_must_to_may = PR_FALSE;
5951
6406
if (oc_2->oc_orig_allowed) {
5952
6407
for (j = 0; oc_2->oc_orig_allowed[j] != NULL; j++) {
5953
if (strcasecmp(oc_2->oc_orig_allowed[j], oc_1->oc_orig_allowed[i]) == 0) {
6408
if (strcasecmp(oc_2->oc_orig_allowed[j], oc_1->oc_orig_required[i]) == 0) {
6409
moved_must_to_may = PR_TRUE;
5960
/* The required attribute in the remote protocol (remote_oc->oc_orig_allowed[i])
5961
* is not required in the local protocol
6415
if (moved_must_to_may) {
6416
/* This is a special case where oc1 is actually NOT a superset of oc2 */
6417
slapi_log_error(SLAPI_LOG_REPL, "schema", "Attribute %s is no longer 'required' in '%s' of the %s schema but is now 'allowed'\n",
6418
oc_1->oc_orig_required[i],
6422
/* The required attribute in the oc1
6423
* is not required in the oc2
5963
slapi_log_error(SLAPI_LOG_REPL, "schema", "Attribute %s is not allowed in '%s' of the %s schema\n",
5964
oc_1->oc_orig_allowed[i],
6425
slapi_log_error(SLAPI_LOG_REPL, "schema", "Attribute %s is not required in '%s' of the %s schema\n",
6426
oc_1->oc_orig_required[i],
5968
6430
/* The oc_1 objectclasses is supperset */
5971
continue; /* we continue to check all attributes */
6437
/* Second check the MAY */
6438
if (oc_1->oc_orig_allowed) {
6439
for (i = 0; oc_1->oc_orig_allowed[i] != NULL; i++) {
6440
/* For each required attribute from the remote schema check that
6441
* it is also required in the local schema
6444
if (oc_2->oc_orig_allowed) {
6445
for (j = 0; oc_2->oc_orig_allowed[j] != NULL; j++) {
6446
if (strcasecmp(oc_2->oc_orig_allowed[j], oc_1->oc_orig_allowed[i]) == 0) {
6453
/* The allowed attribute in the remote schema (remote_oc->oc_orig_allowed[i])
6454
* is not allowed in the local schema
6456
slapi_log_error(SLAPI_LOG_REPL, "schema", "Attribute %s is not allowed in '%s' of the %s schema\n",
6457
oc_1->oc_orig_allowed[i],
6461
/* The oc_1 objectclasses is superset */
6472
/* Compare two objectclass definitions
6476
* 1: if oc_1 is a superset of oc_2
6477
* -1: if oc_2 is a superset of oc_1
6478
* 0: if oc_1 and at_2 are equivalent
6481
schema_oc_compare(struct objclass *oc_1, struct objclass *oc_2, const char *description)
6483
if (schema_oc_compare_strict(oc_1, oc_2, description) > 0) {
6485
} else if (schema_oc_compare_strict(oc_2, oc_1, description) > 0) {
6492
/* Compare two attributes definitions
6494
* - single/multi value
6498
* 1: if at_1 is a superset of at_2
6499
* -1: if at_2 is a superset of at_1
6500
* 0: if at_1 and at_2 are equivalent
6503
schema_at_compare(struct asyntaxinfo *at_1, struct asyntaxinfo *at_2, char *message, int debug_logging)
6507
/* safety checking */
6519
* Check for single vs. multi value
6521
if (!(at_1->asi_flags & SLAPI_ATTR_FLAG_SINGLE) && (at_2->asi_flags & SLAPI_ATTR_FLAG_SINGLE)) {
6523
/* at_1 is a superset */
6524
if (debug_logging) {
6525
slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] is not "
6526
"\"single-valued\" \n", message, at_1->asi_name);
6530
if ((at_1->asi_flags & SLAPI_ATTR_FLAG_SINGLE) && !(at_2->asi_flags & SLAPI_ATTR_FLAG_SINGLE)) {
6531
/* at_2 is a superset */
6532
if (debug_logging) {
6533
slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] is not "
6534
"\"single-valued\" \n", message, at_1->asi_name);
6540
* Check the syntaxes
6542
if (schema_at_superset_check_syntax_oids(at_1->asi_syntax_oid, at_2->asi_syntax_oid)) {
6543
/* at_1 is a superset */
6544
if (debug_logging) {
6545
slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] syntax "
6546
"can not be overwritten\n", message, at_1->asi_name);
6550
if (schema_at_superset_check_syntax_oids(at_2->asi_syntax_oid, at_1->asi_syntax_oid)) {
6551
/* at_2 is a superset */
6552
if (debug_logging) {
6553
slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] syntax "
6554
"can not be overwritten\n", message, at_2->asi_name);
6560
* Check some matching rules - not finished yet...
6562
* For now, skip the matching rule check (rc is never equal to -1)
6564
if (schema_at_superset_check_mr(at_1, at_2, info)) {
6565
if (debug_logging) {
6566
slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] matching "
6567
"rule can not be overwritten\n", message, at_1->asi_name);
6571
if (schema_at_superset_check_mr(at_2, at_1, info)) {
6572
if (debug_logging) {
6573
slapi_log_error(SLAPI_LOG_REPL, "schema", "%s schema attribute [%s] matching "
6574
"rule can not be overwritten\n", message, at_2->asi_name);
6583
schema_at_superset_check(struct asyntaxinfo *at_list1, struct asyntaxinfo *at_list2, char *message, int replica_role)
6585
struct asyntaxinfo *at_1, *at_2;
6586
int debug_logging = 0;
6587
int repl_schema_policy;
6590
if(at_list1 == NULL || at_list2 == NULL){
6594
/* Are we doing replication logging */
6595
if(slapi_is_loglevel_set(SLAPI_LOG_REPL)){
6599
slapi_rwlock_rdlock( schema_policy_lock );
6600
for (at_1 = at_list1; at_1 != NULL; at_1 = at_1->asi_next) {
6602
/* Check if there is a specific policy for that objectclass */
6603
repl_schema_policy = schema_check_policy(replica_role, REPL_SCHEMA_ATTRIBUTE, at_1->asi_name, at_1->asi_oid);
6604
if (repl_schema_policy == REPL_SCHEMA_UPDATE_ACCEPT_VALUE) {
6605
/* We are skipping the superset checking for that attribute */
6606
slapi_log_error(SLAPI_LOG_REPL, "schema", "Do not check if this ATTRIBUTE is missing on local/remote schema [%s or %s]\n", at_1->asi_name, at_1->asi_oid);
6608
} else if (repl_schema_policy == REPL_SCHEMA_UPDATE_REJECT_VALUE) {
6609
/* This attribute being present, we need to fail as if it was a superset
6610
* but keep evaluating to have all the attribute checking
6612
slapi_log_error(SLAPI_LOG_REPL, "schema", "%s attribute prevents replication of the schema\n", at_1->asi_name);
6614
if (debug_logging) {
6615
/* we continue to check all the objectclasses so we log what is wrong */
6622
/* check if at_1 exists in at_list2 */
6623
if((at_2 = attr_syntax_find(at_1, at_list2))) {
6624
if (schema_at_compare(at_1, at_2, message, debug_logging) > 0) {
6626
if (debug_logging) {
6627
if (replica_role == REPL_SCHEMA_AS_CONSUMER) {
6628
slapi_log_error(SLAPI_LOG_REPL, "schema", "Local %s schema attributetypes is a superset of"
6629
" the received one.\n", at_1->asi_name);
6631
slapi_log_error(SLAPI_LOG_REPL, "schema", "Remote %s schema attributetypes is a superset of"
6632
" the received one.\n", at_1->asi_name);
6642
/* we continue to check all attributes so we log what is wrong */
6643
slapi_log_error(SLAPI_LOG_REPL, "schema", "Fail to retrieve in the %s schema [%s or %s]\n",
6644
message, at_1->asi_name, at_1->asi_oid);
6651
slapi_rwlock_unlock( schema_policy_lock );
6658
* Return 1 if a1's matching rules are superset(not to be overwritten). If just one of
6659
* the matching rules should not be overwritten, even if one should, we can not allow it.
6662
schema_at_superset_check_mr(struct asyntaxinfo *a1, struct asyntaxinfo *a2, char *info)
6664
char *a1_mrtype[3] = { a1->asi_mr_equality, a1->asi_mr_substring, a1->asi_mr_ordering };
6665
char *a2_mrtype[3] = { a2->asi_mr_equality, a2->asi_mr_substring, a2->asi_mr_ordering };
6669
* Loop over the three matching rule types
6671
for(i = 0; i < 3; i++){
6675
* Future action item - determine matching rule precedence:
6678
"caseExactIA5Match", "1.3.6.1.4.1.1466.109.114.1"
6679
"caseExactMatch", "2.5.13.5"
6680
"caseExactOrderingMatch", "2.5.13.6"
6681
"caseExactSubstringsMatch", "2.5.13.7"
6682
"caseExactIA5SubstringsMatch", "2.16.840.1.113730.3.3.1"
6685
"generalizedTimeMatch", "2.5.13.27"
6686
"generalizedTimeOrderingMatch", "2.5.13.28"
6687
"booleanMatch", "2.5.13.13"
6688
"caseIgnoreIA5Match", "1.3.6.1.4.1.1466.109.114.2"
6689
"caseIgnoreIA5SubstringsMatch", "1.3.6.1.4.1.1466.109.114.3"
6690
"caseIgnoreListMatch", "2.5.13.11"
6691
"caseIgnoreListSubstringsMatch", "2.5.13.12"
6692
"caseIgnoreMatch", "2.5.13.2" -------------------------------
6693
"caseIgnoreOrderingMatch", "2.5.13.3" -----------------------> can have lang options
6694
"caseIgnoreSubstringsMatch", "2.5.13.4" --------------------- (as seen in the console)!
6695
"directoryStringFirstComponentMatch", "2.5.13.31"
6696
"objectIdentifierMatch", "2.5.13.0"
6697
"objectIdentifierFirstComponentMatch", "2.5.13.30"
6700
"bitStringMatch", "2.5.13.16","2.16.840.1.113730.3.3.1"
6703
"octetStringMatch", "2.5.13.17"
6704
"octetStringOrderingMatch", "2.5.13.18"
6707
"distinguishedNameMatch", "2.5.13.1"
6710
"integerMatch", "2.5.13.14"
6711
"integerOrderingMatch", "2.5.13.15"
6712
"integerFirstComponentMatch", "2.5.13.29"
6715
"uniqueMemberMatch", "2.5.13.23"
6718
"numericStringMatch", "2.5.13.8"
6719
"numericStringOrderingMatch", "2.5.13.9"
6720
"numericStringSubstringsMatch", "2.5.13.10"
6723
"telephoneNumberMatch", "2.5.13.20"
6724
"telephoneNumberSubstringsMatch", "2.5.13.21"
6734
* Return 1 if oid1 is a superset(oid1 is not to be overwritten)
6737
schema_at_superset_check_syntax_oids(char *oid1, char *oid2)
6739
if(oid1 == NULL && oid2 == NULL){
6741
} else if (oid2 == NULL){
6743
} else if (oid1 == NULL){
6747
if(strcmp(oid1, BINARY_SYNTAX_OID) == 0){
6748
if(strcmp(oid2, BINARY_SYNTAX_OID) &&
6749
strcmp(oid2, INTEGER_SYNTAX_OID) &&
6750
strcmp(oid2, NUMERICSTRING_SYNTAX_OID) &&
6751
strcmp(oid2, IA5STRING_SYNTAX_OID) &&
6752
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6753
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6754
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6755
strcmp(oid2, FACSIMILE_SYNTAX_OID) &&
6756
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6757
strcmp(oid2, TELEPHONE_SYNTAX_OID) &&
6758
strcmp(oid2, TELETEXTERMID_SYNTAX_OID) &&
6759
strcmp(oid2, TELEXNUMBER_SYNTAX_OID))
6764
} else if(strcmp(oid1, BITSTRING_SYNTAX_OID) == 0){
6765
if(strcmp(oid2, BINARY_SYNTAX_OID) &&
6766
strcmp(oid2, BITSTRING_SYNTAX_OID) &&
6767
strcmp(oid2, INTEGER_SYNTAX_OID) &&
6768
strcmp(oid2, NUMERICSTRING_SYNTAX_OID) &&
6769
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6770
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6771
strcmp(oid2, IA5STRING_SYNTAX_OID) &&
6772
strcmp(oid2, FACSIMILE_SYNTAX_OID) &&
6773
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6774
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6775
strcmp(oid2, TELEPHONE_SYNTAX_OID) &&
6776
strcmp(oid2, TELETEXTERMID_SYNTAX_OID) &&
6777
strcmp(oid2, TELEXNUMBER_SYNTAX_OID))
6781
} else if(strcmp(oid1, BOOLEAN_SYNTAX_OID) == 0){
6782
if(strcmp(oid2, BOOLEAN_SYNTAX_OID) &&
6783
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6784
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6785
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6786
strcmp(oid2, IA5STRING_SYNTAX_OID))
6790
} else if(strcmp(oid1, COUNTRYSTRING_SYNTAX_OID) ==0){
6791
if(strcmp(oid2, COUNTRYSTRING_SYNTAX_OID) &&
6792
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6793
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6794
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6795
strcmp(oid2, IA5STRING_SYNTAX_OID))
6799
} else if(strcmp(oid1, DN_SYNTAX_OID) == 0){
6800
if(strcmp(oid2, DN_SYNTAX_OID) &&
6801
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6802
strcmp(oid2, DIRSTRING_SYNTAX_OID) )
6806
} else if(strcmp(oid1, DELIVERYMETHOD_SYNTAX_OID) ==0){
6807
if(strcmp(oid2, DELIVERYMETHOD_SYNTAX_OID) &&
6808
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6809
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6810
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6811
strcmp(oid2, IA5STRING_SYNTAX_OID))
6815
} else if(strcmp(oid1, DIRSTRING_SYNTAX_OID) == 0){
6816
if(strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6817
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID)){
6820
} else if(strcmp(oid1, ENHANCEDGUIDE_SYNTAX_OID) == 0){
6821
if(strcmp(oid2, ENHANCEDGUIDE_SYNTAX_OID) &&
6822
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6823
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6824
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6825
strcmp(oid2, IA5STRING_SYNTAX_OID))
6829
} else if(strcmp(oid1, IA5STRING_SYNTAX_OID) == 0){
6830
if(strcmp(oid2, IA5STRING_SYNTAX_OID) &&
6831
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6832
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6833
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID))
6837
} else if(strcmp(oid1, INTEGER_SYNTAX_OID) == 0){
6838
if(strcmp(oid2, INTEGER_SYNTAX_OID) &&
6839
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6840
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6841
strcmp(oid2, NUMERICSTRING_SYNTAX_OID) &&
6842
strcmp(oid2, TELEPHONE_SYNTAX_OID) &&
6843
strcmp(oid2, TELETEXTERMID_SYNTAX_OID) &&
6844
strcmp(oid2, TELEXNUMBER_SYNTAX_OID) &&
6845
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6846
strcmp(oid2, IA5STRING_SYNTAX_OID) )
6850
} else if(strcmp(oid1, JPEG_SYNTAX_OID) == 0){
6851
if(strcmp(oid2, JPEG_SYNTAX_OID) &&
6852
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6853
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6854
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6855
strcmp(oid2, IA5STRING_SYNTAX_OID))
6859
} else if(strcmp(oid1, NAMEANDOPTIONALUID_SYNTAX_OID) == 0){
6860
if(strcmp(oid2, NAMEANDOPTIONALUID_SYNTAX_OID) &&
6861
strcmp(oid2, NAMEANDOPTIONALUID_SYNTAX_OID) &&
6862
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6863
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6864
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6865
strcmp(oid2, IA5STRING_SYNTAX_OID))
6869
} else if(strcmp(oid1, NUMERICSTRING_SYNTAX_OID) == 0){
6870
if(strcmp(oid2, NUMERICSTRING_SYNTAX_OID) &&
6871
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6872
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6873
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6874
strcmp(oid2, IA5STRING_SYNTAX_OID))
6878
} else if(strcmp(oid1, OID_SYNTAX_OID) == 0){
6879
if(strcmp(oid2, OID_SYNTAX_OID) &&
6880
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6881
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6882
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6883
strcmp(oid2, IA5STRING_SYNTAX_OID))
6887
} else if (strcmp(oid1, OCTETSTRING_SYNTAX_OID) == 0){
6888
if(strcmp(oid2, OCTETSTRING_SYNTAX_OID) &&
6889
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6890
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6891
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6892
strcmp(oid2, IA5STRING_SYNTAX_OID))
6896
} else if(strcmp(oid1, POSTALADDRESS_SYNTAX_OID) ==0){
6897
if(strcmp(oid2, POSTALADDRESS_SYNTAX_OID) &&
6898
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6899
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6900
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6901
strcmp(oid2, IA5STRING_SYNTAX_OID))
6905
} else if(strcmp(oid1, PRINTABLESTRING_SYNTAX_OID) == 0){
6906
if(strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6907
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6908
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6909
strcmp(oid2, IA5STRING_SYNTAX_OID))
6913
} else if(strcmp(oid1, TELEPHONE_SYNTAX_OID) == 0){
6914
if(strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6915
strcmp(oid2, TELEPHONE_SYNTAX_OID) &&
6916
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6917
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6918
strcmp(oid2, IA5STRING_SYNTAX_OID))
6922
} else if(strcmp(oid1, TELETEXTERMID_SYNTAX_OID) == 0){
6923
if(strcmp(oid2, TELETEXTERMID_SYNTAX_OID) &&
6924
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6925
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6926
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6927
strcmp(oid2, IA5STRING_SYNTAX_OID))
6931
} else if(strcmp(oid1, TELEXNUMBER_SYNTAX_OID) == 0){
6932
if(strcmp(oid2, TELEXNUMBER_SYNTAX_OID) &&
6933
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6934
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6935
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6936
strcmp(oid2, IA5STRING_SYNTAX_OID))
6940
} else if (strcmp(oid1, SPACE_INSENSITIVE_STRING_SYNTAX_OID) == 0){
6941
if(strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6942
strcmp(oid2, PRINTABLESTRING_SYNTAX_OID) &&
6943
strcmp(oid2, DIRSTRING_SYNTAX_OID) &&
6944
strcmp(oid2, SPACE_INSENSITIVE_STRING_SYNTAX_OID) &&
6945
strcmp(oid2, IA5STRING_SYNTAX_OID))
7101
schema_attributetypes_superset_check(struct berval **remote_schema, char *type)
7103
struct asyntaxinfo *remote_at_list = NULL;
7106
if (remote_schema != NULL) {
7107
/* First build an attribute list from the remote schema */
7108
if ((remote_at_list = schema_berval_to_atlist(remote_schema)) == NULL) {
7114
* Check that for each object from the remote schema
7115
* - MUST attributes are also MUST in local schema
7116
* - ALLOWED attributes are also ALLOWED in local schema
7118
if (remote_at_list) {
7119
attr_syntax_read_lock();
7120
if (strcmp(type, OC_SUPPLIER) == 0) {
7122
* Check if the remote_at_list from a consumer are or not
7123
* a superset of the attributetypes of the local supplier schema
7125
rc = schema_at_superset_check(remote_at_list, attr_syntax_get_global_at(), "local supplier", REPL_SCHEMA_AS_SUPPLIER);
7128
* Check if the attributeypes of the local consumer schema are or not
7129
* a superset of the remote_at_list from a supplier
7131
rc = schema_at_superset_check(attr_syntax_get_global_at(), remote_at_list, "remote supplier", REPL_SCHEMA_AS_CONSUMER);
7133
attr_syntax_unlock_read();
7136
/* Free the remote schema list */
7137
schema_atlist_free(remote_at_list);
7142
/* Do the internal MOD and update the local "nsSchemaCSN" with a local timestamp
7143
* It could be a good idea to set the 'nsSchemaCSN' with the maximum of local time and
7144
* the CSN received with the remote schema
7147
modify_schema_internal_mod(Slapi_DN *sdn, Slapi_Mods *smods)
7149
Slapi_PBlock *newpb;
7153
/* allocate internal mod components: pblock*/
7154
newpb = slapi_pblock_new();
7156
slapi_modify_internal_set_pb_ext (
7159
slapi_mods_get_ldapmods_byref (smods),
7160
NULL, /* Controls */
7162
(void *)plugin_get_default_component_id(),
7166
slapi_modify_internal_pb (newpb);
7167
slapi_pblock_get (newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result);
7168
if (op_result == LDAP_SUCCESS) {
7169
/* Update the schema csn if the operation succeeded */
7170
schema_csn = csn_new();
7171
if (NULL != schema_csn) {
7172
csn_set_replicaid(schema_csn, 0);
7173
csn_set_time(schema_csn, current_time());
7174
g_set_global_schema_csn(schema_csn);
7178
slapi_pblock_destroy(newpb);
7181
/* Prepare slapi_mods for the internal mod
7182
* Caller must free smods with slapi_mods_done
7185
modify_schema_prepare_mods(Slapi_Mods *smods, char *type, struct schema_mods_indexes *values)
7187
struct schema_mods_indexes *object;
7189
struct berval **bvps;
7192
for (object = values, nb_values = 0; object != NULL; object = object->next, nb_values++);
7193
bvps = (struct berval **) slapi_ch_calloc(1, (nb_values + 1) * sizeof(struct berval *));
7196
for (i = 0, object = values; object != NULL; i++, object = object->next) {
7197
bv = (struct berval *) slapi_ch_malloc(sizeof(struct berval));
7198
bv->bv_len = strlen(object->new_value);
7199
bv->bv_val = (void*) object->new_value;
7201
slapi_log_error(SLAPI_LOG_REPL, "schema", "MOD[%d] add (%s): %s\n", i, type, object->new_value);
7203
bvps[nb_values] = NULL;
7204
slapi_mods_init (smods, 2);
7205
slapi_mods_add_modbvps( smods, LDAP_MOD_ADD, type, bvps );
7206
for (i = 0; bvps[i] != NULL; i++) {
7207
/* bv_val should not be free. It belongs to the incoming MOD */
7208
slapi_ch_free((void **) &bvps[i]);
7210
slapi_ch_free((void **) &bvps);
7214
/* called by modify_schema_dse/supplier_learn_new_definitions to learn new
7215
* definitions via internal mod.
7216
* Internal mod is important, because we want those definitions to be updated in 99user.ldif
7217
* and we are not sure that the current operation will succeeds or not.
7220
modify_schema_apply_new_definitions(char *attr_name, struct schema_mods_indexes *list)
7222
Slapi_Mods smods = {0};
7223
Slapi_DN *sdn = NULL;
7229
sdn = slapi_sdn_new();
7231
slapi_log_error( SLAPI_LOG_FATAL, "schema", "modify_schema_apply_new_definitions Out of memory \n");
7234
slapi_sdn_set_dn_byval(sdn, SLAPD_SCHEMA_DN);
7236
/* prepare the mods */
7237
modify_schema_prepare_mods(&smods, attr_name, list);
7239
/* update the schema with the new attributetypes */
7240
/* No need to lock the schema_dse as the internal mod will do */
7241
modify_schema_internal_mod(sdn, &smods);
7246
slapi_sdn_free(&sdn);
7248
slapi_mods_done (&smods);
7252
* This routines retrieves from the remote schema (mods) the
7253
* definitions (attributetypes/objectclasses), that are:
7254
* - unknown from the local schema
7255
* - a superset of the local definition
7257
* It then builds two lists (to be freed by the caller) with those definitions.
7258
* Those list contains a duplicate of the definition (string).
7261
modify_schema_get_new_definitions(Slapi_PBlock *pb, LDAPMod **mods, struct schema_mods_indexes **at_list, struct schema_mods_indexes **oc_list)
7263
struct asyntaxinfo *remote_at_list;
7264
struct objclass *remote_oc_list;
7265
int is_replicated_operation = 0;
7266
int replace_allowed = 0;
7267
slapdFrontendConfig_t *slapdFrontendConfig;
7269
struct schema_mods_indexes *at2learn_list = NULL;
7270
struct schema_mods_indexes *at2learn;
7271
struct schema_mods_indexes *oc2learn_list = NULL;
7272
struct schema_mods_indexes *oc2learn;
7275
slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation);
7277
/* by default nothing to learn */
7281
/* We are only looking for schema received from a supplier */
7282
if (!is_replicated_operation || !mods) {
7286
/* Check if we are allowed to update the schema (if needed) */
7287
slapdFrontendConfig = getFrontendConfig();
7288
CFG_LOCK_READ(slapdFrontendConfig);
7289
if ((0 == strcasecmp(slapdFrontendConfig->schemareplace, CONFIG_SCHEMAREPLACE_STR_ON)) ||
7290
(0 == strcasecmp(slapdFrontendConfig->schemareplace, CONFIG_SCHEMAREPLACE_STR_REPLICATION_ONLY))) {
7291
replace_allowed = 1;
7293
CFG_UNLOCK_READ(slapdFrontendConfig);
7294
if (!replace_allowed) {
7299
/* First retrieve unknowns attributetypes because an unknown objectclasses
7300
* may be composed of unknown attributetypes
7302
at2learn_list = NULL;
7303
oc2learn_list = NULL;
7304
schema_dse_lock_read();
7305
for (i = 0; mods[i]; i++) {
7306
if (SLAPI_IS_MOD_REPLACE(mods[i]->mod_op) && (mods[i]->mod_bvalues)) {
7308
if (strcasecmp(mods[i]->mod_type, "attributetypes") == 0) {
7309
/* we have some MOD_replace of attributetypes*/
7311
/* First build an attribute list from the remote schema */
7312
if ((remote_at_list = schema_berval_to_atlist(mods[i]->mod_bvalues)) == NULL) {
7313
/* If we can not build an attributes list from the mods, just skip
7314
* it and look for objectclasses
7316
slapi_log_error(SLAPI_LOG_FATAL, "schema",
7317
"Not able to build an attributes list (%s) from the schema received from the supplier\n",
7321
/* Build a list of attributestype to learn from the remote definitions */
7322
attr_syntax_read_lock();
7323
at2learn_list = schema_list_attr2learn(attr_syntax_get_global_at(), remote_at_list, REPL_SCHEMA_AS_CONSUMER);
7324
attr_syntax_unlock_read();
7326
/* For each of them copy the value to set */
7327
for (at2learn = at2learn_list; at2learn != NULL; at2learn = at2learn->next) {
7329
bv = mods[i]->mod_bvalues[at2learn->index]; /* takes the berval from the selected mod */
7330
at2learn->new_value = (char *) slapi_ch_malloc(bv->bv_len + 1);
7331
memcpy(at2learn->new_value, bv->bv_val, bv->bv_len);
7332
at2learn->new_value[bv->bv_len] = '\0';
7333
slapi_log_error(SLAPI_LOG_REPL, "schema", "take attributetypes: %s\n", at2learn->new_value);
7336
/* Free the remote schema list */
7337
schema_atlist_free(remote_at_list);
7339
} else if (strcasecmp(mods[i]->mod_type, "objectclasses") == 0) {
7340
/* we have some MOD_replace of objectclasses */
7342
/* First build an objectclass list from the remote schema */
7343
if ((remote_oc_list = schema_berval_to_oclist(mods[i]->mod_bvalues)) == NULL) {
7344
/* If we can not build an objectclasses list from the mods, just skip
7345
* it and look for attributes
7347
slapi_log_error(SLAPI_LOG_FATAL, "schema",
7348
"Not able to build an objectclasses list (%s) from the schema received from the supplier\n",
7352
/* Build a list of objectclasses to learn from the remote definitions */
7354
oc2learn_list = schema_list_oc2learn(remote_oc_list, g_get_global_oc_nolock(), REPL_SCHEMA_AS_CONSUMER);
7357
/* For each of them copy the value to set */
7358
for (oc2learn = oc2learn_list; oc2learn != NULL; oc2learn = oc2learn->next) {
7360
bv = mods[i]->mod_bvalues[oc2learn->index]; /* takes the berval from the selected mod */
7361
oc2learn->new_value = (char *) slapi_ch_malloc(bv->bv_len + 1);
7362
memcpy(oc2learn->new_value, bv->bv_val, bv->bv_len);
7363
oc2learn->new_value[bv->bv_len] = '\0';
7364
slapi_log_error(SLAPI_LOG_REPL, "schema", "take objectclass: %s\n", oc2learn->new_value);
7367
/* Free the remote schema list*/
7368
schema_oclist_free(remote_oc_list);
7372
schema_dse_unlock();
7374
*at_list = at2learn_list;
7375
*oc_list = oc2learn_list;
7379
* It evaluate if the schema in the mods, is a superset of
7381
* Called when we know the mods comes from/to a replicated session
7382
* Caller must not hold schema_dse lock
7384
* mods: set of mod to apply to the schema
7386
* OC_CONSUMER: means the caller is acting as a consumer (receiving a schema)
7387
* OC_SUPPLIER: means the caller is acting as a supplier (sending a schema)
7390
* - PR_TRUE: if replicated schema is a superset of local schema
7391
* - PR_FALSE: if local schema is a superset of local schema
7394
check_replicated_schema(LDAPMod **mods, char *replica_role, char **attr_name)
7397
PRBool rc = PR_TRUE;
7399
schema_dse_lock_read();
7400
for (i = 0; mods[i]; i++) {
7401
if ((SLAPI_IS_MOD_REPLACE(mods[i]->mod_op)) && strcasecmp (mods[i]->mod_type, "attributetypes") == 0) {
7402
if (schema_attributetypes_superset_check(mods[i]->mod_bvalues, replica_role)) {
7404
*attr_name = mods[i]->mod_type;
7407
} else if ((SLAPI_IS_MOD_REPLACE(mods[i]->mod_op)) && strcasecmp (mods[i]->mod_type, "objectclasses") == 0) {
7408
if (schema_objectclasses_superset_check(mods[i]->mod_bvalues, replica_role)) {
7410
*attr_name = mods[i]->mod_type;
7417
schema_dse_unlock();
7422
/* Free the list of definitions allocated in modify_schema_get_new_definitions/supplier_get_new_definitions */
7424
modify_schema_free_new_definitions(struct schema_mods_indexes *def_list)
7426
struct schema_mods_indexes *def, *head;
7428
for (head = def_list; head != NULL; ) {
7432
/* Free the string definition that was copied from the berval */
7433
if (def->new_value) {
7434
slapi_ch_free((void**) &def->new_value);
7437
/* Then the definition cell */
7438
slapi_ch_free((void **) &def);
7442
/* This functions is called by a supplier.
7443
* It builds lists of definitions (attributetypes/objectclasses) to learn
7444
* objectclasses: received objectclass definitions
7445
* attributetypes: received attribute definitions
7446
* new_oc: list of definitions to learn (list should be freed by the caller)
7447
* new_at: list of definitions to learn (list should be freed by the caller)
7451
supplier_get_new_definitions(struct berval **objectclasses, struct berval **attributetypes, struct schema_mods_indexes **new_oc, struct schema_mods_indexes **new_at)
7453
int replace_allowed = 0;
7454
slapdFrontendConfig_t *slapdFrontendConfig;
7455
struct asyntaxinfo *remote_at_list;
7456
struct objclass *remote_oc_list;
7457
struct schema_mods_indexes *at2learn_list = NULL;
7458
struct schema_mods_indexes *at2learn;
7459
struct schema_mods_indexes *oc2learn_list = NULL;
7460
struct schema_mods_indexes *oc2learn;
7465
if ((objectclasses == NULL) && (attributetypes == NULL)) {
7468
/* Check if we are allowed to update the schema (if needed) */
7469
slapdFrontendConfig = getFrontendConfig();
7470
CFG_LOCK_READ(slapdFrontendConfig);
7471
if ((0 == strcasecmp(slapdFrontendConfig->schemareplace, CONFIG_SCHEMAREPLACE_STR_ON)) ||
7472
(0 == strcasecmp(slapdFrontendConfig->schemareplace, CONFIG_SCHEMAREPLACE_STR_REPLICATION_ONLY))) {
7473
replace_allowed = 1;
7475
CFG_UNLOCK_READ(slapdFrontendConfig);
7476
if (!replace_allowed) {
7480
schema_dse_lock_read();
7482
* Build the list of objectclasses
7484
/* from berval to objclass more convenient to compare */
7485
if ((remote_oc_list = schema_berval_to_oclist(objectclasses)) != NULL) {
7486
/* Build a list of objectclasses to learn from the remote definitions */
7488
oc2learn_list = schema_list_oc2learn(remote_oc_list, g_get_global_oc_nolock(), REPL_SCHEMA_AS_SUPPLIER);
7491
/* For each of them copy the value to set */
7492
for (oc2learn = oc2learn_list; oc2learn != NULL; oc2learn = oc2learn->next) {
7494
bv = objectclasses[oc2learn->index]; /* takes the berval from the selected objectclass */
7495
oc2learn->new_value = (char *) slapi_ch_malloc(bv->bv_len + 1);
7496
memcpy(oc2learn->new_value, bv->bv_val, bv->bv_len);
7497
oc2learn->new_value[bv->bv_len] = '\0';
7498
slapi_log_error(SLAPI_LOG_REPL, "schema", "supplier takes objectclass: %s\n", oc2learn->new_value);
7501
/* Free the remote schema list*/
7502
schema_oclist_free(remote_oc_list);
7504
/* If we can not build an objectclasses list */
7505
slapi_log_error(SLAPI_LOG_FATAL, "schema",
7506
"Not able to build an objectclasses list from the consumer schema\n");
7511
* Build the list of attributetypes
7513
/* First build an attribute list from the remote schema */
7514
if ((remote_at_list = schema_berval_to_atlist(attributetypes)) != NULL) {
7515
/* Build a list of attributestype to learn from the remote definitions */
7516
attr_syntax_read_lock();
7517
at2learn_list = schema_list_attr2learn(attr_syntax_get_global_at(), remote_at_list, REPL_SCHEMA_AS_SUPPLIER);
7518
attr_syntax_unlock_read();
7520
/* For each of them copy the value to set */
7521
for (at2learn = at2learn_list; at2learn != NULL; at2learn = at2learn->next) {
7523
bv = attributetypes[at2learn->index]; /* takes the berval from the selected mod */
7524
at2learn->new_value = (char *) slapi_ch_malloc(bv->bv_len + 1);
7525
memcpy(at2learn->new_value, bv->bv_val, bv->bv_len);
7526
at2learn->new_value[bv->bv_len] = '\0';
7527
slapi_log_error(SLAPI_LOG_REPL, "schema", "supplier takes attributetypes: %s\n", at2learn->new_value);
7530
/* Free the remote schema list */
7531
schema_atlist_free(remote_at_list);
7533
/* If we can not build an attributes list from the mods, just skip
7534
* it and look for objectclasses
7536
slapi_log_error(SLAPI_LOG_FATAL, "schema",
7537
"Not able to build an attributes list from the consumer schema");
7539
schema_dse_unlock();
7540
*new_oc = oc2learn_list;
7541
*new_at = at2learn_list;
7545
/* This functions is called by a supplier when it detects new definitions (objectclasses/attributetypes)
7546
* or extension of existing definitions in a consumer schema.
7547
* This function, build lists of definitions to "learn" and add those definitions in the schema and 99user.ldif
7550
supplier_learn_new_definitions(struct berval **objectclasses, struct berval **attributetypes)
7552
struct schema_mods_indexes *oc_list = NULL;
7553
struct schema_mods_indexes *at_list = NULL;
7555
supplier_get_new_definitions(objectclasses, attributetypes, &oc_list, &at_list);
7557
modify_schema_apply_new_definitions("attributetypes", at_list);
7560
modify_schema_apply_new_definitions("objectclasses", oc_list);
7562
/* No need to hold the lock for these list that are local */
7563
modify_schema_free_new_definitions(at_list);
7564
modify_schema_free_new_definitions(oc_list);