r20097: Ensure found_username is freed correctly when
[samba.git] / source / 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(int snum, BOOL vuser_is_guest,
472                                  uid_t *uid, gid_t *gid, fstring username,
473                                  struct nt_user_token **token)
474 {
475         TALLOC_CTX *mem_ctx;
476         char *fuser, *found_username;
477         struct nt_user_token *tmp_token;
478         NTSTATUS result;
479
480         if (!(mem_ctx = talloc_new(NULL))) {
481                 DEBUG(0, ("talloc_new failed\n"));
482                 return NT_STATUS_NO_MEMORY;
483         }
484
485         if (!(fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S",
486                                         lp_servicename(snum)))) {
487                 TALLOC_FREE(mem_ctx);
488                 return NT_STATUS_NO_MEMORY;
489                 
490         }
491
492         result = create_token_from_username(mem_ctx, fuser, vuser_is_guest,
493                                             uid, gid, &found_username,
494                                             &tmp_token);
495         if (!NT_STATUS_IS_OK(result)) {
496                 TALLOC_FREE(mem_ctx);
497                 return result;
498         }
499
500         if (!(*token = dup_nt_token(NULL, tmp_token))) {
501                 TALLOC_FREE(mem_ctx);
502                 return NT_STATUS_NO_MEMORY;
503         }
504
505         fstrcpy(username, found_username);
506
507         TALLOC_FREE(mem_ctx);
508         return NT_STATUS_OK;
509 }
510
511 /*
512  * Go through lookup_name etc to find the force'd group.  
513  *
514  * Create a new token from src_token, replacing the primary group sid with the
515  * one found.
516  */
517
518 static NTSTATUS find_forced_group(BOOL force_user,
519                                   int snum, const char *username,
520                                   DOM_SID *pgroup_sid,
521                                   gid_t *pgid)
522 {
523         NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
524         TALLOC_CTX *mem_ctx;
525         DOM_SID group_sid;
526         enum lsa_SidType type;
527         char *groupname;
528         BOOL user_must_be_member = False;
529         gid_t gid;
530
531         ZERO_STRUCTP(pgroup_sid);
532         *pgid = (gid_t)-1;
533
534         mem_ctx = talloc_new(NULL);
535         if (mem_ctx == NULL) {
536                 DEBUG(0, ("talloc_new failed\n"));
537                 return NT_STATUS_NO_MEMORY;
538         }
539
540         groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
541         if (groupname == NULL) {
542                 DEBUG(1, ("talloc_strdup failed\n"));
543                 result = NT_STATUS_NO_MEMORY;
544                 goto done;
545         }
546
547         if (groupname[0] == '+') {
548                 user_must_be_member = True;
549                 groupname += 1;
550         }
551
552         groupname = talloc_string_sub(mem_ctx, groupname,
553                                       "%S", lp_servicename(snum));
554
555         if (!lookup_name_smbconf(mem_ctx, groupname,
556                          LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
557                          NULL, NULL, &group_sid, &type)) {
558                 DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
559                            groupname));
560                 goto done;
561         }
562
563         if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
564             (type != SID_NAME_WKN_GRP)) {
565                 DEBUG(10, ("%s is a %s, not a group\n", groupname,
566                            sid_type_lookup(type)));
567                 goto done;
568         }
569
570         if (!sid_to_gid(&group_sid, &gid)) {
571                 DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
572                            sid_string_static(&group_sid), groupname));
573                 goto done;
574         }
575
576         /*
577          * If the user has been forced and the forced group starts with a '+',
578          * then we only set the group to be the forced group if the forced
579          * user is a member of that group.  Otherwise, the meaning of the '+'
580          * would be ignored.
581          */
582
583         if (force_user && user_must_be_member) {
584                 if (user_in_group_sid(username, &group_sid)) {
585                         sid_copy(pgroup_sid, &group_sid);
586                         *pgid = gid;
587                         DEBUG(3,("Forced group %s for member %s\n",
588                                  groupname, username));
589                 } else {
590                         DEBUG(0,("find_forced_group: forced user %s is not a member "
591                                 "of forced group %s. Disallowing access.\n",
592                                 username, groupname ));
593                         result = NT_STATUS_MEMBER_NOT_IN_GROUP;
594                         goto done;
595                 }
596         } else {
597                 sid_copy(pgroup_sid, &group_sid);
598                 *pgid = gid;
599                 DEBUG(3,("Forced group %s\n", groupname));
600         }
601
602         result = NT_STATUS_OK;
603  done:
604         TALLOC_FREE(mem_ctx);
605         return result;
606 }
607
608 /****************************************************************************
609   Make a connection, given the snum to connect to, and the vuser of the
610   connecting user if appropriate.
611 ****************************************************************************/
612
613 static connection_struct *make_connection_snum(int snum, user_struct *vuser,
614                                                DATA_BLOB password, 
615                                                const char *pdev,
616                                                NTSTATUS *status)
617 {
618         struct passwd *pass = NULL;
619         BOOL guest = False;
620         connection_struct *conn;
621         SMB_STRUCT_STAT st;
622         fstring user;
623         fstring dev;
624         int ret;
625
626         *user = 0;
627         fstrcpy(dev, pdev);
628         SET_STAT_INVALID(st);
629
630         if (NT_STATUS_IS_ERR(*status = share_sanity_checks(snum, dev))) {
631                 return NULL;
632         }       
633
634         conn = conn_new();
635         if (!conn) {
636                 DEBUG(0,("Couldn't find free connection.\n"));
637                 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
638                 return NULL;
639         }
640
641         conn->nt_user_token = NULL;
642
643         if (lp_guest_only(snum)) {
644                 const char *guestname = lp_guestaccount();
645                 NTSTATUS status2;
646                 char *found_username = NULL;
647
648                 guest = True;
649                 pass = getpwnam_alloc(NULL, guestname);
650                 if (!pass) {
651                         DEBUG(0,("make_connection_snum: Invalid guest "
652                                  "account %s??\n",guestname));
653                         conn_free(conn);
654                         *status = NT_STATUS_NO_SUCH_USER;
655                         return NULL;
656                 }
657                 status2 = create_token_from_username(NULL, pass->pw_name, True,
658                                                      &conn->uid, &conn->gid,
659                                                      &found_username,
660                                                      &conn->nt_user_token);
661                 if (!NT_STATUS_IS_OK(status2)) {
662                         TALLOC_FREE(found_username);
663                         conn_free(conn);
664                         *status = status2;
665                         return NULL;
666                 }
667                 fstrcpy(user, found_username);
668                 string_set(&conn->user,user);
669                 conn->force_user = True;
670                 TALLOC_FREE(found_username);
671                 TALLOC_FREE(pass);
672                 DEBUG(3,("Guest only user %s\n",user));
673         } else if (vuser) {
674                 if (vuser->guest) {
675                         if (!lp_guest_ok(snum)) {
676                                 DEBUG(2, ("guest user (from session setup) "
677                                           "not permitted to access this share "
678                                           "(%s)\n", lp_servicename(snum)));
679                                       conn_free(conn);
680                                       *status = NT_STATUS_ACCESS_DENIED;
681                                       return NULL;
682                         }
683                 } else {
684                         if (!user_ok_token(vuser->user.unix_name,
685                                            vuser->nt_user_token, snum)) {
686                                 DEBUG(2, ("user '%s' (from session setup) not "
687                                           "permitted to access this share "
688                                           "(%s)\n", vuser->user.unix_name,
689                                           lp_servicename(snum)));
690                                 conn_free(conn);
691                                 *status = NT_STATUS_ACCESS_DENIED;
692                                 return NULL;
693                         }
694                 }
695                 conn->vuid = vuser->vuid;
696                 conn->uid = vuser->uid;
697                 conn->gid = vuser->gid;
698                 string_set(&conn->user,vuser->user.unix_name);
699                 fstrcpy(user,vuser->user.unix_name);
700                 guest = vuser->guest; 
701         } else if (lp_security() == SEC_SHARE) {
702                 NTSTATUS status2;
703                 char *found_username = NULL;
704                 /* add it as a possible user name if we 
705                    are in share mode security */
706                 add_session_user(lp_servicename(snum));
707                 /* shall we let them in? */
708                 if (!authorise_login(snum,user,password,&guest)) {
709                         DEBUG( 2, ( "Invalid username/password for [%s]\n", 
710                                     lp_servicename(snum)) );
711                         conn_free(conn);
712                         *status = NT_STATUS_WRONG_PASSWORD;
713                         return NULL;
714                 }
715                 pass = Get_Pwnam(user);
716                 status2 = create_token_from_username(NULL, pass->pw_name, True,
717                                                      &conn->uid, &conn->gid,
718                                                      &found_username,
719                                                      &conn->nt_user_token);
720                 if (!NT_STATUS_IS_OK(status2)) {
721                         TALLOC_FREE(found_username);
722                         conn_free(conn);
723                         *status = status2;
724                         return NULL;
725                 }
726                 fstrcpy(user, found_username);
727                 string_set(&conn->user,user);
728                 TALLOC_FREE(found_username);
729                 conn->force_user = True;
730         } else {
731                 DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
732                 conn_free(conn);
733                 *status = NT_STATUS_ACCESS_DENIED;
734                 return NULL;
735         }
736
737         add_session_user(user);
738
739         safe_strcpy(conn->client_address, client_addr(), 
740                     sizeof(conn->client_address)-1);
741         conn->num_files_open = 0;
742         conn->lastused = conn->lastused_count = time(NULL);
743         conn->params->service = snum;
744         conn->used = True;
745         conn->printer = (strncmp(dev,"LPT",3) == 0);
746         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
747                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
748         conn->dirptr = NULL;
749
750         /* Case options for the share. */
751         if (lp_casesensitive(snum) == Auto) {
752                 /* We will be setting this per packet. Set to be case
753                  * insensitive for now. */
754                 conn->case_sensitive = False;
755         } else {
756                 conn->case_sensitive = (BOOL)lp_casesensitive(snum);
757         }
758
759         conn->case_preserve = lp_preservecase(snum);
760         conn->short_case_preserve = lp_shortpreservecase(snum);
761
762         conn->veto_list = NULL;
763         conn->hide_list = NULL;
764         conn->veto_oplock_list = NULL;
765         conn->aio_write_behind_list = NULL;
766         string_set(&conn->dirpath,"");
767         string_set(&conn->user,user);
768
769         conn->read_only = lp_readonly(SNUM(conn));
770         conn->admin_user = False;
771
772         /*
773          * If force user is true, then store the given userid and the gid of
774          * the user we're forcing.
775          * For auxiliary groups see below.
776          */
777         
778         if (*lp_force_user(snum)) {
779                 NTSTATUS status2;
780
781                 status2 = find_forced_user(snum,
782                                            (vuser != NULL) && vuser->guest,
783                                            &conn->uid, &conn->gid, user,
784                                            &conn->nt_user_token);
785                 if (!NT_STATUS_IS_OK(status2)) {
786                         conn_free(conn);
787                         *status = status2;
788                         return NULL;
789                 }
790                 string_set(&conn->user,user);
791                 conn->force_user = True;
792                 DEBUG(3,("Forced user %s\n",user));       
793         }
794
795         /*
796          * If force group is true, then override
797          * any groupid stored for the connecting user.
798          */
799         
800         if (*lp_force_group(snum)) {
801                 NTSTATUS status2;
802                 DOM_SID group_sid;
803
804                 status2 = find_forced_group(conn->force_user,
805                                             snum, user,
806                                             &group_sid, &conn->gid);
807                 if (!NT_STATUS_IS_OK(status2)) {
808                         conn_free(conn);
809                         *status = status2;
810                         return NULL;
811                 }
812
813                 if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
814
815                         /* Not force user and not security=share, but force
816                          * group. vuser has a token to copy */
817                         
818                         conn->nt_user_token = dup_nt_token(
819                                 NULL, vuser->nt_user_token);
820                         if (conn->nt_user_token == NULL) {
821                                 DEBUG(0, ("dup_nt_token failed\n"));
822                                 conn_free(conn);
823                                 *status = NT_STATUS_NO_MEMORY;
824                                 return NULL;
825                         }
826                 }
827
828                 /* If conn->nt_user_token is still NULL, we have
829                  * security=share. This means ignore the SID, as we had no
830                  * vuser to copy from */
831
832                 if (conn->nt_user_token != NULL) {
833                         /* Overwrite the primary group sid */
834                         sid_copy(&conn->nt_user_token->user_sids[1],
835                                  &group_sid);
836
837                 }
838                 conn->force_group = True;
839         }
840
841         if (conn->nt_user_token != NULL) {
842                 size_t i;
843
844                 /* We have a share-specific token from force [user|group].
845                  * This means we have to create the list of unix groups from
846                  * the list of sids. */
847
848                 conn->ngroups = 0;
849                 conn->groups = NULL;
850
851                 for (i=0; i<conn->nt_user_token->num_sids; i++) {
852                         gid_t gid;
853                         DOM_SID *sid = &conn->nt_user_token->user_sids[i];
854
855                         if (!sid_to_gid(sid, &gid)) {
856                                 DEBUG(10, ("Could not convert SID %s to gid, "
857                                            "ignoring it\n",
858                                            sid_string_static(sid)));
859                                 continue;
860                         }
861                         if (!add_gid_to_array_unique(NULL, gid, &conn->groups,
862                                                 &conn->ngroups)) {
863                                 DEBUG(0, ("add_gid_to_array_unique failed\n"));
864                                 conn_free(conn);
865                                 *status = NT_STATUS_NO_MEMORY;
866                                 return NULL;
867                         }
868                 }
869         }
870
871         {
872                 pstring s;
873                 pstrcpy(s,lp_pathname(snum));
874                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
875                                       conn->connectpath, conn->gid,
876                                       get_current_username(),
877                                       current_user_info.domain,
878                                       s, sizeof(s));
879                 set_conn_connectpath(conn,s);
880                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
881                          lp_servicename(snum)));
882         }
883
884         /*
885          * New code to check if there's a share security descripter
886          * added from NT server manager. This is done after the
887          * smb.conf checks are done as we need a uid and token. JRA.
888          *
889          */
890
891         {
892                 NT_USER_TOKEN *token = conn->nt_user_token ?
893                         conn->nt_user_token : vuser->nt_user_token;
894
895                 BOOL can_write = share_access_check(token,
896                                                     lp_servicename(snum),
897                                                     FILE_WRITE_DATA);
898
899                 if (!can_write) {
900                         if (!share_access_check(token,
901                                                 lp_servicename(snum),
902                                                 FILE_READ_DATA)) {
903                                 /* No access, read or write. */
904                                 DEBUG(0,("make_connection: connection to %s "
905                                          "denied due to security "
906                                          "descriptor.\n",
907                                           lp_servicename(snum)));
908                                 conn_free(conn);
909                                 *status = NT_STATUS_ACCESS_DENIED;
910                                 return NULL;
911                         } else {
912                                 conn->read_only = True;
913                         }
914                 }
915         }
916         /* Initialise VFS function pointers */
917
918         if (!smbd_vfs_init(conn)) {
919                 DEBUG(0, ("vfs_init failed for service %s\n",
920                           lp_servicename(snum)));
921                 conn_free(conn);
922                 *status = NT_STATUS_BAD_NETWORK_NAME;
923                 return NULL;
924         }
925
926         /*
927          * If widelinks are disallowed we need to canonicalise the connect
928          * path here to ensure we don't have any symlinks in the
929          * connectpath. We will be checking all paths on this connection are
930          * below this directory. We must do this after the VFS init as we
931          * depend on the realpath() pointer in the vfs table. JRA.
932          */
933         if (!lp_widelinks(snum)) {
934                 pstring s;
935                 pstrcpy(s,conn->connectpath);
936                 canonicalize_path(conn, s);
937                 set_conn_connectpath(conn,s);
938         }
939
940 /* ROOT Activities: */  
941         /* check number of connections */
942         if (!claim_connection(conn,
943                               lp_servicename(snum),
944                               lp_max_connections(snum),
945                               False,0)) {
946                 DEBUG(1,("too many connections - rejected\n"));
947                 conn_free(conn);
948                 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
949                 return NULL;
950         }  
951
952         /* Preexecs are done here as they might make the dir we are to ChDir
953          * to below */
954         /* execute any "root preexec = " line */
955         if (*lp_rootpreexec(snum)) {
956                 pstring cmd;
957                 pstrcpy(cmd,lp_rootpreexec(snum));
958                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
959                                       conn->connectpath, conn->gid,
960                                       get_current_username(),
961                                       current_user_info.domain,
962                                       cmd, sizeof(cmd));
963                 DEBUG(5,("cmd=%s\n",cmd));
964                 ret = smbrun(cmd,NULL);
965                 if (ret != 0 && lp_rootpreexec_close(snum)) {
966                         DEBUG(1,("root preexec gave %d - failing "
967                                  "connection\n", ret));
968                         yield_connection(conn, lp_servicename(snum));
969                         conn_free(conn);
970                         *status = NT_STATUS_ACCESS_DENIED;
971                         return NULL;
972                 }
973         }
974
975 /* USER Activites: */
976         if (!change_to_user(conn, conn->vuid)) {
977                 /* No point continuing if they fail the basic checks */
978                 DEBUG(0,("Can't become connected user!\n"));
979                 yield_connection(conn, lp_servicename(snum));
980                 conn_free(conn);
981                 *status = NT_STATUS_LOGON_FAILURE;
982                 return NULL;
983         }
984
985         /* Remember that a different vuid can connect later without these
986          * checks... */
987         
988         /* Preexecs are done here as they might make the dir we are to ChDir
989          * to below */
990
991         /* execute any "preexec = " line */
992         if (*lp_preexec(snum)) {
993                 pstring cmd;
994                 pstrcpy(cmd,lp_preexec(snum));
995                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
996                                       conn->connectpath, conn->gid,
997                                       get_current_username(),
998                                       current_user_info.domain,
999                                       cmd, sizeof(cmd));
1000                 ret = smbrun(cmd,NULL);
1001                 if (ret != 0 && lp_preexec_close(snum)) {
1002                         DEBUG(1,("preexec gave %d - failing connection\n",
1003                                  ret));
1004                         change_to_root_user();
1005                         yield_connection(conn, lp_servicename(snum));
1006                         conn_free(conn);
1007                         *status = NT_STATUS_ACCESS_DENIED;
1008                         return NULL;
1009                 }
1010         }
1011
1012 #ifdef WITH_FAKE_KASERVER
1013         if (lp_afs_share(snum)) {
1014                 afs_login(conn);
1015         }
1016 #endif
1017         
1018         /* Add veto/hide lists */
1019         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1020                 set_namearray( &conn->veto_list, lp_veto_files(snum));
1021                 set_namearray( &conn->hide_list, lp_hide_files(snum));
1022                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1023         }
1024         
1025         /* Invoke VFS make connection hook - do this before the VFS_STAT call
1026            to allow any filesystems needing user credentials to initialize
1027            themselves. */
1028
1029         if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1030                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1031                 change_to_root_user();
1032                 yield_connection(conn, lp_servicename(snum));
1033                 conn_free(conn);
1034                 *status = NT_STATUS_UNSUCCESSFUL;
1035                 return NULL;
1036         }
1037
1038         /* win2000 does not check the permissions on the directory
1039            during the tree connect, instead relying on permission
1040            check during individual operations. To match this behaviour
1041            I have disabled this chdir check (tridge) */
1042         /* the alternative is just to check the directory exists */
1043         if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1044             !S_ISDIR(st.st_mode)) {
1045                 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1046                         DEBUG(0,("'%s' is not a directory, when connecting to "
1047                                  "[%s]\n", conn->connectpath,
1048                                  lp_servicename(snum)));
1049                 } else {
1050                         DEBUG(0,("'%s' does not exist or permission denied "
1051                                  "when connecting to [%s] Error was %s\n",
1052                                  conn->connectpath, lp_servicename(snum),
1053                                  strerror(errno) ));
1054                 }
1055                 change_to_root_user();
1056                 /* Call VFS disconnect hook */    
1057                 SMB_VFS_DISCONNECT(conn);
1058                 yield_connection(conn, lp_servicename(snum));
1059                 conn_free(conn);
1060                 *status = NT_STATUS_BAD_NETWORK_NAME;
1061                 return NULL;
1062         }
1063         
1064         string_set(&conn->origpath,conn->connectpath);
1065         
1066 #if SOFTLINK_OPTIMISATION
1067         /* resolve any soft links early if possible */
1068         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1069                 pstring s;
1070                 pstrcpy(s,conn->connectpath);
1071                 vfs_GetWd(conn,s);
1072                 set_conn_connectpath(conn,s);
1073                 vfs_ChDir(conn,conn->connectpath);
1074         }
1075 #endif
1076         
1077         /*
1078          * Print out the 'connected as' stuff here as we need
1079          * to know the effective uid and gid we will be using
1080          * (at least initially).
1081          */
1082
1083         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1084                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1085                          conn->client_address );
1086                 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1087                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1088                 dbgtext( "initially as user %s ", user );
1089                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1090                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1091         }
1092         
1093         /* Setup the minimum value for a change notify wait time (seconds). */
1094         set_change_notify_timeout(lp_change_notify_timeout(snum));
1095
1096         /* we've finished with the user stuff - go back to root */
1097         change_to_root_user();
1098         return(conn);
1099 }
1100
1101 /***************************************************************************************
1102  Simple wrapper function for make_connection() to include a call to 
1103  vfs_chdir()
1104  **************************************************************************************/
1105  
1106 connection_struct *make_connection_with_chdir(const char *service_in,
1107                                               DATA_BLOB password, 
1108                                               const char *dev, uint16 vuid,
1109                                               NTSTATUS *status)
1110 {
1111         connection_struct *conn = NULL;
1112         
1113         conn = make_connection(service_in, password, dev, vuid, status);
1114         
1115         /*
1116          * make_connection() does not change the directory for us any more
1117          * so we have to do it as a separate step  --jerry
1118          */
1119          
1120         if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1121                 DEBUG(0,("move_driver_to_download_area: Can't change "
1122                          "directory to %s for [print$] (%s)\n",
1123                          conn->connectpath,strerror(errno)));
1124                 yield_connection(conn, lp_servicename(SNUM(conn)));
1125                 conn_free(conn);
1126                 *status = NT_STATUS_UNSUCCESSFUL;
1127                 return NULL;
1128         }
1129         
1130         return conn;
1131 }
1132
1133 /****************************************************************************
1134  Make a connection to a service.
1135  *
1136  * @param service 
1137 ****************************************************************************/
1138
1139 connection_struct *make_connection(const char *service_in, DATA_BLOB password, 
1140                                    const char *pdev, uint16 vuid,
1141                                    NTSTATUS *status)
1142 {
1143         uid_t euid;
1144         user_struct *vuser = NULL;
1145         fstring service;
1146         fstring dev;
1147         int snum = -1;
1148
1149         fstrcpy(dev, pdev);
1150
1151         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1152          * root. */
1153         if (!non_root_mode() && (euid = geteuid()) != 0) {
1154                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1155                          "(%u)\n", (unsigned int)euid ));
1156                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1157         }
1158
1159         if (conn_num_open() > 2047) {
1160                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1161                 return NULL;
1162         }
1163
1164         if(lp_security() != SEC_SHARE) {
1165                 vuser = get_valid_user_struct(vuid);
1166                 if (!vuser) {
1167                         DEBUG(1,("make_connection: refusing to connect with "
1168                                  "no session setup\n"));
1169                         *status = NT_STATUS_ACCESS_DENIED;
1170                         return NULL;
1171                 }
1172         }
1173
1174         /* Logic to try and connect to the correct [homes] share, preferably
1175            without too many getpwnam() lookups.  This is particulary nasty for
1176            winbind usernames, where the share name isn't the same as unix
1177            username.
1178
1179            The snum of the homes share is stored on the vuser at session setup
1180            time.
1181         */
1182
1183         if (strequal(service_in,HOMES_NAME)) {
1184                 if(lp_security() != SEC_SHARE) {
1185                         DATA_BLOB no_pw = data_blob(NULL, 0);
1186                         if (vuser->homes_snum == -1) {
1187                                 DEBUG(2, ("[homes] share not available for "
1188                                           "this user because it was not found "
1189                                           "or created at session setup "
1190                                           "time\n"));
1191                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1192                                 return NULL;
1193                         }
1194                         DEBUG(5, ("making a connection to [homes] service "
1195                                   "created at session setup time\n"));
1196                         return make_connection_snum(vuser->homes_snum,
1197                                                     vuser, no_pw, 
1198                                                     dev, status);
1199                 } else {
1200                         /* Security = share. Try with
1201                          * current_user_info.smb_name as the username.  */
1202                         if (*current_user_info.smb_name) {
1203                                 fstring unix_username;
1204                                 fstrcpy(unix_username,
1205                                         current_user_info.smb_name);
1206                                 map_username(unix_username);
1207                                 snum = find_service(unix_username);
1208                         } 
1209                         if (snum != -1) {
1210                                 DEBUG(5, ("making a connection to 'homes' "
1211                                           "service %s based on "
1212                                           "security=share\n", service_in));
1213                                 return make_connection_snum(snum, NULL,
1214                                                             password,
1215                                                             dev, status);
1216                         }
1217                 }
1218         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1219                    && strequal(service_in,
1220                                lp_servicename(vuser->homes_snum))) {
1221                 DATA_BLOB no_pw = data_blob(NULL, 0);
1222                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1223                           "created at session setup time\n", service_in));
1224                 return make_connection_snum(vuser->homes_snum,
1225                                             vuser, no_pw, 
1226                                             dev, status);
1227         }
1228         
1229         fstrcpy(service, service_in);
1230
1231         strlower_m(service);
1232
1233         snum = find_service(service);
1234
1235         if (snum < 0) {
1236                 if (strequal(service,"IPC$") ||
1237                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1238                         DEBUG(3,("refusing IPC connection to %s\n", service));
1239                         *status = NT_STATUS_ACCESS_DENIED;
1240                         return NULL;
1241                 }
1242
1243                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1244                          get_remote_machine_name(), client_addr(), service));
1245                 *status = NT_STATUS_BAD_NETWORK_NAME;
1246                 return NULL;
1247         }
1248
1249         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1250         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1251                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1252                           "(pointing to %s)\n", 
1253                         service, lp_msdfs_proxy(snum)));
1254                 *status = NT_STATUS_BAD_NETWORK_NAME;
1255                 return NULL;
1256         }
1257
1258         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1259
1260         return make_connection_snum(snum, vuser,
1261                                     password,
1262                                     dev, status);
1263 }
1264
1265 /****************************************************************************
1266  Close a cnum.
1267 ****************************************************************************/
1268
1269 void close_cnum(connection_struct *conn, uint16 vuid)
1270 {
1271         if (IS_IPC(conn)) {
1272                 pipe_close_conn(conn);
1273         } else {
1274                 file_close_conn(conn);
1275                 dptr_closecnum(conn);
1276         }
1277
1278         change_to_root_user();
1279
1280         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1281                                  get_remote_machine_name(),
1282                                  conn->client_address,
1283                                  lp_servicename(SNUM(conn))));
1284
1285         /* Call VFS disconnect hook */    
1286         SMB_VFS_DISCONNECT(conn);
1287
1288         yield_connection(conn, lp_servicename(SNUM(conn)));
1289
1290         /* make sure we leave the directory available for unmount */
1291         vfs_ChDir(conn, "/");
1292
1293         /* execute any "postexec = " line */
1294         if (*lp_postexec(SNUM(conn)) && 
1295             change_to_user(conn, vuid))  {
1296                 pstring cmd;
1297                 pstrcpy(cmd,lp_postexec(SNUM(conn)));
1298                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1299                                       conn->connectpath, conn->gid,
1300                                       get_current_username(),
1301                                       current_user_info.domain,
1302                                       cmd, sizeof(cmd));
1303                 smbrun(cmd,NULL);
1304                 change_to_root_user();
1305         }
1306
1307         change_to_root_user();
1308         /* execute any "root postexec = " line */
1309         if (*lp_rootpostexec(SNUM(conn)))  {
1310                 pstring cmd;
1311                 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
1312                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1313                                       conn->connectpath, conn->gid,
1314                                       get_current_username(),
1315                                       current_user_info.domain,
1316                                       cmd, sizeof(cmd));
1317                 smbrun(cmd,NULL);
1318         }
1319
1320         conn_free(conn);
1321 }