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