Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : service (connection) opening and closing
4 : Copyright (C) Andrew Tridgell 1992-1998
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "system/filesys.h"
22 : #include "system/passwd.h" /* uid_wrapper */
23 : #include "../lib/tsocket/tsocket.h"
24 : #include "smbd/smbd.h"
25 : #include "smbd/globals.h"
26 : #include "../librpc/gen_ndr/netlogon.h"
27 : #include "../libcli/security/security.h"
28 : #include "printing/pcap.h"
29 : #include "passdb/lookup_sid.h"
30 : #include "auth.h"
31 : #include "../auth/auth_util.h"
32 : #include "lib/param/loadparm.h"
33 : #include "messages.h"
34 : #include "lib/afs/afs_funcs.h"
35 : #include "lib/util_path.h"
36 : #include "lib/util/string_wrappers.h"
37 : #include "source3/lib/substitute.h"
38 :
39 13589 : bool canonicalize_connect_path(connection_struct *conn)
40 : {
41 : bool ret;
42 13589 : struct smb_filename con_fname = { .base_name = conn->connectpath };
43 13589 : struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
44 : &con_fname);
45 13589 : if (resolved_fname == NULL) {
46 0 : return false;
47 : }
48 13589 : ret = set_conn_connectpath(conn,resolved_fname->base_name);
49 13589 : TALLOC_FREE(resolved_fname);
50 13589 : return ret;
51 : }
52 :
53 : /****************************************************************************
54 : Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
55 : absolute path stating in / and not ending in /.
56 : ****************************************************************************/
57 :
58 21555 : bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
59 : {
60 : char *destname;
61 :
62 21555 : if (connectpath == NULL || connectpath[0] == '\0') {
63 0 : return false;
64 : }
65 :
66 21555 : destname = canonicalize_absolute_path(conn, connectpath);
67 21555 : if (destname == NULL) {
68 0 : return false;
69 : }
70 :
71 21555 : DBG_DEBUG("service %s, connectpath = %s\n",
72 : lp_const_servicename(SNUM(conn)), destname);
73 :
74 21555 : talloc_free(conn->connectpath);
75 21555 : conn->connectpath = destname;
76 : /*
77 : * Ensure conn->cwd_fsp->fsp_name is initialized.
78 : * start as conn->connectpath.
79 : */
80 21555 : TALLOC_FREE(conn->cwd_fsp->fsp_name);
81 28220 : conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn,
82 21555 : conn->connectpath,
83 : NULL,
84 : NULL,
85 : 0,
86 : 0);
87 21555 : if (conn->cwd_fsp->fsp_name == NULL) {
88 0 : return false;
89 : }
90 21555 : return true;
91 : }
92 :
93 : /****************************************************************************
94 : Load parameters specific to a connection/service.
95 : ****************************************************************************/
96 :
97 12 : void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
98 : {
99 : int snum;
100 : enum remote_arch_types ra_type;
101 :
102 12 : SMB_ASSERT(conn != NULL);
103 :
104 12 : snum = SNUM(conn);
105 :
106 12 : if ((conn == last_conn) && (last_flags == flags)) {
107 2 : return;
108 : }
109 :
110 10 : last_conn = conn;
111 10 : last_flags = flags;
112 :
113 : /*
114 : * Obey the client case sensitivity requests - only for clients that
115 : * support it. */
116 10 : switch (lp_case_sensitive(snum)) {
117 10 : case Auto:
118 : /*
119 : * We need this uglyness due to DOS/Win9x clients that lie
120 : * about case insensitivity. */
121 10 : ra_type = get_remote_arch();
122 10 : if (conn->sconn->using_smb2) {
123 0 : conn->case_sensitive = false;
124 10 : } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
125 : /*
126 : * Client can't support per-packet case sensitive
127 : * pathnames. */
128 0 : conn->case_sensitive = false;
129 : } else {
130 10 : conn->case_sensitive =
131 10 : !(flags & FLAG_CASELESS_PATHNAMES);
132 : }
133 10 : break;
134 0 : case True:
135 0 : conn->case_sensitive = true;
136 0 : break;
137 0 : default:
138 0 : conn->case_sensitive = false;
139 0 : break;
140 : }
141 10 : return;
142 : }
143 :
144 139479 : bool chdir_current_service(connection_struct *conn)
145 : {
146 247605 : const struct smb_filename connectpath_fname = {
147 139479 : .base_name = conn->connectpath,
148 : };
149 139479 : int saved_errno = 0;
150 139479 : char *utok_str = NULL;
151 : int ret;
152 :
153 139479 : conn->lastused_count++;
154 :
155 139479 : ret = vfs_ChDir(conn, &connectpath_fname);
156 139479 : if (ret == 0) {
157 139447 : return true;
158 : }
159 32 : saved_errno = errno;
160 :
161 32 : utok_str = utok_string(talloc_tos(),
162 32 : conn->session_info->unix_token);
163 32 : if (utok_str == NULL) {
164 0 : errno = saved_errno;
165 0 : return false;
166 : }
167 :
168 32 : DBG_ERR("vfs_ChDir(%s) failed: %s. Current token: %s\n",
169 : conn->connectpath,
170 : strerror(saved_errno),
171 : utok_str);
172 :
173 32 : if (saved_errno != 0) {
174 32 : errno = saved_errno;
175 : }
176 32 : return false;
177 : }
178 :
179 : /****************************************************************************
180 : do some basic sainity checks on the share.
181 : This function modifies dev, ecode.
182 : ****************************************************************************/
183 :
184 5635 : static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
185 : const char *rhost,
186 : int snum,
187 : fstring dev)
188 : {
189 : char *raddr;
190 :
191 5635 : raddr = tsocket_address_inet_addr_string(remote_address,
192 : talloc_tos());
193 5635 : if (raddr == NULL) {
194 0 : return NT_STATUS_NO_MEMORY;
195 : }
196 :
197 9457 : if (!lp_snum_ok(snum) ||
198 5635 : !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
199 : rhost, raddr)) {
200 0 : return NT_STATUS_ACCESS_DENIED;
201 : }
202 :
203 5635 : if (dev[0] == '?' || !dev[0]) {
204 5635 : if (lp_printable(snum)) {
205 0 : fstrcpy(dev,"LPT1:");
206 5635 : } else if (strequal(lp_fstype(snum), "IPC")) {
207 4069 : fstrcpy(dev, "IPC");
208 : } else {
209 1566 : fstrcpy(dev,"A:");
210 : }
211 : }
212 :
213 5635 : if (!strupper_m(dev)) {
214 0 : DEBUG(2,("strupper_m %s failed\n", dev));
215 0 : return NT_STATUS_INVALID_PARAMETER;
216 : }
217 :
218 5635 : if (lp_printable(snum)) {
219 0 : if (!strequal(dev, "LPT1:")) {
220 0 : return NT_STATUS_BAD_DEVICE_TYPE;
221 : }
222 5635 : } else if (strequal(lp_fstype(snum), "IPC")) {
223 4069 : if (!strequal(dev, "IPC")) {
224 0 : return NT_STATUS_BAD_DEVICE_TYPE;
225 : }
226 1566 : } else if (!strequal(dev, "A:")) {
227 0 : return NT_STATUS_BAD_DEVICE_TYPE;
228 : }
229 :
230 : /* Behave as a printer if we are supposed to */
231 5635 : if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
232 0 : fstrcpy(dev, "LPT1:");
233 : }
234 :
235 5635 : return NT_STATUS_OK;
236 : }
237 :
238 : /*
239 : * Go through lookup_name etc to find the force'd group.
240 : *
241 : * Create a new token from src_token, replacing the primary group sid with the
242 : * one found.
243 : */
244 :
245 42 : static NTSTATUS find_forced_group(bool force_user,
246 : int snum, const char *username,
247 : struct dom_sid *pgroup_sid,
248 : gid_t *pgid)
249 : {
250 42 : NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
251 42 : TALLOC_CTX *frame = talloc_stackframe();
252 23 : const struct loadparm_substitution *lp_sub =
253 19 : loadparm_s3_global_substitution();
254 : struct dom_sid group_sid;
255 : enum lsa_SidType type;
256 : char *groupname;
257 42 : bool user_must_be_member = False;
258 : gid_t gid;
259 :
260 42 : groupname = lp_force_group(talloc_tos(), lp_sub, snum);
261 42 : if (groupname == NULL) {
262 0 : DEBUG(1, ("talloc_strdup failed\n"));
263 0 : result = NT_STATUS_NO_MEMORY;
264 0 : goto done;
265 : }
266 :
267 42 : if (groupname[0] == '+') {
268 0 : user_must_be_member = True;
269 0 : groupname += 1;
270 : }
271 :
272 42 : groupname = talloc_string_sub(talloc_tos(), groupname,
273 : "%S", lp_const_servicename(snum));
274 42 : if (groupname == NULL) {
275 0 : DEBUG(1, ("talloc_string_sub failed\n"));
276 0 : result = NT_STATUS_NO_MEMORY;
277 0 : goto done;
278 : }
279 :
280 42 : if (!lookup_name_smbconf(talloc_tos(), groupname,
281 : LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
282 : NULL, NULL, &group_sid, &type)) {
283 0 : DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
284 : groupname));
285 0 : goto done;
286 : }
287 :
288 42 : if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
289 0 : (type != SID_NAME_WKN_GRP)) {
290 0 : DEBUG(10, ("%s is a %s, not a group\n", groupname,
291 : sid_type_lookup(type)));
292 0 : goto done;
293 : }
294 :
295 42 : if (!sid_to_gid(&group_sid, &gid)) {
296 : struct dom_sid_buf buf;
297 0 : DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
298 : dom_sid_str_buf(&group_sid, &buf), groupname));
299 0 : goto done;
300 : }
301 :
302 : /*
303 : * If the user has been forced and the forced group starts with a '+',
304 : * then we only set the group to be the forced group if the forced
305 : * user is a member of that group. Otherwise, the meaning of the '+'
306 : * would be ignored.
307 : */
308 :
309 42 : if (force_user && user_must_be_member) {
310 0 : if (user_in_group_sid(username, &group_sid)) {
311 0 : sid_copy(pgroup_sid, &group_sid);
312 0 : *pgid = gid;
313 0 : DEBUG(3,("Forced group %s for member %s\n",
314 : groupname, username));
315 : } else {
316 0 : DEBUG(0,("find_forced_group: forced user %s is not a member "
317 : "of forced group %s. Disallowing access.\n",
318 : username, groupname ));
319 0 : result = NT_STATUS_MEMBER_NOT_IN_GROUP;
320 0 : goto done;
321 : }
322 : } else {
323 42 : sid_copy(pgroup_sid, &group_sid);
324 42 : *pgid = gid;
325 42 : DEBUG(3,("Forced group %s\n", groupname));
326 : }
327 :
328 42 : result = NT_STATUS_OK;
329 42 : done:
330 42 : TALLOC_FREE(frame);
331 42 : return result;
332 : }
333 :
334 : /****************************************************************************
335 : Create an auth_session_info structure for a connection_struct
336 : ****************************************************************************/
337 :
338 5635 : static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
339 : TALLOC_CTX *mem_ctx, int snum,
340 : struct auth_session_info *session_info,
341 : struct auth_session_info **presult)
342 : {
343 : struct auth_session_info *result;
344 :
345 5635 : if (lp_guest_only(snum)) {
346 42 : return make_session_info_guest(mem_ctx, presult);
347 : }
348 :
349 : /*
350 : * This is the normal security != share case where we have a
351 : * valid vuid from the session setup. */
352 :
353 5593 : if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
354 469 : if (!lp_guest_ok(snum)) {
355 0 : DBG_WARNING("guest user (from session setup) "
356 : "not permitted to access this share "
357 : "(%s)\n", lp_const_servicename(snum));
358 0 : return NT_STATUS_ACCESS_DENIED;
359 : }
360 : } else {
361 5124 : if (!user_ok_token(session_info->unix_info->unix_name,
362 5124 : session_info->info->domain_name,
363 5124 : session_info->security_token, snum)) {
364 12 : DBG_WARNING("user '%s' (from session setup) not "
365 : "permitted to access this share "
366 : "(%s)\n",
367 : session_info->unix_info->unix_name,
368 : lp_const_servicename(snum));
369 12 : return NT_STATUS_ACCESS_DENIED;
370 : }
371 : }
372 :
373 5581 : result = copy_session_info(mem_ctx, session_info);
374 5581 : if (result == NULL) {
375 0 : return NT_STATUS_NO_MEMORY;
376 : }
377 :
378 5581 : *presult = result;
379 5581 : return NT_STATUS_OK;
380 : }
381 :
382 : /****************************************************************************
383 : Set relevant user and group settings corresponding to force user/group
384 : configuration for the given snum.
385 : ****************************************************************************/
386 :
387 5623 : NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
388 : {
389 3816 : const struct loadparm_substitution *lp_sub =
390 1807 : loadparm_s3_global_substitution();
391 : NTSTATUS status;
392 :
393 5623 : if (*lp_force_user(talloc_tos(), lp_sub, snum)) {
394 :
395 : /*
396 : * Replace conn->session_info with a completely faked up one
397 : * from the username we are forced into :-)
398 : */
399 :
400 : char *fuser;
401 : char *sanitized_username;
402 : struct auth_session_info *forced_serverinfo;
403 : bool guest;
404 :
405 74 : fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), lp_sub, snum), "%S",
406 : lp_const_servicename(snum));
407 74 : if (fuser == NULL) {
408 0 : return NT_STATUS_NO_MEMORY;
409 : }
410 :
411 74 : guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
412 :
413 74 : status = make_session_info_from_username(
414 : conn, fuser,
415 : guest,
416 : &forced_serverinfo);
417 74 : if (!NT_STATUS_IS_OK(status)) {
418 0 : return status;
419 : }
420 :
421 : /* We don't want to replace the original sanitized_username
422 : as it is the original user given in the connect attempt.
423 : This is used in '%U' substitutions. */
424 74 : sanitized_username = discard_const_p(char,
425 : forced_serverinfo->unix_info->sanitized_username);
426 74 : TALLOC_FREE(sanitized_username);
427 148 : forced_serverinfo->unix_info->sanitized_username =
428 115 : talloc_move(forced_serverinfo->unix_info,
429 : &conn->session_info->unix_info->sanitized_username);
430 :
431 74 : TALLOC_FREE(conn->session_info);
432 74 : conn->session_info = forced_serverinfo;
433 :
434 74 : conn->force_user = true;
435 74 : DEBUG(3,("Forced user %s\n", fuser));
436 : }
437 :
438 : /*
439 : * If force group is true, then override
440 : * any groupid stored for the connecting user.
441 : */
442 :
443 5623 : if (*lp_force_group(talloc_tos(), lp_sub, snum)) {
444 :
445 111 : status = find_forced_group(
446 65 : conn->force_user, snum, conn->session_info->unix_info->unix_name,
447 42 : &conn->session_info->security_token->sids[1],
448 42 : &conn->session_info->unix_token->gid);
449 :
450 42 : if (!NT_STATUS_IS_OK(status)) {
451 0 : return status;
452 : }
453 :
454 : /*
455 : * We need to cache this gid, to use within
456 : * change_to_user() separately from the conn->session_info
457 : * struct. We only use conn->session_info directly if
458 : * "force_user" was set.
459 : */
460 42 : conn->force_group_gid = conn->session_info->unix_token->gid;
461 : }
462 :
463 5623 : return NT_STATUS_OK;
464 : }
465 :
466 1554 : static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
467 : {
468 : NTSTATUS status;
469 :
470 1554 : if (sconn->notify_ctx != NULL) {
471 10 : return NT_STATUS_OK;
472 : }
473 :
474 1544 : sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx,
475 : sconn, notify_callback);
476 1544 : if (sconn->notify_ctx == NULL) {
477 0 : return NT_STATUS_NO_MEMORY;
478 : }
479 :
480 1544 : status = messaging_register(sconn->msg_ctx, sconn,
481 : MSG_SMB_NOTIFY_CANCEL_DELETED,
482 : smbd_notify_cancel_deleted);
483 1544 : if (!NT_STATUS_IS_OK(status)) {
484 0 : DBG_DEBUG("messaging_register failed: %s\n",
485 : nt_errstr(status));
486 0 : TALLOC_FREE(sconn->notify_ctx);
487 0 : return status;
488 : }
489 :
490 1544 : status = messaging_register(sconn->msg_ctx, sconn,
491 : MSG_SMB_NOTIFY_STARTED,
492 : smbd_notifyd_restarted);
493 1544 : if (!NT_STATUS_IS_OK(status)) {
494 0 : DBG_DEBUG("messaging_register failed: %s\n",
495 : nt_errstr(status));
496 0 : messaging_deregister(sconn->msg_ctx,
497 : MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
498 0 : TALLOC_FREE(sconn->notify_ctx);
499 0 : return status;
500 : }
501 :
502 1544 : return NT_STATUS_OK;
503 : }
504 :
505 : /****************************************************************************
506 : Make a connection, given the snum to connect to, and the vuser of the
507 : connecting user if appropriate.
508 : ****************************************************************************/
509 :
510 5635 : NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
511 : connection_struct *conn,
512 : int snum,
513 : struct smbXsrv_session *session,
514 : const char *pdev)
515 : {
516 5635 : struct smbd_server_connection *sconn = xconn->client->sconn;
517 3822 : const struct loadparm_substitution *lp_sub =
518 1813 : loadparm_s3_global_substitution();
519 5635 : struct smb_filename *smb_fname_cpath = NULL;
520 : fstring dev;
521 : int ret;
522 5635 : bool on_err_call_dis_hook = false;
523 : uid_t effuid;
524 : gid_t effgid;
525 : NTSTATUS status;
526 : bool ok;
527 :
528 5635 : fstrcpy(dev, pdev);
529 :
530 5635 : status = share_sanity_checks(sconn->remote_address,
531 : sconn->remote_hostname,
532 : snum,
533 : dev);
534 5635 : if (NT_STATUS_IS_ERR(status)) {
535 0 : goto err_root_exit;
536 : }
537 :
538 5635 : conn->params->service = snum;
539 :
540 9457 : status = create_connection_session_info(sconn,
541 5635 : conn, snum, session->global->auth_session_info,
542 : &conn->session_info);
543 :
544 5635 : if (!NT_STATUS_IS_OK(status)) {
545 12 : DEBUG(1, ("create_connection_session_info failed: %s\n",
546 : nt_errstr(status)));
547 12 : goto err_root_exit;
548 : }
549 :
550 5623 : if (lp_guest_only(snum)) {
551 42 : conn->force_user = true;
552 : }
553 :
554 5623 : conn->num_files_open = 0;
555 5623 : conn->lastused = conn->lastused_count = time(NULL);
556 5623 : conn->printer = (strncmp(dev,"LPT",3) == 0);
557 9951 : conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
558 1554 : ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
559 :
560 : /* Case options for the share. */
561 5623 : conn_setup_case_options(conn);
562 :
563 5623 : conn->encrypt_level = lp_server_smb_encrypt(snum);
564 5623 : if (conn->encrypt_level > SMB_ENCRYPTION_OFF) {
565 0 : if (lp_server_smb_encrypt(-1) == SMB_ENCRYPTION_OFF) {
566 0 : if (conn->encrypt_level == SMB_ENCRYPTION_REQUIRED) {
567 0 : DBG_ERR("Service [%s] requires encryption, but "
568 : "it is disabled globally!\n",
569 : lp_const_servicename(snum));
570 0 : status = NT_STATUS_ACCESS_DENIED;
571 0 : goto err_root_exit;
572 : }
573 0 : conn->encrypt_level = SMB_ENCRYPTION_OFF;
574 : }
575 : }
576 :
577 5623 : conn->veto_list = NULL;
578 5623 : conn->hide_list = NULL;
579 5623 : conn->veto_oplock_list = NULL;
580 5623 : conn->aio_write_behind_list = NULL;
581 :
582 5623 : conn->read_only = lp_read_only(SNUM(conn));
583 :
584 5623 : status = set_conn_force_user_group(conn, snum);
585 5623 : if (!NT_STATUS_IS_OK(status)) {
586 0 : goto err_root_exit;
587 : }
588 :
589 5623 : conn->vuid = session->global->session_wire_id;
590 :
591 : {
592 20887 : char *s = talloc_sub_full(talloc_tos(),
593 5623 : lp_const_servicename(SNUM(conn)),
594 5623 : conn->session_info->unix_info->unix_name,
595 5623 : conn->connectpath,
596 5623 : conn->session_info->unix_token->gid,
597 5623 : conn->session_info->unix_info->sanitized_username,
598 5623 : conn->session_info->info->domain_name,
599 5623 : lp_path(talloc_tos(), lp_sub, snum));
600 5623 : if (!s) {
601 0 : status = NT_STATUS_NO_MEMORY;
602 0 : goto err_root_exit;
603 : }
604 :
605 5623 : if (!set_conn_connectpath(conn,s)) {
606 0 : TALLOC_FREE(s);
607 0 : status = NT_STATUS_NO_MEMORY;
608 0 : goto err_root_exit;
609 : }
610 5623 : DBG_NOTICE("Connect path is '%s' for service [%s]\n", s,
611 : lp_const_servicename(snum));
612 5623 : TALLOC_FREE(s);
613 : }
614 :
615 : /*
616 : * Set up the share security descriptor.
617 : * NOTE - we use the *INCOMING USER* session_info
618 : * here, as does (indirectly) change_to_user(),
619 : * which can be called on any incoming packet.
620 : * This way we set up the share access based
621 : * on the authenticated user, not the forced
622 : * user. See bug:
623 : *
624 : * https://bugzilla.samba.org/show_bug.cgi?id=9878
625 : */
626 :
627 9439 : status = check_user_share_access(conn,
628 5623 : session->global->auth_session_info,
629 : &conn->share_access,
630 : &conn->read_only);
631 5623 : if (!NT_STATUS_IS_OK(status)) {
632 0 : goto err_root_exit;
633 : }
634 :
635 : /* Initialise VFS function pointers */
636 :
637 5623 : if (!smbd_vfs_init(conn)) {
638 0 : DBG_ERR("vfs_init failed for service %s\n",
639 : lp_const_servicename(snum));
640 0 : status = NT_STATUS_BAD_NETWORK_NAME;
641 0 : goto err_root_exit;
642 : }
643 :
644 : /* ROOT Activities: */
645 : /* explicitly check widelinks here so that we can correctly warn
646 : * in the logs. */
647 5623 : widelinks_warning(snum);
648 :
649 : /* Invoke VFS make connection hook - this must be the first
650 : filesystem operation that we do. */
651 :
652 5623 : if (SMB_VFS_CONNECT(conn, lp_const_servicename(snum),
653 : conn->session_info->unix_info->unix_name) < 0) {
654 0 : DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
655 : lp_const_servicename(snum), conn->connectpath,
656 : strerror(errno));
657 0 : status = NT_STATUS_UNSUCCESSFUL;
658 0 : goto err_root_exit;
659 : }
660 :
661 : /* Any error exit after here needs to call the disconnect hook. */
662 5623 : on_err_call_dis_hook = true;
663 :
664 7177 : if ((!conn->printer) && (!conn->ipc) &&
665 1554 : lp_change_notify()) {
666 :
667 1554 : status = notify_init_sconn(sconn);
668 1554 : if (!NT_STATUS_IS_OK(status)) {
669 0 : goto err_root_exit;
670 : }
671 : }
672 :
673 5623 : if (lp_kernel_oplocks(snum)) {
674 0 : init_kernel_oplocks(conn->sconn);
675 : }
676 :
677 : /*
678 : * Fix compatibility issue pointed out by Volker.
679 : * We pass the conn->connectpath to the preexec
680 : * scripts as a parameter, so attempt to canonicalize
681 : * it here before calling the preexec scripts.
682 : * We ignore errors here, as it is possible that
683 : * the conn->connectpath doesn't exist yet and
684 : * the preexec scripts will create them.
685 : */
686 :
687 5623 : (void)canonicalize_connect_path(conn);
688 :
689 : /* Preexecs are done here as they might make the dir we are to ChDir
690 : * to below */
691 : /* execute any "root preexec = " line */
692 5623 : if (*lp_root_preexec(talloc_tos(), lp_sub, snum)) {
693 0 : char *cmd = talloc_sub_full(talloc_tos(),
694 0 : lp_const_servicename(SNUM(conn)),
695 0 : conn->session_info->unix_info->unix_name,
696 0 : conn->connectpath,
697 0 : conn->session_info->unix_token->gid,
698 0 : conn->session_info->unix_info->sanitized_username,
699 0 : conn->session_info->info->domain_name,
700 0 : lp_root_preexec(talloc_tos(), lp_sub, snum));
701 0 : DEBUG(5,("cmd=%s\n",cmd));
702 0 : ret = smbrun(cmd, NULL, NULL);
703 0 : TALLOC_FREE(cmd);
704 0 : if (ret != 0 && lp_root_preexec_close(snum)) {
705 0 : DEBUG(1,("root preexec gave %d - failing "
706 : "connection\n", ret));
707 0 : status = NT_STATUS_ACCESS_DENIED;
708 0 : goto err_root_exit;
709 : }
710 : }
711 :
712 : /* USER Activites: */
713 5623 : if (!change_to_user_and_service(conn, conn->vuid)) {
714 : /* No point continuing if they fail the basic checks */
715 0 : DEBUG(0,("Can't become connected user!\n"));
716 0 : status = NT_STATUS_LOGON_FAILURE;
717 0 : goto err_root_exit;
718 : }
719 :
720 5623 : effuid = geteuid();
721 5623 : effgid = getegid();
722 :
723 : /* Remember that a different vuid can connect later without these
724 : * checks... */
725 :
726 : /* Preexecs are done here as they might make the dir we are to ChDir
727 : * to below */
728 :
729 : /* execute any "preexec = " line */
730 5623 : if (*lp_preexec(talloc_tos(), lp_sub, snum)) {
731 0 : char *cmd = talloc_sub_full(talloc_tos(),
732 0 : lp_const_servicename(SNUM(conn)),
733 0 : conn->session_info->unix_info->unix_name,
734 0 : conn->connectpath,
735 0 : conn->session_info->unix_token->gid,
736 0 : conn->session_info->unix_info->sanitized_username,
737 0 : conn->session_info->info->domain_name,
738 0 : lp_preexec(talloc_tos(), lp_sub, snum));
739 0 : ret = smbrun(cmd, NULL, NULL);
740 0 : TALLOC_FREE(cmd);
741 0 : if (ret != 0 && lp_preexec_close(snum)) {
742 0 : DEBUG(1,("preexec gave %d - failing connection\n",
743 : ret));
744 0 : status = NT_STATUS_ACCESS_DENIED;
745 0 : goto err_root_exit;
746 : }
747 : }
748 :
749 : #ifdef WITH_FAKE_KASERVER
750 : if (lp_afs_share(snum)) {
751 : afs_login(conn);
752 : }
753 : #endif
754 :
755 : /*
756 : * we've finished with the user stuff - go back to root
757 : * so the SMB_VFS_STAT call will only fail on path errors,
758 : * not permission problems.
759 : */
760 5623 : change_to_root_user();
761 : /* ROOT Activites: */
762 :
763 : /*
764 : * Canonicalise the connect
765 : * path here to ensure we don't have any symlinks in the
766 : * connectpath. We will be checking all paths on this connection are
767 : * below this directory. We must do this after the VFS init as we
768 : * depend on the realpath() pointer in the vfs table. JRA.
769 : */
770 5623 : ok = canonicalize_connect_path(conn);
771 5623 : if (!ok) {
772 0 : DBG_ERR("canonicalize_connect_path failed "
773 : "for service %s, path %s\n",
774 : lp_const_servicename(snum),
775 : conn->connectpath);
776 0 : status = NT_STATUS_BAD_NETWORK_NAME;
777 0 : goto err_root_exit;
778 : }
779 :
780 : /* Add veto/hide lists */
781 5623 : if (!IS_IPC(conn) && !IS_PRINT(conn)) {
782 1554 : set_namearray( &conn->veto_list,
783 1554 : lp_veto_files(talloc_tos(), lp_sub, snum));
784 1554 : set_namearray( &conn->hide_list,
785 1554 : lp_hide_files(talloc_tos(), lp_sub, snum));
786 1554 : set_namearray( &conn->veto_oplock_list,
787 1554 : lp_veto_oplock_files(talloc_tos(), lp_sub, snum));
788 1554 : set_namearray( &conn->aio_write_behind_list,
789 1554 : lp_aio_write_behind(talloc_tos(), lp_sub, snum));
790 : }
791 5623 : smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
792 5623 : conn->connectpath,
793 : NULL,
794 : NULL,
795 : 0,
796 : 0);
797 5623 : if (smb_fname_cpath == NULL) {
798 0 : status = NT_STATUS_NO_MEMORY;
799 0 : goto err_root_exit;
800 : }
801 :
802 : /* win2000 does not check the permissions on the directory
803 : during the tree connect, instead relying on permission
804 : check during individual operations. To match this behaviour
805 : I have disabled this chdir check (tridge) */
806 : /* the alternative is just to check the directory exists */
807 :
808 9439 : if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
809 5623 : !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
810 0 : if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
811 0 : DBG_ERR("'%s' is not a directory, when connecting to "
812 : "[%s]\n", conn->connectpath,
813 : lp_const_servicename(snum));
814 : } else {
815 0 : DBG_ERR("'%s' does not exist or permission denied "
816 : "when connecting to [%s] Error was %s\n",
817 : conn->connectpath,
818 : lp_const_servicename(snum),
819 : strerror(errno));
820 : }
821 0 : status = NT_STATUS_BAD_NETWORK_NAME;
822 0 : goto err_root_exit;
823 : }
824 5623 : conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
825 :
826 : /* Figure out the characteristics of the underlying filesystem. This
827 : * assumes that all the filesystem mounted within a share path have
828 : * the same characteristics, which is likely but not guaranteed.
829 : */
830 :
831 5623 : if(!IS_IPC(conn) ){
832 1554 : conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
833 : }
834 : /*
835 : * Print out the 'connected as' stuff here as we need
836 : * to know the effective uid and gid we will be using
837 : * (at least initially).
838 : */
839 :
840 5623 : if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
841 : bool signing_active;
842 :
843 0 : dbgtext( "%s (%s) ", get_remote_machine_name(),
844 0 : tsocket_address_string(conn->sconn->remote_address,
845 : talloc_tos()) );
846 : #if defined(WITH_SMB1SERVER)
847 0 : if (sconn->using_smb2) {
848 : #endif
849 0 : signing_active = smb2_signing_key_valid(
850 0 : session->global->encryption_key);
851 : #if defined(WITH_SMB1SERVER)
852 : } else {
853 0 : signing_active = smb1_srv_is_signing_active(xconn);
854 : }
855 : #endif
856 0 : dbgtext( "%s", signing_active ? "signed " : "");
857 0 : dbgtext( "connect to service %s ",
858 : lp_const_servicename(snum) );
859 0 : dbgtext( "initially as user %s ",
860 0 : conn->session_info->unix_info->unix_name );
861 0 : dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
862 0 : dbgtext( "(pid %d)\n", (int)getpid() );
863 : }
864 :
865 5623 : conn->tcon_done = true;
866 5623 : return NT_STATUS_OK;
867 :
868 12 : err_root_exit:
869 :
870 12 : TALLOC_FREE(smb_fname_cpath);
871 : /* We must exit this function as root. */
872 12 : if (geteuid() != 0) {
873 0 : change_to_root_user();
874 : }
875 12 : if (on_err_call_dis_hook) {
876 : /* Call VFS disconnect hook */
877 0 : SMB_VFS_DISCONNECT(conn);
878 : }
879 12 : return status;
880 : }
881 :
882 : /****************************************************************************
883 : Make a connection to a service from SMB2. External SMB2 interface.
884 : We must set cnum before claiming connection.
885 : ****************************************************************************/
886 :
887 5607 : connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
888 : struct smbXsrv_tcon *tcon,
889 : int snum,
890 : const char *pdev,
891 : NTSTATUS *pstatus)
892 : {
893 5607 : struct smbd_server_connection *sconn = req->sconn;
894 5607 : connection_struct *conn = conn_new(sconn);
895 5607 : if (!conn) {
896 0 : DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
897 0 : *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
898 0 : return NULL;
899 : }
900 :
901 5607 : conn->cnum = tcon->global->tcon_wire_id;
902 5607 : conn->tcon = tcon;
903 :
904 5607 : *pstatus = make_connection_snum(req->xconn,
905 : conn,
906 : snum,
907 : req->session,
908 : pdev);
909 5607 : if (!NT_STATUS_IS_OK(*pstatus)) {
910 12 : conn_free(conn);
911 12 : return NULL;
912 : }
913 5595 : return conn;
914 : }
915 :
916 : /****************************************************************************
917 : Close a cnum.
918 : ****************************************************************************/
919 :
920 5623 : void close_cnum(connection_struct *conn,
921 : uint64_t vuid,
922 : enum file_close_type close_type)
923 : {
924 5623 : char rootpath[2] = { '/', '\0'};
925 5623 : struct smb_filename root_fname = { .base_name = rootpath };
926 3816 : const struct loadparm_substitution *lp_sub =
927 1807 : loadparm_s3_global_substitution();
928 :
929 5623 : file_close_conn(conn, close_type);
930 :
931 5623 : change_to_root_user();
932 :
933 5623 : DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
934 : get_remote_machine_name(),
935 : tsocket_address_string(conn->sconn->remote_address,
936 : talloc_tos()),
937 : lp_const_servicename(SNUM(conn))));
938 :
939 : /* make sure we leave the directory available for unmount */
940 5623 : vfs_ChDir(conn, &root_fname);
941 :
942 : /* Call VFS disconnect hook */
943 5623 : SMB_VFS_DISCONNECT(conn);
944 :
945 : /* execute any "postexec = " line */
946 5623 : if (*lp_postexec(talloc_tos(), lp_sub, SNUM(conn)) &&
947 0 : change_to_user_and_service(conn, vuid)) {
948 0 : char *cmd = talloc_sub_full(talloc_tos(),
949 0 : lp_const_servicename(SNUM(conn)),
950 0 : conn->session_info->unix_info->unix_name,
951 0 : conn->connectpath,
952 0 : conn->session_info->unix_token->gid,
953 0 : conn->session_info->unix_info->sanitized_username,
954 0 : conn->session_info->info->domain_name,
955 0 : lp_postexec(talloc_tos(), lp_sub, SNUM(conn)));
956 0 : smbrun(cmd, NULL, NULL);
957 0 : TALLOC_FREE(cmd);
958 0 : change_to_root_user();
959 : }
960 :
961 5623 : change_to_root_user();
962 : /* execute any "root postexec = " line */
963 5623 : if (*lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn))) {
964 0 : char *cmd = talloc_sub_full(talloc_tos(),
965 0 : lp_const_servicename(SNUM(conn)),
966 0 : conn->session_info->unix_info->unix_name,
967 0 : conn->connectpath,
968 0 : conn->session_info->unix_token->gid,
969 0 : conn->session_info->unix_info->sanitized_username,
970 0 : conn->session_info->info->domain_name,
971 0 : lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)));
972 0 : smbrun(cmd, NULL, NULL);
973 0 : TALLOC_FREE(cmd);
974 : }
975 :
976 5623 : conn_free(conn);
977 5623 : }
|