Line data Source code
1 : /*
2 : SSSD
3 :
4 : System Database - SELinux support
5 :
6 : Copyright (C) Jan Zeleny <jzeleny@redhat.com> 2012
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 "util/sss_selinux.h"
23 : #include "db/sysdb_selinux.h"
24 : #include "db/sysdb_private.h"
25 :
26 : /* Some generic routines */
27 : enum selinux_entity_type {
28 : SELINUX_CONFIG,
29 : SELINUX_USER_MAP
30 : };
31 :
32 : static errno_t
33 0 : sysdb_add_selinux_entity(struct sysdb_ctx *sysdb,
34 : struct ldb_dn *dn,
35 : const char *objectclass,
36 : struct sysdb_attrs *attrs,
37 : time_t now)
38 : {
39 : struct ldb_message *msg;
40 : TALLOC_CTX *tmp_ctx;
41 : errno_t ret;
42 :
43 0 : tmp_ctx = talloc_new(NULL);
44 0 : if (!tmp_ctx) {
45 0 : return ENOMEM;
46 : }
47 :
48 0 : msg = ldb_msg_new(tmp_ctx);
49 0 : if (!msg) {
50 0 : ret = ENOMEM;
51 0 : goto done;
52 : }
53 :
54 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, objectclass);
55 0 : if (ret != EOK) {
56 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not set map object class [%d]: %s\n",
57 : ret, strerror(ret));
58 0 : return ret;
59 : }
60 :
61 0 : if (!now) {
62 0 : now = time(NULL);
63 : }
64 :
65 0 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_CREATE_TIME, now);
66 0 : if (ret) goto done;
67 :
68 0 : msg->dn = dn;
69 0 : msg->elements = attrs->a;
70 0 : msg->num_elements = attrs->num;
71 :
72 0 : ret = ldb_add(sysdb->ldb, msg);
73 0 : ret = sysdb_error_to_errno(ret);
74 :
75 : done:
76 0 : if (ret) {
77 0 : DEBUG(SSSDBG_TRACE_LIBS, "Error: %d (%s)\n", ret, strerror(ret));
78 : }
79 0 : talloc_zfree(tmp_ctx);
80 0 : return ret;
81 : }
82 :
83 0 : static errno_t sysdb_store_selinux_entity(struct sss_domain_info *domain,
84 : struct sysdb_attrs *attrs,
85 : enum selinux_entity_type type)
86 : {
87 : TALLOC_CTX *tmp_ctx;
88 0 : bool in_transaction = false;
89 0 : const char *objectclass = NULL;
90 : const char *name;
91 : char *clean_name;
92 0 : struct ldb_dn *dn = NULL;
93 0 : errno_t sret = EOK;
94 : errno_t ret;
95 : time_t now;
96 0 : struct sysdb_ctx *sysdb = domain->sysdb;
97 :
98 0 : tmp_ctx = talloc_new(NULL);
99 0 : if (!tmp_ctx) {
100 0 : return ENOMEM;
101 : }
102 :
103 0 : switch (type) {
104 : case SELINUX_USER_MAP:
105 0 : objectclass = SYSDB_SELINUX_USERMAP_CLASS;
106 0 : ret = sysdb_attrs_get_string(attrs, SYSDB_NAME, &name);
107 0 : if (ret != EOK) {
108 0 : goto done;
109 : }
110 :
111 0 : ret = sysdb_dn_sanitize(tmp_ctx, name, &clean_name);
112 0 : if (ret != EOK) {
113 0 : goto done;
114 : }
115 :
116 0 : dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_SEUSERMAP,
117 : clean_name, domain->name);
118 0 : break;
119 : case SELINUX_CONFIG:
120 0 : objectclass = SYSDB_SELINUX_CLASS;
121 0 : dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_SELINUX_BASE,
122 : domain->name);
123 0 : break;
124 : }
125 :
126 0 : if (type != SELINUX_CONFIG && type != SELINUX_USER_MAP) {
127 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Bad SELinux entity type: [%d]\n", type);
128 0 : ret = EINVAL;
129 0 : goto done;
130 : }
131 :
132 0 : if (!dn) {
133 0 : ret = ENOMEM;
134 0 : goto done;
135 : }
136 :
137 0 : ret = sysdb_transaction_start(sysdb);
138 0 : if (ret != EOK) {
139 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n");
140 0 : goto done;
141 : }
142 :
143 0 : in_transaction = true;
144 :
145 0 : now = time(NULL);
146 0 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
147 0 : if (ret) goto done;
148 :
149 0 : ret = sysdb_add_selinux_entity(sysdb, dn, objectclass, attrs, now);
150 0 : if (ret != EOK) {
151 0 : goto done;
152 : }
153 :
154 0 : ret = sysdb_set_entry_attr(sysdb, dn, attrs, SYSDB_MOD_REP);
155 0 : if (ret != EOK) {
156 0 : goto done;
157 : }
158 :
159 0 : ret = sysdb_transaction_commit(sysdb);
160 0 : if (ret != EOK) {
161 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
162 0 : goto done;
163 : }
164 0 : in_transaction = false;
165 :
166 : done:
167 0 : if (in_transaction) {
168 0 : sret = sysdb_transaction_cancel(sysdb);
169 0 : if (sret != EOK) {
170 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
171 : }
172 : }
173 :
174 0 : if (ret) {
175 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Error: %d (%s)\n", ret, strerror(ret));
176 : }
177 0 : talloc_zfree(tmp_ctx);
178 0 : return ret;
179 : }
180 :
181 0 : errno_t sysdb_store_selinux_usermap(struct sss_domain_info *domain,
182 : struct sysdb_attrs *attrs)
183 : {
184 0 : return sysdb_store_selinux_entity(domain, attrs, SELINUX_USER_MAP);
185 : }
186 :
187 0 : errno_t sysdb_store_selinux_config(struct sss_domain_info *domain,
188 : const char *default_user,
189 : const char *order)
190 : {
191 : errno_t ret;
192 : struct sysdb_attrs *attrs;
193 :
194 0 : attrs = talloc_zero(NULL, struct sysdb_attrs);
195 0 : if (attrs == NULL) {
196 0 : return ENOMEM;
197 : }
198 :
199 0 : if (!order) {
200 0 : DEBUG(SSSDBG_CRIT_FAILURE, "The SELinux order is missing\n");
201 0 : return EINVAL;
202 : }
203 :
204 0 : if (default_user) {
205 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_SELINUX_DEFAULT_USER,
206 : default_user);
207 0 : if (ret != EOK) {
208 0 : goto done;
209 : }
210 : }
211 :
212 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_SELINUX_DEFAULT_ORDER,
213 : order);
214 0 : if (ret != EOK) {
215 0 : goto done;
216 : }
217 :
218 0 : ret = sysdb_store_selinux_entity(domain, attrs, SELINUX_CONFIG);
219 : done:
220 0 : talloc_free(attrs);
221 0 : return ret;
222 : }
223 :
224 0 : errno_t sysdb_delete_usermaps(struct sss_domain_info *domain)
225 : {
226 0 : struct ldb_dn *dn = NULL;
227 : errno_t ret;
228 0 : struct sysdb_ctx *sysdb = domain->sysdb;
229 :
230 0 : dn = ldb_dn_new_fmt(sysdb, sysdb->ldb,
231 : SYSDB_TMPL_SELINUX_BASE, domain->name);
232 0 : if (!dn) return ENOMEM;
233 :
234 0 : ret = sysdb_delete_recursive(sysdb, dn, true);
235 0 : talloc_free(dn);
236 0 : if (ret != EOK) {
237 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_delete_recursive failed.\n");
238 0 : return ret;
239 : }
240 :
241 0 : return EOK;
242 : }
243 :
244 : /* --- SYSDB SELinux search routines --- */
245 : errno_t
246 0 : sysdb_get_selinux_usermaps(TALLOC_CTX *mem_ctx,
247 : struct sss_domain_info *domain,
248 : const char **attrs,
249 : size_t *count,
250 : struct ldb_message ***messages)
251 : {
252 : errno_t ret;
253 : char *filter;
254 : struct ldb_dn *basedn;
255 0 : struct sysdb_ctx *sysdb = domain->sysdb;
256 :
257 0 : basedn = ldb_dn_new_fmt(mem_ctx, sysdb_ctx_get_ldb(sysdb),
258 : SYSDB_TMPL_SELINUX_BASE, domain->name);
259 0 : if (!basedn) {
260 0 : return ENOMEM;
261 : }
262 :
263 0 : filter = talloc_asprintf(mem_ctx, "(%s=%s)",
264 : SYSDB_OBJECTCLASS, SYSDB_SELINUX_USERMAP_CLASS);
265 0 : if (filter == NULL) {
266 0 : talloc_free(basedn);
267 0 : return ENOMEM;
268 : }
269 :
270 0 : ret = sysdb_search_entry(mem_ctx, sysdb, basedn, LDB_SCOPE_SUBTREE, filter,
271 : attrs, count, messages);
272 0 : talloc_free(basedn);
273 0 : talloc_free(filter);
274 0 : if (ret == ENOENT) {
275 0 : *count = 0;
276 0 : *messages = NULL;
277 0 : } else if (ret) {
278 0 : return ret;
279 : }
280 :
281 0 : return EOK;
282 : }
283 :
284 0 : errno_t sysdb_search_selinux_config(TALLOC_CTX *mem_ctx,
285 : struct sss_domain_info *domain,
286 : const char **attrs,
287 : struct ldb_message **_config)
288 : {
289 : TALLOC_CTX *tmp_ctx;
290 0 : const char *def_attrs[] = { SYSDB_SELINUX_DEFAULT_USER,
291 : SYSDB_SELINUX_DEFAULT_ORDER,
292 : NULL };
293 : struct ldb_message **msgs;
294 : size_t msgs_count;
295 : struct ldb_dn *basedn;
296 : errno_t ret;
297 :
298 0 : tmp_ctx = talloc_new(NULL);
299 0 : if (!tmp_ctx) {
300 0 : return ENOMEM;
301 : }
302 :
303 0 : basedn = ldb_dn_new_fmt(tmp_ctx, domain->sysdb->ldb,
304 : SYSDB_TMPL_SELINUX_BASE, domain->name);
305 0 : if (!basedn) {
306 0 : ret = ENOMEM;
307 0 : goto done;
308 : }
309 :
310 0 : ret = sysdb_search_entry(tmp_ctx, domain->sysdb, basedn, LDB_SCOPE_BASE,
311 : NULL, attrs?attrs:def_attrs, &msgs_count, &msgs);
312 0 : if (ret) {
313 0 : goto done;
314 : }
315 :
316 0 : *_config = talloc_steal(mem_ctx, msgs[0]);
317 :
318 : done:
319 0 : if (ret == ENOENT) {
320 0 : DEBUG(SSSDBG_TRACE_FUNC, "No SELinux root entry found\n");
321 0 : } else if (ret) {
322 0 : DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, strerror(ret));
323 : }
324 :
325 0 : talloc_free(tmp_ctx);
326 0 : return ret;
327 : }
328 :
|