]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blame - openssh/patches/openssh-6.1p1-role-mls.patch
openssh: Update to 6.1p1.
[people/ms/ipfire-3.x.git] / openssh / patches / openssh-6.1p1-role-mls.patch
CommitLineData
43c69e28
SS
1diff -up openssh-6.1p1/auth1.c.role-mls openssh-6.1p1/auth1.c
2--- openssh-6.1p1/auth1.c.role-mls 2012-11-28 17:06:43.657990103 +0100
3+++ openssh-6.1p1/auth1.c 2012-11-28 17:06:43.699989959 +0100
852f4e06
SS
4@@ -384,6 +384,9 @@ do_authentication(Authctxt *authctxt)
5 {
6 u_int ulen;
7 char *user, *style = NULL;
8+#ifdef WITH_SELINUX
9+ char *role=NULL;
10+#endif
11
12 /* Get the name of the user that we wish to log in as. */
13 packet_read_expect(SSH_CMSG_USER);
14@@ -392,11 +395,24 @@ do_authentication(Authctxt *authctxt)
15 user = packet_get_cstring(&ulen);
16 packet_check_eom();
17
18+#ifdef WITH_SELINUX
19+ if ((role = strchr(user, '/')) != NULL)
20+ *role++ = '\0';
21+#endif
22+
23 if ((style = strchr(user, ':')) != NULL)
24 *style++ = '\0';
25+#ifdef WITH_SELINUX
26+ else
27+ if (role && (style = strchr(role, ':')) != NULL)
28+ *style++ = '\0';
29+#endif
30
31 authctxt->user = user;
32 authctxt->style = style;
33+#ifdef WITH_SELINUX
34+ authctxt->role = role;
35+#endif
36
37 /* Verify that the user is a valid user. */
38 if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
43c69e28
SS
39diff -up openssh-6.1p1/auth2.c.role-mls openssh-6.1p1/auth2.c
40--- openssh-6.1p1/auth2.c.role-mls 2012-11-28 17:06:43.661990089 +0100
41+++ openssh-6.1p1/auth2.c 2012-11-28 17:11:09.058916613 +0100
42@@ -218,6 +218,9 @@ input_userauth_request(int type, u_int32
43 Authctxt *authctxt = ctxt;
44 Authmethod *m = NULL;
45 char *user, *service, *method, *style = NULL;
46+#ifdef WITH_SELINUX
47+ char *role = NULL;
48+#endif
49 int authenticated = 0;
50
51 if (authctxt == NULL)
52@@ -229,6 +232,11 @@ input_userauth_request(int type, u_int32
53 debug("userauth-request for user %s service %s method %s", user, service, method);
54 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
55
56+#ifdef WITH_SELINUX
57+ if ((role = strchr(user, '/')) != NULL)
58+ *role++ = 0;
59+#endif
60+
61 if ((style = strchr(user, ':')) != NULL)
62 *style++ = 0;
63
64@@ -251,8 +259,15 @@ input_userauth_request(int type, u_int32
65 use_privsep ? " [net]" : "");
66 authctxt->service = xstrdup(service);
67 authctxt->style = style ? xstrdup(style) : NULL;
68- if (use_privsep)
69+#ifdef WITH_SELINUX
70+ authctxt->role = role ? xstrdup(role) : NULL;
71+#endif
72+ if (use_privsep) {
73 mm_inform_authserv(service, style);
74+#ifdef WITH_SELINUX
75+ mm_inform_authrole(role);
76+#endif
77+ }
78 userauth_banner();
79 if (auth2_setup_methods_lists(authctxt) != 0)
80 packet_disconnect("no authentication methods enabled");
81diff -up openssh-6.1p1/auth2-gss.c.role-mls openssh-6.1p1/auth2-gss.c
82--- openssh-6.1p1/auth2-gss.c.role-mls 2011-05-05 06:04:11.000000000 +0200
83+++ openssh-6.1p1/auth2-gss.c 2012-11-28 17:06:43.700989956 +0100
9d8fd3ad 84@@ -260,6 +260,7 @@ input_gssapi_mic(int type, u_int32_t ple
852f4e06
SS
85 Authctxt *authctxt = ctxt;
86 Gssctxt *gssctxt;
87 int authenticated = 0;
88+ char *micuser;
89 Buffer b;
90 gss_buffer_desc mic, gssbuf;
91 u_int len;
9d8fd3ad 92@@ -272,7 +273,13 @@ input_gssapi_mic(int type, u_int32_t ple
852f4e06
SS
93 mic.value = packet_get_string(&len);
94 mic.length = len;
95
96- ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
97+#ifdef WITH_SELINUX
98+ if (authctxt->role && (strlen(authctxt->role) > 0))
99+ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role);
100+ else
101+#endif
102+ micuser = authctxt->user;
103+ ssh_gssapi_buildmic(&b, micuser, authctxt->service,
104 "gssapi-with-mic");
105
106 gssbuf.value = buffer_ptr(&b);
9d8fd3ad 107@@ -284,6 +291,8 @@ input_gssapi_mic(int type, u_int32_t ple
852f4e06
SS
108 logit("GSSAPI MIC check failed");
109
110 buffer_free(&b);
111+ if (micuser != authctxt->user)
112+ xfree(micuser);
113 xfree(mic.value);
114
115 authctxt->postponed = 0;
43c69e28
SS
116diff -up openssh-6.1p1/auth2-hostbased.c.role-mls openssh-6.1p1/auth2-hostbased.c
117--- openssh-6.1p1/auth2-hostbased.c.role-mls 2012-11-28 17:06:43.669990062 +0100
118+++ openssh-6.1p1/auth2-hostbased.c 2012-11-28 17:06:43.700989956 +0100
852f4e06
SS
119@@ -106,7 +106,15 @@ userauth_hostbased(Authctxt *authctxt)
120 buffer_put_string(&b, session_id2, session_id2_len);
121 /* reconstruct packet */
122 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
123- buffer_put_cstring(&b, authctxt->user);
124+#ifdef WITH_SELINUX
125+ if (authctxt->role) {
126+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1);
127+ buffer_append(&b, authctxt->user, strlen(authctxt->user));
128+ buffer_put_char(&b, '/');
129+ buffer_append(&b, authctxt->role, strlen(authctxt->role));
130+ } else
131+#endif
132+ buffer_put_cstring(&b, authctxt->user);
133 buffer_put_cstring(&b, service);
134 buffer_put_cstring(&b, "hostbased");
135 buffer_put_string(&b, pkalg, alen);
43c69e28
SS
136diff -up openssh-6.1p1/auth2-pubkey.c.role-mls openssh-6.1p1/auth2-pubkey.c
137--- openssh-6.1p1/auth2-pubkey.c.role-mls 2012-11-28 17:06:43.669990062 +0100
138+++ openssh-6.1p1/auth2-pubkey.c 2012-11-28 17:06:43.700989956 +0100
9d8fd3ad 139@@ -121,7 +121,15 @@ userauth_pubkey(Authctxt *authctxt)
852f4e06
SS
140 }
141 /* reconstruct packet */
142 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
143- buffer_put_cstring(&b, authctxt->user);
144+#ifdef WITH_SELINUX
145+ if (authctxt->role) {
146+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1);
147+ buffer_append(&b, authctxt->user, strlen(authctxt->user));
148+ buffer_put_char(&b, '/');
149+ buffer_append(&b, authctxt->role, strlen(authctxt->role));
150+ } else
151+#endif
152+ buffer_put_cstring(&b, authctxt->user);
153 buffer_put_cstring(&b,
154 datafellows & SSH_BUG_PKSERVICE ?
155 "ssh-userauth" :
43c69e28
SS
156diff -up openssh-6.1p1/auth.h.role-mls openssh-6.1p1/auth.h
157--- openssh-6.1p1/auth.h.role-mls 2012-11-28 17:06:43.669990062 +0100
158+++ openssh-6.1p1/auth.h 2012-11-28 17:06:43.699989959 +0100
159@@ -59,6 +59,9 @@ struct Authctxt {
160 char *service;
161 struct passwd *pw; /* set if 'valid' */
162 char *style;
9d8fd3ad 163+#ifdef WITH_SELINUX
43c69e28 164+ char *role;
9d8fd3ad 165+#endif
43c69e28
SS
166 void *kbdintctxt;
167 void *jpake_ctx;
168 #ifdef BSD_AUTH
169diff -up openssh-6.1p1/auth-pam.c.role-mls openssh-6.1p1/auth-pam.c
170--- openssh-6.1p1/auth-pam.c.role-mls 2012-11-28 17:06:43.638990168 +0100
171+++ openssh-6.1p1/auth-pam.c 2012-11-28 17:06:43.699989959 +0100
172@@ -1074,7 +1074,7 @@ is_pam_session_open(void)
173 * during the ssh authentication process.
174 */
175 int
176-do_pam_putenv(char *name, char *value)
177+do_pam_putenv(char *name, const char *value)
178 {
179 int ret = 1;
180 #ifdef HAVE_PAM_PUTENV
181diff -up openssh-6.1p1/auth-pam.h.role-mls openssh-6.1p1/auth-pam.h
182--- openssh-6.1p1/auth-pam.h.role-mls 2004-09-11 14:17:26.000000000 +0200
183+++ openssh-6.1p1/auth-pam.h 2012-11-28 17:06:43.699989959 +0100
184@@ -38,7 +38,7 @@ void do_pam_session(void);
185 void do_pam_set_tty(const char *);
186 void do_pam_setcred(int );
187 void do_pam_chauthtok(void);
188-int do_pam_putenv(char *, char *);
189+int do_pam_putenv(char *, const char *);
190 char ** fetch_pam_environment(void);
191 char ** fetch_pam_child_environment(void);
192 void free_pam_environment(char **);
193diff -up openssh-6.1p1/misc.c.role-mls openssh-6.1p1/misc.c
194--- openssh-6.1p1/misc.c.role-mls 2011-09-22 13:34:36.000000000 +0200
195+++ openssh-6.1p1/misc.c 2012-11-28 17:06:43.701989952 +0100
196@@ -427,6 +427,7 @@ char *
197 colon(char *cp)
198 {
199 int flag = 0;
200+ int start = 1;
9d8fd3ad 201
43c69e28
SS
202 if (*cp == ':') /* Leading colon is part of file name. */
203 return NULL;
204@@ -442,6 +443,13 @@ colon(char *cp)
205 return (cp);
206 if (*cp == '/')
207 return NULL;
208+ if (start) {
209+ /* Slash on beginning or after dots only denotes file name. */
210+ if (*cp == '/')
211+ return (0);
212+ if (*cp != '.')
213+ start = 0;
9d8fd3ad 214+ }
43c69e28
SS
215 }
216 return NULL;
217 }
218diff -up openssh-6.1p1/monitor.c.role-mls openssh-6.1p1/monitor.c
219--- openssh-6.1p1/monitor.c.role-mls 2012-11-28 17:06:43.686990004 +0100
220+++ openssh-6.1p1/monitor.c 2012-11-28 17:06:43.701989952 +0100
9d8fd3ad 221@@ -148,6 +148,9 @@ int mm_answer_sign(int, Buffer *);
852f4e06
SS
222 int mm_answer_pwnamallow(int, Buffer *);
223 int mm_answer_auth2_read_banner(int, Buffer *);
224 int mm_answer_authserv(int, Buffer *);
225+#ifdef WITH_SELINUX
226+int mm_answer_authrole(int, Buffer *);
227+#endif
228 int mm_answer_authpassword(int, Buffer *);
229 int mm_answer_bsdauthquery(int, Buffer *);
230 int mm_answer_bsdauthrespond(int, Buffer *);
9d8fd3ad 231@@ -231,6 +234,9 @@ struct mon_table mon_dispatch_proto20[]
852f4e06
SS
232 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
233 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
234 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
235+#ifdef WITH_SELINUX
236+ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
237+#endif
238 {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
239 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
240 #ifdef USE_PAM
43c69e28 241@@ -838,6 +844,9 @@ mm_answer_pwnamallow(int sock, Buffer *m
852f4e06
SS
242 else {
243 /* Allow service/style information on the auth context */
244 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
245+#ifdef WITH_SELINUX
246+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
247+#endif
248 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
249 }
9d8fd3ad 250 #ifdef USE_PAM
43c69e28 251@@ -881,6 +890,25 @@ mm_answer_authserv(int sock, Buffer *m)
852f4e06
SS
252 return (0);
253 }
254
255+#ifdef WITH_SELINUX
256+int
257+mm_answer_authrole(int sock, Buffer *m)
258+{
259+ monitor_permit_authentications(1);
260+
261+ authctxt->role = buffer_get_string(m, NULL);
262+ debug3("%s: role=%s",
263+ __func__, authctxt->role);
264+
265+ if (strlen(authctxt->role) == 0) {
266+ xfree(authctxt->role);
267+ authctxt->role = NULL;
268+ }
269+
270+ return (0);
271+}
272+#endif
273+
274 int
275 mm_answer_authpassword(int sock, Buffer *m)
276 {
43c69e28 277@@ -1251,7 +1279,7 @@ static int
852f4e06
SS
278 monitor_valid_userblob(u_char *data, u_int datalen)
279 {
280 Buffer b;
281- char *p;
282+ char *p, *r;
283 u_int len;
284 int fail = 0;
285
43c69e28 286@@ -1277,6 +1305,8 @@ monitor_valid_userblob(u_char *data, u_i
852f4e06
SS
287 if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
288 fail++;
289 p = buffer_get_string(&b, NULL);
290+ if ((r = strchr(p, '/')) != NULL)
291+ *r = '\0';
292 if (strcmp(authctxt->user, p) != 0) {
293 logit("wrong user name passed to monitor: expected %s != %.100s",
294 authctxt->user, p);
43c69e28 295@@ -1308,7 +1338,7 @@ monitor_valid_hostbasedblob(u_char *data
852f4e06
SS
296 char *chost)
297 {
298 Buffer b;
299- char *p;
300+ char *p, *r;
301 u_int len;
302 int fail = 0;
303
43c69e28 304@@ -1325,6 +1355,8 @@ monitor_valid_hostbasedblob(u_char *data
852f4e06
SS
305 if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
306 fail++;
307 p = buffer_get_string(&b, NULL);
308+ if ((r = strchr(p, '/')) != NULL)
309+ *r = '\0';
310 if (strcmp(authctxt->user, p) != 0) {
311 logit("wrong user name passed to monitor: expected %s != %.100s",
312 authctxt->user, p);
43c69e28
SS
313diff -up openssh-6.1p1/monitor.h.role-mls openssh-6.1p1/monitor.h
314--- openssh-6.1p1/monitor.h.role-mls 2012-11-28 17:06:43.686990004 +0100
315+++ openssh-6.1p1/monitor.h 2012-11-28 17:06:43.701989952 +0100
852f4e06
SS
316@@ -31,6 +31,9 @@
317 enum monitor_reqtype {
318 MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
319 MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
320+#ifdef WITH_SELINUX
321+ MONITOR_REQ_AUTHROLE,
322+#endif
323 MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
324 MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
325 MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
43c69e28
SS
326diff -up openssh-6.1p1/monitor_wrap.c.role-mls openssh-6.1p1/monitor_wrap.c
327--- openssh-6.1p1/monitor_wrap.c.role-mls 2012-11-28 17:06:43.686990004 +0100
328+++ openssh-6.1p1/monitor_wrap.c 2012-11-28 17:06:43.702989948 +0100
9d8fd3ad 329@@ -336,6 +336,25 @@ mm_inform_authserv(char *service, char *
852f4e06
SS
330 buffer_free(&m);
331 }
332
333+/* Inform the privileged process about role */
334+
335+#ifdef WITH_SELINUX
336+void
337+mm_inform_authrole(char *role)
338+{
339+ Buffer m;
340+
341+ debug3("%s entering", __func__);
342+
343+ buffer_init(&m);
344+ buffer_put_cstring(&m, role ? role : "");
345+
346+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m);
347+
348+ buffer_free(&m);
349+}
350+#endif
351+
352 /* Do the password authentication */
353 int
354 mm_auth_password(Authctxt *authctxt, char *password)
43c69e28
SS
355diff -up openssh-6.1p1/monitor_wrap.h.role-mls openssh-6.1p1/monitor_wrap.h
356--- openssh-6.1p1/monitor_wrap.h.role-mls 2012-11-28 17:06:43.686990004 +0100
357+++ openssh-6.1p1/monitor_wrap.h 2012-11-28 17:06:43.702989948 +0100
9d8fd3ad 358@@ -42,6 +42,9 @@ int mm_is_monitor(void);
852f4e06
SS
359 DH *mm_choose_dh(int, int, int);
360 int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
361 void mm_inform_authserv(char *, char *);
362+#ifdef WITH_SELINUX
363+void mm_inform_authrole(char *);
364+#endif
365 struct passwd *mm_getpwnamallow(const char *);
366 char *mm_auth2_read_banner(void);
367 int mm_auth_password(struct Authctxt *, char *);
43c69e28
SS
368diff -up openssh-6.1p1/openbsd-compat/Makefile.in.role-mls openssh-6.1p1/openbsd-compat/Makefile.in
369--- openssh-6.1p1/openbsd-compat/Makefile.in.role-mls 2011-11-04 01:25:25.000000000 +0100
370+++ openssh-6.1p1/openbsd-compat/Makefile.in 2012-11-28 17:06:43.702989948 +0100
852f4e06
SS
371@@ -20,7 +20,7 @@ OPENBSD=base64.o basename.o bindresvport
372
43c69e28 373 COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
852f4e06
SS
374
375-PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o
376+PORTS=port-aix.o port-irix.o port-linux.o port-linux_part_2.o port-solaris.o port-tun.o port-uw.o
377
378 .c.o:
379 $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
43c69e28
SS
380diff -up openssh-6.1p1/openbsd-compat/port-linux.c.role-mls openssh-6.1p1/openbsd-compat/port-linux.c
381--- openssh-6.1p1/openbsd-compat/port-linux.c.role-mls 2012-03-09 00:25:18.000000000 +0100
382+++ openssh-6.1p1/openbsd-compat/port-linux.c 2012-11-28 17:06:43.702989948 +0100
383@@ -31,68 +31,271 @@
852f4e06
SS
384
385 #include "log.h"
386 #include "xmalloc.h"
387+#include "servconf.h"
388 #include "port-linux.h"
389+#include "key.h"
390+#include "hostfile.h"
391+#include "auth.h"
392
393 #ifdef WITH_SELINUX
394 #include <selinux/selinux.h>
43c69e28
SS
395 #include <selinux/flask.h>
396+#include <selinux/context.h>
397 #include <selinux/get_context_list.h>
398+#include <selinux/get_default_type.h>
399+#include <selinux/av_permissions.h>
400+
401+#ifdef HAVE_LINUX_AUDIT
402+#include <libaudit.h>
403+#include <unistd.h>
404+#endif
405
406 #ifndef SSH_SELINUX_UNCONFINED_TYPE
9d8fd3ad
SS
407 # define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:"
408 #endif
852f4e06
SS
409
410-/* Wrapper around is_selinux_enabled() to log its return value once only */
411-int
412-ssh_selinux_enabled(void)
852f4e06
SS
413+extern ServerOptions options;
414+extern Authctxt *the_authctxt;
415+extern int inetd_flag;
416+extern int rexeced_flag;
43c69e28
SS
417+
418+/* Send audit message */
419+static int
420+send_audit_message(int success, security_context_t default_context,
421+ security_context_t selected_context)
422+{
423+ int rc=0;
424+#ifdef HAVE_LINUX_AUDIT
425+ char *msg = NULL;
426+ int audit_fd = audit_open();
427+ security_context_t default_raw=NULL;
428+ security_context_t selected_raw=NULL;
429+ rc = -1;
430+ if (audit_fd < 0) {
431+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
432+ errno == EAFNOSUPPORT)
433+ return 0; /* No audit support in kernel */
434+ error("Error connecting to audit system.");
435+ return rc;
436+ }
437+ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
438+ error("Error translating default context.");
439+ default_raw = NULL;
440+ }
441+ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
442+ error("Error translating selected context.");
443+ selected_raw = NULL;
444+ }
445+ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
446+ default_raw ? default_raw : (default_context ? default_context: "?"),
447+ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
448+ error("Error allocating memory.");
449+ goto out;
450+ }
451+ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
452+ msg, NULL, NULL, NULL, success) <= 0) {
453+ error("Error sending audit message.");
454+ goto out;
455+ }
456+ rc = 0;
457+ out:
458+ free(msg);
459+ freecon(default_raw);
460+ freecon(selected_raw);
461+ close(audit_fd);
462+#endif
463+ return rc;
464+}
465+
466+static int
467+mls_range_allowed(security_context_t src, security_context_t dst)
468 {
469- static int enabled = -1;
470+ struct av_decision avd;
471+ int retval;
472+ unsigned int bit = CONTEXT__CONTAINS;
473+
474+ debug("%s: src:%s dst:%s", __func__, src, dst);
475+ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
476+ if (retval || ((bit & avd.allowed) != bit))
477+ return 0;
478+
479+ return 1;
480+}
481+
482+static int
483+get_user_context(const char *sename, const char *role, const char *lvl,
484+ security_context_t *sc) {
485+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
486+ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
487+ /* User may have requested a level completely outside of his
488+ allowed range. We get a context just for auditing as the
489+ range check below will certainly fail for default context. */
490+#endif
491+ if (get_default_context(sename, NULL, sc) != 0) {
492+ *sc = NULL;
493+ return -1;
494+ }
495+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
496+ }
497+#endif
498+ if (role != NULL && role[0]) {
499+ context_t con;
500+ char *type=NULL;
501+ if (get_default_type(role, &type) != 0) {
502+ error("get_default_type: failed to get default type for '%s'",
503+ role);
504+ goto out;
505+ }
506+ con = context_new(*sc);
507+ if (!con) {
508+ goto out;
509+ }
510+ context_role_set(con, role);
511+ context_type_set(con, type);
512+ freecon(*sc);
513+ *sc = strdup(context_str(con));
514+ context_free(con);
515+ if (!*sc)
516+ return -1;
517+ }
518+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
519+ if (lvl != NULL && lvl[0]) {
520+ /* verify that the requested range is obtained */
521+ context_t con;
522+ security_context_t obtained_raw;
523+ security_context_t requested_raw;
524+ con = context_new(*sc);
525+ if (!con) {
526+ goto out;
527+ }
528+ context_range_set(con, lvl);
529+ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
530+ context_free(con);
531+ goto out;
532+ }
533+ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
534+ freecon(obtained_raw);
535+ context_free(con);
536+ goto out;
537+ }
852f4e06
SS
538
539- if (enabled == -1) {
540- enabled = (is_selinux_enabled() == 1);
541- debug("SELinux support %s", enabled ? "enabled" : "disabled");
43c69e28
SS
542+ debug("get_user_context: obtained context '%s' requested context '%s'",
543+ obtained_raw, requested_raw);
544+ if (strcmp(obtained_raw, requested_raw)) {
545+ /* set the context to the real requested one but fail */
546+ freecon(requested_raw);
547+ freecon(obtained_raw);
548+ freecon(*sc);
549+ *sc = strdup(context_str(con));
550+ context_free(con);
551+ return -1;
552+ }
553+ freecon(requested_raw);
554+ freecon(obtained_raw);
555+ context_free(con);
556 }
557+#endif
558+ return 0;
559+ out:
560+ freecon(*sc);
561+ *sc = NULL;
562+ return -1;
563+}
564
565- return (enabled);
852f4e06
SS
566+static void
567+ssh_selinux_get_role_level(char **role, const char **level)
568+{
569+ *role = NULL;
570+ *level = NULL;
571+ if (the_authctxt) {
572+ if (the_authctxt->role != NULL) {
573+ char *slash;
574+ *role = xstrdup(the_authctxt->role);
575+ if ((slash = strchr(*role, '/')) != NULL) {
576+ *slash = '\0';
577+ *level = slash + 1;
578+ }
579+ }
43c69e28 580+ }
852f4e06
SS
581 }
582
583 /* Return the default security context for the given username */
584 static security_context_t
43c69e28
SS
585-ssh_selinux_getctxbyname(char *pwname)
586+ssh_selinux_getctxbyname(char *pwname,
587+ security_context_t *default_sc, security_context_t *user_sc)
852f4e06 588 {
43c69e28 589- security_context_t sc = NULL;
852f4e06
SS
590- char *sename = NULL, *lvl = NULL;
591- int r;
852f4e06
SS
592+ char *sename, *lvl;
593+ char *role;
594+ const char *reqlvl;
595+ int r = 0;
43c69e28 596+ context_t con = NULL;
9d8fd3ad 597+
852f4e06 598+ ssh_selinux_get_role_level(&role, &reqlvl);
9d8fd3ad 599
852f4e06
SS
600 #ifdef HAVE_GETSEUSERBYNAME
601- if (getseuserbyname(pwname, &sename, &lvl) != 0)
602- return NULL;
603+ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
604+ sename = NULL;
605+ lvl = NULL;
606+ }
607 #else
608 sename = pwname;
43c69e28
SS
609- lvl = NULL;
610+ lvl = "";
852f4e06
SS
611 #endif
612
613+ if (r == 0) {
614 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
615- r = get_default_context_with_level(sename, lvl, NULL, &sc);
43c69e28 616+ r = get_default_context_with_level(sename, lvl, NULL, default_sc);
852f4e06
SS
617 #else
618- r = get_default_context(sename, NULL, &sc);
43c69e28 619+ r = get_default_context(sename, NULL, default_sc);
852f4e06
SS
620 #endif
621+ }
43c69e28
SS
622+
623+ if (r == 0) {
624+ /* If launched from xinetd, we must use current level */
625+ if (inetd_flag && !rexeced_flag) {
626+ security_context_t sshdsc=NULL;
627+
628+ if (getcon_raw(&sshdsc) < 0)
629+ fatal("failed to allocate security context");
630+
631+ if ((con=context_new(sshdsc)) == NULL)
632+ fatal("failed to allocate selinux context");
633+ reqlvl = context_range_get(con);
634+ freecon(sshdsc);
635+ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
636+ /* we actually don't change level */
637+ reqlvl = "";
638+
639+ debug("%s: current connection level '%s'", __func__, reqlvl);
852f4e06 640
43c69e28
SS
641- if (r != 0) {
642- switch (security_getenforce()) {
643- case -1:
644- fatal("%s: ssh_selinux_getctxbyname: "
645- "security_getenforce() failed", __func__);
646- case 0:
647- error("%s: Failed to get default SELinux security "
648- "context for %s", __func__, pwname);
649- sc = NULL;
650- break;
651- default:
652- fatal("%s: Failed to get default SELinux security "
653- "context for %s (in enforcing mode)",
654- __func__, pwname);
655 }
656+
657+ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
658+ r = get_user_context(sename, role, reqlvl, user_sc);
659+
660+ if (r == 0 && reqlvl != NULL && reqlvl[0]) {
661+ security_context_t default_level_sc = *default_sc;
662+ if (role != NULL && role[0]) {
663+ if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
664+ default_level_sc = *default_sc;
665+ }
666+ /* verify that the requested range is contained in the user range */
667+ if (mls_range_allowed(default_level_sc, *user_sc)) {
668+ logit("permit MLS level %s (user range %s)", reqlvl, lvl);
669+ } else {
670+ r = -1;
671+ error("deny MLS level %s (user range %s)", reqlvl, lvl);
672+ }
673+ if (default_level_sc != *default_sc)
674+ freecon(default_level_sc);
675+ }
676+ } else {
677+ *user_sc = *default_sc;
678+ }
679+ }
680+ if (r != 0) {
681+ error("%s: Failed to get default SELinux security "
682+ "context for %s", __func__, pwname);
683 }
852f4e06 684
43c69e28
SS
685 #ifdef HAVE_GETSEUSERBYNAME
686@@ -102,7 +305,42 @@ ssh_selinux_getctxbyname(char *pwname)
687 xfree(lvl);
688 #endif
689
690- return sc;
691+ if (role != NULL)
692+ xfree(role);
693+ if (con)
694+ context_free(con);
695+
696+ return (r);
697+}
698+
852f4e06
SS
699+/* Setup environment variables for pam_selinux */
700+static int
701+ssh_selinux_setup_pam_variables(void)
702+{
703+ const char *reqlvl;
704+ char *role;
705+ char *use_current;
706+ int rv;
707+
708+ debug3("%s: setting execution context", __func__);
709+
710+ ssh_selinux_get_role_level(&role, &reqlvl);
711+
712+ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : "");
713+
714+ if (inetd_flag && !rexeced_flag) {
715+ use_current = "1";
716+ } else {
717+ use_current = "";
718+ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
719+ }
720+
721+ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current);
722+
723+ if (role != NULL)
724+ xfree(role);
725+
726+ return rv;
43c69e28
SS
727 }
728
852f4e06 729 /* Set the execution context to the default for the specified user */
43c69e28 730@@ -110,28 +348,71 @@ void
852f4e06 731 ssh_selinux_setup_exec_context(char *pwname)
43c69e28
SS
732 {
733 security_context_t user_ctx = NULL;
734+ int r = 0;
735+ security_context_t default_ctx = NULL;
736
852f4e06
SS
737 if (!ssh_selinux_enabled())
738 return;
739
740+ if (options.use_pam) {
741+ /* do not compute context, just setup environment for pam_selinux */
742+ if (ssh_selinux_setup_pam_variables()) {
743+ switch (security_getenforce()) {
744+ case -1:
745+ fatal("%s: security_getenforce() failed", __func__);
746+ case 0:
747+ error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.",
748+ __func__);
749+ break;
750+ default:
751+ fatal("%s: SELinux PAM variable setup failure. Aborting connection.",
752+ __func__);
753+ }
754+ }
755+ return;
756+ }
757+
758 debug3("%s: setting execution context", __func__);
759
43c69e28
SS
760- user_ctx = ssh_selinux_getctxbyname(pwname);
761- if (setexeccon(user_ctx) != 0) {
762+ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
763+ if (r >= 0) {
764+ r = setexeccon(user_ctx);
765+ if (r < 0) {
766+ error("%s: Failed to set SELinux execution context %s for %s",
767+ __func__, user_ctx, pwname);
768+ }
769+#ifdef HAVE_SETKEYCREATECON
770+ else if (setkeycreatecon(user_ctx) < 0) {
771+ error("%s: Failed to set SELinux keyring creation context %s for %s",
772+ __func__, user_ctx, pwname);
773+ }
774+#endif
775+ }
776+ if (user_ctx == NULL) {
777+ user_ctx = default_ctx;
778+ }
779+ if (r < 0 || user_ctx != default_ctx) {
780+ /* audit just the case when user changed a role or there was
781+ a failure */
782+ send_audit_message(r >= 0, default_ctx, user_ctx);
783+ }
784+ if (r < 0) {
785 switch (security_getenforce()) {
786 case -1:
787 fatal("%s: security_getenforce() failed", __func__);
788 case 0:
789- error("%s: Failed to set SELinux execution "
790- "context for %s", __func__, pwname);
791+ error("%s: SELinux failure. Continuing in permissive mode.",
792+ __func__);
793 break;
794 default:
795- fatal("%s: Failed to set SELinux execution context "
796- "for %s (in enforcing mode)", __func__, pwname);
797+ fatal("%s: SELinux failure. Aborting connection.",
798+ __func__);
799 }
800 }
801- if (user_ctx != NULL)
802+ if (user_ctx != NULL && user_ctx != default_ctx)
803 freecon(user_ctx);
804+ if (default_ctx != NULL)
805+ freecon(default_ctx);
806
807 debug3("%s: done", __func__);
808 }
809@@ -149,7 +430,10 @@ ssh_selinux_setup_pty(char *pwname, cons
810
811 debug3("%s: setting TTY context on %s", __func__, tty);
812
813- user_ctx = ssh_selinux_getctxbyname(pwname);
814+ if (getexeccon(&user_ctx) < 0) {
815+ error("%s: getexeccon: %s", __func__, strerror(errno));
816+ goto out;
817+ }
818
819 /* XXX: should these calls fatal() upon failure in enforcing mode? */
820
821@@ -221,21 +505,6 @@ ssh_selinux_change_context(const char *n
852f4e06
SS
822 xfree(newctx);
823 }
824
825-void
826-ssh_selinux_setfscreatecon(const char *path)
827-{
828- security_context_t context;
829-
830- if (!ssh_selinux_enabled())
831- return;
832- if (path == NULL) {
833- setfscreatecon(NULL);
834- return;
835- }
836- if (matchpathcon(path, 0700, &context) == 0)
837- setfscreatecon(context);
838-}
839-
840 #endif /* WITH_SELINUX */
841
842 #ifdef LINUX_OOM_ADJUST
43c69e28
SS
843diff -up openssh-6.1p1/openbsd-compat/port-linux_part_2.c.role-mls openssh-6.1p1/openbsd-compat/port-linux_part_2.c
844--- openssh-6.1p1/openbsd-compat/port-linux_part_2.c.role-mls 2012-11-28 17:06:43.703989944 +0100
845+++ openssh-6.1p1/openbsd-compat/port-linux_part_2.c 2012-11-28 17:06:43.703989944 +0100
852f4e06
SS
846@@ -0,0 +1,75 @@
847+/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */
848+
849+/*
850+ * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
851+ * Copyright (c) 2006 Damien Miller <djm@openbsd.org>
852+ *
853+ * Permission to use, copy, modify, and distribute this software for any
854+ * purpose with or without fee is hereby granted, provided that the above
855+ * copyright notice and this permission notice appear in all copies.
856+ *
857+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
858+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
859+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
860+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
861+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
862+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
863+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
864+ */
865+
866+/*
867+ * Linux-specific portability code - just SELinux support at present
868+ */
869+
870+#include "includes.h"
871+
872+#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST)
873+#include <errno.h>
874+#include <stdarg.h>
875+#include <string.h>
876+#include <stdio.h>
877+
878+#include "log.h"
879+#include "xmalloc.h"
880+#include "port-linux.h"
881+#include "key.h"
882+#include "hostfile.h"
883+#include "auth.h"
884+
885+#ifdef WITH_SELINUX
886+#include <selinux/selinux.h>
887+#include <selinux/flask.h>
888+#include <selinux/get_context_list.h>
889+
890+/* Wrapper around is_selinux_enabled() to log its return value once only */
891+int
892+ssh_selinux_enabled(void)
893+{
894+ static int enabled = -1;
895+
896+ if (enabled == -1) {
897+ enabled = (is_selinux_enabled() == 1);
898+ debug("SELinux support %s", enabled ? "enabled" : "disabled");
899+ }
900+
901+ return (enabled);
902+}
903+
904+void
905+ssh_selinux_setfscreatecon(const char *path)
906+{
907+ security_context_t context;
908+
909+ if (!ssh_selinux_enabled())
910+ return;
911+ if (path == NULL) {
912+ setfscreatecon(NULL);
913+ return;
914+ }
915+ if (matchpathcon(path, 0700, &context) == 0)
916+ setfscreatecon(context);
917+}
918+
919+#endif /* WITH_SELINUX */
920+
921+#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */
43c69e28
SS
922diff -up openssh-6.1p1/sshd.c.role-mls openssh-6.1p1/sshd.c
923--- openssh-6.1p1/sshd.c.role-mls 2012-11-28 17:06:43.688989996 +0100
924+++ openssh-6.1p1/sshd.c 2012-11-28 17:06:43.703989944 +0100
925@@ -2101,6 +2101,9 @@ main(int ac, char **av)
926 restore_uid();
927 }
928 #endif
929+#ifdef WITH_SELINUX
930+ ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
931+#endif
932 #ifdef USE_PAM
933 if (options.use_pam) {
934 do_pam_setcred(1);