source: branches/samba-3.2.x/source/smbd/file_access.c

Last change on this file was 133, checked in by Paul Smedley, 17 years ago

Update trunk to 3.2.0pre3

File size: 5.2 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Check access to files based on security descriptors.
4 Copyright (C) Jeremy Allison 2005-2006.
5 Copyright (C) Michael Adam 2007.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22
23extern struct current_user current_user;
24
25#undef DBGC_CLASS
26#define DBGC_CLASS DBGC_ACLS
27
28static bool can_access_file_acl(struct connection_struct *conn,
29 const char * fname, SMB_STRUCT_STAT *psbuf,
30 uint32_t access_mask)
31{
32 bool result;
33 NTSTATUS status;
34 uint32_t access_granted;
35 struct security_descriptor *secdesc = NULL;
36
37 status = SMB_VFS_GET_NT_ACL(conn, fname,
38 (OWNER_SECURITY_INFORMATION |
39 GROUP_SECURITY_INFORMATION |
40 DACL_SECURITY_INFORMATION),
41 &secdesc);
42 if (!NT_STATUS_IS_OK(status)) {
43 DEBUG(5, ("Could not get acl: %s\n", nt_errstr(status)));
44 return false;
45 }
46
47 result = se_access_check(secdesc, current_user.nt_user_token,
48 access_mask, &access_granted, &status);
49 TALLOC_FREE(secdesc);
50 return result;
51}
52
53/****************************************************************************
54 Actually emulate the in-kernel access checking for delete access. We need
55 this to successfully return ACCESS_DENIED on a file open for delete access.
56****************************************************************************/
57
58bool can_delete_file_in_directory(connection_struct *conn, const char *fname)
59{
60 SMB_STRUCT_STAT sbuf;
61 TALLOC_CTX *ctx = talloc_tos();
62 char *dname = NULL;
63
64 if (!CAN_WRITE(conn)) {
65 return False;
66 }
67
68 /* Get the parent directory permission mask and owners. */
69 if (!parent_dirname_talloc(ctx,
70 fname,
71 &dname,
72 NULL)) {
73 return False;
74 }
75 if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
76 return False;
77 }
78
79 /* fast paths first */
80
81 if (!S_ISDIR(sbuf.st_mode)) {
82 return False;
83 }
84#ifndef __OS2__
85 if (current_user.ut.uid == 0 || conn->admin_user) {
86 /* I'm sorry sir, I didn't know you were root... */
87 return True;
88 }
89#endif
90 /* Check primary owner write access. */
91 if (current_user.ut.uid == sbuf.st_uid) {
92 return (sbuf.st_mode & S_IWUSR) ? True : False;
93 }
94
95#ifdef S_ISVTX
96 /* sticky bit means delete only by owner or root. */
97 if (sbuf.st_mode & S_ISVTX) {
98 SMB_STRUCT_STAT sbuf_file;
99 if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
100 if (errno == ENOENT) {
101 /* If the file doesn't already exist then
102 * yes we'll be able to delete it. */
103 return True;
104 }
105 return False;
106 }
107 /*
108 * Patch from SATOH Fumiyasu <fumiyas@miraclelinux.com>
109 * for bug #3348. Don't assume owning sticky bit
110 * directory means write access allowed.
111 */
112 if (current_user.ut.uid != sbuf_file.st_uid) {
113 return False;
114 }
115 }
116#endif
117
118 /* now for ACL checks */
119
120 return can_access_file_acl(conn, dname, &sbuf, FILE_WRITE_DATA);
121}
122
123/****************************************************************************
124 Actually emulate the in-kernel access checking for read/write access. We need
125 this to successfully check for ability to write for dos filetimes.
126 Note this doesn't take into account share write permissions.
127****************************************************************************/
128
129bool can_access_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask)
130{
131 if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) {
132 return False;
133 }
134 access_mask &= (FILE_READ_DATA|FILE_WRITE_DATA);
135
136 /* some fast paths first */
137
138 DEBUG(10,("can_access_file: requesting 0x%x on file %s\n",
139 (unsigned int)access_mask, fname ));
140
141#ifndef __OS2__
142 if (current_user.ut.uid == 0 || conn->admin_user) {
143 /* I'm sorry sir, I didn't know you were root... */
144 return True;
145 }
146#endif
147 if (!VALID_STAT(*psbuf)) {
148 /* Get the file permission mask and owners. */
149 if(SMB_VFS_STAT(conn, fname, psbuf) != 0) {
150 return False;
151 }
152 }
153
154 /* Check primary owner access. */
155 if (current_user.ut.uid == psbuf->st_uid) {
156 switch (access_mask) {
157 case FILE_READ_DATA:
158 return (psbuf->st_mode & S_IRUSR) ? True : False;
159
160 case FILE_WRITE_DATA:
161 return (psbuf->st_mode & S_IWUSR) ? True : False;
162
163 default: /* FILE_READ_DATA|FILE_WRITE_DATA */
164
165 if ((psbuf->st_mode & (S_IWUSR|S_IRUSR)) == (S_IWUSR|S_IRUSR)) {
166 return True;
167 } else {
168 return False;
169 }
170 }
171 }
172
173 /* now for ACL checks */
174
175 return can_access_file_acl(conn, fname, psbuf, access_mask);
176}
177
178/****************************************************************************
179 Userspace check for write access.
180 Note this doesn't take into account share write permissions.
181****************************************************************************/
182
183bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
184{
185 return can_access_file(conn, fname, psbuf, FILE_WRITE_DATA);
186}
187
Note: See TracBrowser for help on using the repository browser.