[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