Coverage Report

Created: 2026-05-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/lib/util/util.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Samba utility functions
4
   Copyright (C) Andrew Tridgell 1992-1998
5
   Copyright (C) Jeremy Allison 2001-2002
6
   Copyright (C) Simo Sorce 2001-2011
7
   Copyright (C) Jim McDonough (jmcd@us.ibm.com)  2003.
8
   Copyright (C) James J Myers 2003
9
   Copyright (C) Volker Lendecke 2010
10
   Copyright (C) Swen Schillig 2019
11
12
   This program is free software; you can redistribute it and/or modify
13
   it under the terms of the GNU General Public License as published by
14
   the Free Software Foundation; either version 3 of the License, or
15
   (at your option) any later version.
16
17
   This program is distributed in the hope that it will be useful,
18
   but WITHOUT ANY WARRANTY; without even the implied warranty of
19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
   GNU General Public License for more details.
21
22
   You should have received a copy of the GNU General Public License
23
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
*/
25
26
#include "replace.h"
27
#include <talloc.h>
28
#include <tevent.h>
29
#include "system/network.h"
30
#include "system/filesys.h"
31
#include "system/locale.h"
32
#include "system/shmem.h"
33
#include "system/passwd.h"
34
#include "system/time.h"
35
#include "system/wait.h"
36
#include "debug.h"
37
#include "samba_util.h"
38
#include "lib/util/select.h"
39
#include <libgen.h>
40
#include <gnutls/gnutls.h>
41
42
#ifdef HAVE_SYS_PRCTL_H
43
#include <sys/prctl.h>
44
#endif
45
46
#undef malloc
47
#undef strcasecmp
48
#undef strncasecmp
49
#undef strdup
50
#undef realloc
51
#undef calloc
52
53
/**
54
 * @file
55
 * @brief Misc utility functions
56
 */
57
58
/**
59
 Find a suitable temporary directory. The result should be copied immediately
60
 as it may be overwritten by a subsequent call.
61
**/
62
_PUBLIC_ const char *tmpdir(void)
63
0
{
64
0
  char *p;
65
0
  if ((p = getenv("TMPDIR")))
66
0
    return p;
67
0
  return "/tmp";
68
0
}
69
70
71
/**
72
 Create a tmp file, open it and immediately unlink it.
73
 If dir is NULL uses tmpdir()
74
 Returns the file descriptor or -1 on error.
75
**/
76
int create_unlink_tmp(const char *dir)
77
0
{
78
0
  size_t len = strlen(dir ? dir : (dir = tmpdir()));
79
0
  char fname[len+25];
80
0
  int fd;
81
0
  mode_t mask;
82
83
0
  len = snprintf(fname, sizeof(fname), "%s/listenerlock_XXXXXX", dir);
84
0
  if (len >= sizeof(fname)) {
85
0
    errno = ENOMEM;
86
0
    return -1;
87
0
  }
88
0
  mask = umask(S_IRWXO | S_IRWXG);
89
0
  fd = mkstemp(fname);
90
0
  umask(mask);
91
0
  if (fd == -1) {
92
0
    return -1;
93
0
  }
94
0
  if (unlink(fname) == -1) {
95
0
    int sys_errno = errno;
96
0
    close(fd);
97
0
    errno = sys_errno;
98
0
    return -1;
99
0
  }
100
0
  return fd;
101
0
}
102
103
104
/**
105
 Check if a file exists - call vfs_file_exist for samba files.
106
**/
107
_PUBLIC_ bool file_exist(const char *fname)
108
0
{
109
0
  struct stat st;
110
111
0
  if (stat(fname, &st) != 0) {
112
0
    return false;
113
0
  }
114
115
0
  return ((S_ISREG(st.st_mode)) || (S_ISFIFO(st.st_mode)));
116
0
}
117
118
/**
119
 * @brief Return a files modification time.
120
 *
121
 * @param fname  The name of the file.
122
 *
123
 * @param mt     A pointer to store the modification time.
124
 *
125
 * @return 0 on success, errno otherwise.
126
 */
127
_PUBLIC_ int file_modtime(const char *fname, struct timespec *mt)
128
0
{
129
0
  struct stat st = {0};
130
131
0
  if (stat(fname, &st) != 0) {
132
0
    return errno;
133
0
  }
134
135
0
  *mt = get_mtimespec(&st);
136
0
  return 0;
137
0
}
138
139
/**
140
 Check file permissions.
141
**/
142
143
_PUBLIC_ bool file_check_permissions(const char *fname,
144
             uid_t uid,
145
             mode_t file_perms,
146
             struct stat *pst)
147
0
{
148
0
  int ret;
149
0
  struct stat st;
150
151
0
  if (pst == NULL) {
152
0
    pst = &st;
153
0
  }
154
155
0
  ZERO_STRUCTP(pst);
156
157
0
  ret = stat(fname, pst);
158
0
  if (ret != 0) {
159
0
    DEBUG(0, ("stat failed on file '%s': %s\n",
160
0
       fname, strerror(errno)));
161
0
    return false;
162
0
  }
163
164
0
  if (pst->st_uid != uid && !uid_wrapper_enabled()) {
165
0
    DEBUG(0, ("invalid ownership of file '%s': "
166
0
       "owned by uid %u, should be %u\n",
167
0
       fname, (unsigned int)pst->st_uid,
168
0
       (unsigned int)uid));
169
0
    return false;
170
0
  }
171
172
0
  if ((pst->st_mode & 0777) != file_perms) {
173
0
    DEBUG(0, ("invalid permissions on file "
174
0
       "'%s': has 0%o should be 0%o\n", fname,
175
0
       (unsigned int)(pst->st_mode & 0777),
176
0
       (unsigned int)file_perms));
177
0
    return false;
178
0
  }
179
180
0
  return true;
181
0
}
182
183
/**
184
 Check if a directory exists.
185
**/
186
187
_PUBLIC_ bool directory_exist(const char *dname)
188
0
{
189
0
  struct stat st;
190
0
  bool ret;
191
192
0
  if (stat(dname,&st) != 0) {
193
0
    return false;
194
0
  }
195
196
0
  ret = S_ISDIR(st.st_mode);
197
0
  if(!ret)
198
0
    errno = ENOTDIR;
199
0
  return ret;
200
0
}
201
202
/**
203
 * Try to create the specified directory if it didn't exist.
204
 * A symlink to a directory is also accepted as a valid existing directory.
205
 *
206
 * @retval true if the directory already existed
207
 * or was successfully created.
208
 */
