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 :
38 88818 : bool canonicalize_connect_path(connection_struct *conn)
39 : {
40 : bool ret;
41 88818 : struct smb_filename con_fname = { .base_name = conn->connectpath };
42 88818 : struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
43 : &con_fname);
44 88818 : if (resolved_fname == NULL) {
45 58 : return false;
46 : }
47 88760 : ret = set_conn_connectpath(conn,resolved_fname->base_name);
48 88760 : TALLOC_FREE(resolved_fname);
49 88760 : return ret;
50 : }
51 :
52 : /****************************************************************************
53 : Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
54 : absolute path stating in / and not ending in /.
55 : ****************************************************************************/
56 :
57 135336 : bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
58 : {
59 : char *destname;
60 :
61 135336 : if (connectpath == NULL || connectpath[0] == '\0') {
62 0 : return false;
63 : }
64 :
65 135336 : destname = canonicalize_absolute_path(conn, connectpath);
66 135336 : if (destname == NULL) {
67 0 : return false;
68 : }
69 :
70 135336 : DBG_DEBUG("service %s, connectpath = %s\n",
71 : lp_const_servicename(SNUM(conn)), destname);
72 :
73 135336 : talloc_free(conn->connectpath);
74 135336 : conn->connectpath = destname;
75 : /*
76 : * Ensure conn->cwd_fsp->fsp_name is initialized.
77 : * start as conn->connectpath.
78 : */
79 135336 : TALLOC_FREE(conn->cwd_fsp->fsp_name);
80 148574 : conn->cwd_fsp->fsp_name = synthetic_smb_fname(conn,
81 135336 : conn->connectpath,
82 : NULL,
83 : NULL,
84 : 0,
85 : 0);
86 135336 : if (conn->cwd_fsp->fsp_name == NULL) {
87 0 : return false;
88 : }
89 135336 : return true;
90 : }
91 :
92 : /****************************************************************************
93 : Load parameters specific to a connection/service.
94 : ****************************************************************************/
95 :
96 338339 : void set_current_case_sensitive(connection_struct *conn, uint16_t flags)
97 : {
98 : int snum;
99 : enum remote_arch_types ra_type;
100 :
101 338339 : SMB_ASSERT(conn != NULL);
102 :
103 338339 : snum = SNUM(conn);
104 :
105 338339 : if ((conn == last_conn) && (last_flags == flags)) {
106 323841 : return;
107 : }
108 :
109 7317 : last_conn = conn;
110 7317 : last_flags = flags;
111 :
112 : /*
113 : * Obey the client case sensitivity requests - only for clients that
114 : * support it. */
115 7317 : switch (lp_case_sensitive(snum)) {
116 7257 : case Auto:
117 : /*
118 : * We need this uglyness due to DOS/Win9x clients that lie
119 : * about case insensitivity. */
120 7257 : ra_type = get_remote_arch();
121 7257 : if (conn->sconn->using_smb2) {
122 0 : conn->case_sensitive = false;
123 7257 : } else if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
124 : /*
125 : * Client can't support per-packet case sensitive
126 : * pathnames. */
127 0 : conn->case_sensitive = false;
128 : } else {
129 7257 : conn->case_sensitive =
130 7257 : !(flags & FLAG_CASELESS_PATHNAMES);
131 : }
132 7160 : break;
133 60 : case True:
134 60 : conn->case_sensitive = true;
135 60 : break;
136 0 : default:
137 0 : conn->case_sensitive = false;
138 0 : break;
139 : }
140 7220 : return;
141 : }
142 :
143 1860772 : bool chdir_current_service(connection_struct *conn)
144 : {
145 3496566 : const struct smb_filename connectpath_fname = {
146 1860772 : .base_name = conn->connectpath,
147 : };
148 1860772 : int saved_errno = 0;
149 1860772 : char *utok_str = NULL;
150 : int ret;
151 :
152 1860772 : conn->lastused_count++;
153 :
154 1860772 : ret = vfs_ChDir(conn, &connectpath_fname);
155 1860772 : if (ret == 0) {
156 1844996 : return true;
157 : }
158 136 : saved_errno = errno;
159 :
160 136 : utok_str = utok_string(talloc_tos(),
161 136 : conn->session_info->unix_token);
162 136 : if (utok_str == NULL) {
163 0 : errno = saved_errno;
164 0 : return false;
165 : }
166 :
167 136 : DBG_ERR("vfs_ChDir(%s) failed: %s. Current token: %s\n",
168 : conn->connectpath,
169 : strerror(saved_errno),
170 : utok_str);
171 :
172 136 : if (saved_errno != 0) {
173 136 : errno = saved_errno;
174 : }
175 136 : return false;
176 : }
177 :
178 : /****************************************************************************
179 : do some basic sainity checks on the share.
180 : This function modifies dev, ecode.
181 : ****************************************************************************/
182 :
183 42316 : static NTSTATUS share_sanity_checks(const struct tsocket_address *remote_address,
184 : const char *rhost,
185 : int snum,
186 : fstring dev)
187 : {
188 : char *raddr;
189 :
190 42316 : raddr = tsocket_address_inet_addr_string(remote_address,
191 : talloc_tos());
192 42316 : if (raddr == NULL) {
193 0 : return NT_STATUS_NO_MEMORY;
194 : }
195 :
196 81038 : if (!lp_snum_ok(snum) ||
197 42316 : !allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
198 : rhost, raddr)) {
199 0 : return NT_STATUS_ACCESS_DENIED;
200 : }
201 :
202 42316 : if (dev[0] == '?' || !dev[0]) {
203 39697 : if (lp_printable(snum)) {
204 28 : fstrcpy(dev,"LPT1:");
205 39669 : } else if (strequal(lp_fstype(snum), "IPC")) {
206 20905 : fstrcpy(dev, "IPC");
207 : } else {
208 18764 : fstrcpy(dev,"A:");
209 : }
210 : }
211 :
212 42316 : if (!strupper_m(dev)) {
213 0 : DEBUG(2,("strupper_m %s failed\n", dev));
214 0 : return NT_STATUS_INVALID_PARAMETER;
215 : }
216 :
217 42316 : if (lp_printable(snum)) {
218 28 : if (!strequal(dev, "LPT1:")) {
219 0 : return NT_STATUS_BAD_DEVICE_TYPE;
220 : }
221 42288 : } else if (strequal(lp_fstype(snum), "IPC")) {
222 23404 : if (!strequal(dev, "IPC")) {
223 27 : return NT_STATUS_BAD_DEVICE_TYPE;
224 : }
225 18884 : } else if (!strequal(dev, "A:")) {
226 27 : return NT_STATUS_BAD_DEVICE_TYPE;
227 : }
228 :
229 : /* Behave as a printer if we are supposed to */
230 42262 : if (lp_printable(snum) && (strcmp(dev, "A:") == 0)) {
231 0 : fstrcpy(dev, "LPT1:");
232 : }
233 :
234 42262 : return NT_STATUS_OK;
235 : }
236 :
237 : /*
238 : * Go through lookup_name etc to find the force'd group.
239 : *
240 : * Create a new token from src_token, replacing the primary group sid with the
241 : * one found.
242 : */
243 :
244 130 : static NTSTATUS find_forced_group(bool force_user,
245 : int snum, const char *username,
246 : struct dom_sid *pgroup_sid,
247 : gid_t *pgid)
248 : {
249 130 : NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
250 130 : TALLOC_CTX *frame = talloc_stackframe();
251 111 : const struct loadparm_substitution *lp_sub =
252 19 : loadparm_s3_global_substitution();
253 : struct dom_sid group_sid;
254 : enum lsa_SidType type;
255 : char *groupname;
256 130 : bool user_must_be_member = False;
257 : gid_t gid;
258 :
259 130 : groupname = lp_force_group(talloc_tos(), lp_sub, snum);
260 130 : if (groupname == NULL) {
261 0 : DEBUG(1, ("talloc_strdup failed\n"));
262 0 : result = NT_STATUS_NO_MEMORY;
263 0 : goto done;
264 : }
265 :
266 130 : if (groupname[0] == '+') {
267 0 : user_must_be_member = True;
268 0 : groupname += 1;
269 : }
270 :
271 130 : groupname = talloc_string_sub(talloc_tos(), groupname,
272 : "%S", lp_const_servicename(snum));
273 130 : if (groupname == NULL) {
274 0 : DEBUG(1, ("talloc_string_sub failed\n"));
275 0 : result = NT_STATUS_NO_MEMORY;
276 0 : goto done;
277 : }
278 :
279 130 : if (!lookup_name_smbconf(talloc_tos(), groupname,
280 : LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
281 : NULL, NULL, &group_sid, &type)) {
282 0 : DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
283 : groupname));
284 0 : goto done;
285 : }
286 :
287 130 : if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
288 0 : (type != SID_NAME_WKN_GRP)) {
289 0 : DEBUG(10, ("%s is a %s, not a group\n", groupname,
290 : sid_type_lookup(type)));
291 0 : goto done;
292 : }
293 :
294 130 : if (!sid_to_gid(&group_sid, &gid)) {
295 : struct dom_sid_buf buf;
296 0 : DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
297 : dom_sid_str_buf(&group_sid, &buf), groupname));
298 0 : goto done;
299 : }
300 :
301 : /*
302 : * If the user has been forced and the forced group starts with a '+',
303 : * then we only set the group to be the forced group if the forced
304 : * user is a member of that group. Otherwise, the meaning of the '+'
305 : * would be ignored.
306 : */
307 :
308 130 : if (force_user && user_must_be_member) {
309 0 : if (user_in_group_sid(username, &group_sid)) {
310 0 : sid_copy(pgroup_sid, &group_sid);
311 0 : *pgid = gid;
312 0 : DEBUG(3,("Forced group %s for member %s\n",
313 : groupname, username));
314 : } else {
315 0 : DEBUG(0,("find_forced_group: forced user %s is not a member "
316 : "of forced group %s. Disallowing access.\n",
317 : username, groupname ));
318 0 : result = NT_STATUS_MEMBER_NOT_IN_GROUP;
319 0 : goto done;
320 : }
321 : } else {
322 130 : sid_copy(pgroup_sid, &group_sid);
323 130 : *pgid = gid;
324 130 : DEBUG(3,("Forced group %s\n", groupname));
325 : }
326 :
327 130 : result = NT_STATUS_OK;
328 130 : done:
329 130 : TALLOC_FREE(frame);
330 130 : return result;
331 : }
332 :
333 : /****************************************************************************
334 : Create an auth_session_info structure for a connection_struct
335 : ****************************************************************************/
336 :
337 42262 : static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
338 : TALLOC_CTX *mem_ctx, int snum,
339 : struct auth_session_info *session_info,
340 : struct auth_session_info **presult)
341 : {
342 : struct auth_session_info *result;
343 :
344 42262 : if (lp_guest_only(snum)) {
345 128 : return make_session_info_guest(mem_ctx, presult);
346 : }
347 :
348 : /*
349 : * This is the normal security != share case where we have a
350 : * valid vuid from the session setup. */
351 :
352 42134 : if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
353 970 : if (!lp_guest_ok(snum)) {
354 4 : DBG_WARNING("guest user (from session setup) "
355 : "not permitted to access this share "
356 : "(%s)\n", lp_const_servicename(snum));
357 4 : return NT_STATUS_ACCESS_DENIED;
358 : }
359 : } else {
360 41164 : if (!user_ok_token(session_info->unix_info->unix_name,
361 41164 : session_info->info->domain_name,
362 41164 : session_info->security_token, snum)) {
363 8 : DBG_WARNING("user '%s' (from session setup) not "
364 : "permitted to access this share "
365 : "(%s)\n",
366 : session_info->unix_info->unix_name,
367 : lp_const_servicename(snum));
368 8 : return NT_STATUS_ACCESS_DENIED;
369 : }
370 : }
371 :
372 42122 : result = copy_session_info(mem_ctx, session_info);
373 42122 : if (result == NULL) {
374 0 : return NT_STATUS_NO_MEMORY;
375 : }
376 :
377 42122 : *presult = result;
378 42122 : return NT_STATUS_OK;
379 : }
380 :
381 : /****************************************************************************
382 : Set relevant user and group settings corresponding to force user/group
383 : configuration for the given snum.
384 : ****************************************************************************/
385 :
386 42344 : NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
387 : {
388 38762 : const struct loadparm_substitution *lp_sub =
389 3582 : loadparm_s3_global_substitution();
390 : NTSTATUS status;
391 :
392 42344 : if (*lp_force_user(talloc_tos(), lp_sub, snum)) {
393 :
394 : /*
395 : * Replace conn->session_info with a completely faked up one
396 : * from the username we are forced into :-)
397 : */
398 :
399 : char *fuser;
400 : char *sanitized_username;
401 : struct auth_session_info *forced_serverinfo;
402 : bool guest;
403 :
404 246 : fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), lp_sub, snum), "%S",
405 : lp_const_servicename(snum));
406 246 : if (fuser == NULL) {
407 0 : return NT_STATUS_NO_MEMORY;
408 : }
409 :
410 246 : guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;
411 :
412 246 : status = make_session_info_from_username(
413 : conn, fuser,
414 : guest,
415 : &forced_serverinfo);
416 246 : if (!NT_STATUS_IS_OK(status)) {
417 0 : return status;
418 : }
419 :
420 : /* We don't want to replace the original sanitized_username
421 : as it is the original user given in the connect attempt.
422 : This is used in '%U' substitutions. */
423 246 : sanitized_username = discard_const_p(char,
424 : forced_serverinfo->unix_info->sanitized_username);
425 246 : TALLOC_FREE(sanitized_username);
426 492 : forced_serverinfo->unix_info->sanitized_username =
427 459 : talloc_move(forced_serverinfo->unix_info,
428 : &conn->session_info->unix_info->sanitized_username);
429 :
430 246 : TALLOC_FREE(conn->session_info);
431 246 : conn->session_info = forced_serverinfo;
432 :
433 246 : conn->force_user = true;
434 246 : DEBUG(3,("Forced user %s\n", fuser));
435 : }
436 :
437 : /*
438 : * If force group is true, then override
439 : * any groupid stored for the connecting user.
440 : */
441 :
442 42344 : if (*lp_force_group(talloc_tos(), lp_sub, snum)) {
443 :
444 463 : status = find_forced_group(
445 241 : conn->force_user, snum, conn->session_info->unix_info->unix_name,
446 130 : &conn->session_info->security_token->sids[1],
447 130 : &conn->session_info->unix_token->gid);
448 :
449 130 : if (!NT_STATUS_IS_OK(status)) {
450 0 : return status;
451 : }
452 :
453 : /*
454 : * We need to cache this gid, to use within
455 : * change_to_user() separately from the conn->session_info
456 : * struct. We only use conn->session_info directly if
457 : * "force_user" was set.
458 : */
459 130 : conn->force_group_gid = conn->session_info->unix_token->gid;
460 : }
461 :
462 42344 : return NT_STATUS_OK;
463 : }
464 :
465 18693 : static NTSTATUS notify_init_sconn(struct smbd_server_connection *sconn)
466 : {
467 : NTSTATUS status;
468 :
469 18693 : if (sconn->notify_ctx != NULL) {
470 1387 : return NT_STATUS_OK;
471 : }
472 :
473 17306 : sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx,
474 : sconn, notify_callback);
475 17306 : if (sconn->notify_ctx == NULL) {
476 0 : return NT_STATUS_NO_MEMORY;
477 : }
478 :
479 17306 : status = messaging_register(sconn->msg_ctx, sconn,
480 : MSG_SMB_NOTIFY_CANCEL_DELETED,
481 : smbd_notify_cancel_deleted);
482 17306 : if (!NT_STATUS_IS_OK(status)) {
483 0 : DBG_DEBUG("messaging_register failed: %s\n",
484 : nt_errstr(status));
485 0 : TALLOC_FREE(sconn->notify_ctx);
486 0 : return status;
487 : }
488 :
489 17306 : status = messaging_register(sconn->msg_ctx, sconn,
490 : MSG_SMB_NOTIFY_STARTED,
491 : smbd_notifyd_restarted);
492 17306 : if (!NT_STATUS_IS_OK(status)) {
493 0 : DBG_DEBUG("messaging_register failed: %s\n",
494 : nt_errstr(status));
495 0 : messaging_deregister(sconn->msg_ctx,
496 : MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
497 0 : TALLOC_FREE(sconn->notify_ctx);
498 0 : return status;
499 : }
500 :
501 17306 : return NT_STATUS_OK;
502 : }
503 :
504 : /****************************************************************************
505 : Make a connection, given the snum to connect to, and the vuser of the
506 : connecting user if appropriate.
507 : ****************************************************************************/
508 :
509 42316 : static NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
510 : connection_struct *conn,
511 : int snum,
512 : struct smbXsrv_session *session,
513 : const char *pdev)
514 : {
515 42316 : struct smbd_server_connection *sconn = xconn->client->sconn;
516 38722 : const struct loadparm_substitution *lp_sub =
517 3594 : loadparm_s3_global_substitution();
518 42316 : struct smb_filename *smb_fname_cpath = NULL;
519 : fstring dev;
520 : int ret;
521 42316 : bool on_err_call_dis_hook = false;
522 : uid_t effuid;
523 : gid_t effgid;
524 : NTSTATUS status;
525 : bool ok;
526 :
527 42316 : fstrcpy(dev, pdev);
528 :
529 42316 : status = share_sanity_checks(sconn->remote_address,
530 : sconn->remote_hostname,
531 : snum,
532 : dev);
533 42316 : if (NT_STATUS_IS_ERR(status)) {
534 48 : goto err_root_exit;
535 : }
536 :
537 42262 : conn->params->service = snum;
538 :
539 80936 : status = create_connection_session_info(sconn,
540 42262 : conn, snum, session->global->auth_session_info,
541 : &conn->session_info);
542 :
543 42262 : if (!NT_STATUS_IS_OK(status)) {
544 12 : DEBUG(1, ("create_connection_session_info failed: %s\n",
545 : nt_errstr(status)));
546 12 : goto err_root_exit;
547 : }
548 :
549 42250 : if (lp_guest_only(snum)) {
550 128 : conn->force_user = true;
551 : }
552 :
553 42250 : conn->num_files_open = 0;
554 42250 : conn->lastused = conn->lastused_count = time(NULL);
555 42250 : conn->printer = (strncmp(dev,"LPT",3) == 0);
556 82697 : conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
557 18873 : ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
558 :
559 : /* Case options for the share. */
560 42250 : conn_setup_case_options(conn);
561 :
562 42250 : conn->encrypt_level = lp_server_smb_encrypt(snum);
563 42250 : if (conn->encrypt_level > SMB_ENCRYPTION_OFF) {
564 238 : if (lp_server_smb_encrypt(-1) == SMB_ENCRYPTION_OFF) {
565 12 : if (conn->encrypt_level == SMB_ENCRYPTION_REQUIRED) {
566 0 : DBG_ERR("Service [%s] requires encryption, but "
567 : "it is disabled globally!\n",
568 : lp_const_servicename(snum));
569 0 : status = NT_STATUS_ACCESS_DENIED;
570 0 : goto err_root_exit;
571 : }
572 12 : conn->encrypt_level = SMB_ENCRYPTION_OFF;
573 : }
574 : }
575 :
576 42250 : conn->veto_list = NULL;
577 42250 : conn->hide_list = NULL;
578 42250 : conn->veto_oplock_list = NULL;
579 42250 : conn->aio_write_behind_list = NULL;
580 :
581 42250 : conn->read_only = lp_read_only(SNUM(conn));
582 :
583 42250 : status = set_conn_force_user_group(conn, snum);
584 42250 : if (!NT_STATUS_IS_OK(status)) {
585 0 : goto err_root_exit;
586 : }
587 :
588 42250 : conn->vuid = session->global->session_wire_id;
589 :
590 : {
591 196922 : char *s = talloc_sub_full(talloc_tos(),
592 42250 : lp_const_servicename(SNUM(conn)),
593 41723 : conn->session_info->unix_info->unix_name,
594 42250 : conn->connectpath,
595 42250 : conn->session_info->unix_token->gid,
596 42250 : conn->session_info->unix_info->sanitized_username,
597 42250 : conn->session_info->info->domain_name,
598 42250 : lp_path(talloc_tos(), lp_sub, snum));
599 42250 : if (!s) {
600 0 : status = NT_STATUS_NO_MEMORY;
601 0 : goto err_root_exit;
602 : }
603 :
604 42250 : if (!set_conn_connectpath(conn,s)) {
605 0 : TALLOC_FREE(s);
606 0 : status = NT_STATUS_NO_MEMORY;
607 0 : goto err_root_exit;
608 : }
609 42250 : DBG_NOTICE("Connect path is '%s' for service [%s]\n", s,
610 : lp_const_servicename(snum));
611 42250 : TALLOC_FREE(s);
612 : }
613 :
614 : /*
615 : * Set up the share security descriptor.
616 : * NOTE - we use the *INCOMING USER* session_info
617 : * here, as does (indirectly) change_to_user(),
618 : * which can be called on any incoming packet.
619 : * This way we set up the share access based
620 : * on the authenticated user, not the forced
621 : * user. See bug:
622 : *
623 : * https://bugzilla.samba.org/show_bug.cgi?id=9878
624 : */
625 :
626 80918 : status = check_user_share_access(conn,
627 42250 : session->global->auth_session_info,
628 : &conn->share_access,
629 : &conn->read_only);
630 42250 : if (!NT_STATUS_IS_OK(status)) {
631 4 : goto err_root_exit;
632 : }
633 :
634 : /* Initialise VFS function pointers */
635 :
636 42246 : if (!smbd_vfs_init(conn)) {
637 0 : DBG_ERR("vfs_init failed for service %s\n",
638 : lp_const_servicename(snum));
639 0 : status = NT_STATUS_BAD_NETWORK_NAME;
640 0 : goto err_root_exit;
641 : }
642 :
643 : /* ROOT Activities: */
644 : /* explicitly check widelinks here so that we can correctly warn
645 : * in the logs. */
646 42246 : widelinks_warning(snum);
647 :
648 : /*
649 : * Enforce the max connections parameter.
650 : */
651 :
652 42246 : if ((lp_max_connections(snum) > 0)
653 0 : && (count_current_connections(lp_const_servicename(SNUM(conn)), true) >=
654 0 : lp_max_connections(snum))) {
655 :
656 0 : DBG_WARNING("Max connections (%d) exceeded for %s\n",
657 : lp_max_connections(snum),
658 : lp_const_servicename(snum));
659 0 : status = NT_STATUS_INSUFFICIENT_RESOURCES;
660 0 : goto err_root_exit;
661 : }
662 :
663 : /* Invoke VFS make connection hook - this must be the first
664 : filesystem operation that we do. */
665 :
666 42246 : if (SMB_VFS_CONNECT(conn, lp_const_servicename(snum),
667 : conn->session_info->unix_info->unix_name) < 0) {
668 0 : DBG_WARNING("SMB_VFS_CONNECT for service '%s' at '%s' failed: %s\n",
669 : lp_const_servicename(snum), conn->connectpath,
670 : strerror(errno));
671 0 : status = NT_STATUS_UNSUCCESSFUL;
672 0 : goto err_root_exit;
673 : }
674 :
675 : /* Any error exit after here needs to call the disconnect hook. */
676 42246 : on_err_call_dis_hook = true;
677 :
678 61087 : if ((!conn->printer) && (!conn->ipc) &&
679 18841 : lp_change_notify()) {
680 :
681 18693 : status = notify_init_sconn(sconn);
682 18693 : if (!NT_STATUS_IS_OK(status)) {
683 0 : goto err_root_exit;
684 : }
685 : }
686 :
687 42246 : if (lp_kernel_oplocks(snum)) {
688 17 : init_kernel_oplocks(conn->sconn);
689 : }
690 :
691 : /*
692 : * Fix compatibility issue pointed out by Volker.
693 : * We pass the conn->connectpath to the preexec
694 : * scripts as a parameter, so attempt to canonicalize
695 : * it here before calling the preexec scripts.
696 : * We ignore errors here, as it is possible that
697 : * the conn->connectpath doesn't exist yet and
698 : * the preexec scripts will create them.
699 : */
700 :
701 42246 : (void)canonicalize_connect_path(conn);
702 :
703 : /* Preexecs are done here as they might make the dir we are to ChDir
704 : * to below */
705 : /* execute any "root preexec = " line */
706 42246 : if (*lp_root_preexec(talloc_tos(), lp_sub, snum)) {
707 50 : char *cmd = talloc_sub_full(talloc_tos(),
708 10 : lp_const_servicename(SNUM(conn)),
709 10 : conn->session_info->unix_info->unix_name,
710 10 : conn->connectpath,
711 10 : conn->session_info->unix_token->gid,
712 10 : conn->session_info->unix_info->sanitized_username,
713 10 : conn->session_info->info->domain_name,
714 10 : lp_root_preexec(talloc_tos(), lp_sub, snum));
715 10 : DEBUG(5,("cmd=%s\n",cmd));
716 10 : ret = smbrun(cmd, NULL, NULL);
717 10 : TALLOC_FREE(cmd);
718 10 : if (ret != 0 && lp_root_preexec_close(snum)) {
719 0 : DEBUG(1,("root preexec gave %d - failing "
720 : "connection\n", ret));
721 0 : status = NT_STATUS_ACCESS_DENIED;
722 0 : goto err_root_exit;
723 : }
724 : }
725 :
726 : /* USER Activites: */
727 42246 : if (!change_to_user_and_service(conn, conn->vuid)) {
728 : /* No point continuing if they fail the basic checks */
729 0 : DEBUG(0,("Can't become connected user!\n"));
730 0 : status = NT_STATUS_LOGON_FAILURE;
731 0 : goto err_root_exit;
732 : }
733 :
734 42246 : effuid = geteuid();
735 42246 : effgid = getegid();
736 :
737 : /* Remember that a different vuid can connect later without these
738 : * checks... */
739 :
740 : /* Preexecs are done here as they might make the dir we are to ChDir
741 : * to below */
742 :
743 : /* execute any "preexec = " line */
744 42246 : if (*lp_preexec(talloc_tos(), lp_sub, snum)) {
745 0 : char *cmd = talloc_sub_full(talloc_tos(),
746 0 : lp_const_servicename(SNUM(conn)),
747 0 : conn->session_info->unix_info->unix_name,
748 0 : conn->connectpath,
749 0 : conn->session_info->unix_token->gid,
750 0 : conn->session_info->unix_info->sanitized_username,
751 0 : conn->session_info->info->domain_name,
752 0 : lp_preexec(talloc_tos(), lp_sub, snum));
753 0 : ret = smbrun(cmd, NULL, NULL);
754 0 : TALLOC_FREE(cmd);
755 0 : if (ret != 0 && lp_preexec_close(snum)) {
756 0 : DEBUG(1,("preexec gave %d - failing connection\n",
757 : ret));
758 0 : status = NT_STATUS_ACCESS_DENIED;
759 0 : goto err_root_exit;
760 : }
761 : }
762 :
763 : #ifdef WITH_FAKE_KASERVER
764 : if (lp_afs_share(snum)) {
765 : afs_login(conn);
766 : }
767 : #endif
768 :
769 : /*
770 : * we've finished with the user stuff - go back to root
771 : * so the SMB_VFS_STAT call will only fail on path errors,
772 : * not permission problems.
773 : */
774 42246 : change_to_root_user();
775 : /* ROOT Activites: */
776 :
777 : /*
778 : * Canonicalise the connect
779 : * path here to ensure we don't have any symlinks in the
780 : * connectpath. We will be checking all paths on this connection are
781 : * below this directory. We must do this after the VFS init as we
782 : * depend on the realpath() pointer in the vfs table. JRA.
783 : */
784 42246 : ok = canonicalize_connect_path(conn);
785 42246 : if (!ok) {
786 24 : DBG_ERR("canonicalize_connect_path failed "
787 : "for service %s, path %s\n",
788 : lp_const_servicename(snum),
789 : conn->connectpath);
790 24 : status = NT_STATUS_BAD_NETWORK_NAME;
791 24 : goto err_root_exit;
792 : }
793 :
794 : /* Add veto/hide lists */
795 42222 : if (!IS_IPC(conn) && !IS_PRINT(conn)) {
796 18817 : set_namearray( &conn->veto_list,
797 18817 : lp_veto_files(talloc_tos(), lp_sub, snum));
798 18817 : set_namearray( &conn->hide_list,
799 18817 : lp_hide_files(talloc_tos(), lp_sub, snum));
800 18817 : set_namearray( &conn->veto_oplock_list,
801 18817 : lp_veto_oplock_files(talloc_tos(), lp_sub, snum));
802 18817 : set_namearray( &conn->aio_write_behind_list,
803 18817 : lp_aio_write_behind(talloc_tos(), lp_sub, snum));
804 : }
805 42222 : smb_fname_cpath = synthetic_smb_fname(talloc_tos(),
806 42222 : conn->connectpath,
807 : NULL,
808 : NULL,
809 : 0,
810 : 0);
811 42222 : if (smb_fname_cpath == NULL) {
812 0 : status = NT_STATUS_NO_MEMORY;
813 0 : goto err_root_exit;
814 : }
815 :
816 : /* win2000 does not check the permissions on the directory
817 : during the tree connect, instead relying on permission
818 : check during individual operations. To match this behaviour
819 : I have disabled this chdir check (tridge) */
820 : /* the alternative is just to check the directory exists */
821 :
822 80863 : if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
823 42222 : !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
824 0 : if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
825 0 : DBG_ERR("'%s' is not a directory, when connecting to "
826 : "[%s]\n", conn->connectpath,
827 : lp_const_servicename(snum));
828 : } else {
829 0 : DBG_ERR("'%s' does not exist or permission denied "
830 : "when connecting to [%s] Error was %s\n",
831 : conn->connectpath,
832 : lp_const_servicename(snum),
833 : strerror(errno));
834 : }
835 0 : status = NT_STATUS_BAD_NETWORK_NAME;
836 0 : goto err_root_exit;
837 : }
838 42222 : conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
839 :
840 : /* Figure out the characteristics of the underlying filesystem. This
841 : * assumes that all the filesystem mounted within a share path have
842 : * the same characteristics, which is likely but not guaranteed.
843 : */
844 :
845 42222 : conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
846 :
847 : /*
848 : * Print out the 'connected as' stuff here as we need
849 : * to know the effective uid and gid we will be using
850 : * (at least initially).
851 : */
852 :
853 42222 : if( DEBUGLVL( IS_IPC(conn) ? 3 : 2 ) ) {
854 0 : dbgtext( "%s (%s) ", get_remote_machine_name(),
855 0 : tsocket_address_string(conn->sconn->remote_address,
856 : talloc_tos()) );
857 0 : dbgtext( "%s", srv_is_signing_active(xconn) ? "signed " : "");
858 0 : dbgtext( "connect to service %s ",
859 : lp_const_servicename(snum) );
860 0 : dbgtext( "initially as user %s ",
861 0 : conn->session_info->unix_info->unix_name );
862 0 : dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
863 0 : dbgtext( "(pid %d)\n", (int)getpid() );
864 : }
865 :
866 42222 : conn->tcon_done = true;
867 42222 : return NT_STATUS_OK;
868 :
869 88 : err_root_exit:
870 :
871 88 : TALLOC_FREE(smb_fname_cpath);
872 : /* We must exit this function as root. */
873 94 : if (geteuid() != 0) {
874 0 : change_to_root_user();
875 : }
876 94 : if (on_err_call_dis_hook) {
877 : /* Call VFS disconnect hook */
878 24 : SMB_VFS_DISCONNECT(conn);
879 : }
880 94 : return status;
881 : }
882 :
883 : /****************************************************************************
884 : Make a connection to a service from SMB1. Internal interface.
885 : ****************************************************************************/
886 :
887 7586 : static connection_struct *make_connection_smb1(struct smb_request *req,
888 : NTTIME now,
889 : int snum,
890 : const char *pdev,
891 : NTSTATUS *pstatus)
892 : {
893 7239 : const struct loadparm_substitution *lp_sub =
894 347 : loadparm_s3_global_substitution();
895 : struct smbXsrv_tcon *tcon;
896 : NTSTATUS status;
897 : struct connection_struct *conn;
898 :
899 7586 : status = smb1srv_tcon_create(req->xconn, now, &tcon);
900 7586 : if (!NT_STATUS_IS_OK(status)) {
901 0 : DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
902 : nt_errstr(status)));
903 0 : *pstatus = status;
904 0 : return NULL;
905 : }
906 :
907 7586 : conn = conn_new(req->sconn);
908 7586 : if (!conn) {
909 0 : TALLOC_FREE(tcon);
910 :
911 0 : DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
912 0 : *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
913 0 : return NULL;
914 : }
915 :
916 7586 : conn->cnum = tcon->global->tcon_wire_id;
917 7586 : conn->tcon = tcon;
918 :
919 7586 : *pstatus = make_connection_snum(req->xconn,
920 : conn,
921 : snum,
922 : req->session,
923 : pdev);
924 7586 : if (!NT_STATUS_IS_OK(*pstatus)) {
925 58 : conn_free(conn);
926 58 : TALLOC_FREE(tcon);
927 52 : return NULL;
928 : }
929 :
930 7528 : tcon->global->share_name = lp_servicename(tcon->global, lp_sub, SNUM(conn));
931 7528 : if (tcon->global->share_name == NULL) {
932 0 : conn_free(conn);
933 0 : TALLOC_FREE(tcon);
934 0 : *pstatus = NT_STATUS_NO_MEMORY;
935 0 : return NULL;
936 : }
937 14579 : tcon->global->session_global_id =
938 14579 : req->session->global->session_global_id;
939 :
940 7528 : tcon->compat = talloc_move(tcon, &conn);
941 7528 : tcon->status = NT_STATUS_OK;
942 :
943 7528 : *pstatus = smbXsrv_tcon_update(tcon);
944 7528 : if (!NT_STATUS_IS_OK(*pstatus)) {
945 0 : TALLOC_FREE(tcon);
946 0 : return NULL;
947 : }
948 :
949 7528 : return tcon->compat;
950 : }
951 :
952 : /****************************************************************************
953 : Make a connection to a service from SMB2. External SMB2 interface.
954 : We must set cnum before claiming connection.
955 : ****************************************************************************/
956 :
957 34730 : connection_struct *make_connection_smb2(struct smbd_smb2_request *req,
958 : struct smbXsrv_tcon *tcon,
959 : int snum,
960 : const char *pdev,
961 : NTSTATUS *pstatus)
962 : {
963 34730 : struct smbd_server_connection *sconn = req->sconn;
964 34730 : connection_struct *conn = conn_new(sconn);
965 34730 : if (!conn) {
966 0 : DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
967 0 : *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
968 0 : return NULL;
969 : }
970 :
971 34730 : conn->cnum = tcon->global->tcon_wire_id;
972 34730 : conn->tcon = tcon;
973 :
974 34730 : *pstatus = make_connection_snum(req->xconn,
975 : conn,
976 : snum,
977 : req->session,
978 : pdev);
979 34730 : if (!NT_STATUS_IS_OK(*pstatus)) {
980 36 : conn_free(conn);
981 36 : return NULL;
982 : }
983 34304 : return conn;
984 : }
985 :
986 : /****************************************************************************
987 : Make a connection to a service. External SMB1 interface.
988 : *
989 : * @param service
990 : ****************************************************************************/
991 :
992 7594 : connection_struct *make_connection(struct smb_request *req,
993 : NTTIME now,
994 : const char *service_in,
995 : const char *pdev, uint64_t vuid,
996 : NTSTATUS *status)
997 : {
998 7594 : struct smbd_server_connection *sconn = req->sconn;
999 7594 : struct smbXsrv_session *session = req->session;
1000 7246 : const struct loadparm_substitution *lp_sub =
1001 348 : loadparm_s3_global_substitution();
1002 : uid_t euid;
1003 7594 : char *service = NULL;
1004 : fstring dev;
1005 7594 : int snum = -1;
1006 :
1007 7594 : fstrcpy(dev, pdev);
1008 :
1009 : /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1010 : * root. */
1011 7594 : if (!non_root_mode() && (euid = geteuid()) != 0) {
1012 0 : DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1013 : "(%u)\n", (unsigned int)euid ));
1014 0 : smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1015 : }
1016 :
1017 7594 : if (conn_num_open(sconn) > 2047) {
1018 0 : *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1019 0 : return NULL;
1020 : }
1021 :
1022 7594 : if (session == NULL) {
1023 0 : DEBUG(1,("make_connection: refusing to connect with "
1024 : "no session setup\n"));
1025 0 : *status = NT_STATUS_ACCESS_DENIED;
1026 0 : return NULL;
1027 : }
1028 :
1029 : /* Logic to try and connect to the correct [homes] share, preferably
1030 : without too many getpwnam() lookups. This is particulary nasty for
1031 : winbind usernames, where the share name isn't the same as unix
1032 : username.
1033 : */
1034 :
1035 7594 : if (strequal(service_in,HOMES_NAME)) {
1036 0 : if (session->homes_snum == -1) {
1037 0 : DEBUG(2, ("[homes] share not available for "
1038 : "this user because it was not found "
1039 : "or created at session setup "
1040 : "time\n"));
1041 0 : *status = NT_STATUS_BAD_NETWORK_NAME;
1042 0 : return NULL;
1043 : }
1044 0 : DEBUG(5, ("making a connection to [homes] service "
1045 : "created at session setup time\n"));
1046 0 : return make_connection_smb1(req, now,
1047 0 : session->homes_snum,
1048 : dev, status);
1049 7594 : } else if ((session->homes_snum != -1)
1050 4400 : && strequal(service_in,
1051 4400 : lp_const_servicename(session->homes_snum))) {
1052 0 : DEBUG(5, ("making a connection to 'homes' service [%s] "
1053 : "created at session setup time\n", service_in));
1054 0 : return make_connection_smb1(req, now,
1055 0 : session->homes_snum,
1056 : dev, status);
1057 : }
1058 :
1059 7594 : service = talloc_strdup(talloc_tos(), service_in);
1060 7594 : if (!service) {
1061 0 : *status = NT_STATUS_NO_MEMORY;
1062 0 : return NULL;
1063 : }
1064 :
1065 7594 : if (!strlower_m(service)) {
1066 0 : DEBUG(2, ("strlower_m %s failed\n", service));
1067 0 : *status = NT_STATUS_INVALID_PARAMETER;
1068 0 : return NULL;
1069 : }
1070 :
1071 7594 : snum = find_service(talloc_tos(), service, &service);
1072 7594 : if (!service) {
1073 0 : *status = NT_STATUS_NO_MEMORY;
1074 0 : return NULL;
1075 : }
1076 :
1077 7594 : if (snum < 0) {
1078 16 : if (strequal(service,"IPC$") ||
1079 8 : (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1080 0 : DEBUG(3,("refusing IPC connection to %s\n", service));
1081 0 : *status = NT_STATUS_ACCESS_DENIED;
1082 0 : return NULL;
1083 : }
1084 :
1085 8 : DEBUG(3,("%s (%s) couldn't find service %s\n",
1086 : get_remote_machine_name(),
1087 : tsocket_address_string(
1088 : sconn->remote_address, talloc_tos()),
1089 : service));
1090 8 : *status = NT_STATUS_BAD_NETWORK_NAME;
1091 8 : return NULL;
1092 : }
1093 :
1094 : /* Handle non-Dfs clients attempting connections to msdfs proxy */
1095 7586 : if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), lp_sub, snum) != '\0')) {
1096 0 : DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1097 : "(pointing to %s)\n",
1098 : service, lp_msdfs_proxy(talloc_tos(), lp_sub, snum)));
1099 0 : *status = NT_STATUS_BAD_NETWORK_NAME;
1100 0 : return NULL;
1101 : }
1102 :
1103 7586 : DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1104 :
1105 7586 : return make_connection_smb1(req, now, snum,
1106 : dev, status);
1107 : }
1108 :
1109 : /****************************************************************************
1110 : Close a cnum.
1111 : ****************************************************************************/
1112 :
1113 42172 : void close_cnum(connection_struct *conn, uint64_t vuid)
1114 : {
1115 42172 : char rootpath[2] = { '/', '\0'};
1116 42172 : struct smb_filename root_fname = { .base_name = rootpath };
1117 38595 : const struct loadparm_substitution *lp_sub =
1118 3577 : loadparm_s3_global_substitution();
1119 :
1120 42172 : file_close_conn(conn);
1121 :
1122 42172 : change_to_root_user();
1123 :
1124 42172 : DEBUG(IS_IPC(conn)?3:2, ("%s (%s) closed connection to service %s\n",
1125 : get_remote_machine_name(),
1126 : tsocket_address_string(conn->sconn->remote_address,
1127 : talloc_tos()),
1128 : lp_const_servicename(SNUM(conn))));
1129 :
1130 : /* make sure we leave the directory available for unmount */
1131 42172 : vfs_ChDir(conn, &root_fname);
1132 :
1133 : /* Call VFS disconnect hook */
1134 42172 : SMB_VFS_DISCONNECT(conn);
1135 :
1136 : /* execute any "postexec = " line */
1137 42172 : if (*lp_postexec(talloc_tos(), lp_sub, SNUM(conn)) &&
1138 0 : change_to_user_and_service(conn, vuid)) {
1139 0 : char *cmd = talloc_sub_full(talloc_tos(),
1140 0 : lp_const_servicename(SNUM(conn)),
1141 0 : conn->session_info->unix_info->unix_name,
1142 0 : conn->connectpath,
1143 0 : conn->session_info->unix_token->gid,
1144 0 : conn->session_info->unix_info->sanitized_username,
1145 0 : conn->session_info->info->domain_name,
1146 0 : lp_postexec(talloc_tos(), lp_sub, SNUM(conn)));
1147 0 : smbrun(cmd, NULL, NULL);
1148 0 : TALLOC_FREE(cmd);
1149 0 : change_to_root_user();
1150 : }
1151 :
1152 42172 : change_to_root_user();
1153 : /* execute any "root postexec = " line */
1154 42172 : if (*lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn))) {
1155 0 : char *cmd = talloc_sub_full(talloc_tos(),
1156 0 : lp_const_servicename(SNUM(conn)),
1157 0 : conn->session_info->unix_info->unix_name,
1158 0 : conn->connectpath,
1159 0 : conn->session_info->unix_token->gid,
1160 0 : conn->session_info->unix_info->sanitized_username,
1161 0 : conn->session_info->info->domain_name,
1162 0 : lp_root_postexec(talloc_tos(), lp_sub, SNUM(conn)));
1163 0 : smbrun(cmd, NULL, NULL);
1164 0 : TALLOC_FREE(cmd);
1165 : }
1166 :
1167 42172 : conn_free(conn);
1168 42172 : }
|