s4-provision: Give better clues on what Samba needs for s3fs ACL support
[obnox/samba/samba-obnox.git] / source3 / smbd / pysmbd.c
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
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include <Python.h>
25 #include "libcli/util/pyerrors.h"
26
27 extern const struct generic_mapping file_generic_mapping;
28
29 #undef  DBGC_CLASS
30 #define DBGC_CLASS DBGC_ACLS
31
32 static NTSTATUS set_sys_acl_no_snum(const char *fname,
33                                      SMB_ACL_TYPE_T acltype,
34                                      SMB_ACL_T theacl)
35 {
36         connection_struct *conn;
37         NTSTATUS status = NT_STATUS_OK;
38         int ret;
39
40         conn = talloc_zero(NULL, connection_struct);
41         if (conn == NULL) {
42                 DEBUG(0, ("talloc failed\n"));
43                 return NT_STATUS_NO_MEMORY;
44         }
45
46         if (!(conn->params = talloc(conn, struct share_params))) {
47                 DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
48                 TALLOC_FREE(conn);
49                 return NT_STATUS_NO_MEMORY;
50         }
51
52         conn->params->service = -1;
53
54         set_conn_connectpath(conn, "/");
55
56         smbd_vfs_init(conn);
57
58         ret = SMB_VFS_SYS_ACL_SET_FILE( conn, fname, acltype, theacl);
59         if (ret != 0) {
60                 status = map_nt_error_from_unix_common(ret);
61                 DEBUG(0,("get_nt_acl_no_snum: fset_nt_acl returned zero.\n"));
62         }
63
64         conn_free(conn);
65
66         return status;
67 }
68
69
70 static SMB_ACL_T make_simple_acl(uid_t uid, gid_t gid)
71 {
72         mode_t mode = SMB_ACL_READ|SMB_ACL_WRITE;
73         mode_t mode0 = 0;
74
75         SMB_ACL_ENTRY_T entry;
76         SMB_ACL_T acl = sys_acl_init(4);
77
78         if (!acl) {
79                 return NULL;
80         }
81
82         if (sys_acl_create_entry(&acl, &entry) != 0) {
83                 sys_acl_free_acl(acl);
84                 return NULL;
85         }
86
87         if (sys_acl_set_tag_type(entry, SMB_ACL_USER_OBJ) != 0) {
88                 sys_acl_free_acl(acl);
89                 return NULL;
90         }
91
92         if (sys_acl_set_permset(entry, &mode) != 0) {
93                 sys_acl_free_acl(acl);
94                 return NULL;
95         }
96
97         if (sys_acl_create_entry(&acl, &entry) != 0) {
98                 sys_acl_free_acl(acl);
99                 return NULL;
100         }
101
102         if (sys_acl_set_tag_type(entry, SMB_ACL_GROUP_OBJ) != 0) {
103                 sys_acl_free_acl(acl);
104                 return NULL;
105         }
106
107         if (sys_acl_set_permset(entry, &mode) != 0) {
108                 sys_acl_free_acl(acl);
109                 return NULL;
110         }
111
112         if (sys_acl_create_entry(&acl, &entry) != 0) {
113                 sys_acl_free_acl(acl);
114                 return NULL;
115         }
116
117         if (sys_acl_set_tag_type(entry, SMB_ACL_OTHER) != 0) {
118                 sys_acl_free_acl(acl);
119                 return NULL;
120         }
121
122         if (sys_acl_set_permset(entry, &mode0) != 0) {
123                 sys_acl_free_acl(acl);
124                 return NULL;
125         }
126
127         if (sys_acl_create_entry(&acl, &entry) != 0) {
128                 sys_acl_free_acl(acl);
129                 return NULL;
130         }
131
132         if (sys_acl_set_tag_type(entry, SMB_ACL_GROUP) != 0) {
133                 sys_acl_free_acl(acl);
134                 return NULL;
135         }
136
137         if (sys_acl_set_qualifier(entry, &gid) != 0) {
138                 sys_acl_free_acl(acl);
139                 return NULL;
140         }
141
142         if (sys_acl_set_permset(entry, &mode) != 0) {
143                 sys_acl_free_acl(acl);
144                 return NULL;
145         }
146
147         if (sys_acl_create_entry(&acl, &entry) != 0) {
148                 sys_acl_free_acl(acl);
149                 return NULL;
150         }
151
152         if (sys_acl_set_tag_type(entry, SMB_ACL_MASK) != 0) {
153                 sys_acl_free_acl(acl);
154                 return NULL;
155         }
156
157         if (sys_acl_set_permset(entry, &mode0) != 0) {
158                 sys_acl_free_acl(acl);
159                 return NULL;
160         }
161         return acl;
162 }
163
164 /*
165   set a simple ACL on a file, as a test
166  */
167 static PyObject *py_smbd_set_simple_acl(PyObject *self, PyObject *args)
168 {
169         NTSTATUS status;
170         char *fname;
171         int uid, gid;
172         SMB_ACL_T acl;
173
174         if (!PyArg_ParseTuple(args, "sii", &fname, &uid, &gid))
175                 return NULL;
176
177         acl = make_simple_acl(uid, gid);
178
179         status = set_sys_acl_no_snum(fname, SMB_ACL_TYPE_ACCESS, acl);
180         sys_acl_free_acl(acl);
181         PyErr_NTSTATUS_IS_ERR_RAISE(status);
182
183         Py_RETURN_NONE;
184 }
185
186 /*
187   check if we have ACL support
188  */
189 static PyObject *py_smbd_have_posix_acls(PyObject *self, PyObject *args)
190 {
191 #ifdef HAVE_POSIX_ACLS
192         return PyBool_FromLong(true);
193 #else
194         return PyBool_FromLong(false);
195 #endif
196 }
197
198 static PyMethodDef py_smbd_methods[] = {
199         { "have_posix_acls",
200                 (PyCFunction)py_smbd_have_posix_acls, METH_VARARGS,
201                 NULL },
202         { "set_simple_acl",
203                 (PyCFunction)py_smbd_set_simple_acl, METH_VARARGS,
204                 NULL },
205         { NULL }
206 };
207
208 void initsmbd(void);
209 void initsmbd(void)
210 {
211         PyObject *m;
212
213         m = Py_InitModule3("smbd", py_smbd_methods,
214                            "Python bindings for the smbd file server.");
215         if (m == NULL)
216                 return;
217
218 }