source: trunk/server/source3/smbd/service.c@ 745

Last change on this file since 745 was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 37.1 KB
Line 
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 "../lib/tsocket/tsocket.h"
23#include "smbd/smbd.h"
24#include "smbd/globals.h"
25#include "../librpc/gen_ndr/netlogon.h"
26#include "../libcli/security/security.h"
27#include "printing/pcap.h"
28#include "passdb/lookup_sid.h"
29#include "auth.h"
30
31extern userdom_struct current_user_info;
32
33static bool canonicalize_connect_path(connection_struct *conn)
34{
35 bool ret;
36 char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath);
37 if (!resolved_name) {
38 return false;
39 }
40 ret = set_conn_connectpath(conn,resolved_name);
41 SAFE_FREE(resolved_name);
42 return ret;
43}
44
45/****************************************************************************
46 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
47 absolute path stating in / and not ending in /.
48 Observent people will notice a similarity between this and check_path_syntax :-).
49****************************************************************************/
50
51bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
52{
53 char *destname;
54 char *d;
55 const char *s = connectpath;
56 bool start_of_name_component = true;
57
58 if (connectpath == NULL || connectpath[0] == '\0') {
59 return false;
60 }
61
62 /* Allocate for strlen + '\0' + possible leading '/' */
63 destname = (char *)SMB_MALLOC(strlen(connectpath) + 2);
64 if (!destname) {
65 return false;
66 }
67 d = destname;
68
69#ifndef __OS2__
70 *d++ = '/'; /* Always start with root. */
71
72 while (*s) {
73 if (*s == '/') {
74 /* Eat multiple '/' */
75 while (*s == '/') {
76 s++;
77 }
78 if ((d > destname + 1) && (*s != '\0')) {
79 *d++ = '/';
80 }
81 start_of_name_component = True;
82 continue;
83 }
84
85 if (start_of_name_component) {
86 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
87 /* Uh oh - "/../" or "/..\0" ! */
88
89 /* Go past the ../ or .. */
90 if (s[2] == '/') {
91 s += 3;
92 } else {
93 s += 2; /* Go past the .. */
94 }
95
96 /* If we just added a '/' - delete it */
97 if ((d > destname) && (*(d-1) == '/')) {
98 *(d-1) = '\0';
99 d--;
100 }
101
102 /* Are we at the start ? Can't go back further if so. */
103 if (d <= destname) {
104 *d++ = '/'; /* Can't delete root */
105 continue;
106 }
107 /* Go back one level... */
108 /* Decrement d first as d points to the *next* char to write into. */
109 for (d--; d > destname; d--) {
110 if (*d == '/') {
111 break;
112 }
113 }
114 /* We're still at the start of a name component, just the previous one. */
115 continue;
116 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
117 /* Component of pathname can't be "." only - skip the '.' . */
118 if (s[1] == '/') {
119 s += 2;
120 } else {
121 s++;
122 }
123 continue;
124 }
125 }
126
127 if (!(*s & 0x80)) {
128 *d++ = *s++;
129 } else {
130 size_t siz;
131 /* Get the size of the next MB character. */
132 next_codepoint(s,&siz);
133 switch(siz) {
134 case 5:
135 *d++ = *s++;
136 /*fall through*/
137 case 4:
138 *d++ = *s++;
139 /*fall through*/
140 case 3:
141 *d++ = *s++;
142 /*fall through*/
143 case 2:
144 *d++ = *s++;
145 /*fall through*/
146 case 1:
147 *d++ = *s++;
148 break;
149 default:
150 break;
151 }
152 }
153 start_of_name_component = false;
154 }
155 *d = '\0';
156
157 /* And must not end in '/' */
158 if (d > destname + 1 && (*(d-1) == '/')) {
159 *(d-1) = '\0';
160 }
161#else
162 /* Assume OS/2 users are smart enough to put a correct path in smb.conf, and simply copy the string */
163 safe_strcpy(destname, connectpath, strlen(connectpath));
164#endif
165
166 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
167 lp_servicename(SNUM(conn)), destname ));
168
169 string_set(&conn->connectpath, destname);
170 SAFE_FREE(destname);
171 return true;
172}
173
174/****************************************************************************
175 Load parameters specific to a connection/service.
176****************************************************************************/
177
178bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
179{
180 int snum;
181
182 if (!conn) {
183 last_conn = NULL;
184 return(False);
185 }
186
187 conn->lastused_count++;
188
189 snum = SNUM(conn);
190
191 if (do_chdir &&
192 vfs_ChDir(conn,conn->connectpath) != 0 &&
193 vfs_ChDir(conn,conn->origpath) != 0) {
194 DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
195 conn->connectpath, strerror(errno)));
196 return(False);
197 }
198
199 if ((conn == last_conn) && (last_flags == flags)) {
200 return(True);
201 }
202
203 last_conn = conn;
204 last_flags = flags;
205
206 /* Obey the client case sensitivity requests - only for clients that support it. */
207 switch (lp_casesensitive(snum)) {
208 case Auto:
209 {
210 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
211 enum remote_arch_types ra_type = get_remote_arch();
212 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
213 /* Client can't support per-packet case sensitive pathnames. */
214 conn->case_sensitive = False;
215 } else {
216 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
217 }
218 }
219 break;
220 case True:
221 conn->case_sensitive = True;
222 break;
223 default:
224 conn->case_sensitive = False;
225 break;
226 }
227 return(True);
228}
229
230static int load_registry_service(const char *servicename)
231{
232 if (!lp_registry_shares()) {
233 return -1;
234 }
235
236 if ((servicename == NULL) || (*servicename == '\0')) {
237 return -1;
238 }
239
240 if (strequal(servicename, GLOBAL_NAME)) {
241 return -2;
242 }
243
244 if (!process_registry_service(servicename)) {
245 return -1;
246 }
247
248 return lp_servicenumber(servicename);
249}
250
251void load_registry_shares(void)
252{
253 DEBUG(8, ("load_registry_shares()\n"));
254 if (!lp_registry_shares()) {
255 return;
256 }
257
258 process_registry_shares();
259
260 return;
261}
262
263/****************************************************************************
264 Add a home service. Returns the new service number or -1 if fail.
265****************************************************************************/
266
267int add_home_service(const char *service, const char *username, const char *homedir)
268{
269 int iHomeService;
270
271 if (!service || !homedir || homedir[0] == '\0')
272 return -1;
273
274 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
275 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
276 return -1;
277 }
278 }
279
280 /*
281 * If this is a winbindd provided username, remove
282 * the domain component before adding the service.
283 * Log a warning if the "path=" parameter does not
284 * include any macros.
285 */
286
287 {
288 const char *p = strchr(service,*lp_winbind_separator());
289
290 /* We only want the 'user' part of the string */
291 if (p) {
292 service = p + 1;
293 }
294 }
295
296 if (!lp_add_home(service, iHomeService, username, homedir)) {
297 return -1;
298 }
299
300 return lp_servicenumber(service);
301
302}
303
304/**
305 * Find a service entry.
306 *
307 * @param service is modified (to canonical form??)
308 **/
309
310int find_service(TALLOC_CTX *ctx, const char *service_in, char **p_service_out)
311{
312 int iService;
313
314 if (!service_in) {
315 return -1;
316 }
317
318 /* First make a copy. */
319 *p_service_out = talloc_strdup(ctx, service_in);
320 if (!*p_service_out) {
321 return -1;
322 }
323
324 all_string_sub(*p_service_out,"\\","/",0);
325
326 iService = lp_servicenumber(*p_service_out);
327
328 /* now handle the special case of a home directory */
329 if (iService < 0) {
330 char *phome_dir = get_user_home_dir(ctx, *p_service_out);
331
332 if(!phome_dir) {
333 /*
334 * Try mapping the servicename, it may
335 * be a Windows to unix mapped user name.
336 */
337 if(map_username(ctx, *p_service_out, p_service_out)) {
338 if (*p_service_out == NULL) {
339 /* Out of memory. */
340 return -1;
341 }
342 phome_dir = get_user_home_dir(
343 ctx, *p_service_out);
344 }
345 }
346
347 DEBUG(3,("checking for home directory %s gave %s\n",*p_service_out,
348 phome_dir?phome_dir:"(NULL)"));
349
350 iService = add_home_service(*p_service_out,*p_service_out /* 'username' */, phome_dir);
351 }
352
353 /* If we still don't have a service, attempt to add it as a printer. */
354 if (iService < 0) {
355 int iPrinterService;
356
357 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
358 iPrinterService = load_registry_service(PRINTERS_NAME);
359 }
360 if (iPrinterService >= 0) {
361 DEBUG(3,("checking whether %s is a valid printer name...\n",
362 *p_service_out));
363 if (pcap_printername_ok(*p_service_out)) {
364 DEBUG(3,("%s is a valid printer name\n",
365 *p_service_out));
366 DEBUG(3,("adding %s as a printer service\n",
367 *p_service_out));
368 lp_add_printer(*p_service_out, iPrinterService);
369 iService = lp_servicenumber(*p_service_out);
370 if (iService < 0) {
371 DEBUG(0,("failed to add %s as a printer service!\n",
372 *p_service_out));
373 }
374 } else {
375 DEBUG(3,("%s is not a valid printer name\n",
376 *p_service_out));
377 }
378 }
379 }
380
381 /* Check for default vfs service? Unsure whether to implement this */
382 if (iService < 0) {
383 }
384
385 if (iService < 0) {
386 iService = load_registry_service(*p_service_out);
387 }
388
389 /* Is it a usershare service ? */
390 if (iService < 0 && *lp_usershare_path()) {
391 /* Ensure the name is canonicalized. */
392 strlower_m(*p_service_out);
393 iService = load_usershare_service(*p_service_out);
394 }
395
396 /* just possibly it's a default service? */
397 if (iService < 0) {
398 char *pdefservice = lp_defaultservice();
399 if (pdefservice &&
400 *pdefservice &&
401 !strequal(pdefservice, *p_service_out)
402 && !strstr_m(*p_service_out,"..")) {
403 /*
404 * We need to do a local copy here as lp_defaultservice()
405 * returns one of the rotating lp_string buffers that
406 * could get overwritten by the recursive find_service() call
407 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
408 */
409 char *defservice = talloc_strdup(ctx, pdefservice);
410
411 if (!defservice) {
412 goto fail;
413 }
414
415 /* Disallow anything except explicit share names. */
416 if (strequal(defservice,HOMES_NAME) ||
417 strequal(defservice, PRINTERS_NAME) ||
418 strequal(defservice, "IPC$")) {
419 TALLOC_FREE(defservice);
420 goto fail;
421 }
422
423 iService = find_service(ctx, defservice, p_service_out);
424 if (!*p_service_out) {
425 TALLOC_FREE(defservice);
426 iService = -1;
427 goto fail;
428 }
429 if (iService >= 0) {
430 all_string_sub(*p_service_out, "_","/",0);
431 iService = lp_add_service(*p_service_out, iService);
432 }
433 TALLOC_FREE(defservice);
434 }
435 }
436
437 if (iService >= 0) {
438 if (!VALID_SNUM(iService)) {
439 DEBUG(0,("Invalid snum %d for %s\n",iService,
440 *p_service_out));
441 iService = -1;
442 }
443 }
444
445 fail:
446
447 if (iService < 0) {
448 DEBUG(3,("find_service() failed to find service %s\n",
449 *p_service_out));
450 }
451
452 return (iService);
453}
454
455
456/****************************************************************************
457 do some basic sainity checks on the share.
458 This function modifies dev, ecode.
459****************************************************************************/
460
461static NTSTATUS share_sanity_checks(struct client_address *client_id, int snum,
462 fstring dev)
463{
464 if (!lp_snum_ok(snum) ||
465 !allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
466 client_id->name, client_id->addr)) {
467 return NT_STATUS_ACCESS_DENIED;
468 }
469
470 if (dev[0] == '?' || !dev[0]) {
471 if (lp_print_ok(snum)) {
472 fstrcpy(dev,"LPT1:");
473 } else if (strequal(lp_fstype(snum), "IPC")) {
474 fstrcpy(dev, "IPC");
475 } else {
476 fstrcpy(dev,"A:");
477 }
478 }
479
480 strupper_m(dev);
481
482 if (lp_print_ok(snum)) {
483 if (!strequal(dev, "LPT1:")) {
484 return NT_STATUS_BAD_DEVICE_TYPE;
485 }
486 } else if (strequal(lp_fstype(snum), "IPC")) {
487 if (!strequal(dev, "IPC")) {
488 return NT_STATUS_BAD_DEVICE_TYPE;
489 }
490 } else if (!strequal(dev, "A:")) {
491 return NT_STATUS_BAD_DEVICE_TYPE;
492 }
493
494 /* Behave as a printer if we are supposed to */
495 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
496 fstrcpy(dev, "LPT1:");
497 }
498
499 return NT_STATUS_OK;
500}
501
502/*
503 * Go through lookup_name etc to find the force'd group.
504 *
505 * Create a new token from src_token, replacing the primary group sid with the
506 * one found.
507 */
508
509static NTSTATUS find_forced_group(bool force_user,
510 int snum, const char *username,
511 struct dom_sid *pgroup_sid,
512 gid_t *pgid)
513{
514 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
515 TALLOC_CTX *frame = talloc_stackframe();
516 struct dom_sid group_sid;
517 enum lsa_SidType type;
518 char *groupname;
519 bool user_must_be_member = False;
520 gid_t gid;
521
522 groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
523 if (groupname == NULL) {
524 DEBUG(1, ("talloc_strdup failed\n"));
525 result = NT_STATUS_NO_MEMORY;
526 goto done;
527 }
528
529 if (groupname[0] == '+') {
530 user_must_be_member = True;
531 groupname += 1;
532 }
533
534 groupname = talloc_string_sub(talloc_tos(), groupname,
535 "%S", lp_servicename(snum));
536 if (groupname == NULL) {
537 DEBUG(1, ("talloc_string_sub failed\n"));
538 result = NT_STATUS_NO_MEMORY;
539 goto done;
540 }
541
542 if (!lookup_name_smbconf(talloc_tos(), groupname,
543 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
544 NULL, NULL, &group_sid, &type)) {
545 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
546 groupname));
547 goto done;
548 }
549
550 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
551 (type != SID_NAME_WKN_GRP)) {
552 DEBUG(10, ("%s is a %s, not a group\n", groupname,
553 sid_type_lookup(type)));
554 goto done;
555 }
556
557 if (!sid_to_gid(&group_sid, &gid)) {
558 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
559 sid_string_dbg(&group_sid), groupname));
560 goto done;
561 }
562
563 /*
564 * If the user has been forced and the forced group starts with a '+',
565 * then we only set the group to be the forced group if the forced
566 * user is a member of that group. Otherwise, the meaning of the '+'
567 * would be ignored.
568 */
569
570 if (force_user && user_must_be_member) {
571 if (user_in_group_sid(username, &group_sid)) {
572 sid_copy(pgroup_sid, &group_sid);
573 *pgid = gid;
574 DEBUG(3,("Forced group %s for member %s\n",
575 groupname, username));
576 } else {
577 DEBUG(0,("find_forced_group: forced user %s is not a member "
578 "of forced group %s. Disallowing access.\n",
579 username, groupname ));
580 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
581 goto done;
582 }
583 } else {
584 sid_copy(pgroup_sid, &group_sid);
585 *pgid = gid;
586 DEBUG(3,("Forced group %s\n", groupname));
587 }
588
589 result = NT_STATUS_OK;
590 done:
591 TALLOC_FREE(frame);
592 return result;
593}
594
595/****************************************************************************
596 Create an auth_serversupplied_info structure for a connection_struct
597****************************************************************************/
598
599static NTSTATUS create_connection_session_info(struct smbd_server_connection *sconn,
600 TALLOC_CTX *mem_ctx, int snum,
601 struct auth_serversupplied_info *vuid_serverinfo,
602 DATA_BLOB password,
603 struct auth_serversupplied_info **presult)
604{
605 if (lp_guest_only(snum)) {
606 return make_server_info_guest(mem_ctx, presult);
607 }
608
609 if (vuid_serverinfo != NULL) {
610
611 struct auth_serversupplied_info *result;
612
613 /*
614 * This is the normal security != share case where we have a
615 * valid vuid from the session setup. */
616
617 if (vuid_serverinfo->guest) {
618 if (!lp_guest_ok(snum)) {
619 DEBUG(2, ("guest user (from session setup) "
620 "not permitted to access this share "
621 "(%s)\n", lp_servicename(snum)));
622 return NT_STATUS_ACCESS_DENIED;
623 }
624 } else {
625 if (!user_ok_token(vuid_serverinfo->unix_name,
626 vuid_serverinfo->info3->base.domain.string,
627 vuid_serverinfo->security_token, snum)) {
628 DEBUG(2, ("user '%s' (from session setup) not "
629 "permitted to access this share "
630 "(%s)\n",
631 vuid_serverinfo->unix_name,
632 lp_servicename(snum)));
633 return NT_STATUS_ACCESS_DENIED;
634 }
635 }
636
637 result = copy_serverinfo(mem_ctx, vuid_serverinfo);
638 if (result == NULL) {
639 return NT_STATUS_NO_MEMORY;
640 }
641
642 *presult = result;
643 return NT_STATUS_OK;
644 }
645
646 if (lp_security() == SEC_SHARE) {
647
648 fstring user;
649 bool guest;
650
651 /* add the sharename as a possible user name if we
652 are in share mode security */
653
654 add_session_user(sconn, lp_servicename(snum));
655
656 /* shall we let them in? */
657
658 if (!authorise_login(sconn, snum,user,password,&guest)) {
659 DEBUG( 2, ( "Invalid username/password for [%s]\n",
660 lp_servicename(snum)) );
661 return NT_STATUS_WRONG_PASSWORD;
662 }
663
664 return make_serverinfo_from_username(mem_ctx, user, guest,
665 presult);
666 }
667
668 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
669 return NT_STATUS_ACCESS_DENIED;
670}
671
672/****************************************************************************
673 set relavent user and group settings corresponding to force user/group
674 configuration for the given snum.
675****************************************************************************/
676
677NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
678{
679 NTSTATUS status;
680
681 if (*lp_force_user(snum)) {
682
683 /*
684 * Replace conn->session_info with a completely faked up one
685 * from the username we are forced into :-)
686 */
687
688 char *fuser;
689 struct auth_serversupplied_info *forced_serverinfo;
690
691 fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
692 lp_const_servicename(snum));
693 if (fuser == NULL) {
694 return NT_STATUS_NO_MEMORY;
695 }
696
697 status = make_serverinfo_from_username(
698 conn, fuser, conn->session_info->guest,
699 &forced_serverinfo);
700 if (!NT_STATUS_IS_OK(status)) {
701 return status;
702 }
703
704 TALLOC_FREE(conn->session_info);
705 conn->session_info = forced_serverinfo;
706
707 conn->force_user = true;
708 DEBUG(3,("Forced user %s\n", fuser));
709 }
710
711 /*
712 * If force group is true, then override
713 * any groupid stored for the connecting user.
714 */
715
716 if (*lp_force_group(snum)) {
717
718 status = find_forced_group(
719 conn->force_user, snum, conn->session_info->unix_name,
720 &conn->session_info->security_token->sids[1],
721 &conn->session_info->utok.gid);
722
723 if (!NT_STATUS_IS_OK(status)) {
724 return status;
725 }
726
727 /*
728 * We need to cache this gid, to use within
729 * change_to_user() separately from the conn->session_info
730 * struct. We only use conn->session_info directly if
731 * "force_user" was set.
732 */
733 conn->force_group_gid = conn->session_info->utok.gid;
734 }
735
736 return NT_STATUS_OK;
737}
738
739/****************************************************************************
740 Make a connection, given the snum to connect to, and the vuser of the
741 connecting user if appropriate.
742****************************************************************************/
743
744connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
745 int snum, user_struct *vuser,
746 DATA_BLOB password,
747 const char *pdev,
748 NTSTATUS *pstatus)
749{
750 connection_struct *conn = NULL;
751 struct smb_filename *smb_fname_cpath = NULL;
752 fstring dev;
753 int ret;
754 bool on_err_call_dis_hook = false;
755 bool claimed_connection = false;
756 uid_t effuid;
757 gid_t effgid;
758 NTSTATUS status;
759
760 fstrcpy(dev, pdev);
761
762 *pstatus = share_sanity_checks(&sconn->client_id, snum, dev);
763 if (NT_STATUS_IS_ERR(*pstatus)) {
764 goto err_root_exit;
765 }
766
767 conn = conn_new(sconn);
768 if (!conn) {
769 DEBUG(0,("Couldn't find free connection.\n"));
770 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
771 goto err_root_exit;
772 }
773
774 conn->params->service = snum;
775
776 status = create_connection_session_info(sconn,
777 conn, snum, vuser ? vuser->session_info : NULL, password,
778 &conn->session_info);
779
780 if (!NT_STATUS_IS_OK(status)) {
781 DEBUG(1, ("create_connection_session_info failed: %s\n",
782 nt_errstr(status)));
783 *pstatus = status;
784 goto err_root_exit;
785 }
786
787 if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
788 conn->force_user = true;
789 }
790
791 add_session_user(sconn, conn->session_info->unix_name);
792
793 conn->num_files_open = 0;
794 conn->lastused = conn->lastused_count = time(NULL);
795 conn->used = True;
796 conn->printer = (strncmp(dev,"LPT",3) == 0);
797 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
798 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
799
800 /* Case options for the share. */
801 if (lp_casesensitive(snum) == Auto) {
802 /* We will be setting this per packet. Set to be case
803 * insensitive for now. */
804 conn->case_sensitive = False;
805 } else {
806 conn->case_sensitive = (bool)lp_casesensitive(snum);
807 }
808
809 conn->case_preserve = lp_preservecase(snum);
810 conn->short_case_preserve = lp_shortpreservecase(snum);
811
812 conn->encrypt_level = lp_smb_encrypt(snum);
813
814 conn->veto_list = NULL;
815 conn->hide_list = NULL;
816 conn->veto_oplock_list = NULL;
817 conn->aio_write_behind_list = NULL;
818
819 conn->read_only = lp_readonly(SNUM(conn));
820
821 status = set_conn_force_user_group(conn, snum);
822 if (!NT_STATUS_IS_OK(status)) {
823 conn_free(conn);
824 *pstatus = status;
825 return NULL;
826 }
827
828 conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;
829
830 {
831 char *s = talloc_sub_advanced(talloc_tos(),
832 lp_servicename(SNUM(conn)),
833 conn->session_info->unix_name,
834 conn->connectpath,
835 conn->session_info->utok.gid,
836 conn->session_info->sanitized_username,
837 conn->session_info->info3->base.domain.string,
838 lp_pathname(snum));
839 if (!s) {
840 *pstatus = NT_STATUS_NO_MEMORY;
841 goto err_root_exit;
842 }
843
844 if (!set_conn_connectpath(conn,s)) {
845 TALLOC_FREE(s);
846 *pstatus = NT_STATUS_NO_MEMORY;
847 goto err_root_exit;
848 }
849 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
850 lp_servicename(snum)));
851 TALLOC_FREE(s);
852 }
853
854 /*
855 * New code to check if there's a share security descripter
856 * added from NT server manager. This is done after the
857 * smb.conf checks are done as we need a uid and token. JRA.
858 *
859 */
860
861 share_access_check(conn->session_info->security_token,
862 lp_servicename(snum), MAXIMUM_ALLOWED_ACCESS,
863 &conn->share_access);
864
865 if ((conn->share_access & FILE_WRITE_DATA) == 0) {
866 if ((conn->share_access & FILE_READ_DATA) == 0) {
867 /* No access, read or write. */
868 DEBUG(0,("make_connection: connection to %s "
869 "denied due to security "
870 "descriptor.\n",
871 lp_servicename(snum)));
872 *pstatus = NT_STATUS_ACCESS_DENIED;
873 goto err_root_exit;
874 } else {
875 conn->read_only = True;
876 }
877 }
878 /* Initialise VFS function pointers */
879
880 if (!smbd_vfs_init(conn)) {
881 DEBUG(0, ("vfs_init failed for service %s\n",
882 lp_servicename(snum)));
883 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
884 goto err_root_exit;
885 }
886
887/* ROOT Activities: */
888 /* explicitly check widelinks here so that we can correctly warn
889 * in the logs. */
890 widelinks_warning(snum);
891
892 /*
893 * Enforce the max connections parameter.
894 */
895
896 if ((lp_max_connections(snum) > 0)
897 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
898 lp_max_connections(snum))) {
899
900 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
901 lp_max_connections(snum), lp_servicename(snum)));
902 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
903 goto err_root_exit;
904 }
905
906 /*
907 * Get us an entry in the connections db
908 */
909 if (!claim_connection(conn, lp_servicename(snum))) {
910 DEBUG(1, ("Could not store connections entry\n"));
911 *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
912 goto err_root_exit;
913 }
914 claimed_connection = true;
915
916 /* Invoke VFS make connection hook - this must be the first
917 filesystem operation that we do. */
918
919 if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
920 conn->session_info->unix_name) < 0) {
921 DEBUG(0,("make_connection: VFS make connection failed!\n"));
922 *pstatus = NT_STATUS_UNSUCCESSFUL;
923 goto err_root_exit;
924 }
925
926 /* Any error exit after here needs to call the disconnect hook. */
927 on_err_call_dis_hook = true;
928
929 if ((!conn->printer) && (!conn->ipc)) {
930 conn->notify_ctx = notify_init(conn,
931 sconn_server_id(sconn),
932 sconn->msg_ctx,
933 smbd_event_context(),
934 conn);
935 }
936
937 /*
938 * Fix compatibility issue pointed out by Volker.
939 * We pass the conn->connectpath to the preexec
940 * scripts as a parameter, so attempt to canonicalize
941 * it here before calling the preexec scripts.
942 * We ignore errors here, as it is possible that
943 * the conn->connectpath doesn't exist yet and
944 * the preexec scripts will create them.
945 */
946
947 (void)canonicalize_connect_path(conn);
948
949 /* Preexecs are done here as they might make the dir we are to ChDir
950 * to below */
951 /* execute any "root preexec = " line */
952 if (*lp_rootpreexec(snum)) {
953 char *cmd = talloc_sub_advanced(talloc_tos(),
954 lp_servicename(SNUM(conn)),
955 conn->session_info->unix_name,
956 conn->connectpath,
957 conn->session_info->utok.gid,
958 conn->session_info->sanitized_username,
959 conn->session_info->info3->base.domain.string,
960 lp_rootpreexec(snum));
961 DEBUG(5,("cmd=%s\n",cmd));
962 ret = smbrun(cmd,NULL);
963 TALLOC_FREE(cmd);
964 if (ret != 0 && lp_rootpreexec_close(snum)) {
965 DEBUG(1,("root preexec gave %d - failing "
966 "connection\n", ret));
967 *pstatus = NT_STATUS_ACCESS_DENIED;
968 goto err_root_exit;
969 }
970 }
971
972/* USER Activites: */
973 if (!change_to_user(conn, conn->vuid)) {
974 /* No point continuing if they fail the basic checks */
975 DEBUG(0,("Can't become connected user!\n"));
976 *pstatus = NT_STATUS_LOGON_FAILURE;
977 goto err_root_exit;
978 }
979
980 effuid = geteuid();
981 effgid = getegid();
982
983 /* Remember that a different vuid can connect later without these
984 * checks... */
985
986 /* Preexecs are done here as they might make the dir we are to ChDir
987 * to below */
988
989 /* execute any "preexec = " line */
990 if (*lp_preexec(snum)) {
991 char *cmd = talloc_sub_advanced(talloc_tos(),
992 lp_servicename(SNUM(conn)),
993 conn->session_info->unix_name,
994 conn->connectpath,
995 conn->session_info->utok.gid,
996 conn->session_info->sanitized_username,
997 conn->session_info->info3->base.domain.string,
998 lp_preexec(snum));
999 ret = smbrun(cmd,NULL);
1000 TALLOC_FREE(cmd);
1001 if (ret != 0 && lp_preexec_close(snum)) {
1002 DEBUG(1,("preexec gave %d - failing connection\n",
1003 ret));
1004 *pstatus = NT_STATUS_ACCESS_DENIED;
1005 goto err_root_exit;
1006 }
1007 }
1008
1009#ifdef WITH_FAKE_KASERVER
1010 if (lp_afs_share(snum)) {
1011 afs_login(conn);
1012 }
1013#endif
1014
1015 /*
1016 * we've finished with the user stuff - go back to root
1017 * so the SMB_VFS_STAT call will only fail on path errors,
1018 * not permission problems.
1019 */
1020 change_to_root_user();
1021/* ROOT Activites: */
1022
1023 /*
1024 * If widelinks are disallowed we need to canonicalise the connect
1025 * path here to ensure we don't have any symlinks in the
1026 * connectpath. We will be checking all paths on this connection are
1027 * below this directory. We must do this after the VFS init as we
1028 * depend on the realpath() pointer in the vfs table. JRA.
1029 */
1030 if (!lp_widelinks(snum)) {
1031 if (!canonicalize_connect_path(conn)) {
1032 DEBUG(0, ("canonicalize_connect_path failed "
1033 "for service %s, path %s\n",
1034 lp_servicename(snum),
1035 conn->connectpath));
1036 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1037 goto err_root_exit;
1038 }
1039 }
1040
1041 /* Add veto/hide lists */
1042 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1043 set_namearray( &conn->veto_list, lp_veto_files(snum));
1044 set_namearray( &conn->hide_list, lp_hide_files(snum));
1045 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1046 set_namearray( &conn->aio_write_behind_list,
1047 lp_aio_write_behind(snum));
1048 }
1049 status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
1050 NULL, NULL, &smb_fname_cpath);
1051 if (!NT_STATUS_IS_OK(status)) {
1052 *pstatus = status;
1053 goto err_root_exit;
1054 }
1055
1056 /* win2000 does not check the permissions on the directory
1057 during the tree connect, instead relying on permission
1058 check during individual operations. To match this behaviour
1059 I have disabled this chdir check (tridge) */
1060 /* the alternative is just to check the directory exists */
1061
1062 if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
1063 !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1064 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
1065 DEBUG(0,("'%s' is not a directory, when connecting to "
1066 "[%s]\n", conn->connectpath,
1067 lp_servicename(snum)));
1068 } else {
1069 DEBUG(0,("'%s' does not exist or permission denied "
1070 "when connecting to [%s] Error was %s\n",
1071 conn->connectpath, lp_servicename(snum),
1072 strerror(errno) ));
1073 }
1074 *pstatus = NT_STATUS_BAD_NETWORK_NAME;
1075 goto err_root_exit;
1076 }
1077 conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
1078
1079 string_set(&conn->origpath,conn->connectpath);
1080
1081 /* Figure out the characteristics of the underlying filesystem. This
1082 * assumes that all the filesystem mounted withing a share path have
1083 * the same characteristics, which is likely but not guaranteed.
1084 */
1085
1086 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
1087
1088 /*
1089 * Print out the 'connected as' stuff here as we need
1090 * to know the effective uid and gid we will be using
1091 * (at least initially).
1092 */
1093
1094 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1095 dbgtext( "%s (%s) ", get_remote_machine_name(),
1096 conn->sconn->client_id.addr );
1097 dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : "");
1098 dbgtext( "connect to service %s ", lp_servicename(snum) );
1099 dbgtext( "initially as user %s ",
1100 conn->session_info->unix_name );
1101 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
1102 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1103 }
1104
1105 return(conn);
1106
1107 err_root_exit:
1108 TALLOC_FREE(smb_fname_cpath);
1109 /* We must exit this function as root. */
1110 if (geteuid() != 0) {
1111 change_to_root_user();
1112 }
1113 if (on_err_call_dis_hook) {
1114 /* Call VFS disconnect hook */
1115 SMB_VFS_DISCONNECT(conn);
1116 }
1117 if (claimed_connection) {
1118 yield_connection(conn, lp_servicename(snum));
1119 }
1120 if (conn) {
1121 conn_free(conn);
1122 }
1123 return NULL;
1124}
1125
1126/****************************************************************************
1127 Make a connection to a service.
1128 *
1129 * @param service
1130****************************************************************************/
1131
1132connection_struct *make_connection(struct smbd_server_connection *sconn,
1133 const char *service_in, DATA_BLOB password,
1134 const char *pdev, uint16 vuid,
1135 NTSTATUS *status)
1136{
1137 uid_t euid;
1138 user_struct *vuser = NULL;
1139 char *service = NULL;
1140 fstring dev;
1141 int snum = -1;
1142
1143 fstrcpy(dev, pdev);
1144
1145 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1146 * root. */
1147 if (!non_root_mode() && (euid = geteuid()) != 0) {
1148 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1149 "(%u)\n", (unsigned int)euid ));
1150 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1151 }
1152
1153 if (conn_num_open(sconn) > 2047) {
1154 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1155 return NULL;
1156 }
1157
1158 if(lp_security() != SEC_SHARE) {
1159 vuser = get_valid_user_struct(sconn, vuid);
1160 if (!vuser) {
1161 DEBUG(1,("make_connection: refusing to connect with "
1162 "no session setup\n"));
1163 *status = NT_STATUS_ACCESS_DENIED;
1164 return NULL;
1165 }
1166 }
1167
1168 /* Logic to try and connect to the correct [homes] share, preferably
1169 without too many getpwnam() lookups. This is particulary nasty for
1170 winbind usernames, where the share name isn't the same as unix
1171 username.
1172
1173 The snum of the homes share is stored on the vuser at session setup
1174 time.
1175 */
1176
1177 if (strequal(service_in,HOMES_NAME)) {
1178 if(lp_security() != SEC_SHARE) {
1179 DATA_BLOB no_pw = data_blob_null;
1180 if (vuser->homes_snum == -1) {
1181 DEBUG(2, ("[homes] share not available for "
1182 "this user because it was not found "
1183 "or created at session setup "
1184 "time\n"));
1185 *status = NT_STATUS_BAD_NETWORK_NAME;
1186 return NULL;
1187 }
1188 DEBUG(5, ("making a connection to [homes] service "
1189 "created at session setup time\n"));
1190 return make_connection_snum(sconn,
1191 vuser->homes_snum,
1192 vuser, no_pw,
1193 dev, status);
1194 } else {
1195 /* Security = share. Try with
1196 * current_user_info.smb_name as the username. */
1197 if (*current_user_info.smb_name) {
1198 char *unix_username = NULL;
1199 (void)map_username(talloc_tos(),
1200 current_user_info.smb_name,
1201 &unix_username);
1202 snum = find_service(talloc_tos(),
1203 unix_username,
1204 &unix_username);
1205 if (!unix_username) {
1206 *status = NT_STATUS_NO_MEMORY;
1207 }
1208 return NULL;
1209 }
1210 if (snum != -1) {
1211 DEBUG(5, ("making a connection to 'homes' "
1212 "service %s based on "
1213 "security=share\n", service_in));
1214 return make_connection_snum(sconn,
1215 snum, NULL,
1216 password,
1217 dev, status);
1218 }
1219 }
1220 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1221 && strequal(service_in,
1222 lp_servicename(vuser->homes_snum))) {
1223 DATA_BLOB no_pw = data_blob_null;
1224 DEBUG(5, ("making a connection to 'homes' service [%s] "
1225 "created at session setup time\n", service_in));
1226 return make_connection_snum(sconn,
1227 vuser->homes_snum,
1228 vuser, no_pw,
1229 dev, status);
1230 }
1231
1232 service = talloc_strdup(talloc_tos(), service_in);
1233 if (!service) {
1234 *status = NT_STATUS_NO_MEMORY;
1235 return NULL;
1236 }
1237
1238 strlower_m(service);
1239
1240 snum = find_service(talloc_tos(), service, &service);
1241 if (!service) {
1242 *status = NT_STATUS_NO_MEMORY;
1243 return NULL;
1244 }
1245
1246 if (snum < 0) {
1247 if (strequal(service,"IPC$") ||
1248 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1249 DEBUG(3,("refusing IPC connection to %s\n", service));
1250 *status = NT_STATUS_ACCESS_DENIED;
1251 return NULL;
1252 }
1253
1254 DEBUG(3,("%s (%s) couldn't find service %s\n",
1255 get_remote_machine_name(),
1256 tsocket_address_string(
1257 sconn->remote_address, talloc_tos()),
1258 service));
1259 *status = NT_STATUS_BAD_NETWORK_NAME;
1260 return NULL;
1261 }
1262
1263 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1264 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1265 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1266 "(pointing to %s)\n",
1267 service, lp_msdfs_proxy(snum)));
1268 *status = NT_STATUS_BAD_NETWORK_NAME;
1269 return NULL;
1270 }
1271
1272 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1273
1274 return make_connection_snum(sconn, snum, vuser,
1275 password,
1276 dev, status);
1277}
1278
1279/****************************************************************************
1280 Close a cnum.
1281****************************************************************************/
1282
1283void close_cnum(connection_struct *conn, uint16 vuid)
1284{
1285 file_close_conn(conn);
1286
1287 if (!IS_IPC(conn)) {
1288 dptr_closecnum(conn);
1289 }
1290
1291 change_to_root_user();
1292
1293 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1294 get_remote_machine_name(),
1295 conn->sconn->client_id.addr,
1296 lp_servicename(SNUM(conn))));
1297
1298 /* Call VFS disconnect hook */
1299 SMB_VFS_DISCONNECT(conn);
1300
1301 yield_connection(conn, lp_servicename(SNUM(conn)));
1302
1303 /* make sure we leave the directory available for unmount */
1304 vfs_ChDir(conn, "/");
1305
1306 /* execute any "postexec = " line */
1307 if (*lp_postexec(SNUM(conn)) &&
1308 change_to_user(conn, vuid)) {
1309 char *cmd = talloc_sub_advanced(talloc_tos(),
1310 lp_servicename(SNUM(conn)),
1311 conn->session_info->unix_name,
1312 conn->connectpath,
1313 conn->session_info->utok.gid,
1314 conn->session_info->sanitized_username,
1315 conn->session_info->info3->base.domain.string,
1316 lp_postexec(SNUM(conn)));
1317 smbrun(cmd,NULL);
1318 TALLOC_FREE(cmd);
1319 change_to_root_user();
1320 }
1321
1322 change_to_root_user();
1323 /* execute any "root postexec = " line */
1324 if (*lp_rootpostexec(SNUM(conn))) {
1325 char *cmd = talloc_sub_advanced(talloc_tos(),
1326 lp_servicename(SNUM(conn)),
1327 conn->session_info->unix_name,
1328 conn->connectpath,
1329 conn->session_info->utok.gid,
1330 conn->session_info->sanitized_username,
1331 conn->session_info->info3->base.domain.string,
1332 lp_rootpostexec(SNUM(conn)));
1333 smbrun(cmd,NULL);
1334 TALLOC_FREE(cmd);
1335 }
1336
1337 conn_free(conn);
1338}
Note: See TracBrowser for help on using the repository browser.