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