*/
#include "includes.h"
+#include "ldb/include/includes.h"
+#include "ldb/tools/cmdline.h"
static void usage(void)
{
printf(" -s base|sub|one choose search scope\n");
printf(" -b basedn choose baseDN\n");
printf(" -i read search expressions from stdin\n");
+ printf(" -S sort returned attributes\n");
+ printf(" -o options pass options like modules to activate\n");
+ printf(" e.g: -o modules:timestamps\n");
exit(1);
}
+static int do_compare_msg(struct ldb_message **el1,
+ struct ldb_message **el2,
+ void *opaque)
+{
+ struct ldb_context *ldb = talloc_get_type(opaque, struct ldb_context);
+ return ldb_dn_compare(ldb, (*el1)->dn, (*el2)->dn);
+}
+
+static 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], "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");
+ 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], "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");
+ 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;
+
+ 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");
+ 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);
+ control[0]->orderingRule = talloc_strdup(control, rule);
+ control[0]->reverse = rev;
+ control[1] = NULL;
+ ctrl[i]->data = control;
+
+ continue;
+ }
+
+ /* no controls matched, throw an error */
+ fprintf(stderr, "Invalid control name\n");
+ return NULL;
+ }
+
+ ctrl[i + 1] = NULL;
+
+ return ctrl;
+}
+
static int do_search(struct ldb_context *ldb,
- const char *basedn,
- int scope,
+ const struct ldb_dn *basedn,
+ struct ldb_cmdline *options,
const char *expression,
const char * const *attrs)
{
int ret, i;
- struct ldb_message **msgs;
+ struct ldb_request req;
+ struct ldb_result *result = NULL;
- ret = ldb_search(ldb, basedn, scope, expression, attrs, &msgs);
- if (ret == -1) {
+ req.operation = LDB_REQ_SEARCH;
+ req.op.search.base = basedn;
+ req.op.search.scope = options->scope;
+ req.op.search.tree = ldb_parse_tree(ldb, expression);
+ req.op.search.attrs = attrs;
+ req.op.search.res = NULL;
+ req.controls = parse_controls(ldb, options->controls);
+ if (options->controls != NULL && req.controls == NULL) return -1;
+ req.creds = NULL;
+
+ ret = ldb_request(ldb, &req);
+ if (ret != LDB_SUCCESS) {
printf("search failed - %s\n", ldb_errstring(ldb));
return -1;
}
+ result = req.op.search.res;
printf("# returned %d records\n", ret);
- for (i=0;i<ret;i++) {
+ if (options->sorted) {
+ ldb_qsort(result->msgs, ret, sizeof(struct ldb_message *),
+ ldb, (ldb_qsort_cmp_fn_t)do_compare_msg);
+ }
+
+ for (i = 0; i < result->count; i++) {
struct ldb_ldif ldif;
printf("# record %d\n", i+1);
ldif.changetype = LDB_CHANGETYPE_NONE;
- ldif.msg = *msgs[i];
+ ldif.msg = result->msgs[i];
- ldif_write_file(ldb, stdout, &ldif);
+ if (options->sorted) {
+ /*
+ * Ensure attributes are always returned in the same
+ * order. For testing, this makes comparison of old
+ * vs. new much easier.
+ */
+ ldb_msg_sort_elements(ldif.msg);
+ }
+
+ ldb_ldif_write_file(ldb, stdout, &ldif);
}
- if (ret > 0) {
- ret = ldb_search_free(ldb, msgs);
+ if (result) {
+ ret = talloc_free(result);
if (ret == -1) {
- fprintf(stderr, "search_free failed\n");
+ fprintf(stderr, "talloc_free failed\n");
exit(1);
}
}
return 0;
}
- int main(int argc, char * const argv[])
+ int main(int argc, const char **argv)
{
struct ldb_context *ldb;
+ struct ldb_dn *basedn = NULL;
const char * const * attrs = NULL;
- const char *ldb_url;
- const char *basedn = NULL;
- int opt;
- enum ldb_scope scope = LDB_SCOPE_SUBTREE;
- int interactive = 0, ret=0;
-
- ldb_url = getenv("LDB_URL");
-
- while ((opt = getopt(argc, argv, "b:H:s:hi")) != EOF) {
- switch (opt) {
- case 'b':
- basedn = optarg;
- break;
-
- case 'H':
- ldb_url = optarg;
- break;
-
- case 's':
- if (strcmp(optarg, "base") == 0) {
- scope = LDB_SCOPE_BASE;
- } else if (strcmp(optarg, "sub") == 0) {
- scope = LDB_SCOPE_SUBTREE;
- } else if (strcmp(optarg, "one") == 0) {
- scope = LDB_SCOPE_ONELEVEL;
- }
- break;
-
- case 'i':
- interactive = 1;
- break;
-
- case 'h':
- default:
- usage();
- break;
- }
- }
+ struct ldb_cmdline *options;
+ int ret = -1;
+ const char *expression = "(objectclass=*)";
- if (!ldb_url) {
- fprintf(stderr, "You must specify a ldb URL\n\n");
- usage();
- }
+ ldb = ldb_init(NULL);
- argc -= optind;
- argv += optind;
+ options = ldb_cmdline_process(ldb, argc, argv, usage);
- if (argc < 1 && !interactive) {
- usage();
- exit(1);
+ /* the check for '=' is for compatibility with ldapsearch */
+ if (!options->interactive &&
+ options->argc > 0 &&
+ strchr(options->argv[0], '=')) {
+ expression = options->argv[0];
+ options->argv++;
+ options->argc--;
}
- if (argc > 1) {
- attrs = (const char * const *)(argv+1);
+ if (options->argc > 0) {
+ attrs = (const char * const *)(options->argv);
}
- ldb = ldb_connect(ldb_url, 0, NULL);
- if (!ldb) {
- perror("ldb_connect");
- exit(1);
+ if (options->basedn != NULL) {
+ basedn = ldb_dn_explode(ldb, options->basedn);
+ if (basedn == NULL) {
+ fprintf(stderr, "Invalid Base DN format\n");
+ exit(1);
+ }
}
- ldb_set_debug_stderr(ldb);
-
- if (interactive) {
+ if (options->interactive) {
char line[1024];
while (fgets(line, sizeof(line), stdin)) {
- if (do_search(ldb, basedn, scope, line, attrs) == -1) {
+ if (do_search(ldb, basedn, options, line, attrs) == -1) {
ret = -1;
}
}
} else {
- ret = do_search(ldb, basedn, scope, argv[0], attrs);
+ ret = do_search(ldb, basedn, options, expression, attrs);
}
- ldb_close(ldb);
+ talloc_free(ldb);
return ret;
}