Coverage Report

Created: 2026-04-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/lib/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-2007
6
   Copyright (C) Simo Sorce 2001
7
   Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8
   Copyright (C) James Peach 2006
9
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
15
   This program 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
18
   GNU General Public License for more details.
19
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
*/
23
24
/**
25
 * @brief  Small functions that don't fit anywhere else
26
 * @file   util.c
27
 */
28
29
#include "includes.h"
30
#include "system/passwd.h"
31
#include "system/filesys.h"
32
#include "lib/util/server_id.h"
33
#include "lib/util/memcache.h"
34
#include "util_tdb.h"
35
#include "ctdbd_conn.h"
36
#include "../lib/util/util_pw.h"
37
#include "messages.h"
38
#include "lib/messaging/messages_dgm.h"
39
#include "libcli/security/security.h"
40
#include "serverid.h"
41
#include "lib/util/sys_rw.h"
42
#include "lib/util/sys_rw_data.h"
43
#include "lib/util/util_process.h"
44
#include "lib/dbwrap/dbwrap_ctdb.h"
45
#include "lib/gencache.h"
46
#include "lib/util/string_wrappers.h"
47
#include "lib/util/strv.h"
48
49
#ifdef HAVE_SYS_PRCTL_H
50
#include <sys/prctl.h>
51
#endif
52
53
/* Max allowable allococation - 256mb - 0x10000000 */
54
0
#define MAX_ALLOC_SIZE (1024*1024*256)
55
56
static enum protocol_types Protocol = PROTOCOL_COREPLUS;
57
58
void set_Protocol(enum protocol_types  p)
59
0
{
60
0
  Protocol = p;
61
0
}
62
63
static enum remote_arch_types ra_type = RA_UNKNOWN;
64
65
void gfree_all( void )
66
0
{
67
0
  gfree_loadparm();
68
0
  gfree_charcnv();
69
0
  gfree_interfaces();
70
0
  gfree_debugsyms();
71
0
  gfree_memcache();
72
73
0
}
74
75
/*******************************************************************
76
 Check if a file exists - call vfs_file_exist for samba files.
77
********************************************************************/
78
79
bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf,
80
         bool fake_dir_create_times)
81
0
{
82
0
  SMB_STRUCT_STAT st;
83
0
  if (!sbuf)
84
0
    sbuf = &st;
85
86
0
  if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
87
0
    return(False);
88
89
0
  return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode)));
90
0
}
91
92
/*******************************************************************
93
 Check if a unix domain socket exists - call vfs_file_exist for samba files.
94
********************************************************************/
95
96
bool socket_exist(const char *fname)
97
0
{
98
0
  SMB_STRUCT_STAT st;
99
0
  if (sys_stat(fname, &st, false) != 0)
100
0
    return(False);
101
102
0
  return S_ISSOCK(st.st_ex_mode);
103
0
}
104
105
/*******************************************************************
106
 Returns the size in bytes of the named given the stat struct.
107
********************************************************************/
108
109
uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
110
0
{
111
0
  return sbuf->st_ex_size;
112
0
}
113
114
/****************************************************************************
115
 Check two stats have identical dev and ino fields.
116
****************************************************************************/
117
118
bool check_same_dev_ino(const SMB_STRUCT_STAT *sbuf1,
119
                        const SMB_STRUCT_STAT *sbuf2)
120
0
{
121
0
  return ((sbuf1->st_ex_dev == sbuf2->st_ex_dev) &&
122
0
    (sbuf1->st_ex_ino == sbuf2->st_ex_ino));
123
0
}
124
125
/****************************************************************************
126
 Check if a stat struct is identical for use.
127
****************************************************************************/
128
129
bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
130
         const SMB_STRUCT_STAT *sbuf2)
