summaryrefslogtreecommitdiff
path: root/libpam
diff options
context:
space:
mode:
authorThorsten Kukuk <kukuk@thkukuk.de>2015-03-25 15:00:38 +0100
committerThorsten Kukuk <kukuk@thkukuk.de>2015-03-25 15:00:38 +0100
commit10b83ef224a5e9c3e2663b3f08dd17090acc58ab (patch)
tree82a9a446b061cb90384bc195478e1383c83a53ee /libpam
parent73bdfac8c091492f466342feb8f2f5daa2f4c39b (diff)
Support alternative "vendor configuration" files as fallback to /etc
(Ticket#34, patch from ay Sievers <kay@vrfy.org>) * doc/man/pam.8.xml: document additonal config directory * libpam/pam_handlers.c: add /usr/lib/pam.d as config file fallback directory * libpam/pam_private.h: adjust defines
Diffstat (limited to 'libpam')
-rw-r--r--libpam/pam_handlers.c124
-rw-r--r--libpam/pam_private.h9
2 files changed, 87 insertions, 46 deletions
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
index df3a1d91..bc3fd9d8 100644
--- a/libpam/pam_handlers.c
+++ b/libpam/pam_handlers.c
@@ -274,6 +274,66 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
return ( (x < 0) ? PAM_ABORT:PAM_SUCCESS );
}
+static int
+_pam_open_config_file(pam_handle_t *pamh
+ , const char *service
+ , char **path
+ , FILE **file)
+{
+ char *p;
+ FILE *f;
+ int err = 0;
+
+ /* Absolute path */
+ if (service[0] == '/') {
+ p = _pam_strdup(service);
+ if (p == NULL) {
+ pam_syslog(pamh, LOG_CRIT, "strdup failed");
+ return PAM_BUF_ERR;
+ }
+
+ f = fopen(service, "r");
+ if (f != NULL) {
+ *path = p;
+ *file = f;
+ return PAM_SUCCESS;
+ }
+
+ _pam_drop(p);
+ return PAM_ABORT;
+ }
+
+ /* Local Machine Configuration /etc/pam.d/ */
+ if (asprintf (&p, PAM_CONFIG_DF, service) < 0) {
+ pam_syslog(pamh, LOG_CRIT, "asprintf failed");
+ return PAM_BUF_ERR;
+ }
+ D(("opening %s", p));
+ f = fopen(p, "r");
+ if (f != NULL) {
+ *path = p;
+ *file = f;
+ return PAM_SUCCESS;
+ }
+
+ /* System Configuration /usr/lib/pam.d/ */
+ _pam_drop(p);
+ if (asprintf (&p, PAM_CONFIG_DIST_DF, service) < 0) {
+ pam_syslog(pamh, LOG_CRIT, "asprintf failed");
+ return PAM_BUF_ERR;
+ }
+ D(("opening %s", p));
+ f = fopen(p, "r");
+ if (f != NULL) {
+ *path = p;
+ *file = f;
+ return PAM_SUCCESS;
+ }
+ _pam_drop(p);
+
+ return PAM_ABORT;
+}
+
static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
, const char *service /* specific file */
, int module_type /* specific type */
@@ -284,7 +344,7 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
)
{
FILE *f;
- char *config_path = NULL;
+ char *path = NULL;
int retval = PAM_ABORT;
D(("_pam_load_conf_file called"));
@@ -297,39 +357,29 @@ static int _pam_load_conf_file(pam_handle_t *pamh, const char *config_name
if (config_name == NULL) {
D(("no config file supplied"));
- pam_syslog(pamh, LOG_ERR, "(%s) no config file supplied", service);
+ pam_syslog(pamh, LOG_ERR, "(%s) no config name supplied", service);
return PAM_ABORT;
}
- if (config_name[0] != '/') {
- if (asprintf (&config_path, PAM_CONFIG_DF, config_name) < 0) {
- pam_syslog(pamh, LOG_CRIT, "asprintf failed");
- return PAM_BUF_ERR;
- }
- config_name = config_path;
- }
-
- D(("opening %s", config_name));
- f = fopen(config_name, "r");
- if (f != NULL) {
+ if (_pam_open_config_file(pamh, config_name, &path, &f) == PAM_SUCCESS) {
retval = _pam_parse_conf_file(pamh, f, service, module_type, stack_level
#ifdef PAM_READ_BOTH_CONFS
, not_other
#endif /* PAM_READ_BOTH_CONFS */
);
- fclose(f);
if (retval != PAM_SUCCESS)
pam_syslog(pamh, LOG_ERR,
"_pam_load_conf_file: error reading %s: %s",
- config_name, pam_strerror(pamh, retval));
+ path, pam_strerror(pamh, retval));
+ _pam_drop(path);
+ fclose(f);
} else {
D(("unable to open %s", config_name));
pam_syslog(pamh, LOG_ERR,
- "_pam_load_conf_file: unable to open %s",
+ "_pam_load_conf_file: unable to open config for %s",
config_name);
}
- _pam_drop(config_path);
return retval;
}
@@ -396,39 +446,31 @@ int _pam_init_handlers(pam_handle_t *pamh)
struct stat test_d;
/* Is there a PAM_CONFIG_D directory? */
- if ( stat(PAM_CONFIG_D, &test_d) == 0 && S_ISDIR(test_d.st_mode) ) {
- char *filename;
+ if ((stat(PAM_CONFIG_D, &test_d) == 0 && S_ISDIR(test_d.st_mode)) ||
+ (stat(PAM_CONFIG_DIST_D, &test_d) == 0 && S_ISDIR(test_d.st_mode))) {
+ char *path = NULL;
int read_something=0;
- D(("searching " PAM_CONFIG_D " for config files"));
- if (asprintf(&filename, PAM_CONFIG_DF, pamh->service_name) < 0) {
- pam_syslog(pamh, LOG_ERR,
- "_pam_init_handlers: no memory; service %s",
- pamh->service_name);
- return PAM_BUF_ERR;
- }
- D(("opening %s", filename));
- f = fopen(filename, "r");
- if (f != NULL) {
- /* would test magic here? */
+ if (_pam_open_config_file(pamh, pamh->service_name, &path, &f) == PAM_SUCCESS) {
retval = _pam_parse_conf_file(pamh, f, pamh->service_name,
PAM_T_ANY, 0
#ifdef PAM_READ_BOTH_CONFS
, 0
#endif /* PAM_READ_BOTH_CONFS */
);
- fclose(f);
if (retval != PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR,
"_pam_init_handlers: error reading %s",
- filename);
+ path);
pam_syslog(pamh, LOG_ERR, "_pam_init_handlers: [%s]",
pam_strerror(pamh, retval));
} else {
read_something = 1;
}
+ _pam_drop(path);
+ fclose(f);
} else {
- D(("unable to open %s", filename));
+ D(("unable to open configuration for %s", pamh->service_name));
#ifdef PAM_READ_BOTH_CONFS
D(("checking %s", PAM_CONFIG));
@@ -443,14 +485,11 @@ int _pam_init_handlers(pam_handle_t *pamh)
* use "other"
*/
}
- _pam_drop(filename);
if (retval == PAM_SUCCESS) {
- /* now parse the PAM_DEFAULT_SERVICE_FILE */
+ /* now parse the PAM_DEFAULT_SERVICE */
- D(("opening %s", PAM_DEFAULT_SERVICE_FILE));
- f = fopen(PAM_DEFAULT_SERVICE_FILE, "r");
- if (f != NULL) {
+ if (_pam_open_config_file(pamh, PAM_DEFAULT_SERVICE, &path, &f) == PAM_SUCCESS) {
/* would test magic here? */
retval = _pam_parse_conf_file(pamh, f, PAM_DEFAULT_SERVICE,
PAM_T_ANY, 0
@@ -458,22 +497,23 @@ int _pam_init_handlers(pam_handle_t *pamh)
, 0
#endif /* PAM_READ_BOTH_CONFS */
);
- fclose(f);
if (retval != PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR,
"_pam_init_handlers: error reading %s",
- PAM_DEFAULT_SERVICE_FILE);
+ path);
pam_syslog(pamh, LOG_ERR,
"_pam_init_handlers: [%s]",
pam_strerror(pamh, retval));
} else {
read_something = 1;
}
+ _pam_drop(path);
+ fclose(f);
} else {
- D(("unable to open %s", PAM_DEFAULT_SERVICE_FILE));
+ D(("unable to open %s", PAM_DEFAULT_SERVICE));
pam_syslog(pamh, LOG_ERR,
"_pam_init_handlers: no default config %s",
- PAM_DEFAULT_SERVICE_FILE);
+ PAM_DEFAULT_SERVICE);
}
if (!read_something) { /* nothing read successfully */
retval = PAM_ABORT;
diff --git a/libpam/pam_private.h b/libpam/pam_private.h
index d93283ce..11382774 100644
--- a/libpam/pam_private.h
+++ b/libpam/pam_private.h
@@ -24,12 +24,13 @@
/* the Linux-PAM configuration file */
-#define PAM_CONFIG "/etc/pam.conf"
-#define PAM_CONFIG_D "/etc/pam.d"
-#define PAM_CONFIG_DF "/etc/pam.d/%s"
+#define PAM_CONFIG "/etc/pam.conf"
+#define PAM_CONFIG_D "/etc/pam.d"
+#define PAM_CONFIG_DF "/etc/pam.d/%s"
+#define PAM_CONFIG_DIST_D "/usr/lib/pam.d"
+#define PAM_CONFIG_DIST_DF "/usr/lib/pam.d/%s"
#define PAM_DEFAULT_SERVICE "other" /* lower case */
-#define PAM_DEFAULT_SERVICE_FILE PAM_CONFIG_D "/" PAM_DEFAULT_SERVICE
#ifdef PAM_LOCKING
/*