int ldap_create_deref_control( LDAP *ld, LDAPDerefSpec *ds, int iscritical, LDAPControl **ctrlp ) { struct berval value; if ( ctrlp == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; return ld->ld_errno; } ld->ld_errno = ldap_create_deref_control_value( ld, ds, &value ); if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS, iscritical, &value, 0, ctrlp ); if ( ld->ld_errno != LDAP_SUCCESS ) { LDAP_FREE( value.bv_val ); } } return ld->ld_errno; }
krb5_error_code ipadb_deref_search(struct ipadb_context *ipactx, char *base_dn, int scope, char *filter, char **entry_attrs, char **deref_attr_names, char **deref_attrs, LDAPMessage **res) { struct berval derefval = { 0, NULL }; LDAPControl *ctrl[2] = { NULL, NULL }; LDAPDerefSpec *ds; krb5_error_code kerr; int times; int ret; int c, i; bool retry; for (c = 0; deref_attr_names[c]; c++) { /* count */ ; } ds = calloc(c+1, sizeof(LDAPDerefSpec)); if (!ds) { return ENOMEM; } for (i = 0; deref_attr_names[i]; i++) { ds[i].derefAttr = deref_attr_names[i]; ds[i].attributes = deref_attrs; } ds[c].derefAttr = NULL; ret = ldap_create_deref_control_value(ipactx->lcontext, ds, &derefval); if (ret != LDAP_SUCCESS) { kerr = ENOMEM; goto done; } ret = ldap_control_create(LDAP_CONTROL_X_DEREF, 1, &derefval, 1, &ctrl[0]); if (ret != LDAP_SUCCESS) { kerr = ENOMEM; goto done; } /* retry once if connection errors (tot. max. 2 tries) */ times = 2; ret = LDAP_SUCCESS; retry = true; while (retry) { times--; ret = ipadb_check_connection(ipactx); if (ret != 0) break; ret = ldap_search_ext_s(ipactx->lcontext, base_dn, scope, filter, entry_attrs, 0, ctrl, NULL, &std_timeout, LDAP_NO_LIMIT, res); retry = ipadb_need_retry(ipactx, ret) && times > 0; if (retry) { /* Free result before next try */ ldap_msgfree(*res); } } kerr = ipadb_simple_ldap_to_kerr(ret); done: ldap_control_free(ctrl[0]); ldap_memfree(derefval.bv_val); free(ds); return kerr; }