traffic_packets: provision request data for packet_drsuapi_13
[Samba.git] / source3 / smbd / service.c
blob75a47dee0caae891a5364ee00a858400250ad17c
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 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
69 lp_servicename(talloc_tos(), 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 bool set_current_service(connection_struct *conn, uint16_t flags, bool do_chdir)
95 int snum;
96 enum remote_arch_types ra_type;
98 if (!conn) {
99 last_conn = NULL;
100 return(False);
103 conn->lastused_count++;
105 snum = SNUM(conn);
108 struct smb_filename connectpath_fname = {
109 .base_name = conn->connectpath
111 struct smb_filename origpath_fname = {
112 .base_name = conn->origpath
115 if (do_chdir &&
116 vfs_ChDir(conn, &connectpath_fname) != 0 &&
117 vfs_ChDir(conn, &origpath_fname) != 0) {
118 DEBUG(((errno!=EACCES)?0:3),
119 ("chdir (%s) failed, reason: %s\n",
120 conn->connectpath, strerror(errno)));
121 return(False);
125 if ((conn == last_conn) && (last_flags == flags)) {
126 return(True);
129 last_conn = conn;
130 last_flags = flags;
133 * Obey the client case sensitivity requests - only for clients that
134 * support it. */
135 switch (lp_case_sensitive(snum)) {
136 case Auto:
138 * We need this uglyness due to DOS/Win9x clients that lie
139 * about case insensitivity. */
140 ra_type = get_remote_arch();
141 if (conn->sconn->using_smb2) {
142 conn->case_sensitive = false;
143 } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
145 * Client can't support per-packet case sensitive
146 * pathnames. */
147 conn->case_sensitive = false;
148 } else {
149 conn->case_sensitive =
150 !(flags & FLAG_CASELESS_PATHNAMES);
152 break;
153 case True:
154 conn->case_sensitive = true;
155 break;
156 default:
157 conn->case_sensitive = false;
158 break;
160 return true;
163 /****************************************************************************
164 do some basic sainity checks on the share.
165 This function modifies dev, ecode.
166 ****************************************************************************/
168 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
169 const char *rhost,
170 int snum,
171 fstring dev)
173 char *raddr;
175 raddr = tsocket_address_inet_addr_string(remote_address,
176 talloc_tos());
177 if (raddr == NULL) {
178 return NT_STATUS_NO_MEMORY;
181 if (!lp_snum_ok(snum) ||
182 !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
183 rhost, raddr)) {
184 return NT_STATUS_ACCESS_DENIED;
187 if (dev[0] == '?' || !dev[0]) {
188 if (lp_printable(snum)) {
189 fstrcpy(dev,"LPT1:");
190 } else if (strequal(lp_fstype(snum), "IPC")) {
191 fstrcpy(dev, "IPC");
192 } else {
193 fstrcpy(dev,"A:");
197 if (!strupper_m(dev)) {
198 DEBUG(2,("strupper_m %s failed\n", dev));
199 return NT_STATUS_INVALID_PARAMETER;
202 if (lp_printable(snum)) {
203 if (!strequal(dev, "LPT1:")) {
204 return NT_STATUS_BAD_DEVICE_TYPE;
206 } else if (strequal(lp_fstype(snum), "IPC")) {
207 if (!strequal(dev, "IPC")) {
208 return NT_STATUS_BAD_DEVICE_TYPE;
210 } else if (!strequal(dev, "A:")) {
211 return NT_STATUS_BAD_DEVICE_TYPE;
214 /* Behave as a printer if we are supposed to */
215 if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
216 fstrcpy(dev, "LPT1:");
219 return NT_STATUS_OK;
223 * Go through lookup_name etc to find the force'd group.
225 * Create a new token from src_token, replacing the primary group sid with the
226 * one found.
229 static NTSTATUS find_forced_group(bool force_user,
230 int snum, const char *username,
231 struct dom_sid *pgroup_sid,
232 gid_t *pgid)
234 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
235 TALLOC_CTX *frame = talloc_stackframe();
236 struct dom_sid group_sid;
237 enum lsa_SidType type;
238 char *groupname;
239 bool user_must_be_member = False;
240 gid_t gid;
242 groupname = lp_force_group(talloc_tos(), snum);
243 if (groupname == NULL) {
244 DEBUG(1, ("talloc_strdup failed\n"));
245 result = NT_STATUS_NO_MEMORY;
246 goto done;
249 if (groupname[0] == '+') {
250 user_must_be_member = True;
251 groupname += 1;
254 groupname = talloc_string_sub(talloc_tos(), groupname,
255 "%S", lp_servicename(talloc_tos(), snum));
256 if (groupname == NULL) {
257 DEBUG(1, ("talloc_string_sub failed\n"));
258 result = NT_STATUS_NO_MEMORY;
259 goto done;
262 if (!lookup_name_smbconf(talloc_tos(), groupname,
263 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
264 NULL, NULL, &group_sid, &type)) {
265 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
266 groupname));
267 goto done;
270 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
271 (type != SID_NAME_WKN_GRP)) {
272 DEBUG(10, ("%s is a %s, not a group\n", groupname,
273 sid_type_lookup(type)));
274 goto done;
277 if (!sid_to_gid(&group_sid, &gid)) {
278 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
279 sid_string_dbg(&group_sid), groupname));
280 goto done;
284 * If the user has been forced and the forced group starts with a '+',
285 * then we only set the group to be the forced group if the forced
286 * user is a member of that group. Otherwise, the meaning of the '+'
287 * would be ignored.
290 if (force_user && user_must_be_member) {
291 if (user_in_group_sid(username, &group_sid)) {
292 sid_copy(pgroup_sid, &group_sid);
293 *pgid = gid;
294 DEBUG(3,("Forced group %s for member %s\n",
295 groupname, username));
296 } else {
297 DEBUG(0,("find_forced_group: forced user %s is not a member "
298 "of forced group %s. Disallowing access.\n",
299 username, groupname ));
300 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
301 goto done;
303 } else {
304 sid_copy(pgroup_sid, &group_sid);
305 *pgid = gid;
306 DEBUG(3,("Forced group %s\n", groupname));
309 result = NT_STATUS_OK;
310 done:
311 TALLOC_FREE(frame);
312 return result;
315 /****************************************************************************
316 Create an auth_session_info structure for a connection_struct
317 ****************************************************************************/
319 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
320 TALLOC_CTX *mem_ctx, int snum,
321 struct auth_session_info *session_info,
322 struct auth_session_info **presult)
324 struct auth_session_info *result;
326 if (lp_guest_only(snum)) {
327 return make_session_info_guest(mem_ctx, presult);
331 * This is the normal security != share case where we have a
332 * valid vuid from the session setup. */
334 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
335 if (!lp_guest_ok(snum)) {
336 DEBUG(2, ("guest user (from session setup) "
337 "not permitted to access this share "
338 "(%s)\n", lp_servicename(talloc_tos(), snum)));
339 return NT_STATUS_ACCESS_DENIED;
341 } else {
342 if (!user_ok_token(session_info->unix_info->unix_name,
343 session_info->info->domain_name,
344 session_info->security_token, snum)) {
345 DEBUG(2, ("user '%s' (from session setup) not "
346 "permitted to access this share "
347 "(%s)\n",
348 session_info->unix_info->unix_name,
349 lp_servicename(talloc_tos(), snum)));
350 return NT_STATUS_ACCESS_DENIED;
354 result = copy_session_info(mem_ctx, session_info);
355 if (result == NULL) {
356 return NT_STATUS_NO_MEMORY;
359 *presult = result;
360 return NT_STATUS_OK;
363 /****************************************************************************
364 Set relevant user and group settings corresponding to force user/group
365 configuration for the given snum.
366 ****************************************************************************/
368 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
370 NTSTATUS status;
372 if (*lp_force_user(talloc_tos(), snum)) {
375 * Replace conn->session_info with a completely faked up one
376 * from the username we are forced into :-)
379 char *fuser;
380 char *sanitized_username;
381 struct auth_session_info *forced_serverinfo;
382 bool guest;
384 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), snum), "%S",
385 lp_const_servicename(snum));
386 if (fuser == NULL) {
387 return NT_STATUS_NO_MEMORY;
390 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
392 status = make_session_info_from_username(
393 conn, fuser,
394 guest,
395 &forced_serverinfo);
396 if (!NT_STATUS_IS_OK(status)) {
397 return status;
400 /* We don't want to replace the original sanitized_username
401 as it is the original user given in the connect attempt.
402 This is used in '%U' substitutions. */
403 sanitized_username = discard_const_p(char,
404 forced_serverinfo->unix_info->sanitized_username);
405 TALLOC_FREE(sanitized_username);
406 forced_serverinfo->unix_info->sanitized_username =
407 talloc_move(forced_serverinfo->unix_info,
408 &conn->session_info->unix_info->sanitized_username);
410 TALLOC_FREE(conn->session_info);
411 conn->session_info = forced_serverinfo;
413 conn->force_user = true;
414 DEBUG(3,("Forced user %s\n", fuser));
418 * If force group is true, then override
419 * any groupid stored for the connecting user.
422 if (*lp_force_group(talloc_tos(), snum)) {
424 status = find_forced_group(
425 conn->force_user, snum, conn->session_info->unix_info->unix_name,
426 &conn->session_info->security_token->sids[1],
427 &conn->session_info->unix_token->gid);
429 if (!NT_STATUS_IS_OK(status)) {
430 return status;
434 * We need to cache this gid, to use within
435 * change_to_user() separately from the conn->session_info
436 * struct. We only use conn->session_info directly if
437 * "force_user" was set.
439 conn->force_group_gid = conn->session_info->unix_token->gid;
442 return NT_STATUS_OK;
445 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
447 NTSTATUS status;
449 if (sconn->notify_ctx != NULL) {
450 return NT_STATUS_OK;
453 sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx, sconn->ev_ctx,
454 sconn, notify_callback);
455 if (sconn->notify_ctx == NULL) {
456 return NT_STATUS_NO_MEMORY;
459 status = messaging_register(sconn->msg_ctx, sconn,
460 MSG_SMB_NOTIFY_CANCEL_DELETED,
461 smbd_notify_cancel_deleted);
462 if (!NT_STATUS_IS_OK(status)) {
463 DBG_DEBUG("messaging_register failed: %s\n",
464 nt_errstr(status));
465 TALLOC_FREE(sconn->notify_ctx);
466 return status;
469 status = messaging_register(sconn->msg_ctx, sconn,
470 MSG_SMB_NOTIFY_STARTED,
471 smbd_notifyd_restarted);
472 if (!NT_STATUS_IS_OK(status)) {
473 DBG_DEBUG("messaging_register failed: %s\n",
474 nt_errstr(status));
475 messaging_deregister(sconn->msg_ctx,
476 MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
477 TALLOC_FREE(sconn->notify_ctx);
478 return status;
481 return NT_STATUS_OK;
484 /****************************************************************************
485 Make a connection, given the snum to connect to, and the vuser of the
486 connecting user if appropriate.
487 ****************************************************************************/
489 static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
490 connection_struct *conn,
491 int snum, struct user_struct *vuser,
492 const char *pdev)
494 struct smbd_server_connection *sconn = xconn->client->sconn;
495 struct smb_filename *smb_fname_cpath = NULL;
496 fstring dev;
497 int ret;
498 bool on_err_call_dis_hook = false;
499 uid_t effuid;
500 gid_t effgid;
501 NTSTATUS status;
503 fstrcpy(dev, pdev);
505 status = share_sanity_checks(sconn->remote_address,
506 sconn->remote_hostname,
507 snum,
508 dev);
509 if (NT_STATUS_IS_ERR(status)) {
510 goto err_root_exit;
513 conn->params->service = snum;
515 status = create_connection_session_info(sconn,
516 conn, snum, vuser->session_info,
517 &conn->session_info);
519 if (!NT_STATUS_IS_OK(status)) {
520 DEBUG(1, ("create_connection_session_info failed: %s\n",
521 nt_errstr(status)));
522 goto err_root_exit;
525 if (lp_guest_only(snum)) {
526 conn->force_user = true;
529 conn->num_files_open = 0;
530 conn->lastused = conn->lastused_count = time(NULL);
531 conn->printer = (strncmp(dev,"LPT",3) == 0);
532 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
533 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
535 /* Case options for the share. */
536 if (lp_case_sensitive(snum) == Auto) {
537 /* We will be setting this per packet. Set to be case
538 * insensitive for now. */
539 conn->case_sensitive = False;
540 } else {
541 conn->case_sensitive = (bool)lp_case_sensitive(snum);
544 conn->case_preserve = lp_preserve_case(snum);
545 conn->short_case_preserve = lp_short_preserve_case(snum);
547 conn->encrypt_level = lp_smb_encrypt(snum);
548 if (conn->encrypt_level > SMB_SIGNING_OFF) {
549 if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
550 if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
551 DBG_ERR("Service [%s] requires encryption, but "
552 "it is disabled globally!\n",
553 lp_servicename(talloc_tos(), snum));
554 status = NT_STATUS_ACCESS_DENIED;
555 goto err_root_exit;
557 conn->encrypt_level = SMB_SIGNING_OFF;
561 conn->veto_list = NULL;
562 conn->hide_list = NULL;
563 conn->veto_oplock_list = NULL;
564 conn->aio_write_behind_list = NULL;
566 conn->read_only = lp_read_only(SNUM(conn));
568 status = set_conn_force_user_group(conn, snum);
569 if (!NT_STATUS_IS_OK(status)) {
570 goto err_root_exit;
573 conn->vuid = vuser->vuid;
576 char *s = talloc_sub_advanced(talloc_tos(),
577 lp_servicename(talloc_tos(), SNUM(conn)),
578 conn->session_info->unix_info->unix_name,
579 conn->connectpath,
580 conn->session_info->unix_token->gid,
581 conn->session_info->unix_info->sanitized_username,
582 conn->session_info->info->domain_name,
583 lp_path(talloc_tos(), snum));
584 if (!s) {
585 status = NT_STATUS_NO_MEMORY;
586 goto err_root_exit;
589 if (!set_conn_connectpath(conn,s)) {
590 TALLOC_FREE(s);
591 status = NT_STATUS_NO_MEMORY;
592 goto err_root_exit;
594 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
595 lp_servicename(talloc_tos(), snum)));
596 TALLOC_FREE(s);
600 * Set up the share security descriptor.
601 * NOTE - we use the *INCOMING USER* session_info
602 * here, as does (indirectly) change_to_user(),
603 * which can be called on any incoming packet.
604 * This way we set up the share access based
605 * on the authenticated user, not the forced
606 * user. See bug:
608 * https://bugzilla.samba.org/show_bug.cgi?id=9878
611 status = check_user_share_access(conn,
612 vuser->session_info,
613 &conn->share_access,
614 &conn->read_only);
615 if (!NT_STATUS_IS_OK(status)) {
616 goto err_root_exit;
619 /* Initialise VFS function pointers */
621 if (!smbd_vfs_init(conn)) {
622 DEBUG(0, ("vfs_init failed for service %s\n",
623 lp_servicename(talloc_tos(), snum)));
624 status = NT_STATUS_BAD_NETWORK_NAME;
625 goto err_root_exit;
628 /* ROOT Activities: */
629 /* explicitly check widelinks here so that we can correctly warn
630 * in the logs. */
631 widelinks_warning(snum);
634 * Enforce the max connections parameter.
637 if ((lp_max_connections(snum) > 0)
638 && (count_current_connections(lp_servicename(talloc_tos(), SNUM(conn)), True) >=
639 lp_max_connections(snum))) {
641 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
642 lp_max_connections(snum),
643 lp_servicename(talloc_tos(), snum)));
644 status = NT_STATUS_INSUFFICIENT_RESOURCES;
645 goto err_root_exit;
648 /* Invoke VFS make connection hook - this must be the first
649 filesystem operation that we do. */
651 if (SMB_VFS_CONNECT(conn, lp_servicename(talloc_tos(), snum),
652 conn->session_info->unix_info->unix_name) < 0) {
653 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
654 lp_servicename(talloc_tos(), snum), conn->connectpath,
655 strerror(errno));
656 status = NT_STATUS_UNSUCCESSFUL;
657 goto err_root_exit;
660 /* Any error exit after here needs to call the disconnect hook. */
661 on_err_call_dis_hook = true;
663 if ((!conn->printer) && (!conn->ipc) &&
664 lp_change_notify()) {
666 status = notify_init_sconn(sconn);
667 if (!NT_STATUS_IS_OK(status)) {
668 goto err_root_exit;
672 if (lp_kernel_oplocks(snum)) {
673 init_kernel_oplocks(conn->sconn);
677 * Fix compatibility issue pointed out by Volker.
678 * We pass the conn->connectpath to the preexec
679 * scripts as a parameter, so attempt to canonicalize
680 * it here before calling the preexec scripts.
681 * We ignore errors here, as it is possible that
682 * the conn->connectpath doesn't exist yet and
683 * the preexec scripts will create them.
686 (void)canonicalize_connect_path(conn);
688 /* Preexecs are done here as they might make the dir we are to ChDir
689 * to below */
690 /* execute any "root preexec = " line */
691 if (*lp_root_preexec(talloc_tos(), snum)) {
692 char *cmd = talloc_sub_advanced(talloc_tos(),
693 lp_servicename(talloc_tos(), SNUM(conn)),
694 conn->session_info->unix_info->unix_name,
695 conn->connectpath,
696 conn->session_info->unix_token->gid,
697 conn->session_info->unix_info->sanitized_username,
698 conn->session_info->info->domain_name,
699 lp_root_preexec(talloc_tos(), snum));
700 DEBUG(5,("cmd=%s\n",cmd));
701 ret = smbrun(cmd, NULL, NULL);
702 TALLOC_FREE(cmd);
703 if (ret != 0 && lp_root_preexec_close(snum)) {
704 DEBUG(1,("root preexec gave %d - failing "
705 "connection\n", ret));
706 status = NT_STATUS_ACCESS_DENIED;
707 goto err_root_exit;
711 /* USER Activites: */
712 if (!change_to_user(conn, conn->vuid)) {
713 /* No point continuing if they fail the basic checks */
714 DEBUG(0,("Can't become connected user!\n"));
715 status = NT_STATUS_LOGON_FAILURE;
716 goto err_root_exit;
719 effuid = geteuid();
720 effgid = getegid();
722 /* Remember that a different vuid can connect later without these
723 * checks... */
725 /* Preexecs are done here as they might make the dir we are to ChDir
726 * to below */
728 /* execute any "preexec = " line */
729 if (*lp_preexec(talloc_tos(), snum)) {
730 char *cmd = talloc_sub_advanced(talloc_tos(),
731 lp_servicename(talloc_tos(), SNUM(conn)),
732 conn->session_info->unix_info->unix_name,
733 conn->connectpath,
734 conn->session_info->unix_token->gid,
735 conn->session_info->unix_info->sanitized_username,
736 conn->session_info->info->domain_name,
737 lp_preexec(talloc_tos(), snum));
738 ret = smbrun(cmd, NULL, NULL);
739 TALLOC_FREE(cmd);
740 if (ret != 0 && lp_preexec_close(snum)) {
741 DEBUG(1,("preexec gave %d - failing connection\n",
742 ret));
743 status = NT_STATUS_ACCESS_DENIED;
744 goto err_root_exit;
748 #ifdef WITH_FAKE_KASERVER
749 if (lp_afs_share(snum)) {
750 afs_login(conn);
752 #endif
755 * we've finished with the user stuff - go back to root
756 * so the SMB_VFS_STAT call will only fail on path errors,
757 * not permission problems.
759 change_to_root_user();
760 /* ROOT Activites: */
763 * If widelinks are disallowed we need to canonicalise the connect
764 * path here to ensure we don't have any symlinks in the
765 * connectpath. We will be checking all paths on this connection are
766 * below this directory. We must do this after the VFS init as we
767 * depend on the realpath() pointer in the vfs table. JRA.
769 if (!lp_widelinks(snum)) {
770 if (!canonicalize_connect_path(conn)) {
771 DEBUG(0, ("canonicalize_connect_path failed "
772 "for service %s, path %s\n",
773 lp_servicename(talloc_tos(), snum),
774 conn->connectpath));
775 status = NT_STATUS_BAD_NETWORK_NAME;
776 goto err_root_exit;
780 /* Add veto/hide lists */
781 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
782 set_namearray( &conn->veto_list,
783 lp_veto_files(talloc_tos(), snum));
784 set_namearray( &conn->hide_list,
785 lp_hide_files(talloc_tos(), snum));
786 set_namearray( &conn->veto_oplock_list,
787 lp_veto_oplock_files(talloc_tos(), snum));
788 set_namearray( &conn->aio_write_behind_list,
789 lp_aio_write_behind(talloc_tos(), snum));
791 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
792 conn->connectpath,
793 NULL,
794 NULL,
796 if (smb_fname_cpath == NULL) {
797 status = NT_STATUS_NO_MEMORY;
798 goto err_root_exit;
801 /* win2000 does not check the permissions on the directory
802 during the tree connect, instead relying on permission
803 check during individual operations. To match this behaviour
804 I have disabled this chdir check (tridge) */
805 /* the alternative is just to check the directory exists */
807 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
808 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
809 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
810 DEBUG(0,("'%s' is not a directory, when connecting to "
811 "[%s]\n", conn->connectpath,
812 lp_servicename(talloc_tos(), snum)));
813 } else {
814 DEBUG(0,("'%s' does not exist or permission denied "
815 "when connecting to [%s] Error was %s\n",
816 conn->connectpath,
817 lp_servicename(talloc_tos(), snum),
818 strerror(errno) ));
820 status = NT_STATUS_BAD_NETWORK_NAME;
821 goto err_root_exit;
823 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
825 talloc_free(conn->origpath);
826 conn->origpath = talloc_strdup(conn, conn->connectpath);
828 /* Figure out the characteristics of the underlying filesystem. This
829 * assumes that all the filesystem mounted withing a share path have
830 * the same characteristics, which is likely but not guaranteed.
833 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
836 * Print out the 'connected as' stuff here as we need
837 * to know the effective uid and gid we will be using
838 * (at least initially).
841 if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
842 dbgtext( "%s (%s) ", get_remote_machine_name(),
843 tsocket_address_string(conn->sconn->remote_address,
844 talloc_tos()) );
845 dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
846 dbgtext( "connect to service %s ",
847 lp_servicename(talloc_tos(), snum) );
848 dbgtext( "initially as user %s ",
849 conn->session_info->unix_info->unix_name );
850 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
851 dbgtext( "(pid %d)\n", (int)getpid() );
854 return status;
856 err_root_exit:
858 TALLOC_FREE(smb_fname_cpath);
859 /* We must exit this function as root. */
860 if (geteuid() != 0) {
861 change_to_root_user();
863 if (on_err_call_dis_hook) {
864 /* Call VFS disconnect hook */
865 SMB_VFS_DISCONNECT(conn);
867 return status;
870 /****************************************************************************
871 Make a connection to a service from SMB1. Internal interface.
872 ****************************************************************************/
874 static connection_struct *make_connection_smb1(struct smb_request *req,
875 NTTIME now,
876 int snum, struct user_struct *vuser,
877 const char *pdev,
878 NTSTATUS *pstatus)
880 struct smbXsrv_tcon *tcon;
881 NTSTATUS status;
882 struct connection_struct *conn;
884 status = smb1srv_tcon_create(req->xconn, now, &tcon);
885 if (!NT_STATUS_IS_OK(status)) {
886 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
887 nt_errstr(status)));
888 *pstatus = status;
889 return NULL;
892 conn = conn_new(req->sconn);
893 if (!conn) {
894 TALLOC_FREE(tcon);
896 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
897 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
898 return NULL;
901 conn->cnum = tcon->global->tcon_wire_id;
902 conn->tcon = tcon;
904 *pstatus = make_connection_snum(req->xconn,
905 conn,
906 snum,
907 vuser,
908 pdev);
909 if (!NT_STATUS_IS_OK(*pstatus)) {
910 conn_free(conn);
911 TALLOC_FREE(tcon);
912 return NULL;
915 tcon->global->share_name = lp_servicename(tcon->global, SNUM(conn));
916 if (tcon->global->share_name == NULL) {
917 conn_free(conn);
918 TALLOC_FREE(tcon);
919 *pstatus = NT_STATUS_NO_MEMORY;
920 return NULL;
922 tcon->global->session_global_id =
923 vuser->session->global->session_global_id;
925 tcon->compat = talloc_move(tcon, &conn);
926 tcon->status = NT_STATUS_OK;
928 *pstatus = smbXsrv_tcon_update(tcon);
929 if (!NT_STATUS_IS_OK(*pstatus)) {
930 TALLOC_FREE(tcon);
931 return NULL;
934 return tcon->compat;
937 /****************************************************************************
938 Make a connection to a service from SMB2. External SMB2 interface.
939 We must set cnum before claiming connection.
940 ****************************************************************************/
942 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
943 struct smbXsrv_tcon *tcon,
944 int snum,
945 struct user_struct *vuser,
946 const char *pdev,
947 NTSTATUS *pstatus)
949 struct smbd_server_connection *sconn = req->sconn;
950 connection_struct *conn = conn_new(sconn);
951 if (!conn) {
952 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
953 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
954 return NULL;
957 conn->cnum = tcon->global->tcon_wire_id;
958 conn->tcon = tcon;
960 *pstatus = make_connection_snum(req->xconn,
961 conn,
962 snum,
963 vuser,
964 pdev);
965 if (!NT_STATUS_IS_OK(*pstatus)) {
966 conn_free(conn);
967 return NULL;
969 return conn;
972 /****************************************************************************
973 Make a connection to a service. External SMB1 interface.
975 * @param service
976 ****************************************************************************/
978 connection_struct *make_connection(struct smb_request *req,
979 NTTIME now,
980 const char *service_in,
981 const char *pdev, uint64_t vuid,
982 NTSTATUS *status)
984 struct smbd_server_connection *sconn = req->sconn;
985 uid_t euid;
986 struct user_struct *vuser = NULL;
987 char *service = NULL;
988 fstring dev;
989 int snum = -1;
991 fstrcpy(dev, pdev);
993 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
994 * root. */
995 if (!non_root_mode() && (euid = geteuid()) != 0) {
996 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
997 "(%u)\n", (unsigned int)euid ));
998 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1001 if (conn_num_open(sconn) > 2047) {
1002 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1003 return NULL;
1006 vuser = get_valid_user_struct(sconn, vuid);
1007 if (!vuser) {
1008 DEBUG(1,("make_connection: refusing to connect with "
1009 "no session setup\n"));
1010 *status = NT_STATUS_ACCESS_DENIED;
1011 return NULL;
1014 /* Logic to try and connect to the correct [homes] share, preferably
1015 without too many getpwnam() lookups. This is particulary nasty for
1016 winbind usernames, where the share name isn't the same as unix
1017 username.
1019 The snum of the homes share is stored on the vuser at session setup
1020 time.
1023 if (strequal(service_in,HOMES_NAME)) {
1024 if (vuser->homes_snum == -1) {
1025 DEBUG(2, ("[homes] share not available for "
1026 "this user because it was not found "
1027 "or created at session setup "
1028 "time\n"));
1029 *status = NT_STATUS_BAD_NETWORK_NAME;
1030 return NULL;
1032 DEBUG(5, ("making a connection to [homes] service "
1033 "created at session setup time\n"));
1034 return make_connection_smb1(req, now,
1035 vuser->homes_snum,
1036 vuser,
1037 dev, status);
1038 } else if ((vuser->homes_snum != -1)
1039 && strequal(service_in,
1040 lp_servicename(talloc_tos(), vuser->homes_snum))) {
1041 DEBUG(5, ("making a connection to 'homes' service [%s] "
1042 "created at session setup time\n", service_in));
1043 return make_connection_smb1(req, now,
1044 vuser->homes_snum,
1045 vuser,
1046 dev, status);
1049 service = talloc_strdup(talloc_tos(), service_in);
1050 if (!service) {
1051 *status = NT_STATUS_NO_MEMORY;
1052 return NULL;
1055 if (!strlower_m(service)) {
1056 DEBUG(2, ("strlower_m %s failed\n", service));
1057 *status = NT_STATUS_INVALID_PARAMETER;
1058 return NULL;
1061 snum = find_service(talloc_tos(), service, &service);
1062 if (!service) {
1063 *status = NT_STATUS_NO_MEMORY;
1064 return NULL;
1067 if (snum < 0) {
1068 if (strequal(service,"IPC$") ||
1069 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1070 DEBUG(3,("refusing IPC connection to %s\n", service));
1071 *status = NT_STATUS_ACCESS_DENIED;
1072 return NULL;
1075 DEBUG(3,("%s (%s) couldn't find service %s\n",
1076 get_remote_machine_name(),
1077 tsocket_address_string(
1078 sconn->remote_address, talloc_tos()),
1079 service));
1080 *status = NT_STATUS_BAD_NETWORK_NAME;
1081 return NULL;
1084 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1085 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum) != '\0')) {
1086 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1087 "(pointing to %s)\n",
1088 service, lp_msdfs_proxy(talloc_tos(), snum)));
1089 *status = NT_STATUS_BAD_NETWORK_NAME;
1090 return NULL;
1093 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1095 return make_connection_smb1(req, now, snum, vuser,
1096 dev, status);
1099 /****************************************************************************
1100 Close a cnum.
1101 ****************************************************************************/
1103 void close_cnum(connection_struct *conn, uint64_t vuid)
1105 char rootpath[2] = { '/', '\0'};
1106 struct smb_filename root_fname = { .base_name = rootpath };
1108 file_close_conn(conn);
1110 if (!IS_IPC(conn)) {
1111 dptr_closecnum(conn);
1114 change_to_root_user();
1116 DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1117 get_remote_machine_name(),
1118 tsocket_address_string(conn->sconn->remote_address,
1119 talloc_tos()),
1120 lp_servicename(talloc_tos(), SNUM(conn))));
1122 /* make sure we leave the directory available for unmount */
1123 vfs_ChDir(conn, &root_fname);
1125 /* Call VFS disconnect hook */
1126 SMB_VFS_DISCONNECT(conn);
1128 /* execute any "postexec = " line */
1129 if (*lp_postexec(talloc_tos(), SNUM(conn)) &&
1130 change_to_user(conn, vuid)) {
1131 char *cmd = talloc_sub_advanced(talloc_tos(),
1132 lp_servicename(talloc_tos(), SNUM(conn)),
1133 conn->session_info->unix_info->unix_name,
1134 conn->connectpath,
1135 conn->session_info->unix_token->gid,
1136 conn->session_info->unix_info->sanitized_username,
1137 conn->session_info->info->domain_name,
1138 lp_postexec(talloc_tos(), SNUM(conn)));
1139 smbrun(cmd, NULL, NULL);
1140 TALLOC_FREE(cmd);
1141 change_to_root_user();
1144 change_to_root_user();
1145 /* execute any "root postexec = " line */
1146 if (*lp_root_postexec(talloc_tos(), SNUM(conn))) {
1147 char *cmd = talloc_sub_advanced(talloc_tos(),
1148 lp_servicename(talloc_tos(), SNUM(conn)),
1149 conn->session_info->unix_info->unix_name,
1150 conn->connectpath,
1151 conn->session_info->unix_token->gid,
1152 conn->session_info->unix_info->sanitized_username,
1153 conn->session_info->info->domain_name,
1154 lp_root_postexec(talloc_tos(), SNUM(conn)));
1155 smbrun(cmd, NULL, NULL);
1156 TALLOC_FREE(cmd);
1159 conn_free(conn);