diff options
| -rw-r--r-- | source4/lib/ldb/ldb_ildap/ldb_ildap.c | 483 | ||||
| -rw-r--r-- | source4/lib/ldb/ldb_ldap/ldb_ldap.c | 588 | ||||
| -rw-r--r-- | source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c | 130 | 
3 files changed, 619 insertions, 582 deletions
diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c index 5ad671ea2e..4aa71e6036 100644 --- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c +++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c @@ -53,17 +53,57 @@  struct ildb_private {  	struct ldap_connection *ldap; -	struct ldb_module *module; +	struct event_context *event_ctx;  };  struct ildb_context { +	struct ldb_module *module; +	struct ldb_request *req; +  	struct ildb_private *ildb; -	struct ldb_handle *handle; -	struct ldap_request *req; -	void *context; -	int (*callback)(struct ldb_context *, void *, struct ldb_reply *); +	struct ldap_request *ireq; + +	bool done; + +	struct ildb_destructor_ctx *dc;  }; +static void ildb_request_done(struct ildb_context *ctx, +			      struct ldb_control **ctrls, int error) +{ +	struct ldb_reply *ares; + +	ctx->done = true; + +	if (ctx->req == NULL) { +		/* if the req has been freed already just return */ +		return; +	} + +	ares = talloc_zero(ctx->req, struct ldb_reply); +	if (!ares) { +		ldb_oom(ctx->req->handle->ldb); +		ctx->req->callback(ctx->req, NULL); +		return; +	} +	ares->type = LDB_REPLY_DONE; +	ares->controls = talloc_steal(ares, ctrls); +	ares->error = error; + +	ctx->req->callback(ctx->req, ares); +} + +static void ildb_auto_done_callback(struct event_context *ev, +				    struct timed_event *te, +				    struct timeval t, +				    void *private_data) +{ +	struct ildb_context *ac; + +	ac = talloc_get_type(private_data, struct ildb_context); +	ildb_request_done(ac, NULL, LDB_SUCCESS); +} +  /*    convert a ldb_message structure to a list of ldap_mod structures    ready for ildap_add() or ildap_modify() @@ -122,17 +162,19 @@ failed:  /*    map an ildap NTSTATUS to a ldb error code  */ -static int ildb_map_error(struct ildb_private *ildb, NTSTATUS status) +static int ildb_map_error(struct ldb_module *module, NTSTATUS status)  { +	struct ildb_private *ildb = talloc_get_type(module->private_data, struct ildb_private); +  	TALLOC_CTX *mem_ctx = talloc_new(ildb);  	if (NT_STATUS_IS_OK(status)) {  		return LDB_SUCCESS;  	}  	if (!mem_ctx) { -		ldb_oom(ildb->module->ldb); +		ldb_oom(module->ldb);  		return LDB_ERR_OPERATIONS_ERROR;  	} -	ldb_set_errstring(ildb->module->ldb, +	ldb_set_errstring(module->ldb,  			  ldap_errstr(ildb->ldap, mem_ctx, status));  	talloc_free(mem_ctx);  	if (NT_STATUS_IS_LDAP(status)) { @@ -141,47 +183,46 @@ static int ildb_map_error(struct ildb_private *ildb, NTSTATUS status)  	return LDB_ERR_OPERATIONS_ERROR;  } -static void ildb_request_timeout(struct event_context *ev, -				 struct timed_event *te, +static void ildb_request_timeout(struct event_context *ev, struct timed_event *te,  				 struct timeval t, void *private_data)  { -	struct ildb_context *ac; -	struct ldb_handle *handle; - -	ac = talloc_get_type(private_data, struct ildb_context); -	handle = ac->handle; - -	ac = talloc_get_type(private_data, struct ildb_context); +	struct ildb_context *ac = talloc_get_type(private_data, struct ildb_context); -	if (ac->req->state == LDAP_REQUEST_PENDING) { -		DLIST_REMOVE(ac->req->conn->pending, ac->req); +	if (ac->ireq->state == LDAP_REQUEST_PENDING) { +		DLIST_REMOVE(ac->ireq->conn->pending, ac->ireq);  	} -	handle->status = LDB_ERR_TIME_LIMIT_EXCEEDED; - -	return; +	ildb_request_done(ac, NULL, LDB_ERR_TIME_LIMIT_EXCEEDED);  }  static void ildb_callback(struct ldap_request *req)  {  	struct ildb_context *ac; -	struct ldb_handle *handle; -	struct ildb_private *ildb;  	NTSTATUS status; +	struct ldap_SearchResEntry *search; +	struct ldap_message *msg; +	struct ldb_control **controls; +	struct ldb_message *ldbmsg; +	char *referral; +	bool callback_failed; +	bool request_done; +	int ret;  	int i;  	ac = talloc_get_type(req->async.private_data, struct ildb_context); -	ildb = ac->ildb; -	handle = ac->handle; -	handle->status = LDB_SUCCESS; +	callback_failed = false; +	request_done = false; +	controls = NULL;  	if (!NT_STATUS_IS_OK(req->status)) { -		handle->status = ildb_map_error(ildb, req->status); +		ret = ildb_map_error(ac->module, req->status); +		ildb_request_done(ac, NULL, ret);  		return;  	}  	if (req->num_replies < 1) { -		handle->status = LDB_ERR_OPERATIONS_ERROR; +		ret = LDB_ERR_OPERATIONS_ERROR; +		ildb_request_done(ac, NULL, ret);  		return;  	} @@ -189,140 +230,112 @@ static void ildb_callback(struct ldap_request *req)  	case LDAP_TAG_ModifyRequest:  		if (req->replies[0]->type != LDAP_TAG_ModifyResponse) { -			handle->status = LDB_ERR_PROTOCOL_ERROR; -			return; +			ret = LDB_ERR_PROTOCOL_ERROR; +			break;  		} -		status = ldap_check_response(req->conn, &req->replies[0]->r.GeneralResult); -		handle->status = ildb_map_error(ildb, status); -		if (ac->callback && handle->status == LDB_SUCCESS) { -			/* FIXME: build a corresponding ares to pass on */ -			handle->status = ac->callback(ac->ildb->module->ldb, ac->context, NULL); -		} -		handle->state = LDB_ASYNC_DONE; +		status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult); +		ret = ildb_map_error(ac->module, status); +		request_done = true;  		break;  	case LDAP_TAG_AddRequest:  		if (req->replies[0]->type != LDAP_TAG_AddResponse) { -			handle->status = LDB_ERR_PROTOCOL_ERROR; +			ret = LDB_ERR_PROTOCOL_ERROR;  			return;  		} -		status = ldap_check_response(req->conn, &req->replies[0]->r.GeneralResult); -		handle->status = ildb_map_error(ildb, status); -		if (ac->callback && handle->status == LDB_SUCCESS) { -			/* FIXME: build a corresponding ares to pass on */ -			handle->status = ac->callback(ac->ildb->module->ldb, ac->context, NULL); -		} -		handle->state = LDB_ASYNC_DONE; +		status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult); +		ret = ildb_map_error(ac->module, status); +		request_done = true;  		break;  	case LDAP_TAG_DelRequest:  		if (req->replies[0]->type != LDAP_TAG_DelResponse) { -			handle->status = LDB_ERR_PROTOCOL_ERROR; +			ret = LDB_ERR_PROTOCOL_ERROR;  			return;  		} -		status = ldap_check_response(req->conn, &req->replies[0]->r.GeneralResult); -		handle->status = ildb_map_error(ildb, status); -		if (ac->callback && handle->status == LDB_SUCCESS) { -			/* FIXME: build a corresponding ares to pass on */ -			handle->status = ac->callback(ac->ildb->module->ldb, ac->context, NULL); -		} -		handle->state = LDB_ASYNC_DONE; +		status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult); +		ret = ildb_map_error(ac->module, status); +		request_done = true;  		break;  	case LDAP_TAG_ModifyDNRequest:  		if (req->replies[0]->type != LDAP_TAG_ModifyDNResponse) { -			handle->status = LDB_ERR_PROTOCOL_ERROR; +			ret = LDB_ERR_PROTOCOL_ERROR;  			return;  		} -		status = ldap_check_response(req->conn, &req->replies[0]->r.GeneralResult); -		handle->status = ildb_map_error(ildb, status); -		if (ac->callback && handle->status == LDB_SUCCESS) { -			/* FIXME: build a corresponding ares to pass on */ -			handle->status = ac->callback(ac->ildb->module->ldb, ac->context, NULL); -		} -		handle->state = LDB_ASYNC_DONE; +		status = ldap_check_response(ac->ireq->conn, &req->replies[0]->r.GeneralResult); +		ret = ildb_map_error(ac->module, status); +		request_done = true;  		break;  	case LDAP_TAG_SearchRequest:  		/* loop over all messages */  		for (i = 0; i < req->num_replies; i++) { -			struct ldap_SearchResEntry *search; -			struct ldb_reply *ares = NULL; -			struct ldap_message *msg; -			int ret; - -			ares = talloc_zero(ac, struct ldb_reply); -			if (!ares) { -				handle->status = LDB_ERR_OPERATIONS_ERROR; -				return; -			}  			msg = req->replies[i];  			switch (msg->type) {  			case LDAP_TAG_SearchResultDone: -				status = ldap_check_response(req->conn, &msg->r.GeneralResult); +				status = ldap_check_response(ac->ireq->conn, &msg->r.GeneralResult);  				if (!NT_STATUS_IS_OK(status)) { -					handle->status = ildb_map_error(ildb, status); -					return; +					ret = ildb_map_error(ac->module, status); +					break;  				} -				ares->controls = talloc_move(ares, &msg->controls); +				controls = talloc_steal(ac, msg->controls);  				if (msg->r.SearchResultDone.resultcode) {  					if (msg->r.SearchResultDone.errormessage) { -						ldb_set_errstring(ac->ildb->module->ldb, msg->r.SearchResultDone.errormessage); +						ldb_set_errstring(ac->module->ldb, msg->r.SearchResultDone.errormessage);  					}  				} -				handle->status = msg->r.SearchResultDone.resultcode; -				handle->state = LDB_ASYNC_DONE; -				ares->type = LDB_REPLY_DONE; +				ret = msg->r.SearchResultDone.resultcode; +				request_done = true;  				break;  			case LDAP_TAG_SearchResultEntry: - -				ares->message = ldb_msg_new(ares); -				if (!ares->message) { -					handle->status = LDB_ERR_OPERATIONS_ERROR; -					return; +				ldbmsg = ldb_msg_new(ac); +				if (!ldbmsg) { +					ret = LDB_ERR_OPERATIONS_ERROR; +					break;  				}  				search = &(msg->r.SearchResultEntry); -				ares->message->dn = ldb_dn_new(ares->message, ac->ildb->module->ldb, search->dn); -				if ( ! ldb_dn_validate(ares->message->dn)) { -					handle->status = LDB_ERR_OPERATIONS_ERROR; -					return; +				ldbmsg->dn = ldb_dn_new(ldbmsg, ac->module->ldb, search->dn); +				if ( ! ldb_dn_validate(ldbmsg->dn)) { +					ret = LDB_ERR_OPERATIONS_ERROR; +					break;  				} -				ares->message->num_elements = search->num_attributes; -				ares->message->elements = talloc_move(ares->message, -								      &search->attributes); +				ldbmsg->num_elements = search->num_attributes; +				ldbmsg->elements = talloc_move(ldbmsg, &search->attributes); -				handle->status = LDB_SUCCESS; -				handle->state = LDB_ASYNC_PENDING; -				ares->type = LDB_REPLY_ENTRY; +				ret = ldb_module_send_entry(ac->req, ldbmsg); +				if (ret != LDB_SUCCESS) { +					callback_failed = true; +				}  				break;  			case LDAP_TAG_SearchResultReference: -				ares->referral = talloc_strdup(ares, msg->r.SearchResultReference.referral); +				referral = talloc_strdup(ac, msg->r.SearchResultReference.referral); -				handle->status = LDB_SUCCESS; -				handle->state = LDB_ASYNC_PENDING; -				ares->type = LDB_REPLY_REFERRAL; +				ret = ldb_module_send_referral(ac->req, referral); +				if (ret != LDB_SUCCESS) { +					callback_failed = true; +				}  				break;  			default:  				/* TAG not handled, fail ! */ -				handle->status = LDB_ERR_PROTOCOL_ERROR; -				return; +				ret = LDB_ERR_PROTOCOL_ERROR; +				break;  			} -			ret = ac->callback(ac->ildb->module->ldb, ac->context, ares); -			if (ret) { -				handle->status = ret; +			if (ret != LDB_SUCCESS) { +				break;  			}  		} @@ -333,121 +346,81 @@ static void ildb_callback(struct ldap_request *req)  		break;  	default: -		handle->status = LDB_ERR_PROTOCOL_ERROR; -		return; +		ret = LDB_ERR_PROTOCOL_ERROR; +		break;  	} -} -static struct ildb_context *init_ildb_handle(struct ildb_private *ildb, -					     struct ldb_request *req) -{ -	struct ildb_context *ildb_ac; -	struct ldb_handle *h; +	if (ret != LDB_SUCCESS) { -	h = talloc_zero(req, struct ldb_handle); -	if (h == NULL) { -		ldb_set_errstring(ildb->module->ldb, "Out of Memory"); -		return NULL; +		/* if the callback failed the caller will have freed the +		 * request. Just return and don't try to use it */ +		if ( ! callback_failed) { +			request_done = true; +		}  	} -	h->module = ildb->module; - -	ildb_ac = talloc(h, struct ildb_context); -	if (ildb_ac == NULL) { -		ldb_set_errstring(ildb->module->ldb, "Out of Memory"); -		talloc_free(h); -		return NULL; +	if (request_done) { +		ildb_request_done(ac, controls, ret);  	} - -	h->private_data = ildb_ac; - -	h->state = LDB_ASYNC_INIT; -	h->status = LDB_SUCCESS; - -	ildb_ac->ildb = ildb; -	ildb_ac->handle = h; -	ildb_ac->context = req->context; -	ildb_ac->callback = req->callback; - -	req->handle = h; -	return ildb_ac; +	return;  } -static int ildb_request_send(struct ildb_private *ildb, struct ldap_message *msg, struct ldb_request *r) +static int ildb_request_send(struct ildb_context *ac, struct ldap_message *msg)  { -	struct ildb_context *ildb_ac = init_ildb_handle(ildb, r);  	struct ldap_request *req; -	if (!ildb_ac) { +	if (!ac) {  		return LDB_ERR_OPERATIONS_ERROR;  	} -	req = ldap_request_send(ildb->ldap, msg); +	req = ldap_request_send(ac->ildb->ldap, msg);  	if (req == NULL) { -		ldb_set_errstring(ildb->module->ldb, "async send request failed"); +		ldb_set_errstring(ac->module->ldb, "async send request failed");  		return LDB_ERR_OPERATIONS_ERROR;  	} -	ildb_ac->req = talloc_steal(ildb_ac, req); +	ac->ireq = talloc_steal(ac, req); -	if (!req->conn) { -		ldb_set_errstring(ildb->module->ldb, "connection to remote LDAP server dropped?"); +	if (!ac->ireq->conn) { +		ldb_set_errstring(ac->module->ldb, "connection to remote LDAP server dropped?");  		return LDB_ERR_OPERATIONS_ERROR;  	}  	talloc_free(req->time_event);  	req->time_event = NULL; -	if (r->timeout) { -		req->time_event = event_add_timed(req->conn->event.event_ctx, ildb_ac,  -						  timeval_current_ofs(r->timeout, 0), -						  ildb_request_timeout, ildb_ac); +	if (ac->req->timeout) { +		req->time_event = event_add_timed(ac->ildb->event_ctx, ac, +						  timeval_current_ofs(ac->req->timeout, 0), +						  ildb_request_timeout, ac);  	}  	req->async.fn = ildb_callback; -	req->async.private_data = ildb_ac; +	req->async.private_data = ac;  	return LDB_SUCCESS;  } -static int ildb_request_noop(struct ildb_private *ildb, struct ldb_request *req)  -{ -	struct ildb_context *ildb_ac = init_ildb_handle(ildb, req); -	int ret = LDB_SUCCESS; - -	if (!ildb_ac) { -		return LDB_ERR_OPERATIONS_ERROR; -	} - -	if (ildb_ac->callback) { -		ret = ildb_ac->callback(ildb->module->ldb, ildb_ac->context, NULL); -	} -	ildb_ac->handle->state = LDB_ASYNC_DONE; -	return ret; -} -  /*    search for matching records using an asynchronous function   */ -static int ildb_search(struct ldb_module *module, struct ldb_request *req) +static int ildb_search(struct ildb_context *ac)  { -	struct ildb_private *ildb = talloc_get_type(module->private_data, struct ildb_private); +	struct ldb_request *req = ac->req;  	struct ldap_message *msg;  	int n; -	req->handle = NULL; -  	if (!req->callback || !req->context) { -		ldb_set_errstring(module->ldb, "Async interface called with NULL callback function or NULL context"); +		ldb_set_errstring(ac->module->ldb, "Async interface called with NULL callback function or NULL context");  		return LDB_ERR_OPERATIONS_ERROR;  	}  	if (req->op.search.tree == NULL) { -		ldb_set_errstring(module->ldb, "Invalid expression parse tree"); +		ldb_set_errstring(ac->module->ldb, "Invalid expression parse tree");  		return LDB_ERR_OPERATIONS_ERROR;  	}  	msg = new_ldap_message(req);  	if (msg == NULL) { -		ldb_set_errstring(module->ldb, "Out of Memory"); +		ldb_set_errstring(ac->module->ldb, "Out of Memory");  		return LDB_ERR_OPERATIONS_ERROR;  	} @@ -459,7 +432,7 @@ static int ildb_search(struct ldb_module *module, struct ldb_request *req)  		msg->r.SearchRequest.basedn  = ldb_dn_alloc_linearized(msg, req->op.search.base);  	}  	if (msg->r.SearchRequest.basedn == NULL) { -		ldb_set_errstring(module->ldb, "Unable to determine baseDN"); +		ldb_set_errstring(ac->module->ldb, "Unable to determine baseDN");  		talloc_free(msg);  		return LDB_ERR_OPERATIONS_ERROR;  	} @@ -481,26 +454,19 @@ static int ildb_search(struct ldb_module *module, struct ldb_request *req)  	msg->r.SearchRequest.attributes = discard_const(req->op.search.attrs);  	msg->controls = req->controls; -	return ildb_request_send(ildb, msg, req); +	return ildb_request_send(ac, msg);  }  /*    add a record  */ -static int ildb_add(struct ldb_module *module, struct ldb_request *req) +static int ildb_add(struct ildb_context *ac)  { -	struct ildb_private *ildb = talloc_get_type(module->private_data, struct ildb_private); +	struct ldb_request *req = ac->req;  	struct ldap_message *msg;  	struct ldap_mod **mods;  	int i,n; -	req->handle = NULL; - -	/* ignore ltdb specials */ -	if (ldb_dn_is_special(req->op.add.message->dn)) { -		return ildb_request_noop(ildb, req); -	} -  	msg = new_ldap_message(req);  	if (msg == NULL) {  		return LDB_ERR_OPERATIONS_ERROR; @@ -531,26 +497,19 @@ static int ildb_add(struct ldb_module *module, struct ldb_request *req)  		msg->r.AddRequest.attributes[i] = mods[i]->attrib;  	} -	return ildb_request_send(ildb, msg, req); +	return ildb_request_send(ac, msg);  }  /*    modify a record  */ -static int ildb_modify(struct ldb_module *module, struct ldb_request *req) +static int ildb_modify(struct ildb_context *ac)  { -	struct ildb_private *ildb = talloc_get_type(module->private_data, struct ildb_private); +	struct ldb_request *req = ac->req;  	struct ldap_message *msg;  	struct ldap_mod **mods;  	int i,n; -	req->handle = NULL; - -	/* ignore ltdb specials */ -	if (ldb_dn_is_special(req->op.mod.message->dn)) { -		return ildb_request_noop(ildb, req); -	} -  	msg = new_ldap_message(req);  	if (msg == NULL) {  		return LDB_ERR_OPERATIONS_ERROR; @@ -581,24 +540,17 @@ static int ildb_modify(struct ldb_module *module, struct ldb_request *req)  		msg->r.ModifyRequest.mods[i] = *mods[i];  	} -	return ildb_request_send(ildb, msg, req); +	return ildb_request_send(ac, msg);  }  /*    delete a record  */ -static int ildb_delete(struct ldb_module *module, struct ldb_request *req) +static int ildb_delete(struct ildb_context *ac)  { -	struct ildb_private *ildb = talloc_get_type(module->private_data, struct ildb_private); +	struct ldb_request *req = ac->req;  	struct ldap_message *msg; -	req->handle = NULL; - -	/* ignore ltdb specials */ -	if (ldb_dn_is_special(req->op.del.dn)) { -		return ildb_request_noop(ildb, req); -	} -  	msg = new_ldap_message(req);  	if (msg == NULL) {  		return LDB_ERR_OPERATIONS_ERROR; @@ -612,24 +564,17 @@ static int ildb_delete(struct ldb_module *module, struct ldb_request *req)  		return LDB_ERR_INVALID_DN_SYNTAX;  	} -	return ildb_request_send(ildb, msg, req); +	return ildb_request_send(ac, msg);  }  /*    rename a record  */ -static int ildb_rename(struct ldb_module *module, struct ldb_request *req) +static int ildb_rename(struct ildb_context *ac)  { -	struct ildb_private *ildb = talloc_get_type(module->private_data, struct ildb_private); +	struct ldb_request *req = ac->req;  	struct ldap_message *msg; -	req->handle = NULL; - -	/* ignore ltdb specials */ -	if (ldb_dn_is_special(req->op.rename.olddn) || ldb_dn_is_special(req->op.rename.newdn)) { -		return ildb_request_noop(ildb, req); -	} -  	msg = new_ldap_message(req);  	if (msg == NULL) {  		return LDB_ERR_OPERATIONS_ERROR; @@ -660,7 +605,7 @@ static int ildb_rename(struct ldb_module *module, struct ldb_request *req)  	msg->r.ModifyDNRequest.deleteolddn = true; -	return ildb_request_send(ildb, msg, req); +	return ildb_request_send(ac, msg);  }  static int ildb_start_trans(struct ldb_module *module) @@ -684,57 +629,105 @@ static int ildb_del_trans(struct ldb_module *module)  	return LDB_SUCCESS;  } -static int ildb_request(struct ldb_module *module, struct ldb_request *req) +static bool ildb_dn_is_special(struct ldb_request *req)  { -	return LDB_ERR_OPERATIONS_ERROR; +	struct ldb_dn *dn = NULL; + +	switch (req->operation) { +	case LDB_ADD: +		dn = req->op.add.message->dn; +		break; +	case LDB_MODIFY: +		dn = req->op.mod.message->dn; +		break; +	case LDB_DELETE: +		dn = req->op.del.dn; +		break; +	case LDB_RENAME: +		dn = req->op.rename.olddn; +		break; +	default: +		break; +	} + +	if (dn && ldb_dn_is_special(dn)) { +		return true; +	} +	return false;  } -static int ildb_wait(struct ldb_handle *handle, enum ldb_wait_type type) +static int ildb_handle_request(struct ldb_module *module, struct ldb_request *req)  { -	struct ildb_context *ac = talloc_get_type(handle->private_data, struct ildb_context); +	struct ildb_private *ildb; +	struct ildb_context *ac; +	struct timed_event *te; +	int ret; + +	ildb = talloc_get_type(module->private_data, struct ildb_private); -	if (handle->state == LDB_ASYNC_DONE) { -		return handle->status; +	if (req->starttime == 0 || req->timeout == 0) { +		ldb_set_errstring(module->ldb, "Invalid timeout settings"); +		return LDB_ERR_TIME_LIMIT_EXCEEDED;  	} -	if (!ac) { +	ac = talloc_zero(req, struct ildb_context); +	if (ac == NULL) { +		ldb_set_errstring(module->ldb, "Out of Memory");  		return LDB_ERR_OPERATIONS_ERROR;  	} -	handle->state = LDB_ASYNC_INIT; +	ac->module = module; +	ac->req = req; +	ac->ildb = ildb; + +	if (ildb_dn_is_special(req)) { -	switch(type) { -	case LDB_WAIT_NONE: -		if (event_loop_once(ac->req->conn->event.event_ctx) != 0) { -			return LDB_ERR_OTHER; +		te = event_add_timed(ac->ildb->event_ctx, +					ac, timeval_zero(), +					ildb_auto_done_callback, ac); +		if (NULL == te) { +			return LDB_ERR_OPERATIONS_ERROR;  		} + +		return LDB_SUCCESS; +	} + +	switch (ac->req->operation) { +	case LDB_SEARCH: +		ret = ildb_search(ac);  		break; -	case LDB_WAIT_ALL: -		while (handle->status == LDB_SUCCESS && handle->state != LDB_ASYNC_DONE) { -			if (event_loop_once(ac->req->conn->event.event_ctx) != 0) { -				return LDB_ERR_OTHER; -			} -		} +	case LDB_ADD: +		ret = ildb_add(ac); +		break; +	case LDB_MODIFY: +		ret = ildb_modify(ac); +		break; +	case LDB_DELETE: +		ret = ildb_delete(ac); +		break; +	case LDB_RENAME: +		ret = ildb_rename(ac);  		break;  	default: -		return LDB_ERR_OPERATIONS_ERROR; +		/* no other op supported */ +		ret = LDB_ERR_OPERATIONS_ERROR; +		break;  	} -	return handle->status; +	return ret;  }  static const struct ldb_module_ops ildb_ops = {  	.name              = "ldap", -	.search            = ildb_search, -	.add               = ildb_add, -	.modify            = ildb_modify, -	.del               = ildb_delete, -	.rename            = ildb_rename, -	.request           = ildb_request, +	.search            = ildb_handle_request, +	.add               = ildb_handle_request, +	.modify            = ildb_handle_request, +	.del               = ildb_handle_request, +	.rename            = ildb_handle_request, +/*	.request           = ildb_handle_request, */  	.start_transaction = ildb_start_trans,  	.end_transaction   = ildb_end_trans,  	.del_transaction   = ildb_del_trans, -	.wait              = ildb_wait  };  /* @@ -748,7 +741,6 @@ static int ildb_connect(struct ldb_context *ldb, const char *url,  	struct ildb_private *ildb;  	NTSTATUS status;  	struct cli_credentials *creds; -	struct event_context *event_ctx;  	module = talloc(ldb, struct ldb_module);  	if (!module) { @@ -758,7 +750,6 @@ static int ildb_connect(struct ldb_context *ldb, const char *url,  	talloc_set_name_const(module, "ldb_ildap backend");  	module->ldb		= ldb;  	module->prev		= module->next = NULL; -	module->private_data	= NULL;  	module->ops		= &ildb_ops;  	ildb = talloc(module, struct ildb_private); @@ -767,12 +758,12 @@ static int ildb_connect(struct ldb_context *ldb, const char *url,  		goto failed;  	}  	module->private_data	= ildb; -	ildb->module		= module; -	event_ctx = ldb_get_event_context(ldb); +	ildb->event_ctx = ldb_get_event_context(ldb); +  	ildb->ldap = ldap4_new_connection(ildb, ldb_get_opaque(ldb, "loadparm"), -					  event_ctx); +					  ildb->event_ctx);  	if (!ildb->ldap) {  		ldb_oom(ldb);  		goto failed; diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c index a4534c549a..7caee10b47 100644 --- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c +++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c @@ -45,17 +45,16 @@  struct lldb_private {  	LDAP *ldap; -	struct ldb_module *module;  };  struct lldb_context { +	struct ldb_module *module; +	struct ldb_request *req; +  	struct lldb_private *lldb; -	struct ldb_handle *handle; + +	struct ldb_control **controls;  	int msgid; -	int timeout; -	time_t starttime; -	void *context; -	int (*callback)(struct ldb_context *, void *, struct ldb_reply *);  };  static int lldb_ldap_to_ldb(int err) { @@ -63,42 +62,6 @@ static int lldb_ldap_to_ldb(int err) {  	return err;  } -static struct lldb_context *init_lldb_handle(struct lldb_private *lldb, struct ldb_request *req) -{ -	struct lldb_context *ac; -	struct ldb_handle *h; - -	h = talloc_zero(req, struct ldb_handle); -	if (h == NULL) { -		ldb_set_errstring(lldb->module->ldb, "Out of Memory"); -		return NULL; -	} - -	h->module = lldb->module; - -	ac = talloc(h, struct lldb_context); -	if (ac == NULL) { -		ldb_set_errstring(lldb->module->ldb, "Out of Memory"); -		talloc_free(h); -		return NULL; -	} - -	h->private_data = ac; - -	h->state = LDB_ASYNC_INIT; -	h->status = LDB_SUCCESS; - -	ac->lldb = lldb; -	ac->handle = h; -	ac->context = req->context; -	ac->callback = req->callback; -	ac->timeout = req->timeout; -	ac->starttime = req->starttime; -	ac->msgid = 0; - -	req->handle = h; -	return ac; -}  /*    convert a ldb_message structure to a list of LDAPMod structures    ready for ldap_add() or ldap_modify() @@ -230,10 +193,11 @@ static int lldb_add_msg_attr(struct ldb_context *ldb,  /*    search for matching records  */ -static int lldb_search(struct ldb_module *module, struct ldb_request *req) +static int lldb_search(struct lldb_context *lldb_ac)  { -	struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private); -	struct lldb_context *lldb_ac; +	struct lldb_private *lldb = lldb_ac->lldb; +	struct ldb_module *module = lldb_ac->module; +	struct ldb_request *req = lldb_ac->req;  	struct timeval tv;  	int ldap_scope;  	char *search_base; @@ -254,10 +218,7 @@ static int lldb_search(struct ldb_module *module, struct ldb_request *req)  		ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!\n");  	} -	lldb_ac = init_lldb_handle(lldb, req); -	if (lldb_ac == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	} +	req->handle->state = LDB_ASYNC_PENDING;  	search_base = ldb_dn_alloc_linearized(lldb_ac, req->op.search.base);  	if (req->op.search.base == NULL) { @@ -307,23 +268,16 @@ static int lldb_search(struct ldb_module *module, struct ldb_request *req)  /*    add a record  */ -static int lldb_add(struct ldb_module *module, struct ldb_request *req) +static int lldb_add(struct lldb_context *lldb_ac)  { -	struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private); -	struct lldb_context *lldb_ac; +	struct lldb_private *lldb = lldb_ac->lldb; +	struct ldb_module *module = lldb_ac->module; +	struct ldb_request *req = lldb_ac->req;  	LDAPMod **mods;  	char *dn;  	int ret; -	/* ltdb specials should not reach this point */ -	if (ldb_dn_is_special(req->op.add.message->dn)) { -		return LDB_ERR_INVALID_DN_SYNTAX; -	} - -	lldb_ac = init_lldb_handle(lldb, req); -	if (lldb_ac == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	} +	req->handle->state = LDB_ASYNC_PENDING;  	mods = lldb_msg_to_mods(lldb_ac, req->op.add.message, 0);  	if (mods == NULL) { @@ -350,23 +304,16 @@ static int lldb_add(struct ldb_module *module, struct ldb_request *req)  /*    modify a record  */ -static int lldb_modify(struct ldb_module *module, struct ldb_request *req) +static int lldb_modify(struct lldb_context *lldb_ac)  { -	struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private); -	struct lldb_context *lldb_ac; +	struct lldb_private *lldb = lldb_ac->lldb; +	struct ldb_module *module = lldb_ac->module; +	struct ldb_request *req = lldb_ac->req;  	LDAPMod **mods;  	char *dn;  	int ret; -	/* ltdb specials should not reach this point */ -	if (ldb_dn_is_special(req->op.mod.message->dn)) { -		return LDB_ERR_INVALID_DN_SYNTAX; -	} - -	lldb_ac = init_lldb_handle(lldb, req); -	if (req->handle == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	} +	req->handle->state = LDB_ASYNC_PENDING;  	mods = lldb_msg_to_mods(lldb_ac, req->op.mod.message, 1);  	if (mods == NULL) { @@ -393,22 +340,15 @@ static int lldb_modify(struct ldb_module *module, struct ldb_request *req)  /*    delete a record  */ -static int lldb_delete(struct ldb_module *module, struct ldb_request *req) +static int lldb_delete(struct lldb_context *lldb_ac)  { -	struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private); -	struct lldb_context *lldb_ac; +	struct lldb_private *lldb = lldb_ac->lldb; +	struct ldb_module *module = lldb_ac->module; +	struct ldb_request *req = lldb_ac->req;  	char *dnstr;  	int ret; -	 -	/* ltdb specials should not reach this point */ -	if (ldb_dn_is_special(req->op.del.dn)) { -		return LDB_ERR_INVALID_DN_SYNTAX; -	} -	lldb_ac = init_lldb_handle(lldb, req); -	if (lldb_ac == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	} +	req->handle->state = LDB_ASYNC_PENDING;  	dnstr = ldb_dn_alloc_linearized(lldb_ac, req->op.del.dn); @@ -427,24 +367,17 @@ static int lldb_delete(struct ldb_module *module, struct ldb_request *req)  /*    rename a record  */ -static int lldb_rename(struct ldb_module *module, struct ldb_request *req) +static int lldb_rename(struct lldb_context *lldb_ac)  { -	struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private); -	struct lldb_context *lldb_ac; +	struct lldb_private *lldb = lldb_ac->lldb; +	struct ldb_module *module = lldb_ac->module; +	struct ldb_request *req = lldb_ac->req;  	char *old_dn;         	char *newrdn;  	char *parentdn;  	int ret; -	 -	/* ltdb specials should not reach this point */ -	if (ldb_dn_is_special(req->op.rename.olddn) || ldb_dn_is_special(req->op.rename.newdn)) { -		return LDB_ERR_INVALID_DN_SYNTAX; -	} -	lldb_ac = init_lldb_handle(lldb, req); -	if (lldb_ac == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	} +	req->handle->state = LDB_ASYNC_PENDING;  	old_dn = ldb_dn_alloc_linearized(lldb_ac, req->op.rename.olddn);  	if (old_dn == NULL) { @@ -474,57 +407,99 @@ static int lldb_rename(struct ldb_module *module, struct ldb_request *req)  	return lldb_ldap_to_ldb(ret);  } -static int lldb_parse_result(struct lldb_context *ac, LDAPMessage *result) +static int lldb_start_trans(struct ldb_module *module) +{ +	/* TODO implement a local transaction mechanism here */ + +	return LDB_SUCCESS; +} + +static int lldb_end_trans(struct ldb_module *module) +{ +	/* TODO implement a local transaction mechanism here */ + +	return LDB_SUCCESS; +} + +static int lldb_del_trans(struct ldb_module *module) +{ +	/* TODO implement a local transaction mechanism here */ + +	return LDB_SUCCESS; +} + +void lldb_request_done(struct ldb_request *req, +			struct ldb_control **ctrls, int error) +{ +	struct ldb_reply *ares; + +	ares = talloc_zero(req, struct ldb_reply); +	if (!ares) { +		ldb_oom(req->handle->ldb); +		req->callback(req, NULL); +		return; +	} +	ares->type = LDB_REPLY_DONE; +	ares->controls = talloc_steal(ares, ctrls); +	ares->error = error; + +	req->callback(req, ares); +} + +/* return false if the request is still in progress + * return true if the request is completed + */ +static bool lldb_parse_result(struct lldb_context *ac, LDAPMessage *result)  { -	struct ldb_handle *handle = ac->handle;  	struct lldb_private *lldb = ac->lldb; -	struct ldb_reply *ares = NULL; -	LDAPMessage *msg; -	int type; +	LDAPControl **serverctrlsp = NULL; +	char **referralsp = NULL;  	char *matcheddnp = NULL;  	char *errmsgp = NULL; -	char **referralsp = NULL; -	LDAPControl **serverctrlsp = NULL; -	int ret = LDB_SUCCESS; -	 -	type = ldap_msgtype(result); +	LDAPMessage *msg; +	int type; +	struct ldb_message *ldbmsg; +	char *referral; +	bool callback_failed; +	bool request_done; +	bool lret; +	int ret; +	int i; -	handle->status = 0; +	type = ldap_msgtype(result); +	callback_failed = false; +	request_done = false;  	switch (type) { -  	case LDAP_RES_SEARCH_ENTRY: +  		msg = ldap_first_entry(lldb->ldap, result);  	       	if (msg != NULL) {  			BerElement *berptr = NULL;  			char *attr, *dn; -			ares = talloc_zero(ac, struct ldb_reply); -			if (!ares) { -				ret = LDB_ERR_OPERATIONS_ERROR; -				goto error; -			} - -			ares->message = ldb_msg_new(ares); -			if (!ares->message) { +			ldbmsg = ldb_msg_new(ac); +			if (!ldbmsg) {  				ret = LDB_ERR_OPERATIONS_ERROR; -				goto error; +				break;  			}  			dn = ldap_get_dn(lldb->ldap, msg);  			if (!dn) { +				talloc_free(ldbmsg);  				ret = LDB_ERR_OPERATIONS_ERROR; -				goto error; +				break;  			} -			ares->message->dn = ldb_dn_new(ares->message, ac->lldb->module->ldb, dn); -			if ( ! ldb_dn_validate(ares->message->dn)) { +			ldbmsg->dn = ldb_dn_new(ldbmsg, ac->module->ldb, dn); +			if ( ! ldb_dn_validate(ldbmsg->dn)) { +				talloc_free(ldbmsg);  				ret = LDB_ERR_OPERATIONS_ERROR; -				goto error; +				break;  			}  			ldap_memfree(dn); -			ares->message->num_elements = 0; -			ares->message->elements = NULL; +			ldbmsg->num_elements = 0; +			ldbmsg->elements = NULL;  			/* loop over all attributes */  			for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr); @@ -534,97 +509,104 @@ static int lldb_parse_result(struct lldb_context *ac, LDAPMessage *result)  				bval = ldap_get_values_len(lldb->ldap, msg, attr);  				if (bval) { -					lldb_add_msg_attr(ac->lldb->module->ldb, ares->message, attr, bval); +					lldb_add_msg_attr(ac->module->ldb, ldbmsg, attr, bval);  					ldap_value_free_len(bval); -				}					   +				}  			}  			if (berptr) ber_free(berptr, 0); +			ret = ldb_module_send_entry(ac->req, ldbmsg); +			if (ret != LDB_SUCCESS) { -			ares->type = LDB_REPLY_ENTRY; -			ret = ac->callback(ac->lldb->module->ldb, ac->context, ares); +				callback_failed = true; +			}  		} else { -			handle->status = LDB_ERR_PROTOCOL_ERROR; -			handle->state = LDB_ASYNC_DONE; +			ret = LDB_ERR_OPERATIONS_ERROR;  		}  		break;  	case LDAP_RES_SEARCH_REFERENCE: -		if (ldap_parse_result(lldb->ldap, result, &handle->status, + +		if (ldap_parse_result(lldb->ldap, result, &ret,  					&matcheddnp, &errmsgp,  					&referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) {  			ret = LDB_ERR_OPERATIONS_ERROR; -			goto error;  		} -		if (referralsp == NULL) { -			handle->status = LDB_ERR_PROTOCOL_ERROR; -			goto error; +		if (ret != LDB_SUCCESS) { +			break;  		} - -		ares = talloc_zero(ac, struct ldb_reply); -		if (!ares) { -			ret = LDB_ERR_OPERATIONS_ERROR; -			goto error; +		if (referralsp == NULL) { +			ret = LDB_ERR_PROTOCOL_ERROR; +			break;  		} -		ares->referral = talloc_strdup(ares, *referralsp); -		ares->type = LDB_REPLY_REFERRAL; -		ret = ac->callback(ac->lldb->module->ldb, ac->context, ares); +		for (i = 0; referralsp[i]; i++) { +			referral = talloc_strdup(ac, referralsp[i]); +			ret = ldb_module_send_referral(ac->req, referral); +			if (ret != LDB_SUCCESS) { +				callback_failed = true; +				break; +			} +		}  		break;  	case LDAP_RES_SEARCH_RESULT: -		if (ldap_parse_result(lldb->ldap, result, &handle->status, +	case LDAP_RES_MODIFY: +	case LDAP_RES_ADD: +	case LDAP_RES_DELETE: +	case LDAP_RES_MODDN: + +		if (ldap_parse_result(lldb->ldap, result, &ret,  					&matcheddnp, &errmsgp,  					&referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) { -			handle->status = LDB_ERR_OPERATIONS_ERROR; -			goto error; -		} - -		ares = talloc_zero(ac, struct ldb_reply); -		if (!ares) {  			ret = LDB_ERR_OPERATIONS_ERROR; -			goto error; +		} +		if (ret != LDB_SUCCESS) { +			break;  		}  		if (serverctrlsp != NULL) {  			/* FIXME: transform the LDAPControl list into an ldb_control one */ -			ares->controls = NULL; +			ac->controls = NULL;  		} -		 -		ares->type = LDB_REPLY_DONE; -		handle->state = LDB_ASYNC_DONE; -		ret = ac->callback(ac->lldb->module->ldb, ac->context, ares); - -		break; -	case LDAP_RES_MODIFY: -	case LDAP_RES_ADD: -	case LDAP_RES_DELETE: -	case LDAP_RES_MODDN: -		if (ldap_parse_result(lldb->ldap, result, &handle->status, -					&matcheddnp, &errmsgp, -					&referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) { -			handle->status = LDB_ERR_OPERATIONS_ERROR; -			goto error; -		} -		if (ac->callback && handle->status == LDB_SUCCESS) { -			ares = NULL; /* FIXME: build a corresponding ares to pass on */ -			ret = ac->callback(ac->lldb->module->ldb, ac->context, ares); -		} -		handle->state = LDB_ASYNC_DONE; +		request_done = true;  		break;  	default:  		ret = LDB_ERR_PROTOCOL_ERROR; -		goto error; +		break;  	} +	if (ret != LDB_SUCCESS) { + +		/* if the callback failed the caller will have freed the +		 * request. Just return and don't try to use it */ +		if (callback_failed) { + +			/* tell lldb_wait to remove the request from the +			 *  queue */ +			lret = true; +			goto free_and_return; +		} + +		request_done = true; +	} + +	if (request_done) { +		lldb_request_done(ac->req, ac->controls, ret); +		lret = true; +		goto free_and_return; +	} + +	lret = false; + +free_and_return: +  	if (matcheddnp) ldap_memfree(matcheddnp);  	if (errmsgp && *errmsgp) { -		ldb_set_errstring(ac->lldb->module->ldb, errmsgp); -	} else if (handle->status) { -		ldb_set_errstring(ac->lldb->module->ldb, ldap_err2string(handle->status)); +		ldb_set_errstring(ac->module->ldb, errmsgp);  	}  	if (errmsgp) {  		ldap_memfree(errmsgp); @@ -633,131 +615,203 @@ static int lldb_parse_result(struct lldb_context *ac, LDAPMessage *result)  	if (serverctrlsp) ldap_controls_free(serverctrlsp);  	ldap_msgfree(result); -	return lldb_ldap_to_ldb(handle->status); -error: -	handle->state = LDB_ASYNC_DONE; -	ldap_msgfree(result); -	return ret; +	return lret;  } -static int lldb_wait(struct ldb_handle *handle, enum ldb_wait_type type) +static void lldb_timeout(struct event_context *ev, +			 struct timed_event *te, +			 struct timeval t, +			 void *private_data)  { -	struct lldb_context *ac = talloc_get_type(handle->private_data, struct lldb_context); -	struct lldb_private *lldb = ac->lldb; -	struct timeval timeout; +	struct lldb_context *ac; +	ac = talloc_get_type(private_data, struct lldb_context); + +	lldb_request_done(ac->req, NULL, LDB_ERR_TIME_LIMIT_EXCEEDED); +} + +static void lldb_callback(struct event_context *ev, +			  struct timed_event *te, +			  struct timeval t, +			  void *private_data) +{ +	struct lldb_context *ac; +	struct timed_event *lte; +	struct timeval tv;  	LDAPMessage *result; -	int ret, lret; +	int lret; + +	ac = talloc_get_type(private_data, struct lldb_context); -	if (handle->state == LDB_ASYNC_DONE) { -		return handle->status; +	if (!ac->msgid) { +		lldb_request_done(ac->req, NULL, LDB_ERR_OPERATIONS_ERROR); +		return;  	} -	if (!ac || !ac->msgid) { -		return LDB_ERR_OPERATIONS_ERROR; +	tv.tv_sec = 0; +	tv.tv_usec = 0; +	lret = ldap_result(ac->lldb->ldap, ac->msgid, 0, &tv, &result); +	if (lret == 0) { +		goto respin; +	} +	if (lret == -1) { +		lldb_request_done(ac->req, NULL, LDB_ERR_OPERATIONS_ERROR); +		return;  	} -	handle->state = LDB_ASYNC_PENDING; -	handle->status = LDB_SUCCESS; +	if ( ! lldb_parse_result(ac, result)) { +		goto respin; +	} -	switch(type) { -	case LDB_WAIT_NONE: +	return; -		if ((ac->timeout != -1) && -		    ((ac->starttime + ac->timeout) > time(NULL))) { -			return LDB_ERR_TIME_LIMIT_EXCEEDED; -		} +respin: +	tv.tv_sec = 0; +	tv.tv_usec = 100; +	lte = event_add_timed(ev, ac, tv, lldb_callback, ac); +	if (NULL == lte) { +		lldb_request_done(ac->req, NULL, LDB_ERR_OPERATIONS_ERROR); +	} +} -		timeout.tv_sec = 0; -		timeout.tv_usec = 0; +static bool lldb_dn_is_special(struct ldb_request *req) +{ +	struct ldb_dn *dn = NULL; -		lret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result); -		if (lret == -1) { -			return LDB_ERR_OPERATIONS_ERROR; -		} -		if (lret == 0) { -			ret = LDB_SUCCESS; -			goto done; -		} +	switch (req->operation) { +	case LDB_ADD: +		dn = req->op.add.message->dn; +		break; +	case LDB_MODIFY: +		dn = req->op.mod.message->dn; +		break; +	case LDB_DELETE: +		dn = req->op.del.dn; +		break; +	case LDB_RENAME: +		dn = req->op.rename.olddn; +		break; +	default: +		break; +	} -		return lldb_parse_result(ac, result); +	if (dn && ldb_dn_is_special(dn)) { +		return true; +	} +	return false; +} -	case LDB_WAIT_ALL: -		timeout.tv_usec = 0; -		ret = LDB_ERR_OPERATIONS_ERROR; +static void lldb_auto_done_callback(struct event_context *ev, +				    struct timed_event *te, +				    struct timeval t, +				    void *private_data) +{ +	struct lldb_context *ac; -		while (handle->status == LDB_SUCCESS && handle->state != LDB_ASYNC_DONE) { +	ac = talloc_get_type(private_data, struct lldb_context); +	lldb_request_done(ac->req, NULL, LDB_SUCCESS); +} -			if (ac->timeout == -1) { -				lret = ldap_result(lldb->ldap, ac->msgid, 0, NULL, &result); -			} else { -				timeout.tv_sec = ac->timeout - (time(NULL) - ac->starttime); -				if (timeout.tv_sec <= 0) -					return LDB_ERR_TIME_LIMIT_EXCEEDED; -				lret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result); -			} -			if (lret == -1) { -				return LDB_ERR_OPERATIONS_ERROR; -			} -			if (lret == 0) { -				return LDB_ERR_TIME_LIMIT_EXCEEDED; -			} +static int lldb_handle_request(struct ldb_module *module, struct ldb_request *req) +{ +	struct lldb_private *lldb; +	struct lldb_context *ac; +	struct event_context *ev; +	struct timed_event *te; +	struct timeval tv; +	int ret; -			ret = lldb_parse_result(ac, result); -			if (ret != LDB_SUCCESS) { -				return ret; -			} +	lldb = talloc_get_type(module->private_data, struct lldb_private); + +	if (req->starttime == 0 || req->timeout == 0) { +		ldb_set_errstring(module->ldb, "Invalid timeout settings"); +		return LDB_ERR_TIME_LIMIT_EXCEEDED; +	} + +	ev = ldb_get_event_context(module->ldb); +	if (NULL == ev) { +		return LDB_ERR_OPERATIONS_ERROR; +	} + +	ac = talloc_zero(module->ldb, struct lldb_context); +	if (ac == NULL) { +		ldb_set_errstring(module->ldb, "Out of Memory"); +		return LDB_ERR_OPERATIONS_ERROR; +	} + +	ac->module = module; +	ac->req = req; +	ac->lldb = lldb; +	ac->msgid = 0; + +	if (lldb_dn_is_special(req)) { +		tv.tv_sec = 0; +		tv.tv_usec = 0; +		te = event_add_timed(ev, ac, tv, +				     lldb_auto_done_callback, ac); +		if (NULL == te) { +			return LDB_ERR_OPERATIONS_ERROR;  		} +		return LDB_SUCCESS; +	} + +	switch (ac->req->operation) { +	case LDB_SEARCH: +		ret = lldb_search(ac); +		break; +	case LDB_ADD: +		ret = lldb_add(ac); +		break; +	case LDB_MODIFY: +		ret = lldb_modify(ac); +		break; +	case LDB_DELETE: +		ret = lldb_delete(ac); +		break; +	case LDB_RENAME: +		ret = lldb_rename(ac);  		break; -		  	default: -		handle->state = LDB_ASYNC_DONE; +		/* no other op supported */  		ret = LDB_ERR_OPERATIONS_ERROR; +		break;  	} -done: -	return ret; -} - -static int lldb_start_trans(struct ldb_module *module) -{ -	/* TODO implement a local transaction mechanism here */ - -	return LDB_SUCCESS; -} +	if (ret != LDB_SUCCESS) { +		lldb_request_done(req, NULL, ret); +		return ret; +	} -static int lldb_end_trans(struct ldb_module *module) -{ -	/* TODO implement a local transaction mechanism here */ +	tv.tv_sec = 0; +	tv.tv_usec = 0; +	te = event_add_timed(ev, ac, tv, lldb_callback, ac); +	if (NULL == te) { +		return LDB_ERR_OPERATIONS_ERROR; +	} -	return LDB_SUCCESS; -} -static int lldb_del_trans(struct ldb_module *module) -{ -	/* TODO implement a local transaction mechanism here */ +	tv.tv_sec = req->starttime + req->timeout; +	tv.tv_usec = 0; +	te = event_add_timed(ev, ac, tv, lldb_timeout, ac); +	if (NULL == te) { +		return LDB_ERR_OPERATIONS_ERROR; +	}  	return LDB_SUCCESS;  } -static int lldb_request(struct ldb_module *module, struct ldb_request *req) -{ -	return LDB_ERR_OPERATIONS_ERROR; -} -  static const struct ldb_module_ops lldb_ops = {  	.name              = "ldap", -	.search            = lldb_search, -	.add               = lldb_add, -	.modify            = lldb_modify, -	.del               = lldb_delete, -	.rename            = lldb_rename, -	.request           = lldb_request, +	.search            = lldb_handle_request, +	.add               = lldb_handle_request, +	.modify            = lldb_handle_request, +	.del               = lldb_handle_request, +	.rename            = lldb_handle_request, +	.request           = lldb_handle_request,  	.start_transaction = lldb_start_trans,  	.end_transaction   = lldb_end_trans,  	.del_transaction   = lldb_del_trans, -	.wait              = lldb_wait  }; @@ -771,8 +825,8 @@ static int lldb_destructor(struct lldb_private *lldb)    connect to the database  */  static int lldb_connect(struct ldb_context *ldb, -			const char *url,  -			unsigned int flags,  +			const char *url, +			unsigned int flags,  			const char *options[],  			struct ldb_module **_module)  { @@ -790,7 +844,6 @@ static int lldb_connect(struct ldb_context *ldb,  	talloc_set_name_const(module, "ldb_ldap backend");  	module->ldb		= ldb;  	module->prev		= module->next = NULL; -	module->private_data	= NULL;  	module->ops		= &lldb_ops;  	lldb = talloc(module, struct lldb_private); @@ -799,7 +852,6 @@ static int lldb_connect(struct ldb_context *ldb,  		goto failed;  	}  	module->private_data	= lldb; -	lldb->module		= module;  	lldb->ldap		= NULL;  	ret = ldap_initialize(&lldb->ldap, url); diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c index a0e63c8da1..be99c29d1e 100644 --- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c +++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c @@ -44,51 +44,14 @@ struct lsqlite3_private {  struct lsql_context {  	struct ldb_module *module; +	struct ldb_request *req;  	/* search stuff */  	long long current_eid;  	const char * const * attrs;  	struct ldb_reply *ares; - -	/* async stuff */ -	void *context; -	int (*callback)(struct ldb_context *, void *, struct ldb_reply *);  }; -static struct ldb_handle *init_handle(struct lsqlite3_private *lsqlite3, -					struct ldb_module *module, -					struct ldb_request *req) -{ -	struct lsql_context *ac; -	struct ldb_handle *h; - -	h = talloc_zero(lsqlite3, struct ldb_handle); -	if (h == NULL) { -		ldb_set_errstring(module->ldb, "Out of Memory"); -		return NULL; -	} - -	h->module = module; - -	ac = talloc(h, struct lsql_context); -	if (ac == NULL) { -		ldb_set_errstring(module->ldb, "Out of Memory"); -		talloc_free(h); -		return NULL; -	} - -	h->private_data = (void *)ac; - -	h->state = LDB_ASYNC_INIT; -	h->status = LDB_SUCCESS; - -	ac->module = module; -	ac->context = req->context; -	ac->callback = req->callback; - -	return h; -} -  /*   * Macros used throughout   */ @@ -835,11 +798,6 @@ int lsql_search(struct ldb_module *module, struct ldb_request *req)  	char *query = NULL;          int ret; -	req->handle = init_handle(lsqlite3, module, req); -	if (req->handle == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	} -  	lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);  	if ((( ! ldb_dn_is_valid(req->op.search.base)) || ldb_dn_is_null(req->op.search.base)) && @@ -1013,10 +971,6 @@ static int lsql_add(struct ldb_module *module, struct ldb_request *req)  	int i;  	int ret = LDB_SUCCESS; -	req->handle = init_handle(lsqlite3, module, req); -	if (req->handle == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	}  	lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);  	req->handle->state = LDB_ASYNC_DONE;  	req->handle->status = LDB_SUCCESS; @@ -1143,10 +1097,6 @@ static int lsql_modify(struct ldb_module *module, struct ldb_request *req)  	int i;  	int ret = LDB_SUCCESS; -	req->handle = init_handle(lsqlite3, module, req); -	if (req->handle == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	}  	lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);  	req->handle->state = LDB_ASYNC_DONE;  	req->handle->status = LDB_SUCCESS; @@ -1329,10 +1279,6 @@ static int lsql_delete(struct ldb_module *module, struct ldb_request *req)  	int ret = LDB_SUCCESS; -	req->handle = init_handle(lsqlite3, module, req); -	if (req->handle == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	}  	lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);  	req->handle->state = LDB_ASYNC_DONE;  	req->handle->status = LDB_SUCCESS; @@ -1382,10 +1328,6 @@ static int lsql_rename(struct ldb_module *module, struct ldb_request *req)  	char *query;  	int ret = LDB_SUCCESS; -	req->handle = init_handle(lsqlite3, module, req); -	if (req->handle == NULL) { -		return LDB_ERR_OPERATIONS_ERROR; -	}  	lsql_ac = talloc_get_type(req->handle->private_data, struct lsql_context);  	req->handle->state = LDB_ASYNC_DONE;  	req->handle->status = LDB_SUCCESS; @@ -1501,9 +1443,61 @@ static int lsql_request(struct ldb_module *module, struct ldb_request *req)  	return LDB_ERR_OPERATIONS_ERROR;  } -static int lsql_wait(struct ldb_handle *handle, enum ldb_wait_type type) +static int lsql_run_request(struct ldb_module *module, struct ldb_request *req) +{ +	switch (req->operation) { +	case LDB_SEARCH: +		return lsql_search(module, req); +		break; +	case LDB_ADD: +		return lsql_add(module, req); +		break; +	case LDB_MODIFY: +		return lsql_modify(module, req); +		break; +	case LDB_DELETE: +		return lsql_delete(module, req); +		break; +	case LDB_RENAME: +		return lsql_rename(module, req); +		break; +/* TODO: +	case LDB_SEQUENCE_NUMBER: +		return lsql_sequence_number(module, req); +		break; + */ +	default: +		return lsql_request(module, req); +		break; +	} + +	return LDB_ERR_OPERATIONS_ERROR; +} + +static int lsql_handle_request(struct ldb_module *module, struct ldb_request *req)  { -	return handle->status; +	struct lsql_context *ac; + +	if (check_critical_controls(req->controls)) { +		return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; +	} + +	ac = talloc_zero(req, struct lsql_context); +	if (ac == NULL) { +		ldb_set_errstring(module->ldb, "Out of Memory"); +		return LDB_ERR_OPERATIONS_ERROR; +	} + +	ac->module = module; +	ac->req = req; + +	req->handle = ldb_handle_new(req, lsql_run_request, ac); +	if (req->handle == NULL) { +		talloc_free(ac); +		return LDB_ERR_OPERATIONS_ERROR; +	} + +	return LDB_SUCCESS;  }  /* @@ -1511,16 +1505,16 @@ static int lsql_wait(struct ldb_handle *handle, enum ldb_wait_type type)   */  static const struct ldb_module_ops lsqlite3_ops = {  	.name              = "sqlite", -	.search            = lsql_search, -	.add               = lsql_add, -        .modify            = lsql_modify, -        .del               = lsql_delete, -        .rename            = lsql_rename, -	.request           = lsql_request, +	.search            = lsql_handle_request, +	.add               = lsql_handle_request, +        .modify            = lsql_handle_request, +        .del               = lsql_handle_request, +        .rename            = lsql_handle_request, +	.request           = lsql_handle_request,  	.start_transaction = lsql_start_trans,  	.end_transaction   = lsql_end_trans,  	.del_transaction   = lsql_del_trans, -	.wait              = lsql_wait, +	/* TODO: .sequence_number   = lsql_handle_request */  };  /*  | 
