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