3e1d87f1f00c4678d17f339a980c53b6f4d77efb
[ddiss/samba.git] / source3 / smbd / service.c
1 /* 
2    Unix SMB/CIFS implementation.
3    service (connection) opening and closing
4    Copyright (C) Andrew Tridgell 1992-1998
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #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 uint32_t create_share_access_mask(connection_struct *conn,
519                                 int snum,
520                                 const struct security_token *token)
521 {
522         uint32_t share_access = 0;
523
524         share_access_check(token,
525                         lp_servicename(talloc_tos(), snum),
526                         MAXIMUM_ALLOWED_ACCESS,
527                         &share_access);
528
529         if (!CAN_WRITE(conn)) {
530                 share_access &=
531                         ~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA |
532                           SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE |
533                           SEC_DIR_DELETE_CHILD );
534         }
535
536         if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
537                 share_access |= SEC_FLAG_SYSTEM_SECURITY;
538         }
539         if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
540                 share_access |= (SEC_RIGHTS_PRIV_RESTORE);
541         }
542         if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
543                 share_access |= (SEC_RIGHTS_PRIV_BACKUP);
544         }
545         if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) {
546                 share_access |= (SEC_STD_WRITE_OWNER);
547         }
548
549         return share_access;
550 }
551
552 /****************************************************************************
553   Make a connection, given the snum to connect to, and the vuser of the
554   connecting user if appropriate.
555 ****************************************************************************/
556
557 static NTSTATUS make_connection_snum(struct smbd_server_connection *sconn,
558                                         connection_struct *conn,
559                                         int snum, struct user_struct *vuser,
560                                         const char *pdev)
561 {
562         struct smb_filename *smb_fname_cpath = NULL;
563         fstring dev;
564         int ret;
565         bool on_err_call_dis_hook = false;
566         uid_t effuid;
567         gid_t effgid;
568         NTSTATUS status;
569
570         fstrcpy(dev, pdev);
571
572         status = share_sanity_checks(sconn->remote_address,
573                                        sconn->remote_hostname,
574                                        snum,
575                                        dev);
576         if (NT_STATUS_IS_ERR(status)) {
577                 goto err_root_exit;
578         }
579
580         conn->params->service = snum;
581
582         status = create_connection_session_info(sconn,
583                 conn, snum, vuser->session_info,
584                 &conn->session_info);
585
586         if (!NT_STATUS_IS_OK(status)) {
587                 DEBUG(1, ("create_connection_session_info failed: %s\n",
588                           nt_errstr(status)));
589                 goto err_root_exit;
590         }
591
592         if (lp_guest_only(snum)) {
593                 conn->force_user = true;
594         }
595
596         conn->num_files_open = 0;
597         conn->lastused = conn->lastused_count = time(NULL);
598         conn->printer = (strncmp(dev,"LPT",3) == 0);
599         conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
600                       ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
601
602         /* Case options for the share. */
603         if (lp_casesensitive(snum) == Auto) {
604                 /* We will be setting this per packet. Set to be case
605                  * insensitive for now. */
606                 conn->case_sensitive = False;
607         } else {
608                 conn->case_sensitive = (bool)lp_casesensitive(snum);
609         }
610
611         conn->case_preserve = lp_preservecase(snum);
612         conn->short_case_preserve = lp_shortpreservecase(snum);
613
614         conn->encrypt_level = lp_smb_encrypt(snum);
615
616         conn->veto_list = NULL;
617         conn->hide_list = NULL;
618         conn->veto_oplock_list = NULL;
619         conn->aio_write_behind_list = NULL;
620
621         conn->read_only = lp_readonly(SNUM(conn));
622
623         status = set_conn_force_user_group(conn, snum);
624         if (!NT_STATUS_IS_OK(status)) {
625                 goto err_root_exit;
626         }
627
628         conn->vuid = vuser->vuid;
629
630         {
631                 char *s = talloc_sub_advanced(talloc_tos(),
632                                         lp_servicename(talloc_tos(), SNUM(conn)),
633                                         conn->session_info->unix_info->unix_name,
634                                         conn->connectpath,
635                                         conn->session_info->unix_token->gid,
636                                         conn->session_info->unix_info->sanitized_username,
637                                         conn->session_info->info->domain_name,
638                                         lp_pathname(talloc_tos(), snum));
639                 if (!s) {
640                         status = NT_STATUS_NO_MEMORY;
641                         goto err_root_exit;
642                 }
643
644                 if (!set_conn_connectpath(conn,s)) {
645                         TALLOC_FREE(s);
646                         status = NT_STATUS_NO_MEMORY;
647                         goto err_root_exit;
648                 }
649                 DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
650                          lp_servicename(talloc_tos(), snum)));
651                 TALLOC_FREE(s);
652         }
653
654         /*
655          * New code to check if there's a share security descripter
656          * added from NT server manager. This is done after the
657          * smb.conf checks are done as we need a uid and token. JRA.
658          *
659          */
660
661         conn->share_access = create_share_access_mask(conn,
662                                         snum,
663                                         conn->session_info->security_token);
664
665         if ((conn->share_access & FILE_WRITE_DATA) == 0) {
666                 if ((conn->share_access & FILE_READ_DATA) == 0) {
667                         /* No access, read or write. */
668                         DEBUG(0,("make_connection: connection to %s "
669                                  "denied due to security "
670                                  "descriptor.\n",
671                                  lp_servicename(talloc_tos(), snum)));
672                         status = NT_STATUS_ACCESS_DENIED;
673                         goto err_root_exit;
674                 } else {
675                         conn->read_only = True;
676                 }
677         }
678         /* Initialise VFS function pointers */
679
680         if (!smbd_vfs_init(conn)) {
681                 DEBUG(0, ("vfs_init failed for service %s\n",
682                           lp_servicename(talloc_tos(), snum)));
683                 status = NT_STATUS_BAD_NETWORK_NAME;
684                 goto err_root_exit;
685         }
686
687 /* ROOT Activities: */
688         /* explicitly check widelinks here so that we can correctly warn
689          * in the logs. */
690         widelinks_warning(snum);
691
692         /*
693          * Enforce the max connections parameter.
694          */
695
696         if ((lp_max_connections(snum) > 0)
697             && (count_current_connections(lp_servicename(talloc_tos(), SNUM(conn)), True) >=
698                 lp_max_connections(snum))) {
699
700                 DEBUG(1, ("Max connections (%d) exceeded for %s\n",
701                           lp_max_connections(snum),
702                           lp_servicename(talloc_tos(), snum)));
703                 status = NT_STATUS_INSUFFICIENT_RESOURCES;
704                 goto err_root_exit;
705         }
706
707         /* Invoke VFS make connection hook - this must be the first
708            filesystem operation that we do. */
709
710         if (SMB_VFS_CONNECT(conn, lp_servicename(talloc_tos(), snum),
711                             conn->session_info->unix_info->unix_name) < 0) {
712                 DEBUG(0,("make_connection: VFS make connection failed!\n"));
713                 status = NT_STATUS_UNSUCCESSFUL;
714                 goto err_root_exit;
715         }
716
717         /* Any error exit after here needs to call the disconnect hook. */
718         on_err_call_dis_hook = true;
719
720         if ((!conn->printer) && (!conn->ipc) &&
721             lp_change_notify(conn->params)) {
722                 if (sconn->notify_ctx == NULL) {
723                         sconn->notify_ctx = notify_init(
724                                 sconn, sconn->msg_ctx, sconn->ev_ctx);
725                 }
726                 if (sconn->sys_notify_ctx == NULL) {
727                         sconn->sys_notify_ctx = sys_notify_context_create(
728                                 sconn, sconn->ev_ctx);
729                 }
730         }
731
732         if (lp_kernel_oplocks(snum)) {
733                 init_kernel_oplocks(conn->sconn);
734         }
735
736         /*
737          * Fix compatibility issue pointed out by Volker.
738          * We pass the conn->connectpath to the preexec
739          * scripts as a parameter, so attempt to canonicalize
740          * it here before calling the preexec scripts.
741          * We ignore errors here, as it is possible that
742          * the conn->connectpath doesn't exist yet and
743          * the preexec scripts will create them.
744          */
745
746         (void)canonicalize_connect_path(conn);
747
748         /* Preexecs are done here as they might make the dir we are to ChDir
749          * to below */
750         /* execute any "root preexec = " line */
751         if (*lp_rootpreexec(talloc_tos(), snum)) {
752                 char *cmd = talloc_sub_advanced(talloc_tos(),
753                                         lp_servicename(talloc_tos(), SNUM(conn)),
754                                         conn->session_info->unix_info->unix_name,
755                                         conn->connectpath,
756                                         conn->session_info->unix_token->gid,
757                                         conn->session_info->unix_info->sanitized_username,
758                                         conn->session_info->info->domain_name,
759                                         lp_rootpreexec(talloc_tos(), snum));
760                 DEBUG(5,("cmd=%s\n",cmd));
761                 ret = smbrun(cmd,NULL);
762                 TALLOC_FREE(cmd);
763                 if (ret != 0 && lp_rootpreexec_close(snum)) {
764                         DEBUG(1,("root preexec gave %d - failing "
765                                  "connection\n", ret));
766                         status = NT_STATUS_ACCESS_DENIED;
767                         goto err_root_exit;
768                 }
769         }
770
771 /* USER Activites: */
772         if (!change_to_user(conn, conn->vuid)) {
773                 /* No point continuing if they fail the basic checks */
774                 DEBUG(0,("Can't become connected user!\n"));
775                 status = NT_STATUS_LOGON_FAILURE;
776                 goto err_root_exit;
777         }
778
779         effuid = geteuid();
780         effgid = getegid();
781
782         /* Remember that a different vuid can connect later without these
783          * checks... */
784
785         /* Preexecs are done here as they might make the dir we are to ChDir
786          * to below */
787
788         /* execute any "preexec = " line */
789         if (*lp_preexec(talloc_tos(), snum)) {
790                 char *cmd = talloc_sub_advanced(talloc_tos(),
791                                         lp_servicename(talloc_tos(), SNUM(conn)),
792                                         conn->session_info->unix_info->unix_name,
793                                         conn->connectpath,
794                                         conn->session_info->unix_token->gid,
795                                         conn->session_info->unix_info->sanitized_username,
796                                         conn->session_info->info->domain_name,
797                                         lp_preexec(talloc_tos(), snum));
798                 ret = smbrun(cmd,NULL);
799                 TALLOC_FREE(cmd);
800                 if (ret != 0 && lp_preexec_close(snum)) {
801                         DEBUG(1,("preexec gave %d - failing connection\n",
802                                  ret));
803                         status = NT_STATUS_ACCESS_DENIED;
804                         goto err_root_exit;
805                 }
806         }
807
808 #ifdef WITH_FAKE_KASERVER
809         if (lp_afs_share(snum)) {
810                 afs_login(conn);
811         }
812 #endif
813
814         /*
815          * we've finished with the user stuff - go back to root
816          * so the SMB_VFS_STAT call will only fail on path errors,
817          * not permission problems.
818          */
819         change_to_root_user();
820 /* ROOT Activites: */
821
822         /*
823          * If widelinks are disallowed we need to canonicalise the connect
824          * path here to ensure we don't have any symlinks in the
825          * connectpath. We will be checking all paths on this connection are
826          * below this directory. We must do this after the VFS init as we
827          * depend on the realpath() pointer in the vfs table. JRA.
828          */
829         if (!lp_widelinks(snum)) {
830                 if (!canonicalize_connect_path(conn)) {
831                         DEBUG(0, ("canonicalize_connect_path failed "
832                         "for service %s, path %s\n",
833                                 lp_servicename(talloc_tos(), snum),
834                                 conn->connectpath));
835                         status = NT_STATUS_BAD_NETWORK_NAME;
836                         goto err_root_exit;
837                 }
838         }
839
840         /* Add veto/hide lists */
841         if (!IS_IPC(conn) && !IS_PRINT(conn)) {
842                 set_namearray( &conn->veto_list,
843                                lp_veto_files(talloc_tos(), snum));
844                 set_namearray( &conn->hide_list,
845                                lp_hide_files(talloc_tos(), snum));
846                 set_namearray( &conn->veto_oplock_list,
847                                lp_veto_oplocks(talloc_tos(), snum));
848                 set_namearray( &conn->aio_write_behind_list,
849                                 lp_aio_write_behind(talloc_tos(), snum));
850         }
851         status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
852                                             NULL, NULL, &smb_fname_cpath);
853         if (!NT_STATUS_IS_OK(status)) {
854                 goto err_root_exit;
855         }
856
857         /* win2000 does not check the permissions on the directory
858            during the tree connect, instead relying on permission
859            check during individual operations. To match this behaviour
860            I have disabled this chdir check (tridge) */
861         /* the alternative is just to check the directory exists */
862
863         if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
864             !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
865                 if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
866                         DEBUG(0,("'%s' is not a directory, when connecting to "
867                                  "[%s]\n", conn->connectpath,
868                                  lp_servicename(talloc_tos(), snum)));
869                 } else {
870                         DEBUG(0,("'%s' does not exist or permission denied "
871                                  "when connecting to [%s] Error was %s\n",
872                                  conn->connectpath,
873                                  lp_servicename(talloc_tos(), snum),
874                                  strerror(errno) ));
875                 }
876                 status = NT_STATUS_BAD_NETWORK_NAME;
877                 goto err_root_exit;
878         }
879         conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
880
881         talloc_free(conn->origpath);
882         conn->origpath = talloc_strdup(conn, conn->connectpath);
883
884         /* Figure out the characteristics of the underlying filesystem. This
885          * assumes that all the filesystem mounted withing a share path have
886          * the same characteristics, which is likely but not guaranteed.
887          */
888
889         conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
890
891         /*
892          * Print out the 'connected as' stuff here as we need
893          * to know the effective uid and gid we will be using
894          * (at least initially).
895          */
896
897         if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
898                 dbgtext( "%s (%s) ", get_remote_machine_name(),
899                          tsocket_address_string(conn->sconn->remote_address,
900                                                 talloc_tos()) );
901                 dbgtext( "%s", srv_is_signing_active(sconn) ? "signed " : "");
902                 dbgtext( "connect to service %s ",
903                          lp_servicename(talloc_tos(), snum) );
904                 dbgtext( "initially as user %s ",
905                          conn->session_info->unix_info->unix_name );
906                 dbgtext( "(uid=%d, gid=%d) ", (int)effuid, (int)effgid );
907                 dbgtext( "(pid %d)\n", (int)getpid() );
908         }
909
910         return status;
911
912   err_root_exit:
913
914         TALLOC_FREE(smb_fname_cpath);
915         /* We must exit this function as root. */
916         if (geteuid() != 0) {
917                 change_to_root_user();
918         }
919         if (on_err_call_dis_hook) {
920                 /* Call VFS disconnect hook */
921                 SMB_VFS_DISCONNECT(conn);
922         }
923         return status;
924 }
925
926 /****************************************************************************
927  Make a connection to a service from SMB1. Internal interface.
928 ****************************************************************************/
929
930 static connection_struct *make_connection_smb1(struct smbd_server_connection *sconn,
931                                         NTTIME now,
932                                         int snum, struct user_struct *vuser,
933                                         const char *pdev,
934                                         NTSTATUS *pstatus)
935 {
936         struct smbXsrv_tcon *tcon;
937         NTSTATUS status;
938         struct connection_struct *conn;
939
940         status = smb1srv_tcon_create(sconn->conn, now, &tcon);
941         if (!NT_STATUS_IS_OK(status)) {
942                 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
943                          nt_errstr(status)));
944                 *pstatus = status;
945                 return NULL;
946         }
947
948         conn = conn_new(sconn);
949         if (!conn) {
950                 TALLOC_FREE(tcon);
951
952                 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
953                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
954                 return NULL;
955         }
956
957         conn->cnum = tcon->global->tcon_wire_id;
958         conn->tcon = tcon;
959
960         *pstatus = make_connection_snum(sconn,
961                                         conn,
962                                         snum,
963                                         vuser,
964                                         pdev);
965         if (!NT_STATUS_IS_OK(*pstatus)) {
966                 conn_free(conn);
967                 TALLOC_FREE(tcon);
968                 return NULL;
969         }
970
971         tcon->global->share_name = lp_servicename(tcon->global, SNUM(conn));
972         if (tcon->global->share_name == NULL) {
973                 conn_free(conn);
974                 TALLOC_FREE(tcon);
975                 *pstatus = NT_STATUS_NO_MEMORY;
976                 return NULL;
977         }
978         tcon->global->session_global_id =
979                 vuser->session->global->session_global_id;
980
981         tcon->compat = talloc_move(tcon, &conn);
982         tcon->status = NT_STATUS_OK;
983
984         *pstatus = smbXsrv_tcon_update(tcon);
985         if (!NT_STATUS_IS_OK(*pstatus)) {
986                 TALLOC_FREE(tcon);
987                 return NULL;
988         }
989
990         return tcon->compat;
991 }
992
993 /****************************************************************************
994  Make a connection to a service from SMB2. External SMB2 interface.
995  We must set cnum before claiming connection.
996 ****************************************************************************/
997
998 connection_struct *make_connection_smb2(struct smbd_server_connection *sconn,
999                                         struct smbXsrv_tcon *tcon,
1000                                         int snum,
1001                                         struct user_struct *vuser,
1002                                         const char *pdev,
1003                                         NTSTATUS *pstatus)
1004 {
1005         connection_struct *conn = conn_new(sconn);
1006         if (!conn) {
1007                 DEBUG(0,("make_connection_smb2: Couldn't find free connection.\n"));
1008                 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
1009                 return NULL;
1010         }
1011
1012         conn->cnum = tcon->global->tcon_wire_id;
1013         conn->tcon = tcon;
1014
1015         *pstatus = make_connection_snum(sconn,
1016                                         conn,
1017                                         snum,
1018                                         vuser,
1019                                         pdev);
1020         if (!NT_STATUS_IS_OK(*pstatus)) {
1021                 conn_free(conn);
1022                 return NULL;
1023         }
1024         return conn;
1025 }
1026
1027 /****************************************************************************
1028  Make a connection to a service. External SMB1 interface.
1029  *
1030  * @param service 
1031 ****************************************************************************/
1032
1033 connection_struct *make_connection(struct smbd_server_connection *sconn,
1034                                    NTTIME now,
1035                                    const char *service_in,
1036                                    const char *pdev, uint64_t vuid,
1037                                    NTSTATUS *status)
1038 {
1039         uid_t euid;
1040         struct user_struct *vuser = NULL;
1041         char *service = NULL;
1042         fstring dev;
1043         int snum = -1;
1044
1045         fstrcpy(dev, pdev);
1046
1047         /* This must ONLY BE CALLED AS ROOT. As it exits this function as
1048          * root. */
1049         if (!non_root_mode() && (euid = geteuid()) != 0) {
1050                 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
1051                          "(%u)\n", (unsigned int)euid ));
1052                 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
1053         }
1054
1055         if (conn_num_open(sconn) > 2047) {
1056                 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
1057                 return NULL;
1058         }
1059
1060         vuser = get_valid_user_struct(sconn, vuid);
1061         if (!vuser) {
1062                 DEBUG(1,("make_connection: refusing to connect with "
1063                          "no session setup\n"));
1064                 *status = NT_STATUS_ACCESS_DENIED;
1065                 return NULL;
1066         }
1067
1068         /* Logic to try and connect to the correct [homes] share, preferably
1069            without too many getpwnam() lookups.  This is particulary nasty for
1070            winbind usernames, where the share name isn't the same as unix
1071            username.
1072
1073            The snum of the homes share is stored on the vuser at session setup
1074            time.
1075         */
1076
1077         if (strequal(service_in,HOMES_NAME)) {
1078                 if (vuser->homes_snum == -1) {
1079                         DEBUG(2, ("[homes] share not available for "
1080                                   "this user because it was not found "
1081                                   "or created at session setup "
1082                                   "time\n"));
1083                         *status = NT_STATUS_BAD_NETWORK_NAME;
1084                         return NULL;
1085                 }
1086                 DEBUG(5, ("making a connection to [homes] service "
1087                           "created at session setup time\n"));
1088                 return make_connection_smb1(sconn, now,
1089                                             vuser->homes_snum,
1090                                             vuser,
1091                                             dev, status);
1092         } else if ((vuser->homes_snum != -1)
1093                    && strequal(service_in,
1094                                lp_servicename(talloc_tos(), vuser->homes_snum))) {
1095                 DEBUG(5, ("making a connection to 'homes' service [%s] "
1096                           "created at session setup time\n", service_in));
1097                 return make_connection_smb1(sconn, now,
1098                                             vuser->homes_snum,
1099                                             vuser,
1100                                             dev, status);
1101         }
1102
1103         service = talloc_strdup(talloc_tos(), service_in);
1104         if (!service) {
1105                 *status = NT_STATUS_NO_MEMORY;
1106                 return NULL;
1107         }
1108
1109         if (!strlower_m(service)) {
1110                 DEBUG(2, ("strlower_m %s failed\n", service));
1111                 *status = NT_STATUS_INVALID_PARAMETER;
1112                 return NULL;
1113         }
1114
1115         snum = find_service(talloc_tos(), service, &service);
1116         if (!service) {
1117                 *status = NT_STATUS_NO_MEMORY;
1118                 return NULL;
1119         }
1120
1121         if (snum < 0) {
1122                 if (strequal(service,"IPC$") ||
1123                     (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
1124                         DEBUG(3,("refusing IPC connection to %s\n", service));
1125                         *status = NT_STATUS_ACCESS_DENIED;
1126                         return NULL;
1127                 }
1128
1129                 DEBUG(3,("%s (%s) couldn't find service %s\n",
1130                         get_remote_machine_name(),
1131                         tsocket_address_string(
1132                                 sconn->remote_address, talloc_tos()),
1133                         service));
1134                 *status = NT_STATUS_BAD_NETWORK_NAME;
1135                 return NULL;
1136         }
1137
1138         /* Handle non-Dfs clients attempting connections to msdfs proxy */
1139         if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), snum) != '\0'))  {
1140                 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
1141                           "(pointing to %s)\n", 
1142                         service, lp_msdfs_proxy(talloc_tos(), snum)));
1143                 *status = NT_STATUS_BAD_NETWORK_NAME;
1144                 return NULL;
1145         }
1146
1147         DEBUG(5, ("making a connection to 'normal' service %s\n", service));
1148
1149         return make_connection_smb1(sconn, now, snum, vuser,
1150                                     dev, status);
1151 }
1152
1153 /****************************************************************************
1154  Close a cnum.
1155 ****************************************************************************/
1156
1157 void close_cnum(connection_struct *conn, uint64_t vuid)
1158 {
1159         file_close_conn(conn);
1160
1161         if (!IS_IPC(conn)) {
1162                 dptr_closecnum(conn);
1163         }
1164
1165         change_to_root_user();
1166
1167         DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",
1168                                  get_remote_machine_name(),
1169                                  tsocket_address_string(conn->sconn->remote_address,
1170                                                         talloc_tos()),
1171                                  lp_servicename(talloc_tos(), SNUM(conn))));
1172
1173         /* Call VFS disconnect hook */    
1174         SMB_VFS_DISCONNECT(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 }