aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--manage.c11
-rw-r--r--manage.h1
-rw-r--r--management/management-notes.txt11
-rw-r--r--multi.c5
-rw-r--r--push.c32
-rw-r--r--push.h2
-rw-r--r--ssl.c19
-rw-r--r--ssl.h17
8 files changed, 84 insertions, 14 deletions
diff --git a/manage.c b/manage.c
index 97d69b4..7c12979 100644
--- a/manage.c
+++ b/manage.c
@@ -94,7 +94,8 @@ man_help ()
#ifdef MANAGEMENT_DEF_AUTH
msg (M_CLIENT, "client-auth CID KID : Authenticate client-id/key-id CID/KID (MULTILINE)");
msg (M_CLIENT, "client-auth-nt CID KID : Authenticate client-id/key-id CID/KID");
- msg (M_CLIENT, "client-deny CID KID R : Deny auth client-id/key-id CID/KID with reason text R");
+ msg (M_CLIENT, "client-deny CID KID R [CR] : Deny auth client-id/key-id CID/KID with log reason");
+ msg (M_CLIENT, " text R and optional client reason text CR");
msg (M_CLIENT, "client-kill CID : Kill client instance CID");
#ifdef MANAGEMENT_PF
msg (M_CLIENT, "client-pf CID : Define packet filter for client CID (MULTILINE)");
@@ -801,6 +802,7 @@ in_extra_dispatch (struct management *man)
man->connection.in_extra_kid,
true,
NULL,
+ NULL,
man->connection.in_extra);
man->connection.in_extra = NULL;
if (status)
@@ -862,7 +864,7 @@ man_client_auth (struct management *man, const char *cid_str, const char *kid_st
}
static void
-man_client_deny (struct management *man, const char *cid_str, const char *kid_str, const char *reason)
+man_client_deny (struct management *man, const char *cid_str, const char *kid_str, const char *reason, const char *client_reason)
{
unsigned long cid = 0;
unsigned int kid = 0;
@@ -876,6 +878,7 @@ man_client_deny (struct management *man, const char *cid_str, const char *kid_st
kid,
false,
reason,
+ client_reason,
NULL);
if (status)
{
@@ -1160,8 +1163,8 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
}
else if (streq (p[0], "client-deny"))
{
- if (man_need (man, p, 3, 0))
- man_client_deny (man, p[1], p[2], p[3]);
+ if (man_need (man, p, 3, MN_AT_LEAST))
+ man_client_deny (man, p[1], p[2], p[3], p[4]);
}
else if (streq (p[0], "client-auth-nt"))
{
diff --git a/manage.h b/manage.h
index 23c1fbc..6d6d710 100644
--- a/manage.h
+++ b/manage.h
@@ -162,6 +162,7 @@ struct management_callback
const unsigned int mda_key_id,
const bool auth,
const char *reason,
+ const char *client_reason,
struct buffer_list *cc_config); /* ownership transferred */
#endif
#ifdef MANAGEMENT_PF
diff --git a/management/management-notes.txt b/management/management-notes.txt
index 45bfda4..1f4cbd0 100644
--- a/management/management-notes.txt
+++ b/management/management-notes.txt
@@ -308,6 +308,12 @@ COMMAND -- password and username
>PASSWORD:Verification Failed: 'Auth'
+ Example 5: The --auth-user-pass username/password failed,
+ and the server provided a custom client-reason-text string
+ using the client-deny server-side management interface command.
+
+ >PASSWORD:Verification Failed: 'custom server-generated string'
+
COMMAND -- forget-passwords
---------------------------
@@ -535,7 +541,7 @@ COMMAND -- client-deny (OpenVPN 2.1 or higher)
Deny a ">CLIENT:CONNECT" or ">CLIENT:REAUTH" request.
- client-deny {CID} {KID} "reason-text"
+ client-deny {CID} {KID} "reason-text" ["client-reason-text"]
CID,KID -- client ID and Key ID. See documentation for ">CLIENT:"
notification for more info.
@@ -544,6 +550,9 @@ reason-text: a human-readable message explaining why the authentication
request was denied. This message will be output to the OpenVPN log
file or syslog.
+client-reason-text: a message that will be sent to the client as
+part of the AUTH_FAILED message.
+
Note that client-deny denies a specific Key ID (pertaining to a
TLS renegotiation). A client-deny command issued in response to
an initial TLS key negotiation (notified by ">CLIENT:CONNECT") will
diff --git a/multi.c b/multi.c
index f62563c..ecd1bb3 100644
--- a/multi.c
+++ b/multi.c
@@ -2552,6 +2552,7 @@ management_client_auth (void *arg,
const unsigned int mda_key_id,
const bool auth,
const char *reason,
+ const char *client_reason,
struct buffer_list *cc_config) /* ownership transferred */
{
struct multi_context *m = (struct multi_context *) arg;
@@ -2561,7 +2562,7 @@ management_client_auth (void *arg,
if (mi)
{
- ret = tls_authenticate_key (mi->context.c2.tls_multi, mda_key_id, auth);
+ ret = tls_authenticate_key (mi->context.c2.tls_multi, mda_key_id, auth, client_reason);
if (ret)
{
if (auth && !mi->connection_established_flag)
@@ -2570,7 +2571,7 @@ management_client_auth (void *arg,
cc_config_owned = false;
}
if (!auth && reason)
- msg (D_MULTI_LOW, "MULTI: connection rejected: %s", reason);
+ msg (D_MULTI_LOW, "MULTI: connection rejected: %s, CLI:%s", reason, np(client_reason));
}
}
if (cc_config_owned && cc_config)
diff --git a/push.c b/push.c
index 36febe1..142222b 100644
--- a/push.c
+++ b/push.c
@@ -61,7 +61,13 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
c->sig->signal_text = "auth-failure";
#ifdef ENABLE_MANAGEMENT
if (management)
- management_auth_failure (management, UP_TYPE_AUTH);
+ {
+ const char *reason = UP_TYPE_AUTH;
+ struct buffer buf = *buffer;
+ if (buf_string_compare_advance (&buf, "AUTH_FAILED,") && BLEN (&buf))
+ reason = BSTR (&buf);
+ management_auth_failure (management, reason);
+ }
#endif
}
}
@@ -71,10 +77,27 @@ receive_auth_failed (struct context *c, const struct buffer *buffer)
* Send auth failed message from server to client.
*/
void
-send_auth_failed (struct context *c)
+send_auth_failed (struct context *c, const char *client_reason)
{
+ struct gc_arena gc = gc_new ();
+ static const char auth_failed[] = "AUTH_FAILED";
+ size_t len;
+
schedule_exit (c, c->options.scheduled_exit_interval);
- send_control_channel_string (c, "AUTH_FAILED", D_PUSH);
+
+ len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed);
+ if (len > TLS_CHANNEL_BUF_SIZE)
+ len = TLS_CHANNEL_BUF_SIZE;
+
+ {
+ struct buffer buf = alloc_buf_gc (len, &gc);
+ buf_printf (&buf, auth_failed);
+ if (client_reason)
+ buf_printf (&buf, ",%s", client_reason);
+ send_control_channel_string (c, BSTR (&buf), D_PUSH);
+ }
+
+ gc_free (&gc);
}
#endif
@@ -258,7 +281,8 @@ process_incoming_push_msg (struct context *c,
{
if (tls_authentication_status (c->c2.tls_multi, 0) == TLS_AUTHENTICATION_FAILED || c->c2.context_auth == CAS_FAILED)
{
- send_auth_failed (c);
+ const char *client_reason = tls_client_reason (c->c2.tls_multi);
+ send_auth_failed (c, client_reason);
ret = PUSH_MSG_AUTH_FAILURE;
}
else if (!c->c2.push_reply_deferred && c->c2.context_auth == CAS_SUCCEEDED)
diff --git a/push.h b/push.h
index a48b077..e281310 100644
--- a/push.h
+++ b/push.h
@@ -62,7 +62,7 @@ bool send_push_reply (struct context *c);
void remove_iroutes_from_push_route_list (struct options *o);
-void send_auth_failed (struct context *c);
+void send_auth_failed (struct context *c, const char *client_reason);
#endif
#endif
diff --git a/ssl.c b/ssl.c
index 224721a..bc8b2da 100644
--- a/ssl.c
+++ b/ssl.c
@@ -908,6 +908,18 @@ tls_lock_common_name (struct tls_multi *multi)
#endif
#ifdef MANAGEMENT_DEF_AUTH
+static void
+man_def_auth_set_client_reason (struct tls_multi *multi, const char *client_reason)
+{
+ if (multi->client_reason)
+ {
+ free (multi->client_reason);
+ multi->client_reason = NULL;
+ }
+ if (client_reason && strlen (client_reason))
+ multi->client_reason = string_alloc (client_reason, NULL);
+}
+
static inline unsigned int
man_def_auth_test (const struct key_state *ks)
{
@@ -1077,12 +1089,13 @@ tls_authentication_status (struct tls_multi *multi, const int latency)
#ifdef MANAGEMENT_DEF_AUTH
bool
-tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth)
+tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason)
{
bool ret = false;
if (multi)
{
int i;
+ man_def_auth_set_client_reason (multi, client_reason);
for (i = 0; i < KEY_SCAN_SIZE; ++i)
{
struct key_state *ks = multi->key_scan[i];
@@ -2397,6 +2410,10 @@ tls_multi_free (struct tls_multi *multi, bool clear)
ASSERT (multi);
+#ifdef MANAGEMENT_DEF_AUTH
+ man_def_auth_set_client_reason(multi, NULL);
+#endif
+
if (multi->locked_cn)
free (multi->locked_cn);
diff --git a/ssl.h b/ssl.h
index e7ccb42..06cd246 100644
--- a/ssl.h
+++ b/ssl.h
@@ -594,6 +594,11 @@ struct tls_multi
char *locked_cn;
#ifdef ENABLE_DEF_AUTH
+ /*
+ * An error message to send to client on AUTH_FAILED
+ */
+ char *client_reason;
+
/* Time of last call to tls_authentication_status */
time_t tas_last;
#endif
@@ -695,7 +700,7 @@ int tls_authentication_status (struct tls_multi *multi, const int latency);
void tls_deauthenticate (struct tls_multi *multi);
#ifdef MANAGEMENT_DEF_AUTH
-bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth);
+bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason);
#endif
/*
@@ -738,6 +743,16 @@ tls_set_single_session (struct tls_multi *multi)
multi->opt.single_session = true;
}
+static inline const char *
+tls_client_reason (struct tls_multi *multi)
+{
+#ifdef ENABLE_DEF_AUTH
+ return multi->client_reason;
+#else
+ return NULL;
+#endif
+}
+
#ifdef ENABLE_PF
static inline bool