[PATCH 2/3] pam_namespace: Add new functions to factor out code
David Quigley
dpquigl at tycho.nsa.gov
Mon Jul 24 17:23:08 UTC 2006
From: David Quigley <dpquigl at tycho.nsa.gov>
This patch adds several functions which are large sections of code taken
from the existing code base to make the code more readable.
Signed-Off-By: David Quigley <dpquigl at tycho.nsa.gov>
---
pam_namespace.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 190 insertions(+)
diff -uprN -X dontdiff pam_namespace_header/pam_namespace.c pam_namespace_functions/pam_namespace.c
--- pam_namespace_header/pam_namespace.c 2006-07-24 12:40:13.000000000 -0400
+++ pam_namespace_functions/pam_namespace.c 2006-07-24 13:01:34.000000000 -0400
@@ -33,6 +33,32 @@
#include "pam_namespace.h"
/*
+ * Copies the contents of ent into pent
+ */
+static int copy_ent(const struct polydir_s *ent, struct polydir_s *pent)
+{
+ unsigned int i;
+
+ strcpy(pent->dir, ent->dir);
+ strcpy(pent->instance_prefix, ent->instance_prefix);
+ pent->method = ent->method;
+ pent->num_uids = ent->num_uids;
+ if (ent->num_uids) {
+ uid_t *pptr, *eptr;
+
+ pent->uid = (uid_t *) malloc(ent->num_uids * sizeof(uid_t));
+ if (!(pent->uid)) {
+ return -1;
+ }
+ for (i = 0, pptr = pent->uid, eptr = ent->uid; i < ent->num_uids;
+ i++, eptr++, pptr++)
+ *pptr = *eptr;
+ } else
+ pent->uid = NULL;
+ return 0;
+}
+
+/*
* Adds an entry for a polyinstantiated directory to the linked list of
* polyinstantiated directories. It is called from process_line() while
* parsing the namespace configuration file.
@@ -413,6 +439,54 @@ static int ns_override(struct polydir_s
return 0;
}
+#ifdef WITH_SELINUX
+static int form_context(const struct polydir_s *polyptr,
+ security_context_t *i_context, security_context_t *origcon,
+ struct instance_data *idata)
+{
+ int rc = PAM_SUCCESS;
+ security_context_t scon = NULL;
+ security_class_t tclass;
+
+ /*
+ * Get the security context of the directory to polyinstantiate.
+ */
+ rc = getfilecon(polyptr->dir, origcon);
+ if (rc < 0 || *origcon == NULL) {
+ pam_syslog(idata->pamh, LOG_ERR,
+ "Error getting poly dir context, %m");
+ return PAM_SESSION_ERR;
+ }
+
+ /*
+ * If polyinstantiating based on security context, get current
+ * process security context, get security class for directories,
+ * and ask the policy to provide security context of the
+ * polyinstantiated instance directory.
+ */
+ if ((polyptr->method == CONTEXT) || (polyptr->method == BOTH)) {
+ rc = getexeccon(&scon);
+ if (rc < 0 || scon == NULL) {
+ pam_syslog(idata->pamh, LOG_ERR,
+ "Error getting exec context, %m");
+ return PAM_SESSION_ERR;
+ }
+ tclass = string_to_security_class("dir");
+
+ if (security_compute_member(scon, *origcon, tclass,
+ i_context) < 0) {
+ pam_syslog(idata->pamh, LOG_ERR,
+ "Error computing poly dir member context");
+ freecon(scon);
+ return PAM_SESSION_ERR;
+ } else if (idata->flags & PAMNS_DEBUG)
+ pam_syslog(idata->pamh, LOG_DEBUG,
+ "member context returned by policy %s", *i_context);
+ freecon(scon);
+ }
+ return PAM_SUCCESS;
+}
+#endif
/*
* poly_name returns the name of the polyinstantiated instance directory
@@ -516,6 +590,122 @@ static int poly_name(const struct polydi
return rc;
}
+static int check_inst_parent(char *ipath, struct instance_data *idata)
+{
+ struct stat instpbuf;
+ char *inst_parent, *trailing_slash;
+ /*
+ * stat the instance parent path to make sure it exists
+ * and is a directory. Check that its mode is 000 (unless the
+ * admin explicitly instructs to ignore the instance parent
+ * mode by the "ignore_instance_parent_mode" argument).
+ */
+ inst_parent = (char *) malloc(strlen(ipath)+1);
+ if (!inst_parent) {
+ pam_syslog(idata->pamh, LOG_ERR, "Error allocating pathname string");
+ return PAM_SESSION_ERR;
+ }
+
+ strcpy(inst_parent, ipath);
+ trailing_slash = strrchr(inst_parent, '/');
+ if (trailing_slash)
+ *trailing_slash = '\0';
+
+ if (stat(inst_parent, &instpbuf) < 0) {
+ pam_syslog(idata->pamh, LOG_ERR, "Error stating %s, %m", inst_parent);
+ free(inst_parent);
+ return PAM_SESSION_ERR;
+ }
+
+ /*
+ * Make sure we are dealing with a directory
+ */
+ if (!S_ISDIR(instpbuf.st_mode)) {
+ pam_syslog(idata->pamh, LOG_ERR, "Instance parent %s is not a dir",
+ inst_parent);
+ free(inst_parent);
+ return PAM_SESSION_ERR;
+ }
+
+ if ((idata->flags & PAMNS_IGN_INST_PARENT_MODE) == 0) {
+ if (instpbuf.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) {
+ pam_syslog(idata->pamh, LOG_ERR, "Mode of inst parent %s not 000",
+ inst_parent);
+ free(inst_parent);
+ return PAM_SESSION_ERR;
+ }
+ }
+ free(inst_parent);
+ return PAM_SUCCESS;
+}
+
+/*
+* Check to see if there is a namespace initialization script in
+* the /etc/security directory. If such a script exists
+* execute it and pass directory to polyinstantiate and instance
+* directory as arguments.
+*/
+static int inst_init(const struct polydir_s *polyptr, char *ipath,
+ struct instance_data *idata)
+{
+ pid_t rc, pid;
+ sighandler_t osighand = NULL;
+ int status;
+
+ osighand = signal(SIGCHLD, SIG_DFL);
+ if (osighand == SIG_ERR) {
+ pam_syslog(idata->pamh, LOG_ERR, "Cannot set signal value");
+ rc = PAM_SESSION_ERR;
+ goto out;
+ }
+
+ if (access(NAMESPACE_INIT_SCRIPT, F_OK) == 0) {
+ if (access(NAMESPACE_INIT_SCRIPT, X_OK) < 0) {
+ if (idata->flags & PAMNS_DEBUG)
+ pam_syslog(idata->pamh, LOG_ERR,
+ "Namespace init script not executable");
+ rc = PAM_SESSION_ERR;
+ goto out;
+ } else {
+ pid = fork();
+ if (pid == 0) {
+#ifdef WITH_SELINUX
+ if (idata->flags & PAMNS_SELINUX_ENABLED) {
+ if (setexeccon(NULL) < 0)
+ exit(1);
+ }
+#endif
+ if (execl(NAMESPACE_INIT_SCRIPT, NAMESPACE_INIT_SCRIPT,
+ polyptr->dir, ipath, (char *)NULL) < 0)
+ exit(1);
+ } else if (pid > 0) {
+ while (((rc = waitpid(pid, &status, 0)) == (pid_t)-1) &&
+ (errno == EINTR));
+ if (rc == (pid_t)-1) {
+ pam_syslog(idata->pamh, LOG_ERR, "waitpid failed- %m");
+ rc = PAM_SESSION_ERR;
+ goto out;
+ }
+ if (!WIFEXITED(status) || WIFSIGNALED(status) > 0) {
+ pam_syslog(idata->pamh, LOG_ERR,
+ "Error initializing instance");
+ rc = PAM_SESSION_ERR;
+ goto out;
+ }
+ } else if (pid < 0) {
+ pam_syslog(idata->pamh, LOG_ERR,
+ "Cannot fork to run namespace init script, %m");
+ rc = PAM_SESSION_ERR;
+ goto out;
+ }
+ }
+ }
+ rc = PAM_SUCCESS;
+out:
+ (void) signal(SIGCHLD, osighand);
+
+ return rc;
+}
/*
* Create polyinstantiated instance directory (ipath).
More information about the Pam-list
mailing list