LCOV - code coverage report
Current view: top level - source3/lib - util.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 612 860 71.2 %
Date: 2023-11-21 12:31:41 Functions: 63 71 88.7 %

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

Generated by: LCOV version 1.14