r5739: sync for 3.0.12rc1 (current with SAMBA_3_0 r5738)
[Samba.git] / source / smbd / service.c
blob684d49c56aeab39adbabe430fa442373263cc41d
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;
27 /****************************************************************************
28 Load parameters specific to a connection/service.
29 ****************************************************************************/
31 BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
33 extern char magic_char;
34 static connection_struct *last_conn;
35 static uint16 last_flags;
36 int snum;
38 if (!conn) {
39 last_conn = NULL;
40 return(False);
43 conn->lastused = smb_last_time.tv_sec;
45 snum = SNUM(conn);
47 if (do_chdir &&
48 vfs_ChDir(conn,conn->connectpath) != 0 &&
49 vfs_ChDir(conn,conn->origpath) != 0) {
50 DEBUG(0,("chdir (%s) failed\n",
51 conn->connectpath));
52 return(False);
55 if ((conn == last_conn) && (last_flags == flags)) {
56 return(True);
59 last_conn = conn;
60 last_flags = flags;
62 /* Obey the client case sensitivity requests - only for clients that support it. */
63 switch (lp_casesensitive(snum)) {
64 case Auto:
66 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
67 enum remote_arch_types ra_type = get_remote_arch();
68 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
69 /* Client can't support per-packet case sensitive pathnames. */
70 conn->case_sensitive = False;
71 } else {
72 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
75 break;
76 case True:
77 conn->case_sensitive = True;
78 break;
79 default:
80 conn->case_sensitive = False;
81 break;
83 magic_char = lp_magicchar(snum);
84 return(True);
87 /****************************************************************************
88 Add a home service. Returns the new service number or -1 if fail.
89 ****************************************************************************/
91 int add_home_service(const char *service, const char *username, const char *homedir)
93 int iHomeService;
95 if (!service || !homedir)
96 return -1;
98 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
99 return -1;
102 * If this is a winbindd provided username, remove
103 * the domain component before adding the service.
104 * Log a warning if the "path=" parameter does not
105 * include any macros.
109 const char *p = strchr(service,*lp_winbind_separator());
111 /* We only want the 'user' part of the string */
112 if (p) {
113 service = p + 1;
117 if (!lp_add_home(service, iHomeService, username, homedir)) {
118 return -1;
121 return lp_servicenumber(service);
127 * Find a service entry.
129 * @param service is modified (to canonical form??)
132 int find_service(fstring service)
134 int iService;
136 all_string_sub(service,"\\","/",0);
138 iService = lp_servicenumber(service);
140 /* now handle the special case of a home directory */
141 if (iService < 0) {
142 char *phome_dir = get_user_home_dir(service);
144 if(!phome_dir) {
146 * Try mapping the servicename, it may
147 * be a Windows to unix mapped user name.
149 if(map_username(service))
150 phome_dir = get_user_home_dir(service);
153 DEBUG(3,("checking for home directory %s gave %s\n",service,
154 phome_dir?phome_dir:"(NULL)"));
156 iService = add_home_service(service,service /* 'username' */, phome_dir);
159 /* If we still don't have a service, attempt to add it as a printer. */
160 if (iService < 0) {
161 int iPrinterService;
163 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
164 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
165 if (pcap_printername_ok(service)) {
166 DEBUG(3,("%s is a valid printer name\n", service));
167 DEBUG(3,("adding %s as a printer service\n", service));
168 lp_add_printer(service, iPrinterService);
169 iService = lp_servicenumber(service);
170 if (iService < 0) {
171 DEBUG(0,("failed to add %s as a printer service!\n", service));
173 } else {
174 DEBUG(3,("%s is not a valid printer name\n", service));
179 /* Check for default vfs service? Unsure whether to implement this */
180 if (iService < 0) {
183 /* just possibly it's a default service? */
184 if (iService < 0) {
185 char *pdefservice = lp_defaultservice();
186 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
188 * We need to do a local copy here as lp_defaultservice()
189 * returns one of the rotating lp_string buffers that
190 * could get overwritten by the recursive find_service() call
191 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
193 pstring defservice;
194 pstrcpy(defservice, pdefservice);
195 iService = find_service(defservice);
196 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)) {
205 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
206 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 ****************************************************************************/
222 static NTSTATUS share_sanity_checks(int snum, fstring dev)
225 if (!lp_snum_ok(snum) ||
226 !check_access(smbd_server_fd(),
227 lp_hostsallow(snum), lp_hostsdeny(snum))) {
228 return NT_STATUS_ACCESS_DENIED;
231 if (dev[0] == '?' || !dev[0]) {
232 if (lp_print_ok(snum)) {
233 fstrcpy(dev,"LPT1:");
234 } else if (strequal(lp_fstype(snum), "IPC")) {
235 fstrcpy(dev, "IPC");
236 } else {
237 fstrcpy(dev,"A:");
241 strupper_m(dev);
243 if (lp_print_ok(snum)) {
244 if (!strequal(dev, "LPT1:")) {
245 return NT_STATUS_BAD_DEVICE_TYPE;
247 } else if (strequal(lp_fstype(snum), "IPC")) {
248 if (!strequal(dev, "IPC")) {
249 return NT_STATUS_BAD_DEVICE_TYPE;
251 } else if (!strequal(dev, "A:")) {
252 return NT_STATUS_BAD_DEVICE_TYPE;
255 /* Behave as a printer if we are supposed to */
256 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
257 fstrcpy(dev, "LPT1:");
260 return NT_STATUS_OK;
263 /****************************************************************************
264 Make a connection, given the snum to connect to, and the vuser of the
265 connecting user if appropriate.
266 ****************************************************************************/
268 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
269 DATA_BLOB password,
270 const char *pdev, NTSTATUS *status)
272 struct passwd *pass = NULL;
273 BOOL guest = False;
274 connection_struct *conn;
275 struct stat st;
276 fstring user;
277 fstring dev;
279 *user = 0;
280 fstrcpy(dev, pdev);
281 ZERO_STRUCT(st);
283 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
284 return NULL;
287 conn = conn_new();
288 if (!conn) {
289 DEBUG(0,("Couldn't find free connection.\n"));
290 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
291 return NULL;
294 if (lp_guest_only(snum)) {
295 const char *guestname = lp_guestaccount();
296 guest = True;
297 pass = getpwnam_alloc(guestname);
298 if (!pass) {
299 DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname));
300 conn_free(conn);
301 *status = NT_STATUS_NO_SUCH_USER;
302 return NULL;
304 fstrcpy(user,pass->pw_name);
305 conn->force_user = True;
306 conn->uid = pass->pw_uid;
307 conn->gid = pass->pw_gid;
308 string_set(&conn->user,pass->pw_name);
309 passwd_free(&pass);
310 DEBUG(3,("Guest only user %s\n",user));
311 } else if (vuser) {
312 if (vuser->guest) {
313 if (!lp_guest_ok(snum)) {
314 DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum)));
315 conn_free(conn);
316 *status = NT_STATUS_ACCESS_DENIED;
317 return NULL;
319 } else {
320 if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) {
321 DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum)));
322 conn_free(conn);
323 *status = NT_STATUS_ACCESS_DENIED;
324 return NULL;
327 conn->vuid = vuser->vuid;
328 conn->uid = vuser->uid;
329 conn->gid = vuser->gid;
330 string_set(&conn->user,vuser->user.unix_name);
331 fstrcpy(user,vuser->user.unix_name);
332 guest = vuser->guest;
333 } else if (lp_security() == SEC_SHARE) {
334 /* add it as a possible user name if we
335 are in share mode security */
336 add_session_user(lp_servicename(snum));
337 /* shall we let them in? */
338 if (!authorise_login(snum,user,password,&guest)) {
339 DEBUG( 2, ( "Invalid username/password for [%s]\n",
340 lp_servicename(snum)) );
341 conn_free(conn);
342 *status = NT_STATUS_WRONG_PASSWORD;
343 return NULL;
345 pass = Get_Pwnam(user);
346 conn->force_user = True;
347 conn->uid = pass->pw_uid;
348 conn->gid = pass->pw_gid;
349 string_set(&conn->user, pass->pw_name);
350 fstrcpy(user, pass->pw_name);
352 } else {
353 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
354 conn_free(conn);
355 *status = NT_STATUS_ACCESS_DENIED;
356 return NULL;
359 add_session_user(user);
361 safe_strcpy(conn->client_address, client_addr(),
362 sizeof(conn->client_address)-1);
363 conn->num_files_open = 0;
364 conn->lastused = time(NULL);
365 conn->service = snum;
366 conn->used = True;
367 conn->printer = (strncmp(dev,"LPT",3) == 0);
368 conn->ipc = ((strncmp(dev,"IPC",3) == 0) || strequal(dev,"ADMIN$"));
369 conn->dirptr = NULL;
371 /* Case options for the share. */
372 if (lp_casesensitive(snum) == Auto) {
373 /* We will be setting this per packet. Set to be case insensitive for now. */
374 conn->case_sensitive = False;
375 } else {
376 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
379 conn->case_preserve = lp_preservecase(snum);
380 conn->short_case_preserve = lp_shortpreservecase(snum);
382 conn->veto_list = NULL;
383 conn->hide_list = NULL;
384 conn->veto_oplock_list = NULL;
385 string_set(&conn->dirpath,"");
386 string_set(&conn->user,user);
387 conn->nt_user_token = NULL;
389 conn->read_only = lp_readonly(conn->service);
390 conn->admin_user = False;
393 * If force user is true, then store the
394 * given userid and also the groups
395 * of the user we're forcing.
398 if (*lp_force_user(snum)) {
399 struct passwd *pass2;
400 pstring fuser;
401 pstrcpy(fuser,lp_force_user(snum));
403 /* Allow %S to be used by force user. */
404 pstring_sub(fuser,"%S",lp_servicename(snum));
406 pass2 = (struct passwd *)Get_Pwnam(fuser);
407 if (pass2) {
408 conn->uid = pass2->pw_uid;
409 conn->gid = pass2->pw_gid;
410 string_set(&conn->user,pass2->pw_name);
411 fstrcpy(user,pass2->pw_name);
412 conn->force_user = True;
413 DEBUG(3,("Forced user %s\n",user));
414 } else {
415 DEBUG(1,("Couldn't find user %s\n",fuser));
416 conn_free(conn);
417 *status = NT_STATUS_NO_SUCH_USER;
418 return NULL;
422 #ifdef HAVE_GETGRNAM
424 * If force group is true, then override
425 * any groupid stored for the connecting user.
428 if (*lp_force_group(snum)) {
429 gid_t gid;
430 pstring gname;
431 pstring tmp_gname;
432 BOOL user_must_be_member = False;
434 pstrcpy(tmp_gname,lp_force_group(snum));
436 if (tmp_gname[0] == '+') {
437 user_must_be_member = True;
438 /* even now, tmp_gname is null terminated */
439 pstrcpy(gname,&tmp_gname[1]);
440 } else {
441 pstrcpy(gname,tmp_gname);
443 /* default service may be a group name */
444 pstring_sub(gname,"%S",lp_servicename(snum));
445 gid = nametogid(gname);
447 if (gid != (gid_t)-1) {
450 * If the user has been forced and the forced group starts
451 * with a '+', then we only set the group to be the forced
452 * group if the forced user is a member of that group.
453 * Otherwise, the meaning of the '+' would be ignored.
455 if (conn->force_user && user_must_be_member) {
456 if (user_in_group_list( user, gname, NULL, 0)) {
457 conn->gid = gid;
458 DEBUG(3,("Forced group %s for member %s\n",gname,user));
460 } else {
461 conn->gid = gid;
462 DEBUG(3,("Forced group %s\n",gname));
464 conn->force_group = True;
465 } else {
466 DEBUG(1,("Couldn't find group %s\n",gname));
467 conn_free(conn);
468 *status = NT_STATUS_NO_SUCH_GROUP;
469 return NULL;
472 #endif /* HAVE_GETGRNAM */
475 pstring s;
476 pstrcpy(s,lp_pathname(snum));
477 standard_sub_conn(conn,s,sizeof(s));
478 string_set(&conn->connectpath,s);
479 DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
482 if (conn->force_user || conn->force_group) {
484 /* groups stuff added by ih */
485 conn->ngroups = 0;
486 conn->groups = NULL;
488 /* Find all the groups this uid is in and
489 store them. Used by change_to_user() */
490 initialise_groups(conn->user, conn->uid, conn->gid);
491 get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
493 conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
494 conn->ngroups, conn->groups,
495 guest);
499 * New code to check if there's a share security descripter
500 * added from NT server manager. This is done after the
501 * smb.conf checks are done as we need a uid and token. JRA.
506 BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA);
508 if (!can_write) {
509 if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
510 /* No access, read or write. */
511 DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
512 lp_servicename(snum)));
513 conn_free(conn);
514 *status = NT_STATUS_ACCESS_DENIED;
515 return NULL;
516 } else {
517 conn->read_only = True;
521 /* Initialise VFS function pointers */
523 if (!smbd_vfs_init(conn)) {
524 DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn))));
525 conn_free(conn);
526 *status = NT_STATUS_BAD_NETWORK_NAME;
527 return NULL;
531 * If widelinks are disallowed we need to canonicalise the
532 * connect path here to ensure we don't have any symlinks in
533 * the connectpath. We will be checking all paths on this
534 * connection are below this directory. We must do this after
535 * the VFS init as we depend on the realpath() pointer in the vfs table. JRA.
537 if (!lp_widelinks(snum)) {
538 pstring s;
539 pstrcpy(s,conn->connectpath);
540 canonicalize_path(conn, s);
541 string_set(&conn->connectpath,s);
544 /* ROOT Activities: */
545 /* check number of connections */
546 if (!claim_connection(conn,
547 lp_servicename(SNUM(conn)),
548 lp_max_connections(SNUM(conn)),
549 False,0)) {
550 DEBUG(1,("too many connections - rejected\n"));
551 conn_free(conn);
552 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
553 return NULL;
556 /* Preexecs are done here as they might make the dir we are to ChDir to below */
557 /* execute any "root preexec = " line */
558 if (*lp_rootpreexec(SNUM(conn))) {
559 int ret;
560 pstring cmd;
561 pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
562 standard_sub_conn(conn,cmd,sizeof(cmd));
563 DEBUG(5,("cmd=%s\n",cmd));
564 ret = smbrun(cmd,NULL);
565 if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) {
566 DEBUG(1,("root preexec gave %d - failing connection\n", ret));
567 yield_connection(conn, lp_servicename(SNUM(conn)));
568 conn_free(conn);
569 *status = NT_STATUS_ACCESS_DENIED;
570 return NULL;
574 /* USER Activites: */
575 if (!change_to_user(conn, conn->vuid)) {
576 /* No point continuing if they fail the basic checks */
577 DEBUG(0,("Can't become connected user!\n"));
578 conn_free(conn);
579 *status = NT_STATUS_LOGON_FAILURE;
580 return NULL;
583 /* Remember that a different vuid can connect later without these checks... */
585 /* Preexecs are done here as they might make the dir we are to ChDir to below */
586 /* execute any "preexec = " line */
587 if (*lp_preexec(SNUM(conn))) {
588 int ret;
589 pstring cmd;
590 pstrcpy(cmd,lp_preexec(SNUM(conn)));
591 standard_sub_conn(conn,cmd,sizeof(cmd));
592 ret = smbrun(cmd,NULL);
593 if (ret != 0 && lp_preexec_close(SNUM(conn))) {
594 DEBUG(1,("preexec gave %d - failing connection\n", ret));
595 change_to_root_user();
596 yield_connection(conn, lp_servicename(SNUM(conn)));
597 conn_free(conn);
598 *status = NT_STATUS_ACCESS_DENIED;
599 return NULL;
603 #ifdef WITH_FAKE_KASERVER
604 if (lp_afs_share(SNUM(conn))) {
605 afs_login(conn);
607 #endif
609 /* win2000 does not check the permissions on the directory
610 during the tree connect, instead relying on permission
611 check during individual operations. To match this behaviour
612 I have disabled this chdir check (tridge) */
613 /* the alternative is just to check the directory exists */
614 if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
615 DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn))));
616 change_to_root_user();
617 yield_connection(conn, lp_servicename(SNUM(conn)));
618 conn_free(conn);
619 *status = NT_STATUS_BAD_NETWORK_NAME;
620 return NULL;
623 string_set(&conn->origpath,conn->connectpath);
625 #if SOFTLINK_OPTIMISATION
626 /* resolve any soft links early if possible */
627 if (vfs_ChDir(conn,conn->connectpath) == 0) {
628 pstring s;
629 pstrcpy(s,conn->connectpath);
630 vfs_GetWd(conn,s);
631 string_set(&conn->connectpath,s);
632 vfs_ChDir(conn,conn->connectpath);
634 #endif
637 * Print out the 'connected as' stuff here as we need
638 * to know the effective uid and gid we will be using
639 * (at least initially).
642 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
643 dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
644 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
645 dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
646 dbgtext( "initially as user %s ", user );
647 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
648 dbgtext( "(pid %d)\n", (int)sys_getpid() );
651 /* Add veto/hide lists */
652 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
653 set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn)));
654 set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn)));
655 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn)));
658 /* Invoke VFS make connection hook */
660 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
661 DEBUG(0,("make_connection: VFS make connection failed!\n"));
662 change_to_root_user();
663 conn_free(conn);
664 *status = NT_STATUS_UNSUCCESSFUL;
665 return NULL;
668 /* we've finished with the user stuff - go back to root */
669 change_to_root_user();
671 return(conn);
674 /***************************************************************************************
675 Simple wrapper function for make_connection() to include a call to
676 vfs_chdir()
677 **************************************************************************************/
679 connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
680 const char *dev, uint16 vuid, NTSTATUS *status)
682 connection_struct *conn = NULL;
684 conn = make_connection(service_in, password, dev, vuid, status);
687 * make_connection() does not change the directory for us any more
688 * so we have to do it as a separate step --jerry
691 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
692 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
693 conn->connectpath,strerror(errno)));
694 yield_connection(conn, lp_servicename(SNUM(conn)));
695 conn_free(conn);
696 *status = NT_STATUS_UNSUCCESSFUL;
697 return NULL;
700 return conn;
703 /****************************************************************************
704 Make a connection to a service.
706 * @param service
707 ****************************************************************************/
709 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
710 const char *pdev, uint16 vuid, NTSTATUS *status)
712 uid_t euid;
713 user_struct *vuser = NULL;
714 fstring service;
715 fstring dev;
716 int snum = -1;
718 fstrcpy(dev, pdev);
720 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
721 if (!non_root_mode() && (euid = geteuid()) != 0) {
722 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
723 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
726 if(lp_security() != SEC_SHARE) {
727 vuser = get_valid_user_struct(vuid);
728 if (!vuser) {
729 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
730 *status = NT_STATUS_ACCESS_DENIED;
731 return NULL;
735 /* Logic to try and connect to the correct [homes] share, preferably without too many
736 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
737 share name isn't the same as unix username.
739 The snum of the homes share is stored on the vuser at session setup time.
742 if (strequal(service_in,HOMES_NAME)) {
743 if(lp_security() != SEC_SHARE) {
744 DATA_BLOB no_pw = data_blob(NULL, 0);
745 if (vuser->homes_snum == -1) {
746 DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n"));
747 *status = NT_STATUS_BAD_NETWORK_NAME;
748 return NULL;
750 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
751 return make_connection_snum(vuser->homes_snum,
752 vuser, no_pw,
753 dev, status);
754 } else {
755 /* Security = share. Try with current_user_info.smb_name
756 * as the username. */
757 if (*current_user_info.smb_name) {
758 fstring unix_username;
759 fstrcpy(unix_username,
760 current_user_info.smb_name);
761 map_username(unix_username);
762 snum = find_service(unix_username);
764 if (snum != -1) {
765 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
766 return make_connection_snum(snum, NULL,
767 password,
768 dev, status);
771 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
772 && strequal(service_in, lp_servicename(vuser->homes_snum))) {
773 DATA_BLOB no_pw = data_blob(NULL, 0);
774 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
775 return make_connection_snum(vuser->homes_snum,
776 vuser, no_pw,
777 dev, status);
780 fstrcpy(service, service_in);
782 strlower_m(service);
784 snum = find_service(service);
786 if (snum < 0) {
787 if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) {
788 DEBUG(3,("refusing IPC connection to %s\n", service));
789 *status = NT_STATUS_ACCESS_DENIED;
790 return NULL;
793 DEBUG(0,("%s (%s) couldn't find service %s\n",
794 get_remote_machine_name(), client_addr(), service));
795 *status = NT_STATUS_BAD_NETWORK_NAME;
796 return NULL;
799 /* Handle non-Dfs clients attempting connections to msdfs proxy */
800 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
801 DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n",
802 service, lp_msdfs_proxy(snum)));
803 *status = NT_STATUS_BAD_NETWORK_NAME;
804 return NULL;
807 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
809 return make_connection_snum(snum, vuser,
810 password,
811 dev, status);
814 /****************************************************************************
815 close a cnum
816 ****************************************************************************/
817 void close_cnum(connection_struct *conn, uint16 vuid)
819 if (IS_IPC(conn)) {
820 pipe_close_conn(conn);
821 } else {
822 file_close_conn(conn);
823 dptr_closecnum(conn);
826 change_to_root_user();
828 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
829 get_remote_machine_name(),conn->client_address,
830 lp_servicename(SNUM(conn))));
832 /* Call VFS disconnect hook */
833 SMB_VFS_DISCONNECT(conn);
835 yield_connection(conn, lp_servicename(SNUM(conn)));
837 /* make sure we leave the directory available for unmount */
838 vfs_ChDir(conn, "/");
840 /* execute any "postexec = " line */
841 if (*lp_postexec(SNUM(conn)) &&
842 change_to_user(conn, vuid)) {
843 pstring cmd;
844 pstrcpy(cmd,lp_postexec(SNUM(conn)));
845 standard_sub_conn(conn,cmd,sizeof(cmd));
846 smbrun(cmd,NULL);
847 change_to_root_user();
850 change_to_root_user();
851 /* execute any "root postexec = " line */
852 if (*lp_rootpostexec(SNUM(conn))) {
853 pstring cmd;
854 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
855 standard_sub_conn(conn,cmd,sizeof(cmd));
856 smbrun(cmd,NULL);
859 conn_free(conn);