r10909: Give better shutdown messages
[Samba/nascimento.git] / source3 / smbd / service.c
blob52f9229ee1c7f59c877cc8a4e77c3de61d0581ab
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 userdom_struct current_user_info;
26 /****************************************************************************
27 Load parameters specific to a connection/service.
28 ****************************************************************************/
30 BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
32 static connection_struct *last_conn;
33 static uint16 last_flags;
34 int snum;
36 if (!conn) {
37 last_conn = NULL;
38 return(False);
41 conn->lastused = smb_last_time.tv_sec;
43 snum = SNUM(conn);
45 if (do_chdir &&
46 vfs_ChDir(conn,conn->connectpath) != 0 &&
47 vfs_ChDir(conn,conn->origpath) != 0) {
48 DEBUG(0,("chdir (%s) failed\n",
49 conn->connectpath));
50 return(False);
53 if ((conn == last_conn) && (last_flags == flags)) {
54 return(True);
57 last_conn = conn;
58 last_flags = flags;
60 /* Obey the client case sensitivity requests - only for clients that support it. */
61 switch (lp_casesensitive(snum)) {
62 case Auto:
64 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
65 enum remote_arch_types ra_type = get_remote_arch();
66 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
67 /* Client can't support per-packet case sensitive pathnames. */
68 conn->case_sensitive = False;
69 } else {
70 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
73 break;
74 case True:
75 conn->case_sensitive = True;
76 break;
77 default:
78 conn->case_sensitive = False;
79 break;
81 return(True);
84 /****************************************************************************
85 Add a home service. Returns the new service number or -1 if fail.
86 ****************************************************************************/
88 int add_home_service(const char *service, const char *username, const char *homedir)
90 int iHomeService;
92 if (!service || !homedir)
93 return -1;
95 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
96 return -1;
99 * If this is a winbindd provided username, remove
100 * the domain component before adding the service.
101 * Log a warning if the "path=" parameter does not
102 * include any macros.
106 const char *p = strchr(service,*lp_winbind_separator());
108 /* We only want the 'user' part of the string */
109 if (p) {
110 service = p + 1;
114 if (!lp_add_home(service, iHomeService, username, homedir)) {
115 return -1;
118 return lp_servicenumber(service);
124 * Find a service entry.
126 * @param service is modified (to canonical form??)
129 int find_service(fstring service)
131 int iService;
133 all_string_sub(service,"\\","/",0);
135 iService = lp_servicenumber(service);
137 /* now handle the special case of a home directory */
138 if (iService < 0) {
139 char *phome_dir = get_user_home_dir(service);
141 if(!phome_dir) {
143 * Try mapping the servicename, it may
144 * be a Windows to unix mapped user name.
146 if(map_username(service))
147 phome_dir = get_user_home_dir(service);
150 DEBUG(3,("checking for home directory %s gave %s\n",service,
151 phome_dir?phome_dir:"(NULL)"));
153 iService = add_home_service(service,service /* 'username' */, phome_dir);
156 /* If we still don't have a service, attempt to add it as a printer. */
157 if (iService < 0) {
158 int iPrinterService;
160 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
161 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
162 if (pcap_printername_ok(service)) {
163 DEBUG(3,("%s is a valid printer name\n", service));
164 DEBUG(3,("adding %s as a printer service\n", service));
165 lp_add_printer(service, iPrinterService);
166 iService = lp_servicenumber(service);
167 if (iService < 0) {
168 DEBUG(0,("failed to add %s as a printer service!\n", service));
170 } else {
171 DEBUG(3,("%s is not a valid printer name\n", service));
176 /* Check for default vfs service? Unsure whether to implement this */
177 if (iService < 0) {
180 /* just possibly it's a default service? */
181 if (iService < 0) {
182 char *pdefservice = lp_defaultservice();
183 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
185 * We need to do a local copy here as lp_defaultservice()
186 * returns one of the rotating lp_string buffers that
187 * could get overwritten by the recursive find_service() call
188 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
190 pstring defservice;
191 pstrcpy(defservice, pdefservice);
192 iService = find_service(defservice);
193 if (iService >= 0) {
194 all_string_sub(service, "_","/",0);
195 iService = lp_add_service(service, iService);
200 if (iService >= 0) {
201 if (!VALID_SNUM(iService)) {
202 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
203 iService = -1;
207 if (iService < 0)
208 DEBUG(3,("find_service() failed to find service %s\n", service));
210 return (iService);
214 /****************************************************************************
215 do some basic sainity checks on the share.
216 This function modifies dev, ecode.
217 ****************************************************************************/
219 static NTSTATUS share_sanity_checks(int snum, fstring dev)
222 if (!lp_snum_ok(snum) ||
223 !check_access(smbd_server_fd(),
224 lp_hostsallow(snum), lp_hostsdeny(snum))) {
225 return NT_STATUS_ACCESS_DENIED;
228 if (dev[0] == '?' || !dev[0]) {
229 if (lp_print_ok(snum)) {
230 fstrcpy(dev,"LPT1:");
231 } else if (strequal(lp_fstype(snum), "IPC")) {
232 fstrcpy(dev, "IPC");
233 } else {
234 fstrcpy(dev,"A:");
238 strupper_m(dev);
240 if (lp_print_ok(snum)) {
241 if (!strequal(dev, "LPT1:")) {
242 return NT_STATUS_BAD_DEVICE_TYPE;
244 } else if (strequal(lp_fstype(snum), "IPC")) {
245 if (!strequal(dev, "IPC")) {
246 return NT_STATUS_BAD_DEVICE_TYPE;
248 } else if (!strequal(dev, "A:")) {
249 return NT_STATUS_BAD_DEVICE_TYPE;
252 /* Behave as a printer if we are supposed to */
253 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
254 fstrcpy(dev, "LPT1:");
257 return NT_STATUS_OK;
260 /****************************************************************************
261 Make a connection, given the snum to connect to, and the vuser of the
262 connecting user if appropriate.
263 ****************************************************************************/
265 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
266 DATA_BLOB password,
267 const char *pdev, NTSTATUS *status)
269 struct passwd *pass = NULL;
270 BOOL guest = False;
271 connection_struct *conn;
272 SMB_STRUCT_STAT st;
273 fstring user;
274 fstring dev;
275 int ret;
277 *user = 0;
278 fstrcpy(dev, pdev);
279 SET_STAT_INVALID(st);
281 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
282 return NULL;
285 conn = conn_new();
286 if (!conn) {
287 DEBUG(0,("Couldn't find free connection.\n"));
288 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
289 return NULL;
292 if (lp_guest_only(snum)) {
293 const char *guestname = lp_guestaccount();
294 guest = True;
295 pass = getpwnam_alloc(guestname);
296 if (!pass) {
297 DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname));
298 conn_free(conn);
299 *status = NT_STATUS_NO_SUCH_USER;
300 return NULL;
302 fstrcpy(user,pass->pw_name);
303 conn->force_user = True;
304 conn->uid = pass->pw_uid;
305 conn->gid = pass->pw_gid;
306 string_set(&conn->user,pass->pw_name);
307 passwd_free(&pass);
308 DEBUG(3,("Guest only user %s\n",user));
309 } else if (vuser) {
310 if (vuser->guest) {
311 if (!lp_guest_ok(snum)) {
312 DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum)));
313 conn_free(conn);
314 *status = NT_STATUS_ACCESS_DENIED;
315 return NULL;
317 } else {
318 if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) {
319 DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum)));
320 conn_free(conn);
321 *status = NT_STATUS_ACCESS_DENIED;
322 return NULL;
325 conn->vuid = vuser->vuid;
326 conn->uid = vuser->uid;
327 conn->gid = vuser->gid;
328 string_set(&conn->user,vuser->user.unix_name);
329 fstrcpy(user,vuser->user.unix_name);
330 guest = vuser->guest;
331 } else if (lp_security() == SEC_SHARE) {
332 /* add it as a possible user name if we
333 are in share mode security */
334 add_session_user(lp_servicename(snum));
335 /* shall we let them in? */
336 if (!authorise_login(snum,user,password,&guest)) {
337 DEBUG( 2, ( "Invalid username/password for [%s]\n",
338 lp_servicename(snum)) );
339 conn_free(conn);
340 *status = NT_STATUS_WRONG_PASSWORD;
341 return NULL;
343 pass = Get_Pwnam(user);
344 conn->force_user = True;
345 conn->uid = pass->pw_uid;
346 conn->gid = pass->pw_gid;
347 string_set(&conn->user, pass->pw_name);
348 fstrcpy(user, pass->pw_name);
350 } else {
351 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
352 conn_free(conn);
353 *status = NT_STATUS_ACCESS_DENIED;
354 return NULL;
357 add_session_user(user);
359 safe_strcpy(conn->client_address, client_addr(),
360 sizeof(conn->client_address)-1);
361 conn->num_files_open = 0;
362 conn->lastused = time(NULL);
363 conn->service = snum;
364 conn->used = True;
365 conn->printer = (strncmp(dev,"LPT",3) == 0);
366 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
367 conn->dirptr = NULL;
369 /* Case options for the share. */
370 if (lp_casesensitive(snum) == Auto) {
371 /* We will be setting this per packet. Set to be case insensitive for now. */
372 conn->case_sensitive = False;
373 } else {
374 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
377 conn->case_preserve = lp_preservecase(snum);
378 conn->short_case_preserve = lp_shortpreservecase(snum);
380 conn->veto_list = NULL;
381 conn->hide_list = NULL;
382 conn->veto_oplock_list = NULL;
383 conn->aio_write_behind_list = NULL;
384 string_set(&conn->dirpath,"");
385 string_set(&conn->user,user);
386 conn->nt_user_token = NULL;
388 conn->read_only = lp_readonly(conn->service);
389 conn->admin_user = False;
392 * If force user is true, then store the
393 * given userid and also the groups
394 * of the user we're forcing.
397 if (*lp_force_user(snum)) {
398 struct passwd *pass2;
399 pstring fuser;
400 pstrcpy(fuser,lp_force_user(snum));
402 /* Allow %S to be used by force user. */
403 pstring_sub(fuser,"%S",lp_servicename(snum));
405 pass2 = (struct passwd *)Get_Pwnam(fuser);
406 if (pass2) {
407 conn->uid = pass2->pw_uid;
408 conn->gid = pass2->pw_gid;
409 string_set(&conn->user,pass2->pw_name);
410 fstrcpy(user,pass2->pw_name);
411 conn->force_user = True;
412 DEBUG(3,("Forced user %s\n",user));
413 } else {
414 DEBUG(1,("Couldn't find user %s\n",fuser));
415 conn_free(conn);
416 *status = NT_STATUS_NO_SUCH_USER;
417 return NULL;
421 #ifdef HAVE_GETGRNAM
423 * If force group is true, then override
424 * any groupid stored for the connecting user.
427 if (*lp_force_group(snum)) {
428 gid_t gid;
429 pstring gname;
430 pstring tmp_gname;
431 BOOL user_must_be_member = False;
433 pstrcpy(tmp_gname,lp_force_group(snum));
435 if (tmp_gname[0] == '+') {
436 user_must_be_member = True;
437 /* even now, tmp_gname is null terminated */
438 pstrcpy(gname,&tmp_gname[1]);
439 } else {
440 pstrcpy(gname,tmp_gname);
442 /* default service may be a group name */
443 pstring_sub(gname,"%S",lp_servicename(snum));
444 gid = nametogid(gname);
446 if (gid != (gid_t)-1) {
449 * If the user has been forced and the forced group starts
450 * with a '+', then we only set the group to be the forced
451 * group if the forced user is a member of that group.
452 * Otherwise, the meaning of the '+' would be ignored.
454 if (conn->force_user && user_must_be_member) {
455 if (user_in_group_list( user, gname, NULL, 0)) {
456 conn->gid = gid;
457 DEBUG(3,("Forced group %s for member %s\n",gname,user));
459 } else {
460 conn->gid = gid;
461 DEBUG(3,("Forced group %s\n",gname));
463 conn->force_group = True;
464 } else {
465 DEBUG(1,("Couldn't find group %s\n",gname));
466 conn_free(conn);
467 *status = NT_STATUS_NO_SUCH_GROUP;
468 return NULL;
471 #endif /* HAVE_GETGRNAM */
474 pstring s;
475 pstrcpy(s,lp_pathname(snum));
476 standard_sub_conn(conn,s,sizeof(s));
477 string_set(&conn->connectpath,s);
478 DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
481 if (conn->force_user || conn->force_group) {
483 /* groups stuff added by ih */
484 conn->ngroups = 0;
485 conn->groups = NULL;
487 /* Find all the groups this uid is in and
488 store them. Used by change_to_user() */
489 initialise_groups(conn->user, conn->uid, conn->gid);
490 get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
492 conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
493 conn->ngroups, conn->groups,
494 guest);
498 * New code to check if there's a share security descripter
499 * added from NT server manager. This is done after the
500 * smb.conf checks are done as we need a uid and token. JRA.
505 BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA);
507 if (!can_write) {
508 if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
509 /* No access, read or write. */
510 DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
511 lp_servicename(snum)));
512 conn_free(conn);
513 *status = NT_STATUS_ACCESS_DENIED;
514 return NULL;
515 } else {
516 conn->read_only = True;
520 /* Initialise VFS function pointers */
522 if (!smbd_vfs_init(conn)) {
523 DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum)));
524 conn_free(conn);
525 *status = NT_STATUS_BAD_NETWORK_NAME;
526 return NULL;
530 * If widelinks are disallowed we need to canonicalise the
531 * connect path here to ensure we don't have any symlinks in
532 * the connectpath. We will be checking all paths on this
533 * connection are below this directory. We must do this after
534 * the VFS init as we depend on the realpath() pointer in the vfs table. JRA.
536 if (!lp_widelinks(snum)) {
537 pstring s;
538 pstrcpy(s,conn->connectpath);
539 canonicalize_path(conn, s);
540 string_set(&conn->connectpath,s);
543 /* ROOT Activities: */
544 /* check number of connections */
545 if (!claim_connection(conn,
546 lp_servicename(snum),
547 lp_max_connections(snum),
548 False,0)) {
549 DEBUG(1,("too many connections - rejected\n"));
550 conn_free(conn);
551 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
552 return NULL;
555 /* Preexecs are done here as they might make the dir we are to ChDir to below */
556 /* execute any "root preexec = " line */
557 if (*lp_rootpreexec(snum)) {
558 pstring cmd;
559 pstrcpy(cmd,lp_rootpreexec(snum));
560 standard_sub_conn(conn,cmd,sizeof(cmd));
561 DEBUG(5,("cmd=%s\n",cmd));
562 ret = smbrun(cmd,NULL);
563 if (ret != 0 && lp_rootpreexec_close(snum)) {
564 DEBUG(1,("root preexec gave %d - failing connection\n", ret));
565 yield_connection(conn, lp_servicename(snum));
566 conn_free(conn);
567 *status = NT_STATUS_ACCESS_DENIED;
568 return NULL;
572 /* USER Activites: */
573 if (!change_to_user(conn, conn->vuid)) {
574 /* No point continuing if they fail the basic checks */
575 DEBUG(0,("Can't become connected user!\n"));
576 yield_connection(conn, lp_servicename(snum));
577 conn_free(conn);
578 *status = NT_STATUS_LOGON_FAILURE;
579 return NULL;
582 /* Remember that a different vuid can connect later without these checks... */
584 /* Preexecs are done here as they might make the dir we are to ChDir to below */
585 /* execute any "preexec = " line */
586 if (*lp_preexec(snum)) {
587 pstring cmd;
588 pstrcpy(cmd,lp_preexec(snum));
589 standard_sub_conn(conn,cmd,sizeof(cmd));
590 ret = smbrun(cmd,NULL);
591 if (ret != 0 && lp_preexec_close(snum)) {
592 DEBUG(1,("preexec gave %d - failing connection\n", ret));
593 change_to_root_user();
594 yield_connection(conn, lp_servicename(snum));
595 conn_free(conn);
596 *status = NT_STATUS_ACCESS_DENIED;
597 return NULL;
601 #ifdef WITH_FAKE_KASERVER
602 if (lp_afs_share(snum)) {
603 afs_login(conn);
605 #endif
607 /* Add veto/hide lists */
608 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
609 set_namearray( &conn->veto_list, lp_veto_files(snum));
610 set_namearray( &conn->hide_list, lp_hide_files(snum));
611 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
614 /* Invoke VFS make connection hook - do this before the VFS_STAT call to allow
615 any filesystems needing user credentials to initialize themselves. */
617 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
618 DEBUG(0,("make_connection: VFS make connection failed!\n"));
619 change_to_root_user();
620 yield_connection(conn, lp_servicename(snum));
621 conn_free(conn);
622 *status = NT_STATUS_UNSUCCESSFUL;
623 return NULL;
626 /* win2000 does not check the permissions on the directory
627 during the tree connect, instead relying on permission
628 check during individual operations. To match this behaviour
629 I have disabled this chdir check (tridge) */
630 /* the alternative is just to check the directory exists */
631 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 || !S_ISDIR(st.st_mode)) {
632 if (ret == 0 && !S_ISDIR(st.st_mode)) {
633 DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum)));
634 } else {
635 DEBUG(0,("'%s' does not exist or permission denied when connecting to [%s] "
636 "Error was %s\n", conn->connectpath, lp_servicename(snum), strerror(errno) ));
638 change_to_root_user();
639 /* Call VFS disconnect hook */
640 SMB_VFS_DISCONNECT(conn);
641 yield_connection(conn, lp_servicename(snum));
642 conn_free(conn);
643 *status = NT_STATUS_BAD_NETWORK_NAME;
644 return NULL;
647 string_set(&conn->origpath,conn->connectpath);
649 #if SOFTLINK_OPTIMISATION
650 /* resolve any soft links early if possible */
651 if (vfs_ChDir(conn,conn->connectpath) == 0) {
652 pstring s;
653 pstrcpy(s,conn->connectpath);
654 vfs_GetWd(conn,s);
655 string_set(&conn->connectpath,s);
656 vfs_ChDir(conn,conn->connectpath);
658 #endif
661 * Print out the 'connected as' stuff here as we need
662 * to know the effective uid and gid we will be using
663 * (at least initially).
666 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
667 dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
668 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
669 dbgtext( "connect to service %s ", lp_servicename(snum) );
670 dbgtext( "initially as user %s ", user );
671 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
672 dbgtext( "(pid %d)\n", (int)sys_getpid() );
675 /* we've finished with the user stuff - go back to root */
676 change_to_root_user();
677 return(conn);
680 /***************************************************************************************
681 Simple wrapper function for make_connection() to include a call to
682 vfs_chdir()
683 **************************************************************************************/
685 connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
686 const char *dev, uint16 vuid, NTSTATUS *status)
688 connection_struct *conn = NULL;
690 conn = make_connection(service_in, password, dev, vuid, status);
693 * make_connection() does not change the directory for us any more
694 * so we have to do it as a separate step --jerry
697 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
698 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
699 conn->connectpath,strerror(errno)));
700 yield_connection(conn, lp_servicename(SNUM(conn)));
701 conn_free(conn);
702 *status = NT_STATUS_UNSUCCESSFUL;
703 return NULL;
706 return conn;
709 /****************************************************************************
710 Make a connection to a service.
712 * @param service
713 ****************************************************************************/
715 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
716 const char *pdev, uint16 vuid, NTSTATUS *status)
718 uid_t euid;
719 user_struct *vuser = NULL;
720 fstring service;
721 fstring dev;
722 int snum = -1;
724 fstrcpy(dev, pdev);
726 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
727 if (!non_root_mode() && (euid = geteuid()) != 0) {
728 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
729 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
732 if(lp_security() != SEC_SHARE) {
733 vuser = get_valid_user_struct(vuid);
734 if (!vuser) {
735 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
736 *status = NT_STATUS_ACCESS_DENIED;
737 return NULL;
741 /* Logic to try and connect to the correct [homes] share, preferably without too many
742 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
743 share name isn't the same as unix username.
745 The snum of the homes share is stored on the vuser at session setup time.
748 if (strequal(service_in,HOMES_NAME)) {
749 if(lp_security() != SEC_SHARE) {
750 DATA_BLOB no_pw = data_blob(NULL, 0);
751 if (vuser->homes_snum == -1) {
752 DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n"));
753 *status = NT_STATUS_BAD_NETWORK_NAME;
754 return NULL;
756 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
757 return make_connection_snum(vuser->homes_snum,
758 vuser, no_pw,
759 dev, status);
760 } else {
761 /* Security = share. Try with current_user_info.smb_name
762 * as the username. */
763 if (*current_user_info.smb_name) {
764 fstring unix_username;
765 fstrcpy(unix_username,
766 current_user_info.smb_name);
767 map_username(unix_username);
768 snum = find_service(unix_username);
770 if (snum != -1) {
771 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
772 return make_connection_snum(snum, NULL,
773 password,
774 dev, status);
777 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
778 && strequal(service_in, lp_servicename(vuser->homes_snum))) {
779 DATA_BLOB no_pw = data_blob(NULL, 0);
780 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
781 return make_connection_snum(vuser->homes_snum,
782 vuser, no_pw,
783 dev, status);
786 fstrcpy(service, service_in);
788 strlower_m(service);
790 snum = find_service(service);
792 if (snum < 0) {
793 if (strequal(service,"IPC$")
794 || (lp_enable_asu_support() && strequal(service,"ADMIN$")))
796 DEBUG(3,("refusing IPC connection to %s\n", service));
797 *status = NT_STATUS_ACCESS_DENIED;
798 return NULL;
801 DEBUG(0,("%s (%s) couldn't find service %s\n",
802 get_remote_machine_name(), client_addr(), service));
803 *status = NT_STATUS_BAD_NETWORK_NAME;
804 return NULL;
807 /* Handle non-Dfs clients attempting connections to msdfs proxy */
808 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
809 DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n",
810 service, lp_msdfs_proxy(snum)));
811 *status = NT_STATUS_BAD_NETWORK_NAME;
812 return NULL;
815 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
817 return make_connection_snum(snum, vuser,
818 password,
819 dev, status);
822 /****************************************************************************
823 Close a cnum.
824 ****************************************************************************/
826 void close_cnum(connection_struct *conn, uint16 vuid)
828 if (IS_IPC(conn)) {
829 pipe_close_conn(conn);
830 } else {
831 file_close_conn(conn);
832 dptr_closecnum(conn);
835 change_to_root_user();
837 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
838 get_remote_machine_name(),conn->client_address,
839 lp_servicename(SNUM(conn))));
841 /* Call VFS disconnect hook */
842 SMB_VFS_DISCONNECT(conn);
844 yield_connection(conn, lp_servicename(SNUM(conn)));
846 /* make sure we leave the directory available for unmount */
847 vfs_ChDir(conn, "/");
849 /* execute any "postexec = " line */
850 if (*lp_postexec(SNUM(conn)) &&
851 change_to_user(conn, vuid)) {
852 pstring cmd;
853 pstrcpy(cmd,lp_postexec(SNUM(conn)));
854 standard_sub_conn(conn,cmd,sizeof(cmd));
855 smbrun(cmd,NULL);
856 change_to_root_user();
859 change_to_root_user();
860 /* execute any "root postexec = " line */
861 if (*lp_rootpostexec(SNUM(conn))) {
862 pstring cmd;
863 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
864 standard_sub_conn(conn,cmd,sizeof(cmd));
865 smbrun(cmd,NULL);
868 conn_free(conn);