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

Last change on this file was 740, checked in by Silvan Scherrer, 13 years ago

Samba Server: update vendor to 3.6.0

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