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
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.
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.
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/>.
25 #include "system/passwd.h"
26 #include "system/filesys.h"
28 #include "ctdbd_conn.h"
29 #include "../lib/util/util_pw.h"
31 #include <ccan/hash/hash.h>
32 #include "libcli/security/security.h"
34 #include "lib/sys_rw.h"
36 #ifdef HAVE_SYS_PRCTL_H
37 #include <sys/prctl.h>
40 /* Max allowable allococation - 256mb - 0x10000000 */
41 #define MAX_ALLOC_SIZE (1024*1024*256)
43 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
44 #ifdef WITH_NISPLUS_HOME
45 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
47 * The following lines are needed due to buggy include files
48 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
49 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
50 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
51 * an enum in /usr/include/rpcsvc/nis.h.
58 #if defined(GROUP_OBJ)
62 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
64 #include <rpcsvc/nis.h>
66 #endif /* WITH_NISPLUS_HOME */
67 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
69 static enum protocol_types Protocol = PROTOCOL_COREPLUS;
71 enum protocol_types get_Protocol(void)
76 void set_Protocol(enum protocol_types p)
81 static enum remote_arch_types ra_type = RA_UNKNOWN;
83 void gfree_all( void )
92 /*******************************************************************
93 Check if a file exists - call vfs_file_exist for samba files.
94 ********************************************************************/
96 bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf,
97 bool fake_dir_create_times)
103 if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
106 return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode)));
109 /*******************************************************************
110 Check if a unix domain socket exists - call vfs_file_exist for samba files.
111 ********************************************************************/
113 bool socket_exist(const char *fname)
116 if (sys_stat(fname, &st, false) != 0)
119 return S_ISSOCK(st.st_ex_mode);
122 /*******************************************************************
123 Returns the size in bytes of the named given the stat struct.
124 ********************************************************************/
126 uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
128 return sbuf->st_ex_size;
131 /****************************************************************************
132 Check two stats have identical dev and ino fields.
133 ****************************************************************************/
135 bool check_same_dev_ino(const SMB_STRUCT_STAT *sbuf1,
136 const SMB_STRUCT_STAT *sbuf2)
138 if (sbuf1->st_ex_dev != sbuf2->st_ex_dev ||
139 sbuf1->st_ex_ino != sbuf2->st_ex_ino) {
145 /****************************************************************************
146 Check if a stat struct is identical for use.
147 ****************************************************************************/
149 bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
150 const SMB_STRUCT_STAT *sbuf2)
152 if (sbuf1->st_ex_uid != sbuf2->st_ex_uid ||
153 sbuf1->st_ex_gid != sbuf2->st_ex_gid ||
154 !check_same_dev_ino(sbuf1, sbuf2)) {
160 /*******************************************************************
161 Show a smb message structure.
162 ********************************************************************/
164 void show_msg(const char *buf)
172 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
174 (int)CVAL(buf,smb_com),
175 (int)CVAL(buf,smb_rcls),
176 (int)CVAL(buf,smb_reh),
177 (int)SVAL(buf,smb_err),
178 (int)CVAL(buf,smb_flg),
179 (int)SVAL(buf,smb_flg2)));
180 DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
181 (int)SVAL(buf,smb_tid),
182 (int)SVAL(buf,smb_pid),
183 (int)SVAL(buf,smb_uid),
184 (int)SVAL(buf,smb_mid)));
185 DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
187 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
188 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
189 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
191 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
193 DEBUGADD(5,("smb_bcc=%d\n",bcc));
201 dump_data(10, (const uint8 *)smb_buf_const(buf), bcc);
204 /*******************************************************************
205 Setup only the byte count for a smb message.
206 ********************************************************************/
208 int set_message_bcc(char *buf,int num_bytes)
210 int num_words = CVAL(buf,smb_wct);
211 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
212 _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
213 return (smb_size + num_words*2 + num_bytes);
216 /*******************************************************************
217 Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
218 Return the bytes added
219 ********************************************************************/
221 ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob)
223 size_t newlen = smb_len(*outbuf) + 4 + blob.length;
226 if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, newlen))) {
227 DEBUG(0, ("talloc failed\n"));
232 memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
233 set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
237 /*******************************************************************
238 Reduce a file name, removing .. elements.
239 ********************************************************************/
241 static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
246 DEBUG(3,("dos_clean_name [%s]\n",s));
248 /* remove any double slashes */
249 str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
254 /* Remove leading .\\ characters */
255 if(strncmp(str, ".\\", 2) == 0) {
256 trim_string(str, ".\\", NULL);
258 str = talloc_strdup(ctx, ".\\");
265 while ((p = strstr_m(str,"\\..\\")) != NULL) {
271 if ((p=strrchr_m(str,'\\')) != NULL) {
276 str = talloc_asprintf(ctx,
285 trim_string(str,NULL,"\\..");
286 return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
289 /*******************************************************************
290 Reduce a file name, removing .. elements.
291 ********************************************************************/
293 char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
298 DEBUG(3,("unix_clean_name [%s]\n",s));
300 /* remove any double slashes */
301 str = talloc_all_string_sub(ctx, s, "//","/");
306 /* Remove leading ./ characters */
307 if(strncmp(str, "./", 2) == 0) {
308 trim_string(str, "./", NULL);
310 str = talloc_strdup(ctx, "./");
317 while ((p = strstr_m(str,"/../")) != NULL) {
323 if ((p=strrchr_m(str,'/')) != NULL) {
328 str = talloc_asprintf(ctx,
337 trim_string(str,NULL,"/..");
338 return talloc_all_string_sub(ctx, str, "/./", "/");
341 char *clean_name(TALLOC_CTX *ctx, const char *s)
343 char *str = dos_clean_name(ctx, s);
347 return unix_clean_name(ctx, str);
350 /*******************************************************************
351 Write data into an fd at a given offset. Ignore seek errors.
352 ********************************************************************/
354 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, off_t pos)
359 if (pos == (off_t)-1) {
360 return write_data(fd, buffer, N);
362 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
364 ret = sys_pwrite(fd,buffer + total,N - total, pos);
365 if (ret == -1 && errno == ESPIPE) {
366 return write_data(fd, buffer + total,N - total);
369 DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
378 return (ssize_t)total;
380 /* Use lseek and write_data. */
381 if (lseek(fd, pos, SEEK_SET) == -1) {
382 if (errno != ESPIPE) {
386 return write_data(fd, buffer, N);
390 static int reinit_after_fork_pipe[2] = { -1, -1 };
392 NTSTATUS init_before_fork(void)
396 ret = pipe(reinit_after_fork_pipe);
400 status = map_nt_error_from_unix_common(errno);
402 DEBUG(0, ("Error creating child_pipe: %s\n",
412 * Detect died parent by detecting EOF on the pipe
414 static void reinit_after_fork_pipe_handler(struct tevent_context *ev,
415 struct tevent_fd *fde,
421 if (sys_read(reinit_after_fork_pipe[0], &c, 1) != 1) {
423 * we have reached EOF on stdin, which means the
424 * parent has exited. Shutdown the server
426 (void)kill(getpid(), SIGTERM);
431 NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
432 struct tevent_context *ev_ctx,
433 bool parent_longlived)
435 NTSTATUS status = NT_STATUS_OK;
437 if (reinit_after_fork_pipe[1] != -1) {
438 close(reinit_after_fork_pipe[1]);
439 reinit_after_fork_pipe[1] = -1;
442 /* Reset the state of the random
443 * number generation system, so
444 * children do not get the same random
445 * numbers as each other */
446 set_need_random_reseed();
448 /* tdb needs special fork handling */
449 if (tdb_reopen_all(parent_longlived ? 1 : 0) != 0) {
450 DEBUG(0,("tdb_reopen_all failed.\n"));
451 status = NT_STATUS_OPEN_FAILED;
455 if (ev_ctx != NULL) {
456 tevent_set_trace_callback(ev_ctx, NULL, NULL);
457 if (tevent_re_initialise(ev_ctx) != 0) {
458 smb_panic(__location__ ": Failed to re-initialise event context");
462 if (reinit_after_fork_pipe[0] != -1) {
463 struct tevent_fd *fde;
465 fde = tevent_add_fd(ev_ctx, ev_ctx /* TALLOC_CTX */,
466 reinit_after_fork_pipe[0], TEVENT_FD_READ,
467 reinit_after_fork_pipe_handler, NULL);
469 smb_panic(__location__ ": Failed to add reinit_after_fork pipe event");
475 * For clustering, we need to re-init our ctdbd connection after the
478 status = messaging_reinit(msg_ctx);
479 if (!NT_STATUS_IS_OK(status)) {
480 DEBUG(0,("messaging_reinit() failed: %s\n",
488 /****************************************************************************
489 (Hopefully) efficient array append.
490 ****************************************************************************/
492 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
493 void *element, void *_array, uint32 *num_elements,
496 void **array = (void **)_array;
498 if (*array_size < 0) {
502 if (*array == NULL) {
503 if (*array_size == 0) {
507 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
511 *array = TALLOC(mem_ctx, element_size * (*array_size));
512 if (*array == NULL) {
517 if (*num_elements == *array_size) {
520 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
524 *array = TALLOC_REALLOC(mem_ctx, *array,
525 element_size * (*array_size));
527 if (*array == NULL) {
532 memcpy((char *)(*array) + element_size*(*num_elements),
533 element, element_size);
543 /****************************************************************************
544 Get my own domain name, or "" if we have none.
545 ****************************************************************************/
547 char *get_mydnsdomname(TALLOC_CTX *ctx)
552 domname = get_mydnsfullname();
557 p = strchr_m(domname, '.');
560 return talloc_strdup(ctx, p);
562 return talloc_strdup(ctx, "");
566 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
567 /******************************************************************
568 Remove any mount options such as -rsize=2048,wsize=2048 etc.
569 Based on a fix from <Thomas.Hepper@icem.de>.
570 Returns a malloc'ed string.
571 *******************************************************************/
573 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
577 while(*p && !isspace(*p))
579 while(*p && isspace(*p))
582 return talloc_strdup(ctx, p);
588 /*******************************************************************
589 Patch from jkf@soton.ac.uk
590 Split Luke's automount_server into YP lookup and string splitter
591 so can easily implement automount_path().
592 Returns a malloc'ed string.
593 *******************************************************************/
595 #ifdef WITH_NISPLUS_HOME
596 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
600 char *nis_map = (char *)lp_homedir_map();
602 char buffer[NIS_MAXATTRVAL + 1];
607 snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
608 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
610 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
611 if (result->status != NIS_SUCCESS) {
612 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
614 object = result->objects.objects_val;
615 if (object->zo_data.zo_type == ENTRY_OBJ) {
616 entry = &object->zo_data.objdata_u.en_data;
617 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
618 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
620 value = talloc_strdup(ctx,
621 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
623 nis_freeresult(result);
626 value = talloc_string_sub(ctx,
633 nis_freeresult(result);
636 value = strip_mount_options(ctx, value);
637 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
642 #else /* WITH_NISPLUS_HOME */
644 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
648 int nis_error; /* returned by yp all functions */
649 char *nis_result; /* yp_match inits this */
650 int nis_result_len; /* and set this */
651 char *nis_domain; /* yp_get_default_domain inits this */
652 char *nis_map = lp_homedir_map(talloc_tos());
654 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
655 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
659 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
661 if ((nis_error = yp_match(nis_domain, nis_map, user_name,
662 strlen(user_name), &nis_result,
663 &nis_result_len)) == 0) {
664 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
665 nis_result[nis_result_len] = '\0';
667 value = talloc_strdup(ctx, nis_result);
671 value = strip_mount_options(ctx, value);
672 } else if(nis_error == YPERR_KEY) {
673 DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
674 user_name, nis_map));
675 DEBUG(3, ("using defaults for server and home directory\n"));
677 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
678 yperr_string(nis_error), user_name, nis_map));
682 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
686 #endif /* WITH_NISPLUS_HOME */
689 bool process_exists(const struct server_id pid)
691 return serverid_exists(&pid);
694 /*******************************************************************
695 Convert a uid into a user name.
696 ********************************************************************/
698 const char *uidtoname(uid_t uid)
700 TALLOC_CTX *ctx = talloc_tos();
702 struct passwd *pass = NULL;
704 pass = getpwuid_alloc(ctx,uid);
706 name = talloc_strdup(ctx,pass->pw_name);
709 name = talloc_asprintf(ctx,
716 /*******************************************************************
717 Convert a gid into a group name.
718 ********************************************************************/
720 char *gidtoname(gid_t gid)
726 return talloc_strdup(talloc_tos(), grp->gr_name);
729 return talloc_asprintf(talloc_tos(),
735 /*******************************************************************
736 Convert a user name into a uid.
737 ********************************************************************/
739 uid_t nametouid(const char *name)
745 pass = Get_Pwnam_alloc(talloc_tos(), name);
752 u = (uid_t)strtol(name, &p, 0);
753 if ((p != name) && (*p == '\0'))
759 /*******************************************************************
760 Convert a name to a gid_t if possible. Return -1 if not a group.
761 ********************************************************************/
763 gid_t nametogid(const char *name)
769 g = (gid_t)strtol(name, &p, 0);
770 if ((p != name) && (*p == '\0'))
773 grp = getgrnam(name);
779 /*******************************************************************
780 Something really nasty happened - panic !
781 ********************************************************************/
783 void smb_panic_s3(const char *why)
788 DEBUG(0,("PANIC (pid %llu): %s\n",
789 (unsigned long long)getpid(), why));
792 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
794 * Make sure all children can attach a debugger.
796 prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
799 cmd = lp_panic_action(talloc_tos());
801 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
802 result = system(cmd);
805 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
808 DEBUG(0, ("smb_panic(): action returned status %d\n",
809 WEXITSTATUS(result)));
815 /*******************************************************************
816 Print a backtrace of the stack to the debug log. This function
817 DELIBERATELY LEAKS MEMORY. The expectation is that you should
818 exit shortly after calling it.
819 ********************************************************************/
821 #ifdef HAVE_LIBUNWIND_H
822 #include <libunwind.h>
825 #ifdef HAVE_EXECINFO_H
826 #include <execinfo.h>
833 void log_stack_trace(void)
835 #ifdef HAVE_LIBUNWIND
836 /* Try to use libunwind before any other technique since on ia64
837 * libunwind correctly walks the stack in more circumstances than
845 unw_word_t ip, sp, off;
847 procname[sizeof(procname) - 1] = '\0';
849 if (unw_getcontext(&uc) != 0) {
850 goto libunwind_failed;
853 if (unw_init_local(&cursor, &uc) != 0) {
854 goto libunwind_failed;
857 DEBUG(0, ("BACKTRACE:\n"));
861 unw_get_reg(&cursor, UNW_REG_IP, &ip);
862 unw_get_reg(&cursor, UNW_REG_SP, &sp);
864 switch (unw_get_proc_name(&cursor,
865 procname, sizeof(procname) - 1, &off) ) {
869 /* Name truncated. */
870 DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
871 i, procname, (long long)off,
872 (long long)ip, (long long) sp));
875 /* case -UNW_ENOINFO: */
876 /* case -UNW_EUNSPEC: */
877 /* No symbol name found. */
878 DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
879 i, "<unknown symbol>",
880 (long long)ip, (long long) sp));
883 } while (unw_step(&cursor) > 0);
888 DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
890 #elif HAVE_BACKTRACE_SYMBOLS
891 void *backtrace_stack[BACKTRACE_STACK_SIZE];
892 size_t backtrace_size;
893 char **backtrace_strings;
895 /* get the backtrace (stack frames) */
896 backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
897 backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
899 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
900 (unsigned long)backtrace_size));
902 if (backtrace_strings) {
905 for (i = 0; i < backtrace_size; i++)
906 DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
908 /* Leak the backtrace_strings, rather than risk what free() might do */
913 /* The IRIX libexc library provides an API for unwinding the stack. See
914 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
915 * since we are about to abort anyway, it hardly matters.
918 #define NAMESIZE 32 /* Arbitrary */
920 __uint64_t addrs[BACKTRACE_STACK_SIZE];
921 char * names[BACKTRACE_STACK_SIZE];
922 char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
931 /* We need to be root so we can open our /proc entry to walk
932 * our stack. It also helps when we want to dump core.
936 for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
937 names[i] = namebuf + (i * NAMESIZE);
940 levels = trace_back_stack(0, addrs, names,
941 BACKTRACE_STACK_SIZE, NAMESIZE - 1);
943 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
944 for (i = 0; i < levels; i++) {
945 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
950 DEBUG(0, ("unable to produce a stack trace on this platform\n"));
954 /*******************************************************************
955 A readdir wrapper which just returns the file name.
956 ********************************************************************/
958 const char *readdirname(DIR *p)
966 ptr = (struct dirent *)readdir(p);
977 #ifdef HAVE_BROKEN_READDIR_NAME
978 /* using /usr/ucb/cc is BAD */
982 return talloc_strdup(talloc_tos(), dname);
985 /*******************************************************************
986 Utility function used to decide if the last component
987 of a path matches a (possibly wildcarded) entry in a namelist.
988 ********************************************************************/
990 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
992 const char *last_component;
994 /* if we have no list it's obviously not in the path */
995 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
999 DEBUG(8, ("is_in_path: %s\n", name));
1001 /* Get the last component of the unix name. */
1002 last_component = strrchr_m(name, '/');
1003 if (!last_component) {
1004 last_component = name;
1006 last_component++; /* Go past '/' */
1009 for(; namelist->name != NULL; namelist++) {
1010 if(namelist->is_wild) {
1011 if (mask_match(last_component, namelist->name, case_sensitive)) {
1012 DEBUG(8,("is_in_path: mask match succeeded\n"));
1016 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1017 (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) {
1018 DEBUG(8,("is_in_path: match succeeded\n"));
1023 DEBUG(8,("is_in_path: match not found\n"));
1027 /*******************************************************************
1028 Strip a '/' separated list into an array of
1029 name_compare_enties structures suitable for
1030 passing to is_in_path(). We do this for
1031 speed so we can pre-parse all the names in the list
1032 and don't do it for each call to is_in_path().
1033 We also check if the entry contains a wildcard to
1034 remove a potentially expensive call to mask_match
1036 ********************************************************************/
1038 void set_namearray(name_compare_entry **ppname_array, const char *namelist_in)
1044 int num_entries = 0;
1047 (*ppname_array) = NULL;
1049 if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0')))
1052 namelist = talloc_strdup(talloc_tos(), namelist_in);
1053 if (namelist == NULL) {
1054 DEBUG(0,("set_namearray: talloc fail\n"));
1059 namelist_end = &namelist[strlen(namelist)];
1061 /* We need to make two passes over the string. The
1062 first to count the number of elements, the second
1066 while(nameptr <= namelist_end) {
1067 if ( *nameptr == '/' ) {
1068 /* cope with multiple (useless) /s) */
1072 /* anything left? */
1073 if ( *nameptr == '\0' )
1076 /* find the next '/' or consume remaining */
1077 name_end = strchr_m(nameptr, '/');
1078 if (name_end == NULL) {
1079 /* Point nameptr at the terminating '\0' */
1080 nameptr += strlen(nameptr);
1082 /* next segment please */
1083 nameptr = name_end + 1;
1088 if(num_entries == 0) {
1089 talloc_free(namelist);
1093 if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1094 DEBUG(0,("set_namearray: malloc fail\n"));
1095 talloc_free(namelist);
1099 /* Now copy out the names */
1102 while(nameptr <= namelist_end) {
1103 if ( *nameptr == '/' ) {
1104 /* cope with multiple (useless) /s) */
1108 /* anything left? */
1109 if ( *nameptr == '\0' )
1112 /* find the next '/' or consume remaining */
1113 name_end = strchr_m(nameptr, '/');
1114 if (name_end != NULL) {
1118 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1119 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1120 DEBUG(0,("set_namearray: malloc fail (1)\n"));
1121 talloc_free(namelist);
1125 if (name_end == NULL) {
1126 /* Point nameptr at the terminating '\0' */
1127 nameptr += strlen(nameptr);
1129 /* next segment please */
1130 nameptr = name_end + 1;
1135 (*ppname_array)[i].name = NULL;
1137 talloc_free(namelist);
1142 #define DBGC_CLASS DBGC_LOCKING
1144 /****************************************************************************
1145 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1146 is dealt with in posix.c
1147 Returns True if we have information regarding this lock region (and returns
1148 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1149 ****************************************************************************/
1151 bool fcntl_getlock(int fd, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1156 DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1157 fd,(double)*poffset,(double)*pcount,*ptype));
1159 lock.l_type = *ptype;
1160 lock.l_whence = SEEK_SET;
1161 lock.l_start = *poffset;
1162 lock.l_len = *pcount;
1165 ret = sys_fcntl_ptr(fd,F_GETLK,&lock);
1169 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1170 (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1175 *ptype = lock.l_type;
1176 *poffset = lock.l_start;
1177 *pcount = lock.l_len;
1180 DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1181 fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1186 #define DBGC_CLASS DBGC_ALL
1188 /*******************************************************************
1189 Is the name specified one of my netbios names.
1190 Returns true if it is equal, false otherwise.
1191 ********************************************************************/
1193 bool is_myname(const char *s)
1198 for (n=0; my_netbios_names(n); n++) {
1199 if (strequal(my_netbios_names(n), s)) {
1204 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1208 /*******************************************************************
1209 we distinguish between 2K and XP by the "Native Lan Manager" string
1210 WinXP => "Windows 2002 5.1"
1211 WinXP 64bit => "Windows XP 5.2"
1212 Win2k => "Windows 2000 5.0"
1213 NT4 => "Windows NT 4.0"
1214 Win9x => "Windows 4.0"
1215 Windows 2003 doesn't set the native lan manager string but
1216 they do set the domain to "Windows 2003 5.2" (probably a bug).
1217 ********************************************************************/
1219 void ra_lanman_string( const char *native_lanman )
1221 if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1222 set_remote_arch( RA_WINXP );
1223 else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1224 set_remote_arch( RA_WINXP64 );
1225 else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1226 set_remote_arch( RA_WIN2K3 );
1229 static const char *remote_arch_str;
1231 const char *get_remote_arch_str(void)
1233 if (!remote_arch_str) {
1236 return remote_arch_str;
1239 /*******************************************************************
1240 Set the horrid remote_arch string based on an enum.
1241 ********************************************************************/
1243 void set_remote_arch(enum remote_arch_types type)
1248 remote_arch_str = "WfWg";
1251 remote_arch_str = "OS2";
1254 remote_arch_str = "Win95";
1257 remote_arch_str = "WinNT";
1260 remote_arch_str = "Win2K";
1263 remote_arch_str = "WinXP";
1266 remote_arch_str = "WinXP64";
1269 remote_arch_str = "Win2K3";
1272 remote_arch_str = "Vista";
1275 remote_arch_str = "Samba";
1278 remote_arch_str = "CIFSFS";
1281 remote_arch_str = "OSX";
1284 ra_type = RA_UNKNOWN;
1285 remote_arch_str = "UNKNOWN";
1289 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1293 /*******************************************************************
1294 Get the remote_arch type.
1295 ********************************************************************/
1297 enum remote_arch_types get_remote_arch(void)
1302 const char *tab_depth(int level, int depth)
1304 if( CHECK_DEBUGLVL(level) ) {
1305 dbgtext("%*s", depth*4, "");
1310 /*****************************************************************************
1311 Provide a checksum on a string
1313 Input: s - the null-terminated character string for which the checksum
1316 Output: The checksum value calculated for s.
1317 *****************************************************************************/
1319 int str_checksum(const char *s)
1323 return hash(s, strlen(s), 0);
1326 /*****************************************************************
1327 Zero a memory area then free it. Used to catch bugs faster.
1328 *****************************************************************/
1330 void zero_free(void *p, size_t size)
1336 /*****************************************************************
1337 Set our open file limit to a requested max and return the limit.
1338 *****************************************************************/
1340 int set_maxfiles(int requested_max)
1342 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1344 int saved_current_limit;
1346 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1347 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1350 return requested_max;
1354 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1355 * account for the extra fd we need
1356 * as well as the log files and standard
1357 * handles etc. Save the limit we want to set in case
1358 * we are running on an OS that doesn't support this limit (AIX)
1359 * which always returns RLIM_INFINITY for rlp.rlim_max.
1362 /* Try raising the hard (max) limit to the requested amount. */
1364 #if defined(RLIM_INFINITY)
1365 if (rlp.rlim_max != RLIM_INFINITY) {
1366 int orig_max = rlp.rlim_max;
1368 if ( rlp.rlim_max < requested_max )
1369 rlp.rlim_max = requested_max;
1371 /* This failing is not an error - many systems (Linux) don't
1372 support our default request of 10,000 open files. JRA. */
1374 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1375 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1376 (int)rlp.rlim_max, strerror(errno) ));
1378 /* Set failed - restore original value from get. */
1379 rlp.rlim_max = orig_max;
1384 /* Now try setting the soft (current) limit. */
1386 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1388 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1389 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1390 (int)rlp.rlim_cur, strerror(errno) ));
1392 return saved_current_limit;
1395 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1396 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1399 return saved_current_limit;
1402 #if defined(RLIM_INFINITY)
1403 if(rlp.rlim_cur == RLIM_INFINITY)
1404 return saved_current_limit;
1407 if((int)rlp.rlim_cur > saved_current_limit)
1408 return saved_current_limit;
1410 return rlp.rlim_cur;
1411 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1413 * No way to know - just guess...
1415 return requested_max;
1419 /*****************************************************************
1420 malloc that aborts with smb_panic on fail or zero size.
1421 *****************************************************************/
1423 void *smb_xmalloc_array(size_t size, unsigned int count)
1427 smb_panic("smb_xmalloc_array: called with zero size");
1429 if (count >= MAX_ALLOC_SIZE/size) {
1430 smb_panic("smb_xmalloc_array: alloc size too large");
1432 if ((p = SMB_MALLOC(size*count)) == NULL) {
1433 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1434 (unsigned long)size, (unsigned long)count));
1435 smb_panic("smb_xmalloc_array: malloc failed");
1441 vasprintf that aborts on malloc fail
1444 int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1451 n = vasprintf(ptr, format, ap2);
1453 if (n == -1 || ! *ptr) {
1454 smb_panic("smb_xvasprintf: out of memory");
1459 /*****************************************************************
1460 Get local hostname and cache result.
1461 *****************************************************************/
1463 char *myhostname(void)
1467 ret = get_myname(NULL);
1472 /*****************************************************************
1473 Get local hostname and cache result.
1474 *****************************************************************/
1476 char *myhostname_upper(void)
1480 char *name = get_myname(NULL);
1484 ret = strupper_talloc(NULL, name);
1491 * @brief Returns an absolute path to a file concatenating the provided
1492 * @a rootpath and @a basename
1494 * @param name Filename, relative to @a rootpath
1496 * @retval Pointer to a string containing the full path.
1499 static char *xx_path(const char *name, const char *rootpath)
1503 fname = talloc_strdup(talloc_tos(), rootpath);
1507 trim_string(fname,"","/");
1509 if (!directory_exist(fname)) {
1510 if (mkdir(fname,0755) == -1) {
1511 /* Did someone else win the race ? */
1512 if (errno != EEXIST) {
1513 DEBUG(1, ("Unable to create directory %s for file %s. "
1514 "Error was %s\n", fname, name, strerror(errno)));
1520 return talloc_asprintf_append(fname, "/%s", name);
1524 * @brief Returns an absolute path to a file in the Samba lock directory.
1526 * @param name File to find, relative to LOCKDIR.
1528 * @retval Pointer to a talloc'ed string containing the full path.
1531 char *lock_path(const char *name)
1533 return xx_path(name, lp_lock_directory());
1537 * @brief Returns an absolute path to a file in the Samba state directory.
1539 * @param name File to find, relative to STATEDIR.
1541 * @retval Pointer to a talloc'ed string containing the full path.
1544 char *state_path(const char *name)
1546 return xx_path(name, lp_state_directory());
1550 * @brief Returns an absolute path to a file in the Samba cache directory.
1552 * @param name File to find, relative to CACHEDIR.
1554 * @retval Pointer to a talloc'ed string containing the full path.
1557 char *cache_path(const char *name)
1559 return xx_path(name, lp_cache_directory());
1562 /*******************************************************************
1563 Given a filename - get its directory name
1564 ********************************************************************/
1566 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1572 p = strrchr_m(dir, '/'); /* Find final '/', if any */
1575 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1586 if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1589 (*parent)[len] = '\0';
1597 /*******************************************************************
1598 Determine if a pattern contains any Microsoft wildcard characters.
1599 *******************************************************************/
1601 bool ms_has_wild(const char *s)
1605 if (lp_posix_pathnames()) {
1606 /* With posix pathnames no characters are wild. */
1610 while ((c = *s++)) {
1623 bool ms_has_wild_w(const smb_ucs2_t *s)
1626 if (!s) return False;
1627 while ((c = *s++)) {
1629 case UCS2_CHAR('*'):
1630 case UCS2_CHAR('?'):
1631 case UCS2_CHAR('<'):
1632 case UCS2_CHAR('>'):
1633 case UCS2_CHAR('"'):
1640 /*******************************************************************
1641 A wrapper that handles case sensitivity and the special handling
1643 *******************************************************************/
1645 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1647 if (ISDOTDOT(string))
1652 return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1655 /*******************************************************************
1656 A wrapper that handles case sensitivity and the special handling
1657 of the ".." name. Varient that is only called by old search code which requires
1658 pattern translation.
1659 *******************************************************************/
1661 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1663 if (ISDOTDOT(string))
1668 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1671 /*******************************************************************
1672 A wrapper that handles a list of patters and calls mask_match()
1673 on each. Returns True if any of the patterns match.
1674 *******************************************************************/
1676 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1678 while (listLen-- > 0) {
1679 if (mask_match(string, *list++, is_case_sensitive))
1685 /*********************************************************
1686 Recursive routine that is called by unix_wild_match.
1687 *********************************************************/
1689 static bool unix_do_match(const char *regexp, const char *str)
1693 for( p = regexp; *p && *str; ) {
1704 * Look for a character matching
1705 * the one after the '*'.
1709 return true; /* Automatic match */
1712 while(*str && (*p != *str))
1716 * Patch from weidel@multichart.de. In the case of the regexp
1717 * '*XX*' we want to ensure there are at least 2 'X' characters
1718 * in the string after the '*' for a match to be made.
1725 * Eat all the characters that match, but count how many there were.
1728 while(*str && (*p == *str)) {
1734 * Now check that if the regexp had n identical characters that
1735 * matchcount had at least that many matches.
1738 while ( *(p+1) && (*(p+1) == *p)) {
1743 if ( matchcount <= 0 )
1747 str--; /* We've eaten the match char after the '*' */
1749 if(unix_do_match(p, str))
1771 if (!*p && str[0] == '.' && str[1] == 0)
1774 if (!*str && *p == '?') {
1780 if(!*str && (*p == '*' && p[1] == '\0'))
1786 /*******************************************************************
1787 Simple case insensitive interface to a UNIX wildcard matcher.
1788 Returns True if match, False if not.
1789 *******************************************************************/
1791 bool unix_wild_match(const char *pattern, const char *string)
1793 TALLOC_CTX *ctx = talloc_stackframe();
1799 p2 = talloc_strdup(ctx,pattern);
1800 s2 = talloc_strdup(ctx,string);
1805 if (!strlower_m(p2)) {
1809 if (!strlower_m(s2)) {
1814 /* Remove any *? and ** from the pattern as they are meaningless */
1815 for(p = p2; *p; p++) {
1816 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
1817 memmove(&p[1], &p[2], strlen(&p[2])+1);
1821 if (strequal(p2,"*")) {
1826 ret = unix_do_match(p2, s2);
1831 /**********************************************************************
1832 Converts a name to a fully qualified domain name.
1833 Returns true if lookup succeeded, false if not (then fqdn is set to name)
1834 Note we deliberately use gethostbyname here, not getaddrinfo as we want
1835 to examine the h_aliases and I don't know how to do that with getaddrinfo.
1836 ***********************************************************************/
1838 bool name_to_fqdn(fstring fqdn, const char *name)
1841 struct hostent *hp = gethostbyname(name);
1843 if (!hp || !hp->h_name || !*hp->h_name) {
1844 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1845 fstrcpy(fqdn, name);
1849 /* Find out if the fqdn is returned as an alias
1850 * to cope with /etc/hosts files where the first
1851 * name is not the fqdn but the short name */
1852 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
1854 for (i = 0; hp->h_aliases[i]; i++) {
1855 if (strchr_m(hp->h_aliases[i], '.')) {
1856 full = hp->h_aliases[i];
1861 if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1862 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1863 DEBUGADD(1, (" Specifying the machine hostname for address 127.0.0.1 may lead\n"));
1864 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
1865 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
1872 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1873 fstrcpy(fqdn, full);
1877 /**********************************************************************
1878 Append a DATA_BLOB to a talloc'ed object
1879 ***********************************************************************/
1881 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
1883 size_t old_size = 0;
1886 if (blob.length == 0) {
1891 old_size = talloc_get_size(buf);
1894 result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
1895 if (result == NULL) {
1899 memcpy(result + old_size, blob.data, blob.length);
1903 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
1905 switch (share_access & ~FILE_SHARE_DELETE) {
1906 case FILE_SHARE_NONE:
1908 case FILE_SHARE_READ:
1910 case FILE_SHARE_WRITE:
1912 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1915 if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1917 } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1924 pid_t procid_to_pid(const struct server_id *proc)
1929 static uint32 my_vnn = NONCLUSTER_VNN;
1931 void set_my_vnn(uint32 vnn)
1933 DEBUG(10, ("vnn pid %d = %u\n", (int)getpid(), (unsigned int)vnn));
1937 uint32 get_my_vnn(void)
1942 static uint64_t my_unique_id = 0;
1944 void set_my_unique_id(uint64_t unique_id)
1946 my_unique_id = unique_id;
1949 struct server_id pid_to_procid(pid_t pid)
1951 struct server_id result;
1954 result.unique_id = my_unique_id;
1955 result.vnn = my_vnn;
1959 struct server_id procid_self(void)
1961 return pid_to_procid(getpid());
1964 bool procid_is_me(const struct server_id *pid)
1966 if (pid->pid != getpid())
1968 if (pid->task_id != 0)
1970 if (pid->vnn != my_vnn)
1975 struct server_id interpret_pid(const char *pid_string)
1977 return server_id_from_string(get_my_vnn(), pid_string);
1980 char *procid_str_static(const struct server_id *pid)
1982 return server_id_str(talloc_tos(), pid);
1985 bool procid_valid(const struct server_id *pid)
1987 return (pid->pid != (uint64_t)-1);
1990 bool procid_is_local(const struct server_id *pid)
1992 return pid->vnn == my_vnn;
1995 /****************************************************************
1996 Check if an offset into a buffer is safe.
1997 If this returns True it's safe to indirect into the byte at
1999 ****************************************************************/
2001 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2003 const char *end_base = buf_base + buf_len;
2004 char *end_ptr = ptr + off;
2006 if (!buf_base || !ptr) {
2010 if (end_base < buf_base || end_ptr < ptr) {
2011 return False; /* wrap. */
2014 if (end_ptr < end_base) {
2020 /****************************************************************
2021 Return a safe pointer into a buffer, or NULL.
2022 ****************************************************************/
2024 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2026 return is_offset_safe(buf_base, buf_len, ptr, off) ?
2030 /****************************************************************
2031 Return a safe pointer into a string within a buffer, or NULL.
2032 ****************************************************************/
2034 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2036 if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2039 /* Check if a valid string exists at this offset. */
2040 if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2046 /****************************************************************
2047 Return an SVAL at a pointer, or failval if beyond the end.
2048 ****************************************************************/
2050 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2053 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2056 if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2059 return SVAL(ptr,off);
2062 /****************************************************************
2063 Return an IVAL at a pointer, or failval if beyond the end.
2064 ****************************************************************/
2066 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2069 * Note we use off+3 here, not off+4 as IVAL accesses
2070 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2072 if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2075 return IVAL(ptr,off);
2078 /****************************************************************
2079 Split DOM\user into DOM and user. Do not mix with winbind variants of that
2080 call (they take care of winbind separator and other winbind specific settings).
2081 ****************************************************************/
2083 void split_domain_user(TALLOC_CTX *mem_ctx,
2084 const char *full_name,
2088 const char *p = NULL;
2090 p = strchr_m(full_name, '\\');
2093 *domain = talloc_strndup(mem_ctx, full_name,
2094 PTR_DIFF(p, full_name));
2095 *user = talloc_strdup(mem_ctx, p+1);
2097 *domain = talloc_strdup(mem_ctx, "");
2098 *user = talloc_strdup(mem_ctx, full_name);
2102 /****************************************************************
2103 strip off leading '\\' from a hostname
2104 ****************************************************************/
2106 const char *strip_hostname(const char *s)
2112 if (strlen_m(s) < 3) {
2116 if (s[0] == '\\') s++;
2117 if (s[0] == '\\') s++;
2122 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2124 if (!NT_STATUS_IS_OK(err1)) {
2128 if (!NT_STATUS_IS_OK(err2)) {
2135 int timeval_to_msec(struct timeval t)
2137 return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2140 /*******************************************************************
2141 Check a given DOS pathname is valid for a share.
2142 ********************************************************************/
2144 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2148 if (!dos_pathname) {
2152 ptr = talloc_strdup(ctx, dos_pathname);
2156 /* Convert any '\' paths to '/' */
2158 ptr = unix_clean_name(ctx, ptr);
2163 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2164 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2167 /* Only absolute paths allowed. */
2174 /*******************************************************************
2175 Return True if the filename is one of the special executable types.
2176 ********************************************************************/
2178 bool is_executable(const char *fname)
2180 if ((fname = strrchr_m(fname,'.'))) {
2181 if (strequal(fname,".com") ||
2182 strequal(fname,".dll") ||
2183 strequal(fname,".exe") ||
2184 strequal(fname,".sym")) {
2191 /****************************************************************************
2192 Open a file with a share mode - old openX method - map into NTCreate.
2193 ****************************************************************************/
2195 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2196 int deny_mode, int open_func,
2197 uint32 *paccess_mask,
2198 uint32 *pshare_mode,
2199 uint32 *pcreate_disposition,
2200 uint32 *pcreate_options,
2201 uint32_t *pprivate_flags)
2205 uint32 create_disposition;
2206 uint32 create_options = FILE_NON_DIRECTORY_FILE;
2207 uint32_t private_flags = 0;
2209 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2210 "open_func = 0x%x\n",
2211 smb_base_fname, (unsigned int)deny_mode,
2212 (unsigned int)open_func ));
2214 /* Create the NT compatible access_mask. */
2215 switch (GET_OPENX_MODE(deny_mode)) {
2216 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2217 case DOS_OPEN_RDONLY:
2218 access_mask = FILE_GENERIC_READ;
2220 case DOS_OPEN_WRONLY:
2221 access_mask = FILE_GENERIC_WRITE;
2225 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2228 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2229 (unsigned int)GET_OPENX_MODE(deny_mode)));
2233 /* Create the NT compatible create_disposition. */
2234 switch (open_func) {
2235 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2236 create_disposition = FILE_CREATE;
2239 case OPENX_FILE_EXISTS_OPEN:
2240 create_disposition = FILE_OPEN;
2243 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2244 create_disposition = FILE_OPEN_IF;
2247 case OPENX_FILE_EXISTS_TRUNCATE:
2248 create_disposition = FILE_OVERWRITE;
2251 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2252 create_disposition = FILE_OVERWRITE_IF;
2256 /* From samba4 - to be confirmed. */
2257 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2258 create_disposition = FILE_CREATE;
2261 DEBUG(10,("map_open_params_to_ntcreate: bad "
2262 "open_func 0x%x\n", (unsigned int)open_func));
2266 /* Create the NT compatible share modes. */
2267 switch (GET_DENY_MODE(deny_mode)) {
2269 share_mode = FILE_SHARE_NONE;
2273 share_mode = FILE_SHARE_READ;
2277 share_mode = FILE_SHARE_WRITE;
2281 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2285 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2286 if (is_executable(smb_base_fname)) {
2287 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2289 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2290 share_mode = FILE_SHARE_READ;
2292 share_mode = FILE_SHARE_NONE;
2298 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2299 share_mode = FILE_SHARE_NONE;
2303 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2304 (unsigned int)GET_DENY_MODE(deny_mode) ));
2308 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2309 "share_mode = 0x%x, create_disposition = 0x%x, "
2310 "create_options = 0x%x private_flags = 0x%x\n",
2312 (unsigned int)access_mask,
2313 (unsigned int)share_mode,
2314 (unsigned int)create_disposition,
2315 (unsigned int)create_options,
2316 (unsigned int)private_flags));
2319 *paccess_mask = access_mask;
2322 *pshare_mode = share_mode;
2324 if (pcreate_disposition) {
2325 *pcreate_disposition = create_disposition;
2327 if (pcreate_options) {
2328 *pcreate_options = create_options;
2330 if (pprivate_flags) {
2331 *pprivate_flags = private_flags;
2338 /*************************************************************************
2339 Return a talloced copy of a struct security_unix_token. NULL on fail.
2340 *************************************************************************/
2342 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
2344 struct security_unix_token *cpy;
2346 cpy = talloc(ctx, struct security_unix_token);
2351 cpy->uid = tok->uid;
2352 cpy->gid = tok->gid;
2353 cpy->ngroups = tok->ngroups;
2355 /* Make this a talloc child of cpy. */
2356 cpy->groups = (gid_t *)talloc_memdup(
2357 cpy, tok->groups, tok->ngroups * sizeof(gid_t));
2368 /****************************************************************************
2369 Check that a file matches a particular file type.
2370 ****************************************************************************/
2372 bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
2376 /* Check the "may have" search bits. */
2377 if (((mode & ~dirtype) &
2378 (FILE_ATTRIBUTE_HIDDEN |
2379 FILE_ATTRIBUTE_SYSTEM |
2380 FILE_ATTRIBUTE_DIRECTORY)) != 0) {
2384 /* Check the "must have" bits,
2385 which are the may have bits shifted eight */
2386 /* If must have bit is set, the file/dir can
2387 not be returned in search unless the matching
2388 file attribute is set */
2389 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
2390 FILE_ATTRIBUTE_ARCHIVE|
2391 FILE_ATTRIBUTE_READONLY|
2392 FILE_ATTRIBUTE_HIDDEN|
2393 FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
2395 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
2396 FILE_ATTRIBUTE_ARCHIVE|
2397 FILE_ATTRIBUTE_READONLY|
2398 FILE_ATTRIBUTE_HIDDEN|
2399 FILE_ATTRIBUTE_SYSTEM))) == mask) {
2400 /* check if matching attribute present */