s3: Fix some blank line endings
[amitay/samba.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,("set_sys_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_sys_acl_no_snum: SMB_VFS_SYS_ACL_SET_FILE "
69                          "returned zero.\n"));
70         }
71
72         conn_free(conn);
73
74         return status;
75 }
76
77 static NTSTATUS set_nt_acl_no_snum(const char *fname,
78                                    uint32 security_info_sent, const struct security_descriptor *sd)
79 {
80         TALLOC_CTX *frame = talloc_stackframe();
81         connection_struct *conn;
82         NTSTATUS status = NT_STATUS_OK;
83         files_struct *fsp;
84         struct smb_filename *smb_fname = NULL;
85         int flags;
86
87         conn = talloc_zero(frame, connection_struct);
88         if (conn == NULL) {
89                 DEBUG(0, ("talloc failed\n"));
90                 return NT_STATUS_NO_MEMORY;
91         }
92
93         if (!(conn->params = talloc(conn, struct share_params))) {
94                 DEBUG(0,("set_nt_acl_no_snum: talloc() failed!\n"));
95                 TALLOC_FREE(frame);
96                 return NT_STATUS_NO_MEMORY;
97         }
98
99         conn->params->service = -1;
100
101         set_conn_connectpath(conn, "/");
102
103         smbd_vfs_init(conn);
104
105         fsp = talloc_zero(frame, struct files_struct);
106         if (fsp == NULL) {
107                 TALLOC_FREE(frame);
108                 return NT_STATUS_NO_MEMORY;
109         }
110         fsp->fh = talloc(fsp, struct fd_handle);
111         if (fsp->fh == NULL) {
112                 TALLOC_FREE(frame);
113                 return NT_STATUS_NO_MEMORY;
114         }
115         fsp->conn = conn;
116
117         status = create_synthetic_smb_fname_split(fsp, fname, NULL,
118                                                   &smb_fname);
119         if (!NT_STATUS_IS_OK(status)) {
120                 TALLOC_FREE(frame);
121                 return status;
122         }
123
124         fsp->fsp_name = smb_fname;
125
126 #ifdef O_DIRECTORY
127         flags = O_RDONLY|O_DIRECTORY;
128 #else
129         /* POSIX allows us to open a directory with O_RDONLY. */
130         flags = O_RDONLY;
131 #endif
132
133         fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, O_RDWR, 00400);
134         if (fsp->fh->fd == -1 && errno == EISDIR) {
135                 fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, 00400);
136         }
137         if (fsp->fh->fd == -1) {
138                 printf("open: error=%d (%s)\n", errno, strerror(errno));
139                 TALLOC_FREE(frame);
140                 return NT_STATUS_UNSUCCESSFUL;
141         }
142
143         status = SMB_VFS_FSET_NT_ACL( fsp, security_info_sent, sd);
144         if (!NT_STATUS_IS_OK(status)) {
145                 DEBUG(0,("set_nt_acl_no_snum: fset_nt_acl returned %s.\n", nt_errstr(status)));
146         }
147
148         conn_free(conn);
149         TALLOC_FREE(frame);
150
151         return status;
152 }
153
154
155 static SMB_ACL_T make_simple_acl(gid_t gid, mode_t chmod_mode)
156 {
157         mode_t mode = SMB_ACL_READ|SMB_ACL_WRITE;
158
159         mode_t mode_user = (chmod_mode & 0700) >> 16;
160         mode_t mode_group = (chmod_mode & 070) >> 8;
161         mode_t mode_other = chmod_mode &  07;
162
163         SMB_ACL_ENTRY_T entry;
164         SMB_ACL_T acl = sys_acl_init();
165
166         if (!acl) {
167                 return NULL;
168         }
169
170         if (sys_acl_create_entry(&acl, &entry) != 0) {
171                 TALLOC_FREE(acl);
172                 return NULL;
173         }
174
175         if (sys_acl_set_tag_type(entry, SMB_ACL_USER_OBJ) != 0) {
176                 TALLOC_FREE(acl);
177                 return NULL;
178         }
179
180         if (sys_acl_set_permset(entry, &mode_user) != 0) {
181                 TALLOC_FREE(acl);
182                 return NULL;
183         }
184
185         if (sys_acl_create_entry(&acl, &entry) != 0) {
186                 TALLOC_FREE(acl);
187                 return NULL;
188         }
189
190         if (sys_acl_set_tag_type(entry, SMB_ACL_GROUP_OBJ) != 0) {
191                 TALLOC_FREE(acl);
192                 return NULL;
193         }
194
195         if (sys_acl_set_permset(entry, &mode_group) != 0) {
196                 TALLOC_FREE(acl);
197                 return NULL;
198         }
199
200         if (sys_acl_create_entry(&acl, &entry) != 0) {
201                 TALLOC_FREE(acl);
202                 return NULL;
203         }
204
205         if (sys_acl_set_tag_type(entry, SMB_ACL_OTHER) != 0) {
206                 TALLOC_FREE(acl);
207                 return NULL;
208         }
209
210         if (sys_acl_set_permset(entry, &mode_other) != 0) {
211                 TALLOC_FREE(acl);
212                 return NULL;
213         }
214
215         if (gid != -1) {
216                 if (sys_acl_create_entry(&acl, &entry) != 0) {
217                         TALLOC_FREE(acl);
218                         return NULL;
219                 }
220
221                 if (sys_acl_set_tag_type(entry, SMB_ACL_GROUP) != 0) {
222                         TALLOC_FREE(acl);
223                         return NULL;
224                 }
225
226                 if (sys_acl_set_qualifier(entry, &gid) != 0) {
227                         TALLOC_FREE(acl);
228                         return NULL;
229                 }
230
231                 if (sys_acl_set_permset(entry, &mode_group) != 0) {
232                         TALLOC_FREE(acl);
233                         return NULL;
234                 }
235         }
236
237         if (sys_acl_create_entry(&acl, &entry) != 0) {
238                 TALLOC_FREE(acl);
239                 return NULL;
240         }
241
242         if (sys_acl_set_tag_type(entry, SMB_ACL_MASK) != 0) {
243                 TALLOC_FREE(acl);
244                 return NULL;
245         }
246
247         if (sys_acl_set_permset(entry, &mode) != 0) {
248                 TALLOC_FREE(acl);
249                 return NULL;
250         }
251         return acl;
252 }
253
254 /*
255   set a simple ACL on a file, as a test
256  */
257 static PyObject *py_smbd_set_simple_acl(PyObject *self, PyObject *args)
258 {
259         NTSTATUS status;
260         char *fname;
261         int mode, gid = -1;
262         SMB_ACL_T acl;
263         TALLOC_CTX *frame;
264
265         if (!PyArg_ParseTuple(args, "si|i", &fname, &mode, &gid))
266                 return NULL;
267
268         acl = make_simple_acl(gid, mode);
269
270         frame = talloc_stackframe();
271
272         status = set_sys_acl_no_snum(fname, SMB_ACL_TYPE_ACCESS, acl);
273         TALLOC_FREE(acl);
274
275         TALLOC_FREE(frame);
276
277         PyErr_NTSTATUS_IS_ERR_RAISE(status);
278
279         Py_RETURN_NONE;
280 }
281
282 /*
283   chown a file
284  */
285 static PyObject *py_smbd_chown(PyObject *self, PyObject *args)
286 {
287         connection_struct *conn;
288         NTSTATUS status = NT_STATUS_OK;
289         int ret;
290
291         char *fname;
292         int uid, gid;
293         TALLOC_CTX *frame;
294
295         if (!PyArg_ParseTuple(args, "sii", &fname, &uid, &gid))
296                 return NULL;
297
298         frame = talloc_stackframe();
299
300         conn = talloc_zero(frame, connection_struct);
301         if (conn == NULL) {
302                 PyErr_NoMemory();
303                 return NULL;
304         }
305
306         if (!(conn->params = talloc(conn, struct share_params))) {
307                 PyErr_NoMemory();
308                 return NULL;
309         }
310
311         conn->params->service = -1;
312
313         set_conn_connectpath(conn, "/");
314
315         smbd_vfs_init(conn);
316
317         ret = SMB_VFS_CHOWN( conn, fname, uid, gid);
318         if (ret != 0) {
319                 status = map_nt_error_from_unix_common(errno);
320                 DEBUG(0,("chown returned failure: %s\n", strerror(errno)));
321         }
322
323         conn_free(conn);
324
325         TALLOC_FREE(frame);
326
327         PyErr_NTSTATUS_IS_ERR_RAISE(status);
328
329         Py_RETURN_NONE;
330 }
331
332 /*
333   check if we have ACL support
334  */
335 static PyObject *py_smbd_have_posix_acls(PyObject *self, PyObject *args)
336 {
337 #ifdef HAVE_POSIX_ACLS
338         return PyBool_FromLong(true);
339 #else
340         return PyBool_FromLong(false);
341 #endif
342 }
343
344 /*
345   set the NT ACL on a file
346  */
347 static PyObject *py_smbd_set_nt_acl(PyObject *self, PyObject *args)
348 {
349         NTSTATUS status;
350         char *fname;
351         int security_info_sent;
352         PyObject *py_sd;
353         struct security_descriptor *sd;
354
355         if (!PyArg_ParseTuple(args, "siO", &fname, &security_info_sent, &py_sd))
356                 return NULL;
357
358         if (!py_check_dcerpc_type(py_sd, "samba.dcerpc.security", "descriptor")) {
359                 return NULL;
360         }
361
362         sd = pytalloc_get_type(py_sd, struct security_descriptor);
363
364         status = set_nt_acl_no_snum(fname, security_info_sent, sd);
365         PyErr_NTSTATUS_IS_ERR_RAISE(status);
366
367         Py_RETURN_NONE;
368 }
369
370 /*
371   Return the NT ACL on a file
372  */
373 static PyObject *py_smbd_get_nt_acl(PyObject *self, PyObject *args)
374 {
375         char *fname;
376         int security_info_wanted;
377         PyObject *py_sd;
378         struct security_descriptor *sd;
379         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
380
381         if (!PyArg_ParseTuple(args, "si", &fname, &security_info_wanted))
382                 return NULL;
383
384         sd = get_nt_acl_no_snum(tmp_ctx, fname, security_info_wanted);
385
386         py_sd = py_return_ndr_struct("samba.dcerpc.security", "descriptor", sd, sd);
387
388         talloc_free(tmp_ctx);
389
390         return py_sd;
391 }
392
393 /*
394   set the posix (or similar) ACL on a file
395  */
396 static PyObject *py_smbd_set_sys_acl(PyObject *self, PyObject *args)
397 {
398         NTSTATUS status;
399         char *fname;
400         PyObject *py_acl;
401         struct smb_acl_t *acl;
402         int acl_type;
403
404         if (!PyArg_ParseTuple(args, "siO", &fname, &acl_type, &py_acl))
405                 return NULL;
406
407         if (!py_check_dcerpc_type(py_acl, "samba.dcerpc.smb_acl", "t")) {
408                 return NULL;
409         }
410
411         acl = pytalloc_get_type(py_acl, struct smb_acl_t);
412
413         status = set_sys_acl_no_snum(fname, acl_type, acl);
414         PyErr_NTSTATUS_IS_ERR_RAISE(status);
415
416         Py_RETURN_NONE;
417 }
418
419 /*
420   Return the posix (or similar) ACL on a file
421  */
422 static PyObject *py_smbd_get_sys_acl(PyObject *self, PyObject *args)
423 {
424         char *fname;
425         PyObject *py_acl;
426         struct smb_acl_t *acl;
427         int acl_type;
428         TALLOC_CTX *frame = talloc_stackframe();
429         connection_struct *conn;
430         NTSTATUS status = NT_STATUS_OK;
431
432         if (!PyArg_ParseTuple(args, "si", &fname, &acl_type)) {
433                 TALLOC_FREE(frame);
434                 return NULL;
435         }
436
437         conn = talloc_zero(frame, connection_struct);
438         if (conn == NULL) {
439                 DEBUG(0, ("talloc failed\n"));
440                 PyErr_NoMemory();
441                 TALLOC_FREE(frame);
442                 return NULL;
443         }
444
445         if (!(conn->params = talloc(conn, struct share_params))) {
446                 DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
447                 PyErr_NoMemory();
448                 TALLOC_FREE(frame);
449                 return NULL;
450         }
451
452         conn->params->service = -1;
453
454         set_conn_connectpath(conn, "/");
455
456         smbd_vfs_init(conn);
457
458         acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, acl_type);
459         if (!acl) {
460                 TALLOC_FREE(frame);
461                 status = map_nt_error_from_unix_common(errno);
462                 DEBUG(0,("sys_acl_get_file returned NULL: %s\n", strerror(errno)));
463                 PyErr_NTSTATUS_IS_ERR_RAISE(status);
464         }
465
466         talloc_steal(frame, acl);
467         conn_free(conn);
468
469         py_acl = py_return_ndr_struct("samba.dcerpc.smb_acl", "t", acl, acl);
470
471         TALLOC_FREE(frame);
472
473         return py_acl;
474 }
475
476 static PyMethodDef py_smbd_methods[] = {
477         { "have_posix_acls",
478                 (PyCFunction)py_smbd_have_posix_acls, METH_VARARGS,
479                 NULL },
480         { "set_simple_acl",
481                 (PyCFunction)py_smbd_set_simple_acl, METH_VARARGS,
482                 NULL },
483         { "set_nt_acl",
484                 (PyCFunction)py_smbd_set_nt_acl, METH_VARARGS,
485                 NULL },
486         { "get_nt_acl",
487                 (PyCFunction)py_smbd_get_nt_acl, METH_VARARGS,
488                 NULL },
489         { "get_sys_acl",
490                 (PyCFunction)py_smbd_get_sys_acl, METH_VARARGS,
491                 NULL },
492         { "set_sys_acl",
493                 (PyCFunction)py_smbd_set_sys_acl, METH_VARARGS,
494                 NULL },
495         { "chown",
496                 (PyCFunction)py_smbd_chown, METH_VARARGS,
497                 NULL },
498         { NULL }
499 };
500
501 void initsmbd(void);
502 void initsmbd(void)
503 {
504         PyObject *m;
505
506         m = Py_InitModule3("smbd", py_smbd_methods,
507                            "Python bindings for the smbd file server.");
508         if (m == NULL)
509                 return;
510
511 }