"Plaintext authentication disabled");
}
client->common.auth_tried_disabled_plaintext = TRUE;
+ client->common.auth_attempts++;
client_send_line(client,
"* BAD [ALERT] Plaintext authentication is disabled, "
"but your client sent password in plaintext anyway. "
{
client_send_line(client, "* BYE Logging out");
client_send_tagline(client, "OK Logout completed.");
- if (client->common.auth_tried_disabled_plaintext) {
- client_destroy(client, "Aborted login "
- "(tried to use disabled plaintext authentication)");
- } else {
- client_destroy(client, "Aborted login");
- }
+ client_destroy(client, "Aborted login");
return 1;
}
client->destroyed = TRUE;
if (!client->login_success && reason != NULL) {
- reason = client->common.auth_attempts == 0 ?
- t_strdup_printf("%s (no auth attempts)", reason) :
- t_strdup_printf("%s (auth failed, %u attempts)",
- reason, client->common.auth_attempts);
+ reason = t_strconcat(reason, " ",
+ client_get_extra_disconnect_reason(&client->common),
+ NULL);
}
if (reason != NULL)
client_syslog(&client->common, reason);
}
return FALSE;
}
+
+const char *client_get_extra_disconnect_reason(struct client *client)
+{
+ if (ssl_require_client_cert && client->proxy != NULL) {
+ if (ssl_proxy_has_broken_client_cert(client->proxy))
+ return "(client sent an invalid cert)";
+ if (!ssl_proxy_has_valid_client_cert(client->proxy))
+ return "(client didn't send a cert)";
+ }
+
+ if (client->auth_attempts == 0)
+ return "(no auth attempts)";
+
+ /* some auth attempts without SSL/TLS */
+ if (client->auth_tried_disabled_plaintext)
+ return "(tried to use disabled plaintext auth)";
+ if (ssl_require_client_cert)
+ return "(cert required, client didn't start TLS)";
+
+ return t_strdup_printf("(auth failed, %u attempts)",
+ client->auth_attempts);
+}
unsigned int clients_get_count(void) ATTR_PURE;
void client_syslog(struct client *client, const char *msg);
+const char *client_get_extra_disconnect_reason(struct client *client);
bool client_is_trusted(struct client *client);
void clients_notify_auth_connected(void);
extern bool disable_plaintext_auth, process_per_connection;
extern bool verbose_proctitle, verbose_ssl, verbose_auth;
+extern bool ssl_require_client_cert;
extern const char *greeting, *log_format;
extern const char *const *log_format_elements;
extern const char *capability_string;
bool disable_plaintext_auth, process_per_connection;
bool verbose_proctitle, verbose_ssl, verbose_auth;
+bool ssl_require_client_cert;
const char *greeting, *log_format;
const char *const *log_format_elements;
const char *trusted_networks;
verbose_proctitle = getenv("VERBOSE_PROCTITLE") != NULL;
verbose_ssl = getenv("VERBOSE_SSL") != NULL;
verbose_auth = getenv("VERBOSE_AUTH") != NULL;
+ ssl_require_client_cert = getenv("SSL_REQUIRE_CLIENT_CERT") != NULL;
greeting = getenv("GREETING");
if (greeting == NULL)
return proxy->cert_received && !proxy->cert_broken;
}
+bool ssl_proxy_has_broken_client_cert(struct ssl_proxy *proxy)
+{
+ return proxy->cert_received && proxy->cert_broken;
+}
+
const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy)
{
X509 *x509;
return FALSE;
}
+bool ssl_proxy_has_broken_client_cert(struct ssl_proxy *proxy ATTR_UNUSED)
+{
+ return FALSE;
+}
+
const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy ATTR_UNUSED)
{
return NULL;
the given fd must be simply forgotten. */
int ssl_proxy_new(int fd, struct ip_addr *ip, struct ssl_proxy **proxy_r);
bool ssl_proxy_has_valid_client_cert(const struct ssl_proxy *proxy) ATTR_PURE;
+bool ssl_proxy_has_broken_client_cert(struct ssl_proxy *proxy);
const char *ssl_proxy_get_peer_name(struct ssl_proxy *proxy);
bool ssl_proxy_is_handshaked(const struct ssl_proxy *proxy) ATTR_PURE;
const char *ssl_proxy_get_last_error(const struct ssl_proxy *proxy) ATTR_PURE;
static void login_process_init_env(struct login_group *group, pid_t pid)
{
struct settings *set = group->set;
+ const struct auth_settings *auth;
+ bool require_cert;
child_process_init_env();
env_put("VERBOSE_SSL=1");
if (set->server->auths->verbose)
env_put("VERBOSE_AUTH=1");
+ require_cert = TRUE;
+ for (auth = set->server->auths; auth != NULL; auth = auth->next) {
+ if (!auth->ssl_require_client_cert)
+ require_cert = FALSE;
+ }
+ if (require_cert)
+ env_put("SSL_REQUIRE_CLIENT_CERT=1");
if (set->login_process_per_connection) {
env_put("PROCESS_PER_CONNECTION=1");
}
client_send_line(client, "-ERR "AUTH_PLAINTEXT_DISABLED_MSG);
client->common.auth_tried_disabled_plaintext = TRUE;
+ client->common.auth_attempts++;
return FALSE;
}
static bool cmd_quit(struct pop3_client *client)
{
client_send_line(client, "+OK Logging out");
- if (client->common.auth_tried_disabled_plaintext) {
- client_destroy(client, "Aborted login "
- "(tried to use disabled plaintext authentication)");
- } else {
- client_destroy(client, "Aborted login");
- }
+ client_destroy(client, "Aborted login");
return TRUE;
}
client->destroyed = TRUE;
if (!client->login_success && reason != NULL) {
- reason = client->common.auth_attempts == 0 ?
- t_strdup_printf("%s (no auth attempts)", reason) :
- t_strdup_printf("%s (auth failed, %u attempts)",
- reason, client->common.auth_attempts);
+ reason = t_strconcat(reason, " ",
+ client_get_extra_disconnect_reason(&client->common),
+ NULL);
}
if (reason != NULL)
client_syslog(&client->common, reason);