1d4af9e69SDag-Erling Smørgrav /* $Id: port-linux.c,v 1.5 2008/03/26 20:27:21 dtucker Exp $ */ 2761efaa7SDag-Erling Smørgrav 3761efaa7SDag-Erling Smørgrav /* 4761efaa7SDag-Erling Smørgrav * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com> 5761efaa7SDag-Erling Smørgrav * Copyright (c) 2006 Damien Miller <djm@openbsd.org> 6761efaa7SDag-Erling Smørgrav * 7761efaa7SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 8761efaa7SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 9761efaa7SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 10761efaa7SDag-Erling Smørgrav * 11761efaa7SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12761efaa7SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13761efaa7SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14761efaa7SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15761efaa7SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16761efaa7SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17761efaa7SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18761efaa7SDag-Erling Smørgrav */ 19761efaa7SDag-Erling Smørgrav 20761efaa7SDag-Erling Smørgrav /* 21761efaa7SDag-Erling Smørgrav * Linux-specific portability code - just SELinux support at present 22761efaa7SDag-Erling Smørgrav */ 23761efaa7SDag-Erling Smørgrav 24761efaa7SDag-Erling Smørgrav #include "includes.h" 25761efaa7SDag-Erling Smørgrav 26761efaa7SDag-Erling Smørgrav #include <errno.h> 27761efaa7SDag-Erling Smørgrav #include <stdarg.h> 28761efaa7SDag-Erling Smørgrav #include <string.h> 29761efaa7SDag-Erling Smørgrav 30761efaa7SDag-Erling Smørgrav #ifdef WITH_SELINUX 31761efaa7SDag-Erling Smørgrav #include "log.h" 32761efaa7SDag-Erling Smørgrav #include "port-linux.h" 33761efaa7SDag-Erling Smørgrav 34761efaa7SDag-Erling Smørgrav #include <selinux/selinux.h> 35761efaa7SDag-Erling Smørgrav #include <selinux/flask.h> 36761efaa7SDag-Erling Smørgrav #include <selinux/get_context_list.h> 37761efaa7SDag-Erling Smørgrav 38761efaa7SDag-Erling Smørgrav /* Wrapper around is_selinux_enabled() to log its return value once only */ 39d4af9e69SDag-Erling Smørgrav int 40761efaa7SDag-Erling Smørgrav ssh_selinux_enabled(void) 41761efaa7SDag-Erling Smørgrav { 42761efaa7SDag-Erling Smørgrav static int enabled = -1; 43761efaa7SDag-Erling Smørgrav 44761efaa7SDag-Erling Smørgrav if (enabled == -1) { 45761efaa7SDag-Erling Smørgrav enabled = is_selinux_enabled(); 46761efaa7SDag-Erling Smørgrav debug("SELinux support %s", enabled ? "enabled" : "disabled"); 47761efaa7SDag-Erling Smørgrav } 48761efaa7SDag-Erling Smørgrav 49761efaa7SDag-Erling Smørgrav return (enabled); 50761efaa7SDag-Erling Smørgrav } 51761efaa7SDag-Erling Smørgrav 52761efaa7SDag-Erling Smørgrav /* Return the default security context for the given username */ 53761efaa7SDag-Erling Smørgrav static security_context_t 54761efaa7SDag-Erling Smørgrav ssh_selinux_getctxbyname(char *pwname) 55761efaa7SDag-Erling Smørgrav { 56761efaa7SDag-Erling Smørgrav security_context_t sc; 57761efaa7SDag-Erling Smørgrav char *sename = NULL, *lvl = NULL; 58761efaa7SDag-Erling Smørgrav int r; 59761efaa7SDag-Erling Smørgrav 60761efaa7SDag-Erling Smørgrav #ifdef HAVE_GETSEUSERBYNAME 61761efaa7SDag-Erling Smørgrav if (getseuserbyname(pwname, &sename, &lvl) != 0) 62761efaa7SDag-Erling Smørgrav return NULL; 63761efaa7SDag-Erling Smørgrav #else 64761efaa7SDag-Erling Smørgrav sename = pwname; 65761efaa7SDag-Erling Smørgrav lvl = NULL; 66761efaa7SDag-Erling Smørgrav #endif 67761efaa7SDag-Erling Smørgrav 68761efaa7SDag-Erling Smørgrav #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL 69761efaa7SDag-Erling Smørgrav r = get_default_context_with_level(sename, lvl, NULL, &sc); 70761efaa7SDag-Erling Smørgrav #else 71761efaa7SDag-Erling Smørgrav r = get_default_context(sename, NULL, &sc); 72761efaa7SDag-Erling Smørgrav #endif 73761efaa7SDag-Erling Smørgrav 74761efaa7SDag-Erling Smørgrav if (r != 0) { 75761efaa7SDag-Erling Smørgrav switch (security_getenforce()) { 76761efaa7SDag-Erling Smørgrav case -1: 77761efaa7SDag-Erling Smørgrav fatal("%s: ssh_selinux_getctxbyname: " 78761efaa7SDag-Erling Smørgrav "security_getenforce() failed", __func__); 79761efaa7SDag-Erling Smørgrav case 0: 80761efaa7SDag-Erling Smørgrav error("%s: Failed to get default SELinux security " 81761efaa7SDag-Erling Smørgrav "context for %s", __func__, pwname); 82d4af9e69SDag-Erling Smørgrav break; 83761efaa7SDag-Erling Smørgrav default: 84761efaa7SDag-Erling Smørgrav fatal("%s: Failed to get default SELinux security " 85761efaa7SDag-Erling Smørgrav "context for %s (in enforcing mode)", 86761efaa7SDag-Erling Smørgrav __func__, pwname); 87761efaa7SDag-Erling Smørgrav } 88761efaa7SDag-Erling Smørgrav } 89761efaa7SDag-Erling Smørgrav 90761efaa7SDag-Erling Smørgrav #ifdef HAVE_GETSEUSERBYNAME 91761efaa7SDag-Erling Smørgrav if (sename != NULL) 92761efaa7SDag-Erling Smørgrav xfree(sename); 93761efaa7SDag-Erling Smørgrav if (lvl != NULL) 94761efaa7SDag-Erling Smørgrav xfree(lvl); 95761efaa7SDag-Erling Smørgrav #endif 96761efaa7SDag-Erling Smørgrav 97761efaa7SDag-Erling Smørgrav return (sc); 98761efaa7SDag-Erling Smørgrav } 99761efaa7SDag-Erling Smørgrav 100761efaa7SDag-Erling Smørgrav /* Set the execution context to the default for the specified user */ 101761efaa7SDag-Erling Smørgrav void 102761efaa7SDag-Erling Smørgrav ssh_selinux_setup_exec_context(char *pwname) 103761efaa7SDag-Erling Smørgrav { 104761efaa7SDag-Erling Smørgrav security_context_t user_ctx = NULL; 105761efaa7SDag-Erling Smørgrav 106761efaa7SDag-Erling Smørgrav if (!ssh_selinux_enabled()) 107761efaa7SDag-Erling Smørgrav return; 108761efaa7SDag-Erling Smørgrav 109761efaa7SDag-Erling Smørgrav debug3("%s: setting execution context", __func__); 110761efaa7SDag-Erling Smørgrav 111761efaa7SDag-Erling Smørgrav user_ctx = ssh_selinux_getctxbyname(pwname); 112761efaa7SDag-Erling Smørgrav if (setexeccon(user_ctx) != 0) { 113761efaa7SDag-Erling Smørgrav switch (security_getenforce()) { 114761efaa7SDag-Erling Smørgrav case -1: 115761efaa7SDag-Erling Smørgrav fatal("%s: security_getenforce() failed", __func__); 116761efaa7SDag-Erling Smørgrav case 0: 117761efaa7SDag-Erling Smørgrav error("%s: Failed to set SELinux execution " 118761efaa7SDag-Erling Smørgrav "context for %s", __func__, pwname); 119d4af9e69SDag-Erling Smørgrav break; 120761efaa7SDag-Erling Smørgrav default: 121761efaa7SDag-Erling Smørgrav fatal("%s: Failed to set SELinux execution context " 122761efaa7SDag-Erling Smørgrav "for %s (in enforcing mode)", __func__, pwname); 123761efaa7SDag-Erling Smørgrav } 124761efaa7SDag-Erling Smørgrav } 125761efaa7SDag-Erling Smørgrav if (user_ctx != NULL) 126761efaa7SDag-Erling Smørgrav freecon(user_ctx); 127761efaa7SDag-Erling Smørgrav 128761efaa7SDag-Erling Smørgrav debug3("%s: done", __func__); 129761efaa7SDag-Erling Smørgrav } 130761efaa7SDag-Erling Smørgrav 131761efaa7SDag-Erling Smørgrav /* Set the TTY context for the specified user */ 132761efaa7SDag-Erling Smørgrav void 133761efaa7SDag-Erling Smørgrav ssh_selinux_setup_pty(char *pwname, const char *tty) 134761efaa7SDag-Erling Smørgrav { 135761efaa7SDag-Erling Smørgrav security_context_t new_tty_ctx = NULL; 136761efaa7SDag-Erling Smørgrav security_context_t user_ctx = NULL; 137761efaa7SDag-Erling Smørgrav security_context_t old_tty_ctx = NULL; 138761efaa7SDag-Erling Smørgrav 139761efaa7SDag-Erling Smørgrav if (!ssh_selinux_enabled()) 140761efaa7SDag-Erling Smørgrav return; 141761efaa7SDag-Erling Smørgrav 142761efaa7SDag-Erling Smørgrav debug3("%s: setting TTY context on %s", __func__, tty); 143761efaa7SDag-Erling Smørgrav 144761efaa7SDag-Erling Smørgrav user_ctx = ssh_selinux_getctxbyname(pwname); 145761efaa7SDag-Erling Smørgrav 146761efaa7SDag-Erling Smørgrav /* XXX: should these calls fatal() upon failure in enforcing mode? */ 147761efaa7SDag-Erling Smørgrav 148761efaa7SDag-Erling Smørgrav if (getfilecon(tty, &old_tty_ctx) == -1) { 149761efaa7SDag-Erling Smørgrav error("%s: getfilecon: %s", __func__, strerror(errno)); 150761efaa7SDag-Erling Smørgrav goto out; 151761efaa7SDag-Erling Smørgrav } 152761efaa7SDag-Erling Smørgrav 153761efaa7SDag-Erling Smørgrav if (security_compute_relabel(user_ctx, old_tty_ctx, 154761efaa7SDag-Erling Smørgrav SECCLASS_CHR_FILE, &new_tty_ctx) != 0) { 155761efaa7SDag-Erling Smørgrav error("%s: security_compute_relabel: %s", 156761efaa7SDag-Erling Smørgrav __func__, strerror(errno)); 157761efaa7SDag-Erling Smørgrav goto out; 158761efaa7SDag-Erling Smørgrav } 159761efaa7SDag-Erling Smørgrav 160761efaa7SDag-Erling Smørgrav if (setfilecon(tty, new_tty_ctx) != 0) 161761efaa7SDag-Erling Smørgrav error("%s: setfilecon: %s", __func__, strerror(errno)); 162761efaa7SDag-Erling Smørgrav out: 163761efaa7SDag-Erling Smørgrav if (new_tty_ctx != NULL) 164761efaa7SDag-Erling Smørgrav freecon(new_tty_ctx); 165761efaa7SDag-Erling Smørgrav if (old_tty_ctx != NULL) 166761efaa7SDag-Erling Smørgrav freecon(old_tty_ctx); 167761efaa7SDag-Erling Smørgrav if (user_ctx != NULL) 168761efaa7SDag-Erling Smørgrav freecon(user_ctx); 169761efaa7SDag-Erling Smørgrav debug3("%s: done", __func__); 170761efaa7SDag-Erling Smørgrav } 171761efaa7SDag-Erling Smørgrav #endif /* WITH_SELINUX */ 172