/* * update one attribute value per _do_modify */ static int _update_one_per_mod(Slapi_DN *entrySDN, /* DN of the searched entry */ Slapi_Attr *attr, /* referred attribute */ char *attrName, Slapi_DN *origDN, /* original DN that was modified */ char *newRDN, /* new RDN from modrdn */ const char *newsuperior, /* new superior from modrdn */ Slapi_PBlock *mod_pb) { LDAPMod attribute1, attribute2; LDAPMod *list_of_mods[3]; char *values_del[2]; char *values_add[2]; char *newDN = NULL; char **dnParts = NULL; char *sval = NULL; char *newvalue = NULL; char *p = NULL; size_t dnlen = 0; int rc = 0; if (NULL == newRDN && NULL == newsuperior) { /* in delete mode */ /* delete old dn so set that up */ values_del[0] = (char *)slapi_sdn_get_dn(origDN); values_del[1] = NULL; attribute1.mod_type = attrName; attribute1.mod_op = LDAP_MOD_DELETE; attribute1.mod_values = values_del; list_of_mods[0] = &attribute1; /* terminate list of mods. */ list_of_mods[1] = NULL; rc = _do_modify(mod_pb, entrySDN, list_of_mods); if (rc) { slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "_update_one_value: entry %s: deleting \"%s: %s\" failed (%d)" "\n", slapi_sdn_get_dn(entrySDN), attrName, slapi_sdn_get_dn(origDN), rc); } } else { /* in modrdn mode */ const char *superior = NULL; int nval = 0; Slapi_Value *v = NULL; if (NULL == origDN) { slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "_update_one_value: NULL dn was passed\n"); goto bail; } /* need to put together rdn into a dn */ dnParts = slapi_ldap_explode_dn( slapi_sdn_get_dn(origDN), 0 ); if (NULL == dnParts) { slapi_log_error(SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "_update_one_value: failed to explode dn %s\n", slapi_sdn_get_dn(origDN)); goto bail; } if (NULL == newRDN) { newRDN = dnParts[0]; } if (newsuperior) { superior = newsuperior; } else { /* do not free superior */ superior = slapi_dn_find_parent(slapi_sdn_get_dn(origDN)); } /* newRDN and superior are already normalized. */ newDN = slapi_ch_smprintf("%s,%s", newRDN, superior); slapi_dn_ignore_case(newDN); /* * Compare the modified dn with the value of * the target attribute of referint to find out * the modified dn is the ancestor (case 2) or * the value itself (case 1). * * E.g., * (case 1) * modrdn: uid=A,ou=B,o=C --> uid=A',ou=B',o=C * (origDN) (newDN) * member: uid=A,ou=B,ou=C --> uid=A',ou=B',ou=C * (sval) (newDN) * * (case 2) * modrdn: ou=B,o=C --> ou=B',o=C * (origDN) (newDN) * member: uid=A,ou=B,ou=C --> uid=A,ou=B',ou=C * (sval) (sval' + newDN) */ for (nval = slapi_attr_first_value(attr, &v); nval != -1; nval = slapi_attr_next_value(attr, nval, &v)) { p = NULL; dnlen = 0; /* DN syntax, which should be a string */ sval = slapi_ch_strdup(slapi_value_get_string(v)); rc = slapi_dn_normalize_case_ext(sval, 0, &p, &dnlen); if (rc == 0) { /* sval is passed in; not terminated */ *(p + dnlen) = '\0'; sval = p; } else if (rc > 0) { slapi_ch_free_string(&sval); sval = p; } /* else: (rc < 0) Ignore the DN normalization error for now. */ p = PL_strstr(sval, slapi_sdn_get_ndn(origDN)); if (p == sval) { /* (case 1) */ values_del[0] = sval; values_del[1] = NULL; attribute1.mod_type = attrName; attribute1.mod_op = LDAP_MOD_DELETE; attribute1.mod_values = values_del; list_of_mods[0] = &attribute1; values_add[0] = newDN; values_add[1] = NULL; attribute2.mod_type = attrName; attribute2.mod_op = LDAP_MOD_ADD; attribute2.mod_values = values_add; list_of_mods[1] = &attribute2; list_of_mods[2] = NULL; rc = _do_modify(mod_pb, entrySDN, list_of_mods); if (rc) { slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "_update_one_value: entry %s: replacing \"%s: %s\" " "with \"%s: %s\" failed (%d)\n", slapi_sdn_get_dn(entrySDN), attrName, slapi_sdn_get_dn(origDN), attrName, newDN, rc); } } else if (p) { char bak; /* (case 2) */ values_del[0] = sval; values_del[1] = NULL; attribute1.mod_type = attrName; attribute1.mod_op = LDAP_MOD_DELETE; attribute1.mod_values = values_del; list_of_mods[0] = &attribute1; bak = *p; *p = '\0'; /* newRDN and superior are already normalized. */ newvalue = slapi_ch_smprintf("%s%s", sval, newDN); *p = bak; values_add[0]=newvalue; values_add[1]=NULL; attribute2.mod_type = attrName; attribute2.mod_op = LDAP_MOD_ADD; attribute2.mod_values = values_add; list_of_mods[1] = &attribute2; list_of_mods[2] = NULL; rc = _do_modify(mod_pb, entrySDN, list_of_mods); if (rc) { slapi_log_error( SLAPI_LOG_FATAL, REFERINT_PLUGIN_SUBSYSTEM, "_update_one_value: entry %s: replacing \"%s: %s\" " "with \"%s: %s\" failed (%d)\n", slapi_sdn_get_dn(entrySDN), attrName, sval, attrName, newvalue, rc); } slapi_ch_free_string(&newvalue); } /* else: value does not include the modified DN. Ignore it. */ slapi_ch_free_string(&sval); } /* cleanup memory allocated for dnParts and newDN */ if (dnParts){ slapi_ldap_value_free(dnParts); dnParts = NULL; } slapi_ch_free_string(&newDN); } bail: return rc; }
/* See if the given entry has an attribute with the given name and the given value; if value is NULL, just test for the presence of the given attribute; if value is an empty string (i.e. value[0] == 0), the first value in the attribute will be copied into the given buffer and returned */ static int entry_has_attr_and_value(Slapi_Entry *e, const char *attrname, char *value, size_t valuebufsize ) { int retval = 0; Slapi_Attr *attr = 0; if (!e || !attrname) return retval; /* see if the entry has the specified attribute name */ if (!slapi_entry_attr_find(e, attrname, &attr) && attr) { /* if value is not null, see if the attribute has that value */ if (!value) { retval = 1; } else { Slapi_Value *v = 0; int index = 0; for (index = slapi_attr_first_value(attr, &v); v && (index != -1); index = slapi_attr_next_value(attr, index, &v)) { const char *s = slapi_value_get_string(v); if (!s) continue; if (!*value) { size_t len = strlen(s); if ( len < valuebufsize ) { strcpy(value, s); retval = 1; } else { slapi_log_error( SLAPI_LOG_FATAL, "bootstrap config", "Ignoring extremely large value for" " configuration attribute %s" " (length=%ld, value=%40.40s...)\n", attrname, len, s ); retval = 0; /* value is too large: ignore it */ } break; } else if (!strcasecmp(s, value)) { retval = 1; break; } } } } return retval; }
void _ger_get_attrs_rights ( Slapi_PBlock *gerpb, Slapi_Entry *e, const char *subjectndn, char **attrs, char **gerstr, size_t *gerstrsize, size_t *gerstrcap, char **errbuf ) { int isfirstattr = 1; /* gerstr was initially allocated with enough space for one more line */ _append_gerstr(gerstr, gerstrsize, gerstrcap, "attributeLevelRights: ", NULL); /* * If it's stated attribute list is given, * the first attr in the list should not be empty. * Otherwise, it's considered the list is not given. */ if (attrs && *attrs && (strlen(*attrs) > 0)) { int i = 0; char **allattrs = NULL; char **opattrs = NULL; char **noexpattrs = NULL; /* attrs not to expose */ char **myattrs = NULL; char **thisattr = NULL; int hasstar = charray_inlist(attrs, "*"); int hasplus = charray_inlist(attrs, "+"); Slapi_Attr *objclasses = NULL; Slapi_ValueSet *objclassvals = NULL; int isextensibleobj = 0; /* get all attrs available for the entry */ slapi_entry_attr_find(e, "objectclass", &objclasses); if (NULL != objclasses) { Slapi_Value *v; slapi_attr_get_valueset(objclasses, &objclassvals); i = slapi_valueset_first_value(objclassvals, &v); if (-1 != i) { const char *ocname = NULL; allattrs = slapi_schema_list_objectclass_attributes( (const char *)v->bv.bv_val, SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); /* check if this entry is an extensble object or not */ ocname = slapi_value_get_string(v); if ( strcasecmp( ocname, "extensibleobject" ) == 0 ) { isextensibleobj = 1; } /* add "aci" to the allattrs to adjust to do_search */ charray_add(&allattrs, slapi_attr_syntax_normalize("aci")); while (-1 != i) { i = slapi_valueset_next_value(objclassvals, i, &v); if (-1 != i) { myattrs = slapi_schema_list_objectclass_attributes( (const char *)v->bv.bv_val, SLAPI_OC_FLAG_REQUIRED|SLAPI_OC_FLAG_ALLOWED); /* check if this entry is an extensble object or not */ ocname = slapi_value_get_string(v); if ( strcasecmp( ocname, "extensibleobject" ) == 0 ) { isextensibleobj = 1; } charray_merge_nodup(&allattrs, myattrs, 1/*copy_strs*/); charray_free(myattrs); } } } slapi_valueset_free(objclassvals); } /* get operational attrs */ opattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_OPATTR); noexpattrs = slapi_schema_list_attribute_names(SLAPI_ATTR_FLAG_NOEXPOSE); /* subtract no expose attrs from opattrs (e.g., unhashed pw) */ charray_subtract(opattrs, noexpattrs, NULL); if (isextensibleobj) { for ( i = 0; attrs[i]; i++ ) { if ('\0' == *attrs[i]) { continue; /* skip an empty attr */ } _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } } else { if (hasstar && hasplus) { GER_GET_ATTR_RIGHTS(allattrs); GER_GET_ATTR_RIGHTS(opattrs); } else if (hasstar) { GER_GET_ATTR_RIGHTS(allattrs); GER_GET_ATTR_RIGHTA_EXT('*', opattrs, allattrs); } else if (hasplus) { GER_GET_ATTR_RIGHTS(opattrs); GER_GET_ATTR_RIGHTA_EXT('+', allattrs, opattrs); } else { for ( i = 0; attrs[i]; i++ ) { if ('\0' == *attrs[i]) { continue; /* skip an empty attr */ } if (charray_inlist(noexpattrs, attrs[i])) { continue; } else if (charray_inlist(allattrs, attrs[i]) || charray_inlist(opattrs, attrs[i]) || (0 == strcasecmp(attrs[i], "dn")) || (0 == strcasecmp(attrs[i], "distinguishedName"))) { _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } else { /* if the attr does not belong to the entry, "<attr>:none" is returned */ if (!isfirstattr) { _append_gerstr(gerstr, gerstrsize, gerstrcap, ", ", NULL); } _append_gerstr(gerstr, gerstrsize, gerstrcap, attrs[i], ":"); _append_gerstr(gerstr, gerstrsize, gerstrcap, "none", NULL); isfirstattr = 0; } } } } charray_free(allattrs); charray_free(opattrs); } else { Slapi_Attr *prevattr = NULL, *attr; char *type; while ( slapi_entry_next_attr ( e, prevattr, &attr ) == 0 ) { if ( ! slapi_attr_flag_is_set (attr, SLAPI_ATTR_FLAG_OPATTR) ) { slapi_attr_get_type ( attr, &type ); _ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf ); isfirstattr = 0; } prevattr = attr; } } if ( isfirstattr ) { /* not a single attribute was retrived or specified */ _append_gerstr(gerstr, gerstrsize, gerstrcap, "*:none", NULL); } return; }
/* * memberof_validate_config() * * Validate the pending changes in the e entry. */ int memberof_validate_config (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry* e, int *returncode, char *returntext, void *arg) { Slapi_Attr *memberof_attr = NULL; Slapi_Attr *group_attr = NULL; Slapi_DN *config_sdn = NULL; Slapi_DN **include_dn = NULL; Slapi_DN **exclude_dn = NULL; char *syntaxoid = NULL; char *config_dn = NULL; char *skip_nested = NULL; char *auto_add_oc = NULL; char **entry_scopes = NULL; char **entry_exclude_scopes = NULL; int not_dn_syntax = 0; int num_vals = 0; *returncode = LDAP_UNWILLING_TO_PERFORM; /* be pessimistic */ /* Make sure both the group attr and the memberOf attr * config atributes are supplied. We don't care about &attr * here, but slapi_entry_attr_find() requires us to pass it. */ if (!slapi_entry_attr_find(e, MEMBEROF_GROUP_ATTR, &group_attr) && !slapi_entry_attr_find(e, MEMBEROF_ATTR, &memberof_attr)) { Slapi_Attr *test_attr = NULL; Slapi_Value *value = NULL; int hint = 0; /* Loop through each group attribute to see if the syntax is correct. */ hint = slapi_attr_first_value(group_attr, &value); while (value && (not_dn_syntax == 0)) { /* We need to create an attribute to find the syntax. */ test_attr = slapi_attr_new(); slapi_attr_init(test_attr, slapi_value_get_string(value)); /* Get the syntax OID and see if it's the Distinguished Name or * Name and Optional UID syntax. */ slapi_attr_get_syntax_oid_copy(test_attr, &syntaxoid ); not_dn_syntax = strcmp(syntaxoid, DN_SYNTAX_OID) & strcmp(syntaxoid, NAME_OPT_UID_SYNTAX_OID); slapi_ch_free_string(&syntaxoid); /* Print an error if the current attribute is not using the Distinguished * Name syntax, otherwise get the next group attribute. */ if (not_dn_syntax) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute must be set to " "an attribute defined to use either the Distinguished " "Name or Name and Optional UID syntax. (illegal value: %s)", slapi_value_get_string(value), MEMBEROF_GROUP_ATTR); } else { hint = slapi_attr_next_value(group_attr, hint, &value); } /* Free the group attribute. */ slapi_attr_free(&test_attr); } if (not_dn_syntax == 0) { /* Check the syntax of the memberof attribute. */ slapi_attr_first_value(memberof_attr, &value); test_attr = slapi_attr_new(); slapi_attr_init(test_attr, slapi_value_get_string(value)); slapi_attr_get_syntax_oid_copy(test_attr, &syntaxoid ); not_dn_syntax = strcmp(syntaxoid, DN_SYNTAX_OID); slapi_ch_free_string(&syntaxoid); slapi_attr_free(&test_attr); if (not_dn_syntax) { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute must be set to " "an attribute defined to use the Distinguished " "Name syntax. (illegal value: %s)", slapi_value_get_string(value), MEMBEROF_ATTR); goto done; } else { *returncode = LDAP_SUCCESS; } } } else { PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s and %s configuration attributes must be provided", MEMBEROF_GROUP_ATTR, MEMBEROF_ATTR); goto done; } if ((skip_nested = slapi_entry_attr_get_charptr(e, MEMBEROF_SKIP_NESTED_ATTR))){ if(strcasecmp(skip_nested, "on") != 0 && strcasecmp(skip_nested, "off") != 0){ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute must be set to " "\"on\" or \"off\". (illegal value: %s)", MEMBEROF_SKIP_NESTED_ATTR, skip_nested); goto done; } } if ((auto_add_oc = slapi_entry_attr_get_charptr(e, MEMBEROF_AUTO_ADD_OC))){ char *sup = NULL; /* Check if the objectclass exists by looking for its superior oc */ if((sup = slapi_schema_get_superior_name(auto_add_oc)) == NULL){ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute must be set to " "to an existing objectclass (unknown: %s)", MEMBEROF_AUTO_ADD_OC, auto_add_oc); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } else { slapi_ch_free_string(&sup); } } if ((config_dn = slapi_entry_attr_get_charptr(e, SLAPI_PLUGIN_SHARED_CONFIG_AREA))){ /* Now check the shared config attribute, validate it now */ Slapi_Entry *e = NULL; int rc = 0; rc = slapi_dn_syntax_check(pb, config_dn, 1); if (rc) { /* syntax check failed */ slapi_log_err(SLAPI_LOG_ERR, MEMBEROF_PLUGIN_SUBSYSTEM, "memberof_validate_config - " "%s does not contain a valid DN (%s)\n", SLAPI_PLUGIN_SHARED_CONFIG_AREA, config_dn); *returncode = LDAP_INVALID_DN_SYNTAX; goto done; } config_sdn = slapi_sdn_new_dn_byval(config_dn); slapi_search_internal_get_entry(config_sdn, NULL, &e, memberof_get_plugin_id()); if(e){ slapi_entry_free(e); *returncode = LDAP_SUCCESS; } else { /* config area does not exist! */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "The %s configuration attribute points to an entry that " "can not be found. (%s)", SLAPI_PLUGIN_SHARED_CONFIG_AREA, config_dn); *returncode = LDAP_UNWILLING_TO_PERFORM; } } /* * Check the entry scopes */ entry_scopes = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_ATTR, &num_vals); if(entry_scopes){ int i = 0; /* Validate the syntax before we create our DN array */ for (i = 0;i < num_vals; i++){ if(slapi_dn_syntax_check(pb, entry_scopes[i], 1)){ /* invalid dn syntax */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s: Invalid DN (%s) for include suffix.", MEMBEROF_PLUGIN_SUBSYSTEM, entry_scopes[i]); slapi_ch_array_free(entry_scopes); entry_scopes = NULL; theConfig.entryScopeCount = 0; *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } } /* Now create our SDN array for conflict checking */ include_dn = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *), num_vals+1); for (i = 0;i < num_vals; i++){ include_dn[i] = slapi_sdn_new_dn_passin(entry_scopes[i]); } } /* * Check and process the entry exclude scopes */ entry_exclude_scopes = slapi_entry_attr_get_charray_ext(e, MEMBEROF_ENTRY_SCOPE_EXCLUDE_SUBTREE, &num_vals); if(entry_exclude_scopes){ int i = 0; /* Validate the syntax before we create our DN array */ for (i = 0;i < num_vals; i++){ if(slapi_dn_syntax_check(pb, entry_exclude_scopes[i], 1)){ /* invalid dn syntax */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s: Invalid DN (%s) for exclude suffix.", MEMBEROF_PLUGIN_SUBSYSTEM, entry_exclude_scopes[i]); slapi_ch_array_free(entry_exclude_scopes); entry_exclude_scopes = NULL; *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } } /* Now create our SDN array for conflict checking */ exclude_dn = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),num_vals+1); for (i = 0;i < num_vals; i++){ exclude_dn[i] = slapi_sdn_new_dn_passin(entry_exclude_scopes[i]); } } /* * Need to do conflict checking */ if(include_dn && exclude_dn){ /* * Make sure we haven't mixed the same suffix, and there are no * conflicts between the includes and excludes */ int i = 0; while(include_dn[i]){ int x = 0; while(exclude_dn[x]){ if(slapi_sdn_compare(include_dn[i], exclude_dn[x] ) == 0) { /* we have a conflict */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s: include suffix (%s) is also listed as an exclude suffix list", MEMBEROF_PLUGIN_SUBSYSTEM, slapi_sdn_get_dn(include_dn[i])); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } x++; } i++; } /* Check for parent/child conflicts */ i = 0; while(include_dn[i]){ int x = 0; while(exclude_dn[x]){ if(slapi_sdn_issuffix(include_dn[i], exclude_dn[x])) { /* we have a conflict */ PR_snprintf(returntext, SLAPI_DSE_RETURNTEXT_SIZE, "%s: include suffix (%s) is a child of the exclude suffix(%s)", MEMBEROF_PLUGIN_SUBSYSTEM, slapi_sdn_get_dn(include_dn[i]), slapi_sdn_get_dn(exclude_dn[i])); *returncode = LDAP_UNWILLING_TO_PERFORM; goto done; } x++; } i++; } } done: memberof_free_scope(exclude_dn, &num_vals); memberof_free_scope(include_dn, &num_vals); slapi_ch_free((void**)&entry_scopes); slapi_ch_free((void**)&entry_exclude_scopes); slapi_sdn_free(&config_sdn); slapi_ch_free_string(&config_dn); slapi_ch_free_string(&skip_nested); slapi_ch_free_string(&auto_add_oc); if (*returncode != LDAP_SUCCESS) { return SLAPI_DSE_CALLBACK_ERROR; } else { return SLAPI_DSE_CALLBACK_OK; } }
int ipapwd_getPolicy(const char *dn, Slapi_Entry *target, struct ipapwd_policy *policy) { const char *krbPwdPolicyReference; char *pdn = NULL; Slapi_PBlock *pb = NULL; char *attrs[] = { "krbMaxPwdLife", "krbMinPwdLife", "krbPwdMinDiffChars", "krbPwdMinLength", "krbPwdHistoryLength", NULL}; Slapi_Entry **es = NULL; Slapi_Entry *pe = NULL; int ret, res, scope, i; int buffer_flags=0; Slapi_ValueSet* results = NULL; char *actual_type_name = NULL; LOG_TRACE("Searching policy for [%s]\n", dn); pwd_get_values(target, "krbPwdPolicyReference", &results, &actual_type_name, &buffer_flags); if (results) { Slapi_Value *sv; slapi_valueset_first_value(results, &sv); krbPwdPolicyReference = slapi_value_get_string(sv); pdn = slapi_ch_strdup(krbPwdPolicyReference); } else { /* Fallback to hardcoded value */ pdn = slapi_ch_smprintf("cn=global_policy,%s", ipa_realm_dn); } if (pdn == NULL) { LOG_OOM(); ret = -1; goto done; } LOG_TRACE("Using policy at [%s]\n", pdn); scope = LDAP_SCOPE_BASE; pb = slapi_pblock_new(); slapi_search_internal_set_pb(pb, pdn, scope, "(objectClass=krbPwdPolicy)", attrs, 0, NULL, /* Controls */ NULL, /* UniqueID */ ipapwd_plugin_id, 0); /* Flags */ /* do search the tree */ ret = slapi_search_internal_pb(pb); slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res); if (ret == -1 || res != LDAP_SUCCESS) { LOG_FATAL("Couldn't find policy, err (%d)\n", res ? res : ret); ret = -1; goto done; } /* get entries */ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &es); if (!es) { LOG_TRACE("No entries ?!"); ret = -1; goto done; } /* count entries */ for (i = 0; es[i]; i++) /* count */ ; /* if there is only one, return that */ if (i == 1) { pe = es[0]; } else { LOG_TRACE("Multiple entries from a base search ?!"); ret = -1; goto done; } /* read data out of policy object */ policy->min_pwd_life = slapi_entry_attr_get_int(pe, "krbMinPwdLife"); policy->max_pwd_life = slapi_entry_attr_get_int(pe, "krbMaxPwdLife"); policy->min_pwd_length = slapi_entry_attr_get_int(pe, "krbPwdMinLength"); policy->history_length = slapi_entry_attr_get_int(pe, "krbPwdHistoryLength"); policy->min_complexity = slapi_entry_attr_get_int(pe, "krbPwdMinDiffChars"); ret = 0; done: if (results) { pwd_values_free(&results, &actual_type_name, buffer_flags); } if (pb) { slapi_free_search_results_internal(pb); slapi_pblock_destroy(pb); } slapi_ch_free_string(&pdn); return ret; }