131
0
{
132
0
  return ((sbuf1->st_ex_uid == sbuf2->st_ex_uid) &&
133
0
    (sbuf1->st_ex_gid == sbuf2->st_ex_gid) &&
134
0
    check_same_dev_ino(sbuf1, sbuf2));
135
0
}
136
137
/*******************************************************************
138
 Show a smb message structure.
139
********************************************************************/
140
141
void show_msg(const char *buf)
142
0
{
143
0
  char *msg = NULL;
144
0
  int i;
145
0
  int bcc=0;
146
147
0
  if (!DEBUGLVL(5))
148
0
    return;
149
150
0
  msg = talloc_asprintf(
151
0
    talloc_tos(),
152
0
    "size=%d\nsmb_com=0x%x\nsmb_rcls=%d\n"
153
0
    "smb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n"
154
0
    "smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n"
155
0
    "smt_wct=%d\n",
156
0
    smb_len(buf),
157
0
    (int)CVAL(buf, smb_com),
158
0
    (int)CVAL(buf, smb_rcls),
159
0
    (int)CVAL(buf, smb_reh),
160
0
    (int)SVAL(buf, smb_err),
161
0
    (int)CVAL(buf, smb_flg),
162
0
    (int)SVAL(buf, smb_flg2),
163
0
    (int)SVAL(buf, smb_tid),
164
0
    (int)SVAL(buf, smb_pid),
165
0
    (int)SVAL(buf, smb_uid),
166
0
    (int)SVAL(buf, smb_mid),
167
0
    (int)CVAL(buf, smb_wct));
168
169
0
  for (i=0;i<(int)CVAL(buf,smb_wct);i++) {
170
0
    talloc_asprintf_addbuf(&msg,
171
0
               "smb_vwv[%2d]=%5d (0x%X)\n",
172
0
               i,
173
0
               SVAL(buf, smb_vwv + 2 * i),
174
0
               SVAL(buf, smb_vwv + 2 * i));
175
0
  }
176
177
0
  bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
178
179
0
  talloc_asprintf_addbuf(&msg, "smb_bcc=%d\n", bcc);
180
181
0
  if (DEBUGLEVEL >= 10) {
182
0
    if (DEBUGLEVEL < 50) {
183
0
      bcc = MIN(bcc, 512);
184
0
    }
185
0
    dump_data_addbuf((const uint8_t *)smb_buf_const(buf),
186
0
         bcc,
187
0
         &msg);
188
0
  }
189
190
0
  DEBUG(5, ("%s", msg));
191
0
  TALLOC_FREE(msg);
192
0
}
193
194
/*******************************************************************
195
 Setup only the byte count for a smb message.
196
********************************************************************/
197
198
int set_message_bcc(char *buf,int num_bytes)
199
0
{
200
0
  int num_words = CVAL(buf,smb_wct);
201
0
  SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
202
0
  _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
203
0
  return (smb_size + num_words*2 + num_bytes);
204
0
}
205
206
/*******************************************************************
207
 Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
208
 Return the bytes added
209
********************************************************************/
210
211
ssize_t message_push_blob(uint8_t **outbuf, DATA_BLOB blob)
212
0
{
213
0
  size_t newlen = smb_len(*outbuf) + 4 + blob.length;
214
0
  uint8_t *tmp;
215
216
0
  if (!(tmp = talloc_realloc(NULL, *outbuf, uint8_t, newlen))) {
217
0
    DEBUG(0, ("talloc failed\n"));
218
0
    return -1;
219
0
  }
220
0
  *outbuf = tmp;
221
222
0
  memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
223
0
  set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
224
0
  return blob.length;
225
0
}
226
227
/*******************************************************************
228
 Reduce a file name, removing .. elements.
229
********************************************************************/
230
231
static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
232
0
{
233
0
  char *p = NULL;
234
0
  char *str = NULL;
235
236
0
  DEBUG(3,("dos_clean_name [%s]\n",s));
237
238
  /* remove any double slashes */
239
0
  str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
240
0
  if (!str) {
241
0
    return NULL;
242
0
  }
243
244
  /* Remove leading .\\ characters */
245
0
  if(strncmp(str, ".\\", 2) == 0) {
246
0
    trim_string(str, ".\\", NULL);
247
0
    if(*str == 0) {
248
0
      str = talloc_strdup(ctx, ".\\");
249
0
      if (!str) {
250
0
        return NULL;
251
0
      }
252
0
    }
253
0
  }
254
255
0
  while ((p = strstr_m(str,"\\..\\")) != NULL) {
256
0
    char *s1;
257
258
0
    *p = 0;
259
0
    s1 = p+3;
260
261
0
    if ((p=strrchr_m(str,'\\')) != NULL) {
262
0
      *p = 0;
263
0
    } else {
264
0
      *str = 0;
265
0
    }
266
0
    str = talloc_asprintf(ctx,
267
0
        "%s%s",
268
0
        str,
269
0
        s1);
270
0
    if (!str) {
271
0
      return NULL;
272
0
    }
273
0
  }
274
275
0
  trim_string(str,NULL,"\\..");
276
0
  return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
277
0
}
278
279
/*******************************************************************
280
 Reduce a file name, removing .. elements.
281
********************************************************************/
282
283
char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
284
0
{
285
0
  char *p = NULL;
286
0
  char *str = NULL;
287
288
0
  DEBUG(3,("unix_clean_name [%s]\n",s));
289
290
  /* remove any double slashes */
291
0
  str = talloc_all_string_sub(ctx, s, "//","/");
292
0
  if (!str) {
293
0
    return NULL;
294
0
  }
295
296
  /* Remove leading ./ characters */
297
0
  if(strncmp(str, "./", 2) == 0) {
298
0
    trim_string(str, "./", NULL);
299
0
    if(*str == 0) {
300
0
      str = talloc_strdup(ctx, "./");
301
0
      if (!str) {
302
0
        return NULL;
303
0
      }
304
0
    }
305
0
  }
306
307
0
  while ((p = strstr_m(str,"/../")) != NULL) {
308
0
    char *s1;
309
310
0
    *p = 0;
311
0
    s1 = p+3;
312
313
0
    if ((p=strrchr_m(str,'/')) != NULL) {
314
0
      *p = 0;
315
0
    } else {
316
0
      *str = 0;
317
0
    }
318
0
    str = talloc_asprintf(ctx,
319
0
        "%s%s",
320
0
        str,
321
0
        s1);
322
0
    if (!str) {
323
0
      return NULL;
324
0
    }
325
0
  }
326
327
0
  trim_string(str,NULL,"/..");
328
0
  return talloc_all_string_sub(ctx, str, "/./", "/");
329
0
}
330
331
char *clean_name(TALLOC_CTX *ctx, const char *s)
332
0
{
333
0
  char *str = dos_clean_name(ctx, s);
334
0
  if (!str) {
335
0
    return NULL;
336
0
  }
337
0
  return unix_clean_name(ctx, str);
338
0
}
339
340
/*******************************************************************
341
 Write data into an fd at a given offset. Ignore seek errors.
342
********************************************************************/
343
344
ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, off_t pos)
345
0
{
346
0
  size_t total=0;
347
0
  ssize_t ret;
348
349
0
  if (pos == (off_t)-1) {
350
0
    return write_data(fd, buffer, N);
351
0
  }
352
0
#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
353
0
  while (total < N) {
354
0
    ret = sys_pwrite(fd,buffer + total,N - total, pos);
355
0
    if (ret == -1 && errno == ESPIPE) {
356
0
      return write_data(fd, buffer + total,N - total);
357
0
    }
358
0
    if (ret == -1) {
359
0
      DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
360
0
      return -1;
361
0
    }
362
0
    if (ret == 0) {
363
0
      return total;
364
0
    }
365
0
    total += ret;
366
0
    pos += ret;
367
0
  }
368
0
  return (ssize_t)total;
369
#else
370
  /* Use lseek and write_data. */
371
  if (lseek(fd, pos, SEEK_SET) == -1) {
372
    if (errno != ESPIPE) {
373
      return -1;
374
    }
375
  }
376
  return write_data(fd, buffer, N);
377
#endif
378
0
}
379
380
static int reinit_after_fork_pipe[2] = { -1, -1 };
381
382
NTSTATUS init_before_fork(void)
383
0
{
384
0
  int ret;
385
386
0
  ret = pipe(reinit_after_fork_pipe);
387
0
  if (ret == -1) {
388
0
    NTSTATUS status;
389
390
0
    status = map_nt_error_from_unix_common(errno);
391
392
0
    DEBUG(0, ("Error creating child_pipe: %s\n",
393
0
        nt_errstr(status)));
394
395
0
    return status;
396
0
  }
397
398
0
  return NT_STATUS_OK;
399
0
}
400
401
/**
402
 * @brief Get a fd to watch for our parent process to exit
403
 *
404
 * Samba parent processes open a pipe that naturally closes when the
405
 * parent exits. Child processes can watch the read end of the pipe
406
 * for readability: Readability with 0 bytes to read means the parent
407
 * has exited and the child process might also want to exit.
408
 */
409
410
int parent_watch_fd(void)
411
0
{
412
0
  return reinit_after_fork_pipe[0];
413
0
}
414
415
/**
416
 * Detect died parent by detecting EOF on the pipe
417
 */
418
static void reinit_after_fork_pipe_handler(struct tevent_context *ev,
419
             struct tevent_fd *fde,
420
             uint16_t flags,
421
             void *private_data)
422
0
{
423
0
  char c;
424
425
0
  if (sys_read(reinit_after_fork_pipe[0], &c, 1) != 1) {
426
    /*
427
     * we have reached EOF on stdin, which means the
428
     * parent has exited. Shutdown the server
429
     */
430
0
    TALLOC_FREE(fde);
431
0
    (void)kill(getpid(), SIGTERM);
432
0
  }
433
0
}
434
435
436
NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
437
         struct tevent_context *ev_ctx,
438
         bool parent_longlived)
