[GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch.
[Samba/gebeck_regimport.git] / source3 / smbd / service.c
blob1c46e3776c28442e94b6fc77770d61c314d4c86f
1 /*
2 Unix SMB/CIFS implementation.
3 service (connection) opening and closing
4 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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/>.
20 #include "includes.h"
22 extern userdom_struct current_user_info;
24 static BOOL canonicalize_path(connection_struct *conn, pstring path)
26 #ifdef REALPATH_TAKES_NULL
27 char *resolved_name = SMB_VFS_REALPATH(conn,path,NULL);
28 if (!resolved_name) {
29 return False;
31 pstrcpy(path, resolved_name);
32 SAFE_FREE(resolved_name);
33 return True;
34 #else
35 #ifdef PATH_MAX
36 char resolved_name_buf[PATH_MAX+1];
37 #else
38 pstring resolved_name_buf;
39 #endif
40 char *resolved_name = SMB_VFS_REALPATH(conn,path,resolved_name_buf);
41 if (!resolved_name) {
42 return False;
44 pstrcpy(path, resolved_name);
45 return True;
46 #endif /* REALPATH_TAKES_NULL */
49 /****************************************************************************
50 Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
51 absolute path stating in / and not ending in /.
52 Observent people will notice a similarity between this and check_path_syntax :-).
53 ****************************************************************************/
55 void set_conn_connectpath(connection_struct *conn, const char *connectpath)
57 pstring destname;
58 char *d = destname;
59 const char *s = connectpath;
60 BOOL start_of_name_component = True;
62 *d++ = '/'; /* Always start with root. */
64 while (*s) {
65 if (*s == '/') {
66 /* Eat multiple '/' */
67 while (*s == '/') {
68 s++;
70 if ((d > destname + 1) && (*s != '\0')) {
71 *d++ = '/';
73 start_of_name_component = True;
74 continue;
77 if (start_of_name_component) {
78 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
79 /* Uh oh - "/../" or "/..\0" ! */
81 /* Go past the ../ or .. */
82 if (s[2] == '/') {
83 s += 3;
84 } else {
85 s += 2; /* Go past the .. */
88 /* If we just added a '/' - delete it */
89 if ((d > destname) && (*(d-1) == '/')) {
90 *(d-1) = '\0';
91 d--;
94 /* Are we at the start ? Can't go back further if so. */
95 if (d <= destname) {
96 *d++ = '/'; /* Can't delete root */
97 continue;
99 /* Go back one level... */
100 /* Decrement d first as d points to the *next* char to write into. */
101 for (d--; d > destname; d--) {
102 if (*d == '/') {
103 break;
106 /* We're still at the start of a name component, just the previous one. */
107 continue;
108 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
109 /* Component of pathname can't be "." only - skip the '.' . */
110 if (s[1] == '/') {
111 s += 2;
112 } else {
113 s++;
115 continue;
119 if (!(*s & 0x80)) {
120 *d++ = *s++;
121 } else {
122 size_t siz;
123 /* Get the size of the next MB character. */
124 next_codepoint(s,&siz);
125 switch(siz) {
126 case 5:
127 *d++ = *s++;
128 /*fall through*/
129 case 4:
130 *d++ = *s++;
131 /*fall through*/
132 case 3:
133 *d++ = *s++;
134 /*fall through*/
135 case 2:
136 *d++ = *s++;
137 /*fall through*/
138 case 1:
139 *d++ = *s++;
140 break;
141 default:
142 break;
145 start_of_name_component = False;
147 *d = '\0';
149 /* And must not end in '/' */
150 if (d > destname + 1 && (*(d-1) == '/')) {
151 *(d-1) = '\0';
154 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
155 lp_servicename(SNUM(conn)), destname ));
157 string_set(&conn->connectpath, destname);
160 /****************************************************************************
161 Load parameters specific to a connection/service.
162 ****************************************************************************/
164 BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
166 static connection_struct *last_conn;
167 static uint16 last_flags;
168 int snum;
170 if (!conn) {
171 last_conn = NULL;
172 return(False);
175 conn->lastused_count++;
177 snum = SNUM(conn);
179 if (do_chdir &&
180 vfs_ChDir(conn,conn->connectpath) != 0 &&
181 vfs_ChDir(conn,conn->origpath) != 0) {
182 DEBUG(0,("chdir (%s) failed\n",
183 conn->connectpath));
184 return(False);
187 if ((conn == last_conn) && (last_flags == flags)) {
188 return(True);
191 last_conn = conn;
192 last_flags = flags;
194 /* Obey the client case sensitivity requests - only for clients that support it. */
195 switch (lp_casesensitive(snum)) {
196 case Auto:
198 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
199 enum remote_arch_types ra_type = get_remote_arch();
200 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
201 /* Client can't support per-packet case sensitive pathnames. */
202 conn->case_sensitive = False;
203 } else {
204 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
207 break;
208 case True:
209 conn->case_sensitive = True;
210 break;
211 default:
212 conn->case_sensitive = False;
213 break;
215 return(True);
218 /****************************************************************************
219 Add a home service. Returns the new service number or -1 if fail.
220 ****************************************************************************/
222 int add_home_service(const char *service, const char *username, const char *homedir)
224 int iHomeService;
226 if (!service || !homedir)
227 return -1;
229 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
230 return -1;
233 * If this is a winbindd provided username, remove
234 * the domain component before adding the service.
235 * Log a warning if the "path=" parameter does not
236 * include any macros.
240 const char *p = strchr(service,*lp_winbind_separator());
242 /* We only want the 'user' part of the string */
243 if (p) {
244 service = p + 1;
248 if (!lp_add_home(service, iHomeService, username, homedir)) {
249 return -1;
252 return lp_servicenumber(service);
256 static int load_registry_service(const char *servicename)
258 struct registry_key *key;
259 char *path;
260 WERROR err;
262 uint32 i;
263 char *value_name;
264 struct registry_value *value;
266 int res = -1;
268 if (!lp_registry_shares()) {
269 return -1;
272 if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
273 return -1;
276 err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(),
277 &key);
278 SAFE_FREE(path);
280 if (!W_ERROR_IS_OK(err)) {
281 return -1;
284 res = lp_add_service(servicename, -1);
285 if (res == -1) {
286 goto error;
289 for (i=0;
290 W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value));
291 i++) {
292 switch (value->type) {
293 case REG_DWORD: {
294 char *tmp;
295 if (asprintf(&tmp, "%d", value->v.dword) == -1) {
296 continue;
298 lp_do_parameter(res, value_name, tmp);
299 SAFE_FREE(tmp);
300 break;
302 case REG_SZ: {
303 lp_do_parameter(res, value_name, value->v.sz.str);
304 break;
306 default:
307 /* Ignore all the rest */
308 break;
311 TALLOC_FREE(value_name);
312 TALLOC_FREE(value);
315 res = 0;
316 error:
318 TALLOC_FREE(key);
319 return res;
322 void load_registry_shares(void)
324 struct registry_key *key;
325 char *name;
326 WERROR err;
327 int i;
329 if (!lp_registry_shares()) {
330 return;
333 err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
334 get_root_nt_token(), &key);
335 if (!(W_ERROR_IS_OK(err))) {
336 return;
339 for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
340 load_registry_service(name);
341 TALLOC_FREE(name);
344 TALLOC_FREE(key);
345 return;
349 * Find a service entry.
351 * @param service is modified (to canonical form??)
354 int find_service(fstring service)
356 int iService;
358 all_string_sub(service,"\\","/",0);
360 iService = lp_servicenumber(service);
362 /* now handle the special case of a home directory */
363 if (iService < 0) {
364 char *phome_dir = get_user_home_dir(service);
366 if(!phome_dir) {
368 * Try mapping the servicename, it may
369 * be a Windows to unix mapped user name.
371 if(map_username(service))
372 phome_dir = get_user_home_dir(service);
375 DEBUG(3,("checking for home directory %s gave %s\n",service,
376 phome_dir?phome_dir:"(NULL)"));
378 iService = add_home_service(service,service /* 'username' */, phome_dir);
381 /* If we still don't have a service, attempt to add it as a printer. */
382 if (iService < 0) {
383 int iPrinterService;
385 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
386 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
387 if (pcap_printername_ok(service)) {
388 DEBUG(3,("%s is a valid printer name\n", service));
389 DEBUG(3,("adding %s as a printer service\n", service));
390 lp_add_printer(service, iPrinterService);
391 iService = lp_servicenumber(service);
392 if (iService < 0) {
393 DEBUG(0,("failed to add %s as a printer service!\n", service));
395 } else {
396 DEBUG(3,("%s is not a valid printer name\n", service));
401 /* Check for default vfs service? Unsure whether to implement this */
402 if (iService < 0) {
405 if (iService < 0) {
406 iService = load_registry_service(service);
409 /* Is it a usershare service ? */
410 if (iService < 0 && *lp_usershare_path()) {
411 /* Ensure the name is canonicalized. */
412 strlower_m(service);
413 iService = load_usershare_service(service);
416 /* just possibly it's a default service? */
417 if (iService < 0) {
418 char *pdefservice = lp_defaultservice();
419 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
421 * We need to do a local copy here as lp_defaultservice()
422 * returns one of the rotating lp_string buffers that
423 * could get overwritten by the recursive find_service() call
424 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
426 pstring defservice;
427 pstrcpy(defservice, pdefservice);
429 /* Disallow anything except explicit share names. */
430 if (strequal(defservice,HOMES_NAME) ||
431 strequal(defservice, PRINTERS_NAME) ||
432 strequal(defservice, "IPC$")) {
433 goto fail;
436 iService = find_service(defservice);
437 if (iService >= 0) {
438 all_string_sub(service, "_","/",0);
439 iService = lp_add_service(service, iService);
444 if (iService >= 0) {
445 if (!VALID_SNUM(iService)) {
446 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
447 iService = -1;
451 fail:
453 if (iService < 0)
454 DEBUG(3,("find_service() failed to find service %s\n", service));
456 return (iService);
460 /****************************************************************************
461 do some basic sainity checks on the share.
462 This function modifies dev, ecode.
463 ****************************************************************************/
465 static NTSTATUS share_sanity_checks(int snum, fstring dev)
468 if (!lp_snum_ok(snum) ||
469 !check_access(smbd_server_fd(),
470 lp_hostsallow(snum), lp_hostsdeny(snum))) {
471 return NT_STATUS_ACCESS_DENIED;
474 if (dev[0] == '?' || !dev[0]) {
475 if (lp_print_ok(snum)) {
476 fstrcpy(dev,"LPT1:");
477 } else if (strequal(lp_fstype(snum), "IPC")) {
478 fstrcpy(dev, "IPC");
479 } else {
480 fstrcpy(dev,"A:");
484 strupper_m(dev);
486 if (lp_print_ok(snum)) {
487 if (!strequal(dev, "LPT1:")) {
488 return NT_STATUS_BAD_DEVICE_TYPE;
490 } else if (strequal(lp_fstype(snum), "IPC")) {
491 if (!strequal(dev, "IPC")) {
492 return NT_STATUS_BAD_DEVICE_TYPE;
494 } else if (!strequal(dev, "A:")) {
495 return NT_STATUS_BAD_DEVICE_TYPE;
498 /* Behave as a printer if we are supposed to */
499 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
500 fstrcpy(dev, "LPT1:");
503 return NT_STATUS_OK;
506 static NTSTATUS find_forced_user(connection_struct *conn, BOOL vuser_is_guest, fstring username)
508 int snum = conn->params->service;
509 char *fuser, *found_username;
510 NTSTATUS result;
512 if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
513 lp_servicename(snum)))) {
514 return NT_STATUS_NO_MEMORY;
517 result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
518 &conn->uid, &conn->gid, &found_username,
519 &conn->nt_user_token);
520 if (!NT_STATUS_IS_OK(result)) {
521 return result;
524 fstrcpy(username, found_username);
526 TALLOC_FREE(fuser);
527 TALLOC_FREE(found_username);
528 return NT_STATUS_OK;
532 * Go through lookup_name etc to find the force'd group.
534 * Create a new token from src_token, replacing the primary group sid with the
535 * one found.
538 static NTSTATUS find_forced_group(BOOL force_user,
539 int snum, const char *username,
540 DOM_SID *pgroup_sid,
541 gid_t *pgid)
543 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
544 TALLOC_CTX *mem_ctx;
545 DOM_SID group_sid;
546 enum lsa_SidType type;
547 char *groupname;
548 BOOL user_must_be_member = False;
549 gid_t gid;
551 ZERO_STRUCTP(pgroup_sid);
552 *pgid = (gid_t)-1;
554 mem_ctx = talloc_new(NULL);
555 if (mem_ctx == NULL) {
556 DEBUG(0, ("talloc_new failed\n"));
557 return NT_STATUS_NO_MEMORY;
560 groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
561 if (groupname == NULL) {
562 DEBUG(1, ("talloc_strdup failed\n"));
563 result = NT_STATUS_NO_MEMORY;
564 goto done;
567 if (groupname[0] == '+') {
568 user_must_be_member = True;
569 groupname += 1;
572 groupname = talloc_string_sub(mem_ctx, groupname,
573 "%S", lp_servicename(snum));
575 if (!lookup_name_smbconf(mem_ctx, groupname,
576 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
577 NULL, NULL, &group_sid, &type)) {
578 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
579 groupname));
580 goto done;
583 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
584 (type != SID_NAME_WKN_GRP)) {
585 DEBUG(10, ("%s is a %s, not a group\n", groupname,
586 sid_type_lookup(type)));
587 goto done;
590 if (!sid_to_gid(&group_sid, &gid)) {
591 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
592 sid_string_static(&group_sid), groupname));
593 goto done;
597 * If the user has been forced and the forced group starts with a '+',
598 * then we only set the group to be the forced group if the forced
599 * user is a member of that group. Otherwise, the meaning of the '+'
600 * would be ignored.
603 if (force_user && user_must_be_member) {
604 if (user_in_group_sid(username, &group_sid)) {
605 sid_copy(pgroup_sid, &group_sid);
606 *pgid = gid;
607 DEBUG(3,("Forced group %s for member %s\n",
608 groupname, username));
609 } else {
610 DEBUG(0,("find_forced_group: forced user %s is not a member "
611 "of forced group %s. Disallowing access.\n",
612 username, groupname ));
613 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
614 goto done;
616 } else {
617 sid_copy(pgroup_sid, &group_sid);
618 *pgid = gid;
619 DEBUG(3,("Forced group %s\n", groupname));
622 result = NT_STATUS_OK;
623 done:
624 TALLOC_FREE(mem_ctx);
625 return result;
628 /****************************************************************************
629 Make a connection, given the snum to connect to, and the vuser of the
630 connecting user if appropriate.
631 ****************************************************************************/
633 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
634 DATA_BLOB password,
635 const char *pdev,
636 NTSTATUS *status)
638 struct passwd *pass = NULL;
639 BOOL guest = False;
640 connection_struct *conn;
641 SMB_STRUCT_STAT st;
642 fstring user;
643 fstring dev;
644 int ret;
646 *user = 0;
647 fstrcpy(dev, pdev);
648 SET_STAT_INVALID(st);
650 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
651 return NULL;
654 conn = conn_new();
655 if (!conn) {
656 DEBUG(0,("Couldn't find free connection.\n"));
657 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
658 return NULL;
661 conn->params->service = snum;
662 conn->nt_user_token = NULL;
664 if (lp_guest_only(snum)) {
665 const char *guestname = lp_guestaccount();
666 NTSTATUS status2;
667 char *found_username = NULL;
669 guest = True;
670 pass = getpwnam_alloc(NULL, guestname);
671 if (!pass) {
672 DEBUG(0,("make_connection_snum: Invalid guest "
673 "account %s??\n",guestname));
674 conn_free(conn);
675 *status = NT_STATUS_NO_SUCH_USER;
676 return NULL;
678 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
679 &conn->uid, &conn->gid,
680 &found_username,
681 &conn->nt_user_token);
682 if (!NT_STATUS_IS_OK(status2)) {
683 TALLOC_FREE(pass);
684 conn_free(conn);
685 *status = status2;
686 return NULL;
688 fstrcpy(user, found_username);
689 string_set(&conn->user,user);
690 conn->force_user = True;
691 TALLOC_FREE(found_username);
692 TALLOC_FREE(pass);
693 DEBUG(3,("Guest only user %s\n",user));
694 } else if (vuser) {
695 if (vuser->guest) {
696 if (!lp_guest_ok(snum)) {
697 DEBUG(2, ("guest user (from session setup) "
698 "not permitted to access this share "
699 "(%s)\n", lp_servicename(snum)));
700 conn_free(conn);
701 *status = NT_STATUS_ACCESS_DENIED;
702 return NULL;
704 } else {
705 if (!user_ok_token(vuser->user.unix_name,
706 vuser->nt_user_token, snum)) {
707 DEBUG(2, ("user '%s' (from session setup) not "
708 "permitted to access this share "
709 "(%s)\n", vuser->user.unix_name,
710 lp_servicename(snum)));
711 conn_free(conn);
712 *status = NT_STATUS_ACCESS_DENIED;
713 return NULL;
716 conn->vuid = vuser->vuid;
717 conn->uid = vuser->uid;
718 conn->gid = vuser->gid;
719 string_set(&conn->user,vuser->user.unix_name);
720 fstrcpy(user,vuser->user.unix_name);
721 guest = vuser->guest;
722 } else if (lp_security() == SEC_SHARE) {
723 NTSTATUS status2;
724 char *found_username = NULL;
726 /* add it as a possible user name if we
727 are in share mode security */
728 add_session_user(lp_servicename(snum));
729 /* shall we let them in? */
730 if (!authorise_login(snum,user,password,&guest)) {
731 DEBUG( 2, ( "Invalid username/password for [%s]\n",
732 lp_servicename(snum)) );
733 conn_free(conn);
734 *status = NT_STATUS_WRONG_PASSWORD;
735 return NULL;
737 pass = Get_Pwnam(user);
738 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
739 &conn->uid, &conn->gid,
740 &found_username,
741 &conn->nt_user_token);
742 if (!NT_STATUS_IS_OK(status2)) {
743 conn_free(conn);
744 *status = status2;
745 return NULL;
747 fstrcpy(user, found_username);
748 string_set(&conn->user,user);
749 TALLOC_FREE(found_username);
750 conn->force_user = True;
751 } else {
752 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
753 conn_free(conn);
754 *status = NT_STATUS_ACCESS_DENIED;
755 return NULL;
758 add_session_user(user);
760 safe_strcpy(conn->client_address, client_addr(),
761 sizeof(conn->client_address)-1);
762 conn->num_files_open = 0;
763 conn->lastused = conn->lastused_count = time(NULL);
764 conn->used = True;
765 conn->printer = (strncmp(dev,"LPT",3) == 0);
766 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
767 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
768 conn->dirptr = NULL;
770 /* Case options for the share. */
771 if (lp_casesensitive(snum) == Auto) {
772 /* We will be setting this per packet. Set to be case
773 * insensitive for now. */
774 conn->case_sensitive = False;
775 } else {
776 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
779 conn->case_preserve = lp_preservecase(snum);
780 conn->short_case_preserve = lp_shortpreservecase(snum);
782 conn->veto_list = NULL;
783 conn->hide_list = NULL;
784 conn->veto_oplock_list = NULL;
785 conn->aio_write_behind_list = NULL;
786 string_set(&conn->dirpath,"");
787 string_set(&conn->user,user);
789 conn->read_only = lp_readonly(SNUM(conn));
790 conn->admin_user = False;
793 * If force user is true, then store the given userid and the gid of
794 * the user we're forcing.
795 * For auxiliary groups see below.
798 if (*lp_force_user(snum)) {
799 NTSTATUS status2;
801 status2 = find_forced_user(conn,
802 (vuser != NULL) && vuser->guest,
803 user);
804 if (!NT_STATUS_IS_OK(status2)) {
805 conn_free(conn);
806 *status = status2;
807 return NULL;
809 string_set(&conn->user,user);
810 conn->force_user = True;
811 DEBUG(3,("Forced user %s\n",user));
815 * If force group is true, then override
816 * any groupid stored for the connecting user.
819 if (*lp_force_group(snum)) {
820 NTSTATUS status2;
821 DOM_SID group_sid;
823 status2 = find_forced_group(conn->force_user,
824 snum, user,
825 &group_sid, &conn->gid);
826 if (!NT_STATUS_IS_OK(status2)) {
827 conn_free(conn);
828 *status = status2;
829 return NULL;
832 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
834 /* Not force user and not security=share, but force
835 * group. vuser has a token to copy */
837 conn->nt_user_token = dup_nt_token(
838 NULL, vuser->nt_user_token);
839 if (conn->nt_user_token == NULL) {
840 DEBUG(0, ("dup_nt_token failed\n"));
841 conn_free(conn);
842 *status = NT_STATUS_NO_MEMORY;
843 return NULL;
847 /* If conn->nt_user_token is still NULL, we have
848 * security=share. This means ignore the SID, as we had no
849 * vuser to copy from */
851 if (conn->nt_user_token != NULL) {
852 /* Overwrite the primary group sid */
853 sid_copy(&conn->nt_user_token->user_sids[1],
854 &group_sid);
857 conn->force_group = True;
860 if (conn->nt_user_token != NULL) {
861 size_t i;
863 /* We have a share-specific token from force [user|group].
864 * This means we have to create the list of unix groups from
865 * the list of sids. */
867 conn->ngroups = 0;
868 conn->groups = NULL;
870 for (i=0; i<conn->nt_user_token->num_sids; i++) {
871 gid_t gid;
872 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
874 if (!sid_to_gid(sid, &gid)) {
875 DEBUG(10, ("Could not convert SID %s to gid, "
876 "ignoring it\n",
877 sid_string_static(sid)));
878 continue;
880 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
881 &conn->ngroups)) {
882 DEBUG(0, ("add_gid_to_array_unique failed\n"));
883 conn_free(conn);
884 *status = NT_STATUS_NO_MEMORY;
885 return NULL;
891 pstring s;
892 pstrcpy(s,lp_pathname(snum));
893 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
894 conn->connectpath, conn->gid,
895 get_current_username(),
896 current_user_info.domain,
897 s, sizeof(s));
898 set_conn_connectpath(conn,s);
899 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
900 lp_servicename(snum)));
904 * New code to check if there's a share security descripter
905 * added from NT server manager. This is done after the
906 * smb.conf checks are done as we need a uid and token. JRA.
911 BOOL can_write = False;
912 NT_USER_TOKEN *token = conn->nt_user_token ?
913 conn->nt_user_token :
914 (vuser ? vuser->nt_user_token : NULL);
917 * I don't believe this can happen. But the
918 * logic above is convoluted enough to confuse
919 * automated checkers, so be sure. JRA.
922 if (token == NULL) {
923 DEBUG(0,("make_connection: connection to %s "
924 "denied due to missing "
925 "NT token.\n",
926 lp_servicename(snum)));
927 conn_free(conn);
928 *status = NT_STATUS_ACCESS_DENIED;
929 return NULL;
932 can_write = share_access_check(token,
933 lp_servicename(snum),
934 FILE_WRITE_DATA);
936 if (!can_write) {
937 if (!share_access_check(token,
938 lp_servicename(snum),
939 FILE_READ_DATA)) {
940 /* No access, read or write. */
941 DEBUG(0,("make_connection: connection to %s "
942 "denied due to security "
943 "descriptor.\n",
944 lp_servicename(snum)));
945 conn_free(conn);
946 *status = NT_STATUS_ACCESS_DENIED;
947 return NULL;
948 } else {
949 conn->read_only = True;
953 /* Initialise VFS function pointers */
955 if (!smbd_vfs_init(conn)) {
956 DEBUG(0, ("vfs_init failed for service %s\n",
957 lp_servicename(snum)));
958 conn_free(conn);
959 *status = NT_STATUS_BAD_NETWORK_NAME;
960 return NULL;
964 * If widelinks are disallowed we need to canonicalise the connect
965 * path here to ensure we don't have any symlinks in the
966 * connectpath. We will be checking all paths on this connection are
967 * below this directory. We must do this after the VFS init as we
968 * depend on the realpath() pointer in the vfs table. JRA.
970 if (!lp_widelinks(snum)) {
971 pstring s;
972 pstrcpy(s,conn->connectpath);
973 canonicalize_path(conn, s);
974 set_conn_connectpath(conn,s);
977 if ((!conn->printer) && (!conn->ipc)) {
978 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
979 smbd_messaging_context(),
980 smbd_event_context(),
981 conn);
984 /* ROOT Activities: */
986 * Enforce the max connections parameter.
989 if ((lp_max_connections(snum) > 0)
990 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
991 lp_max_connections(snum))) {
993 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
994 lp_max_connections(snum), lp_servicename(snum)));
995 conn_free(conn);
996 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
997 return NULL;
1001 * Get us an entry in the connections db
1003 if (!claim_connection(conn, lp_servicename(snum), 0)) {
1004 DEBUG(1, ("Could not store connections entry\n"));
1005 conn_free(conn);
1006 *status = NT_STATUS_INTERNAL_DB_ERROR;
1007 return NULL;
1010 /* Preexecs are done here as they might make the dir we are to ChDir
1011 * to below */
1012 /* execute any "root preexec = " line */
1013 if (*lp_rootpreexec(snum)) {
1014 pstring cmd;
1015 pstrcpy(cmd,lp_rootpreexec(snum));
1016 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1017 conn->connectpath, conn->gid,
1018 get_current_username(),
1019 current_user_info.domain,
1020 cmd, sizeof(cmd));
1021 DEBUG(5,("cmd=%s\n",cmd));
1022 ret = smbrun(cmd,NULL);
1023 if (ret != 0 && lp_rootpreexec_close(snum)) {
1024 DEBUG(1,("root preexec gave %d - failing "
1025 "connection\n", ret));
1026 yield_connection(conn, lp_servicename(snum));
1027 conn_free(conn);
1028 *status = NT_STATUS_ACCESS_DENIED;
1029 return NULL;
1033 /* USER Activites: */
1034 if (!change_to_user(conn, conn->vuid)) {
1035 /* No point continuing if they fail the basic checks */
1036 DEBUG(0,("Can't become connected user!\n"));
1037 yield_connection(conn, lp_servicename(snum));
1038 conn_free(conn);
1039 *status = NT_STATUS_LOGON_FAILURE;
1040 return NULL;
1043 /* Remember that a different vuid can connect later without these
1044 * checks... */
1046 /* Preexecs are done here as they might make the dir we are to ChDir
1047 * to below */
1049 /* execute any "preexec = " line */
1050 if (*lp_preexec(snum)) {
1051 pstring cmd;
1052 pstrcpy(cmd,lp_preexec(snum));
1053 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1054 conn->connectpath, conn->gid,
1055 get_current_username(),
1056 current_user_info.domain,
1057 cmd, sizeof(cmd));
1058 ret = smbrun(cmd,NULL);
1059 if (ret != 0 && lp_preexec_close(snum)) {
1060 DEBUG(1,("preexec gave %d - failing connection\n",
1061 ret));
1062 change_to_root_user();
1063 yield_connection(conn, lp_servicename(snum));
1064 conn_free(conn);
1065 *status = NT_STATUS_ACCESS_DENIED;
1066 return NULL;
1070 #ifdef WITH_FAKE_KASERVER
1071 if (lp_afs_share(snum)) {
1072 afs_login(conn);
1074 #endif
1076 /* Add veto/hide lists */
1077 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1078 set_namearray( &conn->veto_list, lp_veto_files(snum));
1079 set_namearray( &conn->hide_list, lp_hide_files(snum));
1080 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1083 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1084 to allow any filesystems needing user credentials to initialize
1085 themselves. */
1087 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1088 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1089 change_to_root_user();
1090 yield_connection(conn, lp_servicename(snum));
1091 conn_free(conn);
1092 *status = NT_STATUS_UNSUCCESSFUL;
1093 return NULL;
1096 /* win2000 does not check the permissions on the directory
1097 during the tree connect, instead relying on permission
1098 check during individual operations. To match this behaviour
1099 I have disabled this chdir check (tridge) */
1100 /* the alternative is just to check the directory exists */
1101 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1102 !S_ISDIR(st.st_mode)) {
1103 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1104 DEBUG(0,("'%s' is not a directory, when connecting to "
1105 "[%s]\n", conn->connectpath,
1106 lp_servicename(snum)));
1107 } else {
1108 DEBUG(0,("'%s' does not exist or permission denied "
1109 "when connecting to [%s] Error was %s\n",
1110 conn->connectpath, lp_servicename(snum),
1111 strerror(errno) ));
1113 change_to_root_user();
1114 /* Call VFS disconnect hook */
1115 SMB_VFS_DISCONNECT(conn);
1116 yield_connection(conn, lp_servicename(snum));
1117 conn_free(conn);
1118 *status = NT_STATUS_BAD_NETWORK_NAME;
1119 return NULL;
1122 string_set(&conn->origpath,conn->connectpath);
1124 #if SOFTLINK_OPTIMISATION
1125 /* resolve any soft links early if possible */
1126 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1127 TALLOC_CTX *ctx = talloc_stackframe();
1128 char *s = vfs_GetWd(ctx,s);
1129 if (!s) {
1130 *status = map_nt_error_from_unix(errno);
1131 return NULL;
1133 set_conn_connectpath(conn,s);
1134 vfs_ChDir(conn,conn->connectpath);
1135 TALLOC_FREE(ctx);
1137 #endif
1140 * Print out the 'connected as' stuff here as we need
1141 * to know the effective uid and gid we will be using
1142 * (at least initially).
1145 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1146 dbgtext( "%s (%s) ", get_remote_machine_name(),
1147 conn->client_address );
1148 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1149 dbgtext( "connect to service %s ", lp_servicename(snum) );
1150 dbgtext( "initially as user %s ", user );
1151 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1152 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1155 /* we've finished with the user stuff - go back to root */
1156 change_to_root_user();
1157 return(conn);
1160 /***************************************************************************************
1161 Simple wrapper function for make_connection() to include a call to
1162 vfs_chdir()
1163 **************************************************************************************/
1165 connection_struct *make_connection_with_chdir(const char *service_in,
1166 DATA_BLOB password,
1167 const char *dev, uint16 vuid,
1168 NTSTATUS *status)
1170 connection_struct *conn = NULL;
1172 conn = make_connection(service_in, password, dev, vuid, status);
1175 * make_connection() does not change the directory for us any more
1176 * so we have to do it as a separate step --jerry
1179 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1180 DEBUG(0,("move_driver_to_download_area: Can't change "
1181 "directory to %s for [print$] (%s)\n",
1182 conn->connectpath,strerror(errno)));
1183 yield_connection(conn, lp_servicename(SNUM(conn)));
1184 conn_free(conn);
1185 *status = NT_STATUS_UNSUCCESSFUL;
1186 return NULL;
1189 return conn;
1192 /****************************************************************************
1193 Make a connection to a service.
1195 * @param service
1196 ****************************************************************************/
1198 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1199 const char *pdev, uint16 vuid,
1200 NTSTATUS *status)
1202 uid_t euid;
1203 user_struct *vuser = NULL;
1204 fstring service;
1205 fstring dev;
1206 int snum = -1;
1208 fstrcpy(dev, pdev);
1210 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1211 * root. */
1212 if (!non_root_mode() && (euid = geteuid()) != 0) {
1213 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1214 "(%u)\n", (unsigned int)euid ));
1215 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1218 if (conn_num_open() > 2047) {
1219 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1220 return NULL;
1223 if(lp_security() != SEC_SHARE) {
1224 vuser = get_valid_user_struct(vuid);
1225 if (!vuser) {
1226 DEBUG(1,("make_connection: refusing to connect with "
1227 "no session setup\n"));
1228 *status = NT_STATUS_ACCESS_DENIED;
1229 return NULL;
1233 /* Logic to try and connect to the correct [homes] share, preferably
1234 without too many getpwnam() lookups. This is particulary nasty for
1235 winbind usernames, where the share name isn't the same as unix
1236 username.
1238 The snum of the homes share is stored on the vuser at session setup
1239 time.
1242 if (strequal(service_in,HOMES_NAME)) {
1243 if(lp_security() != SEC_SHARE) {
1244 DATA_BLOB no_pw = data_blob_null;
1245 if (vuser->homes_snum == -1) {
1246 DEBUG(2, ("[homes] share not available for "
1247 "this user because it was not found "
1248 "or created at session setup "
1249 "time\n"));
1250 *status = NT_STATUS_BAD_NETWORK_NAME;
1251 return NULL;
1253 DEBUG(5, ("making a connection to [homes] service "
1254 "created at session setup time\n"));
1255 return make_connection_snum(vuser->homes_snum,
1256 vuser, no_pw,
1257 dev, status);
1258 } else {
1259 /* Security = share. Try with
1260 * current_user_info.smb_name as the username. */
1261 if (*current_user_info.smb_name) {
1262 fstring unix_username;
1263 fstrcpy(unix_username,
1264 current_user_info.smb_name);
1265 map_username(unix_username);
1266 snum = find_service(unix_username);
1268 if (snum != -1) {
1269 DEBUG(5, ("making a connection to 'homes' "
1270 "service %s based on "
1271 "security=share\n", service_in));
1272 return make_connection_snum(snum, NULL,
1273 password,
1274 dev, status);
1277 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1278 && strequal(service_in,
1279 lp_servicename(vuser->homes_snum))) {
1280 DATA_BLOB no_pw = data_blob_null;
1281 DEBUG(5, ("making a connection to 'homes' service [%s] "
1282 "created at session setup time\n", service_in));
1283 return make_connection_snum(vuser->homes_snum,
1284 vuser, no_pw,
1285 dev, status);
1288 fstrcpy(service, service_in);
1290 strlower_m(service);
1292 snum = find_service(service);
1294 if (snum < 0) {
1295 if (strequal(service,"IPC$") ||
1296 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1297 DEBUG(3,("refusing IPC connection to %s\n", service));
1298 *status = NT_STATUS_ACCESS_DENIED;
1299 return NULL;
1302 DEBUG(0,("%s (%s) couldn't find service %s\n",
1303 get_remote_machine_name(), client_addr(), service));
1304 *status = NT_STATUS_BAD_NETWORK_NAME;
1305 return NULL;
1308 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1309 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1310 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1311 "(pointing to %s)\n",
1312 service, lp_msdfs_proxy(snum)));
1313 *status = NT_STATUS_BAD_NETWORK_NAME;
1314 return NULL;
1317 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1319 return make_connection_snum(snum, vuser,
1320 password,
1321 dev, status);
1324 /****************************************************************************
1325 Close a cnum.
1326 ****************************************************************************/
1328 void close_cnum(connection_struct *conn, uint16 vuid)
1330 if (IS_IPC(conn)) {
1331 pipe_close_conn(conn);
1332 } else {
1333 file_close_conn(conn);
1334 dptr_closecnum(conn);
1337 change_to_root_user();
1339 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1340 get_remote_machine_name(),
1341 conn->client_address,
1342 lp_servicename(SNUM(conn))));
1344 /* Call VFS disconnect hook */
1345 SMB_VFS_DISCONNECT(conn);
1347 yield_connection(conn, lp_servicename(SNUM(conn)));
1349 /* make sure we leave the directory available for unmount */
1350 vfs_ChDir(conn, "/");
1352 /* execute any "postexec = " line */
1353 if (*lp_postexec(SNUM(conn)) &&
1354 change_to_user(conn, vuid)) {
1355 pstring cmd;
1356 pstrcpy(cmd,lp_postexec(SNUM(conn)));
1357 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1358 conn->connectpath, conn->gid,
1359 get_current_username(),
1360 current_user_info.domain,
1361 cmd, sizeof(cmd));
1362 smbrun(cmd,NULL);
1363 change_to_root_user();
1366 change_to_root_user();
1367 /* execute any "root postexec = " line */
1368 if (*lp_rootpostexec(SNUM(conn))) {
1369 pstring cmd;
1370 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
1371 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1372 conn->connectpath, conn->gid,
1373 get_current_username(),
1374 current_user_info.domain,
1375 cmd, sizeof(cmd));
1376 smbrun(cmd,NULL);
1379 conn_free(conn);