r4348: syncing up for 3.0.11pre1
[Samba.git] / source / smbd / service.c
blob3dcd803a7ce6aa632decc444f3d65c15b7d042c3
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 if (lp_casesensitive(snum) == 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);
74 magic_char = lp_magicchar(snum);
75 return(True);
78 /****************************************************************************
79 Add a home service. Returns the new service number or -1 if fail.
80 ****************************************************************************/
82 int add_home_service(const char *service, const char *username, const char *homedir)
84 int iHomeService;
86 if (!service || !homedir)
87 return -1;
89 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
90 return -1;
93 * If this is a winbindd provided username, remove
94 * the domain component before adding the service.
95 * Log a warning if the "path=" parameter does not
96 * include any macros.
100 const char *p = strchr(service,*lp_winbind_separator());
102 /* We only want the 'user' part of the string */
103 if (p) {
104 service = p + 1;
108 if (!lp_add_home(service, iHomeService, username, homedir)) {
109 return -1;
112 return lp_servicenumber(service);
118 * Find a service entry.
120 * @param service is modified (to canonical form??)
123 int find_service(fstring service)
125 int iService;
127 all_string_sub(service,"\\","/",0);
129 iService = lp_servicenumber(service);
131 /* now handle the special case of a home directory */
132 if (iService < 0) {
133 char *phome_dir = get_user_home_dir(service);
135 if(!phome_dir) {
137 * Try mapping the servicename, it may
138 * be a Windows to unix mapped user name.
140 if(map_username(service))
141 phome_dir = get_user_home_dir(service);
144 DEBUG(3,("checking for home directory %s gave %s\n",service,
145 phome_dir?phome_dir:"(NULL)"));
147 iService = add_home_service(service,service /* 'username' */, phome_dir);
150 /* If we still don't have a service, attempt to add it as a printer. */
151 if (iService < 0) {
152 int iPrinterService;
154 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
155 const char *pszTemp = lp_printcapname();
157 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
158 if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) {
159 DEBUG(3,("%s is a valid printer name\n", service));
160 DEBUG(3,("adding %s as a printer service\n", service));
161 lp_add_printer(service, iPrinterService);
162 iService = lp_servicenumber(service);
163 if (iService < 0) {
164 DEBUG(0,("failed to add %s as a printer service!\n", service));
166 } else {
167 DEBUG(3,("%s is not a valid printer name\n", service));
172 /* Check for default vfs service? Unsure whether to implement this */
173 if (iService < 0) {
176 /* just possibly it's a default service? */
177 if (iService < 0) {
178 char *pdefservice = lp_defaultservice();
179 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
181 * We need to do a local copy here as lp_defaultservice()
182 * returns one of the rotating lp_string buffers that
183 * could get overwritten by the recursive find_service() call
184 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
186 pstring defservice;
187 pstrcpy(defservice, pdefservice);
188 iService = find_service(defservice);
189 if (iService >= 0) {
190 all_string_sub(service, "_","/",0);
191 iService = lp_add_service(service, iService);
196 if (iService >= 0) {
197 if (!VALID_SNUM(iService)) {
198 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
199 iService = -1;
203 if (iService < 0)
204 DEBUG(3,("find_service() failed to find service %s\n", service));
206 return (iService);
210 /****************************************************************************
211 do some basic sainity checks on the share.
212 This function modifies dev, ecode.
213 ****************************************************************************/
215 static NTSTATUS share_sanity_checks(int snum, fstring dev)
218 if (!lp_snum_ok(snum) ||
219 !check_access(smbd_server_fd(),
220 lp_hostsallow(snum), lp_hostsdeny(snum))) {
221 return NT_STATUS_ACCESS_DENIED;
224 if (dev[0] == '?' || !dev[0]) {
225 if (lp_print_ok(snum)) {
226 fstrcpy(dev,"LPT1:");
227 } else if (strequal(lp_fstype(snum), "IPC")) {
228 fstrcpy(dev, "IPC");
229 } else {
230 fstrcpy(dev,"A:");
234 strupper_m(dev);
236 if (lp_print_ok(snum)) {
237 if (!strequal(dev, "LPT1:")) {
238 return NT_STATUS_BAD_DEVICE_TYPE;
240 } else if (strequal(lp_fstype(snum), "IPC")) {
241 if (!strequal(dev, "IPC")) {
242 return NT_STATUS_BAD_DEVICE_TYPE;
244 } else if (!strequal(dev, "A:")) {
245 return NT_STATUS_BAD_DEVICE_TYPE;
248 /* Behave as a printer if we are supposed to */
249 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
250 fstrcpy(dev, "LPT1:");
253 return NT_STATUS_OK;
256 /****************************************************************************
257 Make a connection, given the snum to connect to, and the vuser of the
258 connecting user if appropriate.
259 ****************************************************************************/
261 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
262 DATA_BLOB password,
263 const char *pdev, NTSTATUS *status)
265 struct passwd *pass = NULL;
266 BOOL guest = False;
267 connection_struct *conn;
268 struct stat st;
269 fstring user;
270 fstring dev;
272 *user = 0;
273 fstrcpy(dev, pdev);
275 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
276 return NULL;
279 conn = conn_new();
280 if (!conn) {
281 DEBUG(0,("Couldn't find free connection.\n"));
282 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
283 return NULL;
286 if (lp_guest_only(snum)) {
287 const char *guestname = lp_guestaccount();
288 guest = True;
289 pass = getpwnam_alloc(guestname);
290 if (!pass) {
291 DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname));
292 conn_free(conn);
293 *status = NT_STATUS_NO_SUCH_USER;
294 return NULL;
296 fstrcpy(user,pass->pw_name);
297 conn->force_user = True;
298 conn->uid = pass->pw_uid;
299 conn->gid = pass->pw_gid;
300 string_set(&conn->user,pass->pw_name);
301 passwd_free(&pass);
302 DEBUG(3,("Guest only user %s\n",user));
303 } else if (vuser) {
304 if (vuser->guest) {
305 if (!lp_guest_ok(snum)) {
306 DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum)));
307 conn_free(conn);
308 *status = NT_STATUS_ACCESS_DENIED;
309 return NULL;
311 } else {
312 if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) {
313 DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum)));
314 conn_free(conn);
315 *status = NT_STATUS_ACCESS_DENIED;
316 return NULL;
319 conn->vuid = vuser->vuid;
320 conn->uid = vuser->uid;
321 conn->gid = vuser->gid;
322 string_set(&conn->user,vuser->user.unix_name);
323 fstrcpy(user,vuser->user.unix_name);
324 guest = vuser->guest;
325 } else if (lp_security() == SEC_SHARE) {
326 /* add it as a possible user name if we
327 are in share mode security */
328 add_session_user(lp_servicename(snum));
329 /* shall we let them in? */
330 if (!authorise_login(snum,user,password,&guest)) {
331 DEBUG( 2, ( "Invalid username/password for [%s]\n",
332 lp_servicename(snum)) );
333 conn_free(conn);
334 *status = NT_STATUS_WRONG_PASSWORD;
335 return NULL;
337 pass = Get_Pwnam(user);
338 conn->force_user = True;
339 conn->uid = pass->pw_uid;
340 conn->gid = pass->pw_gid;
341 string_set(&conn->user, pass->pw_name);
342 fstrcpy(user, pass->pw_name);
344 } else {
345 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
346 conn_free(conn);
347 *status = NT_STATUS_ACCESS_DENIED;
348 return NULL;
351 add_session_user(user);
353 safe_strcpy(conn->client_address, client_addr(),
354 sizeof(conn->client_address)-1);
355 conn->num_files_open = 0;
356 conn->lastused = time(NULL);
357 conn->service = snum;
358 conn->used = True;
359 conn->printer = (strncmp(dev,"LPT",3) == 0);
360 conn->ipc = ((strncmp(dev,"IPC",3) == 0) || strequal(dev,"ADMIN$"));
361 conn->dirptr = NULL;
363 /* Case options for the share. */
364 if (lp_casesensitive(snum) == Auto) {
365 /* We will be setting this per packet. Set to be case insensitive for now. */
366 conn->case_sensitive = False;
367 } else {
368 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
371 conn->case_preserve = lp_preservecase(snum);
372 conn->short_case_preserve = lp_shortpreservecase(snum);
374 conn->veto_list = NULL;
375 conn->hide_list = NULL;
376 conn->veto_oplock_list = NULL;
377 string_set(&conn->dirpath,"");
378 string_set(&conn->user,user);
379 conn->nt_user_token = NULL;
381 conn->read_only = lp_readonly(conn->service);
382 conn->admin_user = False;
385 * If force user is true, then store the
386 * given userid and also the groups
387 * of the user we're forcing.
390 if (*lp_force_user(snum)) {
391 struct passwd *pass2;
392 pstring fuser;
393 pstrcpy(fuser,lp_force_user(snum));
395 /* Allow %S to be used by force user. */
396 pstring_sub(fuser,"%S",lp_servicename(snum));
398 pass2 = (struct passwd *)Get_Pwnam(fuser);
399 if (pass2) {
400 conn->uid = pass2->pw_uid;
401 conn->gid = pass2->pw_gid;
402 string_set(&conn->user,pass2->pw_name);
403 fstrcpy(user,pass2->pw_name);
404 conn->force_user = True;
405 DEBUG(3,("Forced user %s\n",user));
406 } else {
407 DEBUG(1,("Couldn't find user %s\n",fuser));
408 conn_free(conn);
409 *status = NT_STATUS_NO_SUCH_USER;
410 return NULL;
414 #ifdef HAVE_GETGRNAM
416 * If force group is true, then override
417 * any groupid stored for the connecting user.
420 if (*lp_force_group(snum)) {
421 gid_t gid;
422 pstring gname;
423 pstring tmp_gname;
424 BOOL user_must_be_member = False;
426 pstrcpy(tmp_gname,lp_force_group(snum));
428 if (tmp_gname[0] == '+') {
429 user_must_be_member = True;
430 /* even now, tmp_gname is null terminated */
431 pstrcpy(gname,&tmp_gname[1]);
432 } else {
433 pstrcpy(gname,tmp_gname);
435 /* default service may be a group name */
436 pstring_sub(gname,"%S",lp_servicename(snum));
437 gid = nametogid(gname);
439 if (gid != (gid_t)-1) {
442 * If the user has been forced and the forced group starts
443 * with a '+', then we only set the group to be the forced
444 * group if the forced user is a member of that group.
445 * Otherwise, the meaning of the '+' would be ignored.
447 if (conn->force_user && user_must_be_member) {
448 if (user_in_group_list( user, gname, NULL, 0)) {
449 conn->gid = gid;
450 DEBUG(3,("Forced group %s for member %s\n",gname,user));
452 } else {
453 conn->gid = gid;
454 DEBUG(3,("Forced group %s\n",gname));
456 conn->force_group = True;
457 } else {
458 DEBUG(1,("Couldn't find group %s\n",gname));
459 conn_free(conn);
460 *status = NT_STATUS_NO_SUCH_GROUP;
461 return NULL;
464 #endif /* HAVE_GETGRNAM */
467 pstring s;
468 pstrcpy(s,lp_pathname(snum));
469 standard_sub_conn(conn,s,sizeof(s));
470 string_set(&conn->connectpath,s);
471 DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
474 if (conn->force_user || conn->force_group) {
476 /* groups stuff added by ih */
477 conn->ngroups = 0;
478 conn->groups = NULL;
480 /* Find all the groups this uid is in and
481 store them. Used by change_to_user() */
482 initialise_groups(conn->user, conn->uid, conn->gid);
483 get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
485 conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
486 conn->ngroups, conn->groups,
487 guest);
491 * New code to check if there's a share security descripter
492 * added from NT server manager. This is done after the
493 * smb.conf checks are done as we need a uid and token. JRA.
498 BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA);
500 if (!can_write) {
501 if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
502 /* No access, read or write. */
503 DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
504 lp_servicename(snum)));
505 conn_free(conn);
506 *status = NT_STATUS_ACCESS_DENIED;
507 return NULL;
508 } else {
509 conn->read_only = True;
513 /* Initialise VFS function pointers */
515 if (!smbd_vfs_init(conn)) {
516 DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn))));
517 conn_free(conn);
518 *status = NT_STATUS_BAD_NETWORK_NAME;
519 return NULL;
523 * If widelinks are disallowed we need to canonicalise the
524 * connect path here to ensure we don't have any symlinks in
525 * the connectpath. We will be checking all paths on this
526 * connection are below this directory. We must do this after
527 * the VFS init as we depend on the realpath() pointer in the vfs table. JRA.
529 if (!lp_widelinks(snum)) {
530 pstring s;
531 pstrcpy(s,conn->connectpath);
532 canonicalize_path(conn, s);
533 string_set(&conn->connectpath,s);
536 /* ROOT Activities: */
537 /* check number of connections */
538 if (!claim_connection(conn,
539 lp_servicename(SNUM(conn)),
540 lp_max_connections(SNUM(conn)),
541 False,0)) {
542 DEBUG(1,("too many connections - rejected\n"));
543 conn_free(conn);
544 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
545 return NULL;
548 /* Preexecs are done here as they might make the dir we are to ChDir to below */
549 /* execute any "root preexec = " line */
550 if (*lp_rootpreexec(SNUM(conn))) {
551 int ret;
552 pstring cmd;
553 pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
554 standard_sub_conn(conn,cmd,sizeof(cmd));
555 DEBUG(5,("cmd=%s\n",cmd));
556 ret = smbrun(cmd,NULL);
557 if (ret != 0 && lp_rootpreexec_close(SNUM(conn))) {
558 DEBUG(1,("root preexec gave %d - failing connection\n", ret));
559 yield_connection(conn, lp_servicename(SNUM(conn)));
560 conn_free(conn);
561 *status = NT_STATUS_ACCESS_DENIED;
562 return NULL;
566 /* USER Activites: */
567 if (!change_to_user(conn, conn->vuid)) {
568 /* No point continuing if they fail the basic checks */
569 DEBUG(0,("Can't become connected user!\n"));
570 conn_free(conn);
571 *status = NT_STATUS_LOGON_FAILURE;
572 return NULL;
575 /* Remember that a different vuid can connect later without these checks... */
577 /* Preexecs are done here as they might make the dir we are to ChDir to below */
578 /* execute any "preexec = " line */
579 if (*lp_preexec(SNUM(conn))) {
580 int ret;
581 pstring cmd;
582 pstrcpy(cmd,lp_preexec(SNUM(conn)));
583 standard_sub_conn(conn,cmd,sizeof(cmd));
584 ret = smbrun(cmd,NULL);
585 if (ret != 0 && lp_preexec_close(SNUM(conn))) {
586 DEBUG(1,("preexec gave %d - failing connection\n", ret));
587 change_to_root_user();
588 yield_connection(conn, lp_servicename(SNUM(conn)));
589 conn_free(conn);
590 *status = NT_STATUS_ACCESS_DENIED;
591 return NULL;
595 #ifdef WITH_FAKE_KASERVER
596 if (lp_afs_share(SNUM(conn))) {
597 afs_login(conn);
599 #endif
601 #if CHECK_PATH_ON_TCONX
602 /* win2000 does not check the permissions on the directory
603 during the tree connect, instead relying on permission
604 check during individual operations. To match this behaviour
605 I have disabled this chdir check (tridge) */
606 if (vfs_ChDir(conn,conn->connectpath) != 0) {
607 DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n",
608 get_remote_machine_name(), conn->client_address,
609 conn->connectpath,strerror(errno)));
610 change_to_root_user();
611 yield_connection(conn, lp_servicename(SNUM(conn)));
612 conn_free(conn);
613 *status = NT_STATUS_BAD_NETWORK_NAME;
614 return NULL;
616 #else
617 /* the alternative is just to check the directory exists */
618 if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
619 DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn))));
620 change_to_root_user();
621 yield_connection(conn, lp_servicename(SNUM(conn)));
622 conn_free(conn);
623 *status = NT_STATUS_BAD_NETWORK_NAME;
624 return NULL;
626 #endif
628 string_set(&conn->origpath,conn->connectpath);
630 #if SOFTLINK_OPTIMISATION
631 /* resolve any soft links early if possible */
632 if (vfs_ChDir(conn,conn->connectpath) == 0) {
633 pstring s;
634 pstrcpy(s,conn->connectpath);
635 vfs_GetWd(conn,s);
636 string_set(&conn->connectpath,s);
637 vfs_ChDir(conn,conn->connectpath);
639 #endif
642 * Print out the 'connected as' stuff here as we need
643 * to know the effective uid and gid we will be using
644 * (at least initially).
647 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
648 dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
649 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
650 dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
651 dbgtext( "initially as user %s ", user );
652 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
653 dbgtext( "(pid %d)\n", (int)sys_getpid() );
656 /* Add veto/hide lists */
657 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
658 set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn)));
659 set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn)));
660 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn)));
663 /* Invoke VFS make connection hook */
665 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
666 DEBUG(0,("make_connection: VFS make connection failed!\n"));
667 change_to_root_user();
668 conn_free(conn);
669 *status = NT_STATUS_UNSUCCESSFUL;
670 return NULL;
673 /* we've finished with the user stuff - go back to root */
674 change_to_root_user();
676 return(conn);
679 /***************************************************************************************
680 Simple wrapper function for make_connection() to include a call to
681 vfs_chdir()
682 **************************************************************************************/
684 connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
685 const char *dev, uint16 vuid, NTSTATUS *status)
687 connection_struct *conn = NULL;
689 conn = make_connection(service_in, password, dev, vuid, status);
692 * make_connection() does not change the directory for us any more
693 * so we have to do it as a separate step --jerry
696 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
697 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
698 conn->connectpath,strerror(errno)));
699 yield_connection(conn, lp_servicename(SNUM(conn)));
700 conn_free(conn);
701 *status = NT_STATUS_UNSUCCESSFUL;
702 return NULL;
705 return conn;
708 /****************************************************************************
709 Make a connection to a service.
711 * @param service
712 ****************************************************************************/
714 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
715 const char *pdev, uint16 vuid, NTSTATUS *status)
717 uid_t euid;
718 user_struct *vuser = NULL;
719 fstring service;
720 fstring dev;
721 int snum = -1;
723 fstrcpy(dev, pdev);
725 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
726 if (!non_root_mode() && (euid = geteuid()) != 0) {
727 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
728 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
731 if(lp_security() != SEC_SHARE) {
732 vuser = get_valid_user_struct(vuid);
733 if (!vuser) {
734 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
735 *status = NT_STATUS_ACCESS_DENIED;
736 return NULL;
740 /* Logic to try and connect to the correct [homes] share, preferably without too many
741 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
742 share name isn't the same as unix username.
744 The snum of the homes share is stored on the vuser at session setup time.
747 if (strequal(service_in,HOMES_NAME)) {
748 if(lp_security() != SEC_SHARE) {
749 DATA_BLOB no_pw = data_blob(NULL, 0);
750 if (vuser->homes_snum == -1) {
751 DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n"));
752 *status = NT_STATUS_BAD_NETWORK_NAME;
753 return NULL;
755 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
756 return make_connection_snum(vuser->homes_snum,
757 vuser, no_pw,
758 dev, status);
759 } else {
760 /* Security = share. Try with current_user_info.smb_name
761 * as the username. */
762 if (*current_user_info.smb_name) {
763 fstring unix_username;
764 fstrcpy(unix_username,
765 current_user_info.smb_name);
766 map_username(unix_username);
767 snum = find_service(unix_username);
769 if (snum != -1) {
770 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
771 return make_connection_snum(snum, NULL,
772 password,
773 dev, status);
776 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
777 && strequal(service_in, lp_servicename(vuser->homes_snum))) {
778 DATA_BLOB no_pw = data_blob(NULL, 0);
779 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
780 return make_connection_snum(vuser->homes_snum,
781 vuser, no_pw,
782 dev, status);
785 fstrcpy(service, service_in);
787 strlower_m(service);
789 snum = find_service(service);
791 if (snum < 0) {
792 if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) {
793 DEBUG(3,("refusing IPC connection to %s\n", service));
794 *status = NT_STATUS_ACCESS_DENIED;
795 return NULL;
798 DEBUG(0,("%s (%s) couldn't find service %s\n",
799 get_remote_machine_name(), client_addr(), service));
800 *status = NT_STATUS_BAD_NETWORK_NAME;
801 return NULL;
804 /* Handle non-Dfs clients attempting connections to msdfs proxy */
805 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
806 DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n",
807 service, lp_msdfs_proxy(snum)));
808 *status = NT_STATUS_BAD_NETWORK_NAME;
809 return NULL;
812 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
814 return make_connection_snum(snum, vuser,
815 password,
816 dev, status);
819 /****************************************************************************
820 close a cnum
821 ****************************************************************************/
822 void close_cnum(connection_struct *conn, uint16 vuid)
824 if (IS_IPC(conn)) {
825 pipe_close_conn(conn);
826 } else {
827 file_close_conn(conn);
828 dptr_closecnum(conn);
831 change_to_root_user();
833 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
834 get_remote_machine_name(),conn->client_address,
835 lp_servicename(SNUM(conn))));
837 /* Call VFS disconnect hook */
838 SMB_VFS_DISCONNECT(conn);
840 yield_connection(conn, lp_servicename(SNUM(conn)));
842 /* make sure we leave the directory available for unmount */
843 vfs_ChDir(conn, "/");
845 /* execute any "postexec = " line */
846 if (*lp_postexec(SNUM(conn)) &&
847 change_to_user(conn, vuid)) {
848 pstring cmd;
849 pstrcpy(cmd,lp_postexec(SNUM(conn)));
850 standard_sub_conn(conn,cmd,sizeof(cmd));
851 smbrun(cmd,NULL);
852 change_to_root_user();
855 change_to_root_user();
856 /* execute any "root postexec = " line */
857 if (*lp_rootpostexec(SNUM(conn))) {
858 pstring cmd;
859 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
860 standard_sub_conn(conn,cmd,sizeof(cmd));
861 smbrun(cmd,NULL);
864 conn_free(conn);
867 /****************************************************************************
868 Remove stale printers
869 ****************************************************************************/
871 void remove_stale_printers( void )
873 int snum, iNumServices, printersServiceNum;
874 const char *pname;
876 iNumServices = lp_numservices();
877 printersServiceNum = lp_servicenumber( PRINTERS_NAME);
878 for( snum = 0; snum < iNumServices; snum++) {
880 /* Never remove PRINTERS_NAME */
882 if ( snum == printersServiceNum)
883 continue;
884 pname = lp_printername( snum);
886 /* Is snum an autoloaded print service and still
887 in the printing subsystem? */
889 if ( lp_snum_ok(snum)
890 && lp_print_ok(snum)
891 && lp_autoloaded(snum)
892 && !pcap_printername_ok( pname, NULL))
894 DEBUG( 3, ( "Removing printer: %s\n", pname));
895 lp_killservice( snum);