1 /* $Id: port-linux.c,v 1.5 2008/03/26 20:27:21 dtucker Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com> 5 * Copyright (c) 2006 Damien Miller <djm@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* 21 * Linux-specific portability code - just SELinux support at present 22 */ 23 24 #include "includes.h" 25 26 #include <errno.h> 27 #include <stdarg.h> 28 #include <string.h> 29 30 #ifdef WITH_SELINUX 31 #include "log.h" 32 #include "port-linux.h" 33 34 #include <selinux/selinux.h> 35 #include <selinux/flask.h> 36 #include <selinux/get_context_list.h> 37 38 /* Wrapper around is_selinux_enabled() to log its return value once only */ 39 int 40 ssh_selinux_enabled(void) 41 { 42 static int enabled = -1; 43 44 if (enabled == -1) { 45 enabled = is_selinux_enabled(); 46 debug("SELinux support %s", enabled ? "enabled" : "disabled"); 47 } 48 49 return (enabled); 50 } 51 52 /* Return the default security context for the given username */ 53 static security_context_t 54 ssh_selinux_getctxbyname(char *pwname) 55 { 56 security_context_t sc; 57 char *sename = NULL, *lvl = NULL; 58 int r; 59 60 #ifdef HAVE_GETSEUSERBYNAME 61 if (getseuserbyname(pwname, &sename, &lvl) != 0) 62 return NULL; 63 #else 64 sename = pwname; 65 lvl = NULL; 66 #endif 67 68 #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL 69 r = get_default_context_with_level(sename, lvl, NULL, &sc); 70 #else 71 r = get_default_context(sename, NULL, &sc); 72 #endif 73 74 if (r != 0) { 75 switch (security_getenforce()) { 76 case -1: 77 fatal("%s: ssh_selinux_getctxbyname: " 78 "security_getenforce() failed", __func__); 79 case 0: 80 error("%s: Failed to get default SELinux security " 81 "context for %s", __func__, pwname); 82 break; 83 default: 84 fatal("%s: Failed to get default SELinux security " 85 "context for %s (in enforcing mode)", 86 __func__, pwname); 87 } 88 } 89 90 #ifdef HAVE_GETSEUSERBYNAME 91 if (sename != NULL) 92 xfree(sename); 93 if (lvl != NULL) 94 xfree(lvl); 95 #endif 96 97 return (sc); 98 } 99 100 /* Set the execution context to the default for the specified user */ 101 void 102 ssh_selinux_setup_exec_context(char *pwname) 103 { 104 security_context_t user_ctx = NULL; 105 106 if (!ssh_selinux_enabled()) 107 return; 108 109 debug3("%s: setting execution context", __func__); 110 111 user_ctx = ssh_selinux_getctxbyname(pwname); 112 if (setexeccon(user_ctx) != 0) { 113 switch (security_getenforce()) { 114 case -1: 115 fatal("%s: security_getenforce() failed", __func__); 116 case 0: 117 error("%s: Failed to set SELinux execution " 118 "context for %s", __func__, pwname); 119 break; 120 default: 121 fatal("%s: Failed to set SELinux execution context " 122 "for %s (in enforcing mode)", __func__, pwname); 123 } 124 } 125 if (user_ctx != NULL) 126 freecon(user_ctx); 127 128 debug3("%s: done", __func__); 129 } 130 131 /* Set the TTY context for the specified user */ 132 void 133 ssh_selinux_setup_pty(char *pwname, const char *tty) 134 { 135 security_context_t new_tty_ctx = NULL; 136 security_context_t user_ctx = NULL; 137 security_context_t old_tty_ctx = NULL; 138 139 if (!ssh_selinux_enabled()) 140 return; 141 142 debug3("%s: setting TTY context on %s", __func__, tty); 143 144 user_ctx = ssh_selinux_getctxbyname(pwname); 145 146 /* XXX: should these calls fatal() upon failure in enforcing mode? */ 147 148 if (getfilecon(tty, &old_tty_ctx) == -1) { 149 error("%s: getfilecon: %s", __func__, strerror(errno)); 150 goto out; 151 } 152 153 if (security_compute_relabel(user_ctx, old_tty_ctx, 154 SECCLASS_CHR_FILE, &new_tty_ctx) != 0) { 155 error("%s: security_compute_relabel: %s", 156 __func__, strerror(errno)); 157 goto out; 158 } 159 160 if (setfilecon(tty, new_tty_ctx) != 0) 161 error("%s: setfilecon: %s", __func__, strerror(errno)); 162 out: 163 if (new_tty_ctx != NULL) 164 freecon(new_tty_ctx); 165 if (old_tty_ctx != NULL) 166 freecon(old_tty_ctx); 167 if (user_ctx != NULL) 168 freecon(user_ctx); 169 debug3("%s: done", __func__); 170 } 171 #endif /* WITH_SELINUX */ 172