r150: Make 3.x pass the Samba 4.x RAW-SEARCH tests - except for the
[Samba/gebeck_regimport.git] / source3 / smbd / service.c
blob08b6648249657270d9840e46cccd373d3dc65d53
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.
117 * @param service is modified (to canonical form??)
120 int find_service(fstring service)
122 int iService;
124 all_string_sub(service,"\\","/",0);
126 iService = lp_servicenumber(service);
128 /* now handle the special case of a home directory */
129 if (iService < 0) {
130 char *phome_dir = get_user_home_dir(service);
132 if(!phome_dir) {
134 * Try mapping the servicename, it may
135 * be a Windows to unix mapped user name.
137 if(map_username(service))
138 phome_dir = get_user_home_dir(service);
141 DEBUG(3,("checking for home directory %s gave %s\n",service,
142 phome_dir?phome_dir:"(NULL)"));
144 iService = add_home_service(service,service /* 'username' */, phome_dir);
147 /* If we still don't have a service, attempt to add it as a printer. */
148 if (iService < 0) {
149 int iPrinterService;
151 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
152 char *pszTemp;
154 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
155 pszTemp = lp_printcapname();
156 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) {
157 DEBUG(3,("%s is a valid printer name\n", service));
158 DEBUG(3,("adding %s as a printer service\n", service));
159 lp_add_printer(service, iPrinterService);
160 iService = lp_servicenumber(service);
161 if (iService < 0) {
162 DEBUG(0,("failed to add %s as a printer service!\n", service));
164 } else {
165 DEBUG(3,("%s is not a valid printer name\n", service));
170 /* Check for default vfs service? Unsure whether to implement this */
171 if (iService < 0) {
174 /* just possibly it's a default service? */
175 if (iService < 0) {
176 char *pdefservice = lp_defaultservice();
177 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
179 * We need to do a local copy here as lp_defaultservice()
180 * returns one of the rotating lp_string buffers that
181 * could get overwritten by the recursive find_service() call
182 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
184 pstring defservice;
185 pstrcpy(defservice, pdefservice);
186 iService = find_service(defservice);
187 if (iService >= 0) {
188 all_string_sub(service, "_","/",0);
189 iService = lp_add_service(service, iService);
194 if (iService >= 0) {
195 if (!VALID_SNUM(iService)) {
196 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
197 iService = -1;
201 if (iService < 0)
202 DEBUG(3,("find_service() failed to find service %s\n", service));
204 return (iService);
208 /****************************************************************************
209 do some basic sainity checks on the share.
210 This function modifies dev, ecode.
211 ****************************************************************************/
213 static NTSTATUS share_sanity_checks(int snum, fstring dev)
216 if (!lp_snum_ok(snum) ||
217 !check_access(smbd_server_fd(),
218 lp_hostsallow(snum), lp_hostsdeny(snum))) {
219 return NT_STATUS_ACCESS_DENIED;
222 if (dev[0] == '?' || !dev[0]) {
223 if (lp_print_ok(snum)) {
224 fstrcpy(dev,"LPT1:");
225 } else if (strequal(lp_fstype(snum), "IPC")) {
226 fstrcpy(dev, "IPC");
227 } else {
228 fstrcpy(dev,"A:");
232 strupper_m(dev);
234 if (lp_print_ok(snum)) {
235 if (!strequal(dev, "LPT1:")) {
236 return NT_STATUS_BAD_DEVICE_TYPE;
238 } else if (strequal(lp_fstype(snum), "IPC")) {
239 if (!strequal(dev, "IPC")) {
240 return NT_STATUS_BAD_DEVICE_TYPE;
242 } else if (!strequal(dev, "A:")) {
243 return NT_STATUS_BAD_DEVICE_TYPE;
246 /* Behave as a printer if we are supposed to */
247 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
248 fstrcpy(dev, "LPT1:");
251 return NT_STATUS_OK;
254 /****************************************************************************
255 Make a connection, given the snum to connect to, and the vuser of the
256 connecting user if appropriate.
257 ****************************************************************************/
259 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
260 DATA_BLOB password,
261 const char *pdev, NTSTATUS *status)
263 struct passwd *pass = NULL;
264 BOOL guest = False;
265 connection_struct *conn;
266 struct stat st;
267 fstring user;
268 fstring dev;
270 *user = 0;
271 fstrcpy(dev, pdev);
273 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
274 return NULL;
277 conn = conn_new();
278 if (!conn) {
279 DEBUG(0,("Couldn't find free connection.\n"));
280 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
281 return NULL;
284 if (lp_guest_only(snum)) {
285 const char *guestname = lp_guestaccount();
286 guest = True;
287 pass = getpwnam_alloc(guestname);
288 if (!pass) {
289 DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname));
290 conn_free(conn);
291 *status = NT_STATUS_NO_SUCH_USER;
292 return NULL;
294 fstrcpy(user,pass->pw_name);
295 conn->force_user = True;
296 conn->uid = pass->pw_uid;
297 conn->gid = pass->pw_gid;
298 string_set(&conn->user,pass->pw_name);
299 passwd_free(&pass);
300 DEBUG(3,("Guest only user %s\n",user));
301 } else if (vuser) {
302 if (vuser->guest) {
303 if (!lp_guest_ok(snum)) {
304 DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum)));
305 conn_free(conn);
306 *status = NT_STATUS_ACCESS_DENIED;
307 return NULL;
309 } else {
310 if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) {
311 DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum)));
312 conn_free(conn);
313 *status = NT_STATUS_ACCESS_DENIED;
314 return NULL;
317 conn->vuid = vuser->vuid;
318 conn->uid = vuser->uid;
319 conn->gid = vuser->gid;
320 string_set(&conn->user,vuser->user.unix_name);
321 fstrcpy(user,vuser->user.unix_name);
322 guest = vuser->guest;
323 } else if (lp_security() == SEC_SHARE) {
324 /* add it as a possible user name if we
325 are in share mode security */
326 add_session_user(lp_servicename(snum));
327 /* shall we let them in? */
328 if (!authorise_login(snum,user,password,&guest)) {
329 DEBUG( 2, ( "Invalid username/password for [%s]\n",
330 lp_servicename(snum)) );
331 conn_free(conn);
332 *status = NT_STATUS_WRONG_PASSWORD;
333 return NULL;
335 pass = Get_Pwnam(user);
336 conn->force_user = True;
337 conn->uid = pass->pw_uid;
338 conn->gid = pass->pw_gid;
339 string_set(&conn->user, pass->pw_name);
340 fstrcpy(user, pass->pw_name);
342 } else {
343 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
344 conn_free(conn);
345 *status = NT_STATUS_ACCESS_DENIED;
346 return NULL;
349 add_session_user(user);
351 safe_strcpy(conn->client_address, client_addr(),
352 sizeof(conn->client_address)-1);
353 conn->num_files_open = 0;
354 conn->lastused = time(NULL);
355 conn->service = snum;
356 conn->used = True;
357 conn->printer = (strncmp(dev,"LPT",3) == 0);
358 conn->ipc = ((strncmp(dev,"IPC",3) == 0) || strequal(dev,"ADMIN$"));
359 conn->dirptr = NULL;
360 conn->veto_list = NULL;
361 conn->hide_list = NULL;
362 conn->veto_oplock_list = NULL;
363 string_set(&conn->dirpath,"");
364 string_set(&conn->user,user);
365 conn->nt_user_token = NULL;
367 conn->read_only = lp_readonly(conn->service);
368 conn->admin_user = False;
371 * If force user is true, then store the
372 * given userid and also the groups
373 * of the user we're forcing.
376 if (*lp_force_user(snum)) {
377 struct passwd *pass2;
378 pstring fuser;
379 pstrcpy(fuser,lp_force_user(snum));
381 /* Allow %S to be used by force user. */
382 pstring_sub(fuser,"%S",lp_servicename(snum));
384 pass2 = (struct passwd *)Get_Pwnam(fuser);
385 if (pass2) {
386 conn->uid = pass2->pw_uid;
387 conn->gid = pass2->pw_gid;
388 string_set(&conn->user,pass2->pw_name);
389 fstrcpy(user,pass2->pw_name);
390 conn->force_user = True;
391 DEBUG(3,("Forced user %s\n",user));
392 } else {
393 DEBUG(1,("Couldn't find user %s\n",fuser));
394 conn_free(conn);
395 *status = NT_STATUS_NO_SUCH_USER;
396 return NULL;
400 #ifdef HAVE_GETGRNAM
402 * If force group is true, then override
403 * any groupid stored for the connecting user.
406 if (*lp_force_group(snum)) {
407 gid_t gid;
408 pstring gname;
409 pstring tmp_gname;
410 BOOL user_must_be_member = False;
412 pstrcpy(tmp_gname,lp_force_group(snum));
414 if (tmp_gname[0] == '+') {
415 user_must_be_member = True;
416 /* even now, tmp_gname is null terminated */
417 pstrcpy(gname,&tmp_gname[1]);
418 } else {
419 pstrcpy(gname,tmp_gname);
421 /* default service may be a group name */
422 pstring_sub(gname,"%S",lp_servicename(snum));
423 gid = nametogid(gname);
425 if (gid != (gid_t)-1) {
428 * If the user has been forced and the forced group starts
429 * with a '+', then we only set the group to be the forced
430 * group if the forced user is a member of that group.
431 * Otherwise, the meaning of the '+' would be ignored.
433 if (conn->force_user && user_must_be_member) {
434 if (user_in_group_list( user, gname, NULL, 0)) {
435 conn->gid = gid;
436 DEBUG(3,("Forced group %s for member %s\n",gname,user));
438 } else {
439 conn->gid = gid;
440 DEBUG(3,("Forced group %s\n",gname));
442 conn->force_group = True;
443 } else {
444 DEBUG(1,("Couldn't find group %s\n",gname));
445 conn_free(conn);
446 *status = NT_STATUS_NO_SUCH_GROUP;
447 return NULL;
450 #endif /* HAVE_GETGRNAM */
453 pstring s;
454 pstrcpy(s,lp_pathname(snum));
455 standard_sub_conn(conn,s,sizeof(s));
456 string_set(&conn->connectpath,s);
457 DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
460 if (conn->force_user || conn->force_group) {
462 /* groups stuff added by ih */
463 conn->ngroups = 0;
464 conn->groups = NULL;
466 /* Find all the groups this uid is in and
467 store them. Used by change_to_user() */
468 initialise_groups(conn->user, conn->uid, conn->gid);
469 get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
471 conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
472 conn->ngroups, conn->groups,
473 guest);
477 * New code to check if there's a share security descripter
478 * added from NT server manager. This is done after the
479 * smb.conf checks are done as we need a uid and token. JRA.
484 BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA);
486 if (!can_write) {
487 if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
488 /* No access, read or write. */
489 DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
490 lp_servicename(snum)));
491 conn_free(conn);
492 *status = NT_STATUS_ACCESS_DENIED;
493 return NULL;
494 } else {
495 conn->read_only = True;
499 /* Initialise VFS function pointers */
501 if (!smbd_vfs_init(conn)) {
502 DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn))));
503 conn_free(conn);
504 *status = NT_STATUS_BAD_NETWORK_NAME;
505 return NULL;
508 /* ROOT Activities: */
509 /* check number of connections */
510 if (!claim_connection(conn,
511 lp_servicename(SNUM(conn)),
512 lp_max_connections(SNUM(conn)),
513 False,0)) {
514 DEBUG(1,("too many connections - rejected\n"));
515 conn_free(conn);
516 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
517 return NULL;
520 /* Preexecs are done here as they might make the dir we are to ChDir to below */
521 /* execute any "root preexec = " line */
522 if (*lp_rootpreexec(SNUM(conn))) {
523 int ret;
524 pstring cmd;
525 pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
526 standard_sub_conn(conn,cmd,sizeof(cmd));
527 DEBUG(5,("cmd=%s\n",cmd));
528 ret = smbrun(cmd,NULL);
529 if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) {
530 DEBUG(1,("root preexec gave %d - failing connection\n", ret));
531 yield_connection(conn, lp_servicename(SNUM(conn)));
532 conn_free(conn);
533 *status = NT_STATUS_ACCESS_DENIED;
534 return NULL;
538 /* USER Activites: */
539 if (!change_to_user(conn, conn->vuid)) {
540 /* No point continuing if they fail the basic checks */
541 DEBUG(0,("Can't become connected user!\n"));
542 conn_free(conn);
543 *status = NT_STATUS_LOGON_FAILURE;
544 return NULL;
547 /* Remember that a different vuid can connect later without these checks... */
549 /* Preexecs are done here as they might make the dir we are to ChDir to below */
550 /* execute any "preexec = " line */
551 if (*lp_preexec(SNUM(conn))) {
552 int ret;
553 pstring cmd;
554 pstrcpy(cmd,lp_preexec(SNUM(conn)));
555 standard_sub_conn(conn,cmd,sizeof(cmd));
556 ret = smbrun(cmd,NULL);
557 if (ret != 0 && lp_preexec_close(SNUM(conn))) {
558 DEBUG(1,("preexec gave %d - failing connection\n", ret));
559 change_to_root_user();
560 yield_connection(conn, lp_servicename(SNUM(conn)));
561 conn_free(conn);
562 *status = NT_STATUS_ACCESS_DENIED;
563 return NULL;
567 #ifdef WITH_FAKE_KASERVER
568 if (lp_afs_share(SNUM(conn))) {
569 afs_login(conn);
571 #endif
573 #if CHECK_PATH_ON_TCONX
574 /* win2000 does not check the permissions on the directory
575 during the tree connect, instead relying on permission
576 check during individual operations. To match this behaviour
577 I have disabled this chdir check (tridge) */
578 if (vfs_ChDir(conn,conn->connectpath) != 0) {
579 DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n",
580 get_remote_machine_name(), conn->client_address,
581 conn->connectpath,strerror(errno)));
582 change_to_root_user();
583 yield_connection(conn, lp_servicename(SNUM(conn)));
584 conn_free(conn);
585 *status = NT_STATUS_BAD_NETWORK_NAME;
586 return NULL;
588 #else
589 /* the alternative is just to check the directory exists */
590 if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
591 DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn))));
592 change_to_root_user();
593 yield_connection(conn, lp_servicename(SNUM(conn)));
594 conn_free(conn);
595 *status = NT_STATUS_BAD_NETWORK_NAME;
596 return NULL;
598 #endif
600 string_set(&conn->origpath,conn->connectpath);
602 #if SOFTLINK_OPTIMISATION
603 /* resolve any soft links early if possible */
604 if (vfs_ChDir(conn,conn->connectpath) == 0) {
605 pstring s;
606 pstrcpy(s,conn->connectpath);
607 vfs_GetWd(conn,s);
608 string_set(&conn->connectpath,s);
609 vfs_ChDir(conn,conn->connectpath);
611 #endif
614 * Print out the 'connected as' stuff here as we need
615 * to know the effective uid and gid we will be using
616 * (at least initially).
619 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
620 dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
621 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
622 dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
623 dbgtext( "initially as user %s ", user );
624 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
625 dbgtext( "(pid %d)\n", (int)sys_getpid() );
628 /* Add veto/hide lists */
629 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
630 set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn)));
631 set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn)));
632 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn)));
635 /* Invoke VFS make connection hook */
637 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
638 DEBUG(0,("make_connection: VFS make connection failed!\n"));
639 change_to_root_user();
640 conn_free(conn);
641 *status = NT_STATUS_UNSUCCESSFUL;
642 return NULL;
645 /* we've finished with the user stuff - go back to root */
646 change_to_root_user();
648 return(conn);
651 /***************************************************************************************
652 Simple wrapper function for make_connection() to include a call to
653 vfs_chdir()
654 **************************************************************************************/
656 connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
657 const char *dev, uint16 vuid, NTSTATUS *status)
659 connection_struct *conn = NULL;
661 conn = make_connection(service_in, password, dev, vuid, status);
664 * make_connection() does not change the directory for us any more
665 * so we have to do it as a separate step --jerry
668 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
669 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
670 conn->connectpath,strerror(errno)));
671 yield_connection(conn, lp_servicename(SNUM(conn)));
672 conn_free(conn);
673 *status = NT_STATUS_UNSUCCESSFUL;
674 return NULL;
677 return conn;
680 /****************************************************************************
681 Make a connection to a service.
683 * @param service
684 ****************************************************************************/
686 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
687 const char *pdev, uint16 vuid, NTSTATUS *status)
689 uid_t euid;
690 user_struct *vuser = NULL;
691 fstring service;
692 fstring dev;
693 int snum = -1;
695 fstrcpy(dev, pdev);
697 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
698 if (!non_root_mode() && (euid = geteuid()) != 0) {
699 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
700 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
703 if(lp_security() != SEC_SHARE) {
704 vuser = get_valid_user_struct(vuid);
705 if (!vuser) {
706 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
707 *status = NT_STATUS_ACCESS_DENIED;
708 return NULL;
712 /* Logic to try and connect to the correct [homes] share, preferably without too many
713 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
714 share name isn't the same as unix username.
716 The snum of the homes share is stored on the vuser at session setup time.
719 if (strequal(service_in,HOMES_NAME)) {
720 if(lp_security() != SEC_SHARE) {
721 DATA_BLOB no_pw = data_blob(NULL, 0);
722 if (vuser->homes_snum == -1) {
723 DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n"));
724 *status = NT_STATUS_BAD_NETWORK_NAME;
725 return NULL;
727 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
728 return make_connection_snum(vuser->homes_snum,
729 vuser, no_pw,
730 dev, status);
731 } else {
732 /* Security = share. Try with current_user_info.smb_name
733 * as the username. */
734 if (*current_user_info.smb_name) {
735 fstring unix_username;
736 fstrcpy(unix_username,
737 current_user_info.smb_name);
738 map_username(unix_username);
739 snum = find_service(unix_username);
741 if (snum != -1) {
742 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
743 return make_connection_snum(snum, NULL,
744 password,
745 dev, status);
748 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
749 && strequal(service_in, lp_servicename(vuser->homes_snum))) {
750 DATA_BLOB no_pw = data_blob(NULL, 0);
751 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
752 return make_connection_snum(vuser->homes_snum,
753 vuser, no_pw,
754 dev, status);
757 fstrcpy(service, service_in);
759 strlower_m(service);
761 snum = find_service(service);
763 if (snum < 0) {
764 if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) {
765 DEBUG(3,("refusing IPC connection to %s\n", service));
766 *status = NT_STATUS_ACCESS_DENIED;
767 return NULL;
770 DEBUG(0,("%s (%s) couldn't find service %s\n",
771 get_remote_machine_name(), client_addr(), service));
772 *status = NT_STATUS_BAD_NETWORK_NAME;
773 return NULL;
776 /* Handle non-Dfs clients attempting connections to msdfs proxy */
777 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
778 DEBUG(3, ("refusing connection to dfs proxy '%s'\n", service));
779 *status = NT_STATUS_BAD_NETWORK_NAME;
780 return NULL;
783 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
785 return make_connection_snum(snum, vuser,
786 password,
787 dev, status);
790 /****************************************************************************
791 close a cnum
792 ****************************************************************************/
793 void close_cnum(connection_struct *conn, uint16 vuid)
795 DirCacheFlush(SNUM(conn));
797 change_to_root_user();
799 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
800 get_remote_machine_name(),conn->client_address,
801 lp_servicename(SNUM(conn))));
803 /* Call VFS disconnect hook */
804 SMB_VFS_DISCONNECT(conn);
806 yield_connection(conn, lp_servicename(SNUM(conn)));
808 file_close_conn(conn);
809 dptr_closecnum(conn);
811 /* make sure we leave the directory available for unmount */
812 vfs_ChDir(conn, "/");
814 /* execute any "postexec = " line */
815 if (*lp_postexec(SNUM(conn)) &&
816 change_to_user(conn, vuid)) {
817 pstring cmd;
818 pstrcpy(cmd,lp_postexec(SNUM(conn)));
819 standard_sub_conn(conn,cmd,sizeof(cmd));
820 smbrun(cmd,NULL);
821 change_to_root_user();
824 change_to_root_user();
825 /* execute any "root postexec = " line */
826 if (*lp_rootpostexec(SNUM(conn))) {
827 pstring cmd;
828 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
829 standard_sub_conn(conn,cmd,sizeof(cmd));
830 smbrun(cmd,NULL);
833 conn_free(conn);