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