Coverage Report

Created: 2026-07-25 07:00

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