1761efaa7SDag-Erling Smørgrav /* $Id: port-linux.c,v 1.3 2006/09/01 05:38:41 djm 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 */ 39761efaa7SDag-Erling Smørgrav static 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); 82761efaa7SDag-Erling Smørgrav default: 83761efaa7SDag-Erling Smørgrav fatal("%s: Failed to get default SELinux security " 84761efaa7SDag-Erling Smørgrav "context for %s (in enforcing mode)", 85761efaa7SDag-Erling Smørgrav __func__, pwname); 86761efaa7SDag-Erling Smørgrav } 87761efaa7SDag-Erling Smørgrav } 88761efaa7SDag-Erling Smørgrav 89761efaa7SDag-Erling Smørgrav #ifdef HAVE_GETSEUSERBYNAME 90761efaa7SDag-Erling Smørgrav if (sename != NULL) 91761efaa7SDag-Erling Smørgrav xfree(sename); 92761efaa7SDag-Erling Smørgrav if (lvl != NULL) 93761efaa7SDag-Erling Smørgrav xfree(lvl); 94761efaa7SDag-Erling Smørgrav #endif 95761efaa7SDag-Erling Smørgrav 96761efaa7SDag-Erling Smørgrav return (sc); 97761efaa7SDag-Erling Smørgrav } 98761efaa7SDag-Erling Smørgrav 99761efaa7SDag-Erling Smørgrav /* Set the execution context to the default for the specified user */ 100761efaa7SDag-Erling Smørgrav void 101761efaa7SDag-Erling Smørgrav ssh_selinux_setup_exec_context(char *pwname) 102761efaa7SDag-Erling Smørgrav { 103761efaa7SDag-Erling Smørgrav security_context_t user_ctx = NULL; 104761efaa7SDag-Erling Smørgrav 105761efaa7SDag-Erling Smørgrav if (!ssh_selinux_enabled()) 106761efaa7SDag-Erling Smørgrav return; 107761efaa7SDag-Erling Smørgrav 108761efaa7SDag-Erling Smørgrav debug3("%s: setting execution context", __func__); 109761efaa7SDag-Erling Smørgrav 110761efaa7SDag-Erling Smørgrav user_ctx = ssh_selinux_getctxbyname(pwname); 111761efaa7SDag-Erling Smørgrav if (setexeccon(user_ctx) != 0) { 112761efaa7SDag-Erling Smørgrav switch (security_getenforce()) { 113761efaa7SDag-Erling Smørgrav case -1: 114761efaa7SDag-Erling Smørgrav fatal("%s: security_getenforce() failed", __func__); 115761efaa7SDag-Erling Smørgrav case 0: 116761efaa7SDag-Erling Smørgrav error("%s: Failed to set SELinux execution " 117761efaa7SDag-Erling Smørgrav "context for %s", __func__, pwname); 118761efaa7SDag-Erling Smørgrav default: 119761efaa7SDag-Erling Smørgrav fatal("%s: Failed to set SELinux execution context " 120761efaa7SDag-Erling Smørgrav "for %s (in enforcing mode)", __func__, pwname); 121761efaa7SDag-Erling Smørgrav } 122761efaa7SDag-Erling Smørgrav } 123761efaa7SDag-Erling Smørgrav if (user_ctx != NULL) 124761efaa7SDag-Erling Smørgrav freecon(user_ctx); 125761efaa7SDag-Erling Smørgrav 126761efaa7SDag-Erling Smørgrav debug3("%s: done", __func__); 127761efaa7SDag-Erling Smørgrav } 128761efaa7SDag-Erling Smørgrav 129761efaa7SDag-Erling Smørgrav /* Set the TTY context for the specified user */ 130761efaa7SDag-Erling Smørgrav void 131761efaa7SDag-Erling Smørgrav ssh_selinux_setup_pty(char *pwname, const char *tty) 132761efaa7SDag-Erling Smørgrav { 133761efaa7SDag-Erling Smørgrav security_context_t new_tty_ctx = NULL; 134761efaa7SDag-Erling Smørgrav security_context_t user_ctx = NULL; 135761efaa7SDag-Erling Smørgrav security_context_t old_tty_ctx = NULL; 136761efaa7SDag-Erling Smørgrav 137761efaa7SDag-Erling Smørgrav if (!ssh_selinux_enabled()) 138761efaa7SDag-Erling Smørgrav return; 139761efaa7SDag-Erling Smørgrav 140761efaa7SDag-Erling Smørgrav debug3("%s: setting TTY context on %s", __func__, tty); 141761efaa7SDag-Erling Smørgrav 142761efaa7SDag-Erling Smørgrav user_ctx = ssh_selinux_getctxbyname(pwname); 143761efaa7SDag-Erling Smørgrav 144761efaa7SDag-Erling Smørgrav /* XXX: should these calls fatal() upon failure in enforcing mode? */ 145761efaa7SDag-Erling Smørgrav 146761efaa7SDag-Erling Smørgrav if (getfilecon(tty, &old_tty_ctx) == -1) { 147761efaa7SDag-Erling Smørgrav error("%s: getfilecon: %s", __func__, strerror(errno)); 148761efaa7SDag-Erling Smørgrav goto out; 149761efaa7SDag-Erling Smørgrav } 150761efaa7SDag-Erling Smørgrav 151761efaa7SDag-Erling Smørgrav if (security_compute_relabel(user_ctx, old_tty_ctx, 152761efaa7SDag-Erling Smørgrav SECCLASS_CHR_FILE, &new_tty_ctx) != 0) { 153761efaa7SDag-Erling Smørgrav error("%s: security_compute_relabel: %s", 154761efaa7SDag-Erling Smørgrav __func__, strerror(errno)); 155761efaa7SDag-Erling Smørgrav goto out; 156761efaa7SDag-Erling Smørgrav } 157761efaa7SDag-Erling Smørgrav 158761efaa7SDag-Erling Smørgrav if (setfilecon(tty, new_tty_ctx) != 0) 159761efaa7SDag-Erling Smørgrav error("%s: setfilecon: %s", __func__, strerror(errno)); 160761efaa7SDag-Erling Smørgrav out: 161761efaa7SDag-Erling Smørgrav if (new_tty_ctx != NULL) 162761efaa7SDag-Erling Smørgrav freecon(new_tty_ctx); 163761efaa7SDag-Erling Smørgrav if (old_tty_ctx != NULL) 164761efaa7SDag-Erling Smørgrav freecon(old_tty_ctx); 165761efaa7SDag-Erling Smørgrav if (user_ctx != NULL) 166761efaa7SDag-Erling Smørgrav freecon(user_ctx); 167761efaa7SDag-Erling Smørgrav debug3("%s: done", __func__); 168761efaa7SDag-Erling Smørgrav } 169761efaa7SDag-Erling Smørgrav #endif /* WITH_SELINUX */ 170