Coverage Report

Created: 2025-07-23 07:04

/src/samba/lib/ldb/common/ldb_msg.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   ldb database library
3
4
   Copyright (C) Andrew Tridgell  2004
5
6
     ** NOTE! The following LGPL license applies to the ldb
7
     ** library. This does NOT imply that all of Samba is released
8
     ** under the LGPL
9
10
   This library is free software; you can redistribute it and/or
11
   modify it under the terms of the GNU Lesser General Public
12
   License as published by the Free Software Foundation; either
13
   version 3 of the License, or (at your option) any later version.
14
15
   This library is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
   Lesser General Public License for more details.
19
20
   You should have received a copy of the GNU Lesser General Public
21
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
22
*/
23
24
/*
25
 *  Name: ldb
26
 *
27
 *  Component: ldb message component utility functions
28
 *
29
 *  Description: functions for manipulating ldb_message structures
30
 *
31
 *  Author: Andrew Tridgell
32
 */
33
34
#include "ldb_private.h"
35
36
/*
37
  create a new ldb_message in a given memory context (NULL for top level)
38
*/
39
struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
40
0
{
41
0
  return talloc_zero(mem_ctx, struct ldb_message);
42
0
}
43
44
/*
45
  find an element in a message by attribute name
46
*/
47
struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
48
             const char *attr_name)
49
0
{
50
0
  unsigned int i;
51
0
  for (i=0;i<msg->num_elements;i++) {
52
0
    if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
53
0
      return &msg->elements[i];
54
0
    }
55
0
  }
56
0
  return NULL;
57
0
}
58
59
/*
60
  see if two ldb_val structures contain exactly the same data
61
  return 1 for a match, 0 for a mismatch
62
*/
63
int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
64
0
{
65
0
  if (v1->length != v2->length) return 0;
66
0
  if (v1->data == v2->data) return 1;
67
0
  if (v1->length == 0) return 1;
68
69
0
  if (memcmp(v1->data, v2->data, v1->length) == 0) {
70
0
    return 1;
71
0
  }
72
73
0
  return 0;
74
0
}
75
76
/*
77
  find a value in an element
78
  assumes case sensitive comparison
79
*/
80
struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
81
         struct ldb_val *val)
82
0
{
83
0
  unsigned int i;
84
0
  for (i=0;i<el->num_values;i++) {
85
0
    if (ldb_val_equal_exact(val, &el->values[i])) {
86
0
      return &el->values[i];
87
0
    }
88
0
  }
89
0
  return NULL;
90
0
}
91
92
93
static int ldb_val_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
94
0
{
95
0
  if (v1->length != v2->length) {
96
0
    return NUMERIC_CMP(v1->length, v2->length);
97
0
  }
98
0
  return memcmp(v1->data, v2->data, v1->length);
99
0
}
100
101
102
/*
103
  ldb_msg_find_duplicate_val() will set the **duplicate pointer to the first
104
  duplicate value it finds. It does a case sensitive comparison (memcmp).
105
106
  LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown
107
  options flag, otherwise LDB_SUCCESS.
108
*/
109
0
#define LDB_DUP_QUADRATIC_THRESHOLD 10
110
111
int ldb_msg_find_duplicate_val(struct ldb_context *ldb,
112
             TALLOC_CTX *mem_ctx,
113
             const struct ldb_message_element *el,
114
             struct ldb_val **duplicate,
115
             uint32_t options)
116
0
{
117
0
  unsigned int i, j;
118
0
  struct ldb_val *val;
119
120
0
  if (options != 0) {
121
0
    return LDB_ERR_OPERATIONS_ERROR;
122
0
  }
123
124
0
  *duplicate = NULL;
125
126
  /*
127
     If there are not many values, it is best to avoid the talloc
128
     overhead and just do a brute force search.
129
   */
130
0
  if (el->num_values < LDB_DUP_QUADRATIC_THRESHOLD) {
131
0
    for (j = 0; j < el->num_values; j++) {
132
0
      val = &el->values[j];
133
0
      for ( i = j + 1; i < el->num_values; i++) {
134
0
        if (ldb_val_equal_exact(val, &el->values[i])) {
135
0
          *duplicate = val;
136
0
          return LDB_SUCCESS;
137
0
        }
138
0
      }
139
0
    }
140
0
  } else {
141
0
    struct ldb_val *values;
142
0
    values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
143
0
    if (values == NULL) {
144
0
      return LDB_ERR_OPERATIONS_ERROR;
145
0
    }
146
147
0
    memcpy(values, el->values,
148
0
           el->num_values * sizeof(struct ldb_val));
149
0
    TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
150
0
    for (i = 1; i < el->num_values; i++) {
151
0
      if (ldb_val_equal_exact(&values[i],
152
0
            &values[i - 1])) {
153
        /* find the original location */
154
0
        for (j = 0; j < el->num_values; j++) {
155
0
          if (ldb_val_equal_exact(&values[i],
156
0
                &el->values[j])
157
0
            ) {
158
0
            *duplicate = &el->values[j];
159
0
            break;
160
0
          }
161
0
        }
162
0
        talloc_free(values);
163
0
        if (*duplicate == NULL) {
164
          /* how we got here, I don't know */
165
0
          return LDB_ERR_OPERATIONS_ERROR;
166
0
        }
167
0
        return LDB_SUCCESS;
168
0
      }
169
0
    }
170
0
    talloc_free(values);
171
0
  }
172
0
  return LDB_SUCCESS;
173
0
}
174
175
176
/*
177
  Determine whether the values in an element are also in another element.
178
179
  Without any flags, return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS if the elements
180
  share values, or LDB_SUCCESS if they don't. In this case, the function
181
  simply determines the set intersection and it doesn't matter in which order
182
  the elements are provided.
183
184
  With the LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES flag, any values in common are
185
  removed from the first element and LDB_SUCCESS is returned.
186
187
  LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown option.
188
  LDB_ERR_INAPPROPRIATE_MATCHING is returned if the elements differ in name.
189
*/
190
191
int ldb_msg_find_common_values(struct ldb_context *ldb,
192
             TALLOC_CTX *mem_ctx,
193
             struct ldb_message_element *el,
194
             struct ldb_message_element *el2,
195
             uint32_t options)
