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.
23 extern userdom_struct current_user_info
;
25 /****************************************************************************
26 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
27 absolute path stating in / and not ending in /.
28 Observent people will notice a similarity between this and check_path_syntax :-).
29 ****************************************************************************/
31 void set_conn_connectpath(connection_struct
*conn
, const pstring connectpath
)
35 const char *s
= connectpath
;
36 BOOL start_of_name_component
= True
;
38 *d
++ = '/'; /* Always start with root. */
42 /* Eat multiple '/' */
46 if ((d
> destname
+ 1) && (*s
!= '\0')) {
49 start_of_name_component
= True
;
53 if (start_of_name_component
) {
54 if ((s
[0] == '.') && (s
[1] == '.') && (s
[2] == '/' || s
[2] == '\0')) {
55 /* Uh oh - "/../" or "/..\0" ! */
57 /* Go past the ../ or .. */
61 s
+= 2; /* Go past the .. */
64 /* If we just added a '/' - delete it */
65 if ((d
> destname
) && (*(d
-1) == '/')) {
70 /* Are we at the start ? Can't go back further if so. */
72 *d
++ = '/'; /* Can't delete root */
75 /* Go back one level... */
76 /* Decrement d first as d points to the *next* char to write into. */
77 for (d
--; d
> destname
; d
--) {
82 /* We're still at the start of a name component, just the previous one. */
84 } else if ((s
[0] == '.') && ((s
[1] == '\0') || s
[1] == '/')) {
85 /* Component of pathname can't be "." only - skip the '.' . */
98 switch(next_mb_char_size(s
)) {
112 start_of_name_component
= False
;
116 /* And must not end in '/' */
117 if (d
> destname
+ 1 && (*(d
-1) == '/')) {
121 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
122 lp_servicename(SNUM(conn
)), destname
));
124 string_set(&conn
->connectpath
, destname
);
127 /****************************************************************************
128 Load parameters specific to a connection/service.
129 ****************************************************************************/
131 BOOL
set_current_service(connection_struct
*conn
, uint16 flags
, BOOL do_chdir
)
133 static connection_struct
*last_conn
;
134 static uint16 last_flags
;
142 conn
->lastused_count
++;
147 vfs_ChDir(conn
,conn
->connectpath
) != 0 &&
148 vfs_ChDir(conn
,conn
->origpath
) != 0) {
149 DEBUG(0,("chdir (%s) failed\n",
154 if ((conn
== last_conn
) && (last_flags
== flags
)) {
161 /* Obey the client case sensitivity requests - only for clients that support it. */
162 switch (lp_casesensitive(snum
)) {
165 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
166 enum remote_arch_types ra_type
= get_remote_arch();
167 if ((ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
168 /* Client can't support per-packet case sensitive pathnames. */
169 conn
->case_sensitive
= False
;
171 conn
->case_sensitive
= !(flags
& FLAG_CASELESS_PATHNAMES
);
176 conn
->case_sensitive
= True
;
179 conn
->case_sensitive
= False
;
185 /****************************************************************************
186 Add a home service. Returns the new service number or -1 if fail.
187 ****************************************************************************/
189 int add_home_service(const char *service
, const char *username
, const char *homedir
)
193 if (!service
|| !homedir
)
196 if ((iHomeService
= lp_servicenumber(HOMES_NAME
)) < 0)
200 * If this is a winbindd provided username, remove
201 * the domain component before adding the service.
202 * Log a warning if the "path=" parameter does not
203 * include any macros.
207 const char *p
= strchr(service
,*lp_winbind_separator());
209 /* We only want the 'user' part of the string */
215 if (!lp_add_home(service
, iHomeService
, username
, homedir
)) {
219 return lp_servicenumber(service
);
225 * Find a service entry.
227 * @param service is modified (to canonical form??)
230 int find_service(fstring service
)
234 all_string_sub(service
,"\\","/",0);
236 iService
= lp_servicenumber(service
);
238 /* now handle the special case of a home directory */
240 char *phome_dir
= get_user_home_dir(service
);
244 * Try mapping the servicename, it may
245 * be a Windows to unix mapped user name.
247 if(map_username(service
))
248 phome_dir
= get_user_home_dir(service
);
251 DEBUG(3,("checking for home directory %s gave %s\n",service
,
252 phome_dir
?phome_dir
:"(NULL)"));
254 iService
= add_home_service(service
,service
/* 'username' */, phome_dir
);
257 /* If we still don't have a service, attempt to add it as a printer. */
261 if ((iPrinterService
= lp_servicenumber(PRINTERS_NAME
)) >= 0) {
262 DEBUG(3,("checking whether %s is a valid printer name...\n", service
));
263 if (pcap_printername_ok(service
)) {
264 DEBUG(3,("%s is a valid printer name\n", service
));
265 DEBUG(3,("adding %s as a printer service\n", service
));
266 lp_add_printer(service
, iPrinterService
);
267 iService
= lp_servicenumber(service
);
269 DEBUG(0,("failed to add %s as a printer service!\n", service
));
272 DEBUG(3,("%s is not a valid printer name\n", service
));
277 /* Check for default vfs service? Unsure whether to implement this */
281 /* just possibly it's a default service? */
283 char *pdefservice
= lp_defaultservice();
284 if (pdefservice
&& *pdefservice
&& !strequal(pdefservice
,service
) && !strstr_m(service
,"..")) {
286 * We need to do a local copy here as lp_defaultservice()
287 * returns one of the rotating lp_string buffers that
288 * could get overwritten by the recursive find_service() call
289 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
292 pstrcpy(defservice
, pdefservice
);
293 iService
= find_service(defservice
);
295 all_string_sub(service
, "_","/",0);
296 iService
= lp_add_service(service
, iService
);
301 /* Is it a usershare service ? */
302 if (iService
< 0 && *lp_usershare_path()) {
303 /* Ensure the name is canonicalized. */
305 iService
= load_usershare_service(service
);
309 if (!VALID_SNUM(iService
)) {
310 DEBUG(0,("Invalid snum %d for %s\n",iService
, service
));
316 DEBUG(3,("find_service() failed to find service %s\n", service
));
322 /****************************************************************************
323 do some basic sainity checks on the share.
324 This function modifies dev, ecode.
325 ****************************************************************************/
327 static NTSTATUS
share_sanity_checks(int snum
, fstring dev
)
330 if (!lp_snum_ok(snum
) ||
331 !check_access(smbd_server_fd(),
332 lp_hostsallow(snum
), lp_hostsdeny(snum
))) {
333 return NT_STATUS_ACCESS_DENIED
;
336 if (dev
[0] == '?' || !dev
[0]) {
337 if (lp_print_ok(snum
)) {
338 fstrcpy(dev
,"LPT1:");
339 } else if (strequal(lp_fstype(snum
), "IPC")) {
348 if (lp_print_ok(snum
)) {
349 if (!strequal(dev
, "LPT1:")) {
350 return NT_STATUS_BAD_DEVICE_TYPE
;
352 } else if (strequal(lp_fstype(snum
), "IPC")) {
353 if (!strequal(dev
, "IPC")) {
354 return NT_STATUS_BAD_DEVICE_TYPE
;
356 } else if (!strequal(dev
, "A:")) {
357 return NT_STATUS_BAD_DEVICE_TYPE
;
360 /* Behave as a printer if we are supposed to */
361 if (lp_print_ok(snum
) && (strcmp(dev
, "A:") == 0)) {
362 fstrcpy(dev
, "LPT1:");
368 static NTSTATUS
find_forced_user(int snum
, BOOL vuser_is_guest
,
369 uid_t
*uid
, gid_t
*gid
, fstring username
,
370 struct nt_user_token
**token
)
373 char *fuser
, *found_username
;
376 mem_ctx
= talloc_new(NULL
);
377 if (mem_ctx
== NULL
) {
378 DEBUG(0, ("talloc_new failed\n"));
379 return NT_STATUS_NO_MEMORY
;
382 fuser
= talloc_string_sub(mem_ctx
, lp_force_user(snum
), "%S",
383 lp_servicename(snum
));
385 result
= NT_STATUS_NO_MEMORY
;
389 result
= create_token_from_username(mem_ctx
, fuser
, vuser_is_guest
,
390 uid
, gid
, &found_username
,
392 if (!NT_STATUS_IS_OK(result
)) {
396 talloc_steal(NULL
, *token
);
397 fstrcpy(username
, found_username
);
399 result
= NT_STATUS_OK
;
401 TALLOC_FREE(mem_ctx
);
406 * Go through lookup_name etc to find the force'd group.
408 * Create a new token from src_token, replacing the primary group sid with the
412 static NTSTATUS
find_forced_group(BOOL force_user
,
413 int snum
, const char *username
,
417 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
420 enum SID_NAME_USE type
;
422 BOOL user_must_be_member
= False
;
425 ZERO_STRUCTP(pgroup_sid
);
428 mem_ctx
= talloc_new(NULL
);
429 if (mem_ctx
== NULL
) {
430 DEBUG(0, ("talloc_new failed\n"));
431 return NT_STATUS_NO_MEMORY
;
434 groupname
= talloc_strdup(mem_ctx
, lp_force_group(snum
));
435 if (groupname
== NULL
) {
436 DEBUG(1, ("talloc_strdup failed\n"));
437 result
= NT_STATUS_NO_MEMORY
;
441 if (groupname
[0] == '+') {
442 user_must_be_member
= True
;
446 groupname
= talloc_string_sub(mem_ctx
, groupname
,
447 "%S", lp_servicename(snum
));
449 if (!lookup_name_smbconf(mem_ctx
, groupname
,
450 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
451 NULL
, NULL
, &group_sid
, &type
)) {
452 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
457 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
458 (type
!= SID_NAME_WKN_GRP
)) {
459 DEBUG(10, ("%s is a %s, not a group\n", groupname
,
460 sid_type_lookup(type
)));
464 if (!sid_to_gid(&group_sid
, &gid
)) {
465 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
466 sid_string_static(&group_sid
), groupname
));
471 * If the user has been forced and the forced group starts with a '+',
472 * then we only set the group to be the forced group if the forced
473 * user is a member of that group. Otherwise, the meaning of the '+'
477 if (force_user
&& user_must_be_member
) {
478 if (user_in_group_sid(username
, &group_sid
)) {
479 sid_copy(pgroup_sid
, &group_sid
);
481 DEBUG(3,("Forced group %s for member %s\n",
482 groupname
, username
));
484 DEBUG(0,("find_forced_group: forced user %s is not a member "
485 "of forced group %s. Disallowing access.\n",
486 username
, groupname
));
487 result
= NT_STATUS_MEMBER_NOT_IN_GROUP
;
491 sid_copy(pgroup_sid
, &group_sid
);
493 DEBUG(3,("Forced group %s\n", groupname
));
496 result
= NT_STATUS_OK
;
498 TALLOC_FREE(mem_ctx
);
502 /****************************************************************************
503 Make a connection, given the snum to connect to, and the vuser of the
504 connecting user if appropriate.
505 ****************************************************************************/
507 static connection_struct
*make_connection_snum(int snum
, user_struct
*vuser
,
512 struct passwd
*pass
= NULL
;
514 connection_struct
*conn
;
522 SET_STAT_INVALID(st
);
524 if (NT_STATUS_IS_ERR(*status
= share_sanity_checks(snum
, dev
))) {
530 DEBUG(0,("Couldn't find free connection.\n"));
531 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
535 conn
->nt_user_token
= NULL
;
537 if (lp_guest_only(snum
)) {
538 const char *guestname
= lp_guestaccount();
540 char *found_username
;
542 pass
= getpwnam_alloc(NULL
, guestname
);
544 DEBUG(0,("make_connection_snum: Invalid guest "
545 "account %s??\n",guestname
));
547 *status
= NT_STATUS_NO_SUCH_USER
;
550 status2
= create_token_from_username(NULL
, pass
->pw_name
, True
,
551 &conn
->uid
, &conn
->gid
,
553 &conn
->nt_user_token
);
554 if (!NT_STATUS_IS_OK(status2
)) {
559 fstrcpy(user
, found_username
);
560 string_set(&conn
->user
,user
);
561 conn
->force_user
= True
;
563 DEBUG(3,("Guest only user %s\n",user
));
566 if (!lp_guest_ok(snum
)) {
567 DEBUG(2, ("guest user (from session setup) "
568 "not permitted to access this share "
569 "(%s)\n", lp_servicename(snum
)));
571 *status
= NT_STATUS_ACCESS_DENIED
;
575 if (!user_ok_token(vuser
->user
.unix_name
,
576 vuser
->nt_user_token
, snum
)) {
577 DEBUG(2, ("user '%s' (from session setup) not "
578 "permitted to access this share "
579 "(%s)\n", vuser
->user
.unix_name
,
580 lp_servicename(snum
)));
582 *status
= NT_STATUS_ACCESS_DENIED
;
586 conn
->vuid
= vuser
->vuid
;
587 conn
->uid
= vuser
->uid
;
588 conn
->gid
= vuser
->gid
;
589 string_set(&conn
->user
,vuser
->user
.unix_name
);
590 fstrcpy(user
,vuser
->user
.unix_name
);
591 guest
= vuser
->guest
;
592 } else if (lp_security() == SEC_SHARE
) {
594 char *found_username
;
595 /* add it as a possible user name if we
596 are in share mode security */
597 add_session_user(lp_servicename(snum
));
598 /* shall we let them in? */
599 if (!authorise_login(snum
,user
,password
,&guest
)) {
600 DEBUG( 2, ( "Invalid username/password for [%s]\n",
601 lp_servicename(snum
)) );
603 *status
= NT_STATUS_WRONG_PASSWORD
;
606 pass
= Get_Pwnam(user
);
607 status2
= create_token_from_username(NULL
, pass
->pw_name
, True
,
608 &conn
->uid
, &conn
->gid
,
610 &conn
->nt_user_token
);
611 if (!NT_STATUS_IS_OK(status2
)) {
616 fstrcpy(user
, found_username
);
617 string_set(&conn
->user
,user
);
618 conn
->force_user
= True
;
620 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
622 *status
= NT_STATUS_ACCESS_DENIED
;
626 add_session_user(user
);
628 safe_strcpy(conn
->client_address
, client_addr(),
629 sizeof(conn
->client_address
)-1);
630 conn
->num_files_open
= 0;
631 conn
->lastused
= conn
->lastused_count
= time(NULL
);
632 conn
->service
= snum
;
634 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
635 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
636 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
639 /* Case options for the share. */
640 if (lp_casesensitive(snum
) == Auto
) {
641 /* We will be setting this per packet. Set to be case
642 * insensitive for now. */
643 conn
->case_sensitive
= False
;
645 conn
->case_sensitive
= (BOOL
)lp_casesensitive(snum
);
648 conn
->case_preserve
= lp_preservecase(snum
);
649 conn
->short_case_preserve
= lp_shortpreservecase(snum
);
651 conn
->veto_list
= NULL
;
652 conn
->hide_list
= NULL
;
653 conn
->veto_oplock_list
= NULL
;
654 conn
->aio_write_behind_list
= NULL
;
655 string_set(&conn
->dirpath
,"");
656 string_set(&conn
->user
,user
);
658 conn
->read_only
= lp_readonly(conn
->service
);
659 conn
->admin_user
= False
;
662 * If force user is true, then store the given userid and the gid of
663 * the user we're forcing.
664 * For auxiliary groups see below.
667 if (*lp_force_user(snum
)) {
670 status2
= find_forced_user(snum
,
671 (vuser
!= NULL
) && vuser
->guest
,
672 &conn
->uid
, &conn
->gid
, user
,
673 &conn
->nt_user_token
);
674 if (!NT_STATUS_IS_OK(status2
)) {
679 string_set(&conn
->user
,user
);
680 conn
->force_user
= True
;
681 DEBUG(3,("Forced user %s\n",user
));
685 * If force group is true, then override
686 * any groupid stored for the connecting user.
689 if (*lp_force_group(snum
)) {
693 status2
= find_forced_group(conn
->force_user
,
695 &group_sid
, &conn
->gid
);
696 if (!NT_STATUS_IS_OK(status2
)) {
702 if ((conn
->nt_user_token
== NULL
) && (vuser
!= NULL
)) {
704 /* Not force user and not security=share, but force
705 * group. vuser has a token to copy */
707 conn
->nt_user_token
= dup_nt_token(
708 NULL
, vuser
->nt_user_token
);
709 if (conn
->nt_user_token
== NULL
) {
710 DEBUG(0, ("dup_nt_token failed\n"));
712 *status
= NT_STATUS_NO_MEMORY
;
717 /* If conn->nt_user_token is still NULL, we have
718 * security=share. This means ignore the SID, as we had no
719 * vuser to copy from */
721 if (conn
->nt_user_token
!= NULL
) {
722 /* Overwrite the primary group sid */
723 sid_copy(&conn
->nt_user_token
->user_sids
[1],
727 conn
->force_group
= True
;
730 if (conn
->nt_user_token
!= NULL
) {
733 /* We have a share-specific token from force [user|group].
734 * This means we have to create the list of unix groups from
735 * the list of sids. */
740 for (i
=0; i
<conn
->nt_user_token
->num_sids
; i
++) {
742 DOM_SID
*sid
= &conn
->nt_user_token
->user_sids
[i
];
744 if (!sid_to_gid(sid
, &gid
)) {
745 DEBUG(10, ("Could not convert SID %s to gid, "
747 sid_string_static(sid
)));
750 add_gid_to_array_unique(NULL
, gid
, &conn
->groups
,
757 pstrcpy(s
,lp_pathname(snum
));
758 standard_sub_conn(conn
,s
,sizeof(s
));
759 set_conn_connectpath(conn
,s
);
760 DEBUG(3,("Connect path is '%s' for service [%s]\n",s
,
761 lp_servicename(snum
)));
765 * New code to check if there's a share security descripter
766 * added from NT server manager. This is done after the
767 * smb.conf checks are done as we need a uid and token. JRA.
772 BOOL can_write
= share_access_check(conn
, snum
, vuser
,
776 if (!share_access_check(conn
, snum
, vuser
,
778 /* No access, read or write. */
779 DEBUG(0,("make_connection: connection to %s "
780 "denied due to security "
782 lp_servicename(snum
)));
784 *status
= NT_STATUS_ACCESS_DENIED
;
787 conn
->read_only
= True
;
791 /* Initialise VFS function pointers */
793 if (!smbd_vfs_init(conn
)) {
794 DEBUG(0, ("vfs_init failed for service %s\n",
795 lp_servicename(snum
)));
797 *status
= NT_STATUS_BAD_NETWORK_NAME
;
802 * If widelinks are disallowed we need to canonicalise the connect
803 * path here to ensure we don't have any symlinks in the
804 * connectpath. We will be checking all paths on this connection are
805 * below this directory. We must do this after the VFS init as we
806 * depend on the realpath() pointer in the vfs table. JRA.
808 if (!lp_widelinks(snum
)) {
810 pstrcpy(s
,conn
->connectpath
);
811 canonicalize_path(conn
, s
);
812 set_conn_connectpath(conn
,s
);
815 /* ROOT Activities: */
816 /* check number of connections */
817 if (!claim_connection(conn
,
818 lp_servicename(snum
),
819 lp_max_connections(snum
),
821 DEBUG(1,("too many connections - rejected\n"));
823 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
827 /* Preexecs are done here as they might make the dir we are to ChDir
829 /* execute any "root preexec = " line */
830 if (*lp_rootpreexec(snum
)) {
832 pstrcpy(cmd
,lp_rootpreexec(snum
));
833 standard_sub_conn(conn
,cmd
,sizeof(cmd
));
834 DEBUG(5,("cmd=%s\n",cmd
));
835 ret
= smbrun(cmd
,NULL
);
836 if (ret
!= 0 && lp_rootpreexec_close(snum
)) {
837 DEBUG(1,("root preexec gave %d - failing "
838 "connection\n", ret
));
839 yield_connection(conn
, lp_servicename(snum
));
841 *status
= NT_STATUS_ACCESS_DENIED
;
846 /* USER Activites: */
847 if (!change_to_user(conn
, conn
->vuid
)) {
848 /* No point continuing if they fail the basic checks */
849 DEBUG(0,("Can't become connected user!\n"));
850 yield_connection(conn
, lp_servicename(snum
));
852 *status
= NT_STATUS_LOGON_FAILURE
;
856 /* Remember that a different vuid can connect later without these
859 /* Preexecs are done here as they might make the dir we are to ChDir
862 /* execute any "preexec = " line */
863 if (*lp_preexec(snum
)) {
865 pstrcpy(cmd
,lp_preexec(snum
));
866 standard_sub_conn(conn
,cmd
,sizeof(cmd
));
867 ret
= smbrun(cmd
,NULL
);
868 if (ret
!= 0 && lp_preexec_close(snum
)) {
869 DEBUG(1,("preexec gave %d - failing connection\n",
871 change_to_root_user();
872 yield_connection(conn
, lp_servicename(snum
));
874 *status
= NT_STATUS_ACCESS_DENIED
;
879 #ifdef WITH_FAKE_KASERVER
880 if (lp_afs_share(snum
)) {
885 /* Add veto/hide lists */
886 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
887 set_namearray( &conn
->veto_list
, lp_veto_files(snum
));
888 set_namearray( &conn
->hide_list
, lp_hide_files(snum
));
889 set_namearray( &conn
->veto_oplock_list
, lp_veto_oplocks(snum
));
892 /* Invoke VFS make connection hook - do this before the VFS_STAT call
893 to allow any filesystems needing user credentials to initialize
896 if (SMB_VFS_CONNECT(conn
, lp_servicename(snum
), user
) < 0) {
897 DEBUG(0,("make_connection: VFS make connection failed!\n"));
898 change_to_root_user();
899 yield_connection(conn
, lp_servicename(snum
));
901 *status
= NT_STATUS_UNSUCCESSFUL
;
905 /* win2000 does not check the permissions on the directory
906 during the tree connect, instead relying on permission
907 check during individual operations. To match this behaviour
908 I have disabled this chdir check (tridge) */
909 /* the alternative is just to check the directory exists */
910 if ((ret
= SMB_VFS_STAT(conn
, conn
->connectpath
, &st
)) != 0 ||
911 !S_ISDIR(st
.st_mode
)) {
912 if (ret
== 0 && !S_ISDIR(st
.st_mode
)) {
913 DEBUG(0,("'%s' is not a directory, when connecting to "
914 "[%s]\n", conn
->connectpath
,
915 lp_servicename(snum
)));
917 DEBUG(0,("'%s' does not exist or permission denied "
918 "when connecting to [%s] Error was %s\n",
919 conn
->connectpath
, lp_servicename(snum
),
922 change_to_root_user();
923 /* Call VFS disconnect hook */
924 SMB_VFS_DISCONNECT(conn
);
925 yield_connection(conn
, lp_servicename(snum
));
927 *status
= NT_STATUS_BAD_NETWORK_NAME
;
931 string_set(&conn
->origpath
,conn
->connectpath
);
933 #if SOFTLINK_OPTIMISATION
934 /* resolve any soft links early if possible */
935 if (vfs_ChDir(conn
,conn
->connectpath
) == 0) {
937 pstrcpy(s
,conn
->connectpath
);
939 set_conn_connectpath(conn
,s
);
940 vfs_ChDir(conn
,conn
->connectpath
);
945 * Print out the 'connected as' stuff here as we need
946 * to know the effective uid and gid we will be using
947 * (at least initially).
950 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 1 ) ) {
951 dbgtext( "%s (%s) ", get_remote_machine_name(),
952 conn
->client_address
);
953 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
954 dbgtext( "connect to service %s ", lp_servicename(snum
) );
955 dbgtext( "initially as user %s ", user
);
956 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
957 dbgtext( "(pid %d)\n", (int)sys_getpid() );
960 /* Setup the minimum value for a change notify wait time (seconds). */
961 set_change_notify_timeout(lp_change_notify_timeout(snum
));
963 /* we've finished with the user stuff - go back to root */
964 change_to_root_user();
968 /***************************************************************************************
969 Simple wrapper function for make_connection() to include a call to
971 **************************************************************************************/
973 connection_struct
*make_connection_with_chdir(const char *service_in
,
975 const char *dev
, uint16 vuid
,
978 connection_struct
*conn
= NULL
;
980 conn
= make_connection(service_in
, password
, dev
, vuid
, status
);
983 * make_connection() does not change the directory for us any more
984 * so we have to do it as a separate step --jerry
987 if ( conn
&& vfs_ChDir(conn
,conn
->connectpath
) != 0 ) {
988 DEBUG(0,("move_driver_to_download_area: Can't change "
989 "directory to %s for [print$] (%s)\n",
990 conn
->connectpath
,strerror(errno
)));
991 yield_connection(conn
, lp_servicename(SNUM(conn
)));
993 *status
= NT_STATUS_UNSUCCESSFUL
;
1000 /****************************************************************************
1001 Make a connection to a service.
1004 ****************************************************************************/
1006 connection_struct
*make_connection(const char *service_in
, DATA_BLOB password
,
1007 const char *pdev
, uint16 vuid
,
1011 user_struct
*vuser
= NULL
;
1018 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1020 if (!non_root_mode() && (euid
= geteuid()) != 0) {
1021 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1022 "(%u)\n", (unsigned int)euid
));
1023 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1026 if (conn_num_open() > 2047) {
1027 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
1031 if(lp_security() != SEC_SHARE
) {
1032 vuser
= get_valid_user_struct(vuid
);
1034 DEBUG(1,("make_connection: refusing to connect with "
1035 "no session setup\n"));
1036 *status
= NT_STATUS_ACCESS_DENIED
;
1041 /* Logic to try and connect to the correct [homes] share, preferably
1042 without too many getpwnam() lookups. This is particulary nasty for
1043 winbind usernames, where the share name isn't the same as unix
1046 The snum of the homes share is stored on the vuser at session setup
1050 if (strequal(service_in
,HOMES_NAME
)) {
1051 if(lp_security() != SEC_SHARE
) {
1052 DATA_BLOB no_pw
= data_blob(NULL
, 0);
1053 if (vuser
->homes_snum
== -1) {
1054 DEBUG(2, ("[homes] share not available for "
1055 "this user because it was not found "
1056 "or created at session setup "
1058 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1061 DEBUG(5, ("making a connection to [homes] service "
1062 "created at session setup time\n"));
1063 return make_connection_snum(vuser
->homes_snum
,
1067 /* Security = share. Try with
1068 * current_user_info.smb_name as the username. */
1069 if (*current_user_info
.smb_name
) {
1070 fstring unix_username
;
1071 fstrcpy(unix_username
,
1072 current_user_info
.smb_name
);
1073 map_username(unix_username
);
1074 snum
= find_service(unix_username
);
1077 DEBUG(5, ("making a connection to 'homes' "
1078 "service %s based on "
1079 "security=share\n", service_in
));
1080 return make_connection_snum(snum
, NULL
,
1085 } else if ((lp_security() != SEC_SHARE
) && (vuser
->homes_snum
!= -1)
1086 && strequal(service_in
,
1087 lp_servicename(vuser
->homes_snum
))) {
1088 DATA_BLOB no_pw
= data_blob(NULL
, 0);
1089 DEBUG(5, ("making a connection to 'homes' service [%s] "
1090 "created at session setup time\n", service_in
));
1091 return make_connection_snum(vuser
->homes_snum
,
1096 fstrcpy(service
, service_in
);
1098 strlower_m(service
);
1100 snum
= find_service(service
);
1103 if (strequal(service
,"IPC$") ||
1104 (lp_enable_asu_support() && strequal(service
,"ADMIN$"))) {
1105 DEBUG(3,("refusing IPC connection to %s\n", service
));
1106 *status
= NT_STATUS_ACCESS_DENIED
;
1110 DEBUG(0,("%s (%s) couldn't find service %s\n",
1111 get_remote_machine_name(), client_addr(), service
));
1112 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1116 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1117 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum
) != '\0')) {
1118 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1119 "(pointing to %s)\n",
1120 service
, lp_msdfs_proxy(snum
)));
1121 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1125 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
1127 return make_connection_snum(snum
, vuser
,
1132 /****************************************************************************
1134 ****************************************************************************/
1136 void close_cnum(connection_struct
*conn
, uint16 vuid
)
1139 pipe_close_conn(conn
);
1141 file_close_conn(conn
);
1142 dptr_closecnum(conn
);
1145 change_to_root_user();
1147 DEBUG(IS_IPC(conn
)?3:1, ("%s (%s) closed connection to service %s\n",
1148 get_remote_machine_name(),
1149 conn
->client_address
,
1150 lp_servicename(SNUM(conn
))));
1152 /* Call VFS disconnect hook */
1153 SMB_VFS_DISCONNECT(conn
);
1155 yield_connection(conn
, lp_servicename(SNUM(conn
)));
1157 /* make sure we leave the directory available for unmount */
1158 vfs_ChDir(conn
, "/");
1160 /* execute any "postexec = " line */
1161 if (*lp_postexec(SNUM(conn
)) &&
1162 change_to_user(conn
, vuid
)) {
1164 pstrcpy(cmd
,lp_postexec(SNUM(conn
)));
1165 standard_sub_conn(conn
,cmd
,sizeof(cmd
));
1167 change_to_root_user();
1170 change_to_root_user();
1171 /* execute any "root postexec = " line */
1172 if (*lp_rootpostexec(SNUM(conn
))) {
1174 pstrcpy(cmd
,lp_rootpostexec(SNUM(conn
)));
1175 standard_sub_conn(conn
,cmd
,sizeof(cmd
));