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