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;
374
struct nt_user_token *tmp_token;
377
if (!(mem_ctx = talloc_new(NULL))) {
378
DEBUG(0, ("talloc_new failed\n"));
379
return NT_STATUS_NO_MEMORY;
382
if (!(fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S",
383
lp_servicename(snum)))) {
384
TALLOC_FREE(mem_ctx);
385
return 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)) {
393
TALLOC_FREE(mem_ctx);
397
if (!(*token = dup_nt_token(NULL, tmp_token))) {
398
TALLOC_FREE(mem_ctx);
399
return NT_STATUS_NO_MEMORY;
402
fstrcpy(username, found_username);
404
TALLOC_FREE(mem_ctx);
409
* Go through lookup_name etc to find the force'd group.
411
* Create a new token from src_token, replacing the primary group sid with the
415
static NTSTATUS find_forced_group(BOOL force_user,
416
int snum, const char *username,
420
NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
423
enum SID_NAME_USE type;
425
BOOL user_must_be_member = False;
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(mem_ctx, groupname,
450
LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
451
NULL, NULL, &group_sid, &type)) {
452
DEBUG(10, ("lookup_name(%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));
485
sid_copy(pgroup_sid, &group_sid);
487
DEBUG(3,("Forced group %s\n", groupname));
490
result = NT_STATUS_OK;
492
TALLOC_FREE(mem_ctx);
496
/****************************************************************************
497
Make a connection, given the snum to connect to, and the vuser of the
498
connecting user if appropriate.
499
****************************************************************************/
501
static connection_struct *make_connection_snum(int snum, user_struct *vuser,
506
struct passwd *pass = NULL;
508
connection_struct *conn;
516
SET_STAT_INVALID(st);
518
if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
524
DEBUG(0,("Couldn't find free connection.\n"));
525
*status = NT_STATUS_INSUFFICIENT_RESOURCES;
529
conn->nt_user_token = NULL;
531
if (lp_guest_only(snum)) {
532
const char *guestname = lp_guestaccount();
534
char *found_username;
536
pass = getpwnam_alloc(NULL, guestname);
538
DEBUG(0,("make_connection_snum: Invalid guest "
539
"account %s??\n",guestname));
541
*status = NT_STATUS_NO_SUCH_USER;
544
status2 = create_token_from_username(NULL, pass->pw_name, True,
545
&conn->uid, &conn->gid,
547
&conn->nt_user_token);
548
if (!NT_STATUS_IS_OK(status2)) {
553
fstrcpy(user, found_username);
554
string_set(&conn->user,user);
555
conn->force_user = True;
557
DEBUG(3,("Guest only user %s\n",user));
560
if (!lp_guest_ok(snum)) {
561
DEBUG(2, ("guest user (from session setup) "
562
"not permitted to access this share "
563
"(%s)\n", lp_servicename(snum)));
565
*status = NT_STATUS_ACCESS_DENIED;
569
if (!user_ok_token(vuser->user.unix_name,
570
vuser->nt_user_token, snum)) {
571
DEBUG(2, ("user '%s' (from session setup) not "
572
"permitted to access this share "
573
"(%s)\n", vuser->user.unix_name,
574
lp_servicename(snum)));
576
*status = NT_STATUS_ACCESS_DENIED;
580
conn->vuid = vuser->vuid;
581
conn->uid = vuser->uid;
582
conn->gid = vuser->gid;
583
string_set(&conn->user,vuser->user.unix_name);
584
fstrcpy(user,vuser->user.unix_name);
585
guest = vuser->guest;
586
} else if (lp_security() == SEC_SHARE) {
588
char *found_username;
589
/* add it as a possible user name if we
590
are in share mode security */
591
add_session_user(lp_servicename(snum));
592
/* shall we let them in? */
593
if (!authorise_login(snum,user,password,&guest)) {
594
DEBUG( 2, ( "Invalid username/password for [%s]\n",
595
lp_servicename(snum)) );
597
*status = NT_STATUS_WRONG_PASSWORD;
600
pass = Get_Pwnam(user);
601
status2 = create_token_from_username(NULL, pass->pw_name, True,
602
&conn->uid, &conn->gid,
604
&conn->nt_user_token);
605
if (!NT_STATUS_IS_OK(status2)) {
610
fstrcpy(user, found_username);
611
string_set(&conn->user,user);
612
conn->force_user = True;
614
DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
616
*status = NT_STATUS_ACCESS_DENIED;
620
add_session_user(user);
622
safe_strcpy(conn->client_address, client_addr(),
623
sizeof(conn->client_address)-1);
624
conn->num_files_open = 0;
625
conn->lastused = conn->lastused_count = time(NULL);
626
conn->params->service = snum;
628
conn->printer = (strncmp(dev,"LPT",3) == 0);
629
conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
630
( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
633
/* Case options for the share. */
634
if (lp_casesensitive(snum) == Auto) {
635
/* We will be setting this per packet. Set to be case
636
* insensitive for now. */
637
conn->case_sensitive = False;
639
conn->case_sensitive = (BOOL)lp_casesensitive(snum);
642
conn->case_preserve = lp_preservecase(snum);
643
conn->short_case_preserve = lp_shortpreservecase(snum);
645
conn->veto_list = NULL;
646
conn->hide_list = NULL;
647
conn->veto_oplock_list = NULL;
648
conn->aio_write_behind_list = NULL;
649
string_set(&conn->dirpath,"");
650
string_set(&conn->user,user);
652
conn->read_only = lp_readonly(SNUM(conn));
653
conn->admin_user = False;
656
* If force user is true, then store the given userid and the gid of
657
* the user we're forcing.
658
* For auxiliary groups see below.
661
if (*lp_force_user(snum)) {
664
status2 = find_forced_user(snum,
665
(vuser != NULL) && vuser->guest,
666
&conn->uid, &conn->gid, user,
667
&conn->nt_user_token);
668
if (!NT_STATUS_IS_OK(status2)) {
673
string_set(&conn->user,user);
674
conn->force_user = True;
675
DEBUG(3,("Forced user %s\n",user));
679
* If force group is true, then override
680
* any groupid stored for the connecting user.
683
if (*lp_force_group(snum)) {
687
status2 = find_forced_group(conn->force_user,
689
&group_sid, &conn->gid);
690
if (!NT_STATUS_IS_OK(status2)) {
696
if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
698
/* Not force user and not security=share, but force
699
* group. vuser has a token to copy */
701
conn->nt_user_token = dup_nt_token(
702
NULL, vuser->nt_user_token);
703
if (conn->nt_user_token == NULL) {
704
DEBUG(0, ("dup_nt_token failed\n"));
706
*status = NT_STATUS_NO_MEMORY;
711
/* If conn->nt_user_token is still NULL, we have
712
* security=share. This means ignore the SID, as we had no
713
* vuser to copy from */
715
if (conn->nt_user_token != NULL) {
716
/* Overwrite the primary group sid */
717
sid_copy(&conn->nt_user_token->user_sids[1],
721
conn->force_group = True;
724
if (conn->nt_user_token != NULL) {
727
/* We have a share-specific token from force [user|group].
728
* This means we have to create the list of unix groups from
729
* the list of sids. */
734
for (i=0; i<conn->nt_user_token->num_sids; i++) {
736
DOM_SID *sid = &conn->nt_user_token->user_sids[i];
738
if (!sid_to_gid(sid, &gid)) {
739
DEBUG(10, ("Could not convert SID %s to gid, "
741
sid_string_static(sid)));
744
add_gid_to_array_unique(NULL, gid, &conn->groups,
751
pstrcpy(s,lp_pathname(snum));
752
standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
753
conn->connectpath, conn->gid,
754
get_current_username(),
755
current_user_info.domain,
757
set_conn_connectpath(conn,s);
758
DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
759
lp_servicename(snum)));
763
* New code to check if there's a share security descripter
764
* added from NT server manager. This is done after the
765
* smb.conf checks are done as we need a uid and token. JRA.
770
BOOL can_write = share_access_check(conn, snum, vuser,
774
if (!share_access_check(conn, snum, vuser,
776
/* No access, read or write. */
777
DEBUG(0,("make_connection: connection to %s "
778
"denied due to security "
780
lp_servicename(snum)));
782
*status = NT_STATUS_ACCESS_DENIED;
785
conn->read_only = True;
789
/* Initialise VFS function pointers */
791
if (!smbd_vfs_init(conn)) {
792
DEBUG(0, ("vfs_init failed for service %s\n",
793
lp_servicename(snum)));
795
*status = NT_STATUS_BAD_NETWORK_NAME;
800
* If widelinks are disallowed we need to canonicalise the connect
801
* path here to ensure we don't have any symlinks in the
802
* connectpath. We will be checking all paths on this connection are
803
* below this directory. We must do this after the VFS init as we
804
* depend on the realpath() pointer in the vfs table. JRA.
806
if (!lp_widelinks(snum)) {
808
pstrcpy(s,conn->connectpath);
809
canonicalize_path(conn, s);
810
set_conn_connectpath(conn,s);
813
/* ROOT Activities: */
814
/* check number of connections */
815
if (!claim_connection(conn,
816
lp_servicename(snum),
817
lp_max_connections(snum),
819
DEBUG(1,("too many connections - rejected\n"));
821
*status = NT_STATUS_INSUFFICIENT_RESOURCES;
825
/* Preexecs are done here as they might make the dir we are to ChDir
827
/* execute any "root preexec = " line */
828
if (*lp_rootpreexec(snum)) {
830
pstrcpy(cmd,lp_rootpreexec(snum));
831
standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
832
conn->connectpath, conn->gid,
833
get_current_username(),
834
current_user_info.domain,
836
DEBUG(5,("cmd=%s\n",cmd));
837
ret = smbrun(cmd,NULL);
838
if (ret != 0 && lp_rootpreexec_close(snum)) {
839
DEBUG(1,("root preexec gave %d - failing "
840
"connection\n", ret));
841
yield_connection(conn, lp_servicename(snum));
843
*status = NT_STATUS_ACCESS_DENIED;
848
/* USER Activites: */
849
if (!change_to_user(conn, conn->vuid)) {
850
/* No point continuing if they fail the basic checks */
851
DEBUG(0,("Can't become connected user!\n"));
852
yield_connection(conn, lp_servicename(snum));
854
*status = NT_STATUS_LOGON_FAILURE;
858
/* Remember that a different vuid can connect later without these
861
/* Preexecs are done here as they might make the dir we are to ChDir
864
/* execute any "preexec = " line */
865
if (*lp_preexec(snum)) {
867
pstrcpy(cmd,lp_preexec(snum));
868
standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
869
conn->connectpath, conn->gid,
870
get_current_username(),
871
current_user_info.domain,
873
ret = smbrun(cmd,NULL);
874
if (ret != 0 && lp_preexec_close(snum)) {
875
DEBUG(1,("preexec gave %d - failing connection\n",
877
change_to_root_user();
878
yield_connection(conn, lp_servicename(snum));
880
*status = NT_STATUS_ACCESS_DENIED;
885
#ifdef WITH_FAKE_KASERVER
886
if (lp_afs_share(snum)) {
891
/* Add veto/hide lists */
892
if (!IS_IPC(conn) && !IS_PRINT(conn)) {
893
set_namearray( &conn->veto_list, lp_veto_files(snum));
894
set_namearray( &conn->hide_list, lp_hide_files(snum));
895
set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
898
/* Invoke VFS make connection hook - do this before the VFS_STAT call
899
to allow any filesystems needing user credentials to initialize
902
if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
903
DEBUG(0,("make_connection: VFS make connection failed!\n"));
904
change_to_root_user();
905
yield_connection(conn, lp_servicename(snum));
907
*status = NT_STATUS_UNSUCCESSFUL;
911
/* win2000 does not check the permissions on the directory
912
during the tree connect, instead relying on permission
913
check during individual operations. To match this behaviour
914
I have disabled this chdir check (tridge) */
915
/* the alternative is just to check the directory exists */
916
if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
917
!S_ISDIR(st.st_mode)) {
918
if (ret == 0 && !S_ISDIR(st.st_mode)) {
919
DEBUG(0,("'%s' is not a directory, when connecting to "
920
"[%s]\n", conn->connectpath,
921
lp_servicename(snum)));
923
DEBUG(0,("'%s' does not exist or permission denied "
924
"when connecting to [%s] Error was %s\n",
925
conn->connectpath, lp_servicename(snum),
928
change_to_root_user();
929
/* Call VFS disconnect hook */
930
SMB_VFS_DISCONNECT(conn);
931
yield_connection(conn, lp_servicename(snum));
933
*status = NT_STATUS_BAD_NETWORK_NAME;
937
string_set(&conn->origpath,conn->connectpath);
939
#if SOFTLINK_OPTIMISATION
940
/* resolve any soft links early if possible */
941
if (vfs_ChDir(conn,conn->connectpath) == 0) {
943
pstrcpy(s,conn->connectpath);
945
set_conn_connectpath(conn,s);
946
vfs_ChDir(conn,conn->connectpath);
951
* Print out the 'connected as' stuff here as we need
952
* to know the effective uid and gid we will be using
953
* (at least initially).
956
if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
957
dbgtext( "%s (%s) ", get_remote_machine_name(),
958
conn->client_address );
959
dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
960
dbgtext( "connect to service %s ", lp_servicename(snum) );
961
dbgtext( "initially as user %s ", user );
962
dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
963
dbgtext( "(pid %d)\n", (int)sys_getpid() );
966
/* Setup the minimum value for a change notify wait time (seconds). */
967
set_change_notify_timeout(lp_change_notify_timeout(snum));
969
/* we've finished with the user stuff - go back to root */
970
change_to_root_user();
974
/***************************************************************************************
975
Simple wrapper function for make_connection() to include a call to
977
**************************************************************************************/
979
connection_struct *make_connection_with_chdir(const char *service_in,
981
const char *dev, uint16 vuid,
984
connection_struct *conn = NULL;
986
conn = make_connection(service_in, password, dev, vuid, status);
989
* make_connection() does not change the directory for us any more
990
* so we have to do it as a separate step --jerry
993
if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
994
DEBUG(0,("move_driver_to_download_area: Can't change "
995
"directory to %s for [print$] (%s)\n",
996
conn->connectpath,strerror(errno)));
997
yield_connection(conn, lp_servicename(SNUM(conn)));
999
*status = NT_STATUS_UNSUCCESSFUL;
1006
/****************************************************************************
1007
Make a connection to a service.
1010
****************************************************************************/
1012
connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1013
const char *pdev, uint16 vuid,
1017
user_struct *vuser = NULL;
1024
/* This must ONLY BE CALLED AS ROOT. As it exits this function as
1026
if (!non_root_mode() && (euid = geteuid()) != 0) {
1027
DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1028
"(%u)\n", (unsigned int)euid ));
1029
smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1032
if(lp_security() != SEC_SHARE) {
1033
vuser = get_valid_user_struct(vuid);
1035
DEBUG(1,("make_connection: refusing to connect with "
1036
"no session setup\n"));
1037
*status = NT_STATUS_ACCESS_DENIED;
1042
/* Logic to try and connect to the correct [homes] share, preferably
1043
without too many getpwnam() lookups. This is particulary nasty for
1044
winbind usernames, where the share name isn't the same as unix
1047
The snum of the homes share is stored on the vuser at session setup
1051
if (strequal(service_in,HOMES_NAME)) {
1052
if(lp_security() != SEC_SHARE) {
1053
DATA_BLOB no_pw = data_blob(NULL, 0);
1054
if (vuser->homes_snum == -1) {
1055
DEBUG(2, ("[homes] share not available for "
1056
"this user because it was not found "
1057
"or created at session setup "
1059
*status = NT_STATUS_BAD_NETWORK_NAME;
1062
DEBUG(5, ("making a connection to [homes] service "
1063
"created at session setup time\n"));
1064
return make_connection_snum(vuser->homes_snum,
1068
/* Security = share. Try with
1069
* current_user_info.smb_name as the username. */
1070
if (*current_user_info.smb_name) {
1071
fstring unix_username;
1072
fstrcpy(unix_username,
1073
current_user_info.smb_name);
1074
map_username(unix_username);
1075
snum = find_service(unix_username);
1078
DEBUG(5, ("making a connection to 'homes' "
1079
"service %s based on "
1080
"security=share\n", service_in));
1081
return make_connection_snum(snum, NULL,
1086
} else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1087
&& strequal(service_in,
1088
lp_servicename(vuser->homes_snum))) {
1089
DATA_BLOB no_pw = data_blob(NULL, 0);
1090
DEBUG(5, ("making a connection to 'homes' service [%s] "
1091
"created at session setup time\n", service_in));
1092
return make_connection_snum(vuser->homes_snum,
1097
fstrcpy(service, service_in);
1099
strlower_m(service);
1101
snum = find_service(service);
1104
if (strequal(service,"IPC$") ||
1105
(lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1106
DEBUG(3,("refusing IPC connection to %s\n", service));
1107
*status = NT_STATUS_ACCESS_DENIED;
1111
DEBUG(0,("%s (%s) couldn't find service %s\n",
1112
get_remote_machine_name(), client_addr(), service));
1113
*status = NT_STATUS_BAD_NETWORK_NAME;
1117
/* Handle non-Dfs clients attempting connections to msdfs proxy */
1118
if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1119
DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1120
"(pointing to %s)\n",
1121
service, lp_msdfs_proxy(snum)));
1122
*status = NT_STATUS_BAD_NETWORK_NAME;
1126
DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1128
return make_connection_snum(snum, vuser,
1133
/****************************************************************************
1135
****************************************************************************/
1137
void close_cnum(connection_struct *conn, uint16 vuid)
1140
pipe_close_conn(conn);
1142
file_close_conn(conn);
1143
dptr_closecnum(conn);
1146
change_to_root_user();
1148
DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1149
get_remote_machine_name(),
1150
conn->client_address,
1151
lp_servicename(SNUM(conn))));
1153
/* Call VFS disconnect hook */
1154
SMB_VFS_DISCONNECT(conn);
1156
yield_connection(conn, lp_servicename(SNUM(conn)));
1158
/* make sure we leave the directory available for unmount */
1159
vfs_ChDir(conn, "/");
1161
/* execute any "postexec = " line */
1162
if (*lp_postexec(SNUM(conn)) &&
1163
change_to_user(conn, vuid)) {
1165
pstrcpy(cmd,lp_postexec(SNUM(conn)));
1166
standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1167
conn->connectpath, conn->gid,
1168
get_current_username(),
1169
current_user_info.domain,
1172
change_to_root_user();
1175
change_to_root_user();
1176
/* execute any "root postexec = " line */
1177
if (*lp_rootpostexec(SNUM(conn))) {
1179
pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
1180
standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1181
conn->connectpath, conn->gid,
1182
get_current_username(),
1183
current_user_info.domain,