209
_PUBLIC_ bool directory_create_or_exist(const char *dname,
210
          mode_t dir_perms)
211
0
{
212
0
  int ret;
213
0
  mode_t old_umask;
214
215
  /* Create directory */
216
0
  old_umask = umask(0);
217
0
  ret = mkdir(dname, dir_perms);
218
0
  if (ret == -1 && errno != EEXIST) {
219
0
    int dbg_level = geteuid() == 0 ? DBGLVL_ERR : DBGLVL_NOTICE;
220
221
0
    DBG_PREFIX(dbg_level,
222
0
         ("mkdir failed on directory %s: %s\n",
223
0
          dname,
224
0
          strerror(errno)));
225
0
    umask(old_umask);
226
0
    return false;
227
0
  }
228
0
  umask(old_umask);
229
230
0
  if (ret != 0 && errno == EEXIST) {
231
0
    struct stat sbuf;
232
233
0
    ret = lstat(dname, &sbuf);
234
0
    if (ret != 0) {
235
0
      return false;
236
0
    }
237
238
0
    if (S_ISDIR(sbuf.st_mode)) {
239
0
      return true;
240
0
    }
241
242
0
    if (S_ISLNK(sbuf.st_mode)) {
243
0
      ret = stat(dname, &sbuf);
244
0
      if (ret != 0) {
245
0
        return false;
246
0
      }
247
248
0
      if (S_ISDIR(sbuf.st_mode)) {
249
0
        return true;
250
0
      }
251
0
    }
252
253
0
    return false;
254
0
  }
255
256
0
  return true;
257
0
}
258
259
_PUBLIC_ bool directory_create_or_exists_recursive(
260
    const char *dname,
261
    mode_t dir_perms)
262
0
{
263
0
  bool ok;
264
265
0
  ok = directory_create_or_exist(dname, dir_perms);
266
0
  if (!ok) {
267
0
    if (!directory_exist(dname)) {
268
0
      char tmp[PATH_MAX] = {0};
269
0
      char *parent = NULL;
270
0
      size_t n;
271
272
      /* Use the null context */
273
0
      n = strlcpy(tmp, dname, sizeof(tmp));
274
0
      if (n < strlen(dname)) {
275
0
        DBG_ERR("Path too long!\n");
276
0
        return false;
277
0
      }
278
279
0
      parent = dirname(tmp);
280
0
      if (parent == NULL) {
281
0
        DBG_ERR("Failed to create dirname!\n");
282
0
        return false;
283
0
      }
284
285
0
      ok = directory_create_or_exists_recursive(parent,
286
0
                  dir_perms);
287
0
      if (!ok) {
288
0
        return false;
289
0
      }
290
291
0
      ok = directory_create_or_exist(dname, dir_perms);
292
0
    }
293
0
  }
294
295
0
  return ok;
296
0
}
297
298
/**
299
 * @brief Try to create a specified directory if it doesn't exist.
300
 *
301
 * The function creates a directory with the given uid and permissions if it
302
 * doesn't exist. If it exists it makes sure the uid and permissions are
303
 * correct and it will fail if they are different.
304
 *
305
 * @param[in]  dname  The directory to create.
306
 *
307
 * @param[in]  uid    The uid the directory needs to belong too.
308
 *
309
 * @param[in]  dir_perms  The expected permissions of the directory.
310
 *
311
 * @return True on success, false on error.
312
 */
313
_PUBLIC_ bool directory_create_or_exist_strict(const char *dname,
314
                 uid_t uid,
315
                 mode_t dir_perms)
