Coverage Report

Created: 2026-05-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/dsdb/schema/schema_prefixmap.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
4
   DRS::prefixMap implementation
5
6
   Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2009
7
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
*/
21
22
#include "includes.h"
23
#include "dsdb/samdb/samdb.h"
24
#include "librpc/gen_ndr/ndr_drsuapi.h"
25
#include "librpc/gen_ndr/ndr_drsblobs.h"
26
#include "../lib/util/asn1.h"
27
#include "lib/util/smb_strtox.h"
28
29
30
/**
31
 * Determine range type for supplied ATTID
32
 */
33
enum dsdb_attid_type dsdb_pfm_get_attid_type(uint32_t attid)
34
0
{
35
0
  if (attid <= 0x7FFFFFFF) {
36
0
    return DSDB_ATTID_TYPE_PFM;
37
0
  }
38
0
  else if (attid <= 0xBFFFFFFF) {
39
0
    return DSDB_ATTID_TYPE_INTID;
40
0
  }
41
0
  else if (attid <= 0xFFFEFFFF) {
42
0
    return DSDB_ATTID_TYPE_RESERVED;
43
0
  }
44
0
  else {
45
0
    return DSDB_ATTID_TYPE_INTERNAL;
46
0
  }
47
0
}
48
49
/**
50
 * Allocates schema_prefixMap object in supplied memory context
51
 */
52
static struct dsdb_schema_prefixmap *_dsdb_schema_prefixmap_talloc(TALLOC_CTX *mem_ctx,
53
                   uint32_t length)
54
0
{
55
0
  struct dsdb_schema_prefixmap *pfm;
56
57
0
  pfm = talloc_zero(mem_ctx, struct dsdb_schema_prefixmap);
58
0
  if (!pfm) {
59
0
    return NULL;
60
0
  }
61
62
0
  pfm->length = length;
63
0
  pfm->prefixes = talloc_zero_array(pfm, struct dsdb_schema_prefixmap_oid,
64
0
            pfm->length);
65
0
  if (!pfm->prefixes) {
66
0
    talloc_free(pfm);
67
0
    return NULL;
68
0
  }
69
70
0
  return pfm;
71
0
}
72
73
/**
74
 * Initial prefixMap creation according to:
75
 * [MS-DRSR] section 5.12.2
76
 */
