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