196
0
{
197
0
  struct ldb_val *values;
198
0
  struct ldb_val *values2;
199
0
  unsigned int i, j, k, n_values;
200
201
0
  bool remove_duplicates = options & LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES;
202
203
0
  if ((options & ~LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES) != 0) {
204
0
    return LDB_ERR_OPERATIONS_ERROR;
205
0
  }
206
207
0
  if (strcmp(el->name, el2->name) != 0) {
208
0
    return LDB_ERR_INAPPROPRIATE_MATCHING;
209
0
  }
210
0
  if (el->num_values == 0 || el2->num_values == 0) {
211
0
    return LDB_SUCCESS;
212
0
  }
213
  /*
214
     With few values, it is better to do the brute-force search than the
215
     clever search involving tallocs, memcpys, sorts, etc.
216
  */
217
0
  if (MIN(el->num_values, el2->num_values) == 1 ||
218
0
      MAX(el->num_values, el2->num_values) < LDB_DUP_QUADRATIC_THRESHOLD) {
219
0
    for (i = 0; i < el2->num_values; i++) {
220
0
      for (j = 0; j < el->num_values; j++) {
221
0
        if (ldb_val_equal_exact(&el->values[j],
222
0
              &el2->values[i])) {
223
0
          if (! remove_duplicates) {
224
0
              return      \
225
0
                LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
226
0
          }
227
          /*
228
            With the remove_duplicates flag, we
229
            resolve the intersection by removing
230
            the offending one from el.
231
          */
232
0
          el->num_values--;
233
0
          for (k = j; k < el->num_values; k++) {
234
0
            el->values[k] = \
235
0
              el->values[k + 1];
236
0
          }
237
0
          j--; /* rewind */
238
0
        }
239
0
      }
240
0
    }
241
0
    return LDB_SUCCESS;
242
0
  }
243
244
0
  values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
245
0
  if (values == NULL) {
246
0
    return LDB_ERR_OPERATIONS_ERROR;
247
0
  }
248
0
  values2 = talloc_array(mem_ctx, struct ldb_val,
249
0
            el2->num_values);
250
0
  if (values2 == NULL) {
251
0
    return LDB_ERR_OPERATIONS_ERROR;
252
0
  }
253
254
0
  memcpy(values, el->values,
255
0
         el->num_values * sizeof(struct ldb_val));
256
0
  memcpy(values2, el2->values,
257
0
         el2->num_values * sizeof(struct ldb_val));
258
0
  TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
259
0
  TYPESAFE_QSORT(values2, el2->num_values, ldb_val_cmp);
260
261
  /*
262
     el->n_values may diverge from the number of values in the sorted
263
     list when the remove_duplicates flag is used.
264
  */
265
0
  n_values = el->num_values;
266
0
  i = 0;
267
0
  j = 0;
268
0
  while (i != n_values && j < el2->num_values) {
269
0
    int ret = ldb_val_cmp(&values[i], &values2[j]);
270
0
    if (ret < 0) {
271
0
      i++;
272
0
    } else if (ret > 0) {
273
0
      j++;
274
0
    } else {
275
      /* we have a collision */
276
0
      if (! remove_duplicates) {
277
0
        TALLOC_FREE(values);
278
0
        TALLOC_FREE(values2);
279
0
        return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
280
0
      }
281
      /*
282
         With the remove_duplicates flag we need to find
283
         this in the original list and remove it, which is
284
         inefficient but hopefully rare.
285
      */
286
0
      for (k = 0; k < el->num_values; k++) {
287
0
        if (ldb_val_equal_exact(&el->values[k],
288
0
              &values[i])) {
289
0
          break;
290
0
        }
291
0
      }
292
0
      el->num_values--;
293
0
      for (; k < el->num_values; k++) {
294
0
        el->values[k] = el->values[k + 1];
295
0
      }
296
0
      i++;
297
0
    }
298
0
  }
299
0
  TALLOC_FREE(values);
300
0
  TALLOC_FREE(values2);
301
302
0
  return LDB_SUCCESS;
303
0
}
304
305
/*
306
  duplicate a ldb_val structure
307
*/
308
struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
309
0
{
310
0
  struct ldb_val v2;
311
0
  v2.length = v->length;
312
0
  if (v->data == NULL) {
313
0
    v2.data = NULL;
314
0
    return v2;
315
0
  }
316
317
  /* the +1 is to cope with buggy C library routines like strndup
318
     that look one byte beyond */
319
0
  v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
320
0
  if (!v2.data) {
321
0
    v2.length = 0;
322
0
    return v2;
323
0
  }
324
325
0
  memcpy(v2.data, v->data, v->length);
326
0
  ((char *)v2.data)[v->length] = 0;
327
0
  return v2;
328
0
}
329
330
/**
331
 * Adds new empty element to msg->elements
332
 */
333
static int _ldb_msg_add_el(struct ldb_message *msg,
334
         struct ldb_message_element **return_el)
335
0
{
336
0
  struct ldb_message_element *els;
337
338
  /*
339
   * TODO: Find out a way to assert on input parameters.
340
   * msg and return_el must be valid
341
   */
342
343
0
  els = talloc_realloc(msg, msg->elements,
344
0
           struct ldb_message_element, msg->num_elements + 1);
345
0
  if (!els) {
346
0
    return LDB_ERR_OPERATIONS_ERROR;
347
0
  }
348
349
0
  els[msg->num_elements] = (struct ldb_message_element) {};
350
351
0
  msg->elements = els;
352
0
  msg->num_elements++;
353
354
0
  *return_el = &els[msg->num_elements-1];
355
356
0
  return LDB_SUCCESS;
357
0
}
358
359
/**
360
 * Add an empty element with a given name to a message
361
 */
362
int ldb_msg_add_empty(struct ldb_message *msg,
363
          const char *attr_name,
364
          int flags,
365
          struct ldb_message_element **return_el)
366
0
{
367
0
  int ret;
368
0
  struct ldb_message_element *el;
369
370
0
  ret = _ldb_msg_add_el(msg, &el);
371
0
  if (ret != LDB_SUCCESS) {
372
0
    return ret;
373
0
  }
374
375
  /* initialize newly added element */
376
0
  el->flags = flags;
377
0
  el->name = talloc_strdup(msg->elements, attr_name);
378
0
  if (!el->name) {
379
0
    return LDB_ERR_OPERATIONS_ERROR;
380
0
  }
381
382
0
  if (return_el) {
383
0
    *return_el = el;
384
0
  }
385
386
0
  return LDB_SUCCESS;
387
0
}
388
389
/**
390
 * Adds an element to a message.
391
 *
392
 * NOTE: Ownership of ldb_message_element fields
393
 *       is NOT transferred. Thus, if *el pointer
394
 *       is invalidated for some reason, this will
395
 *       corrupt *msg contents also
396
 */
397
int ldb_msg_add(struct ldb_message *msg,
398
    const struct ldb_message_element *el,
399
    int flags)
400
0
{
401
0
  int ret;
402
0
  struct ldb_message_element *el_new;
403
  /* We have to copy this, just in case *el is a pointer into
404
   * what ldb_msg_add_empty() is about to realloc() */
405
0
  struct ldb_message_element el_copy = *el;
406
407
0
  ret = _ldb_msg_add_el(msg, &el_new);
408
0
  if (ret != LDB_SUCCESS) {
409
0
    return ret;
410
0
  }
411
412
0
  el_new->flags      = flags;
413
0
  el_new->name       = el_copy.name;
414
0
  el_new->num_values = el_copy.num_values;
415
0
  el_new->values     = el_copy.values;
416
417
0
  return LDB_SUCCESS;
418
0
}
419
420
/*
421
 * add a value to a message element
422
 */
423
int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx,
424
            struct ldb_message_element *el,
425
            const struct ldb_val *val)
426
0
{
427
0
  struct ldb_val *vals;
428
429
0
  if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) {
430
    /*
431
     * Another message is using this message element's values array,
432
     * so we don't want to make any modifications to the original
433
     * message, or potentially invalidate its own values by calling
434
     * talloc_realloc(). Make a copy instead.
435
     */
436
0
    el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
437
438
0
    vals = talloc_array(mem_ctx, struct ldb_val,
439
0
            el->num_values + 1);
440
0
    if (vals == NULL) {
441
0
      return LDB_ERR_OPERATIONS_ERROR;
442
0
    }
443
444
0
    if (el->values != NULL) {
445
0
      memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val));