316
0
{
317
0
  struct stat st;
318
0
  bool ok;
319
0
  int rc;
320
321
0
  ok = directory_create_or_exist(dname, dir_perms);
322
0
  if (!ok) {
323
0
    return false;
324
0
  }
325
326
0
  rc = lstat(dname, &st);
327
0
  if (rc == -1) {
328
0
    DEBUG(0, ("lstat failed on created directory %s: %s\n",
329
0
        dname, strerror(errno)));
330
0
    return false;
331
0
  }
332
333
  /* Check ownership and permission on existing directory */
334
0
  if (!S_ISDIR(st.st_mode)) {
335
0
    DEBUG(0, ("directory %s isn't a directory\n",
336
0
      dname));
337
0
    return false;
338
0
  }
339
0
  if (st.st_uid != uid && !uid_wrapper_enabled()) {
340
0
    DBG_NOTICE("invalid ownership on directory "
341
0
        "%s\n", dname);
342
0
    return false;
343
0
  }
344
0
  if ((st.st_mode & 0777) != dir_perms) {
345
0
    DEBUG(0, ("invalid permissions on directory "
346
0
        "'%s': has 0%o should be 0%o\n", dname,
347
0
        (unsigned int)(st.st_mode & 0777), (unsigned int)dir_perms));
348
0
    return false;
349
0
  }
350
351
0
  return true;
352
0
}
353
354
355
/**
356
 Sleep for a specified number of milliseconds.
357
**/
358
359
_PUBLIC_ void smb_msleep(unsigned int t)
360
0
{
361
0
  sys_poll_intr(NULL, 0, t);
362
0
}
363
364
/**
365
 Get my own name, return in talloc'ed storage.
366
**/
367
368
_PUBLIC_ char *get_myname(TALLOC_CTX *ctx)
369
0
{
370
0
  char *p;
371
0
  char hostname[HOST_NAME_MAX];
372
373
  /* get my host name */
374
0
  if (gethostname(hostname, sizeof(hostname)) == -1) {
375
0
    DEBUG(0,("gethostname failed\n"));
376
0
    return NULL;
377
0
  }
378
379
  /* Ensure null termination. */
380
0
  hostname[sizeof(hostname)-1] = '\0';
381
382
  /* split off any parts after an initial . */
383
0
  p = strchr_m(hostname, '.');
384
0
  if (p) {
385
0
    *p = 0;
386
0
  }
387
388
0
  return talloc_strdup(ctx, hostname);
389
0
}
390
391
/**
392
 Check if a process exists. Does this work on all unixes?
393
**/
394
395
_PUBLIC_ bool process_exists_by_pid(pid_t pid)
396
0
{
397
  /* Doing kill with a non-positive pid causes messages to be
398
   * sent to places we don't want. */
399
0
  if (pid <= 0) {
400
0
    return false;
401
0
  }
402
0
  return(kill(pid,0) == 0 || errno != ESRCH);
403
0
}
404
405
/**
406
 Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
407
 is dealt with in posix.c
408
**/
409
410
_PUBLIC_ bool fcntl_lock(int fd, int op, off_t offset, off_t count, int type)
411
0
{
412
0
  struct flock lock;
413
0
  int ret;
414
415
0
  DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
416
417
0
  lock.l_type = type;
418
0
  lock.l_whence = SEEK_SET;
419
0
  lock.l_start = offset;
420
0
  lock.l_len = count;
421
0
  lock.l_pid = 0;
422
423
0
  ret = fcntl(fd,op,&lock);
424
425
0
  if (ret == -1 && errno != 0)
426
0
    DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
427
428
  /* a lock query */
429
0
  if (op == F_GETLK) {
430
0
    if ((ret != -1) &&
431
0
        (lock.l_type != F_UNLCK) &&
432
0
        (lock.l_pid != 0) &&
433
0
        (lock.l_pid != tevent_cached_getpid())) {
434
0
      DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
435
0
      return true;
436
0
    }
437
438
    /* it must be not locked or locked by me */
439
0
    return false;
440
0
  }
441
442
  /* a lock set or unset */
443
0
  if (ret == -1) {
444
0
    DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
445
0
      (double)offset,(double)count,op,type,strerror(errno)));
446
0
    return false;
447
0
  }
448
449
  /* everything went OK */
450
0
  DEBUG(8,("fcntl_lock: Lock call successful\n"));
451
452
0
  return true;
453
0
}
454
455
struct debug_channel_level {
456
  int channel;
457
  int level;
458
};
459
460
static void debugadd_channel_cb(const char *buf, void *private_data)
461
0
{
462
0
  struct debug_channel_level *dcl =
463
0
    (struct debug_channel_level *)private_data;
464
465
0
  DEBUGADDC(dcl->channel, dcl->level,("%s", buf));
466
0
}
467
468
static void debugadd_cb(const char *buf, void *private_data)
469
6.86M
{
470
6.86M
  int *plevel = (int *)private_data;
471
6.86M
  DEBUGADD(*plevel, ("%s", buf));
472
6.86M
}
473
474
void print_asc_cb(const uint8_t *buf, int len,
475
      void (*cb)(const char *buf, void *private_data),
476
      void *private_data)
477
507M
{
478
507M
  int i;
479
507M
  char s[2];
480
507M
  s[1] = 0;
481
482
1.02G
  for (i=0; i<len; i++) {
483
512M
    s[0] = isprint(buf[i]) ? buf[i] : '.';
484
512M
    cb(s, private_data);
485
512M
  }
486
507M
}
487
488
void print_asc(int level, const uint8_t *buf,int len)
489
1.57M
{
490
1.57M
  print_asc_cb(buf, len, debugadd_cb, &level);
491
1.57M
}
492
493
static void dump_data_block16(const char *prefix, size_t idx,
494
            const uint8_t *buf, size_t len,
495
            void (*cb)(const char *buf, void *private_data),
496
            void *private_data)
497
32.2M
{
498
32.2M
  size_t prefix_len = strlen(prefix);
499
  /* 16 (=%04zX) + 2 (=[]) + 1 (='\0') => 19 */
500
32.2M
  char tmp[prefix_len + 19];
501
32.2M
  size_t i;
502
503
32.2M
  SMB_ASSERT(len <= 16);
504
505
32.2M
  snprintf(tmp, sizeof(tmp), "%s[%04zX]", prefix, idx);
506
32.2M
  cb(tmp, private_data);
507
508
548M
  for (i=0; i<16; i++) {
509
516M
    if (i == 8) {
510
32.2M
      cb("  ", private_data);
511
32.2M
    }
512
516M
    if (i < len) {
513
506M
      snprintf(tmp, sizeof(tmp), " %02X", (int)buf[i]);
514
506M
    } else {
515
10.5M
      snprintf(tmp, sizeof(tmp), "   ");
516
10.5M
    }
517
516M
    cb(tmp, private_data);
518
516M
  }
519
520
32.2M
  cb("   ", private_data);
521
522
32.2M
  if (len == 0) {
523
0
    cb("EMPTY   BLOCK\n", private_data);
524
0
    return;
525
0
  }
526
527
538M
  for (i=0; i<len; i++) {
528
506M
    if (i == 8) {
529
31.5M
      cb(" ", private_data);
530
31.5M
    }
531
506M
    print_asc_cb(&buf[i], 1, cb, private_data);
532
506M
  }
533
534
32.2M
  cb("\n", private_data);
535
32.2M
}
536
537
/**
538
 * Write dump of binary data to a callback
539
 */
