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_path(connection_struct
*conn
, pstring path
)
26 #ifdef REALPATH_TAKES_NULL
27 char *resolved_name
= SMB_VFS_REALPATH(conn
,path
,NULL
);
31 pstrcpy(path
, resolved_name
);
32 SAFE_FREE(resolved_name
);
36 char resolved_name_buf
[PATH_MAX
+1];
38 pstring resolved_name_buf
;
40 char *resolved_name
= SMB_VFS_REALPATH(conn
,path
,resolved_name_buf
);
44 pstrcpy(path
, resolved_name
);
46 #endif /* REALPATH_TAKES_NULL */
49 /****************************************************************************
50 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
51 absolute path stating in / and not ending in /.
52 Observent people will notice a similarity between this and check_path_syntax :-).
53 ****************************************************************************/
55 void set_conn_connectpath(connection_struct
*conn
, const char *connectpath
)
59 const char *s
= connectpath
;
60 bool start_of_name_component
= True
;
62 *d
++ = '/'; /* Always start with root. */
66 /* Eat multiple '/' */
70 if ((d
> destname
+ 1) && (*s
!= '\0')) {
73 start_of_name_component
= True
;
77 if (start_of_name_component
) {
78 if ((s
[0] == '.') && (s
[1] == '.') && (s
[2] == '/' || s
[2] == '\0')) {
79 /* Uh oh - "/../" or "/..\0" ! */
81 /* Go past the ../ or .. */
85 s
+= 2; /* Go past the .. */
88 /* If we just added a '/' - delete it */
89 if ((d
> destname
) && (*(d
-1) == '/')) {
94 /* Are we at the start ? Can't go back further if so. */
96 *d
++ = '/'; /* Can't delete root */
99 /* Go back one level... */
100 /* Decrement d first as d points to the *next* char to write into. */
101 for (d
--; d
> destname
; d
--) {
106 /* We're still at the start of a name component, just the previous one. */
108 } else if ((s
[0] == '.') && ((s
[1] == '\0') || s
[1] == '/')) {
109 /* Component of pathname can't be "." only - skip the '.' . */
123 /* Get the size of the next MB character. */
124 next_codepoint(s
,&siz
);
145 start_of_name_component
= False
;
149 /* And must not end in '/' */
150 if (d
> destname
+ 1 && (*(d
-1) == '/')) {
154 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
155 lp_servicename(SNUM(conn
)), destname
));
157 string_set(&conn
->connectpath
, destname
);
160 /****************************************************************************
161 Load parameters specific to a connection/service.
162 ****************************************************************************/
164 bool set_current_service(connection_struct
*conn
, uint16 flags
, bool do_chdir
)
166 static connection_struct
*last_conn
;
167 static uint16 last_flags
;
175 conn
->lastused_count
++;
180 vfs_ChDir(conn
,conn
->connectpath
) != 0 &&
181 vfs_ChDir(conn
,conn
->origpath
) != 0) {
182 DEBUG(0,("chdir (%s) failed\n",
187 if ((conn
== last_conn
) && (last_flags
== flags
)) {
194 /* Obey the client case sensitivity requests - only for clients that support it. */
195 switch (lp_casesensitive(snum
)) {
198 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
199 enum remote_arch_types ra_type
= get_remote_arch();
200 if ((ra_type
!= RA_SAMBA
) && (ra_type
!= RA_CIFSFS
)) {
201 /* Client can't support per-packet case sensitive pathnames. */
202 conn
->case_sensitive
= False
;
204 conn
->case_sensitive
= !(flags
& FLAG_CASELESS_PATHNAMES
);
209 conn
->case_sensitive
= True
;
212 conn
->case_sensitive
= False
;
218 /****************************************************************************
219 Add a home service. Returns the new service number or -1 if fail.
220 ****************************************************************************/
222 int add_home_service(const char *service
, const char *username
, const char *homedir
)
226 if (!service
|| !homedir
)
229 if ((iHomeService
= lp_servicenumber(HOMES_NAME
)) < 0)
233 * If this is a winbindd provided username, remove
234 * the domain component before adding the service.
235 * Log a warning if the "path=" parameter does not
236 * include any macros.
240 const char *p
= strchr(service
,*lp_winbind_separator());
242 /* We only want the 'user' part of the string */
248 if (!lp_add_home(service
, iHomeService
, username
, homedir
)) {
252 return lp_servicenumber(service
);
256 static int load_registry_service(const char *servicename
)
258 struct registry_key
*key
;
264 struct registry_value
*value
;
268 if (!lp_registry_shares()) {
272 if (asprintf(&path
, "%s\\%s", KEY_SMBCONF
, servicename
) == -1) {
276 err
= reg_open_path(NULL
, path
, REG_KEY_READ
, get_root_nt_token(),
280 if (!W_ERROR_IS_OK(err
)) {
284 res
= lp_add_service(servicename
, -1);
290 W_ERROR_IS_OK(reg_enumvalue(key
, key
, i
, &value_name
, &value
));
292 switch (value
->type
) {
295 if (asprintf(&tmp
, "%d", value
->v
.dword
) == -1) {
298 lp_do_parameter(res
, value_name
, tmp
);
303 lp_do_parameter(res
, value_name
, value
->v
.sz
.str
);
307 /* Ignore all the rest */
311 TALLOC_FREE(value_name
);
322 void load_registry_shares(void)
324 struct registry_key
*key
;
329 if (!lp_registry_shares()) {
333 err
= reg_open_path(NULL
, KEY_SMBCONF
, REG_KEY_READ
,
334 get_root_nt_token(), &key
);
335 if (!(W_ERROR_IS_OK(err
))) {
339 for (i
=0; W_ERROR_IS_OK(reg_enumkey(key
, key
, i
, &name
, NULL
)); i
++) {
340 load_registry_service(name
);
349 * Find a service entry.
351 * @param service is modified (to canonical form??)
354 int find_service(fstring service
)
358 all_string_sub(service
,"\\","/",0);
360 iService
= lp_servicenumber(service
);
362 /* now handle the special case of a home directory */
364 char *phome_dir
= get_user_home_dir(service
);
368 * Try mapping the servicename, it may
369 * be a Windows to unix mapped user name.
371 if(map_username(service
))
372 phome_dir
= get_user_home_dir(service
);
375 DEBUG(3,("checking for home directory %s gave %s\n",service
,
376 phome_dir
?phome_dir
:"(NULL)"));
378 iService
= add_home_service(service
,service
/* 'username' */, phome_dir
);
381 /* If we still don't have a service, attempt to add it as a printer. */
385 if ((iPrinterService
= lp_servicenumber(PRINTERS_NAME
)) >= 0) {
386 DEBUG(3,("checking whether %s is a valid printer name...\n", service
));
387 if (pcap_printername_ok(service
)) {
388 DEBUG(3,("%s is a valid printer name\n", service
));
389 DEBUG(3,("adding %s as a printer service\n", service
));
390 lp_add_printer(service
, iPrinterService
);
391 iService
= lp_servicenumber(service
);
393 DEBUG(0,("failed to add %s as a printer service!\n", service
));
396 DEBUG(3,("%s is not a valid printer name\n", service
));
401 /* Check for default vfs service? Unsure whether to implement this */
406 iService
= load_registry_service(service
);
409 /* Is it a usershare service ? */
410 if (iService
< 0 && *lp_usershare_path()) {
411 /* Ensure the name is canonicalized. */
413 iService
= load_usershare_service(service
);
416 /* just possibly it's a default service? */
418 char *pdefservice
= lp_defaultservice();
419 if (pdefservice
&& *pdefservice
&& !strequal(pdefservice
,service
) && !strstr_m(service
,"..")) {
421 * We need to do a local copy here as lp_defaultservice()
422 * returns one of the rotating lp_string buffers that
423 * could get overwritten by the recursive find_service() call
424 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
427 pstrcpy(defservice
, pdefservice
);
429 /* Disallow anything except explicit share names. */
430 if (strequal(defservice
,HOMES_NAME
) ||
431 strequal(defservice
, PRINTERS_NAME
) ||
432 strequal(defservice
, "IPC$")) {
436 iService
= find_service(defservice
);
438 all_string_sub(service
, "_","/",0);
439 iService
= lp_add_service(service
, iService
);
445 if (!VALID_SNUM(iService
)) {
446 DEBUG(0,("Invalid snum %d for %s\n",iService
, service
));
454 DEBUG(3,("find_service() failed to find service %s\n", service
));
460 /****************************************************************************
461 do some basic sainity checks on the share.
462 This function modifies dev, ecode.
463 ****************************************************************************/
465 static NTSTATUS
share_sanity_checks(int snum
, fstring dev
)
468 if (!lp_snum_ok(snum
) ||
469 !check_access(smbd_server_fd(),
470 lp_hostsallow(snum
), lp_hostsdeny(snum
))) {
471 return NT_STATUS_ACCESS_DENIED
;
474 if (dev
[0] == '?' || !dev
[0]) {
475 if (lp_print_ok(snum
)) {
476 fstrcpy(dev
,"LPT1:");
477 } else if (strequal(lp_fstype(snum
), "IPC")) {
486 if (lp_print_ok(snum
)) {
487 if (!strequal(dev
, "LPT1:")) {
488 return NT_STATUS_BAD_DEVICE_TYPE
;
490 } else if (strequal(lp_fstype(snum
), "IPC")) {
491 if (!strequal(dev
, "IPC")) {
492 return NT_STATUS_BAD_DEVICE_TYPE
;
494 } else if (!strequal(dev
, "A:")) {
495 return NT_STATUS_BAD_DEVICE_TYPE
;
498 /* Behave as a printer if we are supposed to */
499 if (lp_print_ok(snum
) && (strcmp(dev
, "A:") == 0)) {
500 fstrcpy(dev
, "LPT1:");
506 static NTSTATUS
find_forced_user(connection_struct
*conn
, bool vuser_is_guest
, fstring username
)
508 int snum
= conn
->params
->service
;
509 char *fuser
, *found_username
;
512 if (!(fuser
= talloc_string_sub(conn
->mem_ctx
, lp_force_user(snum
), "%S",
513 lp_servicename(snum
)))) {
514 return NT_STATUS_NO_MEMORY
;
517 result
= create_token_from_username(conn
->mem_ctx
, fuser
, vuser_is_guest
,
518 &conn
->uid
, &conn
->gid
, &found_username
,
519 &conn
->nt_user_token
);
520 if (!NT_STATUS_IS_OK(result
)) {
524 fstrcpy(username
, found_username
);
527 TALLOC_FREE(found_username
);
532 * Go through lookup_name etc to find the force'd group.
534 * Create a new token from src_token, replacing the primary group sid with the
538 static NTSTATUS
find_forced_group(bool force_user
,
539 int snum
, const char *username
,
543 NTSTATUS result
= NT_STATUS_NO_SUCH_GROUP
;
546 enum lsa_SidType type
;
548 bool user_must_be_member
= False
;
551 ZERO_STRUCTP(pgroup_sid
);
554 mem_ctx
= talloc_new(NULL
);
555 if (mem_ctx
== NULL
) {
556 DEBUG(0, ("talloc_new failed\n"));
557 return NT_STATUS_NO_MEMORY
;
560 groupname
= talloc_strdup(mem_ctx
, lp_force_group(snum
));
561 if (groupname
== NULL
) {
562 DEBUG(1, ("talloc_strdup failed\n"));
563 result
= NT_STATUS_NO_MEMORY
;
567 if (groupname
[0] == '+') {
568 user_must_be_member
= True
;
572 groupname
= talloc_string_sub(mem_ctx
, groupname
,
573 "%S", lp_servicename(snum
));
575 if (!lookup_name_smbconf(mem_ctx
, groupname
,
576 LOOKUP_NAME_ALL
|LOOKUP_NAME_GROUP
,
577 NULL
, NULL
, &group_sid
, &type
)) {
578 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
583 if ((type
!= SID_NAME_DOM_GRP
) && (type
!= SID_NAME_ALIAS
) &&
584 (type
!= SID_NAME_WKN_GRP
)) {
585 DEBUG(10, ("%s is a %s, not a group\n", groupname
,
586 sid_type_lookup(type
)));
590 if (!sid_to_gid(&group_sid
, &gid
)) {
591 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
592 sid_string_static(&group_sid
), groupname
));
597 * If the user has been forced and the forced group starts with a '+',
598 * then we only set the group to be the forced group if the forced
599 * user is a member of that group. Otherwise, the meaning of the '+'
603 if (force_user
&& user_must_be_member
) {
604 if (user_in_group_sid(username
, &group_sid
)) {
605 sid_copy(pgroup_sid
, &group_sid
);
607 DEBUG(3,("Forced group %s for member %s\n",
608 groupname
, username
));
610 DEBUG(0,("find_forced_group: forced user %s is not a member "
611 "of forced group %s. Disallowing access.\n",
612 username
, groupname
));
613 result
= NT_STATUS_MEMBER_NOT_IN_GROUP
;
617 sid_copy(pgroup_sid
, &group_sid
);
619 DEBUG(3,("Forced group %s\n", groupname
));
622 result
= NT_STATUS_OK
;
624 TALLOC_FREE(mem_ctx
);
628 /****************************************************************************
629 Make a connection, given the snum to connect to, and the vuser of the
630 connecting user if appropriate.
631 ****************************************************************************/
633 static connection_struct
*make_connection_snum(int snum
, user_struct
*vuser
,
638 struct passwd
*pass
= NULL
;
640 connection_struct
*conn
;
648 SET_STAT_INVALID(st
);
650 if (NT_STATUS_IS_ERR(*status
= share_sanity_checks(snum
, dev
))) {
656 DEBUG(0,("Couldn't find free connection.\n"));
657 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
661 conn
->params
->service
= snum
;
662 conn
->nt_user_token
= NULL
;
664 if (lp_guest_only(snum
)) {
665 const char *guestname
= lp_guestaccount();
667 char *found_username
= NULL
;
670 pass
= getpwnam_alloc(NULL
, guestname
);
672 DEBUG(0,("make_connection_snum: Invalid guest "
673 "account %s??\n",guestname
));
675 *status
= NT_STATUS_NO_SUCH_USER
;
678 status2
= create_token_from_username(conn
->mem_ctx
, pass
->pw_name
, True
,
679 &conn
->uid
, &conn
->gid
,
681 &conn
->nt_user_token
);
682 if (!NT_STATUS_IS_OK(status2
)) {
688 fstrcpy(user
, found_username
);
689 string_set(&conn
->user
,user
);
690 conn
->force_user
= True
;
691 TALLOC_FREE(found_username
);
693 DEBUG(3,("Guest only user %s\n",user
));
696 if (!lp_guest_ok(snum
)) {
697 DEBUG(2, ("guest user (from session setup) "
698 "not permitted to access this share "
699 "(%s)\n", lp_servicename(snum
)));
701 *status
= NT_STATUS_ACCESS_DENIED
;
705 if (!user_ok_token(vuser
->user
.unix_name
,
706 vuser
->nt_user_token
, snum
)) {
707 DEBUG(2, ("user '%s' (from session setup) not "
708 "permitted to access this share "
709 "(%s)\n", vuser
->user
.unix_name
,
710 lp_servicename(snum
)));
712 *status
= NT_STATUS_ACCESS_DENIED
;
716 conn
->vuid
= vuser
->vuid
;
717 conn
->uid
= vuser
->uid
;
718 conn
->gid
= vuser
->gid
;
719 string_set(&conn
->user
,vuser
->user
.unix_name
);
720 fstrcpy(user
,vuser
->user
.unix_name
);
721 guest
= vuser
->guest
;
722 } else if (lp_security() == SEC_SHARE
) {
724 char *found_username
= NULL
;
726 /* add it as a possible user name if we
727 are in share mode security */
728 add_session_user(lp_servicename(snum
));
729 /* shall we let them in? */
730 if (!authorise_login(snum
,user
,password
,&guest
)) {
731 DEBUG( 2, ( "Invalid username/password for [%s]\n",
732 lp_servicename(snum
)) );
734 *status
= NT_STATUS_WRONG_PASSWORD
;
737 pass
= Get_Pwnam(user
);
738 status2
= create_token_from_username(conn
->mem_ctx
, pass
->pw_name
, True
,
739 &conn
->uid
, &conn
->gid
,
741 &conn
->nt_user_token
);
742 if (!NT_STATUS_IS_OK(status2
)) {
747 fstrcpy(user
, found_username
);
748 string_set(&conn
->user
,user
);
749 TALLOC_FREE(found_username
);
750 conn
->force_user
= True
;
752 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
754 *status
= NT_STATUS_ACCESS_DENIED
;
758 add_session_user(user
);
760 safe_strcpy(conn
->client_address
, client_addr(),
761 sizeof(conn
->client_address
)-1);
762 conn
->num_files_open
= 0;
763 conn
->lastused
= conn
->lastused_count
= time(NULL
);
765 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
766 conn
->ipc
= ( (strncmp(dev
,"IPC",3) == 0) ||
767 ( lp_enable_asu_support() && strequal(dev
,"ADMIN$")) );
770 /* Case options for the share. */
771 if (lp_casesensitive(snum
) == Auto
) {
772 /* We will be setting this per packet. Set to be case
773 * insensitive for now. */
774 conn
->case_sensitive
= False
;
776 conn
->case_sensitive
= (bool)lp_casesensitive(snum
);
779 conn
->case_preserve
= lp_preservecase(snum
);
780 conn
->short_case_preserve
= lp_shortpreservecase(snum
);
782 conn
->veto_list
= NULL
;
783 conn
->hide_list
= NULL
;
784 conn
->veto_oplock_list
= NULL
;
785 conn
->aio_write_behind_list
= NULL
;
786 string_set(&conn
->dirpath
,"");
787 string_set(&conn
->user
,user
);
789 conn
->read_only
= lp_readonly(SNUM(conn
));
790 conn
->admin_user
= False
;
793 * If force user is true, then store the given userid and the gid of
794 * the user we're forcing.
795 * For auxiliary groups see below.
798 if (*lp_force_user(snum
)) {
801 status2
= find_forced_user(conn
,
802 (vuser
!= NULL
) && vuser
->guest
,
804 if (!NT_STATUS_IS_OK(status2
)) {
809 string_set(&conn
->user
,user
);
810 conn
->force_user
= True
;
811 DEBUG(3,("Forced user %s\n",user
));
815 * If force group is true, then override
816 * any groupid stored for the connecting user.
819 if (*lp_force_group(snum
)) {
823 status2
= find_forced_group(conn
->force_user
,
825 &group_sid
, &conn
->gid
);
826 if (!NT_STATUS_IS_OK(status2
)) {
832 if ((conn
->nt_user_token
== NULL
) && (vuser
!= NULL
)) {
834 /* Not force user and not security=share, but force
835 * group. vuser has a token to copy */
837 conn
->nt_user_token
= dup_nt_token(
838 NULL
, vuser
->nt_user_token
);
839 if (conn
->nt_user_token
== NULL
) {
840 DEBUG(0, ("dup_nt_token failed\n"));
842 *status
= NT_STATUS_NO_MEMORY
;
847 /* If conn->nt_user_token is still NULL, we have
848 * security=share. This means ignore the SID, as we had no
849 * vuser to copy from */
851 if (conn
->nt_user_token
!= NULL
) {
852 /* Overwrite the primary group sid */
853 sid_copy(&conn
->nt_user_token
->user_sids
[1],
857 conn
->force_group
= True
;
860 if (conn
->nt_user_token
!= NULL
) {
863 /* We have a share-specific token from force [user|group].
864 * This means we have to create the list of unix groups from
865 * the list of sids. */
870 for (i
=0; i
<conn
->nt_user_token
->num_sids
; i
++) {
872 DOM_SID
*sid
= &conn
->nt_user_token
->user_sids
[i
];
874 if (!sid_to_gid(sid
, &gid
)) {
875 DEBUG(10, ("Could not convert SID %s to gid, "
877 sid_string_static(sid
)));
880 if (!add_gid_to_array_unique(conn
->mem_ctx
, gid
, &conn
->groups
,
882 DEBUG(0, ("add_gid_to_array_unique failed\n"));
884 *status
= NT_STATUS_NO_MEMORY
;
892 pstrcpy(s
,lp_pathname(snum
));
893 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
894 conn
->connectpath
, conn
->gid
,
895 get_current_username(),
896 current_user_info
.domain
,
898 set_conn_connectpath(conn
,s
);
899 DEBUG(3,("Connect path is '%s' for service [%s]\n",s
,
900 lp_servicename(snum
)));
904 * New code to check if there's a share security descripter
905 * added from NT server manager. This is done after the
906 * smb.conf checks are done as we need a uid and token. JRA.
911 bool can_write
= False
;
912 NT_USER_TOKEN
*token
= conn
->nt_user_token
?
913 conn
->nt_user_token
:
914 (vuser
? vuser
->nt_user_token
: NULL
);
917 * I don't believe this can happen. But the
918 * logic above is convoluted enough to confuse
919 * automated checkers, so be sure. JRA.
923 DEBUG(0,("make_connection: connection to %s "
924 "denied due to missing "
926 lp_servicename(snum
)));
928 *status
= NT_STATUS_ACCESS_DENIED
;
932 can_write
= share_access_check(token
,
933 lp_servicename(snum
),
937 if (!share_access_check(token
,
938 lp_servicename(snum
),
940 /* No access, read or write. */
941 DEBUG(0,("make_connection: connection to %s "
942 "denied due to security "
944 lp_servicename(snum
)));
946 *status
= NT_STATUS_ACCESS_DENIED
;
949 conn
->read_only
= True
;
953 /* Initialise VFS function pointers */
955 if (!smbd_vfs_init(conn
)) {
956 DEBUG(0, ("vfs_init failed for service %s\n",
957 lp_servicename(snum
)));
959 *status
= NT_STATUS_BAD_NETWORK_NAME
;
964 * If widelinks are disallowed we need to canonicalise the connect
965 * path here to ensure we don't have any symlinks in the
966 * connectpath. We will be checking all paths on this connection are
967 * below this directory. We must do this after the VFS init as we
968 * depend on the realpath() pointer in the vfs table. JRA.
970 if (!lp_widelinks(snum
)) {
972 pstrcpy(s
,conn
->connectpath
);
973 canonicalize_path(conn
, s
);
974 set_conn_connectpath(conn
,s
);
977 if ((!conn
->printer
) && (!conn
->ipc
)) {
978 conn
->notify_ctx
= notify_init(conn
->mem_ctx
, server_id_self(),
979 smbd_messaging_context(),
980 smbd_event_context(),
984 /* ROOT Activities: */
986 * Enforce the max connections parameter.
989 if ((lp_max_connections(snum
) > 0)
990 && (count_current_connections(lp_servicename(SNUM(conn
)), True
) >=
991 lp_max_connections(snum
))) {
993 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
994 lp_max_connections(snum
), lp_servicename(snum
)));
996 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
1001 * Get us an entry in the connections db
1003 if (!claim_connection(conn
, lp_servicename(snum
), 0)) {
1004 DEBUG(1, ("Could not store connections entry\n"));
1006 *status
= NT_STATUS_INTERNAL_DB_ERROR
;
1010 /* Preexecs are done here as they might make the dir we are to ChDir
1012 /* execute any "root preexec = " line */
1013 if (*lp_rootpreexec(snum
)) {
1015 pstrcpy(cmd
,lp_rootpreexec(snum
));
1016 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
1017 conn
->connectpath
, conn
->gid
,
1018 get_current_username(),
1019 current_user_info
.domain
,
1021 DEBUG(5,("cmd=%s\n",cmd
));
1022 ret
= smbrun(cmd
,NULL
);
1023 if (ret
!= 0 && lp_rootpreexec_close(snum
)) {
1024 DEBUG(1,("root preexec gave %d - failing "
1025 "connection\n", ret
));
1026 yield_connection(conn
, lp_servicename(snum
));
1028 *status
= NT_STATUS_ACCESS_DENIED
;
1033 /* USER Activites: */
1034 if (!change_to_user(conn
, conn
->vuid
)) {
1035 /* No point continuing if they fail the basic checks */
1036 DEBUG(0,("Can't become connected user!\n"));
1037 yield_connection(conn
, lp_servicename(snum
));
1039 *status
= NT_STATUS_LOGON_FAILURE
;
1043 /* Remember that a different vuid can connect later without these
1046 /* Preexecs are done here as they might make the dir we are to ChDir
1049 /* execute any "preexec = " line */
1050 if (*lp_preexec(snum
)) {
1052 pstrcpy(cmd
,lp_preexec(snum
));
1053 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
1054 conn
->connectpath
, conn
->gid
,
1055 get_current_username(),
1056 current_user_info
.domain
,
1058 ret
= smbrun(cmd
,NULL
);
1059 if (ret
!= 0 && lp_preexec_close(snum
)) {
1060 DEBUG(1,("preexec gave %d - failing connection\n",
1062 change_to_root_user();
1063 yield_connection(conn
, lp_servicename(snum
));
1065 *status
= NT_STATUS_ACCESS_DENIED
;
1070 #ifdef WITH_FAKE_KASERVER
1071 if (lp_afs_share(snum
)) {
1076 /* Add veto/hide lists */
1077 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
1078 set_namearray( &conn
->veto_list
, lp_veto_files(snum
));
1079 set_namearray( &conn
->hide_list
, lp_hide_files(snum
));
1080 set_namearray( &conn
->veto_oplock_list
, lp_veto_oplocks(snum
));
1083 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1084 to allow any filesystems needing user credentials to initialize
1087 if (SMB_VFS_CONNECT(conn
, lp_servicename(snum
), user
) < 0) {
1088 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1089 change_to_root_user();
1090 yield_connection(conn
, lp_servicename(snum
));
1092 *status
= NT_STATUS_UNSUCCESSFUL
;
1096 /* win2000 does not check the permissions on the directory
1097 during the tree connect, instead relying on permission
1098 check during individual operations. To match this behaviour
1099 I have disabled this chdir check (tridge) */
1100 /* the alternative is just to check the directory exists */
1101 if ((ret
= SMB_VFS_STAT(conn
, conn
->connectpath
, &st
)) != 0 ||
1102 !S_ISDIR(st
.st_mode
)) {
1103 if (ret
== 0 && !S_ISDIR(st
.st_mode
)) {
1104 DEBUG(0,("'%s' is not a directory, when connecting to "
1105 "[%s]\n", conn
->connectpath
,
1106 lp_servicename(snum
)));
1108 DEBUG(0,("'%s' does not exist or permission denied "
1109 "when connecting to [%s] Error was %s\n",
1110 conn
->connectpath
, lp_servicename(snum
),
1113 change_to_root_user();
1114 /* Call VFS disconnect hook */
1115 SMB_VFS_DISCONNECT(conn
);
1116 yield_connection(conn
, lp_servicename(snum
));
1118 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1122 string_set(&conn
->origpath
,conn
->connectpath
);
1124 #if SOFTLINK_OPTIMISATION
1125 /* resolve any soft links early if possible */
1126 if (vfs_ChDir(conn
,conn
->connectpath
) == 0) {
1127 TALLOC_CTX
*ctx
= talloc_stackframe();
1128 char *s
= vfs_GetWd(ctx
,s
);
1130 *status
= map_nt_error_from_unix(errno
);
1133 set_conn_connectpath(conn
,s
);
1134 vfs_ChDir(conn
,conn
->connectpath
);
1140 * Print out the 'connected as' stuff here as we need
1141 * to know the effective uid and gid we will be using
1142 * (at least initially).
1145 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 1 ) ) {
1146 dbgtext( "%s (%s) ", get_remote_machine_name(),
1147 conn
->client_address
);
1148 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1149 dbgtext( "connect to service %s ", lp_servicename(snum
) );
1150 dbgtext( "initially as user %s ", user
);
1151 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1152 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1155 /* we've finished with the user stuff - go back to root */
1156 change_to_root_user();
1160 /***************************************************************************************
1161 Simple wrapper function for make_connection() to include a call to
1163 **************************************************************************************/
1165 connection_struct
*make_connection_with_chdir(const char *service_in
,
1167 const char *dev
, uint16 vuid
,
1170 connection_struct
*conn
= NULL
;
1172 conn
= make_connection(service_in
, password
, dev
, vuid
, status
);
1175 * make_connection() does not change the directory for us any more
1176 * so we have to do it as a separate step --jerry
1179 if ( conn
&& vfs_ChDir(conn
,conn
->connectpath
) != 0 ) {
1180 DEBUG(0,("move_driver_to_download_area: Can't change "
1181 "directory to %s for [print$] (%s)\n",
1182 conn
->connectpath
,strerror(errno
)));
1183 yield_connection(conn
, lp_servicename(SNUM(conn
)));
1185 *status
= NT_STATUS_UNSUCCESSFUL
;
1192 /****************************************************************************
1193 Make a connection to a service.
1196 ****************************************************************************/
1198 connection_struct
*make_connection(const char *service_in
, DATA_BLOB password
,
1199 const char *pdev
, uint16 vuid
,
1203 user_struct
*vuser
= NULL
;
1210 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1212 if (!non_root_mode() && (euid
= geteuid()) != 0) {
1213 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1214 "(%u)\n", (unsigned int)euid
));
1215 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1218 if (conn_num_open() > 2047) {
1219 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
1223 if(lp_security() != SEC_SHARE
) {
1224 vuser
= get_valid_user_struct(vuid
);
1226 DEBUG(1,("make_connection: refusing to connect with "
1227 "no session setup\n"));
1228 *status
= NT_STATUS_ACCESS_DENIED
;
1233 /* Logic to try and connect to the correct [homes] share, preferably
1234 without too many getpwnam() lookups. This is particulary nasty for
1235 winbind usernames, where the share name isn't the same as unix
1238 The snum of the homes share is stored on the vuser at session setup
1242 if (strequal(service_in
,HOMES_NAME
)) {
1243 if(lp_security() != SEC_SHARE
) {
1244 DATA_BLOB no_pw
= data_blob_null
;
1245 if (vuser
->homes_snum
== -1) {
1246 DEBUG(2, ("[homes] share not available for "
1247 "this user because it was not found "
1248 "or created at session setup "
1250 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1253 DEBUG(5, ("making a connection to [homes] service "
1254 "created at session setup time\n"));
1255 return make_connection_snum(vuser
->homes_snum
,
1259 /* Security = share. Try with
1260 * current_user_info.smb_name as the username. */
1261 if (*current_user_info
.smb_name
) {
1262 fstring unix_username
;
1263 fstrcpy(unix_username
,
1264 current_user_info
.smb_name
);
1265 map_username(unix_username
);
1266 snum
= find_service(unix_username
);
1269 DEBUG(5, ("making a connection to 'homes' "
1270 "service %s based on "
1271 "security=share\n", service_in
));
1272 return make_connection_snum(snum
, NULL
,
1277 } else if ((lp_security() != SEC_SHARE
) && (vuser
->homes_snum
!= -1)
1278 && strequal(service_in
,
1279 lp_servicename(vuser
->homes_snum
))) {
1280 DATA_BLOB no_pw
= data_blob_null
;
1281 DEBUG(5, ("making a connection to 'homes' service [%s] "
1282 "created at session setup time\n", service_in
));
1283 return make_connection_snum(vuser
->homes_snum
,
1288 fstrcpy(service
, service_in
);
1290 strlower_m(service
);
1292 snum
= find_service(service
);
1295 if (strequal(service
,"IPC$") ||
1296 (lp_enable_asu_support() && strequal(service
,"ADMIN$"))) {
1297 DEBUG(3,("refusing IPC connection to %s\n", service
));
1298 *status
= NT_STATUS_ACCESS_DENIED
;
1302 DEBUG(0,("%s (%s) couldn't find service %s\n",
1303 get_remote_machine_name(), client_addr(), service
));
1304 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1308 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1309 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum
) != '\0')) {
1310 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1311 "(pointing to %s)\n",
1312 service
, lp_msdfs_proxy(snum
)));
1313 *status
= NT_STATUS_BAD_NETWORK_NAME
;
1317 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
1319 return make_connection_snum(snum
, vuser
,
1324 /****************************************************************************
1326 ****************************************************************************/
1328 void close_cnum(connection_struct
*conn
, uint16 vuid
)
1331 pipe_close_conn(conn
);
1333 file_close_conn(conn
);
1334 dptr_closecnum(conn
);
1337 change_to_root_user();
1339 DEBUG(IS_IPC(conn
)?3:1, ("%s (%s) closed connection to service %s\n",
1340 get_remote_machine_name(),
1341 conn
->client_address
,
1342 lp_servicename(SNUM(conn
))));
1344 /* Call VFS disconnect hook */
1345 SMB_VFS_DISCONNECT(conn
);
1347 yield_connection(conn
, lp_servicename(SNUM(conn
)));
1349 /* make sure we leave the directory available for unmount */
1350 vfs_ChDir(conn
, "/");
1352 /* execute any "postexec = " line */
1353 if (*lp_postexec(SNUM(conn
)) &&
1354 change_to_user(conn
, vuid
)) {
1356 pstrcpy(cmd
,lp_postexec(SNUM(conn
)));
1357 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
1358 conn
->connectpath
, conn
->gid
,
1359 get_current_username(),
1360 current_user_info
.domain
,
1363 change_to_root_user();
1366 change_to_root_user();
1367 /* execute any "root postexec = " line */
1368 if (*lp_rootpostexec(SNUM(conn
))) {
1370 pstrcpy(cmd
,lp_rootpostexec(SNUM(conn
)));
1371 standard_sub_advanced(lp_servicename(SNUM(conn
)), conn
->user
,
1372 conn
->connectpath
, conn
->gid
,
1373 get_current_username(),
1374 current_user_info
.domain
,