]>
Commit | Line | Data |
---|---|---|
43c69e28 SS |
1 | diff -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 |
39 | diff -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"); | |
81 | diff -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 |
116 | diff -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 |
136 | diff -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 |
156 | diff -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 | |
169 | diff -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 | |
181 | diff -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 **); | |
193 | diff -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 | } | |
218 | diff -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 |
313 | diff -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 |
326 | diff -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 |
355 | diff -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 |
368 | diff -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 |
380 | diff -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 |
843 | diff -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 |
922 | diff -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); |