From 7ca68ffaecd713b0b4b615278ca730522cbfc687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Sat, 14 Apr 2012 16:11:39 +0000 Subject: [PATCH] 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 --- lib/openpam_configure.c | 100 +++++++++++++++++++++++++++------------- 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/lib/openpam_configure.c b/lib/openpam_configure.c index 9482699..7c13e72 100644 --- a/lib/openpam_configure.c +++ b/lib/openpam_configure.c @@ -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); }