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 char magic_char;
24 extern struct timeval smb_last_time;
25 extern userdom_struct current_user_info;
28 /****************************************************************************
29 Load parameters specific to a connection/service.
30 ****************************************************************************/
32 BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
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 switch (lp_casesensitive(snum)) {
66 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
67 enum remote_arch_types ra_type = get_remote_arch();
68 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
69 /* Client can't support per-packet case sensitive pathnames. */
70 conn->case_sensitive = False;
72 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
77 conn->case_sensitive = True;
80 conn->case_sensitive = False;
83 magic_char = lp_magicchar(snum);
87 /****************************************************************************
88 Add a home service. Returns the new service number or -1 if fail.
89 ****************************************************************************/
91 int add_home_service(const char *service, const char *username, const char *homedir)
95 if (!service || !homedir)
98 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
102 * If this is a winbindd provided username, remove
103 * the domain component before adding the service.
104 * Log a warning if the "path=" parameter does not
105 * include any macros.
109 const char *p = strchr(service,*lp_winbind_separator());
111 /* We only want the 'user' part of the string */
117 if (!lp_add_home(service, iHomeService, username, homedir)) {
121 return lp_servicenumber(service);
127 * Find a service entry.
129 * @param service is modified (to canonical form??)
132 int find_service(fstring service)
136 all_string_sub(service,"\\","/",0);
138 iService = lp_servicenumber(service);
140 /* now handle the special case of a home directory */
142 char *phome_dir = get_user_home_dir(service);
146 * Try mapping the servicename, it may
147 * be a Windows to unix mapped user name.
149 if(map_username(service))
150 phome_dir = get_user_home_dir(service);
153 DEBUG(3,("checking for home directory %s gave %s\n",service,
154 phome_dir?phome_dir:"(NULL)"));
156 iService = add_home_service(service,service /* 'username' */, phome_dir);
159 /* If we still don't have a service, attempt to add it as a printer. */
163 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
164 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
165 if (pcap_printername_ok(service)) {
166 DEBUG(3,("%s is a valid printer name\n", service));
167 DEBUG(3,("adding %s as a printer service\n", service));
168 lp_add_printer(service, iPrinterService);
169 iService = lp_servicenumber(service);
171 DEBUG(0,("failed to add %s as a printer service!\n", service));
174 DEBUG(3,("%s is not a valid printer name\n", service));
179 /* Check for default vfs service? Unsure whether to implement this */
183 /* just possibly it's a default service? */
185 char *pdefservice = lp_defaultservice();
186 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
188 * We need to do a local copy here as lp_defaultservice()
189 * returns one of the rotating lp_string buffers that
190 * could get overwritten by the recursive find_service() call
191 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
194 pstrcpy(defservice, pdefservice);
195 iService = find_service(defservice);
197 all_string_sub(service, "_","/",0);
198 iService = lp_add_service(service, iService);
204 if (!VALID_SNUM(iService)) {
205 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
211 DEBUG(3,("find_service() failed to find service %s\n", service));
217 /****************************************************************************
218 do some basic sainity checks on the share.
219 This function modifies dev, ecode.
220 ****************************************************************************/
222 static NTSTATUS share_sanity_checks(int snum, fstring dev)
225 if (!lp_snum_ok(snum) ||
226 !check_access(smbd_server_fd(),
227 lp_hostsallow(snum), lp_hostsdeny(snum))) {
228 return NT_STATUS_ACCESS_DENIED;
231 if (dev[0] == '?' || !dev[0]) {
232 if (lp_print_ok(snum)) {
233 fstrcpy(dev,"LPT1:");
234 } else if (strequal(lp_fstype(snum), "IPC")) {
243 if (lp_print_ok(snum)) {
244 if (!strequal(dev, "LPT1:")) {
245 return NT_STATUS_BAD_DEVICE_TYPE;
247 } else if (strequal(lp_fstype(snum), "IPC")) {
248 if (!strequal(dev, "IPC")) {
249 return NT_STATUS_BAD_DEVICE_TYPE;
251 } else if (!strequal(dev, "A:")) {
252 return NT_STATUS_BAD_DEVICE_TYPE;
255 /* Behave as a printer if we are supposed to */
256 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
257 fstrcpy(dev, "LPT1:");
263 /****************************************************************************
264 Make a connection, given the snum to connect to, and the vuser of the
265 connecting user if appropriate.
266 ****************************************************************************/
268 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
270 const char *pdev, NTSTATUS *status)
272 struct passwd *pass = NULL;
274 connection_struct *conn;
283 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
289 DEBUG(0,("Couldn't find free connection.\n"));
290 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
294 if (lp_guest_only(snum)) {
295 const char *guestname = lp_guestaccount();
297 pass = getpwnam_alloc(guestname);
299 DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname));
301 *status = NT_STATUS_NO_SUCH_USER;
304 fstrcpy(user,pass->pw_name);
305 conn->force_user = True;
306 conn->uid = pass->pw_uid;
307 conn->gid = pass->pw_gid;
308 string_set(&conn->user,pass->pw_name);
310 DEBUG(3,("Guest only user %s\n",user));
313 if (!lp_guest_ok(snum)) {
314 DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum)));
316 *status = NT_STATUS_ACCESS_DENIED;
320 if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) {
321 DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum)));
323 *status = NT_STATUS_ACCESS_DENIED;
327 conn->vuid = vuser->vuid;
328 conn->uid = vuser->uid;
329 conn->gid = vuser->gid;
330 string_set(&conn->user,vuser->user.unix_name);
331 fstrcpy(user,vuser->user.unix_name);
332 guest = vuser->guest;
333 } else if (lp_security() == SEC_SHARE) {
334 /* add it as a possible user name if we
335 are in share mode security */
336 add_session_user(lp_servicename(snum));
337 /* shall we let them in? */
338 if (!authorise_login(snum,user,password,&guest)) {
339 DEBUG( 2, ( "Invalid username/password for [%s]\n",
340 lp_servicename(snum)) );
342 *status = NT_STATUS_WRONG_PASSWORD;
345 pass = Get_Pwnam(user);
346 conn->force_user = True;
347 conn->uid = pass->pw_uid;
348 conn->gid = pass->pw_gid;
349 string_set(&conn->user, pass->pw_name);
350 fstrcpy(user, pass->pw_name);
353 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
355 *status = NT_STATUS_ACCESS_DENIED;
359 add_session_user(user);
361 safe_strcpy(conn->client_address, client_addr(),
362 sizeof(conn->client_address)-1);
363 conn->num_files_open = 0;
364 conn->lastused = time(NULL);
365 conn->service = snum;
367 conn->printer = (strncmp(dev,"LPT",3) == 0);
368 conn->ipc = ((strncmp(dev,"IPC",3) == 0) || strequal(dev,"ADMIN$"));
371 /* Case options for the share. */
372 if (lp_casesensitive(snum) == Auto) {
373 /* We will be setting this per packet. Set to be case insensitive for now. */
374 conn->case_sensitive = False;
376 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
379 conn->case_preserve = lp_preservecase(snum);
380 conn->short_case_preserve = lp_shortpreservecase(snum);
382 conn->veto_list = NULL;
383 conn->hide_list = NULL;
384 conn->veto_oplock_list = NULL;
385 string_set(&conn->dirpath,"");
386 string_set(&conn->user,user);
387 conn->nt_user_token = NULL;
389 conn->read_only = lp_readonly(conn->service);
390 conn->admin_user = False;
393 * If force user is true, then store the
394 * given userid and also the groups
395 * of the user we're forcing.
398 if (*lp_force_user(snum)) {
399 struct passwd *pass2;
401 pstrcpy(fuser,lp_force_user(snum));
403 /* Allow %S to be used by force user. */
404 pstring_sub(fuser,"%S",lp_servicename(snum));
406 pass2 = (struct passwd *)Get_Pwnam(fuser);
408 conn->uid = pass2->pw_uid;
409 conn->gid = pass2->pw_gid;
410 string_set(&conn->user,pass2->pw_name);
411 fstrcpy(user,pass2->pw_name);
412 conn->force_user = True;
413 DEBUG(3,("Forced user %s\n",user));
415 DEBUG(1,("Couldn't find user %s\n",fuser));
417 *status = NT_STATUS_NO_SUCH_USER;
424 * If force group is true, then override
425 * any groupid stored for the connecting user.
428 if (*lp_force_group(snum)) {
432 BOOL user_must_be_member = False;
434 pstrcpy(tmp_gname,lp_force_group(snum));
436 if (tmp_gname[0] == '+') {
437 user_must_be_member = True;
438 /* even now, tmp_gname is null terminated */
439 pstrcpy(gname,&tmp_gname[1]);
441 pstrcpy(gname,tmp_gname);
443 /* default service may be a group name */
444 pstring_sub(gname,"%S",lp_servicename(snum));
445 gid = nametogid(gname);
447 if (gid != (gid_t)-1) {
450 * If the user has been forced and the forced group starts
451 * with a '+', then we only set the group to be the forced
452 * group if the forced user is a member of that group.
453 * Otherwise, the meaning of the '+' would be ignored.
455 if (conn->force_user && user_must_be_member) {
456 if (user_in_group_list( user, gname, NULL, 0)) {
458 DEBUG(3,("Forced group %s for member %s\n",gname,user));
462 DEBUG(3,("Forced group %s\n",gname));
464 conn->force_group = True;
466 DEBUG(1,("Couldn't find group %s\n",gname));
468 *status = NT_STATUS_NO_SUCH_GROUP;
472 #endif /* HAVE_GETGRNAM */
476 pstrcpy(s,lp_pathname(snum));
477 standard_sub_conn(conn,s,sizeof(s));
478 string_set(&conn->connectpath,s);
479 DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
482 if (conn->force_user || conn->force_group) {
484 /* groups stuff added by ih */
488 /* Find all the groups this uid is in and
489 store them. Used by change_to_user() */
490 initialise_groups(conn->user, conn->uid, conn->gid);
491 get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
493 conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
494 conn->ngroups, conn->groups,
499 * New code to check if there's a share security descripter
500 * added from NT server manager. This is done after the
501 * smb.conf checks are done as we need a uid and token. JRA.
506 BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA);
509 if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
510 /* No access, read or write. */
511 DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
512 lp_servicename(snum)));
514 *status = NT_STATUS_ACCESS_DENIED;
517 conn->read_only = True;
521 /* Initialise VFS function pointers */
523 if (!smbd_vfs_init(conn)) {
524 DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum)));
526 *status = NT_STATUS_BAD_NETWORK_NAME;
531 * If widelinks are disallowed we need to canonicalise the
532 * connect path here to ensure we don't have any symlinks in
533 * the connectpath. We will be checking all paths on this
534 * connection are below this directory. We must do this after
535 * the VFS init as we depend on the realpath() pointer in the vfs table. JRA.
537 if (!lp_widelinks(snum)) {
539 pstrcpy(s,conn->connectpath);
540 canonicalize_path(conn, s);
541 string_set(&conn->connectpath,s);
544 /* ROOT Activities: */
545 /* check number of connections */
546 if (!claim_connection(conn,
547 lp_servicename(snum),
548 lp_max_connections(snum),
550 DEBUG(1,("too many connections - rejected\n"));
552 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
556 /* Preexecs are done here as they might make the dir we are to ChDir to below */
557 /* execute any "root preexec = " line */
558 if (*lp_rootpreexec(snum)) {
561 pstrcpy(cmd,lp_rootpreexec(snum));
562 standard_sub_conn(conn,cmd,sizeof(cmd));
563 DEBUG(5,("cmd=%s\n",cmd));
564 ret = smbrun(cmd,NULL);
565 if (ret != 0 && lp_rootpreexec_close(snum)) {
566 DEBUG(1,("root preexec gave %d - failing connection\n", ret));
567 yield_connection(conn, lp_servicename(snum));
569 *status = NT_STATUS_ACCESS_DENIED;
574 /* USER Activites: */
575 if (!change_to_user(conn, conn->vuid)) {
576 /* No point continuing if they fail the basic checks */
577 DEBUG(0,("Can't become connected user!\n"));
578 yield_connection(conn, lp_servicename(snum));
580 *status = NT_STATUS_LOGON_FAILURE;
584 /* Remember that a different vuid can connect later without these checks... */
586 /* Preexecs are done here as they might make the dir we are to ChDir to below */
587 /* execute any "preexec = " line */
588 if (*lp_preexec(snum)) {
591 pstrcpy(cmd,lp_preexec(snum));
592 standard_sub_conn(conn,cmd,sizeof(cmd));
593 ret = smbrun(cmd,NULL);
594 if (ret != 0 && lp_preexec_close(snum)) {
595 DEBUG(1,("preexec gave %d - failing connection\n", ret));
596 change_to_root_user();
597 yield_connection(conn, lp_servicename(snum));
599 *status = NT_STATUS_ACCESS_DENIED;
604 #ifdef WITH_FAKE_KASERVER
605 if (lp_afs_share(snum)) {
610 /* win2000 does not check the permissions on the directory
611 during the tree connect, instead relying on permission
612 check during individual operations. To match this behaviour
613 I have disabled this chdir check (tridge) */
614 /* the alternative is just to check the directory exists */
615 if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
616 DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum)));
617 change_to_root_user();
618 yield_connection(conn, lp_servicename(snum));
620 *status = NT_STATUS_BAD_NETWORK_NAME;
624 string_set(&conn->origpath,conn->connectpath);
626 #if SOFTLINK_OPTIMISATION
627 /* resolve any soft links early if possible */
628 if (vfs_ChDir(conn,conn->connectpath) == 0) {
630 pstrcpy(s,conn->connectpath);
632 string_set(&conn->connectpath,s);
633 vfs_ChDir(conn,conn->connectpath);
638 * Print out the 'connected as' stuff here as we need
639 * to know the effective uid and gid we will be using
640 * (at least initially).
643 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
644 dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
645 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
646 dbgtext( "connect to service %s ", lp_servicename(snum) );
647 dbgtext( "initially as user %s ", user );
648 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
649 dbgtext( "(pid %d)\n", (int)sys_getpid() );
652 /* Add veto/hide lists */
653 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
654 set_namearray( &conn->veto_list, lp_veto_files(snum));
655 set_namearray( &conn->hide_list, lp_hide_files(snum));
656 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
659 /* Invoke VFS make connection hook */
661 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
662 DEBUG(0,("make_connection: VFS make connection failed!\n"));
663 change_to_root_user();
664 yield_connection(conn, lp_servicename(snum));
666 *status = NT_STATUS_UNSUCCESSFUL;
670 /* we've finished with the user stuff - go back to root */
671 change_to_root_user();
676 /***************************************************************************************
677 Simple wrapper function for make_connection() to include a call to
679 **************************************************************************************/
681 connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
682 const char *dev, uint16 vuid, NTSTATUS *status)
684 connection_struct *conn = NULL;
686 conn = make_connection(service_in, password, dev, vuid, status);
689 * make_connection() does not change the directory for us any more
690 * so we have to do it as a separate step --jerry
693 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
694 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
695 conn->connectpath,strerror(errno)));
696 yield_connection(conn, lp_servicename(SNUM(conn)));
698 *status = NT_STATUS_UNSUCCESSFUL;
705 /****************************************************************************
706 Make a connection to a service.
709 ****************************************************************************/
711 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
712 const char *pdev, uint16 vuid, NTSTATUS *status)
715 user_struct *vuser = NULL;
722 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
723 if (!non_root_mode() && (euid = geteuid()) != 0) {
724 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
725 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
728 if(lp_security() != SEC_SHARE) {
729 vuser = get_valid_user_struct(vuid);
731 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
732 *status = NT_STATUS_ACCESS_DENIED;
737 /* Logic to try and connect to the correct [homes] share, preferably without too many
738 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
739 share name isn't the same as unix username.
741 The snum of the homes share is stored on the vuser at session setup time.
744 if (strequal(service_in,HOMES_NAME)) {
745 if(lp_security() != SEC_SHARE) {
746 DATA_BLOB no_pw = data_blob(NULL, 0);
747 if (vuser->homes_snum == -1) {
748 DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n"));
749 *status = NT_STATUS_BAD_NETWORK_NAME;
752 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
753 return make_connection_snum(vuser->homes_snum,
757 /* Security = share. Try with current_user_info.smb_name
758 * as the username. */
759 if (*current_user_info.smb_name) {
760 fstring unix_username;
761 fstrcpy(unix_username,
762 current_user_info.smb_name);
763 map_username(unix_username);
764 snum = find_service(unix_username);
767 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
768 return make_connection_snum(snum, NULL,
773 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
774 && strequal(service_in, lp_servicename(vuser->homes_snum))) {
775 DATA_BLOB no_pw = data_blob(NULL, 0);
776 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
777 return make_connection_snum(vuser->homes_snum,
782 fstrcpy(service, service_in);
786 snum = find_service(service);
789 if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) {
790 DEBUG(3,("refusing IPC connection to %s\n", service));
791 *status = NT_STATUS_ACCESS_DENIED;
795 DEBUG(0,("%s (%s) couldn't find service %s\n",
796 get_remote_machine_name(), client_addr(), service));
797 *status = NT_STATUS_BAD_NETWORK_NAME;
801 /* Handle non-Dfs clients attempting connections to msdfs proxy */
802 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
803 DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n",
804 service, lp_msdfs_proxy(snum)));
805 *status = NT_STATUS_BAD_NETWORK_NAME;
809 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
811 return make_connection_snum(snum, vuser,
816 /****************************************************************************
818 ****************************************************************************/
820 void close_cnum(connection_struct *conn, uint16 vuid)
823 pipe_close_conn(conn);
825 file_close_conn(conn);
826 dptr_closecnum(conn);
829 change_to_root_user();
831 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
832 get_remote_machine_name(),conn->client_address,
833 lp_servicename(SNUM(conn))));
835 /* Call VFS disconnect hook */
836 SMB_VFS_DISCONNECT(conn);
838 yield_connection(conn, lp_servicename(SNUM(conn)));
840 /* make sure we leave the directory available for unmount */
841 vfs_ChDir(conn, "/");
843 /* execute any "postexec = " line */
844 if (*lp_postexec(SNUM(conn)) &&
845 change_to_user(conn, vuid)) {
847 pstrcpy(cmd,lp_postexec(SNUM(conn)));
848 standard_sub_conn(conn,cmd,sizeof(cmd));
850 change_to_root_user();
853 change_to_root_user();
854 /* execute any "root postexec = " line */
855 if (*lp_rootpostexec(SNUM(conn))) {
857 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
858 standard_sub_conn(conn,cmd,sizeof(cmd));