446
0
    }
447
0
  } else {
448
0
    vals = talloc_realloc(mem_ctx, el->values, struct ldb_val,
449
0
              el->num_values + 1);
450
0
    if (vals == NULL) {
451
0
      return LDB_ERR_OPERATIONS_ERROR;
452
0
    }
453
0
  }
454
0
  el->values = vals;
455
0
  el->values[el->num_values] = *val;
456
0
  el->num_values++;
457
458
0
  return LDB_SUCCESS;
459
0
}
460
461
/*
462
  add a value to a message
463
*/
464
int ldb_msg_add_value(struct ldb_message *msg,
465
          const char *attr_name,
466
          const struct ldb_val *val,
467
          struct ldb_message_element **return_el)
468
0
{
469
0
  struct ldb_message_element *el;
470
0
  int ret;
471
472
0
  el = ldb_msg_find_element(msg, attr_name);
473
0
  if (!el) {
474
0
    ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
475
0
    if (ret != LDB_SUCCESS) {
476
0
      return ret;
477
0
    }
478
0
  }
479
480
0
  ret = ldb_msg_element_add_value(msg->elements, el, val);
481
0
  if (ret != LDB_SUCCESS) {
482
0
    return ret;
483
0
  }
484
485
0
  if (return_el) {
486
0
    *return_el = el;
487
0
  }
488
489
0
  return LDB_SUCCESS;
490
0
}
491
492
493
/*
494
  add a value to a message, stealing it into the 'right' place
495
*/
496
int ldb_msg_add_steal_value(struct ldb_message *msg,
497
          const char *attr_name,
498
          struct ldb_val *val)
499
0
{
500
0
  int ret;
501
0
  struct ldb_message_element *el;
502
503
0
  ret = ldb_msg_add_value(msg, attr_name, val, &el);
504
0
  if (ret == LDB_SUCCESS) {
505
0
    talloc_steal(el->values, val->data);
506
0
  }
507
0
  return ret;
508
0
}
509
510
511
/*
512
  add a string element to a message, specifying flags
513
*/
514
int ldb_msg_add_string_flags(struct ldb_message *msg,
515
           const char *attr_name, const char *str,
516
           int flags)
517
0
{
518
0
  struct ldb_val val;
519
0
  int ret;
520
0
  struct ldb_message_element *el = NULL;
521
522
0
  val.data = discard_const_p(uint8_t, str);
523
0
  val.length = strlen(str);
524
525
0
  if (val.length == 0) {
526
    /* allow empty strings as non-existent attributes */
527
0
    return LDB_SUCCESS;
528
0
  }
529
530
0
  ret = ldb_msg_add_value(msg, attr_name, &val, &el);
531
0
  if (ret != LDB_SUCCESS) {
532
0
    return ret;
533
0
  }
534
535
0
  if (flags != 0) {
536
0
    el->flags = flags;
537
0
  }
538
539
0
  return LDB_SUCCESS;
540
0
}
541
542
/*
543
  add a string element to a message
544
*/
545
int ldb_msg_add_string(struct ldb_message *msg,
546
           const char *attr_name, const char *str)
547
0
{
548
0
  return ldb_msg_add_string_flags(msg, attr_name, str, 0);
549
0
}
550
551
/*
552
  add a string element to a message, stealing it into the 'right' place
553
*/
554
int ldb_msg_add_steal_string(struct ldb_message *msg,
555
           const char *attr_name, char *str)
556
0
{
557
0
  struct ldb_val val;
558
559
0
  val.data = (uint8_t *)str;
560
0
  val.length = strlen(str);
561
562
0
  if (val.length == 0) {
563
    /* allow empty strings as non-existent attributes */
564
0
    return LDB_SUCCESS;
565
0
  }
566
567
0
  return ldb_msg_add_steal_value(msg, attr_name, &val);
568
0
}
569
570
/*
571
  add a DN element to a message
572
*/
573
int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
574
            struct ldb_dn *dn)
575
0
{
576
0
  char *str = ldb_dn_alloc_linearized(msg, dn);
577
578
0
  if (str == NULL) {
579
    /* we don't want to have unknown DNs added */
580
0
    return LDB_ERR_OPERATIONS_ERROR;
581
0
  }
582
583
0
  return ldb_msg_add_steal_string(msg, attr_name, str);
584
0
}
585
586
/*
587
  add a printf formatted element to a message
588
*/
589
int ldb_msg_add_fmt(struct ldb_message *msg,
590
        const char *attr_name, const char *fmt, ...)
591
0
{
592
0
  struct ldb_val val;
593
0
  va_list ap;
594
0
  char *str;
595
596
0
  va_start(ap, fmt);
597
0
  str = talloc_vasprintf(msg, fmt, ap);
598
0
  va_end(ap);
599
600
0
  if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
601
602
0
  val.data   = (uint8_t *)str;
603
0
  val.length = strlen(str);
604
605
0
  return ldb_msg_add_steal_value(msg, attr_name, &val);
606
0
}
607
608
static int ldb_msg_append_value_impl(struct ldb_message *msg,
609
             const char *attr_name,
610
             const struct ldb_val *val,
611
             int flags,
612
             struct ldb_message_element **return_el)
613
0
{
614
0
  struct ldb_message_element *el = NULL;
615
0
  int ret;
616
617
0
  ret = ldb_msg_add_empty(msg, attr_name, flags, &el);
618
0
  if (ret != LDB_SUCCESS) {
619
0
    return ret;
620
0
  }
621
622
0
  ret = ldb_msg_element_add_value(msg->elements, el, val);
623
0
  if (ret != LDB_SUCCESS) {
624
0
    return ret;
625
0
  }
626
627
0
  if (return_el != NULL) {
628
0
    *return_el = el;
629
0
  }
630
631
0
  return LDB_SUCCESS;
632
0
}
633
634
/*
635
  append a value to a message
636
*/
637
int ldb_msg_append_value(struct ldb_message *msg,
638
       const char *attr_name,
639
       const struct ldb_val *val,
640
       int flags)
641
0
{
642
0
  return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL);
643
0
}
644
645
/*
646
  append a value to a message, stealing it into the 'right' place
647
*/
648
int ldb_msg_append_steal_value(struct ldb_message *msg,
649
             const char *attr_name,
650
             struct ldb_val *val,
651
             int flags)
652
0
{
653
0
  int ret;
654
0
  struct ldb_message_element *el = NULL;
655
656
0
  ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el);
657
0
  if (ret == LDB_SUCCESS) {
658
0
    talloc_steal(el->values, val->data);
659
0
  }
660
0
  return ret;
661
0
}
662
663
/*
664
  append a string element to a message, stealing it into the 'right' place
665
*/
666
int ldb_msg_append_steal_string(struct ldb_message *msg,
667
        const char *attr_name, char *str,
668
        int flags)
669
0
{
670
0
  struct ldb_val val;
671
672
0
  val.data = (uint8_t *)str;
673
0
  val.length = strlen(str);
674
675
0
  if (val.length == 0) {
676
    /* allow empty strings as non-existent attributes */
677
0
    return LDB_SUCCESS;
678
0
  }
679
680
0
  return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
681
0
}
682
683
/*
684
  append a string element to a message
685
*/
686
int ldb_msg_append_string(struct ldb_message *msg,
687
        const char *attr_name, const char *str, int flags)
