ldap.c

来自「samba最新软件」· C语言 代码 · 共 1,402 行 · 第 1/3 页

C
1,402
字号
	}	default:		return false;	}	if (msg->controls != NULL) {		asn1_push_tag(data, ASN1_CONTEXT(0));				for (i = 0; msg->controls[i] != NULL; i++) {			if (!ldap_encode_control(mem_ctx, data, msg->controls[i])) {				return false;			}		}		asn1_pop_tag(data);	}	asn1_pop_tag(data);	if (data->has_error) {		asn1_free(data);		return false;	}	*result = data_blob_talloc(mem_ctx, data->data, data->length);	asn1_free(data);	return true;}static const char *blob2string_talloc(TALLOC_CTX *mem_ctx,				      DATA_BLOB blob){	char *result = talloc_array(mem_ctx, char, blob.length+1);	memcpy(result, blob.data, blob.length);	result[blob.length] = '\0';	return result;}static bool asn1_read_OctetString_talloc(TALLOC_CTX *mem_ctx,					 struct asn1_data *data,					 const char **result){	DATA_BLOB string;	if (!asn1_read_OctetString(data, mem_ctx, &string))		return false;	*result = blob2string_talloc(mem_ctx, string);	data_blob_free(&string);	return true;}static void ldap_decode_response(TALLOC_CTX *mem_ctx,				 struct asn1_data *data,				 struct ldap_Result *result){	asn1_read_enumerated(data, &result->resultcode);	asn1_read_OctetString_talloc(mem_ctx, data, &result->dn);	asn1_read_OctetString_talloc(mem_ctx, data, &result->errormessage);	if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {		asn1_start_tag(data, ASN1_CONTEXT(3));		asn1_read_OctetString_talloc(mem_ctx, data, &result->referral);		asn1_end_tag(data);	} else {		result->referral = NULL;	}}static struct ldb_val **ldap_decode_substring(TALLOC_CTX *mem_ctx, struct ldb_val **chunks, int chunk_num, char *value){	chunks = talloc_realloc(mem_ctx, chunks, struct ldb_val *, chunk_num + 2);	if (chunks == NULL) {		return NULL;	}	chunks[chunk_num] = talloc(mem_ctx, struct ldb_val);	if (chunks[chunk_num] == NULL) {		return NULL;	}	chunks[chunk_num]->data = (uint8_t *)talloc_strdup(mem_ctx, value);	if (chunks[chunk_num]->data == NULL) {		return NULL;	}	chunks[chunk_num]->length = strlen(value);	chunks[chunk_num + 1] = '\0';	return chunks;}/*  parse the ASN.1 formatted search string into a ldb_parse_tree*/static struct ldb_parse_tree *ldap_decode_filter_tree(TALLOC_CTX *mem_ctx, 						      struct asn1_data *data){	uint8_t filter_tag;	struct ldb_parse_tree *ret;	if (!asn1_peek_uint8(data, &filter_tag)) {		return NULL;	}	filter_tag &= 0x1f;	/* strip off the asn1 stuff */	ret = talloc(mem_ctx, struct ldb_parse_tree);	if (ret == NULL) return NULL;	switch(filter_tag) {	case 0:	case 1:		/* AND or OR of one or more filters */		ret->operation = (filter_tag == 0)?LDB_OP_AND:LDB_OP_OR;		ret->u.list.num_elements = 0;		ret->u.list.elements = NULL;		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {			goto failed;		}		while (asn1_tag_remaining(data) > 0) {			struct ldb_parse_tree *subtree;			subtree = ldap_decode_filter_tree(ret, data);			if (subtree == NULL) {				goto failed;			}			ret->u.list.elements = 				talloc_realloc(ret, ret->u.list.elements, 					       struct ldb_parse_tree *, 					       ret->u.list.num_elements+1);			if (ret->u.list.elements == NULL) {				goto failed;			}			talloc_steal(ret->u.list.elements, subtree);			ret->u.list.elements[ret->u.list.num_elements] = subtree;			ret->u.list.num_elements++;		}		if (!asn1_end_tag(data)) {			goto failed;		}		break;	case 2:		/* 'not' operation */		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {			goto failed;		}		ret->operation = LDB_OP_NOT;		ret->u.isnot.child = ldap_decode_filter_tree(ret, data);		if (ret->u.isnot.child == NULL) {			goto failed;		}		if (!asn1_end_tag(data)) {			goto failed;		}		break;	case 3: {		/* equalityMatch */		const char *attrib;		DATA_BLOB value;		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);		asn1_read_OctetString(data, mem_ctx, &value);		asn1_end_tag(data);		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {			goto failed;		}		ret->operation = LDB_OP_EQUALITY;		ret->u.equality.attr = talloc_steal(ret, attrib);		ret->u.equality.value.data = talloc_steal(ret, value.data);		ret->u.equality.value.length = value.length;		break;	}	case 4: {		/* substrings */		DATA_BLOB attr;		uint8_t subs_tag;		char *value;		int chunk_num = 0;		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {			goto failed;		}		if (!asn1_read_OctetString(data, mem_ctx, &attr)) {			goto failed;		}		ret->operation = LDB_OP_SUBSTRING;		ret->u.substring.attr = talloc_strndup(ret, (char *)attr.data, attr.length);		ret->u.substring.chunks = NULL;		ret->u.substring.start_with_wildcard = 1;		ret->u.substring.end_with_wildcard = 1;		if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {			goto failed;		}		while (asn1_tag_remaining(data)) {			asn1_peek_uint8(data, &subs_tag);			subs_tag &= 0x1f;	/* strip off the asn1 stuff */			if (subs_tag > 2) goto failed;			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(subs_tag));			asn1_read_LDAPString(data, mem_ctx, &value);			asn1_end_tag(data);			switch (subs_tag) {			case 0:				if (ret->u.substring.chunks != NULL) {					/* initial value found in the middle */					goto failed;				}				ret->u.substring.chunks = ldap_decode_substring(ret, NULL, 0, value);				if (ret->u.substring.chunks == NULL) {					goto failed;				}				ret->u.substring.start_with_wildcard = 0;				chunk_num = 1;				break;			case 1:				if (ret->u.substring.end_with_wildcard == 0) {					/* "any" value found after a "final" value */					goto failed;				}				ret->u.substring.chunks = ldap_decode_substring(ret,										ret->u.substring.chunks,										chunk_num,										value);				if (ret->u.substring.chunks == NULL) {					goto failed;				}				chunk_num++;				break;			case 2:				ret->u.substring.chunks = ldap_decode_substring(ret,										ret->u.substring.chunks,										chunk_num,										value);				if (ret->u.substring.chunks == NULL) {					goto failed;				}				ret->u.substring.end_with_wildcard = 0;				break;			default:				goto failed;			}		}		if (!asn1_end_tag(data)) { /* SEQUENCE */			goto failed;		}		if (!asn1_end_tag(data)) {			goto failed;		}		break;	}	case 5: {		/* greaterOrEqual */		const char *attrib;		DATA_BLOB value;		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);		asn1_read_OctetString(data, mem_ctx, &value);		asn1_end_tag(data);		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {			goto failed;		}		ret->operation = LDB_OP_GREATER;		ret->u.comparison.attr = talloc_steal(ret, attrib);		ret->u.comparison.value.data = talloc_steal(ret, value.data);		ret->u.comparison.value.length = value.length;		break;	}	case 6: {		/* lessOrEqual */		const char *attrib;		DATA_BLOB value;		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);		asn1_read_OctetString(data, mem_ctx, &value);		asn1_end_tag(data);		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {			goto failed;		}		ret->operation = LDB_OP_LESS;		ret->u.comparison.attr = talloc_steal(ret, attrib);		ret->u.comparison.value.data = talloc_steal(ret, value.data);		ret->u.comparison.value.length = value.length;		break;	}	case 7: {		/* Normal presence, "attribute=*" */		char *attr;		if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(filter_tag))) {			goto failed;		}		if (!asn1_read_LDAPString(data, ret, &attr)) {			goto failed;		}		ret->operation = LDB_OP_PRESENT;		ret->u.present.attr = talloc_steal(ret, attr);		if (!asn1_end_tag(data)) {			goto failed;		}		break;	}	case 8: {		/* approx */		const char *attrib;		DATA_BLOB value;		asn1_start_tag(data, ASN1_CONTEXT(filter_tag));		asn1_read_OctetString_talloc(mem_ctx, data, &attrib);		asn1_read_OctetString(data, mem_ctx, &value);		asn1_end_tag(data);		if ((data->has_error) || (attrib == NULL) || (value.data == NULL)) {			goto failed;		}		ret->operation = LDB_OP_APPROX;		ret->u.comparison.attr = talloc_steal(ret, attrib);		ret->u.comparison.value.data = talloc_steal(ret, value.data);		ret->u.comparison.value.length = value.length;		break;	}	case 9: {		char *oid = NULL, *attr = NULL, *value;		uint8_t dnAttributes;		/* an extended search */		if (!asn1_start_tag(data, ASN1_CONTEXT(filter_tag))) {			goto failed;		}		/* FIXME: read carefully rfc2251.txt there are a number of 'MUST's		   we need to check we properly implement --SSS */ 		/* either oid or type must be defined */		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(1))) { /* optional */			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(1));			asn1_read_LDAPString(data, ret, &oid);			asn1_end_tag(data);		}		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(2))) {	/* optional  */			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(2));			asn1_read_LDAPString(data, ret, &attr);			asn1_end_tag(data);		}		asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(3));		asn1_read_LDAPString(data, ret, &value);		asn1_end_tag(data);		/* dnAttributes is marked as BOOLEAN DEFAULT FALSE		   it is not marked as OPTIONAL but openldap tools		   do not set this unless it is to be set as TRUE		   NOTE: openldap tools do not work with AD as it		   seems that AD always requires the dnAttributes		   boolean value to be set */		if (asn1_peek_tag(data, ASN1_CONTEXT_SIMPLE(4))) {			asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(4));			asn1_read_uint8(data, &dnAttributes);			asn1_end_tag(data);		} else {			dnAttributes = 0;		}		if ((oid == NULL && attr == NULL) || (value == NULL)) {			goto failed;		}		if (oid) {			ret->operation               = LDB_OP_EXTENDED;			/* From the RFC2251: If the type field is			   absent and matchingRule is present, the matchValue is compared			   against all attributes in an entry which support that matchingRule			*/			if (attr) {				ret->u.extended.attr = talloc_steal(ret, attr);			} else {				ret->u.extended.attr = talloc_strdup(ret, "*");			}			ret->u.extended.rule_id      = talloc_steal(ret, oid);			ret->u.extended.value.data   = talloc_steal(ret, value);			ret->u.extended.value.length = strlen(value);			ret->u.extended.dnAttributes = dnAttributes;		} else {			ret->operation               = LDB_OP_EQUALITY;			ret->u.equality.attr         = talloc_steal(ret, attr);			ret->u.equality.value.data   = talloc_steal(ret, value);			ret->u.equality.value.length = strlen(value);		}		if (!asn1_end_tag(data)) {			goto failed;		}		break;	}	default:		DEBUG(0,("Unsupported LDAP filter operation 0x%x\n", filter_tag));		goto failed;	}		return ret;failed:	talloc_free(ret);	return NULL;	}static void ldap_decode_attrib(TALLOC_CTX *mem_ctx, struct asn1_data *data,			       struct ldb_message_element *attrib){	asn1_start_tag(data, ASN1_SEQUENCE(0));	asn1_read_OctetString_talloc(mem_ctx, data, &attrib->name);	asn1_start_tag(data, ASN1_SET);	while (asn1_peek_tag(data, ASN1_OCTET_STRING)) {		DATA_BLOB blob;		asn1_read_OctetString(data, mem_ctx, &blob);		add_value_to_attrib(mem_ctx, &blob, attrib);	}	asn1_end_tag(data);	asn1_end_tag(data);	}static void ldap_decode_attribs(TALLOC_CTX *mem_ctx, struct asn1_data *data,				struct ldb_message_element **attributes,				int *num_attributes){	asn1_start_tag(data, ASN1_SEQUENCE(0));	while (asn1_peek_tag(data, ASN1_SEQUENCE(0))) {		struct ldb_message_element attrib;		ZERO_STRUCT(attrib);		ldap_decode_attrib(mem_ctx, data, &attrib);		add_attrib_to_array_talloc(mem_ctx, &attrib,					   attributes, num_attributes);	}	asn1_end_tag(data);}/* This routine returns LDAP status codes */_PUBLIC_ NTSTATUS ldap_decode(struct asn1_data *data, struct ldap_message *msg){	uint8_t tag;	asn1_start_tag(data, ASN1_SEQUENCE(0));	asn1_read_Integer(data, &msg->messageid);

⌨️ 快捷键说明

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