Added the ability for the server to provide a custom reason string

when an AUTH_FAILED message is returned to the client.  This
string can be set by the server-side managment interface and read
by the client-side management interface.

For more info, see management/management-notes.txt, and look for
references to "client-reason-text".


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5012 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
james 2009-09-29 23:10:14 +00:00
parent 8e952ed197
commit 5733ef668f
8 changed files with 84 additions and 14 deletions

View File

@ -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"))
{

View File

@ -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

View File

@ -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

View File

@ -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)

32
push.c
View File

@ -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)

2
push.h
View File

@ -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

19
ssl.c
View File

@ -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);

17
ssl.h
View File

@ -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