77
WERROR dsdb_schema_pfm_new(TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
78
0
{
79
0
  uint32_t i;
80
0
  struct dsdb_schema_prefixmap *pfm;
81
0
  const struct {
82
0
    uint32_t  id;
83
0
    const char  *oid_prefix;
84
0
  } pfm_init_data[] = {
85
0
    {.id=0x00000000, .oid_prefix="2.5.4"},
86
0
    {.id=0x00000001, .oid_prefix="2.5.6"},
87
0
    {.id=0x00000002, .oid_prefix="1.2.840.113556.1.2"},
88
0
    {.id=0x00000003, .oid_prefix="1.2.840.113556.1.3"},
89
0
    {.id=0x00000004, .oid_prefix="2.16.840.1.101.2.2.1"},
90
0
    {.id=0x00000005, .oid_prefix="2.16.840.1.101.2.2.3"},
91
0
    {.id=0x00000006, .oid_prefix="2.16.840.1.101.2.1.5"},
92
0
    {.id=0x00000007, .oid_prefix="2.16.840.1.101.2.1.4"},
93
0
    {.id=0x00000008, .oid_prefix="2.5.5"},
94
0
    {.id=0x00000009, .oid_prefix="1.2.840.113556.1.4"},
95
0
    {.id=0x0000000A, .oid_prefix="1.2.840.113556.1.5"},
96
0
    {.id=0x00000013, .oid_prefix="0.9.2342.19200300.100"},
97
0
    {.id=0x00000014, .oid_prefix="2.16.840.1.113730.3"},
98
0
    {.id=0x00000015, .oid_prefix="0.9.2342.19200300.100.1"},
99
0
    {.id=0x00000016, .oid_prefix="2.16.840.1.113730.3.1"},
100
0
    {.id=0x00000017, .oid_prefix="1.2.840.113556.1.5.7000"},
101
0
    {.id=0x00000018, .oid_prefix="2.5.21"},
102
0
    {.id=0x00000019, .oid_prefix="2.5.18"},
103
0
    {.id=0x0000001A, .oid_prefix="2.5.20"},
104
0
  };
105
106
  /* allocate mem for prefix map */
107
0
  pfm = _dsdb_schema_prefixmap_talloc(mem_ctx, ARRAY_SIZE(pfm_init_data));
108
0
  W_ERROR_HAVE_NO_MEMORY(pfm);
109
110
  /* build prefixes */
111
0
  for (i = 0; i < pfm->length; i++) {
112
0
    if (!ber_write_partial_OID_String(pfm, &pfm->prefixes[i].bin_oid, pfm_init_data[i].oid_prefix)) {
113
0
      talloc_free(pfm);
114
0
      return WERR_INTERNAL_ERROR;
115
0
    }
116
0
    pfm->prefixes[i].id = pfm_init_data[i].id;
117
0
  }
118
119
0
  *_pfm = pfm;
120
121
0
  return WERR_OK;
122
0
}
123
124
125
struct dsdb_schema_prefixmap *dsdb_schema_pfm_copy_shallow(TALLOC_CTX *mem_ctx,
126
                 const struct dsdb_schema_prefixmap *pfm)
127
0
{
128
0
  uint32_t i;
129
0
  struct dsdb_schema_prefixmap *pfm_copy;
130
131
0
  pfm_copy = _dsdb_schema_prefixmap_talloc(mem_ctx, pfm->length);
132
0
  if (!pfm_copy) {
133
0
    return NULL;
134
0
  }
135
0
  for (i = 0; i < pfm_copy->length; i++) {
136
0
    pfm_copy->prefixes[i] = pfm->prefixes[i];
137
0
  }
138
139
0
  return pfm_copy;
140
0
}
141
142
/**
143
 * Adds oid to prefix map.
144
 * On success returns ID for newly added index
145
 * or ID of existing entry that matches oid
146
 * Reference: [MS-DRSR] section 5.12.2
147
 *
148
 * \param pfm prefixMap
149
 * \param bin_oid OID prefix to be added to prefixMap
150
 * \param pfm_id Location where to store prefixMap entry ID
151
 */
152
WERROR dsdb_schema_pfm_add_entry(struct dsdb_schema_prefixmap *pfm,
153
         DATA_BLOB bin_oid,
154
         const uint32_t *remote_id,
155
         uint32_t *_idx)
156
0
{
157
0
  uint32_t i;
158
0
  struct dsdb_schema_prefixmap_oid * pfm_entry;
159
0
  struct dsdb_schema_prefixmap_oid * prefixes_new;
160
161
  /* dup memory for bin-oid prefix to be added */
162
0
  bin_oid = data_blob_dup_talloc(pfm, bin_oid);
163
0
  W_ERROR_HAVE_NO_MEMORY(bin_oid.data);
164
165
  /* make room for new entry */
166
0
  prefixes_new = talloc_realloc(pfm, pfm->prefixes, struct dsdb_schema_prefixmap_oid, pfm->length + 1);
167
0
  if (!prefixes_new) {
168
0
    talloc_free(bin_oid.data);
169
0
    return WERR_NOT_ENOUGH_MEMORY;
170
0
  }
171
0
  pfm->prefixes = prefixes_new;
172
173
  /* make new unique ID in prefixMap */
174
0
  pfm_entry = &pfm->prefixes[pfm->length];
175
0
  pfm_entry->id = 0;
176
0
  for (i = 0; i < pfm->length; i++) {
177
0
    if (pfm_entry->id < pfm->prefixes[i].id) {
178
0
      pfm_entry->id = pfm->prefixes[i].id;
179
0
    }
180
181
0
    if (remote_id == NULL) {
182
0
      continue;
183
0
    }
184
185
0
    if (pfm->prefixes[i].id == *remote_id) {
186
      /*
187
       * We can't use the remote id.
188
       * it's already in use.
189
       */
190
0
      remote_id = NULL;
191
0
    }
192
0
  }
193
194
  /* add new bin-oid prefix */
195
0
  if (remote_id != NULL) {
196
0
    pfm_entry->id = *remote_id;
197
0
  } else {
198
0
    pfm_entry->id++;
199
0
  }
200
0
  pfm_entry->bin_oid = bin_oid;
201
202
0
  if (_idx != NULL) {
203
0
    *_idx = pfm->length;
204
0
  }
205
0
  pfm->length++;
206
207
0
  return WERR_OK;
208
0
}
209
210
211
/**
212
 * Make partial binary OID for supplied OID.
213
 * Reference: [MS-DRSR] section 5.12.2
214
 */
215
static WERROR _dsdb_pfm_make_binary_oid(const char *full_oid, TALLOC_CTX *mem_ctx,
216
          DATA_BLOB *_bin_oid, uint32_t *_last_subid)
217
0
{
218
0
  uint32_t last_subid;
219
0
  const char *oid_subid;
220
0
  int error = 0;
221
222
  /* make last sub-identifier value */
223
0
  oid_subid = strrchr(full_oid, '.');
224
0
  if (!oid_subid) {
225
0
    return WERR_INVALID_PARAMETER;
226
0
  }
227
0
  oid_subid++;
228
0
  last_subid = smb_strtoul(oid_subid, NULL, 10, &error, SMB_STR_STANDARD);
229
0
  if (error != 0) {
230
0
    return WERR_INVALID_PARAMETER;
231
0
  }
232
233
  /* encode oid in BER format */
234
0
  if (!ber_write_OID_String(mem_ctx, _bin_oid, full_oid)) {
235
0
    DEBUG(0,("ber_write_OID_String() failed for %s\n", full_oid));
236
0
    return WERR_INTERNAL_ERROR;
237
0
  }
238
239
  /* get the prefix of the OID */
240
0
  if (last_subid < 128) {
241
0
    _bin_oid->length -= 1;
242
0
  } else {
243
0
    _bin_oid->length -= 2;
244
0
  }
245
246
  /* return last_value if requested */
247
0
  if (_last_subid) {
248
0
    *_last_subid = last_subid;
249
0
  }
250
251
0
  return WERR_OK;
252
0
}
253
254
/**
255
 * Lookup partial-binary-oid in prefixMap
256
 */
257
WERROR dsdb_schema_pfm_find_binary_oid(const struct dsdb_schema_prefixmap *pfm,
258
               DATA_BLOB bin_oid,
259
               uint32_t *_idx)
260
0
{
261
0
  uint32_t i;
262
263
0
  for (i = 0; i < pfm->length; i++) {
264
0
    if (pfm->prefixes[i].bin_oid.length != bin_oid.length) {
265
0
      continue;
266
0
    }
267
268
0
    if (memcmp(pfm->prefixes[i].bin_oid.data, bin_oid.data, bin_oid.length) == 0) {
269
0
      if (_idx) {
270
0
        *_idx = i;
271
0
      }
272
0
      return WERR_OK;
273
0
    }
274
0
  }
275
276
0
  return WERR_NOT_FOUND;
277
0
}
278
279
/**
280
 * Lookup full-oid in prefixMap
281
 * Note: this may be slow.
282
 */
283
WERROR dsdb_schema_pfm_find_oid(const struct dsdb_schema_prefixmap *pfm,
284
        const char *full_oid,
285
        uint32_t *_idx)
286
0
{
287
0
  WERROR werr;
288
0
  DATA_BLOB bin_oid;
289
290
0
  ZERO_STRUCT(bin_oid);
291
292
  /* make partial-binary-oid to look for */
293
0
  werr = _dsdb_pfm_make_binary_oid(full_oid, NULL, &bin_oid, NULL);
294
0
  W_ERROR_NOT_OK_RETURN(werr);
295
296
  /* lookup the partial-oid */
297
0
  werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, _idx);
298
299
0
  data_blob_free(&bin_oid);
300
301
0
  return werr;
302
0
}
303
304
/**
305
 * Make ATTID for given OID
306
 * If OID is not in prefixMap, new prefix
307
 * may be added depending on 'can_change_pfm' flag
308
 * Reference: [MS-DRSR] section 5.12.2
309
 */
