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 + -
显示快捷键?