LCOV - code coverage report
Current view: top level - source3/lib - util.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 601 842 71.4 %
Date: 2021-09-23 10:06:22 Functions: 69 77 89.6 %

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

Generated by: LCOV version 1.13