summaryrefslogtreecommitdiff
path: root/source4/ldap_server/ldap_rootdse.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/ldap_server/ldap_rootdse.c')
-rw-r--r--source4/ldap_server/ldap_rootdse.c235
1 files changed, 194 insertions, 41 deletions
diff --git a/source4/ldap_server/ldap_rootdse.c b/source4/ldap_server/ldap_rootdse.c
index 665bcde9af..b936c92da3 100644
--- a/source4/ldap_server/ldap_rootdse.c
+++ b/source4/ldap_server/ldap_rootdse.c
@@ -20,52 +20,121 @@
#include "includes.h"
-#define ATTR_BLOB_CONST(val) data_blob_talloc(attrs, val, sizeof(val)-1)
-#define ATTR_SINGLE_NOVAL(attr, blob, num, nam) do { \
- attr.name = talloc_strdup(attrs, nam);\
- if (!attr.name) {\
+#define ATTR_BLOB_CONST(val) data_blob_talloc(mem_ctx, val, sizeof(val)-1)
+#define ATTR_SINGLE_NOVAL(ctx, attr, blob, num, nam) do { \
+ attr->name = talloc_strdup(ctx, nam);\
+ if (!attr->name) {\
+ return NT_STATUS_NO_MEMORY;\
+ }\
+ attr->num_values = num; \
+ attr->values = blob;\
+} while(0)
+#define ALLOC_CHECK(ptr) do {\
+ if (!(ptr)) {\
return NT_STATUS_NO_MEMORY;\
}\
- attr.num_values = num; \
- attr.values = blob;\
} while(0)
-static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
- struct ldap_SearchRequest *r)
+
+struct rootdse_db_context {
+ struct ldb_context *ldb;
+ struct rootdse_db_context **static_ptr;
+};
+
+/*
+ this is used to catch debug messages from ldb
+*/
+void rootdse_db_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) _PRINTF_ATTRIBUTE(3,0)
{
- struct ldap_SearchResEntry *ent;
- struct ldap_Result *done;
- int code = 0;
- struct ldapsrv_reply *ent_r, *done_r;
- int num_attrs = 3;
- struct ldap_attribute *attrs;
+ char *s = NULL;
+ if (DEBUGLEVEL < 4 && level > LDB_DEBUG_WARNING) {
+ return;
+ }
+ vasprintf(&s, fmt, ap);
+ if (!s) return;
+ DEBUG(level, ("rootdse: %s\n", s));
+ free(s);
+}
- DEBUG(10, ("Root DSE: %s\n", r->filter));
- if (r->scope != LDAP_SEARCH_SCOPE_BASE) {
- code = 32; /* nosuchobject */
- goto no_base_scope;
+/* destroy the last connection to the sam */
+static int rootdse_db_destructor(void *ctx)
+{
+ struct rootdse_db_context *rd_ctx = ctx;
+ ldb_close(rd_ctx->ldb);
+ *(rd_ctx->static_ptr) = NULL;
+ return 0;
+}
+
+/*
+ connect to the SAM database
+ return an opaque context pointer on success, or NULL on failure
+ */
+void *rootdse_db_connect(TALLOC_CTX *mem_ctx)
+{
+ static struct rootdse_db_context *ctx;
+ char *db_path;
+ /*
+ the way that unix fcntl locking works forces us to have a
+ static ldb handle here rather than a much more sensible
+ approach of having the ldb handle as part of the
+ ldap base structures. Otherwise we would try to open
+ the ldb more than once, and tdb would rightly refuse the
+ second open due to the broken nature of unix locking.
+ */
+ if (ctx != NULL) {
+ return talloc_reference(mem_ctx, ctx);
}
- attrs = talloc_array_p(call, struct ldap_attribute, num_attrs);
- if (!attrs) {
- return NT_STATUS_NO_MEMORY;
+ ctx = talloc_p(mem_ctx, struct rootdse_db_context);
+ if (ctx == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ ctx->static_ptr = &ctx;
+
+ db_path = talloc_asprintf(ctx, "tdb://%s/rootdse.ldb", dyn_PRIVATE_DIR);
+ if (db_path == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ DEBUG(10, ("opening %s", db_path));
+ ctx->ldb = ldb_connect(db_path, 0, NULL);
+ if (ctx->ldb == NULL) {
+ talloc_free(ctx);
+ return NULL;
}
+ talloc_set_destructor(ctx, rootdse_db_destructor);
+ ldb_set_debug(ctx->ldb, rootdse_db_debug, NULL);
+
+ return ctx;
+}
+
+
+static NTSTATUS fill_dynamic_values(void *mem_ctx, struct ldap_attribute *attrs)
+{
/*
* currentTime
* 20040918090350.0Z
*/
+
+ DEBUG(10, ("fill_dynamic_values for %s\n", attrs[0].name));
+
+ if (strcasecmp(attrs->name, "currentTime") == 0)
{
int num_currentTime = 1;
- DATA_BLOB *currentTime = talloc_array_p(attrs, DATA_BLOB, num_currentTime);
- char *str = ldap_timestring(call, time(NULL));
+ DATA_BLOB *currentTime = talloc_array_p(mem_ctx, DATA_BLOB, num_currentTime);
+ char *str = ldap_timestring(mem_ctx, time(NULL));
if (!str) {
return NT_STATUS_NO_MEMORY;
}
currentTime[0].data = str;
currentTime[0].length = strlen(str);
- ATTR_SINGLE_NOVAL(attrs[0], currentTime, num_currentTime, "currentTime");
+ ATTR_SINGLE_NOVAL(mem_ctx, attrs, currentTime, num_currentTime, "currentTime");
+ return NT_STATUS_OK;
}
/*
@@ -137,11 +206,13 @@ static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldaps
* 3
* 2
*/
+ if (strcasecmp(attrs->name, "supportedLDAPVersion") == 0)
{
int num_supportedLDAPVersion = 1;
- DATA_BLOB *supportedLDAPVersion = talloc_array_p(attrs, DATA_BLOB, num_supportedLDAPVersion);
+ DATA_BLOB *supportedLDAPVersion = talloc_array_p(mem_ctx, DATA_BLOB, num_supportedLDAPVersion);
supportedLDAPVersion[0] = ATTR_BLOB_CONST("3");
- ATTR_SINGLE_NOVAL(attrs[1], supportedLDAPVersion, num_supportedLDAPVersion, "supportedLDAPVersion");
+ ATTR_SINGLE_NOVAL(mem_ctx, attrs, supportedLDAPVersion, num_supportedLDAPVersion, "supportedLDAPVersion");
+ return NT_STATUS_OK;
}
/*
@@ -177,12 +248,6 @@ static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldaps
* dnsHostName
* netbiosname.dom.tld
*/
- {
- int num_dnsHostName = 1;
- DATA_BLOB *dnsHostName = talloc_array_p(attrs, DATA_BLOB, num_dnsHostName);
- dnsHostName[0] = data_blob_talloc(attrs, lp_netbios_name(),strlen(lp_netbios_name()));
- ATTR_SINGLE_NOVAL(attrs[2], dnsHostName, num_dnsHostName, "dnsHostName");
- }
/*
* ldapServiceName
@@ -226,18 +291,89 @@ static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldaps
* 2
*/
+def:
+ {
+ DATA_BLOB *x = talloc_array_p(mem_ctx, DATA_BLOB, 1);
+ x[0] = ATTR_BLOB_CONST("0");
+ ATTR_SINGLE_NOVAL(mem_ctx, attrs, x, 1, attrs->name);
+ }
+ return NT_STATUS_OK;
+}
- ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
- if (!ent_r) {
- return NT_STATUS_NO_MEMORY;
+static NTSTATUS rootdse_Search(struct ldapsrv_partition *partition, struct ldapsrv_call *call,
+ struct ldap_SearchRequest *r)
+{
+ NTSTATUS status;
+ void *local_ctx;
+ struct ldap_SearchResEntry *ent;
+ struct ldap_Result *done;
+ struct ldb_message **res;
+ int result = 0;
+ struct ldapsrv_reply *ent_r, *done_r;
+ struct rootdse_db_context *rootdsedb;
+ const char *errstr = NULL;
+ int count, i, j, y;
+
+ if (r->scope != LDAP_SEARCH_SCOPE_BASE) {
+ count = -1;
+ goto no_base_scope;
+ }
+
+ local_ctx = talloc_named(call, 0, "rootdse_Search local memory context");
+ ALLOC_CHECK(local_ctx);
+
+ rootdsedb = rootdse_db_connect(local_ctx);
+ ALLOC_CHECK(rootdsedb);
+
+ ldb_set_alloc(rootdsedb->ldb, talloc_realloc_fn, rootdsedb);
+ count = ldb_search(rootdsedb->ldb, "", 0, "dn=rootDSE", NULL, &res);
+
+ for (i = 0; i < count; i++) {
+ ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
+ if (!ent_r) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ent = &ent_r->msg.r.SearchResultEntry;
+ ent->dn = "";
+ ent->num_attributes = 0;
+ ent->attributes = NULL;
+ if (res[i]->num_elements == 0) {
+ goto queue_reply;
+ }
+ ent->num_attributes = res[i]->num_elements;
+ ent->attributes = talloc_array_p(ent_r, struct ldap_attribute, ent->num_attributes);
+ 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);
+ ent->attributes[j].num_values = 0;
+ ent->attributes[j].values = NULL;
+ ent->attributes[j].num_values = res[i]->elements[j].num_values;
+ if (ent->attributes[j].num_values == 1 &&
+ strncmp(res[i]->elements[j].values[0].data, "_DYNAMIC_", 9) == 0) {
+ fill_dynamic_values(ent->attributes, &(ent->attributes[j]));
+ if (ent->attributes[j].values[0].data == NULL) {
+ DEBUG (10, ("ARRGHH!\n"));
+ }
+ } else {
+ ent->attributes[j].values = talloc_array_p(ent->attributes,
+ DATA_BLOB, ent->attributes[j].num_values);
+ 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,
+ res[i]->elements[j].values[y].data);
+ }
+ }
+ }
+queue_reply:
+ status = ldapsrv_queue_reply(call, ent_r);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
}
- ent = &ent_r->msg.r.SearchResultEntry;
- ent->dn = "";
- ent->num_attributes = num_attrs;
- ent->attributes = attrs;
- ldapsrv_queue_reply(call, ent_r);
no_base_scope:
@@ -246,12 +382,29 @@ no_base_scope:
return NT_STATUS_NO_MEMORY;
}
+ if (count > 0) {
+ DEBUG(10,("rootdse_Search: results: [%d]\n",count));
+ result = 0;
+ errstr = NULL;
+ } else if (count == 0) {
+ DEBUG(10,("rootdse_Search: no results\n"));
+ result = 32; /* nosuchobject */
+ errstr = talloc_strdup(done_r, ldb_errstring(rootdsedb->ldb));
+ } else if (count == -1) {
+ DEBUG(10,("rootdse_Search: error\n"));
+ result = 1;
+ errstr = talloc_strdup(done_r, ldb_errstring(rootdsedb->ldb));
+ }
+
+
done = &done_r->msg.r.SearchResultDone;
- done->resultcode = code;
+ done->resultcode = result;
done->dn = NULL;
done->errormessage = NULL;
done->referral = NULL;
+ talloc_free(local_ctx);
+
return ldapsrv_queue_reply(call, done_r);
}