s4-ldap: handle VERIFY_NAME control encoding/decoding
authorMatthieu Patou <mat@matws.net>
Tue, 15 May 2012 18:15:38 +0000 (11:15 -0700)
committerMatthieu Patou <mat@matws.net>
Sat, 23 Jun 2012 06:22:02 +0000 (23:22 -0700)
source4/libcli/ldap/ldap_controls.c

index c8e562317a9e2cc84361dd5425ce648306dd99bd..17d96f6f9d7dd016180ecf4f2152e12ca75f8c40 100644 (file)
@@ -426,6 +426,101 @@ static bool decode_asq_control(void *mem_ctx, DATA_BLOB in, void *_out)
        return true;
 }
 
+static bool decode_verify_name_request(void *mem_ctx, DATA_BLOB in, void *_out)
+{
+       void **out = (void **)_out;
+       DATA_BLOB name;
+       struct asn1_data *data = asn1_init(mem_ctx);
+       struct ldb_verify_name_control *lvnc;
+       int len;
+
+       if (!data) return false;
+
+       if (!asn1_load(data, in)) {
+               return false;
+       }
+
+       lvnc = talloc(mem_ctx, struct ldb_verify_name_control);
+       if (!lvnc) {
+               return false;
+       }
+
+       if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
+               return false;
+       }
+
+       if (!asn1_read_Integer(data, &(lvnc->flags))) {
+               return false;
+       }
+
+       if (!asn1_read_OctetString(data, mem_ctx, &name)) {
+               return false;
+       }
+
+       if (name.length) {
+               len = utf16_len_n(name.data, name.length);
+               convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX,
+                                       name.data, len,
+                                       (void **)&lvnc->gc, &lvnc->gc_len);
+
+               if (!(lvnc->gc)) {
+                       return false;
+               }
+       } else {
+               lvnc->gc_len = 0;
+               lvnc->gc = NULL;
+       }
+
+       if (!asn1_end_tag(data)) {
+               return false;
+       }
+
+       *out = lvnc;
+       return true;
+}
+
+static bool encode_verify_name_request(void *mem_ctx, void *in, DATA_BLOB *out)
+{
+       struct ldb_verify_name_control *lvnc = talloc_get_type(in, struct ldb_verify_name_control);
+       struct asn1_data *data = asn1_init(mem_ctx);
+       DATA_BLOB gc_utf16;
+
+       if (!data) return false;
+
+       if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
+               return false;
+       }
+
+       if (!asn1_write_Integer(data, lvnc->flags)) {
+               return false;
+       }
+
+       if (lvnc->gc_len) {
+               convert_string_talloc(mem_ctx, CH_UNIX, CH_UTF16,
+                                               lvnc->gc, lvnc->gc_len,
+                                               (void **)&gc_utf16.data, &gc_utf16.length);
+               if (!asn1_write_OctetString(data, gc_utf16.data, gc_utf16.length)) {
+                       return false;
+               }
+       } else {
+               if (!asn1_write_OctetString(data, NULL, 0)) {
+                       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;
+       }
+       talloc_free(data);
+
+       return true;
+}
+
 static bool decode_vlv_request(void *mem_ctx, DATA_BLOB in, void *_out)
 {
        void **out = (void **)_out;
@@ -1158,6 +1253,7 @@ static const struct ldap_control_handler ldap_known_controls[] = {
        { LDB_CONTROL_RODC_DCPROMO_OID, decode_flag_request, encode_flag_request },
        { LDB_CONTROL_RELAX_OID, decode_flag_request, encode_flag_request },
        { DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference },
+       { LDB_CONTROL_VERIFY_NAME_OID, decode_verify_name_request, encode_verify_name_request },
 
        /* the following are internal only, with a network
           representation */