aboutsummaryrefslogtreecommitdiff
path: root/modules/pam_selinux/pam_selinux.c
diff options
context:
space:
mode:
authorSteve Langasek <steve.langasek@canonical.com>2020-08-11 14:54:29 -0700
committerSteve Langasek <steve.langasek@canonical.com>2020-08-11 14:54:29 -0700
commitf6d08ed47a3da3c08345bce2ca366e961c52ad7c (patch)
treedcbd0efb229b17f696f7195671f05b354b4f70fc /modules/pam_selinux/pam_selinux.c
parent668b13da8f830c38388cecac45539972e80cb246 (diff)
parent9e5bea9e146dee574796259ca464ad2435be3590 (diff)
downloadpam-f6d08ed47a3da3c08345bce2ca366e961c52ad7c.tar.gz
pam-f6d08ed47a3da3c08345bce2ca366e961c52ad7c.tar.bz2
pam-f6d08ed47a3da3c08345bce2ca366e961c52ad7c.zip
New upstream version 1.4.0
Diffstat (limited to 'modules/pam_selinux/pam_selinux.c')
-rw-r--r--modules/pam_selinux/pam_selinux.c164
1 files changed, 65 insertions, 99 deletions
diff --git a/modules/pam_selinux/pam_selinux.c b/modules/pam_selinux/pam_selinux.c
index 348cdd40..06c3ce65 100644
--- a/modules/pam_selinux/pam_selinux.c
+++ b/modules/pam_selinux/pam_selinux.c
@@ -36,7 +36,6 @@
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#include "config.h"
@@ -53,81 +52,80 @@
#include <fcntl.h>
#include <syslog.h>
-#define PAM_SM_AUTH
-#define PAM_SM_SESSION
-
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <security/pam_modutil.h>
#include <security/pam_ext.h>
+#include "pam_inline.h"
#include <selinux/selinux.h>
#include <selinux/get_context_list.h>
-#include <selinux/flask.h>
-#include <selinux/av_permissions.h>
-#include <selinux/selinux.h>
#include <selinux/context.h>
#include <selinux/get_default_type.h>
#ifdef HAVE_LIBAUDIT
#include <libaudit.h>
#include <sys/select.h>
-#include <errno.h>
#endif
/* Send audit message */
-static
-
-int send_audit_message(pam_handle_t *pamh, int success, security_context_t default_context,
- security_context_t selected_context)
+static void
+send_audit_message(const pam_handle_t *pamh, int success, const char *default_context,
+ const char *selected_context)
{
- int rc=0;
#ifdef HAVE_LIBAUDIT
char *msg = NULL;
int audit_fd = audit_open();
- security_context_t default_raw=NULL;
- security_context_t selected_raw=NULL;
+ char *default_raw = NULL;
+ char *selected_raw = NULL;
const void *tty = NULL, *rhost = NULL;
- rc = -1;
if (audit_fd < 0) {
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
- errno == EAFNOSUPPORT)
- return 0; /* No audit support in kernel */
- pam_syslog(pamh, LOG_ERR, "Error connecting to audit system.");
- return rc;
+ errno == EAFNOSUPPORT) {
+ goto fallback; /* No audit support in kernel */
+ }
+ pam_syslog(pamh, LOG_ERR, "Error connecting to audit system: %m");
+ goto fallback;
}
(void)pam_get_item(pamh, PAM_TTY, &tty);
(void)pam_get_item(pamh, PAM_RHOST, &rhost);
if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
- pam_syslog(pamh, LOG_ERR, "Error translating default context.");
+ pam_syslog(pamh, LOG_ERR, "Error translating default context '%s'.", default_context);
default_raw = NULL;
}
if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
- pam_syslog(pamh, LOG_ERR, "Error translating selected context.");
+ pam_syslog(pamh, LOG_ERR, "Error translating selected context '%s'.", selected_context);
selected_raw = NULL;
}
if (asprintf(&msg, "pam: default-context=%s selected-context=%s",
default_raw ? default_raw : (default_context ? default_context : "?"),
selected_raw ? selected_raw : (selected_context ? selected_context : "?")) < 0) {
+ msg = NULL; /* asprintf leaves msg in undefined state on failure */
pam_syslog(pamh, LOG_ERR, "Error allocating memory.");
- goto out;
+ goto fallback;
}
if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
msg, rhost, NULL, tty, success) <= 0) {
- pam_syslog(pamh, LOG_ERR, "Error sending audit message.");
- goto out;
+ pam_syslog(pamh, LOG_ERR, "Error sending audit message: %m");
+ goto fallback;
}
- rc = 0;
- out:
+ goto cleanup;
+
+ fallback:
+#endif /* HAVE_LIBAUDIT */
+ pam_syslog(pamh, LOG_NOTICE, "pam: default-context=%s selected-context=%s success %d",
+ default_context, selected_context, success);
+
+#ifdef HAVE_LIBAUDIT
+ cleanup:
free(msg);
freecon(default_raw);
freecon(selected_raw);
- close(audit_fd);
-#else
- pam_syslog(pamh, LOG_NOTICE, "pam: default-context=%s selected-context=%s success %d", default_context, selected_context, success);
-#endif
- return rc;
+ if (audit_fd >= 0)
+ close(audit_fd);
+#endif /* HAVE_LIBAUDIT */
}
+
static int
send_text (pam_handle_t *pamh, const char *text, int debug)
{
@@ -161,53 +159,17 @@ query_response (pam_handle_t *pamh, const char *text, const char *def,
return rc;
}
-static int mls_range_allowed(pam_handle_t *pamh, security_context_t src, security_context_t dst, int debug)
-{
- struct av_decision avd;
- int retval;
- security_class_t class;
- access_vector_t bit;
- context_t src_context;
- context_t dst_context;
-
- class = string_to_security_class("context");
- if (!class) {
- pam_syslog(pamh, LOG_ERR, "Failed to translate security class context. %m");
- return 0;
- }
-
- bit = string_to_av_perm(class, "contains");
- if (!bit) {
- pam_syslog(pamh, LOG_ERR, "Failed to translate av perm contains. %m");
- return 0;
- }
-
- src_context = context_new (src);
- dst_context = context_new (dst);
- context_range_set(dst_context, context_range_get(src_context));
- if (debug)
- pam_syslog(pamh, LOG_NOTICE, "Checking if %s mls range valid for %s", dst, context_str(dst_context));
-
- retval = security_compute_av(context_str(dst_context), dst, class, bit, &avd);
- context_free(src_context);
- context_free(dst_context);
- if (retval || ((bit & avd.allowed) != bit))
- return 0;
-
- return 1;
-}
-
-static security_context_t
-config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_current_range, int debug)
+static char *
+config_context (pam_handle_t *pamh, const char *defaultcon, int use_current_range, int debug)
{
- security_context_t newcon=NULL;
+ char *newcon = NULL;
context_t new_context;
int mls_enabled = is_selinux_mls_enabled();
char *response=NULL;
char *type=NULL;
char resp_val = 0;
- pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), defaultcon);
+ pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("The default security context is %s."), defaultcon);
while (1) {
if (query_response(pamh,
@@ -227,7 +189,8 @@ config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_curre
if (query_response(pamh, _("role:"), context_role_get(new_context),
&response, debug) == PAM_SUCCESS && response[0]) {
if (get_default_type(response, &type)) {
- pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), response);
+ pam_prompt(pamh, PAM_ERROR_MSG, NULL,
+ _("There is no default type for role %s."), response);
_pam_drop(response);
continue;
} else {
@@ -243,7 +206,7 @@ config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_curre
if (mls_enabled)
{
if (use_current_range) {
- security_context_t mycon = NULL;
+ char *mycon = NULL;
context_t my_context;
if (getcon(&mycon) != 0)
@@ -277,22 +240,23 @@ config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_curre
goto fail_set;
context_free(new_context);
- /* we have to check that this user is allowed to go into the
- range they have specified ... role is tied to an seuser, so that'll
- be checked at setexeccon time */
- if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) {
+ /* we have to check that this user is allowed to go into the
+ range they have specified ... role is tied to an seuser, so that'll
+ be checked at setexeccon time */
+ if (mls_enabled &&
+ selinux_check_access(defaultcon, newcon, "context", "contains", NULL) != 0) {
pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon);
send_audit_message(pamh, 0, defaultcon, newcon);
free(newcon);
- goto fail_range;
+ goto fail_range;
}
return newcon;
}
else {
send_audit_message(pamh, 0, defaultcon, context_str(new_context));
- send_text(pamh,_("Not a valid security context"),debug);
+ send_text(pamh,_("This is not a valid security context."),debug);
}
context_free(new_context); /* next time around allocates another */
}
@@ -311,10 +275,10 @@ config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_curre
return NULL;
}
-static security_context_t
-context_from_env (pam_handle_t *pamh, security_context_t defaultcon, int env_params, int use_current_range, int debug)
+static char *
+context_from_env (pam_handle_t *pamh, const char *defaultcon, int env_params, int use_current_range, int debug)
{
- security_context_t newcon = NULL;
+ char *newcon = NULL;
context_t new_context;
context_t my_context = NULL;
int mls_enabled = is_selinux_mls_enabled();
@@ -348,7 +312,7 @@ context_from_env (pam_handle_t *pamh, security_context_t defaultcon, int env_par
}
if (use_current_range) {
- security_context_t mycon = NULL;
+ char *mycon = NULL;
if (getcon(&mycon) != 0)
goto fail_set;
@@ -388,7 +352,8 @@ context_from_env (pam_handle_t *pamh, security_context_t defaultcon, int env_par
/* we have to check that this user is allowed to go into the
range they have specified ... role is tied to an seuser, so that'll
be checked at setexeccon time */
- if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) {
+ if (mls_enabled &&
+ selinux_check_access(defaultcon, newcon, "context", "contains", NULL) != 0) {
pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon);
goto fail_set;
@@ -410,11 +375,11 @@ context_from_env (pam_handle_t *pamh, security_context_t defaultcon, int env_par
#define DATANAME "pam_selinux_context"
typedef struct {
- security_context_t exec_context;
- security_context_t prev_exec_context;
- security_context_t default_user_context;
- security_context_t tty_context;
- security_context_t prev_tty_context;
+ char *exec_context;
+ char *prev_exec_context;
+ char *default_user_context;
+ char *tty_context;
+ char *prev_tty_context;
char *tty_path;
} module_data_t;
@@ -455,7 +420,7 @@ get_item(const pam_handle_t *pamh, int item_type)
}
static int
-set_exec_context(const pam_handle_t *pamh, security_context_t context)
+set_exec_context(const pam_handle_t *pamh, const char *context)
{
if (setexeccon(context) == 0)
return 0;
@@ -465,7 +430,7 @@ set_exec_context(const pam_handle_t *pamh, security_context_t context)
}
static int
-set_file_context(const pam_handle_t *pamh, security_context_t context,
+set_file_context(const pam_handle_t *pamh, const char *context,
const char *file)
{
if (!file)
@@ -489,7 +454,7 @@ compute_exec_context(pam_handle_t *pamh, module_data_t *data,
#endif
char *seuser = NULL;
char *level = NULL;
- security_context_t *contextlist = NULL;
+ char **contextlist = NULL;
int num_contexts = 0;
const struct passwd *pwd;
@@ -541,7 +506,7 @@ compute_exec_context(pam_handle_t *pamh, module_data_t *data,
if (!data->exec_context) {
pam_syslog(pamh, LOG_ERR, "Unable to get valid context for %s", username);
pam_prompt(pamh, PAM_ERROR_MSG, NULL,
- _("Unable to get valid context for %s"), username);
+ _("A valid context for %s could not be obtained."), username);
}
if (getexeccon(&data->prev_exec_context) < 0)
@@ -555,7 +520,8 @@ compute_tty_context(const pam_handle_t *pamh, module_data_t *data)
{
const char *tty = get_item(pamh, PAM_TTY);
- if (!tty || !*tty || !strcmp(tty, "ssh") || !strncmp(tty, "NODEV", 5)) {
+ if (!tty || !*tty || !strcmp(tty, "ssh")
+ || pam_str_skip_prefix(tty, "NODEV") != NULL) {
tty = ttyname(STDIN_FILENO);
if (!tty || !*tty)
tty = ttyname(STDOUT_FILENO);
@@ -565,7 +531,7 @@ compute_tty_context(const pam_handle_t *pamh, module_data_t *data)
return PAM_SUCCESS;
}
- if (strncmp("/dev/", tty, 5)) {
+ if (pam_str_skip_prefix(tty, "/dev/") == NULL) {
if (asprintf(&data->tty_path, "%s%s", "/dev/", tty) < 0)
data->tty_path = NULL;
} else {
@@ -590,7 +556,7 @@ compute_tty_context(const pam_handle_t *pamh, module_data_t *data)
}
if (security_compute_relabel(data->exec_context, data->prev_tty_context,
- SECCLASS_CHR_FILE, &data->tty_context)) {
+ string_to_security_class("chr_file"), &data->tty_context)) {
data->tty_context = NULL;
pam_syslog(pamh, LOG_ERR, "Failed to compute new context for %s: %m",
data->tty_path);
@@ -660,7 +626,7 @@ set_context(pam_handle_t *pamh, const module_data_t *data,
char msg[PATH_MAX];
snprintf(msg, sizeof(msg),
- _("Security Context %s Assigned"), data->exec_context);
+ _("Security context %s has been assigned."), data->exec_context);
send_text(pamh, msg, debug);
}
#ifdef HAVE_SETKEYCREATECON
@@ -676,7 +642,7 @@ set_context(pam_handle_t *pamh, const module_data_t *data,
char msg[PATH_MAX];
snprintf(msg, sizeof(msg),
- _("Key Creation Context %s Assigned"), data->exec_context);
+ _("Key creation context %s has been assigned."), data->exec_context);
send_text(pamh, msg, debug);
}
#endif