Support printer info 7, used for publishing
[Samba/gebeck_regimport.git] / source / smbd / service.c
blob1f168dd3ffff5b62c677be2d1bab9785c904992a
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 = PRINTCAP;
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, pstring 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 /* you can only connect to the IPC$ service as an ipc device */
231 if (strequal(lp_fstype(snum), "IPC"))
232 pstrcpy(dev,"IPC");
234 if (dev[0] == '?' || !dev[0]) {
235 if (lp_print_ok(snum)) {
236 pstrcpy(dev,"LPT1:");
237 } else {
238 pstrcpy(dev,"A:");
242 /* if the request is as a printer and you can't print then refuse */
243 strupper(dev);
244 if (!lp_print_ok(snum) && (strncmp(dev,"LPT",3) == 0)) {
245 DEBUG(1,("Attempt to connect to non-printer as a printer\n"));
246 return NT_STATUS_BAD_DEVICE_TYPE;
249 /* Behave as a printer if we are supposed to */
250 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
251 pstrcpy(dev, "LPT1:");
254 return NT_STATUS_OK;
258 /****************************************************************************
259 readonly share?
260 ****************************************************************************/
261 static void set_read_only(connection_struct *conn)
263 char **list;
264 char *service = lp_servicename(conn->service);
265 conn->read_only = lp_readonly(conn->service);
267 if (!service) return;
269 str_list_copy(&list, lp_readlist(conn->service));
270 if (list) {
271 if (!str_list_substitute(list, "%S", service)) {
272 DEBUG(0, ("ERROR: read list substitution failed\n"));
274 if (user_in_list(conn->user, (const char **)list))
275 conn->read_only = True;
276 str_list_free(&list);
279 str_list_copy(&list, lp_writelist(conn->service));
280 if (list) {
281 if (!str_list_substitute(list, "%S", service)) {
282 DEBUG(0, ("ERROR: write list substitution failed\n"));
284 if (user_in_list(conn->user, (const char **)list))
285 conn->read_only = False;
286 str_list_free(&list);
291 /****************************************************************************
292 admin user check
293 ****************************************************************************/
294 static void set_admin_user(connection_struct *conn)
296 /* admin user check */
298 /* JRA - original code denied admin user if the share was
299 marked read_only. Changed as I don't think this is needed,
300 but old code left in case there is a problem here.
302 if (user_in_list(conn->user,lp_admin_users(conn->service))
303 #if 0
304 && !conn->read_only
305 #endif
307 conn->admin_user = True;
308 conn->force_user = True; /* Admin users are effectivly 'forced' */
309 DEBUG(0,("%s logged in as admin user (root privileges)\n",conn->user));
310 } else {
311 conn->admin_user = False;
314 #if 0 /* This done later, for now */
315 /* admin users always run as uid=0 */
316 if (conn->admin_user) {
317 conn->uid = 0;
319 #endif
322 /****************************************************************************
323 Make a connection, given the snum to connect to, and the vuser of the
324 connecting user if appropriate.
325 ****************************************************************************/
327 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
328 DATA_BLOB password,
329 char *dev, NTSTATUS *status)
331 struct passwd *pass = NULL;
332 BOOL guest = False;
333 connection_struct *conn;
334 struct stat st;
335 fstring user;
336 *user = 0;
338 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
339 return NULL;
342 conn = conn_new();
343 if (!conn) {
344 DEBUG(0,("Couldn't find free connection.\n"));
345 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
346 return NULL;
349 if (lp_guest_only(snum)) {
350 const char *guestname = lp_guestaccount();
351 guest = True;
352 pass = getpwnam_alloc(guestname);
353 if (!pass) {
354 DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname));
355 conn_free(conn);
356 *status = NT_STATUS_NO_SUCH_USER;
357 return NULL;
359 fstrcpy(user,pass->pw_name);
360 conn->force_user = True;
361 string_set(&conn->user,pass->pw_name);
362 passwd_free(&pass);
363 DEBUG(3,("Guest only user %s\n",user));
364 } else if (vuser) {
365 if (vuser->guest) {
366 if (!lp_guest_ok(snum)) {
367 DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)", lp_servicename(snum)));
368 conn_free(conn);
369 *status = NT_STATUS_ACCESS_DENIED;
370 return NULL;
372 } else {
373 if (!user_ok(vuser->user.unix_name, snum)) {
374 DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)", vuser->user.unix_name, lp_servicename(snum)));
375 conn_free(conn);
376 *status = NT_STATUS_ACCESS_DENIED;
377 return NULL;
380 conn->vuid = vuser->vuid;
381 conn->uid = vuser->uid;
382 conn->gid = vuser->gid;
383 string_set(&conn->user,vuser->user.unix_name);
384 fstrcpy(user,vuser->user.unix_name);
385 guest = vuser->guest;
386 } else if (lp_security() == SEC_SHARE) {
387 /* add it as a possible user name if we
388 are in share mode security */
389 add_session_user(lp_servicename(snum));
390 /* shall we let them in? */
391 if (!authorise_login(snum,user,password,&guest)) {
392 DEBUG( 2, ( "Invalid username/password for [%s]\n",
393 lp_servicename(snum)) );
394 conn_free(conn);
395 *status = NT_STATUS_WRONG_PASSWORD;
396 return NULL;
398 pass = Get_Pwnam(user);
399 conn->force_user = True;
400 conn->uid = pass->pw_uid;
401 conn->gid = pass->pw_gid;
402 string_set(&conn->user, pass->pw_name);
403 fstrcpy(user, pass->pw_name);
405 } else {
406 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
407 conn_free(conn);
408 *status = NT_STATUS_ACCESS_DENIED;
409 return NULL;
412 add_session_user(user);
414 safe_strcpy(conn->client_address, client_addr(),
415 sizeof(conn->client_address)-1);
416 conn->num_files_open = 0;
417 conn->lastused = time(NULL);
418 conn->service = snum;
419 conn->used = True;
420 conn->printer = (strncmp(dev,"LPT",3) == 0);
421 conn->ipc = ((strncmp(dev,"IPC",3) == 0) || strequal(dev,"ADMIN$"));
422 conn->dirptr = NULL;
423 conn->veto_list = NULL;
424 conn->hide_list = NULL;
425 conn->veto_oplock_list = NULL;
426 string_set(&conn->dirpath,"");
427 string_set(&conn->user,user);
428 conn->nt_user_token = NULL;
430 set_read_only(conn);
432 set_admin_user(conn);
435 * If force user is true, then store the
436 * given userid and also the groups
437 * of the user we're forcing.
440 if (*lp_force_user(snum)) {
441 struct passwd *pass2;
442 pstring fuser;
443 pstrcpy(fuser,lp_force_user(snum));
445 /* Allow %S to be used by force user. */
446 pstring_sub(fuser,"%S",lp_servicename(snum));
448 pass2 = (struct passwd *)Get_Pwnam(fuser);
449 if (pass2) {
450 conn->uid = pass2->pw_uid;
451 conn->gid = pass2->pw_gid;
452 string_set(&conn->user,pass2->pw_name);
453 fstrcpy(user,pass2->pw_name);
454 conn->force_user = True;
455 DEBUG(3,("Forced user %s\n",user));
456 } else {
457 DEBUG(1,("Couldn't find user %s\n",fuser));
458 conn_free(conn);
459 *status = NT_STATUS_NO_SUCH_USER;
460 return NULL;
464 /* admin users always run as uid=0 */
465 if (conn->admin_user) {
466 conn->uid = 0;
469 #ifdef HAVE_GETGRNAM
471 * If force group is true, then override
472 * any groupid stored for the connecting user.
475 if (*lp_force_group(snum)) {
476 gid_t gid;
477 pstring gname;
478 pstring tmp_gname;
479 BOOL user_must_be_member = False;
481 StrnCpy(tmp_gname,lp_force_group(snum),sizeof(pstring)-1);
483 if (tmp_gname[0] == '+') {
484 user_must_be_member = True;
485 StrnCpy(gname,&tmp_gname[1],sizeof(pstring)-2);
486 } else {
487 StrnCpy(gname,tmp_gname,sizeof(pstring)-1);
489 /* default service may be a group name */
490 pstring_sub(gname,"%S",lp_servicename(snum));
491 gid = nametogid(gname);
493 if (gid != (gid_t)-1) {
496 * If the user has been forced and the forced group starts
497 * with a '+', then we only set the group to be the forced
498 * group if the forced user is a member of that group.
499 * Otherwise, the meaning of the '+' would be ignored.
501 if (conn->force_user && user_must_be_member) {
502 if (user_in_group_list( user, gname )) {
503 conn->gid = gid;
504 DEBUG(3,("Forced group %s for member %s\n",gname,user));
506 } else {
507 conn->gid = gid;
508 DEBUG(3,("Forced group %s\n",gname));
510 conn->force_group = True;
511 } else {
512 DEBUG(1,("Couldn't find group %s\n",gname));
513 conn_free(conn);
514 *status = NT_STATUS_NO_SUCH_GROUP;
515 return NULL;
518 #endif /* HAVE_GETGRNAM */
521 pstring s;
522 pstrcpy(s,lp_pathname(snum));
523 standard_sub_conn(conn,s,sizeof(s));
524 string_set(&conn->connectpath,s);
525 DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
528 if (conn->force_user || conn->force_group) {
530 /* groups stuff added by ih */
531 conn->ngroups = 0;
532 conn->groups = NULL;
534 /* Find all the groups this uid is in and
535 store them. Used by change_to_user() */
536 initialise_groups(conn->user, conn->uid, conn->gid);
537 get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
539 conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
540 conn->ngroups, conn->groups,
541 guest);
545 * New code to check if there's a share security descripter
546 * added from NT server manager. This is done after the
547 * smb.conf checks are done as we need a uid and token. JRA.
552 BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA);
554 if (!can_write) {
555 if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
556 /* No access, read or write. */
557 DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
558 lp_servicename(snum)));
559 conn_free(conn);
560 *status = NT_STATUS_ACCESS_DENIED;
561 return NULL;
562 } else {
563 conn->read_only = True;
567 /* Initialise VFS function pointers */
569 if (!smbd_vfs_init(conn)) {
570 DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn))));
571 conn_free(conn);
572 *status = NT_STATUS_UNSUCCESSFUL;
573 return NULL;
576 /* ROOT Activities: */
577 /* check number of connections */
578 if (!claim_connection(conn,
579 lp_servicename(SNUM(conn)),
580 lp_max_connections(SNUM(conn)),
581 False,0)) {
582 DEBUG(1,("too many connections - rejected\n"));
583 conn_free(conn);
584 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
585 return NULL;
588 /* Preexecs are done here as they might make the dir we are to ChDir to below */
589 /* execute any "root preexec = " line */
590 if (*lp_rootpreexec(SNUM(conn))) {
591 int ret;
592 pstring cmd;
593 pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
594 standard_sub_conn(conn,cmd,sizeof(cmd));
595 DEBUG(5,("cmd=%s\n",cmd));
596 ret = smbrun(cmd,NULL);
597 if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) {
598 DEBUG(1,("root preexec gave %d - failing connection\n", ret));
599 yield_connection(conn, lp_servicename(SNUM(conn)));
600 conn_free(conn);
601 *status = NT_STATUS_UNSUCCESSFUL;
602 return NULL;
606 /* USER Activites: */
607 if (!change_to_user(conn, conn->vuid)) {
608 /* No point continuing if they fail the basic checks */
609 DEBUG(0,("Can't become connected user!\n"));
610 conn_free(conn);
611 *status = NT_STATUS_LOGON_FAILURE;
612 return NULL;
615 /* Remember that a different vuid can connect later without these checks... */
617 /* Preexecs are done here as they might make the dir we are to ChDir to below */
618 /* execute any "preexec = " line */
619 if (*lp_preexec(SNUM(conn))) {
620 int ret;
621 pstring cmd;
622 pstrcpy(cmd,lp_preexec(SNUM(conn)));
623 standard_sub_conn(conn,cmd,sizeof(cmd));
624 ret = smbrun(cmd,NULL);
625 if (ret != 0 && lp_preexec_close(SNUM(conn))) {
626 DEBUG(1,("preexec gave %d - failing connection\n", ret));
627 change_to_root_user();
628 yield_connection(conn, lp_servicename(SNUM(conn)));
629 conn_free(conn);
630 *status = NT_STATUS_UNSUCCESSFUL;
631 return NULL;
635 #if CHECK_PATH_ON_TCONX
636 /* win2000 does not check the permissions on the directory
637 during the tree connect, instead relying on permission
638 check during individual operations. To match this behaviour
639 I have disabled this chdir check (tridge) */
640 if (vfs_ChDir(conn,conn->connectpath) != 0) {
641 DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n",
642 get_remote_machine_name(), conn->client_address,
643 conn->connectpath,strerror(errno)));
644 change_to_root_user();
645 yield_connection(conn, lp_servicename(SNUM(conn)));
646 conn_free(conn);
647 *status = NT_STATUS_BAD_NETWORK_NAME;
648 return NULL;
650 #else
651 /* the alternative is just to check the directory exists */
652 if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
653 DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn))));
654 change_to_root_user();
655 yield_connection(conn, lp_servicename(SNUM(conn)));
656 conn_free(conn);
657 *status = NT_STATUS_BAD_NETWORK_NAME;
658 return NULL;
660 #endif
662 string_set(&conn->origpath,conn->connectpath);
664 #if SOFTLINK_OPTIMISATION
665 /* resolve any soft links early if possible */
666 if (vfs_ChDir(conn,conn->connectpath) == 0) {
667 pstring s;
668 pstrcpy(s,conn->connectpath);
669 vfs_GetWd(conn,s);
670 string_set(&conn->connectpath,s);
671 vfs_ChDir(conn,conn->connectpath);
673 #endif
676 * Print out the 'connected as' stuff here as we need
677 * to know the effective uid and gid we will be using
678 * (at least initially).
681 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
682 dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
683 dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
684 dbgtext( "initially as user %s ", user );
685 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
686 dbgtext( "(pid %d)\n", (int)sys_getpid() );
689 /* Add veto/hide lists */
690 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
691 set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn)));
692 set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn)));
693 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn)));
696 /* Invoke VFS make connection hook */
698 if (conn->vfs_ops.connect) {
699 if (conn->vfs_ops.connect(conn, lp_servicename(snum), user) < 0) {
700 DEBUG(0,("make_connection: VFS make connection failed!\n"));
701 change_to_root_user();
702 conn_free(conn);
703 *status = NT_STATUS_UNSUCCESSFUL;
704 return NULL;
708 /* we've finished with the user stuff - go back to root */
709 change_to_root_user();
711 return(conn);
714 /***************************************************************************************
715 Simple wrapper function for make_connection() to include a call to
716 vfs_chdir()
717 **************************************************************************************/
719 connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
720 char *dev, uint16 vuid, NTSTATUS *status)
722 connection_struct *conn = NULL;
724 conn = make_connection(service_in, password, dev, vuid, status);
727 * make_connection() does not change the directory for us any more
728 * so we have to do it as a separate step --jerry
731 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
732 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
733 conn->connectpath,strerror(errno)));
734 yield_connection(conn, lp_servicename(SNUM(conn)));
735 conn_free(conn);
736 *status = NT_STATUS_UNSUCCESSFUL;
737 return NULL;
740 return conn;
743 /****************************************************************************
744 Make a connection to a service.
746 * @param service
747 ****************************************************************************/
749 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
750 char *dev, uint16 vuid, NTSTATUS *status)
752 uid_t euid;
753 user_struct *vuser = NULL;
754 pstring service;
755 int snum = -1;
757 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
758 if (!non_root_mode() && (euid = geteuid()) != 0) {
759 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
760 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
763 if(lp_security() != SEC_SHARE) {
764 vuser = get_valid_user_struct(vuid);
765 if (!vuser) {
766 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
767 *status = NT_STATUS_ACCESS_DENIED;
768 return NULL;
772 /* Logic to try and connect to the correct [homes] share, preferably without too many
773 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
774 share name isn't the same as unix username.
776 The snum of the homes share is stored on the vuser at session setup time.
779 if (strequal(service_in,HOMES_NAME)) {
780 if(lp_security() != SEC_SHARE) {
781 DATA_BLOB no_pw = data_blob(NULL, 0);
782 if (vuser->homes_snum == -1) {
783 DEBUG(2, ("[homes] share not available for this user becouse it was not found or created at session setup time\n"));
784 *status = NT_STATUS_BAD_NETWORK_NAME;
785 return NULL;
787 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
788 return make_connection_snum(vuser->homes_snum,
789 vuser, no_pw,
790 dev, status);
791 } else {
792 /* Security = share. Try with current_user_info.smb_name
793 * as the username. */
794 if (*current_user_info.smb_name) {
795 fstring unix_username;
796 fstrcpy(unix_username,
797 current_user_info.smb_name);
798 map_username(unix_username);
799 snum = find_service(unix_username);
801 if (snum != -1) {
802 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
803 return make_connection_snum(snum, NULL,
804 password,
805 dev, status);
808 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
809 && strequal(service_in, lp_servicename(vuser->homes_snum))) {
810 DATA_BLOB no_pw = data_blob(NULL, 0);
811 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
812 return make_connection_snum(vuser->homes_snum,
813 vuser, no_pw,
814 dev, status);
817 pstrcpy(service, service_in);
819 strlower(service);
821 snum = find_service(service);
823 if (snum < 0) {
824 if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) {
825 DEBUG(3,("refusing IPC connection to %s\n", service));
826 *status = NT_STATUS_ACCESS_DENIED;
827 return NULL;
830 DEBUG(0,("%s (%s) couldn't find service %s\n",
831 get_remote_machine_name(), client_addr(), service));
832 *status = NT_STATUS_BAD_NETWORK_NAME;
833 return NULL;
836 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
838 return make_connection_snum(snum, vuser,
839 password,
840 dev, status);
843 /****************************************************************************
844 close a cnum
845 ****************************************************************************/
846 void close_cnum(connection_struct *conn, uint16 vuid)
848 DirCacheFlush(SNUM(conn));
850 change_to_root_user();
852 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
853 get_remote_machine_name(),conn->client_address,
854 lp_servicename(SNUM(conn))));
856 if (conn->vfs_ops.disconnect != NULL) {
858 /* Call VFS disconnect hook */
860 conn->vfs_ops.disconnect(conn);
864 yield_connection(conn, lp_servicename(SNUM(conn)));
866 file_close_conn(conn);
867 dptr_closecnum(conn);
869 /* execute any "postexec = " line */
870 if (*lp_postexec(SNUM(conn)) &&
871 change_to_user(conn, vuid)) {
872 pstring cmd;
873 pstrcpy(cmd,lp_postexec(SNUM(conn)));
874 standard_sub_conn(conn,cmd,sizeof(cmd));
875 smbrun(cmd,NULL);
876 change_to_root_user();
879 change_to_root_user();
880 /* execute any "root postexec = " line */
881 if (*lp_rootpostexec(SNUM(conn))) {
882 pstring cmd;
883 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
884 standard_sub_conn(conn,cmd,sizeof(cmd));
885 smbrun(cmd,NULL);
888 /* make sure we leave the directory available for unmount */
889 vfs_ChDir(conn, "/");
891 conn_free(conn);