540
void dump_data_cb(const uint8_t *buf, int len,
541
      bool omit_zero_bytes,
542
      void (*cb)(const char *buf, void *private_data),
543
      void *private_data)
544
900k
{
545
900k
  int i=0;
546
900k
  bool skipped = false;
547
548
900k
  if (len<=0) return;
549
550
73.3M
  for (i=0;i<len;i+=16) {
551
72.4M
    size_t remaining_len = len - i;
552
72.4M
    size_t this_len = MIN(remaining_len, 16);
553
72.4M
    const uint8_t *this_buf = &buf[i];
554
555
72.4M
    if (omit_zero_bytes && (i > 0) && (remaining_len > 16) &&
556
71.3M
        (this_len == 16) && all_zero(this_buf, 16))
557
40.1M
    {
558
40.1M
      if (!skipped) {
559
1.20M
        cb("skipping zero buffer bytes\n",
560
1.20M
           private_data);
561
1.20M
        skipped = true;
562
1.20M
      }
563
40.1M
      continue;
564
40.1M
    }
565
566
32.2M
    skipped = false;
567
32.2M
    dump_data_block16("", i, this_buf, this_len,
568
32.2M
          cb, private_data);
569
32.2M
  }
570
900k
}
571
572
/**
573
 * Write dump of binary data to the log file.
574
 *
575
 * The data is only written if the log level is at least level.
576
 */
577
_PUBLIC_ void dump_data(int level, const uint8_t *buf, int len)
578
0
{
579
0
  if (!DEBUGLVL(level)) {
580
0
    return;
581
0
  }
582
0
  dump_data_cb(buf, len, false, debugadd_cb, &level);
583
0
}
584
585
/**
586
 * Write dump of binary data to the log file.
587
 *
588
 * The data is only written if the log level is at least level for
589
 * debug class dbgc_class.
590
 */
591
_PUBLIC_ void dump_data_dbgc(int dbgc_class, int level, const uint8_t *buf, int len)
592
0
{
593
0
  struct debug_channel_level dcl = { dbgc_class, level };
594
595
0
  if (!DEBUGLVLC(dbgc_class, level)) {
596
0
    return;
597
0
  }
598
0
  dump_data_cb(buf, len, false, debugadd_channel_cb, &dcl);
599
0
}
600
601
/**
602
 * Write dump of binary data to the log file.
603
 *
604
 * The data is only written if the log level is at least level.
605
 * 16 zero bytes in a row are omitted
606
 */
607
_PUBLIC_ void dump_data_skip_zeros(int level, const uint8_t *buf, int len)
608
0
{
609
0
  if (!DEBUGLVL(level)) {
610
0
    return;
611
0
  }
612
0
  dump_data_cb(buf, len, true, debugadd_cb, &level);
613
0
}
614
615
static void fprintf_cb(const char *buf, void *private_data)
616
0
{
617
0
  FILE *f = (FILE *)private_data;
618
0
  fprintf(f, "%s", buf);
619
0
}
620
621
void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes,
622
        FILE *f)
623
0
{
624
0
  dump_data_cb(buf, len, omit_zero_bytes, fprintf_cb, f);
625
0
}
626
627
/**
628
 * Write dump of compared binary data to a callback
629
 */
630
void dump_data_diff_cb(const uint8_t *buf1, size_t len1,
631
           const uint8_t *buf2, size_t len2,
632
           bool omit_zero_bytes,
633
           void (*cb)(const char *buf, void *private_data),
634
           void *private_data)
635
0
{
636
0
  size_t len = MAX(len1, len2);
637
0
  size_t i;
638
0
  bool skipped = false;
639
640
0
  for (i=0; i<len; i+=16) {
641
0
    size_t remaining_len = len - i;
642
0
    size_t remaining_len1 = 0;
643
0
    size_t this_len1 = 0;
644
0
    const uint8_t *this_buf1 = NULL;
645
0
    size_t remaining_len2 = 0;
646
0
    size_t this_len2 = 0;
647
0
    const uint8_t *this_buf2 = NULL;
648
649
0
    if (i < len1) {
650
0
      remaining_len1 = len1 - i;
651
0
      this_len1 = MIN(remaining_len1, 16);
652
0
      this_buf1 = &buf1[i];
653
0
    }
654
0
    if (i < len2) {
655
0
      remaining_len2 = len2 - i;
656
0
      this_len2 = MIN(remaining_len2, 16);
657
0
      this_buf2 = &buf2[i];
658
0
    }
659
660
0
    if (omit_zero_bytes && (i > 0) && (remaining_len > 16) &&
661
0
        (this_len1 == 16) && all_zero(this_buf1, 16) &&
662
0
        (this_len2 == 16) && all_zero(this_buf2, 16))
663
0
    {
664
0
      if (!skipped) {
665
0
        cb("skipping zero buffer bytes\n",
666
0
           private_data);
667
0
        skipped = true;
668
0
      }
669
0
      continue;
670
0
    }
671
672
0
    skipped = false;
673
674
0
    if ((this_len1 == this_len2) &&
675
0
        (memcmp(this_buf1, this_buf2, this_len1) == 0))
676
0
    {
677
0
      dump_data_block16(" ", i, this_buf1, this_len1,
678
0
            cb, private_data);
679
0
      continue;
680
0
    }
681
682
0
    dump_data_block16("-", i, this_buf1, this_len1,
683
0
          cb, private_data);
684
0
    dump_data_block16("+", i, this_buf2, this_len2,
685
0
          cb, private_data);
686
0
  }
687
0
}
688
689
_PUBLIC_ void dump_data_diff(int dbgc_class, int level,
690
           bool omit_zero_bytes,
691
           const uint8_t *buf1, size_t len1,
692
           const uint8_t *buf2, size_t len2)
