s4/drs: Refactor to be more SAMBA.Coding style compliant
[ira/wip.git] / source4 / dsdb / schema / schema_prefixmap.c
index 08e51559d6a50bdfe60f63f425aaf5c216a244da..969b357a399588e213fc20faa2ac2e311e69d054 100644 (file)
 #include "librpc/gen_ndr/ndr_drsblobs.h"
 #include "../lib/util/asn1.h"
 
+
+/**
+ * Allocates schema_prefixMap object in supplied memory context
+ */
+static struct dsdb_schema_prefixmap *_dsdb_schema_prefixmap_talloc(TALLOC_CTX *mem_ctx,
+                                                                  uint32_t length)
+{
+       struct dsdb_schema_prefixmap *pfm;
+
+       pfm = talloc_zero(mem_ctx, struct dsdb_schema_prefixmap);
+       if (!pfm) {
+               return NULL;
+       }
+
+       pfm->length = length;
+       pfm->prefixes = talloc_zero_array(pfm, struct dsdb_schema_prefixmap_oid,
+                                         pfm->length);
+       if (!pfm->prefixes) {
+               talloc_free(pfm);
+               return NULL;
+       }
+
+       return pfm;
+}
+
 /**
  * Initial prefixMap creation according to:
  * [MS-DRSR] section 5.12.2
  */
-WERROR dsdb_schema_pfm_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **ppfm)
+WERROR dsdb_schema_pfm_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
 {
        uint32_t i;
        struct dsdb_schema_prefixmap *pfm;
@@ -59,13 +84,9 @@ WERROR dsdb_schema_pfm_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **p
        };
 
        /* allocate mem for prefix map */
-       pfm = talloc_zero(mem_ctx, struct dsdb_schema_prefixmap);
+       pfm = _dsdb_schema_prefixmap_talloc(mem_ctx, ARRAY_SIZE(pfm_init_data));
        W_ERROR_HAVE_NO_MEMORY(pfm);
 
-       pfm->length = ARRAY_SIZE(pfm_init_data);
-       pfm->prefixes = talloc_array(pfm, struct dsdb_schema_prefixmap_oid, pfm->length);
-       W_ERROR_HAVE_NO_MEMORY(pfm->prefixes);
-
        /* build prefixes */
        for (i = 0; i < pfm->length; i++) {
                if (!ber_write_partial_OID_String(pfm, &pfm->prefixes[i].bin_oid, pfm_init_data[i].oid_prefix)) {
@@ -75,7 +96,7 @@ WERROR dsdb_schema_pfm_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **p
                pfm->prefixes[i].id = pfm_init_data[i].id;
        }
 
-       *ppfm = pfm;
+       *_pfm = pfm;
 
        return WERR_OK;
 }
