s3/service: convert lp_force_group() to const
[Samba.git] / source3 / smbd / service.c
blobdf72172d9b015d1a295daa71073e8bcc6a2448a6
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 "lib/param/loadparm.h"
32 #include "messages.h"
33 #include "lib/afs/afs_funcs.h"
34 #include "lib/util_path.h"
36 static bool canonicalize_connect_path(connection_struct *conn)
38 bool ret;
39 struct smb_filename con_fname = { .base_name = conn->connectpath };
40 struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
41 &con_fname);
42 if (resolved_fname == NULL) {
43 return false;
45 ret = set_conn_connectpath(conn,resolved_fname->base_name);
46 TALLOC_FREE(resolved_fname);
47 return ret;
50 /****************************************************************************
51 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
52 absolute path stating in / and not ending in /.
53 ****************************************************************************/
55 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
57 char *destname;
59 if (connectpath == NULL || connectpath[0] == '\0') {
60 return false;
63 destname = canonicalize_absolute_path(conn, connectpath);
64 if (destname == NULL) {
65 return false;
68 DBG_DEBUG("service %s, connectpath = %s\n",
69 lp_const_servicename(SNUM(conn)), destname);
71 talloc_free(conn->connectpath);
72 conn->connectpath = destname;
74 * Ensure conn->cwd_fname is initialized.
75 * start as conn->connectpath.
77 TALLOC_FREE(conn->cwd_fname);
78 conn->cwd_fname = synthetic_smb_fname(conn,
79 conn->connectpath,
80 NULL,
81 NULL,
82 0);
83 if (conn->cwd_fname == NULL) {
84 return false;
86 return true;
89 /****************************************************************************
90 Load parameters specific to a connection/service.
91 ****************************************************************************/
93 void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
95 int snum;
96 enum remote_arch_types ra_type;
98 SMB_ASSERT(conn != NULL);
100 snum = SNUM(conn);
102 if ((conn == last_conn) && (last_flags == flags)) {
103 return;
106 last_conn = conn;
107 last_flags = flags;
110 * Obey the client case sensitivity requests - only for clients that
111 * support it. */
112 switch (lp_case_sensitive(snum)) {
113 case Auto:
115 * We need this uglyness due to DOS/Win9x clients that lie
116 * about case insensitivity. */
117 ra_type = get_remote_arch();
118 if (conn->sconn->using_smb2) {
119 conn->case_sensitive = false;
120 } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
122 * Client can't support per-packet case sensitive
123 * pathnames. */
124 conn->case_sensitive = false;
125 } else {
126 conn->case_sensitive =
127 !(flags & FLAG_CASELESS_PATHNAMES);
129 break;
130 case True:
131 conn->case_sensitive = true;
132 break;
133 default:
134 conn->case_sensitive = false;
135 break;
137 return;
140 bool chdir_current_service(connection_struct *conn)
142 const struct smb_filename connectpath_fname = {
143 .base_name = conn->connectpath,
145 const struct smb_filename origpath_fname = {
146 .base_name = conn->origpath,
148 int ret;
150 conn->lastused_count++;
152 ret = vfs_ChDir(conn, &connectpath_fname);
153 if (ret != 0) {
154 DEBUG(((errno!=EACCES)?0:3),
155 ("chdir (%s) failed, reason: %s\n",
156 conn->connectpath, strerror(errno)));
157 return false;
160 ret = vfs_ChDir(conn, &origpath_fname);
161 if (ret != 0) {
162 DEBUG(((errno!=EACCES)?0:3),
163 ("chdir (%s) failed, reason: %s\n",
164 conn->origpath, strerror(errno)));
165 return false;
168 return true;
171 /****************************************************************************
172 do some basic sainity checks on the share.
173 This function modifies dev, ecode.
174 ****************************************************************************/
176 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
177 const char *rhost,
178 int snum,
179 fstring dev)
181 char *raddr;
183 raddr = tsocket_address_inet_addr_string(remote_address,
184 talloc_tos());
185 if (raddr == NULL) {
186 return NT_STATUS_NO_MEMORY;
189 if (!lp_snum_ok(snum) ||
190 !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
191 rhost, raddr)) {
192 return NT_STATUS_ACCESS_DENIED;
195 if (dev[0] == '?' || !dev[0]) {
196 if (lp_printable(snum)) {
197 fstrcpy(dev,"LPT1:");
198 } else if (strequal(lp_fstype(snum), "IPC")) {
199 fstrcpy(dev, "IPC");
200 } else {
201 fstrcpy(dev,"A:");
205 if (!strupper_m(dev)) {
206 DEBUG(2,("strupper_m %s failed\n", dev));
207 return NT_STATUS_INVALID_PARAMETER;
210 if (lp_printable(snum)) {
211 if (!strequal(dev, "LPT1:")) {
212 return NT_STATUS_BAD_DEVICE_TYPE;
214 } else if (strequal(lp_fstype(snum), "IPC")) {
215 if (!strequal(dev, "IPC")) {
216 return NT_STATUS_BAD_DEVICE_TYPE;
218 } else if (!strequal(dev, "A:")) {
219 return NT_STATUS_BAD_DEVICE_TYPE;
222 /* Behave as a printer if we are supposed to */
223 if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
224 fstrcpy(dev, "LPT1:");
227 return NT_STATUS_OK;
231 * Go through lookup_name etc to find the force'd group.
233 * Create a new token from src_token, replacing the primary group sid with the
234 * one found.
237 static NTSTATUS find_forced_group(bool force_user,
238 int snum, const char *username,
239 struct dom_sid *pgroup_sid,
240 gid_t *pgid)
242 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
243 TALLOC_CTX *frame = talloc_stackframe();
244 struct dom_sid group_sid;
245 enum lsa_SidType type;
246 const char *force_group;
247 char *groupname;
248 bool user_must_be_member = False;
249 gid_t gid;
251 force_group = lp_force_group(snum);
252 if (force_group[0] == '+') {
253 user_must_be_member = true;
254 force_group += 1;
257 groupname = talloc_string_sub(talloc_tos(), force_group,
258 "%S", lp_const_servicename(snum));
259 if (groupname == NULL) {
260 DEBUG(1, ("talloc_string_sub failed\n"));
261 result = NT_STATUS_NO_MEMORY;
262 goto done;
265 if (!lookup_name_smbconf(talloc_tos(), groupname,
266 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
267 NULL, NULL, &group_sid, &type)) {
268 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
269 groupname));
270 goto done;
273 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
274 (type != SID_NAME_WKN_GRP)) {
275 DEBUG(10, ("%s is a %s, not a group\n", groupname,
276 sid_type_lookup(type)));
277 goto done;
280 if (!sid_to_gid(&group_sid, &gid)) {
281 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
282 sid_string_dbg(&group_sid), groupname));
283 goto done;
287 * If the user has been forced and the forced group starts with a '+',
288 * then we only set the group to be the forced group if the forced
289 * user is a member of that group. Otherwise, the meaning of the '+'
290 * would be ignored.
293 if (force_user && user_must_be_member) {
294 if (user_in_group_sid(username, &group_sid)) {
295 sid_copy(pgroup_sid, &group_sid);
296 *pgid = gid;
297 DEBUG(3,("Forced group %s for member %s\n",
298 groupname, username));
299 } else {
300 DEBUG(0,("find_forced_group: forced user %s is not a member "
301 "of forced group %s. Disallowing access.\n",
302 username, groupname ));
303 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
304 goto done;
306 } else {
307 sid_copy(pgroup_sid, &group_sid);
308 *pgid = gid;
309 DEBUG(3,("Forced group %s\n", groupname));
312 result = NT_STATUS_OK;
313 done:
314 TALLOC_FREE(frame);
315 return result;
318 /****************************************************************************
319 Create an auth_session_info structure for a connection_struct
320 ****************************************************************************/
322 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
323 TALLOC_CTX *mem_ctx, int snum,
324 struct auth_session_info *session_info,
325 struct auth_session_info **presult)
327 struct auth_session_info *result;
329 if (lp_guest_only(snum)) {
330 return make_session_info_guest(mem_ctx, presult);
334 * This is the normal security != share case where we have a
335 * valid vuid from the session setup. */
337 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
338 if (!lp_guest_ok(snum)) {
339 DBG_WARNING("guest user (from session setup) "
340 "not permitted to access this share "
341 "(%s)\n", lp_const_servicename(snum));
342 return NT_STATUS_ACCESS_DENIED;
344 } else {
345 if (!user_ok_token(session_info->unix_info->unix_name,
346 session_info->info->domain_name,
347 session_info->security_token, snum)) {
348 DBG_WARNING("user '%s' (from session setup) not "
349 "permitted to access this share "
350 "(%s)\n",
351 session_info->unix_info->unix_name,
352 lp_const_servicename(snum));
353 return NT_STATUS_ACCESS_DENIED;
357 result = copy_session_info(mem_ctx, session_info);
358 if (result == NULL) {
359 return NT_STATUS_NO_MEMORY;
362 *presult = result;
363 return NT_STATUS_OK;
366 /****************************************************************************
367 Set relevant user and group settings corresponding to force user/group
368 configuration for the given snum.
369 ****************************************************************************/
371 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
373 NTSTATUS status;
375 if (*lp_force_user(talloc_tos(), snum)) {
378 * Replace conn->session_info with a completely faked up one
379 * from the username we are forced into :-)
382 char *fuser;
383 char *sanitized_username;
384 struct auth_session_info *forced_serverinfo;
385 bool guest;
387 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), snum), "%S",
388 lp_const_servicename(snum));
389 if (fuser == NULL) {
390 return NT_STATUS_NO_MEMORY;
393 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
395 status = make_session_info_from_username(
396 conn, fuser,
397 guest,
398 &forced_serverinfo);
399 if (!NT_STATUS_IS_OK(status)) {
400 return status;
403 /* We don't want to replace the original sanitized_username
404 as it is the original user given in the connect attempt.
405 This is used in '%U' substitutions. */
406 sanitized_username = discard_const_p(char,
407 forced_serverinfo->unix_info->sanitized_username);
408 TALLOC_FREE(sanitized_username);
409 forced_serverinfo->unix_info->sanitized_username =
410 talloc_move(forced_serverinfo->unix_info,
411 &conn->session_info->unix_info->sanitized_username);
413 TALLOC_FREE(conn->session_info);
414 conn->session_info = forced_serverinfo;
416 conn->force_user = true;
417 DEBUG(3,("Forced user %s\n", fuser));
421 * If force group is true, then override
422 * any groupid stored for the connecting user.
425 if (*lp_force_group(snum)) {
427 status = find_forced_group(
428 conn->force_user, snum, conn->session_info->unix_info->unix_name,
429 &conn->session_info->security_token->sids[1],
430 &conn->session_info->unix_token->gid);
432 if (!NT_STATUS_IS_OK(status)) {
433 return status;
437 * We need to cache this gid, to use within
438 * change_to_user() separately from the conn->session_info
439 * struct. We only use conn->session_info directly if
440 * "force_user" was set.
442 conn->force_group_gid = conn->session_info->unix_token->gid;
445 return NT_STATUS_OK;
448 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
450 NTSTATUS status;
452 if (sconn->notify_ctx != NULL) {
453 return NT_STATUS_OK;
456 sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx,
457 sconn, notify_callback);
458 if (sconn->notify_ctx == NULL) {
459 return NT_STATUS_NO_MEMORY;
462 status = messaging_register(sconn->msg_ctx, sconn,
463 MSG_SMB_NOTIFY_CANCEL_DELETED,
464 smbd_notify_cancel_deleted);
465 if (!NT_STATUS_IS_OK(status)) {
466 DBG_DEBUG("messaging_register failed: %s\n",
467 nt_errstr(status));
468 TALLOC_FREE(sconn->notify_ctx);
469 return status;
472 status = messaging_register(sconn->msg_ctx, sconn,
473 MSG_SMB_NOTIFY_STARTED,
474 smbd_notifyd_restarted);
475 if (!NT_STATUS_IS_OK(status)) {
476 DBG_DEBUG("messaging_register failed: %s\n",
477 nt_errstr(status));
478 messaging_deregister(sconn->msg_ctx,
479 MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
480 TALLOC_FREE(sconn->notify_ctx);
481 return status;
484 return NT_STATUS_OK;
487 /****************************************************************************
488 Make a connection, given the snum to connect to, and the vuser of the
489 connecting user if appropriate.
490 ****************************************************************************/
492 static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
493 connection_struct *conn,
494 int snum, struct user_struct *vuser,
495 const char *pdev)
497 struct smbd_server_connection *sconn = xconn->client->sconn;
498 struct smb_filename *smb_fname_cpath = NULL;
499 fstring dev;
500 int ret;
501 bool on_err_call_dis_hook = false;
502 uid_t effuid;
503 gid_t effgid;
504 NTSTATUS status;
506 fstrcpy(dev, pdev);
508 status = share_sanity_checks(sconn->remote_address,
509 sconn->remote_hostname,
510 snum,
511 dev);
512 if (NT_STATUS_IS_ERR(status)) {
513 goto err_root_exit;
516 conn->params->service = snum;
518 status = create_connection_session_info(sconn,
519 conn, snum, vuser->session_info,
520 &conn->session_info);
522 if (!NT_STATUS_IS_OK(status)) {
523 DEBUG(1, ("create_connection_session_info failed: %s\n",
524 nt_errstr(status)));
525 goto err_root_exit;
528 if (lp_guest_only(snum)) {
529 conn->force_user = true;
532 conn->num_files_open = 0;
533 conn->lastused = conn->lastused_count = time(NULL);
534 conn->printer = (strncmp(dev,"LPT",3) == 0);
535 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
536 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
538 /* Case options for the share. */
539 if (lp_case_sensitive(snum) == Auto) {
540 /* We will be setting this per packet. Set to be case
541 * insensitive for now. */
542 conn->case_sensitive = False;
543 } else {
544 conn->case_sensitive = (bool)lp_case_sensitive(snum);
547 conn->case_preserve = lp_preserve_case(snum);
548 conn->short_case_preserve = lp_short_preserve_case(snum);
550 conn->encrypt_level = lp_smb_encrypt(snum);
551 if (conn->encrypt_level > SMB_SIGNING_OFF) {
552 if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
553 if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
554 DBG_ERR("Service [%s] requires encryption, but "
555 "it is disabled globally!\n",
556 lp_const_servicename(snum));
557 status = NT_STATUS_ACCESS_DENIED;
558 goto err_root_exit;
560 conn->encrypt_level = SMB_SIGNING_OFF;
564 conn->veto_list = NULL;
565 conn->hide_list = NULL;
566 conn->veto_oplock_list = NULL;
567 conn->aio_write_behind_list = NULL;
569 conn->read_only = lp_read_only(SNUM(conn));
571 status = set_conn_force_user_group(conn, snum);
572 if (!NT_STATUS_IS_OK(status)) {
573 goto err_root_exit;
576 conn->vuid = vuser->vuid;
579 char *s = talloc_sub_advanced(talloc_tos(),
580 lp_const_servicename(SNUM(conn)),
581 conn->session_info->unix_info->unix_name,
582 conn->connectpath,
583 conn->session_info->unix_token->gid,
584 conn->session_info->unix_info->sanitized_username,
585 conn->session_info->info->domain_name,
586 lp_path(talloc_tos(), snum));
587 if (!s) {
588 status = NT_STATUS_NO_MEMORY;
589 goto err_root_exit;
592 if (!set_conn_connectpath(conn,s)) {
593 TALLOC_FREE(s);
594 status = NT_STATUS_NO_MEMORY;
595 goto err_root_exit;
597 DBG_NOTICE("Connect path is '%s' for service [%s]\n", s,
598 lp_const_servicename(snum));
599 TALLOC_FREE(s);
603 * Set up the share security descriptor.
604 * NOTE - we use the *INCOMING USER* session_info
605 * here, as does (indirectly) change_to_user(),
606 * which can be called on any incoming packet.
607 * This way we set up the share access based
608 * on the authenticated user, not the forced
609 * user. See bug:
611 * https://bugzilla.samba.org/show_bug.cgi?id=9878
614 status = check_user_share_access(conn,
615 vuser->session_info,
616 &conn->share_access,
617 &conn->read_only);
618 if (!NT_STATUS_IS_OK(status)) {
619 goto err_root_exit;
622 /* Initialise VFS function pointers */
624 if (!smbd_vfs_init(conn)) {
625 DBG_ERR("vfs_init failed for service %s\n",
626 lp_const_servicename(snum));
627 status = NT_STATUS_BAD_NETWORK_NAME;
628 goto err_root_exit;
631 /* ROOT Activities: */
632 /* explicitly check widelinks here so that we can correctly warn
633 * in the logs. */
634 widelinks_warning(snum);
637 * Enforce the max connections parameter.
640 if ((lp_max_connections(snum) > 0)
641 && (count_current_connections(lp_const_servicename(SNUM(conn)), true) >=
642 lp_max_connections(snum))) {
644 DBG_WARNING("Max connections (%d) exceeded for %s\n",
645 lp_max_connections(snum),
646 lp_const_servicename(snum));
647 status = NT_STATUS_INSUFFICIENT_RESOURCES;
648 goto err_root_exit;
651 /* Invoke VFS make connection hook - this must be the first
652 filesystem operation that we do. */
654 if (SMB_VFS_CONNECT(conn, lp_const_servicename(snum),
655 conn->session_info->unix_info->unix_name) < 0) {
656 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
657 lp_const_servicename(snum), conn->connectpath,
658 strerror(errno));
659 status = NT_STATUS_UNSUCCESSFUL;
660 goto err_root_exit;
663 /* Any error exit after here needs to call the disconnect hook. */
664 on_err_call_dis_hook = true;
666 if ((!conn->printer) && (!conn->ipc) &&
667 lp_change_notify()) {
669 status = notify_init_sconn(sconn);
670 if (!NT_STATUS_IS_OK(status)) {
671 goto err_root_exit;
675 if (lp_kernel_oplocks(snum)) {
676 init_kernel_oplocks(conn->sconn);
680 * Fix compatibility issue pointed out by Volker.
681 * We pass the conn->connectpath to the preexec
682 * scripts as a parameter, so attempt to canonicalize
683 * it here before calling the preexec scripts.
684 * We ignore errors here, as it is possible that
685 * the conn->connectpath doesn't exist yet and
686 * the preexec scripts will create them.
689 (void)canonicalize_connect_path(conn);
691 /* Preexecs are done here as they might make the dir we are to ChDir
692 * to below */
693 /* execute any "root preexec = " line */
694 if (*lp_root_preexec(talloc_tos(), snum)) {
695 char *cmd = talloc_sub_advanced(talloc_tos(),
696 lp_const_servicename(SNUM(conn)),
697 conn->session_info->unix_info->unix_name,
698 conn->connectpath,
699 conn->session_info->unix_token->gid,
700 conn->session_info->unix_info->sanitized_username,
701 conn->session_info->info->domain_name,
702 lp_root_preexec(talloc_tos(), snum));
703 DEBUG(5,("cmd=%s\n",cmd));
704 ret = smbrun(cmd, NULL, NULL);
705 TALLOC_FREE(cmd);
706 if (ret != 0 && lp_root_preexec_close(snum)) {
707 DEBUG(1,("root preexec gave %d - failing "
708 "connection\n", ret));
709 status = NT_STATUS_ACCESS_DENIED;
710 goto err_root_exit;
714 /* USER Activites: */
715 if (!change_to_user(conn, conn->vuid)) {
716 /* No point continuing if they fail the basic checks */
717 DEBUG(0,("Can't become connected user!\n"));
718 status = NT_STATUS_LOGON_FAILURE;
719 goto err_root_exit;
722 effuid = geteuid();
723 effgid = getegid();
725 /* Remember that a different vuid can connect later without these
726 * checks... */
728 /* Preexecs are done here as they might make the dir we are to ChDir
729 * to below */
731 /* execute any "preexec = " line */
732 if (*lp_preexec(talloc_tos(), snum)) {
733 char *cmd = talloc_sub_advanced(talloc_tos(),
734 lp_const_servicename(SNUM(conn)),
735 conn->session_info->unix_info->unix_name,
736 conn->connectpath,
737 conn->session_info->unix_token->gid,
738 conn->session_info->unix_info->sanitized_username,
739 conn->session_info->info->domain_name,
740 lp_preexec(talloc_tos(), snum));
741 ret = smbrun(cmd, NULL, NULL);
742 TALLOC_FREE(cmd);
743 if (ret != 0 && lp_preexec_close(snum)) {
744 DEBUG(1,("preexec gave %d - failing connection\n",
745 ret));
746 status = NT_STATUS_ACCESS_DENIED;
747 goto err_root_exit;
751 #ifdef WITH_FAKE_KASERVER
752 if (lp_afs_share(snum)) {
753 afs_login(conn);
755 #endif
758 * we've finished with the user stuff - go back to root
759 * so the SMB_VFS_STAT call will only fail on path errors,
760 * not permission problems.
762 change_to_root_user();
763 /* ROOT Activites: */
766 * If widelinks are disallowed we need to canonicalise the connect
767 * path here to ensure we don't have any symlinks in the
768 * connectpath. We will be checking all paths on this connection are
769 * below this directory. We must do this after the VFS init as we
770 * depend on the realpath() pointer in the vfs table. JRA.
772 if (!lp_widelinks(snum)) {
773 if (!canonicalize_connect_path(conn)) {
774 DBG_ERR("canonicalize_connect_path failed "
775 "for service %s, path %s\n",
776 lp_const_servicename(snum),
777 conn->connectpath);
778 status = NT_STATUS_BAD_NETWORK_NAME;
779 goto err_root_exit;
783 /* Add veto/hide lists */
784 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
785 set_namearray( &conn->veto_list,
786 lp_veto_files(talloc_tos(), snum));
787 set_namearray( &conn->hide_list,
788 lp_hide_files(talloc_tos(), snum));
789 set_namearray( &conn->veto_oplock_list,
790 lp_veto_oplock_files(talloc_tos(), snum));
791 set_namearray( &conn->aio_write_behind_list,
792 lp_aio_write_behind(talloc_tos(), snum));
794 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
795 conn->connectpath,
796 NULL,
797 NULL,
799 if (smb_fname_cpath == NULL) {
800 status = NT_STATUS_NO_MEMORY;
801 goto err_root_exit;
804 /* win2000 does not check the permissions on the directory
805 during the tree connect, instead relying on permission
806 check during individual operations. To match this behaviour
807 I have disabled this chdir check (tridge) */
808 /* the alternative is just to check the directory exists */
810 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
811 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
812 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
813 DBG_ERR("'%s' is not a directory, when connecting to "
814 "[%s]\n", conn->connectpath,
815 lp_const_servicename(snum));
816 } else {
817 DBG_ERR("'%s' does not exist or permission denied "
818 "when connecting to [%s] Error was %s\n",
819 conn->connectpath,
820 lp_const_servicename(snum),
821 strerror(errno));
823 status = NT_STATUS_BAD_NETWORK_NAME;
824 goto err_root_exit;
826 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
828 talloc_free(conn->origpath);
829 conn->origpath = talloc_strdup(conn, conn->connectpath);
831 /* Figure out the characteristics of the underlying filesystem. This
832 * assumes that all the filesystem mounted withing a share path have
833 * the same characteristics, which is likely but not guaranteed.
836 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
839 * Print out the 'connected as' stuff here as we need
840 * to know the effective uid and gid we will be using
841 * (at least initially).
844 if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
845 dbgtext( "%s (%s) ", get_remote_machine_name(),
846 tsocket_address_string(conn->sconn->remote_address,
847 talloc_tos()) );
848 dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
849 dbgtext( "connect to service %s ",
850 lp_const_servicename(snum) );
851 dbgtext( "initially as user %s ",
852 conn->session_info->unix_info->unix_name );
853 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
854 dbgtext( "(pid %d)\n", (int)getpid() );
857 conn->tcon_done = true;
858 return NT_STATUS_OK;
860 err_root_exit:
862 TALLOC_FREE(smb_fname_cpath);
863 /* We must exit this function as root. */
864 if (geteuid() != 0) {
865 change_to_root_user();
867 if (on_err_call_dis_hook) {
868 /* Call VFS disconnect hook */
869 SMB_VFS_DISCONNECT(conn);
871 return status;
874 /****************************************************************************
875 Make a connection to a service from SMB1. Internal interface.
876 ****************************************************************************/
878 static connection_struct *make_connection_smb1(struct smb_request *req,
879 NTTIME now,
880 int snum, struct user_struct *vuser,
881 const char *pdev,
882 NTSTATUS *pstatus)
884 struct smbXsrv_tcon *tcon;
885 NTSTATUS status;
886 struct connection_struct *conn;
888 status = smb1srv_tcon_create(req->xconn, now, &tcon);
889 if (!NT_STATUS_IS_OK(status)) {
890 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
891 nt_errstr(status)));
892 *pstatus = status;
893 return NULL;
896 conn = conn_new(req->sconn);
897 if (!conn) {
898 TALLOC_FREE(tcon);
900 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
901 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
902 return NULL;
905 conn->cnum = tcon->global->tcon_wire_id;
906 conn->tcon = tcon;
908 *pstatus = make_connection_snum(req->xconn,
909 conn,
910 snum,
911 vuser,
912 pdev);
913 if (!NT_STATUS_IS_OK(*pstatus)) {
914 conn_free(conn);
915 TALLOC_FREE(tcon);
916 return NULL;
919 tcon->global->share_name = lp_servicename(tcon->global, SNUM(conn));
920 if (tcon->global->share_name == NULL) {
921 conn_free(conn);
922 TALLOC_FREE(tcon);
923 *pstatus = NT_STATUS_NO_MEMORY;
924 return NULL;
926 tcon->global->session_global_id =
927 vuser->session->global->session_global_id;
929 tcon->compat = talloc_move(tcon, &conn);
930 tcon->status = NT_STATUS_OK;
932 *pstatus = smbXsrv_tcon_update(tcon);
933 if (!NT_STATUS_IS_OK(*pstatus)) {
934 TALLOC_FREE(tcon);
935 return NULL;
938 return tcon->compat;
941 /****************************************************************************
942 Make a connection to a service from SMB2. External SMB2 interface.
943 We must set cnum before claiming connection.
944 ****************************************************************************/
946 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
947 struct smbXsrv_tcon *tcon,
948 int snum,
949 struct user_struct *vuser,
950 const char *pdev,
951 NTSTATUS *pstatus)
953 struct smbd_server_connection *sconn = req->sconn;
954 connection_struct *conn = conn_new(sconn);
955 if (!conn) {
956 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
957 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
958 return NULL;
961 conn->cnum = tcon->global->tcon_wire_id;
962 conn->tcon = tcon;
964 *pstatus = make_connection_snum(req->xconn,
965 conn,
966 snum,
967 vuser,
968 pdev);
969 if (!NT_STATUS_IS_OK(*pstatus)) {
970 conn_free(conn);
971 return NULL;
973 return conn;
976 /****************************************************************************
977 Make a connection to a service. External SMB1 interface.
979 * @param service
980 ****************************************************************************/
982 connection_struct *make_connection(struct smb_request *req,
983 NTTIME now,
984 const char *service_in,
985 const char *pdev, uint64_t vuid,
986 NTSTATUS *status)
988 struct smbd_server_connection *sconn = req->sconn;
989 uid_t euid;
990 struct user_struct *vuser = NULL;
991 char *service = NULL;
992 fstring dev;
993 int snum = -1;
995 fstrcpy(dev, pdev);
997 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
998 * root. */
999 if (!non_root_mode() && (euid = geteuid()) != 0) {
1000 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1001 "(%u)\n", (unsigned int)euid ));
1002 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1005 if (conn_num_open(sconn) > 2047) {
1006 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1007 return NULL;
1010 vuser = get_valid_user_struct(sconn, vuid);
1011 if (!vuser) {
1012 DEBUG(1,("make_connection: refusing to connect with "
1013 "no session setup\n"));
1014 *status = NT_STATUS_ACCESS_DENIED;
1015 return NULL;
1018 /* Logic to try and connect to the correct [homes] share, preferably
1019 without too many getpwnam() lookups. This is particulary nasty for
1020 winbind usernames, where the share name isn't the same as unix
1021 username.
1023 The snum of the homes share is stored on the vuser at session setup
1024 time.
1027 if (strequal(service_in,HOMES_NAME)) {
1028 if (vuser->homes_snum == -1) {
1029 DEBUG(2, ("[homes] share not available for "
1030 "this user because it was not found "
1031 "or created at session setup "
1032 "time\n"));
1033 *status = NT_STATUS_BAD_NETWORK_NAME;
1034 return NULL;
1036 DEBUG(5, ("making a connection to [homes] service "
1037 "created at session setup time\n"));
1038 return make_connection_smb1(req, now,
1039 vuser->homes_snum,
1040 vuser,
1041 dev, status);
1042 } else if ((vuser->homes_snum != -1)
1043 && strequal(service_in,
1044 lp_const_servicename(vuser->homes_snum))) {
1045 DEBUG(5, ("making a connection to 'homes' service [%s] "
1046 "created at session setup time\n", service_in));
1047 return make_connection_smb1(req, now,
1048 vuser->homes_snum,
1049 vuser,
1050 dev, status);
1053 service = talloc_strdup(talloc_tos(), service_in);
1054 if (!service) {
1055 *status = NT_STATUS_NO_MEMORY;
1056 return NULL;
1059 if (!strlower_m(service)) {
1060 DEBUG(2, ("strlower_m %s failed\n", service));
1061 *status = NT_STATUS_INVALID_PARAMETER;
1062 return NULL;
1065 snum = find_service(talloc_tos(), service, &service);
1066 if (!service) {
1067 *status = NT_STATUS_NO_MEMORY;
1068 return NULL;
1071 if (snum < 0) {
1072 if (strequal(service,"IPC$") ||
1073 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1074 DEBUG(3,("refusing IPC connection to %s\n", service));
1075 *status = NT_STATUS_ACCESS_DENIED;
1076 return NULL;
1079 DEBUG(3,("%s (%s) couldn't find service %s\n",
1080 get_remote_machine_name(),
1081 tsocket_address_string(
1082 sconn->remote_address, talloc_tos()),
1083 service));
1084 *status = NT_STATUS_BAD_NETWORK_NAME;
1085 return NULL;
1088 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1089 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum) != '\0')) {
1090 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1091 "(pointing to %s)\n",
1092 service, lp_msdfs_proxy(talloc_tos(), snum)));
1093 *status = NT_STATUS_BAD_NETWORK_NAME;
1094 return NULL;
1097 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1099 return make_connection_smb1(req, now, snum, vuser,
1100 dev, status);
1103 /****************************************************************************
1104 Close a cnum.
1105 ****************************************************************************/
1107 void close_cnum(connection_struct *conn, uint64_t vuid)
1109 char rootpath[2] = { '/', '\0'};
1110 struct smb_filename root_fname = { .base_name = rootpath };
1112 file_close_conn(conn);
1114 if (!IS_IPC(conn)) {
1115 dptr_closecnum(conn);
1118 change_to_root_user();
1120 DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1121 get_remote_machine_name(),
1122 tsocket_address_string(conn->sconn->remote_address,
1123 talloc_tos()),
1124 lp_const_servicename(SNUM(conn))));
1126 /* make sure we leave the directory available for unmount */
1127 vfs_ChDir(conn, &root_fname);
1129 /* Call VFS disconnect hook */
1130 SMB_VFS_DISCONNECT(conn);
1132 /* execute any "postexec = " line */
1133 if (*lp_postexec(talloc_tos(), SNUM(conn)) &&
1134 change_to_user(conn, vuid)) {
1135 char *cmd = talloc_sub_advanced(talloc_tos(),
1136 lp_const_servicename(SNUM(conn)),
1137 conn->session_info->unix_info->unix_name,
1138 conn->connectpath,
1139 conn->session_info->unix_token->gid,
1140 conn->session_info->unix_info->sanitized_username,
1141 conn->session_info->info->domain_name,
1142 lp_postexec(talloc_tos(), SNUM(conn)));
1143 smbrun(cmd, NULL, NULL);
1144 TALLOC_FREE(cmd);
1145 change_to_root_user();
1148 change_to_root_user();
1149 /* execute any "root postexec = " line */
1150 if (*lp_root_postexec(talloc_tos(), SNUM(conn))) {
1151 char *cmd = talloc_sub_advanced(talloc_tos(),
1152 lp_const_servicename(SNUM(conn)),
1153 conn->session_info->unix_info->unix_name,
1154 conn->connectpath,
1155 conn->session_info->unix_token->gid,
1156 conn->session_info->unix_info->sanitized_username,
1157 conn->session_info->info->domain_name,
1158 lp_root_postexec(talloc_tos(), SNUM(conn)));
1159 smbrun(cmd, NULL, NULL);
1160 TALLOC_FREE(cmd);
1163 conn_free(conn);