693
0
{
694
0
  struct debug_channel_level dcl = { dbgc_class, level };
695
696
0
  if (!DEBUGLVLC(dbgc_class, level)) {
697
0
    return;
698
0
  }
699
0
  dump_data_diff_cb(buf1,
700
0
        len1,
701
0
        buf2,
702
0
        len2,
703
0
        omit_zero_bytes,
704
0
        debugadd_channel_cb,
705
0
        &dcl);
706
0
}
707
708
_PUBLIC_ void dump_data_file_diff(FILE *f,
709
                bool omit_zero_bytes,
710
                const uint8_t *buf1, size_t len1,
711
                const uint8_t *buf2, size_t len2)
712
0
{
713
0
  dump_data_diff_cb(buf1, len1, buf2, len2, omit_zero_bytes, fprintf_cb, f);
714
0
}
715
716
/**
717
 malloc that aborts with smb_panic on fail or zero size.
718
**/
719
720
_PUBLIC_ void *smb_xmalloc(size_t size)
721
0
{
722
0
  void *p;
723
0
  if (size == 0)
724
0
    smb_panic("smb_xmalloc: called with zero size.\n");
725
0
  if ((p = malloc(size)) == NULL)
726
0
    smb_panic("smb_xmalloc: malloc fail.\n");
727
0
  return p;
728
0
}
729
730
/**
731
 Memdup with smb_panic on fail.
732
**/
733
734
_PUBLIC_ void *smb_xmemdup(const void *p, size_t size)
735
0
{
736
0
  void *p2;
737
0
  p2 = smb_xmalloc(size);
738
0
  memcpy(p2, p, size);
739
0
  return p2;
740
0
}
741
742
/**
743
 strdup that aborts on malloc fail.
744
**/
745
746
char *smb_xstrdup(const char *s)
747
105
{
748
#if defined(PARANOID_MALLOC_CHECKER)
749
#ifdef strdup
750
#undef strdup
751
#endif
752
#endif
753
754
#ifndef HAVE_STRDUP
755
#define strdup rep_strdup
756
#endif
757
758
105
  char *s1 = strdup(s);
759
#if defined(PARANOID_MALLOC_CHECKER)
760
#ifdef strdup
761
#undef strdup
762
#endif
763
#define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
764
#endif
765
105
  if (!s1) {
766
0
    smb_panic("smb_xstrdup: malloc failed");
767
0
  }
768
105
  return s1;
769
770
105
}
771
772
/**
773
 strndup that aborts on malloc fail.
774
**/
775
776
char *smb_xstrndup(const char *s, size_t n)
777
0
{
778
#if defined(PARANOID_MALLOC_CHECKER)
779
#ifdef strndup
780
#undef strndup
781
#endif
782
#endif
783
784
#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
785
#undef HAVE_STRNDUP
786
#define strndup rep_strndup
787
#endif
788
789
0
  char *s1 = strndup(s, n);
790
#if defined(PARANOID_MALLOC_CHECKER)
791
#ifdef strndup
792
#undef strndup
793
#endif
794
#define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
795
#endif
796
0
  if (!s1) {
797
0
    smb_panic("smb_xstrndup: malloc failed");
798
0
  }
799
0
  return s1;
800
0
}
801
802
803
804
/**
805
 Like strdup but for memory.
806
**/
807
808
_PUBLIC_ void *smb_memdup(const void *p, size_t size)
809
0
{
810
0
  void *p2;
811
0
  if (size == 0)
812
0
    return NULL;
813
0
  p2 = malloc(size);
814
0
  if (!p2)
815
0
    return NULL;
816
0
  memcpy(p2, p, size);
817
0
  return p2;
818
0
}
819
820
/**
821
 * Write a password to the log file.
822
 *
823
 * @note Only actually does something if DEBUG_PASSWORD was defined during
824
 * compile-time.
825
 */
826
_PUBLIC_ void dump_data_pw(const char *msg, const uint8_t * data, size_t len)
827
0
{
828
0
#ifdef DEBUG_PASSWORD
829
0
  DEBUG(11, ("%s", msg));
830
0
  if (data != NULL && len > 0)
831
0
  {
832
0
    dump_data(11, data, len);
833
0
  }
834
0
#endif
835
0
}
836
837
static void dump_data_addbuf_cb(const char *buf, void *private_data)
838
0
{
839
0
  char **str = private_data;
840
0
  talloc_asprintf_addbuf(str, "%s", buf);
841
0
}
842
843
_PUBLIC_ void dump_data_addbuf(const uint8_t *buf, size_t buflen, char **str)
844
0
{
845
0
  dump_data_cb(buf, buflen, false, dump_data_addbuf_cb, str);
846
0
}
847
848
849
/**
850
 * see if a range of memory is all zero. A NULL pointer is considered
851
 * to be all zero
852
 */
