890e66e26fd7e86ec88bc810d519e97c9cf2974b
[metze/samba/wip.git] / source3 / smbd / pysmbd.c
1 /*
2    Unix SMB/CIFS implementation.
3    Set NT and POSIX ACLs and other VFS operations from Python 
4    
5    Copyrigyt (C) Andrew Bartlett 2012
6    Copyright (C) Jeremy Allison 1994-2009.
7    Copyright (C) Andreas Gruenbacher 2002.
8    Copyright (C) Simo Sorce <idra@samba.org> 2009.
9    Copyright (C) Simo Sorce 2002
10    Copyright (C) Eric Lorimer 2002
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27 #include "smbd/smbd.h"
28 #include <Python.h>
29 #include "libcli/util/pyerrors.h"
30 #include "librpc/rpc/pyrpc_util.h"
31 #include <pytalloc.h>
32 #include "system/filesys.h"
33
34 extern const struct generic_mapping file_generic_mapping;
35
36 #undef  DBGC_CLASS
37 #define DBGC_CLASS DBGC_ACLS
38
39 static NTSTATUS set_sys_acl_no_snum(const char *fname,
40                                      SMB_ACL_TYPE_T acltype,
41                                      SMB_ACL_T theacl)
42 {
43         connection_struct *conn;
44         NTSTATUS status = NT_STATUS_OK;
45         int ret;
46
47         conn = talloc_zero(NULL, connection_struct);
48         if (conn == NULL) {
49                 DEBUG(0, ("talloc failed\n"));
50                 return NT_STATUS_NO_MEMORY;
51         }
52
53         if (!(conn->params = talloc(conn, struct share_params))) {
54                 DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
55                 TALLOC_FREE(conn);
56                 return NT_STATUS_NO_MEMORY;
57         }
58
59         conn->params->service = -1;
60
61         set_conn_connectpath(conn, "/");
62
63         smbd_vfs_init(conn);
64
65         ret = SMB_VFS_SYS_ACL_SET_FILE( conn, fname, acltype, theacl);
66         if (ret != 0) {
67                 status = map_nt_error_from_unix_common(ret);
68                 DEBUG(0,("set_nt_acl_no_snum: fset_nt_acl returned zero.\n"));
69         }
70
71         conn_free(conn);
72
73         return status;
74 }
75
76 static NTSTATUS set_nt_acl_no_snum(const char *fname,
77                                    uint32 security_info_sent, const struct security_descriptor *sd)
78 {
79         TALLOC_CTX *frame = talloc_stackframe();
80         connection_struct *conn;
81         NTSTATUS status = NT_STATUS_OK;
82         files_struct *fsp;
83         struct smb_filename *smb_fname = NULL;
84         int flags;
85
86         conn = talloc_zero(frame, connection_struct);
87         if (conn == NULL) {
88                 DEBUG(0, ("talloc failed\n"));
89                 return NT_STATUS_NO_MEMORY;
90         }
91
92         if (!(conn->params = talloc(conn, struct share_params))) {
93                 DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
94                 TALLOC_FREE(frame);
95                 return NT_STATUS_NO_MEMORY;
96         }
97
98         conn->params->service = -1;
99
100         set_conn_connectpath(conn, "/");
101
102         smbd_vfs_init(conn);
103
104         fsp = talloc_zero(frame, struct files_struct);
105         if (fsp == NULL) {
106                 TALLOC_FREE(frame);
107                 return NT_STATUS_NO_MEMORY;
108         }
109         fsp->fh = talloc(fsp, struct fd_handle);
110         if (fsp->fh == NULL) {
111                 TALLOC_FREE(frame);
112                 return NT_STATUS_NO_MEMORY;
113         }
114         fsp->conn = conn;
115
116         status = create_synthetic_smb_fname_split(fsp, fname, NULL,
117                                                   &smb_fname);
118         if (!NT_STATUS_IS_OK(status)) {
119                 TALLOC_FREE(frame);
120                 return status;
121         }
122
123         fsp->fsp_name = smb_fname;
124
125 #ifdef O_DIRECTORY
126         flags = O_RDONLY|O_DIRECTORY;
127 #else
128         /* POSIX allows us to open a directory with O_RDONLY. */
129         flags = O_RDONLY;
130 #endif
131
132         fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, O_RDWR, 00400);
133         if (fsp->fh->fd == -1 && errno == EISDIR) {
134                 fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, 00400);
135         }
136         if (fsp->fh->fd == -1) {
137                 printf("open: error=%d (%s)\n", errno, strerror(errno));
138                 TALLOC_FREE(frame);
139                 return NT_STATUS_UNSUCCESSFUL;
140         }
141
142         status = SMB_VFS_FSET_NT_ACL( fsp, security_info_sent, sd);
143         if (!NT_STATUS_IS_OK(status)) {
144                 DEBUG(0,("set_nt_acl_no_snum: fset_nt_acl returned %s.\n", nt_errstr(status)));
145         }
146
147         conn_free(conn);
148         TALLOC_FREE(frame);
149
150         return status;
151 }
152
153
154 static SMB_ACL_T make_simple_acl(uid_t uid, gid_t gid)
155 {
156         mode_t mode = SMB_ACL_READ|SMB_ACL_WRITE;
157         mode_t mode0 = 0;
158
159         SMB_ACL_ENTRY_T entry;
160         SMB_ACL_T acl = sys_acl_init(4);
161
162         if (!acl) {
163                 return NULL;
164         }
165
166         if (sys_acl_create_entry(&acl, &entry) != 0) {
167                 TALLOC_FREE(acl);
168                 return NULL;
169         }
170
171         if (sys_acl_set_tag_type(entry, SMB_ACL_USER_OBJ) != 0) {
172                 TALLOC_FREE(acl);
173                 return NULL;
174         }
175
176         if (sys_acl_set_permset(entry, &mode) != 0) {
177                 TALLOC_FREE(acl);
178                 return NULL;
179         }
180
181         if (sys_acl_create_entry(&acl, &entry) != 0) {
182                 TALLOC_FREE(acl);
183                 return NULL;
184         }
185
186         if (sys_acl_set_tag_type(entry, SMB_ACL_GROUP_OBJ) != 0) {
187                 TALLOC_FREE(acl);
188                 return NULL;
189         }
190
191         if (sys_acl_set_permset(entry, &mode) != 0) {
192                 TALLOC_FREE(acl);
193                 return NULL;
194         }
195
196         if (sys_acl_create_entry(&acl, &entry) != 0) {
197                 TALLOC_FREE(acl);
198                 return NULL;
199         }
200
201         if (sys_acl_set_tag_type(entry, SMB_ACL_OTHER) != 0) {
202                 TALLOC_FREE(acl);
203                 return NULL;
204         }
205
206         if (sys_acl_set_permset(entry, &mode0) != 0) {
207                 TALLOC_FREE(acl);
208                 return NULL;
209         }
210
211         if (sys_acl_create_entry(&acl, &entry) != 0) {
212                 TALLOC_FREE(acl);
213                 return NULL;
214         }
215
216         if (sys_acl_set_tag_type(entry, SMB_ACL_GROUP) != 0) {
217                 TALLOC_FREE(acl);
218                 return NULL;
219         }
220
221         if (sys_acl_set_qualifier(entry, &gid) != 0) {
222                 TALLOC_FREE(acl);
223                 return NULL;
224         }
225
226         if (sys_acl_set_permset(entry, &mode) != 0) {
227                 TALLOC_FREE(acl);
228                 return NULL;
229         }
230
231         if (sys_acl_create_entry(&acl, &entry) != 0) {
232                 TALLOC_FREE(acl);
233                 return NULL;
234         }
235
236         if (sys_acl_set_tag_type(entry, SMB_ACL_MASK) != 0) {
237                 TALLOC_FREE(acl);
238                 return NULL;
239         }
240
241         if (sys_acl_set_permset(entry, &mode0) != 0) {
242                 TALLOC_FREE(acl);
243                 return NULL;
244         }
245         return acl;
246 }
247
248 /*
249   set a simple ACL on a file, as a test
250  */
251 static PyObject *py_smbd_set_simple_acl(PyObject *self, PyObject *args)
252 {
253         NTSTATUS status;
254         char *fname;
255         int uid, gid;
256         SMB_ACL_T acl;
257         TALLOC_CTX *frame;
258
259         if (!PyArg_ParseTuple(args, "sii", &fname, &uid, &gid))
260                 return NULL;
261
262         acl = make_simple_acl(uid, gid);
263
264         frame = talloc_stackframe();
265
266         status = set_sys_acl_no_snum(fname, SMB_ACL_TYPE_ACCESS, acl);
267         TALLOC_FREE(acl);
268
269         TALLOC_FREE(frame);
270
271         PyErr_NTSTATUS_IS_ERR_RAISE(status);
272
273         Py_RETURN_NONE;
274 }
275
276 /*
277   check if we have ACL support
278  */
279 static PyObject *py_smbd_have_posix_acls(PyObject *self, PyObject *args)
280 {
281 #ifdef HAVE_POSIX_ACLS
282         return PyBool_FromLong(true);
283 #else
284         return PyBool_FromLong(false);
285 #endif
286 }
287
288 /*
289   set a simple ACL on a file, as a test
290  */
291 static PyObject *py_smbd_set_nt_acl(PyObject *self, PyObject *args)
292 {
293         NTSTATUS status;
294         char *fname;
295         int security_info_sent;
296         PyObject *py_sd;
297         struct security_descriptor *sd;
298
299         if (!PyArg_ParseTuple(args, "siO", &fname, &security_info_sent, &py_sd))
300                 return NULL;
301
302         if (!py_check_dcerpc_type(py_sd, "samba.dcerpc.security", "descriptor")) {
303                 return NULL;
304         }
305
306         sd = pytalloc_get_type(py_sd, struct security_descriptor);
307
308         status = set_nt_acl_no_snum(fname, security_info_sent, sd);
309         PyErr_NTSTATUS_IS_ERR_RAISE(status);
310
311         Py_RETURN_NONE;
312 }
313
314 /*
315   set a simple ACL on a file, as a test
316  */
317 static PyObject *py_smbd_get_nt_acl(PyObject *self, PyObject *args)
318 {
319         char *fname;
320         int security_info_sent;
321         PyObject *py_sd;
322         struct security_descriptor *sd;
323         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
324
325         if (!PyArg_ParseTuple(args, "si", &fname, &security_info_sent))
326                 return NULL;
327         
328         sd = get_nt_acl_no_snum(tmp_ctx, fname);
329
330         py_sd = py_return_ndr_struct("samba.dcerpc.security", "security_descriptor", sd, sd);
331
332         talloc_free(tmp_ctx);
333
334         return py_sd;
335 }
336
337 static PyMethodDef py_smbd_methods[] = {
338         { "have_posix_acls",
339                 (PyCFunction)py_smbd_have_posix_acls, METH_VARARGS,
340                 NULL },
341         { "set_simple_acl",
342                 (PyCFunction)py_smbd_set_simple_acl, METH_VARARGS,
343                 NULL },
344         { "set_nt_acl",
345                 (PyCFunction)py_smbd_set_nt_acl, METH_VARARGS,
346                 NULL },
347         { "get_nt_acl",
348                 (PyCFunction)py_smbd_get_nt_acl, METH_VARARGS,
349                 NULL },
350         { NULL }
351 };
352
353 void initsmbd(void);
354 void initsmbd(void)
355 {
356         PyObject *m;
357
358         m = Py_InitModule3("smbd", py_smbd_methods,
359                            "Python bindings for the smbd file server.");
360         if (m == NULL)
361                 return;
362
363 }