/*
close the socket and shutdown a server_context
*/
-void ldapsrv_terminate_connection(struct ldapsrv_connection *ldap_conn, const char *reason)
+static void ldapsrv_terminate_connection(struct ldapsrv_connection *ldap_conn, const char *reason)
{
server_terminate_connection(ldap_conn->connection, reason);
}
status = socket_recv(sock, sock, &tmp_blob, 1024, 0);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("socket_recv: %s\n",nt_errstr(status)));
+ DEBUG(1,("socket_recv: %s\n",nt_errstr(status)));
return False;
}
return reply;
}
-void ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
+NTSTATUS ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
{
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
+ return NT_STATUS_OK;
}
struct ldapsrv_partition *ldapsrv_get_partition(struct ldapsrv_connection *conn, const char *dn)
{
static struct ldapsrv_partition null_part;
- null_part.ops = ldapsrv_get_sldb_partition_ops();
+ if (strcasecmp("", dn) == 0) {
+ null_part.ops = ldapsrv_get_rootdse_partition_ops();
+ } else {
+ null_part.ops = ldapsrv_get_sldb_partition_ops();
+ }
return &null_part;
}
-void ldapsrv_unwilling(struct ldapsrv_call *call, int error)
+NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
{
struct ldapsrv_reply *reply;
struct ldap_ExtendedResponse *r;
reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
if (!reply) {
- ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
- return;
+ return NT_STATUS_NO_MEMORY;
}
r = &reply->msg.r.ExtendedResponse;
r->value.data = NULL;
r->value.length = 0;
- ldapsrv_queue_reply(call, reply);
+ return ldapsrv_queue_reply(call, reply);
}
-static void ldapsrv_BindRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
{
struct ldap_BindRequest *req = &call->request.r.BindRequest;
struct ldapsrv_reply *reply;
reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
if (!reply) {
- ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
- return;
+ return NT_STATUS_NO_MEMORY;
}
resp = &reply->msg.r.BindResponse;
resp->response.referral = NULL;
resp->SASL.secblob = data_blob(NULL, 0);
- ldapsrv_queue_reply(call, reply);
+ return ldapsrv_queue_reply(call, reply);
}
-static void ldapsrv_UnbindRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_UnbindRequest(struct ldapsrv_call *call)
{
/* struct ldap_UnbindRequest *req = &call->request->r.UnbindRequest;*/
DEBUG(10, ("UnbindRequest\n"));
+ return NT_STATUS_OK;
}
-static void ldapsrv_SearchRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
{
struct ldap_SearchRequest *req = &call->request.r.SearchRequest;
struct ldapsrv_partition *part;
DEBUGADD(10, (" basedn: %s", req->basedn));
DEBUGADD(10, (" filter: %s\n", req->filter));
- if (strcasecmp("", req->basedn) == 0) {
- ldapsrv_RootDSE_Search(call, req);
- return;
- }
-
part = ldapsrv_get_partition(call->conn, req->basedn);
if (!part->ops->Search) {
done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
if (!done_r) {
- ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
- return;
+ return NT_STATUS_NO_MEMORY;
}
done = &done_r->msg.r.SearchResultDone;
done->errormessage = NULL;
done->referral = NULL;
- ldapsrv_queue_reply(call, done_r);
- return;
+ return ldapsrv_queue_reply(call, done_r);
}
- part->ops->Search(part, call, req);
+ return part->ops->Search(part, call, req);
}
-static void ldapsrv_ModifyRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
{
struct ldap_ModifyRequest *req = &call->request.r.ModifyRequest;
struct ldapsrv_partition *part;
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->Modify) {
- ldapsrv_unwilling(call, 53);
- return;
+ return ldapsrv_unwilling(call, 53);
}
- part->ops->Modify(part, call, req);
+ return part->ops->Modify(part, call, req);
}
-static void ldapsrv_AddRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
{
struct ldap_AddRequest *req = &call->request.r.AddRequest;
struct ldapsrv_partition *part;
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->Add) {
- ldapsrv_unwilling(call, 53);
- return;
+ return ldapsrv_unwilling(call, 53);
}
- part->ops->Add(part, call, req);
+ return part->ops->Add(part, call, req);
}
-static void ldapsrv_DelRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_DelRequest(struct ldapsrv_call *call)
{
struct ldap_DelRequest *req = &call->request.r.DelRequest;
struct ldapsrv_partition *part;
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->Del) {
- ldapsrv_unwilling(call, 53);
- return;
+ return ldapsrv_unwilling(call, 53);
}
- part->ops->Del(part, call, req);
+ return part->ops->Del(part, call, req);
}
-static void ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
{
struct ldap_ModifyDNRequest *req = &call->request.r.ModifyDNRequest;
struct ldapsrv_partition *part;
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->ModifyDN) {
- ldapsrv_unwilling(call, 53);
- return;
+ return ldapsrv_unwilling(call, 53);
}
- part->ops->ModifyDN(part, call, req);
+ return part->ops->ModifyDN(part, call, req);
}
-static void ldapsrv_CompareRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_CompareRequest(struct ldapsrv_call *call)
{
struct ldap_CompareRequest *req = &call->request.r.CompareRequest;
struct ldapsrv_partition *part;
part = ldapsrv_get_partition(call->conn, req->dn);
if (!part->ops->Compare) {
- ldapsrv_unwilling(call, 53);
- return;
+ return ldapsrv_unwilling(call, 53);
}
- part->ops->Compare(part, call, req);
+ return part->ops->Compare(part, call, req);
}
-static void ldapsrv_AbandonRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)
{
/* struct ldap_AbandonRequest *req = &call->request.r.AbandonRequest;*/
DEBUG(10, ("AbandonRequest\n"));
+ return NT_STATUS_OK;
}
-static void ldapsrv_ExtendedRequest(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_ExtendedRequest(struct ldapsrv_call *call)
{
/* struct ldap_ExtendedRequest *req = &call->request.r.ExtendedRequest;*/
struct ldapsrv_reply *reply;
reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
if (!reply) {
- ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
- return;
+ return NT_STATUS_NO_MEMORY;
}
ZERO_STRUCT(reply->msg.r);
- ldapsrv_queue_reply(call, reply);
+ return ldapsrv_queue_reply(call, reply);
}
-static void ldapsrv_do_call(struct ldapsrv_call *call)
+static NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
{
switch(call->request.type) {
case LDAP_TAG_BindRequest:
- ldapsrv_BindRequest(call);
- break;
+ return ldapsrv_BindRequest(call);
case LDAP_TAG_UnbindRequest:
- ldapsrv_UnbindRequest(call);
- break;
+ return ldapsrv_UnbindRequest(call);
case LDAP_TAG_SearchRequest:
- ldapsrv_SearchRequest(call);
- break;
+ return ldapsrv_SearchRequest(call);
case LDAP_TAG_ModifyRequest:
- ldapsrv_ModifyRequest(call);
- break;
+ return ldapsrv_ModifyRequest(call);
case LDAP_TAG_AddRequest:
- ldapsrv_AddRequest(call);
- break;
+ return ldapsrv_AddRequest(call);
case LDAP_TAG_DelRequest:
- ldapsrv_DelRequest(call);
- break;
+ return ldapsrv_DelRequest(call);
case LDAP_TAG_ModifyDNRequest:
- ldapsrv_ModifyDNRequest(call);
- break;
+ return ldapsrv_ModifyDNRequest(call);
case LDAP_TAG_CompareRequest:
- ldapsrv_CompareRequest(call);
- break;
+ return ldapsrv_CompareRequest(call);
case LDAP_TAG_AbandonRequest:
- ldapsrv_AbandonRequest(call);
- break;
+ return ldapsrv_AbandonRequest(call);
case LDAP_TAG_ExtendedRequest:
- ldapsrv_ExtendedRequest(call);
- break;
+ return ldapsrv_ExtendedRequest(call);
default:
- ldapsrv_unwilling(call, 2);
- break;
+ return ldapsrv_unwilling(call, 2);
}
}
-static void ldapsrv_do_responses(struct ldapsrv_connection *conn)
+static NTSTATUS ldapsrv_do_responses(struct ldapsrv_connection *conn)
{
struct ldapsrv_call *call, *next_call = NULL;
struct ldapsrv_reply *reply, *next_reply = NULL;
for (call=conn->calls; call; call=next_call) {
for (reply=call->replies; reply; reply=next_reply) {
if (!ldap_append_to_buf(&reply->msg, &conn->out_buffer)) {
- ldapsrv_terminate_connection(conn, "append_to_buf() failed");
- return;
+ return NT_STATUS_FOOBAR;
}
next_reply = reply->next;
DLIST_REMOVE(call->replies, reply);
call->state = LDAPSRV_CALL_STATE_COMPLETE;
talloc_free(call);
}
+
+ return NT_STATUS_OK;
}
/*
DATA_BLOB blob;
ASN1_DATA data;
struct ldapsrv_call *call;
+ NTSTATUS status;
DEBUG(10,("ldapsrv_recv\n"));
ZERO_STRUCTP(call);
call->state = LDAPSRV_CALL_STATE_NEW;
call->conn = ldap_conn;
+ /* TODO: we should use talloc_reference() here */
+ call->session_info = ldap_conn->session_info;
call->request.mem_ctx = call;
if (!ldap_decode(&data, &call->request)) {
consumed_from_buf(&ldap_conn->in_buffer, msg_length);
- ldapsrv_do_call(call);
+ status = ldapsrv_do_call(call);
+ if (!NT_STATUS_IS_OK(status)) {
+ ldapsrv_terminate_connection(ldap_conn, "ldapsrv_do_call() failed");
+ return;
+ }
peek_into_read_buf(&ldap_conn->in_buffer, &buf, &buf_length);
}
- ldapsrv_do_responses(ldap_conn);
+ status = ldapsrv_do_responses(ldap_conn);
+ if (!NT_STATUS_IS_OK(status)) {
+ ldapsrv_terminate_connection(ldap_conn, "ldapsrv_do_responses() failed");
+ return;
+ }
if (ldap_conn->out_buffer.length > 0) {
conn->event.fde->flags |= EVENT_FD_WRITE;
static void ldapsrv_close(struct server_connection *conn, const char *reason)
{
- struct ldapsrv_connection *ldap_conn = conn->private_data;
-
- talloc_free(ldap_conn);
-
return;
}
};
-#define ALLOC_CHECK(ptr, call) do {\
+#define ALLOC_CHECK(ptr) do {\
if (!(ptr)) {\
- ldapsrv_terminate_connection(call->conn, "no memory");\
return NT_STATUS_NO_MEMORY;\
}\
} while(0)
static NTSTATUS sldb_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
struct ldap_SearchRequest *r)
{
+ NTSTATUS status;
struct ldap_Result *done;
struct ldap_SearchResEntry *ent;
struct ldapsrv_reply *ent_r, *done_r;
- int result = 32;
+ int result = 80;
struct samdb_context *samdb;
struct ldb_message **res;
int i, j, y, count;
struct ldb_context *ldb;
enum ldb_scope scope = LDB_SCOPE_DEFAULT;
+ const char **attrs = NULL;
DEBUG(0, ("sldb_Search: %s\n", r->filter));
break;
}
+ if (r->num_attributes >= 1) {
+ attrs = talloc_array_p(samdb, const char *, r->num_attributes+1);
+ ALLOC_CHECK(attrs);
+
+ for (i=0; i < r->num_attributes; i++) {
+ attrs[i] = r->attributes[i];
+ }
+ attrs[i] = NULL;
+ }
+
ldb_set_alloc(ldb, talloc_ldb_alloc, samdb);
- count = ldb_search(ldb, r->basedn, scope, r->filter, r->attributes, &res);
+ count = ldb_search(ldb, r->basedn, scope, r->filter, attrs, &res);
- if (count == 0) {
+ if (count > 0) {
+ result = 0;
+ } else if (count == 0) {
result = 32;
} else if (count == -1) {
- result = 80;
+ result = 1;
}
for (i=0; i < count; i++) {
ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
- if (!ent_r) {
- ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
- return NT_STATUS_NO_MEMORY;
- }
+ ALLOC_CHECK(ent_r);
ent = &ent_r->msg.r.SearchResultEntry;
ent->dn = talloc_steal(ent_r, res[i]->dn);
+ ent->num_attributes = 0;
+ ent->attributes = NULL;
+ if (res[i]->num_elements == 0) {
+ continue;
+ }
ent->num_attributes = res[i]->num_elements;
ent->attributes = talloc_array_p(ent_r, struct ldap_attribute, ent->num_attributes);
- ALLOC_CHECK(ent->attributes, call);
+ ALLOC_CHECK(ent->attributes);
for (j=0; j < ent->num_attributes; j++) {
ent->attributes[j].name = talloc_steal(ent->attributes, res[i]->elements[j].name);
- if (r->attributesonly) {
- ent->attributes[j].num_values = 0;
- ent->attributes[j].values = NULL;
+ ent->attributes[j].num_values = 0;
+ ent->attributes[j].values = NULL;
+ if (r->attributesonly && (res[i]->elements[j].num_values == 0)) {
continue;
}
ent->attributes[j].num_values = res[i]->elements[j].num_values;
ent->attributes[j].values = talloc_array_p(ent->attributes,
DATA_BLOB, ent->attributes[j].num_values);
- ALLOC_CHECK(ent->attributes[j].values, call);
+ ALLOC_CHECK(ent->attributes[j].values);
for (y=0; y < ent->attributes[j].num_values; y++) {
ent->attributes[j].values[y].length = res[i]->elements[j].values[y].length;
ent->attributes[j].values[y].data = talloc_steal(ent->attributes[j].values,
}
}
- ldapsrv_queue_reply(call, ent_r);
+ status = ldapsrv_queue_reply(call, ent_r);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
}
talloc_free(samdb);
done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
- if (!done_r) {
- ldapsrv_terminate_connection(call->conn, "ldapsrv_init_reply() failed");
- return NT_STATUS_NO_MEMORY;
- }
+ ALLOC_CHECK(done_r);
done = &done_r->msg.r.SearchResultDone;
done->resultcode = result;
done->errormessage = NULL;
done->referral = NULL;
- ldapsrv_queue_reply(call, done_r);
-
- return NT_STATUS_OK;
+ return ldapsrv_queue_reply(call, done_r);
}
static const struct ldapsrv_partition_ops sldb_ops = {