]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blob - pkgs/openssh/patches/openssh-5.8p1-mls.patch
Change file layout of the makefiles.
[people/ms/ipfire-3.x.git] / pkgs / openssh / patches / openssh-5.8p1-mls.patch
1 diff -up openssh-5.8p1/misc.c.mls openssh-5.8p1/misc.c
2 --- openssh-5.8p1/misc.c.mls 2011-01-13 02:21:36.000000000 +0100
3 +++ openssh-5.8p1/misc.c 2011-02-12 15:05:06.000000000 +0100
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.8p1/openbsd-compat/port-linux.c.mls openssh-5.8p1/openbsd-compat/port-linux.c
27 --- openssh-5.8p1/openbsd-compat/port-linux.c.mls 2011-02-12 15:05:06.000000000 +0100
28 +++ openssh-5.8p1/openbsd-compat/port-linux.c 2011-02-12 15:09:23.000000000 +0100
29 @@ -40,13 +40,164 @@
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 extern ServerOptions options;
44 extern Authctxt *the_authctxt;
45 extern int inetd_flag;
46 extern int rexeced_flag;
47
48 +/* Send audit message */
49 +static int
50 +send_audit_message(int success, security_context_t default_context,
51 + security_context_t selected_context)
52 +{
53 + int rc=0;
54 +#ifdef HAVE_LINUX_AUDIT
55 + char *msg = NULL;
56 + int audit_fd = audit_open();
57 + security_context_t default_raw=NULL;
58 + security_context_t selected_raw=NULL;
59 + rc = -1;
60 + if (audit_fd < 0) {
61 + if (errno == EINVAL || errno == EPROTONOSUPPORT ||
62 + errno == EAFNOSUPPORT)
63 + return 0; /* No audit support in kernel */
64 + error("Error connecting to audit system.");
65 + return rc;
66 + }
67 + if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
68 + error("Error translating default context.");
69 + default_raw = NULL;
70 + }
71 + if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
72 + error("Error translating selected context.");
73 + selected_raw = NULL;
74 + }
75 + if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
76 + default_raw ? default_raw : (default_context ? default_context: "?"),
77 + selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
78 + error("Error allocating memory.");
79 + goto out;
80 + }
81 + if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
82 + msg, NULL, NULL, NULL, success) <= 0) {
83 + error("Error sending audit message.");
84 + goto out;
85 + }
86 + rc = 0;
87 + out:
88 + free(msg);
89 + freecon(default_raw);
90 + freecon(selected_raw);
91 + close(audit_fd);
92 +#endif
93 + return rc;
94 +}
95 +
96 +static int
97 +mls_range_allowed(security_context_t src, security_context_t dst)
98 +{
99 + struct av_decision avd;
100 + int retval;
101 + unsigned int bit = CONTEXT__CONTAINS;
102 +
103 + debug("%s: src:%s dst:%s", __func__, src, dst);
104 + retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
105 + if (retval || ((bit & avd.allowed) != bit))
106 + return 0;
107 +
108 + return 1;
109 +}
110 +
111 +static int
112 +get_user_context(const char *sename, const char *role, const char *lvl,
113 + security_context_t *sc) {
114 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
115 + if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
116 + /* User may have requested a level completely outside of his
117 + allowed range. We get a context just for auditing as the
118 + range check below will certainly fail for default context. */
119 +#endif
120 + if (get_default_context(sename, NULL, sc) != 0) {
121 + *sc = NULL;
122 + return -1;
123 + }
124 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
125 + }
126 +#endif
127 + if (role != NULL && role[0]) {
128 + context_t con;
129 + char *type=NULL;
130 + if (get_default_type(role, &type) != 0) {
131 + error("get_default_type: failed to get default type for '%s'",
132 + role);
133 + goto out;
134 + }
135 + con = context_new(*sc);
136 + if (!con) {
137 + goto out;
138 + }
139 + context_role_set(con, role);
140 + context_type_set(con, type);
141 + freecon(*sc);
142 + *sc = strdup(context_str(con));
143 + context_free(con);
144 + if (!*sc)
145 + return -1;
146 + }
147 +#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
148 + if (lvl != NULL && lvl[0]) {
149 + /* verify that the requested range is obtained */
150 + context_t con;
151 + security_context_t obtained_raw;
152 + security_context_t requested_raw;
153 + con = context_new(*sc);
154 + if (!con) {
155 + goto out;
156 + }
157 + context_range_set(con, lvl);
158 + if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
159 + context_free(con);
160 + goto out;
161 + }
162 + if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
163 + freecon(obtained_raw);
164 + context_free(con);
165 + goto out;
166 + }
167 +
168 + debug("get_user_context: obtained context '%s' requested context '%s'",
169 + obtained_raw, requested_raw);
170 + if (strcmp(obtained_raw, requested_raw)) {
171 + /* set the context to the real requested one but fail */
172 + freecon(requested_raw);
173 + freecon(obtained_raw);
174 + freecon(*sc);
175 + *sc = strdup(context_str(con));
176 + context_free(con);
177 + return -1;
178 + }
179 + freecon(requested_raw);
180 + freecon(obtained_raw);
181 + context_free(con);
182 + }
183 +#endif
184 + return 0;
185 + out:
186 + freecon(*sc);
187 + *sc = NULL;
188 + return -1;
189 +}
190 +
191 static void
192 ssh_selinux_get_role_level(char **role, const char **level)
193 {
194 @@ -65,14 +216,16 @@ ssh_selinux_get_role_level(char **role,
195 }
196
197 /* Return the default security context for the given username */
198 -static security_context_t
199 -ssh_selinux_getctxbyname(char *pwname)
200 +static int
201 +ssh_selinux_getctxbyname(char *pwname,
202 + security_context_t *default_sc, security_context_t *user_sc)
203 {
204 security_context_t sc = NULL;
205 char *sename, *lvl;
206 char *role;
207 const char *reqlvl;
208 int r = 0;
209 + context_t con;
210
211 ssh_selinux_get_role_level(&role, &reqlvl);
212 #ifdef HAVE_GETSEUSERBYNAME
213 @@ -82,38 +235,63 @@ ssh_selinux_getctxbyname(char *pwname)
214 }
215 #else
216 sename = pwname;
217 - lvl = NULL;
218 + lvl = "";
219 #endif
220
221 if (r == 0) {
222 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
223 - if (role != NULL && role[0])
224 - r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
225 - else
226 - r = get_default_context_with_level(sename, lvl, NULL, &sc);
227 + r = get_default_context_with_level(sename, lvl, NULL, default_sc);
228 #else
229 - if (role != NULL && role[0])
230 - r = get_default_context_with_role(sename, role, NULL, &sc);
231 - else
232 - r = get_default_context(sename, NULL, &sc);
233 + r = get_default_context(sename, NULL, default_sc);
234 #endif
235 }
236
237 - if (r != 0) {
238 - switch (security_getenforce()) {
239 - case -1:
240 - fatal("%s: ssh_selinux_getctxbyname: "
241 - "security_getenforce() failed", __func__);
242 - case 0:
243 - error("%s: Failed to get default SELinux security "
244 - "context for %s", __func__, pwname);
245 - break;
246 - default:
247 - fatal("%s: Failed to get default SELinux security "
248 - "context for %s (in enforcing mode)",
249 - __func__, pwname);
250 + if (r == 0) {
251 + /* If launched from xinetd, we must use current level */
252 + if (inetd_flag && !rexeced_flag) {
253 + security_context_t sshdsc=NULL;
254 +
255 + if (getcon_raw(&sshdsc) < 0)
256 + fatal("failed to allocate security context");
257 +
258 + if ((con=context_new(sshdsc)) == NULL)
259 + fatal("failed to allocate selinux context");
260 + reqlvl = context_range_get(con);
261 + freecon(sshdsc);
262 + if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
263 + /* we actually don't change level */
264 + reqlvl = "";
265 +
266 + debug("%s: current connection level '%s'", __func__, reqlvl);
267 + }
268 +
269 + if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
270 + r = get_user_context(sename, role, reqlvl, user_sc);
271 +
272 + if (r == 0 && reqlvl != NULL && reqlvl[0]) {
273 + security_context_t default_level_sc = *default_sc;
274 + if (role != NULL && role[0]) {
275 + if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
276 + default_level_sc = *default_sc;
277 + }
278 + /* verify that the requested range is contained in the user range */
279 + if (mls_range_allowed(default_level_sc, *user_sc)) {
280 + logit("permit MLS level %s (user range %s)", reqlvl, lvl);
281 + } else {
282 + r = -1;
283 + error("deny MLS level %s (user range %s)", reqlvl, lvl);
284 + }
285 + if (default_level_sc != *default_sc)
286 + freecon(default_level_sc);
287 + }
288 + } else {
289 + *user_sc = *default_sc;
290 }
291 }
292 + if (r != 0) {
293 + error("%s: Failed to get default SELinux security "
294 + "context for %s", __func__, pwname);
295 + }
296
297 #ifdef HAVE_GETSEUSERBYNAME
298 if (sename != NULL)
299 @@ -121,8 +299,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 @@ -160,6 +342,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 @@ -184,22 +368,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 @@ -217,7 +424,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.8p1/sshd.c.mls openssh-5.8p1/sshd.c
389 --- openssh-5.8p1/sshd.c.mls 2011-02-12 15:05:05.000000000 +0100
390 +++ openssh-5.8p1/sshd.c 2011-02-12 15:05:06.000000000 +0100
391 @@ -2011,6 +2011,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);