source: branches/samba-3.2.x/source/smbd/service.c@ 1075

Last change on this file since 1075 was 340, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 to 3.2.15 (security update)

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