853
_PUBLIC_ bool all_zero(const uint8_t *ptr, size_t size)
854
71.6M
{
855
71.6M
  size_t i;
856
71.6M
  if (!ptr) return true;
857
770M
  for (i=0;i<size;i++) {
858
729M
    if (ptr[i]) return false;
859
729M
  }
860
40.3M
  return true;
861
71.6M
}
862
863
/**
864
  realloc an array, checking for integer overflow in the array size
865
*/
866
_PUBLIC_ void *realloc_array(void *ptr, size_t el_size, unsigned count, bool free_on_fail)
867
635
{
868
755
#define MAX_MALLOC_SIZE 0x7fffffff
869
635
  if (count == 0 ||
870
635
      count >= MAX_MALLOC_SIZE/el_size) {
871
0
    if (free_on_fail)
872
0
      SAFE_FREE(ptr);
873
0
    return NULL;
874
0
  }
875
635
  if (!ptr) {
876
635
    return malloc(el_size * count);
877
635
  }
878
0
  return realloc(ptr, el_size * count);
879
635
}
880
881
/****************************************************************************
882
 Type-safe malloc.
883
****************************************************************************/
884
885
void *malloc_array(size_t el_size, unsigned int count)
886
635
{
887
635
  return realloc_array(NULL, el_size, count, false);
888
635
}
889
890
/****************************************************************************
891
 Type-safe memalign
892
****************************************************************************/
893
894
void *memalign_array(size_t el_size, size_t align, unsigned int count)
895
0
{
896
0
  if (el_size == 0 || count >= MAX_MALLOC_SIZE/el_size) {
897
0
    return NULL;
898
0
  }
899
900
0
  return memalign(align, el_size*count);
901
0
}
902
903
/****************************************************************************
904
 Type-safe calloc.
905
****************************************************************************/
906
907
void *calloc_array(size_t size, size_t nmemb)
908
120
{
909
120
  if (nmemb >= MAX_MALLOC_SIZE/size) {
910
0
    return NULL;
911
0
  }
912
120
  if (size == 0 || nmemb == 0) {
913
0
    return NULL;
914
0
  }
915
120
  return calloc(nmemb, size);
916
120
}
917
918
/**
919
 Trim the specified elements off the front and back of a string.
920
**/
921
_PUBLIC_ bool trim_string(char *s, const char *front, const char *back)
922
17.5k
{
923
17.5k
  bool ret = false;
924
17.5k
  size_t front_len;
925
17.5k
  size_t back_len;
926
17.5k
  size_t len;
927
928
  /* Ignore null or empty strings. */
929
17.5k
  if (!s || (s[0] == '\0')) {
930
792
    return false;
931
792
  }
932
16.7k
  len = strlen(s);
933
934
16.7k
  front_len = front? strlen(front) : 0;
935
16.7k
  back_len  = back? strlen(back) : 0;
936
937
16.7k
  if (front_len) {
938
0
    size_t front_trim = 0;
939
940
0
    while (strncmp(s+front_trim, front, front_len)==0) {
941
0
      front_trim += front_len;
942
0
    }
943
0
    if (front_trim > 0) {
944
      /* Must use memmove here as src & dest can
945
       * easily overlap. Found by valgrind. JRA. */
946
0
      memmove(s, s+front_trim, (len-front_trim)+1);
947
0
      len -= front_trim;
948
0
      ret=true;
949
0
    }
950
0
  }
951
952
16.7k
  if (back_len) {
953
17.6k
    while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
954
825
      s[len-back_len]='\0';
955
825
      len -= back_len;
956
825
      ret=true;
957
825
    }
958
16.7k
  }
959
16.7k
  return ret;
960
17.5k
}
961
962
/**
963
 Find the number of 'c' chars in a string
964
**/
965
_PUBLIC_ _PURE_ size_t count_chars(const char *s, char c)
966
0
{
967
0
  size_t count = 0;
968
969
0
  while (*s) {
970
0
    if (*s == c) count++;
971
0
    s ++;
972
0
  }
973
974
0
  return count;
975
0
}
976
977
/**
978
 * Routine to get hex characters and turn them into a byte array.
979
 * the array can be variable length.
980
 * -  "0xnn" or "0Xnn" is specially catered for.
981
 * - The first non-hex-digit character (apart from possibly leading "0x"
982
 *   finishes the conversion and skips the rest of the input.
983
 * - A single hex-digit character at the end of the string is skipped.
984
 *
985
 * valid examples: "0A5D15"; "0x123456"
986
 */
987
_PUBLIC_ size_t strhex_to_str(char *p, size_t p_len, const char *strhex, size_t strhex_len)
988
0
{
989
0
  size_t i = 0;
990
0
  size_t num_chars = 0;
991
992
  /* skip leading 0x prefix */
993
0
  if (strncasecmp(strhex, "0x", 2) == 0) {
994
0
    i += 2; /* skip two chars */
995
0
  }
996
997
0
  while ((i < strhex_len) && (num_chars < p_len)) {
998
0
    bool ok = hex_byte(&strhex[i], (uint8_t *)&p[num_chars]);
999
0
    if (!ok) {
1000
0
      break;
1001
0
    }
1002
0
    i += 2;
1003
0
    num_chars += 1;
1004
0
  }
1005
1006
0
  return num_chars;
1007
0
}
1008
1009
/**
1010
 * Parse a hex string and return a data blob.
1011
 */
1012
_PUBLIC_ DATA_BLOB strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *strhex)
1013
0
{
1014
0
  DATA_BLOB ret_blob = data_blob_talloc(mem_ctx, NULL, strlen(strhex)/2+1);
1015
0
  if (ret_blob.data == NULL) {
1016
    /* ret_blob.length is already 0 */
1017
0
    return ret_blob;
1018
0
  }
1019
0
  ret_blob.length = strhex_to_str((char *)ret_blob.data, ret_blob.length,
1020
0
          strhex,
1021
0
          strlen(strhex));
1022
1023
0
  return ret_blob;
1024
0
}
1025
1026
/**
1027
 * Parse a hex dump and return a data blob. Hex dump is structured as
1028
 * is generated from dump_data_cb() elsewhere in this file
1029
 *
1030
 */
