aboutsummaryrefslogtreecommitdiff
path: root/src/rc/rc-selinux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rc/rc-selinux.c')
-rw-r--r--src/rc/rc-selinux.c417
1 files changed, 0 insertions, 417 deletions
diff --git a/src/rc/rc-selinux.c b/src/rc/rc-selinux.c
deleted file mode 100644
index 8364a5f0..00000000
--- a/src/rc/rc-selinux.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * rc-selinux.c
- * SELinux helpers to get and set contexts.
- */
-
-/*
- * Copyright (c) 2014-2015 The OpenRC Authors.
- * See the Authors file at the top-level directory of this distribution and
- * https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS
- *
- * This file is part of OpenRC. It is subject to the license terms in
- * the LICENSE file found in the top-level directory of this
- * distribution and at https://github.com/OpenRC/openrc/blob/HEAD/LICENSE
- * This file may not be copied, modified, propagated, or distributed
- * except according to the terms contained in the LICENSE file.
- */
-
-#include <stddef.h>
-#include <errno.h>
-#include <dlfcn.h>
-#include <ctype.h>
-#include <limits.h>
-#include <pwd.h>
-#include <unistd.h>
-
-#include <selinux/selinux.h>
-#include <selinux/label.h>
-#include <selinux/get_default_type.h>
-#include <selinux/context.h>
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "einfo.h"
-#include "queue.h"
-#include "rc.h"
-#include "rc-misc.h"
-#include "rc-plugin.h"
-#include "rc-selinux.h"
-
-/* the context files for selinux */
-#define INITRC_FILE "initrc_context"
-
-#ifdef HAVE_AUDIT
-#include <libaudit.h>
-#endif
-
-/* PAM or shadow for authentication */
-#ifdef HAVE_PAM
-# define PAM_SERVICE_NAME "run_init" /* the name of this program for PAM */
-# include <security/pam_appl.h>
-# include <security/pam_misc.h>
-#else
-# define PASSWORD_PROMPT "Password:"
-# include <crypt.h>
-# include <shadow.h>
-# include <string.h>
-#endif
-
-
-/* The handle for the fcontext lookups */
-static struct selabel_handle *hnd = NULL;
-
-int selinux_util_label(const char *path)
-{
- int retval = 0;
- int enforce;
- struct stat st;
- char *con;
-
- enforce = security_getenforce();
- if (retval < 0)
- return retval;
-
- if (!hnd)
- return (enforce) ? -1 : 0;
-
- retval = lstat(path, &st);
- if (retval < 0) {
- if (errno == ENOENT)
- return 0;
- return (enforce) ? -1 : 0;
- }
-
- /* lookup the context */
- retval = selabel_lookup_raw(hnd, &con, path, st.st_mode);
- if (retval < 0) {
- if (errno == ENOENT)
- return 0;
- return (enforce) ? -1 : 0;
- }
-
- /* apply the context */
- retval = lsetfilecon(path, con);
- freecon(con);
- if (retval < 0) {
- if (errno == ENOENT)
- return 0;
- if (errno == ENOTSUP)
- return 0;
- return (enforce) ? -1 : 0;
- }
-
- return 0;
-}
-
-/*
- * Open the label handle
- * returns 1 on success, 0 if no selinux, negative on error
- */
-int selinux_util_open(void)
-{
- int retval = 0;
-
- retval = is_selinux_enabled();
- if (retval <= 0)
- return retval;
-
- hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
- if (!hnd)
- return -2;
-
- return 1;
-}
-
-/*
- * Close the label handle
- * returns 1 on success, 0 if no selinux, negative on error
- */
-int selinux_util_close(void)
-{
- int retval = 0;
-
- retval = is_selinux_enabled();
- if (retval <= 0)
- return retval;
-
- if (hnd) {
- selabel_close(hnd);
- hnd = NULL;
- }
-
- return 0;
-}
-
-/*
- * This will check the users password and return 0 on success or -1 on fail
- *
- * We ask for the password to make sure it is intended vs run by malicious software.
- * Actual authorization is covered by the policy itself.
- */
-static int check_password(char *username)
-{
- int ret = 1;
-#ifdef HAVE_PAM
- pam_handle_t *pamh;
- int pam_err = 0;
- const struct pam_conv pconv = {
- misc_conv,
- NULL
- };
-
- pam_err = pam_start(PAM_SERVICE_NAME, username, &pconv, &pamh);
- if (pam_err != PAM_SUCCESS) {
- ret = -1;
- goto outpam;
- }
-
- pam_err = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK);
- if (pam_err != PAM_SUCCESS) {
- ret = -1;
- goto outpam;
- }
-
- ret = 0;
-outpam:
- pam_end(pamh, pam_err);
- pamh = NULL;
-
-#else /* authenticating via /etc/shadow instead */
- struct spwd *spw;
- char *password;
- char *attempt;
-
- spw = getspnam(username);
- if (!spw) {
- eerror("Failed to read shadow entry");
- ret = -1;
- goto outshadow;
- }
-
- attempt = getpass(PASSWORD_PROMPT);
- if (!attempt) {
- ret = -1;
- goto outshadow;
- }
-
- if (*spw->sp_pwdp == '\0' && *attempt == '\0') {
- ret = -1;
- goto outshadow;
- }
-
- /* salt must be at least two characters long */
- if (!(spw->sp_pwdp[0] && spw->sp_pwdp[1])) {
- ret = -1;
- goto outshadow;
- }
-
- /* encrypt the password attempt */
- password = crypt(attempt, spw->sp_pwdp);
-
- if (password && strcmp(password, spw->sp_pwdp) == 0)
- ret = 0;
- else
- ret = -1;
-outshadow:
-#endif
- return ret;
-}
-
-/* Authenticates the user, returns 0 on success, 1 on fail */
-static int check_auth()
-{
- struct passwd *pw;
- uid_t uid;
-
-#ifdef HAVE_AUDIT
- uid = audit_getloginuid();
- if (uid == (uid_t) -1)
- uid = getuid();
-#else
- uid = getuid();
-#endif
-
- pw = getpwuid(uid);
- if (!pw) {
- eerror("cannot find your entry in the passwd file.");
- return (-1);
- }
-
- printf("Authenticating %s.\n", pw->pw_name);
-
- /* do the actual check */
- if (check_password(pw->pw_name) == 0) {
- return 0;
- }
-
- eerrorx("Authentication failed for %s", pw->pw_name);
- return 1;
-}
-
-/*
- * Read the context from the given context file. context must be free'd by the user.
- */
-static int read_context_file(const char *filename, char **context)
-{
- int ret = -1;
- FILE *fp;
- char *filepath = NULL;
- char *line = NULL;
- char *p;
- char *p2;
- size_t len = 0;
- ssize_t read;
-
- xasprintf(&filepath, "%s/%s", selinux_contexts_path(), filename);
-
- fp = fopen(filepath, "r");
- if (fp == NULL) {
- eerror("Failed to open context file: %s", filename);
- free(filepath);
- return -1;
- }
-
- while ((read = getline(&line, &len, fp)) != -1) {
- /* cut off spaces before the string */
- p = line;
- while (isspace(*p) && *p != '\0')
- p++;
-
- /* empty string, skip */
- if (*p == '\0')
- continue;
-
- /* cut off spaces after the string */
- p2 = p;
- while (!isspace(*p2) && *p2 != '\0')
- p2++;
- *p2 = '\0';
-
- *context = xstrdup(p);
- ret = 0;
- break;
- }
-
- free(line);
- free(filepath);
- fclose(fp);
- return ret;
-}
-
-static int read_run_init_context(char **context)
-{
- int ret = -1;
- RC_STRINGLIST *list;
- char *value = NULL;
-
- list = rc_config_list(selinux_openrc_contexts_path());
- if (list == NULL)
- return ret;
-
- value = rc_config_value(list, "run_init");
- if (value != NULL && strlen(value) > 0) {
- *context = xstrdup(value);
- ret = 0;
- }
-
- rc_stringlist_free(list);
- return ret;
-}
-
-void selinux_setup(char **argv)
-{
- char *new_context = NULL;
- char *curr_context = NULL;
- context_t curr_con;
- char *curr_t = NULL;
- char *run_init_t = NULL;
-
- /* Return, if selinux is disabled. */
- if (is_selinux_enabled() < 1) {
- return;
- }
-
- if (read_run_init_context(&run_init_t) != 0) {
- /* assume a reasonable default, rather than bailing out */
- run_init_t = xstrdup("run_init_t");
- ewarn("Assuming SELinux run_init type is %s", run_init_t);
- }
-
- /* Get our current context. */
- if (getcon(&curr_context) < 0) {
- if (errno == ENOENT) {
- /* should only hit this if proc is not mounted. this
- * happens on Gentoo right after init starts, when
- * the init script processing starts.
- */
- goto out;
- } else {
- perror("getcon");
- exit(1);
- }
- }
-
- /* extract the type from the context */
- curr_con = context_new(curr_context);
- if (!curr_con) {
- free(curr_context);
- goto out;
- }
-
- curr_t = xstrdup(context_type_get(curr_con));
- if (!curr_t) {
- context_free(curr_con);
- free(curr_context);
- goto out;
- }
-
- /* dont need them anymore so free() now */
- context_free(curr_con);
- free(curr_context);
-
- /* if we are not in the run_init domain, we should not do anything */
- if (strncmp(run_init_t, curr_t, strlen(run_init_t)) != 0) {
- goto out;
- }
-
- free(curr_t);
- free(run_init_t);
-
- if (check_auth() != 0) {
- eerrorx("Authentication failed.");
- }
-
- /* Get the context for the script to be run in. */
- if (read_context_file(INITRC_FILE, &new_context) != 0) {
- /* assume a reasonable default, rather than bailing out */
- new_context = xstrdup("system_u:system_r:initrc_t");
- ewarn("Assuming SELinux initrc context is %s", new_context);
- }
-
- /* Set the new context */
- if (setexeccon(new_context) < 0) {
- eerrorx("Could not set SELinux exec context to %s.", new_context);
- }
-
- free(new_context);
-
- /*
- * exec will recycle ptys so try and use open_init_pty if it exists
- * which will open the pty with initrc_devpts_t, if it doesnt exist,
- * fall back to plain exec
- */
- if (!access("/usr/sbin/open_init_pty", X_OK)) {
- if (execvp("/usr/sbin/open_init_pty", argv)) {
- perror("execvp");
- exit(-1);
- }
- } else if (execvp(argv[1], argv + 1)) {
- perror("execvp");
- exit(-1);
- }
-
-out:
- free(run_init_t);
- free(curr_t);
-}