439
0
{
440
0
  NTSTATUS status = NT_STATUS_OK;
441
0
  int ret;
442
443
  /*
444
   * The main process thread should never
445
   * allow per_thread_cwd_enable() to be
446
   * called.
447
   */
448
0
  per_thread_cwd_disable();
449
450
0
  if (reinit_after_fork_pipe[1] != -1) {
451
0
    close(reinit_after_fork_pipe[1]);
452
0
    reinit_after_fork_pipe[1] = -1;
453
0
  }
454
455
  /* tdb needs special fork handling */
456
0
  if (tdb_reopen_all(parent_longlived ? 1 : 0) != 0) {
457
0
    DEBUG(0,("tdb_reopen_all failed.\n"));
458
0
    status = NT_STATUS_OPEN_FAILED;
459
0
    goto done;
460
0
  }
461
462
0
  if (ev_ctx != NULL) {
463
    /*
464
     * The parent can have different private data for the callbacks,
465
     * which are gone in the child. Reset the callbacks to be safe.
466
     */
467
0
    tevent_set_trace_callback(ev_ctx, NULL, NULL);
468
0
    tevent_set_trace_fd_callback(ev_ctx, NULL, NULL);
469
0
    tevent_set_trace_signal_callback(ev_ctx, NULL, NULL);
470
0
    tevent_set_trace_timer_callback(ev_ctx, NULL, NULL);
471
0
    tevent_set_trace_immediate_callback(ev_ctx, NULL, NULL);
472
0
    tevent_set_trace_queue_callback(ev_ctx, NULL, NULL);
473
0
    if (tevent_re_initialise(ev_ctx) != 0) {
474
0
      smb_panic(__location__ ": Failed to re-initialise event context");
475
0
    }
476
0
  }
477
478
0
  if (reinit_after_fork_pipe[0] != -1) {
479
0
    struct tevent_fd *fde;
480
481
0
    fde = tevent_add_fd(ev_ctx, ev_ctx /* TALLOC_CTX */,
482
0
            reinit_after_fork_pipe[0], TEVENT_FD_READ,
483
0
            reinit_after_fork_pipe_handler, NULL);
484
0
    if (fde == NULL) {
485
0
      smb_panic(__location__ ": Failed to add reinit_after_fork pipe event");
486
0
    }
487
0
  }
488
489
0
  if (msg_ctx) {
490
    /*
491
     * For clustering, we need to re-init our ctdbd connection after the
492
     * fork
493
     */
494
0
    status = messaging_reinit(msg_ctx);
495
0
    if (!NT_STATUS_IS_OK(status)) {
496
0
      DEBUG(0,("messaging_reinit() failed: %s\n",
497
0
         nt_errstr(status)));
498
0
      goto done;
499
0
    }
500
501
0
    if (lp_clustering()) {
502
0
      ret = ctdb_async_ctx_reinit(
503
0
        NULL, messaging_tevent_context(msg_ctx));
504
0
      if (ret != 0) {
505
0
        DBG_ERR("db_ctdb_async_ctx_reinit failed: %s\n",
506
0
          strerror(errno));
507
0
        return map_nt_error_from_unix(ret);
508
0
      }
509
0
    }
510
0
  }
511
512
0
 done:
513
0
  return status;
514
0
}
515
516
/****************************************************************************
517
 (Hopefully) efficient array append.
518
****************************************************************************/
519
520
void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
521
      void *element, void *_array, uint32_t *num_elements,
522
      ssize_t *array_size)
523
0
{
524
0
  void **array = (void **)_array;
525
526
0
  if (*array_size < 0) {
527
0
    return;
528
0
  }
529
530
0
  if (*array == NULL) {
531
0
    if (*array_size == 0) {
532
0
      *array_size = 128;
533
0
    }
534
535
0
    if (*array_size >= MAX_ALLOC_SIZE/element_size) {
536
0
      goto error;
537
0
    }
538
539
0
    *array = talloc_size(mem_ctx, element_size * (*array_size));
540
0
    if (*array == NULL) {
541
0
      goto error;
542
0
    }
543
0
  }
544
545
0
  if (*num_elements == *array_size) {
546
0
    *array_size *= 2;
547
548
0
    if (*array_size >= MAX_ALLOC_SIZE/element_size) {
549
0
      goto error;
550
0
    }
551
552
0
    *array = talloc_realloc_size(mem_ctx,
553
0
               *array,
554
0
               element_size * (*array_size));
555
556
0
    if (*array == NULL) {
557
0
      goto error;
558
0
    }
559
0
  }
560
561
0
  memcpy((char *)(*array) + element_size*(*num_elements),
562
0
         element, element_size);
563
0
  *num_elements += 1;
564
565
0
  return;
566
567
0
 error:
568
0
  *num_elements = 0;
569
0
  *array_size = -1;
570
0
}
571
572
/****************************************************************************
573
 Get my own domain name, or "" if we have none.
574
****************************************************************************/
575
576
char *get_mydnsdomname(TALLOC_CTX *ctx)
577
0
{
578
0
  const char *domname;
579
0
  char *p;
580
581
0
  domname = get_mydnsfullname();
582
0
  if (!domname) {
583
0
    return NULL;
584
0
  }
585
586
0
  p = strchr_m(domname, '.');
587
0
  if (p) {
588
0
    p++;
589
0
    return talloc_strdup(ctx, p);
590
0
  } else {
591
0
    return talloc_strdup(ctx, "");
592
0
  }
593
0
}
594
595
bool process_exists(const struct server_id pid)
596
0
{
597
0
  return serverid_exists(&pid);
598
0
}
599
600
/*******************************************************************
601
 Convert a uid into a user name.
602
********************************************************************/
603
604
const char *uidtoname(uid_t uid)
605
0
{
606
0
  TALLOC_CTX *ctx = talloc_tos();
607
0
  char *name = NULL;
608
0
  struct passwd *pass = NULL;
609
610
0
  pass = getpwuid_alloc(ctx,uid);
611
0
  if (pass) {
612
0
    name = talloc_strdup(ctx,pass->pw_name);
613
0
    TALLOC_FREE(pass);
614
0
  } else {
615
0
    name = talloc_asprintf(ctx,
616
0
        "%ld",
617
0
        (long int)uid);
618
0
  }
619
0
  return name;
620
0
}
621
622
/*******************************************************************
623
 Convert a gid into a group name.
624
********************************************************************/
625
626
char *gidtoname(gid_t gid)
627
0
{
628
0
  struct group *grp;
629
630
0
  grp = getgrgid(gid);
631
0
  if (grp) {
632
0
    return talloc_strdup(talloc_tos(), grp->gr_name);
633
0
  }
634
0
  else {
635
0
    return talloc_asprintf(talloc_tos(),
636
0
          "%d",
637
0
          (int)gid);
638
0
  }
639
0
}
640
641
/*******************************************************************
642
 Convert a user name into a uid.
643
********************************************************************/
644
645
uid_t nametouid(const char *name)
646
0
{
647
0
  struct passwd *pass;
648
0
  char *p;
649
0
  uid_t u;
650
651
0
  pass = Get_Pwnam_alloc(talloc_tos(), name);
652
0
  if (pass) {
653
0
    u = pass->pw_uid;
654
0
    TALLOC_FREE(pass);
655
0
    return u;
656
0
  }
657
658
0
  u = (uid_t)strtol(name, &p, 0);
659
0
  if ((p != name) && (*p == '\0'))
660
0
    return u;
661
662
0
  return (uid_t)-1;
663
0
}
664
665
/*******************************************************************
666
 Convert a name to a gid_t if possible. Return -1 if not a group.
667
********************************************************************/
668
669
gid_t nametogid(const char *name)
670
0
{
671
0
  struct group *grp;
672
0
  char *p;
673
0
  gid_t g;
674
675
0
  g = (gid_t)strtol(name, &p, 0);
676
0
  if ((p != name) && (*p == '\0'))
677
0
    return g;
678
679
0
  grp = getgrnam(name);
680
0
  if (grp)
681
0
    return(grp->gr_gid);
682
0
  return (gid_t)-1;
683
0
}
684
685
/*******************************************************************
686
 Something really nasty happened - panic !
687
********************************************************************/
688
689
static void call_panic_action(const char *why, bool as_root)
690
0
{
691
0
  const struct loadparm_substitution *lp_sub =
692
0
    loadparm_s3_global_substitution();
693
0
  char *cmd;
694
0
  int result;
695
696
0
  cmd = lp_panic_action(talloc_tos(), lp_sub);
697
0
  if (cmd == NULL || cmd[0] == '\0') {
698
0
    return;
699
0
  }
700
701
0
  DBG_ERR("Calling panic action [%s]\n", cmd);
702
703
0
#if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
704
  /*
705
   * Make sure all children can attach a debugger.
706
   */
707
0
  prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
708
0
#endif
709
710
0
  if (as_root) {
711
0
    become_root();
712
0
  }
713
714
0
  result = system(cmd);
715
716
0
  if (as_root) {
717
0
    unbecome_root();
718
0
  }
719
720
0
  if (result == -1)
721
0
    DBG_ERR("fork failed in panic action: %s\n",
722
0
      strerror(errno));
723
0
  else
724
0
    DBG_ERR("action returned status %d\n",
725
0
      WEXITSTATUS(result));
726
0
}
727
728
void smb_panic_s3(const char *why)
729
0
{
730
0
  call_panic_action(why, false);
731
0
  dump_core();
732
0
}
733
734
void log_panic_action(const char *msg)
735
0
{
736
0
  DBG_ERR("%s", msg);
737
0
  call_panic_action(msg, true);
738
0
}
739
740
/*******************************************************************
741
  A readdir wrapper which just returns the file name.
742
 ********************************************************************/