310
static WERROR dsdb_schema_pfm_make_attid_impl(struct dsdb_schema_prefixmap *pfm,
311
                const char *oid,
312
                bool can_change_pfm,
313
                uint32_t *attid)
314
0
{
315
0
  WERROR werr;
316
0
  uint32_t idx;
317
0
  uint32_t lo_word, hi_word;
318
0
  uint32_t last_subid;
319
0
  DATA_BLOB bin_oid;
320
321
0
  if (!pfm) {
322
0
    return WERR_INVALID_PARAMETER;
323
0
  }
324
0
  if (!oid) {
325
0
    return WERR_INVALID_PARAMETER;
326
0
  }
327
328
0
  werr = _dsdb_pfm_make_binary_oid(oid, pfm, &bin_oid, &last_subid);
329
0
  W_ERROR_NOT_OK_RETURN(werr);
330
331
  /* search the prefix in the prefix table, if none found, add
332
   * one entry for new prefix.
333
   */
334
0
  werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx);
335
0
  if (W_ERROR_IS_OK(werr)) {
336
    /* free memory allocated for bin_oid */
337
0
    data_blob_free(&bin_oid);
338
0
  } else {
339
    /* return error in read-only mode */
340
0
    if (!can_change_pfm) {
341
0
      DEBUG(0, ("Unable to convert %s to an attid, and can_change_pfm=false!\n", oid));
342
0
      return werr;
343
0
    }
344
345
    /* entry does not exists, add it */
346
0
    werr = dsdb_schema_pfm_add_entry(pfm, bin_oid, NULL, &idx);
347
0
    W_ERROR_NOT_OK_RETURN(werr);
348
0
  }
