diff options
-rw-r--r-- | source4/lib/ldb/include/ldb.h | 16 | ||||
-rw-r--r-- | source4/lib/ldb/tools/ldbsearch.c | 38 | ||||
-rw-r--r-- | source4/libcli/ldap/ldap_controls.c | 99 |
3 files changed, 153 insertions, 0 deletions
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 2a718334fe..569bf9d6a5 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -406,6 +406,15 @@ typedef int (*ldb_qsort_cmp_fn_t) (const void *, const void *, const void *); */ #define LDB_CONTROL_SORT_RESP_OID "1.2.840.113556.1.4.474" +/** + OID for LDAP Attribute Scoped Query extension. + + This control is include in SearchRequest or SearchResponse + messages as part of the controls field of the LDAPMessage. +*/ +#define LDB_CONTROL_ASQ_OID "1.2.840.113556.1.4.1504" + + struct ldb_paged_control { int size; int cookie_len; @@ -427,6 +436,13 @@ struct ldb_sort_resp_control { char *attr_desc; }; +struct ldb_asq_control { + int request; + char *source_attribute; + int src_attr_len; + int result; +}; + struct ldb_control { const char *oid; int critical; diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c index 3b4f84c929..c81db7eb4d 100644 --- a/source4/lib/ldb/tools/ldbsearch.c +++ b/source4/lib/ldb/tools/ldbsearch.c @@ -71,6 +71,32 @@ static struct ldb_control **parse_controls(void *mem_ctx, char **control_strings ctrl = talloc_array(mem_ctx, struct ldb_control *, i + 1); for (i = 0; control_strings[i]; i++) { + 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"); + 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; @@ -176,6 +202,18 @@ static int handle_controls_reply(struct ldb_control **reply, struct ldb_control if (reply == NULL || request == NULL) return -1; for (i = 0; reply[i]; i++) { + 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; diff --git a/source4/libcli/ldap/ldap_controls.c b/source4/libcli/ldap/ldap_controls.c index 55e7a94aa7..2a48d401c9 100644 --- a/source4/libcli/ldap/ldap_controls.c +++ b/source4/libcli/ldap/ldap_controls.c @@ -225,6 +225,67 @@ static BOOL decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void **out return True; } +/* seem that this controls has 2 forms one in case it is used with + * a Search Request and another when used ina Search Response + */ +static BOOL decode_asq_control(void *mem_ctx, DATA_BLOB in, void **out) +{ + DATA_BLOB source_attribute; + struct asn1_data data; + struct ldb_asq_control *lac; + + if (!asn1_load(&data, in)) { + return False; + } + + lac = talloc(mem_ctx, struct ldb_asq_control); + if (!lac) { + return False; + } + + if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) { + return False; + } + + if (asn1_peek_tag(&data, ASN1_OCTET_STRING)) { + + if (!asn1_read_OctetString(&data, &source_attribute)) { + return False; + } + lac->src_attr_len = source_attribute.length; + if (lac->src_attr_len) { + lac->source_attribute = talloc_memdup(lac, source_attribute.data, source_attribute.length); + + if (!(lac->source_attribute)) { + return False; + } + } else { + lac->source_attribute = NULL; + } + + lac->request = 1; + + } else if (asn1_peek_tag(&data, ASN1_ENUMERATED)) { + + if (!asn1_read_enumerated(&data, &(lac->result))) { + return False; + } + + lac->request = 0; + + } else { + return False; + } + + if (!asn1_end_tag(&data)) { + return False; + } + + *out = lac; + + return True; +} + static BOOL encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out) { struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control); @@ -366,11 +427,49 @@ static BOOL encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out return True; } +/* seem that this controls has 2 forms one in case it is used with + * a Search Request and another when used ina Search Response + */ +static BOOL encode_asq_control(void *mem_ctx, void *in, DATA_BLOB *out) +{ + struct ldb_asq_control *lac = talloc_get_type(in, struct ldb_asq_control); + struct asn1_data data; + + ZERO_STRUCT(data); + + if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) { + return False; + } + + if (lac->request) { + + if (!asn1_write_OctetString(&data, lac->source_attribute, lac->src_attr_len)) { + return False; + } + } else { + if (!asn1_write_enumerated(&data, lac->result)) { + return False; + } + } + + if (!asn1_pop_tag(&data)) { + return False; + } + + *out = data_blob_talloc(mem_ctx, data.data, data.length); + if (out->data == NULL) { + return False; + } + + return True; +} + struct control_handler ldap_known_controls[] = { { "1.2.840.113556.1.4.319", decode_paged_results_request, encode_paged_results_request }, { "1.2.840.113556.1.4.529", decode_extended_dn_request, encode_extended_dn_request }, { "1.2.840.113556.1.4.473", decode_server_sort_request, encode_server_sort_request }, { "1.2.840.113556.1.4.474", decode_server_sort_response, encode_server_sort_response }, + { "1.2.840.113556.1.4.1504", decode_asq_control, encode_asq_control }, { NULL, NULL, NULL } }; |