script/autobuild.py: add support git worktree
[Samba.git] / source3 / lib / util.c
blobe9a7368b290c4486d021bdcd3e90f341fe94b0b8
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
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/>.
24 #include "includes.h"
25 #include "system/passwd.h"
26 #include "system/filesys.h"
27 #include "lib/util/server_id.h"
28 #include "util_tdb.h"
29 #include "ctdbd_conn.h"
30 #include "../lib/util/util_pw.h"
31 #include "messages.h"
32 #include "messages_dgm.h"
33 #include "libcli/security/security.h"
34 #include "serverid.h"
35 #include "lib/util/sys_rw.h"
36 #include "lib/util/sys_rw_data.h"
37 #include "lib/util/util_process.h"
38 #include "lib/dbwrap/dbwrap_ctdb.h"
39 #include "lib/gencache.h"
41 #ifdef HAVE_SYS_PRCTL_H
42 #include <sys/prctl.h>
43 #endif
45 /* Max allowable allococation - 256mb - 0x10000000 */
46 #define MAX_ALLOC_SIZE (1024*1024*256)
48 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
49 /* rpc/xdr.h uses TRUE and FALSE */
50 #ifdef TRUE
51 #undef TRUE
52 #endif
54 #ifdef FALSE
55 #undef FALSE
56 #endif
58 #include "system/nis.h"
60 #ifdef WITH_NISPLUS_HOME
61 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
63 * The following lines are needed due to buggy include files
64 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
65 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
66 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
67 * an enum in /usr/include/rpcsvc/nis.h.
70 #if defined(GROUP)
71 #undef GROUP
72 #endif
74 #if defined(GROUP_OBJ)
75 #undef GROUP_OBJ
76 #endif
78 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
80 #include <rpcsvc/nis.h>
82 #endif /* WITH_NISPLUS_HOME */
83 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
85 static enum protocol_types Protocol = PROTOCOL_COREPLUS;
87 enum protocol_types get_Protocol(void)
89 return Protocol;
92 void set_Protocol(enum protocol_types p)
94 Protocol = p;
97 static enum remote_arch_types ra_type = RA_UNKNOWN;
99 void gfree_all( void )
101 gfree_names();
102 gfree_loadparm();
103 gfree_charcnv();
104 gfree_interfaces();
105 gfree_debugsyms();
108 /*******************************************************************
109 Check if a file exists - call vfs_file_exist for samba files.
110 ********************************************************************/
112 bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf,
113 bool fake_dir_create_times)
115 SMB_STRUCT_STAT st;
116 if (!sbuf)
117 sbuf = &st;
119 if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
120 return(False);
122 return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode)));
125 /*******************************************************************
126 Check if a unix domain socket exists - call vfs_file_exist for samba files.
127 ********************************************************************/
129 bool socket_exist(const char *fname)
131 SMB_STRUCT_STAT st;
132 if (sys_stat(fname, &st, false) != 0)
133 return(False);
135 return S_ISSOCK(st.st_ex_mode);
138 /*******************************************************************
139 Returns the size in bytes of the named given the stat struct.
140 ********************************************************************/
142 uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
144 return sbuf->st_ex_size;
147 /****************************************************************************
148 Check two stats have identical dev and ino fields.
149 ****************************************************************************/
151 bool check_same_dev_ino(const SMB_STRUCT_STAT *sbuf1,
152 const SMB_STRUCT_STAT *sbuf2)
154 if (sbuf1->st_ex_dev != sbuf2->st_ex_dev ||
155 sbuf1->st_ex_ino != sbuf2->st_ex_ino) {
156 return false;
158 return true;
161 /****************************************************************************
162 Check if a stat struct is identical for use.
163 ****************************************************************************/
165 bool check_same_stat(const SMB_STRUCT_STAT *sbuf1,
166 const SMB_STRUCT_STAT *sbuf2)
168 if (sbuf1->st_ex_uid != sbuf2->st_ex_uid ||
169 sbuf1->st_ex_gid != sbuf2->st_ex_gid ||
170 !check_same_dev_ino(sbuf1, sbuf2)) {
171 return false;
173 return true;
176 /*******************************************************************
177 Show a smb message structure.
178 ********************************************************************/
180 void show_msg(const char *buf)
182 int i;
183 int bcc=0;
185 if (!DEBUGLVL(5))
186 return;
188 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
189 smb_len(buf),
190 (int)CVAL(buf,smb_com),
191 (int)CVAL(buf,smb_rcls),
192 (int)CVAL(buf,smb_reh),
193 (int)SVAL(buf,smb_err),
194 (int)CVAL(buf,smb_flg),
195 (int)SVAL(buf,smb_flg2)));
196 DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
197 (int)SVAL(buf,smb_tid),
198 (int)SVAL(buf,smb_pid),
199 (int)SVAL(buf,smb_uid),
200 (int)SVAL(buf,smb_mid)));
201 DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
203 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
204 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
205 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
207 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
209 DEBUGADD(5,("smb_bcc=%d\n",bcc));
211 if (DEBUGLEVEL < 10)
212 return;
214 if (DEBUGLEVEL < 50)
215 bcc = MIN(bcc, 512);
217 dump_data(10, (const uint8_t *)smb_buf_const(buf), bcc);
220 /*******************************************************************
221 Setup only the byte count for a smb message.
222 ********************************************************************/
224 int set_message_bcc(char *buf,int num_bytes)
226 int num_words = CVAL(buf,smb_wct);
227 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
228 _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
229 return (smb_size + num_words*2 + num_bytes);
232 /*******************************************************************
233 Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
234 Return the bytes added
235 ********************************************************************/
237 ssize_t message_push_blob(uint8_t **outbuf, DATA_BLOB blob)
239 size_t newlen = smb_len(*outbuf) + 4 + blob.length;
240 uint8_t *tmp;
242 if (!(tmp = talloc_realloc(NULL, *outbuf, uint8_t, newlen))) {
243 DEBUG(0, ("talloc failed\n"));
244 return -1;
246 *outbuf = tmp;
248 memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
249 set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
250 return blob.length;
253 /*******************************************************************
254 Reduce a file name, removing .. elements.
255 ********************************************************************/
257 static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
259 char *p = NULL;
260 char *str = NULL;
262 DEBUG(3,("dos_clean_name [%s]\n",s));
264 /* remove any double slashes */
265 str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
266 if (!str) {
267 return NULL;
270 /* Remove leading .\\ characters */
271 if(strncmp(str, ".\\", 2) == 0) {
272 trim_string(str, ".\\", NULL);
273 if(*str == 0) {
274 str = talloc_strdup(ctx, ".\\");
275 if (!str) {
276 return NULL;
281 while ((p = strstr_m(str,"\\..\\")) != NULL) {
282 char *s1;
284 *p = 0;
285 s1 = p+3;
287 if ((p=strrchr_m(str,'\\')) != NULL) {
288 *p = 0;
289 } else {
290 *str = 0;
292 str = talloc_asprintf(ctx,
293 "%s%s",
294 str,
295 s1);
296 if (!str) {
297 return NULL;
301 trim_string(str,NULL,"\\..");
302 return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
305 /*******************************************************************
306 Reduce a file name, removing .. elements.
307 ********************************************************************/
309 char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
311 char *p = NULL;
312 char *str = NULL;
314 DEBUG(3,("unix_clean_name [%s]\n",s));
316 /* remove any double slashes */
317 str = talloc_all_string_sub(ctx, s, "//","/");
318 if (!str) {
319 return NULL;
322 /* Remove leading ./ characters */
323 if(strncmp(str, "./", 2) == 0) {
324 trim_string(str, "./", NULL);
325 if(*str == 0) {
326 str = talloc_strdup(ctx, "./");
327 if (!str) {
328 return NULL;
333 while ((p = strstr_m(str,"/../")) != NULL) {
334 char *s1;
336 *p = 0;
337 s1 = p+3;
339 if ((p=strrchr_m(str,'/')) != NULL) {
340 *p = 0;
341 } else {
342 *str = 0;
344 str = talloc_asprintf(ctx,
345 "%s%s",
346 str,
347 s1);
348 if (!str) {
349 return NULL;
353 trim_string(str,NULL,"/..");
354 return talloc_all_string_sub(ctx, str, "/./", "/");
357 char *clean_name(TALLOC_CTX *ctx, const char *s)
359 char *str = dos_clean_name(ctx, s);
360 if (!str) {
361 return NULL;
363 return unix_clean_name(ctx, str);
366 /*******************************************************************
367 Write data into an fd at a given offset. Ignore seek errors.
368 ********************************************************************/
370 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, off_t pos)
372 size_t total=0;
373 ssize_t ret;
375 if (pos == (off_t)-1) {
376 return write_data(fd, buffer, N);
378 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
379 while (total < N) {
380 ret = sys_pwrite(fd,buffer + total,N - total, pos);
381 if (ret == -1 && errno == ESPIPE) {
382 return write_data(fd, buffer + total,N - total);
384 if (ret == -1) {
385 DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
386 return -1;
388 if (ret == 0) {
389 return total;
391 total += ret;
392 pos += ret;
394 return (ssize_t)total;
395 #else
396 /* Use lseek and write_data. */
397 if (lseek(fd, pos, SEEK_SET) == -1) {
398 if (errno != ESPIPE) {
399 return -1;
402 return write_data(fd, buffer, N);
403 #endif
406 static int reinit_after_fork_pipe[2] = { -1, -1 };
408 NTSTATUS init_before_fork(void)
410 int ret;
412 ret = pipe(reinit_after_fork_pipe);
413 if (ret == -1) {
414 NTSTATUS status;
416 status = map_nt_error_from_unix_common(errno);
418 DEBUG(0, ("Error creating child_pipe: %s\n",
419 nt_errstr(status)));
421 return status;
424 return NT_STATUS_OK;
428 * Detect died parent by detecting EOF on the pipe
430 static void reinit_after_fork_pipe_handler(struct tevent_context *ev,
431 struct tevent_fd *fde,
432 uint16_t flags,
433 void *private_data)
435 char c;
437 if (sys_read(reinit_after_fork_pipe[0], &c, 1) != 1) {
439 * we have reached EOF on stdin, which means the
440 * parent has exited. Shutdown the server
442 TALLOC_FREE(fde);
443 (void)kill(getpid(), SIGTERM);
448 NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
449 struct tevent_context *ev_ctx,
450 bool parent_longlived,
451 const char *comment)
453 NTSTATUS status = NT_STATUS_OK;
454 int ret;
457 * The main process thread should never
458 * allow per_thread_cwd_enable() to be
459 * called.
461 per_thread_cwd_disable();
463 if (reinit_after_fork_pipe[1] != -1) {
464 close(reinit_after_fork_pipe[1]);
465 reinit_after_fork_pipe[1] = -1;
468 /* tdb needs special fork handling */
469 if (tdb_reopen_all(parent_longlived ? 1 : 0) != 0) {
470 DEBUG(0,("tdb_reopen_all failed.\n"));
471 status = NT_STATUS_OPEN_FAILED;
472 goto done;
475 if (ev_ctx != NULL) {
476 tevent_set_trace_callback(ev_ctx, NULL, NULL);
477 if (tevent_re_initialise(ev_ctx) != 0) {
478 smb_panic(__location__ ": Failed to re-initialise event context");
482 if (reinit_after_fork_pipe[0] != -1) {
483 struct tevent_fd *fde;
485 fde = tevent_add_fd(ev_ctx, ev_ctx /* TALLOC_CTX */,
486 reinit_after_fork_pipe[0], TEVENT_FD_READ,
487 reinit_after_fork_pipe_handler, NULL);
488 if (fde == NULL) {
489 smb_panic(__location__ ": Failed to add reinit_after_fork pipe event");
493 if (msg_ctx) {
495 * For clustering, we need to re-init our ctdbd connection after the
496 * fork
498 status = messaging_reinit(msg_ctx);
499 if (!NT_STATUS_IS_OK(status)) {
500 DEBUG(0,("messaging_reinit() failed: %s\n",
501 nt_errstr(status)));
504 if (lp_clustering()) {
505 ret = ctdb_async_ctx_reinit(
506 NULL, messaging_tevent_context(msg_ctx));
507 if (ret != 0) {
508 DBG_ERR("db_ctdb_async_ctx_reinit failed: %s\n",
509 strerror(errno));
510 return map_nt_error_from_unix(ret);
515 if (comment) {
516 prctl_set_comment(comment);
519 done:
520 return status;
523 /****************************************************************************
524 (Hopefully) efficient array append.
525 ****************************************************************************/
527 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
528 void *element, void *_array, uint32_t *num_elements,
529 ssize_t *array_size)
531 void **array = (void **)_array;
533 if (*array_size < 0) {
534 return;
537 if (*array == NULL) {
538 if (*array_size == 0) {
539 *array_size = 128;
542 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
543 goto error;
546 *array = TALLOC(mem_ctx, element_size * (*array_size));
547 if (*array == NULL) {
548 goto error;
552 if (*num_elements == *array_size) {
553 *array_size *= 2;
555 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
556 goto error;
559 *array = TALLOC_REALLOC(mem_ctx, *array,
560 element_size * (*array_size));
562 if (*array == NULL) {
563 goto error;
567 memcpy((char *)(*array) + element_size*(*num_elements),
568 element, element_size);
569 *num_elements += 1;
571 return;
573 error:
574 *num_elements = 0;
575 *array_size = -1;
578 /****************************************************************************
579 Get my own domain name, or "" if we have none.
580 ****************************************************************************/
582 char *get_mydnsdomname(TALLOC_CTX *ctx)
584 const char *domname;
585 char *p;
587 domname = get_mydnsfullname();
588 if (!domname) {
589 return NULL;
592 p = strchr_m(domname, '.');
593 if (p) {
594 p++;
595 return talloc_strdup(ctx, p);
596 } else {
597 return talloc_strdup(ctx, "");
601 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
602 /******************************************************************
603 Remove any mount options such as -rsize=2048,wsize=2048 etc.
604 Based on a fix from <Thomas.Hepper@icem.de>.
605 Returns a malloc'ed string.
606 *******************************************************************/
608 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
610 if (*str == '-') {
611 const char *p = str;
612 while(*p && !isspace(*p))
613 p++;
614 while(*p && isspace(*p))
615 p++;
616 if(*p) {
617 return talloc_strdup(ctx, p);
620 return NULL;
623 /*******************************************************************
624 Patch from jkf@soton.ac.uk
625 Split Luke's automount_server into YP lookup and string splitter
626 so can easily implement automount_path().
627 Returns a malloc'ed string.
628 *******************************************************************/
630 #ifdef WITH_NISPLUS_HOME
631 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
633 const struct loadparm_substitution *lp_sub =
634 loadparm_s3_global_substitution();
635 char *value = NULL;
637 char *nis_map = (char *)lp_homedir_map(talloc_tos(), lp_sub);
639 char buffer[NIS_MAXATTRVAL + 1];
640 nis_result *result;
641 nis_object *object;
642 entry_obj *entry;
644 snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
645 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
647 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
648 if (result->status != NIS_SUCCESS) {
649 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
650 } else {
651 object = result->objects.objects_val;
652 if (object->zo_data.zo_type == ENTRY_OBJ) {
653 entry = &object->zo_data.objdata_u.en_data;
654 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
655 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
657 value = talloc_strdup(ctx,
658 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
659 if (!value) {
660 nis_freeresult(result);
661 return NULL;
663 value = talloc_string_sub(ctx,
664 value,
665 "&",
666 user_name);
670 nis_freeresult(result);
672 if (value) {
673 value = strip_mount_options(ctx, value);
674 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
675 user_name, value));
677 return value;
679 #else /* WITH_NISPLUS_HOME */
681 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
683 const struct loadparm_substitution *lp_sub =
684 loadparm_s3_global_substitution();
685 char *value = NULL;
687 int nis_error; /* returned by yp all functions */
688 char *nis_result; /* yp_match inits this */
689 int nis_result_len; /* and set this */
690 char *nis_domain; /* yp_get_default_domain inits this */
691 char *nis_map = lp_homedir_map(talloc_tos(), lp_sub);
693 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
694 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
695 return NULL;
698 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
700 if ((nis_error = yp_match(nis_domain, nis_map, user_name,
701 strlen(user_name), &nis_result,
702 &nis_result_len)) == 0) {
703 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
704 nis_result[nis_result_len] = '\0';
706 value = talloc_strdup(ctx, nis_result);
707 if (!value) {
708 return NULL;
710 value = strip_mount_options(ctx, value);
711 } else if(nis_error == YPERR_KEY) {
712 DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
713 user_name, nis_map));
714 DEBUG(3, ("using defaults for server and home directory\n"));
715 } else {
716 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
717 yperr_string(nis_error), user_name, nis_map));
720 if (value) {
721 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
723 return value;
725 #endif /* WITH_NISPLUS_HOME */
726 #endif
728 bool process_exists(const struct server_id pid)
730 return serverid_exists(&pid);
733 /*******************************************************************
734 Convert a uid into a user name.
735 ********************************************************************/
737 const char *uidtoname(uid_t uid)
739 TALLOC_CTX *ctx = talloc_tos();
740 char *name = NULL;
741 struct passwd *pass = NULL;
743 pass = getpwuid_alloc(ctx,uid);
744 if (pass) {
745 name = talloc_strdup(ctx,pass->pw_name);
746 TALLOC_FREE(pass);
747 } else {
748 name = talloc_asprintf(ctx,
749 "%ld",
750 (long int)uid);
752 return name;
755 /*******************************************************************
756 Convert a gid into a group name.
757 ********************************************************************/
759 char *gidtoname(gid_t gid)
761 struct group *grp;
763 grp = getgrgid(gid);
764 if (grp) {
765 return talloc_strdup(talloc_tos(), grp->gr_name);
767 else {
768 return talloc_asprintf(talloc_tos(),
769 "%d",
770 (int)gid);
774 /*******************************************************************
775 Convert a user name into a uid.
776 ********************************************************************/
778 uid_t nametouid(const char *name)
780 struct passwd *pass;
781 char *p;
782 uid_t u;
784 pass = Get_Pwnam_alloc(talloc_tos(), name);
785 if (pass) {
786 u = pass->pw_uid;
787 TALLOC_FREE(pass);
788 return u;
791 u = (uid_t)strtol(name, &p, 0);
792 if ((p != name) && (*p == '\0'))
793 return u;
795 return (uid_t)-1;
798 /*******************************************************************
799 Convert a name to a gid_t if possible. Return -1 if not a group.
800 ********************************************************************/
802 gid_t nametogid(const char *name)
804 struct group *grp;
805 char *p;
806 gid_t g;
808 g = (gid_t)strtol(name, &p, 0);
809 if ((p != name) && (*p == '\0'))
810 return g;
812 grp = getgrnam(name);
813 if (grp)
814 return(grp->gr_gid);
815 return (gid_t)-1;
818 /*******************************************************************
819 Something really nasty happened - panic !
820 ********************************************************************/
822 void smb_panic_s3(const char *why)
824 const struct loadparm_substitution *lp_sub =
825 loadparm_s3_global_substitution();
826 char *cmd;
827 int result;
829 DEBUG(0,("PANIC (pid %llu): %s\n",
830 (unsigned long long)getpid(), why));
831 log_stack_trace();
833 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
835 * Make sure all children can attach a debugger.
837 prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
838 #endif
840 cmd = lp_panic_action(talloc_tos(), lp_sub);
841 if (cmd && *cmd) {
842 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
843 result = system(cmd);
845 if (result == -1)
846 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
847 strerror(errno)));
848 else
849 DEBUG(0, ("smb_panic(): action returned status %d\n",
850 WEXITSTATUS(result)));
853 dump_core();
856 /*******************************************************************
857 A readdir wrapper which just returns the file name.
858 ********************************************************************/
860 const char *readdirname(DIR *p)
862 struct dirent *ptr;
863 char *dname;
865 if (!p)
866 return(NULL);
868 ptr = (struct dirent *)readdir(p);
869 if (!ptr)
870 return(NULL);
872 dname = ptr->d_name;
874 #ifdef NEXT2
875 if (telldir(p) < 0)
876 return(NULL);
877 #endif
879 #ifdef HAVE_BROKEN_READDIR_NAME
880 /* using /usr/ucb/cc is BAD */
881 dname = dname - 2;
882 #endif
884 return talloc_strdup(talloc_tos(), dname);
887 /*******************************************************************
888 Utility function used to decide if the last component
889 of a path matches a (possibly wildcarded) entry in a namelist.
890 ********************************************************************/
892 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
894 const char *last_component;
896 /* if we have no list it's obviously not in the path */
897 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
898 return False;
901 DEBUG(8, ("is_in_path: %s\n", name));
903 /* Get the last component of the unix name. */
904 last_component = strrchr_m(name, '/');
905 if (!last_component) {
906 last_component = name;
907 } else {
908 last_component++; /* Go past '/' */
911 for(; namelist->name != NULL; namelist++) {
912 if(namelist->is_wild) {
913 if (mask_match(last_component, namelist->name, case_sensitive)) {
914 DEBUG(8,("is_in_path: mask match succeeded\n"));
915 return True;
917 } else {
918 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
919 (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) {
920 DEBUG(8,("is_in_path: match succeeded\n"));
921 return True;
925 DEBUG(8,("is_in_path: match not found\n"));
926 return False;
929 /*******************************************************************
930 Strip a '/' separated list into an array of
931 name_compare_enties structures suitable for
932 passing to is_in_path(). We do this for
933 speed so we can pre-parse all the names in the list
934 and don't do it for each call to is_in_path().
935 We also check if the entry contains a wildcard to
936 remove a potentially expensive call to mask_match
937 if possible.
938 ********************************************************************/
940 void set_namearray(name_compare_entry **ppname_array, const char *namelist_in)
942 char *name_end;
943 char *namelist;
944 char *namelist_end;
945 char *nameptr;
946 int num_entries = 0;
947 int i;
949 (*ppname_array) = NULL;
951 if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0')))
952 return;
954 namelist = talloc_strdup(talloc_tos(), namelist_in);
955 if (namelist == NULL) {
956 DEBUG(0,("set_namearray: talloc fail\n"));
957 return;
959 nameptr = namelist;
961 namelist_end = &namelist[strlen(namelist)];
963 /* We need to make two passes over the string. The
964 first to count the number of elements, the second
965 to split it.
968 while(nameptr <= namelist_end) {
969 if ( *nameptr == '/' ) {
970 /* cope with multiple (useless) /s) */
971 nameptr++;
972 continue;
974 /* anything left? */
975 if ( *nameptr == '\0' )
976 break;
978 /* find the next '/' or consume remaining */
979 name_end = strchr_m(nameptr, '/');
980 if (name_end == NULL) {
981 /* Point nameptr at the terminating '\0' */
982 nameptr += strlen(nameptr);
983 } else {
984 /* next segment please */
985 nameptr = name_end + 1;
987 num_entries++;
990 if(num_entries == 0) {
991 talloc_free(namelist);
992 return;
995 if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
996 DEBUG(0,("set_namearray: malloc fail\n"));
997 talloc_free(namelist);
998 return;
1001 /* Now copy out the names */
1002 nameptr = namelist;
1003 i = 0;
1004 while(nameptr <= namelist_end) {
1005 if ( *nameptr == '/' ) {
1006 /* cope with multiple (useless) /s) */
1007 nameptr++;
1008 continue;
1010 /* anything left? */
1011 if ( *nameptr == '\0' )
1012 break;
1014 /* find the next '/' or consume remaining */
1015 name_end = strchr_m(nameptr, '/');
1016 if (name_end != NULL) {
1017 *name_end = '\0';
1020 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1021 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1022 DEBUG(0,("set_namearray: malloc fail (1)\n"));
1023 talloc_free(namelist);
1024 return;
1027 if (name_end == NULL) {
1028 /* Point nameptr at the terminating '\0' */
1029 nameptr += strlen(nameptr);
1030 } else {
1031 /* next segment please */
1032 nameptr = name_end + 1;
1034 i++;
1037 (*ppname_array)[i].name = NULL;
1039 talloc_free(namelist);
1040 return;
1043 #undef DBGC_CLASS
1044 #define DBGC_CLASS DBGC_LOCKING
1046 /****************************************************************************
1047 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1048 is dealt with in posix.c
1049 Returns True if we have information regarding this lock region (and returns
1050 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1051 ****************************************************************************/
1053 bool fcntl_getlock(int fd, int op, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1055 struct flock lock;
1056 int ret;
1058 DEBUG(8,("fcntl_getlock fd=%d op=%d offset=%.0f count=%.0f type=%d\n",
1059 fd,op,(double)*poffset,(double)*pcount,*ptype));
1061 lock.l_type = *ptype;
1062 lock.l_whence = SEEK_SET;
1063 lock.l_start = *poffset;
1064 lock.l_len = *pcount;
1065 lock.l_pid = 0;
1067 ret = sys_fcntl_ptr(fd,op,&lock);
1069 if (ret == -1) {
1070 int sav = errno;
1071 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1072 (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1073 errno = sav;
1074 return False;
1077 *ptype = lock.l_type;
1078 *poffset = lock.l_start;
1079 *pcount = lock.l_len;
1080 *ppid = lock.l_pid;
1082 DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1083 fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1084 return True;
1087 #if defined(HAVE_OFD_LOCKS)
1088 int map_process_lock_to_ofd_lock(int op)
1090 switch (op) {
1091 case F_GETLK:
1092 case F_OFD_GETLK:
1093 op = F_OFD_GETLK;
1094 break;
1095 case F_SETLK:
1096 case F_OFD_SETLK:
1097 op = F_OFD_SETLK;
1098 break;
1099 case F_SETLKW:
1100 case F_OFD_SETLKW:
1101 op = F_OFD_SETLKW;
1102 break;
1103 default:
1104 return -1;
1106 return op;
1108 #else /* HAVE_OFD_LOCKS */
1109 int map_process_lock_to_ofd_lock(int op)
1111 return op;
1113 #endif /* HAVE_OFD_LOCKS */
1115 #undef DBGC_CLASS
1116 #define DBGC_CLASS DBGC_ALL
1118 /*******************************************************************
1119 Is the name specified one of my netbios names.
1120 Returns true if it is equal, false otherwise.
1121 ********************************************************************/
1123 bool is_myname(const char *s)
1125 int n;
1126 bool ret = False;
1128 for (n=0; my_netbios_names(n); n++) {
1129 const char *nbt_name = my_netbios_names(n);
1131 if (strncasecmp_m(nbt_name, s, MAX_NETBIOSNAME_LEN-1) == 0) {
1132 ret=True;
1133 break;
1136 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1137 return(ret);
1140 /*******************************************************************
1141 we distinguish between 2K and XP by the "Native Lan Manager" string
1142 WinXP => "Windows 2002 5.1"
1143 WinXP 64bit => "Windows XP 5.2"
1144 Win2k => "Windows 2000 5.0"
1145 NT4 => "Windows NT 4.0"
1146 Win9x => "Windows 4.0"
1147 Windows 2003 doesn't set the native lan manager string but
1148 they do set the domain to "Windows 2003 5.2" (probably a bug).
1149 ********************************************************************/
1151 void ra_lanman_string( const char *native_lanman )
1153 if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1154 set_remote_arch( RA_WINXP );
1155 else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1156 set_remote_arch( RA_WINXP64 );
1157 else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1158 set_remote_arch( RA_WIN2K3 );
1161 static const char *remote_arch_strings[] = {
1162 [RA_UNKNOWN] = "UNKNOWN",
1163 [RA_WFWG] = "WfWg",
1164 [RA_OS2] = "OS2",
1165 [RA_WIN95] = "Win95",
1166 [RA_WINNT] = "WinNT",
1167 [RA_WIN2K] = "Win2K",
1168 [RA_WINXP] = "WinXP",
1169 [RA_WIN2K3] = "Win2K3",
1170 [RA_VISTA] = "Vista",
1171 [RA_SAMBA] = "Samba",
1172 [RA_CIFSFS] = "CIFSFS",
1173 [RA_WINXP64] = "WinXP64",
1174 [RA_OSX] = "OSX",
1177 const char *get_remote_arch_str(void)
1179 if (ra_type >= ARRAY_SIZE(remote_arch_strings)) {
1181 * set_remote_arch() already checks this so ra_type
1182 * should be in the allowed range, but anyway, let's
1183 * do another bound check here.
1185 DBG_ERR("Remote arch info out of sync [%d] missing\n", ra_type);
1186 ra_type = RA_UNKNOWN;
1188 return remote_arch_strings[ra_type];
1191 enum remote_arch_types get_remote_arch_from_str(const char *remote_arch_string)
1193 int i;
1195 for (i = 0; i < ARRAY_SIZE(remote_arch_strings); i++) {
1196 if (strcmp(remote_arch_string, remote_arch_strings[i]) == 0) {
1197 return i;
1200 return RA_UNKNOWN;
1203 /*******************************************************************
1204 Set the horrid remote_arch string based on an enum.
1205 ********************************************************************/
1207 void set_remote_arch(enum remote_arch_types type)
1209 if (ra_type >= ARRAY_SIZE(remote_arch_strings)) {
1211 * This protects against someone adding values to enum
1212 * remote_arch_types without updating
1213 * remote_arch_strings array.
1215 DBG_ERR("Remote arch info out of sync [%d] missing\n", ra_type);
1216 ra_type = RA_UNKNOWN;
1217 return;
1220 ra_type = type;
1221 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1222 get_remote_arch_str()));
1225 /*******************************************************************
1226 Get the remote_arch type.
1227 ********************************************************************/
1229 enum remote_arch_types get_remote_arch(void)
1231 return ra_type;
1234 #define RA_CACHE_TTL 7*24*3600
1236 static bool remote_arch_cache_key(const struct GUID *client_guid,
1237 fstring key)
1239 struct GUID_txt_buf guid_buf;
1240 const char *guid_string = NULL;
1242 guid_string = GUID_buf_string(client_guid, &guid_buf);
1243 if (guid_string == NULL) {
1244 return false;
1247 fstr_sprintf(key, "RA/%s", guid_string);
1248 return true;
1251 struct ra_parser_state {
1252 bool found;
1253 enum remote_arch_types ra;
1256 static void ra_parser(const struct gencache_timeout *t,
1257 DATA_BLOB blob,
1258 void *priv_data)
1260 struct ra_parser_state *state = (struct ra_parser_state *)priv_data;
1261 const char *ra_str = NULL;
1263 if (gencache_timeout_expired(t)) {
1264 return;
1267 if ((blob.length == 0) || (blob.data[blob.length-1] != '\0')) {
1268 DBG_ERR("Remote arch cache key not a string\n");
1269 return;
1272 ra_str = (const char *)blob.data;
1273 DBG_INFO("Got remote arch [%s] from cache\n", ra_str);
1275 state->ra = get_remote_arch_from_str(ra_str);
1276 state->found = true;
1277 return;
1280 static bool remote_arch_cache_get(const struct GUID *client_guid)
1282 bool ok;
1283 fstring ra_key;
1284 struct ra_parser_state state = (struct ra_parser_state) {
1285 .found = false,
1286 .ra = RA_UNKNOWN,
1289 ok = remote_arch_cache_key(client_guid, ra_key);
1290 if (!ok) {
1291 return false;
1294 ok = gencache_parse(ra_key, ra_parser, &state);
1295 if (!ok || !state.found) {
1296 return true;
1299 if (state.ra == RA_UNKNOWN) {
1300 return true;
1303 set_remote_arch(state.ra);
1304 return true;
1307 static bool remote_arch_cache_set(const struct GUID *client_guid)
1309 bool ok;
1310 fstring ra_key;
1311 const char *ra_str = NULL;
1313 if (get_remote_arch() == RA_UNKNOWN) {
1314 return true;
1317 ok = remote_arch_cache_key(client_guid, ra_key);
1318 if (!ok) {
1319 return false;
1322 ra_str = get_remote_arch_str();
1323 if (ra_str == NULL) {
1324 return false;
1327 ok = gencache_set(ra_key, ra_str, time(NULL) + RA_CACHE_TTL);
1328 if (!ok) {
1329 return false;
1332 return true;
1335 bool remote_arch_cache_update(const struct GUID *client_guid)
1337 bool ok;
1339 if (get_remote_arch() == RA_UNKNOWN) {
1341 become_root();
1342 ok = remote_arch_cache_get(client_guid);
1343 unbecome_root();
1345 return ok;
1348 become_root();
1349 ok = remote_arch_cache_set(client_guid);
1350 unbecome_root();
1352 return ok;
1355 bool remote_arch_cache_delete(const struct GUID *client_guid)
1357 bool ok;
1358 fstring ra_key;
1360 ok = remote_arch_cache_key(client_guid, ra_key);
1361 if (!ok) {
1362 return false;
1365 become_root();
1366 ok = gencache_del(ra_key);
1367 unbecome_root();
1369 if (!ok) {
1370 return false;
1373 return true;
1376 const char *tab_depth(int level, int depth)
1378 if( CHECK_DEBUGLVL(level) ) {
1379 dbgtext("%*s", depth*4, "");
1381 return "";
1384 /*****************************************************************************
1385 Provide a checksum on a string
1387 Input: s - the null-terminated character string for which the checksum
1388 will be calculated.
1390 Output: The checksum value calculated for s.
1391 *****************************************************************************/
1393 int str_checksum(const char *s)
1395 TDB_DATA key;
1396 if (s == NULL)
1397 return 0;
1399 key = (TDB_DATA) { .dptr = discard_const_p(uint8_t, s),
1400 .dsize = strlen(s) };
1402 return tdb_jenkins_hash(&key);
1405 /*****************************************************************
1406 Zero a memory area then free it. Used to catch bugs faster.
1407 *****************************************************************/
1409 void zero_free(void *p, size_t size)
1411 memset(p, 0, size);
1412 SAFE_FREE(p);
1415 /*****************************************************************
1416 Set our open file limit to a requested max and return the limit.
1417 *****************************************************************/
1419 int set_maxfiles(int requested_max)
1421 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1422 struct rlimit rlp;
1423 int saved_current_limit;
1425 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1426 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1427 strerror(errno) ));
1428 /* just guess... */
1429 return requested_max;
1433 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1434 * account for the extra fd we need
1435 * as well as the log files and standard
1436 * handles etc. Save the limit we want to set in case
1437 * we are running on an OS that doesn't support this limit (AIX)
1438 * which always returns RLIM_INFINITY for rlp.rlim_max.
1441 /* Try raising the hard (max) limit to the requested amount. */
1443 #if defined(RLIM_INFINITY)
1444 if (rlp.rlim_max != RLIM_INFINITY) {
1445 int orig_max = rlp.rlim_max;
1447 if ( rlp.rlim_max < requested_max )
1448 rlp.rlim_max = requested_max;
1450 /* This failing is not an error - many systems (Linux) don't
1451 support our default request of 10,000 open files. JRA. */
1453 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1454 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1455 (int)rlp.rlim_max, strerror(errno) ));
1457 /* Set failed - restore original value from get. */
1458 rlp.rlim_max = orig_max;
1461 #endif
1463 /* Now try setting the soft (current) limit. */
1465 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1467 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1468 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1469 (int)rlp.rlim_cur, strerror(errno) ));
1470 /* just guess... */
1471 return saved_current_limit;
1474 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1475 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1476 strerror(errno) ));
1477 /* just guess... */
1478 return saved_current_limit;
1481 #if defined(RLIM_INFINITY)
1482 if(rlp.rlim_cur == RLIM_INFINITY)
1483 return saved_current_limit;
1484 #endif
1486 if((int)rlp.rlim_cur > saved_current_limit)
1487 return saved_current_limit;
1489 return rlp.rlim_cur;
1490 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1492 * No way to know - just guess...
1494 return requested_max;
1495 #endif
1498 /*****************************************************************
1499 malloc that aborts with smb_panic on fail or zero size.
1500 *****************************************************************/
1502 void *smb_xmalloc_array(size_t size, unsigned int count)
1504 void *p;
1505 if (size == 0) {
1506 smb_panic("smb_xmalloc_array: called with zero size");
1508 if (count >= MAX_ALLOC_SIZE/size) {
1509 smb_panic("smb_xmalloc_array: alloc size too large");
1511 if ((p = SMB_MALLOC(size*count)) == NULL) {
1512 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1513 (unsigned long)size, (unsigned long)count));
1514 smb_panic("smb_xmalloc_array: malloc failed");
1516 return p;
1519 /*****************************************************************
1520 Get local hostname and cache result.
1521 *****************************************************************/
1523 char *myhostname(void)
1525 static char *ret;
1526 if (ret == NULL) {
1527 ret = get_myname(NULL);
1529 return ret;
1532 /*****************************************************************
1533 Get local hostname and cache result.
1534 *****************************************************************/
1536 char *myhostname_upper(void)
1538 static char *ret;
1539 if (ret == NULL) {
1540 char *name = get_myname(NULL);
1541 if (name == NULL) {
1542 return NULL;
1544 ret = strupper_talloc(NULL, name);
1545 talloc_free(name);
1547 return ret;
1550 /*******************************************************************
1551 Given a filename - get its directory name
1552 ********************************************************************/
1554 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1555 const char **name)
1557 char *p;
1558 ptrdiff_t len;
1560 p = strrchr_m(dir, '/'); /* Find final '/', if any */
1562 if (p == NULL) {
1563 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1564 return False;
1566 if (name) {
1567 *name = dir;
1569 return True;
1572 len = p-dir;
1574 if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1575 return False;
1577 (*parent)[len] = '\0';
1579 if (name) {
1580 *name = p+1;
1582 return True;
1585 /*******************************************************************
1586 Determine if a pattern contains any Microsoft wildcard characters.
1587 *******************************************************************/
1589 bool ms_has_wild(const char *s)
1591 char c;
1593 while ((c = *s++)) {
1594 switch (c) {
1595 case '*':
1596 case '?':
1597 case '<':
1598 case '>':
1599 case '"':
1600 return True;
1603 return False;
1606 bool ms_has_wild_w(const smb_ucs2_t *s)
1608 smb_ucs2_t c;
1609 if (!s) return False;
1610 while ((c = *s++)) {
1611 switch (c) {
1612 case UCS2_CHAR('*'):
1613 case UCS2_CHAR('?'):
1614 case UCS2_CHAR('<'):
1615 case UCS2_CHAR('>'):
1616 case UCS2_CHAR('"'):
1617 return True;
1620 return False;
1623 /*******************************************************************
1624 A wrapper that handles case sensitivity and the special handling
1625 of the ".." name.
1626 *******************************************************************/
1628 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1630 if (ISDOTDOT(string))
1631 string = ".";
1632 if (ISDOT(pattern))
1633 return False;
1635 return ms_fnmatch_protocol(pattern, string, Protocol, is_case_sensitive) == 0;
1638 /*******************************************************************
1639 A wrapper that handles case sensitivity and the special handling
1640 of the ".." name. Varient that is only called by old search code which requires
1641 pattern translation.
1642 *******************************************************************/
1644 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1646 if (ISDOTDOT(string))
1647 string = ".";
1648 if (ISDOT(pattern))
1649 return False;
1651 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1654 /*******************************************************************
1655 A wrapper that handles a list of patters and calls mask_match()
1656 on each. Returns True if any of the patterns match.
1657 *******************************************************************/
1659 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1661 while (listLen-- > 0) {
1662 if (mask_match(string, *list++, is_case_sensitive))
1663 return True;
1665 return False;
1668 /**********************************************************************
1669 Converts a name to a fully qualified domain name.
1670 Returns true if lookup succeeded, false if not (then fqdn is set to name)
1671 Uses getaddrinfo() with AI_CANONNAME flag to obtain the official
1672 canonical name of the host. getaddrinfo() may use a variety of sources
1673 including /etc/hosts to obtain the domainname. It expects aliases in
1674 /etc/hosts to NOT be the FQDN. The FQDN should come first.
1675 ************************************************************************/
1677 bool name_to_fqdn(fstring fqdn, const char *name)
1679 char *full = NULL;
1680 struct addrinfo hints;
1681 struct addrinfo *result;
1682 int s;
1684 /* Configure hints to obtain canonical name */
1686 memset(&hints, 0, sizeof(struct addrinfo));
1687 hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
1688 hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
1689 hints.ai_flags = AI_CANONNAME; /* Get host's FQDN */
1690 hints.ai_protocol = 0; /* Any protocol */
1692 s = getaddrinfo(name, NULL, &hints, &result);
1693 if (s != 0) {
1694 DEBUG(1, ("getaddrinfo: %s\n", gai_strerror(s)));
1695 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1696 fstrcpy(fqdn, name);
1697 return false;
1699 full = result->ai_canonname;
1701 /* Find out if the FQDN is returned as an alias
1702 * to cope with /etc/hosts files where the first
1703 * name is not the FQDN but the short name.
1704 * getaddrinfo provides no easy way of handling aliases
1705 * in /etc/hosts. Users should make sure the FQDN
1706 * comes first in /etc/hosts. */
1707 if (full && (! strchr_m(full, '.'))) {
1708 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1709 DEBUGADD(1, (" Full qualified domain names (FQDNs) should not be specified\n"));
1710 DEBUGADD(1, (" as an alias in /etc/hosts. FQDN should be the first name\n"));
1711 DEBUGADD(1, (" prior to any aliases.\n"));
1713 if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1714 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1715 DEBUGADD(1, (" Specifying the machine hostname for address 127.0.0.1 may lead\n"));
1716 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
1717 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
1720 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1721 fstrcpy(fqdn, full);
1722 freeaddrinfo(result); /* No longer needed */
1723 return true;
1726 uint32_t map_share_mode_to_deny_mode(uint32_t share_access, uint32_t private_options)
1728 switch (share_access & ~FILE_SHARE_DELETE) {
1729 case FILE_SHARE_NONE:
1730 return DENY_ALL;
1731 case FILE_SHARE_READ:
1732 return DENY_WRITE;
1733 case FILE_SHARE_WRITE:
1734 return DENY_READ;
1735 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1736 return DENY_NONE;
1738 if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1739 return DENY_DOS;
1740 } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1741 return DENY_FCB;
1744 return (uint32_t)-1;
1747 struct server_id interpret_pid(const char *pid_string)
1749 return server_id_from_string(get_my_vnn(), pid_string);
1752 /****************************************************************
1753 Check if an offset into a buffer is safe.
1754 If this returns True it's safe to indirect into the byte at
1755 pointer ptr+off.
1756 ****************************************************************/
1758 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
1760 const char *end_base = buf_base + buf_len;
1761 char *end_ptr = ptr + off;
1763 if (!buf_base || !ptr) {
1764 return False;
1767 if (end_base < buf_base || end_ptr < ptr) {
1768 return False; /* wrap. */
1771 if (end_ptr < end_base) {
1772 return True;
1774 return False;
1777 /****************************************************************
1778 Return a safe pointer into a buffer, or NULL.
1779 ****************************************************************/
1781 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
1783 return is_offset_safe(buf_base, buf_len, ptr, off) ?
1784 ptr + off : NULL;
1787 /****************************************************************
1788 Return a safe pointer into a string within a buffer, or NULL.
1789 ****************************************************************/
1791 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
1793 if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
1794 return NULL;
1796 /* Check if a valid string exists at this offset. */
1797 if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
1798 return NULL;
1800 return ptr + off;
1803 /****************************************************************
1804 Return an SVAL at a pointer, or failval if beyond the end.
1805 ****************************************************************/
1807 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
1810 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
1811 * NOT ptr[2].
1813 if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
1814 return failval;
1816 return SVAL(ptr,off);
1819 /****************************************************************
1820 Return an IVAL at a pointer, or failval if beyond the end.
1821 ****************************************************************/
1823 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
1826 * Note we use off+3 here, not off+4 as IVAL accesses
1827 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
1829 if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
1830 return failval;
1832 return IVAL(ptr,off);
1835 /****************************************************************
1836 Split DOM\user into DOM and user. Do not mix with winbind variants of that
1837 call (they take care of winbind separator and other winbind specific settings).
1838 ****************************************************************/
1840 bool split_domain_user(TALLOC_CTX *mem_ctx,
1841 const char *full_name,
1842 char **domain,
1843 char **user)
1845 const char *p = NULL;
1847 p = strchr_m(full_name, '\\');
1849 if (p != NULL) {
1850 *domain = talloc_strndup(mem_ctx, full_name,
1851 PTR_DIFF(p, full_name));
1852 if (*domain == NULL) {
1853 return false;
1855 *user = talloc_strdup(mem_ctx, p+1);
1856 if (*user == NULL) {
1857 TALLOC_FREE(*domain);
1858 return false;
1860 } else {
1861 *domain = NULL;
1862 *user = talloc_strdup(mem_ctx, full_name);
1863 if (*user == NULL) {
1864 return false;
1868 return true;
1871 /****************************************************************
1872 strip off leading '\\' from a hostname
1873 ****************************************************************/
1875 const char *strip_hostname(const char *s)
1877 if (!s) {
1878 return NULL;
1881 if (strlen_m(s) < 3) {
1882 return s;
1885 if (s[0] == '\\') s++;
1886 if (s[0] == '\\') s++;
1888 return s;
1891 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
1893 if (!NT_STATUS_IS_OK(err1)) {
1894 *result = err1;
1895 return true;
1897 if (!NT_STATUS_IS_OK(err2)) {
1898 *result = err2;
1899 return true;
1901 return false;
1904 int timeval_to_msec(struct timeval t)
1906 return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
1909 /*******************************************************************
1910 Check a given DOS pathname is valid for a share.
1911 ********************************************************************/
1913 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
1915 char *ptr = NULL;
1917 if (!dos_pathname) {
1918 return NULL;
1921 ptr = talloc_strdup(ctx, dos_pathname);
1922 if (!ptr) {
1923 return NULL;
1925 /* Convert any '\' paths to '/' */
1926 unix_format(ptr);
1927 ptr = unix_clean_name(ctx, ptr);
1928 if (!ptr) {
1929 return NULL;
1932 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
1933 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
1934 ptr += 2;
1936 /* Only absolute paths allowed. */
1937 if (*ptr != '/')
1938 return NULL;
1940 return ptr;
1943 /*******************************************************************
1944 Return True if the filename is one of the special executable types.
1945 ********************************************************************/
1947 bool is_executable(const char *fname)
1949 if ((fname = strrchr_m(fname,'.'))) {
1950 if (strequal(fname,".com") ||
1951 strequal(fname,".dll") ||
1952 strequal(fname,".exe") ||
1953 strequal(fname,".sym")) {
1954 return True;
1957 return False;
1960 /****************************************************************************
1961 Open a file with a share mode - old openX method - map into NTCreate.
1962 ****************************************************************************/
1964 bool map_open_params_to_ntcreate(const char *smb_base_fname,
1965 int deny_mode, int open_func,
1966 uint32_t *paccess_mask,
1967 uint32_t *pshare_mode,
1968 uint32_t *pcreate_disposition,
1969 uint32_t *pcreate_options,
1970 uint32_t *pprivate_flags)
1972 uint32_t access_mask;
1973 uint32_t share_mode;
1974 uint32_t create_disposition;
1975 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
1976 uint32_t private_flags = 0;
1978 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
1979 "open_func = 0x%x\n",
1980 smb_base_fname, (unsigned int)deny_mode,
1981 (unsigned int)open_func ));
1983 /* Create the NT compatible access_mask. */
1984 switch (GET_OPENX_MODE(deny_mode)) {
1985 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
1986 case DOS_OPEN_RDONLY:
1987 access_mask = FILE_GENERIC_READ;
1988 break;
1989 case DOS_OPEN_WRONLY:
1990 access_mask = FILE_GENERIC_WRITE;
1991 break;
1992 case DOS_OPEN_RDWR:
1993 case DOS_OPEN_FCB:
1994 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
1995 break;
1996 default:
1997 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
1998 (unsigned int)GET_OPENX_MODE(deny_mode)));
1999 return False;
2002 /* Create the NT compatible create_disposition. */
2003 switch (open_func) {
2004 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2005 create_disposition = FILE_CREATE;
2006 break;
2008 case OPENX_FILE_EXISTS_OPEN:
2009 create_disposition = FILE_OPEN;
2010 break;
2012 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2013 create_disposition = FILE_OPEN_IF;
2014 break;
2016 case OPENX_FILE_EXISTS_TRUNCATE:
2017 create_disposition = FILE_OVERWRITE;
2018 break;
2020 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2021 create_disposition = FILE_OVERWRITE_IF;
2022 break;
2024 default:
2025 /* From samba4 - to be confirmed. */
2026 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2027 create_disposition = FILE_CREATE;
2028 break;
2030 DEBUG(10,("map_open_params_to_ntcreate: bad "
2031 "open_func 0x%x\n", (unsigned int)open_func));
2032 return False;
2035 /* Create the NT compatible share modes. */
2036 switch (GET_DENY_MODE(deny_mode)) {
2037 case DENY_ALL:
2038 share_mode = FILE_SHARE_NONE;
2039 break;
2041 case DENY_WRITE:
2042 share_mode = FILE_SHARE_READ;
2043 break;
2045 case DENY_READ:
2046 share_mode = FILE_SHARE_WRITE;
2047 break;
2049 case DENY_NONE:
2050 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2051 break;
2053 case DENY_DOS:
2054 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2055 if (is_executable(smb_base_fname)) {
2056 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2057 } else {
2058 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2059 share_mode = FILE_SHARE_READ;
2060 } else {
2061 share_mode = FILE_SHARE_NONE;
2064 break;
2066 case DENY_FCB:
2067 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2068 share_mode = FILE_SHARE_NONE;
2069 break;
2071 default:
2072 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2073 (unsigned int)GET_DENY_MODE(deny_mode) ));
2074 return False;
2077 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2078 "share_mode = 0x%x, create_disposition = 0x%x, "
2079 "create_options = 0x%x private_flags = 0x%x\n",
2080 smb_base_fname,
2081 (unsigned int)access_mask,
2082 (unsigned int)share_mode,
2083 (unsigned int)create_disposition,
2084 (unsigned int)create_options,
2085 (unsigned int)private_flags));
2087 if (paccess_mask) {
2088 *paccess_mask = access_mask;
2090 if (pshare_mode) {
2091 *pshare_mode = share_mode;
2093 if (pcreate_disposition) {
2094 *pcreate_disposition = create_disposition;
2096 if (pcreate_options) {
2097 *pcreate_options = create_options;
2099 if (pprivate_flags) {
2100 *pprivate_flags = private_flags;
2103 return True;
2107 /*************************************************************************
2108 Return a talloced copy of a struct security_unix_token. NULL on fail.
2109 *************************************************************************/
2111 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
2113 struct security_unix_token *cpy;
2115 cpy = talloc(ctx, struct security_unix_token);
2116 if (!cpy) {
2117 return NULL;
2120 cpy->uid = tok->uid;
2121 cpy->gid = tok->gid;
2122 cpy->ngroups = tok->ngroups;
2123 if (tok->ngroups) {
2124 /* Make this a talloc child of cpy. */
2125 cpy->groups = (gid_t *)talloc_memdup(
2126 cpy, tok->groups, tok->ngroups * sizeof(gid_t));
2127 if (!cpy->groups) {
2128 TALLOC_FREE(cpy);
2129 return NULL;
2131 } else {
2132 cpy->groups = NULL;
2134 return cpy;
2137 /****************************************************************************
2138 Return a root token
2139 ****************************************************************************/
2141 struct security_unix_token *root_unix_token(TALLOC_CTX *mem_ctx)
2143 struct security_unix_token *t = NULL;
2145 t = talloc_zero(mem_ctx, struct security_unix_token);
2146 if (t == NULL) {
2147 return NULL;
2151 * This is not needed, but lets make it explicit, not implicit.
2153 *t = (struct security_unix_token) {
2154 .uid = 0,
2155 .gid = 0,
2156 .ngroups = 0,
2157 .groups = NULL
2160 return t;
2163 char *utok_string(TALLOC_CTX *mem_ctx, const struct security_unix_token *tok)
2165 char *str;
2166 uint32_t i;
2168 str = talloc_asprintf(
2169 mem_ctx,
2170 "uid=%ju, gid=%ju, %"PRIu32" groups:",
2171 (uintmax_t)(tok->uid),
2172 (uintmax_t)(tok->gid),
2173 tok->ngroups);
2174 if (str == NULL) {
2175 return NULL;
2178 for (i=0; i<tok->ngroups; i++) {
2179 char *tmp;
2180 tmp = talloc_asprintf_append_buffer(
2181 str, " %ju", (uintmax_t)tok->groups[i]);
2182 if (tmp == NULL) {
2183 TALLOC_FREE(str);
2184 return NULL;
2186 str = tmp;
2189 return str;
2192 /****************************************************************************
2193 Check that a file matches a particular file type.
2194 ****************************************************************************/
2196 bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
2198 uint32_t mask;
2200 /* Check the "may have" search bits. */
2201 if (((mode & ~dirtype) &
2202 (FILE_ATTRIBUTE_HIDDEN |
2203 FILE_ATTRIBUTE_SYSTEM |
2204 FILE_ATTRIBUTE_DIRECTORY)) != 0) {
2205 return false;
2208 /* Check the "must have" bits,
2209 which are the may have bits shifted eight */
2210 /* If must have bit is set, the file/dir can
2211 not be returned in search unless the matching
2212 file attribute is set */
2213 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
2214 FILE_ATTRIBUTE_ARCHIVE|
2215 FILE_ATTRIBUTE_READONLY|
2216 FILE_ATTRIBUTE_HIDDEN|
2217 FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
2218 if(mask) {
2219 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
2220 FILE_ATTRIBUTE_ARCHIVE|
2221 FILE_ATTRIBUTE_READONLY|
2222 FILE_ATTRIBUTE_HIDDEN|
2223 FILE_ATTRIBUTE_SYSTEM))) == mask) {
2224 /* check if matching attribute present */
2225 return true;
2226 } else {
2227 return false;
2231 return true;