Line data Source code
1 : /*
2 : SSSD
3 :
4 : SELinux-related utility functions
5 :
6 : Authors:
7 : Jan Zeleny <jzeleny@redhat.com>
8 :
9 : Copyright (C) 2012 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "util/sss_selinux.h"
26 : #include "util/sss_utf8.h"
27 : #include "db/sysdb_selinux.h"
28 :
29 0 : static bool match_entity(struct ldb_message_element *values,
30 : struct ldb_message_element *sought_values)
31 : {
32 : int i, j;
33 :
34 0 : for (i = 0; i < values->num_values; i++) {
35 0 : for (j = 0; j < sought_values->num_values; j++) {
36 0 : if (values->values[i].length != sought_values->values[j].length) {
37 0 : continue;
38 : }
39 :
40 0 : if (strncasecmp((char *)values->values[i].data,
41 0 : (char *)sought_values->values[j].data,
42 0 : values->values[i].length) == 0)
43 0 : return true;
44 : }
45 : }
46 :
47 0 : return false;
48 : }
49 :
50 0 : bool sss_selinux_match(struct sysdb_attrs *usermap,
51 : struct sysdb_attrs *user,
52 : struct sysdb_attrs *host,
53 : uint32_t *_priority)
54 : {
55 0 : struct ldb_message_element *users_el = NULL;
56 0 : struct ldb_message_element *usercat = NULL;
57 0 : struct ldb_message_element *hosts_el = NULL;
58 0 : struct ldb_message_element *hostcat = NULL;
59 : struct ldb_message_element *dn;
60 : struct ldb_message_element *memberof;
61 : int i;
62 0 : uint32_t priority = 0;
63 : bool matched_name;
64 : bool matched_group;
65 : bool matched_category;
66 : errno_t ret;
67 :
68 0 : if (usermap == NULL) {
69 0 : DEBUG(SSSDBG_MINOR_FAILURE, "NULL given as usermap! Skipping ...\n");
70 0 : return false;
71 : }
72 :
73 : /* Search for user and host related elements */
74 0 : for (i = 0; i < usermap->num; i++) {
75 0 : if (!strcasecmp(usermap->a[i].name, SYSDB_ORIG_MEMBER_USER)) {
76 0 : users_el = &usermap->a[i];
77 0 : } else if (!strcasecmp(usermap->a[i].name, SYSDB_ORIG_MEMBER_HOST)) {
78 0 : hosts_el = &usermap->a[i];
79 0 : } else if (!strcasecmp(usermap->a[i].name, SYSDB_USER_CATEGORY)) {
80 0 : usercat = &usermap->a[i];
81 0 : } else if (!strcasecmp(usermap->a[i].name, SYSDB_HOST_CATEGORY)) {
82 0 : hostcat = &usermap->a[i];
83 : }
84 : }
85 :
86 0 : if (user) {
87 0 : ret = sysdb_attrs_get_el(user, SYSDB_ORIG_DN, &dn);
88 0 : if (ret != EOK) {
89 0 : DEBUG(SSSDBG_MINOR_FAILURE, "User does not have origDN\n");
90 0 : return false;
91 : }
92 0 : ret = sysdb_attrs_get_el(user, SYSDB_ORIG_MEMBEROF, &memberof);
93 0 : if (ret != EOK) {
94 0 : DEBUG(SSSDBG_TRACE_ALL,
95 : "User does not have orig memberof, "
96 : "therefore it can't match to any rule\n");
97 0 : return false;
98 : }
99 :
100 : /**
101 : * The rule won't match if user category != "all" and user map doesn't
102 : * contain neither user nor any of his groups in memberUser attribute
103 : */
104 0 : matched_category = false;
105 0 : if (usercat != NULL) {
106 0 : for (i = 0; i < usercat->num_values; i++) {
107 0 : if (strcasecmp((char *)usercat->values[i].data, "all") == 0) {
108 0 : matched_category = true;
109 0 : break;
110 : }
111 : }
112 : }
113 :
114 0 : if (!matched_category) {
115 0 : if (users_el == NULL) {
116 0 : DEBUG(SSSDBG_TRACE_ALL, "No users specified in the rule!\n");
117 0 : return false;
118 : } else {
119 0 : matched_name = match_entity(users_el, dn);
120 0 : matched_group = match_entity(users_el, memberof);
121 0 : if (matched_name) {
122 0 : priority |= SELINUX_PRIORITY_USER_NAME;
123 0 : } else if (matched_group) {
124 0 : priority |= SELINUX_PRIORITY_USER_GROUP;
125 : } else {
126 0 : DEBUG(SSSDBG_TRACE_ALL, "User did not match\n");
127 0 : return false;
128 : }
129 : }
130 : } else {
131 0 : priority |= SELINUX_PRIORITY_USER_CAT;
132 : }
133 : }
134 :
135 0 : if (host) {
136 0 : ret = sysdb_attrs_get_el(host, SYSDB_ORIG_DN, &dn);
137 0 : if (ret != EOK) {
138 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Host does not have origDN\n");
139 0 : return false;
140 : }
141 0 : ret = sysdb_attrs_get_el(host, SYSDB_ORIG_MEMBEROF, &memberof);
142 0 : if (ret != EOK) {
143 0 : DEBUG(SSSDBG_TRACE_ALL,
144 : "Host does not have orig memberof, "
145 : "therefore it can't match to any rule\n");
146 0 : return false;
147 : }
148 :
149 : /**
150 : * The rule won't match if host category != "all" and user map doesn't
151 : * contain neither host nor any of its groups in memberHost attribute
152 : */
153 0 : matched_category = false;
154 0 : if (hostcat != NULL) {
155 0 : for (i = 0; i < hostcat->num_values; i++) {
156 0 : if (strcasecmp((char *)hostcat->values[i].data, "all") == 0) {
157 0 : matched_category = true;
158 0 : break;
159 : }
160 : }
161 : }
162 0 : if (!matched_category) {
163 0 : if (hosts_el == NULL) {
164 0 : DEBUG(SSSDBG_TRACE_ALL, "No users specified in the rule!\n");
165 0 : return false;
166 : } else {
167 0 : matched_name = match_entity(hosts_el, dn);
168 0 : matched_group = match_entity(hosts_el, memberof);
169 0 : if (matched_name) {
170 0 : priority |= SELINUX_PRIORITY_HOST_NAME;
171 0 : } else if (matched_group) {
172 0 : priority |= SELINUX_PRIORITY_HOST_GROUP;
173 : } else {
174 0 : DEBUG(SSSDBG_TRACE_ALL, "Host did not match\n");
175 0 : return false;
176 : }
177 : }
178 : } else {
179 0 : priority |= SELINUX_PRIORITY_HOST_CAT;
180 : }
181 : }
182 :
183 0 : if (_priority != NULL) {
184 0 : *_priority = priority;
185 : }
186 :
187 0 : return true;
188 : }
189 :
190 0 : errno_t sss_selinux_extract_user(TALLOC_CTX *mem_ctx,
191 : struct sss_domain_info *domain,
192 : const char *username,
193 : struct sysdb_attrs **_user_attrs)
194 : {
195 : TALLOC_CTX *tmp_ctx;
196 : const char **attrs;
197 : struct sysdb_attrs *user_attrs;
198 : struct ldb_message *user_msg;
199 :
200 : errno_t ret;
201 :
202 0 : tmp_ctx = talloc_new(NULL);
203 0 : if (tmp_ctx == NULL) {
204 0 : ret = ENOMEM;
205 0 : goto done;
206 : }
207 :
208 0 : attrs = talloc_array(tmp_ctx, const char *, 3);
209 0 : if (attrs == NULL) {
210 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_array failed.\n");
211 0 : ret = ENOMEM;
212 0 : goto done;
213 : }
214 0 : attrs[0] = SYSDB_ORIG_DN;
215 0 : attrs[1] = SYSDB_ORIG_MEMBEROF;
216 0 : attrs[2] = NULL;
217 :
218 0 : ret = sysdb_search_user_by_name(tmp_ctx, domain, username, attrs,
219 : &user_msg);
220 0 : if (ret != EOK) {
221 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_name failed.\n");
222 0 : goto done;
223 : }
224 :
225 0 : user_attrs = talloc_zero(tmp_ctx, struct sysdb_attrs);
226 0 : if (user_attrs == NULL) {
227 0 : ret = ENOMEM;
228 0 : goto done;
229 : }
230 0 : user_attrs->a = talloc_steal(user_attrs, user_msg->elements);
231 0 : user_attrs->num = user_msg->num_elements;
232 :
233 0 : *_user_attrs = talloc_steal(mem_ctx, user_attrs);
234 0 : ret = EOK;
235 :
236 : done:
237 0 : talloc_free(tmp_ctx);
238 0 : return ret;
239 : }
240 :
241 0 : const char *sss_selinux_map_get_seuser(struct sysdb_attrs *usermap)
242 : {
243 : int i;
244 : const uint8_t *name;
245 0 : const uint8_t *template = (const uint8_t *)SYSDB_SELINUX_USER;
246 :
247 0 : for (i = 0; i < usermap->num; i++) {
248 0 : name = (const uint8_t *)usermap->a[i].name;
249 0 : if (sss_utf8_case_eq(name, template) == 0) {
250 0 : return (const char *)usermap->a[i].values[0].data;
251 : }
252 : }
253 :
254 0 : return NULL;
255 : }
|