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