688
0
{
689
0
  struct ldb_val val;
690
691
0
  val.data = discard_const_p(uint8_t, str);
692
0
  val.length = strlen(str);
693
694
0
  if (val.length == 0) {
695
    /* allow empty strings as non-existent attributes */
696
0
    return LDB_SUCCESS;
697
0
  }
698
699
0
  return ldb_msg_append_value(msg, attr_name, &val, flags);
700
0
}
701
702
/*
703
  append a DN element to a message
704
*/
705
int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name,
706
         struct ldb_dn *dn, int flags)
707
0
{
708
0
  char *str = ldb_dn_alloc_linearized(msg, dn);
709
710
0
  if (str == NULL) {
711
    /* we don't want to have unknown DNs added */
712
0
    return LDB_ERR_OPERATIONS_ERROR;
713
0
  }
714
715
0
  return ldb_msg_append_steal_string(msg, attr_name, str, flags);
716
0
}
717
718
/*
719
  append a printf formatted element to a message
720
*/
721
int ldb_msg_append_fmt(struct ldb_message *msg, int flags,
722
           const char *attr_name, const char *fmt, ...)
723
0
{
724
0
  struct ldb_val val;
725
0
  va_list ap;
726
0
  char *str = NULL;
727
728
0
  va_start(ap, fmt);
729
0
  str = talloc_vasprintf(msg, fmt, ap);
730
0
  va_end(ap);
731
732
0
  if (str == NULL) {
733
0
    return LDB_ERR_OPERATIONS_ERROR;
734
0
  }
735
736
0
  val.data   = (uint8_t *)str;
737
0
  val.length = strlen(str);
738
739
0
  return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
740
0
}
741
742
/*
743
  compare two ldb_message_element structures
744
  assumes case sensitive comparison
745
*/
746
int ldb_msg_element_compare(struct ldb_message_element *el1,
747
          struct ldb_message_element *el2)
748
0
{
749
0
  unsigned int i;
750
751
0
  if (el1->num_values != el2->num_values) {
752
0
    return NUMERIC_CMP(el1->num_values, el2->num_values);
753
0
  }
754
  /*
755
   * Note this is an inconsistent comparison, unsuitable for
756
   * sorting. If A has values {a, b} and B has values {b, c},
757
   * then
758
   *
759
   * ldb_msg_element_compare(A, B) returns -1, meaning A < B
760
   * ldb_msg_element_compare(B, A) returns -1, meaning B < A
761
   */
762
0
  for (i=0;i<el1->num_values;i++) {
763
0
    if (!ldb_msg_find_val(el2, &el1->values[i])) {
764
0
      return -1;
765
0
    }
766
0
  }
767
768
0
  return 0;
769
0
}
770
771
/*
772
  compare two ldb_message_element structures.
773
  Different ordering is considered a mismatch
774
*/
775
bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
776
           const struct ldb_message_element *el2)
777
0
{
778
0
  unsigned i;
779
0
  if (el1->num_values != el2->num_values) {
780
0
    return false;
781
0
  }
782
0
  for (i=0;i<el1->num_values;i++) {
783
0
    if (ldb_val_equal_exact(&el1->values[i],
784
0
          &el2->values[i]) != 1) {
785
0
      return false;
786
0
    }
787
0
  }
788
0
  return true;
789
0
}
790
791
/*
792
  compare two ldb_message_element structures
793
  comparing by element name
794
*/
795
int ldb_msg_element_compare_name(struct ldb_message_element *el1,
796
         struct ldb_message_element *el2)
797
0
{
798
0
  if (el1->name == el2->name) {
799
0
    return 0;
800
0
  }
801
802
0
  if (el1->name == NULL) {
803
0
    return -1;
804
0
  }
805
806
0
  if (el2->name == NULL) {
807
0
    return 1;
808
0
  }
809
810
0
  return ldb_attr_cmp(el1->name, el2->name);
811
0
}
812
813
void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el)
814
0
{
815
0
  el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
816
0
}
817
818
bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el)
819
0
{
820
0
  return (el->flags & LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE) != 0;
821
0
}
822
823
void ldb_msg_remove_inaccessible(struct ldb_message *msg)
824
0
{
825
0
  unsigned i;
826
0
  unsigned num_del = 0;
827
828
0
  for (i = 0; i < msg->num_elements; ++i) {
829
0
    if (ldb_msg_element_is_inaccessible(&msg->elements[i])) {
830
0
      ++num_del;
831
0
    } else if (num_del) {
832
0
      msg->elements[i - num_del] = msg->elements[i];
833
0
    }
834
0
  }
835
836
0
  msg->num_elements -= num_del;
837
0
}
838
839
/*
840
  convenience functions to return common types from a message
841
  these return the first value if the attribute is multi-valued
842
*/
843
const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
844
             const char *attr_name)
845
0
{
846
0
  struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
847
0
  if (!el || el->num_values == 0) {
848
0
    return NULL;
849
0
  }
850
0
  return &el->values[0];
851
0
}
852
853
int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
854
           const char *attr_name,
855
           int default_value)
856
0
{
857
0
  const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
858
0
  char buf[sizeof("-2147483648")] = {};
859
0
  char *end = NULL;
860
0
  int ret;
861
862
0
  if (!v || !v->data) {
863
0
    return default_value;
864
0
  }
865
866
0
  if (v->length >= sizeof(buf)) {
867
0
    return default_value;
868
0
  }
869
870
0
  memcpy(buf, v->data, v->length);
871
0
  errno = 0;
872
0
  ret = (int) strtoll(buf, &end, 10);
873
0
  if (errno != 0) {
874
0
    return default_value;
875
0
  }
876
0
  if (end && end[0] != '\0') {
877
0
    return default_value;
878
0
  }
879
0
  return ret;
880
0
}
881
882
unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
883
               const char *attr_name,
884
               unsigned int default_value)
885
0
{
886
0
  const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
887
0
  char buf[sizeof("-2147483648")] = {};
888
0
  char *end = NULL;
889
0
  unsigned int ret;
890
891
0
  if (!v || !v->data) {
892
0
    return default_value;
893
0
  }
894
895
0
  if (v->length >= sizeof(buf)) {
896
0
    return default_value;
897
0
  }
898
899
0
  memcpy(buf, v->data, v->length);
900
0
  errno = 0;
901
0
  ret = (unsigned int) strtoll(buf, &end, 10);
902
0
  if (errno != 0) {
903
0
    errno = 0;
904
0
    ret = (unsigned int) strtoull(buf, &end, 10);
905
0
    if (errno != 0) {
906
0
      return default_value;
907
0
    }
908
0
  }
909
0
  if (end && end[0] != '\0') {
910
0
    return default_value;
911
0
  }
912
0
  return ret;
913
0
}
914
915
int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
916
           const char *attr_name,
917
           int64_t default_value)
