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