@@ -99,9 +120,7 @@ static WERROR _dsdb_schema_pfm_add_entry(struct dsdb_schema_prefixmap *pfm, DATA
 
        /* dup memory for bin-oid prefix to be added */
        bin_oid = data_blob_dup_talloc(pfm, &bin_oid);
-       if (!bin_oid.data) {
-               return WERR_NOMEM;
-       }
+       W_ERROR_HAVE_NO_MEMORY(bin_oid.data);
 
        /* make room for new entry */
        prefixes_new = talloc_realloc(pfm, pfm->prefixes, struct dsdb_schema_prefixmap_oid, pfm->length + 1);
@@ -131,74 +150,136 @@ static WERROR _dsdb_schema_pfm_add_entry(struct dsdb_schema_prefixmap *pfm, DATA
 
 
 /**
- * Make ATTID for given OID
+ * Make partial binary OID for supplied OID.
  * Reference: [MS-DRSR] section 5.12.2
  */
-WERROR dsdb_schema_pfm_make_attid(struct dsdb_schema_prefixmap *pfm, const char *oid, uint32_t *attid)
+static WERROR _dsdb_pfm_make_binary_oid(const char *full_oid, TALLOC_CTX *mem_ctx,
+                                       DATA_BLOB *_bin_oid, uint32_t *_last_subid)
 {
-       uint32_t i;
-       uint32_t lo_word, hi_word;
-       DATA_BLOB bin_oid;
-       const char *last_subid;
-       uint32_t last_value;
-       struct dsdb_schema_prefixmap_oid *pfm_entry;
-
-       if (!pfm)       return WERR_INVALID_PARAMETER;
-       if (!oid)       return WERR_INVALID_PARAMETER;
+       uint32_t last_subid;
+       const char *oid_subid;
 
        /* make last sub-identifier value */
-       last_subid = strrchr(oid, '.');
-       if (!last_subid) {
+       oid_subid = strrchr(full_oid, '.');
+       if (!oid_subid) {
                return WERR_INVALID_PARAMETER;
        }
-       last_subid++;
-       last_value = strtoul(last_subid, NULL, 10);
+       oid_subid++;
+       last_subid = strtoul(oid_subid, NULL, 10);
 
        /* encode oid in BER format */
-       if (!ber_write_OID_String(pfm, &bin_oid, oid)) {
+       if (!ber_write_OID_String(mem_ctx, _bin_oid, full_oid)) {
                return WERR_INTERNAL_ERROR;
        }
 
        /* get the prefix of the OID */
-       if (last_value < 128) {
-               bin_oid.length -= 1;
+       if (last_subid < 128) {
+               _bin_oid->length -= 1;
        } else {
-               bin_oid.length -= 2;
+               _bin_oid->length -= 2;
        }
 
-       /* search the prefix in the prefix table, if none found, add
-        * one entry for new prefix.
-        */
-       pfm_entry = NULL;
+       /* return last_value if requested */
+       if (_last_subid) {
+               *_last_subid = last_subid;
+       }
+
+       return WERR_OK;
+}
+
+/**
+ * Lookup partial-binary-oid in prefixMap
+ */
+WERROR dsdb_schema_pfm_find_binary_oid(const struct dsdb_schema_prefixmap *pfm,
+                                      DATA_BLOB bin_oid,
+                                      uint32_t *_idx)
+{
+       uint32_t i;
+
        for (i = 0; i < pfm->length; i++) {
-               if (pfm->prefixes[i].bin_oid.length != bin_oid.length)
+               if (pfm->prefixes[i].bin_oid.length != bin_oid.length) {
                        continue;
+               }
 
                if (memcmp(pfm->prefixes[i].bin_oid.data, bin_oid.data, bin_oid.length) == 0) {
-                       pfm_entry = &pfm->prefixes[i];
-                       break;
+                       if (_idx) {
+                               *_idx = i;
+                       }
+                       return WERR_OK;
                }
        }
-       /* add entry in no entry exists */
-       if (!pfm_entry) {
-               uint32_t idx;
-               WERROR werr = _dsdb_schema_pfm_add_entry(pfm, bin_oid, &idx);
-               W_ERROR_NOT_OK_RETURN(werr);
 
-               pfm_entry = &pfm->prefixes[idx];
-       } else {
+       return WERR_DS_NO_MSDS_INTID;
+}
+
+/**
+ * Lookup full-oid in prefixMap
+ * Note: this may be slow.
+ */
+WERROR dsdb_schema_pfm_find_oid(const struct dsdb_schema_prefixmap *pfm,
+                               const char *full_oid,
+                               uint32_t *_idx)
+{
+       WERROR werr;
+       DATA_BLOB bin_oid;
+
+       ZERO_STRUCT(bin_oid);
+
+       /* make partial-binary-oid to look for */
+       werr = _dsdb_pfm_make_binary_oid(full_oid, NULL, &bin_oid, NULL);
+       W_ERROR_NOT_OK_RETURN(werr);
+
+       /* lookup the partial-oid */
+       werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, _idx);
+
+       data_blob_free(&bin_oid);
+
+       return werr;
+}
+
+/**
+ * Make ATTID for given OID
+ * Reference: [MS-DRSR] section 5.12.2
+ */
+WERROR dsdb_schema_pfm_make_attid(struct dsdb_schema_prefixmap *pfm, const char *oid, uint32_t *attid)
+{
+       WERROR werr;
+       uint32_t idx;
+       uint32_t lo_word, hi_word;
+       uint32_t last_subid;
+       DATA_BLOB bin_oid;
+
+       if (!pfm) {
+               return WERR_INVALID_PARAMETER;
+       }
+       if (!oid) {
+               return WERR_INVALID_PARAMETER;
+       }
+
+       werr = _dsdb_pfm_make_binary_oid(oid, pfm, &bin_oid, &last_subid);
+       W_ERROR_NOT_OK_RETURN(werr);
+
+       /* search the prefix in the prefix table, if none found, add
+        * one entry for new prefix.
+        */
+       werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx);
+       if (W_ERROR_IS_OK(werr)) {
                /* free memory allocated for bin_oid */
                data_blob_free(&bin_oid);
+       } else {
+               /* entry does not exists, add it */
+               werr = _dsdb_schema_pfm_add_entry(pfm, bin_oid, &idx);
+               W_ERROR_NOT_OK_RETURN(werr);
        }
 
        /* compose the attid */
-       lo_word = last_value % 16384;   /* actually get lower 14 bits: lo_word & 0x3FFF */
-       if (last_value >= 16384) {
+       lo_word = last_subid % 16384;   /* actually get lower 14 bits: lo_word & 0x3FFF */
+       if (last_subid >= 16384) {
                /* mark it so that it is known to not be the whole lastValue
                 * This will raise 16-th bit*/
                lo_word += 32768;
        }
-       hi_word = pfm_entry->id;
+       hi_word = pfm->prefixes[idx].id;
 
        /* make ATTID:
         * HIWORD is prefixMap id
@@ -267,3 +348,247 @@ WERROR dsdb_schema_pfm_oid_from_attid(struct dsdb_schema_prefixmap *pfm, uint32_
        return werr;
 }
 
+
+/**
+ * Verifies drsuapi mappings.
+ */
+static WERROR _dsdb_drsuapi_pfm_verify(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
+                                      bool have_schema_info)
+{
+       uint32_t i;
+       uint32_t num_mappings;
+       struct drsuapi_DsReplicaOIDMapping *mapping;
+
+       /* check input params */
+       if (!ctr) {
+               return WERR_INVALID_PARAMETER;
+       }
+       if (!ctr->mappings) {
+               return WERR_INVALID_PARAMETER;
+       }
+       num_mappings = ctr->num_mappings;
+
+       if (have_schema_info) {
+               if (ctr->num_mappings < 2) {
+                       return WERR_INVALID_PARAMETER;
+               }
+
+               /* check last entry for being special */
+               mapping = &ctr->mappings[ctr->num_mappings - 1];
+               if (!mapping->oid.binary_oid) {
+                       return WERR_INVALID_PARAMETER;
+               }
+               if (mapping->id_prefix != 0) {
+                       return WERR_INVALID_PARAMETER;
+               }
+               if (mapping->oid.length != 21) {
+                       return WERR_INVALID_PARAMETER;
+               }
+               if (*mapping->oid.binary_oid != 0xFF) {
+                       return WERR_INVALID_PARAMETER;
+               }
+
+               /* get number of read mappings in the map */
+               num_mappings--;
+       }
+
+       /* now, verify rest of entries for being at least not null */
+       for (i = 0; i < num_mappings; i++) {
+               mapping = &ctr->mappings[i];
+               if (!mapping->oid.length) {
+                       return WERR_INVALID_PARAMETER;
+               }
+               if (!mapping->oid.binary_oid) {
+                       return WERR_INVALID_PARAMETER;
+               }
+               /* check it is not the special entry */
+               if (*mapping->oid.binary_oid == 0xFF) {
+                       return WERR_INVALID_PARAMETER;
+               }
+       }
+
+       return WERR_OK;
+}
+
+/**
+ * Convert drsuapi_ prefix map to prefixMap internal presentation.
+ *
+ * \param ctr Pointer to drsuapi_DsReplicaOIDMapping_Ctr which represents drsuapi_ prefixMap
+ * \param have_schema_info if drsuapi_prefixMap have schem_info in it or not
+ * \param mem_ctx TALLOC_CTX to make allocations in
+ * \param _pfm Out pointer to hold newly created prefixMap
+ * \param _schema_info Out param to store schema_info to. If NULL, schema_info is not decoded
+ */
+WERROR dsdb_schema_pfm_from_drsuapi_pfm(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
+                                       bool have_schema_info,
+                                       TALLOC_CTX *mem_ctx,
+                                       struct dsdb_schema_prefixmap **_pfm,
+                                       const char **_schema_info)
+{
+       WERROR werr;
+       uint32_t i;
+       DATA_BLOB blob;
+       uint32_t num_mappings;
+       struct dsdb_schema_prefixmap *pfm;
+
+       if (!_pfm) {
+               return WERR_INVALID_PARAMETER;
+       }
+
+       /*
+        * error out if schema_info is requested
+        * but it is not in the drsuapi_prefixMap
+        */
+       if (_schema_info && !have_schema_info) {
+               return WERR_INVALID_PARAMETER;
+       }
+
+       /* verify drsuapi_pefixMap */
+       werr =_dsdb_drsuapi_pfm_verify(ctr, have_schema_info);
+       W_ERROR_NOT_OK_RETURN(werr);
+
+       /* allocate mem for prefix map */
+       num_mappings = ctr->num_mappings;
+       if (have_schema_info) {
+               num_mappings--;
+       }
+       pfm = _dsdb_schema_prefixmap_talloc(mem_ctx, num_mappings);
+       W_ERROR_HAVE_NO_MEMORY(pfm);
+
+       /* copy entries from drsuapi_prefixMap */
+       for (i = 0; i < pfm->length; i++) {
+               blob = data_blob_talloc(pfm,
+                                       ctr->mappings[i].oid.binary_oid,
+                                       ctr->mappings[i].oid.length);
+               if (!blob.data) {
+                       talloc_free(pfm);
+                       return WERR_NOMEM;
+               }
+               pfm->prefixes[i].id = ctr->mappings[i].id_prefix;
+               pfm->prefixes[i].bin_oid = blob;
+       }
+
+       /* fetch schema_info if requested */
+       if (_schema_info) {
+               /* by this time, i should have this value,
+                *  but set it here for clarity */
+               i = ctr->num_mappings - 1;
+
+               *_schema_info = hex_encode_talloc(mem_ctx,
+                                                 ctr->mappings[i].oid.binary_oid,
+                                                 ctr->mappings[i].oid.length);
+               if (!*_schema_info) {
+                       talloc_free(pfm);
+                       return WERR_NOMEM;
+               }
+       }
+
+       /* schema_prefixMap created successfully */
+       *_pfm = pfm;
+
+       return WERR_OK;
+}
+
+/**
+ * Convert drsuapi_ prefix map to prefixMap internal presentation.
+ *
+ * \param pfm Schema prefixMap to be converted
+ * \param schema_info schema_info string - if NULL, we don't need it
+ * \param mem_ctx TALLOC_CTX to make allocations in
+ * \param _ctr Out pointer to drsuapi_DsReplicaOIDMapping_Ctr prefix map structure
+ */
+WERROR dsdb_drsuapi_pfm_from_schema_pfm(const struct dsdb_schema_prefixmap *pfm,
+                                       const char *schema_info,
+                                       TALLOC_CTX *mem_ctx,
+                                       struct drsuapi_DsReplicaOIDMapping_Ctr **_ctr)
+{
+       uint32_t i;
+       DATA_BLOB blob;
+       struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
+
+       if (!_ctr) {
+               return WERR_INVALID_PARAMETER;
+       }
+       if (!pfm) {
+               return WERR_INVALID_PARAMETER;
+       }
+       if (pfm->length == 0) {
+               return WERR_INVALID_PARAMETER;
+       }
+
+       /* allocate memory for the structure */
+       ctr = talloc_zero(mem_ctx, struct drsuapi_DsReplicaOIDMapping_Ctr);
+       W_ERROR_HAVE_NO_MEMORY(ctr);
+
+       ctr->num_mappings = (schema_info ? pfm->length + 1 : pfm->length);
+       ctr->mappings = talloc_array(ctr, struct drsuapi_DsReplicaOIDMapping, ctr->num_mappings);
+       if (!ctr->mappings) {
+               talloc_free(ctr);
+               return WERR_NOMEM;
+       }
+
+       /* copy entries from schema_prefixMap */
+       for (i = 0; i < pfm->length; i++) {
+               blob = data_blob_dup_talloc(ctr, &pfm->prefixes[i].bin_oid);
+               if (!blob.data) {
+                       talloc_free(ctr);
+                       return WERR_NOMEM;
+               }
+               ctr->mappings[i].id_prefix = pfm->prefixes[i].id;
+               ctr->mappings[i].oid.length = blob.length;
+               ctr->mappings[i].oid.binary_oid = blob.data;
+       }
+
+       /* make schema_info entry if needed */
+       if (schema_info) {
+               /* by this time, i should have this value,
+                *  but set it here for clarity */
+               i = ctr->num_mappings - 1;
+
+               blob = strhex_to_data_blob(ctr, schema_info);
+               if (!blob.data) {
+                       talloc_free(ctr);
+                       return WERR_NOMEM;
+               }
+
+               ctr->mappings[i].id_prefix = 0;
+               ctr->mappings[i].oid.length = blob.length;
+               ctr->mappings[i].oid.binary_oid = blob.data;
+       }
+
+       /* drsuapi_prefixMap constructed successfully */
+       *_ctr = ctr;
+
+       return WERR_OK;
+}
+
+/**
+ * Verifies schema prefixMap and drsuapi prefixMap are same.
+ * Note that we just need to verify pfm contains prefixes
+ * from ctr, not that those prefixes has same id_prefix.
+ */
+WERROR dsdb_schema_pfm_contains_drsuapi_pfm(const struct dsdb_schema_prefixmap *pfm,
+                                           const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
+{
+       WERROR werr;
+       uint32_t i;
+       uint32_t idx;
+       DATA_BLOB bin_oid;
+
+       /* verify drsuapi_pefixMap */
+       werr = _dsdb_drsuapi_pfm_verify(ctr, true);
+       W_ERROR_NOT_OK_RETURN(werr);
+
+       /* check pfm contains every entry from ctr, except the last one */
+       for (i = 0; i < ctr->num_mappings - 1; i++) {
+               bin_oid.length = ctr->mappings[i].oid.length;
+               bin_oid.data   = ctr->mappings[i].oid.binary_oid;
+
+               werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx);
+               if (!W_ERROR_IS_OK(werr)) {
+                       return WERR_DS_DRA_SCHEMA_MISMATCH;
+               }
+       }
+
+       return WERR_OK;
+}