]> git.ipfire.org Git - people/pmueller/ipfire-3.x.git/blob - openssh/patches/openssh-5.9p1-mls.patch
Merge remote-tracking branch 'maniacikarus/ids'
[people/pmueller/ipfire-3.x.git] / openssh / patches / openssh-5.9p1-mls.patch
1 diff -up openssh-5.9p0/misc.c.mls openssh-5.9p0/misc.c
2 --- openssh-5.9p0/misc.c.mls 2011-05-05 06:14:34.000000000 +0200
3 +++ openssh-5.9p0/misc.c 2011-08-30 12:29:29.157087474 +0200
4 @@ -427,6 +427,7 @@ char *
5 colon(char *cp)
6 {
7 int flag = 0;
8 + int start = 1;
9
10 if (*cp == ':') /* Leading colon is part of file name. */
11 return NULL;
12 @@ -442,6 +443,13 @@ colon(char *cp)
13 return (cp);
14 if (*cp == '/')
15 return NULL;
16 + if (start) {
17 + /* Slash on beginning or after dots only denotes file name. */
18 + if (*cp == '/')
19 + return (0);
20 + if (*cp != '.')
21 + start = 0;
22 + }
23 }
24 return NULL;
25 }
26 diff -up openssh-5.9p0/openbsd-compat/port-linux.c.mls openssh-5.9p0/openbsd-compat/port-linux.c
27 --- openssh-5.9p0/openbsd-compat/port-linux.c.mls 2011-08-30 12:29:28.873086987 +0200
28 +++ openssh-5.9p0/openbsd-compat/port-linux.c 2011-08-30 13:28:12.584149668 +0200
29 @@ -40,7 +40,15 @@
30 #ifdef WITH_SELINUX
31 #include <selinux/selinux.h>
32 #include <selinux/flask.h>
33 +#include <selinux/context.h>
34 #include <selinux/get_context_list.h>
35 +#include <selinux/get_default_type.h>
36 +#include <selinux/av_permissions.h>
37 +
38 +#ifdef HAVE_LINUX_AUDIT
39 +#include <libaudit.h>
40 +#include <unistd.h>
41 +#endif
42
43 #ifndef SSH_SELINUX_UNCONFINED_TYPE
44 # define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:"
45 @@ -51,6 +59,149 @@ extern Authctxt *the_authctxt;
46 extern int inetd_flag;
47 extern int rexeced_flag;
48
49 +/* Send audit message */
50 +static int
51 +send_audit_message(int success, security_context_t default_context,
52 + security_context_t selected_context)
53 +{
54 + int rc=0;
55 +#ifdef HAVE_LINUX_AUDIT
56 + char *msg = NULL;
57 + int audit_fd = audit_open();
58 + security_context_t default_raw=NULL;
59 + security_context_t selected_raw=NULL;
60 + rc = -1;
61 + if (audit_fd < 0) {
62 + if (errno == EINVAL || errno == EPROTONOSUPPORT ||
63 + errno == EAFNOSUPPORT)
64 + return 0; /* No audit support in kernel */
65 + error("Error connecting to audit system.");
66 + return rc;
67 + }
68 + if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
69 + error("Error translating default context.");
70 + default_raw = NULL;
71 + }
72 + if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
73 + error("Error translating selected context.");
74 + selected_raw = NULL;
75 + }
76 + if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
77 + default_raw ? default_raw : (default_context ? default_context: "?"),
78 + selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
79 + error("Error allocating memory.");
80 + goto out;
81 + }
82 + if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
83 + msg, NULL, NULL, NULL, success) <= 0) {
84 + error("Error sending audit message.");
85 + goto out;
86 + }
87 + rc = 0;
88 + out:
89 + free(msg);
90 + freecon(default_raw);
91 + freecon(selected_raw);
92 + close(audit_fd);
93 +#endif
94 + return rc;
95 +}
96 +
97 +static int
98 +mls_range_allowed(security_context_t src, security_context_t dst)
99 +{
100 + struct av_decision avd;
101 + int retval;
102 + unsigned int bit = CONTEXT__CONTAINS;
103 +
104 + debug("%s: src:%s dst:%s", __func__, src, dst);
105 + retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
106 + if (retval || ((bit & avd.allowed) != bit))
107 + return 0;
108 +
109 + return 1;
110 +}
111 +
112 +static int
113 +get_user_context(const char *sename, const char *role, const char *lvl,
114 + security_context_t *sc) {
115 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
116 + if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
117 + /* User may have requested a level completely outside of his
118 + allowed range. We get a context just for auditing as the
119 + range check below will certainly fail for default context. */
120 +#endif
121 + if (get_default_context(sename, NULL, sc) != 0) {
122 + *sc = NULL;
123 + return -1;
124 + }
125 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
126 + }
127 +#endif
128 + if (role != NULL && role[0]) {
129 + context_t con;
130 + char *type=NULL;
131 + if (get_default_type(role, &type) != 0) {
132 + error("get_default_type: failed to get default type for '%s'",
133 + role);
134 + goto out;
135 + }
136 + con = context_new(*sc);
137 + if (!con) {
138 + goto out;
139 + }
140 + context_role_set(con, role);
141 + context_type_set(con, type);
142 + freecon(*sc);
143 + *sc = strdup(context_str(con));
144 + context_free(con);
145 + if (!*sc)
146 + return -1;
147 + }
148 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
149 + if (lvl != NULL && lvl[0]) {
150 + /* verify that the requested range is obtained */
151 + context_t con;
152 + security_context_t obtained_raw;
153 + security_context_t requested_raw;
154 + con = context_new(*sc);
155 + if (!con) {
156 + goto out;
157 + }
158 + context_range_set(con, lvl);
159 + if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
160 + context_free(con);
161 + goto out;
162 + }
163 + if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
164 + freecon(obtained_raw);
165 + context_free(con);
166 + goto out;
167 + }
168 +
169 + debug("get_user_context: obtained context '%s' requested context '%s'",
170 + obtained_raw, requested_raw);
171 + if (strcmp(obtained_raw, requested_raw)) {
172 + /* set the context to the real requested one but fail */
173 + freecon(requested_raw);
174 + freecon(obtained_raw);
175 + freecon(*sc);
176 + *sc = strdup(context_str(con));
177 + context_free(con);
178 + return -1;
179 + }
180 + freecon(requested_raw);
181 + freecon(obtained_raw);
182 + context_free(con);
183 + }
184 +#endif
185 + return 0;
186 + out:
187 + freecon(*sc);
188 + *sc = NULL;
189 + return -1;
190 +}
191 +
192 static void
193 ssh_selinux_get_role_level(char **role, const char **level)
194 {
195 @@ -69,14 +220,15 @@ ssh_selinux_get_role_level(char **role,
196 }
197
198 /* Return the default security context for the given username */
199 -static security_context_t
200 -ssh_selinux_getctxbyname(char *pwname)
201 +static int
202 +ssh_selinux_getctxbyname(char *pwname,
203 + security_context_t *default_sc, security_context_t *user_sc)
204 {
205 - security_context_t sc = NULL;
206 char *sename, *lvl;
207 char *role;
208 const char *reqlvl;
209 int r = 0;
210 + context_t con = NULL;
211
212 ssh_selinux_get_role_level(&role, &reqlvl);
213
214 @@ -87,37 +239,62 @@ ssh_selinux_getctxbyname(char *pwname)
215 }
216 #else
217 sename = pwname;
218 - lvl = NULL;
219 + lvl = "";
220 #endif
221
222 if (r == 0) {
223 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
224 - if (role != NULL && role[0])
225 - r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
226 - else
227 - r = get_default_context_with_level(sename, lvl, NULL, &sc);
228 + r = get_default_context_with_level(sename, lvl, NULL, default_sc);
229 #else
230 - if (role != NULL && role[0])
231 - r = get_default_context_with_role(sename, role, NULL, &sc);
232 - else
233 - r = get_default_context(sename, NULL, &sc);
234 + r = get_default_context(sename, NULL, default_sc);
235 #endif
236 }
237
238 - if (r != 0) {
239 - switch (security_getenforce()) {
240 - case -1:
241 - fatal("%s: ssh_selinux_getctxbyname: "
242 - "security_getenforce() failed", __func__);
243 - case 0:
244 - error("%s: Failed to get default SELinux security "
245 - "context for %s", __func__, pwname);
246 - break;
247 - default:
248 - fatal("%s: Failed to get default SELinux security "
249 - "context for %s (in enforcing mode)",
250 - __func__, pwname);
251 + if (r == 0) {
252 + /* If launched from xinetd, we must use current level */
253 + if (inetd_flag && !rexeced_flag) {
254 + security_context_t sshdsc=NULL;
255 +
256 + if (getcon_raw(&sshdsc) < 0)
257 + fatal("failed to allocate security context");
258 +
259 + if ((con=context_new(sshdsc)) == NULL)
260 + fatal("failed to allocate selinux context");
261 + reqlvl = context_range_get(con);
262 + freecon(sshdsc);
263 + if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
264 + /* we actually don't change level */
265 + reqlvl = "";
266 +
267 + debug("%s: current connection level '%s'", __func__, reqlvl);
268 }
269 +
270 + if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
271 + r = get_user_context(sename, role, reqlvl, user_sc);
272 +
273 + if (r == 0 && reqlvl != NULL && reqlvl[0]) {
274 + security_context_t default_level_sc = *default_sc;
275 + if (role != NULL && role[0]) {
276 + if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
277 + default_level_sc = *default_sc;
278 + }
279 + /* verify that the requested range is contained in the user range */
280 + if (mls_range_allowed(default_level_sc, *user_sc)) {
281 + logit("permit MLS level %s (user range %s)", reqlvl, lvl);
282 + } else {
283 + r = -1;
284 + error("deny MLS level %s (user range %s)", reqlvl, lvl);
285 + }
286 + if (default_level_sc != *default_sc)
287 + freecon(default_level_sc);
288 + }
289 + } else {
290 + *user_sc = *default_sc;
291 + }
292 + }
293 + if (r != 0) {
294 + error("%s: Failed to get default SELinux security "
295 + "context for %s", __func__, pwname);
296 }
297
298 #ifdef HAVE_GETSEUSERBYNAME
299 @@ -126,8 +303,12 @@ ssh_selinux_getctxbyname(char *pwname)
300 if (lvl != NULL)
301 xfree(lvl);
302 #endif
303 -
304 - return (sc);
305 + if (role != NULL)
306 + xfree(role);
307 + if (con)
308 + context_free(con);
309 +
310 + return (r);
311 }
312
313 /* Setup environment variables for pam_selinux */
314 @@ -165,6 +346,8 @@ void
315 ssh_selinux_setup_exec_context(char *pwname)
316 {
317 security_context_t user_ctx = NULL;
318 + int r = 0;
319 + security_context_t default_ctx = NULL;
320
321 if (!ssh_selinux_enabled())
322 return;
323 @@ -189,22 +372,45 @@ ssh_selinux_setup_exec_context(char *pwn
324
325 debug3("%s: setting execution context", __func__);
326
327 - user_ctx = ssh_selinux_getctxbyname(pwname);
328 - if (setexeccon(user_ctx) != 0) {
329 + r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
330 + if (r >= 0) {
331 + r = setexeccon(user_ctx);
332 + if (r < 0) {
333 + error("%s: Failed to set SELinux execution context %s for %s",
334 + __func__, user_ctx, pwname);
335 + }
336 +#ifdef HAVE_SETKEYCREATECON
337 + else if (setkeycreatecon(user_ctx) < 0) {
338 + error("%s: Failed to set SELinux keyring creation context %s for %s",
339 + __func__, user_ctx, pwname);
340 + }
341 +#endif
342 + }
343 + if (user_ctx == NULL) {
344 + user_ctx = default_ctx;
345 + }
346 + if (r < 0 || user_ctx != default_ctx) {
347 + /* audit just the case when user changed a role or there was
348 + a failure */
349 + send_audit_message(r >= 0, default_ctx, user_ctx);
350 + }
351 + if (r < 0) {
352 switch (security_getenforce()) {
353 case -1:
354 fatal("%s: security_getenforce() failed", __func__);
355 case 0:
356 - error("%s: Failed to set SELinux execution "
357 - "context for %s", __func__, pwname);
358 + error("%s: SELinux failure. Continuing in permissive mode.",
359 + __func__);
360 break;
361 default:
362 - fatal("%s: Failed to set SELinux execution context "
363 - "for %s (in enforcing mode)", __func__, pwname);
364 + fatal("%s: SELinux failure. Aborting connection.",
365 + __func__);
366 }
367 }
368 - if (user_ctx != NULL)
369 + if (user_ctx != NULL && user_ctx != default_ctx)
370 freecon(user_ctx);
371 + if (default_ctx != NULL)
372 + freecon(default_ctx);
373
374 debug3("%s: done", __func__);
375 }
376 @@ -222,7 +428,10 @@ ssh_selinux_setup_pty(char *pwname, cons
377
378 debug3("%s: setting TTY context on %s", __func__, tty);
379
380 - user_ctx = ssh_selinux_getctxbyname(pwname);
381 + if (getexeccon(&user_ctx) < 0) {
382 + error("%s: getexeccon: %s", __func__, strerror(errno));
383 + goto out;
384 + }
385
386 /* XXX: should these calls fatal() upon failure in enforcing mode? */
387
388 diff -up openssh-5.9p0/sshd.c.mls openssh-5.9p0/sshd.c
389 --- openssh-5.9p0/sshd.c.mls 2011-08-30 12:29:22.663149706 +0200
390 +++ openssh-5.9p0/sshd.c 2011-08-30 12:29:29.524024777 +0200
391 @@ -2082,6 +2082,9 @@ main(int ac, char **av)
392 restore_uid();
393 }
394 #endif
395 +#ifdef WITH_SELINUX
396 + ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
397 +#endif
398 #ifdef USE_PAM
399 if (options.use_pam) {
400 do_pam_setcred(1);