Separate the code that opens and validates the policy file from the code

that searches for it.  If the service name contains a path separator
character, treat it is a relative or absolute path to the policy file.

This need to be documented either in pam.conf(5) or in pam_start(3) once
the feature mechanism is no longer experimental.


git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@600 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
Dag-Erling Smørgrav 2012-04-14 16:11:39 +00:00
parent aa1f7162f1
commit 7ca68ffaec
1 changed files with 69 additions and 31 deletions

View File

@ -314,6 +314,53 @@ static const char *openpam_policy_path[] = {
NULL
};
/*
* Read the specified chains from the specified file.
*
* Returns 0 if the file exists but does not contain any matching lines.
*
* Returns -1 and sets errno to ENOENT if the file does not exist.
*
* Returns -1 and sets errno to some other non-zero value if the file
* exists but is unsafe or unreadable, or an I/O error occurs.
*/
static int
openpam_load_file(pam_handle_t *pamh,
const char *service,
pam_facility_t facility,
const char *filename,
openpam_style_t style)
{
FILE *f;
int ret, serrno;
/* attempt to open the file */
if ((f = fopen(filename, "r")) == NULL) {
serrno = errno;
openpam_log(errno == ENOENT ? PAM_LOG_DEBUG : PAM_LOG_ERROR,
"%s: %m", filename);
errno = serrno;
RETURNN(-1);
} else {
openpam_log(PAM_LOG_DEBUG, "found %s", filename);
}
/* verify type, ownership and permissions */
if (OPENPAM_FEATURE(VERIFY_POLICY_FILE) &&
openpam_check_desc_owner_perms(filename, fileno(f)) != 0) {
/* already logged the cause */
serrno = errno;
fclose(f);
errno = serrno;
RETURNN(-1);
}
/* parse the file */
ret = openpam_parse_chain(pamh, service, facility,
f, filename, style);
RETURNN(ret);
}
/*
* Locates the policy file for a given service and reads the given chains
* from it.
@ -327,7 +374,7 @@ openpam_load_chain(pam_handle_t *pamh,
const char *service,
pam_facility_t facility)
{
const char **path;
const char *p, **path;
char filename[PATH_MAX];
size_t len;
openpam_style_t style;
@ -335,6 +382,19 @@ openpam_load_chain(pam_handle_t *pamh,
int ret, serrno;
ENTERS(facility < 0 ? "any" : pam_facility_name[facility]);
/* either absolute or relative to cwd */
if (strchr(service, '/') != NULL) {
if (p = strrchr(service, '.') && strcmp(p, ".conf") == 0)
style = pam_conf_style;
else
style = pam_d_style;
ret = openpam_load_file(pamh, service, facility,
service, style);
RETURNN(ret);
}
/* search standard locations */
for (path = openpam_policy_path; *path != NULL; ++path) {
/* construct filename */
len = strlcpy(filename, *path, sizeof filename);
@ -348,39 +408,17 @@ openpam_load_chain(pam_handle_t *pamh,
} else {
style = pam_conf_style;
}
/* attempt to open the file */
if ((f = fopen(filename, "r")) == NULL) {
if (errno == ENOENT || errno == ENOTDIR) {
openpam_log(PAM_LOG_DEBUG, "%s: %m", filename);
continue;
} else {
serrno = errno;
openpam_log(PAM_LOG_ERROR, "%s: %m", filename);
errno = serrno;
RETURNN(-1);
}
} else {
openpam_log(PAM_LOG_DEBUG, "found %s", filename);
}
/* verify type, ownership and permissions */
if (OPENPAM_FEATURE(VERIFY_POLICY_FILE) &&
openpam_check_desc_owner_perms(filename, fileno(f)) != 0) {
serrno = errno;
fclose(f);
errno = serrno;
RETURNN(-1);
}
/* parse the file */
ret = openpam_parse_chain(pamh, service, facility,
f, filename, style);
ret = openpam_load_file(pamh, service, facility,
filename, style);
/* the file exists, but an error occurred */
if (ret == -1 && errno != ENOENT)
RETURNN(ret);
/* in pam.d style, an empty file counts as a hit */
if (ret != 0 || style == pam_d_style)
if (ret == 0 && style == pam_d_style)
RETURNN(ret);
}
/* no hit */
RETURNN(0);
}