1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-02 09:47:23 +03:00

r21496: A number of ldb control and LDAP changes, surrounding the

'phantom_root' flag in the search_options control

- Add in support for LDB controls to the js layer
- Test the behaviour
- Implement support for the 'phantom_root' flag in the partitions module
- Make the LDAP server set the 'phantom_root' flag in the search_options control
  - This replaces the global_catalog flag passed down as an opaque pointer
- Rework the string-format control parsing function into
  ldb_parse_control_strings(), returning errors by ldb_errorstring()
  method, rather than with printf to stderr
- Rework some of the ldb_control handling logic

Andrew Bartlett
(This used to be commit 2b3df7f38d7790358dbb4de1b8609bf794a351fb)
This commit is contained in:
Andrew Bartlett 2007-02-22 01:54:40 +00:00 committed by Gerald (Jerry) Carter
parent 81adf162a8
commit 7dc7156bd7
15 changed files with 603 additions and 413 deletions

View File

@ -215,7 +215,7 @@ static int extended_search(struct ldb_module *module, struct ldb_request *req)
int ret;
/* check if there's an extended dn control */
control = get_control_from_list(req->controls, LDB_CONTROL_EXTENDED_DN_OID);
control = ldb_request_get_control(req, LDB_CONTROL_EXTENDED_DN_OID);
if (control == NULL) {
/* not found go on */
return ldb_next_request(module, req);

View File

@ -1,3 +1,4 @@
/*
Partitions ldb module
@ -219,16 +220,26 @@ static int partition_send_request(struct partition_context *ac, struct dsdb_cont
ac->down_req = talloc_realloc(ac, ac->down_req,
struct ldb_request *, ac->num_requests + 1);
if (!ac->down_req) {
ldb_set_errstring(ac->module->ldb, "Out of Memory");
ldb_oom(ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
req = ac->down_req[ac->num_requests] = talloc(ac, struct ldb_request);
if (req == NULL) {
ldb_set_errstring(ac->module->ldb, "Out of Memory");
ldb_oom(ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
*ac->down_req[ac->num_requests] = *ac->orig_req; /* copy the request */
*req = *ac->orig_req; /* copy the request */
if (ac->orig_req->controls) {
req->controls
= talloc_memdup(req,
ac->orig_req->controls, talloc_get_size(ac->orig_req->controls));
if (req->controls == NULL) {
ldb_oom(ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
}
if (req->operation == LDB_SEARCH) {
/* If the search is for 'more' than this partition,
@ -350,7 +361,14 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req)
/* (later) consider if we should be searching multiple
* partitions (for 'invisible' partition behaviour */
if (ldb_get_opaque(module->ldb, "global_catalog")) {
struct ldb_control *search_control = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID);
struct ldb_search_options_control *search_options = NULL;
if (search_control) {
search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
}
if (search_options && (search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT)) {
int ret, i;
struct partition_context *ac;

View File

@ -260,7 +260,7 @@ static int replmd_prepare_originating(struct ldb_module *module, struct ldb_requ
return LDB_ERR_CONSTRAINT_VIOLATION;
}
partition_ctrl = get_control_from_list(req->controls, DSDB_CONTROL_CURRENT_PARTITION_OID);
partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
if (!partition_ctrl) {
ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
"%s: no current partition control found",

View File

@ -96,7 +96,7 @@ static int show_deleted_search(struct ldb_module *module, struct ldb_request *re
int ret;
/* check if there's a show deleted control */
control = get_control_from_list(req->controls, LDB_CONTROL_SHOW_DELETED_OID);
control = ldb_request_get_control(req, LDB_CONTROL_SHOW_DELETED_OID);
/* copy the request for modification */
down_req = talloc(req, struct ldb_request);

View File

@ -90,10 +90,6 @@ NTSTATUS ldapsrv_backend_Init(struct ldapsrv_connection *conn)
ldb_set_opaque(conn->ldb, "supportedSASLMechanims", sasl_mechs);
}
if (conn->global_catalog) {
ldb_set_opaque(conn->ldb, "global_catalog", (void *)(-1));
}
return NT_STATUS_OK;
}
@ -229,6 +225,21 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
lreq->controls = call->request->controls;
if (call->conn->global_catalog) {
struct ldb_control *search_control = ldb_request_get_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID);
struct ldb_search_options_control *search_options = NULL;
if (search_control) {
search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
search_options->search_options |= LDB_SEARCH_OPTION_PHANTOM_ROOT;
} else {
search_options = talloc(lreq, struct ldb_search_options_control);
NT_STATUS_HAVE_NO_MEMORY(search_options);
search_options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
ldb_request_add_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID, false, search_options);
}
}
lreq->context = res;
lreq->callback = ldb_search_default_callback;

View File

@ -37,19 +37,19 @@
/* check if a control with the specified "oid" exist and return it */
/* returns NULL if not found */
struct ldb_control *get_control_from_list(struct ldb_control **controls, const char *oid)
struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid)
{
int i;
/* check if there's a paged request control */
if (controls != NULL) {
for (i = 0; controls[i]; i++) {
if (strcmp(oid, controls[i]->oid) == 0) {
if (req->controls != NULL) {
for (i = 0; req->controls[i]; i++) {
if (strcmp(oid, req->controls[i]->oid) == 0) {
break;
}
}
return controls[i];
return req->controls[i];
}
return NULL;
@ -132,3 +132,440 @@ int ldb_request_add_control(struct ldb_request *req, const char *oid, bool criti
ctrls[n] = ctrl;
return LDB_SUCCESS;
}
/* Parse controls from the format used on the command line and in ejs */
struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *mem_ctx, const char **control_strings)
{
int i;
struct ldb_control **ctrl;
char *error_string = NULL;
if (control_strings == NULL || control_strings[0] == NULL)
return NULL;
for (i = 0; control_strings[i]; i++);
ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
for (i = 0; control_strings[i]; i++) {
if (strncmp(control_strings[i], "vlv:", 4) == 0) {
struct ldb_vlv_req_control *control;
const char *p;
char attr[1024];
char ctxid[1024];
int crit, bc, ac, os, cc, ret;
attr[0] = '\0';
ctxid[0] = '\0';
p = &(control_strings[i][4]);
ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
if (ret < 5) {
ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
}
if ((ret < 4) || (crit < 0) || (crit > 1)) {
error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, s = string, o = b64 binary blob");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID;
ctrl[i]->critical = crit;
if (!(control = talloc(ctrl[i],
struct ldb_vlv_req_control))) {
ldb_oom(ldb);
return NULL;
}
control->beforeCount = bc;
control->afterCount = ac;
if (attr[0]) {
control->type = 1;
control->match.gtOrEq.value = talloc_strdup(control, attr);
control->match.gtOrEq.value_len = strlen(attr);
} else {
control->type = 0;
control->match.byOffset.offset = os;
control->match.byOffset.contentCount = cc;
}
if (ctxid[0]) {
control->ctxid_len = ldb_base64_decode(ctxid);
control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
} else {
control->ctxid_len = 0;
control->contextId = NULL;
}
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "dirsync:", 8) == 0) {
struct ldb_dirsync_control *control;
const char *p;
char cookie[1024];
int crit, flags, max_attrs, ret;
cookie[0] = '\0';
p = &(control_strings[i][8]);
ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) {
error_string = talloc_asprintf(mem_ctx, "invalid dirsync control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number, o = b64 binary blob");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
/* w2k3 seems to ignore the parameter,
* but w2k sends a wrong cookie when this value is to small
* this would cause looping forever, while getting
* the same data and same cookie forever
*/
if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_DIRSYNC_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_dirsync_control);
control->flags = flags;
control->max_attributes = max_attrs;
if (*cookie) {
control->cookie_len = ldb_base64_decode(cookie);
control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
} else {
control->cookie = NULL;
control->cookie_len = 0;
}
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "asq:", 4) == 0) {
struct ldb_asq_control *control;
const char *p;
char attr[256];
int crit, ret;
attr[0] = '\0';
p = &(control_strings[i][4]);
ret = sscanf(p, "%d:%255[^$]", &crit, attr);
if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
error_string = talloc_asprintf(mem_ctx, "invalid asq control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b):attr(s)\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_ASQ_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_asq_control);
control->request = 1;
control->source_attribute = talloc_strdup(control, attr);
control->src_attr_len = strlen(attr);
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "extended_dn:", 12) == 0) {
struct ldb_extended_dn_control *control;
const char *p;
int crit, type, ret;
p = &(control_strings[i][12]);
ret = sscanf(p, "%d:%d", &crit, &type);
if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
error_string = talloc_asprintf(mem_ctx, "invalid extended_dn control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b):type(b)\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_extended_dn_control);
control->type = type;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "sd_flags:", 9) == 0) {
struct ldb_sd_flags_control *control;
const char *p;
int crit, ret;
unsigned secinfo_flags;
p = &(control_strings[i][9]);
ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) {
error_string = talloc_asprintf(mem_ctx, "invalid sd_flags control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b):secinfo_flags(n)\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_SD_FLAGS_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_sd_flags_control);
control->secinfo_flags = secinfo_flags;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "search_options:", 15) == 0) {
struct ldb_search_options_control *control;
const char *p;
int crit, ret;
unsigned search_options;
p = &(control_strings[i][15]);
ret = sscanf(p, "%d:%u", &crit, &search_options);
if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) {
error_string = talloc_asprintf(mem_ctx, "invalid search_options control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b):search_options(n)\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_search_options_control);
control->search_options = search_options;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "domain_scope:", 13) == 0) {
const char *p;
int crit, ret;
p = &(control_strings[i][13]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
error_string = talloc_asprintf(mem_ctx, "invalid domain_scope control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
ctrl[i]->critical = crit;
ctrl[i]->data = NULL;
continue;
}
if (strncmp(control_strings[i], "paged_results:", 14) == 0) {
struct ldb_paged_control *control;
const char *p;
int crit, size, ret;
p = &(control_strings[i][14]);
ret = sscanf(p, "%d:%d", &crit, &size);
if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
error_string = talloc_asprintf(mem_ctx, "invalid paged_results control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b):size(n)\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean, n = number");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_paged_control);
control->size = size;
control->cookie = NULL;
control->cookie_len = 0;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "server_sort:", 12) == 0) {
struct ldb_server_sort_control **control;
const char *p;
char attr[256];
char rule[128];
int crit, rev, ret;
attr[0] = '\0';
rule[0] = '\0';
p = &(control_strings[i][12]);
ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
error_string = talloc_asprintf(mem_ctx, "invalid server_sort control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean, s = string");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID;
ctrl[i]->critical = crit;
control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2);
control[0] = talloc(control, struct ldb_server_sort_control);
control[0]->attributeName = talloc_strdup(control, attr);
if (rule[0])
control[0]->orderingRule = talloc_strdup(control, rule);
else
control[0]->orderingRule = NULL;
control[0]->reverse = rev;
control[1] = NULL;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "notification:", 13) == 0) {
const char *p;
int crit, ret;
p = &(control_strings[i][13]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
error_string = talloc_asprintf(mem_ctx, "invalid notification control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID;
ctrl[i]->critical = crit;
ctrl[i]->data = NULL;
continue;
}
if (strncmp(control_strings[i], "show_deleted:", 13) == 0) {
const char *p;
int crit, ret;
p = &(control_strings[i][13]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
error_string = talloc_asprintf(mem_ctx, "invalid show_deleted control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_SHOW_DELETED_OID;
ctrl[i]->critical = crit;
ctrl[i]->data = NULL;
continue;
}
if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
const char *p;
int crit, ret;
p = &(control_strings[i][18]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
error_string = talloc_asprintf(mem_ctx, "invalid permissive_modify control syntax\n");
error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
error_string = talloc_asprintf_append(error_string, " note: b = boolean");
ldb_set_errstring(ldb, error_string);
talloc_free(error_string);
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
if (!ctrl[i]) {
ldb_oom(ldb);
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
ctrl[i]->critical = crit;
ctrl[i]->data = NULL;
continue;
}
/* no controls matched, throw an error */
ldb_asprintf_errstring(ldb, "Invalid control name: '%s'", control_strings[i]);
return NULL;
}
ctrl[i] = NULL;
return ctrl;
}

View File

@ -535,18 +535,10 @@ typedef int (*ldb_qsort_cmp_fn_t) (void *v1, void *v2, void *opaque);
#define LDB_EXTENDED_START_TLS_OID "1.3.6.1.4.1.1466.20037"
/**
OID for LDAP Extended Operation START_TLS.
This Extended operation is used to start a new TLS
channel on top of a clear text channel.
*/
#define LDB_EXTENDED_DYNAMIC_OID "1.3.6.1.4.1.1466.101.119.1"
/**
OID for LDAP Extended Operation START_TLS.
This Extended operation is used to start a new TLS
channel on top of a clear text channel.
*/
#define LDB_EXTENDED_FAST_BIND_OID "1.2.840.113556.1.4.1781"
@ -560,8 +552,7 @@ struct ldb_sd_flags_control {
unsigned secinfo_flags;
};
struct ldb_search_options_control {
/*
/*
* DOMAIN_SCOPE 0x00000001
* this limits the search to one partition,
* and no referrals will be returned.
@ -574,6 +565,11 @@ struct ldb_search_options_control {
* over multiple partitions without referrals.
* (This is the default behavior on the Global Catalog Port)
*/
#define LDB_SEARCH_OPTION_DOMAIN_SCOPE 0x00000001
#define LDB_SEARCH_OPTION_PHANTOM_ROOT 0x00000002
struct ldb_search_options_control {
unsigned search_options;
};
@ -1001,6 +997,15 @@ int ldb_build_rename_req(struct ldb_request **ret_req,
*/
int ldb_request_add_control(struct ldb_request *req, const char *oid, bool critical, void *data);
/**
check if a control with the specified "oid" exist and return it
\param req the request struct where to add the control
\param oid the object identifier of the control as string
\return the control, NULL if not found
*/
struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char *oid);
/**
Search the database
@ -1676,4 +1681,17 @@ time_t ldb_string_utc_to_time(const char *s);
void ldb_qsort (void *const pbase, size_t total_elems, size_t size, void *opaque, ldb_qsort_cmp_fn_t cmp);
/**
Convert an array of string represention of a control into an array of ldb_control structures
\param ldb LDB context
\param mem_ctx TALLOC context to return result on, and to allocate error_string on
\param control_strings Array of string-formatted controls
\return array of ldb_control elements
*/
struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *mem_ctx, const char **control_strings);
#endif

View File

@ -224,6 +224,9 @@ void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element
*/
int ldb_sequence_number(struct ldb_context *ldb, enum ldb_sequence_type type, uint64_t *seq_num);
/* Parse controls from the format used on the command line and in ejs */
#define LDB_SEQ_GLOBAL_SEQUENCE 0x01
#define LDB_SEQ_TIMESTAMP_SEQUENCE 0x02

View File

@ -401,7 +401,7 @@ static int asq_search(struct ldb_module *module, struct ldb_request *req)
struct ldb_handle *h;
/* check if there's a paged request control */
control = get_control_from_list(req->controls, LDB_CONTROL_ASQ_OID);
control = ldb_request_get_control(req, LDB_CONTROL_ASQ_OID);
if (control == NULL) {
/* not found go on */
return ldb_next_request(module, req);

View File

@ -239,7 +239,7 @@ static int paged_search(struct ldb_module *module, struct ldb_request *req)
int ret;
/* check if there's a paged request control */
control = get_control_from_list(req->controls, LDB_CONTROL_PAGED_RESULTS_OID);
control = ldb_request_get_control(req, LDB_CONTROL_PAGED_RESULTS_OID);
if (control == NULL) {
/* not found go on */
return ldb_next_request(module, req);

View File

@ -223,7 +223,7 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req
int ret;
/* check if there's a paged request control */
control = get_control_from_list(req->controls, LDB_CONTROL_SERVER_SORT_OID);
control = ldb_request_get_control(req, LDB_CONTROL_SERVER_SORT_OID);
if (control == NULL) {
/* not found go on */
return ldb_next_request(module, req);

View File

@ -235,374 +235,6 @@ failed:
return NULL;
}
struct ldb_control **parse_controls(void *mem_ctx, char **control_strings)
{
int i;
struct ldb_control **ctrl;
if (control_strings == NULL || control_strings[0] == NULL)
return NULL;
for (i = 0; control_strings[i]; i++);
ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1);
for (i = 0; control_strings[i]; i++) {
if (strncmp(control_strings[i], "vlv:", 4) == 0) {
struct ldb_vlv_req_control *control;
const char *p;
char attr[1024];
char ctxid[1024];
int crit, bc, ac, os, cc, ret;
attr[0] = '\0';
ctxid[0] = '\0';
p = &(control_strings[i][4]);
ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid);
if (ret < 5) {
ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid);
}
if ((ret < 4) || (crit < 0) || (crit > 1)) {
fprintf(stderr, "invalid server_sort control syntax\n");
fprintf(stderr, " syntax: crit(b):bc(n):ac(n):<os(n):cc(n)|attr(s)>[:ctxid(o)]\n");
fprintf(stderr, " note: b = boolean, n = number, s = string, o = b64 binary blob\n");
return NULL;
}
if (!(ctrl[i] = talloc(ctrl, struct ldb_control))) {
fprintf(stderr, "talloc failed\n");
return NULL;
}
ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID;
ctrl[i]->critical = crit;
if (!(control = talloc(ctrl[i],
struct ldb_vlv_req_control))) {
fprintf(stderr, "talloc failed\n");
return NULL;
}
control->beforeCount = bc;
control->afterCount = ac;
if (attr[0]) {
control->type = 1;
control->match.gtOrEq.value = talloc_strdup(control, attr);
control->match.gtOrEq.value_len = strlen(attr);
} else {
control->type = 0;
control->match.byOffset.offset = os;
control->match.byOffset.contentCount = cc;
}
if (ctxid[0]) {
control->ctxid_len = ldb_base64_decode(ctxid);
control->contextId = (char *)talloc_memdup(control, ctxid, control->ctxid_len);
} else {
control->ctxid_len = 0;
control->contextId = NULL;
}
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "dirsync:", 8) == 0) {
struct ldb_dirsync_control *control;
const char *p;
char cookie[1024];
int crit, flags, max_attrs, ret;
cookie[0] = '\0';
p = &(control_strings[i][8]);
ret = sscanf(p, "%d:%d:%d:%1023[^$]", &crit, &flags, &max_attrs, cookie);
if ((ret < 3) || (crit < 0) || (crit > 1) || (flags < 0) || (max_attrs < 0)) {
fprintf(stderr, "invalid dirsync control syntax\n");
fprintf(stderr, " syntax: crit(b):flags(n):max_attrs(n)[:cookie(o)]\n");
fprintf(stderr, " note: b = boolean, n = number, o = b64 binary blob\n");
return NULL;
}
/* w2k3 seems to ignore the parameter,
* but w2k sends a wrong cookie when this value is to small
* this would cause looping forever, while getting
* the same data and same cookie forever
*/
if (max_attrs == 0) max_attrs = 0x0FFFFFFF;
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_DIRSYNC_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_dirsync_control);
control->flags = flags;
control->max_attributes = max_attrs;
if (*cookie) {
control->cookie_len = ldb_base64_decode(cookie);
control->cookie = (char *)talloc_memdup(control, cookie, control->cookie_len);
} else {
control->cookie = NULL;
control->cookie_len = 0;
}
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "asq:", 4) == 0) {
struct ldb_asq_control *control;
const char *p;
char attr[256];
int crit, ret;
attr[0] = '\0';
p = &(control_strings[i][4]);
ret = sscanf(p, "%d:%255[^$]", &crit, attr);
if ((ret != 2) || (crit < 0) || (crit > 1) || (attr[0] == '\0')) {
fprintf(stderr, "invalid asq control syntax\n");
fprintf(stderr, " syntax: crit(b):attr(s)\n");
fprintf(stderr, " note: b = boolean, s = string\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_ASQ_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_asq_control);
control->request = 1;
control->source_attribute = talloc_strdup(control, attr);
control->src_attr_len = strlen(attr);
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "extended_dn:", 12) == 0) {
struct ldb_extended_dn_control *control;
const char *p;
int crit, type, ret;
p = &(control_strings[i][12]);
ret = sscanf(p, "%d:%d", &crit, &type);
if ((ret != 2) || (crit < 0) || (crit > 1) || (type < 0) || (type > 1)) {
fprintf(stderr, "invalid extended_dn control syntax\n");
fprintf(stderr, " syntax: crit(b):type(b)\n");
fprintf(stderr, " note: b = boolean\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_EXTENDED_DN_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_extended_dn_control);
control->type = type;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "sd_flags:", 9) == 0) {
struct ldb_sd_flags_control *control;
const char *p;
int crit, ret;
unsigned secinfo_flags;
p = &(control_strings[i][9]);
ret = sscanf(p, "%d:%u", &crit, &secinfo_flags);
if ((ret != 2) || (crit < 0) || (crit > 1) || (secinfo_flags < 0) || (secinfo_flags > 0xF)) {
fprintf(stderr, "invalid sd_flags control syntax\n");
fprintf(stderr, " syntax: crit(b):secinfo_flags(n)\n");
fprintf(stderr, " note: b = boolean, n = number\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_SD_FLAGS_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_sd_flags_control);
control->secinfo_flags = secinfo_flags;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "search_options:", 15) == 0) {
struct ldb_search_options_control *control;
const char *p;
int crit, ret;
unsigned search_options;
p = &(control_strings[i][15]);
ret = sscanf(p, "%d:%u", &crit, &search_options);
if ((ret != 2) || (crit < 0) || (crit > 1) || (search_options < 0) || (search_options > 0xF)) {
fprintf(stderr, "invalid search_options control syntax\n");
fprintf(stderr, " syntax: crit(b):search_options(n)\n");
fprintf(stderr, " note: b = boolean, n = number\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_SEARCH_OPTIONS_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_search_options_control);
control->search_options = search_options;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "domain_scope:", 13) == 0) {
const char *p;
int crit, ret;
p = &(control_strings[i][13]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
fprintf(stderr, "invalid domain_scope control syntax\n");
fprintf(stderr, " syntax: crit(b)\n");
fprintf(stderr, " note: b = boolean\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_DOMAIN_SCOPE_OID;
ctrl[i]->critical = crit;
ctrl[i]->data = NULL;
continue;
}
if (strncmp(control_strings[i], "paged_results:", 14) == 0) {
struct ldb_paged_control *control;
const char *p;
int crit, size, ret;
p = &(control_strings[i][14]);
ret = sscanf(p, "%d:%d", &crit, &size);
if ((ret != 2) || (crit < 0) || (crit > 1) || (size < 0)) {
fprintf(stderr, "invalid paged_results control syntax\n");
fprintf(stderr, " syntax: crit(b):size(n)\n");
fprintf(stderr, " note: b = boolean, n = number\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
ctrl[i]->critical = crit;
control = talloc(ctrl[i], struct ldb_paged_control);
control->size = size;
control->cookie = NULL;
control->cookie_len = 0;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "server_sort:", 12) == 0) {
struct ldb_server_sort_control **control;
const char *p;
char attr[256];
char rule[128];
int crit, rev, ret;
attr[0] = '\0';
rule[0] = '\0';
p = &(control_strings[i][12]);
ret = sscanf(p, "%d:%d:%255[^:]:%127[^:]", &crit, &rev, attr, rule);
if ((ret < 3) || (crit < 0) || (crit > 1) || (rev < 0 ) || (rev > 1) ||attr[0] == '\0') {
fprintf(stderr, "invalid server_sort control syntax\n");
fprintf(stderr, " syntax: crit(b):rev(b):attr(s)[:rule(s)]\n");
fprintf(stderr, " note: b = boolean, s = string\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_SERVER_SORT_OID;
ctrl[i]->critical = crit;
control = talloc_array(ctrl[i], struct ldb_server_sort_control *, 2);
control[0] = talloc(control, struct ldb_server_sort_control);
control[0]->attributeName = talloc_strdup(control, attr);
if (rule[0])
control[0]->orderingRule = talloc_strdup(control, rule);
else
control[0]->orderingRule = NULL;
control[0]->reverse = rev;
control[1] = NULL;
ctrl[i]->data = control;
continue;
}
if (strncmp(control_strings[i], "notification:", 13) == 0) {
const char *p;
int crit, ret;
p = &(control_strings[i][13]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
fprintf(stderr, "invalid notification control syntax\n");
fprintf(stderr, " syntax: crit(b)\n");
fprintf(stderr, " note: b = boolean\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_NOTIFICATION_OID;
ctrl[i]->critical = crit;
ctrl[i]->data = NULL;
continue;
}
if (strncmp(control_strings[i], "show_deleted:", 13) == 0) {
const char *p;
int crit, ret;
p = &(control_strings[i][13]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
fprintf(stderr, "invalid show_deleted control syntax\n");
fprintf(stderr, " syntax: crit(b)\n");
fprintf(stderr, " note: b = boolean\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_SHOW_DELETED_OID;
ctrl[i]->critical = crit;
ctrl[i]->data = NULL;
continue;
}
if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
const char *p;
int crit, ret;
p = &(control_strings[i][18]);
ret = sscanf(p, "%d", &crit);
if ((ret != 1) || (crit < 0) || (crit > 1)) {
fprintf(stderr, "invalid permissive_modify control syntax\n");
fprintf(stderr, " syntax: crit(b)\n");
fprintf(stderr, " note: b = boolean\n");
return NULL;
}
ctrl[i] = talloc(ctrl, struct ldb_control);
ctrl[i]->oid = LDB_CONTROL_PERMISSIVE_MODIFY_OID;
ctrl[i]->critical = crit;
ctrl[i]->data = NULL;
continue;
}
/* no controls matched, throw an error */
fprintf(stderr, "Invalid control name: '%s'\n", control_strings[i]);
return NULL;
}
ctrl[i] = NULL;
return ctrl;
}
/* this function check controls reply and determines if more
* processing is needed setting up the request controls correctly
*

View File

@ -202,8 +202,11 @@ static int do_search(struct ldb_context *ldb,
sctx->sort = options->sorted;
sctx->num_stored = 0;
sctx->store = NULL;
sctx->req_ctrls = parse_controls(ldb, options->controls);
if (options->controls != NULL && sctx->req_ctrls== NULL) return -1;
sctx->req_ctrls = ldb_parse_control_strings(ldb, sctx, (const char **)options->controls);
if (options->controls != NULL && sctx->req_ctrls== NULL) {
printf("parsing controls failed: %s\n", ldb_errstring(ldb));
return -1;
}
sctx->entries = 0;
sctx->refs = 0;

View File

@ -49,6 +49,7 @@ static struct ldb_context *ejs_get_ldb_context(int eid)
ldb.search("expression", attrs);
var basedn = "cn=this,dc=is,dc=a,dc=test";
ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs);
ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs, controls);
*/
static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
{
@ -60,10 +61,12 @@ static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
struct ldb_context *ldb;
int ret;
struct ldb_control **parsed_controls = NULL;
struct ldb_result *res=NULL;
struct ldb_request *req;
/* validate arguments */
if (argc < 1 || argc > 4) {
if (argc < 1 || argc > 5) {
ejsSetErrorMsg(eid, "ldb.search invalid number of arguments");
goto failed;
}
@ -88,6 +91,8 @@ static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
ejsSetErrorMsg(eid, "ldb.search malformed base dn");
goto failed;
}
} else {
basedn = ldb_get_default_basedn(ldb);
}
if (argc > 2) {
scope = mprToInt(argv[2]);
@ -105,14 +110,51 @@ static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
if (argc > 3) {
attrs = mprToList(tmp_ctx, argv[3]);
}
ret = ldb_search(ldb, basedn, scope, expression, attrs, &res);
if (argc > 4) {
const char **controls;
controls = mprToList(tmp_ctx, argv[4]);
if (controls) {
parsed_controls = ldb_parse_control_strings(ldb, tmp_ctx, controls);
if (!parsed_controls) {
ejsSetErrorMsg(eid, "ldb.search cannot parse controls: %s",
ldb_errstring(ldb));
goto failed;
}
}
}
res = talloc_zero(tmp_ctx, struct ldb_result);
if (!res) {
return LDB_ERR_OPERATIONS_ERROR;
}
ret = ldb_build_search_req(&req, ldb, tmp_ctx,
basedn,
scope,
expression,
attrs,
parsed_controls,
res,
ldb_search_default_callback);
if (ret == LDB_SUCCESS) {
ldb_set_timeout(ldb, req, 0); /* use default timeout */
ret = ldb_request(ldb, req);
if (ret == LDB_SUCCESS) {
ret = ldb_wait(req->handle, LDB_WAIT_ALL);
}
}
if (ret != LDB_SUCCESS) {
ejsSetErrorMsg(eid, "ldb.search failed - %s", ldb_errstring(ldb));
mpr_Return(eid, mprLdbResult(ldb, ret, NULL));
} else {
mpr_Return(eid, mprLdbResult(ldb, ret, res));
talloc_free(res);
}
talloc_free(tmp_ctx);
return 0;

View File

@ -218,6 +218,18 @@ objectClass: user
assert(res.msgs[0].dn == res3gc.msgs[0].dn);
}
println("Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control");
var attrs = new Array("cn");
var controls = new Array("search_options:1:2");
var res3control = gc_ldb.search("(&(cn=ldaptestuser)(objectCategory=PerSon))", base_dn, ldb.SCOPE_SUBTREE, attrs, controls);
if (res3control.error != 0 || res3control.msgs.length != 1) {
println("Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog");
assert(res3control.error == 0);
assert(res3control.msgs.length == 1);
}
assert(res.msgs[0].dn == res3control.msgs[0].dn);
ok = ldb.del(res.msgs[0].dn);
if (ok.error != 0) {
println(ok.errstr);
@ -414,7 +426,21 @@ objectClass: user
assert(res.error == 0);
assert(res.msgs.length == 0);
println("Testing that we can get at the configuration DN from the main search base on the LDAP port with the 'phantom root' search_options control");
var attrs = new Array("cn");
var controls = new Array("search_options:1:2");
var res = ldb.search("objectClass=crossRef", base_dn, ldb.SCOPE_SUBTREE, attrs, controls);
assert(res.error == 0);
assert(res.msgs.length > 0);
if (gc_ldb != undefined) {
println("Testing that we can get at the configuration DN from the main search base on the GC port with the search_options control == 0");
var attrs = new Array("cn");
var controls = new Array("search_options:1:0");
var res = gc_ldb.search("objectClass=crossRef", base_dn, gc_ldb.SCOPE_SUBTREE, attrs, controls);
assert(res.error == 0);
assert(res.msgs.length > 0);
println("Testing that we do find configuration elements in the global catlog");
var attrs = new Array("cn");
var res = gc_ldb.search("objectClass=crossRef", base_dn, ldb.SCOPE_SUBTREE, attrs);