743
744
const char *readdirname(DIR *p)
745
0
{
746
0
  struct dirent *ptr;
747
0
  char *dname;
748
749
0
  if (!p)
750
0
    return(NULL);
751
752
0
  ptr = (struct dirent *)readdir(p);
753
0
  if (!ptr)
754
0
    return(NULL);
755
756
0
  dname = ptr->d_name;
757
758
0
  return talloc_strdup(talloc_tos(), dname);
759
0
}
760
761
/*******************************************************************
762
 Utility function used to decide if the last component
763
 of a path matches a (possibly wildcarded) entry in a namelist.
764
********************************************************************/
765
766
bool is_in_path(const char *name,
767
    struct name_compare_entry *namelist,
768
    bool case_sensitive)
769
0
{
770
0
  const char *last_component;
771
772
  /* if we have no list it's obviously not in the path */
773
0
  if ((namelist == NULL) || (namelist[0].name == NULL)) {
774
0
    return False;
775
0
  }
776
777
  /* Do not reject path components if namelist is set to '.*' */
778
0
  if (ISDOT(name) || ISDOTDOT(name)) {
779
0
    return false;
780
0
  }
781
782
0
  DEBUG(8, ("is_in_path: %s\n", name));
783
784
  /* Get the last component of the unix name. */
785
0
  last_component = strrchr_m(name, '/');
786
0
  if (!last_component) {
787
0
    last_component = name;
788
0
  } else {
789
0
    last_component++; /* Go past '/' */
790
0
  }
791
792
0
  for(; namelist->name != NULL; namelist++) {
793
0
    if(namelist->is_wild) {
794
0
      if (mask_match(last_component, namelist->name, case_sensitive)) {
795
0
        DEBUG(8,("is_in_path: mask match succeeded\n"));
796
0
        return True;
797
0
      }
798
0
    } else {
799
0
      if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
800
0
            (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) {
801
0
        DEBUG(8,("is_in_path: match succeeded\n"));
802
0
        return True;
803
0
      }
804
0
    }
805
0
  }
806
0
  DEBUG(8,("is_in_path: match not found\n"));
807
0
  return False;
808
0
}
809
810
#undef DBGC_CLASS
811
0
#define DBGC_CLASS DBGC_LOCKING
812
813
/****************************************************************************
814
 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
815
 is dealt with in posix.c
816
 Returns True if we have information regarding this lock region (and returns
817
 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
818
****************************************************************************/
819
820
bool fcntl_getlock(int fd, int op, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
821
0
{
822
0
  struct flock lock;
823
0
  int ret;
824
825
0
  DEBUG(8,("fcntl_getlock fd=%d op=%d offset=%.0f count=%.0f type=%d\n",
826
0
        fd,op,(double)*poffset,(double)*pcount,*ptype));
827
828
0
  lock.l_type = *ptype;
829
0
  lock.l_whence = SEEK_SET;
830
0
  lock.l_start = *poffset;
831
0
  lock.l_len = *pcount;
832
0
  lock.l_pid = 0;
833
834
0
  ret = sys_fcntl_ptr(fd,op,&lock);
835
836
0
  if (ret == -1) {
837
0
    int saved_errno = errno;
838
0
    DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
839
0
      (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
840
0
    errno = saved_errno;
841
0
    return False;
842
0
  }
843
844
0
  *ptype = lock.l_type;
845
0
  *poffset = lock.l_start;
846
0
  *pcount = lock.l_len;
847
0
  *ppid = lock.l_pid;
848
849
0
  DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
850
0
      fd, (int)lock.l_type, (unsigned int)lock.l_pid));
851
0
  return True;
852
0
}
853
854
#if defined(HAVE_OFD_LOCKS)
855
int map_process_lock_to_ofd_lock(int op)
856
0
{
857
0
  switch (op) {
858
0
  case F_GETLK:
859
0
  case F_OFD_GETLK:
860
0
    op = F_OFD_GETLK;
861
0
    break;
862
0
  case F_SETLK:
863
0
  case F_OFD_SETLK:
864
0
    op = F_OFD_SETLK;
865
0
    break;
866
0
  case F_SETLKW:
867
0
  case F_OFD_SETLKW:
868
0
    op = F_OFD_SETLKW;
869
0
    break;
870
0
  default:
871
0
    return -1;
872
0
  }
873
0
  return op;
874
0
}
875
#else /* HAVE_OFD_LOCKS */
876
int map_process_lock_to_ofd_lock(int op)
877
{
878
  return op;
879
}
880
#endif /* HAVE_OFD_LOCKS */
881
882
#undef DBGC_CLASS
883
0
#define DBGC_CLASS DBGC_ALL
884
885
/*******************************************************************
886
 Is the name specified one of my netbios names.
887
 Returns true if it is equal, false otherwise.
888
********************************************************************/
889
890
static bool nb_name_equal(const char *s1, const char *s2)
891
0
{
892
0
  int cmp = strncasecmp_m(s1, s2, MAX_NETBIOSNAME_LEN-1);
893
0
  return (cmp == 0);
894
0
}
895
896
bool is_myname(const char *s)
897
0
{
898
0
  const char **aliases = NULL;
899
0
  bool ok = false;
900
901
0
  ok = nb_name_equal(lp_netbios_name(), s);
902
0
  if (ok) {
903
0
    goto done;
904
0
  }
905
906
0
  aliases = lp_netbios_aliases();
907
0
  if (aliases == NULL) {
908
0
    goto done;
909
0
  }
910
911
0
  while (*aliases != NULL) {
912
0
    ok = nb_name_equal(*aliases, s);
913
0
    if (ok) {
914
0
      goto done;
915
0
    }
916
0
    aliases += 1;
917
0
  }
918
919
0
done:
920
0
  DBG_DEBUG("is_myname(\"%s\") returns %d\n", s, (int)ok);
921
0
  return ok;
922
0
}
923
924
/*******************************************************************
925
 we distinguish between 2K and XP by the "Native Lan Manager" string
926
   WinXP => "Windows 2002 5.1"
927
   WinXP 64bit => "Windows XP 5.2"
928
   Win2k => "Windows 2000 5.0"
929
   NT4   => "Windows NT 4.0"
930
   Win9x => "Windows 4.0"
931
 Windows 2003 doesn't set the native lan manager string but
932
 they do set the domain to "Windows 2003 5.2" (probably a bug).
933
********************************************************************/
934
935
void ra_lanman_string( const char *native_lanman )
936
0
{
937
0
  if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
938
0
    set_remote_arch( RA_WINXP );
939
0
  else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
940
0
    set_remote_arch( RA_WINXP64 );
941
0
  else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
942
0
    set_remote_arch( RA_WIN2K3 );
943
0
}
944
945
static const char *remote_arch_strings[] = {
946
  [RA_UNKNOWN] =  "UNKNOWN",
947
  [RA_WFWG] = "WfWg",
948
  [RA_OS2] =  "OS2",
949
  [RA_WIN95] =  "Win95",
950
  [RA_WINNT] =  "WinNT",
951
  [RA_WIN2K] =  "Win2K",
952
  [RA_WINXP] =  "WinXP",
953
  [RA_WIN2K3] = "Win2K3",
954
  [RA_VISTA] =  "Vista",
955
  [RA_SAMBA] =  "Samba",
956
  [RA_CIFSFS] = "CIFSFS",
957
  [RA_WINXP64] =  "WinXP64",
958
  [RA_OSX] =  "OSX",
959
};
960
961
const char *get_remote_arch_str(void)
962
0
{
963
0
  if (ra_type >= ARRAY_SIZE(remote_arch_strings)) {
964
    /*
965
     * set_remote_arch() already checks this so ra_type
966
     * should be in the allowed range, but anyway, let's
967
     * do another bound check here.
968
     */
969
0
    DBG_ERR("Remote arch info out of sync [%d] missing\n", ra_type);
970
0
    ra_type = RA_UNKNOWN;
971
0
  }
972
0
  return remote_arch_strings[ra_type];
973
0
}
974
975
enum remote_arch_types get_remote_arch_from_str(const char *remote_arch_string)
976
0
{
977
0
  size_t i;
978
979
0
  for (i = 0; i < ARRAY_SIZE(remote_arch_strings); i++) {
980
0
    if (strcmp(remote_arch_string, remote_arch_strings[i]) == 0) {
981
0
      return i;
982
0
    }
983
0
  }
984
0
  return RA_UNKNOWN;
985
0
}
986
987
/*******************************************************************
988
 Set the horrid remote_arch string based on an enum.
989
********************************************************************/
990
991
void set_remote_arch(enum remote_arch_types type)
992
0
{
993
0
  if (ra_type >= ARRAY_SIZE(remote_arch_strings)) {
994
    /*
995
     * This protects against someone adding values to enum
996
     * remote_arch_types without updating
997
     * remote_arch_strings array.
998
     */
999
0
    DBG_ERR("Remote arch info out of sync [%d] missing\n", ra_type);
1000
0
    ra_type = RA_UNKNOWN;
1001
0
    return;
1002
0
  }
1003
1004
0
  ra_type = type;
1005
0
  DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1006
0
      get_remote_arch_str()));