918
0
{
919
0
  int64_t val = 0;
920
0
  const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
921
0
  int ret = ldb_val_as_int64(v, &val);
922
0
  return ret ? default_value : val;
923
0
}
924
925
int ldb_val_as_int64(const struct ldb_val *v, int64_t *val)
926
0
{
927
0
  char buf[sizeof("-9223372036854775808")] = {};
928
0
  char *end = NULL;
929
0
  int64_t result;
930
931
0
  if (!v || !v->data) {
932
0
    return LDB_ERR_OPERATIONS_ERROR;
933
0
  }
934
935
0
  if (v->length >= sizeof(buf)) {
936
0
    return LDB_ERR_OPERATIONS_ERROR;
937
0
  }
938
939
0
  memcpy(buf, v->data, v->length);
940
0
  errno = 0;
941
0
  result = (int64_t) strtoll(buf, &end, 10);
942
0
  if (errno != 0) {
943
0
    return LDB_ERR_OPERATIONS_ERROR;
944
0
  }
945
0
  if (end && end[0] != '\0') {
946
0
    return LDB_ERR_OPERATIONS_ERROR;
947
0
  }
948
949
0
  *val = result;
950
0
  return LDB_SUCCESS;
951
0
}
952
953
uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
954
             const char *attr_name,
955
             uint64_t default_value)
956
0
{
957
0
  uint64_t val = 0;
958
0
  const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
959
0
  int ret = ldb_val_as_uint64(v, &val);
960
0
  return ret ? default_value : val;
961
0
}
962
963
int ldb_val_as_uint64(const struct ldb_val *v, uint64_t *val)
964
0
{
965
0
  char buf[sizeof("-9223372036854775808")] = {};
966
0
  char *end = NULL;
967
0
  uint64_t result;
968
969
0
  if (!v || !v->data) {
970
0
    return LDB_ERR_OPERATIONS_ERROR;
971
0
  }
972
973
0
  if (v->length >= sizeof(buf)) {
974
0
    return LDB_ERR_OPERATIONS_ERROR;
975
0
  }
976
977
0
  memcpy(buf, v->data, v->length);
978
0
  errno = 0;
979
0
  result = (uint64_t) strtoll(buf, &end, 10);
980
0
  if (errno != 0) {
981
0
    errno = 0;
982
0
    result = (uint64_t) strtoull(buf, &end, 10);
983
0
    if (errno != 0) {
984
0
      return LDB_ERR_OPERATIONS_ERROR;
985
0
    }
986
0
  }
987
0
  if (end && end[0] != '\0') {
988
0
    return LDB_ERR_OPERATIONS_ERROR;
989
0
  }
990
991
0
  *val = result;
992
0
  return LDB_SUCCESS;
993
0
}
994
995
double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
996
           const char *attr_name,
997
           double default_value)
998
0
{
999
0
  const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1000
0
  char *buf;
1001
0
  char *end = NULL;
1002
0
  double ret;
1003
1004
0
  if (!v || !v->data) {
1005
0
    return default_value;
1006
0
  }
1007
0
  buf = talloc_strndup(msg, (const char *)v->data, v->length);
1008
0
  if (buf == NULL) {
1009
0
    return default_value;
1010
0
  }
1011
1012
0
  errno = 0;
1013
0
  ret = strtod(buf, &end);
1014
0
  talloc_free(buf);
1015
0
  if (errno != 0) {
1016
0
    return default_value;
1017
0
  }
1018
0
  if (end && end[0] != '\0') {
1019
0
    return default_value;
1020
0
  }
1021
0
  return ret;
1022
0
}
1023
1024
int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
1025
            const char *attr_name,
1026
            int default_value)
1027
0
{
1028
0
  bool val = false;
1029
0
  const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1030
0
  int ret = ldb_val_as_bool(v, &val);
1031
0
  return ret ? default_value : val;
1032
0
}
1033
1034
int ldb_val_as_bool(const struct ldb_val *v, bool *val)
1035
0
{
1036
0
  if (!v || !v->data) {
1037
0
    return LDB_ERR_OPERATIONS_ERROR;
1038
0
  }
1039
0
  if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
1040
0
    *val = false;
1041
0
    return LDB_SUCCESS;
1042
0
  }
1043
0
  if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
1044
0
    *val = true;
1045
0
    return LDB_SUCCESS;
1046
0
  }
1047
0
  return LDB_ERR_OPERATIONS_ERROR;
1048
0
}
1049
1050
const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
1051
          const char *attr_name,
1052
          const char *default_value)
1053
0
{
1054
0
  const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1055
0
  if (!v || !v->data) {
1056
0
    return default_value;
1057
0
  }
1058
0
  if (v->data[v->length] != '\0') {
1059
0
    return default_value;
1060
0
  }
1061
0
  return (const char *)v->data;
1062
0
}
1063
1064
struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
1065
               TALLOC_CTX *mem_ctx,
1066
               const struct ldb_message *msg,
1067
               const char *attr_name)
1068
0
{
1069
0
  const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1070
0
  return ldb_val_as_dn(ldb, mem_ctx, v);
1071
0
}
1072
1073
struct ldb_dn *ldb_val_as_dn(struct ldb_context *ldb,
1074
           TALLOC_CTX *mem_ctx,
1075
           const struct ldb_val *v)
1076
0
{
1077
0
  struct ldb_dn *res_dn;
1078
1079
0
  if (!v || !v->data) {
1080
0
    return NULL;
1081
0
  }
1082
0
  res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
1083
0
  if ( ! ldb_dn_validate(res_dn)) {
1084
0
    talloc_free(res_dn);
1085
0
    return NULL;
1086
0
  }
1087
0
  return res_dn;
1088
0
}
1089
1090
/*
1091
  sort the elements of a message by name
1092
*/
1093
void ldb_msg_sort_elements(struct ldb_message *msg)
1094
0
{
1095
0
  TYPESAFE_QSORT(msg->elements, msg->num_elements,
1096
0
           ldb_msg_element_compare_name);
1097
0
}
1098
1099
static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx,
1100
           const struct ldb_message *msg)
1101
0
{
1102
0
  struct ldb_message *msg2;
1103
0
  unsigned int i;
1104
1105
0
  msg2 = talloc(mem_ctx, struct ldb_message);
1106
0
  if (msg2 == NULL) return NULL;
1107
1108
0
  *msg2 = *msg;
1109
1110
0
  msg2->elements = talloc_array(msg2, struct ldb_message_element,
1111
0
              msg2->num_elements);
1112
0
  if (msg2->elements == NULL) goto failed;
1113
1114
0
  for (i=0;i<msg2->num_elements;i++) {
1115
0
    msg2->elements[i] = msg->elements[i];
1116
0
  }
1117
1118
0
  return msg2;
1119
1120
0
failed:
1121
0
  talloc_free(msg2);
1122
0
  return NULL;
1123
0
}
1124
1125
/*
1126
  shallow copy a message - copying only the elements array so that the caller
1127
  can safely add new elements without changing the message
1128
*/
1129
struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
1130
           const struct ldb_message *msg)
1131
0
{
1132
0
  struct ldb_message *msg2;
1133
0
  unsigned int i;
1134
1135
0
  msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1136
0
  if (msg2 == NULL) {
1137
0
    return NULL;
1138
0
  }
1139
1140
0
  for (i = 0; i < msg2->num_elements; ++i) {
1141
    /*
1142
     * Mark this message's elements as sharing their values with the
1143
     * original message, so that we don't inadvertently modify or
1144
     * free them. We don't mark the original message element as
1145
     * shared, so the original message element should not be
1146
     * modified or freed while the shallow copy lives.
1147
     */
1148
0
    struct ldb_message_element *el = &msg2->elements[i];
1149
0
    el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
1150
0
  }
1151
1152
0
        return msg2;
1153
0
}
1154
1155
/*
1156
  copy a message, allocating new memory for all parts
1157
*/
1158
struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
1159
         const struct ldb_message *msg)
