Module Name:    src
Committed By:   msaitoh
Date:           Wed Jun 18 02:15:27 UTC 2014

Modified Files:
        src/external/bsd/openpam/dist/lib [netbsd-6-1]: openpam_configure.c

Log Message:
Pull up following revision(s) (requested by christos in ticket #1076):
        src/external/bsd/openpam/dist/lib/openpam_configure.c 1.8 via patch

CVE-2014-3879: Incorrect error handling in PAM policy parser:
Missing module files were treated as soft failures leading to
unexpected behavior if policy files were copied between hosts with
differently installed modules or in the short period during upgrades
when module files were being replaced.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.4.16.1 \
    src/external/bsd/openpam/dist/lib/openpam_configure.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/bsd/openpam/dist/lib/openpam_configure.c
diff -u src/external/bsd/openpam/dist/lib/openpam_configure.c:1.4 src/external/bsd/openpam/dist/lib/openpam_configure.c:1.4.16.1
--- src/external/bsd/openpam/dist/lib/openpam_configure.c:1.4	Tue Jan  3 18:56:49 2012
+++ src/external/bsd/openpam/dist/lib/openpam_configure.c	Wed Jun 18 02:15:27 2014
@@ -1,8 +1,8 @@
-/*	$NetBSD: openpam_configure.c,v 1.4 2012/01/03 18:56:49 christos Exp $	*/
+/*	$NetBSD: openpam_configure.c,v 1.4.16.1 2014/06/18 02:15:27 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 2001-2003 Networks Associates Technology, Inc.
- * Copyright (c) 2004-2011 Dag-Erling Smørgrav
+ * Copyright (c) 2004-2014 Dag-Erling Smørgrav
  * All rights reserved.
  *
  * This software was developed for the FreeBSD Project by ThinkSec AS and
@@ -365,12 +365,17 @@ openpam_parse_chain(pam_handle_t *pamh,
 	char *line, *str, *name;
 	char *option, **optv;
 	size_t len;
-	int lineno, ret;
+	int lineno, ret, serrno;
 	FILE *f;
 
+	if (errno == ENOENT)
+		errno = 0;
+
 	if ((f = fopen(filename, "r")) == NULL) {
+		serrno = errno;
 		openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_NOTICE,
 		    "%s: %s", filename, strerror(errno));
+		errno = serrno;
 		return (PAM_SUCCESS);
 	}
 	if (openpam_check_desc_owner_perms(filename, fileno(f)) != 0) {
@@ -380,6 +385,7 @@ openpam_parse_chain(pam_handle_t *pamh,
 	this = NULL;
 	name = NULL;
 	lineno = 0;
+	serrno = 0;
 	while ((line = openpam_readline(f, &lineno, NULL)) != NULL) {
 		/* get service name if necessary */
 		if (style == pam_conf_style) {
@@ -425,9 +431,14 @@ openpam_parse_chain(pam_handle_t *pamh,
 				goto fail;
 			}
 			ret = openpam_load_chain(pamh, name, fclt);
-			FREE(name);
-			if (ret != PAM_SUCCESS)
+			if (ret != PAM_SUCCESS || errno == ENOENT) {
+				serrno = errno;
+				openpam_log(PAM_LOG_ERROR, "failed loading "
+					"include for service %s in %s: %s",
+					name, filename, strerror(errno));
 				goto fail;
+			}
+			FREE(name);
 			FREE(line);
 			continue;
 		}
@@ -477,9 +488,11 @@ openpam_parse_chain(pam_handle_t *pamh,
 
 		/* load module */
 		this->module = openpam_load_module(name);
-		FREE(name);
-		if (this->module == NULL)
+		if (this->module == NULL) {
+			serrno = (errno == ENOENT ? ENOEXEC : errno);
 			goto fail;
+		}
+		FREE(name);
 
 		/* hook it up */
 		for (next = &pamh->chains[fclt]; *next != NULL;
@@ -496,6 +509,7 @@ openpam_parse_chain(pam_handle_t *pamh,
 	fclose(f);
 	return (PAM_SUCCESS);
 syserr:
+	serrno = errno;
 	openpam_log(PAM_LOG_ERROR, "%s: %s", filename, strerror(errno));
 fail:
 	if (this && this->optc) {
@@ -507,6 +521,10 @@ fail:
 	FREE(line);
 	FREE(name);
 	fclose(f);
+	if (serrno == 0)
+		errno = EINVAL;
+	else
+		errno = serrno;
 	return (PAM_SYSTEM_ERR);
 }
 
@@ -534,7 +552,7 @@ openpam_load_chain(pam_handle_t *pamh,
 	const char **path;
 	char *filename;
 	size_t len;
-	int ret;
+	int ret, serrno;
 
 	/* don't allow to escape from policy_path */
 	if (strchr(service, '/')) {
@@ -542,6 +560,7 @@ openpam_load_chain(pam_handle_t *pamh,
 		return (-PAM_SYSTEM_ERR);
 	}
 
+	ret = PAM_SYSTEM_ERR; /* shut up compiler stupidity */
 	for (path = openpam_policy_path; *path != NULL; ++path) {
 		len = strlen(*path);
 		if ((*path)[len - 1] == '/') {
@@ -552,11 +571,19 @@ openpam_load_chain(pam_handle_t *pamh,
 			}
 			ret = openpam_parse_chain(pamh, service, facility,
 			    filename, pam_d_style);
+			serrno = errno;
 			FREE(filename);
+			errno = serrno;
 		} else {
 			ret = openpam_parse_chain(pamh, service, facility,
 			    *path, pam_conf_style);
 		}
+
+		/* If /etc/pam.d/ exists, /etc/pam.conf will be ignored */
+		if (ret == PAM_SUCCESS && errno != ENOENT)
+			return (PAM_SUCCESS);
+
+		/* If we had a definitive error, bail out immediately */
 		if (ret != PAM_SUCCESS)
 			return (ret);
 	}

Reply via email to