349
350
  /* compose the attid */
351
0
  lo_word = last_subid % 16384; /* actually get lower 14 bits: lo_word & 0x3FFF */
352
0
  if (last_subid >= 16384) {
353
    /* mark it so that it is known to not be the whole lastValue
354
     * This will raise 16-th bit*/
355
0
    lo_word += 32768;
356
0
  }
357
0
  hi_word = pfm->prefixes[idx].id;
358
359
  /* make ATTID:
360
   * HIWORD is prefixMap id
361
   * LOWORD is truncated binary-oid */
362
0
  *attid = (hi_word * 65536) + lo_word;
363
364
0
  return WERR_OK;
365
0
}
366
367
/**
368
 * Make ATTID for given OID
369
 * Reference: [MS-DRSR] section 5.12.2
370
 *
371
 * Note: This function may change prefixMap if prefix
372
 * for supplied 'oid' doesn't exists yet.
373
 * It is recommended to be used mostly when caller
374
 * want to add new prefixes.
375
 * Otherwise dsdb_schema_pfm_attid_from_oid() should be used.
376
 */
377
WERROR dsdb_schema_pfm_make_attid(struct dsdb_schema_prefixmap *pfm,
378
          const char *oid,
379
          uint32_t *attid)
380
0
{
381
0
  return dsdb_schema_pfm_make_attid_impl(pfm, oid, true, attid);
382
0
}
383
384
/**
385
 * Make ATTID for given OID
386
 * Reference: [MS-DRSR] section 5.12.2
387
 */
388
WERROR dsdb_schema_pfm_attid_from_oid(struct dsdb_schema_prefixmap *pfm,
389
              const char *oid,
390
              uint32_t *attid)
391
0
{
392
0
  return dsdb_schema_pfm_make_attid_impl(pfm, oid, false, attid);
393
0
}
394
395
/**
396
 * Make OID for given ATTID.
397
 * Reference: [MS-DRSR] section 5.12.2
398
 */
399
WERROR dsdb_schema_pfm_oid_from_attid(const struct dsdb_schema_prefixmap *pfm,
400
              uint32_t attid,
401
              TALLOC_CTX *mem_ctx, const char **_oid)