1160
0
{
1161
0
  struct ldb_message *msg2;
1162
0
  unsigned int i, j;
1163
1164
0
  msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1165
0
  if (msg2 == NULL) return NULL;
1166
1167
0
  if (msg2->dn != NULL) {
1168
0
    msg2->dn = ldb_dn_copy(msg2, msg2->dn);
1169
0
    if (msg2->dn == NULL) goto failed;
1170
0
  }
1171
1172
0
  for (i=0;i<msg2->num_elements;i++) {
1173
0
    struct ldb_message_element *el = &msg2->elements[i];
1174
0
    struct ldb_val *values = el->values;
1175
0
    if (el->name != NULL) {
1176
0
      el->name = talloc_strdup(msg2->elements, el->name);
1177
0
      if (el->name == NULL) goto failed;
1178
0
    }
1179
0
    el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
1180
0
    if (el->values == NULL) goto failed;
1181
0
    for (j=0;j<el->num_values;j++) {
1182
0
      el->values[j] = ldb_val_dup(el->values, &values[j]);
1183
0
      if (el->values[j].data == NULL && values[j].length != 0) {
1184
0
        goto failed;
1185
0
      }
1186
0
    }
1187
1188
                /*
1189
                 * Since we copied this element's values, we can mark them as
1190
                 * not shared.
1191
     */
1192
0
    el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
1193
0
  }
1194
1195
0
  return msg2;
1196
1197
0
failed:
1198
0
  talloc_free(msg2);
1199
0
  return NULL;
1200
0
}
1201
1202
1203
/**
1204
 * Canonicalize a message, merging elements of the same name
1205
 */
1206
struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
1207
           const struct ldb_message *msg)
1208
0
{
1209
0
  int ret;
1210
0
  struct ldb_message *msg2;
1211
1212
  /*
1213
   * Preserve previous behavior and allocate
1214
   * *msg2 into *ldb context
1215
   */
1216
0
  ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
1217
0
  if (ret != LDB_SUCCESS) {
1218
0
    return NULL;
1219
0
  }
1220
1221
0
  return msg2;
1222
0
}
1223
1224
/**
1225
 * Canonicalize a message, merging elements of the same name
1226
 */
1227
int ldb_msg_normalize(struct ldb_context *ldb,
1228
          TALLOC_CTX *mem_ctx,
1229
          const struct ldb_message *msg,
1230
          struct ldb_message **_msg_out)
1231
0
{
1232
0
  unsigned int i;
1233
0
  struct ldb_message *msg2;
1234
1235
0
  msg2 = ldb_msg_copy(mem_ctx, msg);
1236
0
  if (msg2 == NULL) {
1237
0
    return LDB_ERR_OPERATIONS_ERROR;
1238
0
  }
1239
1240
0
  ldb_msg_sort_elements(msg2);
1241
1242
0
  for (i=1; i < msg2->num_elements; i++) {
1243
0
    struct ldb_message_element *el1 = &msg2->elements[i-1];
1244
0
    struct ldb_message_element *el2 = &msg2->elements[i];
1245
1246
0
    if (ldb_msg_element_compare_name(el1, el2) == 0) {
1247
0
      el1->values = talloc_realloc(msg2->elements,
1248
0
                                   el1->values, struct ldb_val,
1249
0
                                   el1->num_values + el2->num_values);
1250
0
      if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
1251
0
        talloc_free(msg2);
1252
0
        return LDB_ERR_OPERATIONS_ERROR;
1253
0
      }
1254
0
      memcpy(el1->values + el1->num_values,
1255
0
             el2->values,
1256
0
             sizeof(struct ldb_val) * el2->num_values);
1257
0
      el1->num_values += el2->num_values;
1258
0
      talloc_free(discard_const_p(char, el2->name));
1259
0
      if ((i + 1 > i) && ((i + 1) < msg2->num_elements)) {
1260
0
        memmove(el2, el2+1, sizeof(struct ldb_message_element) *
1261
0
          (msg2->num_elements - (i+1)));
1262
0
      }
1263
0
      msg2->num_elements--;
1264
0
      i--;
1265
0
    }
1266
0
  }
1267
1268
0
  *_msg_out = msg2;
1269
0
  return LDB_SUCCESS;
1270
0
}
1271
1272
1273
/**
1274
 * return a ldb_message representing the differences between msg1 and msg2.
1275
 * If you then use this in a ldb_modify() call,
1276
 * it can be used to save edits to a message
1277
 */
1278
struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
1279
         struct ldb_message *msg1,
1280
         struct ldb_message *msg2)
1281
0
{
1282
0
  int ldb_ret;
1283
0
  struct ldb_message *mod;
1284
1285
0
  ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
1286
0
  if (ldb_ret != LDB_SUCCESS) {
1287
0
    return NULL;
1288
0
  }
1289
1290
0
  return mod;
1291
0
}
1292
1293
/**
1294
 * return a ldb_message representing the differences between msg1 and msg2.
1295
 * If you then use this in a ldb_modify() call it can be used to save edits to a message
1296
 *
1297
 * Result message is constructed as follows:
1298
 * - LDB_FLAG_MOD_ADD     - elements found only in msg2
1299
 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
1300
 *                          Value for msg2 element is used
1301
 * - LDB_FLAG_MOD_DELETE  - elements found only in msg2
1302
 *
1303
 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
1304
 */
1305
int ldb_msg_difference(struct ldb_context *ldb,
1306
           TALLOC_CTX *mem_ctx,
1307
           struct ldb_message *msg1,
1308
           struct ldb_message *msg2,
1309
           struct ldb_message **_msg_out)
1310
0
{
1311
0
  int ldb_res;
1312
0
  unsigned int i;
1313
0
  struct ldb_message *mod;
1314
0
  struct ldb_message_element *el;
1315
0
  TALLOC_CTX *temp_ctx;
1316
1317
0
  temp_ctx = talloc_new(mem_ctx);
1318
0
  if (!temp_ctx) {
1319
0
    return LDB_ERR_OPERATIONS_ERROR;
1320
0
  }
1321
1322
0
  mod = ldb_msg_new(temp_ctx);
1323
0
  if (mod == NULL) {
1324
0
    goto failed;
1325
0
  }
1326
1327
0
  mod->dn = msg1->dn;
1328
0
  mod->num_elements = 0;
1329
0
  mod->elements = NULL;
1330
1331
  /*
1332
   * Canonicalize *msg2 so we have no repeated elements
1333
   * Resulting message is allocated in *mod's mem context,
1334
   * as we are going to move some elements from *msg2 to
1335
   * *mod object later
1336
   */
1337
0
  ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
1338
0
  if (ldb_res != LDB_SUCCESS) {
1339
0
    goto failed;
1340
0
  }
1341
1342
  /* look in msg2 to find elements that need to be added or modified */
1343
0
  for (i=0;i<msg2->num_elements;i++) {
1344
0
    el = ldb_msg_find_element(msg1, msg2->elements[i].name);
1345
1346
0
    if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
1347
0
      continue;
1348
0
    }
1349
1350
0
    ldb_res = ldb_msg_add(mod,
1351
0
                          &msg2->elements[i],
1352
0
                          el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
1353
0
    if (ldb_res != LDB_SUCCESS) {
1354
0
      goto failed;
1355
0
    }
1356
0
  }
1357
1358
  /* look in msg1 to find elements that need to be deleted */
1359
0
  for (i=0;i<msg1->num_elements;i++) {
1360
0
    el = ldb_msg_find_element(msg2, msg1->elements[i].name);
1361
0
    if (el == NULL) {
1362
0
      ldb_res = ldb_msg_add_empty(mod,
1363
0
                                  msg1->elements[i].name,
1364
0
                                  LDB_FLAG_MOD_DELETE, NULL);
1365
0
      if (ldb_res != LDB_SUCCESS) {
1366
0
        goto failed;
1367
0
      }
1368
0
    }
1369
0
  }
1370
1371
  /* steal resulting message into supplied context */
1372
0
  talloc_steal(mem_ctx, mod);
1373
0
  *_msg_out = mod;
1374
1375
0
  talloc_free(temp_ctx);
1376
0
  return LDB_SUCCESS;
1377
1378
0
failed:
1379
0
  talloc_free(temp_ctx);
1380
0
  return LDB_ERR_OPERATIONS_ERROR;
1381
0
}
1382
1383
1384
int ldb_msg_sanity_check(struct ldb_context *ldb,
1385
       const struct ldb_message *msg)
