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