s3-pysmbd: Add set_nt_acl() function based on parts of vfstest
[Samba.git] / source3 / smbd / pysmbd.c
blob647831975628cf958af3bd684357026ec3d44663
1 /*
2 Unix SMB/CIFS implementation.
3 SMB NT Security Descriptor / Unix permission conversion.
4 Copyright (C) Jeremy Allison 1994-2009.
5 Copyright (C) Andreas Gruenbacher 2002.
6 Copyright (C) Simo Sorce <idra@samba.org> 2009.
7 Copyright (C) Simo Sorce 2002
8 Copyright (C) Eric Lorimer 2002
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "smbd/smbd.h"
26 #include <Python.h>
27 #include "libcli/util/pyerrors.h"
28 #include "librpc/rpc/pyrpc_util.h"
29 #include <pytalloc.h>
30 #include "system/filesys.h"
32 extern const struct generic_mapping file_generic_mapping;
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_ACLS
37 static NTSTATUS set_sys_acl_no_snum(const char *fname,
38 SMB_ACL_TYPE_T acltype,
39 SMB_ACL_T theacl)
41 connection_struct *conn;
42 NTSTATUS status = NT_STATUS_OK;
43 int ret;
45 conn = talloc_zero(NULL, connection_struct);
46 if (conn == NULL) {
47 DEBUG(0, ("talloc failed\n"));
48 return NT_STATUS_NO_MEMORY;
51 if (!(conn->params = talloc(conn, struct share_params))) {
52 DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
53 TALLOC_FREE(conn);
54 return NT_STATUS_NO_MEMORY;
57 conn->params->service = -1;
59 set_conn_connectpath(conn, "/");
61 smbd_vfs_init(conn);
63 ret = SMB_VFS_SYS_ACL_SET_FILE( conn, fname, acltype, theacl);
64 if (ret != 0) {
65 status = map_nt_error_from_unix_common(ret);
66 DEBUG(0,("get_nt_acl_no_snum: fset_nt_acl returned zero.\n"));
69 conn_free(conn);
71 return status;
74 static NTSTATUS set_nt_acl_no_snum(const char *fname,
75 uint32 security_info_sent, const struct security_descriptor *sd)
77 TALLOC_CTX *frame = talloc_stackframe();
78 connection_struct *conn;
79 NTSTATUS status = NT_STATUS_OK;
80 files_struct *fsp;
81 struct smb_filename *smb_fname = NULL;
82 int flags;
84 conn = talloc_zero(frame, connection_struct);
85 if (conn == NULL) {
86 DEBUG(0, ("talloc failed\n"));
87 return NT_STATUS_NO_MEMORY;
90 if (!(conn->params = talloc(conn, struct share_params))) {
91 DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
92 TALLOC_FREE(frame);
93 return NT_STATUS_NO_MEMORY;
96 conn->params->service = -1;
98 set_conn_connectpath(conn, "/");
100 smbd_vfs_init(conn);
102 fsp = talloc(frame, struct files_struct);
103 if (fsp == NULL) {
104 TALLOC_FREE(frame);
105 return NT_STATUS_NO_MEMORY;
107 fsp->fh = talloc(fsp, struct fd_handle);
108 if (fsp->fh == NULL) {
109 TALLOC_FREE(frame);
110 return NT_STATUS_NO_MEMORY;
112 fsp->conn = conn;
114 status = create_synthetic_smb_fname_split(fsp, fname, NULL,
115 &smb_fname);
116 if (!NT_STATUS_IS_OK(status)) {
117 TALLOC_FREE(frame);
118 return status;
121 fsp->fsp_name = smb_fname;
123 #ifdef O_DIRECTORY
124 flags = O_RDONLY|O_DIRECTORY;
125 #else
126 /* POSIX allows us to open a directory with O_RDONLY. */
127 flags = O_RDONLY;
128 #endif
130 fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, 00400);
131 if (fsp->fh->fd == -1 && errno == EISDIR) {
132 fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, O_RDWR, 00400);
134 if (fsp->fh->fd == -1) {
135 printf("open: error=%d (%s)\n", errno, strerror(errno));
136 TALLOC_FREE(frame);
137 return NT_STATUS_UNSUCCESSFUL;
140 status = SMB_VFS_FSET_NT_ACL( fsp, security_info_sent, sd);
141 if (!NT_STATUS_IS_OK(status)) {
142 DEBUG(0,("set_nt_acl_no_snum: fset_nt_acl returned %s.\n", nt_errstr(status)));
145 conn_free(conn);
146 TALLOC_FREE(frame);
148 return status;
152 static SMB_ACL_T make_simple_acl(uid_t uid, gid_t gid)
154 mode_t mode = SMB_ACL_READ|SMB_ACL_WRITE;
155 mode_t mode0 = 0;
157 SMB_ACL_ENTRY_T entry;
158 SMB_ACL_T acl = sys_acl_init(4);
160 if (!acl) {
161 return NULL;
164 if (sys_acl_create_entry(&acl, &entry) != 0) {
165 sys_acl_free_acl(acl);
166 return NULL;
169 if (sys_acl_set_tag_type(entry, SMB_ACL_USER_OBJ) != 0) {
170 sys_acl_free_acl(acl);
171 return NULL;
174 if (sys_acl_set_permset(entry, &mode) != 0) {
175 sys_acl_free_acl(acl);
176 return NULL;
179 if (sys_acl_create_entry(&acl, &entry) != 0) {
180 sys_acl_free_acl(acl);
181 return NULL;
184 if (sys_acl_set_tag_type(entry, SMB_ACL_GROUP_OBJ) != 0) {
185 sys_acl_free_acl(acl);
186 return NULL;
189 if (sys_acl_set_permset(entry, &mode) != 0) {
190 sys_acl_free_acl(acl);
191 return NULL;
194 if (sys_acl_create_entry(&acl, &entry) != 0) {
195 sys_acl_free_acl(acl);
196 return NULL;
199 if (sys_acl_set_tag_type(entry, SMB_ACL_OTHER) != 0) {
200 sys_acl_free_acl(acl);
201 return NULL;
204 if (sys_acl_set_permset(entry, &mode0) != 0) {
205 sys_acl_free_acl(acl);
206 return NULL;
209 if (sys_acl_create_entry(&acl, &entry) != 0) {
210 sys_acl_free_acl(acl);
211 return NULL;
214 if (sys_acl_set_tag_type(entry, SMB_ACL_GROUP) != 0) {
215 sys_acl_free_acl(acl);
216 return NULL;
219 if (sys_acl_set_qualifier(entry, &gid) != 0) {
220 sys_acl_free_acl(acl);
221 return NULL;
224 if (sys_acl_set_permset(entry, &mode) != 0) {
225 sys_acl_free_acl(acl);
226 return NULL;
229 if (sys_acl_create_entry(&acl, &entry) != 0) {
230 sys_acl_free_acl(acl);
231 return NULL;
234 if (sys_acl_set_tag_type(entry, SMB_ACL_MASK) != 0) {
235 sys_acl_free_acl(acl);
236 return NULL;
239 if (sys_acl_set_permset(entry, &mode0) != 0) {
240 sys_acl_free_acl(acl);
241 return NULL;
243 return acl;
247 set a simple ACL on a file, as a test
249 static PyObject *py_smbd_set_simple_acl(PyObject *self, PyObject *args)
251 NTSTATUS status;
252 char *fname;
253 int uid, gid;
254 SMB_ACL_T acl;
256 if (!PyArg_ParseTuple(args, "sii", &fname, &uid, &gid))
257 return NULL;
259 acl = make_simple_acl(uid, gid);
261 status = set_sys_acl_no_snum(fname, SMB_ACL_TYPE_ACCESS, acl);
262 sys_acl_free_acl(acl);
263 PyErr_NTSTATUS_IS_ERR_RAISE(status);
265 Py_RETURN_NONE;
269 check if we have ACL support
271 static PyObject *py_smbd_have_posix_acls(PyObject *self, PyObject *args)
273 #ifdef HAVE_POSIX_ACLS
274 return PyBool_FromLong(true);
275 #else
276 return PyBool_FromLong(false);
277 #endif
281 set a simple ACL on a file, as a test
283 static PyObject *py_smbd_set_nt_acl(PyObject *self, PyObject *args)
285 NTSTATUS status;
286 char *fname;
287 int security_info_sent;
288 PyObject *py_sd;
289 struct security_descriptor *sd;
291 if (!PyArg_ParseTuple(args, "siO", &fname, &security_info_sent, &py_sd))
292 return NULL;
294 if (!py_check_dcerpc_type(py_sd, "samba.dcerpc.security", "descriptor")) {
295 return NULL;
298 sd = pytalloc_get_type(py_sd, struct security_descriptor);
300 status = set_nt_acl_no_snum(fname, security_info_sent, sd);
301 PyErr_NTSTATUS_IS_ERR_RAISE(status);
303 Py_RETURN_NONE;
306 static PyMethodDef py_smbd_methods[] = {
307 { "have_posix_acls",
308 (PyCFunction)py_smbd_have_posix_acls, METH_VARARGS,
309 NULL },
310 { "set_simple_acl",
311 (PyCFunction)py_smbd_set_simple_acl, METH_VARARGS,
312 NULL },
313 { "set_nt_acl",
314 (PyCFunction)py_smbd_set_nt_acl, METH_VARARGS,
315 NULL },
316 { NULL }
319 void initsmbd(void);
320 void initsmbd(void)
322 PyObject *m;
324 m = Py_InitModule3("smbd", py_smbd_methods,
325 "Python bindings for the smbd file server.");
326 if (m == NULL)
327 return;