1386
0
{
1387
0
  unsigned int i, j;
1388
1389
  /* basic check on DN */
1390
0
  if (msg->dn == NULL) {
1391
0
    ldb_set_errstring(ldb, "ldb message lacks a DN!");
1392
0
    return LDB_ERR_INVALID_DN_SYNTAX;
1393
0
  }
1394
1395
  /* basic syntax checks */
1396
0
  for (i = 0; i < msg->num_elements; i++) {
1397
0
    for (j = 0; j < msg->elements[i].num_values; j++) {
1398
0
      if (msg->elements[i].values[j].length == 0) {
1399
        /* an attribute cannot be empty */
1400
0
        ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
1401
0
                  msg->elements[i].name,
1402
0
                  ldb_dn_get_linearized(msg->dn));
1403
0
        return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1404
0
      }
1405
0
    }
1406
0
  }
1407
1408
0
  return LDB_SUCCESS;
1409
0
}
1410
1411
1412
1413
1414
/*
1415
  copy an attribute list. This only copies the array, not the elements
1416
  (ie. the elements are left as the same pointers)
1417
*/
1418
const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
1419
0
{
1420
0
  const char **ret;
1421
0
  unsigned int i;
1422
1423
0
  for (i=0;attrs && attrs[i];i++) /* noop */ ;
1424
0
  ret = talloc_array(mem_ctx, const char *, i+1);
1425
0
  if (ret == NULL) {
1426
0
    return NULL;
1427
0
  }
1428
0
  for (i=0;attrs && attrs[i];i++) {
1429
0
    ret[i] = attrs[i];
1430
0
  }
1431
0
  ret[i] = attrs[i];
1432
0
  return ret;
1433
0
}
1434
1435
1436
/*
1437
  copy an attribute list. This only copies the array, not the elements
1438
  (ie. the elements are left as the same pointers).  The new attribute is added to the list.
1439
*/
1440
const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
1441
0
{
1442
0
  const char **ret;
1443
0
  unsigned int i;
1444
0
  bool found = false;
1445
1446
0
  for (i=0;attrs && attrs[i];i++) {
1447
0
    if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
1448
0
      found = true;
1449
0
    }
1450
0
  }
1451
0
  if (found) {
1452
0
    return ldb_attr_list_copy(mem_ctx, attrs);
1453
0
  }
1454
0
  ret = talloc_array(mem_ctx, const char *, i+2);
1455
0
  if (ret == NULL) {
1456
0
    return NULL;
1457
0
  }
1458
0
  for (i=0;attrs && attrs[i];i++) {
1459
0
    ret[i] = attrs[i];
1460
0
  }
1461
0
  ret[i] = new_attr;
1462
0
  ret[i+1] = NULL;
1463
0
  return ret;
1464
0
}
1465
1466
1467
/*
1468
  return 1 if an attribute is in a list of attributes, or 0 otherwise
1469
*/
1470
int ldb_attr_in_list(const char * const *attrs, const char *attr)
1471
0
{
1472
0
  unsigned int i;
1473
0
  for (i=0;attrs && attrs[i];i++) {
1474
0
    if (ldb_attr_cmp(attrs[i], attr) == 0) {
1475
0
      return 1;
1476
0
    }
1477
0
  }
1478
0
  return 0;
1479
0
}
1480
1481
1482
/*
1483
  rename the specified attribute in a search result
1484
*/
1485
int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
1486
0
{
1487
0
  struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1488
0
  if (el == NULL) {
1489
0
    return LDB_SUCCESS;
1490
0
  }
1491
0
  el->name = talloc_strdup(msg->elements, replace);
1492
0
  if (el->name == NULL) {
1493
0
    return LDB_ERR_OPERATIONS_ERROR;
1494
0
  }
1495
0
  return LDB_SUCCESS;
1496
0
}
1497
1498
1499
/*
1500
  copy the specified attribute in a search result to a new attribute
1501
*/
1502
int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
1503
0
{
1504
0
  struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1505
0
  int ret;
1506
1507
0
  if (el == NULL) {
1508
0
    return LDB_SUCCESS;
1509
0
  }
1510
0
  ret = ldb_msg_add(msg, el, 0);
1511
0
  if (ret != LDB_SUCCESS) {
1512
0
    return ret;
1513
0
  }
1514
0
  return ldb_msg_rename_attr(msg, attr, replace);
1515
0
}
1516
1517
/*
1518
  remove the specified element in a search result
1519
*/
1520
void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
1521
0
{
1522
0
  ptrdiff_t n = (el - msg->elements);
1523
0
  if (n >= msg->num_elements || n < 0) {
1524
    /* the element is not in the list. the caller is crazy. */
1525
0
    return;
1526
0
  }
1527
0
  msg->num_elements--;
1528
0
  if (n != msg->num_elements) {
1529
0
    memmove(el, el+1, (msg->num_elements - n)*sizeof(*el));
1530
0
  }
1531
0
}
1532
1533
1534
/*
1535
  remove the specified attribute in a search result
1536
*/
1537
void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
1538
0
{
1539
0
  unsigned int i;
1540
0
  unsigned int num_del = 0;
1541
1542
0
  for (i = 0; i < msg->num_elements; ++i) {
1543
0
    if (ldb_attr_cmp(msg->elements[i].name, attr) == 0) {
1544
0
      ++num_del;
1545
0
    } else if (num_del) {
1546
0
      msg->elements[i - num_del] = msg->elements[i];
1547
0
    }
1548
0
  }
1549
1550
0
  msg->num_elements -= num_del;
1551
0
}
1552
1553
/* Reallocate elements to drop any excess capacity. */
1554
void ldb_msg_shrink_to_fit(struct ldb_message *msg)
1555
0
{
1556
0
  if (msg->num_elements > 0) {
1557
0
    struct ldb_message_element *elements = talloc_realloc(msg,
1558
0
                      msg->elements,
1559
0
                      struct ldb_message_element,
1560
0
                      msg->num_elements);
1561
0
    if (elements != NULL) {
1562
0
      msg->elements = elements;
1563
0
    }
1564
0
  } else {
1565
0
    TALLOC_FREE(msg->elements);
1566
0
  }
1567
0
}
1568
1569
/*
1570
  return a LDAP formatted GeneralizedTime string
1571
*/
1572
char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
1573
0
{
1574
0
  struct tm *tm = gmtime(&t);
1575
0
  char *ts;
1576
0
  int r;
1577
1578
0
  if (!tm) {
1579
0
    return NULL;
1580
0
  }
1581
1582
  /* we know exactly how long this string will be */
1583
0
  ts = talloc_array(mem_ctx, char, 18);
1584
1585
  /* formatted like: 20040408072012.0Z */
1586
0
  r = snprintf(ts, 18,
1587
0
      "%04u%02u%02u%02u%02u%02u.0Z",
1588
0
      tm->tm_year+1900, tm->tm_mon+1,
1589
0
      tm->tm_mday, tm->tm_hour, tm->tm_min,
1590
0
      tm->tm_sec);
1591
1592
0
  if (r != 17) {
1593
0
    talloc_free(ts);
1594
0
    errno = EOVERFLOW;
1595
0
    return NULL;
1596
0
  }
1597
1598
0
  return ts;
1599
0
}
1600
1601
/*
1602
  convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1603
*/
1604
time_t ldb_string_to_time(const char *s)
1605
0
{
1606
0
  struct tm tm;
1607
0
  time_t t;
1608
1609
0
  if (s == NULL) return 0;
1610
1611
0
  memset(&tm, 0, sizeof(tm));
1612
0
  if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
1613
0
       &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1614
0
       &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1615
0
    return 0;
1616
0
  }
