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 static BOOL
canonicalize_path(connection_struct
*conn
, pstring path
)
27 #ifdef REALPATH_TAKES_NULL
28 char *resolved_name
= SMB_VFS_REALPATH(conn
,path
,NULL
);
32 pstrcpy(path
, resolved_name
);
33 SAFE_FREE(resolved_name
);
37 char resolved_name_buf
[PATH_MAX
+1];
39 pstring resolved_name_buf
;
41 char *resolved_name
= SMB_VFS_REALPATH(conn
,path
,resolved_name_buf
);
45 pstrcpy(path
, resolved_name
);
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
)
60 const char *s
= connectpath
;
61 BOOL start_of_name_component
= True
;
63 *d
++ = '/'; /* Always start with root. */
67 /* Eat multiple '/' */
71 if ((d
> destname
+ 1) && (*s
!= '\0')) {
74 start_of_name_component
= True
;
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 .. */
86 s
+= 2; /* Go past the .. */
89 /* If we just added a '/' - delete it */
90 if ((d
> destname
) && (*(d
-1) == '/')) {
95 /* Are we at the start ? Can't go back further if so. */
97 *d
++ = '/'; /* Can't delete root */
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
--) {
107 /* We're still at the start of a name component, just the previous one. */
109 } else if ((s
[0] == '.') && ((s
[1] == '\0') || s
[1] == '/')) {
110 /* Component of pathname can't be "." only - skip the '.' . */
124 /* Get the size of the next MB character. */
125 next_codepoint(s
,&siz
);
146 start_of_name_component
= False
;
150 /* And must not end in '/' */
151 if (d
> destname
+ 1 && (*(d
-1) == '/')) {
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
;
176 conn
->lastused_count
++;
181 vfs_ChDir(conn
,conn
->connectpath
) != 0 &&
182 vfs_ChDir(conn
,conn
->origpath
) != 0) {
183 DEBUG(0,("chdir (%s) failed\n",
188 if ((conn
== last_conn
) && (last_flags
== flags
)) {
195 /* Obey the client case sensitivity requests - only for clients that support it. */
196 switch (lp_casesensitive(snum
)) {
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
;
205 conn
->case_sensitive
= !(flags
& FLAG_CASELESS_PATHNAMES
);
210 conn
->case_sensitive
= True
;
213 conn
->case_sensitive
= False
;
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
)
227 if (!service
|| !homedir
|| homedir
[0] == '\0')
230 if ((iHomeService
= lp_servicenumber(HOMES_NAME
)) < 0)
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 */
249 if (!lp_add_home(service
, iHomeService
, username
, homedir
)) {
253 return lp_servicenumber(service
);
259 * Find a service entry.
261 * @param service is modified (to canonical form??)
264 int find_service(fstring service
)
268 all_string_sub(service
,"\\","/",0);
270 iService
= lp_servicenumber(service
);
272 /* now handle the special case of a home directory */
274 char *phome_dir
= get_user_home_dir(service
);
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. */
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
);
303 DEBUG(0,("failed to add %s as a printer service!\n", service
));
306 DEBUG(3,("%s is not a valid printer name\n", service
));
311 /* Check for default vfs service? Unsure whether to implement this */
315 /* Is it a usershare service ? */
316 if (iService
< 0 && *lp_usershare_path()) {
317 /* Ensure the name is canonicalized. */
319 iService
= load_usershare_service(service
);
322 /* just possibly it's a default service? */
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>.
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$")) {
342 iService
= find_service(defservice
);
344 all_string_sub(service
, "_","/",0);
345 iService
= lp_add_service(service
, iService
);
351 if (!VALID_SNUM(iService
)) {
352 DEBUG(0,("Invalid snum %d for %s\n",iService
, service
));
360 DEBUG(3,("find_service() failed to find service %s\n", service
));
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")) {
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:");
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
;
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
)) {
430 fstrcpy(username
, found_username
);
433 TALLOC_FREE(found_username
);
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
444 static NTSTATUS
find_forced_group(BOOL force_user
,
445 int snum
, const char *username
,
449 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
452 enum lsa_SidType type
;
454 BOOL user_must_be_member
= False
;
457 ZERO_STRUCTP(pgroup_sid
);
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
;
473 if (groupname
[0] == '+') {
474 user_must_be_member
= True
;
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",
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
)));
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
));
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 '+'
509 if (force_user
&& user_must_be_member
) {
510 if (user_in_group_sid(username
, &group_sid
)) {
511 sid_copy(pgroup_sid
, &group_sid
);
513 DEBUG(3,("Forced group %s for member %s\n",
514 groupname
, username
));
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
;
523 sid_copy(pgroup_sid
, &group_sid
);
525 DEBUG(3,("Forced group %s\n", groupname
));
528 result
= NT_STATUS_OK
;
530 TALLOC_FREE(mem_ctx
);
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
,
544 struct passwd
*pass
= NULL
;
546 connection_struct
*conn
;
554 SET_STAT_INVALID(st
);
556 if (NT_STATUS_IS_ERR(*status
= share_sanity_checks(snum
, dev
))) {
562 DEBUG(0,("Couldn't find free connection.\n"));
563 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
567 conn
->params
->service
= snum
;
568 conn
->nt_user_token
= NULL
;
570 if (lp_guest_only(snum
)) {
571 const char *guestname
= lp_guestaccount();
573 char *found_username
= NULL
;
576 pass
= getpwnam_alloc(NULL
, guestname
);
578 DEBUG(0,("make_connection_snum: Invalid guest "
579 "account %s??\n",guestname
));
581 *status
= NT_STATUS_NO_SUCH_USER
;
584 status2
= create_token_from_username(conn
->mem_ctx
, pass
->pw_name
, True
,
585 &conn
->uid
, &conn
->gid
,
587 &conn
->nt_user_token
);
588 if (!NT_STATUS_IS_OK(status2
)) {
594 fstrcpy(user
, found_username
);
595 string_set(&conn
->user
,user
);
596 conn
->force_user
= True
;
597 TALLOC_FREE(found_username
);
599 DEBUG(3,("Guest only user %s\n",user
));
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
)));
607 *status
= NT_STATUS_ACCESS_DENIED
;
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
)));
618 *status
= NT_STATUS_ACCESS_DENIED
;
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
) {
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
)) );
640 *status
= NT_STATUS_WRONG_PASSWORD
;
643 pass
= Get_Pwnam(user
);
644 status2
= create_token_from_username(conn
->mem_ctx
, pass
->pw_name
, True
,
645 &conn
->uid
, &conn
->gid
,
647 &conn
->nt_user_token
);
648 if (!NT_STATUS_IS_OK(status2
)) {
653 fstrcpy(user
, found_username
);
654 string_set(&conn
->user
,user
);
655 TALLOC_FREE(found_username
);
656 conn
->force_user
= True
;
658 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
660 *status
= NT_STATUS_ACCESS_DENIED
;
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
);
671 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
672 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
673 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
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
;
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
)) {
707 status2
= find_forced_user(conn
,
708 (vuser
!= NULL
) && vuser
->guest
,
710 if (!NT_STATUS_IS_OK(status2
)) {
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
)) {
729 status2
= find_forced_group(conn
->force_user
,
731 &group_sid
, &conn
->gid
);
732 if (!NT_STATUS_IS_OK(status2
)) {
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"));
748 *status
= NT_STATUS_NO_MEMORY
;
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],
763 conn
->force_group
= True
;
766 if (conn
->nt_user_token
!= NULL
) {
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. */
776 for (i
=0; i
<conn
->nt_user_token
->num_sids
; i
++) {
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, "
783 sid_string_static(sid
)));
786 if (!add_gid_to_array_unique(conn
->mem_ctx
, gid
, &conn
->groups
,
788 DEBUG(0, ("add_gid_to_array_unique failed\n"));
790 *status
= NT_STATUS_NO_MEMORY
;
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
,
806 DEBUG(6, ("service [%s] did not resolve to a path\n",
807 lp_servicename(snum
)));
809 *status
= NT_STATUS_BAD_NETWORK_NAME
;
813 set_conn_connectpath(conn
,s
);
814 DEBUG(3,("Connect path is '%s' for service [%s]\n",s
,
815 lp_servicename(snum
)));
819 * New code to check if there's a share security descripter
820 * added from NT server manager. This is done after the
821 * smb.conf checks are done as we need a uid and token. JRA.
826 BOOL can_write
= False
;
827 NT_USER_TOKEN
*token
= conn
->nt_user_token
?
828 conn
->nt_user_token
:
829 (vuser
? vuser
->nt_user_token
: NULL
);
832 * I don't believe this can happen. But the
833 * logic above is convoluted enough to confuse
834 * automated checkers, so be sure. JRA.
838 DEBUG(0,("make_connection: connection to %s "
839 "denied due to missing "
841 lp_servicename(snum
)));
843 *status
= NT_STATUS_ACCESS_DENIED
;
847 can_write
= share_access_check(token
,
848 lp_servicename(snum
),
852 if (!share_access_check(token
,
853 lp_servicename(snum
),
855 /* No access, read or write. */
856 DEBUG(0,("make_connection: connection to %s "
857 "denied due to security "
859 lp_servicename(snum
)));
861 *status
= NT_STATUS_ACCESS_DENIED
;
864 conn
->read_only
= True
;
868 /* Initialise VFS function pointers */
870 if (!smbd_vfs_init(conn
)) {
871 DEBUG(0, ("vfs_init failed for service %s\n",
872 lp_servicename(snum
)));
874 *status
= NT_STATUS_BAD_NETWORK_NAME
;
879 * If widelinks are disallowed we need to canonicalise the connect
880 * path here to ensure we don't have any symlinks in the
881 * connectpath. We will be checking all paths on this connection are
882 * below this directory. We must do this after the VFS init as we
883 * depend on the realpath() pointer in the vfs table. JRA.
885 if (!lp_widelinks(snum
)) {
887 pstrcpy(s
,conn
->connectpath
);
888 canonicalize_path(conn
, s
);
889 set_conn_connectpath(conn
,s
);
892 if ((!conn
->printer
) && (!conn
->ipc
)) {
893 conn
->notify_ctx
= notify_init(conn
->mem_ctx
, server_id_self(),
894 smbd_messaging_context(),
895 smbd_event_context(),
899 /* ROOT Activities: */
900 /* check number of connections */
901 if (!claim_connection(conn
,
902 lp_servicename(snum
),
903 lp_max_connections(snum
),
905 DEBUG(1,("too many connections - rejected\n"));
907 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
911 /* Preexecs are done here as they might make the dir we are to ChDir
913 /* execute any "root preexec = " line */
914 if (*lp_rootpreexec(snum
)) {
916 pstrcpy(cmd
,lp_rootpreexec(snum
));
917 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
918 conn
->connectpath
, conn
->gid
,
919 get_current_username(),
920 current_user_info
.domain
,
922 DEBUG(5,("cmd=%s\n",cmd
));
923 ret
= smbrun(cmd
,NULL
);
924 if (ret
!= 0 && lp_rootpreexec_close(snum
)) {
925 DEBUG(1,("root preexec gave %d - failing "
926 "connection\n", ret
));
927 yield_connection(conn
, lp_servicename(snum
));
929 *status
= NT_STATUS_ACCESS_DENIED
;
934 /* USER Activites: */
935 if (!change_to_user(conn
, conn
->vuid
)) {
936 /* No point continuing if they fail the basic checks */
937 DEBUG(0,("Can't become connected user!\n"));
938 yield_connection(conn
, lp_servicename(snum
));
940 *status
= NT_STATUS_LOGON_FAILURE
;
944 /* Remember that a different vuid can connect later without these
947 /* Preexecs are done here as they might make the dir we are to ChDir
950 /* execute any "preexec = " line */
951 if (*lp_preexec(snum
)) {
953 pstrcpy(cmd
,lp_preexec(snum
));
954 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
955 conn
->connectpath
, conn
->gid
,
956 get_current_username(),
957 current_user_info
.domain
,
959 ret
= smbrun(cmd
,NULL
);
960 if (ret
!= 0 && lp_preexec_close(snum
)) {
961 DEBUG(1,("preexec gave %d - failing connection\n",
963 change_to_root_user();
964 yield_connection(conn
, lp_servicename(snum
));
966 *status
= NT_STATUS_ACCESS_DENIED
;
971 #ifdef WITH_FAKE_KASERVER
972 if (lp_afs_share(snum
)) {
977 /* Add veto/hide lists */
978 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
979 set_namearray( &conn
->veto_list
, lp_veto_files(snum
));
980 set_namearray( &conn
->hide_list
, lp_hide_files(snum
));
981 set_namearray( &conn
->veto_oplock_list
, lp_veto_oplocks(snum
));
984 /* Invoke VFS make connection hook - do this before the VFS_STAT call
985 to allow any filesystems needing user credentials to initialize
988 if (SMB_VFS_CONNECT(conn
, lp_servicename(snum
), user
) < 0) {
989 DEBUG(0,("make_connection: VFS make connection failed!\n"));
990 change_to_root_user();
991 yield_connection(conn
, lp_servicename(snum
));
993 *status
= NT_STATUS_UNSUCCESSFUL
;
997 /* win2000 does not check the permissions on the directory
998 during the tree connect, instead relying on permission
999 check during individual operations. To match this behaviour
1000 I have disabled this chdir check (tridge) */
1001 /* the alternative is just to check the directory exists */
1002 if ((ret
= SMB_VFS_STAT(conn
, conn
->connectpath
, &st
)) != 0 ||
1003 !S_ISDIR(st
.st_mode
)) {
1004 if (ret
== 0 && !S_ISDIR(st
.st_mode
)) {
1005 DEBUG(0,("'%s' is not a directory, when connecting to "
1006 "[%s]\n", conn
->connectpath
,
1007 lp_servicename(snum
)));
1009 DEBUG(0,("'%s' does not exist or permission denied "
1010 "when connecting to [%s] Error was %s\n",
1011 conn
->connectpath
, lp_servicename(snum
),
1014 change_to_root_user();
1015 /* Call VFS disconnect hook */
1016 SMB_VFS_DISCONNECT(conn
);
1017 yield_connection(conn
, lp_servicename(snum
));
1019 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1023 string_set(&conn
->origpath
,conn
->connectpath
);
1025 #if SOFTLINK_OPTIMISATION
1026 /* resolve any soft links early if possible */
1027 if (vfs_ChDir(conn
,conn
->connectpath
) == 0) {
1029 pstrcpy(s
,conn
->connectpath
);
1031 set_conn_connectpath(conn
,s
);
1032 vfs_ChDir(conn
,conn
->connectpath
);
1037 * Print out the 'connected as' stuff here as we need
1038 * to know the effective uid and gid we will be using
1039 * (at least initially).
1042 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 1 ) ) {
1043 dbgtext( "%s (%s) ", get_remote_machine_name(),
1044 conn
->client_address
);
1045 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1046 dbgtext( "connect to service %s ", lp_servicename(snum
) );
1047 dbgtext( "initially as user %s ", user
);
1048 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1049 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1052 /* we've finished with the user stuff - go back to root */
1053 change_to_root_user();
1057 /***************************************************************************************
1058 Simple wrapper function for make_connection() to include a call to
1060 **************************************************************************************/
1062 connection_struct
*make_connection_with_chdir(const char *service_in
,
1064 const char *dev
, uint16 vuid
,
1067 connection_struct
*conn
= NULL
;
1069 conn
= make_connection(service_in
, password
, dev
, vuid
, status
);
1072 * make_connection() does not change the directory for us any more
1073 * so we have to do it as a separate step --jerry
1076 if ( conn
&& vfs_ChDir(conn
,conn
->connectpath
) != 0 ) {
1077 DEBUG(0,("move_driver_to_download_area: Can't change "
1078 "directory to %s for [print$] (%s)\n",
1079 conn
->connectpath
,strerror(errno
)));
1080 yield_connection(conn
, lp_servicename(SNUM(conn
)));
1082 *status
= NT_STATUS_UNSUCCESSFUL
;
1089 /****************************************************************************
1090 Make a connection to a service.
1093 ****************************************************************************/
1095 connection_struct
*make_connection(const char *service_in
, DATA_BLOB password
,
1096 const char *pdev
, uint16 vuid
,
1100 user_struct
*vuser
= NULL
;
1107 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1109 if (!non_root_mode() && (euid
= geteuid()) != 0) {
1110 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1111 "(%u)\n", (unsigned int)euid
));
1112 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1115 if (conn_num_open() > 2047) {
1116 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
1120 if(lp_security() != SEC_SHARE
) {
1121 vuser
= get_valid_user_struct(vuid
);
1123 DEBUG(1,("make_connection: refusing to connect with "
1124 "no session setup\n"));
1125 *status
= NT_STATUS_ACCESS_DENIED
;
1130 /* Logic to try and connect to the correct [homes] share, preferably
1131 without too many getpwnam() lookups. This is particulary nasty for
1132 winbind usernames, where the share name isn't the same as unix
1135 The snum of the homes share is stored on the vuser at session setup
1139 if (strequal(service_in
,HOMES_NAME
)) {
1140 if(lp_security() != SEC_SHARE
) {
1141 DATA_BLOB no_pw
= data_blob(NULL
, 0);
1142 if (vuser
->homes_snum
== -1) {
1143 DEBUG(2, ("[homes] share not available for "
1144 "this user because it was not found "
1145 "or created at session setup "
1147 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1150 DEBUG(5, ("making a connection to [homes] service "
1151 "created at session setup time\n"));
1152 return make_connection_snum(vuser
->homes_snum
,
1156 /* Security = share. Try with
1157 * current_user_info.smb_name as the username. */
1158 if (*current_user_info
.smb_name
) {
1159 fstring unix_username
;
1160 fstrcpy(unix_username
,
1161 current_user_info
.smb_name
);
1162 map_username(unix_username
);
1163 snum
= find_service(unix_username
);
1166 DEBUG(5, ("making a connection to 'homes' "
1167 "service %s based on "
1168 "security=share\n", service_in
));
1169 return make_connection_snum(snum
, NULL
,
1174 } else if ((lp_security() != SEC_SHARE
) && (vuser
->homes_snum
!= -1)
1175 && strequal(service_in
,
1176 lp_servicename(vuser
->homes_snum
))) {
1177 DATA_BLOB no_pw
= data_blob(NULL
, 0);
1178 DEBUG(5, ("making a connection to 'homes' service [%s] "
1179 "created at session setup time\n", service_in
));
1180 return make_connection_snum(vuser
->homes_snum
,
1185 fstrcpy(service
, service_in
);
1187 strlower_m(service
);
1189 snum
= find_service(service
);
1192 if (strequal(service
,"IPC$") ||
1193 (lp_enable_asu_support() && strequal(service
,"ADMIN$"))) {
1194 DEBUG(3,("refusing IPC connection to %s\n", service
));
1195 *status
= NT_STATUS_ACCESS_DENIED
;
1199 DEBUG(0,("%s (%s) couldn't find service %s\n",
1200 get_remote_machine_name(), client_addr(), service
));
1201 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1205 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1206 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum
) != '\0')) {
1207 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1208 "(pointing to %s)\n",
1209 service
, lp_msdfs_proxy(snum
)));
1210 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1214 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
1216 return make_connection_snum(snum
, vuser
,
1221 /****************************************************************************
1223 ****************************************************************************/
1225 void close_cnum(connection_struct
*conn
, uint16 vuid
)
1228 pipe_close_conn(conn
);
1230 file_close_conn(conn
);
1231 dptr_closecnum(conn
);
1234 change_to_root_user();
1236 DEBUG(IS_IPC(conn
)?3:1, ("%s (%s) closed connection to service %s\n",
1237 get_remote_machine_name(),
1238 conn
->client_address
,
1239 lp_servicename(SNUM(conn
))));
1241 /* Call VFS disconnect hook */
1242 SMB_VFS_DISCONNECT(conn
);
1244 yield_connection(conn
, lp_servicename(SNUM(conn
)));
1246 /* make sure we leave the directory available for unmount */
1247 vfs_ChDir(conn
, "/");
1249 /* execute any "postexec = " line */
1250 if (*lp_postexec(SNUM(conn
)) &&
1251 change_to_user(conn
, vuid
)) {
1253 pstrcpy(cmd
,lp_postexec(SNUM(conn
)));
1254 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
1255 conn
->connectpath
, conn
->gid
,
1256 get_current_username(),
1257 current_user_info
.domain
,
1260 change_to_root_user();
1263 change_to_root_user();
1264 /* execute any "root postexec = " line */
1265 if (*lp_rootpostexec(SNUM(conn
))) {
1267 pstrcpy(cmd
,lp_rootpostexec(SNUM(conn
)));
1268 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
1269 conn
->connectpath
, conn
->gid
,
1270 get_current_username(),
1271 current_user_info
.domain
,