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