1617
0
  tm.tm_year -= 1900;
1618
0
  tm.tm_mon -= 1;
1619
1620
0
  t = timegm(&tm);
1621
1622
0
  if (t == (time_t)-1 && errno != 0) {
1623
    /*
1624
     * timegm() returns -1 on error, but also for '19691231235959.0Z'.
1625
     */
1626
0
    return 0;
1627
0
  }
1628
0
  return t;
1629
0
}
1630
1631
/*
1632
  convert a LDAP GeneralizedTime string in ldb_val format to a
1633
  time_t.
1634
*/
1635
int ldb_val_to_time(const struct ldb_val *v, time_t *t)
1636
0
{
1637
0
  char val[15] = {0};
1638
0
  struct tm tm = {
1639
0
    .tm_year = 0,
1640
0
  };
1641
1642
0
  if (v == NULL) {
1643
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1644
0
  }
1645
1646
0
  if (v->data == NULL) {
1647
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1648
0
  }
1649
1650
0
  if (v->length < 16 && v->length != 13) {
1651
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1652
0
  }
1653
1654
0
  if (v->data[v->length - 1] != 'Z') {
1655
0
    return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1656
0
  }
1657
1658
0
  if (v->length == 13) {
1659
0
    memcpy(val, v->data, 12);
1660
1661
0
    if (sscanf(val, "%02u%02u%02u%02u%02u%02u",
1662
0
      &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1663
0
      &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1664
0
      return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1665
0
    }
1666
0
    if (tm.tm_year < 50) {
1667
0
      tm.tm_year += 100;
1668
0
    }
1669
0
  } else {
1670
1671
    /*
1672
     * anything between '.' and 'Z' is silently ignored.
1673
     */
1674
0
    if (v->data[14] != '.') {
1675
0
      return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1676
0
    }
1677
1678
0
    memcpy(val, v->data, 14);
1679
1680
0
    if (sscanf(val, "%04u%02u%02u%02u%02u%02u",
1681
0
      &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1682
0
      &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1683
0
      return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1684
0
    }
1685
0
    tm.tm_year -= 1900;
1686
0
  }
1687
0
  tm.tm_mon -= 1;
1688
1689
0
  *t = timegm(&tm);
1690
1691
0
  return LDB_SUCCESS;
1692
0
}
1693
1694
/*
1695
  return a LDAP formatted UTCTime string
1696
*/
1697
char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
1698
0
{
1699
0
  struct tm *tm = gmtime(&t);
1700
0
  char *ts;
1701
0
  int r;
1702
1703
0
  if (!tm) {
1704
0
    return NULL;
1705
0
  }
1706
1707
  /* we know exactly how long this string will be */
1708
0
  ts = talloc_array(mem_ctx, char, 14);
1709
1710
  /* formatted like: 20040408072012.0Z => 040408072012Z */
1711
0
  r = snprintf(ts, 14,
1712
0
      "%02u%02u%02u%02u%02u%02uZ",
1713
0
      (tm->tm_year+1900)%100, tm->tm_mon+1,
1714
0
      tm->tm_mday, tm->tm_hour, tm->tm_min,
1715
0
      tm->tm_sec);
1716
1717
0
  if (r != 13) {
1718
0
    talloc_free(ts);
1719
0
    return NULL;
1720
0
  }
1721
1722
0
  return ts;
1723
0
}
1724
1725
/*
1726
  convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1727
*/
1728
time_t ldb_string_utc_to_time(const char *s)
1729
0
{
1730
0
  struct tm tm;
1731
1732
0
  if (s == NULL) return 0;
1733
1734
0
  memset(&tm, 0, sizeof(tm));
1735
0
  if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
1736
0
       &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1737
0
       &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1738
0
    return 0;
1739
0
  }
1740
0
  if (tm.tm_year < 50) {
1741
0
    tm.tm_year += 100;
1742
0
  }
1743
0
  tm.tm_mon -= 1;
1744
1745
0
  return timegm(&tm);
1746
0
}
1747
1748
1749
/*
1750
  dump a set of results to a file. Useful from within gdb
1751
*/
1752
void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1753
0
{
1754
0
  unsigned int i;
1755
1756
0
  for (i = 0; i < result->count; i++) {
1757
0
    struct ldb_ldif ldif;
1758
0
    fprintf(f, "# record %d\n", i+1);
1759
0
    ldif.changetype = LDB_CHANGETYPE_NONE;
1760
0
    ldif.msg = result->msgs[i];
1761
0
    ldb_ldif_write_file(ldb, f, &ldif);
1762
0
  }
1763
0
}
1764
1765
/*
1766
  checks for a string attribute. Returns "1" on match and otherwise "0".
1767
*/
1768
int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1769
           const char *name, const char *value)
1770
0
{
1771
0
  struct ldb_message_element *el;
1772
0
  struct ldb_val val;
1773
1774
0
  el = ldb_msg_find_element(msg, name);
1775
0
  if (el == NULL) {
1776
0
    return 0;
1777
0
  }
1778
1779
0
  val.data = discard_const_p(uint8_t, value);
1780
0
  val.length = strlen(value);
1781
1782
0
  if (ldb_msg_find_val(el, &val)) {
1783
0
    return 1;
1784
0
  }
1785
1786
0
  return 0;
1787
0
}
1788
1789
1790
/*
1791
  compare a ldb_val to a string
1792
*/
1793
int ldb_val_string_cmp(const struct ldb_val *v, const char *str)
1794
0
{
1795
0
  size_t len = strlen(str);
1796
0
  if (len != v->length) {
1797
0
    return len - v->length;
1798
0
  }
1799
0
  return strncmp((const char *)v->data, str, len);
1800
0
}