⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldb_dn.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    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: ldb dn creation and manipulation utility functions * *  Description: - explode a dn into it's own basic elements *                 and put them in a structure (only if necessary) *               - manipulate ldb_dn structures * *  Author: Simo Sorce */#include "ldb_includes.h"#include <ctype.h>#define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed#define LDB_FREE(x) do { talloc_free(x); x = NULL; } while(0)/**   internal ldb exploded dn structures*/struct ldb_dn_component {	char *name;	struct ldb_val value;	char *cf_name;	struct ldb_val cf_value;};struct ldb_dn {	struct ldb_context *ldb;	/* Special DNs are always linearized */	bool special;	bool invalid;	bool valid_case;	char *linearized;	char *casefold;	unsigned int comp_num;	struct ldb_dn_component *components;};/* strdn may be NULL */struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn){	struct ldb_dn *dn;	if (! ldb) return NULL;	dn = talloc_zero(mem_ctx, struct ldb_dn);	LDB_DN_NULL_FAILED(dn);	dn->ldb = ldb;	if (strdn) {		if (strdn[0] == '@') {			dn->special = true;		}		if (strncasecmp(strdn, "<GUID=", 6) == 0) {			/* this is special DN returned when the			 * exploded_dn control is used */			dn->special = true;			/* FIXME: add a GUID string to ldb_dn structure */		} else if (strncasecmp(strdn, "<SID=", 8) == 0) {			/* this is special DN returned when the			 * exploded_dn control is used */			dn->special = true;			/* FIXME: add a SID string to ldb_dn structure */		} else if (strncasecmp(strdn, "<WKGUID=", 8) == 0) {			/* this is special DN returned when the			 * exploded_dn control is used */			dn->special = true;			/* FIXME: add a WKGUID string to ldb_dn structure */		}		dn->linearized = talloc_strdup(dn, strdn);	} else {		dn->linearized = talloc_strdup(dn, "");	}	LDB_DN_NULL_FAILED(dn->linearized);	return dn;failed:	talloc_free(dn);	return NULL;}struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...){	struct ldb_dn *dn;	char *strdn;	va_list ap;	if ( (! mem_ctx) || (! ldb)) return NULL;	dn = talloc_zero(mem_ctx, struct ldb_dn);	LDB_DN_NULL_FAILED(dn);	dn->ldb = ldb;	va_start(ap, new_fmt);	strdn = talloc_vasprintf(dn, new_fmt, ap);	va_end(ap);	LDB_DN_NULL_FAILED(strdn);	if (strdn[0] == '@') {		dn->special = true;	}	if (strncasecmp(strdn, "<GUID=", 6) == 0) {		/* this is special DN returned when the		 * exploded_dn control is used */		dn->special = true;		/* FIXME: add a GUID string to ldb_dn structure */	} else if (strncasecmp(strdn, "<SID=", 8) == 0) {		/* this is special DN returned when the		 * exploded_dn control is used */		dn->special = true;		/* FIXME: add a SID string to ldb_dn structure */	} else if (strncasecmp(strdn, "<WKGUID=", 8) == 0) {		/* this is special DN returned when the		 * exploded_dn control is used */		dn->special = true;		/* FIXME: add a WKGUID string to ldb_dn structure */	}	dn->linearized = strdn;	return dn;failed:	talloc_free(dn);	return NULL;}static int ldb_dn_escape_internal(char *dst, const char *src, int len){	const char *p, *s;	char *d;	int l;	p = s = src;	d = dst;	while (p - src < len) {		p += strcspn(p, ",=\n+<>#;\\\"");		if (p - src == len) /* found no escapable chars */			break;		memcpy(d, s, p - s); /* copy the part of the string before the stop */		d += (p - s); /* move to current position */		if (*p) { /* it is a normal escapable character */			*d++ = '\\';			*d++ = *p++;		} else { /* we have a zero byte in the string */			strncpy(d, "\00", 3); /* escape the zero */			d += 3;			p++; /* skip the zero */		}		s = p; /* move forward */	}	/* copy the last part (with zero) and return */	l = len - (s - src);	memcpy(d, s, l + 1);	/* return the length of the resulting string */	return (l + (d - dst));} char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value){	char *dst;	if (!value.length)		return NULL;	/* allocate destination string, it will be at most 3 times the source */	dst = talloc_array(mem_ctx, char, value.length * 3 + 1);	if ( ! dst) {		talloc_free(dst);		return NULL;	}	ldb_dn_escape_internal(dst, (const char *)value.data, value.length);	dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1);	return dst;}/*  explode a DN string into a ldb_dn structure  based on RFC4514 except that we don't support multiple valued RDNs*/static bool ldb_dn_explode(struct ldb_dn *dn){	char *p, *data, *d, *dt, *t;	bool trim = false;	bool in_attr = false;	bool in_value = false;	bool in_quote = false;	bool is_oid = false;	bool escape = false;	unsigned x;	int l;	if ( ! dn || dn->invalid) return false;	if (dn->components) {		return true;	}	if ( ! dn->linearized) {		return false;	}	/* Empty DNs */	if (dn->linearized[0] == '\0') {		return true;	}	/* Special DNs case */	if (dn->special) {		return true;	}	/* make sure we free this if alloced previously before replacing */	talloc_free(dn->components);	/* in the common case we have 3 or more components */	/* make sure all components are zeroed, other functions depend on this */	dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3);	if ( ! dn->components) {		return false;	}	dn->comp_num = 0;	/* Components data space is allocated here once */	data = talloc_array(dn->components, char, strlen(dn->linearized) + 1);	if (!data) {		return false;	}	p = dn->linearized;	in_attr = true;	trim = true;	t = NULL;	d = dt = data;	while (*p) {		if (in_attr) {			if (trim) {				if (*p == ' ') {					p++;					continue;				}				/* first char */				trim = false;				if (!isascii(*p)) {					/* attr names must be ascii only */					dn->invalid = true;					goto failed;				}				if (isdigit(*p)) {					is_oid = true;				} else				if ( ! isalpha(*p)) {					/* not a digit nor an alpha, invalid attribute name */					dn->invalid = true;					goto failed;				}								*d++ = *p++;				continue;			}			if (*p == ' ') {				p++;				/* valid only if we are at the end */				trim = true;				continue;			}			if (trim && (*p != '=')) {				/* spaces/tabs are not allowed in attribute names */				dn->invalid = true;				goto failed;			}			if (*p == '=') {				/* attribute terminated */				in_attr = false;				in_value = true;				trim = true;				l = 0;				*d++ = '\0';				dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt);				if ( ! dn->components[dn->comp_num].name) {					/* ouch */					goto failed;				}				dt = d;				p++;				continue;			}			if (!isascii(*p)) {				/* attr names must be ascii only */				dn->invalid = true;				goto failed;			}			if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {				/* not a digit nor a dot, invalid attribute oid */				dn->invalid = true;				goto failed;			} else			if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) {				/* not ALPHA, DIGIT or HYPHEN */				dn->invalid = true;				goto failed;			}			*d++ = *p++;			continue;		}		if (in_value) {			if (in_quote) {				if (*p == '\"') {					if (p[-1] != '\\') {						p++;						in_quote = false;						continue;					}				}				*d++ = *p++;				l++;				continue;			}			if (trim) {				if (*p == ' ') {					p++;					continue;				}				/* first char */				trim = false;				if (*p == '\"') {					in_quote = true;					p++;					continue;				}			}			switch (*p) {			/* TODO: support ber encoded values			case '#':			*/			case ',':				if (escape) {					*d++ = *p++;					l++;					escape = false;					continue;				}				/* ok found value terminator */				if ( t ) {					/* trim back */					d -= (p - t);					l -= (p - t);				}				in_attr = true;				in_value = false;				trim = true;				p++;				*d++ = '\0';				dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);				dn->components[dn->comp_num].value.length = l;				if ( ! dn->components[dn->comp_num].value.data) {					/* ouch ! */					goto failed;				}				dt = d;				dn->comp_num++;				if (dn->comp_num > 2) {					dn->components = talloc_realloc(dn,									dn->components,									struct ldb_dn_component,									dn->comp_num + 1);					if ( ! dn->components) {						/* ouch ! */						goto failed;					}					/* make sure all components are zeroed, other functions depend on this */					memset(&dn->components[dn->comp_num], '\0', sizeof(struct ldb_dn_component));				}				continue;			case '=':			case '\n':			case '+':			case '<':			case '>':			case '#':			case ';':			case '\"':				/* a string with not escaped specials is invalid (tested) */				if ( ! escape) {					dn->invalid = true;					goto failed;				}				escape = false;				*d++ = *p++;				l++;				if ( t ) t = NULL;				break;			case '\\':				if ( ! escape) {					escape = true;					p++;					continue;				}				escape = false;				*d++ = *p++;				l++;				if ( t ) t = NULL;				break;			default:				if (escape) {	 				if (sscanf(p, "%02x", &x) != 1) {						/* invalid escaping sequence */						dn->invalid = true;						goto failed;					}					escape = false;					p += 2;					*d++ = (unsigned char)x;					l++;					if ( t ) t = NULL;					break;				}				if (*p == ' ') { 					if ( ! t) t = p;				} else {					if ( t ) t = NULL;				}				*d++ = *p++;				l++;								break;			}		}	}	if (in_attr || in_quote) {		/* invalid dn */		dn->invalid = true;		goto failed;	}	/* save last element */	if ( t ) {		/* trim back */		d -= (p - t);		l -= (p - t);	}	*d++ = '\0';	dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);	dn->components[dn->comp_num].value.length = l;	if ( ! dn->components[dn->comp_num].value.data) {		/* ouch */		goto failed;	}	dn->comp_num++;	talloc_free(data);	return true;failed:	dn->comp_num = 0;	talloc_free(dn->components);	return false;}bool ldb_dn_validate(struct ldb_dn *dn){	return ldb_dn_explode(dn);}const char *ldb_dn_get_linearized(struct ldb_dn *dn){	int i, len;	char *d, *n;	if ( ! dn || ( dn->invalid)) return NULL;	if (dn->linearized) return dn->linearized;	if ( ! dn->components) {		dn->invalid = true;		return NULL;	}	if (dn->comp_num == 0) {		dn->linearized = talloc_strdup(dn, "");		if ( ! dn->linearized) return NULL;		return dn->linearized;	}	/* calculate maximum possible length of DN */	for (len = 0, i = 0; i < dn->comp_num; i++) {		len += strlen(dn->components[i].name); /* name len */		len += (dn->components[i].value.length * 3); /* max escaped data len */		len += 2; /* '=' and ',' */	}	dn->linearized = talloc_array(dn, char, len);	if ( ! dn->linearized) return NULL;	d = dn->linearized;	for (i = 0; i < dn->comp_num; i++) {		/* copy the name */		n = dn->components[i].name;		while (*n) *d++ = *n++;		*d++ = '=';		/* and the value */		d += ldb_dn_escape_internal( d,				(char *)dn->components[i].value.data,				dn->components[i].value.length);		*d++ = ',';	}	*(--d) = '\0';	/* don't waste more memory than necessary */	dn->linearized = talloc_realloc(dn, dn->linearized, char, (d - dn->linearized + 1));	return dn->linearized;}char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn){	return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));}/*  casefold a dn. We need to casefold the attribute names, and canonicalize   attribute values of case insensitive attributes.*/static bool ldb_dn_casefold_internal(struct ldb_dn *dn){	int i, ret;	if ( ! dn || dn->invalid) return false;	if (dn->valid_case) return true;	if (( ! dn->components) && ( ! ldb_dn_explode(dn))) {		return false;	}	for (i = 0; i < dn->comp_num; i++) {		const struct ldb_schema_attribute *a;		dn->components[i].cf_name = ldb_attr_casefold(dn->components, dn->components[i].name);		if (!dn->components[i].cf_name) {			goto failed;		}		a = ldb_schema_attribute_by_name(dn->ldb, dn->components[i].cf_name);		ret = a->syntax->canonicalise_fn(dn->ldb, dn->components,						 &(dn->components[i].value),						 &(dn->components[i].cf_value));		if (ret != 0) {			goto failed;		}	}	dn->valid_case = true;	return true;failed:	for (i = 0; i < dn->comp_num; i++) {		LDB_FREE(dn->components[i].cf_name);		LDB_FREE(dn->components[i].cf_value.data);	}	return false;}const char *ldb_dn_get_casefold(struct ldb_dn *dn){	int i, len;	char *d, *n;	if (dn->casefold) return dn->casefold;	if (dn->special) { 		dn->casefold = talloc_strdup(dn, dn->linearized);		if (!dn->casefold) return NULL;		dn->valid_case = true;		return dn->casefold;	}	if ( ! ldb_dn_casefold_internal(dn)) {		return NULL;	}	if (dn->comp_num == 0) {		if (dn->linearized && dn->linearized[0] == '\0') {			/* hmm a NULL dn, should we faild casefolding ? */			dn->casefold = talloc_strdup(dn, "");			return dn->casefold;		}		/* A DN must be NULL, special, or have components */		dn->invalid = true;		return NULL;	}	/* calculate maximum possible length of DN */	for (len = 0, i = 0; i < dn->comp_num; i++) {		len += strlen(dn->components[i].cf_name); /* name len */		len += (dn->components[i].cf_value.length * 3); /* max escaped data len */		len += 2; /* '=' and ',' */	}	dn->casefold = talloc_array(dn, char, len);	if ( ! dn->casefold) return NULL;	d = dn->casefold;	for (i = 0; i < dn->comp_num; i++) {		/* copy the name */		n = dn->components[i].cf_name;		while (*n) *d++ = *n++;		*d++ = '=';		/* and the value */		d += ldb_dn_escape_internal( d,				(char *)dn->components[i].cf_value.data,				dn->components[i].cf_value.length);		*d++ = ',';	}	*(--d) = '\0';	/* don't waste more memory than necessary */	dn->casefold = talloc_realloc(dn, dn->casefold, char, strlen(dn->casefold) + 1);	return dn->casefold;}char *ldb_dn_alloc_casefold(void *mem_ctx, struct ldb_dn *dn){	return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn));}/* Determine if dn is below base, in the ldap tree.  Used for * evaluating a subtree search. * 0 if they match, otherwise non-zero

⌨️ 快捷键说明

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