source: vendor/3.6.23/source3/lib/util.c

Last change on this file was 860, checked in by Silvan Scherrer, 11 years ago

Samba 3.6: updated vendor to latest version

File size: 68.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2001-2007
6 Copyright (C) Simo Sorce 2001
7 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8 Copyright (C) James Peach 2006
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "includes.h"
25#include "system/passwd.h"
26#include "system/filesys.h"
27#include "util_tdb.h"
28#include "ctdbd_conn.h"
29#include "../lib/util/util_pw.h"
30#include "messages.h"
31#include "libcli/security/security.h"
32
33extern char *global_clobber_region_function;
34extern unsigned int global_clobber_region_line;
35
36/* Max allowable allococation - 256mb - 0x10000000 */
37#define MAX_ALLOC_SIZE (1024*1024*256)
38
39#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
40#ifdef WITH_NISPLUS_HOME
41#ifdef BROKEN_NISPLUS_INCLUDE_FILES
42/*
43 * The following lines are needed due to buggy include files
44 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
45 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
46 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
47 * an enum in /usr/include/rpcsvc/nis.h.
48 */
49
50#if defined(GROUP)
51#undef GROUP
52#endif
53
54#if defined(GROUP_OBJ)
55#undef GROUP_OBJ
56#endif
57
58#endif /* BROKEN_NISPLUS_INCLUDE_FILES */
59
60#include <rpcsvc/nis.h>
61
62#endif /* WITH_NISPLUS_HOME */
63#endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
64
65static enum protocol_types Protocol = PROTOCOL_COREPLUS;
66
67enum protocol_types get_Protocol(void)
68{
69 return Protocol;
70}
71
72void set_Protocol(enum protocol_types p)
73{
74 Protocol = p;
75}
76
77static enum remote_arch_types ra_type = RA_UNKNOWN;
78
79/***********************************************************************
80 Definitions for all names.
81***********************************************************************/
82
83static char *smb_scope;
84static int smb_num_netbios_names;
85static char **smb_my_netbios_names;
86
87/***********************************************************************
88 Allocate and set scope. Ensure upper case.
89***********************************************************************/
90
91bool set_global_scope(const char *scope)
92{
93 SAFE_FREE(smb_scope);
94 smb_scope = SMB_STRDUP(scope);
95 if (!smb_scope)
96 return False;
97 strupper_m(smb_scope);
98 return True;
99}
100
101/*********************************************************************
102 Ensure scope is never null string.
103*********************************************************************/
104
105const char *global_scope(void)
106{
107 if (!smb_scope)
108 set_global_scope("");
109 return smb_scope;
110}
111
112static void free_netbios_names_array(void)
113{
114 int i;
115
116 for (i = 0; i < smb_num_netbios_names; i++)
117 SAFE_FREE(smb_my_netbios_names[i]);
118
119 SAFE_FREE(smb_my_netbios_names);
120 smb_num_netbios_names = 0;
121}
122
123static bool allocate_my_netbios_names_array(size_t number)
124{
125 free_netbios_names_array();
126
127 smb_num_netbios_names = number + 1;
128 smb_my_netbios_names = SMB_MALLOC_ARRAY( char *, smb_num_netbios_names );
129
130 if (!smb_my_netbios_names)
131 return False;
132
133 memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names);
134 return True;
135}
136
137static bool set_my_netbios_names(const char *name, int i)
138{
139 SAFE_FREE(smb_my_netbios_names[i]);
140
141 smb_my_netbios_names[i] = SMB_STRDUP(name);
142 if (!smb_my_netbios_names[i])
143 return False;
144 strupper_m(smb_my_netbios_names[i]);
145 return True;
146}
147
148/***********************************************************************
149 Free memory allocated to global objects
150***********************************************************************/
151
152void gfree_names(void)
153{
154 gfree_netbios_names();
155 SAFE_FREE( smb_scope );
156 free_netbios_names_array();
157 free_local_machine_name();
158}
159
160void gfree_all( void )
161{
162 gfree_names();
163 gfree_loadparm();
164 gfree_case_tables();
165 gfree_charcnv();
166 gfree_interfaces();
167 gfree_debugsyms();
168}
169
170const char *my_netbios_names(int i)
171{
172 return smb_my_netbios_names[i];
173}
174
175bool set_netbios_aliases(const char **str_array)
176{
177 size_t namecount;
178
179 /* Work out the max number of netbios aliases that we have */
180 for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ )
181 ;
182
183 if ( global_myname() && *global_myname())
184 namecount++;
185
186 /* Allocate space for the netbios aliases */
187 if (!allocate_my_netbios_names_array(namecount))
188 return False;
189
190 /* Use the global_myname string first */
191 namecount=0;
192 if ( global_myname() && *global_myname()) {
193 set_my_netbios_names( global_myname(), namecount );
194 namecount++;
195 }
196
197 if (str_array) {
198 size_t i;
199 for ( i = 0; str_array[i] != NULL; i++) {
200 size_t n;
201 bool duplicate = False;
202
203 /* Look for duplicates */
204 for( n=0; n<namecount; n++ ) {
205 if( strequal( str_array[i], my_netbios_names(n) ) ) {
206 duplicate = True;
207 break;
208 }
209 }
210 if (!duplicate) {
211 if (!set_my_netbios_names(str_array[i], namecount))
212 return False;
213 namecount++;
214 }
215 }
216 }
217 return True;
218}
219
220/****************************************************************************
221 Common name initialization code.
222****************************************************************************/
223
224bool init_names(void)
225{
226 int n;
227
228 if (global_myname() == NULL || *global_myname() == '\0') {
229 if (!set_global_myname(myhostname())) {
230 DEBUG( 0, ( "init_names: malloc fail.\n" ) );
231 return False;
232 }
233 }
234
235 if (!set_netbios_aliases(lp_netbios_aliases())) {
236 DEBUG( 0, ( "init_names: malloc fail.\n" ) );
237 return False;
238 }
239
240 set_local_machine_name(global_myname(),false);
241
242 DEBUG( 5, ("Netbios name list:-\n") );
243 for( n=0; my_netbios_names(n); n++ ) {
244 DEBUGADD( 5, ("my_netbios_names[%d]=\"%s\"\n",
245 n, my_netbios_names(n) ) );
246 }
247
248 return( True );
249}
250
251/*******************************************************************
252 Check if a file exists - call vfs_file_exist for samba files.
253********************************************************************/
254
255bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf,
256 bool fake_dir_create_times)
257{
258 SMB_STRUCT_STAT st;
259 if (!sbuf)
260 sbuf = &st;
261
262 if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
263 return(False);
264
265 return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode)));
266}
267
268/*******************************************************************
269 Check if a unix domain socket exists - call vfs_file_exist for samba files.
270********************************************************************/
271
272bool socket_exist(const char *fname)
273{
274 SMB_STRUCT_STAT st;
275 if (sys_stat(fname, &st, false) != 0)
276 return(False);
277
278 return S_ISSOCK(st.st_ex_mode);
279}
280
281/*******************************************************************
282 Returns the size in bytes of the named given the stat struct.
283********************************************************************/
284
285uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
286{
287 return sbuf->st_ex_size;
288}
289
290/*******************************************************************
291 Returns the size in bytes of the named file.
292********************************************************************/
293
294SMB_OFF_T get_file_size(char *file_name)
295{
296 SMB_STRUCT_STAT buf;
297 buf.st_ex_size = 0;
298 if (sys_stat(file_name, &buf, false) != 0)
299 return (SMB_OFF_T)-1;
300 return get_file_size_stat(&buf);
301}
302
303/*******************************************************************
304 Return a string representing an attribute for a file.
305********************************************************************/
306
307char *attrib_string(uint16 mode)
308{
309 fstring attrstr;
310
311 attrstr[0] = 0;
312
313 if (mode & FILE_ATTRIBUTE_VOLUME) fstrcat(attrstr,"V");
314 if (mode & FILE_ATTRIBUTE_DIRECTORY) fstrcat(attrstr,"D");
315 if (mode & FILE_ATTRIBUTE_ARCHIVE) fstrcat(attrstr,"A");
316 if (mode & FILE_ATTRIBUTE_HIDDEN) fstrcat(attrstr,"H");
317 if (mode & FILE_ATTRIBUTE_SYSTEM) fstrcat(attrstr,"S");
318 if (mode & FILE_ATTRIBUTE_READONLY) fstrcat(attrstr,"R");
319
320 return talloc_strdup(talloc_tos(), attrstr);
321}
322
323/*******************************************************************
324 Show a smb message structure.
325********************************************************************/
326
327void show_msg(char *buf)
328{
329 int i;
330 int bcc=0;
331
332 if (!DEBUGLVL(5))
333 return;
334
335 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
336 smb_len(buf),
337 (int)CVAL(buf,smb_com),
338 (int)CVAL(buf,smb_rcls),
339 (int)CVAL(buf,smb_reh),
340 (int)SVAL(buf,smb_err),
341 (int)CVAL(buf,smb_flg),
342 (int)SVAL(buf,smb_flg2)));
343 DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
344 (int)SVAL(buf,smb_tid),
345 (int)SVAL(buf,smb_pid),
346 (int)SVAL(buf,smb_uid),
347 (int)SVAL(buf,smb_mid)));
348 DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
349
350 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
351 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
352 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
353
354 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
355
356 DEBUGADD(5,("smb_bcc=%d\n",bcc));
357
358 if (DEBUGLEVEL < 10)
359 return;
360
361 if (DEBUGLEVEL < 50)
362 bcc = MIN(bcc, 512);
363
364 dump_data(10, (uint8 *)smb_buf(buf), bcc);
365}
366
367/*******************************************************************
368 Set the length and marker of an encrypted smb packet.
369********************************************************************/
370
371void smb_set_enclen(char *buf,int len,uint16 enc_ctx_num)
372{
373 _smb_setlen(buf,len);
374
375 SCVAL(buf,4,0xFF);
376 SCVAL(buf,5,'E');
377 SSVAL(buf,6,enc_ctx_num);
378}
379
380/*******************************************************************
381 Set the length and marker of an smb packet.
382********************************************************************/
383
384void smb_setlen(char *buf,int len)
385{
386 _smb_setlen_large(buf,len);
387
388 SCVAL(buf,4,0xFF);
389 SCVAL(buf,5,'S');
390 SCVAL(buf,6,'M');
391 SCVAL(buf,7,'B');
392}
393
394/*******************************************************************
395 Setup only the byte count for a smb message.
396********************************************************************/
397
398int set_message_bcc(char *buf,int num_bytes)
399{
400 int num_words = CVAL(buf,smb_wct);
401 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
402 _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
403 return (smb_size + num_words*2 + num_bytes);
404}
405
406/*******************************************************************
407 Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
408 Return the bytes added
409********************************************************************/
410
411ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob)
412{
413 size_t newlen = smb_len(*outbuf) + 4 + blob.length;
414 uint8 *tmp;
415
416 if (!(tmp = TALLOC_REALLOC_ARRAY(NULL, *outbuf, uint8, newlen))) {
417 DEBUG(0, ("talloc failed\n"));
418 return -1;
419 }
420 *outbuf = tmp;
421
422 memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
423 set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
424 return blob.length;
425}
426
427/*******************************************************************
428 Reduce a file name, removing .. elements.
429********************************************************************/
430
431static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
432{
433 char *p = NULL;
434 char *str = NULL;
435
436 DEBUG(3,("dos_clean_name [%s]\n",s));
437
438 /* remove any double slashes */
439 str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
440 if (!str) {
441 return NULL;
442 }
443
444 /* Remove leading .\\ characters */
445 if(strncmp(str, ".\\", 2) == 0) {
446 trim_string(str, ".\\", NULL);
447 if(*str == 0) {
448 str = talloc_strdup(ctx, ".\\");
449 if (!str) {
450 return NULL;
451 }
452 }
453 }
454
455 while ((p = strstr_m(str,"\\..\\")) != NULL) {
456 char *s1;
457
458 *p = 0;
459 s1 = p+3;
460
461 if ((p=strrchr_m(str,'\\')) != NULL) {
462 *p = 0;
463 } else {
464 *str = 0;
465 }
466 str = talloc_asprintf(ctx,
467 "%s%s",
468 str,
469 s1);
470 if (!str) {
471 return NULL;
472 }
473 }
474
475 trim_string(str,NULL,"\\..");
476 return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
477}
478
479/*******************************************************************
480 Reduce a file name, removing .. elements.
481********************************************************************/
482
483char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
484{
485 char *p = NULL;
486 char *str = NULL;
487
488 DEBUG(3,("unix_clean_name [%s]\n",s));
489
490 /* remove any double slashes */
491 str = talloc_all_string_sub(ctx, s, "//","/");
492 if (!str) {
493 return NULL;
494 }
495
496 /* Remove leading ./ characters */
497 if(strncmp(str, "./", 2) == 0) {
498 trim_string(str, "./", NULL);
499 if(*str == 0) {
500 str = talloc_strdup(ctx, "./");
501 if (!str) {
502 return NULL;
503 }
504 }
505 }
506
507 while ((p = strstr_m(str,"/../")) != NULL) {
508 char *s1;
509
510 *p = 0;
511 s1 = p+3;
512
513 if ((p=strrchr_m(str,'/')) != NULL) {
514 *p = 0;
515 } else {
516 *str = 0;
517 }
518 str = talloc_asprintf(ctx,
519 "%s%s",
520 str,
521 s1);
522 if (!str) {
523 return NULL;
524 }
525 }
526
527 trim_string(str,NULL,"/..");
528 return talloc_all_string_sub(ctx, str, "/./", "/");
529}
530
531char *clean_name(TALLOC_CTX *ctx, const char *s)
532{
533 char *str = dos_clean_name(ctx, s);
534 if (!str) {
535 return NULL;
536 }
537 return unix_clean_name(ctx, str);
538}
539
540/*******************************************************************
541 Write data into an fd at a given offset. Ignore seek errors.
542********************************************************************/
543
544ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos)
545{
546 size_t total=0;
547 ssize_t ret;
548
549 if (pos == (SMB_OFF_T)-1) {
550 return write_data(fd, buffer, N);
551 }
552#if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
553 while (total < N) {
554 ret = sys_pwrite(fd,buffer + total,N - total, pos);
555 if (ret == -1 && errno == ESPIPE) {
556 return write_data(fd, buffer + total,N - total);
557 }
558 if (ret == -1) {
559 DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
560 return -1;
561 }
562 if (ret == 0) {
563 return total;
564 }
565 total += ret;
566 pos += ret;
567 }
568 return (ssize_t)total;
569#else
570 /* Use lseek and write_data. */
571 if (sys_lseek(fd, pos, SEEK_SET) == -1) {
572 if (errno != ESPIPE) {
573 return -1;
574 }
575 }
576 return write_data(fd, buffer, N);
577#endif
578}
579
580
581NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
582 struct event_context *ev_ctx,
583 struct server_id id,
584 bool parent_longlived)
585{
586 NTSTATUS status = NT_STATUS_OK;
587
588 /* Reset the state of the random
589 * number generation system, so
590 * children do not get the same random
591 * numbers as each other */
592 set_need_random_reseed();
593
594 /* tdb needs special fork handling */
595 if (tdb_reopen_all(parent_longlived ? 1 : 0) == -1) {
596 DEBUG(0,("tdb_reopen_all failed.\n"));
597 status = NT_STATUS_OPEN_FAILED;
598 goto done;
599 }
600
601 if (ev_ctx && tevent_re_initialise(ev_ctx) != 0) {
602 smb_panic(__location__ ": Failed to re-initialise event context");
603 }
604
605 if (msg_ctx) {
606 /*
607 * For clustering, we need to re-init our ctdbd connection after the
608 * fork
609 */
610 status = messaging_reinit(msg_ctx, id);
611 if (!NT_STATUS_IS_OK(status)) {
612 DEBUG(0,("messaging_reinit() failed: %s\n",
613 nt_errstr(status)));
614 }
615 }
616 done:
617 return status;
618}
619
620#if defined(PARANOID_MALLOC_CHECKER)
621
622/****************************************************************************
623 Internal malloc wrapper. Externally visible.
624****************************************************************************/
625
626void *malloc_(size_t size)
627{
628 if (size == 0) {
629 return NULL;
630 }
631#undef malloc
632 return malloc(size);
633#define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
634}
635
636/****************************************************************************
637 Internal calloc wrapper. Not externally visible.
638****************************************************************************/
639
640static void *calloc_(size_t count, size_t size)
641{
642 if (size == 0 || count == 0) {
643 return NULL;
644 }
645#undef calloc
646 return calloc(count, size);
647#define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY
648}
649
650/****************************************************************************
651 Internal realloc wrapper. Not externally visible.
652****************************************************************************/
653
654static void *realloc_(void *ptr, size_t size)
655{
656#undef realloc
657 return realloc(ptr, size);
658#define realloc(p,s) __ERROR_DONT_USE_RELLOC_DIRECTLY
659}
660
661#endif /* PARANOID_MALLOC_CHECKER */
662
663/****************************************************************************
664 Type-safe memalign
665****************************************************************************/
666
667void *memalign_array(size_t el_size, size_t align, unsigned int count)
668{
669 if (count >= MAX_ALLOC_SIZE/el_size) {
670 return NULL;
671 }
672
673 return sys_memalign(align, el_size*count);
674}
675
676/****************************************************************************
677 Type-safe calloc.
678****************************************************************************/
679
680void *calloc_array(size_t size, size_t nmemb)
681{
682 if (nmemb >= MAX_ALLOC_SIZE/size) {
683 return NULL;
684 }
685 if (size == 0 || nmemb == 0) {
686 return NULL;
687 }
688#if defined(PARANOID_MALLOC_CHECKER)
689 return calloc_(nmemb, size);
690#else
691 return calloc(nmemb, size);
692#endif
693}
694
695/****************************************************************************
696 Expand a pointer to be a particular size.
697 Note that this version of Realloc has an extra parameter that decides
698 whether to free the passed in storage on allocation failure or if the
699 new size is zero.
700
701 This is designed for use in the typical idiom of :
702
703 p = SMB_REALLOC(p, size)
704 if (!p) {
705 return error;
706 }
707
708 and not to have to keep track of the old 'p' contents to free later, nor
709 to worry if the size parameter was zero. In the case where NULL is returned
710 we guarentee that p has been freed.
711
712 If free later semantics are desired, then pass 'free_old_on_error' as False which
713 guarentees that the old contents are not freed on error, even if size == 0. To use
714 this idiom use :
715
716 tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
717 if (!tmp) {
718 SAFE_FREE(p);
719 return error;
720 } else {
721 p = tmp;
722 }
723
724 Changes were instigated by Coverity error checking. JRA.
725****************************************************************************/
726
727void *Realloc(void *p, size_t size, bool free_old_on_error)
728{
729 void *ret=NULL;
730
731 if (size == 0) {
732 if (free_old_on_error) {
733 SAFE_FREE(p);
734 }
735 DEBUG(2,("Realloc asked for 0 bytes\n"));
736 return NULL;
737 }
738
739#if defined(PARANOID_MALLOC_CHECKER)
740 if (!p) {
741 ret = (void *)malloc_(size);
742 } else {
743 ret = (void *)realloc_(p,size);
744 }
745#else
746 if (!p) {
747 ret = (void *)malloc(size);
748 } else {
749 ret = (void *)realloc(p,size);
750 }
751#endif
752
753 if (!ret) {
754 if (free_old_on_error && p) {
755 SAFE_FREE(p);
756 }
757 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
758 }
759
760 return(ret);
761}
762
763/****************************************************************************
764 (Hopefully) efficient array append.
765****************************************************************************/
766
767void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
768 void *element, void *_array, uint32 *num_elements,
769 ssize_t *array_size)
770{
771 void **array = (void **)_array;
772
773 if (*array_size < 0) {
774 return;
775 }
776
777 if (*array == NULL) {
778 if (*array_size == 0) {
779 *array_size = 128;
780 }
781
782 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
783 goto error;
784 }
785
786 *array = TALLOC(mem_ctx, element_size * (*array_size));
787 if (*array == NULL) {
788 goto error;
789 }
790 }
791
792 if (*num_elements == *array_size) {
793 *array_size *= 2;
794
795 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
796 goto error;
797 }
798
799 *array = TALLOC_REALLOC(mem_ctx, *array,
800 element_size * (*array_size));
801
802 if (*array == NULL) {
803 goto error;
804 }
805 }
806
807 memcpy((char *)(*array) + element_size*(*num_elements),
808 element, element_size);
809 *num_elements += 1;
810
811 return;
812
813 error:
814 *num_elements = 0;
815 *array_size = -1;
816}
817
818/****************************************************************************
819 Get my own domain name, or "" if we have none.
820****************************************************************************/
821
822char *get_mydnsdomname(TALLOC_CTX *ctx)
823{
824 const char *domname;
825 char *p;
826
827 domname = get_mydnsfullname();
828 if (!domname) {
829 return NULL;
830 }
831
832 p = strchr_m(domname, '.');
833 if (p) {
834 p++;
835 return talloc_strdup(ctx, p);
836 } else {
837 return talloc_strdup(ctx, "");
838 }
839}
840
841/****************************************************************************
842 Interpret a protocol description string, with a default.
843****************************************************************************/
844
845int interpret_protocol(const char *str,int def)
846{
847 if (strequal(str,"NT1"))
848 return(PROTOCOL_NT1);
849 if (strequal(str,"LANMAN2"))
850 return(PROTOCOL_LANMAN2);
851 if (strequal(str,"LANMAN1"))
852 return(PROTOCOL_LANMAN1);
853 if (strequal(str,"CORE"))
854 return(PROTOCOL_CORE);
855 if (strequal(str,"COREPLUS"))
856 return(PROTOCOL_COREPLUS);
857 if (strequal(str,"CORE+"))
858 return(PROTOCOL_COREPLUS);
859
860 DEBUG(0,("Unrecognised protocol level %s\n",str));
861
862 return(def);
863}
864
865
866#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
867/******************************************************************
868 Remove any mount options such as -rsize=2048,wsize=2048 etc.
869 Based on a fix from <Thomas.Hepper@icem.de>.
870 Returns a malloc'ed string.
871*******************************************************************/
872
873static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
874{
875 if (*str == '-') {
876 const char *p = str;
877 while(*p && !isspace(*p))
878 p++;
879 while(*p && isspace(*p))
880 p++;
881 if(*p) {
882 return talloc_strdup(ctx, p);
883 }
884 }
885 return NULL;
886}
887
888/*******************************************************************
889 Patch from jkf@soton.ac.uk
890 Split Luke's automount_server into YP lookup and string splitter
891 so can easily implement automount_path().
892 Returns a malloc'ed string.
893*******************************************************************/
894
895#ifdef WITH_NISPLUS_HOME
896char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
897{
898 char *value = NULL;
899
900 char *nis_map = (char *)lp_nis_home_map_name();
901
902 char buffer[NIS_MAXATTRVAL + 1];
903 nis_result *result;
904 nis_object *object;
905 entry_obj *entry;
906
907 snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
908 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
909
910 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
911 if (result->status != NIS_SUCCESS) {
912 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
913 } else {
914 object = result->objects.objects_val;
915 if (object->zo_data.zo_type == ENTRY_OBJ) {
916 entry = &object->zo_data.objdata_u.en_data;
917 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
918 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
919
920 value = talloc_strdup(ctx,
921 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
922 if (!value) {
923 nis_freeresult(result);
924 return NULL;
925 }
926 value = talloc_string_sub(ctx,
927 value,
928 "&",
929 user_name);
930 }
931 }
932 }
933 nis_freeresult(result);
934
935 if (value) {
936 value = strip_mount_options(ctx, value);
937 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
938 user_name, value));
939 }
940 return value;
941}
942#else /* WITH_NISPLUS_HOME */
943
944char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
945{
946 char *value = NULL;
947
948 int nis_error; /* returned by yp all functions */
949 char *nis_result; /* yp_match inits this */
950 int nis_result_len; /* and set this */
951 char *nis_domain; /* yp_get_default_domain inits this */
952 char *nis_map = (char *)lp_nis_home_map_name();
953
954 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
955 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
956 return NULL;
957 }
958
959 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
960
961 if ((nis_error = yp_match(nis_domain, nis_map, user_name,
962 strlen(user_name), &nis_result,
963 &nis_result_len)) == 0) {
964 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
965 nis_result[nis_result_len] = '\0';
966 }
967 value = talloc_strdup(ctx, nis_result);
968 if (!value) {
969 return NULL;
970 }
971 value = strip_mount_options(ctx, value);
972 } else if(nis_error == YPERR_KEY) {
973 DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
974 user_name, nis_map));
975 DEBUG(3, ("using defaults for server and home directory\n"));
976 } else {
977 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
978 yperr_string(nis_error), user_name, nis_map));
979 }
980
981 if (value) {
982 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
983 }
984 return value;
985}
986#endif /* WITH_NISPLUS_HOME */
987#endif
988
989/****************************************************************************
990 Check if a process exists. Does this work on all unixes?
991****************************************************************************/
992
993bool process_exists(const struct server_id pid)
994{
995 if (procid_is_me(&pid)) {
996 return True;
997 }
998
999 if (procid_is_local(&pid)) {
1000 return (kill(pid.pid,0) == 0 || errno != ESRCH);
1001 }
1002
1003#ifdef CLUSTER_SUPPORT
1004 return ctdbd_process_exists(messaging_ctdbd_connection(),
1005 pid.vnn, pid.pid);
1006#else
1007 return False;
1008#endif
1009}
1010
1011/*******************************************************************
1012 Convert a uid into a user name.
1013********************************************************************/
1014
1015const char *uidtoname(uid_t uid)
1016{
1017 TALLOC_CTX *ctx = talloc_tos();
1018 char *name = NULL;
1019 struct passwd *pass = NULL;
1020
1021 pass = getpwuid_alloc(ctx,uid);
1022 if (pass) {
1023 name = talloc_strdup(ctx,pass->pw_name);
1024 TALLOC_FREE(pass);
1025 } else {
1026 name = talloc_asprintf(ctx,
1027 "%ld",
1028 (long int)uid);
1029 }
1030 return name;
1031}
1032
1033/*******************************************************************
1034 Convert a gid into a group name.
1035********************************************************************/
1036
1037char *gidtoname(gid_t gid)
1038{
1039 struct group *grp;
1040
1041 grp = getgrgid(gid);
1042 if (grp) {
1043 return talloc_strdup(talloc_tos(), grp->gr_name);
1044 }
1045 else {
1046 return talloc_asprintf(talloc_tos(),
1047 "%d",
1048 (int)gid);
1049 }
1050}
1051
1052/*******************************************************************
1053 Convert a user name into a uid.
1054********************************************************************/
1055
1056uid_t nametouid(const char *name)
1057{
1058 struct passwd *pass;
1059 char *p;
1060 uid_t u;
1061
1062 pass = Get_Pwnam_alloc(talloc_tos(), name);
1063 if (pass) {
1064 u = pass->pw_uid;
1065 TALLOC_FREE(pass);
1066 return u;
1067 }
1068
1069 u = (uid_t)strtol(name, &p, 0);
1070 if ((p != name) && (*p == '\0'))
1071 return u;
1072
1073 return (uid_t)-1;
1074}
1075
1076/*******************************************************************
1077 Convert a name to a gid_t if possible. Return -1 if not a group.
1078********************************************************************/
1079
1080gid_t nametogid(const char *name)
1081{
1082 struct group *grp;
1083 char *p;
1084 gid_t g;
1085
1086 g = (gid_t)strtol(name, &p, 0);
1087 if ((p != name) && (*p == '\0'))
1088 return g;
1089
1090 grp = sys_getgrnam(name);
1091 if (grp)
1092 return(grp->gr_gid);
1093 return (gid_t)-1;
1094}
1095
1096/*******************************************************************
1097 Something really nasty happened - panic !
1098********************************************************************/
1099
1100void smb_panic(const char *const why)
1101{
1102 char *cmd;
1103 int result;
1104
1105#ifdef DEVELOPER
1106 {
1107
1108 if (global_clobber_region_function) {
1109 DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]\n",
1110 global_clobber_region_function,
1111 global_clobber_region_line));
1112 }
1113 }
1114#endif
1115
1116 DEBUG(0,("PANIC (pid %llu): %s\n",
1117 (unsigned long long)sys_getpid(), why));
1118 log_stack_trace();
1119
1120 cmd = lp_panic_action();
1121 if (cmd && *cmd) {
1122 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
1123 result = system(cmd);
1124
1125 if (result == -1)
1126 DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
1127 strerror(errno)));
1128 else
1129 DEBUG(0, ("smb_panic(): action returned status %d\n",
1130 WEXITSTATUS(result)));
1131 }
1132
1133 dump_core();
1134}
1135
1136/*******************************************************************
1137 Print a backtrace of the stack to the debug log. This function
1138 DELIBERATELY LEAKS MEMORY. The expectation is that you should
1139 exit shortly after calling it.
1140********************************************************************/
1141
1142#ifdef HAVE_LIBUNWIND_H
1143#include <libunwind.h>
1144#endif
1145
1146#ifdef HAVE_EXECINFO_H
1147#include <execinfo.h>
1148#endif
1149
1150#ifdef HAVE_LIBEXC_H
1151#include <libexc.h>
1152#endif
1153
1154void log_stack_trace(void)
1155{
1156#ifdef HAVE_LIBUNWIND
1157 /* Try to use libunwind before any other technique since on ia64
1158 * libunwind correctly walks the stack in more circumstances than
1159 * backtrace.
1160 */
1161 unw_cursor_t cursor;
1162 unw_context_t uc;
1163 unsigned i = 0;
1164
1165 char procname[256];
1166 unw_word_t ip, sp, off;
1167
1168 procname[sizeof(procname) - 1] = '\0';
1169
1170 if (unw_getcontext(&uc) != 0) {
1171 goto libunwind_failed;
1172 }
1173
1174 if (unw_init_local(&cursor, &uc) != 0) {
1175 goto libunwind_failed;
1176 }
1177
1178 DEBUG(0, ("BACKTRACE:\n"));
1179
1180 do {
1181 ip = sp = 0;
1182 unw_get_reg(&cursor, UNW_REG_IP, &ip);
1183 unw_get_reg(&cursor, UNW_REG_SP, &sp);
1184
1185 switch (unw_get_proc_name(&cursor,
1186 procname, sizeof(procname) - 1, &off) ) {
1187 case 0:
1188 /* Name found. */
1189 case -UNW_ENOMEM:
1190 /* Name truncated. */
1191 DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
1192 i, procname, (long long)off,
1193 (long long)ip, (long long) sp));
1194 break;
1195 default:
1196 /* case -UNW_ENOINFO: */
1197 /* case -UNW_EUNSPEC: */
1198 /* No symbol name found. */
1199 DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
1200 i, "<unknown symbol>",
1201 (long long)ip, (long long) sp));
1202 }
1203 ++i;
1204 } while (unw_step(&cursor) > 0);
1205
1206 return;
1207
1208libunwind_failed:
1209 DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
1210
1211#elif HAVE_BACKTRACE_SYMBOLS
1212 void *backtrace_stack[BACKTRACE_STACK_SIZE];
1213 size_t backtrace_size;
1214 char **backtrace_strings;
1215
1216 /* get the backtrace (stack frames) */
1217 backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
1218 backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
1219
1220 DEBUG(0, ("BACKTRACE: %lu stack frames:\n",
1221 (unsigned long)backtrace_size));
1222
1223 if (backtrace_strings) {
1224 int i;
1225
1226 for (i = 0; i < backtrace_size; i++)
1227 DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
1228
1229 /* Leak the backtrace_strings, rather than risk what free() might do */
1230 }
1231
1232#elif HAVE_LIBEXC
1233
1234 /* The IRIX libexc library provides an API for unwinding the stack. See
1235 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
1236 * since we are about to abort anyway, it hardly matters.
1237 */
1238
1239#define NAMESIZE 32 /* Arbitrary */
1240
1241 __uint64_t addrs[BACKTRACE_STACK_SIZE];
1242 char * names[BACKTRACE_STACK_SIZE];
1243 char namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
1244
1245 int i;
1246 int levels;
1247
1248 ZERO_ARRAY(addrs);
1249 ZERO_ARRAY(names);
1250 ZERO_ARRAY(namebuf);
1251
1252 /* We need to be root so we can open our /proc entry to walk
1253 * our stack. It also helps when we want to dump core.
1254 */
1255 become_root();
1256
1257 for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
1258 names[i] = namebuf + (i * NAMESIZE);
1259 }
1260
1261 levels = trace_back_stack(0, addrs, names,
1262 BACKTRACE_STACK_SIZE, NAMESIZE - 1);
1263
1264 DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
1265 for (i = 0; i < levels; i++) {
1266 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
1267 }
1268#undef NAMESIZE
1269
1270#else
1271 DEBUG(0, ("unable to produce a stack trace on this platform\n"));
1272#endif
1273}
1274
1275/*******************************************************************
1276 A readdir wrapper which just returns the file name.
1277 ********************************************************************/
1278
1279const char *readdirname(SMB_STRUCT_DIR *p)
1280{
1281 SMB_STRUCT_DIRENT *ptr;
1282 char *dname;
1283
1284 if (!p)
1285 return(NULL);
1286
1287 ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
1288 if (!ptr)
1289 return(NULL);
1290
1291 dname = ptr->d_name;
1292
1293#ifdef NEXT2
1294 if (telldir(p) < 0)
1295 return(NULL);
1296#endif
1297
1298#ifdef HAVE_BROKEN_READDIR_NAME
1299 /* using /usr/ucb/cc is BAD */
1300 dname = dname - 2;
1301#endif
1302
1303 return talloc_strdup(talloc_tos(), dname);
1304}
1305
1306/*******************************************************************
1307 Utility function used to decide if the last component
1308 of a path matches a (possibly wildcarded) entry in a namelist.
1309********************************************************************/
1310
1311bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
1312{
1313 const char *last_component;
1314
1315 /* if we have no list it's obviously not in the path */
1316 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
1317 return False;
1318 }
1319
1320 DEBUG(8, ("is_in_path: %s\n", name));
1321
1322 /* Get the last component of the unix name. */
1323 last_component = strrchr_m(name, '/');
1324 if (!last_component) {
1325 last_component = name;
1326 } else {
1327 last_component++; /* Go past '/' */
1328 }
1329
1330 for(; namelist->name != NULL; namelist++) {
1331 if(namelist->is_wild) {
1332 if (mask_match(last_component, namelist->name, case_sensitive)) {
1333 DEBUG(8,("is_in_path: mask match succeeded\n"));
1334 return True;
1335 }
1336 } else {
1337 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1338 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) {
1339 DEBUG(8,("is_in_path: match succeeded\n"));
1340 return True;
1341 }
1342 }
1343 }
1344 DEBUG(8,("is_in_path: match not found\n"));
1345 return False;
1346}
1347
1348/*******************************************************************
1349 Strip a '/' separated list into an array of
1350 name_compare_enties structures suitable for
1351 passing to is_in_path(). We do this for
1352 speed so we can pre-parse all the names in the list
1353 and don't do it for each call to is_in_path().
1354 namelist is modified here and is assumed to be
1355 a copy owned by the caller.
1356 We also check if the entry contains a wildcard to
1357 remove a potentially expensive call to mask_match
1358 if possible.
1359********************************************************************/
1360
1361void set_namearray(name_compare_entry **ppname_array, const char *namelist)
1362{
1363 char *name_end;
1364 char *nameptr = (char *)namelist;
1365 int num_entries = 0;
1366 int i;
1367
1368 (*ppname_array) = NULL;
1369
1370 if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
1371 return;
1372
1373 /* We need to make two passes over the string. The
1374 first to count the number of elements, the second
1375 to split it.
1376 */
1377
1378 while(*nameptr) {
1379 if ( *nameptr == '/' ) {
1380 /* cope with multiple (useless) /s) */
1381 nameptr++;
1382 continue;
1383 }
1384 /* anything left? */
1385 if ( *nameptr == '\0' )
1386 break;
1387
1388 /* find the next '/' or consume remaining */
1389 name_end = strchr_m(nameptr, '/');
1390 if (name_end == NULL)
1391 name_end = (char *)nameptr + strlen(nameptr);
1392
1393 /* next segment please */
1394 nameptr = name_end + 1;
1395 num_entries++;
1396 }
1397
1398 if(num_entries == 0)
1399 return;
1400
1401 if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1402 DEBUG(0,("set_namearray: malloc fail\n"));
1403 return;
1404 }
1405
1406 /* Now copy out the names */
1407 nameptr = (char *)namelist;
1408 i = 0;
1409 while(*nameptr) {
1410 if ( *nameptr == '/' ) {
1411 /* cope with multiple (useless) /s) */
1412 nameptr++;
1413 continue;
1414 }
1415 /* anything left? */
1416 if ( *nameptr == '\0' )
1417 break;
1418
1419 /* find the next '/' or consume remaining */
1420 name_end = strchr_m(nameptr, '/');
1421 if (name_end)
1422 *name_end = '\0';
1423 else
1424 name_end = nameptr + strlen(nameptr);
1425
1426 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1427 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1428 DEBUG(0,("set_namearray: malloc fail (1)\n"));
1429 return;
1430 }
1431
1432 /* next segment please */
1433 nameptr = name_end + 1;
1434 i++;
1435 }
1436
1437 (*ppname_array)[i].name = NULL;
1438
1439 return;
1440}
1441
1442/****************************************************************************
1443 Routine to free a namearray.
1444****************************************************************************/
1445
1446void free_namearray(name_compare_entry *name_array)
1447{
1448 int i;
1449
1450 if(name_array == NULL)
1451 return;
1452
1453 for(i=0; name_array[i].name!=NULL; i++)
1454 SAFE_FREE(name_array[i].name);
1455 SAFE_FREE(name_array);
1456}
1457
1458#undef DBGC_CLASS
1459#define DBGC_CLASS DBGC_LOCKING
1460
1461/****************************************************************************
1462 Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1463 is dealt with in posix.c
1464 Returns True if we have information regarding this lock region (and returns
1465 F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1466****************************************************************************/
1467
1468bool fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
1469{
1470 SMB_STRUCT_FLOCK lock;
1471 int ret;
1472
1473 DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1474 fd,(double)*poffset,(double)*pcount,*ptype));
1475
1476 lock.l_type = *ptype;
1477 lock.l_whence = SEEK_SET;
1478 lock.l_start = *poffset;
1479 lock.l_len = *pcount;
1480 lock.l_pid = 0;
1481
1482 ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
1483
1484 if (ret == -1) {
1485 int sav = errno;
1486 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1487 (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1488 errno = sav;
1489 return False;
1490 }
1491
1492 *ptype = lock.l_type;
1493 *poffset = lock.l_start;
1494 *pcount = lock.l_len;
1495 *ppid = lock.l_pid;
1496
1497 DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1498 fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1499 return True;
1500}
1501
1502#undef DBGC_CLASS
1503#define DBGC_CLASS DBGC_ALL
1504
1505/*******************************************************************
1506 Is the name specified one of my netbios names.
1507 Returns true if it is equal, false otherwise.
1508********************************************************************/
1509
1510bool is_myname(const char *s)
1511{
1512 int n;
1513 bool ret = False;
1514
1515 for (n=0; my_netbios_names(n); n++) {
1516 if (strequal(my_netbios_names(n), s)) {
1517 ret=True;
1518 break;
1519 }
1520 }
1521 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1522 return(ret);
1523}
1524
1525/*******************************************************************
1526 Is the name specified our workgroup/domain.
1527 Returns true if it is equal, false otherwise.
1528********************************************************************/
1529
1530bool is_myworkgroup(const char *s)
1531{
1532 bool ret = False;
1533
1534 if (strequal(s, lp_workgroup())) {
1535 ret=True;
1536 }
1537
1538 DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
1539 return(ret);
1540}
1541
1542/*******************************************************************
1543 we distinguish between 2K and XP by the "Native Lan Manager" string
1544 WinXP => "Windows 2002 5.1"
1545 WinXP 64bit => "Windows XP 5.2"
1546 Win2k => "Windows 2000 5.0"
1547 NT4 => "Windows NT 4.0"
1548 Win9x => "Windows 4.0"
1549 Windows 2003 doesn't set the native lan manager string but
1550 they do set the domain to "Windows 2003 5.2" (probably a bug).
1551********************************************************************/
1552
1553void ra_lanman_string( const char *native_lanman )
1554{
1555 if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1556 set_remote_arch( RA_WINXP );
1557 else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1558 set_remote_arch( RA_WINXP64 );
1559 else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1560 set_remote_arch( RA_WIN2K3 );
1561}
1562
1563static const char *remote_arch_str;
1564
1565const char *get_remote_arch_str(void)
1566{
1567 if (!remote_arch_str) {
1568 return "UNKNOWN";
1569 }
1570 return remote_arch_str;
1571}
1572
1573/*******************************************************************
1574 Set the horrid remote_arch string based on an enum.
1575********************************************************************/
1576
1577void set_remote_arch(enum remote_arch_types type)
1578{
1579 ra_type = type;
1580 switch( type ) {
1581 case RA_WFWG:
1582 remote_arch_str = "WfWg";
1583 break;
1584 case RA_OS2:
1585 remote_arch_str = "OS2";
1586 break;
1587 case RA_WIN95:
1588 remote_arch_str = "Win95";
1589 break;
1590 case RA_WINNT:
1591 remote_arch_str = "WinNT";
1592 break;
1593 case RA_WIN2K:
1594 remote_arch_str = "Win2K";
1595 break;
1596 case RA_WINXP:
1597 remote_arch_str = "WinXP";
1598 break;
1599 case RA_WINXP64:
1600 remote_arch_str = "WinXP64";
1601 break;
1602 case RA_WIN2K3:
1603 remote_arch_str = "Win2K3";
1604 break;
1605 case RA_VISTA:
1606 remote_arch_str = "Vista";
1607 break;
1608 case RA_SAMBA:
1609 remote_arch_str = "Samba";
1610 break;
1611 case RA_CIFSFS:
1612 remote_arch_str = "CIFSFS";
1613 break;
1614 case RA_OSX:
1615 remote_arch_str = "OSX";
1616 break;
1617 default:
1618 ra_type = RA_UNKNOWN;
1619 remote_arch_str = "UNKNOWN";
1620 break;
1621 }
1622
1623 DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1624 remote_arch_str));
1625}
1626
1627/*******************************************************************
1628 Get the remote_arch type.
1629********************************************************************/
1630
1631enum remote_arch_types get_remote_arch(void)
1632{
1633 return ra_type;
1634}
1635
1636const char *tab_depth(int level, int depth)
1637{
1638 if( CHECK_DEBUGLVL(level) ) {
1639 dbgtext("%*s", depth*4, "");
1640 }
1641 return "";
1642}
1643
1644/*****************************************************************************
1645 Provide a checksum on a string
1646
1647 Input: s - the null-terminated character string for which the checksum
1648 will be calculated.
1649
1650 Output: The checksum value calculated for s.
1651*****************************************************************************/
1652
1653int str_checksum(const char *s)
1654{
1655 TDB_DATA key = string_tdb_data(s);
1656 return tdb_jenkins_hash(&key);
1657}
1658
1659/*****************************************************************
1660 Zero a memory area then free it. Used to catch bugs faster.
1661*****************************************************************/
1662
1663void zero_free(void *p, size_t size)
1664{
1665 memset(p, 0, size);
1666 SAFE_FREE(p);
1667}
1668
1669/*****************************************************************
1670 Set our open file limit to a requested max and return the limit.
1671*****************************************************************/
1672
1673int set_maxfiles(int requested_max)
1674{
1675#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1676 struct rlimit rlp;
1677 int saved_current_limit;
1678
1679 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1680 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1681 strerror(errno) ));
1682 /* just guess... */
1683 return requested_max;
1684 }
1685
1686 /*
1687 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1688 * account for the extra fd we need
1689 * as well as the log files and standard
1690 * handles etc. Save the limit we want to set in case
1691 * we are running on an OS that doesn't support this limit (AIX)
1692 * which always returns RLIM_INFINITY for rlp.rlim_max.
1693 */
1694
1695 /* Try raising the hard (max) limit to the requested amount. */
1696
1697#if defined(RLIM_INFINITY)
1698 if (rlp.rlim_max != RLIM_INFINITY) {
1699 int orig_max = rlp.rlim_max;
1700
1701 if ( rlp.rlim_max < requested_max )
1702 rlp.rlim_max = requested_max;
1703
1704 /* This failing is not an error - many systems (Linux) don't
1705 support our default request of 10,000 open files. JRA. */
1706
1707 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1708 DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
1709 (int)rlp.rlim_max, strerror(errno) ));
1710
1711 /* Set failed - restore original value from get. */
1712 rlp.rlim_max = orig_max;
1713 }
1714 }
1715#endif
1716
1717 /* Now try setting the soft (current) limit. */
1718
1719 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1720
1721 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1722 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
1723 (int)rlp.rlim_cur, strerror(errno) ));
1724 /* just guess... */
1725 return saved_current_limit;
1726 }
1727
1728 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1729 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1730 strerror(errno) ));
1731 /* just guess... */
1732 return saved_current_limit;
1733 }
1734
1735#if defined(RLIM_INFINITY)
1736 if(rlp.rlim_cur == RLIM_INFINITY)
1737 return saved_current_limit;
1738#endif
1739
1740 if((int)rlp.rlim_cur > saved_current_limit)
1741 return saved_current_limit;
1742
1743 return rlp.rlim_cur;
1744#else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1745 /*
1746 * No way to know - just guess...
1747 */
1748 return requested_max;
1749#endif
1750}
1751
1752/*****************************************************************
1753 malloc that aborts with smb_panic on fail or zero size.
1754 *****************************************************************/
1755
1756void *smb_xmalloc_array(size_t size, unsigned int count)
1757{
1758 void *p;
1759 if (size == 0) {
1760 smb_panic("smb_xmalloc_array: called with zero size");
1761 }
1762 if (count >= MAX_ALLOC_SIZE/size) {
1763 smb_panic("smb_xmalloc_array: alloc size too large");
1764 }
1765 if ((p = SMB_MALLOC(size*count)) == NULL) {
1766 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1767 (unsigned long)size, (unsigned long)count));
1768 smb_panic("smb_xmalloc_array: malloc failed");
1769 }
1770 return p;
1771}
1772
1773/*
1774 vasprintf that aborts on malloc fail
1775*/
1776
1777 int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1778{
1779 int n;
1780 va_list ap2;
1781
1782 va_copy(ap2, ap);
1783
1784 n = vasprintf(ptr, format, ap2);
1785 va_end(ap2);
1786 if (n == -1 || ! *ptr) {
1787 smb_panic("smb_xvasprintf: out of memory");
1788 }
1789 return n;
1790}
1791
1792/*****************************************************************
1793 Get local hostname and cache result.
1794*****************************************************************/
1795
1796char *myhostname(void)
1797{
1798 static char *ret;
1799 if (ret == NULL) {
1800 ret = get_myname(NULL);
1801 }
1802 return ret;
1803}
1804
1805/**
1806 * @brief Returns an absolute path to a file concatenating the provided
1807 * @a rootpath and @a basename
1808 *
1809 * @param name Filename, relative to @a rootpath
1810 *
1811 * @retval Pointer to a string containing the full path.
1812 **/
1813
1814static char *xx_path(const char *name, const char *rootpath)
1815{
1816 char *fname = NULL;
1817
1818 fname = talloc_strdup(talloc_tos(), rootpath);
1819 if (!fname) {
1820 return NULL;
1821 }
1822 trim_string(fname,"","/");
1823
1824 if (!directory_exist(fname)) {
1825 if (!mkdir(fname,0755))
1826 DEBUG(1, ("Unable to create directory %s for file %s. "
1827 "Error was %s\n", fname, name, strerror(errno)));
1828 }
1829
1830 return talloc_asprintf(talloc_tos(),
1831 "%s/%s",
1832 fname,
1833 name);
1834}
1835
1836/**
1837 * @brief Returns an absolute path to a file in the Samba lock directory.
1838 *
1839 * @param name File to find, relative to LOCKDIR.
1840 *
1841 * @retval Pointer to a talloc'ed string containing the full path.
1842 **/
1843
1844char *lock_path(const char *name)
1845{
1846 return xx_path(name, lp_lockdir());
1847}
1848
1849/**
1850 * @brief Returns an absolute path to a file in the Samba pid directory.
1851 *
1852 * @param name File to find, relative to PIDDIR.
1853 *
1854 * @retval Pointer to a talloc'ed string containing the full path.
1855 **/
1856
1857char *pid_path(const char *name)
1858{
1859 return xx_path(name, lp_piddir());
1860}
1861
1862/**
1863 * @brief Returns an absolute path to a file in the Samba lib directory.
1864 *
1865 * @param name File to find, relative to LIBDIR.
1866 *
1867 * @retval Pointer to a string containing the full path.
1868 **/
1869
1870char *lib_path(const char *name)
1871{
1872 return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_LIBDIR(), name);
1873}
1874
1875/**
1876 * @brief Returns an absolute path to a file in the Samba modules directory.
1877 *
1878 * @param name File to find, relative to MODULESDIR.
1879 *
1880 * @retval Pointer to a string containing the full path.
1881 **/
1882
1883char *modules_path(const char *name)
1884{
1885 return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_MODULESDIR(), name);
1886}
1887
1888/**
1889 * @brief Returns an absolute path to a file in the Samba data directory.
1890 *
1891 * @param name File to find, relative to CODEPAGEDIR.
1892 *
1893 * @retval Pointer to a talloc'ed string containing the full path.
1894 **/
1895
1896char *data_path(const char *name)
1897{
1898 return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_CODEPAGEDIR(), name);
1899}
1900
1901/**
1902 * @brief Returns an absolute path to a file in the Samba state directory.
1903 *
1904 * @param name File to find, relative to STATEDIR.
1905 *
1906 * @retval Pointer to a talloc'ed string containing the full path.
1907 **/
1908
1909char *state_path(const char *name)
1910{
1911 return xx_path(name, lp_statedir());
1912}
1913
1914/**
1915 * @brief Returns an absolute path to a file in the Samba cache directory.
1916 *
1917 * @param name File to find, relative to CACHEDIR.
1918 *
1919 * @retval Pointer to a talloc'ed string containing the full path.
1920 **/
1921
1922char *cache_path(const char *name)
1923{
1924 return xx_path(name, lp_cachedir());
1925}
1926
1927/**
1928 * @brief Returns the platform specific shared library extension.
1929 *
1930 * @retval Pointer to a const char * containing the extension.
1931 **/
1932
1933const char *shlib_ext(void)
1934{
1935 return get_dyn_SHLIBEXT();
1936}
1937
1938/*******************************************************************
1939 Given a filename - get its directory name
1940********************************************************************/
1941
1942bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1943 const char **name)
1944{
1945 char *p;
1946 ptrdiff_t len;
1947
1948 p = strrchr_m(dir, '/'); /* Find final '/', if any */
1949
1950 if (p == NULL) {
1951 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1952 return False;
1953 }
1954 if (name) {
1955 *name = dir;
1956 }
1957 return True;
1958 }
1959
1960 len = p-dir;
1961
1962 if (!(*parent = (char *)TALLOC_MEMDUP(mem_ctx, dir, len+1))) {
1963 return False;
1964 }
1965 (*parent)[len] = '\0';
1966
1967 if (name) {
1968 *name = p+1;
1969 }
1970 return True;
1971}
1972
1973/*******************************************************************
1974 Determine if a pattern contains any Microsoft wildcard characters.
1975*******************************************************************/
1976
1977bool ms_has_wild(const char *s)
1978{
1979 char c;
1980
1981 if (lp_posix_pathnames()) {
1982 /* With posix pathnames no characters are wild. */
1983 return False;
1984 }
1985
1986 while ((c = *s++)) {
1987 switch (c) {
1988 case '*':
1989 case '?':
1990 case '<':
1991 case '>':
1992 case '"':
1993 return True;
1994 }
1995 }
1996 return False;
1997}
1998
1999bool ms_has_wild_w(const smb_ucs2_t *s)
2000{
2001 smb_ucs2_t c;
2002 if (!s) return False;
2003 while ((c = *s++)) {
2004 switch (c) {
2005 case UCS2_CHAR('*'):
2006 case UCS2_CHAR('?'):
2007 case UCS2_CHAR('<'):
2008 case UCS2_CHAR('>'):
2009 case UCS2_CHAR('"'):
2010 return True;
2011 }
2012 }
2013 return False;
2014}
2015
2016/*******************************************************************
2017 A wrapper that handles case sensitivity and the special handling
2018 of the ".." name.
2019*******************************************************************/
2020
2021bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
2022{
2023 if (ISDOTDOT(string))
2024 string = ".";
2025 if (ISDOT(pattern))
2026 return False;
2027
2028 return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
2029}
2030
2031/*******************************************************************
2032 A wrapper that handles case sensitivity and the special handling
2033 of the ".." name. Varient that is only called by old search code which requires
2034 pattern translation.
2035*******************************************************************/
2036
2037bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
2038{
2039 if (ISDOTDOT(string))
2040 string = ".";
2041 if (ISDOT(pattern))
2042 return False;
2043
2044 return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
2045}
2046
2047/*******************************************************************
2048 A wrapper that handles a list of patters and calls mask_match()
2049 on each. Returns True if any of the patterns match.
2050*******************************************************************/
2051
2052bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
2053{
2054 while (listLen-- > 0) {
2055 if (mask_match(string, *list++, is_case_sensitive))
2056 return True;
2057 }
2058 return False;
2059}
2060
2061/*********************************************************
2062 Recursive routine that is called by unix_wild_match.
2063*********************************************************/
2064
2065static bool unix_do_match(const char *regexp, const char *str)
2066{
2067 const char *p;
2068
2069 for( p = regexp; *p && *str; ) {
2070
2071 switch(*p) {
2072 case '?':
2073 str++;
2074 p++;
2075 break;
2076
2077 case '*':
2078
2079 /*
2080 * Look for a character matching
2081 * the one after the '*'.
2082 */
2083 p++;
2084 if(!*p)
2085 return true; /* Automatic match */
2086 while(*str) {
2087
2088 while(*str && (*p != *str))
2089 str++;
2090
2091 /*
2092 * Patch from weidel@multichart.de. In the case of the regexp
2093 * '*XX*' we want to ensure there are at least 2 'X' characters
2094 * in the string after the '*' for a match to be made.
2095 */
2096
2097 {
2098 int matchcount=0;
2099
2100 /*
2101 * Eat all the characters that match, but count how many there were.
2102 */
2103
2104 while(*str && (*p == *str)) {
2105 str++;
2106 matchcount++;
2107 }
2108
2109 /*
2110 * Now check that if the regexp had n identical characters that
2111 * matchcount had at least that many matches.
2112 */
2113
2114 while ( *(p+1) && (*(p+1) == *p)) {
2115 p++;
2116 matchcount--;
2117 }
2118
2119 if ( matchcount <= 0 )
2120 return false;
2121 }
2122
2123 str--; /* We've eaten the match char after the '*' */
2124
2125 if(unix_do_match(p, str))
2126 return true;
2127
2128 if(!*str)
2129 return false;
2130 else
2131 str++;
2132 }
2133 return false;
2134
2135 default:
2136 if(*str != *p)
2137 return false;
2138 str++;
2139 p++;
2140 break;
2141 }
2142 }
2143
2144 if(!*p && !*str)
2145 return true;
2146
2147 if (!*p && str[0] == '.' && str[1] == 0)
2148 return true;
2149
2150 if (!*str && *p == '?') {
2151 while (*p == '?')
2152 p++;
2153 return(!*p);
2154 }
2155
2156 if(!*str && (*p == '*' && p[1] == '\0'))
2157 return true;
2158
2159 return false;
2160}
2161
2162/*******************************************************************
2163 Simple case insensitive interface to a UNIX wildcard matcher.
2164 Returns True if match, False if not.
2165*******************************************************************/
2166
2167bool unix_wild_match(const char *pattern, const char *string)
2168{
2169 TALLOC_CTX *ctx = talloc_stackframe();
2170 char *p2;
2171 char *s2;
2172 char *p;
2173 bool ret = false;
2174
2175 p2 = talloc_strdup(ctx,pattern);
2176 s2 = talloc_strdup(ctx,string);
2177 if (!p2 || !s2) {
2178 TALLOC_FREE(ctx);
2179 return false;
2180 }
2181 strlower_m(p2);
2182 strlower_m(s2);
2183
2184 /* Remove any *? and ** from the pattern as they are meaningless */
2185 for(p = p2; *p; p++) {
2186 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
2187 memmove(&p[1], &p[2], strlen(&p[2])+1);
2188 }
2189 }
2190
2191 if (strequal(p2,"*")) {
2192 TALLOC_FREE(ctx);
2193 return true;
2194 }
2195
2196 ret = unix_do_match(p2, s2);
2197 TALLOC_FREE(ctx);
2198 return ret;
2199}
2200
2201/**********************************************************************
2202 Converts a name to a fully qualified domain name.
2203 Returns true if lookup succeeded, false if not (then fqdn is set to name)
2204 Note we deliberately use gethostbyname here, not getaddrinfo as we want
2205 to examine the h_aliases and I don't know how to do that with getaddrinfo.
2206***********************************************************************/
2207
2208bool name_to_fqdn(fstring fqdn, const char *name)
2209{
2210 char *full = NULL;
2211 struct hostent *hp = gethostbyname(name);
2212
2213 if (!hp || !hp->h_name || !*hp->h_name) {
2214 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
2215 fstrcpy(fqdn, name);
2216 return false;
2217 }
2218
2219 /* Find out if the fqdn is returned as an alias
2220 * to cope with /etc/hosts files where the first
2221 * name is not the fqdn but the short name */
2222 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
2223 int i;
2224 for (i = 0; hp->h_aliases[i]; i++) {
2225 if (strchr_m(hp->h_aliases[i], '.')) {
2226 full = hp->h_aliases[i];
2227 break;
2228 }
2229 }
2230 }
2231 if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
2232 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
2233 DEBUGADD(1, (" Specifing the machine hostname for address 127.0.0.1 may lead\n"));
2234 DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
2235 DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
2236 full = hp->h_name;
2237 }
2238 if (!full) {
2239 full = hp->h_name;
2240 }
2241
2242 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
2243 fstrcpy(fqdn, full);
2244 return true;
2245}
2246
2247/**********************************************************************
2248 Append a DATA_BLOB to a talloc'ed object
2249***********************************************************************/
2250
2251void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
2252{
2253 size_t old_size = 0;
2254 char *result;
2255
2256 if (blob.length == 0) {
2257 return buf;
2258 }
2259
2260 if (buf != NULL) {
2261 old_size = talloc_get_size(buf);
2262 }
2263
2264 result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
2265 if (result == NULL) {
2266 return NULL;
2267 }
2268
2269 memcpy(result + old_size, blob.data, blob.length);
2270 return result;
2271}
2272
2273uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
2274{
2275 switch (share_access & ~FILE_SHARE_DELETE) {
2276 case FILE_SHARE_NONE:
2277 return DENY_ALL;
2278 case FILE_SHARE_READ:
2279 return DENY_WRITE;
2280 case FILE_SHARE_WRITE:
2281 return DENY_READ;
2282 case FILE_SHARE_READ|FILE_SHARE_WRITE:
2283 return DENY_NONE;
2284 }
2285 if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
2286 return DENY_DOS;
2287 } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
2288 return DENY_FCB;
2289 }
2290
2291 return (uint32)-1;
2292}
2293
2294pid_t procid_to_pid(const struct server_id *proc)
2295{
2296 return proc->pid;
2297}
2298
2299static uint32 my_vnn = NONCLUSTER_VNN;
2300
2301void set_my_vnn(uint32 vnn)
2302{
2303 DEBUG(10, ("vnn pid %d = %u\n", (int)sys_getpid(), (unsigned int)vnn));
2304 my_vnn = vnn;
2305}
2306
2307uint32 get_my_vnn(void)
2308{
2309 return my_vnn;
2310}
2311
2312static uint64_t my_unique_id = 0;
2313
2314void set_my_unique_id(uint64_t unique_id)
2315{
2316 my_unique_id = unique_id;
2317}
2318
2319struct server_id pid_to_procid(pid_t pid)
2320{
2321 struct server_id result;
2322 result.pid = pid;
2323 result.unique_id = my_unique_id;
2324 result.vnn = my_vnn;
2325 return result;
2326}
2327
2328struct server_id procid_self(void)
2329{
2330 return pid_to_procid(sys_getpid());
2331}
2332
2333bool procid_equal(const struct server_id *p1, const struct server_id *p2)
2334{
2335 if (p1->pid != p2->pid)
2336 return False;
2337 if (p1->vnn != p2->vnn)
2338 return False;
2339 return True;
2340}
2341
2342bool cluster_id_equal(const struct server_id *id1,
2343 const struct server_id *id2)
2344{
2345 return procid_equal(id1, id2);
2346}
2347
2348bool procid_is_me(const struct server_id *pid)
2349{
2350 if (pid->pid != sys_getpid())
2351 return False;
2352 if (pid->vnn != my_vnn)
2353 return False;
2354 return True;
2355}
2356
2357struct server_id interpret_pid(const char *pid_string)
2358{
2359 struct server_id result;
2360 int pid;
2361 unsigned int vnn;
2362 if (sscanf(pid_string, "%u:%d", &vnn, &pid) == 2) {
2363 result.vnn = vnn;
2364 result.pid = pid;
2365 }
2366 else if (sscanf(pid_string, "%d", &pid) == 1) {
2367 result.vnn = get_my_vnn();
2368 result.pid = pid;
2369 }
2370 else {
2371 result.vnn = NONCLUSTER_VNN;
2372 result.pid = -1;
2373 }
2374 /* Assigning to result.pid may have overflowed
2375 Map negative pid to -1: i.e. error */
2376 if (result.pid < 0) {
2377 result.pid = -1;
2378 }
2379 result.unique_id = 0;
2380 return result;
2381}
2382
2383char *procid_str(TALLOC_CTX *mem_ctx, const struct server_id *pid)
2384{
2385 if (pid->vnn == NONCLUSTER_VNN) {
2386 return talloc_asprintf(mem_ctx,
2387 "%d",
2388 (int)pid->pid);
2389 }
2390 else {
2391 return talloc_asprintf(mem_ctx,
2392 "%u:%d",
2393 (unsigned)pid->vnn,
2394 (int)pid->pid);
2395 }
2396}
2397
2398char *procid_str_static(const struct server_id *pid)
2399{
2400 return procid_str(talloc_tos(), pid);
2401}
2402
2403bool procid_valid(const struct server_id *pid)
2404{
2405 return (pid->pid != -1);
2406}
2407
2408bool procid_is_local(const struct server_id *pid)
2409{
2410 return pid->vnn == my_vnn;
2411}
2412
2413/****************************************************************
2414 Check if offset/length fit into bufsize. Should probably be
2415 merged with is_offset_safe, but this would require a rewrite
2416 of lanman.c. Later :-)
2417****************************************************************/
2418
2419bool trans_oob(uint32_t bufsize, uint32_t offset, uint32_t length)
2420{
2421 if ((offset + length < offset) || (offset + length < length)) {
2422 /* wrap */
2423 return true;
2424 }
2425 if ((offset > bufsize) || (offset + length > bufsize)) {
2426 /* overflow */
2427 return true;
2428 }
2429 return false;
2430}
2431
2432/****************************************************************
2433 Check if an offset into a buffer is safe.
2434 If this returns True it's safe to indirect into the byte at
2435 pointer ptr+off.
2436****************************************************************/
2437
2438bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2439{
2440 const char *end_base = buf_base + buf_len;
2441 char *end_ptr = ptr + off;
2442
2443 if (!buf_base || !ptr) {
2444 return False;
2445 }
2446
2447 if (end_base < buf_base || end_ptr < ptr) {
2448 return False; /* wrap. */
2449 }
2450
2451 if (end_ptr < end_base) {
2452 return True;
2453 }
2454 return False;
2455}
2456
2457/****************************************************************
2458 Return a safe pointer into a buffer, or NULL.
2459****************************************************************/
2460
2461char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2462{
2463 return is_offset_safe(buf_base, buf_len, ptr, off) ?
2464 ptr + off : NULL;
2465}
2466
2467/****************************************************************
2468 Return a safe pointer into a string within a buffer, or NULL.
2469****************************************************************/
2470
2471char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2472{
2473 if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2474 return NULL;
2475 }
2476 /* Check if a valid string exists at this offset. */
2477 if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2478 return NULL;
2479 }
2480 return ptr + off;
2481}
2482
2483/****************************************************************
2484 Return an SVAL at a pointer, or failval if beyond the end.
2485****************************************************************/
2486
2487int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2488{
2489 /*
2490 * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2491 * NOT ptr[2].
2492 */
2493 if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2494 return failval;
2495 }
2496 return SVAL(ptr,off);
2497}
2498
2499/****************************************************************
2500 Return an IVAL at a pointer, or failval if beyond the end.
2501****************************************************************/
2502
2503int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2504{
2505 /*
2506 * Note we use off+3 here, not off+4 as IVAL accesses
2507 * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2508 */
2509 if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2510 return failval;
2511 }
2512 return IVAL(ptr,off);
2513}
2514
2515/****************************************************************
2516 Split DOM\user into DOM and user. Do not mix with winbind variants of that
2517 call (they take care of winbind separator and other winbind specific settings).
2518****************************************************************/
2519
2520void split_domain_user(TALLOC_CTX *mem_ctx,
2521 const char *full_name,
2522 char **domain,
2523 char **user)
2524{
2525 const char *p = NULL;
2526
2527 p = strchr_m(full_name, '\\');
2528
2529 if (p != NULL) {
2530 *domain = talloc_strndup(mem_ctx, full_name,
2531 PTR_DIFF(p, full_name));
2532 *user = talloc_strdup(mem_ctx, p+1);
2533 } else {
2534 *domain = talloc_strdup(mem_ctx, "");
2535 *user = talloc_strdup(mem_ctx, full_name);
2536 }
2537}
2538
2539#if 0
2540
2541Disable these now we have checked all code paths and ensured
2542NULL returns on zero request. JRA.
2543
2544/****************************************************************
2545 talloc wrapper functions that guarentee a null pointer return
2546 if size == 0.
2547****************************************************************/
2548
2549#ifndef MAX_TALLOC_SIZE
2550#define MAX_TALLOC_SIZE 0x10000000
2551#endif
2552
2553/*
2554 * talloc and zero memory.
2555 * - returns NULL if size is zero.
2556 */
2557
2558void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name)
2559{
2560 void *p;
2561
2562 if (size == 0) {
2563 return NULL;
2564 }
2565
2566 p = talloc_named_const(ctx, size, name);
2567
2568 if (p) {
2569 memset(p, '\0', size);
2570 }
2571
2572 return p;
2573}
2574
2575/*
2576 * memdup with a talloc.
2577 * - returns NULL if size is zero.
2578 */
2579
2580void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name)
2581{
2582 void *newp;
2583
2584 if (size == 0) {
2585 return NULL;
2586 }
2587
2588 newp = talloc_named_const(t, size, name);
2589 if (newp) {
2590 memcpy(newp, p, size);
2591 }
2592
2593 return newp;
2594}
2595
2596/*
2597 * alloc an array, checking for integer overflow in the array size.
2598 * - returns NULL if count or el_size are zero.
2599 */
2600
2601void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
2602{
2603 if (count >= MAX_TALLOC_SIZE/el_size) {
2604 return NULL;
2605 }
2606
2607 if (el_size == 0 || count == 0) {
2608 return NULL;
2609 }
2610
2611 return talloc_named_const(ctx, el_size * count, name);
2612}
2613
2614/*
2615 * alloc an zero array, checking for integer overflow in the array size
2616 * - returns NULL if count or el_size are zero.
2617 */
2618
2619void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
2620{
2621 if (count >= MAX_TALLOC_SIZE/el_size) {
2622 return NULL;
2623 }
2624
2625 if (el_size == 0 || count == 0) {
2626 return NULL;
2627 }
2628
2629 return _talloc_zero(ctx, el_size * count, name);
2630}
2631
2632/*
2633 * Talloc wrapper that returns NULL if size == 0.
2634 */
2635void *talloc_zeronull(const void *context, size_t size, const char *name)
2636{
2637 if (size == 0) {
2638 return NULL;
2639 }
2640 return talloc_named_const(context, size, name);
2641}
2642#endif
2643
2644/****************************************************************
2645 strip off leading '\\' from a hostname
2646****************************************************************/
2647
2648const char *strip_hostname(const char *s)
2649{
2650 if (!s) {
2651 return NULL;
2652 }
2653
2654 if (strlen_m(s) < 3) {
2655 return s;
2656 }
2657
2658 if (s[0] == '\\') s++;
2659 if (s[0] == '\\') s++;
2660
2661 return s;
2662}
2663
2664bool tevent_req_poll_ntstatus(struct tevent_req *req,
2665 struct tevent_context *ev,
2666 NTSTATUS *status)
2667{
2668 bool ret = tevent_req_poll(req, ev);
2669 if (!ret) {
2670 *status = map_nt_error_from_unix(errno);
2671 }
2672 return ret;
2673}
2674
2675bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2676{
2677 if (!NT_STATUS_IS_OK(err1)) {
2678 *result = err1;
2679 return true;
2680 }
2681 if (!NT_STATUS_IS_OK(err2)) {
2682 *result = err2;
2683 return true;
2684 }
2685 return false;
2686}
2687
2688int timeval_to_msec(struct timeval t)
2689{
2690 return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2691}
2692
2693/*******************************************************************
2694 Check a given DOS pathname is valid for a share.
2695********************************************************************/
2696
2697char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2698{
2699 char *ptr = NULL;
2700
2701 if (!dos_pathname) {
2702 return NULL;
2703 }
2704
2705 ptr = talloc_strdup(ctx, dos_pathname);
2706 if (!ptr) {
2707 return NULL;
2708 }
2709 /* Convert any '\' paths to '/' */
2710 unix_format(ptr);
2711 ptr = unix_clean_name(ctx, ptr);
2712 if (!ptr) {
2713 return NULL;
2714 }
2715
2716 /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2717 if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2718 ptr += 2;
2719
2720 /* Only absolute paths allowed. */
2721 if (*ptr != '/')
2722 return NULL;
2723
2724 return ptr;
2725}
2726
2727/*******************************************************************
2728 Return True if the filename is one of the special executable types.
2729********************************************************************/
2730
2731bool is_executable(const char *fname)
2732{
2733 if ((fname = strrchr_m(fname,'.'))) {
2734 if (strequal(fname,".com") ||
2735 strequal(fname,".dll") ||
2736 strequal(fname,".exe") ||
2737 strequal(fname,".sym")) {
2738 return True;
2739 }
2740 }
2741 return False;
2742}
2743
2744/****************************************************************************
2745 Open a file with a share mode - old openX method - map into NTCreate.
2746****************************************************************************/
2747
2748bool map_open_params_to_ntcreate(const char *smb_base_fname,
2749 int deny_mode, int open_func,
2750 uint32 *paccess_mask,
2751 uint32 *pshare_mode,
2752 uint32 *pcreate_disposition,
2753 uint32 *pcreate_options,
2754 uint32_t *pprivate_flags)
2755{
2756 uint32 access_mask;
2757 uint32 share_mode;
2758 uint32 create_disposition;
2759 uint32 create_options = FILE_NON_DIRECTORY_FILE;
2760 uint32_t private_flags = 0;
2761
2762 DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2763 "open_func = 0x%x\n",
2764 smb_base_fname, (unsigned int)deny_mode,
2765 (unsigned int)open_func ));
2766
2767 /* Create the NT compatible access_mask. */
2768 switch (GET_OPENX_MODE(deny_mode)) {
2769 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2770 case DOS_OPEN_RDONLY:
2771 access_mask = FILE_GENERIC_READ;
2772 break;
2773 case DOS_OPEN_WRONLY:
2774 access_mask = FILE_GENERIC_WRITE;
2775 break;
2776 case DOS_OPEN_RDWR:
2777 case DOS_OPEN_FCB:
2778 access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2779 break;
2780 default:
2781 DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2782 (unsigned int)GET_OPENX_MODE(deny_mode)));
2783 return False;
2784 }
2785
2786 /* Create the NT compatible create_disposition. */
2787 switch (open_func) {
2788 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2789 create_disposition = FILE_CREATE;
2790 break;
2791
2792 case OPENX_FILE_EXISTS_OPEN:
2793 create_disposition = FILE_OPEN;
2794 break;
2795
2796 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2797 create_disposition = FILE_OPEN_IF;
2798 break;
2799
2800 case OPENX_FILE_EXISTS_TRUNCATE:
2801 create_disposition = FILE_OVERWRITE;
2802 break;
2803
2804 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2805 create_disposition = FILE_OVERWRITE_IF;
2806 break;
2807
2808 default:
2809 /* From samba4 - to be confirmed. */
2810 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2811 create_disposition = FILE_CREATE;
2812 break;
2813 }
2814 DEBUG(10,("map_open_params_to_ntcreate: bad "
2815 "open_func 0x%x\n", (unsigned int)open_func));
2816 return False;
2817 }
2818
2819 /* Create the NT compatible share modes. */
2820 switch (GET_DENY_MODE(deny_mode)) {
2821 case DENY_ALL:
2822 share_mode = FILE_SHARE_NONE;
2823 break;
2824
2825 case DENY_WRITE:
2826 share_mode = FILE_SHARE_READ;
2827 break;
2828
2829 case DENY_READ:
2830 share_mode = FILE_SHARE_WRITE;
2831 break;
2832
2833 case DENY_NONE:
2834 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2835 break;
2836
2837 case DENY_DOS:
2838 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2839 if (is_executable(smb_base_fname)) {
2840 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2841 } else {
2842 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2843 share_mode = FILE_SHARE_READ;
2844 } else {
2845 share_mode = FILE_SHARE_NONE;
2846 }
2847 }
2848 break;
2849
2850 case DENY_FCB:
2851 private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2852 share_mode = FILE_SHARE_NONE;
2853 break;
2854
2855 default:
2856 DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2857 (unsigned int)GET_DENY_MODE(deny_mode) ));
2858 return False;
2859 }
2860
2861 DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2862 "share_mode = 0x%x, create_disposition = 0x%x, "
2863 "create_options = 0x%x private_flags = 0x%x\n",
2864 smb_base_fname,
2865 (unsigned int)access_mask,
2866 (unsigned int)share_mode,
2867 (unsigned int)create_disposition,
2868 (unsigned int)create_options,
2869 (unsigned int)private_flags));
2870
2871 if (paccess_mask) {
2872 *paccess_mask = access_mask;
2873 }
2874 if (pshare_mode) {
2875 *pshare_mode = share_mode;
2876 }
2877 if (pcreate_disposition) {
2878 *pcreate_disposition = create_disposition;
2879 }
2880 if (pcreate_options) {
2881 *pcreate_options = create_options;
2882 }
2883 if (pprivate_flags) {
2884 *pprivate_flags = private_flags;
2885 }
2886
2887 return True;
2888
2889}
Note: See TracBrowser for help on using the repository browser.