1007
0
}
1008
1009
/*******************************************************************
1010
 Get the remote_arch type.
1011
********************************************************************/
1012
1013
enum remote_arch_types get_remote_arch(void)
1014
0
{
1015
0
  return ra_type;
1016
0
}
1017
1018
0
#define RA_CACHE_TTL 7*24*3600
1019
1020
static bool remote_arch_cache_key(const struct GUID *client_guid,
1021
          fstring key)
1022
0
{
1023
0
  struct GUID_txt_buf guid_buf;
1024
0
  const char *guid_string = NULL;
1025
1026
0
  guid_string = GUID_buf_string(client_guid, &guid_buf);
1027
0
  if (guid_string == NULL) {
1028
0
    return false;
1029
0
  }
1030
1031
0
  fstr_sprintf(key, "RA/%s", guid_string);
1032
0
  return true;
1033
0
}
1034
1035
struct ra_parser_state {
1036
  bool found;
1037
  enum remote_arch_types ra;
1038
};
1039
1040
static void ra_parser(const struct gencache_timeout *t,
1041
          DATA_BLOB blob,
1042
          void *priv_data)
1043
0
{
1044
0
  struct ra_parser_state *state = (struct ra_parser_state *)priv_data;
1045
0
  const char *ra_str = NULL;
1046
1047
0
  if (gencache_timeout_expired(t)) {
1048
0
    return;
1049
0
  }
1050
1051
0
  if ((blob.length == 0) || (blob.data[blob.length-1] != '\0')) {
1052
0
    DBG_ERR("Remote arch cache key not a string\n");
1053
0
    return;
1054
0
  }
1055
1056
0
  ra_str = (const char *)blob.data;
1057
0
  DBG_INFO("Got remote arch [%s] from cache\n", ra_str);
1058
1059
0
  state->ra = get_remote_arch_from_str(ra_str);
1060
0
  state->found = true;
1061
0
  return;
1062
0
}
1063
1064
static bool remote_arch_cache_get(const struct GUID *client_guid)
1065
0
{
1066
0
  bool ok;
1067
0
  fstring ra_key;
1068
0
  struct ra_parser_state state = (struct ra_parser_state) {
1069
0
    .found = false,
1070
0
    .ra = RA_UNKNOWN,
1071
0
  };
1072
1073
0
  ok = remote_arch_cache_key(client_guid, ra_key);
1074
0
  if (!ok) {
1075
0
    return false;
1076
0
  }
1077
1078
0
  ok = gencache_parse(ra_key, ra_parser, &state);
1079
0
  if (!ok || !state.found) {
1080
0
    return true;
1081
0
  }
1082
1083
0
  if (state.ra == RA_UNKNOWN) {
1084
0
    return true;
1085
0
  }
1086
1087
0
  set_remote_arch(state.ra);
1088
0
  return true;
1089
0
}
1090
1091
static bool remote_arch_cache_set(const struct GUID *client_guid)
1092
0
{
1093
0
  bool ok;
1094
0
  fstring ra_key;
1095
0
  const char *ra_str = NULL;
1096
1097
0
  if (get_remote_arch() == RA_UNKNOWN) {
1098
0
    return true;
1099
0
  }
1100
1101
0
  ok = remote_arch_cache_key(client_guid, ra_key);
1102
0
  if (!ok) {
1103
0
    return false;
1104
0
  }
1105
1106
0
  ra_str = get_remote_arch_str();
1107
0
  if (ra_str == NULL) {
1108
0
    return false;
1109
0
  }
1110
1111
0
  ok = gencache_set(ra_key, ra_str, time(NULL) + RA_CACHE_TTL);
1112
0
  if (!ok) {
1113
0
    return false;
1114
0
  }
1115
1116
0
  return true;
1117
0
}
1118
1119
bool remote_arch_cache_update(const struct GUID *client_guid)
1120
0
{
1121
0
  bool ok;
1122
1123
0
  if (get_remote_arch() == RA_UNKNOWN) {
1124
1125
0
    become_root();
1126
0
    ok = remote_arch_cache_get(client_guid);
1127
0
    unbecome_root();
1128
1129
0
    return ok;
1130
0
  }
1131
1132
0
  become_root();
1133
0
  ok = remote_arch_cache_set(client_guid);
1134
0
  unbecome_root();
1135
1136
0
  return ok;
1137
0
}
1138
1139
bool remote_arch_cache_delete(const struct GUID *client_guid)
1140
0
{
1141
0
  bool ok;
1142
0
  fstring ra_key;
1143
1144
0
  ok = remote_arch_cache_key(client_guid, ra_key);
1145
0
  if (!ok) {
1146
0
    return false;
1147
0
  }
1148
1149
0
  become_root();
1150
0
  ok = gencache_del(ra_key);
1151
0
  unbecome_root();
1152
1153
0
  if (!ok) {
1154
0
    return false;
1155
0
  }
1156
1157
0
  return true;
1158
0
}
1159
1160
1161
/*****************************************************************************
1162
 Provide a checksum on a string
1163
1164
 Input:  s - the null-terminated character string for which the checksum
1165
             will be calculated.
1166
1167
  Output: The checksum value calculated for s.
1168
*****************************************************************************/
1169
1170
int str_checksum(const char *s)
1171
0
{
1172
0
  TDB_DATA key;
1173
0
  if (s == NULL)
1174
0
    return 0;
1175
1176
0
  key = (TDB_DATA) { .dptr = discard_const_p(uint8_t, s),
1177
0
         .dsize = strlen(s) };
1178
1179
0
  return tdb_jenkins_hash(&key);
1180
0
}
1181
1182
/*****************************************************************
1183
 Zero a memory area then free it. Used to catch bugs faster.
1184
*****************************************************************/
1185
1186
void zero_free(void *p, size_t size)
1187
0
{
1188
0
  memset(p, 0, size);
1189
0
  SAFE_FREE(p);
1190
0
}
1191
1192
/*****************************************************************
1193
 Set our open file limit to a requested max and return the limit.
1194
*****************************************************************/
1195
1196
int set_maxfiles(int requested_max)
1197
0
{
1198
0
#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1199
0
  struct rlimit rlp;
1200
0
  int saved_current_limit;
1201
1202
0
  if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1203
0
    DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1204
0
      strerror(errno) ));