402
0
{
403
0
  uint32_t i;
404
0
  uint32_t hi_word, lo_word;
405
0
  DATA_BLOB bin_oid = {NULL, 0};
406
0
  char *oid;
407
0
  struct dsdb_schema_prefixmap_oid *pfm_entry;
408
0
  WERROR werr = WERR_OK;
409
410
  /* sanity check for attid requested */
411
0
  if (dsdb_pfm_get_attid_type(attid) != DSDB_ATTID_TYPE_PFM) {
412
0
    return WERR_INVALID_PARAMETER;
413
0
  }
414
415
  /* crack attid value */
416
0
  hi_word = attid >> 16;
417
0
  lo_word = attid & 0xFFFF;
418
419
  /* locate corRespoNding prefixMap entry */
420
0
  pfm_entry = NULL;
421
0
  for (i = 0; i < pfm->length; i++) {
422
0
    if (hi_word == pfm->prefixes[i].id) {
423
0
      pfm_entry = &pfm->prefixes[i];
424
0
      break;
425
0
    }
426
0
  }
427
428
0
  if (!pfm_entry) {
429
0
    DEBUG(1,("Failed to find prefixMap entry for ATTID = 0x%08X (%d)\n",
430
0
       attid, attid));
431
0
    return WERR_DS_NO_ATTRIBUTE_OR_VALUE;
432
0
  }
433
434
  /* copy oid prefix making enough room */
435
0
  bin_oid.length = pfm_entry->bin_oid.length + 2;
436
0
  bin_oid.data = talloc_array(mem_ctx, uint8_t, bin_oid.length);
437
0
  W_ERROR_HAVE_NO_MEMORY(bin_oid.data);
438
0
  memcpy(bin_oid.data, pfm_entry->bin_oid.data, pfm_entry->bin_oid.length);
439
440
0
  if (lo_word < 128) {
441
0
    bin_oid.length = bin_oid.length - 1;
442
0
    bin_oid.data[bin_oid.length-1] = lo_word;
443
0
  }
444
0
  else {
445
0
    if (lo_word >= 32768) {
446
0
      lo_word -= 32768;
447
0
    }
448
0
    bin_oid.data[bin_oid.length-2] = (0x80 | ((lo_word>>7) & 0x7f));
449
0
    bin_oid.data[bin_oid.length-1] = lo_word & 0x7f;
450
0
  }
451
452
0
  if (!ber_read_OID_String(mem_ctx, bin_oid, &oid)) {
453
0
    DEBUG(0,("ber_read_OID_String() failed for %s\n",
454
0
       hex_encode_talloc(bin_oid.data, bin_oid.data, bin_oid.length)));
455
0
    werr = WERR_INTERNAL_ERROR;
456
0
  }
457
458
  /* free locally allocated memory */
459
0
  talloc_free(bin_oid.data);
460
461
0
  *_oid = oid;
462
463
0
  return werr;
464
0
}
465
466
467
/**
468
 * Verifies drsuapi mappings.
469
 */
470
static WERROR _dsdb_drsuapi_pfm_verify(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
471
               bool have_schema_info)
472
0
{
473
0
  uint32_t i;
474
0
  uint32_t num_mappings;
475
0
  struct drsuapi_DsReplicaOIDMapping *mapping;
476
477
  /* check input params */
478
0
  if (!ctr) {
479
0
    return WERR_INVALID_PARAMETER;
480
0
  }
481
0
  if (!ctr->mappings) {
482
0
    return WERR_INVALID_PARAMETER;
483
0
  }
484
0
  num_mappings = ctr->num_mappings;
485
486
0
  if (have_schema_info) {
487
0
    DATA_BLOB blob;
488
489
0
    if (ctr->num_mappings < 2) {
490
0
      return WERR_INVALID_PARAMETER;
491
0
    }
492
493
    /* check last entry for being special */
494
0
    mapping = &ctr->mappings[ctr->num_mappings - 1];
495
0
    if (mapping->id_prefix != 0) {
496
0
      return WERR_INVALID_PARAMETER;
497
0
    }
498
499
    /* verify schemaInfo blob is valid one */
500
0
    blob = data_blob_const(mapping->oid.binary_oid, mapping->oid.length);
501
0
    if (!dsdb_schema_info_blob_is_valid(&blob)) {
502
0
      return WERR_INVALID_PARAMETER;
503
0
    }
504
505
    /* get number of read mappings in the map */
506
0
    num_mappings--;
507
0
  }
508
509
  /* now, verify rest of entries for being at least not null */
510
0
  for (i = 0; i < num_mappings; i++) {
511
0
    mapping = &ctr->mappings[i];
512
0
    if (!mapping->oid.length) {
513
0
      return WERR_INVALID_PARAMETER;
514
0
    }
515
0
    if (!mapping->oid.binary_oid) {
516
0
      return WERR_INVALID_PARAMETER;
517
0
    }
518
    /* check it is not the special entry */
519
0
    if (*mapping->oid.binary_oid == 0xFF) {
520
0
      return WERR_INVALID_PARAMETER;
521
0
    }
522
0
  }
523
524
0
  return WERR_OK;
525
0
}
526
527
/**
528
 * Convert drsuapi_ prefix map to prefixMap internal presentation.
529
 *
530
 * \param ctr Pointer to drsuapi_DsReplicaOIDMapping_Ctr which represents drsuapi_ prefixMap
531
 * \param have_schema_info if drsuapi_prefixMap have schem_info in it or not
532
 * \param mem_ctx TALLOC_CTX to make allocations in
533
 * \param _pfm Out pointer to hold newly created prefixMap
534
 * \param _schema_info Out param to store schema_info to. If NULL, schema_info is not decoded
535
 */
