diff options
-rw-r--r-- | ldap/servers/plugins/acl/acleffectiverights.c | 274 | ||||
-rw-r--r-- | ldap/servers/plugins/chainingdb/cb_config.c | 6 | ||||
-rw-r--r-- | ldap/servers/plugins/chainingdb/cb_controls.c | 2 | ||||
-rw-r--r-- | ldap/servers/plugins/chainingdb/cb_instance.c | 6 | ||||
-rw-r--r-- | ldap/servers/plugins/schema_reload/schema_reload.c | 2 | ||||
-rw-r--r-- | ldap/servers/slapd/charray.c | 52 | ||||
-rw-r--r-- | ldap/servers/slapd/opshared.c | 225 | ||||
-rw-r--r-- | ldap/servers/slapd/pblock.c | 12 | ||||
-rw-r--r-- | ldap/servers/slapd/result.c | 30 | ||||
-rw-r--r-- | ldap/servers/slapd/schema.c | 122 | ||||
-rw-r--r-- | ldap/servers/slapd/search.c | 329 | ||||
-rw-r--r-- | ldap/servers/slapd/slapi-plugin.h | 4 | ||||
-rw-r--r-- | ldap/servers/slapd/slapi-private.h | 13 |
13 files changed, 824 insertions, 253 deletions
diff --git a/ldap/servers/plugins/acl/acleffectiverights.c b/ldap/servers/plugins/acl/acleffectiverights.c index c40840a5..c50807f9 100644 --- a/ldap/servers/plugins/acl/acleffectiverights.c +++ b/ldap/servers/plugins/acl/acleffectiverights.c @@ -46,7 +46,13 @@ /* news2 is optional, provided as a convenience */ /* 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) +_append_gerstr( + char **gerstr, + size_t *capacity, + size_t *size, + const char *news, + const char *news2 + ) { size_t len; size_t increment = 128; @@ -90,7 +96,12 @@ _append_gerstr(char **gerstr, size_t *capacity, size_t *size, const char *news, } static int -_ger_g_permission_granted ( Slapi_PBlock *pb, Slapi_Entry *e, char **errbuf ) +_ger_g_permission_granted ( + Slapi_PBlock *pb, + Slapi_Entry *e, + const char *subjectdn, + char **errbuf + ) { char *proxydn = NULL; Slapi_DN *requestor_sdn, *entry_sdn; @@ -151,6 +162,14 @@ _ger_g_permission_granted ( Slapi_PBlock *pb, Slapi_Entry *e, char **errbuf ) goto bailout; } + /* if the requestor and the subject user are identical, let's grant it */ + if ( strcasecmp ( slapi_sdn_get_ndn(requestor_sdn), subjectdn ) == 0) + { + /* Requestor should see his own permission rights on any entry */ + rc = LDAP_SUCCESS; + goto bailout; + } + aclutil_str_appened ( errbuf, "get-effective-rights: requestor has no g permission on the entry" ); slapi_log_error (SLAPI_LOG_ACL, plugin_name, "_ger_g_permission_granted: %s\n", *errbuf); @@ -166,11 +185,17 @@ bailout: } static int -_ger_parse_control ( Slapi_PBlock *pb, char **subjectndn, int *iscritical, char **errbuf ) +_ger_parse_control ( + Slapi_PBlock *pb, + char **subjectndn, + int *iscritical, + char **errbuf + ) { LDAPControl **requestcontrols; struct berval *subjectber; BerElement *ber; + int subjectndnlen = 0; if (NULL == subjectndn) { @@ -231,7 +256,8 @@ _ger_parse_control ( Slapi_PBlock *pb, char **subjectndn, int *iscritical, char * (see section 9 of RFC 2829) only. It also only supports the "dnAuthzId" * flavor, which looks like "dn:<DN>" where null <DN> is for anonymous. */ - if ( NULL == *subjectndn || strlen (*subjectndn) < 3 || + subjectndnlen = strlen(*subjectndn); + if ( NULL == *subjectndn || subjectndnlen < 3 || strncasecmp ( "dn:", *subjectndn, 3 ) != 0 ) { aclutil_str_appened ( errbuf, "get-effective-rights: subject is not dnAuthzId" ); @@ -239,7 +265,8 @@ _ger_parse_control ( Slapi_PBlock *pb, char **subjectndn, int *iscritical, char return LDAP_INVALID_SYNTAX; } - strcpy ( *subjectndn, *subjectndn + 3 ); + /* memmove is safe for overlapping copy */ + memmove ( *subjectndn, *subjectndn + 3, subjectndnlen - 2);/* 1 for '\0' */ slapi_dn_normalize ( *subjectndn ); return LDAP_SUCCESS; } @@ -533,6 +560,27 @@ _ger_get_attr_rights ( return attrrights; } +#define GER_GET_ATTR_RIGHTS(attrs) \ + for (thisattr = (attrs); thisattr && *thisattr; thisattr++) \ + { \ + _ger_get_attr_rights (gerpb, e, subjectndn, *thisattr, \ + gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf); \ + isfirstattr = 0; \ + } \ + +#define GER_GET_ATTR_RIGHTA_EXT(c, inattrs, exattrs); \ + for ( i = 0; attrs[i]; i++ ) \ + { \ + if ((c) != *attrs[i] && charray_inlist((inattrs), attrs[i]) && \ + !charray_inlist((exattrs), attrs[i])) \ + { \ + _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], \ + gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); \ + isfirstattr = 0; \ + } \ + } + + void _ger_get_attrs_rights ( Slapi_PBlock *gerpb, @@ -552,12 +600,76 @@ _ger_get_attrs_rights ( if (attrs && *attrs) { - int i; - for ( i = 0; attrs[i]; i++ ) + int i = 0; + char **allattrs = NULL; + char **opattrs = NULL; + char **myattrs = NULL; + char **thisattr = NULL; + int hasstar = charray_inlist(attrs, "*"); + int hasplus = charray_inlist(attrs, "+"); + Slapi_Attr *objclasses = NULL; + Slapi_ValueSet *objclassvals = NULL; + + /* get all attrs available for the entry */ + slapi_entry_attr_find(e, "objectclass", &objclasses); + if (NULL != objclasses) { + Slapi_Value *v; + slapi_attr_get_valueset(objclasses, &objclassvals); + i = slapi_valueset_first_value(objclassvals, &v); + if (-1 != i) { + allattrs = slapi_schema_list_objectclass_attributes( + (const char *)v->bv.bv_val, + SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); + /* add "aci" to the allattrs to adjust to do_search */ + charray_add(&allattrs, slapi_attr_syntax_normalize("aci")); + while (-1 != i) + { + i = slapi_valueset_next_value(objclassvals, i, &v); + if (-1 != i) + { + myattrs = slapi_schema_list_objectclass_attributes( + (const char *)v->bv.bv_val, + SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); + charray_merge_nodup(&allattrs, myattrs, 1/*copy_strs*/); + charray_free(myattrs); + } + } + } + } + + /* get operational attrs */ + opattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_OPATTR); + + if (hasstar && hasplus) + { + GER_GET_ATTR_RIGHTS(allattrs); + GER_GET_ATTR_RIGHTS(opattrs); + } + else if (hasstar) + { + GER_GET_ATTR_RIGHTS(allattrs); + GER_GET_ATTR_RIGHTA_EXT('*', opattrs, allattrs); + } + else if (hasplus) { - _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); - isfirstattr = 0; + GER_GET_ATTR_RIGHTS(opattrs); + GER_GET_ATTR_RIGHTA_EXT('+', allattrs, opattrs); } + else + { + for ( i = 0; attrs[i]; i++ ) + { + if (charray_inlist(allattrs, attrs[i]) || + charray_inlist(opattrs, attrs[i])) + { + _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], + gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); + isfirstattr = 0; + } + } + } + charray_free(allattrs); + charray_free(opattrs); } else { @@ -569,7 +681,8 @@ _ger_get_attrs_rights ( if ( ! slapi_attr_flag_is_set (attr, SLAPI_ATTR_FLAG_OPATTR) ) { slapi_attr_get_type ( attr, &type ); - _ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); + _ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr, + gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } prevattr = attr; @@ -648,6 +761,131 @@ bailout: } int +_ger_generate_template_entry ( + Slapi_PBlock *pb + ) +{ + Slapi_Entry *e = NULL; + char **gerattrs = NULL; + char **attrs = NULL; + char *templateentry = NULL; + char *object = NULL; + char *superior = NULL; + char *p = 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_error (SLAPI_LOG_FATAL, plugin_name, + "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; + } + attrs = slapi_schema_list_objectclass_attributes( + (const char *)object, SLAPI_OC_FLAG_REQUIRED); + 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>: dummy\n\0 */ + siz += strlen(attrs[i]) + 4 + 5; + } + } + siz += 32 + strlen(object); /* dn: cn=<template_name>\n\0 */ + templateentry = (char *)slapi_ch_malloc(siz); + PR_snprintf(templateentry, siz, + "dn: cn=template_%s_objectclass\n", 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: dummy\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); + } + 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; +} + +int acl_get_effective_rights ( Slapi_PBlock *pb, Slapi_Entry *e, /* target entry */ @@ -664,10 +902,20 @@ acl_get_effective_rights ( size_t gerstrsize = 0; size_t gerstrcap = 0; int iscritical = 1; - int rc; + int rc = LDAP_SUCCESS; *errbuf = '\0'; + if (NULL == e) /* create a template entry from SLAPI_SEARCH_GERATTRS */ + { + rc = _ger_generate_template_entry ( pb ); + slapi_pblock_get ( pb, SLAPI_SEARCH_RESULT_ENTRY, &e ); + if ( rc != LDAP_SUCCESS || NULL == e ) + { + goto bailout; + } + } + /* * Get the subject */ @@ -681,7 +929,7 @@ acl_get_effective_rights ( * The requestor should have g permission on the entry * to get the effective rights. */ - rc = _ger_g_permission_granted (pb, e, errbuf); + rc = _ger_g_permission_granted (pb, e, subjectndn, errbuf); if ( rc != LDAP_SUCCESS ) { goto bailout; @@ -718,7 +966,7 @@ bailout: slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name, "###### Effective Rights on Entry (%s) for Subject (%s) ######\n", - slapi_entry_get_ndn (e), subjectndn); + e?slapi_entry_get_ndn(e):"null", subjectndn?subjectndn:"null"); slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name, "%s\n", gerstr); /* Restore pb */ diff --git a/ldap/servers/plugins/chainingdb/cb_config.c b/ldap/servers/plugins/chainingdb/cb_config.c index f2846b49..f95723ff 100644 --- a/ldap/servers/plugins/chainingdb/cb_config.c +++ b/ldap/servers/plugins/chainingdb/cb_config.c @@ -477,7 +477,8 @@ cb_config_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr } else if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) { charray_remove(cb->config.chaining_components, - slapi_dn_normalize(slapi_ch_strdup(config_attr_value))); + slapi_dn_normalize(slapi_ch_strdup(config_attr_value)), + 0 /* freeit */); } } if (NULL == mods[i]->mod_bvalues) { @@ -513,7 +514,8 @@ cb_config_modify_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entr if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) { charray_remove(cb->config.chainable_components, slapi_dn_normalize(slapi_ch_strdup(config_attr_value) -)); +), + 0 /* freeit */); } } if (NULL == mods[i]->mod_bvalues) { diff --git a/ldap/servers/plugins/chainingdb/cb_controls.c b/ldap/servers/plugins/chainingdb/cb_controls.c index 3c79f1cc..ca64595c 100644 --- a/ldap/servers/plugins/chainingdb/cb_controls.c +++ b/ldap/servers/plugins/chainingdb/cb_controls.c @@ -91,7 +91,7 @@ cb_unregister_supported_control( cb_backend * cb, char *controloid, unsigned lon return; } if ( controlops == 0 ) { - charray_remove(cb->config.forward_ctrls,controloid); + charray_remove(cb->config.forward_ctrls,controloid,0/* free it */); } PR_RWLock_Unlock(cb->config.rwl_config_lock); } diff --git a/ldap/servers/plugins/chainingdb/cb_instance.c b/ldap/servers/plugins/chainingdb/cb_instance.c index 91da2aab..13791c0c 100644 --- a/ldap/servers/plugins/chainingdb/cb_instance.c +++ b/ldap/servers/plugins/chainingdb/cb_instance.c @@ -392,7 +392,8 @@ int cb_instance_modify_config_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor } else if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) { charray_remove(inst->illegal_attributes, - slapi_ch_strdup(config_attr_value)); + slapi_ch_strdup(config_attr_value), + 0 /* freeit */); } } if (NULL == mods[i]->mod_bvalues) { @@ -426,7 +427,8 @@ int cb_instance_modify_config_callback(Slapi_PBlock *pb, Slapi_Entry* entryBefor } else if ( (mods[i]->mod_op & ~LDAP_MOD_BVALUES) == LDAP_MOD_DELETE) { charray_remove(inst->chaining_components, - slapi_dn_normalize(slapi_ch_strdup(config_attr_value))); + slapi_dn_normalize(slapi_ch_strdup(config_attr_value)), + 0 /* freeit */); } } if (NULL == mods[i]->mod_bvalues) { diff --git a/ldap/servers/plugins/schema_reload/schema_reload.c b/ldap/servers/plugins/schema_reload/schema_reload.c index d4661f19..ac389cbb 100644 --- a/ldap/servers/plugins/schema_reload/schema_reload.c +++ b/ldap/servers/plugins/schema_reload/schema_reload.c @@ -214,10 +214,10 @@ schemareload_add(Slapi_PBlock *pb, Slapi_Entry *e, { PRThread *thread = NULL; const char *cn; + const char *schemadir = NULL; int rv = SLAPI_DSE_CALLBACK_OK; Slapi_PBlock *mypb = NULL; Slapi_Task *task = NULL; - char *schemadir = NULL; *returncode = LDAP_SUCCESS; if ((cn = fetch_attr(e, "cn", NULL)) == NULL) { diff --git a/ldap/servers/slapd/charray.c b/ldap/servers/slapd/charray.c index 64dc1976..2f97f4d1 100644 --- a/ldap/servers/slapd/charray.c +++ b/ldap/servers/slapd/charray.c @@ -118,6 +118,48 @@ charray_merge( (*a)[n + nn] = NULL; } +/* + * charray_merge_nodup: + * merge a string array (second arg) into the first string array + * unless the each string is in the first string array. + */ +void +charray_merge_nodup( + char ***a, + char **s, + int copy_strs +) +{ + int i, j, n, nn; + char **dupa; + + if ( (s == NULL) || (s[0] == NULL) ) + return; + + for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) { + ; /* NULL */ + } + for ( nn = 0; s[nn] != NULL; nn++ ) { + ; /* NULL */ + } + + dupa = (char **)slapi_ch_calloc(1, (n+nn+1) * sizeof(char *)); + memcpy(dupa, *a, sizeof(char *) * n); + slapi_ch_free((void **)a); + + for ( i = 0, j = 0; i < nn; i++ ) { + if (!charray_inlist(dupa, s[i])) { /* skip if s[i] is already in *a */ + if ( copy_strs ) { + dupa[n+j] = slapi_ch_strdup( s[i] ); + } else { + dupa[n+j] = s[i]; + } + j++; + } + } + *a = dupa; +} + /* Routines which don't pound on malloc. Don't interchange the arrays with the * regular calls---they can end up freeing non-heap memory, which is wrong */ @@ -337,13 +379,15 @@ charray_print( char **a ) * Remove the char string from the array of char strings. * Performs a case *insensitive* comparison! * Just shunts the strings down to cover the deleted string. - * Doesn't free up the unused memory. + * freeit: none zero -> free the found string + * : zero -> Doesn't free up the unused memory. * Returns 1 if the entry found and removed, 0 if not. */ int charray_remove( char **a, - const char *s + const char *s, + int freeit ) { int i; @@ -353,6 +397,10 @@ charray_remove( if ( !found && strcasecmp (a[i],s) == 0 ) { found= 1; + if (freeit) + { + slapi_ch_free_string(&a[i]); + } } if (found) { diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c index b9aec66a..6c81b5c2 100644 --- a/ldap/servers/slapd/opshared.c +++ b/ldap/servers/slapd/opshared.c @@ -953,67 +953,188 @@ iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries) int rc; int attrsonly; int done = 0; - Slapi_Entry *e; + Slapi_Entry *e = NULL; char **attrs = NULL; slapi_pblock_get(pb, SLAPI_SEARCH_ATTRS, &attrs); slapi_pblock_get(pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly); - *pnentries = 0; + *pnentries = 0; while (!done) - { - rc = be->be_next_search_entry(pb); - if (rc < 0) - { - /* - * Some exceptional condition occurred. Results have been sent, so we're finished. - */ - if (rc == SLAPI_FAIL_DISKFULL) - { - operation_out_of_disk_space(); - } - return -1; - } - else - { - slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e); - if (e == NULL) - { - /* no more entries */ - done = 1; - continue; - } - } + { + Slapi_Entry *gerentry = NULL; + Slapi_Operation *operation; - if (process_entry(pb, e, send_result)) - { - /* shouldn't send this entry */ - continue; - } + rc = be->be_next_search_entry(pb); + if (rc < 0) + { + /* + * Some exceptional condition occurred. Results have been sent, so we're finished. + */ + if (rc == SLAPI_FAIL_DISKFULL) + { + operation_out_of_disk_space(); + } + return -1; + } - /* - * It's a regular entry, or it's a referral and - * managedsait control is on. In either case, send - * the entry. - */ - switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly)) - { - case 0: /* entry sent ok */ - (*pnentries)++; - slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries); - break; - case 1: /* entry not sent */ - break; - case -1: /* connection closed */ - /* - * mark the operation as abandoned so the backend - * next entry function gets called again and has - * a chance to clean things up. - */ - pb->pb_op->o_status = SLAPI_OP_STATUS_ABANDONED; - break; - } + slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e); + + /* Check for possible get_effective_rights control */ + slapi_pblock_get (pb, SLAPI_OPERATION, &operation); + if ( operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS ) + { + char *errbuf = NULL; + char **gerattrs = NULL; + char **gerattrsdup = NULL; + char **gap = NULL; + char *gapnext = NULL; + + slapi_pblock_get( pb, SLAPI_SEARCH_GERATTRS, &gerattrs ); + + gerattrsdup = cool_charray_dup(gerattrs); + gap = gerattrsdup; + do + { + gapnext = NULL; + if (gap) + { + if (*gap && *(gap+1)) + { + gapnext = *(gap+1); + *(gap+1) = NULL; + } + slapi_pblock_set( pb, SLAPI_SEARCH_GERATTRS, gap ); + rc = plugin_call_acl_plugin (pb, e, attrs, NULL, + SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS, + &errbuf); + if (NULL != gapnext) + { + *(gap+1) = gapnext; + } + } + else if (NULL != e) + { + rc = plugin_call_acl_plugin (pb, e, attrs, NULL, + SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS, + &errbuf); + } + if (NULL == e) { + /* get the template entry, if any */ + slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e); + if (NULL == e) { + /* everything is ok - don't send the result */ + return 1; + } + gerentry = e; + } + if ( rc != LDAP_SUCCESS ) { + /* Send error result and + abort op if the control is critical */ + LDAPDebug( LDAP_DEBUG_ANY, + "Failed to get effective rights for entry (%s), rc=%d\n", + slapi_entry_get_dn_const(e), rc, 0 ); + send_ldap_result( pb, rc, NULL, errbuf, 0, NULL ); + slapi_ch_free ( (void**)&errbuf ); + if (gerentry) + { + slapi_pblock_set(pb, + SLAPI_SEARCH_RESULT_ENTRY, NULL); + slapi_entry_free(gerentry); + gerentry = e = NULL; + } + return( -1 ); + } + slapi_ch_free ( (void**)&errbuf ); + if (process_entry(pb, e, send_result)) + { + /* shouldn't send this entry */ + if (gerentry) + { + slapi_pblock_set(pb, + SLAPI_SEARCH_RESULT_ENTRY, NULL); + slapi_entry_free(gerentry); + gerentry = e = NULL; + } + continue; + } + + /* + * It's a regular entry, or it's a referral and + * managedsait control is on. In either case, send + * the entry. + */ + switch (send_ldap_search_entry(pb, e, + NULL, attrs, attrsonly)) + { + case 0: /* entry sent ok */ + (*pnentries)++; + slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries); + break; + case 1: /* entry not sent */ + break; + case -1: /* connection closed */ + /* + * mark the operation as abandoned so the backend + * next entry function gets called again and has + * a chance to clean things up. + */ + pb->pb_op->o_status = SLAPI_OP_STATUS_ABANDONED; + break; + } + if (gerentry) + { + slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL); + slapi_entry_free(gerentry); + gerentry = e = NULL; + } + } + while (gap && ++gap && *gap); + slapi_pblock_set( pb, SLAPI_SEARCH_GERATTRS, gerattrs ); + cool_charray_free(gerattrsdup); + if (NULL == e) + { + /* no more entries */ + done = 1; + } + } + else if (e) + { + if (process_entry(pb, e, send_result)) + { + /* shouldn't send this entry */ + continue; + } + + /* + * It's a regular entry, or it's a referral and + * managedsait control is on. In either case, send + * the entry. + */ + switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly)) + { + case 0: /* entry sent ok */ + (*pnentries)++; + slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries); + break; + case 1: /* entry not sent */ + break; + case -1: /* connection closed */ + /* + * mark the operation as abandoned so the backend + * next entry function gets called again and has + * a chance to clean things up. + */ + pb->pb_op->o_status = SLAPI_OP_STATUS_ABANDONED; + break; + } + } + else + { + /* no more entries */ + done = 1; + } } return 1; diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c index ae98dc23..987b2476 100644 --- a/ldap/servers/slapd/pblock.c +++ b/ldap/servers/slapd/pblock.c @@ -1231,6 +1231,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value ) (*(char ***)value) = pblock->pb_op->o_params.p.p_search.search_attrs; } break; + case SLAPI_SEARCH_GERATTRS: + if(pblock->pb_op!=NULL) + { + (*(char ***)value) = pblock->pb_op->o_params.p.p_search.search_gerattrs; + } + break; case SLAPI_SEARCH_ATTRSONLY: if(pblock->pb_op!=NULL) { @@ -2509,6 +2515,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value ) pblock->pb_op->o_params.p.p_search.search_attrs = (char **) value; } break; + case SLAPI_SEARCH_GERATTRS: + if(pblock->pb_op!=NULL) + { + pblock->pb_op->o_params.p.p_search.search_gerattrs = (char **) value; + } + break; case SLAPI_SEARCH_ATTRSONLY: if(pblock->pb_op!=NULL) { diff --git a/ldap/servers/slapd/result.c b/ldap/servers/slapd/result.c index 31c839d1..49331dce 100644 --- a/ldap/servers/slapd/result.c +++ b/ldap/servers/slapd/result.c @@ -1203,14 +1203,15 @@ send_ldap_search_entry_ext( int *dontsendattr= NULL; Slapi_Operation *operation; int real_attrs_only = 0; - LDAPControl **ctrlp = 0; + LDAPControl **ctrlp = 0; + Slapi_Entry *gerentry = NULL; slapi_pblock_get (pb, SLAPI_OPERATION, &operation); LDAPDebug( LDAP_DEBUG_TRACE, "=> send_ldap_search_entry (%s)\n", - slapi_entry_get_dn_const(e), 0, 0 ); + e?slapi_entry_get_dn_const(e):"null", 0, 0 ); - if ( conn == NULL ) { + if ( conn == NULL && e ) { if ( op->o_search_entry_handler != NULL ) { if (( rc = (*op->o_search_entry_handler)( pb->pb_backend, conn, op, e )) == 0 ) { @@ -1224,7 +1225,7 @@ send_ldap_search_entry_ext( } #if !defined(DISABLE_ACL_CHECK) - if ( plugin_call_acl_plugin (pb, e, attrs, NULL, + if ( e && plugin_call_acl_plugin (pb, e, attrs, NULL, SLAPI_ACL_READ, ACLPLUGIN_ACCESS_READ_ON_ENTRY, NULL ) != LDAP_SUCCESS ) { LDAPDebug( LDAP_DEBUG_ACL, "acl: access to entry not allowed\n", 0, 0, 0 ); @@ -1232,21 +1233,8 @@ send_ldap_search_entry_ext( } #endif - /* Check for possible get_effective_rights control */ - if ( operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS ) { - char *errbuf = NULL; - rc = plugin_call_acl_plugin (pb, e, attrs, NULL, SLAPI_ACL_ALL, - ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS, &errbuf); - if ( rc != LDAP_SUCCESS ) { - LDAPDebug( LDAP_DEBUG_ANY, - "Failed to get effective rights for entry (%s), rc=%d\n", - slapi_entry_get_dn_const(e), rc, 0 ); - /* Send error result and abort op if the control is critical */ - send_ldap_result( pb, rc, NULL, errbuf, 0, NULL ); - slapi_ch_free ( (void**)&errbuf ); - return( -1 ); - } - slapi_ch_free ( (void**)&errbuf ); + if (NULL == e) { + return 1; /* everything is ok - don't send the result */ } if ( (ber = der_alloc()) == NULL ) { @@ -1454,6 +1442,10 @@ log_and_return: } } + if (gerentry) + { + slapi_entry_free(gerentry); + } LDAPDebug( LDAP_DEBUG_TRACE, "<= send_ldap_search_entry\n", 0, 0, 0 ); exit: return( rc ); diff --git a/ldap/servers/slapd/schema.c b/ldap/servers/slapd/schema.c index d116e340..b8e154af 100644 --- a/ldap/servers/slapd/schema.c +++ b/ldap/servers/slapd/schema.c @@ -641,41 +641,41 @@ static int oc_check_required( Slapi_PBlock *pb, Slapi_Entry *e, struct objclass *oc ) { int i; - int rc = 0; /* success, by default */ + int rc = 0; /* success, by default */ Slapi_Attr *a; if (oc == NULL || oc->oc_required == NULL || oc->oc_required[0] == NULL) { - return 0; /* success, as none required */ + return 0; /* success, as none required */ } /* for each required attribute */ for ( i = 0; oc->oc_required[i] != NULL; i++ ) { /* see if it's in the entry */ for ( a = e->e_attrs; a != NULL; a = a->a_next ) { - if ( slapi_attr_type_cmp( oc->oc_required[i], a->a_type, - SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) { - break; - } - } - - /* not there => schema violation */ - if ( a == NULL ) { - char errtext[ BUFSIZ ]; - char ebuf[ BUFSIZ ]; - LDAPDebug( LDAP_DEBUG_ANY, - "Entry \"%s\" missing attribute \"%s\" required" - " by object class \"%s\"\n", - escape_string( slapi_entry_get_dn_const(e), ebuf ), - oc->oc_required[i], oc->oc_name); - if (pb) { - PR_snprintf( errtext, sizeof( errtext ), - "missing attribute \"%s\" required" - " by object class \"%s\"\n", - oc->oc_required[i], oc->oc_name ); - slapi_pblock_set( pb, SLAPI_PB_RESULT_TEXT, errtext ); - } - rc = 1; /* failure */ - } + if ( slapi_attr_type_cmp( oc->oc_required[i], a->a_type, + SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) { + break; + } + } + + /* not there => schema violation */ + if ( a == NULL ) { + char errtext[ BUFSIZ ]; + char ebuf[ BUFSIZ ]; + LDAPDebug( LDAP_DEBUG_ANY, + "Entry \"%s\" missing attribute \"%s\" required" + " by object class \"%s\"\n", + escape_string( slapi_entry_get_dn_const(e), ebuf ), + oc->oc_required[i], oc->oc_name); + if (pb) { + PR_snprintf( errtext, sizeof( errtext ), + "missing attribute \"%s\" required" + " by object class \"%s\"\n", + oc->oc_required[i], oc->oc_name ); + slapi_pblock_set( pb, SLAPI_PB_RESULT_TEXT, errtext ); + } + rc = 1; /* failure */ + } } return rc; @@ -1392,8 +1392,8 @@ schema_list_attributes_callback(struct asyntaxinfo *asi, void *arg) } /* Return the list of attributes names matching attribute flags */ - -char ** slapi_schema_list_attribute_names(unsigned long flag) +char ** +slapi_schema_list_attribute_names(unsigned long flag) { struct listargs aew; memset(&aew,0,sizeof(struct listargs)); @@ -4966,3 +4966,69 @@ slapi_reload_schema_files(char *schemadir) return LDAP_LOCAL_ERROR; } } + +/* + * slapi_schema_list_objectclass_attributes: + * Return the list of attributes belonging to the objectclass + * + * The caller is responsible to free the returned list with charray_free. + * flags: one of them or both: + * SLAPI_OC_FLAG_REQUIRED + * SLAPI_OC_FLAG_ALLOWED + */ +char ** +slapi_schema_list_objectclass_attributes(const char *ocname_or_oid, + PRUint32 flags) +{ + struct objclass *oc = NULL; + char **attrs = NULL; + PRUint32 mask = SLAPI_OC_FLAG_REQUIRED | SLAPI_OC_FLAG_ALLOWED; + + if (!flags) { + return attrs; + } + + oc_lock_read(); + oc = oc_find_nolock(ocname_or_oid); + if (oc) { + switch (flags & mask) { + case SLAPI_OC_FLAG_REQUIRED: + attrs = charray_dup(oc->oc_required); + break; + case SLAPI_OC_FLAG_ALLOWED: + attrs = charray_dup(oc->oc_allowed); + break; + case SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED: + attrs = charray_dup(oc->oc_required); + charray_merge(&attrs, oc->oc_allowed, 1/*copy_strs*/); + break; + default: + slapi_log_error( SLAPI_LOG_FATAL, "list objectclass attributes", + "flag 0x%x not supported\n", flags ); + break; + } + } + oc_unlock(); + return attrs; +} + +/* + * slapi_schema_get_superior_name: + * Return the name of the superior objectclass + * + * The caller is responsible to free the returned name + */ +char * +slapi_schema_get_superior_name(const char *ocname_or_oid) +{ + struct objclass *oc = NULL; + char *superior = NULL; + + oc_lock_read(); + oc = oc_find_nolock(ocname_or_oid); + if (oc) { + superior = slapi_ch_strdup(oc->oc_superior); + } + oc_unlock(); + return superior; +} diff --git a/ldap/servers/slapd/search.c b/ldap/servers/slapd/search.c index dcd8265c..c3d1c80d 100644 --- a/ldap/servers/slapd/search.c +++ b/ldap/servers/slapd/search.c @@ -65,92 +65,93 @@ void do_search( Slapi_PBlock *pb ) { Slapi_Operation *operation; - BerElement *ber; - int i, err, attrsonly; - ber_int_t scope, deref, sizelimit, timelimit; - char *base = NULL, *fstr = NULL; - struct slapi_filter *filter = NULL; - char **attrs = NULL; - int psearch = 0; - struct berval *psbvp; - ber_int_t changetypes; + BerElement *ber; + int i, err, attrsonly; + ber_int_t scope, deref, sizelimit, timelimit; + char *base = NULL, *fstr = NULL; + struct slapi_filter *filter = NULL; + char **attrs = NULL; + char **gerattrs = NULL; + int psearch = 0; + struct berval *psbvp; + ber_int_t changetypes; int send_entchg_controls; int changesonly = 0; int rc = -1; char *original_base = 0; char *new_base = 0; - LDAPDebug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 ); + LDAPDebug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 ); slapi_pblock_get( pb, SLAPI_OPERATION, &operation); - ber = operation->o_ber; + ber = operation->o_ber; - /* count the search request */ - snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsSearchOps); + /* count the search request */ + snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsSearchOps); - /* - * Parse the search request. It looks like this: - * - * SearchRequest := [APPLICATION 3] SEQUENCE { - * baseObject DistinguishedName, - * scope ENUMERATED { - * baseObject (0), - * singleLevel (1), - * wholeSubtree (2) - * }, - * derefAliases ENUMERATED { - * neverDerefaliases (0), - * derefInSearching (1), - * derefFindingBaseObj (2), - * alwaysDerefAliases (3) - * }, - * sizelimit INTEGER (0 .. 65535), - * timelimit INTEGER (0 .. 65535), - * attrsOnly BOOLEAN, - * filter Filter, - * attributes SEQUENCE OF AttributeType - * } - */ + /* + * Parse the search request. It looks like this: + * + * SearchRequest := [APPLICATION 3] SEQUENCE { + * baseObject DistinguishedName, + * scope ENUMERATED { + * baseObject (0), + * singleLevel (1), + * wholeSubtree (2) + * }, + * derefAliases ENUMERATED { + * neverDerefaliases (0), + * derefInSearching (1), + * derefFindingBaseObj (2), + * alwaysDerefAliases (3) + * }, + * sizelimit INTEGER (0 .. 65535), + * timelimit INTEGER (0 .. 65535), + * attrsOnly BOOLEAN, + * filter Filter, + * attributes SEQUENCE OF AttributeType + * } + */ - /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */ - if ( ber_scanf( ber, "{aiiiib", &base, &scope, &deref, &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ){ - slapi_ch_free((void**)&base ); - log_search_access (pb, "???", -1, "???", "decoding error"); - send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL ); - return; - } + /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */ + if ( ber_scanf( ber, "{aiiiib", &base, &scope, &deref, &sizelimit, &timelimit, &attrsonly ) == LBER_ERROR ){ + slapi_ch_free((void**)&base ); + log_search_access (pb, "???", -1, "???", "decoding error"); + send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL ); + return; + } - /* - * ignore negative time and size limits since they make no sense - */ - if ( timelimit < 0 ) { + /* + * ignore negative time and size limits since they make no sense + */ + if ( timelimit < 0 ) { timelimit = 0; - } - if ( sizelimit < 0 ) { + } + if ( sizelimit < 0 ) { sizelimit = 0; - } + } - if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL + if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL && scope != LDAP_SCOPE_SUBTREE ) { log_search_access (pb, base, scope, "???", "Unknown search scope"); - send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, + send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "Unknown search scope", 0, NULL ); - goto free_and_return; - } - /* check and record the scope for snmp */ - if ( scope == LDAP_SCOPE_ONELEVEL) { + goto free_and_return; + } + /* check and record the scope for snmp */ + if ( scope == LDAP_SCOPE_ONELEVEL) { /* count the one level search request */ snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps); - } else if (scope == LDAP_SCOPE_SUBTREE) { + } else if (scope == LDAP_SCOPE_SUBTREE) { /* count the subtree search request */ snmp_increment_counter(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps); - } + } - /* filter - returns a "normalized" version */ - filter = NULL; - fstr = NULL; - if ( (err = get_filter( pb->pb_conn, ber, scope, &filter, &fstr )) != 0 ) { + /* filter - returns a "normalized" version */ + filter = NULL; + fstr = NULL; + if ( (err = get_filter( pb->pb_conn, ber, scope, &filter, &fstr )) != 0 ) { char *errtxt; if ( LDAP_UNWILLING_TO_PERFORM == err ) { @@ -159,18 +160,18 @@ do_search( Slapi_PBlock *pb ) errtxt = "Bad search filter"; } log_search_access( pb, base, scope, "???", errtxt ); - send_ldap_result( pb, err, NULL, errtxt, 0, NULL ); - goto free_and_return; - } + send_ldap_result( pb, err, NULL, errtxt, 0, NULL ); + goto free_and_return; + } - /* attributes */ - attrs = NULL; - if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) { + /* attributes */ + attrs = NULL; + if ( ber_scanf( ber, "{v}}", &attrs ) == LBER_ERROR ) { log_search_access (pb, base, scope, fstr, "decoding error"); - send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, + send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL ); - goto free_and_return; - } + goto free_and_return; + } /* * This search is performed against the legacy consumer, so ask explicitly @@ -186,56 +187,128 @@ do_search( Slapi_PBlock *pb ) charray_add(&attrs, slapi_attr_syntax_normalize("aci")); charray_add(&attrs, slapi_attr_syntax_normalize(LDAP_ALL_USER_ATTRS)); } - else + } + + if ( attrs != NULL ) { + int gerattrsiz = 1; + int gerattridx = 0; + int aciin = 0; + /* + * . store gerattrs if any + * . add "aci" once if "*" is given + */ + for ( i = 0; attrs[i] != NULL; i++ ) { - for ( i = 0; attrs[i] != NULL; i++ ) + char *p = NULL; + /* check if @<objectclass> is included */ + p = strchr(attrs[i], '@'); + if ( p && '\0' != *(p+1) ) /* don't store "*@", e.g. */ { - if ( strcasecmp(attrs[i], LDAP_ALL_USER_ATTRS) == 0 ) + int j = 0; + if (gerattridx + 1 >= gerattrsiz) + { + char **tmpgerattrs; + gerattrsiz *= 2; + tmpgerattrs = + (char **)slapi_ch_calloc(1, gerattrsiz*sizeof(char *)); + if (NULL != gerattrs) + { + memcpy(tmpgerattrs, gerattrs, gerattrsiz*sizeof(char *)); + slapi_ch_free((void **)&gerattrs); + } + gerattrs = tmpgerattrs; + } + for ( j = 0; gerattrs; j++ ) { - charray_add(&attrs, slapi_attr_syntax_normalize("aci")); - break; + char *attri = NULL; + if ( NULL == gerattrs[j] ) + { + if (0 == j) + { + /* first time */ + gerattrs[gerattridx++] = attrs[i]; + /* get rid of "@<objectclass>" part from the attr + list, which is needed only in gerattr list */ + *p = '\0'; + attri = slapi_ch_strdup(attrs[i]); + attrs[i] = attri; + *p = '@'; + } + else + { + break; /* done */ + } + } + else if ( 0 == strcasecmp( attrs[i], gerattrs[j] )) + { + /* skip if attrs[i] is already in gerattrs */ + continue; + } + else + { + char *q = strchr(gerattrs[j], '@'); /* q never be 0 */ + if ( 0 != strcasecmp( p+1, q+1 )) + { + /* you don't want to display the same template + entry multiple times */ + gerattrs[gerattridx++] = attrs[i]; + } + /* get rid of "@<objectclass>" part from the attr + list, which is needed only in gerattr list */ + *p = '\0'; + attri = slapi_ch_strdup(attrs[i]); + attrs[i] = attri; + *p = '@'; + } } } + else if ( !aciin && strcasecmp(attrs[i], LDAP_ALL_USER_ATTRS) == 0 ) + { + charray_add(&attrs, slapi_attr_syntax_normalize("aci")); + aciin = 1; + } + } + if (NULL != gerattrs) + { + gerattrs[gerattridx] = NULL; } - } - if ( attrs != NULL ) { - operation->o_searchattrs = cool_charray_dup( attrs ); - for ( i = 0; attrs[i] != NULL; i++ ) { - char *type; + operation->o_searchattrs = cool_charray_dup( attrs ); + for ( i = 0; attrs[i] != NULL; i++ ) { + char *type; - type = slapi_attr_syntax_normalize(attrs[i]); - slapi_ch_free( (void**)&(attrs[i]) ); - attrs[i] = type; - } - } - if ( slapd_ldap_debug & LDAP_DEBUG_ARGS ) { - char abuf[ 1024 ], *astr; + type = slapi_attr_syntax_normalize(attrs[i]); + slapi_ch_free( (void**)&(attrs[i]) ); + attrs[i] = type; + } + } + if ( slapd_ldap_debug & LDAP_DEBUG_ARGS ) { + char abuf[ 1024 ], *astr; - if ( NULL == attrs ) { - astr = "ALL"; - } else { - strarray2str( attrs, abuf, sizeof( abuf ), 1 /* include quotes */); - astr = abuf; + if ( NULL == attrs ) { + astr = "ALL"; + } else { + strarray2str( attrs, abuf, sizeof( abuf ), 1 /* include quotes */); + astr = abuf; + } + slapi_log_error( SLAPI_LOG_ARGS, NULL, "SRCH base=\"%s\" " + "scope=%d deref=%d " + "sizelimit=%d timelimit=%d attrsonly=%d filter=\"%s\" " + "attrs=%s\n", base, scope, deref, sizelimit, timelimit, + attrsonly, fstr, astr ); } - slapi_log_error( SLAPI_LOG_ARGS, NULL, "SRCH base=\"%s\" " - "scope=%d deref=%d " - "sizelimit=%d timelimit=%d attrsonly=%d filter=\"%s\" " - "attrs=%s\n", base, scope, deref, sizelimit, timelimit, - attrsonly, fstr, astr ); - } - /* - * in LDAPv3 there can be optional control extensions on - * the end of an LDAPMessage. we need to read them in and - * pass them to the backend. get_ldapmessage_controls() - * reads the controls and sets any we know about in the pb. - */ - if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) { + /* + * in LDAPv3 there can be optional control extensions on + * the end of an LDAPMessage. we need to read them in and + * pass them to the backend. get_ldapmessage_controls() + * reads the controls and sets any we know about in the pb. + */ + if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 ) { log_search_access (pb, base, scope, fstr, "failed to decode LDAP controls"); - send_ldap_result( pb, err, NULL, NULL, 0, NULL ); - goto free_and_return; - } + send_ldap_result( pb, err, NULL, NULL, 0, NULL ); + goto free_and_return; + } /* we support persistent search for regular operations only */ if ( slapi_control_present( operation->o_params.request_controls, @@ -254,15 +327,16 @@ do_search( Slapi_PBlock *pb ) } } - slapi_pblock_set( pb, SLAPI_SEARCH_TARGET, base ); + slapi_pblock_set( pb, SLAPI_SEARCH_TARGET, base ); slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET_DN, slapi_ch_strdup(base) ); - slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE, &scope ); - slapi_pblock_set( pb, SLAPI_SEARCH_DEREF, &deref ); - slapi_pblock_set( pb, SLAPI_SEARCH_FILTER, filter ); - slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, fstr ); - slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS, attrs ); - slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly ); - slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &operation->o_isroot ); + slapi_pblock_set( pb, SLAPI_SEARCH_SCOPE, &scope ); + slapi_pblock_set( pb, SLAPI_SEARCH_DEREF, &deref ); + slapi_pblock_set( pb, SLAPI_SEARCH_FILTER, filter ); + slapi_pblock_set( pb, SLAPI_SEARCH_STRFILTER, fstr ); + slapi_pblock_set( pb, SLAPI_SEARCH_ATTRS, attrs ); + slapi_pblock_set( pb, SLAPI_SEARCH_GERATTRS, gerattrs ); + slapi_pblock_set( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly ); + slapi_pblock_set( pb, SLAPI_REQUESTOR_ISROOT, &operation->o_isroot ); slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit ); slapi_pblock_set( pb, SLAPI_SEARCH_TIMELIMIT, &timelimit ); @@ -277,23 +351,22 @@ do_search( Slapi_PBlock *pb ) slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &new_base); slapi_pblock_get (pb, SLAPI_PLUGIN_OPRETURN, &rc); - slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ); + slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ); - if ( psearch && rc == 0 ) { + if ( psearch && rc == 0 ) { ps_add( pb, changetypes, send_entchg_controls ); - } + } free_and_return:; - if ( !psearch || rc < 0 ) { + if ( !psearch || rc < 0 ) { if(original_base != new_base) { slapi_ch_free_string(&new_base); } - slapi_ch_free_string(&base); - slapi_ch_free_string(&fstr); - slapi_filter_free( filter, 1 ); - if ( attrs != NULL ) { - charray_free( attrs ); - } + slapi_ch_free_string(&base); + slapi_ch_free_string(&fstr); + slapi_filter_free( filter, 1 ); + charray_free( attrs ); /* passing NULL is fine */ + charray_free( gerattrs ); /* passing NULL is fine */ /* * Fix for defect 526719 / 553356 : Persistent search op failed. * Marking it as non-persistent so that operation resources get freed @@ -304,7 +377,7 @@ free_and_return:; /* we strdup'd this above - need to free */ slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET_DN, &base); slapi_ch_free_string(&base); - } + } } static void log_search_access (Slapi_PBlock *pb, const char *base, int scope, const char *fstr, const char *msg) diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index 26733b1f..92cac83c 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -72,6 +72,9 @@ extern "C" { #define SLAPI_OP_FLAG_NEVER_CHAIN 0x00800 /* Do not chain the operation */ #define SLAPI_OP_FLAG_NO_ACCESS_CHECK 0x10000 /* Do not check for access control - bypass them */ +#define SLAPI_OC_FLAG_REQUIRED 0x0001 +#define SLAPI_OC_FLAG_ALLOWED 0x0002 + /* * access control levels */ @@ -1703,6 +1706,7 @@ typedef struct slapi_plugindesc { #define SLAPI_SEARCH_FILTER 114 #define SLAPI_SEARCH_STRFILTER 115 #define SLAPI_SEARCH_ATTRS 116 +#define SLAPI_SEARCH_GERATTRS 1160 #define SLAPI_SEARCH_ATTRSONLY 117 #define SLAPI_SEARCH_IS_AND 118 diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h index 59e95d4a..8d16deee 100644 --- a/ldap/servers/slapd/slapi-private.h +++ b/ldap/servers/slapd/slapi-private.h @@ -574,6 +574,7 @@ typedef struct slapi_operation_parameters char **search_attrs; int search_attrsonly; int search_is_and; + char **search_gerattrs; } p_search; struct abandon_parameters @@ -726,6 +727,11 @@ struct slapi_componentid * plugin_get_default_component_id(); /* return the list of attr defined in the schema matching the attr flags */ char ** slapi_schema_list_attribute_names(unsigned long flag); +/* return the list of attributes belonging to the objectclass */ +char ** slapi_schema_list_objectclass_attributes(const char *ocname_or_oid, + PRUint32 flags); +char * slapi_schema_get_superior_name(const char *ocname_or_oid); + CSN *dup_global_schema_csn(); /* misc function for the chaining backend */ @@ -787,13 +793,14 @@ int slapi_config_get_readonly(); */ void charray_add( char ***a, char *s ); void charray_merge( char ***a, char **s, int copy_strs ); +void charray_merge_nodup( char ***a, char **s, int copy_strs ); void charray_free( char **array ); int charray_inlist( char **a, char *s ); int charray_utf8_inlist( char **a, char *s ); char ** charray_dup( char **a ); char ** str2charray( char *str, char *brkstr ); char ** str2charray_ext( char *str, char *brkstr, int allow_dups ); -int charray_remove(char **a,const char *s); +int charray_remove(char **a, const char *s, int freeit); char ** cool_charray_dup( char **a ); void cool_charray_free( char **array ); void charray_subtract( char **a, char **b, char ***c ); @@ -1124,10 +1131,6 @@ char* slapd_get_tmp_dir( void ); const char* escape_string (const char* str, char buf[BUFSIZ]); const char* escape_string_with_punctuation(const char* str, char buf[BUFSIZ]); const char* escape_filter_value(const char* str, int len, char buf[BUFSIZ]); -void charray_add( char ***a, char *s ); -void charray_free(char **array); -int charray_remove(char **a,const char *s); -int charray_inlist( char **a, char *s ); char *slapi_berval_get_string_copy(const struct berval *bval); |