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