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;
26 /****************************************************************************
27 Load parameters specific to a connection/service.
28 ****************************************************************************/
30 BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
32 static connection_struct *last_conn;
33 static uint16 last_flags;
41 conn->lastused = smb_last_time.tv_sec;
46 vfs_ChDir(conn,conn->connectpath) != 0 &&
47 vfs_ChDir(conn,conn->origpath) != 0) {
48 DEBUG(0,("chdir (%s) failed\n",
53 if ((conn == last_conn) && (last_flags == flags)) {
60 /* Obey the client case sensitivity requests - only for clients that support it. */
61 switch (lp_casesensitive(snum)) {
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);
75 conn->case_sensitive = True;
78 conn->case_sensitive = False;
84 /****************************************************************************
85 Add a home service. Returns the new service number or -1 if fail.
86 ****************************************************************************/
88 int add_home_service(const char *service, const char *username, const char *homedir)
92 if (!service || !homedir)
95 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
99 * If this is a winbindd provided username, remove
100 * the domain component before adding the service.
101 * Log a warning if the "path=" parameter does not
102 * include any macros.
106 const char *p = strchr(service,*lp_winbind_separator());
108 /* We only want the 'user' part of the string */
114 if (!lp_add_home(service, iHomeService, username, homedir)) {
118 return lp_servicenumber(service);
124 * Find a service entry.
126 * @param service is modified (to canonical form??)
129 int find_service(fstring service)
133 all_string_sub(service,"\\","/",0);
135 iService = lp_servicenumber(service);
137 /* now handle the special case of a home directory */
139 char *phome_dir = get_user_home_dir(service);
143 * Try mapping the servicename, it may
144 * be a Windows to unix mapped user name.
146 if(map_username(service))
147 phome_dir = get_user_home_dir(service);
150 DEBUG(3,("checking for home directory %s gave %s\n",service,
151 phome_dir?phome_dir:"(NULL)"));
153 iService = add_home_service(service,service /* 'username' */, phome_dir);
156 /* If we still don't have a service, attempt to add it as a printer. */
160 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
161 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
162 if (pcap_printername_ok(service)) {
163 DEBUG(3,("%s is a valid printer name\n", service));
164 DEBUG(3,("adding %s as a printer service\n", service));
165 lp_add_printer(service, iPrinterService);
166 iService = lp_servicenumber(service);
168 DEBUG(0,("failed to add %s as a printer service!\n", service));
171 DEBUG(3,("%s is not a valid printer name\n", service));
176 /* Check for default vfs service? Unsure whether to implement this */
180 /* just possibly it's a default service? */
182 char *pdefservice = lp_defaultservice();
183 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
185 * We need to do a local copy here as lp_defaultservice()
186 * returns one of the rotating lp_string buffers that
187 * could get overwritten by the recursive find_service() call
188 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
191 pstrcpy(defservice, pdefservice);
192 iService = find_service(defservice);
194 all_string_sub(service, "_","/",0);
195 iService = lp_add_service(service, iService);
201 if (!VALID_SNUM(iService)) {
202 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
208 DEBUG(3,("find_service() failed to find service %s\n", service));
214 /****************************************************************************
215 do some basic sainity checks on the share.
216 This function modifies dev, ecode.
217 ****************************************************************************/
219 static NTSTATUS share_sanity_checks(int snum, fstring dev)
222 if (!lp_snum_ok(snum) ||
223 !check_access(smbd_server_fd(),
224 lp_hostsallow(snum), lp_hostsdeny(snum))) {
225 return NT_STATUS_ACCESS_DENIED;
228 if (dev[0] == '?' || !dev[0]) {
229 if (lp_print_ok(snum)) {
230 fstrcpy(dev,"LPT1:");
231 } else if (strequal(lp_fstype(snum), "IPC")) {
240 if (lp_print_ok(snum)) {
241 if (!strequal(dev, "LPT1:")) {
242 return NT_STATUS_BAD_DEVICE_TYPE;
244 } else if (strequal(lp_fstype(snum), "IPC")) {
245 if (!strequal(dev, "IPC")) {
246 return NT_STATUS_BAD_DEVICE_TYPE;
248 } else if (!strequal(dev, "A:")) {
249 return NT_STATUS_BAD_DEVICE_TYPE;
252 /* Behave as a printer if we are supposed to */
253 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
254 fstrcpy(dev, "LPT1:");
260 /****************************************************************************
261 Make a connection, given the snum to connect to, and the vuser of the
262 connecting user if appropriate.
263 ****************************************************************************/
265 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
267 const char *pdev, NTSTATUS *status)
269 struct passwd *pass = NULL;
271 connection_struct *conn;
280 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
286 DEBUG(0,("Couldn't find free connection.\n"));
287 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
291 if (lp_guest_only(snum)) {
292 const char *guestname = lp_guestaccount();
294 pass = getpwnam_alloc(guestname);
296 DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname));
298 *status = NT_STATUS_NO_SUCH_USER;
301 fstrcpy(user,pass->pw_name);
302 conn->force_user = True;
303 conn->uid = pass->pw_uid;
304 conn->gid = pass->pw_gid;
305 string_set(&conn->user,pass->pw_name);
307 DEBUG(3,("Guest only user %s\n",user));
310 if (!lp_guest_ok(snum)) {
311 DEBUG(2, ("guest user (from session setup) not permitted to access this share (%s)\n", lp_servicename(snum)));
313 *status = NT_STATUS_ACCESS_DENIED;
317 if (!user_ok(vuser->user.unix_name, snum, vuser->groups, vuser->n_groups)) {
318 DEBUG(2, ("user '%s' (from session setup) not permitted to access this share (%s)\n", vuser->user.unix_name, lp_servicename(snum)));
320 *status = NT_STATUS_ACCESS_DENIED;
324 conn->vuid = vuser->vuid;
325 conn->uid = vuser->uid;
326 conn->gid = vuser->gid;
327 string_set(&conn->user,vuser->user.unix_name);
328 fstrcpy(user,vuser->user.unix_name);
329 guest = vuser->guest;
330 } else if (lp_security() == SEC_SHARE) {
331 /* add it as a possible user name if we
332 are in share mode security */
333 add_session_user(lp_servicename(snum));
334 /* shall we let them in? */
335 if (!authorise_login(snum,user,password,&guest)) {
336 DEBUG( 2, ( "Invalid username/password for [%s]\n",
337 lp_servicename(snum)) );
339 *status = NT_STATUS_WRONG_PASSWORD;
342 pass = Get_Pwnam(user);
343 conn->force_user = True;
344 conn->uid = pass->pw_uid;
345 conn->gid = pass->pw_gid;
346 string_set(&conn->user, pass->pw_name);
347 fstrcpy(user, pass->pw_name);
350 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
352 *status = NT_STATUS_ACCESS_DENIED;
356 add_session_user(user);
358 safe_strcpy(conn->client_address, client_addr(),
359 sizeof(conn->client_address)-1);
360 conn->num_files_open = 0;
361 conn->lastused = time(NULL);
362 conn->service = snum;
364 conn->printer = (strncmp(dev,"LPT",3) == 0);
365 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) || ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
368 /* Case options for the share. */
369 if (lp_casesensitive(snum) == Auto) {
370 /* We will be setting this per packet. Set to be case insensitive for now. */
371 conn->case_sensitive = False;
373 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
376 conn->case_preserve = lp_preservecase(snum);
377 conn->short_case_preserve = lp_shortpreservecase(snum);
379 conn->veto_list = NULL;
380 conn->hide_list = NULL;
381 conn->veto_oplock_list = NULL;
382 string_set(&conn->dirpath,"");
383 string_set(&conn->user,user);
384 conn->nt_user_token = NULL;
386 conn->read_only = lp_readonly(conn->service);
387 conn->admin_user = False;
390 * If force user is true, then store the
391 * given userid and also the groups
392 * of the user we're forcing.
395 if (*lp_force_user(snum)) {
396 struct passwd *pass2;
398 pstrcpy(fuser,lp_force_user(snum));
400 /* Allow %S to be used by force user. */
401 pstring_sub(fuser,"%S",lp_servicename(snum));
403 pass2 = (struct passwd *)Get_Pwnam(fuser);
405 conn->uid = pass2->pw_uid;
406 conn->gid = pass2->pw_gid;
407 string_set(&conn->user,pass2->pw_name);
408 fstrcpy(user,pass2->pw_name);
409 conn->force_user = True;
410 DEBUG(3,("Forced user %s\n",user));
412 DEBUG(1,("Couldn't find user %s\n",fuser));
414 *status = NT_STATUS_NO_SUCH_USER;
421 * If force group is true, then override
422 * any groupid stored for the connecting user.
425 if (*lp_force_group(snum)) {
429 BOOL user_must_be_member = False;
431 pstrcpy(tmp_gname,lp_force_group(snum));
433 if (tmp_gname[0] == '+') {
434 user_must_be_member = True;
435 /* even now, tmp_gname is null terminated */
436 pstrcpy(gname,&tmp_gname[1]);
438 pstrcpy(gname,tmp_gname);
440 /* default service may be a group name */
441 pstring_sub(gname,"%S",lp_servicename(snum));
442 gid = nametogid(gname);
444 if (gid != (gid_t)-1) {
447 * If the user has been forced and the forced group starts
448 * with a '+', then we only set the group to be the forced
449 * group if the forced user is a member of that group.
450 * Otherwise, the meaning of the '+' would be ignored.
452 if (conn->force_user && user_must_be_member) {
453 if (user_in_group_list( user, gname, NULL, 0)) {
455 DEBUG(3,("Forced group %s for member %s\n",gname,user));
459 DEBUG(3,("Forced group %s\n",gname));
461 conn->force_group = True;
463 DEBUG(1,("Couldn't find group %s\n",gname));
465 *status = NT_STATUS_NO_SUCH_GROUP;
469 #endif /* HAVE_GETGRNAM */
473 pstrcpy(s,lp_pathname(snum));
474 standard_sub_conn(conn,s,sizeof(s));
475 string_set(&conn->connectpath,s);
476 DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
479 if (conn->force_user || conn->force_group) {
481 /* groups stuff added by ih */
485 /* Find all the groups this uid is in and
486 store them. Used by change_to_user() */
487 initialise_groups(conn->user, conn->uid, conn->gid);
488 get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
490 conn->nt_user_token = create_nt_token(conn->uid, conn->gid,
491 conn->ngroups, conn->groups,
496 * New code to check if there's a share security descripter
497 * added from NT server manager. This is done after the
498 * smb.conf checks are done as we need a uid and token. JRA.
503 BOOL can_write = share_access_check(conn, snum, vuser, FILE_WRITE_DATA);
506 if (!share_access_check(conn, snum, vuser, FILE_READ_DATA)) {
507 /* No access, read or write. */
508 DEBUG(0,( "make_connection: connection to %s denied due to security descriptor.\n",
509 lp_servicename(snum)));
511 *status = NT_STATUS_ACCESS_DENIED;
514 conn->read_only = True;
518 /* Initialise VFS function pointers */
520 if (!smbd_vfs_init(conn)) {
521 DEBUG(0, ("vfs_init failed for service %s\n", lp_servicename(snum)));
523 *status = NT_STATUS_BAD_NETWORK_NAME;
528 * If widelinks are disallowed we need to canonicalise the
529 * connect path here to ensure we don't have any symlinks in
530 * the connectpath. We will be checking all paths on this
531 * connection are below this directory. We must do this after
532 * the VFS init as we depend on the realpath() pointer in the vfs table. JRA.
534 if (!lp_widelinks(snum)) {
536 pstrcpy(s,conn->connectpath);
537 canonicalize_path(conn, s);
538 string_set(&conn->connectpath,s);
541 /* ROOT Activities: */
542 /* check number of connections */
543 if (!claim_connection(conn,
544 lp_servicename(snum),
545 lp_max_connections(snum),
547 DEBUG(1,("too many connections - rejected\n"));
549 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
553 /* Preexecs are done here as they might make the dir we are to ChDir to below */
554 /* execute any "root preexec = " line */
555 if (*lp_rootpreexec(snum)) {
558 pstrcpy(cmd,lp_rootpreexec(snum));
559 standard_sub_conn(conn,cmd,sizeof(cmd));
560 DEBUG(5,("cmd=%s\n",cmd));
561 ret = smbrun(cmd,NULL);
562 if (ret != 0 && lp_rootpreexec_close(snum)) {
563 DEBUG(1,("root preexec gave %d - failing connection\n", ret));
564 yield_connection(conn, lp_servicename(snum));
566 *status = NT_STATUS_ACCESS_DENIED;
571 /* USER Activites: */
572 if (!change_to_user(conn, conn->vuid)) {
573 /* No point continuing if they fail the basic checks */
574 DEBUG(0,("Can't become connected user!\n"));
575 yield_connection(conn, lp_servicename(snum));
577 *status = NT_STATUS_LOGON_FAILURE;
581 /* Remember that a different vuid can connect later without these checks... */
583 /* Preexecs are done here as they might make the dir we are to ChDir to below */
584 /* execute any "preexec = " line */
585 if (*lp_preexec(snum)) {
588 pstrcpy(cmd,lp_preexec(snum));
589 standard_sub_conn(conn,cmd,sizeof(cmd));
590 ret = smbrun(cmd,NULL);
591 if (ret != 0 && lp_preexec_close(snum)) {
592 DEBUG(1,("preexec gave %d - failing connection\n", ret));
593 change_to_root_user();
594 yield_connection(conn, lp_servicename(snum));
596 *status = NT_STATUS_ACCESS_DENIED;
601 #ifdef WITH_FAKE_KASERVER
602 if (lp_afs_share(snum)) {
607 /* win2000 does not check the permissions on the directory
608 during the tree connect, instead relying on permission
609 check during individual operations. To match this behaviour
610 I have disabled this chdir check (tridge) */
611 /* the alternative is just to check the directory exists */
612 if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
613 DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(snum)));
614 change_to_root_user();
615 yield_connection(conn, lp_servicename(snum));
617 *status = NT_STATUS_BAD_NETWORK_NAME;
621 string_set(&conn->origpath,conn->connectpath);
623 #if SOFTLINK_OPTIMISATION
624 /* resolve any soft links early if possible */
625 if (vfs_ChDir(conn,conn->connectpath) == 0) {
627 pstrcpy(s,conn->connectpath);
629 string_set(&conn->connectpath,s);
630 vfs_ChDir(conn,conn->connectpath);
635 * Print out the 'connected as' stuff here as we need
636 * to know the effective uid and gid we will be using
637 * (at least initially).
640 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
641 dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
642 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
643 dbgtext( "connect to service %s ", lp_servicename(snum) );
644 dbgtext( "initially as user %s ", user );
645 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
646 dbgtext( "(pid %d)\n", (int)sys_getpid() );
649 /* Add veto/hide lists */
650 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
651 set_namearray( &conn->veto_list, lp_veto_files(snum));
652 set_namearray( &conn->hide_list, lp_hide_files(snum));
653 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
656 /* Invoke VFS make connection hook */
658 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
659 DEBUG(0,("make_connection: VFS make connection failed!\n"));
660 change_to_root_user();
661 yield_connection(conn, lp_servicename(snum));
663 *status = NT_STATUS_UNSUCCESSFUL;
667 /* we've finished with the user stuff - go back to root */
668 change_to_root_user();
673 /***************************************************************************************
674 Simple wrapper function for make_connection() to include a call to
676 **************************************************************************************/
678 connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
679 const char *dev, uint16 vuid, NTSTATUS *status)
681 connection_struct *conn = NULL;
683 conn = make_connection(service_in, password, dev, vuid, status);
686 * make_connection() does not change the directory for us any more
687 * so we have to do it as a separate step --jerry
690 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
691 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
692 conn->connectpath,strerror(errno)));
693 yield_connection(conn, lp_servicename(SNUM(conn)));
695 *status = NT_STATUS_UNSUCCESSFUL;
702 /****************************************************************************
703 Make a connection to a service.
706 ****************************************************************************/
708 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
709 const char *pdev, uint16 vuid, NTSTATUS *status)
712 user_struct *vuser = NULL;
719 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
720 if (!non_root_mode() && (euid = geteuid()) != 0) {
721 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
722 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
725 if(lp_security() != SEC_SHARE) {
726 vuser = get_valid_user_struct(vuid);
728 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
729 *status = NT_STATUS_ACCESS_DENIED;
734 /* Logic to try and connect to the correct [homes] share, preferably without too many
735 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
736 share name isn't the same as unix username.
738 The snum of the homes share is stored on the vuser at session setup time.
741 if (strequal(service_in,HOMES_NAME)) {
742 if(lp_security() != SEC_SHARE) {
743 DATA_BLOB no_pw = data_blob(NULL, 0);
744 if (vuser->homes_snum == -1) {
745 DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n"));
746 *status = NT_STATUS_BAD_NETWORK_NAME;
749 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
750 return make_connection_snum(vuser->homes_snum,
754 /* Security = share. Try with current_user_info.smb_name
755 * as the username. */
756 if (*current_user_info.smb_name) {
757 fstring unix_username;
758 fstrcpy(unix_username,
759 current_user_info.smb_name);
760 map_username(unix_username);
761 snum = find_service(unix_username);
764 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
765 return make_connection_snum(snum, NULL,
770 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
771 && strequal(service_in, lp_servicename(vuser->homes_snum))) {
772 DATA_BLOB no_pw = data_blob(NULL, 0);
773 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
774 return make_connection_snum(vuser->homes_snum,
779 fstrcpy(service, service_in);
783 snum = find_service(service);
786 if (strequal(service,"IPC$")
787 || (lp_enable_asu_support() && strequal(service,"ADMIN$")))
789 DEBUG(3,("refusing IPC connection to %s\n", service));
790 *status = NT_STATUS_ACCESS_DENIED;
794 DEBUG(0,("%s (%s) couldn't find service %s\n",
795 get_remote_machine_name(), client_addr(), service));
796 *status = NT_STATUS_BAD_NETWORK_NAME;
800 /* Handle non-Dfs clients attempting connections to msdfs proxy */
801 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
802 DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n",
803 service, lp_msdfs_proxy(snum)));
804 *status = NT_STATUS_BAD_NETWORK_NAME;
808 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
810 return make_connection_snum(snum, vuser,
815 /****************************************************************************
817 ****************************************************************************/
819 void close_cnum(connection_struct *conn, uint16 vuid)
822 pipe_close_conn(conn);
824 file_close_conn(conn);
825 dptr_closecnum(conn);
828 change_to_root_user();
830 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
831 get_remote_machine_name(),conn->client_address,
832 lp_servicename(SNUM(conn))));
834 /* Call VFS disconnect hook */
835 SMB_VFS_DISCONNECT(conn);
837 yield_connection(conn, lp_servicename(SNUM(conn)));
839 /* make sure we leave the directory available for unmount */
840 vfs_ChDir(conn, "/");
842 /* execute any "postexec = " line */
843 if (*lp_postexec(SNUM(conn)) &&
844 change_to_user(conn, vuid)) {
846 pstrcpy(cmd,lp_postexec(SNUM(conn)));
847 standard_sub_conn(conn,cmd,sizeof(cmd));
849 change_to_root_user();
852 change_to_root_user();
853 /* execute any "root postexec = " line */
854 if (*lp_rootpostexec(SNUM(conn))) {
856 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
857 standard_sub_conn(conn,cmd,sizeof(cmd));