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

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

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

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