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