sdap_async.c revision 0daccb28ba9b40a20ac3494aea42ce68c7a92a31
/*
SSSD
Async LDAP Helper routines
Copyright (C) Simo Sorce <ssorce@redhat.com> - 2009
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include "providers/ldap/sdap_async_private.h"
#define REALM_SEPARATOR '@'
#define REPLY_REALLOC_INCREMENT 10
void make_realm_upper_case(const char *upn)
{
char *c;
if (c == NULL) {
return;
}
while(*(++c) != '\0') {
c[0] = toupper(*c);
}
return;
}
/* ==LDAP-Memory-Handling================================================= */
static int lmsg_destructor(void *mem)
{
return 0;
}
{
void *h;
if (!h) return ENOMEM;
return EOK;
}
/* ==sdap-hanlde-utility-functions======================================== */
static int sdap_handle_destructor(void *mem);
{
struct sdap_handle *sh;
return sh;
}
static int sdap_handle_destructor(void *mem)
{
/* if the structure is currently locked, then mark it to be released
* and prevent talloc from freeing the memory */
if (sh->destructor_lock) {
sh->release_memory = true;
return -1;
}
return 0;
}
{
"destructor_lock[%d], release_memory[%d]\n",
if (sh->destructor_lock) return;
sh->destructor_lock = true;
/* make sure nobody tries to reuse this connection from now on */
/* calling the callback may result in freeing the op */
/* check if it is still the same or avoid freeing */
}
}
/* ok, we have done the job, unlock now */
sh->destructor_lock = false;
/* finally if a destructor was ever called, free sh before
* exiting */
if (sh->release_memory) {
/* neutralize the destructor as we already handled
* all was needed to be released */
}
}
/* ==Parse-Results-And-Handle-Disconnections============================== */
struct tevent_timer *te,
{
}
struct tevent_timer *te,
{
}
{
struct timeval no_timeout = {0, 0};
struct tevent_timer *te;
int ret;
return;
}
if (ret == 0) {
/* this almost always means we have reached the end of
* the list of received messages */
return;
}
if (ret == -1) {
return;
}
/* We don't know if this will be the last result.
*
* important: we must do this before actually processing the message
* because the message processing might even free the sdap_handler
* so it must be the last operation.
* FIXME: use tevent_immediate/tevent_queues, when avilable */
if (!te) {
}
/* now process this message */
}
/* process a messgae calling the right operation callback.
* msg is completely taken care of (including freeeing it)
* NOTE: this function may even end up freeing the sdap_handle
* so sdap_hanbdle must not be used after this function is called
*/
{
int msgid;
int msgtype;
int ret;
if (msgid == -1) {
return;
}
}
msgtype));
return;
}
/* shouldn't happen */
return;
}
switch (msgtype) {
case LDAP_RES_SEARCH_ENTRY:
/* go and process entry */
break;
/* more ops to come with this msgid */
/* just ignore */
return;
case LDAP_RES_BIND:
case LDAP_RES_SEARCH_RESULT:
case LDAP_RES_MODIFY:
case LDAP_RES_ADD:
case LDAP_RES_DELETE:
case LDAP_RES_MODDN:
case LDAP_RES_COMPARE:
case LDAP_RES_EXTENDED:
case LDAP_RES_INTERMEDIATE:
/* no more results expected with this msgid */
break;
default:
/* unkwon msg type ?? */
return;
}
if (!reply) {
} else {
}
}
/* list exist, queue it */
} else {
/* create list, then call callback */
/* must be the last operation as it may end up freeing all memory
* including all ops handlers */
}
}
{
struct tevent_timer *te;
struct sdap_msg *next_reply;
/* get rid of the previous reply, it has been processed already */
}
/* if there are still replies to parse, queue a new operation */
/* use a very small timeout, so that fd operations have a chance to be
* served while processing a long reply */
tv = tevent_timeval_current();
/* wait 5 microsecond */
if (!te) {
}
}
}
struct tevent_timer *te,
{
}
/* ==LDAP-Operations-Helpers============================================== */
static int sdap_op_destructor(void *mem)
{
/* we don't check the result here, if a message was really abandoned,
* hopefully the server will get an abandon.
* If the operation was already fully completed, this is going to be
* just a noop */
return 0;
}
{
/* should never happen, but just in case */
return;
}
/* signal the caller that we have a timeout */
}
{
/* check if we need to set a timeout */
if (timeout) {
struct tevent_req *req;
tv = tevent_timeval_current();
/* allocate on op, so when it get freed the timeout is removed */
if (!req) {
return ENOMEM;
}
}
return EOK;
}
/* ==Modify-Password====================================================== */
struct sdap_exop_modify_passwd_state {
struct sdap_handle *sh;
int result;
char *user_error_message;
};
struct tevent_context *ev,
struct sdap_handle *sh,
char *user_dn,
char *password,
char *new_password)
{
struct sdap_exop_modify_passwd_state *state;
int ret;
int msgid;
struct sdap_exop_modify_passwd_state);
return NULL;
}
if (ret == -1) {
return NULL;
}
if (ret == -1) {
return NULL;
}
0, NULL, 0, &request_controls[0]);
if (ret != LDAP_SUCCESS) {
goto fail;
}
ber_bvfree(bv);
goto fail;
}
/* FIXME: get timeouts from configuration, for now 5 secs. */
if (ret) {
goto fail;
}
return req;
fail:
return req;
}
{
struct sdap_exop_modify_passwd_state);
int ret;
int c;
if (error) {
return;
}
&response_controls, 0);
if (ret != LDAP_SUCCESS) {
goto done;
}
if (response_controls == NULL) {
} else {
for (c = 0; response_controls[c] != NULL; c++) {
response_controls[c]->ldctl_oid));
LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) {
&pp_error);
if (ret != LDAP_SUCCESS) {
goto done;
}
}
}
}
}
}
ret = LDAP_SUCCESS;
done:
if (ret == LDAP_SUCCESS) {
} else {
}
}
enum sdap_result *result,
char **user_error_message)
{
struct sdap_exop_modify_passwd_state);
*result = SDAP_ERROR;
*result = SDAP_SUCCESS;
}
return EOK;
}
/* ==Fetch-RootDSE============================================= */
struct sdap_get_rootdse_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sdap_handle *sh;
struct sysdb_attrs *rootdse;
};
struct tevent_context *ev,
struct sdap_options *opts,
struct sdap_handle *sh)
{
struct sdap_get_rootdse_state *state;
const char *attrs[] = {
"*",
"altServer",
"namingContexts",
"supportedControl",
"supportedExtension",
"supportedFeatures",
"supportedLDAPVersion",
"supportedSASLMechanisms",
};
"", LDAP_SCOPE_BASE,
if (!subreq) {
return NULL;
}
return req;
}
{
struct tevent_req);
struct sdap_get_rootdse_state);
struct sysdb_attrs **results;
int ret;
if (ret) {
return;
}
if (num_results == 0 || !results) {
"Please check that anonymous access to RootDSE is allowed\n"
));
return;
}
if (num_results > 1) {
return;
}
}
struct sysdb_attrs **rootdse)
{
struct sdap_get_rootdse_state);
return EOK;
}
/* ==Generic Search============================================ */
struct sdap_get_generic_state {
struct tevent_context *ev;
struct sdap_options *opts;
struct sdap_handle *sh;
const char *search_base;
int scope;
const char *filter;
const char **attrs;
struct sdap_attr_map *map;
int map_num_attrs;
struct sysdb_attrs **reply;
};
struct sysdb_attrs *msg);
struct tevent_context *ev,
struct sdap_options *opts,
struct sdap_handle *sh,
const char *search_base,
int scope,
const char *filter,
const char **attrs,
struct sdap_attr_map *map,
int map_num_attrs)
{
int lret;
int ret;
int msgid;
state->reply_count = 0;
state->search_base));
if (debug_level >= 7) {
int i;
}
}
}
if (lret != LDAP_SUCCESS) {
if (lret == LDAP_SERVER_DOWN) {
} else {
}
goto fail;
}
goto fail;
}
return req;
fail:
return req;
}
{
struct sdap_get_generic_state);
struct sysdb_attrs *attrs;
char *errmsg;
int result;
int ret;
if (error) {
return;
}
/* ignore references for now */
/* unlock the operation so that we can proceed with the next result */
break;
case LDAP_RES_SEARCH_ENTRY:
return;
}
return;
}
break;
case LDAP_RES_SEARCH_RESULT:
if (ret != LDAP_SUCCESS) {
return;
}
}
return;
default:
/* what is going on here !? */
return;
}
}
struct sysdb_attrs *msg)
{
struct sysdb_attrs *,
return ENOMEM;
}
}
return EOK;
}
struct sysdb_attrs ***reply)
{
struct sdap_get_generic_state);
return EOK;
}