olschema2ldif.c

来自「samba最新软件」· C语言 代码 · 共 604 行

C
604
字号
/*    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 3 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, see <http://www.gnu.org/licenses/>.*//* *  Name: ldb * *  Component: oLschema2ldif * *  Description: utility to convert an OpenLDAP schema into AD LDIF * *  Author: Simo Sorce */#include "ldb_includes.h"#include "tools/cmdline.h"#include "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 13struct 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;	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;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?