536
WERROR dsdb_schema_pfm_from_drsuapi_pfm(const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr,
537
          bool have_schema_info,
538
          TALLOC_CTX *mem_ctx,
539
          struct dsdb_schema_prefixmap **_pfm,
540
          struct dsdb_schema_info **_schema_info)
541
0
{
542
0
  WERROR werr;
543
0
  uint32_t i;
544
0
  DATA_BLOB blob;
545
0
  uint32_t num_mappings;
546
0
  struct dsdb_schema_prefixmap *pfm;
547
548
0
  if (!_pfm) {
549
0
    return WERR_INVALID_PARAMETER;
550
0
  }
551
552
  /*
553
   * error out if schema_info is requested
554
   * but it is not in the drsuapi_prefixMap
555
   */
556
0
  if (_schema_info && !have_schema_info) {
557
0
    return WERR_INVALID_PARAMETER;
558
0
  }
559
560
  /* verify drsuapi_pefixMap */
561
0
  werr =_dsdb_drsuapi_pfm_verify(ctr, have_schema_info);
562
0
  W_ERROR_NOT_OK_RETURN(werr);
563
564
  /* allocate mem for prefix map */
565
0
  num_mappings = ctr->num_mappings;
566
0
  if (have_schema_info) {
567
0
    num_mappings--;
568
0
  }
569
0
  pfm = _dsdb_schema_prefixmap_talloc(mem_ctx, num_mappings);
570
0
  W_ERROR_HAVE_NO_MEMORY(pfm);
571
572
  /* copy entries from drsuapi_prefixMap */
573
0
  for (i = 0; i < pfm->length; i++) {
574
0
    blob = data_blob_talloc(pfm,
575
0
          ctr->mappings[i].oid.binary_oid,
576
0
          ctr->mappings[i].oid.length);
577
0
    if (!blob.data) {
578
0
      talloc_free(pfm);
579
0
      return WERR_NOT_ENOUGH_MEMORY;
580
0
    }
581
0
    pfm->prefixes[i].id = ctr->mappings[i].id_prefix;
582
0
    pfm->prefixes[i].bin_oid = blob;
583
0
  }
584
585
  /* fetch schema_info if requested */
586
0
  if (_schema_info) {
587
    /* by this time, i should have this value,
588
     *  but set it here for clarity */
589
0
    i = ctr->num_mappings - 1;
590
591
0
    blob = data_blob_const(ctr->mappings[i].oid.binary_oid,
592
0
               ctr->mappings[i].oid.length);
593
0
    werr = dsdb_schema_info_from_blob(&blob, mem_ctx, _schema_info);
594
0
    if (!W_ERROR_IS_OK(werr)) {
595
0
      talloc_free(pfm);
596
0
      return werr;
597
0
    }
598
0
  }
599
600
  /* schema_prefixMap created successfully */
601
0
  *_pfm = pfm;
602
603
0
  return WERR_OK;
604
0
}
605
606
/**
607
 * Convert drsuapi_ prefix map to prefixMap internal presentation.
608
 *
609
 * \param pfm Schema prefixMap to be converted
610
 * \param schema_info schema_info string - if NULL, we don't need it
611
 * \param mem_ctx TALLOC_CTX to make allocations in
612
 * \param _ctr Out pointer to drsuapi_DsReplicaOIDMapping_Ctr prefix map structure
613
 */