1031
_PUBLIC_ DATA_BLOB hexdump_to_data_blob(TALLOC_CTX *mem_ctx, const char *hexdump, size_t hexdump_len)
1032
0
{
1033
0
  DATA_BLOB ret_blob = { 0 };
1034
0
  size_t i = 0;
1035
0
  size_t char_count = 0;
1036
  /* hexdump line length is 77 chars long. We then use the ASCII representation of the bytes
1037
   * at the end of the final line to calculate how many are in that line, minus the extra space
1038
   * and newline. */
1039
0
  size_t hexdump_byte_count = (16 * (hexdump_len / 77));
1040
0
  if (hexdump_len % 77) {
1041
0
    hexdump_byte_count += ((hexdump_len % 77) - 59 - 2);
1042
0
  }
1043
1044
0
  ret_blob = data_blob_talloc(mem_ctx, NULL, hexdump_byte_count+1);
1045
0
  for (; i+1 < hexdump_len && hexdump[i] != 0 && hexdump[i+1] != 0; i++) {
1046
0
    if ((i%77) == 0)
1047
0
      i += 7; /* Skip the offset at the start of the line */
1048
0
    if ((i%77) < 56) { /* position 56 is after both hex chunks */
1049
0
      if (hexdump[i] != ' ') {
1050
0
        char_count += strhex_to_str((char *)&ret_blob.data[char_count],
1051
0
                  hexdump_byte_count - char_count,
1052
0
                  &hexdump[i], 2);
1053
0
        i += 2;
1054
0
      } else {
1055
0
        i++;
1056
0
      }
1057
0
    } else {
1058
0
      i++;
1059
0
    }
1060
0
  }
1061
0
  ret_blob.length = char_count;
1062
1063
0
  return ret_blob;
1064
0
}
1065
1066
/**
1067
 * Print a buf in hex. Assumes dst is at least (srclen*2)+1 large.
1068
 */
1069
_PUBLIC_ void hex_encode_buf(char *dst, const uint8_t *src, size_t srclen)
1070
9.21k
{
1071
9.21k
  size_t i;
1072
201k
  for (i=0; i<srclen; i++) {
1073
192k
    snprintf(dst + i*2, 3, "%02X", src[i]);
1074
192k
  }
1075
  /*
1076
   * Ensure 0-termination for 0-length buffers
1077
   */
1078
9.21k
  dst[srclen*2] = '\0';
1079
9.21k
}
1080
1081
/**
1082
 * talloc version of hex_encode_buf()
1083
 */
1084
_PUBLIC_ char *hex_encode_talloc(TALLOC_CTX *mem_ctx, const unsigned char *buff_in, size_t len)
1085
9.21k
{
1086
9.21k
  char *hex_buffer;
1087
1088
9.21k
  hex_buffer = talloc_array(mem_ctx, char, (len*2)+1);
1089
9.21k
  if (!hex_buffer) {
1090
0
    return NULL;
1091
0
  }
1092
9.21k
  hex_encode_buf(hex_buffer, buff_in, len);
1093
9.21k
  talloc_set_name_const(hex_buffer, hex_buffer);
1094
9.21k
  return hex_buffer;
1095
9.21k
}
1096
1097
/**
1098
  variant of strcmp() that handles NULL ptrs
1099
**/
1100
_PUBLIC_ int strcmp_safe(const char *s1, const char *s2)
1101
0
{
1102
0
  if (s1 == s2) {
1103
0
    return 0;
1104
0
  }
1105
0
  if (s1 == NULL || s2 == NULL) {
1106
0
    return s1?-1:1;
1107
0
  }
1108
0
  return strcmp(s1, s2);
1109
0
}
1110
1111
1112
/**
1113
return the number of bytes occupied by a buffer in ASCII format
1114
the result includes the null termination
1115
limited by 'n' bytes
1116
**/
1117
_PUBLIC_ size_t ascii_len_n(const char *src, size_t n)
1118
9.37M
{
1119
9.37M
  size_t len;
1120
1121
9.37M
  len = strnlen(src, n);
1122
9.37M
  if (len+1 <= n) {
1123
9.32M
    len += 1;
1124
9.32M
  }
1125
1126
9.37M
  return len;
1127
9.37M
}
1128
1129
_PUBLIC_ bool mem_equal_const_time(const void *s1, const void *s2, size_t n)
1130
0
{
1131
  /* Ensure we won't overflow the unsigned index used by gnutls. */
1132
0
  SMB_ASSERT(n <= UINT_MAX);
1133
1134
0
  return gnutls_memcmp(s1, s2, n) == 0;
1135
0
}
1136
1137
struct anonymous_shared_header {
1138
  union {
1139
    size_t length;
1140
    uint8_t pad[16];
1141
  } u;
1142
};
1143
1144
/* Map a shared memory buffer of at least nelem counters. */
1145
void *anonymous_shared_allocate(size_t orig_bufsz)
1146
0
{
1147
0
  void *ptr;
1148
0
  void *buf;
1149
0
  size_t pagesz = getpagesize();
1150
0
  size_t pagecnt;
1151
0
  size_t bufsz = orig_bufsz;
1152
0
  struct anonymous_shared_header *hdr;
1153
1154
0
  bufsz += sizeof(*hdr);
1155
1156
  /* round up to full pages */
1157
0
  pagecnt = bufsz / pagesz;
1158
0
  if (bufsz % pagesz) {
1159
0
    pagecnt += 1;
1160
0
  }
1161
0
  bufsz = pagesz * pagecnt;
1162
1163
0
  if (orig_bufsz >= bufsz) {
1164
    /* integer wrap */
1165
0
    errno = ENOMEM;
1166
0
    return NULL;
1167
0
  }
1168
1169
0
#ifdef MAP_ANON
1170
  /* BSD */
1171
0
  buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
1172
0
      -1 /* fd */, 0 /* offset */);
