File patches_to_master.patch of Package apache2-mod_authn_dovecot
From de0fddf62a9fb5800b258a658ca511a885d5e3ee Mon Sep 17 00:00:00 2001
From: Kevin Locke <kevin@kevinlocke.name>
Date: Mon, 16 Jul 2018 11:33:27 -0600
Subject: [PATCH 1/3] Include system error message in logged errors
When connect(2) or select(2) fail, include the system error message for
errno in the logged error message to indicate the cause of the failure
to assist in debugging.
Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
---
mod_authn_dovecot.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/mod_authn_dovecot.c b/mod_authn_dovecot.c
index 7025e6c..e70197d 100644
--- a/mod_authn_dovecot.c
+++ b/mod_authn_dovecot.c
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <stdio.h>
+#include <string.h>
#include "apr_base64.h" // base64 encode
@@ -157,7 +158,7 @@ static authn_status check_password(request_rec * r, const char *user, const char
strncpy(address.sun_path,conf->dovecotauthsocket, strlen(conf->dovecotauthsocket));
result = connect(auths, (struct sockaddr *)&address, sizeof address);
if (result) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: could not connect to dovecot socket");
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: could not connect to dovecot socket %s: %s", address.sun_path, strerror(errno));
if (conf->authoritative == 0) {
return DECLINED;
} else {
@@ -186,7 +187,7 @@ static authn_status check_password(request_rec * r, const char *user, const char
readsocks = select(fdmax + 1, &socks_r, &socks_w, NULL, &tv);
if (readsocks < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: socket select");
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: socket select: %s", strerror(errno));
return DECLINED;
}
From 9c6eab35f48c8c3f0adaf6b15f4bf8b7df3977bd Mon Sep 17 00:00:00 2001
From: Kevin Locke <kevin@kevinlocke.name>
Date: Tue, 17 Jul 2018 00:18:39 -0600
Subject: [PATCH 2/3] Prevent sun_path overflow and ensure null-termination
* Ensure sun_path is null-terminated. The previous code did not copy the
terminating null byte, which would cause connection failure when
strlen(conf->dovecotauthsocket) < sizeof(sun_path) and sun_path
happened to contain non-'\0' after the end of the copied bytes.
* Avoid overflowing sun_path when conf->dovecotauthsocket is longer than
sizeof(sun_path). Instead, log an error and exit early.
Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
---
mod_authn_dovecot.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/mod_authn_dovecot.c b/mod_authn_dovecot.c
index e70197d..84fb7d5 100644
--- a/mod_authn_dovecot.c
+++ b/mod_authn_dovecot.c
@@ -132,6 +132,19 @@ static authn_status check_password(request_rec * r, const char *user, const char
struct timeval tv;
struct connection_state cs;
+ size_t authsocklen = strlen(conf->dovecotauthsocket);
+ if (authsocklen >= sizeof address.sun_path) {
+ // Note: Some OS support longer sun_path via the "struct hack".
+ // Not Linux. See:
+ // https://mail-index.netbsd.org/tech-net/2006/10/11/0008.html
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: dovecot socket path %s is too long.", conf->dovecotauthsocket);
+ if (conf->authoritative == 0) {
+ return DECLINED;
+ } else {
+ return AUTH_USER_NOT_FOUND;
+ }
+ }
+
apr_pool_create(&p, r->pool); // create subpool for local functions, variables...
// setting default values for connection state
@@ -155,7 +168,7 @@ static authn_status check_password(request_rec * r, const char *user, const char
perror("fcntl(F_SETFL)");
}
address.sun_family = AF_UNIX;
- strncpy(address.sun_path,conf->dovecotauthsocket, strlen(conf->dovecotauthsocket));
+ memcpy(address.sun_path, conf->dovecotauthsocket, authsocklen + 1);
result = connect(auths, (struct sockaddr *)&address, sizeof address);
if (result) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: could not connect to dovecot socket %s: %s", address.sun_path, strerror(errno));
From b12df24ebf4a4937c02e4cbe335e90ab161948ad Mon Sep 17 00:00:00 2001
From: Kevin Locke <kevin@kevinlocke.name>
Date: Mon, 16 Jul 2018 11:37:10 -0600
Subject: [PATCH 3/3] Handle asynchronous connection via EINPROGRESS
POSIX/SUS specifies:
If the connection cannot be established immediately and O_NONBLOCK
is set for the file descriptor for the socket, connect() shall fail
and set errno to [EINPROGRESS], but the connection request shall not
be aborted, and the connection shall be established asynchronously.
This can occur when the request load is higher than Dovecot is
configured to accept or connections are made faster than Dovecot can
keep up. When this happens, proceed. The connection will finish
asynchronously in the select loop.
Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
---
mod_authn_dovecot.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mod_authn_dovecot.c b/mod_authn_dovecot.c
index 84fb7d5..fa69c90 100644
--- a/mod_authn_dovecot.c
+++ b/mod_authn_dovecot.c
@@ -25,6 +25,7 @@
#include "http_request.h"
#include "mod_auth.h"
+#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
@@ -170,7 +171,7 @@ static authn_status check_password(request_rec * r, const char *user, const char
address.sun_family = AF_UNIX;
memcpy(address.sun_path, conf->dovecotauthsocket, authsocklen + 1);
result = connect(auths, (struct sockaddr *)&address, sizeof address);
- if (result) {
+ if (result && errno != EINPROGRESS) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Dovecot Authentication: could not connect to dovecot socket %s: %s", address.sun_path, strerror(errno));
if (conf->authoritative == 0) {
return DECLINED;