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