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