summaryrefslogtreecommitdiff
path: root/main/openvpn/src
diff options
context:
space:
mode:
Diffstat (limited to 'main/openvpn/src')
-rw-r--r--main/openvpn/src/openvpn/crypto.c54
-rw-r--r--main/openvpn/src/openvpn/crypto.h3
-rw-r--r--main/openvpn/src/openvpn/init.c13
-rw-r--r--main/openvpn/src/openvpn/manage.c7
-rw-r--r--main/openvpn/src/openvpn/misc.c6
-rw-r--r--main/openvpn/src/openvpn/mudp.c106
-rw-r--r--main/openvpn/src/openvpn/multi.c14
-rw-r--r--main/openvpn/src/openvpn/multi.h2
-rw-r--r--main/openvpn/src/openvpn/options.c15
-rw-r--r--main/openvpn/src/openvpn/options.h4
-rw-r--r--main/openvpn/src/openvpn/push.c8
-rw-r--r--main/openvpn/src/openvpn/ssl.c59
-rw-r--r--main/openvpn/src/openvpn/ssl.h9
-rw-r--r--main/openvpn/src/openvpn/ssl_common.h4
-rw-r--r--main/openvpn/src/openvpn/ssl_verify_polarssl.c2
15 files changed, 283 insertions, 23 deletions
diff --git a/main/openvpn/src/openvpn/crypto.c b/main/openvpn/src/openvpn/crypto.c
index d0dc069a..8201708a 100644
--- a/main/openvpn/src/openvpn/crypto.c
+++ b/main/openvpn/src/openvpn/crypto.c
@@ -389,6 +389,60 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,
}
/*
+ * This verifies if a packet and its HMAC fit to a crypto context.
+ *
+ * On success true is returned.
+ */
+bool
+crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt)
+{
+ struct gc_arena gc;
+ gc_init (&gc);
+ int offset = 4; /* 1 byte opcode + 3 bytes session-id */
+
+ if (buf->len > 0 && opt->key_ctx_bi)
+ {
+ struct key_ctx *ctx = &opt->key_ctx_bi->decrypt;
+
+ /* Verify the HMAC */
+ if (ctx->hmac)
+ {
+ int hmac_len;
+ uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */
+
+ hmac_ctx_reset(ctx->hmac);
+
+ /* Assume the length of the input HMAC */
+ hmac_len = hmac_ctx_size (ctx->hmac);
+
+ /* Authentication fails if insufficient data in packet for HMAC */
+ if ((buf->len - offset) < hmac_len)
+ {
+ gc_free (&gc);
+ return false;
+ }
+
+ hmac_ctx_update (ctx->hmac, BPTR (buf) + offset + hmac_len,
+ BLEN (buf) - offset - hmac_len);
+ hmac_ctx_final (ctx->hmac, local_hmac);
+
+ /* Compare locally computed HMAC with packet HMAC */
+ if (memcmp (local_hmac, BPTR (buf) + offset, hmac_len))
+ {
+ gc_free (&gc);
+ return false;
+ }
+
+ gc_free (&gc);
+ return true;
+ }
+ }
+
+ gc_free (&gc);
+ return false;
+}
+
+/*
* How many bytes will we add to frame buffer for a given
* set of crypto options?
*/
diff --git a/main/openvpn/src/openvpn/crypto.h b/main/openvpn/src/openvpn/crypto.h
index 3b4b88ea..68cdf162 100644
--- a/main/openvpn/src/openvpn/crypto.h
+++ b/main/openvpn/src/openvpn/crypto.h
@@ -279,6 +279,9 @@ bool openvpn_decrypt (struct buffer *buf, struct buffer work,
const struct crypto_options *opt,
const struct frame* frame);
+
+bool crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt);
+
/** @} name Functions for performing security operations on data channel packets */
void crypto_adjust_frame_parameters(struct frame *frame,
diff --git a/main/openvpn/src/openvpn/init.c b/main/openvpn/src/openvpn/init.c
index ede955a1..7dd61a20 100644
--- a/main/openvpn/src/openvpn/init.c
+++ b/main/openvpn/src/openvpn/init.c
@@ -3165,13 +3165,24 @@ management_show_net_callback (void *arg, const int msglevel)
int
managmenet_callback_network_change (void *arg)
{
+ int socketfd=-1;
struct context *c = (struct context *) arg;
if (!c->c2.link_socket)
return -1;
if (c->c2.link_socket->sd == SOCKET_UNDEFINED)
return -1;
- return c->c2.link_socket->sd;
+ /* Check if the client should translate the network change to a SIGUSR1 to
+ reestablish the connection or just reprotect the socket */
+
+ /* At the moment just assume that, for all settings that use pull
+ reestablishing the connection is required */
+
+ socketfd = c->c2.link_socket->sd;
+ if (!c->options.pull || c->c2.tls_multi->use_session_id)
+ return socketfd;
+ else
+ return -2;
}
#endif
diff --git a/main/openvpn/src/openvpn/manage.c b/main/openvpn/src/openvpn/manage.c
index e7a7fe85..386718d4 100644
--- a/main/openvpn/src/openvpn/manage.c
+++ b/main/openvpn/src/openvpn/manage.c
@@ -1113,7 +1113,9 @@ man_network_change (struct management *man)
{
int fd = (*man->persist.callback.network_change)(man->persist.callback.arg);
man->connection.fdtosend = fd;
- msg (M_CLIENT, "PROTECTFD: fd '%d' sent to be protected", fd);
+ msg (M_CLIENT, "PROTECTFD: fd '%d' sent to be protected", fd);
+ if (fd == -2)
+ man_signal (man, "USR1");
}
}
#endif
@@ -1164,7 +1166,8 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
#ifdef TARGET_ANDROID
else if (streq (p[0], "network-change"))
{
- man_network_change(man);
+ if (man_need (man, p, 1, 0))
+ man_network_change(man);
}
#endif
else if (streq (p[0], "load-stats"))
diff --git a/main/openvpn/src/openvpn/misc.c b/main/openvpn/src/openvpn/misc.c
index 7483184f..63b4c1cf 100644
--- a/main/openvpn/src/openvpn/misc.c
+++ b/main/openvpn/src/openvpn/misc.c
@@ -861,6 +861,12 @@ test_file (const char *filename)
fclose (fp);
ret = true;
}
+ else
+ {
+ if( openvpn_errno () == EACCES ) {
+ msg( M_WARN | M_ERRNO, "Could not access file '%s'", filename);
+ }
+ }
}
dmsg (D_TEST_FILE, "TEST FILE '%s' [%d]",
diff --git a/main/openvpn/src/openvpn/mudp.c b/main/openvpn/src/openvpn/mudp.c
index 3468dab5..f7ab6253 100644
--- a/main/openvpn/src/openvpn/mudp.c
+++ b/main/openvpn/src/openvpn/mudp.c
@@ -38,6 +38,55 @@
#include "memdbg.h"
/*
+ * Update instance with new peer address
+ */
+void
+update_floated(struct multi_context *m, struct multi_instance *mi,
+ struct mroute_addr real, uint32_t hv)
+{
+ struct mroute_addr real_old;
+
+ real_old = mi->real;
+ generate_prefix (mi);
+
+ /* remove before modifying mi->real, since it also modifies key in hash */
+ hash_remove(m->hash, &real_old);
+ hash_remove(m->iter, &real_old);
+
+ /* update address */
+ memcpy(&mi->real, &real, sizeof(real));
+
+ mi->context.c2.from = m->top.c2.from;
+ mi->context.c2.to_link_addr = &mi->context.c2.from;
+
+ /* switch to new log prefix */
+ generate_prefix (mi);
+ /* inherit buffers */
+ mi->context.c2.buffers = m->top.c2.buffers;
+
+ /* inherit parent link_socket and link_socket_info */
+ mi->context.c2.link_socket = m->top.c2.link_socket;
+ mi->context.c2.link_socket_info->lsa->actual = m->top.c2.from;
+
+ /* fix remote_addr in tls structure */
+ tls_update_remote_addr (mi->context.c2.tls_multi, &mi->context.c2.from);
+ mi->did_open_context = true;
+
+ hash_add(m->hash, &mi->real, mi, false);
+ hash_add(m->iter, &mi->real, mi, false);
+
+ mi->did_real_hash = true;
+#ifdef MANAGEMENT_DEF_AUTH
+ hash_remove (m->cid_hash, &mi->context.c2.mda_context.cid);
+ hash_add (m->cid_hash, &mi->context.c2.mda_context.cid, mi, false);
+#endif
+
+#ifdef MANAGEMENT_DEF_AUTH
+ mi->did_cid_hash = true;
+#endif
+}
+
+/*
* Get a client instance based on real address. If
* the instance doesn't exist, create it while
* maintaining real address hash table atomicity.
@@ -56,15 +105,47 @@ multi_get_create_instance_udp (struct multi_context *m)
struct hash_element *he;
const uint32_t hv = hash_value (hash, &real);
struct hash_bucket *bucket = hash_bucket (hash, hv);
-
- he = hash_lookup_fast (hash, bucket, &real, hv);
+ uint8_t* ptr = BPTR(&m->top.c2.buf);
+ uint8_t op = ptr[0] >> P_OPCODE_SHIFT;
+ uint32_t sess_id;
+ bool session_forged = false;
- if (he)
+ if (op == P_DATA_V2)
{
- mi = (struct multi_instance *) he->value;
+ sess_id = (*(uint32_t*)ptr) >> 8;
+ if ((sess_id < m->max_clients) && (m->instances[sess_id]))
+ {
+ mi = m->instances[sess_id];
+
+ if (!link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from))
+ {
+ msg(D_MULTI_MEDIUM, "floating detected from %s to %s",
+ print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc));
+
+ /* session-id is not trusted, so check hmac */
+ session_forged = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options));
+ if (session_forged)
+ {
+ mi = NULL;
+ msg (D_MULTI_MEDIUM, "hmac verification failed, session forge detected!");
+ }
+ else
+ {
+ update_floated(m, mi, real, hv);
+ }
+ }
+ }
}
else
{
+ he = hash_lookup_fast (hash, bucket, &real, hv);
+ if (he)
+ {
+ mi = (struct multi_instance *) he->value;
+ }
+ }
+ if (!mi && !session_forged)
+ {
if (!m->top.c2.tls_auth_standalone
|| tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf))
{
@@ -75,6 +156,17 @@ multi_get_create_instance_udp (struct multi_context *m)
{
hash_add_fast (hash, bucket, &mi->real, hv, mi);
mi->did_real_hash = true;
+
+ int i;
+ for (i = 0; i < m->max_clients; ++ i)
+ {
+ if (!m->instances[i])
+ {
+ mi->context.c2.tls_multi->vpn_session_id = i;
+ m->instances[i] = mi;
+ break;
+ }
+ }
}
}
else
@@ -89,15 +181,17 @@ multi_get_create_instance_udp (struct multi_context *m)
#ifdef ENABLE_DEBUG
if (check_debug_level (D_MULTI_DEBUG))
{
- const char *status;
+ const char *status = mi ? "[ok]" : "[failed]";
+ /*
if (he && mi)
status = "[succeeded]";
else if (!he && mi)
status = "[created]";
else
status = "[failed]";
-
+ */
+
dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s",
mroute_addr_print (&real, &gc),
status);
diff --git a/main/openvpn/src/openvpn/multi.c b/main/openvpn/src/openvpn/multi.c
index 9a2b0237..a4289ac7 100644
--- a/main/openvpn/src/openvpn/multi.c
+++ b/main/openvpn/src/openvpn/multi.c
@@ -303,6 +303,7 @@ multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa
cid_compare_function);
#endif
+
/*
* This is our scheduler, for time-based wakeup
* events.
@@ -373,6 +374,13 @@ multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa
*/
m->max_clients = t->options.max_clients;
+ int i;
+ m->instances = malloc(sizeof(struct multi_instance*) * m->max_clients);
+ for (i = 0; i < m->max_clients; ++ i)
+ {
+ m->instances[i] = NULL;
+ }
+
/*
* Initialize multi-socket TCP I/O wait object
*/
@@ -553,6 +561,8 @@ multi_close_instance (struct multi_context *m,
}
#endif
+ m->instances[mi->context.c2.tls_multi->vpn_session_id] = NULL;
+
schedule_remove_entry (m->schedule, (struct schedule_entry *) mi);
ifconfig_pool_release (m->ifconfig_pool, mi->vaddr_handle, false);
@@ -629,6 +639,8 @@ multi_uninit (struct multi_context *m)
#endif
m->hash = NULL;
+ free(m->instances);
+
schedule_free (m->schedule);
mbuf_free (m->mbuf);
ifconfig_pool_free (m->ifconfig_pool);
@@ -652,8 +664,6 @@ multi_create_instance (struct multi_context *m, const struct mroute_addr *real)
perf_push (PERF_MULTI_CREATE_INSTANCE);
- msg (D_MULTI_MEDIUM, "MULTI: multi_create_instance called");
-
ALLOC_OBJ_CLEAR (mi, struct multi_instance);
mi->gc = gc_new ();
diff --git a/main/openvpn/src/openvpn/multi.h b/main/openvpn/src/openvpn/multi.h
index fc2ffb24..0446fbfc 100644
--- a/main/openvpn/src/openvpn/multi.h
+++ b/main/openvpn/src/openvpn/multi.h
@@ -125,6 +125,8 @@ struct multi_context {
# define MC_WORK_THREAD (MC_MULTI_THREADED_WORKER|MC_MULTI_THREADED_SCHEDULER)
int thread_mode;
+ struct multi_instance** instances;
+
struct hash *hash; /**< VPN tunnel instances indexed by real
* address of the remote peer. */
struct hash *vhash; /**< VPN tunnel instances indexed by
diff --git a/main/openvpn/src/openvpn/options.c b/main/openvpn/src/openvpn/options.c
index fc764616..addca14a 100644
--- a/main/openvpn/src/openvpn/options.c
+++ b/main/openvpn/src/openvpn/options.c
@@ -3898,7 +3898,8 @@ apply_push_options (struct options *options,
struct buffer *buf,
unsigned int permission_mask,
unsigned int *option_types_found,
- struct env_set *es)
+ struct env_set *es,
+ struct tls_multi *tls_multi)
{
char line[OPTION_PARM_SIZE];
int line_num = 0;
@@ -3912,7 +3913,17 @@ apply_push_options (struct options *options,
++line_num;
if (parse_line (line, p, SIZE (p), file, line_num, msglevel, &options->gc))
{
- add_option (options, p, file, line_num, 0, msglevel, permission_mask, option_types_found, es);
+ if (streq(p[0], "session_id"))
+ {
+ /* Server supports P_DATA_V2 */
+ tls_multi->vpn_session_id = atoi(p[1]);
+ tls_multi->use_session_id = true;
+ msg(D_PUSH, "session id: %d", tls_multi->vpn_session_id);
+ }
+ else
+ {
+ add_option (options, p, file, line_num, 0, msglevel, permission_mask, option_types_found, es);
+ }
}
}
return true;
diff --git a/main/openvpn/src/openvpn/options.h b/main/openvpn/src/openvpn/options.h
index 21c210ee..77c942ca 100644
--- a/main/openvpn/src/openvpn/options.h
+++ b/main/openvpn/src/openvpn/options.h
@@ -712,11 +712,13 @@ void options_postprocess (struct options *options);
void pre_pull_save (struct options *o);
void pre_pull_restore (struct options *o, struct gc_arena *gc);
+struct tls_multi;
bool apply_push_options (struct options *options,
struct buffer *buf,
unsigned int permission_mask,
unsigned int *option_types_found,
- struct env_set *es);
+ struct env_set *es,
+ struct tls_multi* tls_multi);
void options_detach (struct options *o);
diff --git a/main/openvpn/src/openvpn/push.c b/main/openvpn/src/openvpn/push.c
index 24d12c7b..028d838e 100644
--- a/main/openvpn/src/openvpn/push.c
+++ b/main/openvpn/src/openvpn/push.c
@@ -303,6 +303,11 @@ send_push_reply (struct context *c)
if (multi_push)
buf_printf (&buf, ",push-continuation 1");
+ /* Send session_id if client supports it */
+ if (c->c2.tls_multi->peer_info && strstr(c->c2.tls_multi->peer_info, "IV_PROTO=2")) {
+ buf_printf(&buf, ",session_id %d", c->c2.tls_multi->vpn_session_id);
+ }
+
if (BLEN (&buf) > sizeof(cmd)-1)
{
const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH);
@@ -462,7 +467,8 @@ process_incoming_push_msg (struct context *c,
&buf,
permission_mask,
option_types_found,
- c->c2.es))
+ c->c2.es,
+ c->c2.tls_multi))
switch (c->options.push_continuation)
{
case 0:
diff --git a/main/openvpn/src/openvpn/ssl.c b/main/openvpn/src/openvpn/ssl.c
index 95bbb277..44f50808 100644
--- a/main/openvpn/src/openvpn/ssl.c
+++ b/main/openvpn/src/openvpn/ssl.c
@@ -624,6 +624,8 @@ packet_opcode_name (int op)
return "P_ACK_V1";
case P_DATA_V1:
return "P_DATA_V1";
+ case P_DATA_V2:
+ return "P_DATA_V2";
default:
return "P_???";
}
@@ -1069,6 +1071,9 @@ tls_multi_init (struct tls_options *tls_options)
ret->key_scan[1] = &ret->session[TM_ACTIVE].key[KS_LAME_DUCK];
ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK];
+ /* By default not use P_DATA_V2 */
+ ret->use_session_id = false;
+
return ret;
}
@@ -1842,6 +1847,9 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
buf_printf (&out, "IV_PLAT=win\n");
#endif
+ /* support for P_DATA_V2 */
+ buf_printf(&out, "IV_PROTO=2\n");
+
/* push compression status */
#ifdef USE_COMP
comp_generate_peer_info_string(&session->opt->comp_options, &out);
@@ -2799,8 +2807,9 @@ tls_pre_decrypt (struct tls_multi *multi,
key_id = c & P_KEY_ID_MASK;
}
- if (op == P_DATA_V1)
- { /* data channel packet */
+ if ((op == P_DATA_V1) || (op == P_DATA_V2))
+ {
+ /* data channel packet */
for (i = 0; i < KEY_SCAN_SIZE; ++i)
{
struct key_state *ks = multi->key_scan[i];
@@ -2832,7 +2841,9 @@ tls_pre_decrypt (struct tls_multi *multi,
opt->pid_persist = NULL;
opt->flags &= multi->opt.crypto_flags_and;
opt->flags |= multi->opt.crypto_flags_or;
- ASSERT (buf_advance (buf, 1));
+
+ ASSERT (buf_advance (buf, op == P_DATA_V1 ? 1 : 4));
+
++ks->n_packets;
ks->n_bytes += buf->len;
dmsg (D_TLS_KEYSELECT,
@@ -3329,6 +3340,7 @@ tls_pre_decrypt_lite (const struct tls_auth_standalone *tas,
return ret;
error:
+
tls_clear_error();
gc_free (&gc);
return ret;
@@ -3397,14 +3409,24 @@ tls_post_encrypt (struct tls_multi *multi, struct buffer *buf)
{
struct key_state *ks;
uint8_t *op;
+ uint32_t sess;
ks = multi->save_ks;
multi->save_ks = NULL;
if (buf->len > 0)
{
ASSERT (ks);
- ASSERT (op = buf_prepend (buf, 1));
- *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id;
+
+ if (!multi->opt.server && multi->use_session_id)
+ {
+ sess = ((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) | (multi->vpn_session_id << 8);
+ ASSERT (buf_write_prepend (buf, &sess, 4));
+ }
+ else
+ {
+ ASSERT (op = buf_prepend (buf, 1));
+ *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id;
+ }
++ks->n_packets;
ks->n_bytes += buf->len;
}
@@ -3477,6 +3499,31 @@ tls_rec_payload (struct tls_multi *multi,
return ret;
}
+/* Update the remote_addr, needed if a client floats. */
+void
+tls_update_remote_addr (struct tls_multi *multi,
+const struct link_socket_actual *from)
+{
+ struct gc_arena gc = gc_new ();
+ int i;
+
+ for (i = 0; i < KEY_SCAN_SIZE; ++i)
+ {
+ struct key_state *ks = multi->key_scan[i];
+ if (DECRYPT_KEY_ENABLED (multi, ks) && ks->authenticated && link_socket_actual_defined(&ks->remote_addr))
+ {
+ if (link_socket_actual_match (from, &ks->remote_addr))
+ continue;
+ dmsg (D_TLS_KEYSELECT,
+ "TLS: tls_update_remote_addr from IP=%s to IP=%s",
+ print_link_socket_actual (&ks->remote_addr, &gc),
+ print_link_socket_actual (from, &gc));
+ memcpy(&ks->remote_addr, from, sizeof(*from));
+ }
+ }
+ gc_free (&gc);
+}
+
/*
* Dump a human-readable rendition of an openvpn packet
* into a garbage collectable string which is returned.
@@ -3511,7 +3558,7 @@ protocol_dump (struct buffer *buffer, unsigned int flags, struct gc_arena *gc)
key_id = c & P_KEY_ID_MASK;
buf_printf (&out, "%s kid=%d", packet_opcode_name (op), key_id);
- if (op == P_DATA_V1)
+ if ((op == P_DATA_V1) || (op == P_DATA_V2))
goto print_data;
/*
diff --git a/main/openvpn/src/openvpn/ssl.h b/main/openvpn/src/openvpn/ssl.h
index aaecff43..9bdd641f 100644
--- a/main/openvpn/src/openvpn/ssl.h
+++ b/main/openvpn/src/openvpn/ssl.h
@@ -60,6 +60,7 @@
#define P_CONTROL_V1 4 /* control channel packet (usually TLS ciphertext) */
#define P_ACK_V1 5 /* acknowledgement for packets received */
#define P_DATA_V1 6 /* data channel packet */
+#define P_DATA_V2 9 /* data channel packet with session_id */
/* indicates key_method >= 2 */
#define P_CONTROL_HARD_RESET_CLIENT_V2 7 /* initial key from client, forget previous state */
@@ -67,7 +68,7 @@
/* define the range of legal opcodes */
#define P_FIRST_OPCODE 1
-#define P_LAST_OPCODE 8
+#define P_LAST_OPCODE 9
/* Should we aggregate TLS
* acknowledgements, and tack them onto
@@ -430,6 +431,12 @@ bool tls_send_payload (struct tls_multi *multi,
bool tls_rec_payload (struct tls_multi *multi,
struct buffer *buf);
+/*
+ * Update remote address of a tls_multi structure
+ */
+void tls_update_remote_addr (struct tls_multi *multi,
+ const struct link_socket_actual *from);
+
#ifdef MANAGEMENT_DEF_AUTH
static inline char *
tls_get_peer_info(const struct tls_multi *multi)
diff --git a/main/openvpn/src/openvpn/ssl_common.h b/main/openvpn/src/openvpn/ssl_common.h
index 04ba7892..2fc72aa6 100644
--- a/main/openvpn/src/openvpn/ssl_common.h
+++ b/main/openvpn/src/openvpn/ssl_common.h
@@ -495,6 +495,10 @@ struct tls_multi
char *peer_info;
#endif
+ /* For P_DATA_V2 */
+ uint32_t vpn_session_id;
+ int use_session_id;
+
/*
* Our session objects.
*/
diff --git a/main/openvpn/src/openvpn/ssl_verify_polarssl.c b/main/openvpn/src/openvpn/ssl_verify_polarssl.c
index 71d38a9d..7e8b5179 100644
--- a/main/openvpn/src/openvpn/ssl_verify_polarssl.c
+++ b/main/openvpn/src/openvpn/ssl_verify_polarssl.c
@@ -337,7 +337,7 @@ x509_verify_cert_eku (x509_crt *cert, const char * const expected_oid)
}
}
- if (0 == x509_oid_get_numeric_string( oid_num_str,
+ if (0 < x509_oid_get_numeric_string( oid_num_str,
sizeof (oid_num_str), oid))
{
msg (D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s",