Fix VFS layer:
[Samba/gebeck_regimport.git] / source / smbd / service.c
blob0e4c87c7fb2523aebc56f24d6f3ba766d98d8955
1 /*
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.
21 #include "includes.h"
23 extern struct timeval smb_last_time;
24 extern int case_default;
25 extern BOOL case_preserve;
26 extern BOOL short_case_preserve;
27 extern BOOL case_mangle;
28 extern BOOL case_sensitive;
29 extern BOOL use_mangled_map;
30 extern userdom_struct current_user_info;
33 /****************************************************************************
34 Load parameters specific to a connection/service.
35 ****************************************************************************/
37 BOOL set_current_service(connection_struct *conn,BOOL do_chdir)
39 extern char magic_char;
40 static connection_struct *last_conn;
41 int snum;
43 if (!conn) {
44 last_conn = NULL;
45 return(False);
48 conn->lastused = smb_last_time.tv_sec;
50 snum = SNUM(conn);
52 if (do_chdir &&
53 vfs_ChDir(conn,conn->connectpath) != 0 &&
54 vfs_ChDir(conn,conn->origpath) != 0) {
55 DEBUG(0,("chdir (%s) failed\n",
56 conn->connectpath));
57 return(False);
60 if (conn == last_conn)
61 return(True);
63 last_conn = conn;
65 case_default = lp_defaultcase(snum);
66 case_preserve = lp_preservecase(snum);
67 short_case_preserve = lp_shortpreservecase(snum);
68 case_mangle = lp_casemangle(snum);
69 case_sensitive = lp_casesensitive(snum);
70 magic_char = lp_magicchar(snum);
71 use_mangled_map = (*lp_mangled_map(snum) ? True:False);
72 return(True);
75 /****************************************************************************
76 Add a home service. Returns the new service number or -1 if fail.
77 ****************************************************************************/
79 int add_home_service(const char *service, const char *username, const char *homedir)
81 int iHomeService;
83 if (!service || !homedir)
84 return -1;
86 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
87 return -1;
90 * If this is a winbindd provided username, remove
91 * the domain component before adding the service.
92 * Log a warning if the "path=" parameter does not
93 * include any macros.
97 const char *p = strchr(service,*lp_winbind_separator());
99 /* We only want the 'user' part of the string */
100 if (p) {
101 service = p + 1;
105 if (!lp_add_home(service, iHomeService, username, homedir)) {
106 return -1;
109 return lp_servicenumber(service);
115 * Find a service entry. service is always in dos codepage.
117 * @param service is modified (to canonical form??)
119 int find_service(fstring service)
121 int iService;
123 all_string_sub(service,"\\","/",0);
125 iService = lp_servicenumber(service);
127 /* now handle the special case of a home directory */
128 if (iService < 0)
130 char *phome_dir = get_user_home_dir(service);
132 if(!phome_dir)
135 * Try mapping the servicename, it may
136 * be a Windows to unix mapped user name.
138 if(map_username(service))
139 phome_dir = get_user_home_dir(service);
142 DEBUG(3,("checking for home directory %s gave %s\n",service,
143 phome_dir?phome_dir:"(NULL)"));
145 iService = add_home_service(service,service /* 'username' */, phome_dir);
148 /* If we still don't have a service, attempt to add it as a printer. */
149 if (iService < 0)
151 int iPrinterService;
153 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0)
155 char *pszTemp;
157 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
158 pszTemp = lp_printcapname();
159 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp))
161 DEBUG(3,("%s is a valid printer name\n", service));
162 DEBUG(3,("adding %s as a printer service\n", service));
163 lp_add_printer(service, iPrinterService);
164 iService = lp_servicenumber(service);
165 if (iService < 0)
166 DEBUG(0,("failed to add %s as a printer service!\n", service));
168 else
169 DEBUG(3,("%s is not a valid printer name\n", service));
173 /* Check for default vfs service? Unsure whether to implement this */
174 if (iService < 0)
178 /* just possibly it's a default service? */
179 if (iService < 0)
181 char *pdefservice = lp_defaultservice();
182 if (pdefservice && *pdefservice &&
183 !strequal(pdefservice,service) &&
184 !strstr(service,".."))
187 * We need to do a local copy here as lp_defaultservice()
188 * returns one of the rotating lp_string buffers that
189 * could get overwritten by the recursive find_service() call
190 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
192 pstring defservice;
193 pstrcpy(defservice, pdefservice);
194 iService = find_service(defservice);
195 if (iService >= 0)
197 all_string_sub(service, "_","/",0);
198 iService = lp_add_service(service, iService);
203 if (iService >= 0)
204 if (!VALID_SNUM(iService))
206 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
207 iService = -1;
210 if (iService < 0)
211 DEBUG(3,("find_service() failed to find service %s\n", service));
213 return (iService);
217 /****************************************************************************
218 do some basic sainity checks on the share.
219 This function modifies dev, ecode.
220 ****************************************************************************/
221 static NTSTATUS share_sanity_checks(int snum, fstring dev)
224 if (!lp_snum_ok(snum) ||
225 !check_access(smbd_server_fd(),
226 lp_hostsallow(snum), lp_hostsdeny(snum))) {
227 return NT_STATUS_ACCESS_DENIED;
230 if (dev[0] == '?' || !dev[0]) {
231 if (lp_print_ok(snum)) {
232 fstrcpy(dev,"LPT1:");
233 } else if (strequal(lp_fstype(snum), "IPC")) {
234 fstrcpy(dev, "IPC");
235 } else {
236 fstrcpy(dev,"A:");
240 strupper(dev);
242 if (lp_print_ok(snum)) {
243 if (!strequal(dev, "LPT1:")) {
244 return NT_STATUS_BAD_DEVICE_TYPE;
246 } else if (strequal(lp_fstype(snum), "IPC")) {
247 if (!strequal(dev, "IPC")) {
248 return NT_STATUS_BAD_DEVICE_TYPE;
250 } else if (!strequal(dev, "A:")) {
251 return NT_STATUS_BAD_DEVICE_TYPE;
254 /* Behave as a printer if we are supposed to */
255 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
256 fstrcpy(dev, "LPT1:");
259 return NT_STATUS_OK;
263 /****************************************************************************
264 readonly share?
265 ****************************************************************************/
266 static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_groups)
268 char **list;
269 char *service = lp_servicename(conn->service);
270 conn->read_only = lp_readonly(conn->service);
272 if (!service) return;
274 str_list_copy(&list, lp_readlist(conn->service));
275 if (list) {
276 if (!str_list_substitute(list, "%S", service)) {
277 DEBUG(0, ("ERROR: read list substitution failed\n"));
279 if (user_in_list(conn->user, (const char **)list, groups, n_groups))
280 conn->read_only = True;
281 str_list_free(&list);
284 str_list_copy(&list, lp_writelist(conn->service));
285 if (list) {
286 if (!str_list_substitute(list, "%S", service)) {
287 DEBUG(0, ("ERROR: write list substitution failed\n"));
289 if (user_in_list(conn->user, (const char **)list, groups, n_groups))
290 conn->read_only = False;
291 str_list_free(&list);
296 /****************************************************************************
297 admin user check
298 ****************************************************************************/
299 static void set_admin_user(connection_struct *conn, gid_t *groups, size_t n_groups)
301 /* admin user check */
303 /* JRA - original code denied admin user if the share was
304 marked read_only. Changed as I don't think this is needed,
305 but old code left in case there is a problem here.
307 if (user_in_list(conn->user,lp_admin_users(conn->service), groups, n_groups)
308 #if 0
309 && !conn->read_only
310 #endif
312 conn->admin_user = True;
313 conn->force_user = True; /* Admin users are effectivly 'forced' */
314 DEBUG(0,("%s logged in as admin user (root privileges)\n",conn->user));
315 } else {
316 conn->admin_user = False;
319 #if 0 /* This done later, for now */
320 /* admin users always run as uid=0 */
321 if (conn->admin_user) {
322 conn->uid = 0;
324 #endif
327 /****************************************************************************
328 Make a connection, given the snum to connect to, and the vuser of the
329 connecting user if appropriate.
330 ****************************************************************************/
332 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
333 DATA_BLOB password,
334 const char *pdev, NTSTATUS *status)
336 struct passwd *pass = NULL;
337 BOOL guest = False;
338 connection_struct *conn;
339 struct stat st;
340 fstring user;
341 fstring dev;
343 *user = 0;
344 fstrcpy(dev, pdev);
346 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
347 return NULL;
350 conn = conn_new();
351 if (!conn) {
352 DEBUG(0,("Couldn't find free connection.\n"));
353 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
354 return NULL;
357 if (lp_guest_only(snum)) {
358 const char *guestname = lp_guestaccount();
359 guest = True;
360 pass = getpwnam_alloc(guestname);
361 if (!pass) {
362 DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname));
363 conn_free(conn);
364 *status = NT_STATUS_NO_SUCH_USER;
365 return NULL;
367 fstrcpy(user,pass->pw_name);
368 conn->force_user = True;
369 string_set(&conn->user,pass->pw_name);
370 passwd_free(&pass);
371 DEBUG(3,("Guest only user %s\n",user));
372 } else if (vuser) {
373 if (vuser->guest) {
374 if (!lp_guest_ok(snum)) {
375 DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum)));
376 conn_free(conn);
377 *status = NT_STATUS_ACCESS_DENIED;
378 return NULL;
380 } else {
381 if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) {
382 DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum)));
383 conn_free(conn);
384 *status = NT_STATUS_ACCESS_DENIED;
385 return NULL;
388 conn->vuid = vuser->vuid;
389 conn->uid = vuser->uid;
390 conn->gid = vuser->gid;
391 string_set(&conn->user,vuser->user.unix_name);
392 fstrcpy(user,vuser->user.unix_name);
393 guest = vuser->guest;
394 } else if (lp_security() == SEC_SHARE) {
395 /* add it as a possible user name if we
396 are in share mode security */
397 add_session_user(lp_servicename(snum));
398 /* shall we let them in? */
399 if (!authorise_login(snum,user,password,&guest)) {
400 DEBUG( 2, ( "Invalid username/password for [%s]\n",
401 lp_servicename(snum)) );
402 conn_free(conn);
403 *status = NT_STATUS_WRONG_PASSWORD;
404 return NULL;
406 pass = Get_Pwnam(user);
407 conn->force_user = True;
408 conn->uid = pass->pw_uid;
409 conn->gid = pass->pw_gid;
410 string_set(&conn->user, pass->pw_name);
411 fstrcpy(user, pass->pw_name);
413 } else {
414 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
415 conn_free(conn);
416 *status = NT_STATUS_ACCESS_DENIED;
417 return NULL;
420 add_session_user(user);
422 safe_strcpy(conn->client_address, client_addr(),
423 sizeof(conn->client_address)-1);
424 conn->num_files_open = 0;
425 conn->lastused = time(NULL);
426 conn->service = snum;
427 conn->used = True;
428 conn->printer = (strncmp(dev,"LPT",3) == 0);
429 conn->ipc = ((strncmp(dev,"IPC",3) == 0) || strequal(dev,"ADMIN$"));
430 conn->dirptr = NULL;
431 conn->veto_list = NULL;
432 conn->hide_list = NULL;
433 conn->veto_oplock_list = NULL;
434 string_set(&conn->dirpath,"");
435 string_set(&conn->user,user);
436 conn->nt_user_token = NULL;
438 set_read_only(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0);
440 set_admin_user(conn, vuser ? vuser->groups : NULL, vuser ? vuser->n_groups : 0);
443 * If force user is true, then store the
444 * given userid and also the groups
445 * of the user we're forcing.
448 if (*lp_force_user(snum)) {
449 struct passwd *pass2;
450 pstring fuser;
451 pstrcpy(fuser,lp_force_user(snum));
453 /* Allow %S to be used by force user. */
454 pstring_sub(fuser,"%S",lp_servicename(snum));
456 pass2 = (struct passwd *)Get_Pwnam(fuser);
457 if (pass2) {
458 conn->uid = pass2->pw_uid;
459 conn->gid = pass2->pw_gid;
460 string_set(&conn->user,pass2->pw_name);
461 fstrcpy(user,pass2->pw_name);
462 conn->force_user = True;
463 DEBUG(3,("Forced user %s\n",user));
464 } else {
465 DEBUG(1,("Couldn't find user %s\n",fuser));
466 conn_free(conn);
467 *status = NT_STATUS_NO_SUCH_USER;
468 return NULL;
472 /* admin users always run as uid=0 */
473 if (conn->admin_user) {
474 conn->uid = 0;
477 #ifdef HAVE_GETGRNAM
479 * If force group is true, then override
480 * any groupid stored for the connecting user.
483 if (*lp_force_group(snum)) {
484 gid_t gid;
485 pstring gname;
486 pstring tmp_gname;
487 BOOL user_must_be_member = False;
489 pstrcpy(tmp_gname,lp_force_group(snum));
491 if (tmp_gname[0] == '+') {
492 user_must_be_member = True;
493 /* even now, tmp_gname is null terminated */
494 pstrcpy(gname,&tmp_gname[1]);
495 } else {
496 pstrcpy(gname,tmp_gname);
498 /* default service may be a group name */
499 pstring_sub(gname,"%S",lp_servicename(snum));
500 gid = nametogid(gname);
502 if (gid != (gid_t)-1) {
505 * If the user has been forced and the forced group starts
506 * with a '+', then we only set the group to be the forced
507 * group if the forced user is a member of that group.
508 * Otherwise, the meaning of the '+' would be ignored.
510 if (conn->force_user && user_must_be_member) {
511 if (user_in_group_list( user, gname, NULL, 0)) {
512 conn->gid = gid;
513 DEBUG(3,("Forced group %s for member %s\n",gname,user));
515 } else {
516 conn->gid = gid;
517 DEBUG(3,("Forced group %s\n",gname));
519 conn->force_group = True;
520 } else {
521 DEBUG(1,("Couldn't find group %s\n",gname));
522 conn_free(conn);
523 *status = NT_STATUS_NO_SUCH_GROUP;
524 return NULL;
527 #endif /* HAVE_GETGRNAM */
530 pstring s;
531 pstrcpy(s,lp_pathname(snum));
532 standard_sub_conn(conn,s,sizeof(s));
533 string_set(&conn->connectpath,s);
534 DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
537 if (conn->force_user || conn->force_group) {
539 /* groups stuff added by ih */
540 conn->ngroups = 0;
541 conn->groups = NULL;
543 /* Find all the groups this uid is in and
544 store them. Used by change_to_user() */
545 initialise_groups(conn->user, conn->uid, conn->gid);
546 get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
548 conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
549 conn->ngroups, conn->groups,
550 guest);
554 * New code to check if there's a share security descripter
555 * added from NT server manager. This is done after the
556 * smb.conf checks are done as we need a uid and token. JRA.
561 BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA);
563 if (!can_write) {
564 if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
565 /* No access, read or write. */
566 DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
567 lp_servicename(snum)));
568 conn_free(conn);
569 *status = NT_STATUS_ACCESS_DENIED;
570 return NULL;
571 } else {
572 conn->read_only = True;
576 /* Initialise VFS function pointers */
578 if (!smbd_vfs_init(conn)) {
579 DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn))));
580 conn_free(conn);
581 *status = NT_STATUS_BAD_NETWORK_NAME;
582 return NULL;
585 /* ROOT Activities: */
586 /* check number of connections */
587 if (!claim_connection(conn,
588 lp_servicename(SNUM(conn)),
589 lp_max_connections(SNUM(conn)),
590 False,0)) {
591 DEBUG(1,("too many connections - rejected\n"));
592 conn_free(conn);
593 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
594 return NULL;
597 /* Preexecs are done here as they might make the dir we are to ChDir to below */
598 /* execute any "root preexec = " line */
599 if (*lp_rootpreexec(SNUM(conn))) {
600 int ret;
601 pstring cmd;
602 pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
603 standard_sub_conn(conn,cmd,sizeof(cmd));
604 DEBUG(5,("cmd=%s\n",cmd));
605 ret = smbrun(cmd,NULL);
606 if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) {
607 DEBUG(1,("root preexec gave %d - failing connection\n", ret));
608 yield_connection(conn, lp_servicename(SNUM(conn)));
609 conn_free(conn);
610 *status = NT_STATUS_ACCESS_DENIED;
611 return NULL;
615 /* USER Activites: */
616 if (!change_to_user(conn, conn->vuid)) {
617 /* No point continuing if they fail the basic checks */
618 DEBUG(0,("Can't become connected user!\n"));
619 conn_free(conn);
620 *status = NT_STATUS_LOGON_FAILURE;
621 return NULL;
624 /* Remember that a different vuid can connect later without these checks... */
626 /* Preexecs are done here as they might make the dir we are to ChDir to below */
627 /* execute any "preexec = " line */
628 if (*lp_preexec(SNUM(conn))) {
629 int ret;
630 pstring cmd;
631 pstrcpy(cmd,lp_preexec(SNUM(conn)));
632 standard_sub_conn(conn,cmd,sizeof(cmd));
633 ret = smbrun(cmd,NULL);
634 if (ret != 0 && lp_preexec_close(SNUM(conn))) {
635 DEBUG(1,("preexec gave %d - failing connection\n", ret));
636 change_to_root_user();
637 yield_connection(conn, lp_servicename(SNUM(conn)));
638 conn_free(conn);
639 *status = NT_STATUS_ACCESS_DENIED;
640 return NULL;
644 #if CHECK_PATH_ON_TCONX
645 /* win2000 does not check the permissions on the directory
646 during the tree connect, instead relying on permission
647 check during individual operations. To match this behaviour
648 I have disabled this chdir check (tridge) */
649 if (vfs_ChDir(conn,conn->connectpath) != 0) {
650 DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n",
651 get_remote_machine_name(), conn->client_address,
652 conn->connectpath,strerror(errno)));
653 change_to_root_user();
654 yield_connection(conn, lp_servicename(SNUM(conn)));
655 conn_free(conn);
656 *status = NT_STATUS_BAD_NETWORK_NAME;
657 return NULL;
659 #else
660 /* the alternative is just to check the directory exists */
661 if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
662 DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn))));
663 change_to_root_user();
664 yield_connection(conn, lp_servicename(SNUM(conn)));
665 conn_free(conn);
666 *status = NT_STATUS_BAD_NETWORK_NAME;
667 return NULL;
669 #endif
671 string_set(&conn->origpath,conn->connectpath);
673 #if SOFTLINK_OPTIMISATION
674 /* resolve any soft links early if possible */
675 if (vfs_ChDir(conn,conn->connectpath) == 0) {
676 pstring s;
677 pstrcpy(s,conn->connectpath);
678 vfs_GetWd(conn,s);
679 string_set(&conn->connectpath,s);
680 vfs_ChDir(conn,conn->connectpath);
682 #endif
685 * Print out the 'connected as' stuff here as we need
686 * to know the effective uid and gid we will be using
687 * (at least initially).
690 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
691 dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
692 dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
693 dbgtext( "initially as user %s ", user );
694 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
695 dbgtext( "(pid %d)\n", (int)sys_getpid() );
698 /* Add veto/hide lists */
699 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
700 set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn)));
701 set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn)));
702 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn)));
705 /* Invoke VFS make connection hook */
707 if (VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
708 DEBUG(0,("make_connection: VFS make connection failed!\n"));
709 change_to_root_user();
710 conn_free(conn);
711 *status = NT_STATUS_UNSUCCESSFUL;
712 return NULL;
715 /* we've finished with the user stuff - go back to root */
716 change_to_root_user();
718 return(conn);
721 /***************************************************************************************
722 Simple wrapper function for make_connection() to include a call to
723 vfs_chdir()
724 **************************************************************************************/
726 connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
727 const char *dev, uint16 vuid, NTSTATUS *status)
729 connection_struct *conn = NULL;
731 conn = make_connection(service_in, password, dev, vuid, status);
734 * make_connection() does not change the directory for us any more
735 * so we have to do it as a separate step --jerry
738 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
739 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
740 conn->connectpath,strerror(errno)));
741 yield_connection(conn, lp_servicename(SNUM(conn)));
742 conn_free(conn);
743 *status = NT_STATUS_UNSUCCESSFUL;
744 return NULL;
747 return conn;
750 /****************************************************************************
751 Make a connection to a service.
753 * @param service
754 ****************************************************************************/
756 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
757 const char *pdev, uint16 vuid, NTSTATUS *status)
759 uid_t euid;
760 user_struct *vuser = NULL;
761 fstring service;
762 fstring dev;
763 int snum = -1;
765 fstrcpy(dev, pdev);
767 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
768 if (!non_root_mode() && (euid = geteuid()) != 0) {
769 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
770 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
773 if(lp_security() != SEC_SHARE) {
774 vuser = get_valid_user_struct(vuid);
775 if (!vuser) {
776 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
777 *status = NT_STATUS_ACCESS_DENIED;
778 return NULL;
782 /* Logic to try and connect to the correct [homes] share, preferably without too many
783 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
784 share name isn't the same as unix username.
786 The snum of the homes share is stored on the vuser at session setup time.
789 if (strequal(service_in,HOMES_NAME)) {
790 if(lp_security() != SEC_SHARE) {
791 DATA_BLOB no_pw = data_blob(NULL, 0);
792 if (vuser->homes_snum == -1) {
793 DEBUG(2, ("[homes] share not available for this user becouse it was not found or created at session setup time\n"));
794 *status = NT_STATUS_BAD_NETWORK_NAME;
795 return NULL;
797 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
798 return make_connection_snum(vuser->homes_snum,
799 vuser, no_pw,
800 dev, status);
801 } else {
802 /* Security = share. Try with current_user_info.smb_name
803 * as the username. */
804 if (*current_user_info.smb_name) {
805 fstring unix_username;
806 fstrcpy(unix_username,
807 current_user_info.smb_name);
808 map_username(unix_username);
809 snum = find_service(unix_username);
811 if (snum != -1) {
812 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
813 return make_connection_snum(snum, NULL,
814 password,
815 dev, status);
818 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
819 && strequal(service_in, lp_servicename(vuser->homes_snum))) {
820 DATA_BLOB no_pw = data_blob(NULL, 0);
821 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
822 return make_connection_snum(vuser->homes_snum,
823 vuser, no_pw,
824 dev, status);
827 fstrcpy(service, service_in);
829 strlower(service);
831 snum = find_service(service);
833 if (snum < 0) {
834 if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) {
835 DEBUG(3,("refusing IPC connection to %s\n", service));
836 *status = NT_STATUS_ACCESS_DENIED;
837 return NULL;
840 DEBUG(0,("%s (%s) couldn't find service %s\n",
841 get_remote_machine_name(), client_addr(), service));
842 *status = NT_STATUS_BAD_NETWORK_NAME;
843 return NULL;
846 /* Handle non-Dfs clients attempting connections to msdfs proxy */
847 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
848 DEBUG(3, ("refusing connection to dfs proxy '%s'\n", service));
849 *status = NT_STATUS_BAD_NETWORK_NAME;
850 return NULL;
853 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
855 return make_connection_snum(snum, vuser,
856 password,
857 dev, status);
860 /****************************************************************************
861 close a cnum
862 ****************************************************************************/
863 void close_cnum(connection_struct *conn, uint16 vuid)
865 DirCacheFlush(SNUM(conn));
867 change_to_root_user();
869 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
870 get_remote_machine_name(),conn->client_address,
871 lp_servicename(SNUM(conn))));
873 /* Call VFS disconnect hook */
874 VFS_DISCONNECT(conn);
876 yield_connection(conn, lp_servicename(SNUM(conn)));
878 file_close_conn(conn);
879 dptr_closecnum(conn);
881 /* execute any "postexec = " line */
882 if (*lp_postexec(SNUM(conn)) &&
883 change_to_user(conn, vuid)) {
884 pstring cmd;
885 pstrcpy(cmd,lp_postexec(SNUM(conn)));
886 standard_sub_conn(conn,cmd,sizeof(cmd));
887 smbrun(cmd,NULL);
888 change_to_root_user();
891 change_to_root_user();
892 /* execute any "root postexec = " line */
893 if (*lp_rootpostexec(SNUM(conn))) {
894 pstring cmd;
895 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
896 standard_sub_conn(conn,cmd,sizeof(cmd));
897 smbrun(cmd,NULL);
900 /* make sure we leave the directory available for unmount */
901 vfs_ChDir(conn, "/");
903 conn_free(conn);