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