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.
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
;
43 conn
->lastused
= smb_last_time
.tv_sec
;
48 vfs_ChDir(conn
,conn
->connectpath
) != 0 &&
49 vfs_ChDir(conn
,conn
->origpath
) != 0) {
50 DEBUG(0,("chdir (%s) failed\n",
55 if ((conn
== last_conn
) && (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
;
70 conn
->case_sensitive
= !(flags
& FLAG_CASELESS_PATHNAMES
);
74 magic_char
= lp_magicchar(snum
);
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
)
86 if (!service
|| !homedir
)
89 if ((iHomeService
= lp_servicenumber(HOMES_NAME
)) < 0)
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
100 const char *p
= strchr(service
,*lp_winbind_separator());
102 /* We only want the 'user' part of the string */
108 if (!lp_add_home(service
, iHomeService
, username
, homedir
)) {
112 return lp_servicenumber(service
);
118 * Find a service entry.
120 * @param service is modified (to canonical form??)
123 int find_service(fstring service
)
127 all_string_sub(service
,"\\","/",0);
129 iService
= lp_servicenumber(service
);
131 /* now handle the special case of a home directory */
133 char *phome_dir
= get_user_home_dir(service
);
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. */
154 if ((iPrinterService
= lp_servicenumber(PRINTERS_NAME
)) >= 0) {
157 DEBUG(3,("checking whether %s is a valid printer name...\n", service
));
158 pszTemp
= lp_printcapname();
159 if ((pszTemp
!= NULL
) && pcap_printername_ok(service
, pszTemp
)) {
160 DEBUG(3,("%s is a valid printer name\n", service
));
161 DEBUG(3,("adding %s as a printer service\n", service
));
162 lp_add_printer(service
, iPrinterService
);
163 iService
= lp_servicenumber(service
);
165 DEBUG(0,("failed to add %s as a printer service!\n", service
));
168 DEBUG(3,("%s is not a valid printer name\n", service
));
173 /* Check for default vfs service? Unsure whether to implement this */
177 /* just possibly it's a default service? */
179 char *pdefservice
= lp_defaultservice();
180 if (pdefservice
&& *pdefservice
&& !strequal(pdefservice
,service
) && !strstr_m(service
,"..")) {
182 * We need to do a local copy here as lp_defaultservice()
183 * returns one of the rotating lp_string buffers that
184 * could get overwritten by the recursive find_service() call
185 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
188 pstrcpy(defservice
, pdefservice
);
189 iService
= find_service(defservice
);
191 all_string_sub(service
, "_","/",0);
192 iService
= lp_add_service(service
, iService
);
198 if (!VALID_SNUM(iService
)) {
199 DEBUG(0,("Invalid snum %d for %s\n",iService
, service
));
205 DEBUG(3,("find_service() failed to find service %s\n", service
));
211 /****************************************************************************
212 do some basic sainity checks on the share.
213 This function modifies dev, ecode.
214 ****************************************************************************/
216 static NTSTATUS
share_sanity_checks(int snum
, fstring dev
)
219 if (!lp_snum_ok(snum
) ||
220 !check_access(smbd_server_fd(),
221 lp_hostsallow(snum
), lp_hostsdeny(snum
))) {
222 return NT_STATUS_ACCESS_DENIED
;
225 if (dev
[0] == '?' || !dev
[0]) {
226 if (lp_print_ok(snum
)) {
227 fstrcpy(dev
,"LPT1:");
228 } else if (strequal(lp_fstype(snum
), "IPC")) {
237 if (lp_print_ok(snum
)) {
238 if (!strequal(dev
, "LPT1:")) {
239 return NT_STATUS_BAD_DEVICE_TYPE
;
241 } else if (strequal(lp_fstype(snum
), "IPC")) {
242 if (!strequal(dev
, "IPC")) {
243 return NT_STATUS_BAD_DEVICE_TYPE
;
245 } else if (!strequal(dev
, "A:")) {
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 fstrcpy(dev
, "LPT1:");
257 /****************************************************************************
258 Make a connection, given the snum to connect to, and the vuser of the
259 connecting user if appropriate.
260 ****************************************************************************/
262 static connection_struct
*make_connection_snum(int snum
, user_struct
*vuser
,
264 const char *pdev
, NTSTATUS
*status
)
266 struct passwd
*pass
= NULL
;
268 connection_struct
*conn
;
276 if (NT_STATUS_IS_ERR(*status
= share_sanity_checks(snum
, dev
))) {
282 DEBUG(0,("Couldn't find free connection.\n"));
283 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
287 if (lp_guest_only(snum
)) {
288 const char *guestname
= lp_guestaccount();
290 pass
= getpwnam_alloc(guestname
);
292 DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname
));
294 *status
= NT_STATUS_NO_SUCH_USER
;
297 fstrcpy(user
,pass
->pw_name
);
298 conn
->force_user
= True
;
299 conn
->uid
= pass
->pw_uid
;
300 conn
->gid
= pass
->pw_gid
;
301 string_set(&conn
->user
,pass
->pw_name
);
303 DEBUG(3,("Guest only user %s\n",user
));
306 if (!lp_guest_ok(snum
)) {
307 DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum
)));
309 *status
= NT_STATUS_ACCESS_DENIED
;
313 if (!user_ok(vuser
->user
.unix_name
, snum
, vuser
->groups
, vuser
->n_groups
)) {
314 DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser
->user
.unix_name
, lp_servicename(snum
)));
316 *status
= NT_STATUS_ACCESS_DENIED
;
320 conn
->vuid
= vuser
->vuid
;
321 conn
->uid
= vuser
->uid
;
322 conn
->gid
= vuser
->gid
;
323 string_set(&conn
->user
,vuser
->user
.unix_name
);
324 fstrcpy(user
,vuser
->user
.unix_name
);
325 guest
= vuser
->guest
;
326 } else if (lp_security() == SEC_SHARE
) {
327 /* add it as a possible user name if we
328 are in share mode security */
329 add_session_user(lp_servicename(snum
));
330 /* shall we let them in? */
331 if (!authorise_login(snum
,user
,password
,&guest
)) {
332 DEBUG( 2, ( "Invalid username/password for [%s]\n",
333 lp_servicename(snum
)) );
335 *status
= NT_STATUS_WRONG_PASSWORD
;
338 pass
= Get_Pwnam(user
);
339 conn
->force_user
= True
;
340 conn
->uid
= pass
->pw_uid
;
341 conn
->gid
= pass
->pw_gid
;
342 string_set(&conn
->user
, pass
->pw_name
);
343 fstrcpy(user
, pass
->pw_name
);
346 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
348 *status
= NT_STATUS_ACCESS_DENIED
;
352 add_session_user(user
);
354 safe_strcpy(conn
->client_address
, client_addr(),
355 sizeof(conn
->client_address
)-1);
356 conn
->num_files_open
= 0;
357 conn
->lastused
= time(NULL
);
358 conn
->service
= snum
;
360 conn
->printer
= (strncmp(dev
,"LPT",3) == 0);
361 conn
->ipc
= ((strncmp(dev
,"IPC",3) == 0) || strequal(dev
,"ADMIN$"));
364 /* Case options for the share. */
365 if (lp_casesensitive(snum
) == Auto
) {
366 /* We will be setting this per packet. Set to be case insensitive for now. */
367 conn
->case_sensitive
= False
;
369 conn
->case_sensitive
= (BOOL
)lp_casesensitive(snum
);
372 conn
->case_preserve
= lp_preservecase(snum
);
373 conn
->short_case_preserve
= lp_shortpreservecase(snum
);
375 conn
->veto_list
= NULL
;
376 conn
->hide_list
= NULL
;
377 conn
->veto_oplock_list
= NULL
;
378 string_set(&conn
->dirpath
,"");
379 string_set(&conn
->user
,user
);
380 conn
->nt_user_token
= NULL
;
382 conn
->read_only
= lp_readonly(conn
->service
);
383 conn
->admin_user
= False
;
386 * If force user is true, then store the
387 * given userid and also the groups
388 * of the user we're forcing.
391 if (*lp_force_user(snum
)) {
392 struct passwd
*pass2
;
394 pstrcpy(fuser
,lp_force_user(snum
));
396 /* Allow %S to be used by force user. */
397 pstring_sub(fuser
,"%S",lp_servicename(snum
));
399 pass2
= (struct passwd
*)Get_Pwnam(fuser
);
401 conn
->uid
= pass2
->pw_uid
;
402 conn
->gid
= pass2
->pw_gid
;
403 string_set(&conn
->user
,pass2
->pw_name
);
404 fstrcpy(user
,pass2
->pw_name
);
405 conn
->force_user
= True
;
406 DEBUG(3,("Forced user %s\n",user
));
408 DEBUG(1,("Couldn't find user %s\n",fuser
));
410 *status
= NT_STATUS_NO_SUCH_USER
;
417 * If force group is true, then override
418 * any groupid stored for the connecting user.
421 if (*lp_force_group(snum
)) {
425 BOOL user_must_be_member
= False
;
427 pstrcpy(tmp_gname
,lp_force_group(snum
));
429 if (tmp_gname
[0] == '+') {
430 user_must_be_member
= True
;
431 /* even now, tmp_gname is null terminated */
432 pstrcpy(gname
,&tmp_gname
[1]);
434 pstrcpy(gname
,tmp_gname
);
436 /* default service may be a group name */
437 pstring_sub(gname
,"%S",lp_servicename(snum
));
438 gid
= nametogid(gname
);
440 if (gid
!= (gid_t
)-1) {
443 * If the user has been forced and the forced group starts
444 * with a '+', then we only set the group to be the forced
445 * group if the forced user is a member of that group.
446 * Otherwise, the meaning of the '+' would be ignored.
448 if (conn
->force_user
&& user_must_be_member
) {
449 if (user_in_group_list( user
, gname
, NULL
, 0)) {
451 DEBUG(3,("Forced group %s for member %s\n",gname
,user
));
455 DEBUG(3,("Forced group %s\n",gname
));
457 conn
->force_group
= True
;
459 DEBUG(1,("Couldn't find group %s\n",gname
));
461 *status
= NT_STATUS_NO_SUCH_GROUP
;
465 #endif /* HAVE_GETGRNAM */
469 pstrcpy(s
,lp_pathname(snum
));
470 standard_sub_conn(conn
,s
,sizeof(s
));
471 string_set(&conn
->connectpath
,s
);
472 DEBUG(3,("Connect path is '%s' for service [%s]\n",s
, lp_servicename(snum
)));
475 if (conn
->force_user
|| conn
->force_group
) {
477 /* groups stuff added by ih */
481 /* Find all the groups this uid is in and
482 store them. Used by change_to_user() */
483 initialise_groups(conn
->user
, conn
->uid
, conn
->gid
);
484 get_current_groups(conn
->gid
, &conn
->ngroups
,&conn
->groups
);
486 conn
->nt_user_token
= create_nt_token(conn
->uid
, conn
->gid
,
487 conn
->ngroups
, conn
->groups
,
492 * New code to check if there's a share security descripter
493 * added from NT server manager. This is done after the
494 * smb.conf checks are done as we need a uid and token. JRA.
499 BOOL can_write
= share_access_check(conn
, snum
, vuser
, FILE_WRITE_DATA
);
502 if (!share_access_check(conn
, snum
, vuser
, FILE_READ_DATA
)) {
503 /* No access, read or write. */
504 DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
505 lp_servicename(snum
)));
507 *status
= NT_STATUS_ACCESS_DENIED
;
510 conn
->read_only
= True
;
514 /* Initialise VFS function pointers */
516 if (!smbd_vfs_init(conn
)) {
517 DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(SNUM(conn
))));
519 *status
= NT_STATUS_BAD_NETWORK_NAME
;
524 * If widelinks are disallowed we need to canonicalise the
525 * connect path here to ensure we don't have any symlinks in
526 * the connectpath. We will be checking all paths on this
527 * connection are below this directory. We must do this after
528 * the VFS init as we depend on the realpath() pointer in the vfs table. JRA.
530 if (!lp_widelinks(snum
)) {
532 pstrcpy(s
,conn
->connectpath
);
533 canonicalize_path(conn
, s
);
534 string_set(&conn
->connectpath
,s
);
537 /* ROOT Activities: */
538 /* check number of connections */
539 if (!claim_connection(conn
,
540 lp_servicename(SNUM(conn
)),
541 lp_max_connections(SNUM(conn
)),
543 DEBUG(1,("too many connections - rejected\n"));
545 *status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
549 /* Preexecs are done here as they might make the dir we are to ChDir to below */
550 /* execute any "root preexec = " line */
551 if (*lp_rootpreexec(SNUM(conn
))) {
554 pstrcpy(cmd
,lp_rootpreexec(SNUM(conn
)));
555 standard_sub_conn(conn
,cmd
,sizeof(cmd
));
556 DEBUG(5,("cmd=%s\n",cmd
));
557 ret
= smbrun(cmd
,NULL
);
558 if (ret
!= 0 && lp_rootpreexec_close(SNUM(conn
))) {
559 DEBUG(1,("root preexec gave %d - failing connection\n", ret
));
560 yield_connection(conn
, lp_servicename(SNUM(conn
)));
562 *status
= NT_STATUS_ACCESS_DENIED
;
567 /* USER Activites: */
568 if (!change_to_user(conn
, conn
->vuid
)) {
569 /* No point continuing if they fail the basic checks */
570 DEBUG(0,("Can't become connected user!\n"));
572 *status
= NT_STATUS_LOGON_FAILURE
;
576 /* Remember that a different vuid can connect later without these checks... */
578 /* Preexecs are done here as they might make the dir we are to ChDir to below */
579 /* execute any "preexec = " line */
580 if (*lp_preexec(SNUM(conn
))) {
583 pstrcpy(cmd
,lp_preexec(SNUM(conn
)));
584 standard_sub_conn(conn
,cmd
,sizeof(cmd
));
585 ret
= smbrun(cmd
,NULL
);
586 if (ret
!= 0 && lp_preexec_close(SNUM(conn
))) {
587 DEBUG(1,("preexec gave %d - failing connection\n", ret
));
588 change_to_root_user();
589 yield_connection(conn
, lp_servicename(SNUM(conn
)));
591 *status
= NT_STATUS_ACCESS_DENIED
;
596 #ifdef WITH_FAKE_KASERVER
597 if (lp_afs_share(SNUM(conn
))) {
602 #if CHECK_PATH_ON_TCONX
603 /* win2000 does not check the permissions on the directory
604 during the tree connect, instead relying on permission
605 check during individual operations. To match this behaviour
606 I have disabled this chdir check (tridge) */
607 if (vfs_ChDir(conn
,conn
->connectpath
) != 0) {
608 DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n",
609 get_remote_machine_name(), conn
->client_address
,
610 conn
->connectpath
,strerror(errno
)));
611 change_to_root_user();
612 yield_connection(conn
, lp_servicename(SNUM(conn
)));
614 *status
= NT_STATUS_BAD_NETWORK_NAME
;
618 /* the alternative is just to check the directory exists */
619 if (stat(conn
->connectpath
, &st
) != 0 || !S_ISDIR(st
.st_mode
)) {
620 DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn
->connectpath
, lp_servicename(SNUM(conn
))));
621 change_to_root_user();
622 yield_connection(conn
, lp_servicename(SNUM(conn
)));
624 *status
= NT_STATUS_BAD_NETWORK_NAME
;
629 string_set(&conn
->origpath
,conn
->connectpath
);
631 #if SOFTLINK_OPTIMISATION
632 /* resolve any soft links early if possible */
633 if (vfs_ChDir(conn
,conn
->connectpath
) == 0) {
635 pstrcpy(s
,conn
->connectpath
);
637 string_set(&conn
->connectpath
,s
);
638 vfs_ChDir(conn
,conn
->connectpath
);
643 * Print out the 'connected as' stuff here as we need
644 * to know the effective uid and gid we will be using
645 * (at least initially).
648 if( DEBUGLVL( IS_IPC(conn
) ? 3 : 1 ) ) {
649 dbgtext( "%s (%s) ", get_remote_machine_name(), conn
->client_address
);
650 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
651 dbgtext( "connect to service %s ", lp_servicename(SNUM(conn
)) );
652 dbgtext( "initially as user %s ", user
);
653 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
654 dbgtext( "(pid %d)\n", (int)sys_getpid() );
657 /* Add veto/hide lists */
658 if (!IS_IPC(conn
) && !IS_PRINT(conn
)) {
659 set_namearray( &conn
->veto_list
, lp_veto_files(SNUM(conn
)));
660 set_namearray( &conn
->hide_list
, lp_hide_files(SNUM(conn
)));
661 set_namearray( &conn
->veto_oplock_list
, lp_veto_oplocks(SNUM(conn
)));
664 /* Invoke VFS make connection hook */
666 if (SMB_VFS_CONNECT(conn
, lp_servicename(snum
), user
) < 0) {
667 DEBUG(0,("make_connection: VFS make connection failed!\n"));
668 change_to_root_user();
670 *status
= NT_STATUS_UNSUCCESSFUL
;
674 /* we've finished with the user stuff - go back to root */
675 change_to_root_user();
680 /***************************************************************************************
681 Simple wrapper function for make_connection() to include a call to
683 **************************************************************************************/
685 connection_struct
*make_connection_with_chdir(const char *service_in
, DATA_BLOB password
,
686 const char *dev
, uint16 vuid
, NTSTATUS
*status
)
688 connection_struct
*conn
= NULL
;
690 conn
= make_connection(service_in
, password
, dev
, vuid
, status
);
693 * make_connection() does not change the directory for us any more
694 * so we have to do it as a separate step --jerry
697 if ( conn
&& vfs_ChDir(conn
,conn
->connectpath
) != 0 ) {
698 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
699 conn
->connectpath
,strerror(errno
)));
700 yield_connection(conn
, lp_servicename(SNUM(conn
)));
702 *status
= NT_STATUS_UNSUCCESSFUL
;
709 /****************************************************************************
710 Make a connection to a service.
713 ****************************************************************************/
715 connection_struct
*make_connection(const char *service_in
, DATA_BLOB password
,
716 const char *pdev
, uint16 vuid
, NTSTATUS
*status
)
719 user_struct
*vuser
= NULL
;
726 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
727 if (!non_root_mode() && (euid
= geteuid()) != 0) {
728 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid
));
729 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
732 if(lp_security() != SEC_SHARE
) {
733 vuser
= get_valid_user_struct(vuid
);
735 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
736 *status
= NT_STATUS_ACCESS_DENIED
;
741 /* Logic to try and connect to the correct [homes] share, preferably without too many
742 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
743 share name isn't the same as unix username.
745 The snum of the homes share is stored on the vuser at session setup time.
748 if (strequal(service_in
,HOMES_NAME
)) {
749 if(lp_security() != SEC_SHARE
) {
750 DATA_BLOB no_pw
= data_blob(NULL
, 0);
751 if (vuser
->homes_snum
== -1) {
752 DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n"));
753 *status
= NT_STATUS_BAD_NETWORK_NAME
;
756 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
757 return make_connection_snum(vuser
->homes_snum
,
761 /* Security = share. Try with current_user_info.smb_name
762 * as the username. */
763 if (*current_user_info
.smb_name
) {
764 fstring unix_username
;
765 fstrcpy(unix_username
,
766 current_user_info
.smb_name
);
767 map_username(unix_username
);
768 snum
= find_service(unix_username
);
771 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in
));
772 return make_connection_snum(snum
, NULL
,
777 } else if ((lp_security() != SEC_SHARE
) && (vuser
->homes_snum
!= -1)
778 && strequal(service_in
, lp_servicename(vuser
->homes_snum
))) {
779 DATA_BLOB no_pw
= data_blob(NULL
, 0);
780 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in
));
781 return make_connection_snum(vuser
->homes_snum
,
786 fstrcpy(service
, service_in
);
790 snum
= find_service(service
);
793 if (strequal(service
,"IPC$") || strequal(service
,"ADMIN$")) {
794 DEBUG(3,("refusing IPC connection to %s\n", service
));
795 *status
= NT_STATUS_ACCESS_DENIED
;
799 DEBUG(0,("%s (%s) couldn't find service %s\n",
800 get_remote_machine_name(), client_addr(), service
));
801 *status
= NT_STATUS_BAD_NETWORK_NAME
;
805 /* Handle non-Dfs clients attempting connections to msdfs proxy */
806 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum
) != '\0')) {
807 DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n",
808 service
, lp_msdfs_proxy(snum
)));
809 *status
= NT_STATUS_BAD_NETWORK_NAME
;
813 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
815 return make_connection_snum(snum
, vuser
,
820 /****************************************************************************
822 ****************************************************************************/
823 void close_cnum(connection_struct
*conn
, uint16 vuid
)
826 pipe_close_conn(conn
);
828 file_close_conn(conn
);
829 dptr_closecnum(conn
);
832 change_to_root_user();
834 DEBUG(IS_IPC(conn
)?3:1, ("%s (%s) closed connection to service %s\n",
835 get_remote_machine_name(),conn
->client_address
,
836 lp_servicename(SNUM(conn
))));
838 /* Call VFS disconnect hook */
839 SMB_VFS_DISCONNECT(conn
);
841 yield_connection(conn
, lp_servicename(SNUM(conn
)));
843 /* make sure we leave the directory available for unmount */
844 vfs_ChDir(conn
, "/");
846 /* execute any "postexec = " line */
847 if (*lp_postexec(SNUM(conn
)) &&
848 change_to_user(conn
, vuid
)) {
850 pstrcpy(cmd
,lp_postexec(SNUM(conn
)));
851 standard_sub_conn(conn
,cmd
,sizeof(cmd
));
853 change_to_root_user();
856 change_to_root_user();
857 /* execute any "root postexec = " line */
858 if (*lp_rootpostexec(SNUM(conn
))) {
860 pstrcpy(cmd
,lp_rootpostexec(SNUM(conn
)));
861 standard_sub_conn(conn
,cmd
,sizeof(cmd
));
868 /****************************************************************************
869 Remove stale printers
870 ****************************************************************************/
872 void remove_stale_printers( void )
874 int snum
, iNumServices
, printersServiceNum
;
877 iNumServices
= lp_numservices();
878 printersServiceNum
= lp_servicenumber( PRINTERS_NAME
);
879 for( snum
= 0; snum
< iNumServices
; snum
++) {
880 /* Never remove PRINTERS_NAME */
881 if ( snum
== printersServiceNum
)
883 pname
= lp_printername( snum
);
884 /* Is snum a print service and still in the printing subsystem? */
885 if ( lp_print_ok( snum
) && !pcap_printername_ok( pname
, NULL
)) {
886 DEBUG( 3, ( "Removing printer: %s\n", pname
));
887 lp_killservice( snum
);