source: branches/samba-3.3.x/source/smbd/service.c@ 932

Last change on this file since 932 was 411, checked in by Herwig Bauernfeind, 15 years ago

Update Samba 3.3.x to 3.3.11

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