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 3 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, see <http://www.gnu.org/licenses/>.
22 extern userdom_struct current_user_info
;
24 static bool canonicalize_connect_path(connection_struct
*conn
)
26 #ifdef REALPATH_TAKES_NULL
28 char *resolved_name
= SMB_VFS_REALPATH(conn
,conn
->connectpath
,NULL
);
32 ret
= set_conn_connectpath(conn
,resolved_name
);
33 SAFE_FREE(resolved_name
);
36 char resolved_name_buf
[PATH_MAX
+1];
37 char *resolved_name
= SMB_VFS_REALPATH(conn
,conn
->connectpath
,resolved_name_buf
);
41 return set_conn_connectpath(conn
,resolved_name
);
42 #endif /* REALPATH_TAKES_NULL */
45 /****************************************************************************
46 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
47 absolute path stating in / and not ending in /.
48 Observent people will notice a similarity between this and check_path_syntax :-).
49 ****************************************************************************/
51 bool set_conn_connectpath(connection_struct
*conn
, const char *connectpath
)
55 const char *s
= connectpath
;
56 bool start_of_name_component
= true;
58 destname
= SMB_STRDUP(connectpath
);
64 *d
++ = '/'; /* Always start with root. */
68 /* Eat multiple '/' */
72 if ((d
> destname
+ 1) && (*s
!= '\0')) {
75 start_of_name_component
= True
;
79 if (start_of_name_component
) {
80 if ((s
[0] == '.') && (s
[1] == '.') && (s
[2] == '/' || s
[2] == '\0')) {
81 /* Uh oh - "/../" or "/..\0" ! */
83 /* Go past the ../ or .. */
87 s
+= 2; /* Go past the .. */
90 /* If we just added a '/' - delete it */
91 if ((d
> destname
) && (*(d
-1) == '/')) {
96 /* Are we at the start ? Can't go back further if so. */
98 *d
++ = '/'; /* Can't delete root */
101 /* Go back one level... */
102 /* Decrement d first as d points to the *next* char to write into. */
103 for (d
--; d
> destname
; d
--) {
108 /* We're still at the start of a name component, just the previous one. */
110 } else if ((s
[0] == '.') && ((s
[1] == '\0') || s
[1] == '/')) {
111 /* Component of pathname can't be "." only - skip the '.' . */
125 /* Get the size of the next MB character. */
126 next_codepoint(s
,&siz
);
147 start_of_name_component
= false;
151 /* And must not end in '/' */
152 if (d
> destname
+ 1 && (*(d
-1) == '/')) {
156 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
157 lp_servicename(SNUM(conn
)), destname
));
159 string_set(&conn
->connectpath
, destname
);
164 /****************************************************************************
165 Load parameters specific to a connection/service.
166 ****************************************************************************/
168 bool set_current_service(connection_struct
*conn
, uint16 flags
, bool do_chdir
)
170 static connection_struct
*last_conn
;
171 static uint16 last_flags
;
179 conn
->lastused_count
++;
184 vfs_ChDir(conn
,conn
->connectpath
) != 0 &&
185 vfs_ChDir(conn
,conn
->origpath
) != 0) {
186 DEBUG(0,("chdir (%s) failed\n",
191 if ((conn
== last_conn
) && (last_flags
== flags
)) {
198 /* Obey the client case sensitivity requests - only for clients that support it. */
199 switch (lp_casesensitive(snum
)) {
202 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
203 enum remote_arch_types ra_type
= get_remote_arch();
204 if ((ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
205 /* Client can't support per-packet case sensitive pathnames. */
206 conn
->case_sensitive
= False
;
208 conn
->case_sensitive
= !(flags
& FLAG_CASELESS_PATHNAMES
);
213 conn
->case_sensitive
= True
;
216 conn
->case_sensitive
= False
;
222 static int load_registry_service(const char *servicename
)
224 struct registry_key
*key
;
230 struct registry_value
*value
;
234 if (!lp_registry_shares()) {
238 if ((servicename
== NULL
) || (*servicename
== '\0')) {
242 if (strequal(servicename
, GLOBAL_NAME
)) {
246 if (asprintf(&path
, "%s\\%s", KEY_SMBCONF
, servicename
) == -1) {
250 err
= reg_open_path(NULL
, path
, REG_KEY_READ
, get_root_nt_token(),
254 if (!W_ERROR_IS_OK(err
)) {
258 res
= lp_add_service(servicename
, -1);
264 W_ERROR_IS_OK(reg_enumvalue(key
, key
, i
, &value_name
, &value
));
266 switch (value
->type
) {
269 if (asprintf(&tmp
, "%d", value
->v
.dword
) == -1) {
272 lp_do_parameter(res
, value_name
, tmp
);
277 lp_do_parameter(res
, value_name
, value
->v
.sz
.str
);
281 /* Ignore all the rest */
285 TALLOC_FREE(value_name
);
295 void load_registry_shares(void)
297 struct registry_key
*key
;
302 DEBUG(8, ("load_registry_shares()\n"));
303 if (!lp_registry_shares()) {
307 err
= reg_open_path(NULL
, KEY_SMBCONF
, REG_KEY_READ
,
308 get_root_nt_token(), &key
);
309 if (!(W_ERROR_IS_OK(err
))) {
313 for (i
=0; W_ERROR_IS_OK(reg_enumkey(key
, key
, i
, &name
, NULL
)); i
++) {
314 load_registry_service(name
);
322 /****************************************************************************
323 Add a home service. Returns the new service number or -1 if fail.
324 ****************************************************************************/
326 int add_home_service(const char *service
, const char *username
, const char *homedir
)
330 if (!service
|| !homedir
)
333 if ((iHomeService
= lp_servicenumber(HOMES_NAME
)) < 0) {
334 if ((iHomeService
= load_registry_service(HOMES_NAME
)) < 0) {
340 * If this is a winbindd provided username, remove
341 * the domain component before adding the service.
342 * Log a warning if the "path=" parameter does not
343 * include any macros.
347 const char *p
= strchr(service
,*lp_winbind_separator());
349 /* We only want the 'user' part of the string */
355 if (!lp_add_home(service
, iHomeService
, username
, homedir
)) {
359 return lp_servicenumber(service
);
364 * Find a service entry.
366 * @param service is modified (to canonical form??)
369 int find_service(fstring service
)
373 all_string_sub(service
,"\\","/",0);
375 iService
= lp_servicenumber(service
);
377 /* now handle the special case of a home directory */
379 char *phome_dir
= get_user_home_dir(talloc_tos(), service
);
383 * Try mapping the servicename, it may
384 * be a Windows to unix mapped user name.
386 if(map_username(service
))
387 phome_dir
= get_user_home_dir(
388 talloc_tos(), service
);
391 DEBUG(3,("checking for home directory %s gave %s\n",service
,
392 phome_dir
?phome_dir
:"(NULL)"));
394 iService
= add_home_service(service
,service
/* 'username' */, phome_dir
);
397 /* If we still don't have a service, attempt to add it as a printer. */
401 if ((iPrinterService
= lp_servicenumber(PRINTERS_NAME
)) < 0) {
402 iPrinterService
= load_registry_service(PRINTERS_NAME
);
404 if (iPrinterService
) {
405 DEBUG(3,("checking whether %s is a valid printer name...\n", service
));
406 if (pcap_printername_ok(service
)) {
407 DEBUG(3,("%s is a valid printer name\n", service
));
408 DEBUG(3,("adding %s as a printer service\n", service
));
409 lp_add_printer(service
, iPrinterService
);
410 iService
= lp_servicenumber(service
);
412 DEBUG(0,("failed to add %s as a printer service!\n", service
));
415 DEBUG(3,("%s is not a valid printer name\n", service
));
420 /* Check for default vfs service? Unsure whether to implement this */
425 iService
= load_registry_service(service
);
428 /* Is it a usershare service ? */
429 if (iService
< 0 && *lp_usershare_path()) {
430 /* Ensure the name is canonicalized. */
432 iService
= load_usershare_service(service
);
435 /* just possibly it's a default service? */
437 char *pdefservice
= lp_defaultservice();
438 if (pdefservice
&& *pdefservice
&& !strequal(pdefservice
,service
) && !strstr_m(service
,"..")) {
440 * We need to do a local copy here as lp_defaultservice()
441 * returns one of the rotating lp_string buffers that
442 * could get overwritten by the recursive find_service() call
443 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
445 char *defservice
= SMB_STRDUP(pdefservice
);
451 /* Disallow anything except explicit share names. */
452 if (strequal(defservice
,HOMES_NAME
) ||
453 strequal(defservice
, PRINTERS_NAME
) ||
454 strequal(defservice
, "IPC$")) {
455 SAFE_FREE(defservice
);
459 iService
= find_service(defservice
);
461 all_string_sub(service
, "_","/",0);
462 iService
= lp_add_service(service
, iService
);
464 SAFE_FREE(defservice
);
469 if (!VALID_SNUM(iService
)) {
470 DEBUG(0,("Invalid snum %d for %s\n",iService
, service
));
478 DEBUG(3,("find_service() failed to find service %s\n", service
));
484 /****************************************************************************
485 do some basic sainity checks on the share.
486 This function modifies dev, ecode.
487 ****************************************************************************/
489 static NTSTATUS
share_sanity_checks(int snum
, fstring dev
)
492 if (!lp_snum_ok(snum
) ||
493 !check_access(smbd_server_fd(),
494 lp_hostsallow(snum
), lp_hostsdeny(snum
))) {
495 return NT_STATUS_ACCESS_DENIED
;
498 if (dev
[0] == '?' || !dev
[0]) {
499 if (lp_print_ok(snum
)) {
500 fstrcpy(dev
,"LPT1:");
501 } else if (strequal(lp_fstype(snum
), "IPC")) {
510 if (lp_print_ok(snum
)) {
511 if (!strequal(dev
, "LPT1:")) {
512 return NT_STATUS_BAD_DEVICE_TYPE
;
514 } else if (strequal(lp_fstype(snum
), "IPC")) {
515 if (!strequal(dev
, "IPC")) {
516 return NT_STATUS_BAD_DEVICE_TYPE
;
518 } else if (!strequal(dev
, "A:")) {
519 return NT_STATUS_BAD_DEVICE_TYPE
;
522 /* Behave as a printer if we are supposed to */
523 if (lp_print_ok(snum
) && (strcmp(dev
, "A:") == 0)) {
524 fstrcpy(dev
, "LPT1:");
530 static NTSTATUS
find_forced_user(connection_struct
*conn
, bool vuser_is_guest
, fstring username
)
532 int snum
= conn
->params
->service
;
533 char *fuser
, *found_username
;
536 if (!(fuser
= talloc_string_sub(conn
->mem_ctx
, lp_force_user(snum
), "%S",
537 lp_servicename(snum
)))) {
538 return NT_STATUS_NO_MEMORY
;
541 result
= create_token_from_username(conn
->mem_ctx
, fuser
, vuser_is_guest
,
542 &conn
->uid
, &conn
->gid
, &found_username
,
543 &conn
->nt_user_token
);
544 if (!NT_STATUS_IS_OK(result
)) {
548 fstrcpy(username
, found_username
);
551 TALLOC_FREE(found_username
);
556 * Go through lookup_name etc to find the force'd group.
558 * Create a new token from src_token, replacing the primary group sid with the
562 static NTSTATUS
find_forced_group(bool force_user
,
563 int snum
, const char *username
,
567 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
570 enum lsa_SidType type
;
572 bool user_must_be_member
= False
;
575 ZERO_STRUCTP(pgroup_sid
);
578 mem_ctx
= talloc_new(NULL
);
579 if (mem_ctx
== NULL
) {
580 DEBUG(0, ("talloc_new failed\n"));
581 return NT_STATUS_NO_MEMORY
;
584 groupname
= talloc_strdup(mem_ctx
, lp_force_group(snum
));
585 if (groupname
== NULL
) {
586 DEBUG(1, ("talloc_strdup failed\n"));
587 result
= NT_STATUS_NO_MEMORY
;
591 if (groupname
[0] == '+') {
592 user_must_be_member
= True
;
596 groupname
= talloc_string_sub(mem_ctx
, groupname
,
597 "%S", lp_servicename(snum
));
599 if (!lookup_name_smbconf(mem_ctx
, groupname
,
600 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
601 NULL
, NULL
, &group_sid
, &type
)) {
602 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
607 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
608 (type
!= SID_NAME_WKN_GRP
)) {
609 DEBUG(10, ("%s is a %s, not a group\n", groupname
,
610 sid_type_lookup(type
)));
614 if (!sid_to_gid(&group_sid
, &gid
)) {
615 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
616 sid_string_dbg(&group_sid
), groupname
));
621 * If the user has been forced and the forced group starts with a '+',
622 * then we only set the group to be the forced group if the forced
623 * user is a member of that group. Otherwise, the meaning of the '+'
627 if (force_user
&& user_must_be_member
) {
628 if (user_in_group_sid(username
, &group_sid
)) {
629 sid_copy(pgroup_sid
, &group_sid
);
631 DEBUG(3,("Forced group %s for member %s\n",
632 groupname
, username
));
634 DEBUG(0,("find_forced_group: forced user %s is not a member "
635 "of forced group %s. Disallowing access.\n",
636 username
, groupname
));
637 result
= NT_STATUS_MEMBER_NOT_IN_GROUP
;
641 sid_copy(pgroup_sid
, &group_sid
);
643 DEBUG(3,("Forced group %s\n", groupname
));
646 result
= NT_STATUS_OK
;
648 TALLOC_FREE(mem_ctx
);
652 /****************************************************************************
653 Make a connection, given the snum to connect to, and the vuser of the
654 connecting user if appropriate.
655 ****************************************************************************/
657 static connection_struct
*make_connection_snum(int snum
, user_struct
*vuser
,
662 struct passwd
*pass
= NULL
;
664 connection_struct
*conn
;
669 char addr
[INET6_ADDRSTRLEN
];
670 bool on_err_call_dis_hook
= false;
674 SET_STAT_INVALID(st
);
676 if (NT_STATUS_IS_ERR(*status
= share_sanity_checks(snum
, dev
))) {
682 DEBUG(0,("Couldn't find free connection.\n"));
683 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
687 conn
->params
->service
= snum
;
688 conn
->nt_user_token
= NULL
;
690 if (lp_guest_only(snum
)) {
691 const char *guestname
= lp_guestaccount();
693 char *found_username
= NULL
;
696 pass
= getpwnam_alloc(talloc_tos(), guestname
);
698 DEBUG(0,("make_connection_snum: Invalid guest "
699 "account %s??\n",guestname
));
701 *status
= NT_STATUS_NO_SUCH_USER
;
704 status2
= create_token_from_username(conn
->mem_ctx
, pass
->pw_name
, True
,
705 &conn
->uid
, &conn
->gid
,
707 &conn
->nt_user_token
);
708 if (!NT_STATUS_IS_OK(status2
)) {
714 fstrcpy(user
, found_username
);
715 string_set(&conn
->user
,user
);
716 conn
->force_user
= True
;
717 TALLOC_FREE(found_username
);
719 DEBUG(3,("Guest only user %s\n",user
));
722 if (!lp_guest_ok(snum
)) {
723 DEBUG(2, ("guest user (from session setup) "
724 "not permitted to access this share "
725 "(%s)\n", lp_servicename(snum
)));
727 *status
= NT_STATUS_ACCESS_DENIED
;
731 if (!user_ok_token(vuser
->user
.unix_name
,
732 vuser
->nt_user_token
, snum
)) {
733 DEBUG(2, ("user '%s' (from session setup) not "
734 "permitted to access this share "
735 "(%s)\n", vuser
->user
.unix_name
,
736 lp_servicename(snum
)));
738 *status
= NT_STATUS_ACCESS_DENIED
;
742 conn
->vuid
= vuser
->vuid
;
743 conn
->uid
= vuser
->uid
;
744 conn
->gid
= vuser
->gid
;
745 string_set(&conn
->user
,vuser
->user
.unix_name
);
746 fstrcpy(user
,vuser
->user
.unix_name
);
747 guest
= vuser
->guest
;
748 } else if (lp_security() == SEC_SHARE
) {
750 char *found_username
= NULL
;
752 /* add it as a possible user name if we
753 are in share mode security */
754 add_session_user(lp_servicename(snum
));
755 /* shall we let them in? */
756 if (!authorise_login(snum
,user
,password
,&guest
)) {
757 DEBUG( 2, ( "Invalid username/password for [%s]\n",
758 lp_servicename(snum
)) );
760 *status
= NT_STATUS_WRONG_PASSWORD
;
763 pass
= Get_Pwnam_alloc(talloc_tos(), user
);
764 status2
= create_token_from_username(conn
->mem_ctx
, pass
->pw_name
, True
,
765 &conn
->uid
, &conn
->gid
,
767 &conn
->nt_user_token
);
769 if (!NT_STATUS_IS_OK(status2
)) {
774 fstrcpy(user
, found_username
);
775 string_set(&conn
->user
,user
);
776 TALLOC_FREE(found_username
);
777 conn
->force_user
= True
;
779 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
781 *status
= NT_STATUS_ACCESS_DENIED
;
785 add_session_user(user
);
787 safe_strcpy(conn
->client_address
,
788 client_addr(get_client_fd(),addr
,sizeof(addr
)),
789 sizeof(conn
->client_address
)-1);
790 conn
->num_files_open
= 0;
791 conn
->lastused
= conn
->lastused_count
= time(NULL
);
793 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
794 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
795 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
798 /* Case options for the share. */
799 if (lp_casesensitive(snum
) == Auto
) {
800 /* We will be setting this per packet. Set to be case
801 * insensitive for now. */
802 conn
->case_sensitive
= False
;
804 conn
->case_sensitive
= (bool)lp_casesensitive(snum
);
807 conn
->case_preserve
= lp_preservecase(snum
);
808 conn
->short_case_preserve
= lp_shortpreservecase(snum
);
810 conn
->encrypt_level
= lp_smb_encrypt(snum
);
812 conn
->veto_list
= NULL
;
813 conn
->hide_list
= NULL
;
814 conn
->veto_oplock_list
= NULL
;
815 conn
->aio_write_behind_list
= NULL
;
816 string_set(&conn
->dirpath
,"");
817 string_set(&conn
->user
,user
);
819 conn
->read_only
= lp_readonly(SNUM(conn
));
820 conn
->admin_user
= False
;
823 * If force user is true, then store the given userid and the gid of
824 * the user we're forcing.
825 * For auxiliary groups see below.
828 if (*lp_force_user(snum
)) {
831 status2
= find_forced_user(conn
,
832 (vuser
!= NULL
) && vuser
->guest
,
834 if (!NT_STATUS_IS_OK(status2
)) {
839 string_set(&conn
->user
,user
);
840 conn
->force_user
= True
;
841 DEBUG(3,("Forced user %s\n",user
));
845 * If force group is true, then override
846 * any groupid stored for the connecting user.
849 if (*lp_force_group(snum
)) {
853 status2
= find_forced_group(conn
->force_user
,
855 &group_sid
, &conn
->gid
);
856 if (!NT_STATUS_IS_OK(status2
)) {
862 if ((conn
->nt_user_token
== NULL
) && (vuser
!= NULL
)) {
864 /* Not force user and not security=share, but force
865 * group. vuser has a token to copy */
867 conn
->nt_user_token
= dup_nt_token(
868 NULL
, vuser
->nt_user_token
);
869 if (conn
->nt_user_token
== NULL
) {
870 DEBUG(0, ("dup_nt_token failed\n"));
872 *status
= NT_STATUS_NO_MEMORY
;
877 /* If conn->nt_user_token is still NULL, we have
878 * security=share. This means ignore the SID, as we had no
879 * vuser to copy from */
881 if (conn
->nt_user_token
!= NULL
) {
882 /* Overwrite the primary group sid */
883 sid_copy(&conn
->nt_user_token
->user_sids
[1],
887 conn
->force_group
= True
;
890 if (conn
->nt_user_token
!= NULL
) {
893 /* We have a share-specific token from force [user|group].
894 * This means we have to create the list of unix groups from
895 * the list of sids. */
900 for (i
=0; i
<conn
->nt_user_token
->num_sids
; i
++) {
902 DOM_SID
*sid
= &conn
->nt_user_token
->user_sids
[i
];
904 if (!sid_to_gid(sid
, &gid
)) {
905 DEBUG(10, ("Could not convert SID %s to gid, "
907 sid_string_dbg(sid
)));
910 if (!add_gid_to_array_unique(conn
->mem_ctx
, gid
, &conn
->groups
,
912 DEBUG(0, ("add_gid_to_array_unique failed\n"));
914 *status
= NT_STATUS_NO_MEMORY
;
921 char *s
= talloc_sub_advanced(talloc_tos(),
922 lp_servicename(SNUM(conn
)), conn
->user
,
923 conn
->connectpath
, conn
->gid
,
924 get_current_username(),
925 current_user_info
.domain
,
929 *status
= NT_STATUS_NO_MEMORY
;
933 if (!set_conn_connectpath(conn
,s
)) {
936 *status
= NT_STATUS_NO_MEMORY
;
939 DEBUG(3,("Connect path is '%s' for service [%s]\n",s
,
940 lp_servicename(snum
)));
945 * New code to check if there's a share security descripter
946 * added from NT server manager. This is done after the
947 * smb.conf checks are done as we need a uid and token. JRA.
952 bool can_write
= False
;
953 NT_USER_TOKEN
*token
= conn
->nt_user_token
?
954 conn
->nt_user_token
:
955 (vuser
? vuser
->nt_user_token
: NULL
);
958 * I don't believe this can happen. But the
959 * logic above is convoluted enough to confuse
960 * automated checkers, so be sure. JRA.
964 DEBUG(0,("make_connection: connection to %s "
965 "denied due to missing "
967 lp_servicename(snum
)));
969 *status
= NT_STATUS_ACCESS_DENIED
;
973 can_write
= share_access_check(token
,
974 lp_servicename(snum
),
978 if (!share_access_check(token
,
979 lp_servicename(snum
),
981 /* No access, read or write. */
982 DEBUG(0,("make_connection: connection to %s "
983 "denied due to security "
985 lp_servicename(snum
)));
987 *status
= NT_STATUS_ACCESS_DENIED
;
990 conn
->read_only
= True
;
994 /* Initialise VFS function pointers */
996 if (!smbd_vfs_init(conn
)) {
997 DEBUG(0, ("vfs_init failed for service %s\n",
998 lp_servicename(snum
)));
1000 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1005 * If widelinks are disallowed we need to canonicalise the connect
1006 * path here to ensure we don't have any symlinks in the
1007 * connectpath. We will be checking all paths on this connection are
1008 * below this directory. We must do this after the VFS init as we
1009 * depend on the realpath() pointer in the vfs table. JRA.
1011 if (!lp_widelinks(snum
)) {
1012 if (!canonicalize_connect_path(conn
)) {
1013 DEBUG(0, ("canonicalize_connect_path failed "
1014 "for service %s, path %s\n",
1015 lp_servicename(snum
),
1016 conn
->connectpath
));
1018 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1023 if ((!conn
->printer
) && (!conn
->ipc
)) {
1024 conn
->notify_ctx
= notify_init(conn
->mem_ctx
, server_id_self(),
1025 smbd_messaging_context(),
1026 smbd_event_context(),
1030 /* ROOT Activities: */
1032 * Enforce the max connections parameter.
1035 if ((lp_max_connections(snum
) > 0)
1036 && (count_current_connections(lp_servicename(SNUM(conn
)), True
) >=
1037 lp_max_connections(snum
))) {
1039 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
1040 lp_max_connections(snum
), lp_servicename(snum
)));
1042 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
1047 * Get us an entry in the connections db
1049 if (!claim_connection(conn
, lp_servicename(snum
), 0)) {
1050 DEBUG(1, ("Could not store connections entry\n"));
1052 *status
= NT_STATUS_INTERNAL_DB_ERROR
;
1056 /* Preexecs are done here as they might make the dir we are to ChDir
1058 /* execute any "root preexec = " line */
1059 if (*lp_rootpreexec(snum
)) {
1060 char *cmd
= talloc_sub_advanced(talloc_tos(),
1061 lp_servicename(SNUM(conn
)), conn
->user
,
1062 conn
->connectpath
, conn
->gid
,
1063 get_current_username(),
1064 current_user_info
.domain
,
1065 lp_rootpreexec(snum
));
1066 DEBUG(5,("cmd=%s\n",cmd
));
1067 ret
= smbrun(cmd
,NULL
);
1069 if (ret
!= 0 && lp_rootpreexec_close(snum
)) {
1070 DEBUG(1,("root preexec gave %d - failing "
1071 "connection\n", ret
));
1072 yield_connection(conn
, lp_servicename(snum
));
1074 *status
= NT_STATUS_ACCESS_DENIED
;
1079 /* USER Activites: */
1080 if (!change_to_user(conn
, conn
->vuid
)) {
1081 /* No point continuing if they fail the basic checks */
1082 DEBUG(0,("Can't become connected user!\n"));
1083 yield_connection(conn
, lp_servicename(snum
));
1085 *status
= NT_STATUS_LOGON_FAILURE
;
1089 /* Remember that a different vuid can connect later without these
1092 /* Preexecs are done here as they might make the dir we are to ChDir
1095 /* execute any "preexec = " line */
1096 if (*lp_preexec(snum
)) {
1097 char *cmd
= talloc_sub_advanced(talloc_tos(),
1098 lp_servicename(SNUM(conn
)), conn
->user
,
1099 conn
->connectpath
, conn
->gid
,
1100 get_current_username(),
1101 current_user_info
.domain
,
1103 ret
= smbrun(cmd
,NULL
);
1105 if (ret
!= 0 && lp_preexec_close(snum
)) {
1106 DEBUG(1,("preexec gave %d - failing connection\n",
1108 *status
= NT_STATUS_ACCESS_DENIED
;
1113 #ifdef WITH_FAKE_KASERVER
1114 if (lp_afs_share(snum
)) {
1119 /* Add veto/hide lists */
1120 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
1121 set_namearray( &conn
->veto_list
, lp_veto_files(snum
));
1122 set_namearray( &conn
->hide_list
, lp_hide_files(snum
));
1123 set_namearray( &conn
->veto_oplock_list
, lp_veto_oplocks(snum
));
1124 set_namearray( &conn
->aio_write_behind_list
,
1125 lp_aio_write_behind(snum
));
1128 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1129 to allow any filesystems needing user credentials to initialize
1132 if (SMB_VFS_CONNECT(conn
, lp_servicename(snum
), user
) < 0) {
1133 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1134 *status
= NT_STATUS_UNSUCCESSFUL
;
1138 /* Any error exit after here needs to call the disconnect hook. */
1139 on_err_call_dis_hook
= true;
1141 /* win2000 does not check the permissions on the directory
1142 during the tree connect, instead relying on permission
1143 check during individual operations. To match this behaviour
1144 I have disabled this chdir check (tridge) */
1145 /* the alternative is just to check the directory exists */
1146 if ((ret
= SMB_VFS_STAT(conn
, conn
->connectpath
, &st
)) != 0 ||
1147 !S_ISDIR(st
.st_mode
)) {
1148 if (ret
== 0 && !S_ISDIR(st
.st_mode
)) {
1149 DEBUG(0,("'%s' is not a directory, when connecting to "
1150 "[%s]\n", conn
->connectpath
,
1151 lp_servicename(snum
)));
1153 DEBUG(0,("'%s' does not exist or permission denied "
1154 "when connecting to [%s] Error was %s\n",
1155 conn
->connectpath
, lp_servicename(snum
),
1158 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1162 string_set(&conn
->origpath
,conn
->connectpath
);
1164 #if SOFTLINK_OPTIMISATION
1165 /* resolve any soft links early if possible */
1166 if (vfs_ChDir(conn
,conn
->connectpath
) == 0) {
1167 TALLOC_CTX
*ctx
= talloc_tos();
1168 char *s
= vfs_GetWd(ctx
,s
);
1170 *status
= map_nt_error_from_unix(errno
);
1173 if (!set_conn_connectpath(conn
,s
)) {
1174 *status
= NT_STATUS_NO_MEMORY
;
1177 vfs_ChDir(conn
,conn
->connectpath
);
1181 /* Figure out the characteristics of the underlying filesystem. This
1182 * assumes that all the filesystem mounted withing a share path have
1183 * the same characteristics, which is likely but not guaranteed.
1186 conn
->fs_capabilities
= SMB_VFS_FS_CAPABILITIES(conn
);
1189 * Print out the 'connected as' stuff here as we need
1190 * to know the effective uid and gid we will be using
1191 * (at least initially).
1194 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 1 ) ) {
1195 dbgtext( "%s (%s) ", get_remote_machine_name(),
1196 conn
->client_address
);
1197 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1198 dbgtext( "connect to service %s ", lp_servicename(snum
) );
1199 dbgtext( "initially as user %s ", user
);
1200 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1201 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1204 /* we've finished with the user stuff - go back to root */
1205 change_to_root_user();
1210 change_to_root_user();
1211 if (on_err_call_dis_hook
) {
1212 /* Call VFS disconnect hook */
1213 SMB_VFS_DISCONNECT(conn
);
1215 yield_connection(conn
, lp_servicename(snum
));
1220 /***************************************************************************************
1221 Simple wrapper function for make_connection() to include a call to
1223 **************************************************************************************/
1225 connection_struct
*make_connection_with_chdir(const char *service_in
,
1227 const char *dev
, uint16 vuid
,
1230 connection_struct
*conn
= NULL
;
1232 conn
= make_connection(service_in
, password
, dev
, vuid
, status
);
1235 * make_connection() does not change the directory for us any more
1236 * so we have to do it as a separate step --jerry
1239 if ( conn
&& vfs_ChDir(conn
,conn
->connectpath
) != 0 ) {
1240 DEBUG(0,("move_driver_to_download_area: Can't change "
1241 "directory to %s for [print$] (%s)\n",
1242 conn
->connectpath
,strerror(errno
)));
1243 yield_connection(conn
, lp_servicename(SNUM(conn
)));
1245 *status
= NT_STATUS_UNSUCCESSFUL
;
1252 /****************************************************************************
1253 Make a connection to a service.
1256 ****************************************************************************/
1258 connection_struct
*make_connection(const char *service_in
, DATA_BLOB password
,
1259 const char *pdev
, uint16 vuid
,
1263 user_struct
*vuser
= NULL
;
1267 char addr
[INET6_ADDRSTRLEN
];
1271 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1273 if (!non_root_mode() && (euid
= geteuid()) != 0) {
1274 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1275 "(%u)\n", (unsigned int)euid
));
1276 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1279 if (conn_num_open() > 2047) {
1280 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
1284 if(lp_security() != SEC_SHARE
) {
1285 vuser
= get_valid_user_struct(vuid
);
1287 DEBUG(1,("make_connection: refusing to connect with "
1288 "no session setup\n"));
1289 *status
= NT_STATUS_ACCESS_DENIED
;
1294 /* Logic to try and connect to the correct [homes] share, preferably
1295 without too many getpwnam() lookups. This is particulary nasty for
1296 winbind usernames, where the share name isn't the same as unix
1299 The snum of the homes share is stored on the vuser at session setup
1303 if (strequal(service_in
,HOMES_NAME
)) {
1304 if(lp_security() != SEC_SHARE
) {
1305 DATA_BLOB no_pw
= data_blob_null
;
1306 if (vuser
->homes_snum
== -1) {
1307 DEBUG(2, ("[homes] share not available for "
1308 "this user because it was not found "
1309 "or created at session setup "
1311 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1314 DEBUG(5, ("making a connection to [homes] service "
1315 "created at session setup time\n"));
1316 return make_connection_snum(vuser
->homes_snum
,
1320 /* Security = share. Try with
1321 * current_user_info.smb_name as the username. */
1322 if (*current_user_info
.smb_name
) {
1323 fstring unix_username
;
1324 fstrcpy(unix_username
,
1325 current_user_info
.smb_name
);
1326 map_username(unix_username
);
1327 snum
= find_service(unix_username
);
1330 DEBUG(5, ("making a connection to 'homes' "
1331 "service %s based on "
1332 "security=share\n", service_in
));
1333 return make_connection_snum(snum
, NULL
,
1338 } else if ((lp_security() != SEC_SHARE
) && (vuser
->homes_snum
!= -1)
1339 && strequal(service_in
,
1340 lp_servicename(vuser
->homes_snum
))) {
1341 DATA_BLOB no_pw
= data_blob_null
;
1342 DEBUG(5, ("making a connection to 'homes' service [%s] "
1343 "created at session setup time\n", service_in
));
1344 return make_connection_snum(vuser
->homes_snum
,
1349 fstrcpy(service
, service_in
);
1351 strlower_m(service
);
1353 snum
= find_service(service
);
1356 if (strequal(service
,"IPC$") ||
1357 (lp_enable_asu_support() && strequal(service
,"ADMIN$"))) {
1358 DEBUG(3,("refusing IPC connection to %s\n", service
));
1359 *status
= NT_STATUS_ACCESS_DENIED
;
1363 DEBUG(0,("%s (%s) couldn't find service %s\n",
1364 get_remote_machine_name(),
1365 client_addr(get_client_fd(),addr
,sizeof(addr
)),
1367 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1371 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1372 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum
) != '\0')) {
1373 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1374 "(pointing to %s)\n",
1375 service
, lp_msdfs_proxy(snum
)));
1376 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1380 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
1382 return make_connection_snum(snum
, vuser
,
1387 /****************************************************************************
1389 ****************************************************************************/
1391 void close_cnum(connection_struct
*conn
, uint16 vuid
)
1394 pipe_close_conn(conn
);
1396 file_close_conn(conn
);
1397 dptr_closecnum(conn
);
1400 change_to_root_user();
1402 DEBUG(IS_IPC(conn
)?3:1, ("%s (%s) closed connection to service %s\n",
1403 get_remote_machine_name(),
1404 conn
->client_address
,
1405 lp_servicename(SNUM(conn
))));
1407 /* Call VFS disconnect hook */
1408 SMB_VFS_DISCONNECT(conn
);
1410 yield_connection(conn
, lp_servicename(SNUM(conn
)));
1412 /* make sure we leave the directory available for unmount */
1413 vfs_ChDir(conn
, "/");
1415 /* execute any "postexec = " line */
1416 if (*lp_postexec(SNUM(conn
)) &&
1417 change_to_user(conn
, vuid
)) {
1418 char *cmd
= talloc_sub_advanced(talloc_tos(),
1419 lp_servicename(SNUM(conn
)), conn
->user
,
1420 conn
->connectpath
, conn
->gid
,
1421 get_current_username(),
1422 current_user_info
.domain
,
1423 lp_postexec(SNUM(conn
)));
1426 change_to_root_user();
1429 change_to_root_user();
1430 /* execute any "root postexec = " line */
1431 if (*lp_rootpostexec(SNUM(conn
))) {
1432 char *cmd
= talloc_sub_advanced(talloc_tos(),
1433 lp_servicename(SNUM(conn
)), conn
->user
,
1434 conn
->connectpath
, conn
->gid
,
1435 get_current_username(),
1436 current_user_info
.domain
,
1437 lp_rootpostexec(SNUM(conn
)));