1205
    /* just guess... */
1206
0
    return requested_max;
1207
0
  }
1208
1209
  /*
1210
   * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1211
   * account for the extra fd we need
1212
   * as well as the log files and standard
1213
   * handles etc. Save the limit we want to set in case
1214
   * we are running on an OS that doesn't support this limit (AIX)
1215
   * which always returns RLIM_INFINITY for rlp.rlim_max.
1216
   */
1217
1218
  /* Try raising the hard (max) limit to the requested amount. */
1219
1220
0
#if defined(RLIM_INFINITY)
1221
0
  if (rlp.rlim_max != RLIM_INFINITY) {
1222
0
    int orig_max = rlp.rlim_max;
1223
1224
0
    if ( rlp.rlim_max < requested_max )
1225
0
      rlp.rlim_max = requested_max;
1226
1227
    /* This failing is not an error - many systems (Linux) don't
1228
      support our default request of 10,000 open files. JRA. */
1229
1230
0
    if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1231
0
      DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1232
0
        (int)rlp.rlim_max, strerror(errno) ));
1233
1234
      /* Set failed - restore original value from get. */
1235
0
      rlp.rlim_max = orig_max;
1236
0
    }
1237
0
  }
1238
0
#endif
1239
1240
  /* Now try setting the soft (current) limit. */
1241
1242
0
  saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1243
1244
0
  if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1245
0
    DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1246
0
      (int)rlp.rlim_cur, strerror(errno) ));
1247
    /* just guess... */
1248
0
    return saved_current_limit;
1249
0
  }
1250
1251
0
  if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1252
0
    DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1253
0
      strerror(errno) ));
1254
    /* just guess... */
1255
0
    return saved_current_limit;
1256
0
    }
1257
1258
0
#if defined(RLIM_INFINITY)
1259
0
  if(rlp.rlim_cur == RLIM_INFINITY)
1260
0
    return saved_current_limit;
1261
0
#endif
1262
1263
0
  if((int)rlp.rlim_cur > saved_current_limit)
1264
0
    return saved_current_limit;
1265
1266
0
  return rlp.rlim_cur;
1267
#else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1268
  /*
1269
   * No way to know - just guess...
1270
   */
1271
  return requested_max;
1272
#endif
1273
0
}
1274
1275
/*****************************************************************
1276
 malloc that aborts with smb_panic on fail or zero size.
1277
 *****************************************************************/
1278
1279
void *smb_xmalloc_array(size_t size, unsigned int count)
1280
0
{
1281
0
  void *p;
1282
0
  if (size == 0) {
1283
0
    smb_panic("smb_xmalloc_array: called with zero size");
1284
0
  }
1285
0
        if (count >= MAX_ALLOC_SIZE/size) {
1286
0
                smb_panic("smb_xmalloc_array: alloc size too large");
1287
0
        }
1288
0
  if ((p = SMB_MALLOC(size*count)) == NULL) {
1289
0
    DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1290
0
      (unsigned long)size, (unsigned long)count));
1291
0
    smb_panic("smb_xmalloc_array: malloc failed");
1292
0
  }
1293
0
  return p;
1294
0
}
1295
1296
/*****************************************************************
1297
 Get local hostname and cache result.
1298
*****************************************************************/
1299
1300
char *myhostname(void)
1301
0
{
1302
0
  static char *ret;
1303
0
  if (ret == NULL) {
1304
0
    ret = get_myname(NULL);
1305
0
  }
1306
0
  return ret;
1307
0
}
1308
1309
/*****************************************************************
1310
 Get local hostname and cache result.
1311
*****************************************************************/
1312
1313
char *myhostname_upper(void)
1314
0
{
1315
0
  static char *ret;
1316
0
  if (ret == NULL) {
1317
0
    char *name = get_myname(NULL);
1318
0
    if (name == NULL) {
1319
0
      return NULL;
1320
0
    }
1321
0
    ret = strupper_talloc(NULL, name);
1322
0
    talloc_free(name);
1323
0
  }
1324
0
  return ret;
1325
0
}
1326
1327
/*******************************************************************
1328
 Given a filename - get its directory name
1329
********************************************************************/
1330
1331
bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1332
        const char **name)
1333
0
{
1334
0
  char *p;
1335
0
  ptrdiff_t len;
1336
1337
0
  p = strrchr_m(dir, '/'); /* Find final '/', if any */
1338
1339
0
  if (p == NULL) {
1340
0
    if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1341
0
      return False;
1342
0
    }
1343
0
    if (name) {
1344
0
      *name = dir;
1345
0
    }
1346
0
    return True;
1347
0
  }
1348
1349
0
  len = p-dir;
1350
1351
0
  *parent = talloc_strndup(mem_ctx, dir, len);
1352
0
  if (*parent == NULL) {
1353
0
    return False;
1354
0
  }
1355
1356
0
  if (name) {
1357
0
    *name = p+1;
1358
0
  }
1359
0
  return True;
