mirror of
https://github.com/OpenVPN/openvpn.git
synced 2025-05-08 21:25:53 +08:00
Implemented a key/value auth channel from client to server.
Version 2.1.1i git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5668 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
3cf6c93282
commit
aaf7297467
9
common.h
9
common.h
@ -76,8 +76,15 @@ typedef unsigned long ptr_type;
|
||||
/*
|
||||
* This parameter controls the TLS channel buffer size and the
|
||||
* maximum size of a single TLS message (cleartext).
|
||||
* This parameter must be >= PUSH_BUNDLE_SIZE
|
||||
*/
|
||||
#define TLS_CHANNEL_BUF_SIZE 1024
|
||||
#define TLS_CHANNEL_BUF_SIZE 2048
|
||||
|
||||
/*
|
||||
* This parameter controls the maximum size of a bundle
|
||||
* of pushed options.
|
||||
*/
|
||||
#define PUSH_BUNDLE_SIZE 1024
|
||||
|
||||
/*
|
||||
* A sort of pseudo-filename for data provided inline within
|
||||
|
3
init.c
3
init.c
@ -2007,6 +2007,9 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
|
||||
to.renegotiate_packets = options->renegotiate_packets;
|
||||
to.renegotiate_seconds = options->renegotiate_seconds;
|
||||
to.single_session = options->single_session;
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
to.push_peer_info = options->push_peer_info;
|
||||
#endif
|
||||
|
||||
/* should we not xmit any packets until we get an initial
|
||||
response from client? */
|
||||
|
53
manage.c
53
manage.c
@ -2275,6 +2275,58 @@ man_output_extra_env (struct management *man)
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_peer_info_line(const char *line)
|
||||
{
|
||||
uint8_t c;
|
||||
int state = 0;
|
||||
while ((c=*line++))
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
if (c == '=' && state == 1)
|
||||
state = 2;
|
||||
else if (isalnum(c) || c == '_')
|
||||
state = 1;
|
||||
else
|
||||
return false;
|
||||
case 2:
|
||||
if (isprint(c))
|
||||
;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (state == 2);
|
||||
}
|
||||
|
||||
static void
|
||||
man_output_peer_info_env (struct management *man, struct man_def_auth_context *mdac)
|
||||
{
|
||||
char line[256];
|
||||
if (man->persist.callback.get_peer_info)
|
||||
{
|
||||
const char *peer_info = (*man->persist.callback.get_peer_info) (man->persist.callback.arg, mdac->cid);
|
||||
if (peer_info)
|
||||
{
|
||||
struct buffer buf;
|
||||
buf_set_read (&buf, (const uint8_t *) peer_info, strlen(peer_info));
|
||||
while (buf_parse (&buf, '\n', line, sizeof (line)))
|
||||
{
|
||||
chomp (line);
|
||||
if (validate_peer_info_line(line))
|
||||
{
|
||||
msg (M_CLIENT, ">CLIENT:ENV,%s", line);
|
||||
}
|
||||
else
|
||||
msg (D_MANAGEMENT, "validation failed on peer_info line received from client");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
management_notify_client_needing_auth (struct management *management,
|
||||
const unsigned int mda_key_id,
|
||||
@ -2288,6 +2340,7 @@ management_notify_client_needing_auth (struct management *management,
|
||||
mode = "REAUTH";
|
||||
msg (M_CLIENT, ">CLIENT:%s,%lu,%u", mode, mdac->cid, mda_key_id);
|
||||
man_output_extra_env (management);
|
||||
man_output_peer_info_env(management, mdac);
|
||||
man_output_env (es, true, management->connection.env_filter_level);
|
||||
mdac->flags |= DAF_INITIAL_AUTH;
|
||||
}
|
||||
|
1
manage.h
1
manage.h
@ -164,6 +164,7 @@ struct management_callback
|
||||
const char *reason,
|
||||
const char *client_reason,
|
||||
struct buffer_list *cc_config); /* ownership transferred */
|
||||
char *(*get_peer_info) (void *arg, const unsigned long cid);
|
||||
#endif
|
||||
#ifdef MANAGEMENT_PF
|
||||
bool (*client_pf) (void *arg,
|
||||
|
15
multi.c
15
multi.c
@ -2597,6 +2597,20 @@ management_client_auth (void *arg,
|
||||
buffer_list_free (cc_config);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
management_get_peer_info (void *arg, const unsigned long cid)
|
||||
{
|
||||
struct multi_context *m = (struct multi_context *) arg;
|
||||
struct multi_instance *mi = lookup_by_cid (m, cid);
|
||||
char *ret = NULL;
|
||||
|
||||
if (mi)
|
||||
ret = tls_get_peer_info (mi->context.c2.tls_multi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MANAGEMENT_PF
|
||||
@ -2637,6 +2651,7 @@ init_management_callback_multi (struct multi_context *m)
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
cb.kill_by_cid = management_kill_by_cid;
|
||||
cb.client_auth = management_client_auth;
|
||||
cb.get_peer_info = management_get_peer_info;
|
||||
#endif
|
||||
#ifdef MANAGEMENT_PF
|
||||
cb.client_pf = management_client_pf;
|
||||
|
16
options.c
16
options.c
@ -196,6 +196,9 @@ static const char usage_message[] =
|
||||
" Add 'bypass-dns' flag to similarly bypass tunnel for DNS.\n"
|
||||
"--redirect-private [flags]: Like --redirect-gateway, but omit actually changing\n"
|
||||
" the default gateway. Useful when pushing private subnets.\n"
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
"--push-peer-info : (client only) push client info to server.\n"
|
||||
#endif
|
||||
"--setenv name value : Set a custom environmental variable to pass to script.\n"
|
||||
"--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to allow\n"
|
||||
" directives for future OpenVPN versions to be ignored.\n"
|
||||
@ -1348,6 +1351,9 @@ show_settings (const struct options *o)
|
||||
SHOW_INT (transition_window);
|
||||
|
||||
SHOW_BOOL (single_session);
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
SHOW_BOOL (push_peer_info);
|
||||
#endif
|
||||
SHOW_BOOL (tls_exit);
|
||||
|
||||
SHOW_STR (tls_auth_file);
|
||||
@ -2057,6 +2063,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
||||
MUST_BE_UNDEF (transition_window);
|
||||
MUST_BE_UNDEF (tls_auth_file);
|
||||
MUST_BE_UNDEF (single_session);
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
MUST_BE_UNDEF (push_peer_info);
|
||||
#endif
|
||||
MUST_BE_UNDEF (tls_exit);
|
||||
MUST_BE_UNDEF (crl_file);
|
||||
MUST_BE_UNDEF (key_method);
|
||||
@ -5672,6 +5681,13 @@ add_option (struct options *options,
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->single_session = true;
|
||||
}
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
else if (streq (p[0], "push-peer-info"))
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->push_peer_info = true;
|
||||
}
|
||||
#endif
|
||||
else if (streq (p[0], "tls-exit"))
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
|
@ -520,6 +520,10 @@ struct options
|
||||
/* Allow only one session */
|
||||
bool single_session;
|
||||
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
bool push_peer_info;
|
||||
#endif
|
||||
|
||||
bool tls_exit;
|
||||
|
||||
#endif /* USE_SSL */
|
||||
|
6
push.c
6
push.c
@ -102,8 +102,8 @@ send_auth_failed (struct context *c, const char *client_reason)
|
||||
schedule_exit (c, c->options.scheduled_exit_interval, SIGTERM);
|
||||
|
||||
len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed);
|
||||
if (len > TLS_CHANNEL_BUF_SIZE)
|
||||
len = TLS_CHANNEL_BUF_SIZE;
|
||||
if (len > PUSH_BUNDLE_SIZE)
|
||||
len = PUSH_BUNDLE_SIZE;
|
||||
|
||||
{
|
||||
struct buffer buf = alloc_buf_gc (len, &gc);
|
||||
@ -171,7 +171,7 @@ bool
|
||||
send_push_reply (struct context *c)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct buffer buf = alloc_buf_gc (TLS_CHANNEL_BUF_SIZE, &gc);
|
||||
struct buffer buf = alloc_buf_gc (PUSH_BUNDLE_SIZE, &gc);
|
||||
struct push_entry *e = c->options.push_list.head;
|
||||
bool multi_push = false;
|
||||
static char cmd[] = "PUSH_REPLY";
|
||||
|
2
route.c
2
route.c
@ -2186,7 +2186,7 @@ get_bypass_addresses (struct route_bypass *rb, const unsigned int flags) /* PLA
|
||||
|
||||
#endif
|
||||
|
||||
#if AUTO_USERID
|
||||
#if AUTO_USERID || defined(ENABLE_PUSH_PEER_INFO)
|
||||
|
||||
#if defined(TARGET_LINUX)
|
||||
|
||||
|
2
route.h
2
route.h
@ -174,7 +174,7 @@ bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask);
|
||||
#define TLA_LOCAL 2
|
||||
int test_local_addr (const in_addr_t addr);
|
||||
|
||||
#if AUTO_USERID
|
||||
#if AUTO_USERID || defined(ENABLE_PUSH_PEER_INFO)
|
||||
bool get_default_gateway_mac_addr (unsigned char *macaddr);
|
||||
#endif
|
||||
|
||||
|
124
ssl.c
124
ssl.c
@ -2558,6 +2558,8 @@ tls_multi_free (struct tls_multi *multi, bool clear)
|
||||
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
man_def_auth_set_client_reason(multi, NULL);
|
||||
|
||||
free (multi->peer_info);
|
||||
#endif
|
||||
|
||||
if (multi->locked_cn)
|
||||
@ -3105,6 +3107,14 @@ write_string (struct buffer *buf, const char *str, const int maxlen)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
write_empty_string (struct buffer *buf)
|
||||
{
|
||||
if (!buf_write_u16 (buf, 0))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
read_string (struct buffer *buf, char *str, const unsigned int capacity)
|
||||
{
|
||||
@ -3117,6 +3127,33 @@ read_string (struct buffer *buf, char *str, const unsigned int capacity)
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *
|
||||
read_string_alloc (struct buffer *buf)
|
||||
{
|
||||
const int len = buf_read_u16 (buf);
|
||||
char *str;
|
||||
|
||||
if (len < 1)
|
||||
return NULL;
|
||||
str = (char *) malloc(len);
|
||||
check_malloc_return(str);
|
||||
if (!buf_read (buf, str, len))
|
||||
{
|
||||
free (str);
|
||||
return NULL;
|
||||
}
|
||||
str[len-1] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
read_string_discard (struct buffer *buf)
|
||||
{
|
||||
char *data = read_string_alloc(buf);
|
||||
if (data)
|
||||
free (data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticate a client using username/password.
|
||||
* Runs on server.
|
||||
@ -3327,6 +3364,73 @@ key_method_1_write (struct buffer *buf, struct tls_session *session)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
push_peer_info(struct buffer *buf, struct tls_session *session)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
bool ret = false;
|
||||
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
if (session->opt->push_peer_info) /* write peer info */
|
||||
{
|
||||
struct env_set *es = session->opt->es;
|
||||
struct env_item *e;
|
||||
struct buffer out = alloc_buf_gc (512*3, &gc);
|
||||
|
||||
/* push version */
|
||||
buf_printf (&out, "IV_VER=%s\n", PACKAGE_VERSION);
|
||||
|
||||
/* push platform */
|
||||
#if defined(TARGET_LINUX)
|
||||
buf_printf (&out, "IV_PLAT=linux\n");
|
||||
#elif defined(TARGET_SOLARIS)
|
||||
buf_printf (&out, "IV_PLAT=solaris\n");
|
||||
#elif defined(TARGET_OPENBSD)
|
||||
buf_printf (&out, "IV_PLAT=openbsd\n");
|
||||
#elif defined(TARGET_DARWIN)
|
||||
buf_printf (&out, "IV_PLAT=mac\n");
|
||||
#elif defined(TARGET_NETBSD)
|
||||
buf_printf (&out, "IV_PLAT=netbsd\n");
|
||||
#elif defined(TARGET_FREEBSD)
|
||||
buf_printf (&out, "IV_PLAT=freebsd\n");
|
||||
#elif defined(WIN32)
|
||||
buf_printf (&out, "IV_PLAT=win\n");
|
||||
#endif
|
||||
|
||||
/* push mac addr */
|
||||
{
|
||||
bool get_default_gateway_mac_addr (unsigned char *macaddr);
|
||||
uint8_t macaddr[6];
|
||||
get_default_gateway_mac_addr (macaddr);
|
||||
buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (macaddr, 6, 0, 1, ":", &gc));
|
||||
}
|
||||
|
||||
/* push env vars that begin with UV_ */
|
||||
for (e=es->list; e != NULL; e=e->next)
|
||||
{
|
||||
if (e->string)
|
||||
{
|
||||
if (!strncmp(e->string, "UV_", 3) && buf_safe(&out, strlen(e->string)+1))
|
||||
buf_printf (&out, "%s\n", e->string);
|
||||
}
|
||||
}
|
||||
|
||||
if (!write_string(buf, BSTR(&out), -1))
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!write_empty_string (buf)) /* no peer info */
|
||||
goto error;
|
||||
}
|
||||
ret = true;
|
||||
|
||||
error:
|
||||
gc_free (&gc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
key_method_2_write (struct buffer *buf, struct tls_session *session)
|
||||
{
|
||||
@ -3361,6 +3465,16 @@ key_method_2_write (struct buffer *buf, struct tls_session *session)
|
||||
goto error;
|
||||
purge_user_pass (&auth_user_pass, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!write_empty_string (buf)) /* no username */
|
||||
goto error;
|
||||
if (!write_empty_string (buf)) /* no password */
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!push_peer_info (buf, session))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* generate tunnel keys if server
|
||||
@ -3507,11 +3621,13 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
|
||||
int s1 = OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
bool s2 = true;
|
||||
char *raw_username;
|
||||
bool username_status, password_status;
|
||||
|
||||
/* get username/password from plaintext buffer */
|
||||
ALLOC_OBJ_CLEAR_GC (up, struct user_pass, &gc);
|
||||
if (!read_string (buf, up->username, USER_PASS_LEN)
|
||||
|| !read_string (buf, up->password, USER_PASS_LEN))
|
||||
username_status = read_string (buf, up->username, USER_PASS_LEN);
|
||||
password_status = read_string (buf, up->password, USER_PASS_LEN);
|
||||
if (!username_status || !password_status)
|
||||
{
|
||||
CLEAR (*up);
|
||||
if (!(session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL))
|
||||
@ -3532,6 +3648,10 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi
|
||||
|
||||
/* call plugin(s) and/or script */
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
/* get peer info from control channel */
|
||||
free (multi->peer_info);
|
||||
multi->peer_info = read_string_alloc (buf);
|
||||
|
||||
if (man_def_auth == KMDA_DEF)
|
||||
man_def_auth = verify_user_pass_management (session, up, raw_username);
|
||||
#endif
|
||||
|
15
ssl.h
15
ssl.h
@ -431,6 +431,9 @@ struct tls_options
|
||||
bool single_session;
|
||||
#ifdef ENABLE_OCC
|
||||
bool disable_occ;
|
||||
#endif
|
||||
#ifdef ENABLE_PUSH_PEER_INFO
|
||||
bool push_peer_info;
|
||||
#endif
|
||||
int transition_window;
|
||||
int handshake_window;
|
||||
@ -618,6 +621,12 @@ struct tls_multi
|
||||
*/
|
||||
char *client_reason;
|
||||
|
||||
/*
|
||||
* A multi-line string of general-purpose info received from peer
|
||||
* over control channel.
|
||||
*/
|
||||
char *peer_info;
|
||||
|
||||
/* Time of last call to tls_authentication_status */
|
||||
time_t tas_last;
|
||||
#endif
|
||||
@ -721,6 +730,12 @@ 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, const char *client_reason);
|
||||
|
||||
static inline char *
|
||||
tls_get_peer_info(const struct tls_multi *multi)
|
||||
{
|
||||
return multi->peer_info;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -662,4 +662,9 @@ socket_defined (const socket_descriptor_t sd)
|
||||
#define AUTO_USERID 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do we support pushing peer info?
|
||||
*/
|
||||
#define ENABLE_PUSH_PEER_INFO
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
dnl define the OpenVPN version
|
||||
define(PRODUCT_VERSION,[2.1.1h])
|
||||
define(PRODUCT_VERSION,[2.1.1i])
|
||||
dnl define the TAP version
|
||||
define(PRODUCT_TAP_ID,[tap0901])
|
||||
define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])
|
||||
|
Loading…
x
Reference in New Issue
Block a user