s3: libsmb: Do some hardening in the receive processing of cli_shadow_copy_data_recv().
[Samba.git] / source3 / smbd / service.c
blob5b54aecd12f1ca774e019a74c294a74f525d5bca
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"
35 static bool canonicalize_connect_path(connection_struct *conn)
37 bool ret;
38 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath);
39 if (!resolved_name) {
40 return false;
42 ret = set_conn_connectpath(conn,resolved_name);
43 SAFE_FREE(resolved_name);
44 return ret;
47 /****************************************************************************
48 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
49 absolute path stating in / and not ending in /.
50 Observent people will notice a similarity between this and check_path_syntax :-).
51 ****************************************************************************/
53 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
55 char *destname;
56 char *d;
57 const char *s = connectpath;
58 bool start_of_name_component = true;
60 if (connectpath == NULL || connectpath[0] == '\0') {
61 return false;
64 /* Allocate for strlen + '\0' + possible leading '/' */
65 destname = (char *)talloc_size(conn, strlen(connectpath) + 2);
66 if (!destname) {
67 return false;
69 d = destname;
71 *d++ = '/'; /* Always start with root. */
73 while (*s) {
74 if (*s == '/') {
75 /* Eat multiple '/' */
76 while (*s == '/') {
77 s++;
79 if ((d > destname + 1) && (*s != '\0')) {
80 *d++ = '/';
82 start_of_name_component = True;
83 continue;
86 if (start_of_name_component) {
87 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
88 /* Uh oh - "/../" or "/..\0" ! */
90 /* Go past the ../ or .. */
91 if (s[2] == '/') {
92 s += 3;
93 } else {
94 s += 2; /* Go past the .. */
97 /* If we just added a '/' - delete it */
98 if ((d > destname) && (*(d-1) == '/')) {
99 *(d-1) = '\0';
100 d--;
103 /* Are we at the start ? Can't go back further if so. */
104 if (d <= destname) {
105 *d++ = '/'; /* Can't delete root */
106 continue;
108 /* Go back one level... */
109 /* Decrement d first as d points to the *next* char to write into. */
110 for (d--; d > destname; d--) {
111 if (*d == '/') {
112 break;
115 /* We're still at the start of a name component, just the previous one. */
116 continue;
117 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
118 /* Component of pathname can't be "." only - skip the '.' . */
119 if (s[1] == '/') {
120 s += 2;
121 } else {
122 s++;
124 continue;
128 if (!(*s & 0x80)) {
129 *d++ = *s++;
130 } else {
131 size_t siz;
132 /* Get the size of the next MB character. */
133 next_codepoint(s,&siz);
134 switch(siz) {
135 case 5:
136 *d++ = *s++;
137 /*fall through*/
138 case 4:
139 *d++ = *s++;
140 /*fall through*/
141 case 3:
142 *d++ = *s++;
143 /*fall through*/
144 case 2:
145 *d++ = *s++;
146 /*fall through*/
147 case 1:
148 *d++ = *s++;
149 break;
150 default:
151 break;
154 start_of_name_component = false;
156 *d = '\0';
158 /* And must not end in '/' */
159 if (d > destname + 1 && (*(d-1) == '/')) {
160 *(d-1) = '\0';
163 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
164 lp_servicename(talloc_tos(), SNUM(conn)), destname ));
166 talloc_free(conn->connectpath);
167 conn->connectpath = destname;
168 /* Ensure conn->cwd is initialized - start as conn->connectpath. */
169 TALLOC_FREE(conn->cwd);
170 conn->cwd = talloc_strdup(conn, conn->connectpath);
171 if (!conn->cwd) {
172 return false;
174 return true;
177 /****************************************************************************
178 Load parameters specific to a connection/service.
179 ****************************************************************************/
181 bool set_current_service(connection_struct *conn, uint16_t flags, bool do_chdir)
183 int snum;
184 enum remote_arch_types ra_type;
186 if (!conn) {
187 last_conn = NULL;
188 return(False);
191 conn->lastused_count++;
193 snum = SNUM(conn);
195 if (do_chdir &&
196 vfs_ChDir(conn,conn->connectpath) != 0 &&
197 vfs_ChDir(conn,conn->origpath) != 0) {
198 DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
199 conn->connectpath, strerror(errno)));
200 return(False);
203 if ((conn == last_conn) && (last_flags == flags)) {
204 return(True);
207 last_conn = conn;
208 last_flags = flags;
211 * Obey the client case sensitivity requests - only for clients that
212 * support it. */
213 switch (lp_case_sensitive(snum)) {
214 case Auto:
216 * We need this uglyness due to DOS/Win9x clients that lie
217 * about case insensitivity. */
218 ra_type = get_remote_arch();
219 if (conn->sconn->using_smb2) {
220 conn->case_sensitive = false;
221 } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
223 * Client can't support per-packet case sensitive
224 * pathnames. */
225 conn->case_sensitive = false;
226 } else {
227 conn->case_sensitive =
228 !(flags & FLAG_CASELESS_PATHNAMES);
230 break;
231 case True:
232 conn->case_sensitive = true;
233 break;
234 default:
235 conn->case_sensitive = false;
236 break;
238 return true;
241 /****************************************************************************
242 do some basic sainity checks on the share.
243 This function modifies dev, ecode.
244 ****************************************************************************/
246 static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
247 const char *rhost,
248 int snum,
249 fstring dev)
251 char *raddr;
253 raddr = tsocket_address_inet_addr_string(remote_address,
254 talloc_tos());
255 if (raddr == NULL) {
256 return NT_STATUS_NO_MEMORY;
259 if (!lp_snum_ok(snum) ||
260 !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
261 rhost, raddr)) {
262 return NT_STATUS_ACCESS_DENIED;
265 if (dev[0] == '?' || !dev[0]) {
266 if (lp_printable(snum)) {
267 fstrcpy(dev,"LPT1:");
268 } else if (strequal(lp_fstype(snum), "IPC")) {
269 fstrcpy(dev, "IPC");
270 } else {
271 fstrcpy(dev,"A:");
275 if (!strupper_m(dev)) {
276 DEBUG(2,("strupper_m %s failed\n", dev));
277 return NT_STATUS_INVALID_PARAMETER;
280 if (lp_printable(snum)) {
281 if (!strequal(dev, "LPT1:")) {
282 return NT_STATUS_BAD_DEVICE_TYPE;
284 } else if (strequal(lp_fstype(snum), "IPC")) {
285 if (!strequal(dev, "IPC")) {
286 return NT_STATUS_BAD_DEVICE_TYPE;
288 } else if (!strequal(dev, "A:")) {
289 return NT_STATUS_BAD_DEVICE_TYPE;
292 /* Behave as a printer if we are supposed to */
293 if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
294 fstrcpy(dev, "LPT1:");
297 return NT_STATUS_OK;
301 * Go through lookup_name etc to find the force'd group.
303 * Create a new token from src_token, replacing the primary group sid with the
304 * one found.
307 static NTSTATUS find_forced_group(bool force_user,
308 int snum, const char *username,
309 struct dom_sid *pgroup_sid,
310 gid_t *pgid)
312 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
313 TALLOC_CTX *frame = talloc_stackframe();
314 struct dom_sid group_sid;
315 enum lsa_SidType type;
316 char *groupname;
317 bool user_must_be_member = False;
318 gid_t gid;
320 groupname = lp_force_group(talloc_tos(), snum);
321 if (groupname == NULL) {
322 DEBUG(1, ("talloc_strdup failed\n"));
323 result = NT_STATUS_NO_MEMORY;
324 goto done;
327 if (groupname[0] == '+') {
328 user_must_be_member = True;
329 groupname += 1;
332 groupname = talloc_string_sub(talloc_tos(), groupname,
333 "%S", lp_servicename(talloc_tos(), snum));
334 if (groupname == NULL) {
335 DEBUG(1, ("talloc_string_sub failed\n"));
336 result = NT_STATUS_NO_MEMORY;
337 goto done;
340 if (!lookup_name_smbconf(talloc_tos(), groupname,
341 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
342 NULL, NULL, &group_sid, &type)) {
343 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
344 groupname));
345 goto done;
348 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
349 (type != SID_NAME_WKN_GRP)) {
350 DEBUG(10, ("%s is a %s, not a group\n", groupname,
351 sid_type_lookup(type)));
352 goto done;
355 if (!sid_to_gid(&group_sid, &gid)) {
356 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
357 sid_string_dbg(&group_sid), groupname));
358 goto done;
362 * If the user has been forced and the forced group starts with a '+',
363 * then we only set the group to be the forced group if the forced
364 * user is a member of that group. Otherwise, the meaning of the '+'
365 * would be ignored.
368 if (force_user && user_must_be_member) {
369 if (user_in_group_sid(username, &group_sid)) {
370 sid_copy(pgroup_sid, &group_sid);
371 *pgid = gid;
372 DEBUG(3,("Forced group %s for member %s\n",
373 groupname, username));
374 } else {
375 DEBUG(0,("find_forced_group: forced user %s is not a member "
376 "of forced group %s. Disallowing access.\n",
377 username, groupname ));
378 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
379 goto done;
381 } else {
382 sid_copy(pgroup_sid, &group_sid);
383 *pgid = gid;
384 DEBUG(3,("Forced group %s\n", groupname));
387 result = NT_STATUS_OK;
388 done:
389 TALLOC_FREE(frame);
390 return result;
393 /****************************************************************************
394 Create an auth_session_info structure for a connection_struct
395 ****************************************************************************/
397 static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
398 TALLOC_CTX *mem_ctx, int snum,
399 struct auth_session_info *session_info,
400 struct auth_session_info **presult)
402 struct auth_session_info *result;
404 if (lp_guest_only(snum)) {
405 return make_session_info_guest(mem_ctx, presult);
409 * This is the normal security != share case where we have a
410 * valid vuid from the session setup. */
412 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
413 if (!lp_guest_ok(snum)) {
414 DEBUG(2, ("guest user (from session setup) "
415 "not permitted to access this share "
416 "(%s)\n", lp_servicename(talloc_tos(), snum)));
417 return NT_STATUS_ACCESS_DENIED;
419 } else {
420 if (!user_ok_token(session_info->unix_info->unix_name,
421 session_info->info->domain_name,
422 session_info->security_token, snum)) {
423 DEBUG(2, ("user '%s' (from session setup) not "
424 "permitted to access this share "
425 "(%s)\n",
426 session_info->unix_info->unix_name,
427 lp_servicename(talloc_tos(), snum)));
428 return NT_STATUS_ACCESS_DENIED;
432 result = copy_session_info(mem_ctx, session_info);
433 if (result == NULL) {
434 return NT_STATUS_NO_MEMORY;
437 *presult = result;
438 return NT_STATUS_OK;
441 /****************************************************************************
442 Set relevant user and group settings corresponding to force user/group
443 configuration for the given snum.
444 ****************************************************************************/
446 NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
448 NTSTATUS status;
450 if (*lp_force_user(talloc_tos(), snum)) {
453 * Replace conn->session_info with a completely faked up one
454 * from the username we are forced into :-)
457 char *fuser;
458 char *sanitized_username;
459 struct auth_session_info *forced_serverinfo;
460 bool guest;
462 fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), snum), "%S",
463 lp_const_servicename(snum));
464 if (fuser == NULL) {
465 return NT_STATUS_NO_MEMORY;
468 guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
470 status = make_session_info_from_username(
471 conn, fuser,
472 guest,
473 &forced_serverinfo);
474 if (!NT_STATUS_IS_OK(status)) {
475 return status;
478 /* We don't want to replace the original sanitized_username
479 as it is the original user given in the connect attempt.
480 This is used in '%U' substitutions. */
481 sanitized_username = discard_const_p(char,
482 forced_serverinfo->unix_info->sanitized_username);
483 TALLOC_FREE(sanitized_username);
484 forced_serverinfo->unix_info->sanitized_username =
485 talloc_move(forced_serverinfo->unix_info,
486 &conn->session_info->unix_info->sanitized_username);
488 TALLOC_FREE(conn->session_info);
489 conn->session_info = forced_serverinfo;
491 conn->force_user = true;
492 DEBUG(3,("Forced user %s\n", fuser));
496 * If force group is true, then override
497 * any groupid stored for the connecting user.
500 if (*lp_force_group(talloc_tos(), snum)) {
502 status = find_forced_group(
503 conn->force_user, snum, conn->session_info->unix_info->unix_name,
504 &conn->session_info->security_token->sids[1],
505 &conn->session_info->unix_token->gid);
507 if (!NT_STATUS_IS_OK(status)) {
508 return status;
512 * We need to cache this gid, to use within
513 * change_to_user() separately from the conn->session_info
514 * struct. We only use conn->session_info directly if
515 * "force_user" was set.
517 conn->force_group_gid = conn->session_info->unix_token->gid;
520 return NT_STATUS_OK;
523 static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
525 NTSTATUS status;
527 if (sconn->notify_ctx != NULL) {
528 return NT_STATUS_OK;
531 sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx, sconn->ev_ctx,
532 sconn, notify_callback);
533 if (sconn->notify_ctx == NULL) {
534 return NT_STATUS_NO_MEMORY;
537 status = messaging_register(sconn->msg_ctx, sconn,
538 MSG_SMB_NOTIFY_CANCEL_DELETED,
539 smbd_notify_cancel_deleted);
540 if (!NT_STATUS_IS_OK(status)) {
541 DBG_DEBUG("messaging_register failed: %s\n",
542 nt_errstr(status));
543 TALLOC_FREE(sconn->notify_ctx);
544 return status;
547 status = messaging_register(sconn->msg_ctx, sconn,
548 MSG_SMB_NOTIFY_STARTED,
549 smbd_notifyd_restarted);
550 if (!NT_STATUS_IS_OK(status)) {
551 DBG_DEBUG("messaging_register failed: %s\n",
552 nt_errstr(status));
553 messaging_deregister(sconn->msg_ctx,
554 MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
555 TALLOC_FREE(sconn->notify_ctx);
556 return status;
559 return NT_STATUS_OK;
562 /****************************************************************************
563 Make a connection, given the snum to connect to, and the vuser of the
564 connecting user if appropriate.
565 ****************************************************************************/
567 static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
568 connection_struct *conn,
569 int snum, struct user_struct *vuser,
570 const char *pdev)
572 struct smbd_server_connection *sconn = xconn->client->sconn;
573 struct smb_filename *smb_fname_cpath = NULL;
574 fstring dev;
575 int ret;
576 bool on_err_call_dis_hook = false;
577 uid_t effuid;
578 gid_t effgid;
579 NTSTATUS status;
581 fstrcpy(dev, pdev);
583 status = share_sanity_checks(sconn->remote_address,
584 sconn->remote_hostname,
585 snum,
586 dev);
587 if (NT_STATUS_IS_ERR(status)) {
588 goto err_root_exit;
591 conn->params->service = snum;
593 status = create_connection_session_info(sconn,
594 conn, snum, vuser->session_info,
595 &conn->session_info);
597 if (!NT_STATUS_IS_OK(status)) {
598 DEBUG(1, ("create_connection_session_info failed: %s\n",
599 nt_errstr(status)));
600 goto err_root_exit;
603 if (lp_guest_only(snum)) {
604 conn->force_user = true;
607 conn->num_files_open = 0;
608 conn->lastused = conn->lastused_count = time(NULL);
609 conn->printer = (strncmp(dev,"LPT",3) == 0);
610 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
611 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
613 /* Case options for the share. */
614 if (lp_case_sensitive(snum) == Auto) {
615 /* We will be setting this per packet. Set to be case
616 * insensitive for now. */
617 conn->case_sensitive = False;
618 } else {
619 conn->case_sensitive = (bool)lp_case_sensitive(snum);
622 conn->case_preserve = lp_preserve_case(snum);
623 conn->short_case_preserve = lp_short_preserve_case(snum);
625 conn->encrypt_level = lp_smb_encrypt(snum);
627 conn->veto_list = NULL;
628 conn->hide_list = NULL;
629 conn->veto_oplock_list = NULL;
630 conn->aio_write_behind_list = NULL;
632 conn->read_only = lp_read_only(SNUM(conn));
634 status = set_conn_force_user_group(conn, snum);
635 if (!NT_STATUS_IS_OK(status)) {
636 goto err_root_exit;
639 conn->vuid = vuser->vuid;
642 char *s = talloc_sub_advanced(talloc_tos(),
643 lp_servicename(talloc_tos(), SNUM(conn)),
644 conn->session_info->unix_info->unix_name,
645 conn->connectpath,
646 conn->session_info->unix_token->gid,
647 conn->session_info->unix_info->sanitized_username,
648 conn->session_info->info->domain_name,
649 lp_path(talloc_tos(), snum));
650 if (!s) {
651 status = NT_STATUS_NO_MEMORY;
652 goto err_root_exit;
655 if (!set_conn_connectpath(conn,s)) {
656 TALLOC_FREE(s);
657 status = NT_STATUS_NO_MEMORY;
658 goto err_root_exit;
660 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
661 lp_servicename(talloc_tos(), snum)));
662 TALLOC_FREE(s);
666 * Set up the share security descriptor.
667 * NOTE - we use the *INCOMING USER* session_info
668 * here, as does (indirectly) change_to_user(),
669 * which can be called on any incoming packet.
670 * This way we set up the share access based
671 * on the authenticated user, not the forced
672 * user. See bug:
674 * https://bugzilla.samba.org/show_bug.cgi?id=9878
677 status = check_user_share_access(conn,
678 vuser->session_info,
679 &conn->share_access,
680 &conn->read_only);
681 if (!NT_STATUS_IS_OK(status)) {
682 goto err_root_exit;
685 /* Initialise VFS function pointers */
687 if (!smbd_vfs_init(conn)) {
688 DEBUG(0, ("vfs_init failed for service %s\n",
689 lp_servicename(talloc_tos(), snum)));
690 status = NT_STATUS_BAD_NETWORK_NAME;
691 goto err_root_exit;
694 /* ROOT Activities: */
695 /* explicitly check widelinks here so that we can correctly warn
696 * in the logs. */
697 widelinks_warning(snum);
700 * Enforce the max connections parameter.
703 if ((lp_max_connections(snum) > 0)
704 && (count_current_connections(lp_servicename(talloc_tos(), SNUM(conn)), True) >=
705 lp_max_connections(snum))) {
707 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
708 lp_max_connections(snum),
709 lp_servicename(talloc_tos(), snum)));
710 status = NT_STATUS_INSUFFICIENT_RESOURCES;
711 goto err_root_exit;
714 /* Invoke VFS make connection hook - this must be the first
715 filesystem operation that we do. */
717 if (SMB_VFS_CONNECT(conn, lp_servicename(talloc_tos(), snum),
718 conn->session_info->unix_info->unix_name) < 0) {
719 DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
720 lp_servicename(talloc_tos(), snum), conn->connectpath,
721 strerror(errno));
722 status = NT_STATUS_UNSUCCESSFUL;
723 goto err_root_exit;
726 /* Any error exit after here needs to call the disconnect hook. */
727 on_err_call_dis_hook = true;
729 if ((!conn->printer) && (!conn->ipc) &&
730 lp_change_notify()) {
732 status = notify_init_sconn(sconn);
733 if (!NT_STATUS_IS_OK(status)) {
734 goto err_root_exit;
738 if (lp_kernel_oplocks(snum)) {
739 init_kernel_oplocks(conn->sconn);
743 * Fix compatibility issue pointed out by Volker.
744 * We pass the conn->connectpath to the preexec
745 * scripts as a parameter, so attempt to canonicalize
746 * it here before calling the preexec scripts.
747 * We ignore errors here, as it is possible that
748 * the conn->connectpath doesn't exist yet and
749 * the preexec scripts will create them.
752 (void)canonicalize_connect_path(conn);
754 /* Preexecs are done here as they might make the dir we are to ChDir
755 * to below */
756 /* execute any "root preexec = " line */
757 if (*lp_root_preexec(talloc_tos(), snum)) {
758 char *cmd = talloc_sub_advanced(talloc_tos(),
759 lp_servicename(talloc_tos(), SNUM(conn)),
760 conn->session_info->unix_info->unix_name,
761 conn->connectpath,
762 conn->session_info->unix_token->gid,
763 conn->session_info->unix_info->sanitized_username,
764 conn->session_info->info->domain_name,
765 lp_root_preexec(talloc_tos(), snum));
766 DEBUG(5,("cmd=%s\n",cmd));
767 ret = smbrun(cmd,NULL);
768 TALLOC_FREE(cmd);
769 if (ret != 0 && lp_root_preexec_close(snum)) {
770 DEBUG(1,("root preexec gave %d - failing "
771 "connection\n", ret));
772 status = NT_STATUS_ACCESS_DENIED;
773 goto err_root_exit;
777 /* USER Activites: */
778 if (!change_to_user(conn, conn->vuid)) {
779 /* No point continuing if they fail the basic checks */
780 DEBUG(0,("Can't become connected user!\n"));
781 status = NT_STATUS_LOGON_FAILURE;
782 goto err_root_exit;
785 effuid = geteuid();
786 effgid = getegid();
788 /* Remember that a different vuid can connect later without these
789 * checks... */
791 /* Preexecs are done here as they might make the dir we are to ChDir
792 * to below */
794 /* execute any "preexec = " line */
795 if (*lp_preexec(talloc_tos(), snum)) {
796 char *cmd = talloc_sub_advanced(talloc_tos(),
797 lp_servicename(talloc_tos(), SNUM(conn)),
798 conn->session_info->unix_info->unix_name,
799 conn->connectpath,
800 conn->session_info->unix_token->gid,
801 conn->session_info->unix_info->sanitized_username,
802 conn->session_info->info->domain_name,
803 lp_preexec(talloc_tos(), snum));
804 ret = smbrun(cmd,NULL);
805 TALLOC_FREE(cmd);
806 if (ret != 0 && lp_preexec_close(snum)) {
807 DEBUG(1,("preexec gave %d - failing connection\n",
808 ret));
809 status = NT_STATUS_ACCESS_DENIED;
810 goto err_root_exit;
814 #ifdef WITH_FAKE_KASERVER
815 if (lp_afs_share(snum)) {
816 afs_login(conn);
818 #endif
821 * we've finished with the user stuff - go back to root
822 * so the SMB_VFS_STAT call will only fail on path errors,
823 * not permission problems.
825 change_to_root_user();
826 /* ROOT Activites: */
829 * If widelinks are disallowed we need to canonicalise the connect
830 * path here to ensure we don't have any symlinks in the
831 * connectpath. We will be checking all paths on this connection are
832 * below this directory. We must do this after the VFS init as we
833 * depend on the realpath() pointer in the vfs table. JRA.
835 if (!lp_widelinks(snum)) {
836 if (!canonicalize_connect_path(conn)) {
837 DEBUG(0, ("canonicalize_connect_path failed "
838 "for service %s, path %s\n",
839 lp_servicename(talloc_tos(), snum),
840 conn->connectpath));
841 status = NT_STATUS_BAD_NETWORK_NAME;
842 goto err_root_exit;
846 /* Add veto/hide lists */
847 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
848 set_namearray( &conn->veto_list,
849 lp_veto_files(talloc_tos(), snum));
850 set_namearray( &conn->hide_list,
851 lp_hide_files(talloc_tos(), snum));
852 set_namearray( &conn->veto_oplock_list,
853 lp_veto_oplock_files(talloc_tos(), snum));
854 set_namearray( &conn->aio_write_behind_list,
855 lp_aio_write_behind(talloc_tos(), snum));
857 smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
858 conn->connectpath,
859 NULL,
860 NULL,
862 if (smb_fname_cpath == NULL) {
863 status = NT_STATUS_NO_MEMORY;
864 goto err_root_exit;
867 /* win2000 does not check the permissions on the directory
868 during the tree connect, instead relying on permission
869 check during individual operations. To match this behaviour
870 I have disabled this chdir check (tridge) */
871 /* the alternative is just to check the directory exists */
873 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
874 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
875 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
876 DEBUG(0,("'%s' is not a directory, when connecting to "
877 "[%s]\n", conn->connectpath,
878 lp_servicename(talloc_tos(), snum)));
879 } else {
880 DEBUG(0,("'%s' does not exist or permission denied "
881 "when connecting to [%s] Error was %s\n",
882 conn->connectpath,
883 lp_servicename(talloc_tos(), snum),
884 strerror(errno) ));
886 status = NT_STATUS_BAD_NETWORK_NAME;
887 goto err_root_exit;
889 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
891 talloc_free(conn->origpath);
892 conn->origpath = talloc_strdup(conn, conn->connectpath);
894 /* Figure out the characteristics of the underlying filesystem. This
895 * assumes that all the filesystem mounted withing a share path have
896 * the same characteristics, which is likely but not guaranteed.
899 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
902 * Print out the 'connected as' stuff here as we need
903 * to know the effective uid and gid we will be using
904 * (at least initially).
907 if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
908 dbgtext( "%s (%s) ", get_remote_machine_name(),
909 tsocket_address_string(conn->sconn->remote_address,
910 talloc_tos()) );
911 dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
912 dbgtext( "connect to service %s ",
913 lp_servicename(talloc_tos(), snum) );
914 dbgtext( "initially as user %s ",
915 conn->session_info->unix_info->unix_name );
916 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
917 dbgtext( "(pid %d)\n", (int)getpid() );
920 return status;
922 err_root_exit:
924 TALLOC_FREE(smb_fname_cpath);
925 /* We must exit this function as root. */
926 if (geteuid() != 0) {
927 change_to_root_user();
929 if (on_err_call_dis_hook) {
930 /* Call VFS disconnect hook */
931 SMB_VFS_DISCONNECT(conn);
933 return status;
936 /****************************************************************************
937 Make a connection to a service from SMB1. Internal interface.
938 ****************************************************************************/
940 static connection_struct *make_connection_smb1(struct smb_request *req,
941 NTTIME now,
942 int snum, struct user_struct *vuser,
943 const char *pdev,
944 NTSTATUS *pstatus)
946 struct smbXsrv_tcon *tcon;
947 NTSTATUS status;
948 struct connection_struct *conn;
950 status = smb1srv_tcon_create(req->xconn, now, &tcon);
951 if (!NT_STATUS_IS_OK(status)) {
952 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
953 nt_errstr(status)));
954 *pstatus = status;
955 return NULL;
958 conn = conn_new(req->sconn);
959 if (!conn) {
960 TALLOC_FREE(tcon);
962 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
963 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
964 return NULL;
967 conn->cnum = tcon->global->tcon_wire_id;
968 conn->tcon = tcon;
970 *pstatus = make_connection_snum(req->xconn,
971 conn,
972 snum,
973 vuser,
974 pdev);
975 if (!NT_STATUS_IS_OK(*pstatus)) {
976 conn_free(conn);
977 TALLOC_FREE(tcon);
978 return NULL;
981 tcon->global->share_name = lp_servicename(tcon->global, SNUM(conn));
982 if (tcon->global->share_name == NULL) {
983 conn_free(conn);
984 TALLOC_FREE(tcon);
985 *pstatus = NT_STATUS_NO_MEMORY;
986 return NULL;
988 tcon->global->session_global_id =
989 vuser->session->global->session_global_id;
991 tcon->compat = talloc_move(tcon, &conn);
992 tcon->status = NT_STATUS_OK;
994 *pstatus = smbXsrv_tcon_update(tcon);
995 if (!NT_STATUS_IS_OK(*pstatus)) {
996 TALLOC_FREE(tcon);
997 return NULL;
1000 return tcon->compat;
1003 /****************************************************************************
1004 Make a connection to a service from SMB2. External SMB2 interface.
1005 We must set cnum before claiming connection.
1006 ****************************************************************************/
1008 connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
1009 struct smbXsrv_tcon *tcon,
1010 int snum,
1011 struct user_struct *vuser,
1012 const char *pdev,
1013 NTSTATUS *pstatus)
1015 struct smbd_server_connection *sconn = req->sconn;
1016 connection_struct *conn = conn_new(sconn);
1017 if (!conn) {
1018 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
1019 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
1020 return NULL;
1023 conn->cnum = tcon->global->tcon_wire_id;
1024 conn->tcon = tcon;
1026 *pstatus = make_connection_snum(req->xconn,
1027 conn,
1028 snum,
1029 vuser,
1030 pdev);
1031 if (!NT_STATUS_IS_OK(*pstatus)) {
1032 conn_free(conn);
1033 return NULL;
1035 return conn;
1038 /****************************************************************************
1039 Make a connection to a service. External SMB1 interface.
1041 * @param service
1042 ****************************************************************************/
1044 connection_struct *make_connection(struct smb_request *req,
1045 NTTIME now,
1046 const char *service_in,
1047 const char *pdev, uint64_t vuid,
1048 NTSTATUS *status)
1050 struct smbd_server_connection *sconn = req->sconn;
1051 uid_t euid;
1052 struct user_struct *vuser = NULL;
1053 char *service = NULL;
1054 fstring dev;
1055 int snum = -1;
1057 fstrcpy(dev, pdev);
1059 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1060 * root. */
1061 if (!non_root_mode() && (euid = geteuid()) != 0) {
1062 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1063 "(%u)\n", (unsigned int)euid ));
1064 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1067 if (conn_num_open(sconn) > 2047) {
1068 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1069 return NULL;
1072 vuser = get_valid_user_struct(sconn, vuid);
1073 if (!vuser) {
1074 DEBUG(1,("make_connection: refusing to connect with "
1075 "no session setup\n"));
1076 *status = NT_STATUS_ACCESS_DENIED;
1077 return NULL;
1080 /* Logic to try and connect to the correct [homes] share, preferably
1081 without too many getpwnam() lookups. This is particulary nasty for
1082 winbind usernames, where the share name isn't the same as unix
1083 username.
1085 The snum of the homes share is stored on the vuser at session setup
1086 time.
1089 if (strequal(service_in,HOMES_NAME)) {
1090 if (vuser->homes_snum == -1) {
1091 DEBUG(2, ("[homes] share not available for "
1092 "this user because it was not found "
1093 "or created at session setup "
1094 "time\n"));
1095 *status = NT_STATUS_BAD_NETWORK_NAME;
1096 return NULL;
1098 DEBUG(5, ("making a connection to [homes] service "
1099 "created at session setup time\n"));
1100 return make_connection_smb1(req, now,
1101 vuser->homes_snum,
1102 vuser,
1103 dev, status);
1104 } else if ((vuser->homes_snum != -1)
1105 && strequal(service_in,
1106 lp_servicename(talloc_tos(), vuser->homes_snum))) {
1107 DEBUG(5, ("making a connection to 'homes' service [%s] "
1108 "created at session setup time\n", service_in));
1109 return make_connection_smb1(req, now,
1110 vuser->homes_snum,
1111 vuser,
1112 dev, status);
1115 service = talloc_strdup(talloc_tos(), service_in);
1116 if (!service) {
1117 *status = NT_STATUS_NO_MEMORY;
1118 return NULL;
1121 if (!strlower_m(service)) {
1122 DEBUG(2, ("strlower_m %s failed\n", service));
1123 *status = NT_STATUS_INVALID_PARAMETER;
1124 return NULL;
1127 snum = find_service(talloc_tos(), service, &service);
1128 if (!service) {
1129 *status = NT_STATUS_NO_MEMORY;
1130 return NULL;
1133 if (snum < 0) {
1134 if (strequal(service,"IPC$") ||
1135 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1136 DEBUG(3,("refusing IPC connection to %s\n", service));
1137 *status = NT_STATUS_ACCESS_DENIED;
1138 return NULL;
1141 DEBUG(3,("%s (%s) couldn't find service %s\n",
1142 get_remote_machine_name(),
1143 tsocket_address_string(
1144 sconn->remote_address, talloc_tos()),
1145 service));
1146 *status = NT_STATUS_BAD_NETWORK_NAME;
1147 return NULL;
1150 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1151 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum) != '\0')) {
1152 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1153 "(pointing to %s)\n",
1154 service, lp_msdfs_proxy(talloc_tos(), snum)));
1155 *status = NT_STATUS_BAD_NETWORK_NAME;
1156 return NULL;
1159 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1161 return make_connection_smb1(req, now, snum, vuser,
1162 dev, status);
1165 /****************************************************************************
1166 Close a cnum.
1167 ****************************************************************************/
1169 void close_cnum(connection_struct *conn, uint64_t vuid)
1171 file_close_conn(conn);
1173 if (!IS_IPC(conn)) {
1174 dptr_closecnum(conn);
1177 change_to_root_user();
1179 DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1180 get_remote_machine_name(),
1181 tsocket_address_string(conn->sconn->remote_address,
1182 talloc_tos()),
1183 lp_servicename(talloc_tos(), SNUM(conn))));
1185 /* make sure we leave the directory available for unmount */
1186 vfs_ChDir(conn, "/");
1188 /* Call VFS disconnect hook */
1189 SMB_VFS_DISCONNECT(conn);
1191 /* execute any "postexec = " line */
1192 if (*lp_postexec(talloc_tos(), SNUM(conn)) &&
1193 change_to_user(conn, vuid)) {
1194 char *cmd = talloc_sub_advanced(talloc_tos(),
1195 lp_servicename(talloc_tos(), SNUM(conn)),
1196 conn->session_info->unix_info->unix_name,
1197 conn->connectpath,
1198 conn->session_info->unix_token->gid,
1199 conn->session_info->unix_info->sanitized_username,
1200 conn->session_info->info->domain_name,
1201 lp_postexec(talloc_tos(), SNUM(conn)));
1202 smbrun(cmd,NULL);
1203 TALLOC_FREE(cmd);
1204 change_to_root_user();
1207 change_to_root_user();
1208 /* execute any "root postexec = " line */
1209 if (*lp_root_postexec(talloc_tos(), SNUM(conn))) {
1210 char *cmd = talloc_sub_advanced(talloc_tos(),
1211 lp_servicename(talloc_tos(), SNUM(conn)),
1212 conn->session_info->unix_info->unix_name,
1213 conn->connectpath,
1214 conn->session_info->unix_token->gid,
1215 conn->session_info->unix_info->sanitized_username,
1216 conn->session_info->info->domain_name,
1217 lp_root_postexec(talloc_tos(), SNUM(conn)));
1218 smbrun(cmd,NULL);
1219 TALLOC_FREE(cmd);
1222 conn_free(conn);