LCOV - code coverage report
Current view: top level - source3/lib - util.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 584 839 69.6 %
Date: 2024-05-31 13:13:24 Functions: 60 71 84.5 %

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

Generated by: LCOV version 1.14