diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/lib/ldb/include/ldb.h | 48 | ||||
-rw-r--r-- | source4/lib/ldb/tools/cmdline.c | 72 | ||||
-rw-r--r-- | source4/libcli/ldap/ldap_controls.c | 245 |
3 files changed, 361 insertions, 4 deletions
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 44f2f5840c..a6cec7f774 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -455,20 +455,36 @@ typedef int (*ldb_qsort_cmp_fn_t) (void *v1, void *v2, void *opaque); /** OID for LDAP Attribute Scoped Query extension. - This control is include in SearchRequest or SearchResponse + This control is included 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" /** - OID for LDAPrectory Sync extension. + OID for LDAP Directory Sync extension. - This control is include in SearchRequest or SearchResponse + This control is included in SearchRequest or SearchResponse messages as part of the controls field of the LDAPMessage. */ #define LDB_CONTROL_DIRSYNC_OID "1.2.840.113556.1.4.841" +/** + OID for LDAP Virtual List View Request extension. + + This control is included in SearchRequest messages + as part of the controls field of the LDAPMessage. +*/ +#define LDB_CONTROL_VLV_REQ_OID "2.16.840.1.113730.3.4.9" + +/** + OID for LDAP Virtual List View Response extension. + + This control is included in SearchResponse messages + as part of the controls field of the LDAPMessage. +*/ +#define LDB_CONTROL_VLV_RESP_OID "2.16.840.1.113730.3.4.10" + struct ldb_paged_control { int size; int cookie_len; @@ -504,6 +520,32 @@ struct ldb_dirsync_control { char *cookie; }; +struct ldb_vlv_req_control { + int beforeCount; + int afterCount; + int type; + union { + struct { + int offset; + int contentCount; + } byOffset; + struct { + int value_len; + char *value; + } gtOrEq; + } match; + int ctxid_len; + char *contextId; +}; + +struct ldb_vlv_resp_control { + int targetPosition; + int contentCount; + int vlv_result; + int ctxid_len; + char *contextId; +}; + struct ldb_control { const char *oid; int critical; diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c index 8937f9d4f6..24005c450c 100644 --- a/source4/lib/ldb/tools/cmdline.c +++ b/source4/lib/ldb/tools/cmdline.c @@ -235,6 +235,52 @@ 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], "vlv:", 4) == 0) { + struct ldb_vlv_req_control *control; + const char *p; + char attr[1024]; + char ctxid[1024]; + int crit, bc, ac, os, cc, ret; + + attr[0] = '\0'; + ctxid[0] = '\0'; + p = &(control_strings[i][4]); + ret = sscanf(p, "%d:%d:%d:%d:%d:%1023[^$]", &crit, &bc, &ac, &os, &cc, ctxid); + if (ret < 5) { + ret = sscanf(p, "%d:%d:%d:%1023[^:]:%1023[^$]", &crit, &bc, &ac, attr, ctxid); + } + + if ((ret < 4) || (crit < 0) || (crit > 1)) { + fprintf(stderr, "invalid server_sort control syntax\n"); + return NULL; + } + ctrl[i] = talloc(ctrl, struct ldb_control); + ctrl[i]->oid = LDB_CONTROL_VLV_REQ_OID; + ctrl[i]->critical = crit; + control = talloc(ctrl[i], struct ldb_vlv_req_control); + control->beforeCount = bc; + control->afterCount = ac; + if (attr[0]) { + control->type = 1; + control->match.gtOrEq.value = talloc_strdup(control, attr); + control->match.gtOrEq.value_len = strlen(attr); + } else { + control->type = 0; + control->match.byOffset.offset = os; + control->match.byOffset.contentCount = cc; + } + if (ctxid[0]) { + control->ctxid_len = ldb_base64_decode(ctxid); + control->contextId = talloc_memdup(control, ctxid, control->ctxid_len); + } else { + control->ctxid_len = 0; + control->contextId = NULL; + } + ctrl[i]->data = control; + + continue; + } + if (strncmp(control_strings[i], "dirsync:", 8) == 0) { struct ldb_dirsync_control *control; const char *p; @@ -426,6 +472,31 @@ int handle_controls_reply(struct ldb_control **reply, struct ldb_control **reque if (reply == NULL || request == NULL) return -1; for (i = 0; reply[i]; i++) { + if (strcmp(LDB_CONTROL_VLV_RESP_OID, reply[i]->oid) == 0) { + struct ldb_vlv_resp_control *rep_control; + + rep_control = talloc_get_type(reply[i]->data, struct ldb_vlv_resp_control); + + /* check we have a matching control in the request */ + for (j = 0; request[j]; j++) { + if (strcmp(LDB_CONTROL_VLV_REQ_OID, request[j]->oid) == 0) + break; + } + if (! request[j]) { + fprintf(stderr, "Warning VLV reply received but no request have been made\n"); + continue; + } + + /* check the result */ + if (rep_control->vlv_result != 0) { + fprintf(stderr, "Warning: VLV not performed with error: %d\n", rep_control->vlv_result); + } else { + fprintf(stderr, "VLV Info: target position = %d, content count = %d\n", rep_control->targetPosition, rep_control->contentCount); + } + + continue; + } + if (strcmp(LDB_CONTROL_ASQ_OID, reply[i]->oid) == 0) { struct ldb_asq_control *rep_control; @@ -438,6 +509,7 @@ int handle_controls_reply(struct ldb_control **reply, struct ldb_control **reque 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 e02efdee2c..222b4a3358 100644 --- a/source4/libcli/ldap/ldap_controls.c +++ b/source4/libcli/ldap/ldap_controls.c @@ -304,7 +304,7 @@ static BOOL decode_asq_control(void *mem_ctx, DATA_BLOB in, void **out) } lac->src_attr_len = source_attribute.length; if (lac->src_attr_len) { - lac->source_attribute = talloc_strndup(lac, source_attribute.data, source_attribute.length); + lac->source_attribute = talloc_strndup(lac, (char *)source_attribute.data, source_attribute.length); if (!(lac->source_attribute)) { return False; @@ -354,6 +354,154 @@ static BOOL decode_manageDSAIT_request(void *mem_ctx, DATA_BLOB in, void **out) return True; } +static BOOL decode_vlv_request(void *mem_ctx, DATA_BLOB in, void **out) +{ + DATA_BLOB assertion_value, context_id; + struct asn1_data data; + struct ldb_vlv_req_control *lvrc; + + if (!asn1_load(&data, in)) { + return False; + } + + lvrc = talloc(mem_ctx, struct ldb_vlv_req_control); + if (!lvrc) { + return False; + } + + if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) { + return False; + } + + if (!asn1_read_Integer(&data, &(lvrc->beforeCount))) { + return False; + } + + if (!asn1_read_Integer(&data, &(lvrc->afterCount))) { + return False; + } + + if (asn1_peek_tag(&data, ASN1_SEQUENCE(0))) { + + lvrc->type = 0; + + if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) { + return False; + } + + if (!asn1_read_Integer(&data, &(lvrc->match.byOffset.offset))) { + return False; + } + + if (!asn1_read_Integer(&data, &(lvrc->match.byOffset.contentCount))) { + return False; + } + + if (!asn1_end_tag(&data)) { + return False; + } + + } else { + + lvrc->type = 1; + + if (!asn1_read_OctetString(&data, &assertion_value)) { + return False; + } + lvrc->match.gtOrEq.value_len = assertion_value.length; + if (lvrc->match.gtOrEq.value_len) { + lvrc->match.gtOrEq.value = talloc_memdup(lvrc, assertion_value.data, assertion_value.length); + + if (!(lvrc->match.gtOrEq.value)) { + return False; + } + } else { + lvrc->match.gtOrEq.value = NULL; + } + } + + if (asn1_peek_tag(&data, ASN1_OCTET_STRING)) { + if (!asn1_read_OctetString(&data, &context_id)) { + return False; + } + lvrc->ctxid_len = context_id.length; + if (lvrc->ctxid_len) { + lvrc->contextId = talloc_memdup(lvrc, context_id.data, context_id.length); + + if (!(lvrc->contextId)) { + return False; + } + } else { + lvrc->contextId = NULL; + } + } else { + lvrc->contextId = NULL; + lvrc->ctxid_len = 0; + } + + if (!asn1_end_tag(&data)) { + return False; + } + + *out = lvrc; + + return True; +} + +static BOOL decode_vlv_response(void *mem_ctx, DATA_BLOB in, void **out) +{ + DATA_BLOB context_id; + struct asn1_data data; + struct ldb_vlv_resp_control *lvrc; + + if (!asn1_load(&data, in)) { + return False; + } + + lvrc = talloc(mem_ctx, struct ldb_vlv_resp_control); + if (!lvrc) { + return False; + } + + if (!asn1_start_tag(&data, ASN1_SEQUENCE(0))) { + return False; + } + + if (!asn1_read_Integer(&data, &(lvrc->targetPosition))) { + return False; + } + + if (!asn1_read_Integer(&data, &(lvrc->contentCount))) { + return False; + } + + if (!asn1_read_enumerated(&data, &(lvrc->vlv_result))) { + return False; + } + + if (asn1_peek_tag(&data, ASN1_OCTET_STRING)) { + if (!asn1_read_OctetString(&data, &context_id)) { + return False; + } + lvrc->contextId = talloc_strndup(lvrc, (const char *)context_id.data, context_id.length); + if (!lvrc->contextId) { + return False; + } + lvrc->ctxid_len = context_id.length; + } else { + lvrc->contextId = NULL; + lvrc->ctxid_len = 0; + } + + if (!asn1_end_tag(&data)) { + return False; + } + + *out = lvrc; + + 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); @@ -587,6 +735,99 @@ static BOOL encode_manageDSAIT_request(void *mem_ctx, void *in, DATA_BLOB *out) return True; } +static BOOL encode_vlv_request(void *mem_ctx, void *in, DATA_BLOB *out) +{ + struct ldb_vlv_req_control *lvrc = talloc_get_type(in, struct ldb_vlv_req_control); + struct asn1_data data; + + ZERO_STRUCT(data); + + if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) { + return False; + } + + if (!asn1_write_Integer(&data, lvrc->beforeCount)) { + return False; + } + + if (!asn1_write_Integer(&data, lvrc->afterCount)) { + return False; + } + + if (lvrc->type == 0) { + if (!asn1_write_Integer(&data, lvrc->match.byOffset.offset)) { + return False; + } + + if (!asn1_write_Integer(&data, lvrc->match.byOffset.contentCount)) { + return False; + } + } else { + + if (!asn1_write_OctetString(&data, lvrc->match.gtOrEq.value, lvrc->match.gtOrEq.value_len)) { + return False; + } + } + + if (lvrc->ctxid_len) { + if (!asn1_write_OctetString(&data, lvrc->contextId, lvrc->ctxid_len)) { + 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; +} + +static BOOL encode_vlv_response(void *mem_ctx, void *in, DATA_BLOB *out) +{ + struct ldb_vlv_resp_control *lvrc = talloc_get_type(in, struct ldb_vlv_resp_control); + struct asn1_data data; + + ZERO_STRUCT(data); + + if (!asn1_push_tag(&data, ASN1_SEQUENCE(0))) { + return False; + } + + if (!asn1_write_Integer(&data, lvrc->targetPosition)) { + return False; + } + + if (!asn1_write_Integer(&data, lvrc->contentCount)) { + return False; + } + + if (!asn1_write_enumerated(&data, lvrc->vlv_result)) { + return False; + } + + if (lvrc->ctxid_len) { + if (!asn1_write_OctetString(&data, lvrc->contextId, lvrc->ctxid_len)) { + 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 }, @@ -596,6 +837,8 @@ struct control_handler ldap_known_controls[] = { { "1.2.840.113556.1.4.841", decode_dirsync_request, encode_dirsync_request }, { "1.2.840.113556.1.4.528", decode_notification_request, encode_notification_request }, { "2.16.840.1.113730.3.4.2", decode_manageDSAIT_request, encode_manageDSAIT_request }, + { "2.16.840.1.113730.3.4.9", decode_vlv_request, encode_vlv_request }, + { "2.16.840.1.113730.3.4.10", decode_vlv_response, encode_vlv_response }, { NULL, NULL, NULL } }; |