summaryrefslogtreecommitdiff
path: root/debian/patches/selinux-role.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/selinux-role.patch')
-rw-r--r--debian/patches/selinux-role.patch472
1 files changed, 472 insertions, 0 deletions
diff --git a/debian/patches/selinux-role.patch b/debian/patches/selinux-role.patch
new file mode 100644
index 000000000..3161999a9
--- /dev/null
+++ b/debian/patches/selinux-role.patch
@@ -0,0 +1,472 @@
1From c574865182e2c5dfa183b577f49ac602d16df5c0 Mon Sep 17 00:00:00 2001
2From: Manoj Srivastava <srivasta@debian.org>
3Date: Sun, 9 Feb 2014 16:09:49 +0000
4Subject: Handle SELinux authorisation roles
5
6Rejected upstream due to discomfort with magic usernames; a better approach
7will need an SSH protocol change. In the meantime, this came from Debian's
8SELinux maintainer, so we'll keep it until we have something better.
9
10Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1641
11Bug-Debian: http://bugs.debian.org/394795
12Last-Update: 2020-10-18
13
14Patch-Name: selinux-role.patch
15---
16 auth.h | 1 +
17 auth2.c | 10 ++++++++--
18 monitor.c | 37 +++++++++++++++++++++++++++++++++----
19 monitor.h | 2 ++
20 monitor_wrap.c | 27 ++++++++++++++++++++++++---
21 monitor_wrap.h | 3 ++-
22 openbsd-compat/port-linux.c | 21 ++++++++++++++-------
23 openbsd-compat/port-linux.h | 4 ++--
24 platform.c | 4 ++--
25 platform.h | 2 +-
26 session.c | 10 +++++-----
27 session.h | 2 +-
28 sshd.c | 2 +-
29 sshpty.c | 4 ++--
30 sshpty.h | 2 +-
31 15 files changed, 99 insertions(+), 32 deletions(-)
32
33diff --git a/auth.h b/auth.h
34index becc672b5..5da9fe75f 100644
35--- a/auth.h
36+++ b/auth.h
37@@ -63,6 +63,7 @@ struct Authctxt {
38 char *service;
39 struct passwd *pw; /* set if 'valid' */
40 char *style;
41+ char *role;
42
43 /* Method lists for multiple authentication */
44 char **auth_methods; /* modified from server config */
45diff --git a/auth2.c b/auth2.c
46index 9fa1404b3..d8363bdba 100644
47--- a/auth2.c
48+++ b/auth2.c
49@@ -265,7 +265,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
50 {
51 Authctxt *authctxt = ssh->authctxt;
52 Authmethod *m = NULL;
53- char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
54+ char *user = NULL, *service = NULL, *method = NULL, *style = NULL, *role = NULL;
55 int r, authenticated = 0;
56 double tstart = monotime_double();
57
58@@ -279,8 +279,13 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
59 debug("userauth-request for user %s service %s method %s", user, service, method);
60 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
61
62+ if ((role = strchr(user, '/')) != NULL)
63+ *role++ = 0;
64+
65 if ((style = strchr(user, ':')) != NULL)
66 *style++ = 0;
67+ else if (role && (style = strchr(role, ':')) != NULL)
68+ *style++ = '\0';
69
70 if (authctxt->attempt++ == 0) {
71 /* setup auth context */
72@@ -307,8 +312,9 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
73 use_privsep ? " [net]" : "");
74 authctxt->service = xstrdup(service);
75 authctxt->style = style ? xstrdup(style) : NULL;
76+ authctxt->role = role ? xstrdup(role) : NULL;
77 if (use_privsep)
78- mm_inform_authserv(service, style);
79+ mm_inform_authserv(service, style, role);
80 userauth_banner(ssh);
81 if (auth2_setup_methods_lists(authctxt) != 0)
82 ssh_packet_disconnect(ssh,
83diff --git a/monitor.c b/monitor.c
84index 11868952b..98362948f 100644
85--- a/monitor.c
86+++ b/monitor.c
87@@ -118,6 +118,7 @@ int mm_answer_sign(struct ssh *, int, struct sshbuf *);
88 int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
89 int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
90 int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
91+int mm_answer_authrole(struct ssh *, int, struct sshbuf *);
92 int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
93 int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
94 int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
95@@ -198,6 +199,7 @@ struct mon_table mon_dispatch_proto20[] = {
96 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
97 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
98 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
99+ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
100 {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
101 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
102 #ifdef USE_PAM
103@@ -820,6 +822,7 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
104
105 /* Allow service/style information on the auth context */
106 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
107+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
108 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
109
110 #ifdef USE_PAM
111@@ -853,16 +856,42 @@ mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m)
112 monitor_permit_authentications(1);
113
114 if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 ||
115- (r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0)
116+ (r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0 ||
117+ (r = sshbuf_get_cstring(m, &authctxt->role, NULL)) != 0)
118 fatal("%s: buffer error: %s", __func__, ssh_err(r));
119- debug3("%s: service=%s, style=%s",
120- __func__, authctxt->service, authctxt->style);
121+ debug3("%s: service=%s, style=%s, role=%s",
122+ __func__, authctxt->service, authctxt->style, authctxt->role);
123
124 if (strlen(authctxt->style) == 0) {
125 free(authctxt->style);
126 authctxt->style = NULL;
127 }
128
129+ if (strlen(authctxt->role) == 0) {
130+ free(authctxt->role);
131+ authctxt->role = NULL;
132+ }
133+
134+ return (0);
135+}
136+
137+int
138+mm_answer_authrole(struct ssh *ssh, int sock, struct sshbuf *m)
139+{
140+ int r;
141+
142+ monitor_permit_authentications(1);
143+
144+ if ((r = sshbuf_get_cstring(m, &authctxt->role, NULL)) != 0)
145+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
146+ debug3("%s: role=%s",
147+ __func__, authctxt->role);
148+
149+ if (strlen(authctxt->role) == 0) {
150+ free(authctxt->role);
151+ authctxt->role = NULL;
152+ }
153+
154 return (0);
155 }
156
157@@ -1566,7 +1595,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
158 res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
159 if (res == 0)
160 goto error;
161- pty_setowner(authctxt->pw, s->tty);
162+ pty_setowner(authctxt->pw, s->tty, authctxt->role);
163
164 if ((r = sshbuf_put_u32(m, 1)) != 0 ||
165 (r = sshbuf_put_cstring(m, s->tty)) != 0)
166diff --git a/monitor.h b/monitor.h
167index 2b1a2d590..4d87284aa 100644
168--- a/monitor.h
169+++ b/monitor.h
170@@ -65,6 +65,8 @@ enum monitor_reqtype {
171
172 MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151,
173 MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153,
174+
175+ MONITOR_REQ_AUTHROLE = 154,
176 };
177
178 struct ssh;
179diff --git a/monitor_wrap.c b/monitor_wrap.c
180index 0e78cd006..d41d3949d 100644
181--- a/monitor_wrap.c
182+++ b/monitor_wrap.c
183@@ -364,10 +364,10 @@ mm_auth2_read_banner(void)
184 return (banner);
185 }
186
187-/* Inform the privileged process about service and style */
188+/* Inform the privileged process about service, style, and role */
189
190 void
191-mm_inform_authserv(char *service, char *style)
192+mm_inform_authserv(char *service, char *style, char *role)
193 {
194 struct sshbuf *m;
195 int r;
196@@ -377,7 +377,8 @@ mm_inform_authserv(char *service, char *style)
197 if ((m = sshbuf_new()) == NULL)
198 fatal("%s: sshbuf_new failed", __func__);
199 if ((r = sshbuf_put_cstring(m, service)) != 0 ||
200- (r = sshbuf_put_cstring(m, style ? style : "")) != 0)
201+ (r = sshbuf_put_cstring(m, style ? style : "")) != 0 ||
202+ (r = sshbuf_put_cstring(m, role ? role : "")) != 0)
203 fatal("%s: buffer error: %s", __func__, ssh_err(r));
204
205 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
206@@ -385,6 +386,26 @@ mm_inform_authserv(char *service, char *style)
207 sshbuf_free(m);
208 }
209
210+/* Inform the privileged process about role */
211+
212+void
213+mm_inform_authrole(char *role)
214+{
215+ struct sshbuf *m;
216+ int r;
217+
218+ debug3("%s entering", __func__);
219+
220+ if ((m = sshbuf_new()) == NULL)
221+ fatal("%s: sshbuf_new failed", __func__);
222+ if ((r = sshbuf_put_cstring(m, role ? role : "")) != 0)
223+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
224+
225+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, m);
226+
227+ sshbuf_free(m);
228+}
229+
230 /* Do the password authentication */
231 int
232 mm_auth_password(struct ssh *ssh, char *password)
233diff --git a/monitor_wrap.h b/monitor_wrap.h
234index 75aef1c74..c39e5dd8b 100644
235--- a/monitor_wrap.h
236+++ b/monitor_wrap.h
237@@ -48,7 +48,8 @@ DH *mm_choose_dh(int, int, int);
238 int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *,
239 const u_char *, size_t, const char *, const char *,
240 const char *, u_int compat);
241-void mm_inform_authserv(char *, char *);
242+void mm_inform_authserv(char *, char *, char *);
243+void mm_inform_authrole(char *);
244 struct passwd *mm_getpwnamallow(struct ssh *, const char *);
245 char *mm_auth2_read_banner(void);
246 int mm_auth_password(struct ssh *, char *);
247diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
248index f46094faf..56f1d2c1e 100644
249--- a/openbsd-compat/port-linux.c
250+++ b/openbsd-compat/port-linux.c
251@@ -56,7 +56,7 @@ ssh_selinux_enabled(void)
252
253 /* Return the default security context for the given username */
254 static security_context_t
255-ssh_selinux_getctxbyname(char *pwname)
256+ssh_selinux_getctxbyname(char *pwname, const char *role)
257 {
258 security_context_t sc = NULL;
259 char *sename = NULL, *lvl = NULL;
260@@ -71,9 +71,16 @@ ssh_selinux_getctxbyname(char *pwname)
261 #endif
262
263 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
264- r = get_default_context_with_level(sename, lvl, NULL, &sc);
265+ if (role != NULL && role[0])
266+ r = get_default_context_with_rolelevel(sename, role, lvl, NULL,
267+ &sc);
268+ else
269+ r = get_default_context_with_level(sename, lvl, NULL, &sc);
270 #else
271- r = get_default_context(sename, NULL, &sc);
272+ if (role != NULL && role[0])
273+ r = get_default_context_with_role(sename, role, NULL, &sc);
274+ else
275+ r = get_default_context(sename, NULL, &sc);
276 #endif
277
278 if (r != 0) {
279@@ -103,7 +110,7 @@ ssh_selinux_getctxbyname(char *pwname)
280
281 /* Set the execution context to the default for the specified user */
282 void
283-ssh_selinux_setup_exec_context(char *pwname)
284+ssh_selinux_setup_exec_context(char *pwname, const char *role)
285 {
286 security_context_t user_ctx = NULL;
287
288@@ -112,7 +119,7 @@ ssh_selinux_setup_exec_context(char *pwname)
289
290 debug3("%s: setting execution context", __func__);
291
292- user_ctx = ssh_selinux_getctxbyname(pwname);
293+ user_ctx = ssh_selinux_getctxbyname(pwname, role);
294 if (setexeccon(user_ctx) != 0) {
295 switch (security_getenforce()) {
296 case -1:
297@@ -134,7 +141,7 @@ ssh_selinux_setup_exec_context(char *pwname)
298
299 /* Set the TTY context for the specified user */
300 void
301-ssh_selinux_setup_pty(char *pwname, const char *tty)
302+ssh_selinux_setup_pty(char *pwname, const char *tty, const char *role)
303 {
304 security_context_t new_tty_ctx = NULL;
305 security_context_t user_ctx = NULL;
306@@ -146,7 +153,7 @@ ssh_selinux_setup_pty(char *pwname, const char *tty)
307
308 debug3("%s: setting TTY context on %s", __func__, tty);
309
310- user_ctx = ssh_selinux_getctxbyname(pwname);
311+ user_ctx = ssh_selinux_getctxbyname(pwname, role);
312
313 /* XXX: should these calls fatal() upon failure in enforcing mode? */
314
315diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h
316index 3c22a854d..c88129428 100644
317--- a/openbsd-compat/port-linux.h
318+++ b/openbsd-compat/port-linux.h
319@@ -19,8 +19,8 @@
320
321 #ifdef WITH_SELINUX
322 int ssh_selinux_enabled(void);
323-void ssh_selinux_setup_pty(char *, const char *);
324-void ssh_selinux_setup_exec_context(char *);
325+void ssh_selinux_setup_pty(char *, const char *, const char *);
326+void ssh_selinux_setup_exec_context(char *, const char *);
327 void ssh_selinux_change_context(const char *);
328 void ssh_selinux_setfscreatecon(const char *);
329 #endif
330diff --git a/platform.c b/platform.c
331index 44ba71dc5..2defe9425 100644
332--- a/platform.c
333+++ b/platform.c
334@@ -143,7 +143,7 @@ platform_setusercontext(struct passwd *pw)
335 * called if sshd is running as root.
336 */
337 void
338-platform_setusercontext_post_groups(struct passwd *pw)
339+platform_setusercontext_post_groups(struct passwd *pw, const char *role)
340 {
341 #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
342 /*
343@@ -184,7 +184,7 @@ platform_setusercontext_post_groups(struct passwd *pw)
344 }
345 #endif /* HAVE_SETPCRED */
346 #ifdef WITH_SELINUX
347- ssh_selinux_setup_exec_context(pw->pw_name);
348+ ssh_selinux_setup_exec_context(pw->pw_name, role);
349 #endif
350 }
351
352diff --git a/platform.h b/platform.h
353index ea4f9c584..60d72ffe7 100644
354--- a/platform.h
355+++ b/platform.h
356@@ -25,7 +25,7 @@ void platform_post_fork_parent(pid_t child_pid);
357 void platform_post_fork_child(void);
358 int platform_privileged_uidswap(void);
359 void platform_setusercontext(struct passwd *);
360-void platform_setusercontext_post_groups(struct passwd *);
361+void platform_setusercontext_post_groups(struct passwd *, const char *);
362 char *platform_get_krb5_client(const char *);
363 char *platform_krb5_get_principal_name(const char *);
364 int platform_sys_dir_uid(uid_t);
365diff --git a/session.c b/session.c
366index 857f17b3c..b1796a803 100644
367--- a/session.c
368+++ b/session.c
369@@ -1364,7 +1364,7 @@ safely_chroot(const char *path, uid_t uid)
370
371 /* Set login name, uid, gid, and groups. */
372 void
373-do_setusercontext(struct passwd *pw)
374+do_setusercontext(struct passwd *pw, const char *role)
375 {
376 char uidstr[32], *chroot_path, *tmp;
377
378@@ -1392,7 +1392,7 @@ do_setusercontext(struct passwd *pw)
379 endgrent();
380 #endif
381
382- platform_setusercontext_post_groups(pw);
383+ platform_setusercontext_post_groups(pw, role);
384
385 if (!in_chroot && options.chroot_directory != NULL &&
386 strcasecmp(options.chroot_directory, "none") != 0) {
387@@ -1536,7 +1536,7 @@ do_child(struct ssh *ssh, Session *s, const char *command)
388
389 /* Force a password change */
390 if (s->authctxt->force_pwchange) {
391- do_setusercontext(pw);
392+ do_setusercontext(pw, s->authctxt->role);
393 child_close_fds(ssh);
394 do_pwchange(s);
395 exit(1);
396@@ -1554,7 +1554,7 @@ do_child(struct ssh *ssh, Session *s, const char *command)
397 /* When PAM is enabled we rely on it to do the nologin check */
398 if (!options.use_pam)
399 do_nologin(pw);
400- do_setusercontext(pw);
401+ do_setusercontext(pw, s->authctxt->role);
402 /*
403 * PAM session modules in do_setusercontext may have
404 * generated messages, so if this in an interactive
405@@ -1953,7 +1953,7 @@ session_pty_req(struct ssh *ssh, Session *s)
406 sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
407
408 if (!use_privsep)
409- pty_setowner(s->pw, s->tty);
410+ pty_setowner(s->pw, s->tty, s->authctxt->role);
411
412 /* Set window size from the packet. */
413 pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
414diff --git a/session.h b/session.h
415index ce59dabd9..675c91146 100644
416--- a/session.h
417+++ b/session.h
418@@ -77,7 +77,7 @@ void session_pty_cleanup2(Session *);
419 Session *session_new(void);
420 Session *session_by_tty(char *);
421 void session_close(struct ssh *, Session *);
422-void do_setusercontext(struct passwd *);
423+void do_setusercontext(struct passwd *, const char *);
424
425 const char *session_get_remote_name_or_ip(struct ssh *, u_int, int);
426
427diff --git a/sshd.c b/sshd.c
428index a50ec3584..38d281ab4 100644
429--- a/sshd.c
430+++ b/sshd.c
431@@ -594,7 +594,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
432 reseed_prngs();
433
434 /* Drop privileges */
435- do_setusercontext(authctxt->pw);
436+ do_setusercontext(authctxt->pw, authctxt->role);
437
438 skip:
439 /* It is safe now to apply the key state */
440diff --git a/sshpty.c b/sshpty.c
441index bce09e255..308449b37 100644
442--- a/sshpty.c
443+++ b/sshpty.c
444@@ -162,7 +162,7 @@ pty_change_window_size(int ptyfd, u_int row, u_int col,
445 }
446
447 void
448-pty_setowner(struct passwd *pw, const char *tty)
449+pty_setowner(struct passwd *pw, const char *tty, const char *role)
450 {
451 struct group *grp;
452 gid_t gid;
453@@ -186,7 +186,7 @@ pty_setowner(struct passwd *pw, const char *tty)
454 strerror(errno));
455
456 #ifdef WITH_SELINUX
457- ssh_selinux_setup_pty(pw->pw_name, tty);
458+ ssh_selinux_setup_pty(pw->pw_name, tty, role);
459 #endif
460
461 if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
462diff --git a/sshpty.h b/sshpty.h
463index 9ec7e9a15..de7e000ae 100644
464--- a/sshpty.h
465+++ b/sshpty.h
466@@ -24,5 +24,5 @@ int pty_allocate(int *, int *, char *, size_t);
467 void pty_release(const char *);
468 void pty_make_controlling_tty(int *, const char *);
469 void pty_change_window_size(int, u_int, u_int, u_int, u_int);
470-void pty_setowner(struct passwd *, const char *);
471+void pty_setowner(struct passwd *, const char *, const char *);
472 void disconnect_controlling_tty(void);