1360
0
}
1361
1362
/*******************************************************************
1363
 Determine if a pattern contains any Microsoft wildcard characters.
1364
*******************************************************************/
1365
1366
bool ms_has_wild(const char *s)
1367
0
{
1368
0
  const char *found = strpbrk(s, "*?<>\"");
1369
0
  return (found != NULL);
1370
0
}
1371
1372
bool ms_has_wild_w(const smb_ucs2_t *s)
1373
0
{
1374
0
  smb_ucs2_t c;
1375
0
  if (!s) return False;
1376
0
  while ((c = *s++)) {
1377
0
    switch (c) {
1378
0
    case UCS2_CHAR('*'):
1379
0
    case UCS2_CHAR('?'):
1380
0
    case UCS2_CHAR('<'):
1381
0
    case UCS2_CHAR('>'):
1382
0
    case UCS2_CHAR('"'):
1383
0
      return True;
1384
0
    }
1385
0
  }
1386
0
  return False;
1387
0
}
1388
1389
/*******************************************************************
1390
 A wrapper that handles case sensitivity and the special handling
1391
 of the ".." name.
1392
*******************************************************************/
1393
1394
bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1395
0
{
1396
0
  if (ISDOTDOT(string))
1397
0
    string = ".";
1398
0
  if (ISDOT(pattern))
1399
0
    return False;
1400
1401
0
  return ms_fnmatch_protocol(pattern, string, Protocol, is_case_sensitive) == 0;
1402
0
}
1403
1404
/*******************************************************************
1405
 A wrapper that handles a list of patterns and calls mask_match()
1406
 on each.  Returns True if any of the patterns match.
1407
*******************************************************************/
1408
1409
bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1410
0
{
1411
0
       while (listLen-- > 0) {
1412
0
               if (mask_match(string, *list++, is_case_sensitive))
1413
0
                       return True;
1414
0
       }
1415
0
       return False;
1416
0
}
1417
1418
struct server_id interpret_pid(const char *pid_string)
1419
0
{
1420
0
  return server_id_from_string(get_my_vnn(), pid_string);
1421
0
}
1422
1423
/****************************************************************
1424
 Check if an offset into a buffer is safe.
1425
 If this returns True it's safe to indirect into the byte at
1426
 pointer ptr+off.
1427
****************************************************************/
1428
1429
bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
1430
0
{
1431
0
  const char *end_base = buf_base + buf_len;
1432
0
  char *end_ptr = ptr + off;
1433
1434
0
  if (!buf_base || !ptr) {
1435
0
    return False;
1436
0
  }
1437
1438
0
  if (end_base < buf_base || end_ptr < ptr) {
1439
0
    return False; /* wrap. */
1440
0
  }
1441
1442
0
  if (end_ptr < end_base) {
1443
0
    return True;
1444
0
  }
1445
0
  return False;
1446
0
}
1447
1448
/****************************************************************
1449
 Return a safe pointer into a string within a buffer, or NULL.
1450
****************************************************************/
1451
1452
char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
1453
0
{
1454
0
  if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
1455
0
    return NULL;
1456
0
  }
1457
  /* Check if a valid string exists at this offset. */
1458
0
  if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
1459
0
    return NULL;
1460
0
  }
1461
0
  return ptr + off;
1462
0
}
1463
1464
1465
/****************************************************************
1466
 Split DOM\user into DOM and user. Do not mix with winbind variants of that
1467
 call (they take care of winbind separator and other winbind specific settings).
1468
****************************************************************/
1469
1470
bool split_domain_user(TALLOC_CTX *mem_ctx,
1471
           const char *full_name,
1472
           char **domain,
1473
           char **user)
1474
0
{
1475
0
  const char *p = NULL;
1476
1477
0
  p = strchr_m(full_name, '\\');
1478
1479
0
  if (p != NULL) {
1480
0
    *domain = talloc_strndup(mem_ctx, full_name,
1481
0
           PTR_DIFF(p, full_name));
1482
0
    if (*domain == NULL) {
1483
0
      return false;
1484
0
    }
1485
0
    *user = talloc_strdup(mem_ctx, p+1);
1486
0
    if (*user == NULL) {
1487
0
      TALLOC_FREE(*domain);
1488
0
      return false;
1489
0
    }
1490
0
  } else {
1491
0
    *domain = NULL;
1492
0
    *user = talloc_strdup(mem_ctx, full_name);
1493
0
    if (*user == NULL) {
1494
0
      return false;
1495
0
    }
1496
0
  }
1497
1498
0
  return true;
1499
0
}
1500
1501
/****************************************************************
1502
 strip off leading '\\' from a hostname
1503
****************************************************************/
1504
1505
const char *strip_hostname(const char *s)
1506
0
{
1507
0
  if (!s) {
1508
0
    return NULL;
1509
0
  }
1510
1511
0
  if (strlen_m(s) < 3) {
1512
0
    return s;
1513
0
  }
1514
1515
0
  if (s[0] == '\\') s++;
1516
0
  if (s[0] == '\\') s++;
1517
1518
0
  return s;
1519
0
}
1520
1521
bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
1522
0
{
1523
0
  if (!NT_STATUS_IS_OK(err1)) {
1524
0
    *result = err1;
1525
0
    return true;
1526
0
  }
1527
0
  if (!NT_STATUS_IS_OK(err2)) {
1528
0
    *result = err2;
1529
0
    return true;
1530
0
  }
1531
0
  return false;
1532
0
}
1533
1534
/*******************************************************************
1535
 Return True if the filename is one of the special executable types.
1536
********************************************************************/
1537
1538
bool is_executable(const char *fname)
1539
0
{
1540
0
  if ((fname = strrchr_m(fname,'.'))) {
1541
0
    if (strequal(fname,".com") ||
1542
0
        strequal(fname,".dll") ||
1543
0
        strequal(fname,".exe") ||
1544
0
        strequal(fname,".sym")) {
1545
0
      return True;
1546
0
    }
1547
0
  }
1548
0
  return False;
1549
0
}
1550
1551
/****************************************************************************
1552
 Open a file with a share mode - old openX method - map into NTCreate.
1553
****************************************************************************/
1554
1555
bool map_open_params_to_ntcreate(const char *smb_base_fname,
1556
         int deny_mode, int open_func,
1557
         uint32_t *paccess_mask,
1558
         uint32_t *pshare_mode,
1559
         uint32_t *pcreate_disposition,
1560
         uint32_t *pcreate_options,
1561
         uint32_t *pprivate_flags)
1562
0
{
1563
0
  uint32_t access_mask;
1564
0
  uint32_t share_mode;
1565
0
  uint32_t create_disposition;
1566
0
  uint32_t create_options = FILE_NON_DIRECTORY_FILE;
1567
0
  uint32_t private_flags = 0;
1568
1569
0
  DBG_DEBUG("fname = %s, deny_mode = 0x%x, open_func = 0x%x\n",
1570
0
      smb_base_fname,
1571
0
      (unsigned int)deny_mode,
1572
0
      (unsigned int)open_func);
1573
1574
  /* Create the NT compatible access_mask. */
1575
0
  switch (GET_OPENX_MODE(deny_mode)) {
1576
0
    case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
1577
0
    case DOS_OPEN_RDONLY:
1578
0
      access_mask = FILE_GENERIC_READ;
1579
0
      break;
1580
0
    case DOS_OPEN_WRONLY:
1581
0
      access_mask = FILE_GENERIC_WRITE;
1582
0
      break;
1583
0
    case DOS_OPEN_RDWR:
1584
0
    case DOS_OPEN_FCB:
1585
0
      access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
1586
0
      break;
1587
0
    default:
1588
0
      DBG_DEBUG("bad open mode = 0x%x\n",
1589
0
          (unsigned int)GET_OPENX_MODE(deny_mode));
1590
0
      return False;
1591
0
  }
1592
1593
  /* Create the NT compatible create_disposition. */
1594
0
  switch (open_func) {
1595
0
    case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
1596
0
      create_disposition = FILE_CREATE;
1597
0
      break;
1598
1599
0
    case OPENX_FILE_EXISTS_OPEN:
1600
0
      create_disposition = FILE_OPEN;
1601
0
      break;
1602
1603
0
    case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
1604
0
      create_disposition = FILE_OPEN_IF;
1605
0
      break;
1606
1607
0
    case OPENX_FILE_EXISTS_TRUNCATE:
1608
0
      create_disposition = FILE_OVERWRITE;
1609
0
      break;
1610
1611
0
    case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
1612
0
      create_disposition = FILE_OVERWRITE_IF;
1613
0
      break;
1614
1615
0
    default:
1616
      /* From samba4 - to be confirmed. */
1617
0
      if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
1618
0
        create_disposition = FILE_CREATE;
1619
0
        break;
1620
0
      }
1621
0
      DBG_DEBUG("bad open_func 0x%x\n",
1622
0
          (unsigned int)open_func);
1623
0
      return False;
1624
0
  }