1173
#else
1174
{
1175
  int saved_errno;
1176
  int fd;
1177
1178
  fd = open("/dev/zero", O_RDWR);
1179
  if (fd == -1) {
1180
    return NULL;
1181
  }
1182
1183
  buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
1184
       fd, 0 /* offset */);
1185
  saved_errno = errno;
1186
  close(fd);
1187
  errno = saved_errno;
1188
}
1189
#endif
1190
1191
0
  if (buf == MAP_FAILED) {
1192
0
    return NULL;
1193
0
  }
1194
1195
0
  hdr = (struct anonymous_shared_header *)buf;
1196
0
  hdr->u.length = bufsz;
1197
1198
0
  ptr = (void *)(&hdr[1]);
1199
1200
0
  return ptr;
1201
0
}
1202
1203
void *anonymous_shared_resize(void *ptr, size_t new_size, bool maymove)
1204
0
{
1205
0
#ifdef HAVE_MREMAP
1206
0
  void *buf;
1207
0
  size_t pagesz = getpagesize();
1208
0
  size_t pagecnt;
1209
0
  size_t bufsz;
1210
0
  struct anonymous_shared_header *hdr;
1211
0
  int flags = 0;
1212
1213
0
  if (ptr == NULL) {
1214
0
    errno = EINVAL;
1215
0
    return NULL;
1216
0
  }
1217
1218
0
  hdr = (struct anonymous_shared_header *)ptr;
1219
0
  hdr--;
1220
0
  if (hdr->u.length > (new_size + sizeof(*hdr))) {
1221
0
    errno = EINVAL;
1222
0
    return NULL;
1223
0
  }
1224
1225
0
  bufsz = new_size + sizeof(*hdr);
1226
1227
  /* round up to full pages */
1228
0
  pagecnt = bufsz / pagesz;
1229
0
  if (bufsz % pagesz) {
1230
0
    pagecnt += 1;
1231
0
  }
1232
0
  bufsz = pagesz * pagecnt;
1233
1234
0
  if (new_size >= bufsz) {
1235
    /* integer wrap */
1236
0
    errno = ENOSPC;
1237
0
    return NULL;
1238
0
  }
1239
1240
0
  if (bufsz <= hdr->u.length) {
1241
0
    return ptr;
1242
0
  }
1243
1244
0
  if (maymove) {
1245
0
    flags = MREMAP_MAYMOVE;
1246
0
  }
1247
1248
0
  buf = mremap(hdr, hdr->u.length, bufsz, flags);
1249
1250
0
  if (buf == MAP_FAILED) {
1251
0
    errno = ENOSPC;
1252
0
    return NULL;
1253
0
  }
1254
1255
0
  hdr = (struct anonymous_shared_header *)buf;
1256
0
  hdr->u.length = bufsz;
1257
1258
0
  ptr = (void *)(&hdr[1]);
1259
1260
0
  return ptr;
1261
#else
1262
  errno = ENOSPC;
1263
  return NULL;
1264
#endif
1265
0
}
1266
1267
void anonymous_shared_free(void *ptr)
1268
0
{
1269
0
  struct anonymous_shared_header *hdr;
1270
1271
0
  if (ptr == NULL) {
1272
0
    return;
1273
0
  }
1274
1275
0
  hdr = (struct anonymous_shared_header *)ptr;
1276
1277
0
  hdr--;
1278
1279
0
  munmap(hdr, hdr->u.length);
1280
0
}
1281
1282
#ifdef DEVELOPER
1283
/* used when you want a debugger started at a particular point in the
1284
   code. Mostly useful in code that runs as a child process, where
1285
   normal gdb attach is harder to organise.
1286
*/
1287
void samba_start_debugger(void)
1288
0
{
1289
0
  int ready_pipe[2];
1290
0
  char c;
1291
0
  int ret;
1292
0
  pid_t pid;
1293
1294
0
  ret = pipe(ready_pipe);
1295
0
  SMB_ASSERT(ret == 0);
1296
1297
0
  pid = fork();
1298
0
  SMB_ASSERT(pid >= 0);
1299
1300
0
  if (pid) {
1301
0
    c = 0;
1302
1303
0
    ret = close(ready_pipe[0]);
1304
0
    SMB_ASSERT(ret == 0);
1305
0
#if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
1306
    /*
1307
     * Make sure the child process can attach a debugger.
1308
     *
1309
     * We don't check the error code as the debugger
1310
     * will tell us if it can't attach.
1311
     */
1312
0
    (void)prctl(PR_SET_PTRACER, pid, 0, 0, 0);
1313
0
#endif
1314
0
    ret = write(ready_pipe[1], &c, 1);
1315
0
    SMB_ASSERT(ret == 1);
1316
1317
0
    ret = close(ready_pipe[1]);
1318
0
    SMB_ASSERT(ret == 0);
1319
1320
    /* Wait for gdb to attach. */
1321
0
    sleep(2);
1322
0
  } else {
1323
0
    char *cmd = NULL;
1324
1325
0
    ret = close(ready_pipe[1]);
1326
0
    SMB_ASSERT(ret == 0);
1327
1328
0
    ret = read(ready_pipe[0], &c, 1);
1329
0
    SMB_ASSERT(ret == 1);
1330
1331
0
    ret = close(ready_pipe[0]);
1332
0
    SMB_ASSERT(ret == 0);
1333
1334
0
    ret = asprintf(&cmd, "gdb --pid %u", getppid());
1335
0
    SMB_ASSERT(ret != -1);
1336
1337
0
    execlp("xterm", "xterm", "-e", cmd, (char *) NULL);
1338
0
    smb_panic("execlp() failed");
1339
0
  }
1340
0
}
1341
#endif