614
WERROR dsdb_drsuapi_pfm_from_schema_pfm(const struct dsdb_schema_prefixmap *pfm,
615
          const struct dsdb_schema_info *schema_info,
616
          TALLOC_CTX *mem_ctx,
617
          struct drsuapi_DsReplicaOIDMapping_Ctr **_ctr)
618
0
{
619
0
  uint32_t i;
620
0
  DATA_BLOB blob;
621
0
  struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
622
623
0
  if (!_ctr) {
624
0
    return WERR_INVALID_PARAMETER;
625
0
  }
626
0
  if (!pfm) {
627
0
    return WERR_INVALID_PARAMETER;
628
0
  }
629
0
  if (pfm->length == 0) {
630
0
    return WERR_INVALID_PARAMETER;
631
0
  }
632
633
  /* allocate memory for the structure */
634
0
  ctr = talloc_zero(mem_ctx, struct drsuapi_DsReplicaOIDMapping_Ctr);
635
0
  W_ERROR_HAVE_NO_MEMORY(ctr);
636
637
0
  ctr->num_mappings = (schema_info ? pfm->length + 1 : pfm->length);
638
0
  ctr->mappings = talloc_array(ctr, struct drsuapi_DsReplicaOIDMapping, ctr->num_mappings);
639
0
  if (!ctr->mappings) {
640
0
    talloc_free(ctr);
641
0
    return WERR_NOT_ENOUGH_MEMORY;
642
0
  }
643
644
  /* copy entries from schema_prefixMap */
645
0
  for (i = 0; i < pfm->length; i++) {
646
0
    blob = data_blob_dup_talloc(ctr, pfm->prefixes[i].bin_oid);
647
0
    if (!blob.data) {
648
0
      talloc_free(ctr);
649
0
      return WERR_NOT_ENOUGH_MEMORY;
650
0
    }
651
0
    ctr->mappings[i].id_prefix = pfm->prefixes[i].id;
652
0
    ctr->mappings[i].oid.length = blob.length;
653
0
    ctr->mappings[i].oid.binary_oid = blob.data;
654
0
  }
655
656
  /* make schema_info entry if needed */
657
0
  if (schema_info) {
658
0
    WERROR werr;
659
660
    /* by this time, i should have this value,
661
     *  but set it here for clarity */
662
0
    i = ctr->num_mappings - 1;
663
664
0
    werr = dsdb_blob_from_schema_info(schema_info, ctr, &blob);
665
0
    if (!W_ERROR_IS_OK(werr)) {
666
0
      talloc_free(ctr);
667
0
      return werr;
668
0
    }
669
670
0
    ctr->mappings[i].id_prefix = 0;
671
0
    ctr->mappings[i].oid.length = blob.length;
672
0
    ctr->mappings[i].oid.binary_oid = blob.data;
673
0
  }
674
675
  /* drsuapi_prefixMap constructed successfully */
676
0
  *_ctr = ctr;
677
678
0
  return WERR_OK;
679
0
}
680
681
/**
682
 * Verifies schema prefixMap and drsuapi prefixMap are same.
683
 * Note that we just need to verify pfm contains prefixes
684
 * from ctr, not that those prefixes has same id_prefix.
685
 */
686
WERROR dsdb_schema_pfm_contains_drsuapi_pfm(const struct dsdb_schema_prefixmap *pfm,
687
              const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
688
0
{
689
0
  WERROR werr;
690
0
  uint32_t i;
691
0
  uint32_t idx;
692
0
  DATA_BLOB bin_oid;
693
694
  /* verify drsuapi_pefixMap */
695
0
  werr = _dsdb_drsuapi_pfm_verify(ctr, true);
696
0
  W_ERROR_NOT_OK_RETURN(werr);
697
698
  /* check pfm contains every entry from ctr, except the last one */
699
0
  for (i = 0; i < ctr->num_mappings - 1; i++) {
700
0
    bin_oid.length = ctr->mappings[i].oid.length;
701
0
    bin_oid.data   = ctr->mappings[i].oid.binary_oid;
702
703
0
    werr = dsdb_schema_pfm_find_binary_oid(pfm, bin_oid, &idx);
704
0
    if (!W_ERROR_IS_OK(werr)) {
705
0
      return WERR_DS_DRA_SCHEMA_MISMATCH;
706
0
    }
707
0
  }
708
709
0
  return WERR_OK;
710
0
}