|
From: <ssm...@us...> - 2006-11-13 23:47:22
|
Revision: 2078
http://svn.sourceforge.net/selinux/?rev=2078&view=rev
Author: ssmalley
Date: 2006-11-13 15:47:17 -0800 (Mon, 13 Nov 2006)
Log Message:
-----------
Author: Michael C Thompson
Email: tho...@us...
Subject: make newrole suid (take 3)
Date: Thu, 02 Nov 2006 19:03:34 -0600
Michael C Thompson wrote:
> The 8 patches are as follows:
> 1) Modifications to Makefile to support future patch needs
> Add newrole-lspp.pamd
> 2) New extract_pw_data function and use in main()
This is the 2nd of 8 patches.
This patch applies against policycoreutils-1.30.30-1.
This patch moves the parse /etc/passwd functionality from
main() into a separate function.
Changes:
* Introduces the extract_pw_data() function and uses it in main()
Signed-off-by: Michael Thompson <tho...@us...>
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:45:08 UTC (rev 2077)
+++ trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:47:17 UTC (rev 2078)
@@ -332,6 +332,61 @@
return found;
}
+/**
+ * Determine the Linux user identity to re-authenticate.
+ * If supported and set, use the login uid, as this should be more stable.
+ * Otherwise, use the real uid.
+ *
+ * This function assigns malloc'd memory into the pw_copy struct.
+ * Returns zero on success, non-zero otherwise
+ */
+int extract_pw_data(struct passwd *pw_copy)
+{
+ uid_t uid;
+ struct passwd *pw;
+
+#ifdef USE_AUDIT
+ uid = audit_getloginuid();
+ if (uid == (uid_t) - 1)
+ uid = getuid();
+#else
+ uid = getuid();
+#endif
+
+ setpwent();
+ pw = getpwuid(uid);
+ endpwent();
+ if (!(pw && pw->pw_name && pw->pw_name[0] && pw->pw_shell
+ && pw->pw_shell[0] && pw->pw_dir && pw->pw_dir[0])) {
+ fprintf(stderr,
+ _("cannot find valid entry in the passwd file.\n"));
+ return -1;
+ }
+
+ *pw_copy = *pw;
+ pw = pw_copy;
+ pw->pw_name = strdup(pw->pw_name);
+ pw->pw_dir = strdup(pw->pw_dir);
+ pw->pw_shell = strdup(pw->pw_shell);
+
+ if (! (pw->pw_name && pw->pw_dir && pw->pw_shell)) {
+ fprintf(stderr, _("Out of memory!\n"));
+ goto out_free;
+ }
+
+ if (verify_shell(pw->pw_shell) == 0) {
+ fprintf(stderr, _("Error! Shell is not valid.\n"));
+ goto out_free;
+ }
+ return 0;
+
+out_free:
+ free(pw->pw_name);
+ free(pw->pw_dir);
+ free(pw->pw_shell);
+ return -1;
+}
+
/*
* This function will drop the capabilities so that we are left
* only with access to the audit system. If the user is root, we leave
@@ -460,8 +515,7 @@
context_t context; /* manipulatable form of new_context */
- struct passwd *pw; /* struct derived from passwd file line */
- struct passwd pw_copy;
+ struct passwd pw; /* struct derived from passwd file line */
int clflag; /* holds codes for command line flags */
int flag_index; /* flag index in argv[] */
@@ -639,23 +693,9 @@
#endif
/* Get the passwd info for the Linux user identity. */
- pw = getpwuid(uid);
- if (!pw) {
- fprintf(stderr,
- _("cannot find your entry in the passwd file.\n"));
- exit(-1);
- }
- pw_copy = *pw;
- pw = &pw_copy;
- pw->pw_name = xstrdup(pw->pw_name);
- pw->pw_dir = xstrdup(pw->pw_dir);
- pw->pw_shell = xstrdup(pw->pw_shell);
+ if (extract_pw_data(&pw))
+ return -1;
- if (verify_shell(pw->pw_shell) == 0) {
- fprintf(stderr, _("Error! Shell is not valid.\n"));
- exit(-1);
- }
-
/* Get the tty name. Pam will need it. */
ttyn = ttyname(0);
if (!ttyn || *ttyn == '\0') {
@@ -664,7 +704,7 @@
exit(-1);
}
- printf(_("Authenticating %s.\n"), pw->pw_name);
+ printf(_("Authenticating %s.\n"), pw.pw_name);
/*
* Re-authenticate the user running this program.
@@ -673,13 +713,13 @@
* by policy). Trusted path mechanism would be preferred.
*/
#ifdef USE_PAM
- if (!authenticate_via_pam(pw, ttyn))
+ if (!authenticate_via_pam(&pw, ttyn))
#else /* !USE_PAM */
- if (!authenticate_via_shadow_passwd(pw))
+ if (!authenticate_via_shadow_passwd(&pw))
#endif /* if/else USE_PAM */
{
fprintf(stderr, _("newrole: incorrect password for %s\n"),
- pw->pw_name);
+ pw.pw_name);
return (-1);
}
/* If we reach here, then we have authenticated the user. */
@@ -904,7 +944,7 @@
if (optind < 1)
optind = 1;
- if (asprintf(&argv[optind - 1], "-%s", pw->pw_shell) < 0) {
+ if (asprintf(&argv[optind - 1], "-%s", pw.pw_shell) < 0) {
fprintf(stderr, _("Error allocating shell.\n"));
exit(-1);
}
@@ -925,7 +965,7 @@
if (send_audit_message(1, old_context, new_context, ttyn))
exit(-1);
freecon(old_context);
- execv(pw->pw_shell, argv + optind - 1);
+ execv(pw.pw_shell, argv + optind - 1);
/* If we reach here, then we failed to exec the new shell. */
perror(_("failed to exec shell\n"));
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ssm...@us...> - 2006-11-13 23:48:37
|
Revision: 2079
http://svn.sourceforge.net/selinux/?rev=2079&view=rev
Author: ssmalley
Date: 2006-11-13 15:48:36 -0800 (Mon, 13 Nov 2006)
Log Message:
-----------
Author: Michael C Thompson
Email: tho...@us...
Subject: make newrole suid (take 3)
Date: Thu, 02 Nov 2006 19:04:20 -0600
Michael C Thompson wrote:
> The 8 patches are as follows:
> 1) Modifications to Makefile to support future patch needs
> Add newrole-lspp.pamd
> 2) New extract_pw_data function and use in main()
> 3) Add signal handler function
This is the 3rd of 8 patches.
This patch applies against policycoreutils-1.30.30-1.
This patch moves the signal handler setup from main() into a new
function.
Changes:
* Adds set_signal_handles() and uses it in main()
Signed-off-by: Michael Thompson <tho...@us...>
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:47:17 UTC (rev 2078)
+++ trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:48:36 UTC (rev 2079)
@@ -498,6 +498,30 @@
}
#endif
+/**
+ * Take care of any signal setup
+ */
+static int set_signal_handles()
+{
+ sigset_t empty;
+
+ /* Empty the signal mask in case someone is blocking a signal */
+ if (sigemptyset(&empty)) {
+ fprintf(stderr, _("Unable to obtain empty signal set\n"));
+ return -1;
+ }
+
+ (void)sigprocmask(SIG_SETMASK, &empty, NULL);
+
+ /* Terminate on SIGHUP. */
+ if (signal(SIGHUP, SIG_DFL) == SIG_ERR) {
+ fprintf(stderr, _("Unable to set SIGHUP handler\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
/************************************************************************
*
* All code used for both PAM and shadow passwd goes in this section.
@@ -534,19 +558,14 @@
uid_t uid;
int fd;
int enforcing;
- sigset_t empty;
#ifdef LOG_AUDIT_PRIV
drop_capabilities();
#endif
- /* Empty the signal mask in case someone is blocking a signal */
- sigemptyset(&empty);
- (void)sigprocmask(SIG_SETMASK, &empty, NULL);
+ if (set_signal_handles())
+ return -1;
- /* Terminate on SIGHUP. */
- signal(SIGHUP, SIG_DFL);
-
#ifdef USE_NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ssm...@us...> - 2006-11-13 23:50:11
|
Revision: 2080
http://svn.sourceforge.net/selinux/?rev=2080&view=rev
Author: ssmalley
Date: 2006-11-13 15:50:09 -0800 (Mon, 13 Nov 2006)
Log Message:
-----------
Author: Michael C Thompson
Email: tho...@us...
Subject: make newrole suid (take 3)
Date: Thu, 02 Nov 2006 19:05:00 -0600
Michael C Thompson wrote:
> The 8 patches are as follows:
> 1) Modifications to Makefile to support future patch needs
> Add newrole-lspp.pamd
> 2) New extract_pw_data function and use in main()
> 3) Add signal handler function
> 4) Update drop_capabilities() and use in main()
This is the 4th of 8 patches.
This patch applies against policycoreutils-1.30.30-1.
This patch adds expands the drop_capabilities functionality
to support various compile-time options (with audit, with
namespace, or neither).
Changes:
* Splits drop_capabilities into three versions (compile time option):
- 'No-cap' version, returns true
- 'audit-only' version, retains only CAP_AUDIT_WRITE
Enable with AUDIT_LOG_PRIV=y
- 'namespace+' version, retains CAP_AUDIT_WRITE, CAP_SYS_ADMIN and
more to allow namespace actions
Enable with NAMESPACE_PRIV = y
* main() calls drop_capabilities unconditionally
Signed-off-by: Michael Thompson <tho...@us...>
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:48:36 UTC (rev 2079)
+++ trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:50:09 UTC (rev 2080)
@@ -387,68 +387,139 @@
return -1;
}
-/*
+/**
* This function will drop the capabilities so that we are left
* only with access to the audit system. If the user is root, we leave
* the capabilities alone since they already should have access to the
* audit netlink socket.
+ *
+ * Returns zero on success, non-zero otherwise
*/
-#ifdef LOG_AUDIT_PRIV
-static void drop_capabilities(void)
+#if defined(AUDIT_LOG_PRIV) && !defined(NAMESPACE_PRIV)
+static int drop_capabilities(void)
{
+ int rc = 0;
+ cap_t new_caps, tmp_caps;
+ cap_value_t cap_list[] = { CAP_AUDIT_WRITE };
+ cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID };
uid_t uid = getuid();
- if (uid) { /* Non-root path */
- cap_t new_caps, tmp_caps;
- cap_value_t cap_list[] = { CAP_AUDIT_WRITE };
- cap_value_t tmp_cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID };
+ if (!uid)
+ return 0;
- new_caps = cap_init();
- tmp_caps = cap_init();
- if (!new_caps || !tmp_caps) {
- fprintf(stderr,
- _("Error initing capabilities, aborting.\n"));
- exit(-1);
- }
- cap_set_flag(new_caps, CAP_PERMITTED, 1, cap_list, CAP_SET);
- cap_set_flag(new_caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET);
- cap_set_flag(tmp_caps, CAP_PERMITTED, 2, tmp_cap_list, CAP_SET);
- cap_set_flag(tmp_caps, CAP_EFFECTIVE, 2, tmp_cap_list, CAP_SET);
+ /* Non-root caller, suid root path */
+ new_caps = cap_init();
+ tmp_caps = cap_init();
+ if (!new_caps || !tmp_caps) {
+ fprintf(stderr, _("Error initing capabilities, aborting.\n"));
+ return -1;
+ }
+ rc |= cap_set_flag(new_caps, CAP_PERMITTED, 1, cap_list, CAP_SET);
+ rc |= cap_set_flag(new_caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET);
+ rc |= cap_set_flag(tmp_caps, CAP_PERMITTED, 2, tmp_cap_list, CAP_SET);
+ rc |= cap_set_flag(tmp_caps, CAP_EFFECTIVE, 2, tmp_cap_list, CAP_SET);
+ if (rc) {
+ fprintf(stderr, _("Error setting capabilities, aborting\n"));
+ goto out;
+ }
- /* Keep capabilities across uid change */
- prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+ /* Keep capabilities across uid change */
+ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
+ fprintf(stderr, _("Error setting KEEPCAPS, aborting\n"));
+ rc = -1;
+ goto out;
+ }
- /* We should still have root's caps, so drop most capabilities now */
- if (cap_set_proc(tmp_caps)) {
- fprintf(stderr,
- _("Error dropping capabilities, aborting\n"));
- exit(-1);
- }
- cap_free(tmp_caps);
+ /* Does this temporary change really buy us much? */
+ /* We should still have root's caps, so drop most capabilities now */
+ if ((rc = cap_set_proc(tmp_caps))) {
+ fprintf(stderr, _("Error dropping capabilities, aborting\n"));
+ goto out;
+ }
- /* Change uid */
- if (setresuid(uid, uid, uid)) {
- fprintf(stderr, _("Error changing uid, aborting.\n"));
- exit(-1);
- }
+ /* Change uid */
+ if ((rc = setresuid(uid, uid, uid))) {
+ fprintf(stderr, _("Error changing uid, aborting.\n"));
+ goto out;
+ }
- /* Now get rid of this ability */
- if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0) {
- fprintf(stderr,
- _("Error resetting KEEPCAPS, aborting\n"));
- exit(-1);
- }
+ /* Now get rid of this ability */
+ if ((rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0)) {
+ fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n"));
+ goto out;
+ }
- /* Finish dropping capabilities. */
- if (cap_set_proc(new_caps)) {
- fprintf(stderr,
- _
- ("Error dropping SETUID capability, aborting\n"));
- exit(-1);
- }
- cap_free(new_caps);
+ /* Finish dropping capabilities. */
+ if ((rc = cap_set_proc(new_caps))) {
+ fprintf(stderr,
+ _("Error dropping SETUID capability, aborting\n"));
+ goto out;
}
+out:
+ if (cap_free(tmp_caps) || cap_free(new_caps))
+ fprintf(stderr, _("Error freeing caps\n"));
+ return rc;
}
+#elif defined(NAMESPACE_PRIV)
+/**
+ * This function will drop the capabilities so that we are left
+ * only with access to the audit system and the ability to raise
+ * CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, CAP_FOWNER and CAP_CHOWN,
+ * before invoking pam_namespace. These capabilities are needed
+ * for performing bind mounts/unmounts and to create potential new
+ * instance directories with appropriate DAC attributes. If the
+ * user is root, we leave the capabilities alone since they already
+ * should have access to the audit netlink socket and should have
+ * the ability to create/mount/unmount instance directories.
+ *
+ * Returns zero on success, non-zero otherwise
+ */
+static int drop_capabilities(void)
+{
+ int rc = 0;
+ cap_t new_caps;
+ cap_value_t cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID,
+ CAP_SYS_ADMIN, CAP_FOWNER, CAP_CHOWN,
+ CAP_DAC_OVERRIDE };
+
+ if (!getuid())
+ return 0;
+
+ /* Non-root caller, suid root path */
+ new_caps = cap_init();
+ if (!new_caps) {
+ fprintf(stderr, _("Error initing capabilities, aborting.\n"));
+ return -1;
+ }
+ rc |= cap_set_flag(new_caps, CAP_PERMITTED, 6, cap_list, CAP_SET);
+ rc |= cap_set_flag(new_caps, CAP_EFFECTIVE, 6, cap_list, CAP_SET);
+ if (rc) {
+ fprintf(stderr, _("Error setting capabilities, aborting\n"));
+ goto out;
+ }
+
+ /* Ensure that caps are dropped after setuid call */
+ if ((rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) < 0)) {
+ fprintf(stderr, _("Error resetting KEEPCAPS, aborting\n"));
+ goto out;
+ }
+
+ /* We should still have root's caps, so drop most capabilities now */
+ if ((rc = cap_set_proc(new_caps))) {
+ fprintf(stderr, _("Error dropping capabilities, aborting\n"));
+ goto out;
+ }
+out:
+ if (cap_free(new_caps))
+ fprintf(stderr, _("Error freeing caps\n"));
+ return rc;
+}
+
+#else
+static inline int drop_capabilities(void)
+{
+ return 0;
+}
#endif
#ifdef LOG_AUDIT_PRIV
@@ -559,10 +630,15 @@
int fd;
int enforcing;
-#ifdef LOG_AUDIT_PRIV
- drop_capabilities();
-#endif
-
+ /*
+ * Step 0: Setup
+ *
+ * Do some intial setup, including dropping capabilities, checking
+ * if it makes sense to continue to run newrole, and setting up
+ * a scrubbed environment.
+ */
+ if (drop_capabilities())
+ return -1;
if (set_signal_handles())
return -1;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ssm...@us...> - 2006-11-13 23:52:01
|
Revision: 2081
http://svn.sourceforge.net/selinux/?rev=2081&view=rev
Author: ssmalley
Date: 2006-11-13 15:51:59 -0800 (Mon, 13 Nov 2006)
Log Message:
-----------
Author: Michael C Thompson
Email: tho...@us...
Subject: make newrole suid (take 3)
Date: Thu, 02 Nov 2006 19:05:37 -0600
Michael C Thompson wrote:
> The 8 patches are as follows:
> 1) Modifications to Makefile to support future patch needs
> Add newrole-lspp.pamd
> 2) New extract_pw_data function and use in main()
> 3) Add signal handler function
> 4) Update drop_capabilities() and use in main()
> 5) Update the authentication functions and use in main()
> Add cleanup since pam_start is now left till program end
This is the 5th of 8 patches.
This patch applies against policycoreutils-1.30.30-1.
This patch updates the authentication functions so that they are
cleaner, and moves pam_start() into main() in prep for namespace
support.
Changes:
* Updates the authentication functions
- Noteably, pam_start is now done in main()
- Removed a lot of very obvious comments and clutter
* Adds pam variables to main()
* Adds pam_start() to main()
* Adds cleanup gotos to main() for pam_end() and missing frees
Signed-off-by: Michael Thompson <tho...@us...>
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:50:09 UTC (rev 2080)
+++ trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:51:59 UTC (rev 2081)
@@ -150,16 +150,11 @@
* All PAM code goes in this section.
*
************************************************************************/
-
-#include <unistd.h> /* for getuid(), exit(), getopt() */
-
#include <security/pam_appl.h> /* for PAM functions */
#include <security/pam_misc.h> /* for misc_conv PAM utility function */
#define SERVICE_NAME "newrole" /* the name of this program for PAM */
-int authenticate_via_pam(const struct passwd *, const char *);
-
/* authenticate_via_pam()
*
* in: pw - struct containing data from our user's line in
@@ -173,63 +168,39 @@
* This function uses PAM to authenticate the user running this
* program. This is the only function in this program that makes PAM
* calls.
- *
*/
-
-int authenticate_via_pam(const struct passwd *pw, const char *ttyn)
+int authenticate_via_pam(const char *ttyn, pam_handle_t *pam_handle)
{
- int result = 0; /* our result, set to 0 (not authenticated) by default */
- int rc; /* pam return code */
- pam_handle_t *pam_handle; /* opaque handle used by all PAM functions */
+ int result = 0; /* set to 0 (not authenticated) by default */
+ int pam_rc; /* pam return code */
const char *tty_name;
- /* This is a jump table of functions for PAM to use when it wants to *
- * communicate with the user. We'll be using misc_conv(), which is *
- * provided for us via pam_misc.h. */
- struct pam_conv pam_conversation = {
- misc_conv,
- NULL
- };
-
- /* Make `p_pam_handle' a valid PAM handle so we can use it when *
- * calling PAM functions. */
- rc = pam_start(SERVICE_NAME,
- pw->pw_name, &pam_conversation, &pam_handle);
- if (rc != PAM_SUCCESS) {
- fprintf(stderr, _("failed to initialize PAM\n"));
- exit(-1);
- }
-
if (strncmp(ttyn, "/dev/", 5) == 0)
tty_name = ttyn + 5;
else
tty_name = ttyn;
- rc = pam_set_item(pam_handle, PAM_TTY, tty_name);
- if (rc != PAM_SUCCESS) {
+ pam_rc = pam_set_item(pam_handle, PAM_TTY, tty_name);
+ if (pam_rc != PAM_SUCCESS) {
fprintf(stderr, _("failed to set PAM_TTY\n"));
goto out;
}
/* Ask PAM to authenticate the user running this program */
- rc = pam_authenticate(pam_handle, 0);
- if (rc != PAM_SUCCESS) {
+ pam_rc = pam_authenticate(pam_handle, 0);
+ if (pam_rc != PAM_SUCCESS) {
goto out;
}
/* Ask PAM to verify acct_mgmt */
- rc = pam_acct_mgmt(pam_handle, 0);
- if (rc == PAM_SUCCESS) {
+ pam_rc = pam_acct_mgmt(pam_handle, 0);
+ if (pam_rc == PAM_SUCCESS) {
result = 1; /* user authenticated OK! */
}
- /* We're done with PAM. Free `pam_handle'. */
out:
- pam_end(pam_handle, rc);
-
- return (result);
-
+ return result;
} /* authenticate_via_pam() */
#else /* else !USE_PAM */
@@ -239,19 +210,14 @@
* All shadow passwd code goes in this section.
*
************************************************************************/
-
-#include <unistd.h> /* for getuid(), exit(), crypt() */
#include <shadow.h> /* for shadow passwd functions */
#include <string.h> /* for strlen(), memset() */
#define PASSWORD_PROMPT _("Password:") /* prompt for getpass() */
-int authenticate_via_shadow_passwd(const struct passwd *);
-
/* authenticate_via_shadow_passwd()
*
- * in: pw - struct containing data from our user's line in
- * the passwd file.
+ * in: uname - the calling user's user name
* out: nothing
* return: value condition
* ----- ---------
@@ -261,48 +227,34 @@
*
* This function uses the shadow passwd file to thenticate the user running
* this program.
- *
*/
-
-int authenticate_via_shadow_passwd(const struct passwd *pw)
+int authenticate_via_shadow_passwd(const char *uname)
{
+ struct spwd *p_shadow_line;
+ char *unencrypted_password_s;
+ char *encrypted_password_s;
- struct spwd *p_shadow_line; /* struct derived from shadow passwd file line */
- char *unencrypted_password_s; /* unencrypted password input by user */
- char *encrypted_password_s; /* user's password input after being crypt()ed */
-
- /* Make `p_shadow_line' point to the data from the current user's *
- * line in the shadow passwd file. */
- setspent(); /* Begin access to the shadow passwd file. */
- p_shadow_line = getspnam(pw->pw_name);
- endspent(); /* End access to the shadow passwd file. */
+ setspent();
+ p_shadow_line = getspnam(uname);
+ endspent();
if (!(p_shadow_line)) {
- fprintf(stderr,
- _
- ("Cannot find your entry in the shadow passwd file.\n"));
- exit(-1);
+ fprintf(stderr, _("Cannot find your entry in the shadow "
+ "passwd file.\n"));
+ return 0;
}
/* Ask user to input unencrypted password */
if (!(unencrypted_password_s = getpass(PASSWORD_PROMPT))) {
fprintf(stderr, _("getpass cannot open /dev/tty\n"));
- exit(-1);
+ return 0;
}
- /* Use crypt() to encrypt user's input password. Clear the *
- * unencrypted password as soon as we're done, so it is not *
- * visible to memory snoopers. */
+ /* Use crypt() to encrypt user's input password. */
encrypted_password_s = crypt(unencrypted_password_s,
p_shadow_line->sp_pwdp);
memset(unencrypted_password_s, 0, strlen(unencrypted_password_s));
-
- /* Return 1 (authenticated) iff the encrypted version of the user's *
- * input password matches the encrypted password stored in the *
- * shadow password file. */
return (!strcmp(encrypted_password_s, p_shadow_line->sp_pwdp));
-
-} /* authenticate_via_shadow_passwd() */
-
+}
#endif /* if/else USE_PAM */
/*
@@ -626,10 +578,22 @@
char *level_s = NULL; /* level spec'd by user in argv[] */
char *ttyn = NULL; /* tty path */
pid_t childPid = 0;
- uid_t uid;
- int fd;
+ int fd, rc;
int enforcing;
+#ifdef USE_PAM
+ int pam_status; /* pam return code */
+ pam_handle_t *pam_handle; /* opaque handle used by all PAM functions */
+
+ /* This is a jump table of functions for PAM to use when it wants to *
+ * communicate with the user. We'll be using misc_conv(), which is *
+ * provided for us via pam_misc.h. */
+ struct pam_conv pam_conversation = {
+ misc_conv,
+ NULL
+ };
+#endif
+
/*
* Step 0: Setup
*
@@ -771,26 +735,6 @@
exit(-1);
}
- /*
- * Determine the Linux user identity to re-authenticate.
- * If supported and set, use the login uid, as this should be more stable.
- * Otherwise, use the real uid.
- * The SELinux user identity is no longer used, as Linux users are now
- * mapped to SELinux users via seusers and the SELinux user identity space
- * is separate.
- */
-#ifdef USE_AUDIT
- uid = audit_getloginuid();
- if (uid == (uid_t) - 1)
- uid = getuid();
-#else
- uid = getuid();
-#endif
-
- /* Get the passwd info for the Linux user identity. */
- if (extract_pw_data(&pw))
- return -1;
-
/* Get the tty name. Pam will need it. */
ttyn = ttyname(0);
if (!ttyn || *ttyn == '\0') {
@@ -799,28 +743,36 @@
exit(-1);
}
- printf(_("Authenticating %s.\n"), pw.pw_name);
+ /* Get the passwd info for the Linux user identity. */
+ if (extract_pw_data(&pw))
+ return -1;
- /*
+ /*
+ * Step 2: Authenticate the user.
+ *
* Re-authenticate the user running this program.
* This is just to help confirm user intent (vs. invocation by
* malicious software), not to authorize the operation (which is covered
* by policy). Trusted path mechanism would be preferred.
*/
+ printf(_("Authenticating %s.\n"), pw.pw_name);
#ifdef USE_PAM
- if (!authenticate_via_pam(&pw, ttyn))
-#else /* !USE_PAM */
- if (!authenticate_via_shadow_passwd(&pw))
-#endif /* if/else USE_PAM */
+ pam_status = pam_start(SERVICE_NAME, pw.pw_name, &pam_conversation,
+ &pam_handle);
+ if (pam_status != PAM_SUCCESS) {
+ fprintf(stderr, _("failed to initialize PAM\n"));
+ goto err_free;
+ }
+
+ if (!authenticate_via_pam(ttyn, pam_handle))
+#else
+ if (!authenticate_via_shadow_passwd(pw.pw_name))
+#endif
{
fprintf(stderr, _("newrole: incorrect password for %s\n"),
pw.pw_name);
- return (-1);
+ goto err_close_pam;
}
- /* If we reach here, then we have authenticated the user. */
-#ifdef CANTSPELLGDB
- printf("You are authenticated!\n");
-#endif
/*
*
@@ -1062,7 +1014,26 @@
freecon(old_context);
execv(pw.pw_shell, argv + optind - 1);
- /* If we reach here, then we failed to exec the new shell. */
+ /*
+ * Error path cleanup
+ *
+ * If we reach here, then we failed to exec the new shell.
+ */
perror(_("failed to exec shell\n"));
- return (-1);
+err_close_pam:
+#ifdef USE_PAM
+ rc = pam_end(pam_handle, pam_status);
+ if (rc != PAM_SUCCESS)
+ fprintf(stderr, "pam_end failed with %s\n",
+ pam_strerror(pam_handle, rc));
+#endif
+err_free:
+ freecon(tty_context);
+ freecon(new_tty_context);
+ freecon(old_context);
+ freecon(new_context);
+ free(pw.pw_name);
+ free(pw.pw_dir);
+ free(pw.pw_shell);
+ return -1;
} /* main() */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ssm...@us...> - 2006-11-13 23:53:43
|
Revision: 2082
http://svn.sourceforge.net/selinux/?rev=2082&view=rev
Author: ssmalley
Date: 2006-11-13 15:53:42 -0800 (Mon, 13 Nov 2006)
Log Message:
-----------
Author: Michael C Thompson
Email: tho...@us...
Subject: make newrole suid (take 3)
Date: Thu, 02 Nov 2006 19:06:16 -0600
Michael C Thompson wrote:
> The 8 patches are as follows:
> 1) Modifications to Makefile to support future patch needs
> Add newrole-lspp.pamd
> 2) New extract_pw_data function and use in main()
> 3) Add signal handler function
> 4) Update drop_capabilities() and use in main()
> 5) Update the authentication functions and use in main()
> Add cleanup since pam_start is now left till program end
> 6) Move relabeling tty actions into functions
This is the 6th of 8 patches.
This patch applies against policycoreutils-1.30.30-1.
This patch moves the tty relabeling actions into their own
functions and adds better cleanup to main on error paths.
Changes:
* Introduces relabel_tty() and restore_tty_label()
- Move functionality from main() into functions
* Uses the above new functions in main()
* Updates the parent process to have better cleanup
Signed-off-by: Michael Thompson <tho...@us...>
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:51:59 UTC (rev 2081)
+++ trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:53:42 UTC (rev 2082)
@@ -522,6 +522,113 @@
#endif
/**
+ * This function attempts to relabel the tty. If this function fails, then
+ * the fd is closed, the contexts are free'd and -1 is returned. On success,
+ * a valid fd is returned and tty_context and new_tty_context are set.
+ *
+ * This function will not fail if it can not relabel the tty when selinux is
+ * in permissive mode.
+ */
+static int relabel_tty(const char *ttyn, security_context_t new_context,
+ security_context_t *tty_context,
+ security_context_t *new_tty_context)
+{
+ int fd;
+ int enforcing = security_getenforce();
+ security_context_t tty_con = NULL;
+ security_context_t new_tty_con = NULL;
+
+ if (enforcing < 0) {
+ fprintf(stderr, _("Could not determine enforcing mode.\n"));
+ return -1;
+ }
+
+ /* Re-open TTY descriptor */
+ fd = open(ttyn, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, _("Error! Could not open %s.\n"), ttyn);
+ return fd;
+ }
+
+ if (fgetfilecon(fd, &tty_con) < 0) {
+ fprintf(stderr, _("%s! Could not get current context "
+ "for %s, not relabeling tty.\n"),
+ enforcing ? "Error" : "Warning", ttyn);
+ if (enforcing)
+ goto close_fd;
+ }
+
+ if (tty_con &&
+ (security_compute_relabel(new_context, tty_con,
+ SECCLASS_CHR_FILE, &new_tty_con) < 0)) {
+ fprintf(stderr, _("%s! Could not get new context for %s, "
+ "not relabeling tty.\n"),
+ enforcing ? "Error" : "Warning", ttyn);
+ if (enforcing)
+ goto close_fd;
+ }
+
+ if (new_tty_con)
+ if (fsetfilecon(fd, new_tty_con) < 0) {
+ fprintf(stderr,
+ _("%s! Could not set new context for %s\n"),
+ enforcing ? "Error" : "Warning", ttyn);
+ freecon(new_tty_con);
+ new_tty_con = NULL;
+ if (enforcing)
+ goto close_fd;
+ }
+
+ *tty_context = tty_con;
+ *new_tty_context = new_tty_con;
+ return fd;
+
+close_fd:
+ freecon(tty_con);
+ close(fd);
+ return -1;
+}
+
+/**
+ * This function attempts to revert the relabeling done to the tty.
+ * fd - referencing the opened ttyn
+ * ttyn - name of tty to restore
+ * tty_context - original context of the tty
+ * new_tty_context - context tty was relabeled to
+ *
+ * Returns zero on success, non-zero otherwise
+ */
+static int restore_tty_label(int fd, const char *ttyn,
+ security_context_t tty_context,
+ security_context_t new_tty_context)
+{
+ int rc = 0;
+ security_context_t chk_tty_context = NULL;
+
+ if (!new_tty_context)
+ goto skip_relabel;
+
+ /* Verify that the tty still has the context set by newrole. */
+ if ((rc = fgetfilecon(fd, &chk_tty_context)) < 0) {
+ fprintf(stderr, "Could not fgetfilecon %s.\n", ttyn);
+ goto skip_relabel;
+ }
+
+ if ((rc = strcmp(chk_tty_context, new_tty_context))) {
+ fprintf(stderr, _("%s changed labels.\n"), ttyn);
+ goto skip_relabel;
+ }
+
+ if ((rc = fsetfilecon(fd, tty_context)) < 0)
+ fprintf(stderr,
+ _("Warning! Could not restore context for %s\n"), ttyn);
+skip_relabel:
+ freecon(chk_tty_context);
+ return rc;
+}
+
+
+/**
* Take care of any signal setup
*/
static int set_signal_handles()
@@ -558,7 +665,6 @@
security_context_t old_context = NULL; /* our original securiy context */
security_context_t tty_context = NULL; /* The current context of tty file */
security_context_t new_tty_context = NULL; /* The new context of tty file */
- security_context_t chk_tty_context = NULL;
context_t context; /* manipulatable form of new_context */
@@ -580,6 +686,7 @@
pid_t childPid = 0;
int fd, rc;
int enforcing;
+ char *shell_argv0 = NULL;
#ifdef USE_PAM
int pam_status; /* pam return code */
@@ -855,110 +962,77 @@
}
/*
+ * Step 3: Handle relabeling of the tty.
*
- * Step 4: Handle relabeling of the tty.
+ * Once we authenticate the user, we know that we want to proceed with
+ * the action. Prior to this point, no changes are made the to system.
+ */
+ fd = relabel_tty(ttyn, new_context, &tty_context, &new_tty_context);
+ if (fd < 0)
+ goto err_close_pam;
+
+ /*
+ * Step 4: Fork
*
+ * Fork, allowing parent to clean up after shell has executed.
+ * Child: reopen stdin, stdout, stderr and exec shell
+ * Parnet: wait for child to die and restore tty's context
*/
-
- /* Re-open TTY descriptor */
- fd = open(ttyn, O_RDWR);
- if (fd < 0) {
- fprintf(stderr, _("Error! Could not open %s.\n"), ttyn);
- exit(-1);
- }
-
- tty_context = NULL;
- if (fgetfilecon(fd, &tty_context) < 0) {
- fprintf(stderr,
- _
- ("%s! Could not get current context for %s, not relabeling tty.\n"),
- enforcing ? "Error" : "Warning", ttyn);
- if (enforcing)
- exit(-1);
- }
-#ifdef CANTSPELLGDB
- if (tty_context)
- printf("Your tty %s was labeled with context %s\n", ttyn,
- tty_context);
-#endif
-
- new_tty_context = NULL;
- if (tty_context
- &&
- (security_compute_relabel
- (new_context, tty_context, SECCLASS_CHR_FILE,
- &new_tty_context) < 0)) {
- fprintf(stderr,
- _
- ("%s! Could not get new context for %s, not relabeling tty.\n"),
- enforcing ? "Error" : "Warning", ttyn);
- if (enforcing)
- exit(-1);
- }
-#ifdef CANTSPELLGDB
- if (new_tty_context)
- printf("Relabeling tty %s to context %s\n", ttyn,
- new_tty_context);
-#endif
-
- if (new_tty_context) {
- if (fsetfilecon(fd, new_tty_context) < 0) {
- fprintf(stderr,
- _("%s! Could not set new context for %s\n"),
- enforcing ? "Error" : "Warning", ttyn);
- freecon(new_tty_context);
- new_tty_context = NULL;
- if (enforcing)
- exit(-1);
- }
- }
-
- /* Fork, allowing parent to clean up after shell has executed */
childPid = fork();
if (childPid < 0) {
+ /* fork failed, no child to worry about */
int errsv = errno;
fprintf(stderr, _("newrole: failure forking: %s"),
strerror(errsv));
- if (fsetfilecon(fd, tty_context) < 0)
- fprintf(stderr,
- _
- ("Warning! Could not restore context for %s\n"),
- ttyn);
- freecon(tty_context);
- exit(-1);
+ if (restore_tty_label(fd, ttyn, tty_context, new_tty_context))
+ fprintf(stderr, _("Unable to restore tty label...\n"));
+ if (close(fd))
+ fprintf(stderr, _("Failed to close tty properly\n"));
+ goto err_close_pam;
} else if (childPid) {
- /* PARENT */
+ /* PARENT
+ * It doesn't make senes to exit early on errors at this point,
+ * since we are doing cleanup which needs to be done.
+ * We can exit with a bad rc though
+ */
int rc;
+ int exit_code = 0;
+
do {
rc = wait(NULL);
} while (rc < 0 && errno == EINTR);
- if (!new_tty_context || !tty_context)
- exit(0);
-
- /* Verify that the tty still has the context set by newrole. */
- if (fgetfilecon(fd, &chk_tty_context) < 0) {
- fprintf(stderr, "Could not fgetfilecon %s.\n", ttyn);
- exit(-1);
+ if (restore_tty_label(fd, ttyn, tty_context, new_tty_context)) {
+ fprintf(stderr, _("Unable to restore tty label...\n"));
+ exit_code = -1;
}
-
- if (strcmp(chk_tty_context, new_tty_context)) {
- fprintf(stderr, _("%s changed labels.\n"), ttyn);
- exit(-1);
+ freecon(tty_context);
+ freecon(new_tty_context);
+ if (close(fd)) {
+ fprintf(stderr, _("Failed to close tty properly\n"));
+ exit_code = -1;
}
-
- freecon(new_tty_context);
-
-#ifdef CANTSPELLGDB
- printf("Restoring tty %s back to context %s\n", ttyn,
- tty_context);
+#ifdef USE_PAM
+#ifdef NAMESPACE_PRIV
+ pam_status = pam_close_session(pam_handle,0);
+ if (pam_status != PAM_SUCCESS) {
+ fprintf(stderr, "pam_close_session failed with %s\n",
+ pam_strerror(pam_handle, pam_status));
+ exit_code = -1;
+ }
#endif
-
- fsetfilecon(fd, tty_context);
- freecon(tty_context);
-
- /* Done! */
- exit(0);
+ rc = pam_end(pam_handle, pam_status);
+ if (rc != PAM_SUCCESS) {
+ fprintf(stderr, "pam_end failed with %s\n",
+ pam_strerror(pam_handle, rc));
+ exit_code = -1;
+ }
+#endif
+ free(pw.pw_name);
+ free(pw.pw_dir);
+ free(pw.pw_shell);
+ free(shell_argv0);
+ return exit_code;
}
/* CHILD */
@@ -1035,5 +1109,6 @@
free(pw.pw_name);
free(pw.pw_dir);
free(pw.pw_shell);
+ free(shell_argv0);
return -1;
} /* main() */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ssm...@us...> - 2006-11-13 23:56:31
|
Revision: 2083
http://svn.sourceforge.net/selinux/?rev=2083&view=rev
Author: ssmalley
Date: 2006-11-13 15:56:30 -0800 (Mon, 13 Nov 2006)
Log Message:
-----------
Author: Michael C Thompson
Email: tho...@us...
Subject: make newrole suid (take 3)
Date: Thu, 02 Nov 2006 19:06:49 -0600
Michael C Thompson wrote:
> The 8 patches are as follows:
> 1) Modifications to Makefile to support future patch needs
> Add newrole-lspp.pamd
> 2) New extract_pw_data function and use in main()
> 3) Add signal handler function
> 4) Update drop_capabilities() and use in main()
> 5) Update the authentication functions and use in main()
> Add cleanup since pam_start is now left till program end
> 6) Move relabeling tty actions into functions
> 7) Move command-line argument parsing into a function
> Clear the environment during execution
> Add support for preserving the environment (-p)
This is the 7th of 8 patches.
This patch applies against policycoreutils-1.30.30-1.
This function introduces a sanitized environment during the life-time
of newrole's execution, and sets the environment to either the preserved
environment or a minimal environment before shell execution.
Changes:
* Introduces restore_environment()
- New functionality, for preserving the environment or sanitizing it
* Introduces parse_command_line_arguments()
- Move functionality from main() into parse_command_line_arguments
* Uses the above new functions in main()
Signed-off-by: Michael Thompson <tho...@us...>
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:53:42 UTC (rev 2082)
+++ trunk/policycoreutils/newrole/newrole.c 2006-11-13 23:56:30 UTC (rev 2083)
@@ -85,10 +85,13 @@
#endif
/* USAGE_STRING describes the command-line args of this program. */
-#define USAGE_STRING "USAGE: newrole [ -r role ] [ -t type ] [ -l level ] [ -V ] [ -- args ]"
+#define USAGE_STRING "USAGE: newrole [ -r role ] [ -t type ] [ -l level ] [ -p ] [ -V ] [ -- args ]"
+#define DEFAULT_PATH "/usr/bin:/bin"
#define DEFAULT_CONTEXT_SIZE 255 /* first guess at context size */
+extern char **environ;
+
char *xstrdup(const char *s)
{
char *s2;
@@ -340,6 +343,74 @@
}
/**
+ * Either restore the original environment, or set up a minimal one.
+ *
+ * The minimal environment contains:
+ * TERM, DISPLAY and XAUTHORITY - if they are set, preserve values
+ * HOME, SHELL, USER and LOGNAME - set to contents of /etc/passwd
+ * PATH - set to default value DEFAULT_PATH
+ *
+ * Returns zero on success, non-zero otherwise
+ */
+static int restore_environment(int preserve_environment,
+ char **old_environ, const struct passwd *pw)
+{
+ char const *term_env;
+ char const *display_env;
+ char const *xauthority_env;
+ char *term = NULL; /* temporary container */
+ char *display = NULL; /* temporary container */
+ char *xauthority = NULL; /* temporary container */
+ int rc;
+
+ environ = old_environ;
+
+ if (preserve_environment)
+ return 0;
+
+ term_env = getenv("TERM");
+ display_env = getenv("DISPLAY");
+ xauthority_env = getenv("XAUTHORITY");
+
+ /* Save the variable values we want */
+ if (term_env)
+ term = strdup(term_env);
+ if (display_env)
+ display = strdup(display_env);
+ if (xauthority_env)
+ xauthority = strdup(xauthority_env);
+ if ((term_env && !term) || (display_env && !display) ||
+ (xauthority_env && !xauthority)) {
+ rc = -1;
+ goto out;
+ }
+
+ /* Construct a new environment */
+ if ((rc = clearenv())) {
+ fprintf(stderr, _("Unable to clear environment\n"));
+ goto out;
+ }
+
+ /* Restore that which we saved */
+ if (term)
+ rc |= setenv("TERM", term, 1);
+ if (display)
+ rc |= setenv("DISPLAY", display, 1);
+ if (xauthority)
+ rc |= setenv("XAUTHORITY", xauthority, 1);
+ rc |= setenv("HOME", pw->pw_dir, 1);
+ rc |= setenv("SHELL", pw->pw_shell, 1);
+ rc |= setenv("USER", pw->pw_name, 1);
+ rc |= setenv("LOGNAME", pw->pw_name, 1);
+ rc |= setenv("PATH", DEFAULT_PATH, 1);
+out:
+ free(term);
+ free(display);
+ free(xauthority);
+ return rc;
+}
+
+/**
* This function will drop the capabilities so that we are left
* only with access to the audit system. If the user is root, we leave
* the capabilities alone since they already should have access to the
@@ -627,7 +698,173 @@
return rc;
}
+/**
+ * Parses and validates the provided command line options and
+ * constructs a new context based on our old context and the
+ * arguments specified on the command line. On success
+ * new_context will be set to valid values, otherwise its value
+ * is left unchanged.
+ *
+ * Returns zero on success, non-zero otherwise.
+ */
+static int parse_command_line_arguments(int argc, char **argv, char *ttyn,
+ security_context_t old_context,
+ security_context_t *new_context,
+ int *preserve_environment)
+{
+ int flag_index; /* flag index in argv[] */
+ int clflag; /* holds codes for command line flags */
+ char *role_s = NULL; /* role spec'd by user in argv[] */
+ char *type_s = NULL; /* type spec'd by user in argv[] */
+ char *type_ptr = NULL; /* stores malloc'd data from get_default_type */
+ char *level_s = NULL; /* level spec'd by user in argv[] */
+ char *range_ptr = NULL;
+ security_context_t new_con = NULL;
+ context_t context = NULL; /* manipulatable form of new_context */
+ const struct option long_options[] = {
+ {"role", 1, 0, 'r'},
+ {"type", 1, 0, 't'},
+ {"level", 1, 0, 'l'},
+ {"preserve-environment", 0, 0, 'p'},
+ {"version", 0, 0, 'V'},
+ {NULL, 0, 0, 0}
+ };
+ *preserve_environment = 0;
+ while (1) {
+ clflag = getopt_long(argc, argv, "r:t:l:pV", long_options,
+ &flag_index);
+ if (clflag == -1)
+ break;
+
+ switch (clflag) {
+ case 'V':
+ printf("newrole: %s version %s\n", PACKAGE, VERSION);
+ exit(0);
+ break;
+ case 'p':
+ *preserve_environment = 1;
+ break;
+ case 'r':
+ if (role_s) {
+ fprintf(stderr,
+ _("Error: multiple roles specified\n"));
+ return -1;
+ }
+ role_s = optarg;
+ break;
+ case 't':
+ if (type_s) {
+ fprintf(stderr,
+ _("Error: multiple types specified\n"));
+ return -1;
+ }
+ type_s = optarg;
+ break;
+ case 'l':
+ if (!is_selinux_mls_enabled()) {
+ fprintf(stderr, _("Sorry, -l may be used with "
+ "SELinux MLS support.\n"));
+ return -1;
+ }
+ if (level_s) {
+ fprintf(stderr, _("Error: multiple levels "
+ "specified\n"));
+ return -1;
+ }
+ level_s = optarg;
+ break;
+ default:
+ fprintf(stderr, "%s\n", USAGE_STRING);
+ return -1;
+ }
+ }
+
+ /* Verify that the combination of command-line arguments are viable */
+ if (!(role_s || type_s || level_s)) {
+ fprintf(stderr, "%s\n", USAGE_STRING);
+ return -1;
+ }
+
+ /* Fill in a default type if one hasn't been specified. */
+ if (role_s && !type_s) {
+ /* get_default_type() returns malloc'd memory */
+ if (get_default_type(role_s, &type_ptr)) {
+ fprintf(stderr, _("Couldn't get default type.\n"));
+ send_audit_message(0, old_context, new_con, ttyn);
+ return -1;
+ }
+ type_s = type_ptr;
+ }
+
+ /* Create a temporary new context structure we extract and modify */
+ context = context_new(old_context);
+ if (!context) {
+ fprintf(stderr, _("failed to get new context.\n"));
+ goto err_free;
+ }
+
+ /* Modify the temporary new context */
+ if (role_s)
+ if (context_role_set(context, role_s)) {
+ fprintf(stderr, _("failed to set new role %s\n"),
+ role_s);
+ goto err_free;
+ }
+
+ if (type_s)
+ if (context_type_set(context, type_s)) {
+ fprintf(stderr, _("failed to set new type %s\n"),
+ type_s);
+ goto err_free;
+ }
+
+ if (level_s) {
+ range_ptr = build_new_range(level_s,context_range_get(context));
+ if (!range_ptr) {
+ fprintf(stderr,
+ _("failed to build new range with level %s\n"),
+ level_s);
+ goto err_free;
+ }
+ if (context_range_set(context, range_ptr)) {
+ fprintf(stderr, _("failed to set new range %s\n"),
+ range_ptr);
+ goto err_free;
+ }
+ }
+
+ /* Construct the final new context */
+ if (!(new_con = context_str(context))) {
+ fprintf(stderr, _("failed to convert new context to string\n"));
+ goto err_free;
+ }
+
+ if (security_check_context(new_con) < 0) {
+ fprintf(stderr, _("%s is not a valid context\n"), new_con);
+ send_audit_message(0, old_context, new_con, ttyn);
+ goto err_free;
+ }
+
+ *new_context = strdup(new_con);
+ if (!*new_context) {
+ fprintf(stderr, _("Unable to allocate memory for new_context"));
+ goto err_free;
+ }
+
+ free(type_ptr);
+ free(range_ptr);
+ context_free(context);
+ return 0;
+
+err_free:
+ free(type_ptr);
+ free(range_ptr);
+ /* Don't free new_con, context_free(context) handles this */
+ context_free(context);
+ return -1;
+}
+
/**
* Take care of any signal setup
*/
@@ -660,32 +897,20 @@
int main(int argc, char *argv[])
{
+ security_context_t new_context = NULL; /* target security context */
+ security_context_t old_context = NULL; /* original securiy context */
+ security_context_t tty_context = NULL; /* current context of tty */
+ security_context_t new_tty_context = NULL; /* new context of tty */
- security_context_t new_context = NULL; /* our target security context */
- security_context_t old_context = NULL; /* our original securiy context */
- security_context_t tty_context = NULL; /* The current context of tty file */
- security_context_t new_tty_context = NULL; /* The new context of tty file */
+ struct passwd pw; /* struct derived from passwd file line */
+ char *ttyn = NULL; /* tty path */
- context_t context; /* manipulatable form of new_context */
+ char **old_environ;
+ int preserve_environment;
- struct passwd pw; /* struct derived from passwd file line */
-
- int clflag; /* holds codes for command line flags */
- int flag_index; /* flag index in argv[] */
- const struct option long_options[] = { /* long option flags for getopt() */
- {"role", 1, 0, 'r'},
- {"type", 1, 0, 't'},
- {"level", 1, 0, 'l'},
- {"version", 0, 0, 'V'},
- {NULL, 0, 0, 0}
- };
- char *role_s = NULL; /* role spec'd by user in argv[] */
- char *type_s = NULL; /* type spec'd by user in argv[] */
- char *level_s = NULL; /* level spec'd by user in argv[] */
- char *ttyn = NULL; /* tty path */
+ int fd;
+ int rc;
pid_t childPid = 0;
- int fd, rc;
- int enforcing;
char *shell_argv0 = NULL;
#ifdef USE_PAM
@@ -719,139 +944,40 @@
textdomain(PACKAGE);
#endif
- /*
- *
- * Step 1: Handle command-line arguments.
- *
- */
+ old_environ = environ;
+ environ = NULL;
if (!is_selinux_enabled()) {
- fprintf(stderr,
- _
- ("Sorry, newrole may be used only on a SELinux kernel.\n"));
- exit(-1);
+ fprintf(stderr, _("Sorry, newrole may be used only on "
+ "a SELinux kernel.\n"));
+ return -1;
}
- enforcing = security_getenforce();
- if (enforcing < 0) {
+
+ if (security_getenforce() < 0) {
fprintf(stderr, _("Could not determine enforcing mode.\n"));
- exit(-1);
+ return -1;
}
- while (1) {
- clflag =
- getopt_long(argc, argv, "r:t:l:V", long_options,
- &flag_index);
- if (clflag == -1)
- break;
-
- switch (clflag) {
- case 'V':
- printf("newrole: %s version %s\n", PACKAGE, VERSION);
- exit(0);
- break;
- case 'r':
- /* If role_s is already set, the user spec'd multiple roles - bad. */
- if (role_s) {
- fprintf(stderr,
- _("Error: multiple roles specified\n"));
- exit(-1);
- }
- role_s = optarg; /* save the role string spec'd by user */
- break;
-
- case 't':
- /* If type_s is already set, the user spec'd multiple types - bad. */
- if (type_s) {
- fprintf(stderr,
- _("Error: multiple types specified\n"));
- exit(-1);
- }
- type_s = optarg; /* save the type string spec'd by user */
- break;
-
- case 'l':
- if (!is_selinux_mls_enabled()) {
- fprintf(stderr,
- _
- ("Sorry, -l may be used with SELinux MLS support.\n"));
- exit(-1);
- }
- /* If level_s is already set, the user spec'd multiple levels - bad. */
- if (level_s) {
- fprintf(stderr,
- _
- ("Error: multiple levels specified\n"));
- exit(-1);
- }
- level_s = optarg; /* save the level string spec'd by user */
- break;
-
- default:
- fprintf(stderr, "%s\n", USAGE_STRING);
- exit(-1);
- } /* switch( clflag ) */
- } /* while command-line flags remain for newrole */
-
- /* Verify that the combination of command-line arguments we were *
- * given is a viable one. */
- if (!(role_s || type_s || level_s)) {
- fprintf(stderr, "%s\n", USAGE_STRING);
- exit(-1);
- }
-
- /* Fill in a default type if one hasn't been specified */
- if (role_s && !type_s) {
- if (get_default_type(role_s, &type_s)) {
- fprintf(stderr, _("Couldn't get default type.\n"));
- send_audit_message(0, old_context, new_context, ttyn);
- exit(-1);
- }
-#ifdef CANTSPELLGDB
- printf("Your type will be %s.\n", type_s);
-#endif
- }
-
/*
+ * Step 1: Parse command line and valid arguments
*
- * Step 2: Authenticate the user.
- *
+ * old_context and ttyn are required for audit logging,
+ * context validation and pam
*/
-
- /*
- * Get the context of the caller, and extract
- * the username from the context. Don't rely on the Linux
- * uid information - it isn't trustworthy.
- */
-
- /* Put the caller's context into `old_context'. */
- if (0 != (getprevcon(&old_context))) {
+ if (getprevcon(&old_context)) {
fprintf(stderr, _("failed to get old_context.\n"));
- exit(-1);
+ return -1;
}
-#ifdef CANTSPELLGDB
- printf("Your old context was %s\n", old_context);
-#endif
- /*
- * Create a context structure so that we extract and modify
- * components easily.
- */
- context = context_new(old_context);
- if (context == 0) {
- fprintf(stderr, _("failed to get new context.\n"));
- exit(-1);
- }
-
- /* Get the tty name. Pam will need it. */
ttyn = ttyname(0);
if (!ttyn || *ttyn == '\0') {
fprintf(stderr,
_("Error! Could not retrieve tty information.\n"));
- exit(-1);
+ return -1;
}
- /* Get the passwd info for the Linux user identity. */
- if (extract_pw_data(&pw))
+ if (parse_command_line_arguments(argc, argv, ttyn, old_context,
+ &new_context, &preserve_environment))
return -1;
/*
@@ -862,6 +988,9 @@
* malicious software), not to authorize the operation (which is covered
* by policy). Trusted path mechanism would be preferred.
*/
+ if (extract_pw_data(&pw))
+ goto err_free;
+
printf(_("Authenticating %s.\n"), pw.pw_name);
#ifdef USE_PAM
pam_status = pam_start(SERVICE_NAME, pw.pw_name, &pam_conversation,
@@ -882,86 +1011,6 @@
}
/*
- *
- * Step 3: Construct a new context based on our old context and the
- * arguments specified on the command line.
- *
- */
-
- /* The first step in constructing a new context for the new shell we *
- * plan to exec is to take our old context in `context' as a *
- * starting point, and modify it according to the options the user *
- * specified on the command line. */
-
- /* If the user specified a new role on the command line (if `role_s' *
- * is set), then replace the old role in `context' with this new role. */
- if (role_s) {
- if (context_role_set(context, role_s)) {
- fprintf(stderr, _("failed to set new role %s\n"),
- role_s);
- exit(-1);
- }
-#ifdef CANTSPELLGDB
- printf("Your new role is %s\n", context_role_get(context));
-#endif
- }
-
- /* if user specified new role */
- /* If the user specified a new type on the command line (if `type_s' *
- * is set), then replace the old type in `context' with this new type. */
- if (type_s) {
- if (context_type_set(context, type_s)) {
- fprintf(stderr, _("failed to set new type %s\n"),
- type_s);
- exit(-1);
- }
-#ifdef CANTSPELLGDB
- printf("Your new type is %s\n", context_type_get(context));
-#endif
- }
-
- /* if user specified new type */
- /* If the user specified a new level on the command line (if `level_s' *
- * is set), then replace the old level in `context' with this new level. */
- if (level_s) {
- char *range_s =
- build_new_range(level_s, context_range_get(context));
- if (!range_s) {
- fprintf(stderr,
- _("failed to build new range with level %s\n"),
- level_s);
- exit(-1);
- }
- if (context_range_set(context, range_s)) {
- fprintf(stderr, _("failed to set new range %s\n"),
- range_s);
- free(range_s);
- exit(-1);
- }
- free(range_s);
-#ifdef CANTSPELLGDB
- printf("Your new range is %s\n", context_range_get(context));
-#endif
- }
-
- /* if user specified new level */
- /* The second step in creating the new context is to convert our modified *
- * `context' structure back to a context string and then to a Context. */
- if (!(new_context = context_str(context))) {
- fprintf(stderr, _("failed to convert new context to string\n"));
- exit(-1);
- }
-#ifdef CANTSPELLGDB
- printf("Your new context is %s\n", new_context);
-#endif
-
- if (security_check_context(new_context) < 0) {
- fprintf(stderr, _("%s is not a valid context\n"), new_context);
- send_audit_message(0, old_context, new_context, ttyn);
- exit(-1);
- }
-
- /*
* Step 3: Handle relabeling of the tty.
*
* Once we authenticate the user, we know that we want to proceed with
@@ -1086,6 +1135,13 @@
if (send_audit_message(1, old_context, new_context, ttyn))
exit(-1);
freecon(old_context);
+
+ /* Handle environment changes */
+ if (restore_environment(preserve_environment, old_environ, &pw)) {
+ fprintf(stderr, _("Unable to restore the environment, "
+ "aborting\n"));
+ goto err_close_pam;
+ }
execv(pw.pw_shell, argv + optind - 1);
/*
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mad...@us...> - 2006-11-29 21:12:09
|
Revision: 2114
http://svn.sourceforge.net/selinux/?rev=2114&view=rev
Author: madmethod
Date: 2006-11-29 13:12:08 -0800 (Wed, 29 Nov 2006)
Log Message:
-----------
Author: Daniel J Walsh
Email: dw...@re...
Subject: More small fixes to policycoreutils
Date: Wed, 22 Nov 2006 15:08:44 -0500
Amy's patch for handling exit codes in newrole.
Acked-By: Joshua Brindle <jbr...@tr...>
Acked-By: Stephen Smalley <sd...@ty...>
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2006-11-29 21:11:24 UTC (rev 2113)
+++ trunk/policycoreutils/newrole/newrole.c 2006-11-29 21:12:08 UTC (rev 2114)
@@ -1068,11 +1068,16 @@
*/
int rc;
int exit_code = 0;
+ int status;
do {
- rc = wait(NULL);
+ rc = wait(&status);
} while (rc < 0 && errno == EINTR);
+ /* Preserve child exit status, unless there is another error. */
+ if (WIFEXITED(status))
+ exit_code = WEXITSTATUS(status);
+
if (restore_tty_label(fd, ttyn, tty_context, new_tty_context)) {
fprintf(stderr, _("Unable to restore tty label...\n"));
exit_code = -1;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ssm...@us...> - 2007-02-22 16:03:09
|
Revision: 2264
http://svn.sourceforge.net/selinux/?rev=2264&view=rev
Author: ssmalley
Date: 2007-02-22 08:03:05 -0800 (Thu, 22 Feb 2007)
Log Message:
-----------
Author: Linda Knippers
Email: lin...@hp...
Subject: newrole: fix for newrole hanging on some serial consoles
Date: Thu, 22 Feb 2007 10:20:45 -0500
Reposting to fix a whitespace problem and adjust the patch location.
Signed-off-by: Linda Knippers <lin...@hp...>
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2007-02-22 14:56:16 UTC (rev 2263)
+++ trunk/policycoreutils/newrole/newrole.c 2007-02-22 16:03:05 UTC (rev 2264)
@@ -640,11 +640,12 @@
}
/* Re-open TTY descriptor */
- fd = open(ttyn, O_RDWR);
+ fd = open(ttyn, O_RDWR|O_NONBLOCK);
if (fd < 0) {
fprintf(stderr, _("Error! Could not open %s.\n"), ttyn);
return fd;
}
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
if (fgetfilecon(fd, &tty_con) < 0) {
fprintf(stderr, _("%s! Could not get current context "
@@ -1131,15 +1132,18 @@
fprintf(stderr, _("Could not close descriptors.\n"));
goto err_close_pam;
}
- fd = open(ttyn, O_RDONLY);
+ fd = open(ttyn, O_RDONLY|O_NONBLOCK);
if (fd != 0)
goto err_close_pam;
- fd = open(ttyn, O_RDWR);
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+ fd = open(ttyn, O_RDWR|O_NONBLOCK);
if (fd != 1)
goto err_close_pam;
- fd = open(ttyn, O_RDWR);
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+ fd = open(ttyn, O_RDWR|O_NONBLOCK);
if (fd != 2)
goto err_close_pam;
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
/*
* Step 5: Execute a new shell with the new context in `new_context'.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ssm...@us...> - 2007-12-21 16:49:26
|
Revision: 2709
http://selinux.svn.sourceforge.net/selinux/?rev=2709&view=rev
Author: ssmalley
Date: 2007-12-21 08:47:34 -0800 (Fri, 21 Dec 2007)
Log Message:
-----------
Author: "Reed, Tim \(US SSA\)"
Email: tim...@ba...
Subject: RE: newrole in the background
Date: Mon, 17 Dec 2007 12:40:13 -0800
Lets try this again....Patch Try #3
[allow newrole to be used non-interactively for command invocation
when configured to permit unauthenticated use]
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2007-12-14 15:38:00 UTC (rev 2708)
+++ trunk/policycoreutils/newrole/newrole.c 2007-12-21 16:47:34 UTC (rev 2709)
@@ -180,22 +180,24 @@
* program. This is the only function in this program that makes PAM
* calls.
*/
-int authenticate_via_pam(const char *ttyn, pam_handle_t *pam_handle)
+int authenticate_via_pam(const char *ttyn, pam_handle_t * pam_handle)
{
int result = 0; /* set to 0 (not authenticated) by default */
int pam_rc; /* pam return code */
const char *tty_name;
- if (strncmp(ttyn, "/dev/", 5) == 0)
- tty_name = ttyn + 5;
- else
- tty_name = ttyn;
+ if (ttyn) {
+ if (strncmp(ttyn, "/dev/", 5) == 0)
+ tty_name = ttyn + 5;
+ else
+ tty_name = ttyn;
- pam_rc = pam_set_item(pam_handle, PAM_TTY, tty_name);
- if (pam_rc != PAM_SUCCESS) {
- fprintf(stderr, _("failed to set PAM_TTY\n"));
- goto out;
+ pam_rc = pam_set_item(pam_handle, PAM_TTY, tty_name);
+ if (pam_rc != PAM_SUCCESS) {
+ fprintf(stderr, _("failed to set PAM_TTY\n"));
+ goto out;
+ }
}
/* Ask PAM to authenticate the user running this program */
@@ -216,8 +218,8 @@
#include "hashtab.h"
-static int free_hashtab_entry(hashtab_key_t key, hashtab_datum_t d,
- void *args __attribute__ ((unused)) )
+static int free_hashtab_entry(hashtab_key_t key, hashtab_datum_t d,
+ void *args __attribute__ ((unused)))
{
free(key);
free(d);
@@ -281,7 +283,8 @@
ret = hashtab_insert(app_service_names, app, service);
if (ret == HASHTAB_OVERFLOW) {
fprintf(stderr,
- _("newrole: service name configuration hashtable overflow\n"));
+ _
+ ("newrole: service name configuration hashtable overflow\n"));
goto err;
}
}
@@ -291,7 +294,8 @@
err:
free(app);
free(service);
- fprintf(stderr, _("newrole: %s: error on line %lu.\n"), config_file_path, lineno);
+ fprintf(stderr, _("newrole: %s: error on line %lu.\n"),
+ config_file_path, lineno);
free(line_buf);
return -1;
}
@@ -357,7 +361,7 @@
endspent();
if (!(p_shadow_line)) {
fprintf(stderr, _("Cannot find your entry in the shadow "
- "passwd file.\n"));
+ "passwd file.\n"));
return 0;
}
@@ -384,7 +388,7 @@
int found = 0;
const char *buf;
- if (! (shell_name && shell_name[0]))
+ if (!(shell_name && shell_name[0]))
return found;
while ((buf = getusershell()) != NULL) {
@@ -439,7 +443,7 @@
pw->pw_dir = strdup(pw->pw_dir);
pw->pw_shell = strdup(pw->pw_shell);
- if (! (pw->pw_name && pw->pw_dir && pw->pw_shell)) {
+ if (!(pw->pw_name && pw->pw_dir && pw->pw_shell)) {
fprintf(stderr, _("Out of memory!\n"));
goto out_free;
}
@@ -450,7 +454,7 @@
}
return 0;
-out_free:
+ out_free:
free(pw->pw_name);
free(pw->pw_dir);
free(pw->pw_shell);
@@ -473,8 +477,8 @@
char const *term_env;
char const *display_env;
char const *xauthority_env;
- char *term = NULL; /* temporary container */
- char *display = NULL; /* temporary container */
+ char *term = NULL; /* temporary container */
+ char *display = NULL; /* temporary container */
char *xauthority = NULL; /* temporary container */
int rc;
@@ -495,7 +499,7 @@
if (xauthority_env)
xauthority = strdup(xauthority_env);
if ((term_env && !term) || (display_env && !display) ||
- (xauthority_env && !xauthority)) {
+ (xauthority_env && !xauthority)) {
rc = -1;
goto out;
}
@@ -518,7 +522,7 @@
rc |= setenv("USER", pw->pw_name, 1);
rc |= setenv("LOGNAME", pw->pw_name, 1);
rc |= setenv("PATH", DEFAULT_PATH, 1);
-out:
+ out:
free(term);
free(display);
free(xauthority);
@@ -593,7 +597,7 @@
_("Error dropping SETUID capability, aborting\n"));
goto out;
}
-out:
+ out:
if (cap_free(tmp_caps) || cap_free(new_caps))
fprintf(stderr, _("Error freeing caps\n"));
return rc;
@@ -617,8 +621,9 @@
int rc = 0;
cap_t new_caps;
cap_value_t cap_list[] = { CAP_AUDIT_WRITE, CAP_SETUID,
- CAP_SYS_ADMIN, CAP_FOWNER, CAP_CHOWN,
- CAP_DAC_OVERRIDE };
+ CAP_SYS_ADMIN, CAP_FOWNER, CAP_CHOWN,
+ CAP_DAC_OVERRIDE
+ };
if (!getuid())
return 0;
@@ -647,7 +652,7 @@
fprintf(stderr, _("Error dropping capabilities, aborting\n"));
goto out;
}
-out:
+ out:
if (cap_free(new_caps))
fprintf(stderr, _("Error freeing caps\n"));
return rc;
@@ -738,21 +743,24 @@
* in permissive mode.
*/
static int relabel_tty(const char *ttyn, security_context_t new_context,
- security_context_t *tty_context,
- security_context_t *new_tty_context)
+ security_context_t * tty_context,
+ security_context_t * new_tty_context)
{
int fd;
int enforcing = security_getenforce();
security_context_t tty_con = NULL;
security_context_t new_tty_con = NULL;
+ if (!ttyn)
+ return 0;
+
if (enforcing < 0) {
fprintf(stderr, _("Could not determine enforcing mode.\n"));
return -1;
}
/* Re-open TTY descriptor */
- fd = open(ttyn, O_RDWR|O_NONBLOCK);
+ fd = open(ttyn, O_RDWR | O_NONBLOCK);
if (fd < 0) {
fprintf(stderr, _("Error! Could not open %s.\n"), ttyn);
return fd;
@@ -761,7 +769,7 @@
if (fgetfilecon(fd, &tty_con) < 0) {
fprintf(stderr, _("%s! Could not get current context "
- "for %s, not relabeling tty.\n"),
+ "for %s, not relabeling tty.\n"),
enforcing ? "Error" : "Warning", ttyn);
if (enforcing)
goto close_fd;
@@ -770,8 +778,8 @@
if (tty_con &&
(security_compute_relabel(new_context, tty_con,
SECCLASS_CHR_FILE, &new_tty_con) < 0)) {
- fprintf(stderr, _("%s! Could not get new context for %s, "
- "not relabeling tty.\n"),
+ fprintf(stderr, _("%s! Could not get new context for %s, "
+ "not relabeling tty.\n"),
enforcing ? "Error" : "Warning", ttyn);
if (enforcing)
goto close_fd;
@@ -792,7 +800,7 @@
*new_tty_context = new_tty_con;
return fd;
-close_fd:
+ close_fd:
freecon(tty_con);
close(fd);
return -1;
@@ -814,6 +822,9 @@
int rc = 0;
security_context_t chk_tty_context = NULL;
+ if (!ttyn)
+ goto skip_relabel;
+
if (!new_tty_context)
goto skip_relabel;
@@ -831,7 +842,7 @@
if ((rc = fsetfilecon(fd, tty_context)) < 0)
fprintf(stderr,
_("Warning! Could not restore context for %s\n"), ttyn);
-skip_relabel:
+ skip_relabel:
freecon(chk_tty_context);
return rc;
}
@@ -847,7 +858,7 @@
*/
static int parse_command_line_arguments(int argc, char **argv, char *ttyn,
security_context_t old_context,
- security_context_t *new_context,
+ security_context_t * new_context,
int *preserve_environment)
{
int flag_index; /* flag index in argv[] */
@@ -859,7 +870,7 @@
char *range_ptr = NULL;
security_context_t new_con = NULL;
security_context_t tty_con = NULL;
- context_t context = NULL; /* manipulatable form of new_context */
+ context_t context = NULL; /* manipulatable form of new_context */
const struct option long_options[] = {
{"role", 1, 0, 'r'},
{"type", 1, 0, 't'},
@@ -903,21 +914,26 @@
case 'l':
if (!is_selinux_mls_enabled()) {
fprintf(stderr, _("Sorry, -l may be used with "
- "SELinux MLS support.\n"));
+ "SELinux MLS support.\n"));
return -1;
}
if (level_s) {
fprintf(stderr, _("Error: multiple levels "
- "specified\n"));
+ "specified\n"));
return -1;
}
- if (fgetfilecon(0,&tty_con) >= 0) {
- if (selinux_check_securetty_context(tty_con) < 0) {
- fprintf(stderr, _("Error: you are not allowed to change levels on a non secure terminal\n"));
+ if (ttyn) {
+ if (fgetfilecon(STDIN_FILENO, &tty_con) >= 0) {
+ if (selinux_check_securetty_context
+ (tty_con) < 0) {
+ fprintf(stderr,
+ _
+ ("Error: you are not allowed to change levels on a non secure terminal \n"));
+ freecon(tty_con);
+ return -1;
+ }
freecon(tty_con);
- return -1;
}
- freecon(tty_con);
}
level_s = optarg;
@@ -936,7 +952,7 @@
/* Fill in a default type if one hasn't been specified. */
if (role_s && !type_s) {
- /* get_default_type() returns malloc'd memory */
+ /* get_default_type() returns malloc'd memory */
if (get_default_type(role_s, &type_ptr)) {
fprintf(stderr, _("Couldn't get default type.\n"));
send_audit_message(0, old_context, new_con, ttyn);
@@ -968,7 +984,8 @@
}
if (level_s) {
- range_ptr = build_new_range(level_s,context_range_get(context));
+ range_ptr =
+ build_new_range(level_s, context_range_get(context));
if (!range_ptr) {
fprintf(stderr,
_("failed to build new range with level %s\n"),
@@ -1005,7 +1022,7 @@
context_free(context);
return 0;
-err_free:
+ err_free:
free(type_ptr);
free(range_ptr);
/* Don't free new_con, context_free(context) handles this */
@@ -1048,7 +1065,7 @@
security_context_t new_context = NULL; /* target security context */
security_context_t old_context = NULL; /* original securiy context */
security_context_t tty_context = NULL; /* current context of tty */
- security_context_t new_tty_context = NULL; /* new context of tty */
+ security_context_t new_tty_context = NULL; /* new context of tty */
struct passwd pw; /* struct derived from passwd file line */
char *ttyn = NULL; /* tty path */
@@ -1062,8 +1079,8 @@
#ifdef USE_PAM
int rc;
- int pam_status; /* pam return code */
- pam_handle_t *pam_handle; /* opaque handle used by all PAM functions */
+ int pam_status; /* pam return code */
+ pam_handle_t *pam_handle; /* opaque handle used by all PAM functions */
/* This is a jump table of functions for PAM to use when it wants to *
* communicate with the user. We'll be using misc_conv(), which is *
@@ -1097,7 +1114,7 @@
if (!is_selinux_enabled()) {
fprintf(stderr, _("Sorry, newrole may be used only on "
- "a SELinux kernel.\n"));
+ "a SELinux kernel.\n"));
return -1;
}
@@ -1117,11 +1134,10 @@
return -1;
}
- ttyn = ttyname(0);
+ ttyn = ttyname(STDIN_FILENO);
if (!ttyn || *ttyn == '\0') {
fprintf(stderr,
- _("Error! Could not retrieve tty information.\n"));
- return -1;
+ _("Warning! Could not retrieve tty information.\n"));
}
if (parse_command_line_arguments(argc, argv, ttyn, old_context,
@@ -1141,7 +1157,8 @@
#ifdef USE_PAM
if (read_pam_config()) {
- fprintf(stderr, _("error on reading PAM service configuration.\n"));
+ fprintf(stderr,
+ _("error on reading PAM service configuration.\n"));
goto err_free;
}
@@ -1240,7 +1257,7 @@
}
#ifdef USE_PAM
#ifdef NAMESPACE_PRIV
- pam_status = pam_close_session(pam_handle,0);
+ pam_status = pam_close_session(pam_handle, 0);
if (pam_status != PAM_SUCCESS) {
fprintf(stderr, "pam_close_session failed with %s\n",
pam_strerror(pam_handle, pam_status));
@@ -1265,23 +1282,25 @@
/* CHILD */
/* Close the tty and reopen descriptors 0 through 2 */
- if (close(fd) || close(0) || close(1) || close(2)) {
- fprintf(stderr, _("Could not close descriptors.\n"));
- goto err_close_pam;
+ if (ttyn) {
+ if (close(fd) || close(0) || close(1) || close(2)) {
+ fprintf(stderr, _("Could not close descriptors.\n"));
+ goto err_close_pam;
+ }
+ fd = open(ttyn, O_RDONLY | O_NONBLOCK);
+ if (fd != 0)
+ goto err_close_pam;
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+ fd = open(ttyn, O_RDWR | O_NONBLOCK);
+ if (fd != 1)
+ goto err_close_pam;
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+ fd = open(ttyn, O_RDWR | O_NONBLOCK);
+ if (fd != 2)
+ goto err_close_pam;
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
+
}
- fd = open(ttyn, O_RDONLY|O_NONBLOCK);
- if (fd != 0)
- goto err_close_pam;
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
- fd = open(ttyn, O_RDWR|O_NONBLOCK);
- if (fd != 1)
- goto err_close_pam;
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
- fd = open(ttyn, O_RDWR|O_NONBLOCK);
- if (fd != 2)
- goto err_close_pam;
- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
-
/*
* Step 5: Execute a new shell with the new context in `new_context'.
*
@@ -1296,17 +1315,16 @@
shell_argv0 = NULL;
goto err_close_pam;
}
- argv[optind-1] = shell_argv0;
+ argv[optind - 1] = shell_argv0;
if (setexeccon(new_context)) {
fprintf(stderr, _("Could not set exec context to %s.\n"),
new_context);
goto err_close_pam;
}
-
#ifdef NAMESPACE_PRIV
/* Ask PAM to setup session for user running this program */
- pam_status = pam_open_session(pam_handle,0);
+ pam_status = pam_open_session(pam_handle, 0);
if (pam_status != PAM_SUCCESS) {
fprintf(stderr, "pam_open_session failed with %s\n",
pam_strerror(pam_handle, pam_status));
@@ -1326,7 +1344,7 @@
/* Handle environment changes */
if (restore_environment(preserve_environment, old_environ, &pw)) {
fprintf(stderr, _("Unable to restore the environment, "
- "aborting\n"));
+ "aborting\n"));
goto err_close_pam_session;
}
execv(pw.pw_shell, argv + optind - 1);
@@ -1337,21 +1355,21 @@
* If we reach here, then we failed to exec the new shell.
*/
perror(_("failed to exec shell\n"));
-err_close_pam_session:
+ err_close_pam_session:
#ifdef NAMESPACE_PRIV
- pam_status = pam_close_session(pam_handle,0);
- if(pam_status != PAM_SUCCESS)
+ pam_status = pam_close_session(pam_handle, 0);
+ if (pam_status != PAM_SUCCESS)
fprintf(stderr, "pam_close_session failed with %s\n",
pam_strerror(pam_handle, pam_status));
#endif
-err_close_pam:
+ err_close_pam:
#ifdef USE_PAM
rc = pam_end(pam_handle, pam_status);
if (rc != PAM_SUCCESS)
fprintf(stderr, "pam_end failed with %s\n",
pam_strerror(pam_handle, rc));
#endif
-err_free:
+ err_free:
freecon(tty_context);
freecon(new_tty_context);
freecon(old_context);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <mil...@us...> - 2008-01-09 15:33:53
|
Revision: 2727
http://selinux.svn.sourceforge.net/selinux/?rev=2727&view=rev
Author: millertc
Date: 2008-01-09 07:33:51 -0800 (Wed, 09 Jan 2008)
Log Message:
-----------
Fix shadowed variable declaration.
Modified Paths:
--------------
trunk/policycoreutils/newrole/newrole.c
Modified: trunk/policycoreutils/newrole/newrole.c
===================================================================
--- trunk/policycoreutils/newrole/newrole.c 2008-01-09 14:25:39 UTC (rev 2726)
+++ trunk/policycoreutils/newrole/newrole.c 2008-01-09 15:33:51 UTC (rev 2727)
@@ -1233,13 +1233,13 @@
* since we are doing cleanup which needs to be done.
* We can exit with a bad rc though
*/
- int rc;
+ pid_t pid;
int exit_code = 0;
int status;
do {
- rc = wait(&status);
- } while (rc < 0 && errno == EINTR);
+ pid = wait(&status);
+ } while (pid < 0 && errno == EINTR);
/* Preserve child exit status, unless there is another error. */
if (WIFEXITED(status))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|