dovecot-1.1: PAM: Attempt to give better error messages.
dovecot at dovecot.org
dovecot at dovecot.org
Mon Oct 6 00:21:22 EEST 2008
details: http://hg.dovecot.org/dovecot-1.1/rev/eb3e3e677a4c
changeset: 7925:eb3e3e677a4c
user: Timo Sirainen <tss at iki.fi>
date: Mon Oct 06 00:21:18 2008 +0300
description:
PAM: Attempt to give better error messages.
Detect missing /etc/pam.d/service file and log it as an error the first time
after startup. Don't return "unknown user" and "password mismatch" as errors
but informational messages.
diffstat:
1 file changed, 59 insertions(+), 5 deletions(-)
src/auth/passdb-pam.c | 64 +++++++++++++++++++++++++++++++++++++++++++++----
diffs (102 lines):
diff -r af9ec623c641 -r eb3e3e677a4c src/auth/passdb-pam.c
--- a/src/auth/passdb-pam.c Sun Oct 05 23:26:55 2008 +0300
+++ b/src/auth/passdb-pam.c Mon Oct 06 00:21:18 2008 +0300
@@ -20,6 +20,7 @@
#include "auth-cache.h"
#include <stdlib.h>
+#include <sys/stat.h>
#ifdef HAVE_SECURITY_PAM_APPL_H
# include <security/pam_appl.h>
@@ -31,6 +32,10 @@
/* Sun's PAM doesn't use const. we use a bit dirty hack to check it.
Originally it was just __sun__ check, but HP/UX also uses Sun's PAM
so I thought this might work better. */
+# define SUNPAM
+#endif
+
+#ifdef SUNPAM
# define linux_const
#else
# define linux_const const
@@ -117,17 +122,66 @@ pam_userpass_conv(int num_msg, linux_con
return PAM_SUCCESS;
}
-static int try_pam_auth(struct auth_request *request, pam_handle_t *pamh)
+static const char *
+pam_get_missing_service_file_path(const char *service ATTR_UNUSED)
+{
+#ifdef SUNPAM
+ /* Uses /etc/pam.conf - we're not going to parse that */
+ return NULL;
+#else
+ static bool service_checked = FALSE;
+ const char *path;
+ struct stat st;
+
+ if (service_checked) {
+ /* check and complain only once */
+ return NULL;
+ }
+ service_checked = TRUE;
+
+ path = t_strdup_printf("/etc/pam.d/%s", service);
+ if (stat(path, &st) < 0 && errno == ENOENT) {
+ /* looks like it's missing. but before assuming that the system
+ even uses /etc/pam.d, make sure that it exists. */
+ if (stat("/etc/pam.d", &st) == 0)
+ return path;
+ }
+ /* exists or is unknown */
+ return NULL;
+}
+#endif
+
+static int try_pam_auth(struct auth_request *request, pam_handle_t *pamh,
+ const char *service)
{
struct passdb_module *_module = request->passdb->passdb;
struct pam_passdb_module *module = (struct pam_passdb_module *)_module;
+ const char *path, *str;
pam_item_t item;
int status;
if ((status = pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
- auth_request_log_error(request, "pam",
- "pam_authenticate() failed: %s",
- pam_strerror(pamh, status));
+ path = pam_get_missing_service_file_path(service);
+ switch (status) {
+ case PAM_USER_UNKNOWN:
+ str = "unknown user";
+ break;
+ default:
+ str = t_strconcat("pam_authenticate() failed: ",
+ pam_strerror(pamh, status), NULL);
+ break;
+ }
+ if (path != NULL) {
+ /* log this as error, since it probably is */
+ str = t_strdup_printf("%s (%s missing?)", str, path);
+ auth_request_log_error(request, "pam", "%s", str);
+ } else {
+ if (status == PAM_AUTH_ERR) {
+ str = t_strconcat(str, " (password mismatch?)",
+ NULL);
+ }
+ auth_request_log_info(request, "pam", "%s", str);
+ }
return status;
}
@@ -215,7 +269,7 @@ pam_verify_plain_call(struct auth_reques
}
set_pam_items(request, pamh);
- status = try_pam_auth(request, pamh);
+ status = try_pam_auth(request, pamh, service);
if ((status2 = pam_end(pamh, status)) != PAM_SUCCESS) {
auth_request_log_error(request, "pam", "pam_end() failed: %s",
pam_strerror(pamh, status2));
More information about the dovecot-cvs
mailing list