WHATSNEW: Add release notes for Samba 4.12.3.
[Samba.git] / source3 / smbd / service.c
blob03125a30dad56acb2b23838936ebcbe1aab638ac
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 3 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, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "system/filesys.h"
22 #include "system/passwd.h" /* uid_wrapper */
23 #include "../lib/tsocket/tsocket.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "../librpc/gen_ndr/netlogon.h"
27 #include "../libcli/security/security.h"
28 #include "printing/pcap.h"
29 #include "passdb/lookup_sid.h"
30 #include "auth.h"
31 #include "../auth/auth_util.h"
32 #include "lib/param/loadparm.h"
33 #include "messages.h"
34 #include "lib/afs/afs_funcs.h"
35 #include "lib/util_path.h"
37 static bool canonicalize_connect_path(connection_struct *conn)
39 bool ret;
40 struct smb_filename con_fname = { .base_name = conn->connectpath };
41 struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
42 &con_fname);
43 if (resolved_fname == NULL) {
44 return false;
46 ret = set_conn_connectpath(conn,resolved_fname->base_name);
47 TALLOC_FREE(resolved_fname);
48 return ret;
51 /****************************************************************************
52 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
53 absolute path stating in / and not ending in /.
54 ****************************************************************************/
56 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
58 char *destname;
60 if (connectpath == NULL || connectpath[0] == '\0') {
61 return false;
64 destname = canonicalize_absolute_path(conn, connectpath);
65 if (destname == NULL) {
66 return false;
69 DBG_DEBUG("service %s, connectpath = %s\n",
70 lp_const_servicename(SNUM(conn)), destname);
72 talloc_free(conn->connectpath);
73 conn->connectpath = destname;
75 * Ensure conn->cwd_fsp->fsp_name is initialized.
76 * start as conn->connectpath.
78 TALLOC_FREE(conn->cwd_fsp->fsp_name);
79 conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn,
80 conn->connectpath,
81 NULL,
82 NULL,
83 0);
84 if (conn->cwd_fsp->fsp_name == NULL) {
85 return false;
87 return true;
90 /****************************************************************************
91 Load parameters specific to a connection/service.
92 ****************************************************************************/
94 void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
96 int snum;
97 enum remote_arch_types ra_type;
99 SMB_ASSERT(conn != NULL);
101 snum = SNUM(conn);
103 if ((conn == last_conn) && (last_flags == flags)) {
104 return;
107 last_conn = conn;
108 last_flags = flags;
111 * Obey the client case sensitivity requests - only for clients that
112 * support it. */
113 switch (lp_case_sensitive(snum)) {
114 case Auto:
116 * We need this uglyness due to DOS/Win9x clients that lie
117 * about case insensitivity. */
118 ra_type = get_remote_arch();
119 if (conn->sconn->using_smb2) {
120 conn->case_sensitive = false;
121 } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
123 * Client can't support per-packet case sensitive
124 * pathnames. */
125 conn->case_sensitive = false;
126 } else {
127 conn->case_sensitive =
128 !(flags & FLAG_CASELESS_PATHNAMES);
130 break;
131 case True:
132 conn->case_sensitive = true;
133 break;
134 default:
135 conn->case_sensitive = false;
136 break;
138 return;
141 bool chdir_current_service(connection_struct *conn)
143 const struct smb_filename connectpath_fname = {
144 .base_name = conn->connectpath,
146 const struct smb_filename origpath_fname = {
147 .base_name = conn->origpath,
149 int saved_errno = 0;
150 char *utok_str = NULL;
151 int ret;
153 conn->lastused_count++;
155 ret = vfs_ChDir(conn, &connectpath_fname);
156 if (ret == 0) {
157 return true;
159 saved_errno = errno;
161 utok_str = utok_string(talloc_tos(),
162 conn->session_info->unix_token);
163 if (utok_str == NULL) {
164 errno = saved_errno;
165 return false;
168 DBG_ERR("vfs_ChDir(%s) failed: %s. Current token: %s\n",
169 conn->connectpath,
170 strerror(saved_errno),
171 utok_str);
173 ret = vfs_ChDir(conn, &origpath_fname);
174 if (ret == 0) {
175 TALLOC_FREE(utok_str);
176 return true;
178 saved_errno = errno;
180 DBG_ERR("vfs_ChDir(%s) failed: %s. Current token: %s\n",
181 conn->origpath,
182 strerror(saved_errno),
183 utok_str);
185 if (saved_errno != 0) {
186 errno = saved_errno;
188 return false;
191 /****************************************************************************
192 do some basic sainity checks on the share.
193 This function modifies dev, ecode.
194 ****************************************************************************/
196 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
197 const char *rhost,
198 int snum,
199 fstring dev)
201 char *raddr;
203 raddr = tsocket_address_inet_addr_string(remote_address,
204 talloc_tos());
205 if (raddr == NULL) {
206 return NT_STATUS_NO_MEMORY;
209 if (!lp_snum_ok(snum) ||
210 !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
211 rhost, raddr)) {
212 return NT_STATUS_ACCESS_DENIED;
215 if (dev[0] == '?' || !dev[0]) {
216 if (lp_printable(snum)) {
217 fstrcpy(dev,"LPT1:");
218 } else if (strequal(lp_fstype(snum), "IPC")) {
219 fstrcpy(dev, "IPC");
220 } else {
221 fstrcpy(dev,"A:");
225 if (!strupper_m(dev)) {
226 DEBUG(2,("strupper_m %s failed\n", dev));
227 return NT_STATUS_INVALID_PARAMETER;
230 if (lp_printable(snum)) {
231 if (!strequal(dev, "LPT1:")) {
232 return NT_STATUS_BAD_DEVICE_TYPE;
234 } else if (strequal(lp_fstype(snum), "IPC")) {
235 if (!strequal(dev, "IPC")) {
236 return NT_STATUS_BAD_DEVICE_TYPE;
238 } else if (!strequal(dev, "A:")) {
239 return NT_STATUS_BAD_DEVICE_TYPE;
242 /* Behave as a printer if we are supposed to */
243 if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
244 fstrcpy(dev, "LPT1:");
247 return NT_STATUS_OK;
251 * Go through lookup_name etc to find the force'd group.
253 * Create a new token from src_token, replacing the primary group sid with the
254 * one found.
257 static NTSTATUS find_forced_group(bool force_user,
258 int snum, const char *username,
259 struct dom_sid *pgroup_sid,
260 gid_t *pgid)
262 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
263 TALLOC_CTX *frame = talloc_stackframe();
264 const struct loadparm_substitution *lp_sub =
265 loadparm_s3_global_substitution();
266 struct dom_sid group_sid;
267 enum lsa_SidType type;
268 char *groupname;
269 bool user_must_be_member = False;
270 gid_t gid;
272 groupname = lp_force_group(talloc_tos(), lp_sub, snum);
273 if (groupname == NULL) {
274 DEBUG(1, ("talloc_strdup failed\n"));
275 result = NT_STATUS_NO_MEMORY;
276 goto done;
279 if (groupname[0] == '+') {
280 user_must_be_member = True;
281 groupname += 1;
284 groupname = talloc_string_sub(talloc_tos(), groupname,
285 "%S", lp_const_servicename(snum));
286 if (groupname == NULL) {
287 DEBUG(1, ("talloc_string_sub failed\n"));
288 result = NT_STATUS_NO_MEMORY;
289 goto done;
292 if (!lookup_name_smbconf(talloc_tos(), groupname,
293 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
294 NULL, NULL, &group_sid, &type)) {
295 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
296 groupname));
297 goto done;
300 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
301 (type != SID_NAME_WKN_GRP)) {
302 DEBUG(10, ("%s is a %s, not a group\n", groupname,
303 sid_type_lookup(type)));
304 goto done;
307 if (!sid_to_gid(&group_sid, &gid)) {
308 struct dom_sid_buf buf;
309 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
310 dom_sid_str_buf(&group_sid, &buf), groupname));
311 goto done;
315 * If the user has been forced and the forced group starts with a '+',
316 * then we only set the group to be the forced group if the forced
317 * user is a member of that group. Otherwise, the meaning of the '+'
318 * would be ignored.
321 if (force_user && user_must_be_member) {
322 if (user_in_group_sid(username, &group_sid)) {
323 sid_copy(pgroup_sid, &group_sid);
324 *pgid = gid;
325 DEBUG(3,("Forced group %s for member %s\n",
326 groupname, username));
327 } else {
328 DEBUG(0,("find_forced_group: forced user %s is not a member "
329 "of forced group %s. Disallowing access.\n",
330 username, groupname ));
331 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
332 goto done;
334 } else {
335 sid_copy(pgroup_sid, &group_sid);
336 *pgid = gid;
337 DEBUG(3,("Forced group %s\n", groupname));
340 result = NT_STATUS_OK;
341 done:
342 TALLOC_FREE(frame);
343 return result;
346 /****************************************************************************
347 Create an auth_session_info structure for a connection_struct
348 ****************************************************************************/
350 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
351 TALLOC_CTX *mem_ctx, int snum,
352 struct auth_session_info *session_info,
353 struct auth_session_info **presult)
355 struct auth_session_info *result;
357 if (lp_guest_only(snum)) {
358 return make_session_info_guest(mem_ctx, presult);
362 * This is the normal security != share case where we have a
363 * valid vuid from the session setup. */
365 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
366 if (!lp_guest_ok(snum)) {
367 DBG_WARNING("guest user (from session setup) "
368 "not permitted to access this share "
369 "(%s)\n", lp_const_servicename(snum));
370 return NT_STATUS_ACCESS_DENIED;
372 } else {
373 if (!user_ok_token(session_info->unix_info->unix_name,
374 session_info->info->domain_name,
375 session_info->security_token, snum)) {
376 DBG_WARNING("user '%s' (from session setup) not "
377 "permitted to access this share "
378 "(%s)\n",
379 session_info->unix_info->unix_name,
380 lp_const_servicename(snum));
381 return NT_STATUS_ACCESS_DENIED;
385 result = copy_session_info(mem_ctx, session_info);
386 if (result == NULL) {
387 return NT_STATUS_NO_MEMORY;
390 *presult = result;
391 return NT_STATUS_OK;
394 /****************************************************************************
395 Set relevant user and group settings corresponding to force user/group
396 configuration for the given snum.
397 ****************************************************************************/
399 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
401 const struct loadparm_substitution *lp_sub =
402 loadparm_s3_global_substitution();
403 NTSTATUS status;
405 if (*lp_force_user(talloc_tos(), lp_sub, snum)) {
408 * Replace conn->session_info with a completely faked up one
409 * from the username we are forced into :-)
412 char *fuser;
413 char *sanitized_username;
414 struct auth_session_info *forced_serverinfo;
415 bool guest;
417 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), lp_sub, snum), "%S",
418 lp_const_servicename(snum));
419 if (fuser == NULL) {
420 return NT_STATUS_NO_MEMORY;
423 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
425 status = make_session_info_from_username(
426 conn, fuser,
427 guest,
428 &forced_serverinfo);
429 if (!NT_STATUS_IS_OK(status)) {
430 return status;
433 /* We don't want to replace the original sanitized_username
434 as it is the original user given in the connect attempt.
435 This is used in '%U' substitutions. */
436 sanitized_username = discard_const_p(char,
437 forced_serverinfo->unix_info->sanitized_username);
438 TALLOC_FREE(sanitized_username);
439 forced_serverinfo->unix_info->sanitized_username =
440 talloc_move(forced_serverinfo->unix_info,
441 &conn->session_info->unix_info->sanitized_username);
443 TALLOC_FREE(conn->session_info);
444 conn->session_info = forced_serverinfo;
446 conn->force_user = true;
447 DEBUG(3,("Forced user %s\n", fuser));
451 * If force group is true, then override
452 * any groupid stored for the connecting user.
455 if (*lp_force_group(talloc_tos(), lp_sub, snum)) {
457 status = find_forced_group(
458 conn->force_user, snum, conn->session_info->unix_info->unix_name,
459 &conn->session_info->security_token->sids[1],
460 &conn->session_info->unix_token->gid);
462 if (!NT_STATUS_IS_OK(status)) {
463 return status;
467 * We need to cache this gid, to use within
468 * change_to_user() separately from the conn->session_info
469 * struct. We only use conn->session_info directly if
470 * "force_user" was set.
472 conn->force_group_gid = conn->session_info->unix_token->gid;
475 return NT_STATUS_OK;
478 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
480 NTSTATUS status;
482 if (sconn->notify_ctx != NULL) {
483 return NT_STATUS_OK;
486 sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx,
487 sconn, notify_callback);
488 if (sconn->notify_ctx == NULL) {
489 return NT_STATUS_NO_MEMORY;
492 status = messaging_register(sconn->msg_ctx, sconn,
493 MSG_SMB_NOTIFY_CANCEL_DELETED,
494 smbd_notify_cancel_deleted);
495 if (!NT_STATUS_IS_OK(status)) {
496 DBG_DEBUG("messaging_register failed: %s\n",
497 nt_errstr(status));
498 TALLOC_FREE(sconn->notify_ctx);
499 return status;
502 status = messaging_register(sconn->msg_ctx, sconn,
503 MSG_SMB_NOTIFY_STARTED,
504 smbd_notifyd_restarted);
505 if (!NT_STATUS_IS_OK(status)) {
506 DBG_DEBUG("messaging_register failed: %s\n",
507 nt_errstr(status));
508 messaging_deregister(sconn->msg_ctx,
509 MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
510 TALLOC_FREE(sconn->notify_ctx);
511 return status;
514 return NT_STATUS_OK;
517 /****************************************************************************
518 Make a connection, given the snum to connect to, and the vuser of the
519 connecting user if appropriate.
520 ****************************************************************************/
522 static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
523 connection_struct *conn,
524 int snum,
525 struct smbXsrv_session *session,
526 const char *pdev)
528 struct smbd_server_connection *sconn = xconn->client->sconn;
529 const struct loadparm_substitution *lp_sub =
530 loadparm_s3_global_substitution();
531 struct smb_filename *smb_fname_cpath = NULL;
532 fstring dev;
533 int ret;
534 bool on_err_call_dis_hook = false;
535 uid_t effuid;
536 gid_t effgid;
537 NTSTATUS status;
539 fstrcpy(dev, pdev);
541 status = share_sanity_checks(sconn->remote_address,
542 sconn->remote_hostname,
543 snum,
544 dev);
545 if (NT_STATUS_IS_ERR(status)) {
546 goto err_root_exit;
549 conn->params->service = snum;
551 status = create_connection_session_info(sconn,
552 conn, snum, session->global->auth_session_info,
553 &conn->session_info);
555 if (!NT_STATUS_IS_OK(status)) {
556 DEBUG(1, ("create_connection_session_info failed: %s\n",
557 nt_errstr(status)));
558 goto err_root_exit;
561 if (lp_guest_only(snum)) {
562 conn->force_user = true;
565 conn->num_files_open = 0;
566 conn->lastused = conn->lastused_count = time(NULL);
567 conn->printer = (strncmp(dev,"LPT",3) == 0);
568 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
569 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
571 /* Case options for the share. */
572 if (lp_case_sensitive(snum) == Auto) {
573 /* We will be setting this per packet. Set to be case
574 * insensitive for now. */
575 conn->case_sensitive = False;
576 } else {
577 conn->case_sensitive = (bool)lp_case_sensitive(snum);
580 conn->case_preserve = lp_preserve_case(snum);
581 conn->short_case_preserve = lp_short_preserve_case(snum);
583 conn->encrypt_level = lp_smb_encrypt(snum);
584 if (conn->encrypt_level > SMB_SIGNING_OFF) {
585 if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
586 if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
587 DBG_ERR("Service [%s] requires encryption, but "
588 "it is disabled globally!\n",
589 lp_const_servicename(snum));
590 status = NT_STATUS_ACCESS_DENIED;
591 goto err_root_exit;
593 conn->encrypt_level = SMB_SIGNING_OFF;
597 conn->veto_list = NULL;
598 conn->hide_list = NULL;
599 conn->veto_oplock_list = NULL;
600 conn->aio_write_behind_list = NULL;
602 conn->read_only = lp_read_only(SNUM(conn));
604 status = set_conn_force_user_group(conn, snum);
605 if (!NT_STATUS_IS_OK(status)) {
606 goto err_root_exit;
609 conn->vuid = session->global->session_wire_id;
612 char *s = talloc_sub_full(talloc_tos(),
613 lp_const_servicename(SNUM(conn)),
614 conn->session_info->unix_info->unix_name,
615 conn->connectpath,
616 conn->session_info->unix_token->gid,
617 conn->session_info->unix_info->sanitized_username,
618 conn->session_info->info->domain_name,
619 lp_path(talloc_tos(), lp_sub, snum));
620 if (!s) {
621 status = NT_STATUS_NO_MEMORY;
622 goto err_root_exit;
625 if (!set_conn_connectpath(conn,s)) {
626 TALLOC_FREE(s);
627 status = NT_STATUS_NO_MEMORY;
628 goto err_root_exit;
630 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s,
631 lp_const_servicename(snum));
632 TALLOC_FREE(s);
636 * Set up the share security descriptor.
637 * NOTE - we use the *INCOMING USER* session_info
638 * here, as does (indirectly) change_to_user(),
639 * which can be called on any incoming packet.
640 * This way we set up the share access based
641 * on the authenticated user, not the forced
642 * user. See bug:
644 * https://bugzilla.samba.org/show_bug.cgi?id=9878
647 status = check_user_share_access(conn,
648 session->global->auth_session_info,
649 &conn->share_access,
650 &conn->read_only);
651 if (!NT_STATUS_IS_OK(status)) {
652 goto err_root_exit;
655 /* Initialise VFS function pointers */
657 if (!smbd_vfs_init(conn)) {
658 DBG_ERR("vfs_init failed for service %s\n",
659 lp_const_servicename(snum));
660 status = NT_STATUS_BAD_NETWORK_NAME;
661 goto err_root_exit;
664 /* ROOT Activities: */
665 /* explicitly check widelinks here so that we can correctly warn
666 * in the logs. */
667 widelinks_warning(snum);
670 * Enforce the max connections parameter.
673 if ((lp_max_connections(snum) > 0)
674 && (count_current_connections(lp_const_servicename(SNUM(conn)), true) >=
675 lp_max_connections(snum))) {
677 DBG_WARNING("Max connections (%d) exceeded for %s\n",
678 lp_max_connections(snum),
679 lp_const_servicename(snum));
680 status = NT_STATUS_INSUFFICIENT_RESOURCES;
681 goto err_root_exit;
684 /* Invoke VFS make connection hook - this must be the first
685 filesystem operation that we do. */
687 if (SMB_VFS_CONNECT(conn, lp_const_servicename(snum),
688 conn->session_info->unix_info->unix_name) < 0) {
689 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
690 lp_const_servicename(snum), conn->connectpath,
691 strerror(errno));
692 status = NT_STATUS_UNSUCCESSFUL;
693 goto err_root_exit;
696 /* Any error exit after here needs to call the disconnect hook. */
697 on_err_call_dis_hook = true;
699 if ((!conn->printer) && (!conn->ipc) &&
700 lp_change_notify()) {
702 status = notify_init_sconn(sconn);
703 if (!NT_STATUS_IS_OK(status)) {
704 goto err_root_exit;
708 if (lp_kernel_oplocks(snum)) {
709 init_kernel_oplocks(conn->sconn);
713 * Fix compatibility issue pointed out by Volker.
714 * We pass the conn->connectpath to the preexec
715 * scripts as a parameter, so attempt to canonicalize
716 * it here before calling the preexec scripts.
717 * We ignore errors here, as it is possible that
718 * the conn->connectpath doesn't exist yet and
719 * the preexec scripts will create them.
722 (void)canonicalize_connect_path(conn);
724 /* Preexecs are done here as they might make the dir we are to ChDir
725 * to below */
726 /* execute any "root preexec = " line */
727 if (*lp_root_preexec(talloc_tos(), lp_sub, snum)) {
728 char *cmd = talloc_sub_full(talloc_tos(),
729 lp_const_servicename(SNUM(conn)),
730 conn->session_info->unix_info->unix_name,
731 conn->connectpath,
732 conn->session_info->unix_token->gid,
733 conn->session_info->unix_info->sanitized_username,
734 conn->session_info->info->domain_name,
735 lp_root_preexec(talloc_tos(), lp_sub, snum));
736 DEBUG(5,("cmd=%s\n",cmd));
737 ret = smbrun(cmd, NULL, NULL);
738 TALLOC_FREE(cmd);
739 if (ret != 0 && lp_root_preexec_close(snum)) {
740 DEBUG(1,("root preexec gave %d - failing "
741 "connection\n", ret));
742 status = NT_STATUS_ACCESS_DENIED;
743 goto err_root_exit;
747 /* USER Activites: */
748 if (!change_to_user_and_service(conn, conn->vuid)) {
749 /* No point continuing if they fail the basic checks */
750 DEBUG(0,("Can't become connected user!\n"));
751 status = NT_STATUS_LOGON_FAILURE;
752 goto err_root_exit;
755 effuid = geteuid();
756 effgid = getegid();
758 /* Remember that a different vuid can connect later without these
759 * checks... */
761 /* Preexecs are done here as they might make the dir we are to ChDir
762 * to below */
764 /* execute any "preexec = " line */
765 if (*lp_preexec(talloc_tos(), lp_sub, snum)) {
766 char *cmd = talloc_sub_full(talloc_tos(),
767 lp_const_servicename(SNUM(conn)),
768 conn->session_info->unix_info->unix_name,
769 conn->connectpath,
770 conn->session_info->unix_token->gid,
771 conn->session_info->unix_info->sanitized_username,
772 conn->session_info->info->domain_name,
773 lp_preexec(talloc_tos(), lp_sub, snum));
774 ret = smbrun(cmd, NULL, NULL);
775 TALLOC_FREE(cmd);
776 if (ret != 0 && lp_preexec_close(snum)) {
777 DEBUG(1,("preexec gave %d - failing connection\n",
778 ret));
779 status = NT_STATUS_ACCESS_DENIED;
780 goto err_root_exit;
784 #ifdef WITH_FAKE_KASERVER
785 if (lp_afs_share(snum)) {
786 afs_login(conn);
788 #endif
791 * we've finished with the user stuff - go back to root
792 * so the SMB_VFS_STAT call will only fail on path errors,
793 * not permission problems.
795 change_to_root_user();
796 /* ROOT Activites: */
799 * If widelinks are disallowed we need to canonicalise the connect
800 * path here to ensure we don't have any symlinks in the
801 * connectpath. We will be checking all paths on this connection are
802 * below this directory. We must do this after the VFS init as we
803 * depend on the realpath() pointer in the vfs table. JRA.
805 if (!lp_widelinks(snum)) {
806 if (!canonicalize_connect_path(conn)) {
807 DBG_ERR("canonicalize_connect_path failed "
808 "for service %s, path %s\n",
809 lp_const_servicename(snum),
810 conn->connectpath);
811 status = NT_STATUS_BAD_NETWORK_NAME;
812 goto err_root_exit;
816 /* Add veto/hide lists */
817 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
818 set_namearray( &conn->veto_list,
819 lp_veto_files(talloc_tos(), lp_sub, snum));
820 set_namearray( &conn->hide_list,
821 lp_hide_files(talloc_tos(), lp_sub, snum));
822 set_namearray( &conn->veto_oplock_list,
823 lp_veto_oplock_files(talloc_tos(), lp_sub, snum));
824 set_namearray( &conn->aio_write_behind_list,
825 lp_aio_write_behind(talloc_tos(), lp_sub, snum));
827 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
828 conn->connectpath,
829 NULL,
830 NULL,
832 if (smb_fname_cpath == NULL) {
833 status = NT_STATUS_NO_MEMORY;
834 goto err_root_exit;
837 /* win2000 does not check the permissions on the directory
838 during the tree connect, instead relying on permission
839 check during individual operations. To match this behaviour
840 I have disabled this chdir check (tridge) */
841 /* the alternative is just to check the directory exists */
843 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
844 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
845 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
846 DBG_ERR("'%s' is not a directory, when connecting to "
847 "[%s]\n", conn->connectpath,
848 lp_const_servicename(snum));
849 } else {
850 DBG_ERR("'%s' does not exist or permission denied "
851 "when connecting to [%s] Error was %s\n",
852 conn->connectpath,
853 lp_const_servicename(snum),
854 strerror(errno));
856 status = NT_STATUS_BAD_NETWORK_NAME;
857 goto err_root_exit;
859 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
861 talloc_free(conn->origpath);
862 conn->origpath = talloc_strdup(conn, conn->connectpath);
864 /* Figure out the characteristics of the underlying filesystem. This
865 * assumes that all the filesystem mounted within a share path have
866 * the same characteristics, which is likely but not guaranteed.
869 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
872 * Print out the 'connected as' stuff here as we need
873 * to know the effective uid and gid we will be using
874 * (at least initially).
877 if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
878 dbgtext( "%s (%s) ", get_remote_machine_name(),
879 tsocket_address_string(conn->sconn->remote_address,
880 talloc_tos()) );
881 dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
882 dbgtext( "connect to service %s ",
883 lp_const_servicename(snum) );
884 dbgtext( "initially as user %s ",
885 conn->session_info->unix_info->unix_name );
886 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
887 dbgtext( "(pid %d)\n", (int)getpid() );
890 conn->tcon_done = true;
891 return NT_STATUS_OK;
893 err_root_exit:
895 TALLOC_FREE(smb_fname_cpath);
896 /* We must exit this function as root. */
897 if (geteuid() != 0) {
898 change_to_root_user();
900 if (on_err_call_dis_hook) {
901 /* Call VFS disconnect hook */
902 SMB_VFS_DISCONNECT(conn);
904 return status;
907 /****************************************************************************
908 Make a connection to a service from SMB1. Internal interface.
909 ****************************************************************************/
911 static connection_struct *make_connection_smb1(struct smb_request *req,
912 NTTIME now,
913 int snum,
914 const char *pdev,
915 NTSTATUS *pstatus)
917 const struct loadparm_substitution *lp_sub =
918 loadparm_s3_global_substitution();
919 struct smbXsrv_tcon *tcon;
920 NTSTATUS status;
921 struct connection_struct *conn;
923 status = smb1srv_tcon_create(req->xconn, now, &tcon);
924 if (!NT_STATUS_IS_OK(status)) {
925 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
926 nt_errstr(status)));
927 *pstatus = status;
928 return NULL;
931 conn = conn_new(req->sconn);
932 if (!conn) {
933 TALLOC_FREE(tcon);
935 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
936 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
937 return NULL;
940 conn->cnum = tcon->global->tcon_wire_id;
941 conn->tcon = tcon;
943 *pstatus = make_connection_snum(req->xconn,
944 conn,
945 snum,
946 req->session,
947 pdev);
948 if (!NT_STATUS_IS_OK(*pstatus)) {
949 conn_free(conn);
950 TALLOC_FREE(tcon);
951 return NULL;
954 tcon->global->share_name = lp_servicename(tcon->global, lp_sub, SNUM(conn));
955 if (tcon->global->share_name == NULL) {
956 conn_free(conn);
957 TALLOC_FREE(tcon);
958 *pstatus = NT_STATUS_NO_MEMORY;
959 return NULL;
961 tcon->global->session_global_id =
962 req->session->global->session_global_id;
964 tcon->compat = talloc_move(tcon, &conn);
965 tcon->status = NT_STATUS_OK;
967 *pstatus = smbXsrv_tcon_update(tcon);
968 if (!NT_STATUS_IS_OK(*pstatus)) {
969 TALLOC_FREE(tcon);
970 return NULL;
973 return tcon->compat;
976 /****************************************************************************
977 Make a connection to a service from SMB2. External SMB2 interface.
978 We must set cnum before claiming connection.
979 ****************************************************************************/
981 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
982 struct smbXsrv_tcon *tcon,
983 int snum,
984 const char *pdev,
985 NTSTATUS *pstatus)
987 struct smbd_server_connection *sconn = req->sconn;
988 connection_struct *conn = conn_new(sconn);
989 if (!conn) {
990 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
991 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
992 return NULL;
995 conn->cnum = tcon->global->tcon_wire_id;
996 conn->tcon = tcon;
998 *pstatus = make_connection_snum(req->xconn,
999 conn,
1000 snum,
1001 req->session,
1002 pdev);
1003 if (!NT_STATUS_IS_OK(*pstatus)) {
1004 conn_free(conn);
1005 return NULL;
1007 return conn;
1010 /****************************************************************************
1011 Make a connection to a service. External SMB1 interface.
1013 * @param service
1014 ****************************************************************************/
1016 connection_struct *make_connection(struct smb_request *req,
1017 NTTIME now,
1018 const char *service_in,
1019 const char *pdev, uint64_t vuid,
1020 NTSTATUS *status)
1022 struct smbd_server_connection *sconn = req->sconn;
1023 struct smbXsrv_session *session = req->session;
1024 const struct loadparm_substitution *lp_sub =
1025 loadparm_s3_global_substitution();
1026 uid_t euid;
1027 char *service = NULL;
1028 fstring dev;
1029 int snum = -1;
1031 fstrcpy(dev, pdev);
1033 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1034 * root. */
1035 if (!non_root_mode() && (euid = geteuid()) != 0) {
1036 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1037 "(%u)\n", (unsigned int)euid ));
1038 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1041 if (conn_num_open(sconn) > 2047) {
1042 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1043 return NULL;
1046 if (session == NULL) {
1047 DEBUG(1,("make_connection: refusing to connect with "
1048 "no session setup\n"));
1049 *status = NT_STATUS_ACCESS_DENIED;
1050 return NULL;
1053 /* Logic to try and connect to the correct [homes] share, preferably
1054 without too many getpwnam() lookups. This is particulary nasty for
1055 winbind usernames, where the share name isn't the same as unix
1056 username.
1059 if (strequal(service_in,HOMES_NAME)) {
1060 if (session->homes_snum == -1) {
1061 DEBUG(2, ("[homes] share not available for "
1062 "this user because it was not found "
1063 "or created at session setup "
1064 "time\n"));
1065 *status = NT_STATUS_BAD_NETWORK_NAME;
1066 return NULL;
1068 DEBUG(5, ("making a connection to [homes] service "
1069 "created at session setup time\n"));
1070 return make_connection_smb1(req, now,
1071 session->homes_snum,
1072 dev, status);
1073 } else if ((session->homes_snum != -1)
1074 && strequal(service_in,
1075 lp_const_servicename(session->homes_snum))) {
1076 DEBUG(5, ("making a connection to 'homes' service [%s] "
1077 "created at session setup time\n", service_in));
1078 return make_connection_smb1(req, now,
1079 session->homes_snum,
1080 dev, status);
1083 service = talloc_strdup(talloc_tos(), service_in);
1084 if (!service) {
1085 *status = NT_STATUS_NO_MEMORY;
1086 return NULL;
1089 if (!strlower_m(service)) {
1090 DEBUG(2, ("strlower_m %s failed\n", service));
1091 *status = NT_STATUS_INVALID_PARAMETER;
1092 return NULL;
1095 snum = find_service(talloc_tos(), service, &service);
1096 if (!service) {
1097 *status = NT_STATUS_NO_MEMORY;
1098 return NULL;
1101 if (snum < 0) {
1102 if (strequal(service,"IPC$") ||
1103 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1104 DEBUG(3,("refusing IPC connection to %s\n", service));
1105 *status = NT_STATUS_ACCESS_DENIED;
1106 return NULL;
1109 DEBUG(3,("%s (%s) couldn't find service %s\n",
1110 get_remote_machine_name(),
1111 tsocket_address_string(
1112 sconn->remote_address, talloc_tos()),
1113 service));
1114 *status = NT_STATUS_BAD_NETWORK_NAME;
1115 return NULL;
1118 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1119 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), lp_sub, snum) != '\0')) {
1120 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1121 "(pointing to %s)\n",
1122 service, lp_msdfs_proxy(talloc_tos(), lp_sub, snum)));
1123 *status = NT_STATUS_BAD_NETWORK_NAME;
1124 return NULL;
1127 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1129 return make_connection_smb1(req, now, snum,
1130 dev, status);
1133 /****************************************************************************
1134 Close a cnum.
1135 ****************************************************************************/
1137 void close_cnum(connection_struct *conn, uint64_t vuid)
1139 char rootpath[2] = { '/', '\0'};
1140 struct smb_filename root_fname = { .base_name = rootpath };
1141 const struct loadparm_substitution *lp_sub =
1142 loadparm_s3_global_substitution();
1144 file_close_conn(conn);
1146 change_to_root_user();
1148 DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1149 get_remote_machine_name(),
1150 tsocket_address_string(conn->sconn->remote_address,
1151 talloc_tos()),
1152 lp_const_servicename(SNUM(conn))));
1154 /* make sure we leave the directory available for unmount */
1155 vfs_ChDir(conn, &root_fname);
1157 /* Call VFS disconnect hook */
1158 SMB_VFS_DISCONNECT(conn);
1160 /* execute any "postexec = " line */
1161 if (*lp_postexec(talloc_tos(), lp_sub, SNUM(conn)) &&
1162 change_to_user_and_service(conn, vuid)) {
1163 char *cmd = talloc_sub_full(talloc_tos(),
1164 lp_const_servicename(SNUM(conn)),
1165 conn->session_info->unix_info->unix_name,
1166 conn->connectpath,
1167 conn->session_info->unix_token->gid,
1168 conn->session_info->unix_info->sanitized_username,
1169 conn->session_info->info->domain_name,
1170 lp_postexec(talloc_tos(), lp_sub, SNUM(conn)));
1171 smbrun(cmd, NULL, NULL);
1172 TALLOC_FREE(cmd);
1173 change_to_root_user();
1176 change_to_root_user();
1177 /* execute any "root postexec = " line */
1178 if (*lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn))) {
1179 char *cmd = talloc_sub_full(talloc_tos(),
1180 lp_const_servicename(SNUM(conn)),
1181 conn->session_info->unix_info->unix_name,
1182 conn->connectpath,
1183 conn->session_info->unix_token->gid,
1184 conn->session_info->unix_info->sanitized_username,
1185 conn->session_info->info->domain_name,
1186 lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)));
1187 smbrun(cmd, NULL, NULL);
1188 TALLOC_FREE(cmd);
1191 conn_free(conn);