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 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(conn))));
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(conn)),
548 lp_max_connections(SNUM(conn)),
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(conn))) {
561 pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
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(conn))) {
566 DEBUG(1,("root preexec gave %d - failing connection\n", ret));
567 yield_connection(conn, lp_servicename(SNUM(conn)));
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"));
579 *status = NT_STATUS_LOGON_FAILURE;
583 /* Remember that a different vuid can connect later without these checks... */
585 /* Preexecs are done here as they might make the dir we are to ChDir to below */
586 /* execute any "preexec = " line */
587 if (*lp_preexec(SNUM(conn))) {
590 pstrcpy(cmd,lp_preexec(SNUM(conn)));
591 standard_sub_conn(conn,cmd,sizeof(cmd));
592 ret = smbrun(cmd,NULL);
593 if (ret != 0 && lp_preexec_close(SNUM(conn))) {
594 DEBUG(1,("preexec gave %d - failing connection\n", ret));
595 change_to_root_user();
596 yield_connection(conn, lp_servicename(SNUM(conn)));
598 *status = NT_STATUS_ACCESS_DENIED;
603 #ifdef WITH_FAKE_KASERVER
604 if (lp_afs_share(SNUM(conn))) {
609 /* win2000 does not check the permissions on the directory
610 during the tree connect, instead relying on permission
611 check during individual operations. To match this behaviour
612 I have disabled this chdir check (tridge) */
613 /* the alternative is just to check the directory exists */
614 if (SMB_VFS_STAT(conn, conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) {
615 DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn))));
616 change_to_root_user();
617 yield_connection(conn, lp_servicename(SNUM(conn)));
619 *status = NT_STATUS_BAD_NETWORK_NAME;
623 string_set(&conn->origpath,conn->connectpath);
625 #if SOFTLINK_OPTIMISATION
626 /* resolve any soft links early if possible */
627 if (vfs_ChDir(conn,conn->connectpath) == 0) {
629 pstrcpy(s,conn->connectpath);
631 string_set(&conn->connectpath,s);
632 vfs_ChDir(conn,conn->connectpath);
637 * Print out the 'connected as' stuff here as we need
638 * to know the effective uid and gid we will be using
639 * (at least initially).
642 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
643 dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address );
644 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
645 dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) );
646 dbgtext( "initially as user %s ", user );
647 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
648 dbgtext( "(pid %d)\n", (int)sys_getpid() );
651 /* Add veto/hide lists */
652 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
653 set_namearray( &conn->veto_list, lp_veto_files(SNUM(conn)));
654 set_namearray( &conn->hide_list, lp_hide_files(SNUM(conn)));
655 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(SNUM(conn)));
658 /* Invoke VFS make connection hook */
660 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
661 DEBUG(0,("make_connection: VFS make connection failed!\n"));
662 change_to_root_user();
664 *status = NT_STATUS_UNSUCCESSFUL;
668 /* we've finished with the user stuff - go back to root */
669 change_to_root_user();
674 /***************************************************************************************
675 Simple wrapper function for make_connection() to include a call to
677 **************************************************************************************/
679 connection_struct *make_connection_with_chdir(const char *service_in, DATA_BLOB password,
680 const char *dev, uint16 vuid, NTSTATUS *status)
682 connection_struct *conn = NULL;
684 conn = make_connection(service_in, password, dev, vuid, status);
687 * make_connection() does not change the directory for us any more
688 * so we have to do it as a separate step --jerry
691 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
692 DEBUG(0,("move_driver_to_download_area: Can't change directory to %s for [print$] (%s)\n",
693 conn->connectpath,strerror(errno)));
694 yield_connection(conn, lp_servicename(SNUM(conn)));
696 *status = NT_STATUS_UNSUCCESSFUL;
703 /****************************************************************************
704 Make a connection to a service.
707 ****************************************************************************/
709 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
710 const char *pdev, uint16 vuid, NTSTATUS *status)
713 user_struct *vuser = NULL;
720 /* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */
721 if (!non_root_mode() && (euid = geteuid()) != 0) {
722 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid ));
723 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
726 if(lp_security() != SEC_SHARE) {
727 vuser = get_valid_user_struct(vuid);
729 DEBUG(1,("make_connection: refusing to connect with no session setup\n"));
730 *status = NT_STATUS_ACCESS_DENIED;
735 /* Logic to try and connect to the correct [homes] share, preferably without too many
736 getpwnam() lookups. This is particulary nasty for winbind usernames, where the
737 share name isn't the same as unix username.
739 The snum of the homes share is stored on the vuser at session setup time.
742 if (strequal(service_in,HOMES_NAME)) {
743 if(lp_security() != SEC_SHARE) {
744 DATA_BLOB no_pw = data_blob(NULL, 0);
745 if (vuser->homes_snum == -1) {
746 DEBUG(2, ("[homes] share not available for this user because it was not found or created at session setup time\n"));
747 *status = NT_STATUS_BAD_NETWORK_NAME;
750 DEBUG(5, ("making a connection to [homes] service created at session setup time\n"));
751 return make_connection_snum(vuser->homes_snum,
755 /* Security = share. Try with current_user_info.smb_name
756 * as the username. */
757 if (*current_user_info.smb_name) {
758 fstring unix_username;
759 fstrcpy(unix_username,
760 current_user_info.smb_name);
761 map_username(unix_username);
762 snum = find_service(unix_username);
765 DEBUG(5, ("making a connection to 'homes' service %s based on security=share\n", service_in));
766 return make_connection_snum(snum, NULL,
771 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
772 && strequal(service_in, lp_servicename(vuser->homes_snum))) {
773 DATA_BLOB no_pw = data_blob(NULL, 0);
774 DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
775 return make_connection_snum(vuser->homes_snum,
780 fstrcpy(service, service_in);
784 snum = find_service(service);
787 if (strequal(service,"IPC$") || strequal(service,"ADMIN$")) {
788 DEBUG(3,("refusing IPC connection to %s\n", service));
789 *status = NT_STATUS_ACCESS_DENIED;
793 DEBUG(0,("%s (%s) couldn't find service %s\n",
794 get_remote_machine_name(), client_addr(), service));
795 *status = NT_STATUS_BAD_NETWORK_NAME;
799 /* Handle non-Dfs clients attempting connections to msdfs proxy */
800 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
801 DEBUG(3, ("refusing connection to dfs proxy share '%s' (pointing to %s)\n",
802 service, lp_msdfs_proxy(snum)));
803 *status = NT_STATUS_BAD_NETWORK_NAME;
807 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
809 return make_connection_snum(snum, vuser,
814 /****************************************************************************
816 ****************************************************************************/
817 void close_cnum(connection_struct *conn, uint16 vuid)
820 pipe_close_conn(conn);
822 file_close_conn(conn);
823 dptr_closecnum(conn);
826 change_to_root_user();
828 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
829 get_remote_machine_name(),conn->client_address,
830 lp_servicename(SNUM(conn))));
832 /* Call VFS disconnect hook */
833 SMB_VFS_DISCONNECT(conn);
835 yield_connection(conn, lp_servicename(SNUM(conn)));
837 /* make sure we leave the directory available for unmount */
838 vfs_ChDir(conn, "/");
840 /* execute any "postexec = " line */
841 if (*lp_postexec(SNUM(conn)) &&
842 change_to_user(conn, vuid)) {
844 pstrcpy(cmd,lp_postexec(SNUM(conn)));
845 standard_sub_conn(conn,cmd,sizeof(cmd));
847 change_to_root_user();
850 change_to_root_user();
851 /* execute any "root postexec = " line */
852 if (*lp_rootpostexec(SNUM(conn))) {
854 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
855 standard_sub_conn(conn,cmd,sizeof(cmd));