[GLUE] Rsync SAMBA_3_0 SVN r25598 in order to create the v3-0-test branch.
[Samba.git] / source / smbd / service.c
blobbfe9649ea4a987ed5f58dca6f5f3984588c02055
1 /*
2 Unix SMB/CIFS implementation.
3 service (connection) opening and closing
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 extern userdom_struct current_user_info;
25 static BOOL canonicalize_path(connection_struct *conn, pstring path)
27 #ifdef REALPATH_TAKES_NULL
28 char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);
29 if (!resolved_name) {
30 return False;
32 pstrcpy(path, resolved_name);
33 SAFE_FREE(resolved_name);
34 return True;
35 #else
36 #ifdef PATH_MAX
37 char resolved_name_buf[PATH_MAX+1];
38 #else
39 pstring resolved_name_buf;
40 #endif
41 char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf);
42 if (!resolved_name) {
43 return False;
45 pstrcpy(path, resolved_name);
46 return True;
47 #endif /* REALPATH_TAKES_NULL */
50 /****************************************************************************
51 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
52 absolute path stating in / and not ending in /.
53 Observent people will notice a similarity between this and check_path_syntax :-).
54 ****************************************************************************/
56 void set_conn_connectpath(connection_struct *conn, const pstring connectpath)
58 pstring destname;
59 char *d = destname;
60 const char *s = connectpath;
61 BOOL start_of_name_component = True;
63 *d++ = '/'; /* Always start with root. */
65 while (*s) {
66 if (*s == '/') {
67 /* Eat multiple '/' */
68 while (*s == '/') {
69 s++;
71 if ((d > destname + 1) && (*s != '\0')) {
72 *d++ = '/';
74 start_of_name_component = True;
75 continue;
78 if (start_of_name_component) {
79 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
80 /* Uh oh - "/../" or "/..\0" ! */
82 /* Go past the ../ or .. */
83 if (s[2] == '/') {
84 s += 3;
85 } else {
86 s += 2; /* Go past the .. */
89 /* If we just added a '/' - delete it */
90 if ((d > destname) && (*(d-1) == '/')) {
91 *(d-1) = '\0';
92 d--;
95 /* Are we at the start ? Can't go back further if so. */
96 if (d <= destname) {
97 *d++ = '/'; /* Can't delete root */
98 continue;
100 /* Go back one level... */
101 /* Decrement d first as d points to the *next* char to write into. */
102 for (d--; d > destname; d--) {
103 if (*d == '/') {
104 break;
107 /* We're still at the start of a name component, just the previous one. */
108 continue;
109 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
110 /* Component of pathname can't be "." only - skip the '.' . */
111 if (s[1] == '/') {
112 s += 2;
113 } else {
114 s++;
116 continue;
120 if (!(*s & 0x80)) {
121 *d++ = *s++;
122 } else {
123 size_t siz;
124 /* Get the size of the next MB character. */
125 next_codepoint(s,&siz);
126 switch(siz) {
127 case 5:
128 *d++ = *s++;
129 /*fall through*/
130 case 4:
131 *d++ = *s++;
132 /*fall through*/
133 case 3:
134 *d++ = *s++;
135 /*fall through*/
136 case 2:
137 *d++ = *s++;
138 /*fall through*/
139 case 1:
140 *d++ = *s++;
141 break;
142 default:
143 break;
146 start_of_name_component = False;
148 *d = '\0';
150 /* And must not end in '/' */
151 if (d > destname + 1 && (*(d-1) == '/')) {
152 *(d-1) = '\0';
155 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
156 lp_servicename(SNUM(conn)), destname ));
158 string_set(&conn->connectpath, destname);
161 /****************************************************************************
162 Load parameters specific to a connection/service.
163 ****************************************************************************/
165 BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
167 static connection_struct *last_conn;
168 static uint16 last_flags;
169 int snum;
171 if (!conn) {
172 last_conn = NULL;
173 return(False);
176 conn->lastused_count++;
178 snum = SNUM(conn);
180 if (do_chdir &&
181 vfs_ChDir(conn,conn->connectpath) != 0 &&
182 vfs_ChDir(conn,conn->origpath) != 0) {
183 DEBUG(0,("chdir (%s) failed\n",
184 conn->connectpath));
185 return(False);
188 if ((conn == last_conn) && (last_flags == flags)) {
189 return(True);
192 last_conn = conn;
193 last_flags = flags;
195 /* Obey the client case sensitivity requests - only for clients that support it. */
196 switch (lp_casesensitive(snum)) {
197 case Auto:
199 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
200 enum remote_arch_types ra_type = get_remote_arch();
201 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
202 /* Client can't support per-packet case sensitive pathnames. */
203 conn->case_sensitive = False;
204 } else {
205 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
208 break;
209 case True:
210 conn->case_sensitive = True;
211 break;
212 default:
213 conn->case_sensitive = False;
214 break;
216 return(True);
219 /****************************************************************************
220 Add a home service. Returns the new service number or -1 if fail.
221 ****************************************************************************/
223 int add_home_service(const char *service, const char *username, const char *homedir)
225 int iHomeService;
227 if (!service || !homedir)
228 return -1;
230 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
231 return -1;
234 * If this is a winbindd provided username, remove
235 * the domain component before adding the service.
236 * Log a warning if the "path=" parameter does not
237 * include any macros.
241 const char *p = strchr(service,*lp_winbind_separator());
243 /* We only want the 'user' part of the string */
244 if (p) {
245 service = p + 1;
249 if (!lp_add_home(service, iHomeService, username, homedir)) {
250 return -1;
253 return lp_servicenumber(service);
259 * Find a service entry.
261 * @param service is modified (to canonical form??)
264 int find_service(fstring service)
266 int iService;
268 all_string_sub(service,"\\","/",0);
270 iService = lp_servicenumber(service);
272 /* now handle the special case of a home directory */
273 if (iService < 0) {
274 char *phome_dir = get_user_home_dir(service);
276 if(!phome_dir) {
278 * Try mapping the servicename, it may
279 * be a Windows to unix mapped user name.
281 if(map_username(service))
282 phome_dir = get_user_home_dir(service);
285 DEBUG(3,("checking for home directory %s gave %s\n",service,
286 phome_dir?phome_dir:"(NULL)"));
288 iService = add_home_service(service,service /* 'username' */, phome_dir);
291 /* If we still don't have a service, attempt to add it as a printer. */
292 if (iService < 0) {
293 int iPrinterService;
295 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
296 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
297 if (pcap_printername_ok(service)) {
298 DEBUG(3,("%s is a valid printer name\n", service));
299 DEBUG(3,("adding %s as a printer service\n", service));
300 lp_add_printer(service, iPrinterService);
301 iService = lp_servicenumber(service);
302 if (iService < 0) {
303 DEBUG(0,("failed to add %s as a printer service!\n", service));
305 } else {
306 DEBUG(3,("%s is not a valid printer name\n", service));
311 /* Check for default vfs service? Unsure whether to implement this */
312 if (iService < 0) {
315 /* Is it a usershare service ? */
316 if (iService < 0 && *lp_usershare_path()) {
317 /* Ensure the name is canonicalized. */
318 strlower_m(service);
319 iService = load_usershare_service(service);
322 /* just possibly it's a default service? */
323 if (iService < 0) {
324 char *pdefservice = lp_defaultservice();
325 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
327 * We need to do a local copy here as lp_defaultservice()
328 * returns one of the rotating lp_string buffers that
329 * could get overwritten by the recursive find_service() call
330 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
332 pstring defservice;
333 pstrcpy(defservice, pdefservice);
335 /* Disallow anything except explicit share names. */
336 if (strequal(defservice,HOMES_NAME) ||
337 strequal(defservice, PRINTERS_NAME) ||
338 strequal(defservice, "IPC$")) {
339 goto fail;
342 iService = find_service(defservice);
343 if (iService >= 0) {
344 all_string_sub(service, "_","/",0);
345 iService = lp_add_service(service, iService);
350 if (iService >= 0) {
351 if (!VALID_SNUM(iService)) {
352 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
353 iService = -1;
357 fail:
359 if (iService < 0)
360 DEBUG(3,("find_service() failed to find service %s\n", service));
362 return (iService);
366 /****************************************************************************
367 do some basic sainity checks on the share.
368 This function modifies dev, ecode.
369 ****************************************************************************/
371 static NTSTATUS share_sanity_checks(int snum, fstring dev)
374 if (!lp_snum_ok(snum) ||
375 !check_access(smbd_server_fd(),
376 lp_hostsallow(snum), lp_hostsdeny(snum))) {
377 return NT_STATUS_ACCESS_DENIED;
380 if (dev[0] == '?' || !dev[0]) {
381 if (lp_print_ok(snum)) {
382 fstrcpy(dev,"LPT1:");
383 } else if (strequal(lp_fstype(snum), "IPC")) {
384 fstrcpy(dev, "IPC");
385 } else {
386 fstrcpy(dev,"A:");
390 strupper_m(dev);
392 if (lp_print_ok(snum)) {
393 if (!strequal(dev, "LPT1:")) {
394 return NT_STATUS_BAD_DEVICE_TYPE;
396 } else if (strequal(lp_fstype(snum), "IPC")) {
397 if (!strequal(dev, "IPC")) {
398 return NT_STATUS_BAD_DEVICE_TYPE;
400 } else if (!strequal(dev, "A:")) {
401 return NT_STATUS_BAD_DEVICE_TYPE;
404 /* Behave as a printer if we are supposed to */
405 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
406 fstrcpy(dev, "LPT1:");
409 return NT_STATUS_OK;
412 static NTSTATUS find_forced_user(connection_struct *conn, BOOL vuser_is_guest, fstring username)
414 int snum = conn->params->service;
415 char *fuser, *found_username;
416 NTSTATUS result;
418 if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
419 lp_servicename(snum)))) {
420 return NT_STATUS_NO_MEMORY;
423 result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
424 &conn->uid, &conn->gid, &found_username,
425 &conn->nt_user_token);
426 if (!NT_STATUS_IS_OK(result)) {
427 return result;
430 fstrcpy(username, found_username);
432 TALLOC_FREE(fuser);
433 TALLOC_FREE(found_username);
434 return NT_STATUS_OK;
438 * Go through lookup_name etc to find the force'd group.
440 * Create a new token from src_token, replacing the primary group sid with the
441 * one found.
444 static NTSTATUS find_forced_group(BOOL force_user,
445 int snum, const char *username,
446 DOM_SID *pgroup_sid,
447 gid_t *pgid)
449 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
450 TALLOC_CTX *mem_ctx;
451 DOM_SID group_sid;
452 enum lsa_SidType type;
453 char *groupname;
454 BOOL user_must_be_member = False;
455 gid_t gid;
457 ZERO_STRUCTP(pgroup_sid);
458 *pgid = (gid_t)-1;
460 mem_ctx = talloc_new(NULL);
461 if (mem_ctx == NULL) {
462 DEBUG(0, ("talloc_new failed\n"));
463 return NT_STATUS_NO_MEMORY;
466 groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
467 if (groupname == NULL) {
468 DEBUG(1, ("talloc_strdup failed\n"));
469 result = NT_STATUS_NO_MEMORY;
470 goto done;
473 if (groupname[0] == '+') {
474 user_must_be_member = True;
475 groupname += 1;
478 groupname = talloc_string_sub(mem_ctx, groupname,
479 "%S", lp_servicename(snum));
481 if (!lookup_name_smbconf(mem_ctx, groupname,
482 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
483 NULL, NULL, &group_sid, &type)) {
484 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
485 groupname));
486 goto done;
489 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
490 (type != SID_NAME_WKN_GRP)) {
491 DEBUG(10, ("%s is a %s, not a group\n", groupname,
492 sid_type_lookup(type)));
493 goto done;
496 if (!sid_to_gid(&group_sid, &gid)) {
497 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
498 sid_string_static(&group_sid), groupname));
499 goto done;
503 * If the user has been forced and the forced group starts with a '+',
504 * then we only set the group to be the forced group if the forced
505 * user is a member of that group. Otherwise, the meaning of the '+'
506 * would be ignored.
509 if (force_user && user_must_be_member) {
510 if (user_in_group_sid(username, &group_sid)) {
511 sid_copy(pgroup_sid, &group_sid);
512 *pgid = gid;
513 DEBUG(3,("Forced group %s for member %s\n",
514 groupname, username));
515 } else {
516 DEBUG(0,("find_forced_group: forced user %s is not a member "
517 "of forced group %s. Disallowing access.\n",
518 username, groupname ));
519 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
520 goto done;
522 } else {
523 sid_copy(pgroup_sid, &group_sid);
524 *pgid = gid;
525 DEBUG(3,("Forced group %s\n", groupname));
528 result = NT_STATUS_OK;
529 done:
530 TALLOC_FREE(mem_ctx);
531 return result;
534 /****************************************************************************
535 Make a connection, given the snum to connect to, and the vuser of the
536 connecting user if appropriate.
537 ****************************************************************************/
539 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
540 DATA_BLOB password,
541 const char *pdev,
542 NTSTATUS *status)
544 struct passwd *pass = NULL;
545 BOOL guest = False;
546 connection_struct *conn;
547 SMB_STRUCT_STAT st;
548 fstring user;
549 fstring dev;
550 int ret;
552 *user = 0;
553 fstrcpy(dev, pdev);
554 SET_STAT_INVALID(st);
556 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
557 return NULL;
560 conn = conn_new();
561 if (!conn) {
562 DEBUG(0,("Couldn't find free connection.\n"));
563 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
564 return NULL;
567 conn->params->service = snum;
568 conn->nt_user_token = NULL;
570 if (lp_guest_only(snum)) {
571 const char *guestname = lp_guestaccount();
572 NTSTATUS status2;
573 char *found_username = NULL;
575 guest = True;
576 pass = getpwnam_alloc(NULL, guestname);
577 if (!pass) {
578 DEBUG(0,("make_connection_snum: Invalid guest "
579 "account %s??\n",guestname));
580 conn_free(conn);
581 *status = NT_STATUS_NO_SUCH_USER;
582 return NULL;
584 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
585 &conn->uid, &conn->gid,
586 &found_username,
587 &conn->nt_user_token);
588 if (!NT_STATUS_IS_OK(status2)) {
589 TALLOC_FREE(pass);
590 conn_free(conn);
591 *status = status2;
592 return NULL;
594 fstrcpy(user, found_username);
595 string_set(&conn->user,user);
596 conn->force_user = True;
597 TALLOC_FREE(found_username);
598 TALLOC_FREE(pass);
599 DEBUG(3,("Guest only user %s\n",user));
600 } else if (vuser) {
601 if (vuser->guest) {
602 if (!lp_guest_ok(snum)) {
603 DEBUG(2, ("guest user (from session setup) "
604 "not permitted to access this share "
605 "(%s)\n", lp_servicename(snum)));
606 conn_free(conn);
607 *status = NT_STATUS_ACCESS_DENIED;
608 return NULL;
610 } else {
611 if (!user_ok_token(vuser->user.unix_name,
612 vuser->nt_user_token, snum)) {
613 DEBUG(2, ("user '%s' (from session setup) not "
614 "permitted to access this share "
615 "(%s)\n", vuser->user.unix_name,
616 lp_servicename(snum)));
617 conn_free(conn);
618 *status = NT_STATUS_ACCESS_DENIED;
619 return NULL;
622 conn->vuid = vuser->vuid;
623 conn->uid = vuser->uid;
624 conn->gid = vuser->gid;
625 string_set(&conn->user,vuser->user.unix_name);
626 fstrcpy(user,vuser->user.unix_name);
627 guest = vuser->guest;
628 } else if (lp_security() == SEC_SHARE) {
629 NTSTATUS status2;
630 char *found_username = NULL;
632 /* add it as a possible user name if we
633 are in share mode security */
634 add_session_user(lp_servicename(snum));
635 /* shall we let them in? */
636 if (!authorise_login(snum,user,password,&guest)) {
637 DEBUG( 2, ( "Invalid username/password for [%s]\n",
638 lp_servicename(snum)) );
639 conn_free(conn);
640 *status = NT_STATUS_WRONG_PASSWORD;
641 return NULL;
643 pass = Get_Pwnam(user);
644 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
645 &conn->uid, &conn->gid,
646 &found_username,
647 &conn->nt_user_token);
648 if (!NT_STATUS_IS_OK(status2)) {
649 conn_free(conn);
650 *status = status2;
651 return NULL;
653 fstrcpy(user, found_username);
654 string_set(&conn->user,user);
655 TALLOC_FREE(found_username);
656 conn->force_user = True;
657 } else {
658 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
659 conn_free(conn);
660 *status = NT_STATUS_ACCESS_DENIED;
661 return NULL;
664 add_session_user(user);
666 safe_strcpy(conn->client_address, client_addr(),
667 sizeof(conn->client_address)-1);
668 conn->num_files_open = 0;
669 conn->lastused = conn->lastused_count = time(NULL);
670 conn->used = True;
671 conn->printer = (strncmp(dev,"LPT",3) == 0);
672 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
673 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
674 conn->dirptr = NULL;
676 /* Case options for the share. */
677 if (lp_casesensitive(snum) == Auto) {
678 /* We will be setting this per packet. Set to be case
679 * insensitive for now. */
680 conn->case_sensitive = False;
681 } else {
682 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
685 conn->case_preserve = lp_preservecase(snum);
686 conn->short_case_preserve = lp_shortpreservecase(snum);
688 conn->veto_list = NULL;
689 conn->hide_list = NULL;
690 conn->veto_oplock_list = NULL;
691 conn->aio_write_behind_list = NULL;
692 string_set(&conn->dirpath,"");
693 string_set(&conn->user,user);
695 conn->read_only = lp_readonly(SNUM(conn));
696 conn->admin_user = False;
699 * If force user is true, then store the given userid and the gid of
700 * the user we're forcing.
701 * For auxiliary groups see below.
704 if (*lp_force_user(snum)) {
705 NTSTATUS status2;
707 status2 = find_forced_user(conn,
708 (vuser != NULL) && vuser->guest,
709 user);
710 if (!NT_STATUS_IS_OK(status2)) {
711 conn_free(conn);
712 *status = status2;
713 return NULL;
715 string_set(&conn->user,user);
716 conn->force_user = True;
717 DEBUG(3,("Forced user %s\n",user));
721 * If force group is true, then override
722 * any groupid stored for the connecting user.
725 if (*lp_force_group(snum)) {
726 NTSTATUS status2;
727 DOM_SID group_sid;
729 status2 = find_forced_group(conn->force_user,
730 snum, user,
731 &group_sid, &conn->gid);
732 if (!NT_STATUS_IS_OK(status2)) {
733 conn_free(conn);
734 *status = status2;
735 return NULL;
738 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
740 /* Not force user and not security=share, but force
741 * group. vuser has a token to copy */
743 conn->nt_user_token = dup_nt_token(
744 NULL, vuser->nt_user_token);
745 if (conn->nt_user_token == NULL) {
746 DEBUG(0, ("dup_nt_token failed\n"));
747 conn_free(conn);
748 *status = NT_STATUS_NO_MEMORY;
749 return NULL;
753 /* If conn->nt_user_token is still NULL, we have
754 * security=share. This means ignore the SID, as we had no
755 * vuser to copy from */
757 if (conn->nt_user_token != NULL) {
758 /* Overwrite the primary group sid */
759 sid_copy(&conn->nt_user_token->user_sids[1],
760 &group_sid);
763 conn->force_group = True;
766 if (conn->nt_user_token != NULL) {
767 size_t i;
769 /* We have a share-specific token from force [user|group].
770 * This means we have to create the list of unix groups from
771 * the list of sids. */
773 conn->ngroups = 0;
774 conn->groups = NULL;
776 for (i=0; i<conn->nt_user_token->num_sids; i++) {
777 gid_t gid;
778 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
780 if (!sid_to_gid(sid, &gid)) {
781 DEBUG(10, ("Could not convert SID %s to gid, "
782 "ignoring it\n",
783 sid_string_static(sid)));
784 continue;
786 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
787 &conn->ngroups)) {
788 DEBUG(0, ("add_gid_to_array_unique failed\n"));
789 conn_free(conn);
790 *status = NT_STATUS_NO_MEMORY;
791 return NULL;
797 pstring s;
798 pstrcpy(s,lp_pathname(snum));
799 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
800 conn->connectpath, conn->gid,
801 get_current_username(),
802 current_user_info.domain,
803 s, sizeof(s));
804 set_conn_connectpath(conn,s);
805 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
806 lp_servicename(snum)));
810 * New code to check if there's a share security descripter
811 * added from NT server manager. This is done after the
812 * smb.conf checks are done as we need a uid and token. JRA.
817 BOOL can_write = False;
818 NT_USER_TOKEN *token = conn->nt_user_token ?
819 conn->nt_user_token :
820 (vuser ? vuser->nt_user_token : NULL);
823 * I don't believe this can happen. But the
824 * logic above is convoluted enough to confuse
825 * automated checkers, so be sure. JRA.
828 if (token == NULL) {
829 DEBUG(0,("make_connection: connection to %s "
830 "denied due to missing "
831 "NT token.\n",
832 lp_servicename(snum)));
833 conn_free(conn);
834 *status = NT_STATUS_ACCESS_DENIED;
835 return NULL;
838 can_write = share_access_check(token,
839 lp_servicename(snum),
840 FILE_WRITE_DATA);
842 if (!can_write) {
843 if (!share_access_check(token,
844 lp_servicename(snum),
845 FILE_READ_DATA)) {
846 /* No access, read or write. */
847 DEBUG(0,("make_connection: connection to %s "
848 "denied due to security "
849 "descriptor.\n",
850 lp_servicename(snum)));
851 conn_free(conn);
852 *status = NT_STATUS_ACCESS_DENIED;
853 return NULL;
854 } else {
855 conn->read_only = True;
859 /* Initialise VFS function pointers */
861 if (!smbd_vfs_init(conn)) {
862 DEBUG(0, ("vfs_init failed for service %s\n",
863 lp_servicename(snum)));
864 conn_free(conn);
865 *status = NT_STATUS_BAD_NETWORK_NAME;
866 return NULL;
870 * If widelinks are disallowed we need to canonicalise the connect
871 * path here to ensure we don't have any symlinks in the
872 * connectpath. We will be checking all paths on this connection are
873 * below this directory. We must do this after the VFS init as we
874 * depend on the realpath() pointer in the vfs table. JRA.
876 if (!lp_widelinks(snum)) {
877 pstring s;
878 pstrcpy(s,conn->connectpath);
879 canonicalize_path(conn, s);
880 set_conn_connectpath(conn,s);
883 if ((!conn->printer) && (!conn->ipc)) {
884 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
885 smbd_messaging_context(),
886 smbd_event_context(),
887 conn);
890 /* ROOT Activities: */
891 /* check number of connections */
892 if (!claim_connection(conn,
893 lp_servicename(snum),
894 lp_max_connections(snum),
895 False,0)) {
896 DEBUG(1,("too many connections - rejected\n"));
897 conn_free(conn);
898 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
899 return NULL;
902 /* Preexecs are done here as they might make the dir we are to ChDir
903 * to below */
904 /* execute any "root preexec = " line */
905 if (*lp_rootpreexec(snum)) {
906 pstring cmd;
907 pstrcpy(cmd,lp_rootpreexec(snum));
908 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
909 conn->connectpath, conn->gid,
910 get_current_username(),
911 current_user_info.domain,
912 cmd, sizeof(cmd));
913 DEBUG(5,("cmd=%s\n",cmd));
914 ret = smbrun(cmd,NULL);
915 if (ret != 0 && lp_rootpreexec_close(snum)) {
916 DEBUG(1,("root preexec gave %d - failing "
917 "connection\n", ret));
918 yield_connection(conn, lp_servicename(snum));
919 conn_free(conn);
920 *status = NT_STATUS_ACCESS_DENIED;
921 return NULL;
925 /* USER Activites: */
926 if (!change_to_user(conn, conn->vuid)) {
927 /* No point continuing if they fail the basic checks */
928 DEBUG(0,("Can't become connected user!\n"));
929 yield_connection(conn, lp_servicename(snum));
930 conn_free(conn);
931 *status = NT_STATUS_LOGON_FAILURE;
932 return NULL;
935 /* Remember that a different vuid can connect later without these
936 * checks... */
938 /* Preexecs are done here as they might make the dir we are to ChDir
939 * to below */
941 /* execute any "preexec = " line */
942 if (*lp_preexec(snum)) {
943 pstring cmd;
944 pstrcpy(cmd,lp_preexec(snum));
945 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
946 conn->connectpath, conn->gid,
947 get_current_username(),
948 current_user_info.domain,
949 cmd, sizeof(cmd));
950 ret = smbrun(cmd,NULL);
951 if (ret != 0 && lp_preexec_close(snum)) {
952 DEBUG(1,("preexec gave %d - failing connection\n",
953 ret));
954 change_to_root_user();
955 yield_connection(conn, lp_servicename(snum));
956 conn_free(conn);
957 *status = NT_STATUS_ACCESS_DENIED;
958 return NULL;
962 #ifdef WITH_FAKE_KASERVER
963 if (lp_afs_share(snum)) {
964 afs_login(conn);
966 #endif
968 /* Add veto/hide lists */
969 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
970 set_namearray( &conn->veto_list, lp_veto_files(snum));
971 set_namearray( &conn->hide_list, lp_hide_files(snum));
972 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
975 /* Invoke VFS make connection hook - do this before the VFS_STAT call
976 to allow any filesystems needing user credentials to initialize
977 themselves. */
979 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
980 DEBUG(0,("make_connection: VFS make connection failed!\n"));
981 change_to_root_user();
982 yield_connection(conn, lp_servicename(snum));
983 conn_free(conn);
984 *status = NT_STATUS_UNSUCCESSFUL;
985 return NULL;
988 /* win2000 does not check the permissions on the directory
989 during the tree connect, instead relying on permission
990 check during individual operations. To match this behaviour
991 I have disabled this chdir check (tridge) */
992 /* the alternative is just to check the directory exists */
993 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
994 !S_ISDIR(st.st_mode)) {
995 if (ret == 0 && !S_ISDIR(st.st_mode)) {
996 DEBUG(0,("'%s' is not a directory, when connecting to "
997 "[%s]\n", conn->connectpath,
998 lp_servicename(snum)));
999 } else {
1000 DEBUG(0,("'%s' does not exist or permission denied "
1001 "when connecting to [%s] Error was %s\n",
1002 conn->connectpath, lp_servicename(snum),
1003 strerror(errno) ));
1005 change_to_root_user();
1006 /* Call VFS disconnect hook */
1007 SMB_VFS_DISCONNECT(conn);
1008 yield_connection(conn, lp_servicename(snum));
1009 conn_free(conn);
1010 *status = NT_STATUS_BAD_NETWORK_NAME;
1011 return NULL;
1014 string_set(&conn->origpath,conn->connectpath);
1016 #if SOFTLINK_OPTIMISATION
1017 /* resolve any soft links early if possible */
1018 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1019 pstring s;
1020 pstrcpy(s,conn->connectpath);
1021 vfs_GetWd(conn,s);
1022 set_conn_connectpath(conn,s);
1023 vfs_ChDir(conn,conn->connectpath);
1025 #endif
1028 * Print out the 'connected as' stuff here as we need
1029 * to know the effective uid and gid we will be using
1030 * (at least initially).
1033 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1034 dbgtext( "%s (%s) ", get_remote_machine_name(),
1035 conn->client_address );
1036 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1037 dbgtext( "connect to service %s ", lp_servicename(snum) );
1038 dbgtext( "initially as user %s ", user );
1039 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1040 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1043 /* we've finished with the user stuff - go back to root */
1044 change_to_root_user();
1045 return(conn);
1048 /***************************************************************************************
1049 Simple wrapper function for make_connection() to include a call to
1050 vfs_chdir()
1051 **************************************************************************************/
1053 connection_struct *make_connection_with_chdir(const char *service_in,
1054 DATA_BLOB password,
1055 const char *dev, uint16 vuid,
1056 NTSTATUS *status)
1058 connection_struct *conn = NULL;
1060 conn = make_connection(service_in, password, dev, vuid, status);
1063 * make_connection() does not change the directory for us any more
1064 * so we have to do it as a separate step --jerry
1067 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1068 DEBUG(0,("move_driver_to_download_area: Can't change "
1069 "directory to %s for [print$] (%s)\n",
1070 conn->connectpath,strerror(errno)));
1071 yield_connection(conn, lp_servicename(SNUM(conn)));
1072 conn_free(conn);
1073 *status = NT_STATUS_UNSUCCESSFUL;
1074 return NULL;
1077 return conn;
1080 /****************************************************************************
1081 Make a connection to a service.
1083 * @param service
1084 ****************************************************************************/
1086 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1087 const char *pdev, uint16 vuid,
1088 NTSTATUS *status)
1090 uid_t euid;
1091 user_struct *vuser = NULL;
1092 fstring service;
1093 fstring dev;
1094 int snum = -1;
1096 fstrcpy(dev, pdev);
1098 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1099 * root. */
1100 if (!non_root_mode() && (euid = geteuid()) != 0) {
1101 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1102 "(%u)\n", (unsigned int)euid ));
1103 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1106 if (conn_num_open() > 2047) {
1107 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1108 return NULL;
1111 if(lp_security() != SEC_SHARE) {
1112 vuser = get_valid_user_struct(vuid);
1113 if (!vuser) {
1114 DEBUG(1,("make_connection: refusing to connect with "
1115 "no session setup\n"));
1116 *status = NT_STATUS_ACCESS_DENIED;
1117 return NULL;
1121 /* Logic to try and connect to the correct [homes] share, preferably
1122 without too many getpwnam() lookups. This is particulary nasty for
1123 winbind usernames, where the share name isn't the same as unix
1124 username.
1126 The snum of the homes share is stored on the vuser at session setup
1127 time.
1130 if (strequal(service_in,HOMES_NAME)) {
1131 if(lp_security() != SEC_SHARE) {
1132 DATA_BLOB no_pw = data_blob(NULL, 0);
1133 if (vuser->homes_snum == -1) {
1134 DEBUG(2, ("[homes] share not available for "
1135 "this user because it was not found "
1136 "or created at session setup "
1137 "time\n"));
1138 *status = NT_STATUS_BAD_NETWORK_NAME;
1139 return NULL;
1141 DEBUG(5, ("making a connection to [homes] service "
1142 "created at session setup time\n"));
1143 return make_connection_snum(vuser->homes_snum,
1144 vuser, no_pw,
1145 dev, status);
1146 } else {
1147 /* Security = share. Try with
1148 * current_user_info.smb_name as the username. */
1149 if (*current_user_info.smb_name) {
1150 fstring unix_username;
1151 fstrcpy(unix_username,
1152 current_user_info.smb_name);
1153 map_username(unix_username);
1154 snum = find_service(unix_username);
1156 if (snum != -1) {
1157 DEBUG(5, ("making a connection to 'homes' "
1158 "service %s based on "
1159 "security=share\n", service_in));
1160 return make_connection_snum(snum, NULL,
1161 password,
1162 dev, status);
1165 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1166 && strequal(service_in,
1167 lp_servicename(vuser->homes_snum))) {
1168 DATA_BLOB no_pw = data_blob(NULL, 0);
1169 DEBUG(5, ("making a connection to 'homes' service [%s] "
1170 "created at session setup time\n", service_in));
1171 return make_connection_snum(vuser->homes_snum,
1172 vuser, no_pw,
1173 dev, status);
1176 fstrcpy(service, service_in);
1178 strlower_m(service);
1180 snum = find_service(service);
1182 if (snum < 0) {
1183 if (strequal(service,"IPC$") ||
1184 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1185 DEBUG(3,("refusing IPC connection to %s\n", service));
1186 *status = NT_STATUS_ACCESS_DENIED;
1187 return NULL;
1190 DEBUG(0,("%s (%s) couldn't find service %s\n",
1191 get_remote_machine_name(), client_addr(), service));
1192 *status = NT_STATUS_BAD_NETWORK_NAME;
1193 return NULL;
1196 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1197 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1198 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1199 "(pointing to %s)\n",
1200 service, lp_msdfs_proxy(snum)));
1201 *status = NT_STATUS_BAD_NETWORK_NAME;
1202 return NULL;
1205 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1207 return make_connection_snum(snum, vuser,
1208 password,
1209 dev, status);
1212 /****************************************************************************
1213 Close a cnum.
1214 ****************************************************************************/
1216 void close_cnum(connection_struct *conn, uint16 vuid)
1218 if (IS_IPC(conn)) {
1219 pipe_close_conn(conn);
1220 } else {
1221 file_close_conn(conn);
1222 dptr_closecnum(conn);
1225 change_to_root_user();
1227 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1228 get_remote_machine_name(),
1229 conn->client_address,
1230 lp_servicename(SNUM(conn))));
1232 /* Call VFS disconnect hook */
1233 SMB_VFS_DISCONNECT(conn);
1235 yield_connection(conn, lp_servicename(SNUM(conn)));
1237 /* make sure we leave the directory available for unmount */
1238 vfs_ChDir(conn, "/");
1240 /* execute any "postexec = " line */
1241 if (*lp_postexec(SNUM(conn)) &&
1242 change_to_user(conn, vuid)) {
1243 pstring cmd;
1244 pstrcpy(cmd,lp_postexec(SNUM(conn)));
1245 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1246 conn->connectpath, conn->gid,
1247 get_current_username(),
1248 current_user_info.domain,
1249 cmd, sizeof(cmd));
1250 smbrun(cmd,NULL);
1251 change_to_root_user();
1254 change_to_root_user();
1255 /* execute any "root postexec = " line */
1256 if (*lp_rootpostexec(SNUM(conn))) {
1257 pstring cmd;
1258 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
1259 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1260 conn->connectpath, conn->gid,
1261 get_current_username(),
1262 current_user_info.domain,
1263 cmd, sizeof(cmd));
1264 smbrun(cmd,NULL);
1267 conn_free(conn);