r20014: Ouch.... "res" is not a flag here, it is the service number...
[samba.git] / source3 / smbd / service.c
1 /* 
2    Unix SMB/CIFS implementation.
3    service (connection) opening and closing
4    Copyright (C) Andrew Tridgell 1992-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 extern userdom_struct current_user_info;
24
25 /****************************************************************************
26  Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
27  absolute path stating in / and not ending in /.
28  Observent people will notice a similarity between this and check_path_syntax :-).
29 ****************************************************************************/
30
31 void set_conn_connectpath(connection_struct *conn, const pstring connectpath)
32 {
33         pstring destname;
34         char *d = destname;
35         const char *s = connectpath;
36         BOOL start_of_name_component = True;
37
38         *d++ = '/'; /* Always start with root. */
39
40         while (*s) {
41                 if (*s == '/') {
42                         /* Eat multiple '/' */
43                         while (*s == '/') {
44                                 s++;
45                         }
46                         if ((d > destname + 1) && (*s != '\0')) {
47                                 *d++ = '/';
48                         }
49                         start_of_name_component = True;
50                         continue;
51                 }
52
53                 if (start_of_name_component) {
54                         if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
55                                 /* Uh oh - "/../" or "/..\0" ! */
56
57                                 /* Go past the ../ or .. */
58                                 if (s[2] == '/') {
59                                         s += 3;
60                                 } else {
61                                         s += 2; /* Go past the .. */
62                                 }
63
64                                 /* If  we just added a '/' - delete it */
65                                 if ((d > destname) && (*(d-1) == '/')) {
66                                         *(d-1) = '\0';
67                                         d--;
68                                 }
69
70                                 /* Are we at the start ? Can't go back further if so. */
71                                 if (d <= destname) {
72                                         *d++ = '/'; /* Can't delete root */
73                                         continue;
74                                 }
75                                 /* Go back one level... */
76                                 /* Decrement d first as d points to the *next* char to write into. */
77                                 for (d--; d > destname; d--) {
78                                         if (*d == '/') {
79                                                 break;
80                                         }
81                                 }
82                                 /* We're still at the start of a name component, just the previous one. */
83                                 continue;
84                         } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
85                                 /* Component of pathname can't be "." only - skip the '.' . */
86                                 if (s[1] == '/') {
87                                         s += 2;
88                                 } else {
89                                         s++;
90                                 }
91                                 continue;
92                         }
93                 }
94
95                 if (!(*s & 0x80)) {
96                         *d++ = *s++;
97                 } else {
98                         size_t siz;
99                         /* Get the size of the next MB character. */
100                         next_codepoint(s,&siz);
101                         switch(siz) {
102                                 case 5:
103                                         *d++ = *s++;
104                                         /*fall through*/
105                                 case 4:
106                                         *d++ = *s++;
107                                         /*fall through*/
108                                 case 3:
109                                         *d++ = *s++;
110                                         /*fall through*/
111                                 case 2:
112                                         *d++ = *s++;
113                                         /*fall through*/
114                                 case 1:
115                                         *d++ = *s++;
116                                         break;
117                                 default:
118                                         break;
119                         }
120                 }
121                 start_of_name_component = False;
122         }
123         *d = '\0';
124
125         /* And must not end in '/' */
126         if (d > destname + 1 && (*(d-1) == '/')) {
127                 *(d-1) = '\0';
128         }
129
130         DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
131                 lp_servicename(SNUM(conn)), destname ));
132
133         string_set(&conn->connectpath, destname);
134 }
135
136 /****************************************************************************
137  Load parameters specific to a connection/service.
138 ****************************************************************************/
139
140 BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir)
141 {
142         static connection_struct *last_conn;
143         static uint16 last_flags;
144         int snum;
145
146         if (!conn)  {
147                 last_conn = NULL;
148                 return(False);
149         }
150
151         conn->lastused_count++;
152
153         snum = SNUM(conn);
154   
155         if (do_chdir &&
156             vfs_ChDir(conn,conn->connectpath) != 0 &&
157             vfs_ChDir(conn,conn->origpath) != 0) {
158                 DEBUG(0,("chdir (%s) failed\n",
159                          conn->connectpath));
160                 return(False);
161         }
162
163         if ((conn == last_conn) && (last_flags == flags)) {
164                 return(True);
165         }
166
167         last_conn = conn;
168         last_flags = flags;
169         
170         /* Obey the client case sensitivity requests - only for clients that support it. */
171         switch (lp_casesensitive(snum)) {
172                 case Auto:
173                         {
174                                 /* We need this uglyness due to DOS/Win9x clients that lie about case insensitivity. */
175                                 enum remote_arch_types ra_type = get_remote_arch();
176                                 if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
177                                         /* Client can't support per-packet case sensitive pathnames. */
178                                         conn->case_sensitive = False;
179                                 } else {
180                                         conn->case_sensitive = !(flags & FLAG_CASELESS_PATHNAMES);
181                                 }
182                         }
183                         break;
184                 case True:
185                         conn->case_sensitive = True;
186                         break;
187                 default:
188                         conn->case_sensitive = False;
189                         break;
190         }
191         return(True);
192 }
193
194 /****************************************************************************
195  Add a home service. Returns the new service number or -1 if fail.
196 ****************************************************************************/
197
198 int add_home_service(const char *service, const char *username, const char *homedir)
199 {
200         int iHomeService;
201
202         if (!service || !homedir)
203                 return -1;
204
205         if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0)
206                 return -1;
207
208         /*
209          * If this is a winbindd provided username, remove
210          * the domain component before adding the service.
211          * Log a warning if the "path=" parameter does not
212          * include any macros.
213          */
214
215         {
216                 const char *p = strchr(service,*lp_winbind_separator());
217
218                 /* We only want the 'user' part of the string */
219                 if (p) {
220                         service = p + 1;
221                 }
222         }
223
224         if (!lp_add_home(service, iHomeService, username, homedir)) {
225                 return -1;
226         }
227         
228         return lp_servicenumber(service);
229
230 }
231
232 static int load_registry_service(const char *servicename)
233 {
234         struct registry_key *key;
235         char *path;
236         WERROR err;
237
238         uint32 i;
239         char *value_name;
240         struct registry_value *value;
241
242         int res = -1;
243
244         if (!lp_registry_shares()) {
245                 return -1;
246         }
247
248         if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
249                 return -1;
250         }
251
252         err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(),
253                             &key);
254         SAFE_FREE(path);
255
256         if (!W_ERROR_IS_OK(err)) {
257                 return -1;
258         }
259
260         res = lp_add_service(servicename, -1);
261         if (res == -1) {
262                 goto error;
263         }
264
265         for (i=0;
266              W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value));
267              i++) {
268                 switch (value->type) {
269                 case REG_DWORD: { 
270                         char *tmp;
271                         if (asprintf(&tmp, "%d", value->v.dword) == -1) {
272                                 continue;
273                         }
274                         lp_do_parameter(res, value_name, tmp);
275                         SAFE_FREE(tmp);
276                         break;
277                 }
278                 case REG_SZ: {
279                         lp_do_parameter(res, value_name, value->v.sz.str);
280                         break;
281                 }
282                 default:
283                         /* Ignore all the rest */
284                         break;
285                 }
286
287                 TALLOC_FREE(value_name);
288                 TALLOC_FREE(value);
289         }
290
291  error:
292
293         TALLOC_FREE(key);
294         return res;
295 }
296
297 void load_registry_shares(void)
298 {
299         struct registry_key *key;
300         char *name;
301         WERROR err;
302         int i;
303
304         if (!lp_registry_shares()) {
305                 return;
306         }
307
308         err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
309                             get_root_nt_token(), &key);
310         if (!(W_ERROR_IS_OK(err))) {
311                 return;
312         }
313
314         for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
315                 load_registry_service(name);
316                 TALLOC_FREE(name);
317         }
318
319         TALLOC_FREE(key);
320         return;
321 }
322
323 /**
324  * Find a service entry.
325  *
326  * @param service is modified (to canonical form??)
327  **/
328
329 int find_service(fstring service)
330 {
331         int iService;
332
333         all_string_sub(service,"\\","/",0);
334
335         iService = lp_servicenumber(service);
336
337         /* now handle the special case of a home directory */
338         if (iService < 0) {
339                 char *phome_dir = get_user_home_dir(service);
340
341                 if(!phome_dir) {
342                         /*
343                          * Try mapping the servicename, it may
344                          * be a Windows to unix mapped user name.
345                          */
346                         if(map_username(service))
347                                 phome_dir = get_user_home_dir(service);
348                 }
349
350                 DEBUG(3,("checking for home directory %s gave %s\n",service,
351                         phome_dir?phome_dir:"(NULL)"));
352
353                 iService = add_home_service(service,service /* 'username' */, phome_dir);
354         }
355
356         /* If we still don't have a service, attempt to add it as a printer. */
357         if (iService < 0) {
358                 int iPrinterService;
359
360                 if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
361                         DEBUG(3,("checking whether %s is a valid printer name...\n", service));
362                         if (pcap_printername_ok(service)) {
363                                 DEBUG(3,("%s is a valid printer name\n", service));
364                                 DEBUG(3,("adding %s as a printer service\n", service));
365                                 lp_add_printer(service, iPrinterService);
366                                 iService = lp_servicenumber(service);
367                                 if (iService < 0) {
368                                         DEBUG(0,("failed to add %s as a printer service!\n", service));
369                                 }
370                         } else {
371                                 DEBUG(3,("%s is not a valid printer name\n", service));
372                         }
373                 }
374         }
375
376         /* Check for default vfs service?  Unsure whether to implement this */
377         if (iService < 0) {
378         }
379
380         /* just possibly it's a default service? */
381         if (iService < 0) {
382                 char *pdefservice = lp_defaultservice();
383                 if (pdefservice && *pdefservice && !strequal(pdefservice,service) && !strstr_m(service,"..")) {
384                         /*
385                          * We need to do a local copy here as lp_defaultservice() 
386                          * returns one of the rotating lp_string buffers that
387                          * could get overwritten by the recursive find_service() call
388                          * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
389                          */
390                         pstring defservice;
391                         pstrcpy(defservice, pdefservice);
392                         iService = find_service(defservice);
393                         if (iService >= 0) {
394                                 all_string_sub(service, "_","/",0);
395                                 iService = lp_add_service(service, iService);
396                         }
397                 }
398         }
399
400         if (iService < 0) {
401                 iService = load_registry_service(service);
402         }
403
404         /* Is it a usershare service ? */
405         if (iService < 0 && *lp_usershare_path()) {
406                 /* Ensure the name is canonicalized. */
407                 strlower_m(service);
408                 iService = load_usershare_service(service);
409         }
410
411         if (iService >= 0) {
412                 if (!VALID_SNUM(iService)) {
413                         DEBUG(0,("Invalid snum %d for %s\n",iService, service));
414                         iService = -1;
415                 }
416         }
417
418         if (iService < 0)
419                 DEBUG(3,("find_service() failed to find service %s\n", service));
420
421         return (iService);
422 }
423
424
425 /****************************************************************************
426  do some basic sainity checks on the share.  
427  This function modifies dev, ecode.
428 ****************************************************************************/
429
430 static NTSTATUS share_sanity_checks(int snum, fstring dev) 
431 {
432         
433         if (!lp_snum_ok(snum) || 
434             !check_access(smbd_server_fd(), 
435                           lp_hostsallow(snum), lp_hostsdeny(snum))) {    
436                 return NT_STATUS_ACCESS_DENIED;
437         }
438
439         if (dev[0] == '?' || !dev[0]) {
440                 if (lp_print_ok(snum)) {
441                         fstrcpy(dev,"LPT1:");
442                 } else if (strequal(lp_fstype(snum), "IPC")) {
443                         fstrcpy(dev, "IPC");
444                 } else {
445                         fstrcpy(dev,"A:");
446                 }
447         }
448
449         strupper_m(dev);
450
451         if (lp_print_ok(snum)) {
452                 if (!strequal(dev, "LPT1:")) {
453                         return NT_STATUS_BAD_DEVICE_TYPE;
454                 }
455         } else if (strequal(lp_fstype(snum), "IPC")) {
456                 if (!strequal(dev, "IPC")) {
457                         return NT_STATUS_BAD_DEVICE_TYPE;
458                 }
459         } else if (!strequal(dev, "A:")) {
460                 return NT_STATUS_BAD_DEVICE_TYPE;
461         }
462
463         /* Behave as a printer if we are supposed to */
464         if (lp_print_ok(snum) && (strcmp(dev, "A:") == 0)) {
465                 fstrcpy(dev, "LPT1:");
466         }
467
468         return NT_STATUS_OK;
469 }
470
471 static NTSTATUS find_forced_user(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                         add_gid_to_array_unique(NULL, gid, &conn->groups,
857                                                 &conn->ngroups);
858                 }
859         }
860
861         {
862                 pstring s;
863                 pstrcpy(s,lp_pathname(snum));
864                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
865                                       conn->connectpath, conn->gid,
866                                       get_current_username(),
867                                       current_user_info.domain,
868                                       s, sizeof(s));
869                 set_conn_connectpath(conn,s);
870                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
871                          lp_servicename(snum)));
872         }
873
874         /*
875          * New code to check if there's a share security descripter
876          * added from NT server manager. This is done after the
877          * smb.conf checks are done as we need a uid and token. JRA.
878          *
879          */
880
881         {
882                 NT_USER_TOKEN *token = conn->nt_user_token ?
883                         conn->nt_user_token : vuser->nt_user_token;
884
885                 BOOL can_write = share_access_check(token,
886                                                     lp_servicename(snum),
887                                                     FILE_WRITE_DATA);
888
889                 if (!can_write) {
890                         if (!share_access_check(token,
891                                                 lp_servicename(snum),
892                                                 FILE_READ_DATA)) {
893                                 /* No access, read or write. */
894                                 DEBUG(0,("make_connection: connection to %s "
895                                          "denied due to security "
896                                          "descriptor.\n",
897                                           lp_servicename(snum)));
898                                 conn_free(conn);
899                                 *status = NT_STATUS_ACCESS_DENIED;
900                                 return NULL;
901                         } else {
902                                 conn->read_only = True;
903                         }
904                 }
905         }
906         /* Initialise VFS function pointers */
907
908         if (!smbd_vfs_init(conn)) {
909                 DEBUG(0, ("vfs_init failed for service %s\n",
910                           lp_servicename(snum)));
911                 conn_free(conn);
912                 *status = NT_STATUS_BAD_NETWORK_NAME;
913                 return NULL;
914         }
915
916         /*
917          * If widelinks are disallowed we need to canonicalise the connect
918          * path here to ensure we don't have any symlinks in the
919          * connectpath. We will be checking all paths on this connection are
920          * below this directory. We must do this after the VFS init as we
921          * depend on the realpath() pointer in the vfs table. JRA.
922          */
923         if (!lp_widelinks(snum)) {
924                 pstring s;
925                 pstrcpy(s,conn->connectpath);
926                 canonicalize_path(conn, s);
927                 set_conn_connectpath(conn,s);
928         }
929
930 /* ROOT Activities: */  
931         /* check number of connections */
932         if (!claim_connection(conn,
933                               lp_servicename(snum),
934                               lp_max_connections(snum),
935                               False,0)) {
936                 DEBUG(1,("too many connections - rejected\n"));
937                 conn_free(conn);
938                 *status = NT_STATUS_INSUFFICIENT_RESOURCES;
939                 return NULL;
940         }  
941
942         /* Preexecs are done here as they might make the dir we are to ChDir
943          * to below */
944         /* execute any "root preexec = " line */
945         if (*lp_rootpreexec(snum)) {
946                 pstring cmd;
947                 pstrcpy(cmd,lp_rootpreexec(snum));
948                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
949                                       conn->connectpath, conn->gid,
950                                       get_current_username(),
951                                       current_user_info.domain,
952                                       cmd, sizeof(cmd));
953                 DEBUG(5,("cmd=%s\n",cmd));
954                 ret = smbrun(cmd,NULL);
955                 if (ret != 0 && lp_rootpreexec_close(snum)) {
956                         DEBUG(1,("root preexec gave %d - failing "
957                                  "connection\n", ret));
958                         yield_connection(conn, lp_servicename(snum));
959                         conn_free(conn);
960                         *status = NT_STATUS_ACCESS_DENIED;
961                         return NULL;
962                 }
963         }
964
965 /* USER Activites: */
966         if (!change_to_user(conn, conn->vuid)) {
967                 /* No point continuing if they fail the basic checks */
968                 DEBUG(0,("Can't become connected user!\n"));
969                 yield_connection(conn, lp_servicename(snum));
970                 conn_free(conn);
971                 *status = NT_STATUS_LOGON_FAILURE;
972                 return NULL;
973         }
974
975         /* Remember that a different vuid can connect later without these
976          * checks... */
977         
978         /* Preexecs are done here as they might make the dir we are to ChDir
979          * to below */
980
981         /* execute any "preexec = " line */
982         if (*lp_preexec(snum)) {
983                 pstring cmd;
984                 pstrcpy(cmd,lp_preexec(snum));
985                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
986                                       conn->connectpath, conn->gid,
987                                       get_current_username(),
988                                       current_user_info.domain,
989                                       cmd, sizeof(cmd));
990                 ret = smbrun(cmd,NULL);
991                 if (ret != 0 && lp_preexec_close(snum)) {
992                         DEBUG(1,("preexec gave %d - failing connection\n",
993                                  ret));
994                         change_to_root_user();
995                         yield_connection(conn, lp_servicename(snum));
996                         conn_free(conn);
997                         *status = NT_STATUS_ACCESS_DENIED;
998                         return NULL;
999                 }
1000         }
1001
1002 #ifdef WITH_FAKE_KASERVER
1003         if (lp_afs_share(snum)) {
1004                 afs_login(conn);
1005         }
1006 #endif
1007         
1008         /* Add veto/hide lists */
1009         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
1010                 set_namearray( &conn->veto_list, lp_veto_files(snum));
1011                 set_namearray( &conn->hide_list, lp_hide_files(snum));
1012                 set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
1013         }
1014         
1015         /* Invoke VFS make connection hook - do this before the VFS_STAT call
1016            to allow any filesystems needing user credentials to initialize
1017            themselves. */
1018
1019         if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) {
1020                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
1021                 change_to_root_user();
1022                 yield_connection(conn, lp_servicename(snum));
1023                 conn_free(conn);
1024                 *status = NT_STATUS_UNSUCCESSFUL;
1025                 return NULL;
1026         }
1027
1028         /* win2000 does not check the permissions on the directory
1029            during the tree connect, instead relying on permission
1030            check during individual operations. To match this behaviour
1031            I have disabled this chdir check (tridge) */
1032         /* the alternative is just to check the directory exists */
1033         if ((ret = SMB_VFS_STAT(conn, conn->connectpath, &st)) != 0 ||
1034             !S_ISDIR(st.st_mode)) {
1035                 if (ret == 0 && !S_ISDIR(st.st_mode)) {
1036                         DEBUG(0,("'%s' is not a directory, when connecting to "
1037                                  "[%s]\n", conn->connectpath,
1038                                  lp_servicename(snum)));
1039                 } else {
1040                         DEBUG(0,("'%s' does not exist or permission denied "
1041                                  "when connecting to [%s] Error was %s\n",
1042                                  conn->connectpath, lp_servicename(snum),
1043                                  strerror(errno) ));
1044                 }
1045                 change_to_root_user();
1046                 /* Call VFS disconnect hook */    
1047                 SMB_VFS_DISCONNECT(conn);
1048                 yield_connection(conn, lp_servicename(snum));
1049                 conn_free(conn);
1050                 *status = NT_STATUS_BAD_NETWORK_NAME;
1051                 return NULL;
1052         }
1053         
1054         string_set(&conn->origpath,conn->connectpath);
1055         
1056 #if SOFTLINK_OPTIMISATION
1057         /* resolve any soft links early if possible */
1058         if (vfs_ChDir(conn,conn->connectpath) == 0) {
1059                 pstring s;
1060                 pstrcpy(s,conn->connectpath);
1061                 vfs_GetWd(conn,s);
1062                 set_conn_connectpath(conn,s);
1063                 vfs_ChDir(conn,conn->connectpath);
1064         }
1065 #endif
1066         
1067         /*
1068          * Print out the 'connected as' stuff here as we need
1069          * to know the effective uid and gid we will be using
1070          * (at least initially).
1071          */
1072
1073         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
1074                 dbgtext( "%s (%s) ", get_remote_machine_name(),
1075                          conn->client_address );
1076                 dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
1077                 dbgtext( "connect to service %s ", lp_servicename(snum) );
1078                 dbgtext( "initially as user %s ", user );
1079                 dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
1080                 dbgtext( "(pid %d)\n", (int)sys_getpid() );
1081         }
1082         
1083         /* Setup the minimum value for a change notify wait time (seconds). */
1084         set_change_notify_timeout(lp_change_notify_timeout(snum));
1085
1086         /* we've finished with the user stuff - go back to root */
1087         change_to_root_user();
1088         return(conn);
1089 }
1090
1091 /***************************************************************************************
1092  Simple wrapper function for make_connection() to include a call to 
1093  vfs_chdir()
1094  **************************************************************************************/
1095  
1096 connection_struct *make_connection_with_chdir(const char *service_in,
1097                                               DATA_BLOB password, 
1098                                               const char *dev, uint16 vuid,
1099                                               NTSTATUS *status)
1100 {
1101         connection_struct *conn = NULL;
1102         
1103         conn = make_connection(service_in, password, dev, vuid, status);
1104         
1105         /*
1106          * make_connection() does not change the directory for us any more
1107          * so we have to do it as a separate step  --jerry
1108          */
1109          
1110         if ( conn && vfs_ChDir(conn,conn->connectpath) != 0 ) {
1111                 DEBUG(0,("move_driver_to_download_area: Can't change "
1112                          "directory to %s for [print$] (%s)\n",
1113                          conn->connectpath,strerror(errno)));
1114                 yield_connection(conn, lp_servicename(SNUM(conn)));
1115                 conn_free(conn);
1116                 *status = NT_STATUS_UNSUCCESSFUL;
1117                 return NULL;
1118         }
1119         
1120         return conn;
1121 }
1122
1123 /****************************************************************************
1124  Make a connection to a service.
1125  *
1126  * @param service 
1127 ****************************************************************************/
1128
1129 connection_struct *make_connection(const char *service_in, DATA_BLOB password, 
1130                                    const char *pdev, uint16 vuid,
1131                                    NTSTATUS *status)
1132 {
1133         uid_t euid;
1134         user_struct *vuser = NULL;
1135         fstring service;
1136         fstring dev;
1137         int snum = -1;
1138
1139         fstrcpy(dev, pdev);
1140
1141         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1142          * root. */
1143         if (!non_root_mode() && (euid = geteuid()) != 0) {
1144                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1145                          "(%u)\n", (unsigned int)euid ));
1146                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1147         }
1148
1149         if (conn_num_open() > 2047) {
1150                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1151                 return NULL;
1152         }
1153
1154         if(lp_security() != SEC_SHARE) {
1155                 vuser = get_valid_user_struct(vuid);
1156                 if (!vuser) {
1157                         DEBUG(1,("make_connection: refusing to connect with "
1158                                  "no session setup\n"));
1159                         *status = NT_STATUS_ACCESS_DENIED;
1160                         return NULL;
1161                 }
1162         }
1163
1164         /* Logic to try and connect to the correct [homes] share, preferably
1165            without too many getpwnam() lookups.  This is particulary nasty for
1166            winbind usernames, where the share name isn't the same as unix
1167            username.
1168
1169            The snum of the homes share is stored on the vuser at session setup
1170            time.
1171         */
1172
1173         if (strequal(service_in,HOMES_NAME)) {
1174                 if(lp_security() != SEC_SHARE) {
1175                         DATA_BLOB no_pw = data_blob(NULL, 0);
1176                         if (vuser->homes_snum == -1) {
1177                                 DEBUG(2, ("[homes] share not available for "
1178                                           "this user because it was not found "
1179                                           "or created at session setup "
1180                                           "time\n"));
1181                                 *status = NT_STATUS_BAD_NETWORK_NAME;
1182                                 return NULL;
1183                         }
1184                         DEBUG(5, ("making a connection to [homes] service "
1185                                   "created at session setup time\n"));
1186                         return make_connection_snum(vuser->homes_snum,
1187                                                     vuser, no_pw, 
1188                                                     dev, status);
1189                 } else {
1190                         /* Security = share. Try with
1191                          * current_user_info.smb_name as the username.  */
1192                         if (*current_user_info.smb_name) {
1193                                 fstring unix_username;
1194                                 fstrcpy(unix_username,
1195                                         current_user_info.smb_name);
1196                                 map_username(unix_username);
1197                                 snum = find_service(unix_username);
1198                         } 
1199                         if (snum != -1) {
1200                                 DEBUG(5, ("making a connection to 'homes' "
1201                                           "service %s based on "
1202                                           "security=share\n", service_in));
1203                                 return make_connection_snum(snum, NULL,
1204                                                             password,
1205                                                             dev, status);
1206                         }
1207                 }
1208         } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
1209                    && strequal(service_in,
1210                                lp_servicename(vuser->homes_snum))) {
1211                 DATA_BLOB no_pw = data_blob(NULL, 0);
1212                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1213                           "created at session setup time\n", service_in));
1214                 return make_connection_snum(vuser->homes_snum,
1215                                             vuser, no_pw, 
1216                                             dev, status);
1217         }
1218         
1219         fstrcpy(service, service_in);
1220
1221         strlower_m(service);
1222
1223         snum = find_service(service);
1224
1225         if (snum < 0) {
1226                 if (strequal(service,"IPC$") ||
1227                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1228                         DEBUG(3,("refusing IPC connection to %s\n", service));
1229                         *status = NT_STATUS_ACCESS_DENIED;
1230                         return NULL;
1231                 }
1232
1233                 DEBUG(0,("%s (%s) couldn't find service %s\n",
1234                          get_remote_machine_name(), client_addr(), service));
1235                 *status = NT_STATUS_BAD_NETWORK_NAME;
1236                 return NULL;
1237         }
1238
1239         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1240         if (lp_host_msdfs() && (*lp_msdfs_proxy(snum) != '\0'))  {
1241                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1242                           "(pointing to %s)\n", 
1243                         service, lp_msdfs_proxy(snum)));
1244                 *status = NT_STATUS_BAD_NETWORK_NAME;
1245                 return NULL;
1246         }
1247
1248         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1249
1250         return make_connection_snum(snum, vuser,
1251                                     password,
1252                                     dev, status);
1253 }
1254
1255 /****************************************************************************
1256  Close a cnum.
1257 ****************************************************************************/
1258
1259 void close_cnum(connection_struct *conn, uint16 vuid)
1260 {
1261         if (IS_IPC(conn)) {
1262                 pipe_close_conn(conn);
1263         } else {
1264                 file_close_conn(conn);
1265                 dptr_closecnum(conn);
1266         }
1267
1268         change_to_root_user();
1269
1270         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1271                                  get_remote_machine_name(),
1272                                  conn->client_address,
1273                                  lp_servicename(SNUM(conn))));
1274
1275         /* Call VFS disconnect hook */    
1276         SMB_VFS_DISCONNECT(conn);
1277
1278         yield_connection(conn, lp_servicename(SNUM(conn)));
1279
1280         /* make sure we leave the directory available for unmount */
1281         vfs_ChDir(conn, "/");
1282
1283         /* execute any "postexec = " line */
1284         if (*lp_postexec(SNUM(conn)) && 
1285             change_to_user(conn, vuid))  {
1286                 pstring cmd;
1287                 pstrcpy(cmd,lp_postexec(SNUM(conn)));
1288                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1289                                       conn->connectpath, conn->gid,
1290                                       get_current_username(),
1291                                       current_user_info.domain,
1292                                       cmd, sizeof(cmd));
1293                 smbrun(cmd,NULL);
1294                 change_to_root_user();
1295         }
1296
1297         change_to_root_user();
1298         /* execute any "root postexec = " line */
1299         if (*lp_rootpostexec(SNUM(conn)))  {
1300                 pstring cmd;
1301                 pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
1302                 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
1303                                       conn->connectpath, conn->gid,
1304                                       get_current_username(),
1305                                       current_user_info.domain,
1306                                       cmd, sizeof(cmd));
1307                 smbrun(cmd,NULL);
1308         }
1309
1310         conn_free(conn);
1311 }