summaryrefslogtreecommitdiff
path: root/main/openvpn/src
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2015-02-09 10:01:57 +0100
committerArne Schwabe <arne@rfc2549.org>2015-02-09 10:01:57 +0100
commit68d26e1b1b5b411adce714c88532fc8889289f34 (patch)
tree8d2db5723a8956ada01c1f875aa0158dcf64d91f /main/openvpn/src
parent8e481f24a63d42f423b6f33ad83b80f512ebadd2 (diff)
Update OpenVPN
Diffstat (limited to 'main/openvpn/src')
-rw-r--r--main/openvpn/src/openvpn/buffer.c13
-rw-r--r--main/openvpn/src/openvpn/buffer.h1
-rw-r--r--main/openvpn/src/openvpn/error.c2
-rw-r--r--main/openvpn/src/openvpn/init.c24
-rw-r--r--main/openvpn/src/openvpn/manage.c145
-rw-r--r--main/openvpn/src/openvpn/manage.h5
-rw-r--r--main/openvpn/src/openvpn/mtu.h6
-rw-r--r--main/openvpn/src/openvpn/mudp.c9
-rw-r--r--main/openvpn/src/openvpn/options.c19
-rw-r--r--main/openvpn/src/openvpn/ssl.c26
10 files changed, 207 insertions, 43 deletions
diff --git a/main/openvpn/src/openvpn/buffer.c b/main/openvpn/src/openvpn/buffer.c
index 46f874b2..421d60e9 100644
--- a/main/openvpn/src/openvpn/buffer.c
+++ b/main/openvpn/src/openvpn/buffer.c
@@ -1066,8 +1066,10 @@ buffer_list_peek (struct buffer_list *ol)
}
void
-buffer_list_aggregate (struct buffer_list *bl, const size_t max)
+buffer_list_aggregate_separator (struct buffer_list *bl, const size_t max, const char *sep)
{
+ int sep_len = strlen(sep);
+
if (bl->head)
{
struct buffer_entry *more = bl->head;
@@ -1075,7 +1077,7 @@ buffer_list_aggregate (struct buffer_list *bl, const size_t max)
int count = 0;
for (count = 0; more && size <= max; ++count)
{
- size += BLEN(&more->buf);
+ size += BLEN(&more->buf) + sep_len;
more = more->next;
}
@@ -1092,6 +1094,7 @@ buffer_list_aggregate (struct buffer_list *bl, const size_t max)
{
struct buffer_entry *next = e->next;
buf_copy (&f->buf, &e->buf);
+ buf_write(&f->buf, sep, sep_len);
free_buf (&e->buf);
free (e);
e = next;
@@ -1105,6 +1108,12 @@ buffer_list_aggregate (struct buffer_list *bl, const size_t max)
}
void
+buffer_list_aggregate (struct buffer_list *bl, const size_t max)
+{
+ buffer_list_aggregate_separator(bl, max, "");
+}
+
+void
buffer_list_pop (struct buffer_list *ol)
{
if (ol && ol->head)
diff --git a/main/openvpn/src/openvpn/buffer.h b/main/openvpn/src/openvpn/buffer.h
index 7469da63..5695f64f 100644
--- a/main/openvpn/src/openvpn/buffer.h
+++ b/main/openvpn/src/openvpn/buffer.h
@@ -931,6 +931,7 @@ void buffer_list_advance (struct buffer_list *ol, int n);
void buffer_list_pop (struct buffer_list *ol);
void buffer_list_aggregate (struct buffer_list *bl, const size_t max);
+void buffer_list_aggregate_separator (struct buffer_list *bl, const size_t max, const char *sep);
struct buffer_list *buffer_list_file (const char *fn, int max_line_len);
#endif /* BUFFER_H */
diff --git a/main/openvpn/src/openvpn/error.c b/main/openvpn/src/openvpn/error.c
index 72ebfab6..08503238 100644
--- a/main/openvpn/src/openvpn/error.c
+++ b/main/openvpn/src/openvpn/error.c
@@ -323,7 +323,7 @@ void x_msg_va (const unsigned int flags, const char *format, va_list arglist)
fprintf (fp, "%lu.%06lu %x %s%s%s%s",
tv.tv_sec,
- tv.tv_usec,
+ (unsigned long)tv.tv_usec,
flags,
prefix,
prefix_sep,
diff --git a/main/openvpn/src/openvpn/init.c b/main/openvpn/src/openvpn/init.c
index 77827a57..077b130e 100644
--- a/main/openvpn/src/openvpn/init.c
+++ b/main/openvpn/src/openvpn/init.c
@@ -1794,6 +1794,19 @@ do_deferred_options (struct context *c, const unsigned int found)
msg (D_PUSH, "OPTIONS IMPORT: peer-id set");
c->c2.tls_multi->use_peer_id = true;
c->c2.tls_multi->peer_id = c->options.peer_id;
+ frame_add_to_extra_frame(&c->c2.frame, +3); /* peer-id overhead */
+ if ( !c->options.ce.link_mtu_defined )
+ {
+ frame_add_to_link_mtu(&c->c2.frame, +3);
+ msg (D_PUSH, "OPTIONS IMPORT: adjusting link_mtu to %d",
+ EXPANDED_SIZE(&c->c2.frame));
+ }
+ else
+ {
+ msg (M_WARN, "OPTIONS IMPORT: WARNING: peer-id set, but link-mtu"
+ " fixed by config - reducing tun-mtu to %d, expect"
+ " MTU problems", TUN_MTU_SIZE(&c->c2.frame) );
+ }
}
#endif
}
@@ -2403,6 +2416,17 @@ do_init_frame (struct context *c)
#endif
#endif /* USE_COMP */
+ /* packets with peer-id (P_DATA_V2) need 3 extra bytes in frame (on client)
+ * and need link_mtu+3 bytes on socket reception (on server).
+ *
+ * accomodate receive path in f->extra_link, which has the side effect of
+ * also increasing send buffers (BUF_SIZE() macro), which need to be
+ * allocated big enough before receiving peer-id option from server.
+ *
+ * f->extra_frame is adjusted when peer-id option is push-received
+ */
+ frame_add_to_extra_link(&c->c2.frame, 3);
+
#ifdef ENABLE_FRAGMENT
/*
* Set frame parameter for fragment code. This is necessary because
diff --git a/main/openvpn/src/openvpn/manage.c b/main/openvpn/src/openvpn/manage.c
index 27164f18..6617ccd4 100644
--- a/main/openvpn/src/openvpn/manage.c
+++ b/main/openvpn/src/openvpn/manage.c
@@ -113,6 +113,8 @@ man_help ()
#ifdef MANAGMENT_EXTERNAL_KEY
msg (M_CLIENT, "rsa-sig : Enter an RSA signature in response to >RSA_SIGN challenge");
msg (M_CLIENT, " Enter signature base64 on subsequent lines followed by END");
+ msg (M_CLIENT, "certificate : Enter a client certificate in response to >NEED-CERT challenge");
+ msg (M_CLIENT, " Enter certificate base64 on subsequent lines followed by END");
#endif
msg (M_CLIENT, "signal s : Send signal s to daemon,");
msg (M_CLIENT, " s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2.");
@@ -868,6 +870,12 @@ in_extra_dispatch (struct management *man)
man->connection.ext_key_input = man->connection.in_extra;
man->connection.in_extra = NULL;
return;
+ case IEC_CERTIFICATE:
+ man->connection.ext_cert_state = EKS_READY;
+ buffer_list_free (man->connection.ext_cert_input);
+ man->connection.ext_cert_input = man->connection.in_extra;
+ man->connection.in_extra = NULL;
+ return;
#endif
}
in_extra_reset (&man->connection, IER_RESET);
@@ -1030,6 +1038,20 @@ man_rsa_sig (struct management *man)
msg (M_CLIENT, "ERROR: The rsa-sig command is not currently available");
}
+static void
+man_certificate (struct management *man)
+{
+ struct man_connection *mc = &man->connection;
+ if (mc->ext_cert_state == EKS_SOLICIT)
+ {
+ mc->ext_cert_state = EKS_INPUT;
+ mc->in_extra_cmd = IEC_CERTIFICATE;
+ in_extra_reset (mc, IER_NEW);
+ }
+ else
+ msg (M_CLIENT, "ERROR: The certificate command is not currently available");
+}
+
#endif
static void
@@ -1332,6 +1354,10 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
{
man_rsa_sig (man);
}
+ else if (streq (p[0], "certificate"))
+ {
+ man_certificate (man);
+ }
#endif
#ifdef ENABLE_PKCS11
else if (streq (p[0], "pkcs11-id-count"))
@@ -3118,15 +3144,14 @@ management_query_user_pass (struct management *man,
#ifdef MANAGMENT_EXTERNAL_KEY
-char * /* returns allocated base64 signature */
-management_query_rsa_sig (struct management *man,
- const char *b64_data)
+int
+management_query_multiline (struct management *man,
+ const char *b64_data, const char *prompt, const char *cmd, int *state, struct buffer_list **input)
{
struct gc_arena gc = gc_new ();
- char *ret = NULL;
+ int ret = 0;
volatile int signal_received = 0;
struct buffer alert_msg = clear_buf();
- struct buffer *buf;
const bool standalone_disabled_save = man->persist.standalone_disabled;
struct man_connection *mc = &man->connection;
@@ -3135,10 +3160,15 @@ management_query_rsa_sig (struct management *man,
man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
man->persist.special_state_msg = NULL;
- mc->ext_key_state = EKS_SOLICIT;
+ *state = EKS_SOLICIT;
- alert_msg = alloc_buf_gc (strlen(b64_data)+64, &gc);
- buf_printf (&alert_msg, ">RSA_SIGN:%s", b64_data);
+ if (b64_data) {
+ alert_msg = alloc_buf_gc (strlen(b64_data)+strlen(prompt)+3, &gc);
+ buf_printf (&alert_msg, ">%s:%s", prompt, b64_data);
+ } else {
+ alert_msg = alloc_buf_gc (strlen(prompt)+3, &gc);
+ buf_printf (&alert_msg, ">%s", prompt);
+ }
man_wait_for_client_connection (man, &signal_received, 0, MWCC_OTHER_WAIT);
@@ -3156,40 +3186,99 @@ management_query_rsa_sig (struct management *man,
man_check_for_signals (&signal_received);
if (signal_received)
goto done;
- } while (mc->ext_key_state != EKS_READY);
+ } while (*state != EKS_READY);
- if (buffer_list_defined(mc->ext_key_input))
- {
- buffer_list_aggregate (mc->ext_key_input, 2048);
- buf = buffer_list_peek (mc->ext_key_input);
- if (buf && BLEN(buf) > 0)
- {
- ret = (char *) malloc(BLEN(buf)+1);
- check_malloc_return(ret);
- memcpy(ret, buf->data, BLEN(buf));
- ret[BLEN(buf)] = '\0';
- }
- }
+ ret = 1;
}
done:
- if (mc->ext_key_state == EKS_READY && ret)
- msg (M_CLIENT, "SUCCESS: rsa-sig command succeeded");
- else if (mc->ext_key_state == EKS_INPUT || mc->ext_key_state == EKS_READY)
- msg (M_CLIENT, "ERROR: rsa-sig command failed");
+ if (*state == EKS_READY && ret)
+ msg (M_CLIENT, "SUCCESS: %s command succeeded", cmd);
+ else if (*state == EKS_INPUT || *state == EKS_READY)
+ msg (M_CLIENT, "ERROR: %s command failed", cmd);
/* revert state */
man->persist.standalone_disabled = standalone_disabled_save;
man->persist.special_state_msg = NULL;
in_extra_reset (mc, IER_RESET);
- mc->ext_key_state = EKS_UNDEF;
- buffer_list_free (mc->ext_key_input);
- mc->ext_key_input = NULL;
+ *state = EKS_UNDEF;
gc_free (&gc);
return ret;
}
+char * /* returns allocated base64 signature */
+management_query_multiline_flatten_newline (struct management *man,
+ const char *b64_data, const char *prompt, const char *cmd, int *state, struct buffer_list **input)
+{
+ int ok;
+ char *result = NULL;
+ struct buffer *buf;
+
+ ok = management_query_multiline(man, b64_data, prompt, cmd, state, input);
+ if (ok && buffer_list_defined(*input))
+ {
+ buffer_list_aggregate_separator (*input, 10000, "\n");
+ buf = buffer_list_peek (*input);
+ if (buf && BLEN(buf) > 0)
+ {
+ result = (char *) malloc(BLEN(buf)+1);
+ check_malloc_return(result);
+ memcpy(result, buf->data, BLEN(buf));
+ result[BLEN(buf)] = '\0';
+ }
+ }
+
+ buffer_list_free (*input);
+ *input = NULL;
+
+ return result;
+}
+
+char * /* returns allocated base64 signature */
+management_query_multiline_flatten (struct management *man,
+ const char *b64_data, const char *prompt, const char *cmd, int *state, struct buffer_list **input)
+{
+ int ok;
+ char *result = NULL;
+ struct buffer *buf;
+
+ ok = management_query_multiline(man, b64_data, prompt, cmd, state, input);
+ if (ok && buffer_list_defined(*input))
+ {
+ buffer_list_aggregate (*input, 2048);
+ buf = buffer_list_peek (*input);
+ if (buf && BLEN(buf) > 0)
+ {
+ result = (char *) malloc(BLEN(buf)+1);
+ check_malloc_return(result);
+ memcpy(result, buf->data, BLEN(buf));
+ result[BLEN(buf)] = '\0';
+ }
+ }
+
+ buffer_list_free (*input);
+ *input = NULL;
+
+ return result;
+}
+
+char * /* returns allocated base64 signature */
+management_query_rsa_sig (struct management *man,
+ const char *b64_data)
+{
+ return management_query_multiline_flatten(man, b64_data, "RSA_SIGN", "rsa-sign",
+ &man->connection.ext_key_state, &man->connection.ext_key_input);
+}
+
+
+char* management_query_cert (struct management *man)
+{
+ return management_query_multiline_flatten_newline(management,
+ NULL, "NEED-CERTIFICATE", "certificate",
+ &man->connection.ext_cert_state, &man->connection.ext_cert_input);
+}
+
#endif
/*
diff --git a/main/openvpn/src/openvpn/manage.h b/main/openvpn/src/openvpn/manage.h
index c48875c7..d9da0063 100644
--- a/main/openvpn/src/openvpn/manage.h
+++ b/main/openvpn/src/openvpn/manage.h
@@ -271,6 +271,7 @@ struct man_connection {
# define IEC_CLIENT_AUTH 1
# define IEC_CLIENT_PF 2
# define IEC_RSA_SIGN 3
+# define IEC_CERTIFICATE 4
int in_extra_cmd;
struct buffer_list *in_extra;
#ifdef MANAGEMENT_DEF_AUTH
@@ -284,6 +285,8 @@ struct man_connection {
# define EKS_READY 3
int ext_key_state;
struct buffer_list *ext_key_input;
+ int ext_cert_state;
+ struct buffer_list *ext_cert_input;
#endif
#endif
struct event_set *es;
@@ -341,6 +344,7 @@ struct management *management_init (void);
#define MF_UP_DOWN (1<<10)
#define MF_QUERY_REMOTE (1<<11)
#define MF_QUERY_PROXY (1<<12)
+#define MF_EXTERNAL_CERT (1<<13)
bool management_open (struct management *man,
const char *addr,
@@ -423,6 +427,7 @@ void management_learn_addr (struct management *management,
#ifdef MANAGMENT_EXTERNAL_KEY
char *management_query_rsa_sig (struct management *man, const char *b64_data);
+char* management_query_cert (struct management *man);
#endif
diff --git a/main/openvpn/src/openvpn/mtu.h b/main/openvpn/src/openvpn/mtu.h
index 29ec21fd..bccd6810 100644
--- a/main/openvpn/src/openvpn/mtu.h
+++ b/main/openvpn/src/openvpn/mtu.h
@@ -258,6 +258,12 @@ frame_headroom (const struct frame *f, const unsigned int flag_mask)
*/
static inline void
+frame_add_to_link_mtu (struct frame *frame, const int increment)
+{
+ frame->link_mtu += increment;
+}
+
+static inline void
frame_add_to_extra_frame (struct frame *frame, const int increment)
{
frame->extra_frame += increment;
diff --git a/main/openvpn/src/openvpn/mudp.c b/main/openvpn/src/openvpn/mudp.c
index 3e3f7508..57118f87 100644
--- a/main/openvpn/src/openvpn/mudp.c
+++ b/main/openvpn/src/openvpn/mudp.c
@@ -52,20 +52,19 @@ multi_get_create_instance_udp (struct multi_context *m, bool *floated)
struct multi_instance *mi = NULL;
struct hash *hash = m->hash;
- if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true))
+ if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true) &&
+ m->top.c2.buf.len > 0)
{
struct hash_element *he;
const uint32_t hv = hash_value (hash, &real);
struct hash_bucket *bucket = hash_bucket (hash, hv);
uint8_t* ptr = BPTR(&m->top.c2.buf);
uint8_t op = ptr[0] >> P_OPCODE_SHIFT;
- uint32_t peer_id;
- int i;
/* make sure buffer has enough length to read opcode (1 byte) and peer-id (3 bytes) */
if (op == P_DATA_V2 && m->top.c2.buf.len >= (1 + 3))
{
- peer_id = ntohl(*(uint32_t*)ptr) & 0xFFFFFF;
+ uint32_t peer_id = ntohl(*(uint32_t*)ptr) & 0xFFFFFF;
if ((peer_id < m->max_clients) && (m->instances[peer_id]))
{
mi = m->instances[peer_id];
@@ -99,6 +98,8 @@ multi_get_create_instance_udp (struct multi_context *m, bool *floated)
mi = multi_create_instance (m, &real);
if (mi)
{
+ int i;
+
hash_add_fast (hash, bucket, &mi->real, hv, mi);
mi->did_real_hash = true;
diff --git a/main/openvpn/src/openvpn/options.c b/main/openvpn/src/openvpn/options.c
index e2897984..c2a377b3 100644
--- a/main/openvpn/src/openvpn/options.c
+++ b/main/openvpn/src/openvpn/options.c
@@ -1568,6 +1568,11 @@ show_settings (const struct options *o)
SHOW_STR (ca_file);
SHOW_STR (ca_path);
SHOW_STR (dh_file);
+#ifdef MANAGMENT_EXTERNAL_KEY
+ if((o->management_flags & MF_EXTERNAL_CERT))
+ SHOW_PARM ("cert_file","EXTERNAL_CERT","%s");
+ else
+#endif
SHOW_STR (cert_file);
#ifdef MANAGMENT_EXTERNAL_KEY
@@ -2144,6 +2149,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
#ifdef MANAGMENT_EXTERNAL_KEY
if (options->management_flags & MF_EXTERNAL_KEY)
msg(M_USAGE, "Parameter --management-external-key cannot be used when --pkcs11-provider is also specified.");
+ if (options->management_flags & MF_EXTERNAL_CERT)
+ msg(M_USAGE, "Parameter --management-external-cert cannot be used when --pkcs11-provider is also specified.");
#endif
if (options->pkcs12_file)
msg(M_USAGE, "Parameter --pkcs12 cannot be used when --pkcs11-provider is also specified.");
@@ -2175,6 +2182,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
#ifdef MANAGMENT_EXTERNAL_KEY
if (options->management_flags & MF_EXTERNAL_KEY)
msg(M_USAGE, "Parameter --management-external-key cannot be used when --cryptoapicert is also specified.");
+ if (options->management_flags & MF_EXTERNAL_CERT)
+ msg(M_USAGE, "Parameter --management-external-cert cannot be used when --cryptoapicert is also specified.");
#endif
}
else
@@ -2193,6 +2202,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
#ifdef MANAGMENT_EXTERNAL_KEY
if (options->management_flags & MF_EXTERNAL_KEY)
msg(M_USAGE, "Parameter --external-management-key cannot be used when --pkcs12 is also specified.");
+ if (options->management_flags & MF_EXTERNAL_CERT)
+ msg(M_USAGE, "Parameter --external-management-cert cannot be used when --pkcs12 is also specified.");
#endif
#endif
}
@@ -2234,6 +2245,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
}
else
{
+#ifdef MANAGMENT_EXTERNAL_KEY
+ if (!(options->management_flags & MF_EXTERNAL_CERT))
+#endif
notnull (options->cert_file, "certificate file (--cert) or PKCS#12 file (--pkcs12)");
#ifdef MANAGMENT_EXTERNAL_KEY
if (!(options->management_flags & MF_EXTERNAL_KEY))
@@ -4232,6 +4246,11 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_GENERAL);
options->management_flags |= MF_EXTERNAL_KEY;
}
+ else if (streq (p[0], "management-external-cert"))
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->management_flags |= MF_EXTERNAL_CERT;
+ }
#endif
#ifdef MANAGEMENT_DEF_AUTH
else if (streq (p[0], "management-client-auth"))
diff --git a/main/openvpn/src/openvpn/ssl.c b/main/openvpn/src/openvpn/ssl.c
index 80293efd..59bb2a12 100644
--- a/main/openvpn/src/openvpn/ssl.c
+++ b/main/openvpn/src/openvpn/ssl.c
@@ -264,14 +264,16 @@ tls_get_cipher_name_pair (const char * cipher_name, size_t len) {
return NULL;
}
-/**
- * Max number of bytes we will add for data structures common to both data and
- * control channel packets (1 byte opcode + 3 bytes peer-id).
+/*
+ * Max number of bytes we will add
+ * for data structures common to both
+ * data and control channel packets.
+ * (opcode only).
*/
void
tls_adjust_frame_parameters(struct frame *frame)
{
- frame_add_to_extra_frame (frame, 1 + 3); /* space for opcode + peer-id */
+ frame_add_to_extra_frame (frame, 1); /* space for opcode */
}
/*
@@ -518,10 +520,18 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
}
#endif
#ifdef MANAGMENT_EXTERNAL_KEY
- else if ((options->management_flags & MF_EXTERNAL_KEY) && options->cert_file)
- {
- tls_ctx_use_external_private_key(new_ctx, options->cert_file,
- options->cert_file_inline);
+ else if ((options->management_flags & MF_EXTERNAL_KEY) &&
+ (options->cert_file || options->management_flags & MF_EXTERNAL_CERT))
+ {
+ if (options->cert_file) {
+ tls_ctx_use_external_private_key(new_ctx, options->cert_file,
+ options->cert_file_inline);
+ } else {
+ char *external_certificate = management_query_cert(management);
+ tls_ctx_use_external_private_key(new_ctx, INLINE_FILE_TAG,
+ external_certificate);
+ free(external_certificate);
+ }
}
#endif
else