s3-groupdb: fix enum_aliasmem in ldb branch.
[Samba.git] / source / smbd / service.c
blob1c8ffbd627dd6648568d44053eb6e1157943204a
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_connect_path(connection_struct *conn)
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;
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;
41 return set_conn_connectpath(conn,resolved_name);
42 #endif /* REALPATH_TAKES_NULL */
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 ****************************************************************************/
51 bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
53 char *destname;
54 char *d;
55 const char *s = connectpath;
56 bool start_of_name_component = true;
58 destname = SMB_STRDUP(connectpath);
59 if (!destname) {
60 return false;
62 d = destname;
64 *d++ = '/'; /* Always start with root. */
66 while (*s) {
67 if (*s == '/') {
68 /* Eat multiple '/' */
69 while (*s == '/') {
70 s++;
72 if ((d > destname + 1) && (*s != '\0')) {
73 *d++ = '/';
75 start_of_name_component = True;
76 continue;
79 if (start_of_name_component) {
80 if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
81 /* Uh oh - "/../" or "/..\0" ! */
83 /* Go past the ../ or .. */
84 if (s[2] == '/') {
85 s += 3;
86 } else {
87 s += 2; /* Go past the .. */
90 /* If we just added a '/' - delete it */
91 if ((d > destname) && (*(d-1) == '/')) {
92 *(d-1) = '\0';
93 d--;
96 /* Are we at the start ? Can't go back further if so. */
97 if (d <= destname) {
98 *d++ = '/'; /* Can't delete root */
99 continue;
101 /* Go back one level... */
102 /* Decrement d first as d points to the *next* char to write into. */
103 for (d--; d > destname; d--) {
104 if (*d == '/') {
105 break;
108 /* We're still at the start of a name component, just the previous one. */
109 continue;
110 } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
111 /* Component of pathname can't be "." only - skip the '.' . */
112 if (s[1] == '/') {
113 s += 2;
114 } else {
115 s++;
117 continue;
121 if (!(*s & 0x80)) {
122 *d++ = *s++;
123 } else {
124 size_t siz;
125 /* Get the size of the next MB character. */
126 next_codepoint(s,&siz);
127 switch(siz) {
128 case 5:
129 *d++ = *s++;
130 /*fall through*/
131 case 4:
132 *d++ = *s++;
133 /*fall through*/
134 case 3:
135 *d++ = *s++;
136 /*fall through*/
137 case 2:
138 *d++ = *s++;
139 /*fall through*/
140 case 1:
141 *d++ = *s++;
142 break;
143 default:
144 break;
147 start_of_name_component = false;
149 *d = '\0';
151 /* And must not end in '/' */
152 if (d > destname + 1 && (*(d-1) == '/')) {
153 *(d-1) = '\0';
156 DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
157 lp_servicename(SNUM(conn)), destname ));
159 string_set(&conn->connectpath, destname);
160 SAFE_FREE(destname);
161 return true;
164 /****************************************************************************
165 Load parameters specific to a connection/service.
166 ****************************************************************************/
168 bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
170 static connection_struct *last_conn;
171 static uint16 last_flags;
172 int snum;
174 if (!conn) {
175 last_conn = NULL;
176 return(False);
179 conn->lastused_count++;
181 snum = SNUM(conn);
183 if (do_chdir &&
184 vfs_ChDir(conn,conn->connectpath) != 0 &&
185 vfs_ChDir(conn,conn->origpath) != 0) {
186 DEBUG(0,("chdir (%s) failed\n",
187 conn->connectpath));
188 return(False);
191 if ((conn == last_conn) && (last_flags == flags)) {
192 return(True);
195 last_conn = conn;
196 last_flags = flags;
198 /* Obey the client case sensitivity requests - only for clients that support it. */
199 switch (lp_casesensitive(snum)) {
200 case Auto:
202 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
203 enum remote_arch_types ra_type = get_remote_arch();
204 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
205 /* Client can't support per-packet case sensitive pathnames. */
206 conn->case_sensitive = False;
207 } else {
208 conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
211 break;
212 case True:
213 conn->case_sensitive = True;
214 break;
215 default:
216 conn->case_sensitive = False;
217 break;
219 return(True);
222 static int load_registry_service(const char *servicename)
224 struct registry_key *key;
225 char *path;
226 WERROR err;
228 uint32 i;
229 char *value_name;
230 struct registry_value *value;
232 int res = -1;
234 if (!lp_registry_shares()) {
235 return -1;
238 if ((servicename == NULL) || (*servicename == '\0')) {
239 return -1;
242 if (strequal(servicename, GLOBAL_NAME)) {
243 return -2;
246 if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
247 return -1;
250 err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(),
251 &key);
252 SAFE_FREE(path);
254 if (!W_ERROR_IS_OK(err)) {
255 return -1;
258 res = lp_add_service(servicename, -1);
259 if (res == -1) {
260 goto error;
263 for (i=0;
264 W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value));
265 i++) {
266 switch (value->type) {
267 case REG_DWORD: {
268 char *tmp;
269 if (asprintf(&tmp, "%d", value->v.dword) == -1) {
270 continue;
272 lp_do_parameter(res, value_name, tmp);
273 SAFE_FREE(tmp);
274 break;
276 case REG_SZ: {
277 lp_do_parameter(res, value_name, value->v.sz.str);
278 break;
280 default:
281 /* Ignore all the rest */
282 break;
285 TALLOC_FREE(value_name);
286 TALLOC_FREE(value);
289 error:
291 TALLOC_FREE(key);
292 return res;
295 void load_registry_shares(void)
297 struct registry_key *key;
298 char *name;
299 WERROR err;
300 int i;
302 DEBUG(8, ("load_registry_shares()\n"));
303 if (!lp_registry_shares()) {
304 return;
307 err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
308 get_root_nt_token(), &key);
309 if (!(W_ERROR_IS_OK(err))) {
310 return;
313 for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
314 load_registry_service(name);
315 TALLOC_FREE(name);
318 TALLOC_FREE(key);
319 return;
322 /****************************************************************************
323 Add a home service. Returns the new service number or -1 if fail.
324 ****************************************************************************/
326 int add_home_service(const char *service, const char *username, const char *homedir)
328 int iHomeService;
330 if (!service || !homedir)
331 return -1;
333 if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
334 if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
335 return -1;
340 * If this is a winbindd provided username, remove
341 * the domain component before adding the service.
342 * Log a warning if the "path=" parameter does not
343 * include any macros.
347 const char *p = strchr(service,*lp_winbind_separator());
349 /* We only want the 'user' part of the string */
350 if (p) {
351 service = p + 1;
355 if (!lp_add_home(service, iHomeService, username, homedir)) {
356 return -1;
359 return lp_servicenumber(service);
364 * Find a service entry.
366 * @param service is modified (to canonical form??)
369 int find_service(fstring service)
371 int iService;
373 all_string_sub(service,"\\","/",0);
375 iService = lp_servicenumber(service);
377 /* now handle the special case of a home directory */
378 if (iService < 0) {
379 char *phome_dir = get_user_home_dir(talloc_tos(), service);
381 if(!phome_dir) {
383 * Try mapping the servicename, it may
384 * be a Windows to unix mapped user name.
386 if(map_username(service))
387 phome_dir = get_user_home_dir(
388 talloc_tos(), service);
391 DEBUG(3,("checking for home directory %s gave %s\n",service,
392 phome_dir?phome_dir:"(NULL)"));
394 iService = add_home_service(service,service /* 'username' */, phome_dir);
397 /* If we still don't have a service, attempt to add it as a printer. */
398 if (iService < 0) {
399 int iPrinterService;
401 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
402 iPrinterService = load_registry_service(PRINTERS_NAME);
404 if (iPrinterService) {
405 DEBUG(3,("checking whether %s is a valid printer name...\n", service));
406 if (pcap_printername_ok(service)) {
407 DEBUG(3,("%s is a valid printer name\n", service));
408 DEBUG(3,("adding %s as a printer service\n", service));
409 lp_add_printer(service, iPrinterService);
410 iService = lp_servicenumber(service);
411 if (iService < 0) {
412 DEBUG(0,("failed to add %s as a printer service!\n", service));
414 } else {
415 DEBUG(3,("%s is not a valid printer name\n", service));
420 /* Check for default vfs service? Unsure whether to implement this */
421 if (iService < 0) {
424 if (iService < 0) {
425 iService = load_registry_service(service);
428 /* Is it a usershare service ? */
429 if (iService < 0 && *lp_usershare_path()) {
430 /* Ensure the name is canonicalized. */
431 strlower_m(service);
432 iService = load_usershare_service(service);
435 /* just possibly it's a default service? */
436 if (iService < 0) {
437 char *pdefservice = lp_defaultservice();
438 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
440 * We need to do a local copy here as lp_defaultservice()
441 * returns one of the rotating lp_string buffers that
442 * could get overwritten by the recursive find_service() call
443 * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
445 char *defservice = SMB_STRDUP(pdefservice);
447 if (!defservice) {
448 goto fail;
451 /* Disallow anything except explicit share names. */
452 if (strequal(defservice,HOMES_NAME) ||
453 strequal(defservice, PRINTERS_NAME) ||
454 strequal(defservice, "IPC$")) {
455 SAFE_FREE(defservice);
456 goto fail;
459 iService = find_service(defservice);
460 if (iService >= 0) {
461 all_string_sub(service, "_","/",0);
462 iService = lp_add_service(service, iService);
464 SAFE_FREE(defservice);
468 if (iService >= 0) {
469 if (!VALID_SNUM(iService)) {
470 DEBUG(0,("Invalid snum %d for %s\n",iService, service));
471 iService = -1;
475 fail:
477 if (iService < 0)
478 DEBUG(3,("find_service() failed to find service %s\n", service));
480 return (iService);
484 /****************************************************************************
485 do some basic sainity checks on the share.
486 This function modifies dev, ecode.
487 ****************************************************************************/
489 static NTSTATUS share_sanity_checks(int snum, fstring dev)
492 if (!lp_snum_ok(snum) ||
493 !check_access(smbd_server_fd(),
494 lp_hostsallow(snum), lp_hostsdeny(snum))) {
495 return NT_STATUS_ACCESS_DENIED;
498 if (dev[0] == '?' || !dev[0]) {
499 if (lp_print_ok(snum)) {
500 fstrcpy(dev,"LPT1:");
501 } else if (strequal(lp_fstype(snum), "IPC")) {
502 fstrcpy(dev, "IPC");
503 } else {
504 fstrcpy(dev,"A:");
508 strupper_m(dev);
510 if (lp_print_ok(snum)) {
511 if (!strequal(dev, "LPT1:")) {
512 return NT_STATUS_BAD_DEVICE_TYPE;
514 } else if (strequal(lp_fstype(snum), "IPC")) {
515 if (!strequal(dev, "IPC")) {
516 return NT_STATUS_BAD_DEVICE_TYPE;
518 } else if (!strequal(dev, "A:")) {
519 return NT_STATUS_BAD_DEVICE_TYPE;
522 /* Behave as a printer if we are supposed to */
523 if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
524 fstrcpy(dev, "LPT1:");
527 return NT_STATUS_OK;
530 static NTSTATUS find_forced_user(connection_struct *conn, bool vuser_is_guest, fstring username)
532 int snum = conn->params->service;
533 char *fuser, *found_username;
534 NTSTATUS result;
536 if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
537 lp_servicename(snum)))) {
538 return NT_STATUS_NO_MEMORY;
541 result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
542 &conn->uid, &conn->gid, &found_username,
543 &conn->nt_user_token);
544 if (!NT_STATUS_IS_OK(result)) {
545 return result;
548 fstrcpy(username, found_username);
550 TALLOC_FREE(fuser);
551 TALLOC_FREE(found_username);
552 return NT_STATUS_OK;
556 * Go through lookup_name etc to find the force'd group.
558 * Create a new token from src_token, replacing the primary group sid with the
559 * one found.
562 static NTSTATUS find_forced_group(bool force_user,
563 int snum, const char *username,
564 DOM_SID *pgroup_sid,
565 gid_t *pgid)
567 NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
568 TALLOC_CTX *mem_ctx;
569 DOM_SID group_sid;
570 enum lsa_SidType type;
571 char *groupname;
572 bool user_must_be_member = False;
573 gid_t gid;
575 ZERO_STRUCTP(pgroup_sid);
576 *pgid = (gid_t)-1;
578 mem_ctx = talloc_new(NULL);
579 if (mem_ctx == NULL) {
580 DEBUG(0, ("talloc_new failed\n"));
581 return NT_STATUS_NO_MEMORY;
584 groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
585 if (groupname == NULL) {
586 DEBUG(1, ("talloc_strdup failed\n"));
587 result = NT_STATUS_NO_MEMORY;
588 goto done;
591 if (groupname[0] == '+') {
592 user_must_be_member = True;
593 groupname += 1;
596 groupname = talloc_string_sub(mem_ctx, groupname,
597 "%S", lp_servicename(snum));
599 if (!lookup_name_smbconf(mem_ctx, groupname,
600 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
601 NULL, NULL, &group_sid, &type)) {
602 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
603 groupname));
604 goto done;
607 if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
608 (type != SID_NAME_WKN_GRP)) {
609 DEBUG(10, ("%s is a %s, not a group\n", groupname,
610 sid_type_lookup(type)));
611 goto done;
614 if (!sid_to_gid(&group_sid, &gid)) {
615 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
616 sid_string_dbg(&group_sid), groupname));
617 goto done;
621 * If the user has been forced and the forced group starts with a '+',
622 * then we only set the group to be the forced group if the forced
623 * user is a member of that group. Otherwise, the meaning of the '+'
624 * would be ignored.
627 if (force_user && user_must_be_member) {
628 if (user_in_group_sid(username, &group_sid)) {
629 sid_copy(pgroup_sid, &group_sid);
630 *pgid = gid;
631 DEBUG(3,("Forced group %s for member %s\n",
632 groupname, username));
633 } else {
634 DEBUG(0,("find_forced_group: forced user %s is not a member "
635 "of forced group %s. Disallowing access.\n",
636 username, groupname ));
637 result = NT_STATUS_MEMBER_NOT_IN_GROUP;
638 goto done;
640 } else {
641 sid_copy(pgroup_sid, &group_sid);
642 *pgid = gid;
643 DEBUG(3,("Forced group %s\n", groupname));
646 result = NT_STATUS_OK;
647 done:
648 TALLOC_FREE(mem_ctx);
649 return result;
652 /****************************************************************************
653 Make a connection, given the snum to connect to, and the vuser of the
654 connecting user if appropriate.
655 ****************************************************************************/
657 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
658 DATA_BLOB password,
659 const char *pdev,
660 NTSTATUS *status)
662 struct passwd *pass = NULL;
663 bool guest = False;
664 connection_struct *conn;
665 SMB_STRUCT_STAT st;
666 fstring user;
667 fstring dev;
668 int ret;
669 char addr[INET6_ADDRSTRLEN];
670 bool on_err_call_dis_hook = false;
672 *user = 0;
673 fstrcpy(dev, pdev);
674 SET_STAT_INVALID(st);
676 if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
677 return NULL;
680 conn = conn_new();
681 if (!conn) {
682 DEBUG(0,("Couldn't find free connection.\n"));
683 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
684 return NULL;
687 conn->params->service = snum;
688 conn->nt_user_token = NULL;
690 if (lp_guest_only(snum)) {
691 const char *guestname = lp_guestaccount();
692 NTSTATUS status2;
693 char *found_username = NULL;
695 guest = True;
696 pass = getpwnam_alloc(talloc_tos(), guestname);
697 if (!pass) {
698 DEBUG(0,("make_connection_snum: Invalid guest "
699 "account %s??\n",guestname));
700 conn_free(conn);
701 *status = NT_STATUS_NO_SUCH_USER;
702 return NULL;
704 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
705 &conn->uid, &conn->gid,
706 &found_username,
707 &conn->nt_user_token);
708 if (!NT_STATUS_IS_OK(status2)) {
709 TALLOC_FREE(pass);
710 conn_free(conn);
711 *status = status2;
712 return NULL;
714 fstrcpy(user, found_username);
715 string_set(&conn->user,user);
716 conn->force_user = True;
717 TALLOC_FREE(found_username);
718 TALLOC_FREE(pass);
719 DEBUG(3,("Guest only user %s\n",user));
720 } else if (vuser) {
721 if (vuser->guest) {
722 if (!lp_guest_ok(snum)) {
723 DEBUG(2, ("guest user (from session setup) "
724 "not permitted to access this share "
725 "(%s)\n", lp_servicename(snum)));
726 conn_free(conn);
727 *status = NT_STATUS_ACCESS_DENIED;
728 return NULL;
730 } else {
731 if (!user_ok_token(vuser->user.unix_name,
732 vuser->nt_user_token, snum)) {
733 DEBUG(2, ("user '%s' (from session setup) not "
734 "permitted to access this share "
735 "(%s)\n", vuser->user.unix_name,
736 lp_servicename(snum)));
737 conn_free(conn);
738 *status = NT_STATUS_ACCESS_DENIED;
739 return NULL;
742 conn->vuid = vuser->vuid;
743 conn->uid = vuser->uid;
744 conn->gid = vuser->gid;
745 string_set(&conn->user,vuser->user.unix_name);
746 fstrcpy(user,vuser->user.unix_name);
747 guest = vuser->guest;
748 } else if (lp_security() == SEC_SHARE) {
749 NTSTATUS status2;
750 char *found_username = NULL;
752 /* add it as a possible user name if we
753 are in share mode security */
754 add_session_user(lp_servicename(snum));
755 /* shall we let them in? */
756 if (!authorise_login(snum,user,password,&guest)) {
757 DEBUG( 2, ( "Invalid username/password for [%s]\n",
758 lp_servicename(snum)) );
759 conn_free(conn);
760 *status = NT_STATUS_WRONG_PASSWORD;
761 return NULL;
763 pass = Get_Pwnam_alloc(talloc_tos(), user);
764 status2 = create_token_from_username(conn->mem_ctx, pass->pw_name, True,
765 &conn->uid, &conn->gid,
766 &found_username,
767 &conn->nt_user_token);
768 TALLOC_FREE(pass);
769 if (!NT_STATUS_IS_OK(status2)) {
770 conn_free(conn);
771 *status = status2;
772 return NULL;
774 fstrcpy(user, found_username);
775 string_set(&conn->user,user);
776 TALLOC_FREE(found_username);
777 conn->force_user = True;
778 } else {
779 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
780 conn_free(conn);
781 *status = NT_STATUS_ACCESS_DENIED;
782 return NULL;
785 add_session_user(user);
787 safe_strcpy(conn->client_address,
788 client_addr(get_client_fd(),addr,sizeof(addr)),
789 sizeof(conn->client_address)-1);
790 conn->num_files_open = 0;
791 conn->lastused = conn->lastused_count = time(NULL);
792 conn->used = True;
793 conn->printer = (strncmp(dev,"LPT",3) == 0);
794 conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
795 ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
796 conn->dirptr = NULL;
798 /* Case options for the share. */
799 if (lp_casesensitive(snum) == Auto) {
800 /* We will be setting this per packet. Set to be case
801 * insensitive for now. */
802 conn->case_sensitive = False;
803 } else {
804 conn->case_sensitive = (bool)lp_casesensitive(snum);
807 conn->case_preserve = lp_preservecase(snum);
808 conn->short_case_preserve = lp_shortpreservecase(snum);
810 conn->encrypt_level = lp_smb_encrypt(snum);
812 conn->veto_list = NULL;
813 conn->hide_list = NULL;
814 conn->veto_oplock_list = NULL;
815 conn->aio_write_behind_list = NULL;
816 string_set(&conn->dirpath,"");
817 string_set(&conn->user,user);
819 conn->read_only = lp_readonly(SNUM(conn));
820 conn->admin_user = False;
823 * If force user is true, then store the given userid and the gid of
824 * the user we're forcing.
825 * For auxiliary groups see below.
828 if (*lp_force_user(snum)) {
829 NTSTATUS status2;
831 status2 = find_forced_user(conn,
832 (vuser != NULL) && vuser->guest,
833 user);
834 if (!NT_STATUS_IS_OK(status2)) {
835 conn_free(conn);
836 *status = status2;
837 return NULL;
839 string_set(&conn->user,user);
840 conn->force_user = True;
841 DEBUG(3,("Forced user %s\n",user));
845 * If force group is true, then override
846 * any groupid stored for the connecting user.
849 if (*lp_force_group(snum)) {
850 NTSTATUS status2;
851 DOM_SID group_sid;
853 status2 = find_forced_group(conn->force_user,
854 snum, user,
855 &group_sid, &conn->gid);
856 if (!NT_STATUS_IS_OK(status2)) {
857 conn_free(conn);
858 *status = status2;
859 return NULL;
862 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
864 /* Not force user and not security=share, but force
865 * group. vuser has a token to copy */
867 conn->nt_user_token = dup_nt_token(
868 NULL, vuser->nt_user_token);
869 if (conn->nt_user_token == NULL) {
870 DEBUG(0, ("dup_nt_token failed\n"));
871 conn_free(conn);
872 *status = NT_STATUS_NO_MEMORY;
873 return NULL;
877 /* If conn->nt_user_token is still NULL, we have
878 * security=share. This means ignore the SID, as we had no
879 * vuser to copy from */
881 if (conn->nt_user_token != NULL) {
882 /* Overwrite the primary group sid */
883 sid_copy(&conn->nt_user_token->user_sids[1],
884 &group_sid);
887 conn->force_group = True;
890 if (conn->nt_user_token != NULL) {
891 size_t i;
893 /* We have a share-specific token from force [user|group].
894 * This means we have to create the list of unix groups from
895 * the list of sids. */
897 conn->ngroups = 0;
898 conn->groups = NULL;
900 for (i=0; i<conn->nt_user_token->num_sids; i++) {
901 gid_t gid;
902 DOM_SID *sid = &conn->nt_user_token->user_sids[i];
904 if (!sid_to_gid(sid, &gid)) {
905 DEBUG(10, ("Could not convert SID %s to gid, "
906 "ignoring it\n",
907 sid_string_dbg(sid)));
908 continue;
910 if (!add_gid_to_array_unique(conn->mem_ctx, gid, &conn->groups,
911 &conn->ngroups)) {
912 DEBUG(0, ("add_gid_to_array_unique failed\n"));
913 conn_free(conn);
914 *status = NT_STATUS_NO_MEMORY;
915 return NULL;
921 char *s = talloc_sub_advanced(talloc_tos(),
922 lp_servicename(SNUM(conn)), conn->user,
923 conn->connectpath, conn->gid,
924 get_current_username(),
925 current_user_info.domain,
926 lp_pathname(snum));
927 if (!s) {
928 conn_free(conn);
929 *status = NT_STATUS_NO_MEMORY;
930 return NULL;
933 if (!set_conn_connectpath(conn,s)) {
934 TALLOC_FREE(s);
935 conn_free(conn);
936 *status = NT_STATUS_NO_MEMORY;
937 return NULL;
939 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
940 lp_servicename(snum)));
941 TALLOC_FREE(s);
945 * New code to check if there's a share security descripter
946 * added from NT server manager. This is done after the
947 * smb.conf checks are done as we need a uid and token. JRA.
952 bool can_write = False;
953 NT_USER_TOKEN *token = conn->nt_user_token ?
954 conn->nt_user_token :
955 (vuser ? vuser->nt_user_token : NULL);
958 * I don't believe this can happen. But the
959 * logic above is convoluted enough to confuse
960 * automated checkers, so be sure. JRA.
963 if (token == NULL) {
964 DEBUG(0,("make_connection: connection to %s "
965 "denied due to missing "
966 "NT token.\n",
967 lp_servicename(snum)));
968 conn_free(conn);
969 *status = NT_STATUS_ACCESS_DENIED;
970 return NULL;
973 can_write = share_access_check(token,
974 lp_servicename(snum),
975 FILE_WRITE_DATA);
977 if (!can_write) {
978 if (!share_access_check(token,
979 lp_servicename(snum),
980 FILE_READ_DATA)) {
981 /* No access, read or write. */
982 DEBUG(0,("make_connection: connection to %s "
983 "denied due to security "
984 "descriptor.\n",
985 lp_servicename(snum)));
986 conn_free(conn);
987 *status = NT_STATUS_ACCESS_DENIED;
988 return NULL;
989 } else {
990 conn->read_only = True;
994 /* Initialise VFS function pointers */
996 if (!smbd_vfs_init(conn)) {
997 DEBUG(0, ("vfs_init failed for service %s\n",
998 lp_servicename(snum)));
999 conn_free(conn);
1000 *status = NT_STATUS_BAD_NETWORK_NAME;
1001 return NULL;
1005 * If widelinks are disallowed we need to canonicalise the connect
1006 * path here to ensure we don't have any symlinks in the
1007 * connectpath. We will be checking all paths on this connection are
1008 * below this directory. We must do this after the VFS init as we
1009 * depend on the realpath() pointer in the vfs table. JRA.
1011 if (!lp_widelinks(snum)) {
1012 if (!canonicalize_connect_path(conn)) {
1013 DEBUG(0, ("canonicalize_connect_path failed "
1014 "for service %s, path %s\n",
1015 lp_servicename(snum),
1016 conn->connectpath));
1017 conn_free(conn);
1018 *status = NT_STATUS_BAD_NETWORK_NAME;
1019 return NULL;
1023 if ((!conn->printer) && (!conn->ipc)) {
1024 conn->notify_ctx = notify_init(conn->mem_ctx, server_id_self(),
1025 smbd_messaging_context(),
1026 smbd_event_context(),
1027 conn);
1030 /* ROOT Activities: */
1032 * Enforce the max connections parameter.
1035 if ((lp_max_connections(snum) > 0)
1036 && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
1037 lp_max_connections(snum))) {
1039 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
1040 lp_max_connections(snum), lp_servicename(snum)));
1041 conn_free(conn);
1042 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
1043 return NULL;
1047 * Get us an entry in the connections db
1049 if (!claim_connection(conn, lp_servicename(snum), 0)) {
1050 DEBUG(1, ("Could not store connections entry\n"));
1051 conn_free(conn);
1052 *status = NT_STATUS_INTERNAL_DB_ERROR;
1053 return NULL;
1056 /* Preexecs are done here as they might make the dir we are to ChDir
1057 * to below */
1058 /* execute any "root preexec = " line */
1059 if (*lp_rootpreexec(snum)) {
1060 char *cmd = talloc_sub_advanced(talloc_tos(),
1061 lp_servicename(SNUM(conn)), conn->user,
1062 conn->connectpath, conn->gid,
1063 get_current_username(),
1064 current_user_info.domain,
1065 lp_rootpreexec(snum));
1066 DEBUG(5,("cmd=%s\n",cmd));
1067 ret = smbrun(cmd,NULL);
1068 TALLOC_FREE(cmd);
1069 if (ret != 0 && lp_rootpreexec_close(snum)) {
1070 DEBUG(1,("root preexec gave %d - failing "
1071 "connection\n", ret));
1072 yield_connection(conn, lp_servicename(snum));
1073 conn_free(conn);
1074 *status = NT_STATUS_ACCESS_DENIED;
1075 return NULL;
1079 /* USER Activites: */
1080 if (!change_to_user(conn, conn->vuid)) {
1081 /* No point continuing if they fail the basic checks */
1082 DEBUG(0,("Can't become connected user!\n"));
1083 yield_connection(conn, lp_servicename(snum));
1084 conn_free(conn);
1085 *status = NT_STATUS_LOGON_FAILURE;
1086 return NULL;
1089 /* Remember that a different vuid can connect later without these
1090 * checks... */
1092 /* Preexecs are done here as they might make the dir we are to ChDir
1093 * to below */
1095 /* execute any "preexec = " line */
1096 if (*lp_preexec(snum)) {
1097 char *cmd = talloc_sub_advanced(talloc_tos(),
1098 lp_servicename(SNUM(conn)), conn->user,
1099 conn->connectpath, conn->gid,
1100 get_current_username(),
1101 current_user_info.domain,
1102 lp_preexec(snum));
1103 ret = smbrun(cmd,NULL);
1104 TALLOC_FREE(cmd);
1105 if (ret != 0 && lp_preexec_close(snum)) {
1106 DEBUG(1,("preexec gave %d - failing connection\n",
1107 ret));
1108 *status = NT_STATUS_ACCESS_DENIED;
1109 goto err_root_exit;
1113 #ifdef WITH_FAKE_KASERVER
1114 if (lp_afs_share(snum)) {
1115 afs_login(conn);
1117 #endif
1119 /* Add veto/hide lists */
1120 if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1121 set_namearray( &conn->veto_list, lp_veto_files(snum));
1122 set_namearray( &conn->hide_list, lp_hide_files(snum));
1123 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1124 set_namearray( &conn->aio_write_behind_list,
1125 lp_aio_write_behind(snum));
1128 /* Invoke VFS make connection hook - do this before the VFS_STAT call
1129 to allow any filesystems needing user credentials to initialize
1130 themselves. */
1132 if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1133 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1134 *status = NT_STATUS_UNSUCCESSFUL;
1135 goto err_root_exit;
1138 /* Any error exit after here needs to call the disconnect hook. */
1139 on_err_call_dis_hook = true;
1141 /* win2000 does not check the permissions on the directory
1142 during the tree connect, instead relying on permission
1143 check during individual operations. To match this behaviour
1144 I have disabled this chdir check (tridge) */
1145 /* the alternative is just to check the directory exists */
1146 if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1147 !S_ISDIR(st.st_mode)) {
1148 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1149 DEBUG(0,("'%s' is not a directory, when connecting to "
1150 "[%s]\n", conn->connectpath,
1151 lp_servicename(snum)));
1152 } else {
1153 DEBUG(0,("'%s' does not exist or permission denied "
1154 "when connecting to [%s] Error was %s\n",
1155 conn->connectpath, lp_servicename(snum),
1156 strerror(errno) ));
1158 *status = NT_STATUS_BAD_NETWORK_NAME;
1159 goto err_root_exit;
1162 string_set(&conn->origpath,conn->connectpath);
1164 #if SOFTLINK_OPTIMISATION
1165 /* resolve any soft links early if possible */
1166 if (vfs_ChDir(conn,conn->connectpath) == 0) {
1167 TALLOC_CTX *ctx = talloc_tos();
1168 char *s = vfs_GetWd(ctx,s);
1169 if (!s) {
1170 *status = map_nt_error_from_unix(errno);
1171 goto err_root_exit;
1173 if (!set_conn_connectpath(conn,s)) {
1174 *status = NT_STATUS_NO_MEMORY;
1175 goto err_root_exit;
1177 vfs_ChDir(conn,conn->connectpath);
1179 #endif
1181 /* Figure out the characteristics of the underlying filesystem. This
1182 * assumes that all the filesystem mounted withing a share path have
1183 * the same characteristics, which is likely but not guaranteed.
1186 conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
1189 * Print out the 'connected as' stuff here as we need
1190 * to know the effective uid and gid we will be using
1191 * (at least initially).
1194 if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1195 dbgtext( "%s (%s) ", get_remote_machine_name(),
1196 conn->client_address );
1197 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1198 dbgtext( "connect to service %s ", lp_servicename(snum) );
1199 dbgtext( "initially as user %s ", user );
1200 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1201 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1204 /* we've finished with the user stuff - go back to root */
1205 change_to_root_user();
1206 return(conn);
1208 err_root_exit:
1210 change_to_root_user();
1211 if (on_err_call_dis_hook) {
1212 /* Call VFS disconnect hook */
1213 SMB_VFS_DISCONNECT(conn);
1215 yield_connection(conn, lp_servicename(snum));
1216 conn_free(conn);
1217 return NULL;
1220 /***************************************************************************************
1221 Simple wrapper function for make_connection() to include a call to
1222 vfs_chdir()
1223 **************************************************************************************/
1225 connection_struct *make_connection_with_chdir(const char *service_in,
1226 DATA_BLOB password,
1227 const char *dev, uint16 vuid,
1228 NTSTATUS *status)
1230 connection_struct *conn = NULL;
1232 conn = make_connection(service_in, password, dev, vuid, status);
1235 * make_connection() does not change the directory for us any more
1236 * so we have to do it as a separate step --jerry
1239 if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1240 DEBUG(0,("move_driver_to_download_area: Can't change "
1241 "directory to %s for [print$] (%s)\n",
1242 conn->connectpath,strerror(errno)));
1243 yield_connection(conn, lp_servicename(SNUM(conn)));
1244 conn_free(conn);
1245 *status = NT_STATUS_UNSUCCESSFUL;
1246 return NULL;
1249 return conn;
1252 /****************************************************************************
1253 Make a connection to a service.
1255 * @param service
1256 ****************************************************************************/
1258 connection_struct *make_connection(const char *service_in, DATA_BLOB password,
1259 const char *pdev, uint16 vuid,
1260 NTSTATUS *status)
1262 uid_t euid;
1263 user_struct *vuser = NULL;
1264 fstring service;
1265 fstring dev;
1266 int snum = -1;
1267 char addr[INET6_ADDRSTRLEN];
1269 fstrcpy(dev, pdev);
1271 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1272 * root. */
1273 if (!non_root_mode() && (euid = geteuid()) != 0) {
1274 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1275 "(%u)\n", (unsigned int)euid ));
1276 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1279 if (conn_num_open() > 2047) {
1280 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1281 return NULL;
1284 if(lp_security() != SEC_SHARE) {
1285 vuser = get_valid_user_struct(vuid);
1286 if (!vuser) {
1287 DEBUG(1,("make_connection: refusing to connect with "
1288 "no session setup\n"));
1289 *status = NT_STATUS_ACCESS_DENIED;
1290 return NULL;
1294 /* Logic to try and connect to the correct [homes] share, preferably
1295 without too many getpwnam() lookups. This is particulary nasty for
1296 winbind usernames, where the share name isn't the same as unix
1297 username.
1299 The snum of the homes share is stored on the vuser at session setup
1300 time.
1303 if (strequal(service_in,HOMES_NAME)) {
1304 if(lp_security() != SEC_SHARE) {
1305 DATA_BLOB no_pw = data_blob_null;
1306 if (vuser->homes_snum == -1) {
1307 DEBUG(2, ("[homes] share not available for "
1308 "this user because it was not found "
1309 "or created at session setup "
1310 "time\n"));
1311 *status = NT_STATUS_BAD_NETWORK_NAME;
1312 return NULL;
1314 DEBUG(5, ("making a connection to [homes] service "
1315 "created at session setup time\n"));
1316 return make_connection_snum(vuser->homes_snum,
1317 vuser, no_pw,
1318 dev, status);
1319 } else {
1320 /* Security = share. Try with
1321 * current_user_info.smb_name as the username. */
1322 if (*current_user_info.smb_name) {
1323 fstring unix_username;
1324 fstrcpy(unix_username,
1325 current_user_info.smb_name);
1326 map_username(unix_username);
1327 snum = find_service(unix_username);
1329 if (snum != -1) {
1330 DEBUG(5, ("making a connection to 'homes' "
1331 "service %s based on "
1332 "security=share\n", service_in));
1333 return make_connection_snum(snum, NULL,
1334 password,
1335 dev, status);
1338 } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1339 && strequal(service_in,
1340 lp_servicename(vuser->homes_snum))) {
1341 DATA_BLOB no_pw = data_blob_null;
1342 DEBUG(5, ("making a connection to 'homes' service [%s] "
1343 "created at session setup time\n", service_in));
1344 return make_connection_snum(vuser->homes_snum,
1345 vuser, no_pw,
1346 dev, status);
1349 fstrcpy(service, service_in);
1351 strlower_m(service);
1353 snum = find_service(service);
1355 if (snum < 0) {
1356 if (strequal(service,"IPC$") ||
1357 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1358 DEBUG(3,("refusing IPC connection to %s\n", service));
1359 *status = NT_STATUS_ACCESS_DENIED;
1360 return NULL;
1363 DEBUG(0,("%s (%s) couldn't find service %s\n",
1364 get_remote_machine_name(),
1365 client_addr(get_client_fd(),addr,sizeof(addr)),
1366 service));
1367 *status = NT_STATUS_BAD_NETWORK_NAME;
1368 return NULL;
1371 /* Handle non-Dfs clients attempting connections to msdfs proxy */
1372 if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0')) {
1373 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1374 "(pointing to %s)\n",
1375 service, lp_msdfs_proxy(snum)));
1376 *status = NT_STATUS_BAD_NETWORK_NAME;
1377 return NULL;
1380 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1382 return make_connection_snum(snum, vuser,
1383 password,
1384 dev, status);
1387 /****************************************************************************
1388 Close a cnum.
1389 ****************************************************************************/
1391 void close_cnum(connection_struct *conn, uint16 vuid)
1393 if (IS_IPC(conn)) {
1394 pipe_close_conn(conn);
1395 } else {
1396 file_close_conn(conn);
1397 dptr_closecnum(conn);
1400 change_to_root_user();
1402 DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1403 get_remote_machine_name(),
1404 conn->client_address,
1405 lp_servicename(SNUM(conn))));
1407 /* Call VFS disconnect hook */
1408 SMB_VFS_DISCONNECT(conn);
1410 yield_connection(conn, lp_servicename(SNUM(conn)));
1412 /* make sure we leave the directory available for unmount */
1413 vfs_ChDir(conn, "/");
1415 /* execute any "postexec = " line */
1416 if (*lp_postexec(SNUM(conn)) &&
1417 change_to_user(conn, vuid)) {
1418 char *cmd = talloc_sub_advanced(talloc_tos(),
1419 lp_servicename(SNUM(conn)), conn->user,
1420 conn->connectpath, conn->gid,
1421 get_current_username(),
1422 current_user_info.domain,
1423 lp_postexec(SNUM(conn)));
1424 smbrun(cmd,NULL);
1425 TALLOC_FREE(cmd);
1426 change_to_root_user();
1429 change_to_root_user();
1430 /* execute any "root postexec = " line */
1431 if (*lp_rootpostexec(SNUM(conn))) {
1432 char *cmd = talloc_sub_advanced(talloc_tos(),
1433 lp_servicename(SNUM(conn)), conn->user,
1434 conn->connectpath, conn->gid,
1435 get_current_username(),
1436 current_user_info.domain,
1437 lp_rootpostexec(SNUM(conn)));
1438 smbrun(cmd,NULL);
1439 TALLOC_FREE(cmd);
1442 conn_free(conn);