1625
1626
  /* Create the NT compatible share modes. */
1627
0
  switch (GET_DENY_MODE(deny_mode)) {
1628
0
    case DENY_ALL:
1629
0
      share_mode = FILE_SHARE_NONE;
1630
0
      break;
1631
1632
0
    case DENY_WRITE:
1633
0
      share_mode = FILE_SHARE_READ;
1634
0
      break;
1635
1636
0
    case DENY_READ:
1637
0
      share_mode = FILE_SHARE_WRITE;
1638
0
      break;
1639
1640
0
    case DENY_NONE:
1641
0
      share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1642
0
      break;
1643
1644
0
    case DENY_DOS:
1645
0
      private_flags |= NTCREATEX_FLAG_DENY_DOS;
1646
0
                  if (is_executable(smb_base_fname)) {
1647
0
        share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1648
0
      } else {
1649
0
        if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
1650
0
          share_mode = FILE_SHARE_READ;
1651
0
        } else {
1652
0
          share_mode = FILE_SHARE_NONE;
1653
0
        }
1654
0
      }
1655
0
      break;
1656
1657
0
    case DENY_FCB:
1658
0
      private_flags |= NTCREATEX_FLAG_DENY_FCB;
1659
0
      share_mode = FILE_SHARE_NONE;
1660
0
      break;
1661
1662
0
    default:
1663
0
      DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
1664
0
        (unsigned int)GET_DENY_MODE(deny_mode) ));
1665
0
      return False;
1666
0
  }
1667
1668
0
  DBG_DEBUG("file %s, access_mask = 0x%x, "
1669
0
      "share_mode = 0x%x, create_disposition = 0x%x, "
1670
0
      "create_options = 0x%x private_flags = 0x%x\n",
1671
0
      smb_base_fname,
1672
0
      (unsigned int)access_mask,
1673
0
      (unsigned int)share_mode,
1674
0
      (unsigned int)create_disposition,
1675
0
      (unsigned int)create_options,
1676
0
      (unsigned int)private_flags);
1677
1678
0
  if (paccess_mask) {
1679
0
    *paccess_mask = access_mask;
1680
0
  }
1681
0
  if (pshare_mode) {
1682
0
    *pshare_mode = share_mode;
1683
0
  }
1684
0
  if (pcreate_disposition) {
1685
0
    *pcreate_disposition = create_disposition;
1686
0
  }
1687
0
  if (pcreate_options) {
1688
0
    *pcreate_options = create_options;
1689
0
  }
1690
0
  if (pprivate_flags) {
1691
0
    *pprivate_flags = private_flags;
1692
0
  }
1693
1694
0
  return True;
1695
1696
0
}
1697
1698
/*************************************************************************
1699
 Return a talloced copy of a struct security_unix_token. NULL on fail.
1700
*************************************************************************/
1701
1702
struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
1703
0
{
1704
0
  struct security_unix_token *cpy;
1705
1706
0
  cpy = talloc(ctx, struct security_unix_token);
1707
0
  if (!cpy) {
1708
0
    return NULL;
1709
0
  }
1710
1711
0
  *cpy = (struct security_unix_token){
1712
0
    .uid = tok->uid,
1713
0
    .gid = tok->gid,
1714
0
    .ngroups = tok->ngroups,
1715
0
  };
1716
1717
0
  if (tok->ngroups) {
1718
    /* Make this a talloc child of cpy. */
1719
0
    cpy->groups = (gid_t *)talloc_memdup(
1720
0
      cpy, tok->groups, tok->ngroups * sizeof(gid_t));
1721
0
    if (!cpy->groups) {
1722
0
      TALLOC_FREE(cpy);
1723
0
      return NULL;
1724
0
    }
1725
0
  }
1726
0
  return cpy;
1727
0
}
1728
1729
/****************************************************************************
1730
 Return a root token
1731
****************************************************************************/
1732
1733
struct security_unix_token *root_unix_token(TALLOC_CTX *mem_ctx)
1734
0
{
1735
0
  struct security_unix_token *t = NULL;
1736
1737
0
  t = talloc_zero(mem_ctx, struct security_unix_token);
1738
0
  if (t == NULL) {
1739
0
    return NULL;
1740
0
  }
1741
1742
  /*
1743
   * This is not needed, but lets make it explicit, not implicit.
1744
   */
1745
0
  *t = (struct security_unix_token) {
1746
0
    .uid = 0,
1747
0
    .gid = 0,
1748
0
    .ngroups = 0,
1749
0
    .groups = NULL
1750
0
  };
1751
1752
0
  return t;
1753
0
}
1754
1755
/****************************************************************************
1756
 Check that a file matches a particular file type.
1757
****************************************************************************/
1758
1759
bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
1760
0
{
1761
0
  uint32_t mask;
1762
1763
  /* Check the "may have" search bits. */
1764
0
  if (((mode & ~dirtype) &
1765
0
      (FILE_ATTRIBUTE_HIDDEN |
1766
0
       FILE_ATTRIBUTE_SYSTEM |
1767
0
       FILE_ATTRIBUTE_DIRECTORY)) != 0) {
1768
0
    return false;
1769
0
  }
1770
1771
  /* Check the "must have" bits,
1772
     which are the may have bits shifted eight */
1773
  /* If must have bit is set, the file/dir can
1774
     not be returned in search unless the matching
1775
     file attribute is set */
1776
0
  mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
1777
0
            FILE_ATTRIBUTE_ARCHIVE|
1778
0
           FILE_ATTRIBUTE_READONLY|
1779
0
             FILE_ATTRIBUTE_HIDDEN|
1780
0
             FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
1781
0
  if(mask) {
1782
0
    if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
1783
0
              FILE_ATTRIBUTE_ARCHIVE|
1784
0
             FILE_ATTRIBUTE_READONLY|
1785
0
               FILE_ATTRIBUTE_HIDDEN|
1786
0
          FILE_ATTRIBUTE_SYSTEM))) == mask) {
1787
      /* check if matching attribute present */
1788
0
      return true;
1789
0
    } else {
1790
0
      return false;
1791
0
    }
1792
0
  }
1793
1794
0
  return true;
1795
0
}