1:5.8.1p1-3
[openssh.git] / debian / patches / selinux-role.patch
1 Description: Handle SELinux authorisation roles
2  Rejected upstream due to discomfort with magic usernames; a better approach
3  will need an SSH protocol change.  In the meantime, this came from Debian's
4  SELinux maintainer, so we'll keep it until we have something better.
5 Author: Manoj Srivastava <srivasta@debian.org>
6 Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1641
7 Bug-Debian: http://bugs.debian.org/394795
8 Last-Update: 2010-02-27
9
10 Index: b/auth.h
11 ===================================================================
12 --- a/auth.h
13 +++ b/auth.h
14 @@ -59,6 +59,7 @@
15         char            *service;
16         struct passwd   *pw;            /* set if 'valid' */
17         char            *style;
18 +       char            *role;
19         void            *kbdintctxt;
20         void            *jpake_ctx;
21  #ifdef BSD_AUTH
22 Index: b/auth1.c
23 ===================================================================
24 --- a/auth1.c
25 +++ b/auth1.c
26 @@ -383,7 +383,7 @@
27  do_authentication(Authctxt *authctxt)
28  {
29         u_int ulen;
30 -       char *user, *style = NULL;
31 +       char *user, *style = NULL, *role = NULL;
32  
33         /* Get the name of the user that we wish to log in as. */
34         packet_read_expect(SSH_CMSG_USER);
35 @@ -392,11 +392,17 @@
36         user = packet_get_cstring(&ulen);
37         packet_check_eom();
38  
39 +       if ((role = strchr(user, '/')) != NULL)
40 +               *role++ = '\0';
41 +
42         if ((style = strchr(user, ':')) != NULL)
43                 *style++ = '\0';
44 +       else if (role && (style = strchr(role, ':')) != NULL)
45 +               *style++ = '\0';
46  
47         authctxt->user = user;
48         authctxt->style = style;
49 +       authctxt->role = role;
50  
51         /* Verify that the user is a valid user. */
52         if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
53 Index: b/auth2.c
54 ===================================================================
55 --- a/auth2.c
56 +++ b/auth2.c
57 @@ -217,7 +217,7 @@
58  {
59         Authctxt *authctxt = ctxt;
60         Authmethod *m = NULL;
61 -       char *user, *service, *method, *style = NULL;
62 +       char *user, *service, *method, *style = NULL, *role = NULL;
63         int authenticated = 0;
64  
65         if (authctxt == NULL)
66 @@ -229,8 +229,13 @@
67         debug("userauth-request for user %s service %s method %s", user, service, method);
68         debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
69  
70 +       if ((role = strchr(user, '/')) != NULL)
71 +               *role++ = 0;
72 +
73         if ((style = strchr(user, ':')) != NULL)
74                 *style++ = 0;
75 +       else if (role && (style = strchr(role, ':')) != NULL)
76 +               *style++ = '\0';
77  
78         if (authctxt->attempt++ == 0) {
79                 /* setup auth context */
80 @@ -254,8 +259,9 @@
81                     use_privsep ? " [net]" : "");
82                 authctxt->service = xstrdup(service);
83                 authctxt->style = style ? xstrdup(style) : NULL;
84 +               authctxt->role = role ? xstrdup(role) : NULL;
85                 if (use_privsep)
86 -                       mm_inform_authserv(service, style);
87 +                       mm_inform_authserv(service, style, role);
88                 userauth_banner();
89         } else if (strcmp(user, authctxt->user) != 0 ||
90             strcmp(service, authctxt->service) != 0) {
91 Index: b/monitor.c
92 ===================================================================
93 --- a/monitor.c
94 +++ b/monitor.c
95 @@ -137,6 +137,7 @@
96  int mm_answer_pwnamallow(int, Buffer *);
97  int mm_answer_auth2_read_banner(int, Buffer *);
98  int mm_answer_authserv(int, Buffer *);
99 +int mm_answer_authrole(int, Buffer *);
100  int mm_answer_authpassword(int, Buffer *);
101  int mm_answer_bsdauthquery(int, Buffer *);
102  int mm_answer_bsdauthrespond(int, Buffer *);
103 @@ -215,6 +216,7 @@
104      {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
105      {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
106      {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
107 +    {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
108      {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
109      {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
110  #ifdef USE_PAM
111 @@ -699,6 +701,7 @@
112         else {
113                 /* Allow service/style information on the auth context */
114                 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
115 +               monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
116                 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
117         }
118  
119 @@ -732,14 +735,37 @@
120  
121         authctxt->service = buffer_get_string(m, NULL);
122         authctxt->style = buffer_get_string(m, NULL);
123 -       debug3("%s: service=%s, style=%s",
124 -           __func__, authctxt->service, authctxt->style);
125 +       authctxt->role = buffer_get_string(m, NULL);
126 +       debug3("%s: service=%s, style=%s, role=%s",
127 +           __func__, authctxt->service, authctxt->style, authctxt->role);
128  
129         if (strlen(authctxt->style) == 0) {
130                 xfree(authctxt->style);
131                 authctxt->style = NULL;
132         }
133  
134 +       if (strlen(authctxt->role) == 0) {
135 +               xfree(authctxt->role);
136 +               authctxt->role = NULL;
137 +       }
138 +
139 +       return (0);
140 +}
141 +
142 +int
143 +mm_answer_authrole(int sock, Buffer *m)
144 +{
145 +       monitor_permit_authentications(1);
146 +
147 +       authctxt->role = buffer_get_string(m, NULL);
148 +       debug3("%s: role=%s",
149 +           __func__, authctxt->role);
150 +
151 +       if (strlen(authctxt->role) == 0) {
152 +               xfree(authctxt->role);
153 +               authctxt->role = NULL;
154 +       }
155 +
156         return (0);
157  }
158  
159 @@ -1327,7 +1353,7 @@
160         res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
161         if (res == 0)
162                 goto error;
163 -       pty_setowner(authctxt->pw, s->tty);
164 +       pty_setowner(authctxt->pw, s->tty, authctxt->role);
165  
166         buffer_put_int(m, 1);
167         buffer_put_cstring(m, s->tty);
168 Index: b/monitor.h
169 ===================================================================
170 --- a/monitor.h
171 +++ b/monitor.h
172 @@ -30,7 +30,7 @@
173  
174  enum monitor_reqtype {
175         MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
176 -       MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
177 +       MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, MONITOR_REQ_AUTHROLE,
178         MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
179         MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
180         MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
181 Index: b/monitor_wrap.c
182 ===================================================================
183 --- a/monitor_wrap.c
184 +++ b/monitor_wrap.c
185 @@ -280,10 +280,10 @@
186         return (banner);
187  }
188  
189 -/* Inform the privileged process about service and style */
190 +/* Inform the privileged process about service, style, and role */
191  
192  void
193 -mm_inform_authserv(char *service, char *style)
194 +mm_inform_authserv(char *service, char *style, char *role)
195  {
196         Buffer m;
197  
198 @@ -292,11 +292,29 @@
199         buffer_init(&m);
200         buffer_put_cstring(&m, service);
201         buffer_put_cstring(&m, style ? style : "");
202 +       buffer_put_cstring(&m, role ? role : "");
203  
204         mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m);
205  
206         buffer_free(&m);
207  }
208 +
209 +/* Inform the privileged process about role */
210 +
211 +void
212 +mm_inform_authrole(char *role)
213 +{
214 +       Buffer m;
215 +
216 +       debug3("%s entering", __func__);
217 +
218 +       buffer_init(&m);
219 +       buffer_put_cstring(&m, role ? role : "");
220 +
221 +       mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m);
222 +
223 +       buffer_free(&m);
224 +}
225  
226  /* Do the password authentication */
227  int
228 Index: b/monitor_wrap.h
229 ===================================================================
230 --- a/monitor_wrap.h
231 +++ b/monitor_wrap.h
232 @@ -40,7 +40,8 @@
233  int mm_is_monitor(void);
234  DH *mm_choose_dh(int, int, int);
235  int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
236 -void mm_inform_authserv(char *, char *);
237 +void mm_inform_authserv(char *, char *, char *);
238 +void mm_inform_authrole(char *);
239  struct passwd *mm_getpwnamallow(const char *);
240  char *mm_auth2_read_banner(void);
241  int mm_auth_password(struct Authctxt *, char *);
242 Index: b/openbsd-compat/port-linux.c
243 ===================================================================
244 --- a/openbsd-compat/port-linux.c
245 +++ b/openbsd-compat/port-linux.c
246 @@ -29,6 +29,12 @@
247  #include <string.h>
248  #include <stdio.h>
249  
250 +#ifdef WITH_SELINUX
251 +#include "key.h"
252 +#include "hostfile.h"
253 +#include "auth.h"
254 +#endif
255 +
256  #include "log.h"
257  #include "xmalloc.h"
258  #include "port-linux.h"
259 @@ -54,9 +60,9 @@
260  
261  /* Return the default security context for the given username */
262  static security_context_t
263 -ssh_selinux_getctxbyname(char *pwname)
264 +ssh_selinux_getctxbyname(char *pwname, const char *role)
265  {
266 -       security_context_t sc;
267 +       security_context_t sc = NULL;
268         char *sename = NULL, *lvl = NULL;
269         int r;
270  
271 @@ -69,9 +75,16 @@
272  #endif
273  
274  #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
275 -       r = get_default_context_with_level(sename, lvl, NULL, &sc);
276 +       if (role != NULL && role[0])
277 +               r = get_default_context_with_rolelevel(sename, role, lvl, NULL,
278 +                                                      &sc);
279 +       else
280 +               r = get_default_context_with_level(sename, lvl, NULL, &sc);
281  #else
282 -       r = get_default_context(sename, NULL, &sc);
283 +       if (role != NULL && role[0])
284 +               r = get_default_context_with_role(sename, role, NULL, &sc);
285 +       else
286 +               r = get_default_context(sename, NULL, &sc);
287  #endif
288  
289         if (r != 0) {
290 @@ -102,7 +115,7 @@
291  
292  /* Set the execution context to the default for the specified user */
293  void
294 -ssh_selinux_setup_exec_context(char *pwname)
295 +ssh_selinux_setup_exec_context(char *pwname, const char *role)
296  {
297         security_context_t user_ctx = NULL;
298  
299 @@ -111,7 +124,7 @@
300  
301         debug3("%s: setting execution context", __func__);
302  
303 -       user_ctx = ssh_selinux_getctxbyname(pwname);
304 +       user_ctx = ssh_selinux_getctxbyname(pwname, role);
305         if (setexeccon(user_ctx) != 0) {
306                 switch (security_getenforce()) {
307                 case -1:
308 @@ -133,7 +146,7 @@
309  
310  /* Set the TTY context for the specified user */
311  void
312 -ssh_selinux_setup_pty(char *pwname, const char *tty)
313 +ssh_selinux_setup_pty(char *pwname, const char *tty, const char *role)
314  {
315         security_context_t new_tty_ctx = NULL;
316         security_context_t user_ctx = NULL;
317 @@ -144,7 +157,7 @@
318  
319         debug3("%s: setting TTY context on %s", __func__, tty);
320  
321 -       user_ctx = ssh_selinux_getctxbyname(pwname);
322 +       user_ctx = ssh_selinux_getctxbyname(pwname, role);
323  
324         /* XXX: should these calls fatal() upon failure in enforcing mode? */
325  
326 Index: b/openbsd-compat/port-linux.h
327 ===================================================================
328 --- a/openbsd-compat/port-linux.h
329 +++ b/openbsd-compat/port-linux.h
330 @@ -21,8 +21,8 @@
331  
332  #ifdef WITH_SELINUX
333  int ssh_selinux_enabled(void);
334 -void ssh_selinux_setup_pty(char *, const char *);
335 -void ssh_selinux_setup_exec_context(char *);
336 +void ssh_selinux_setup_pty(char *, const char *, const char *);
337 +void ssh_selinux_setup_exec_context(char *, const char *);
338  void ssh_selinux_change_context(const char *);
339  void ssh_selinux_setfscreatecon(const char *);
340  #endif
341 Index: b/platform.c
342 ===================================================================
343 --- a/platform.c
344 +++ b/platform.c
345 @@ -134,7 +134,7 @@
346   * called if sshd is running as root.
347   */
348  void
349 -platform_setusercontext_post_groups(struct passwd *pw)
350 +platform_setusercontext_post_groups(struct passwd *pw, const char *role)
351  {
352  #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
353         /*
354 @@ -181,7 +181,7 @@
355         }
356  #endif /* HAVE_SETPCRED */
357  #ifdef WITH_SELINUX
358 -       ssh_selinux_setup_exec_context(pw->pw_name);
359 +       ssh_selinux_setup_exec_context(pw->pw_name, role);
360  #endif
361  }
362  
363 Index: b/platform.h
364 ===================================================================
365 --- a/platform.h
366 +++ b/platform.h
367 @@ -26,7 +26,7 @@
368  void platform_post_fork_child(void);
369  int  platform_privileged_uidswap(void);
370  void platform_setusercontext(struct passwd *);
371 -void platform_setusercontext_post_groups(struct passwd *);
372 +void platform_setusercontext_post_groups(struct passwd *, const char *);
373  char *platform_get_krb5_client(const char *);
374  char *platform_krb5_get_principal_name(const char *);
375  
376 Index: b/session.c
377 ===================================================================
378 --- a/session.c
379 +++ b/session.c
380 @@ -1467,7 +1467,7 @@
381  
382  /* Set login name, uid, gid, and groups. */
383  void
384 -do_setusercontext(struct passwd *pw)
385 +do_setusercontext(struct passwd *pw, const char *role)
386  {
387         char *chroot_path, *tmp;
388  
389 @@ -1495,7 +1495,7 @@
390                 endgrent();
391  #endif
392  
393 -               platform_setusercontext_post_groups(pw);
394 +               platform_setusercontext_post_groups(pw, role);
395  
396                 if (options.chroot_directory != NULL &&
397                     strcasecmp(options.chroot_directory, "none") != 0) {
398 @@ -1618,7 +1618,7 @@
399  
400         /* Force a password change */
401         if (s->authctxt->force_pwchange) {
402 -               do_setusercontext(pw);
403 +               do_setusercontext(pw, s->authctxt->role);
404                 child_close_fds();
405                 do_pwchange(s);
406                 exit(1);
407 @@ -1645,7 +1645,7 @@
408                 /* When PAM is enabled we rely on it to do the nologin check */
409                 if (!options.use_pam)
410                         do_nologin(pw);
411 -               do_setusercontext(pw);
412 +               do_setusercontext(pw, s->authctxt->role);
413                 /*
414                  * PAM session modules in do_setusercontext may have
415                  * generated messages, so if this in an interactive
416 @@ -2057,7 +2057,7 @@
417         tty_parse_modes(s->ttyfd, &n_bytes);
418  
419         if (!use_privsep)
420 -               pty_setowner(s->pw, s->tty);
421 +               pty_setowner(s->pw, s->tty, s->authctxt->role);
422  
423         /* Set window size from the packet. */
424         pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
425 Index: b/session.h
426 ===================================================================
427 --- a/session.h
428 +++ b/session.h
429 @@ -76,7 +76,7 @@
430  Session        *session_new(void);
431  Session        *session_by_tty(char *);
432  void    session_close(Session *);
433 -void    do_setusercontext(struct passwd *);
434 +void    do_setusercontext(struct passwd *, const char *);
435  void    child_set_env(char ***envp, u_int *envsizep, const char *name,
436                        const char *value);
437  
438 Index: b/sshd.c
439 ===================================================================
440 --- a/sshd.c
441 +++ b/sshd.c
442 @@ -707,7 +707,7 @@
443         RAND_seed(rnd, sizeof(rnd));
444  
445         /* Drop privileges */
446 -       do_setusercontext(authctxt->pw);
447 +       do_setusercontext(authctxt->pw, authctxt->role);
448  
449   skip:
450         /* It is safe now to apply the key state */
451 Index: b/sshpty.c
452 ===================================================================
453 --- a/sshpty.c
454 +++ b/sshpty.c
455 @@ -200,7 +200,7 @@
456  }
457  
458  void
459 -pty_setowner(struct passwd *pw, const char *tty)
460 +pty_setowner(struct passwd *pw, const char *tty, const char *role)
461  {
462         struct group *grp;
463         gid_t gid;
464 @@ -227,7 +227,7 @@
465                     strerror(errno));
466  
467  #ifdef WITH_SELINUX
468 -       ssh_selinux_setup_pty(pw->pw_name, tty);
469 +       ssh_selinux_setup_pty(pw->pw_name, tty, role);
470  #endif
471  
472         if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
473 Index: b/sshpty.h
474 ===================================================================
475 --- a/sshpty.h
476 +++ b/sshpty.h
477 @@ -24,4 +24,4 @@
478  void    pty_release(const char *);
479  void    pty_make_controlling_tty(int *, const char *);
480  void    pty_change_window_size(int, u_int, u_int, u_int, u_int);
481 -void    pty_setowner(struct passwd *, const char *);
482 +void    pty_setowner(struct passwd *, const char *, const char *);