wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -0,0 +1,626 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Andrew Bartlett 2006
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Name: ldb
|
||||
*
|
||||
* Component: ad2oLschema
|
||||
*
|
||||
* Description: utility to convert an AD schema into the format required by OpenLDAP
|
||||
*
|
||||
* Author: Andrew Tridgell
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "system/locale.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
#include "ldb/tools/convert.h"
|
||||
|
||||
struct schema_conv {
|
||||
int count;
|
||||
int skipped;
|
||||
int failures;
|
||||
};
|
||||
|
||||
enum convert_target {
|
||||
TARGET_OPENLDAP,
|
||||
TARGET_FEDORA_DS
|
||||
};
|
||||
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: ad2oLschema <options>\n");
|
||||
printf("\nConvert AD-like LDIF to OpenLDAP schema format\n\n");
|
||||
printf("Options:\n");
|
||||
printf(" -I inputfile inputfile of mapped OIDs and skipped attributes/ObjectClasses");
|
||||
printf(" -H url LDB or LDAP server to read schmea from\n");
|
||||
printf(" -O outputfile outputfile otherwise STDOUT\n");
|
||||
printf(" -o options pass options like modules to activate\n");
|
||||
printf(" e.g: -o modules:timestamps\n");
|
||||
printf("\n");
|
||||
printf("Converts records from an AD-like LDIF schema into an openLdap formatted schema\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int fetch_attrs_schema(struct ldb_context *ldb, struct ldb_dn *schemadn,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct ldb_result **attrs_res)
|
||||
{
|
||||
TALLOC_CTX *local_ctx = talloc_new(mem_ctx);
|
||||
int ret;
|
||||
const char *attrs[] = {
|
||||
"lDAPDisplayName",
|
||||
"isSingleValued",
|
||||
"attributeID",
|
||||
"attributeSyntax",
|
||||
"description",
|
||||
NULL
|
||||
};
|
||||
|
||||
if (!local_ctx) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
/* Downlaod schema */
|
||||
ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE,
|
||||
"objectClass=attributeSchema",
|
||||
attrs, attrs_res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
printf("Search failed: %s\n", ldb_errstring(ldb));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *oc_attrs[] = {
|
||||
"lDAPDisplayName",
|
||||
"mayContain",
|
||||
"mustContain",
|
||||
"systemMayContain",
|
||||
"systemMustContain",
|
||||
"objectClassCategory",
|
||||
"governsID",
|
||||
"description",
|
||||
"subClassOf",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct ldb_result *search_from,
|
||||
struct ldb_result *res_list)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
for (i=0; i < search_from->count; i++) {
|
||||
struct ldb_result *res;
|
||||
const char *name = ldb_msg_find_attr_as_string(search_from->msgs[i],
|
||||
"lDAPDisplayname", NULL);
|
||||
|
||||
ret = ldb_search_exp_fmt(ldb, mem_ctx, &res,
|
||||
schemadn, LDB_SCOPE_SUBTREE, oc_attrs,
|
||||
"(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))",
|
||||
name, name);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
printf("Search failed: %s\n", ldb_errstring(ldb));
|
||||
return ret;
|
||||
}
|
||||
|
||||
res_list->msgs = talloc_realloc(res_list, res_list->msgs,
|
||||
struct ldb_message *, res_list->count + 2);
|
||||
if (!res_list->msgs) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
res_list->msgs[res_list->count] = talloc_move(res_list,
|
||||
&search_from->msgs[i]);
|
||||
res_list->count++;
|
||||
res_list->msgs[res_list->count] = NULL;
|
||||
|
||||
if (res->count > 0) {
|
||||
ret = fetch_oc_recursive(ldb, schemadn, mem_ctx, res, res_list);
|
||||
}
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *schemadn,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct ldb_result **objectclasses_res)
|
||||
{
|
||||
TALLOC_CTX *local_ctx = talloc_new(mem_ctx);
|
||||
struct ldb_result *top_res, *ret_res;
|
||||
int ret;
|
||||
if (!local_ctx) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
/* Downlaod 'top' */
|
||||
ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE,
|
||||
"(&(objectClass=classSchema)(lDAPDisplayName=top))",
|
||||
oc_attrs, &top_res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
printf("Search failed: %s\n", ldb_errstring(ldb));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
talloc_steal(local_ctx, top_res);
|
||||
|
||||
if (top_res->count != 1) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
ret_res = talloc_zero(local_ctx, struct ldb_result);
|
||||
if (!ret_res) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
ret = fetch_oc_recursive(ldb, schemadn, local_ctx, top_res, ret_res);
|
||||
|
||||
if (ret != LDB_SUCCESS) {
|
||||
printf("Search failed: %s\n", ldb_errstring(ldb));
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
*objectclasses_res = talloc_move(mem_ctx, &ret_res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
|
||||
{
|
||||
const char *rootdse_attrs[] = {"schemaNamingContext", NULL};
|
||||
struct ldb_dn *schemadn;
|
||||
struct ldb_dn *basedn = ldb_dn_new(mem_ctx, ldb, NULL);
|
||||
struct ldb_result *rootdse_res;
|
||||
int ldb_ret;
|
||||
if (!basedn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Search for rootdse */
|
||||
ldb_ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, NULL, rootdse_attrs, &rootdse_res);
|
||||
if (ldb_ret != LDB_SUCCESS) {
|
||||
printf("Search failed: %s\n", ldb_errstring(ldb));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
talloc_steal(mem_ctx, rootdse_res);
|
||||
|
||||
if (rootdse_res->count != 1) {
|
||||
printf("Failed to find rootDSE");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Locate schema */
|
||||
schemadn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, rootdse_res->msgs[0], "schemaNamingContext");
|
||||
if (!schemadn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
talloc_free(rootdse_res);
|
||||
return schemadn;
|
||||
}
|
||||
|
||||
#define IF_NULL_FAIL_RET(x) do { \
|
||||
if (!x) { \
|
||||
ret.failures++; \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_target target, FILE *in, FILE *out)
|
||||
{
|
||||
/* Read list of attributes to skip, OIDs to map */
|
||||
TALLOC_CTX *mem_ctx = talloc_new(ldb);
|
||||
char *line;
|
||||
const char **attrs_skip = NULL;
|
||||
int num_skip = 0;
|
||||
struct oid_map {
|
||||
char *old_oid;
|
||||
char *new_oid;
|
||||
} *oid_map = NULL;
|
||||
int num_maps = 0;
|
||||
struct ldb_result *attrs_res, *objectclasses_res;
|
||||
struct ldb_dn *schemadn;
|
||||
struct schema_conv ret;
|
||||
|
||||
int ldb_ret, i;
|
||||
|
||||
ret.count = 0;
|
||||
ret.skipped = 0;
|
||||
ret.failures = 0;
|
||||
|
||||
while ((line = afdgets(fileno(in), mem_ctx, 0))) {
|
||||
/* Blank Line */
|
||||
if (line[0] == '\0') {
|
||||
continue;
|
||||
}
|
||||
/* Comment */
|
||||
if (line[0] == '#') {
|
||||
continue;
|
||||
}
|
||||
if (isdigit(line[0])) {
|
||||
char *p = strchr(line, ':');
|
||||
IF_NULL_FAIL_RET(p);
|
||||
if (!p) {
|
||||
ret.failures = 1;
|
||||
return ret;
|
||||
}
|
||||
p[0] = '\0';
|
||||
p++;
|
||||
oid_map = talloc_realloc(mem_ctx, oid_map, struct oid_map, num_maps + 2);
|
||||
trim_string(line, " ", " ");
|
||||
oid_map[num_maps].old_oid = talloc_move(oid_map, &line);
|
||||
trim_string(p, " ", " ");
|
||||
oid_map[num_maps].new_oid = p;
|
||||
num_maps++;
|
||||
oid_map[num_maps].old_oid = NULL;
|
||||
} else {
|
||||
attrs_skip = talloc_realloc(mem_ctx, attrs_skip, const char *, num_skip + 2);
|
||||
trim_string(line, " ", " ");
|
||||
attrs_skip[num_skip] = talloc_move(attrs_skip, &line);
|
||||
num_skip++;
|
||||
attrs_skip[num_skip] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
schemadn = find_schema_dn(ldb, mem_ctx);
|
||||
if (!schemadn) {
|
||||
printf("Failed to find schema DN: %s\n", ldb_errstring(ldb));
|
||||
ret.failures = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ldb_ret = fetch_attrs_schema(ldb, schemadn, mem_ctx, &attrs_res);
|
||||
if (ldb_ret != LDB_SUCCESS) {
|
||||
printf("Failed to fetch attribute schema: %s\n", ldb_errstring(ldb));
|
||||
ret.failures = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (target) {
|
||||
case TARGET_OPENLDAP:
|
||||
break;
|
||||
case TARGET_FEDORA_DS:
|
||||
fprintf(out, "dn: cn=schema\n");
|
||||
break;
|
||||
}
|
||||
|
||||
for (i=0; i < attrs_res->count; i++) {
|
||||
struct ldb_message *msg = attrs_res->msgs[i];
|
||||
|
||||
const char *name = ldb_msg_find_attr_as_string(msg, "lDAPDisplayName", NULL);
|
||||
const char *description = ldb_msg_find_attr_as_string(msg, "description", NULL);
|
||||
const char *oid = ldb_msg_find_attr_as_string(msg, "attributeID", NULL);
|
||||
const char *syntax = ldb_msg_find_attr_as_string(msg, "attributeSyntax", NULL);
|
||||
BOOL single_value = ldb_msg_find_attr_as_bool(msg, "isSingleValued", False);
|
||||
const struct syntax_map *map = find_syntax_map_by_ad_oid(syntax);
|
||||
char *schema_entry = NULL;
|
||||
int j;
|
||||
|
||||
/* We have been asked to skip some attributes/objectClasses */
|
||||
if (attrs_skip && str_list_check_ci(attrs_skip, name)) {
|
||||
ret.skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We might have been asked to remap this oid, due to a conflict */
|
||||
for (j=0; oid && oid_map[j].old_oid; j++) {
|
||||
if (strcmp(oid, oid_map[j].old_oid) == 0) {
|
||||
oid = oid_map[j].new_oid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (target) {
|
||||
case TARGET_OPENLDAP:
|
||||
schema_entry = talloc_asprintf(mem_ctx,
|
||||
"attributetype (\n"
|
||||
" %s\n", oid);
|
||||
break;
|
||||
case TARGET_FEDORA_DS:
|
||||
schema_entry = talloc_asprintf(mem_ctx,
|
||||
"attributeTypes: (\n"
|
||||
" %s\n", oid);
|
||||
break;
|
||||
}
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" NAME '%s'\n", name);
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
|
||||
if (description) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" DESC %s\n", description);
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
}
|
||||
|
||||
if (map) {
|
||||
const char *syntax_oid;
|
||||
if (map->equality) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" EQUALITY %s\n", map->equality);
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
}
|
||||
if (map->substring) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" SUBSTR %s\n", map->substring);
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
}
|
||||
syntax_oid = map->Standard_OID;
|
||||
/* We might have been asked to remap this oid,
|
||||
* due to a conflict, or lack of
|
||||
* implementation */
|
||||
for (j=0; syntax_oid && oid_map[j].old_oid; j++) {
|
||||
if (strcmp(syntax_oid, oid_map[j].old_oid) == 0) {
|
||||
syntax_oid = oid_map[j].new_oid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" SYNTAX %s\n", syntax_oid);
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
}
|
||||
|
||||
if (single_value) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" SINGLE-VALUE\n");
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
}
|
||||
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" )");
|
||||
|
||||
switch (target) {
|
||||
case TARGET_OPENLDAP:
|
||||
fprintf(out, "%s\n\n", schema_entry);
|
||||
break;
|
||||
case TARGET_FEDORA_DS:
|
||||
fprintf(out, "%s\n", schema_entry);
|
||||
break;
|
||||
}
|
||||
ret.count++;
|
||||
}
|
||||
|
||||
ldb_ret = fetch_objectclass_schema(ldb, schemadn, mem_ctx, &objectclasses_res);
|
||||
if (ldb_ret != LDB_SUCCESS) {
|
||||
printf("Failed to fetch objectClass schema elements: %s\n", ldb_errstring(ldb));
|
||||
ret.failures = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i=0; i < objectclasses_res->count; i++) {
|
||||
struct ldb_message *msg = objectclasses_res->msgs[i];
|
||||
const char *name = ldb_msg_find_attr_as_string(msg, "lDAPDisplayName", NULL);
|
||||
const char *description = ldb_msg_find_attr_as_string(msg, "description", NULL);
|
||||
const char *oid = ldb_msg_find_attr_as_string(msg, "governsID", NULL);
|
||||
const char *subClassOf = ldb_msg_find_attr_as_string(msg, "subClassOf", NULL);
|
||||
int objectClassCategory = ldb_msg_find_attr_as_int(msg, "objectClassCategory", 0);
|
||||
struct ldb_message_element *must = ldb_msg_find_element(msg, "mustContain");
|
||||
struct ldb_message_element *sys_must = ldb_msg_find_element(msg, "systemMustContain");
|
||||
struct ldb_message_element *may = ldb_msg_find_element(msg, "mayContain");
|
||||
struct ldb_message_element *sys_may = ldb_msg_find_element(msg, "systemMayContain");
|
||||
char *schema_entry = NULL;
|
||||
int j;
|
||||
|
||||
/* We have been asked to skip some attributes/objectClasses */
|
||||
if (attrs_skip && str_list_check_ci(attrs_skip, name)) {
|
||||
ret.skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We might have been asked to remap this oid, due to a conflict */
|
||||
for (j=0; oid_map[j].old_oid; j++) {
|
||||
if (strcmp(oid, oid_map[j].old_oid) == 0) {
|
||||
oid = oid_map[j].new_oid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (target) {
|
||||
case TARGET_OPENLDAP:
|
||||
schema_entry = talloc_asprintf(mem_ctx,
|
||||
"objectclass (\n"
|
||||
" %s\n", oid);
|
||||
break;
|
||||
case TARGET_FEDORA_DS:
|
||||
schema_entry = talloc_asprintf(mem_ctx,
|
||||
"objectClasses: (\n"
|
||||
" %s\n", oid);
|
||||
break;
|
||||
}
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
if (!schema_entry) {
|
||||
ret.failures++;
|
||||
break;
|
||||
}
|
||||
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" NAME '%s'\n", name);
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
|
||||
if (!schema_entry) return ret;
|
||||
|
||||
if (description) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" DESC %s\n", description);
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
}
|
||||
|
||||
if (subClassOf) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" SUP %s\n", subClassOf);
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
}
|
||||
|
||||
switch (objectClassCategory) {
|
||||
case 1:
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" STRUCTURAL\n");
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
break;
|
||||
case 2:
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" ABSTRACT\n");
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
break;
|
||||
case 3:
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" AUXILIARY\n");
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
break;
|
||||
}
|
||||
|
||||
#define APPEND_ATTRS(attributes) \
|
||||
do { \
|
||||
int k; \
|
||||
for (k=0; attributes && k < attributes->num_values; k++) { \
|
||||
schema_entry = talloc_asprintf_append(schema_entry, \
|
||||
" %s", \
|
||||
(const char *)attributes->values[k].data); \
|
||||
IF_NULL_FAIL_RET(schema_entry); \
|
||||
if (k != (attributes->num_values - 1)) { \
|
||||
schema_entry = talloc_asprintf_append(schema_entry, \
|
||||
" $"); \
|
||||
IF_NULL_FAIL_RET(schema_entry); \
|
||||
if (target == TARGET_OPENLDAP && ((k+1)%5 == 0)) { \
|
||||
schema_entry = talloc_asprintf_append(schema_entry, \
|
||||
"\n "); \
|
||||
IF_NULL_FAIL_RET(schema_entry); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
if (must || sys_must) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" MUST (");
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
|
||||
APPEND_ATTRS(must);
|
||||
if (must && sys_must) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry, \
|
||||
" $"); \
|
||||
}
|
||||
APPEND_ATTRS(sys_must);
|
||||
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" )\n");
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
}
|
||||
|
||||
if (may || sys_may) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" MAY (");
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
|
||||
APPEND_ATTRS(may);
|
||||
if (may && sys_may) {
|
||||
schema_entry = talloc_asprintf_append(schema_entry, \
|
||||
" $"); \
|
||||
}
|
||||
APPEND_ATTRS(sys_may);
|
||||
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" )\n");
|
||||
IF_NULL_FAIL_RET(schema_entry);
|
||||
}
|
||||
|
||||
schema_entry = talloc_asprintf_append(schema_entry,
|
||||
" )");
|
||||
|
||||
switch (target) {
|
||||
case TARGET_OPENLDAP:
|
||||
fprintf(out, "%s\n\n", schema_entry);
|
||||
break;
|
||||
case TARGET_FEDORA_DS:
|
||||
fprintf(out, "%s\n", schema_entry);
|
||||
break;
|
||||
}
|
||||
ret.count++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
TALLOC_CTX *ctx;
|
||||
struct ldb_cmdline *options;
|
||||
FILE *in = stdin;
|
||||
FILE *out = stdout;
|
||||
struct ldb_context *ldb;
|
||||
struct schema_conv ret;
|
||||
const char *target_str;
|
||||
enum convert_target target;
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
ctx = talloc_new(NULL);
|
||||
ldb = ldb_init(ctx);
|
||||
|
||||
options = ldb_cmdline_process(ldb, argc, argv, usage);
|
||||
|
||||
if (options->input) {
|
||||
in = fopen(options->input, "r");
|
||||
if (!in) {
|
||||
perror(options->input);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (options->output) {
|
||||
out = fopen(options->output, "w");
|
||||
if (!out) {
|
||||
perror(options->output);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
target_str = lp_parm_string(-1, "convert", "target");
|
||||
|
||||
if (!target_str || strcasecmp(target_str, "openldap") == 0) {
|
||||
target = TARGET_OPENLDAP;
|
||||
} else if (strcasecmp(target_str, "fedora-ds") == 0) {
|
||||
target = TARGET_FEDORA_DS;
|
||||
} else {
|
||||
printf("Unsupported target: %s\n", target_str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = process_convert(ldb, target, in, out);
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
printf("Converted %d records (skipped %d) with %d failures\n", ret.count, ret.skipped, ret.failures);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,755 @@
|
||||
/*
|
||||
ldb database library - command line handling for ldb tools
|
||||
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
|
||||
#if (_SAMBA_BUILD_ >= 4)
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
#include "lib/ldb/samba/ldif_handlers.h"
|
||||
#include "auth/gensec/gensec.h"
|
||||
#include "auth/auth.h"
|
||||
#include "db_wrap.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
process command line options
|
||||
*/
|
||||
struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv,
|
||||
void (*usage)(void))
|
||||
{
|
||||
static struct ldb_cmdline options; /* needs to be static for older compilers */
|
||||
struct ldb_cmdline *ret=NULL;
|
||||
poptContext pc;
|
||||
#if (_SAMBA_BUILD_ >= 4)
|
||||
int r;
|
||||
#endif
|
||||
int num_options = 0;
|
||||
int opt;
|
||||
int flags = 0;
|
||||
|
||||
struct poptOption popt_options[] = {
|
||||
POPT_AUTOHELP
|
||||
{ "url", 'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" },
|
||||
{ "basedn", 'b', POPT_ARG_STRING, &options.basedn, 0, "base DN", "DN" },
|
||||
{ "editor", 'e', POPT_ARG_STRING, &options.editor, 0, "external editor", "PROGRAM" },
|
||||
{ "scope", 's', POPT_ARG_STRING, NULL, 's', "search scope", "SCOPE" },
|
||||
{ "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "increase verbosity", NULL },
|
||||
{ "interactive", 'i', POPT_ARG_NONE, &options.interactive, 0, "input from stdin", NULL },
|
||||
{ "recursive", 'r', POPT_ARG_NONE, &options.recursive, 0, "recursive delete", NULL },
|
||||
{ "num-searches", 0, POPT_ARG_INT, &options.num_searches, 0, "number of test searches", NULL },
|
||||
{ "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL },
|
||||
{ "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "(|(objectClass=*)(distinguishedName=*))", NULL },
|
||||
{ "nosync", 0, POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL },
|
||||
{ "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL },
|
||||
{ "sasl-mechanism", 0, POPT_ARG_STRING, &options.sasl_mechanism, 0, "choose SASL mechanism", "MECHANISM" },
|
||||
{ "input", 'I', POPT_ARG_STRING, &options.input, 0, "Input File", "Input" },
|
||||
{ "output", 'O', POPT_ARG_STRING, &options.output, 0, "Output File", "Output" },
|
||||
{ NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" },
|
||||
{ "controls", 0, POPT_ARG_STRING, NULL, 'c', "controls", NULL },
|
||||
#if (_SAMBA_BUILD_ >= 4)
|
||||
POPT_COMMON_SAMBA
|
||||
POPT_COMMON_CREDENTIALS
|
||||
POPT_COMMON_VERSION
|
||||
#endif
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
#if (_SAMBA_BUILD_ >= 4)
|
||||
r = ldb_register_samba_handlers(ldb);
|
||||
if (r != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ret = talloc_zero(ldb, struct ldb_cmdline);
|
||||
if (ret == NULL) {
|
||||
ldb_oom(ldb);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
options = *ret;
|
||||
|
||||
/* pull in URL */
|
||||
options.url = getenv("LDB_URL");
|
||||
|
||||
/* and editor (used by ldbedit) */
|
||||
options.editor = getenv("VISUAL");
|
||||
if (!options.editor) {
|
||||
options.editor = getenv("EDITOR");
|
||||
}
|
||||
if (!options.editor) {
|
||||
options.editor = "vi";
|
||||
}
|
||||
|
||||
options.scope = LDB_SCOPE_DEFAULT;
|
||||
|
||||
pc = poptGetContext(argv[0], argc, argv, popt_options,
|
||||
POPT_CONTEXT_KEEP_FIRST);
|
||||
|
||||
while((opt = poptGetNextOpt(pc)) != -1) {
|
||||
switch (opt) {
|
||||
case 's': {
|
||||
const char *arg = poptGetOptArg(pc);
|
||||
if (strcmp(arg, "base") == 0) {
|
||||
options.scope = LDB_SCOPE_BASE;
|
||||
} else if (strcmp(arg, "sub") == 0) {
|
||||
options.scope = LDB_SCOPE_SUBTREE;
|
||||
} else if (strcmp(arg, "one") == 0) {
|
||||
options.scope = LDB_SCOPE_ONELEVEL;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid scope '%s'\n", arg);
|
||||
goto failed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'v':
|
||||
options.verbose++;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
options.options = talloc_realloc(ret, options.options,
|
||||
const char *, num_options+3);
|
||||
if (options.options == NULL) {
|
||||
ldb_oom(ldb);
|
||||
goto failed;
|
||||
}
|
||||
options.options[num_options] = poptGetOptArg(pc);
|
||||
options.options[num_options+1] = NULL;
|
||||
num_options++;
|
||||
break;
|
||||
|
||||
case 'c': {
|
||||
const char *cs = poptGetOptArg(pc);
|
||||
const char *p, *q;
|
||||
int cc;
|
||||
|
||||
for (p = cs, cc = 1; (q = strchr(p, ',')); cc++, p = q + 1) ;
|
||||
|
||||
options.controls = talloc_array(ret, char *, cc + 1);
|
||||
if (options.controls == NULL) {
|
||||
ldb_oom(ldb);
|
||||
goto failed;
|
||||
}
|
||||
for (p = cs, cc = 0; p != NULL; cc++) {
|
||||
const char *t;
|
||||
|
||||
t = strchr(p, ',');
|
||||
if (t == NULL) {
|
||||
options.controls[cc] = talloc_strdup(options.controls, p);
|
||||
p = NULL;
|
||||
} else {
|
||||
options.controls[cc] = talloc_strndup(options.controls, p, t-p);
|
||||
p = t + 1;
|
||||
}
|
||||
}
|
||||
options.controls[cc] = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Invalid option %s: %s\n",
|
||||
poptBadOption(pc, 0), poptStrerror(opt));
|
||||
if (usage) usage();
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* setup the remaining options for the main program to use */
|
||||
options.argv = poptGetArgs(pc);
|
||||
if (options.argv) {
|
||||
options.argv++;
|
||||
while (options.argv[options.argc]) options.argc++;
|
||||
}
|
||||
|
||||
*ret = options;
|
||||
|
||||
/* all utils need some option */
|
||||
if (ret->url == NULL) {
|
||||
fprintf(stderr, "You must supply a url with -H or with $LDB_URL\n");
|
||||
if (usage) usage();
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (strcmp(ret->url, "NONE") == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (options.nosync) {
|
||||
flags |= LDB_FLG_NOSYNC;
|
||||
}
|
||||
|
||||
#if (_SAMBA_BUILD_ >= 4)
|
||||
/* Must be after we have processed command line options */
|
||||
gensec_init();
|
||||
|
||||
if (ldb_set_opaque(ldb, "sessionInfo", system_session(ldb))) {
|
||||
goto failed;
|
||||
}
|
||||
if (ldb_set_opaque(ldb, "credentials", cmdline_credentials)) {
|
||||
goto failed;
|
||||
}
|
||||
ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
|
||||
#endif
|
||||
|
||||
/* now connect to the ldb */
|
||||
if (ldb_connect(ldb, ret->url, flags, ret->options) != 0) {
|
||||
fprintf(stderr, "Failed to connect to %s - %s\n",
|
||||
ret->url, ldb_errstring(ldb));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
failed:
|
||||
talloc_free(ret);
|
||||
exit(1);
|
||||
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
|
||||
*
|
||||
* returns:
|
||||
* -1 error
|
||||
* 0 all ok
|
||||
* 1 all ok, more processing required
|
||||
*/
|
||||
int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request)
|
||||
{
|
||||
int i, j;
|
||||
int ret = 0;
|
||||
|
||||
if (reply == NULL || request == NULL) return -1;
|
||||
|
||||
for (i = 0; reply[i]; i++) {
|
||||
if (strcmp(LDB_CONTROL_VLV_RESP_OID, reply[i]->oid) == 0) {
|
||||
struct ldb_vlv_resp_control *rep_control;
|
||||
|
||||
rep_control = talloc_get_type(reply[i]->data, struct ldb_vlv_resp_control);
|
||||
|
||||
/* check we have a matching control in the request */
|
||||
for (j = 0; request[j]; j++) {
|
||||
if (strcmp(LDB_CONTROL_VLV_REQ_OID, request[j]->oid) == 0)
|
||||
break;
|
||||
}
|
||||
if (! request[j]) {
|
||||
fprintf(stderr, "Warning VLV reply received but no request have been made\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check the result */
|
||||
if (rep_control->vlv_result != 0) {
|
||||
fprintf(stderr, "Warning: VLV not performed with error: %d\n", rep_control->vlv_result);
|
||||
} else {
|
||||
fprintf(stderr, "VLV Info: target position = %d, content count = %d\n", rep_control->targetPosition, rep_control->contentCount);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(LDB_CONTROL_ASQ_OID, reply[i]->oid) == 0) {
|
||||
struct ldb_asq_control *rep_control;
|
||||
|
||||
rep_control = talloc_get_type(reply[i]->data, struct ldb_asq_control);
|
||||
|
||||
/* check the result */
|
||||
if (rep_control->result != 0) {
|
||||
fprintf(stderr, "Warning: ASQ not performed with error: %d\n", rep_control->result);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, reply[i]->oid) == 0) {
|
||||
struct ldb_paged_control *rep_control, *req_control;
|
||||
|
||||
rep_control = talloc_get_type(reply[i]->data, struct ldb_paged_control);
|
||||
if (rep_control->cookie_len == 0) /* we are done */
|
||||
break;
|
||||
|
||||
/* more processing required */
|
||||
/* let's fill in the request control with the new cookie */
|
||||
|
||||
for (j = 0; request[j]; j++) {
|
||||
if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, request[j]->oid) == 0)
|
||||
break;
|
||||
}
|
||||
/* if there's a reply control we must find a request
|
||||
* control matching it */
|
||||
if (! request[j]) return -1;
|
||||
|
||||
req_control = talloc_get_type(request[j]->data, struct ldb_paged_control);
|
||||
|
||||
if (req_control->cookie)
|
||||
talloc_free(req_control->cookie);
|
||||
req_control->cookie = (char *)talloc_memdup(
|
||||
req_control, rep_control->cookie,
|
||||
rep_control->cookie_len);
|
||||
req_control->cookie_len = rep_control->cookie_len;
|
||||
|
||||
ret = 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(LDB_CONTROL_SORT_RESP_OID, reply[i]->oid) == 0) {
|
||||
struct ldb_sort_resp_control *rep_control;
|
||||
|
||||
rep_control = talloc_get_type(reply[i]->data, struct ldb_sort_resp_control);
|
||||
|
||||
/* check we have a matching control in the request */
|
||||
for (j = 0; request[j]; j++) {
|
||||
if (strcmp(LDB_CONTROL_SERVER_SORT_OID, request[j]->oid) == 0)
|
||||
break;
|
||||
}
|
||||
if (! request[j]) {
|
||||
fprintf(stderr, "Warning Server Sort reply received but no request found\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check the result */
|
||||
if (rep_control->result != 0) {
|
||||
fprintf(stderr, "Warning: Sorting not performed with error: %d\n", rep_control->result);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(LDB_CONTROL_DIRSYNC_OID, reply[i]->oid) == 0) {
|
||||
struct ldb_dirsync_control *rep_control, *req_control;
|
||||
char *cookie;
|
||||
|
||||
rep_control = talloc_get_type(reply[i]->data, struct ldb_dirsync_control);
|
||||
if (rep_control->cookie_len == 0) /* we are done */
|
||||
break;
|
||||
|
||||
/* more processing required */
|
||||
/* let's fill in the request control with the new cookie */
|
||||
|
||||
for (j = 0; request[j]; j++) {
|
||||
if (strcmp(LDB_CONTROL_DIRSYNC_OID, request[j]->oid) == 0)
|
||||
break;
|
||||
}
|
||||
/* if there's a reply control we must find a request
|
||||
* control matching it */
|
||||
if (! request[j]) return -1;
|
||||
|
||||
req_control = talloc_get_type(request[j]->data, struct ldb_dirsync_control);
|
||||
|
||||
if (req_control->cookie)
|
||||
talloc_free(req_control->cookie);
|
||||
req_control->cookie = (char *)talloc_memdup(
|
||||
req_control, rep_control->cookie,
|
||||
rep_control->cookie_len);
|
||||
req_control->cookie_len = rep_control->cookie_len;
|
||||
|
||||
cookie = ldb_base64_encode(req_control, rep_control->cookie, rep_control->cookie_len);
|
||||
printf("# DIRSYNC cookie returned was:\n# %s\n", cookie);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* no controls matched, throw a warning */
|
||||
fprintf(stderr, "Unknown reply control oid: %s\n", reply[i]->oid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
ldb database library - command line handling for ldb tools
|
||||
|
||||
Copyright (C) Andrew Tridgell 2005
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <popt.h>
|
||||
|
||||
struct ldb_cmdline {
|
||||
const char *url;
|
||||
enum ldb_scope scope;
|
||||
const char *basedn;
|
||||
int interactive;
|
||||
int sorted;
|
||||
const char *editor;
|
||||
int verbose;
|
||||
int recursive;
|
||||
int all_records;
|
||||
int nosync;
|
||||
const char **options;
|
||||
int argc;
|
||||
const char **argv;
|
||||
int num_records;
|
||||
int num_searches;
|
||||
const char *sasl_mechanism;
|
||||
const char *input;
|
||||
const char *output;
|
||||
char **controls;
|
||||
};
|
||||
|
||||
struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv,
|
||||
void (*usage)(void));
|
||||
|
||||
|
||||
struct ldb_control **parse_controls(void *mem_ctx, char **control_strings);
|
||||
int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request);
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Simo Sorce 2005
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "convert.h"
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
|
||||
/* Shared map for converting syntax between formats */
|
||||
static const struct syntax_map syntax_map[] = {
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.12",
|
||||
.AD_OID = "2.5.5.1",
|
||||
.equality = "distinguishedNameMatch",
|
||||
.comment = "Object(DS-DN) == a DN"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.38",
|
||||
.AD_OID = "2.5.5.2",
|
||||
.equality = "objectIdentifierMatch",
|
||||
.comment = "OID String"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.2.840.113556.1.4.905",
|
||||
.AD_OID = "2.5.5.4",
|
||||
.equality = "caseIgnoreMatch",
|
||||
.substring = "caseIgnoreSubstringsMatch",
|
||||
.comment = "Case Insensitive String"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.26",
|
||||
.AD_OID = "2.5.5.5",
|
||||
.equality = "caseExactIA5Match",
|
||||
.comment = "Printable String"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.36",
|
||||
.AD_OID = "2.5.5.6",
|
||||
.equality = "numericStringMatch",
|
||||
.substring = "numericStringSubstringsMatch",
|
||||
.comment = "Numeric String"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.2.840.113556.1.4.903",
|
||||
.AD_OID = "2.5.5.7",
|
||||
.equality = "distinguishedNameMatch",
|
||||
.comment = "OctetString: Binary+DN"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.7",
|
||||
.AD_OID = "2.5.5.8",
|
||||
.equality = "booleanMatch",
|
||||
.comment = "Boolean"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.27",
|
||||
.AD_OID = "2.5.5.9",
|
||||
.equality = "integerMatch",
|
||||
.comment = "Integer"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.40",
|
||||
.AD_OID = "2.5.5.10",
|
||||
.equality = "octetStringMatch",
|
||||
.comment = "Octet String"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.24",
|
||||
.AD_OID = "2.5.5.11",
|
||||
.equality = "generalizedTimeMatch",
|
||||
.comment = "Generalized Time"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.53",
|
||||
.AD_OID = "2.5.5.11",
|
||||
.equality = "generalizedTimeMatch",
|
||||
.comment = "UTC Time"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.15",
|
||||
.AD_OID = "2.5.5.12",
|
||||
.equality = "caseIgnoreMatch",
|
||||
.substring = "caseIgnoreSubstringsMatch",
|
||||
.comment = "Directory String"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.43",
|
||||
.AD_OID = "2.5.5.13",
|
||||
.comment = "Presentation Address"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "Not Found Yet",
|
||||
.AD_OID = "2.5.5.14",
|
||||
.equality = "distinguishedNameMatch",
|
||||
.comment = "OctetString: String+DN"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.2.840.113556.1.4.907",
|
||||
.AD_OID = "2.5.5.15",
|
||||
.equality = "octetStringMatch",
|
||||
.comment = "NT Security Descriptor"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.2.840.113556.1.4.906",
|
||||
.AD_OID = "2.5.5.16",
|
||||
.equality = "integerMatch",
|
||||
.comment = "Large Integer"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.40",
|
||||
.AD_OID = "2.5.5.17",
|
||||
.equality = "octetStringMatch",
|
||||
.comment = "Octet String - Security Identifier (SID)"
|
||||
},
|
||||
{
|
||||
.Standard_OID = "1.3.6.1.4.1.1466.115.121.1.26",
|
||||
.AD_OID = "2.5.5.5",
|
||||
.equality = "caseExactIA5Match",
|
||||
.comment = "IA5 String"
|
||||
},
|
||||
{ .Standard_OID = NULL
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const struct syntax_map *find_syntax_map_by_ad_oid(const char *ad_oid)
|
||||
{
|
||||
int i;
|
||||
for (i=0; syntax_map[i].Standard_OID; i++) {
|
||||
if (strcasecmp(ad_oid, syntax_map[i].AD_OID) == 0) {
|
||||
return &syntax_map[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct syntax_map *find_syntax_map_by_standard_oid(const char *standard_oid)
|
||||
{
|
||||
int i;
|
||||
for (i=0; syntax_map[i].Standard_OID; i++) {
|
||||
if (strcasecmp(standard_oid, syntax_map[i].Standard_OID) == 0) {
|
||||
return &syntax_map[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
struct syntax_map {
|
||||
const char *Standard_OID;
|
||||
const char *AD_OID;
|
||||
const char *equality;
|
||||
const char *substring;
|
||||
const char *comment;
|
||||
};
|
||||
|
||||
const struct syntax_map *find_syntax_map_by_ad_oid(const char *ad_oid);
|
||||
const struct syntax_map *find_syntax_map_by_standard_oid(const char *standard_oid);
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Name: ldb
|
||||
*
|
||||
* Component: ldbadd
|
||||
*
|
||||
* Description: utility to add records - modelled on ldapadd
|
||||
*
|
||||
* Author: Andrew Tridgell
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
|
||||
static int failures;
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: ldbadd <options> <ldif...>\n");
|
||||
printf("Options:\n");
|
||||
printf(" -H ldb_url choose the database (or $LDB_URL)\n");
|
||||
printf(" -o options pass options like modules to activate\n");
|
||||
printf(" e.g: -o modules:timestamps\n");
|
||||
printf("\n");
|
||||
printf("Adds records to a ldb, reading ldif the specified list of files\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
add records from an opened file
|
||||
*/
|
||||
static int process_file(struct ldb_context *ldb, FILE *f, int *count)
|
||||
{
|
||||
struct ldb_ldif *ldif;
|
||||
int ret = LDB_SUCCESS;
|
||||
|
||||
while ((ldif = ldb_ldif_read_file(ldb, f))) {
|
||||
if (ldif->changetype != LDB_CHANGETYPE_ADD &&
|
||||
ldif->changetype != LDB_CHANGETYPE_NONE) {
|
||||
fprintf(stderr, "Only CHANGETYPE_ADD records allowed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
ldif->msg = ldb_msg_canonicalize(ldb, ldif->msg);
|
||||
|
||||
ret = ldb_add(ldb, ldif->msg);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
fprintf(stderr, "ERR: \"%s\" on DN %s\n",
|
||||
ldb_errstring(ldb), ldb_dn_get_linearized(ldif->msg->dn));
|
||||
failures++;
|
||||
} else {
|
||||
(*count)++;
|
||||
}
|
||||
ldb_ldif_read_free(ldb, ldif);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
int i, ret=0, count=0;
|
||||
struct ldb_cmdline *options;
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
ldb = ldb_init(NULL);
|
||||
|
||||
options = ldb_cmdline_process(ldb, argc, argv, usage);
|
||||
|
||||
if (options->argc == 0) {
|
||||
ret = process_file(ldb, stdin, &count);
|
||||
} else {
|
||||
for (i=0;i<options->argc;i++) {
|
||||
const char *fname = options->argv[i];
|
||||
FILE *f;
|
||||
f = fopen(fname, "r");
|
||||
if (!f) {
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
ret = process_file(ldb, f, &count);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(ldb);
|
||||
|
||||
printf("Added %d records with %d failures\n", count, failures);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Name: ldb
|
||||
*
|
||||
* Component: ldbdel
|
||||
*
|
||||
* Description: utility to delete records - modelled on ldapdelete
|
||||
*
|
||||
* Author: Andrew Tridgell
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
|
||||
static int ldb_delete_recursive(struct ldb_context *ldb, struct ldb_dn *dn)
|
||||
{
|
||||
int ret, i, total=0;
|
||||
const char *attrs[] = { NULL };
|
||||
struct ldb_result *res;
|
||||
|
||||
ret = ldb_search(ldb, dn, LDB_SCOPE_SUBTREE, "distinguishedName=*", attrs, &res);
|
||||
if (ret != LDB_SUCCESS) return -1;
|
||||
|
||||
for (i = 0; i < res->count; i++) {
|
||||
if (ldb_delete(ldb, res->msgs[i]->dn) == 0) {
|
||||
total++;
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(res);
|
||||
|
||||
if (total == 0) {
|
||||
return -1;
|
||||
}
|
||||
printf("Deleted %d records\n", total);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: ldbdel <options> <DN...>\n");
|
||||
printf("Options:\n");
|
||||
printf(" -r recursively delete the given subtree\n");
|
||||
printf(" -H ldb_url choose the database (or $LDB_URL)\n");
|
||||
printf(" -o options pass options like modules to activate\n");
|
||||
printf(" e.g: -o modules:timestamps\n");
|
||||
printf("\n");
|
||||
printf("Deletes records from a ldb\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
int ret = 0, i;
|
||||
struct ldb_cmdline *options;
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
ldb = ldb_init(NULL);
|
||||
|
||||
options = ldb_cmdline_process(ldb, argc, argv, usage);
|
||||
|
||||
if (options->argc < 1) {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i=0;i<options->argc;i++) {
|
||||
struct ldb_dn *dn;
|
||||
|
||||
dn = ldb_dn_new(ldb, ldb, options->argv[i]);
|
||||
if ( ! ldb_dn_validate(dn)) {
|
||||
printf("Invalid DN format\n");
|
||||
exit(1);
|
||||
}
|
||||
if (options->recursive) {
|
||||
ret = ldb_delete_recursive(ldb, dn);
|
||||
} else {
|
||||
ret = ldb_delete(ldb, dn);
|
||||
if (ret == 0) {
|
||||
printf("Deleted 1 record\n");
|
||||
}
|
||||
}
|
||||
if (ret != 0) {
|
||||
printf("delete of '%s' failed - %s\n",
|
||||
ldb_dn_get_linearized(dn),
|
||||
ldb_errstring(ldb));
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(ldb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Name: ldb
|
||||
*
|
||||
* Component: ldbedit
|
||||
*
|
||||
* Description: utility for ldb database editing
|
||||
*
|
||||
* Author: Andrew Tridgell
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
|
||||
static struct ldb_cmdline *options;
|
||||
|
||||
/*
|
||||
debug routine
|
||||
*/
|
||||
static void ldif_write_msg(struct ldb_context *ldb,
|
||||
FILE *f,
|
||||
enum ldb_changetype changetype,
|
||||
struct ldb_message *msg)
|
||||
{
|
||||
struct ldb_ldif ldif;
|
||||
ldif.changetype = changetype;
|
||||
ldif.msg = msg;
|
||||
ldb_ldif_write_file(ldb, f, &ldif);
|
||||
}
|
||||
|
||||
/*
|
||||
modify a database record so msg1 becomes msg2
|
||||
returns the number of modified elements
|
||||
*/
|
||||
static int modify_record(struct ldb_context *ldb,
|
||||
struct ldb_message *msg1,
|
||||
struct ldb_message *msg2)
|
||||
{
|
||||
struct ldb_message *mod;
|
||||
|
||||
mod = ldb_msg_diff(ldb, msg1, msg2);
|
||||
if (mod == NULL) {
|
||||
fprintf(stderr, "Failed to calculate message differences\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mod->num_elements == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (options->verbose > 0) {
|
||||
ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_MODIFY, mod);
|
||||
}
|
||||
|
||||
if (ldb_modify(ldb, mod) != 0) {
|
||||
fprintf(stderr, "failed to modify %s - %s\n",
|
||||
ldb_dn_get_linearized(msg1->dn), ldb_errstring(ldb));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mod->num_elements;
|
||||
}
|
||||
|
||||
/*
|
||||
find dn in msgs[]
|
||||
*/
|
||||
static struct ldb_message *msg_find(struct ldb_context *ldb,
|
||||
struct ldb_message **msgs,
|
||||
int count,
|
||||
struct ldb_dn *dn)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<count;i++) {
|
||||
if (ldb_dn_compare(dn, msgs[i]->dn) == 0) {
|
||||
return msgs[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
merge the changes in msgs2 into the messages from msgs1
|
||||
*/
|
||||
static int merge_edits(struct ldb_context *ldb,
|
||||
struct ldb_message **msgs1, int count1,
|
||||
struct ldb_message **msgs2, int count2)
|
||||
{
|
||||
int i;
|
||||
struct ldb_message *msg;
|
||||
int ret = 0;
|
||||
int adds=0, modifies=0, deletes=0;
|
||||
|
||||
/* do the adds and modifies */
|
||||
for (i=0;i<count2;i++) {
|
||||
msg = msg_find(ldb, msgs1, count1, msgs2[i]->dn);
|
||||
if (!msg) {
|
||||
if (options->verbose > 0) {
|
||||
ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_ADD, msgs2[i]);
|
||||
}
|
||||
if (ldb_add(ldb, msgs2[i]) != 0) {
|
||||
fprintf(stderr, "failed to add %s - %s\n",
|
||||
ldb_dn_get_linearized(msgs2[i]->dn),
|
||||
ldb_errstring(ldb));
|
||||
return -1;
|
||||
}
|
||||
adds++;
|
||||
} else {
|
||||
if (modify_record(ldb, msg, msgs2[i]) > 0) {
|
||||
modifies++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* do the deletes */
|
||||
for (i=0;i<count1;i++) {
|
||||
msg = msg_find(ldb, msgs2, count2, msgs1[i]->dn);
|
||||
if (!msg) {
|
||||
if (options->verbose > 0) {
|
||||
ldif_write_msg(ldb, stdout, LDB_CHANGETYPE_DELETE, msgs1[i]);
|
||||
}
|
||||
if (ldb_delete(ldb, msgs1[i]->dn) != 0) {
|
||||
fprintf(stderr, "failed to delete %s - %s\n",
|
||||
ldb_dn_get_linearized(msgs1[i]->dn),
|
||||
ldb_errstring(ldb));
|
||||
return -1;
|
||||
}
|
||||
deletes++;
|
||||
}
|
||||
}
|
||||
|
||||
printf("# %d adds %d modifies %d deletes\n", adds, modifies, deletes);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
save a set of messages as ldif to a file
|
||||
*/
|
||||
static int save_ldif(struct ldb_context *ldb,
|
||||
FILE *f, struct ldb_message **msgs, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(f, "# editing %d records\n", count);
|
||||
|
||||
for (i=0;i<count;i++) {
|
||||
struct ldb_ldif ldif;
|
||||
fprintf(f, "# record %d\n", i+1);
|
||||
|
||||
ldif.changetype = LDB_CHANGETYPE_NONE;
|
||||
ldif.msg = msgs[i];
|
||||
|
||||
ldb_ldif_write_file(ldb, f, &ldif);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
edit the ldb search results in msgs using the user selected editor
|
||||
*/
|
||||
static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int count1,
|
||||
const char *editor)
|
||||
{
|
||||
int fd, ret;
|
||||
FILE *f;
|
||||
char file_template[] = "/tmp/ldbedit.XXXXXX";
|
||||
char *cmd;
|
||||
struct ldb_ldif *ldif;
|
||||
struct ldb_message **msgs2 = NULL;
|
||||
int count2 = 0;
|
||||
|
||||
/* write out the original set of messages to a temporary
|
||||
file */
|
||||
fd = mkstemp(file_template);
|
||||
|
||||
if (fd == -1) {
|
||||
perror(file_template);
|
||||
return -1;
|
||||
}
|
||||
|
||||
f = fdopen(fd, "r+");
|
||||
|
||||
if (!f) {
|
||||
perror("fopen");
|
||||
close(fd);
|
||||
unlink(file_template);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (save_ldif(ldb, f, msgs1, count1) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
cmd = talloc_asprintf(ldb, "%s %s", editor, file_template);
|
||||
|
||||
if (!cmd) {
|
||||
unlink(file_template);
|
||||
fprintf(stderr, "out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* run the editor */
|
||||
ret = system(cmd);
|
||||
talloc_free(cmd);
|
||||
|
||||
if (ret != 0) {
|
||||
unlink(file_template);
|
||||
fprintf(stderr, "edit with %s failed\n", editor);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read the resulting ldif into msgs2 */
|
||||
f = fopen(file_template, "r");
|
||||
if (!f) {
|
||||
perror(file_template);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((ldif = ldb_ldif_read_file(ldb, f))) {
|
||||
msgs2 = talloc_realloc(ldb, msgs2, struct ldb_message *, count2+1);
|
||||
if (!msgs2) {
|
||||
fprintf(stderr, "out of memory");
|
||||
return -1;
|
||||
}
|
||||
msgs2[count2++] = ldif->msg;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
unlink(file_template);
|
||||
|
||||
return merge_edits(ldb, msgs1, count1, msgs2, count2);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: ldbedit <options> <expression> <attributes ...>\n");
|
||||
printf("Options:\n");
|
||||
printf(" -H ldb_url choose the database (or $LDB_URL)\n");
|
||||
printf(" -s base|sub|one choose search scope\n");
|
||||
printf(" -b basedn choose baseDN\n");
|
||||
printf(" -a edit all records (expression 'objectclass=*')\n");
|
||||
printf(" -e editor choose editor (or $VISUAL or $EDITOR)\n");
|
||||
printf(" -v verbose mode\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_result *result = NULL;
|
||||
struct ldb_dn *basedn = NULL;
|
||||
int ret;
|
||||
const char *expression = "(|(objectClass=*)(distinguishedName=*))";
|
||||
const char * const * attrs = NULL;
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
ldb = ldb_init(NULL);
|
||||
|
||||
options = ldb_cmdline_process(ldb, argc, argv, usage);
|
||||
|
||||
/* the check for '=' is for compatibility with ldapsearch */
|
||||
if (options->argc > 0 &&
|
||||
strchr(options->argv[0], '=')) {
|
||||
expression = options->argv[0];
|
||||
options->argv++;
|
||||
options->argc--;
|
||||
}
|
||||
|
||||
if (options->argc > 0) {
|
||||
attrs = (const char * const *)(options->argv);
|
||||
}
|
||||
|
||||
if (options->basedn != NULL) {
|
||||
basedn = ldb_dn_new(ldb, ldb, options->basedn);
|
||||
if ( ! ldb_dn_validate(basedn)) {
|
||||
printf("Invalid Base DN format\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ret = ldb_search(ldb, basedn, options->scope, expression, attrs, &result);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
printf("search failed - %s\n", ldb_errstring(ldb));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (result->count == 0) {
|
||||
printf("no matching records - cannot edit\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
do_edit(ldb, result->msgs, result->count, options->editor);
|
||||
|
||||
if (result) {
|
||||
ret = talloc_free(result);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "talloc_free failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(ldb);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Name: ldb
|
||||
*
|
||||
* Component: ldbmodify
|
||||
*
|
||||
* Description: utility to modify records - modelled on ldapmodify
|
||||
*
|
||||
* Author: Andrew Tridgell
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
|
||||
static int failures;
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: ldbmodify <options> <ldif...>\n");
|
||||
printf("Options:\n");
|
||||
printf(" -H ldb_url choose the database (or $LDB_URL)\n");
|
||||
printf(" -o options pass options like modules to activate\n");
|
||||
printf(" e.g: -o modules:timestamps\n");
|
||||
printf("\n");
|
||||
printf("Modifies a ldb based upon ldif change records\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
process modifies for one file
|
||||
*/
|
||||
static int process_file(struct ldb_context *ldb, FILE *f, int *count)
|
||||
{
|
||||
struct ldb_ldif *ldif;
|
||||
int ret = LDB_SUCCESS;
|
||||
|
||||
while ((ldif = ldb_ldif_read_file(ldb, f))) {
|
||||
switch (ldif->changetype) {
|
||||
case LDB_CHANGETYPE_NONE:
|
||||
case LDB_CHANGETYPE_ADD:
|
||||
ret = ldb_add(ldb, ldif->msg);
|
||||
break;
|
||||
case LDB_CHANGETYPE_DELETE:
|
||||
ret = ldb_delete(ldb, ldif->msg->dn);
|
||||
break;
|
||||
case LDB_CHANGETYPE_MODIFY:
|
||||
ret = ldb_modify(ldb, ldif->msg);
|
||||
break;
|
||||
}
|
||||
if (ret != LDB_SUCCESS) {
|
||||
fprintf(stderr, "ERR: \"%s\" on DN %s\n",
|
||||
ldb_errstring(ldb), ldb_dn_get_linearized(ldif->msg->dn));
|
||||
failures++;
|
||||
} else {
|
||||
(*count)++;
|
||||
}
|
||||
ldb_ldif_read_free(ldb, ldif);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
int count=0;
|
||||
int i, ret=LDB_SUCCESS;
|
||||
struct ldb_cmdline *options;
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
ldb = ldb_init(NULL);
|
||||
|
||||
options = ldb_cmdline_process(ldb, argc, argv, usage);
|
||||
|
||||
if (options->argc == 0) {
|
||||
ret = process_file(ldb, stdin, &count);
|
||||
} else {
|
||||
for (i=0;i<options->argc;i++) {
|
||||
const char *fname = options->argv[i];
|
||||
FILE *f;
|
||||
f = fopen(fname, "r");
|
||||
if (!f) {
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
ret = process_file(ldb, f, &count);
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(ldb);
|
||||
|
||||
printf("Modified %d records with %d failures\n", count, failures);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
Copyright (C) Stefan Metzmacher 2004
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Name: ldb
|
||||
*
|
||||
* Component: ldbrename
|
||||
*
|
||||
* Description: utility to rename records - modelled on ldapmodrdn
|
||||
*
|
||||
* Author: Andrew Tridgell
|
||||
* Author: Stefan Metzmacher
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: ldbrename [<options>] <olddn> <newdn>\n");
|
||||
printf("Options:\n");
|
||||
printf(" -H ldb_url choose the database (or $LDB_URL)\n");
|
||||
printf(" -o options pass options like modules to activate\n");
|
||||
printf(" e.g: -o modules:timestamps\n");
|
||||
printf("\n");
|
||||
printf("Renames records in a ldb\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
int ret;
|
||||
struct ldb_cmdline *options;
|
||||
struct ldb_dn *dn1, *dn2;
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
ldb = ldb_init(NULL);
|
||||
|
||||
options = ldb_cmdline_process(ldb, argc, argv, usage);
|
||||
|
||||
if (options->argc < 2) {
|
||||
usage();
|
||||
}
|
||||
|
||||
dn1 = ldb_dn_new(ldb, ldb, options->argv[0]);
|
||||
dn2 = ldb_dn_new(ldb, ldb, options->argv[1]);
|
||||
|
||||
if ( ! ldb_dn_validate(dn1)) {
|
||||
printf("Invalid DN1: %s\n", options->argv[0]);
|
||||
return -1;
|
||||
}
|
||||
if ( ! ldb_dn_validate(dn2)) {
|
||||
printf("Invalid DN2: %s\n", options->argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ldb_rename(ldb, dn1, dn2);
|
||||
if (ret == 0) {
|
||||
printf("Renamed 1 record\n");
|
||||
} else {
|
||||
printf("rename of '%s' to '%s' failed - %s\n",
|
||||
options->argv[0], options->argv[1], ldb_errstring(ldb));
|
||||
}
|
||||
|
||||
talloc_free(ldb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Name: ldb
|
||||
*
|
||||
* Component: ldbsearch
|
||||
*
|
||||
* Description: utility for ldb search - modelled on ldapsearch
|
||||
*
|
||||
* Author: Andrew Tridgell
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
|
||||
printf("Options:\n");
|
||||
printf(" -H ldb_url choose the database (or $LDB_URL)\n");
|
||||
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)
|
||||
{
|
||||
return ldb_dn_compare((*el1)->dn, (*el2)->dn);
|
||||
}
|
||||
|
||||
struct search_context {
|
||||
struct ldb_control **req_ctrls;
|
||||
|
||||
int sort;
|
||||
int num_stored;
|
||||
struct ldb_message **store;
|
||||
char **refs_store;
|
||||
|
||||
int entries;
|
||||
int refs;
|
||||
|
||||
int pending;
|
||||
int status;
|
||||
};
|
||||
|
||||
static int store_message(struct ldb_message *msg, struct search_context *sctx) {
|
||||
|
||||
sctx->store = talloc_realloc(sctx, sctx->store, struct ldb_message *, sctx->num_stored + 2);
|
||||
if (!sctx->store) {
|
||||
fprintf(stderr, "talloc_realloc failed while storing messages\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sctx->store[sctx->num_stored] = talloc_move(sctx->store, &msg);
|
||||
sctx->num_stored++;
|
||||
sctx->store[sctx->num_stored] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int store_referral(char *referral, struct search_context *sctx) {
|
||||
|
||||
sctx->refs_store = talloc_realloc(sctx, sctx->refs_store, char *, sctx->refs + 2);
|
||||
if (!sctx->refs_store) {
|
||||
fprintf(stderr, "talloc_realloc failed while storing referrals\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sctx->refs_store[sctx->refs] = talloc_move(sctx->refs_store, &referral);
|
||||
sctx->refs++;
|
||||
sctx->refs_store[sctx->refs] = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int display_message(struct ldb_context *ldb, struct ldb_message *msg, struct search_context *sctx) {
|
||||
struct ldb_ldif ldif;
|
||||
|
||||
sctx->entries++;
|
||||
printf("# record %d\n", sctx->entries);
|
||||
|
||||
ldif.changetype = LDB_CHANGETYPE_NONE;
|
||||
ldif.msg = msg;
|
||||
|
||||
if (sctx->sort) {
|
||||
/*
|
||||
* 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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int display_referral(char *referral, struct search_context *sctx)
|
||||
{
|
||||
|
||||
sctx->refs++;
|
||||
printf("# Referral\nref: %s\n\n", referral);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
|
||||
{
|
||||
struct search_context *sctx = talloc_get_type(context, struct search_context);
|
||||
int ret;
|
||||
|
||||
switch (ares->type) {
|
||||
|
||||
case LDB_REPLY_ENTRY:
|
||||
if (sctx->sort) {
|
||||
ret = store_message(ares->message, sctx);
|
||||
} else {
|
||||
ret = display_message(ldb, ares->message, sctx);
|
||||
}
|
||||
break;
|
||||
|
||||
case LDB_REPLY_REFERRAL:
|
||||
if (sctx->sort) {
|
||||
ret = store_referral(ares->referral, sctx);
|
||||
} else {
|
||||
ret = display_referral(ares->referral, sctx);
|
||||
}
|
||||
break;
|
||||
|
||||
case LDB_REPLY_DONE:
|
||||
if (ares->controls) {
|
||||
if (handle_controls_reply(ares->controls, sctx->req_ctrls) == 1)
|
||||
sctx->pending = 1;
|
||||
}
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "unknown Reply Type\n");
|
||||
return LDB_ERR_OTHER;
|
||||
}
|
||||
|
||||
if (talloc_free(ares) == -1) {
|
||||
fprintf(stderr, "talloc_free failed\n");
|
||||
sctx->pending = 0;
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
static int do_search(struct ldb_context *ldb,
|
||||
struct ldb_dn *basedn,
|
||||
struct ldb_cmdline *options,
|
||||
const char *expression,
|
||||
const char * const *attrs)
|
||||
{
|
||||
struct ldb_request *req;
|
||||
struct search_context *sctx;
|
||||
int ret;
|
||||
|
||||
req = talloc(ldb, struct ldb_request);
|
||||
if (!req) return -1;
|
||||
|
||||
sctx = talloc(req, struct search_context);
|
||||
if (!sctx) return -1;
|
||||
|
||||
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->entries = 0;
|
||||
sctx->refs = 0;
|
||||
|
||||
if (basedn == NULL) {
|
||||
basedn = ldb_get_default_basedn(ldb);
|
||||
}
|
||||
|
||||
req->operation = LDB_SEARCH;
|
||||
req->op.search.base = basedn;
|
||||
req->op.search.scope = options->scope;
|
||||
req->op.search.tree = ldb_parse_tree(req, expression);
|
||||
if (req->op.search.tree == NULL) return -1;
|
||||
req->op.search.attrs = attrs;
|
||||
req->controls = sctx->req_ctrls;
|
||||
req->context = sctx;
|
||||
req->callback = &search_callback;
|
||||
ldb_set_timeout(ldb, req, 0); /* TODO: make this settable by command line */
|
||||
|
||||
again:
|
||||
sctx->pending = 0;
|
||||
|
||||
ret = ldb_request(ldb, req);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
printf("search failed - %s\n", ldb_errstring(ldb));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ldb_wait(req->handle, LDB_WAIT_ALL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
printf("search error - %s\n", ldb_errstring(ldb));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sctx->pending)
|
||||
goto again;
|
||||
|
||||
if (sctx->sort && sctx->num_stored != 0) {
|
||||
int i;
|
||||
|
||||
ldb_qsort(sctx->store, ret, sizeof(struct ldb_message *),
|
||||
ldb, (ldb_qsort_cmp_fn_t)do_compare_msg);
|
||||
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "An error occurred while sorting messages\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < sctx->num_stored; i++) {
|
||||
display_message(ldb, sctx->store[i], sctx);
|
||||
}
|
||||
|
||||
for (i = 0; i < sctx->refs; i++) {
|
||||
display_referral(sctx->refs_store[i], sctx);
|
||||
}
|
||||
}
|
||||
|
||||
printf("# returned %d records\n# %d entries\n# %d referrals\n",
|
||||
sctx->entries + sctx->refs, sctx->entries, sctx->refs);
|
||||
|
||||
talloc_free(req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
struct ldb_context *ldb;
|
||||
struct ldb_dn *basedn = NULL;
|
||||
const char * const * attrs = NULL;
|
||||
struct ldb_cmdline *options;
|
||||
int ret = -1;
|
||||
const char *expression = "(|(objectClass=*)(distinguishedName=*))";
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
ldb = ldb_init(NULL);
|
||||
|
||||
options = ldb_cmdline_process(ldb, argc, argv, usage);
|
||||
|
||||
/* 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 (options->argc > 0) {
|
||||
attrs = (const char * const *)(options->argv);
|
||||
}
|
||||
|
||||
if (options->basedn != NULL) {
|
||||
basedn = ldb_dn_new(ldb, ldb, options->basedn);
|
||||
if ( ! ldb_dn_validate(basedn)) {
|
||||
fprintf(stderr, "Invalid Base DN format\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (options->interactive) {
|
||||
char line[1024];
|
||||
while (fgets(line, sizeof(line), stdin)) {
|
||||
if (do_search(ldb, basedn, options, line, attrs) == -1) {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = do_search(ldb, basedn, options, expression, attrs);
|
||||
}
|
||||
|
||||
talloc_free(ldb);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Andrew Tridgell 2004
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Name: ldb
|
||||
*
|
||||
* Component: ldbtest
|
||||
*
|
||||
* Description: utility to test ldb
|
||||
*
|
||||
* Author: Andrew Tridgell
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
|
||||
static struct timeval tp1,tp2;
|
||||
static struct ldb_cmdline *options;
|
||||
|
||||
static void _start_timer(void)
|
||||
{
|
||||
gettimeofday(&tp1,NULL);
|
||||
}
|
||||
|
||||
static double _end_timer(void)
|
||||
{
|
||||
gettimeofday(&tp2,NULL);
|
||||
return((tp2.tv_sec - tp1.tv_sec) +
|
||||
(tp2.tv_usec - tp1.tv_usec)*1.0e-6);
|
||||
}
|
||||
|
||||
static void add_records(struct ldb_context *ldb,
|
||||
struct ldb_dn *basedn,
|
||||
int count)
|
||||
{
|
||||
struct ldb_message msg;
|
||||
int i;
|
||||
|
||||
#if 0
|
||||
if (ldb_lock(ldb, "transaction") != 0) {
|
||||
printf("transaction lock failed\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
for (i=0;i<count;i++) {
|
||||
struct ldb_message_element el[6];
|
||||
struct ldb_val vals[6][1];
|
||||
char *name;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(ldb);
|
||||
|
||||
name = talloc_asprintf(tmp_ctx, "Test%d", i);
|
||||
|
||||
msg.dn = ldb_dn_copy(tmp_ctx, basedn);
|
||||
ldb_dn_add_child_fmt(msg.dn, "cn=%s", name);
|
||||
msg.num_elements = 6;
|
||||
msg.elements = el;
|
||||
|
||||
el[0].flags = 0;
|
||||
el[0].name = talloc_strdup(tmp_ctx, "cn");
|
||||
el[0].num_values = 1;
|
||||
el[0].values = vals[0];
|
||||
vals[0][0].data = (uint8_t *)name;
|
||||
vals[0][0].length = strlen(name);
|
||||
|
||||
el[1].flags = 0;
|
||||
el[1].name = "title";
|
||||
el[1].num_values = 1;
|
||||
el[1].values = vals[1];
|
||||
vals[1][0].data = (uint8_t *)talloc_asprintf(tmp_ctx, "The title of %s", name);
|
||||
vals[1][0].length = strlen((char *)vals[1][0].data);
|
||||
|
||||
el[2].flags = 0;
|
||||
el[2].name = talloc_strdup(tmp_ctx, "uid");
|
||||
el[2].num_values = 1;
|
||||
el[2].values = vals[2];
|
||||
vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name);
|
||||
vals[2][0].length = strlen((char *)vals[2][0].data);
|
||||
|
||||
el[3].flags = 0;
|
||||
el[3].name = talloc_strdup(tmp_ctx, "mail");
|
||||
el[3].num_values = 1;
|
||||
el[3].values = vals[3];
|
||||
vals[3][0].data = (uint8_t *)talloc_asprintf(tmp_ctx, "%s@example.com", name);
|
||||
vals[3][0].length = strlen((char *)vals[3][0].data);
|
||||
|
||||
el[4].flags = 0;
|
||||
el[4].name = talloc_strdup(tmp_ctx, "objectClass");
|
||||
el[4].num_values = 1;
|
||||
el[4].values = vals[4];
|
||||
vals[4][0].data = (uint8_t *)talloc_strdup(tmp_ctx, "OpenLDAPperson");
|
||||
vals[4][0].length = strlen((char *)vals[4][0].data);
|
||||
|
||||
el[5].flags = 0;
|
||||
el[5].name = talloc_strdup(tmp_ctx, "sn");
|
||||
el[5].num_values = 1;
|
||||
el[5].values = vals[5];
|
||||
vals[5][0].data = (uint8_t *)name;
|
||||
vals[5][0].length = strlen((char *)vals[5][0].data);
|
||||
|
||||
ldb_delete(ldb, msg.dn);
|
||||
|
||||
if (ldb_add(ldb, &msg) != 0) {
|
||||
printf("Add of %s failed - %s\n", name, ldb_errstring(ldb));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("adding uid %s\r", name);
|
||||
fflush(stdout);
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
}
|
||||
#if 0
|
||||
if (ldb_unlock(ldb, "transaction") != 0) {
|
||||
printf("transaction unlock failed\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void modify_records(struct ldb_context *ldb,
|
||||
struct ldb_dn *basedn,
|
||||
int count)
|
||||
{
|
||||
struct ldb_message msg;
|
||||
int i;
|
||||
|
||||
for (i=0;i<count;i++) {
|
||||
struct ldb_message_element el[3];
|
||||
struct ldb_val vals[3];
|
||||
char *name;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(ldb);
|
||||
|
||||
name = talloc_asprintf(tmp_ctx, "Test%d", i);
|
||||
msg.dn = ldb_dn_copy(tmp_ctx, basedn);
|
||||
ldb_dn_add_child_fmt(msg.dn, "cn=%s", name);
|
||||
|
||||
msg.num_elements = 3;
|
||||
msg.elements = el;
|
||||
|
||||
el[0].flags = LDB_FLAG_MOD_DELETE;
|
||||
el[0].name = talloc_strdup(tmp_ctx, "mail");
|
||||
el[0].num_values = 0;
|
||||
|
||||
el[1].flags = LDB_FLAG_MOD_ADD;
|
||||
el[1].name = talloc_strdup(tmp_ctx, "mail");
|
||||
el[1].num_values = 1;
|
||||
el[1].values = &vals[1];
|
||||
vals[1].data = (uint8_t *)talloc_asprintf(tmp_ctx, "%s@other.example.com", name);
|
||||
vals[1].length = strlen((char *)vals[1].data);
|
||||
|
||||
el[2].flags = LDB_FLAG_MOD_REPLACE;
|
||||
el[2].name = talloc_strdup(tmp_ctx, "mail");
|
||||
el[2].num_values = 1;
|
||||
el[2].values = &vals[2];
|
||||
vals[2].data = (uint8_t *)talloc_asprintf(tmp_ctx, "%s@other2.example.com", name);
|
||||
vals[2].length = strlen((char *)vals[2].data);
|
||||
|
||||
if (ldb_modify(ldb, &msg) != 0) {
|
||||
printf("Modify of %s failed - %s\n", name, ldb_errstring(ldb));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Modifying uid %s\r", name);
|
||||
fflush(stdout);
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
static void delete_records(struct ldb_context *ldb,
|
||||
struct ldb_dn *basedn,
|
||||
int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<count;i++) {
|
||||
struct ldb_dn *dn;
|
||||
char *name = talloc_asprintf(ldb, "Test%d", i);
|
||||
dn = ldb_dn_copy(name, basedn);
|
||||
ldb_dn_add_child_fmt(dn, "cn=%s", name);
|
||||
|
||||
printf("Deleting uid Test%d\r", i);
|
||||
fflush(stdout);
|
||||
|
||||
if (ldb_delete(ldb, dn) != 0) {
|
||||
printf("Delete of %s failed - %s\n", ldb_dn_get_linearized(dn), ldb_errstring(ldb));
|
||||
exit(1);
|
||||
}
|
||||
talloc_free(name);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void search_uid(struct ldb_context *ldb, struct ldb_dn *basedn, int nrecords, int nsearches)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<nsearches;i++) {
|
||||
int uid = (i * 700 + 17) % (nrecords * 2);
|
||||
char *expr;
|
||||
struct ldb_result *res = NULL;
|
||||
int ret;
|
||||
|
||||
expr = talloc_asprintf(ldb, "(uid=TEST%d)", uid);
|
||||
ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, expr, NULL, &res);
|
||||
|
||||
if (ret != LDB_SUCCESS || (uid < nrecords && res->count != 1)) {
|
||||
printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uid >= nrecords && res->count > 0) {
|
||||
printf("Found %s !? - %d\n", expr, ret);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("testing uid %d/%d - %d \r", i, uid, res->count);
|
||||
fflush(stdout);
|
||||
|
||||
talloc_free(res);
|
||||
talloc_free(expr);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void start_test(struct ldb_context *ldb, int nrecords, int nsearches)
|
||||
{
|
||||
struct ldb_dn *basedn;
|
||||
|
||||
basedn = ldb_dn_new(ldb, ldb, options->basedn);
|
||||
if ( ! ldb_dn_validate(basedn)) {
|
||||
printf("Invalid base DN\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Adding %d records\n", nrecords);
|
||||
add_records(ldb, basedn, nrecords);
|
||||
|
||||
printf("Starting search on uid\n");
|
||||
_start_timer();
|
||||
search_uid(ldb, basedn, nrecords, nsearches);
|
||||
printf("uid search took %.2f seconds\n", _end_timer());
|
||||
|
||||
printf("Modifying records\n");
|
||||
modify_records(ldb, basedn, nrecords);
|
||||
|
||||
printf("Deleting records\n");
|
||||
delete_records(ldb, basedn, nrecords);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
2) Store an @indexlist record
|
||||
|
||||
3) Store a record that contains fields that should be index according
|
||||
to @index
|
||||
|
||||
4) disconnection from database
|
||||
|
||||
5) connect to same database
|
||||
|
||||
6) search for record added in step 3 using a search key that should
|
||||
be indexed
|
||||
*/
|
||||
static void start_test_index(struct ldb_context **ldb)
|
||||
{
|
||||
struct ldb_message *msg;
|
||||
struct ldb_result *res = NULL;
|
||||
struct ldb_dn *indexlist;
|
||||
struct ldb_dn *basedn;
|
||||
int ret;
|
||||
int flags = 0;
|
||||
const char *specials;
|
||||
|
||||
specials = getenv("LDB_SPECIALS");
|
||||
if (specials && atoi(specials) == 0) {
|
||||
printf("LDB_SPECIALS disabled - skipping index test\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (options->nosync) {
|
||||
flags |= LDB_FLG_NOSYNC;
|
||||
}
|
||||
|
||||
printf("Starting index test\n");
|
||||
|
||||
indexlist = ldb_dn_new(*ldb, *ldb, "@INDEXLIST");
|
||||
|
||||
ldb_delete(*ldb, indexlist);
|
||||
|
||||
msg = ldb_msg_new(NULL);
|
||||
|
||||
msg->dn = indexlist;
|
||||
ldb_msg_add_string(msg, "@IDXATTR", strdup("uid"));
|
||||
|
||||
if (ldb_add(*ldb, msg) != 0) {
|
||||
printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
basedn = ldb_dn_new(*ldb, *ldb, options->basedn);
|
||||
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
msg->dn = ldb_dn_copy(msg, basedn);
|
||||
ldb_dn_add_child_fmt(msg->dn, "cn=test");
|
||||
ldb_msg_add_string(msg, "cn", strdup("test"));
|
||||
ldb_msg_add_string(msg, "sn", strdup("test"));
|
||||
ldb_msg_add_string(msg, "uid", strdup("test"));
|
||||
ldb_msg_add_string(msg, "objectClass", strdup("OpenLDAPperson"));
|
||||
|
||||
if (ldb_add(*ldb, msg) != 0) {
|
||||
printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (talloc_free(*ldb) != 0) {
|
||||
printf("failed to free/close ldb database");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(*ldb) = ldb_init(options);
|
||||
|
||||
ret = ldb_connect(*ldb, options->url, flags, NULL);
|
||||
if (ret != 0) {
|
||||
printf("failed to connect to %s\n", options->url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
basedn = ldb_dn_new(*ldb, *ldb, options->basedn);
|
||||
|
||||
ret = ldb_search(*ldb, basedn, LDB_SCOPE_SUBTREE, "uid=test", NULL, &res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
printf("Search with (uid=test) filter failed!\n");
|
||||
exit(1);
|
||||
}
|
||||
if(res->count != 1) {
|
||||
printf("Should have found 1 record - found %d\n", res->count);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
indexlist = ldb_dn_new(*ldb, *ldb, "@INDEXLIST");
|
||||
|
||||
if (ldb_delete(*ldb, msg->dn) != 0 ||
|
||||
ldb_delete(*ldb, indexlist) != 0) {
|
||||
printf("cleanup failed - %s\n", ldb_errstring(*ldb));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Finished index test\n");
|
||||
}
|
||||
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: ldbtest <options>\n");
|
||||
printf("Options:\n");
|
||||
printf(" -H ldb_url choose the database (or $LDB_URL)\n");
|
||||
printf(" --num-records nrecords database size to use\n");
|
||||
printf(" --num-searches nsearches number of searches to do\n");
|
||||
printf("\n");
|
||||
printf("tests ldb API\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
TALLOC_CTX *mem_ctx = talloc_new(NULL);
|
||||
struct ldb_context *ldb;
|
||||
|
||||
ldb_global_init();
|
||||
|
||||
ldb = ldb_init(mem_ctx);
|
||||
|
||||
options = ldb_cmdline_process(ldb, argc, argv, usage);
|
||||
|
||||
talloc_steal(mem_ctx, options);
|
||||
|
||||
if (options->basedn == NULL) {
|
||||
options->basedn = "ou=Ldb Test,ou=People,o=University of Michigan,c=TEST";
|
||||
}
|
||||
|
||||
srandom(1);
|
||||
|
||||
printf("Testing with num-records=%d and num-searches=%d\n",
|
||||
options->num_records, options->num_searches);
|
||||
|
||||
start_test(ldb, options->num_records, options->num_searches);
|
||||
|
||||
start_test_index(&ldb);
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,607 @@
|
||||
/*
|
||||
ldb database library
|
||||
|
||||
Copyright (C) Simo Sorce 2005
|
||||
|
||||
** NOTE! The following LGPL license applies to the ldb
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Name: ldb
|
||||
*
|
||||
* Component: oLschema2ldif
|
||||
*
|
||||
* Description: utility to convert an OpenLDAP schema into AD LDIF
|
||||
*
|
||||
* Author: Simo Sorce
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "ldb/include/includes.h"
|
||||
#include "ldb/tools/cmdline.h"
|
||||
#include "ldb/tools/convert.h"
|
||||
|
||||
#define SCHEMA_UNKNOWN 0
|
||||
#define SCHEMA_NAME 1
|
||||
#define SCHEMA_SUP 2
|
||||
#define SCHEMA_STRUCTURAL 3
|
||||
#define SCHEMA_ABSTRACT 4
|
||||
#define SCHEMA_AUXILIARY 5
|
||||
#define SCHEMA_MUST 6
|
||||
#define SCHEMA_MAY 7
|
||||
#define SCHEMA_SINGLE_VALUE 8
|
||||
#define SCHEMA_EQUALITY 9
|
||||
#define SCHEMA_ORDERING 10
|
||||
#define SCHEMA_SUBSTR 11
|
||||
#define SCHEMA_SYNTAX 12
|
||||
#define SCHEMA_DESC 13
|
||||
|
||||
struct schema_conv {
|
||||
int count;
|
||||
int failures;
|
||||
};
|
||||
|
||||
struct schema_token {
|
||||
int type;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct ldb_context *ldb_ctx;
|
||||
struct ldb_dn *basedn;
|
||||
|
||||
static int check_braces(const char *string)
|
||||
{
|
||||
int b;
|
||||
char *c;
|
||||
|
||||
b = 0;
|
||||
if ((c = strchr(string, '(')) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
b++;
|
||||
c++;
|
||||
while (b) {
|
||||
c = strpbrk(c, "()");
|
||||
if (c == NULL) return 1;
|
||||
if (*c == '(') b++;
|
||||
if (*c == ')') b--;
|
||||
c++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *skip_spaces(char *string) {
|
||||
return (string + strspn(string, " \t\n"));
|
||||
}
|
||||
|
||||
static int add_multi_string(struct ldb_message *msg, const char *attr, char *values)
|
||||
{
|
||||
char *c;
|
||||
char *s;
|
||||
int n;
|
||||
|
||||
c = skip_spaces(values);
|
||||
while (*c) {
|
||||
n = strcspn(c, " \t$");
|
||||
s = talloc_strndup(msg, c, n);
|
||||
if (ldb_msg_add_string(msg, attr, s) != 0) {
|
||||
return -1;
|
||||
}
|
||||
c += n;
|
||||
c += strspn(c, " \t$");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MSG_ADD_STRING(a, v) do { if (ldb_msg_add_string(msg, a, v) != 0) goto failed; } while(0)
|
||||
#define MSG_ADD_M_STRING(a, v) do { if (add_multi_string(msg, a, v) != 0) goto failed; } while(0)
|
||||
|
||||
static char *get_def_value(TALLOC_CTX *ctx, char **string)
|
||||
{
|
||||
char *c = *string;
|
||||
char *value;
|
||||
int n;
|
||||
|
||||
if (*c == '\'') {
|
||||
c++;
|
||||
n = strcspn(c, "\'");
|
||||
value = talloc_strndup(ctx, c, n);
|
||||
c += n;
|
||||
c++; /* skip closing \' */
|
||||
} else {
|
||||
n = strcspn(c, " \t\n");
|
||||
value = talloc_strndup(ctx, c, n);
|
||||
c += n;
|
||||
}
|
||||
*string = c;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static struct schema_token *get_next_schema_token(TALLOC_CTX *ctx, char **string)
|
||||
{
|
||||
char *c = skip_spaces(*string);
|
||||
char *type;
|
||||
struct schema_token *token;
|
||||
int n;
|
||||
|
||||
token = talloc(ctx, struct schema_token);
|
||||
|
||||
n = strcspn(c, " \t\n");
|
||||
type = talloc_strndup(token, c, n);
|
||||
c += n;
|
||||
c = skip_spaces(c);
|
||||
|
||||
if (strcasecmp("NAME", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_NAME;
|
||||
/* we do not support aliases so we get only the first name given and skip others */
|
||||
if (*c == '(') {
|
||||
char *s = strchr(c, ')');
|
||||
if (s == NULL) return NULL;
|
||||
s = skip_spaces(s);
|
||||
*string = s;
|
||||
|
||||
c++;
|
||||
c = skip_spaces(c);
|
||||
}
|
||||
|
||||
token->value = get_def_value(ctx, &c);
|
||||
|
||||
if (*string < c) { /* single name */
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
if (strcasecmp("SUP", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_SUP;
|
||||
|
||||
if (*c == '(') {
|
||||
c++;
|
||||
n = strcspn(c, ")");
|
||||
token->value = talloc_strndup(ctx, c, n);
|
||||
c += n;
|
||||
c++;
|
||||
} else {
|
||||
token->value = get_def_value(ctx, &c);
|
||||
}
|
||||
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("STRUCTURAL", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_STRUCTURAL;
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("ABSTRACT", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_ABSTRACT;
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("AUXILIARY", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_AUXILIARY;
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("MUST", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_MUST;
|
||||
|
||||
if (*c == '(') {
|
||||
c++;
|
||||
n = strcspn(c, ")");
|
||||
token->value = talloc_strndup(ctx, c, n);
|
||||
c += n;
|
||||
c++;
|
||||
} else {
|
||||
token->value = get_def_value(ctx, &c);
|
||||
}
|
||||
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("MAY", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_MAY;
|
||||
|
||||
if (*c == '(') {
|
||||
c++;
|
||||
n = strcspn(c, ")");
|
||||
token->value = talloc_strndup(ctx, c, n);
|
||||
c += n;
|
||||
c++;
|
||||
} else {
|
||||
token->value = get_def_value(ctx, &c);
|
||||
}
|
||||
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("SINGLE-VALUE", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_SINGLE_VALUE;
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("EQUALITY", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_EQUALITY;
|
||||
|
||||
token->value = get_def_value(ctx, &c);
|
||||
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("ORDERING", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_ORDERING;
|
||||
|
||||
token->value = get_def_value(ctx, &c);
|
||||
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("SUBSTR", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_SUBSTR;
|
||||
|
||||
token->value = get_def_value(ctx, &c);
|
||||
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("SYNTAX", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_SYNTAX;
|
||||
|
||||
token->value = get_def_value(ctx, &c);
|
||||
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
if (strcasecmp("DESC", type) == 0) {
|
||||
talloc_free(type);
|
||||
token->type = SCHEMA_DESC;
|
||||
|
||||
token->value = get_def_value(ctx, &c);
|
||||
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
|
||||
token->type = SCHEMA_UNKNOWN;
|
||||
token->value = type;
|
||||
if (*c == ')') {
|
||||
*string = c;
|
||||
return token;
|
||||
}
|
||||
if (*c == '\'') {
|
||||
c = strchr(++c, '\'');
|
||||
c++;
|
||||
} else {
|
||||
c += strcspn(c, " \t\n");
|
||||
}
|
||||
c = skip_spaces(c);
|
||||
*string = c;
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
static struct ldb_message *process_entry(TALLOC_CTX *mem_ctx, const char *entry)
|
||||
{
|
||||
TALLOC_CTX *ctx;
|
||||
struct ldb_message *msg;
|
||||
struct schema_token *token;
|
||||
char *c, *s;
|
||||
int n;
|
||||
|
||||
ctx = talloc_new(mem_ctx);
|
||||
msg = ldb_msg_new(ctx);
|
||||
|
||||
ldb_msg_add_string(msg, "objectClass", "top");
|
||||
|
||||
c = talloc_strdup(ctx, entry);
|
||||
if (!c) return NULL;
|
||||
|
||||
c = skip_spaces(c);
|
||||
|
||||
switch (*c) {
|
||||
case 'a':
|
||||
if (strncmp(c, "attributetype", 13) == 0) {
|
||||
c += 13;
|
||||
MSG_ADD_STRING("objectClass", "attributeSchema");
|
||||
break;
|
||||
}
|
||||
goto failed;
|
||||
case 'o':
|
||||
if (strncmp(c, "objectclass", 11) == 0) {
|
||||
c += 11;
|
||||
MSG_ADD_STRING("objectClass", "classSchema");
|
||||
break;
|
||||
}
|
||||
goto failed;
|
||||
default:
|
||||
goto failed;
|
||||
}
|
||||
|
||||
c = strchr(c, '(');
|
||||
if (c == NULL) goto failed;
|
||||
c++;
|
||||
|
||||
c = skip_spaces(c);
|
||||
|
||||
/* get attributeID */
|
||||
n = strcspn(c, " \t");
|
||||
s = talloc_strndup(msg, c, n);
|
||||
MSG_ADD_STRING("attributeID", s);
|
||||
c += n;
|
||||
c = skip_spaces(c);
|
||||
|
||||
while (*c != ')') {
|
||||
token = get_next_schema_token(msg, &c);
|
||||
if (!token) goto failed;
|
||||
|
||||
switch (token->type) {
|
||||
case SCHEMA_NAME:
|
||||
MSG_ADD_STRING("cn", token->value);
|
||||
MSG_ADD_STRING("name", token->value);
|
||||
MSG_ADD_STRING("lDAPDisplayName", token->value);
|
||||
msg->dn = ldb_dn_copy(msg, basedn);
|
||||
ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Schema,CN=Configuration", token->value);
|
||||
break;
|
||||
|
||||
case SCHEMA_SUP:
|
||||
MSG_ADD_M_STRING("subClassOf", token->value);
|
||||
break;
|
||||
|
||||
case SCHEMA_STRUCTURAL:
|
||||
MSG_ADD_STRING("objectClassCategory", "1");
|
||||
break;
|
||||
|
||||
case SCHEMA_ABSTRACT:
|
||||
MSG_ADD_STRING("objectClassCategory", "2");
|
||||
break;
|
||||
|
||||
case SCHEMA_AUXILIARY:
|
||||
MSG_ADD_STRING("objectClassCategory", "3");
|
||||
break;
|
||||
|
||||
case SCHEMA_MUST:
|
||||
MSG_ADD_M_STRING("mustContain", token->value);
|
||||
break;
|
||||
|
||||
case SCHEMA_MAY:
|
||||
MSG_ADD_M_STRING("mayContain", token->value);
|
||||
break;
|
||||
|
||||
case SCHEMA_SINGLE_VALUE:
|
||||
MSG_ADD_STRING("isSingleValued", "TRUE");
|
||||
break;
|
||||
|
||||
case SCHEMA_EQUALITY:
|
||||
/* TODO */
|
||||
break;
|
||||
|
||||
case SCHEMA_ORDERING:
|
||||
/* TODO */
|
||||
break;
|
||||
|
||||
case SCHEMA_SUBSTR:
|
||||
/* TODO */
|
||||
break;
|
||||
|
||||
case SCHEMA_SYNTAX:
|
||||
{
|
||||
const struct syntax_map *map =
|
||||
find_syntax_map_by_standard_oid(token->value);
|
||||
if (!map) {
|
||||
break;
|
||||
}
|
||||
MSG_ADD_STRING("attributeSyntax", map->AD_OID);
|
||||
break;
|
||||
}
|
||||
case SCHEMA_DESC:
|
||||
MSG_ADD_STRING("description", token->value);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown Definition: %s\n", token->value);
|
||||
}
|
||||
}
|
||||
|
||||
talloc_steal(mem_ctx, msg);
|
||||
talloc_free(ctx);
|
||||
return msg;
|
||||
|
||||
failed:
|
||||
talloc_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct schema_conv process_file(FILE *in, FILE *out)
|
||||
{
|
||||
TALLOC_CTX *ctx;
|
||||
struct schema_conv ret;
|
||||
char *entry;
|
||||
int c, t, line;
|
||||
struct ldb_ldif ldif;
|
||||
|
||||
ldif.changetype = LDB_CHANGETYPE_NONE;
|
||||
|
||||
ctx = talloc_new(NULL);
|
||||
|
||||
ret.count = 0;
|
||||
ret.failures = 0;
|
||||
line = 0;
|
||||
|
||||
while ((c = fgetc(in)) != EOF) {
|
||||
line++;
|
||||
/* fprintf(stderr, "Parsing line %d\n", line); */
|
||||
if (c == '#') {
|
||||
do {
|
||||
c = fgetc(in);
|
||||
} while (c != EOF && c != '\n');
|
||||
continue;
|
||||
}
|
||||
if (c == '\n') {
|
||||
continue;
|
||||
}
|
||||
|
||||
t = 0;
|
||||
entry = talloc_array(ctx, char, 1024);
|
||||
if (entry == NULL) exit(-1);
|
||||
|
||||
do {
|
||||
if (c == '\n') {
|
||||
entry[t] = '\0';
|
||||
if (check_braces(entry) == 0) {
|
||||
ret.count++;
|
||||
ldif.msg = process_entry(ctx, entry);
|
||||
if (ldif.msg == NULL) {
|
||||
ret.failures++;
|
||||
fprintf(stderr, "No valid msg from entry \n[%s]\n at line %d\n", entry, line);
|
||||
break;
|
||||
}
|
||||
ldb_ldif_write_file(ldb_ctx, out, &ldif);
|
||||
break;
|
||||
}
|
||||
line++;
|
||||
} else {
|
||||
entry[t] = c;
|
||||
t++;
|
||||
}
|
||||
if ((t % 1023) == 0) {
|
||||
entry = talloc_realloc(ctx, entry, char, t + 1024);
|
||||
if (entry == NULL) exit(-1);
|
||||
}
|
||||
} while ((c = fgetc(in)) != EOF);
|
||||
|
||||
if (c != '\n') {
|
||||
entry[t] = '\0';
|
||||
if (check_braces(entry) == 0) {
|
||||
ret.count++;
|
||||
ldif.msg = process_entry(ctx, entry);
|
||||
if (ldif.msg == NULL) {
|
||||
ret.failures++;
|
||||
fprintf(stderr, "No valid msg from entry \n[%s]\n at line %d\n", entry, line);
|
||||
break;
|
||||
}
|
||||
ldb_ldif_write_file(ldb_ctx, out, &ldif);
|
||||
} else {
|
||||
fprintf(stderr, "malformed entry on line %d\n", line);
|
||||
ret.failures++;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == EOF) break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: oLschema2ldif -H NONE <options>\n");
|
||||
printf("\nConvert OpenLDAP schema to AD-like LDIF format\n\n");
|
||||
printf("Options:\n");
|
||||
printf(" -I inputfile inputfile of OpenLDAP style schema otherwise STDIN\n");
|
||||
printf(" -O outputfile outputfile otherwise STDOUT\n");
|
||||
printf(" -o options pass options like modules to activate\n");
|
||||
printf(" e.g: -o modules:timestamps\n");
|
||||
printf("\n");
|
||||
printf("Converts records from an openLdap formatted schema to an ldif schema\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
TALLOC_CTX *ctx;
|
||||
struct schema_conv ret;
|
||||
struct ldb_cmdline *options;
|
||||
FILE *in = stdin;
|
||||
FILE *out = stdout;
|
||||
ldb_global_init();
|
||||
|
||||
ctx = talloc_new(NULL);
|
||||
ldb_ctx = ldb_init(ctx);
|
||||
|
||||
setenv("LDB_URL", "NONE", 1);
|
||||
options = ldb_cmdline_process(ldb_ctx, argc, argv, usage);
|
||||
|
||||
if (options->basedn == NULL) {
|
||||
perror("Base DN not specified");
|
||||
exit(1);
|
||||
} else {
|
||||
basedn = ldb_dn_new(ctx, ldb_ctx, options->basedn);
|
||||
if ( ! ldb_dn_validate(basedn)) {
|
||||
perror("Malformed Base DN");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (options->input) {
|
||||
in = fopen(options->input, "r");
|
||||
if (!in) {
|
||||
perror(options->input);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (options->output) {
|
||||
out = fopen(options->output, "w");
|
||||
if (!out) {
|
||||
perror(options->output);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ret = process_file(in, out);
|
||||
|
||||
fclose(in);
|
||||
fclose(out);
|
||||
|
||||
printf("Converted %d records with %d failures\n", ret.count, ret.failures);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user