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