summaryrefslogtreecommitdiff
path: root/src/openvpn/ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/ssl.c')
-rw-r--r--src/openvpn/ssl.c139
1 files changed, 98 insertions, 41 deletions
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index cff4052..15cd94a 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -18,10 +18,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program (see the file COPYING included with this
- * distribution); if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
@@ -269,10 +268,12 @@ static void
key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key, size_t key_len);
const tls_cipher_name_pair *
-tls_get_cipher_name_pair(const char *cipher_name, size_t len) {
+tls_get_cipher_name_pair(const char *cipher_name, size_t len)
+{
const tls_cipher_name_pair *pair = tls_cipher_name_translation_table;
- while (pair->openssl_name != NULL) {
+ while (pair->openssl_name != NULL)
+ {
if ((strlen(pair->openssl_name) == len && 0 == memcmp(cipher_name, pair->openssl_name, len))
|| (strlen(pair->iana_name) == len && 0 == memcmp(cipher_name, pair->iana_name, len)))
{
@@ -450,6 +451,8 @@ ssl_set_auth_nocache(void)
{
passbuf.nocache = true;
auth_user_pass.nocache = true;
+ /* wait for push-reply, because auth-token may invert nocache */
+ auth_user_pass.wait_for_push = true;
}
/*
@@ -458,6 +461,14 @@ ssl_set_auth_nocache(void)
void
ssl_set_auth_token(const char *token)
{
+ if (auth_user_pass.nocache)
+ {
+ msg(M_INFO,
+ "auth-token received, disabling auth-nocache for the "
+ "authentication token");
+ auth_user_pass.nocache = false;
+ }
+
set_auth_token(&auth_user_pass, token);
}
@@ -569,12 +580,12 @@ tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file,
* Note: Windows does not support tv_nsec.
*/
if ((ssl_ctx->crl_last_size == crl_stat.st_size)
- && (ssl_ctx->crl_last_mtime.tv_sec == crl_stat.st_mtime))
+ && (ssl_ctx->crl_last_mtime == crl_stat.st_mtime))
{
return;
}
- ssl_ctx->crl_last_mtime.tv_sec = crl_stat.st_mtime;
+ ssl_ctx->crl_last_mtime = crl_stat.st_mtime;
ssl_ctx->crl_last_size = crl_stat.st_size;
backend_tls_ctx_reload_crl(ssl_ctx, crl_file, crl_file_inline);
}
@@ -830,14 +841,7 @@ print_key_id(struct tls_multi *multi, struct gc_arena *gc)
return BSTR(&out);
}
-/*
- * Given a key_method, return true if op
- * represents the required form of hard_reset.
- *
- * If key_method = 0, return true if any
- * form of hard reset is used.
- */
-static bool
+bool
is_hard_reset(int op, int key_method)
{
if (!key_method || key_method == 1)
@@ -1068,7 +1072,9 @@ tls_session_init(struct tls_multi *multi, struct tls_session *session)
/* Randomize session # if it is 0 */
while (!session_id_defined(&session->session_id))
+ {
session_id_random(&session->session_id);
+ }
/* Are we a TLS server or client? */
ASSERT(session->opt->key_method >= 1);
@@ -1130,7 +1136,9 @@ tls_session_free(struct tls_session *session, bool clear)
free_buf(&session->tls_wrap.work);
for (i = 0; i < KS_SIZE; ++i)
+ {
key_state_free(&session->key[i], false);
+ }
if (session->common_name)
{
@@ -1187,7 +1195,8 @@ reset_session(struct tls_multi *multi, struct tls_session *session)
* called again.
*/
static inline void
-compute_earliest_wakeup(interval_t *earliest, interval_t seconds_from_now) {
+compute_earliest_wakeup(interval_t *earliest, interval_t seconds_from_now)
+{
if (seconds_from_now < *earliest)
{
*earliest = seconds_from_now;
@@ -1357,7 +1366,9 @@ tls_multi_free(struct tls_multi *multi, bool clear)
free(multi->remote_ciphername);
for (i = 0; i < TM_SIZE; ++i)
+ {
tls_session_free(&multi->session[i], false);
+ }
if (clear)
{
@@ -1605,8 +1616,8 @@ tls1_P_hash(const md_kt_t *md_kt,
{
struct gc_arena gc = gc_new();
int chunk;
- hmac_ctx_t ctx;
- hmac_ctx_t ctx_tmp;
+ hmac_ctx_t *ctx;
+ hmac_ctx_t *ctx_tmp;
uint8_t A1[MAX_HMAC_KEY_LENGTH];
unsigned int A1_len;
@@ -1615,8 +1626,8 @@ tls1_P_hash(const md_kt_t *md_kt,
const uint8_t *out_orig = out;
#endif
- CLEAR(ctx);
- CLEAR(ctx_tmp);
+ ctx = hmac_ctx_new();
+ ctx_tmp = hmac_ctx_new();
dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash sec: %s", format_hex(sec, sec_len, 0, &gc));
dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash seed: %s", format_hex(seed, seed_len, 0, &gc));
@@ -1624,36 +1635,38 @@ tls1_P_hash(const md_kt_t *md_kt,
chunk = md_kt_size(md_kt);
A1_len = md_kt_size(md_kt);
- hmac_ctx_init(&ctx, sec, sec_len, md_kt);
- hmac_ctx_init(&ctx_tmp, sec, sec_len, md_kt);
+ hmac_ctx_init(ctx, sec, sec_len, md_kt);
+ hmac_ctx_init(ctx_tmp, sec, sec_len, md_kt);
- hmac_ctx_update(&ctx,seed,seed_len);
- hmac_ctx_final(&ctx, A1);
+ hmac_ctx_update(ctx,seed,seed_len);
+ hmac_ctx_final(ctx, A1);
for (;; )
{
- hmac_ctx_reset(&ctx);
- hmac_ctx_reset(&ctx_tmp);
- hmac_ctx_update(&ctx,A1,A1_len);
- hmac_ctx_update(&ctx_tmp,A1,A1_len);
- hmac_ctx_update(&ctx,seed,seed_len);
+ hmac_ctx_reset(ctx);
+ hmac_ctx_reset(ctx_tmp);
+ hmac_ctx_update(ctx,A1,A1_len);
+ hmac_ctx_update(ctx_tmp,A1,A1_len);
+ hmac_ctx_update(ctx,seed,seed_len);
if (olen > chunk)
{
- hmac_ctx_final(&ctx, out);
+ hmac_ctx_final(ctx, out);
out += chunk;
olen -= chunk;
- hmac_ctx_final(&ctx_tmp, A1); /* calc the next A1 value */
+ hmac_ctx_final(ctx_tmp, A1); /* calc the next A1 value */
}
else /* last one */
{
- hmac_ctx_final(&ctx, A1);
+ hmac_ctx_final(ctx, A1);
memcpy(out,A1,olen);
break;
}
}
- hmac_ctx_cleanup(&ctx);
- hmac_ctx_cleanup(&ctx_tmp);
+ hmac_ctx_cleanup(ctx);
+ hmac_ctx_free(ctx);
+ hmac_ctx_cleanup(ctx_tmp);
+ hmac_ctx_free(ctx_tmp);
secure_memzero(A1, sizeof(A1));
dmsg(D_SHOW_KEY_SOURCE, "tls1_P_hash out: %s", format_hex(out_orig, olen_orig, 0, &gc));
@@ -1705,7 +1718,9 @@ tls1_PRF(const uint8_t *label,
tls1_P_hash(sha1,S2,len,label,label_len,out2,olen);
for (i = 0; i<olen; i++)
+ {
out1[i] ^= out2[i];
+ }
secure_memzero(out2, olen);
@@ -1855,7 +1870,8 @@ exit:
}
static void
-key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key, size_t key_len) {
+key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key, size_t key_len)
+{
const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
/* Only use implicit IV in AEAD cipher mode, where HMAC key is not used */
@@ -1954,6 +1970,12 @@ tls_session_update_crypto_params(struct tls_session *session,
return false;
}
+ if (strcmp(options->ciphername, session->opt->config_ciphername))
+ {
+ msg(D_HANDSHAKE, "Data Channel: using negotiated cipher '%s'",
+ options->ciphername);
+ }
+
init_key_type(&session->opt->key_type, options->ciphername,
options->authname, options->keysize, true, true);
@@ -2371,7 +2393,21 @@ key_method_2_write(struct buffer *buf, struct tls_session *session)
{
goto error;
}
- purge_user_pass(&auth_user_pass, false);
+ /* if auth-nocache was specified, the auth_user_pass object reaches
+ * a "complete" state only after having received the push-reply
+ * message.
+ * This is the case because auth-token statement in a push-reply would
+ * invert its nocache.
+ *
+ * For this reason, skip the purge operation here if no push-reply
+ * message has been received yet.
+ *
+ * This normally happens upon first negotiation only.
+ */
+ if (!auth_user_pass.wait_for_push)
+ {
+ purge_user_pass(&auth_user_pass, false);
+ }
}
else
{
@@ -2487,7 +2523,7 @@ key_method_2_read(struct buffer *buf, struct tls_multi *multi, struct tls_sessio
struct gc_arena gc = gc_new();
char *options;
- struct user_pass *up;
+ struct user_pass *up = NULL;
/* allocate temporary objects */
ALLOC_ARRAY_CLEAR_GC(options, char, TLS_OPTIONS_LEN, &gc);
@@ -2649,6 +2685,10 @@ key_method_2_read(struct buffer *buf, struct tls_multi *multi, struct tls_sessio
error:
secure_memzero(ks->key_src, sizeof(*ks->key_src));
+ if (up)
+ {
+ secure_memzero(up, sizeof(*up));
+ }
buf_clear(buf);
gc_free(&gc);
return false;
@@ -2810,6 +2850,9 @@ tls_process(struct tls_multi *multi,
session->opt->crl_file, session->opt->crl_file_inline);
}
+ /* New connection, remove any old X509 env variables */
+ tls_x509_clear_env(session->opt->es);
+
dmsg(D_TLS_DEBUG_MED, "STATE S_START");
}
@@ -3708,7 +3751,12 @@ tls_pre_decrypt(struct tls_multi *multi,
/* Save incoming ciphertext packet to reliable buffer */
struct buffer *in = reliable_get_buf(ks->rec_reliable);
ASSERT(in);
- ASSERT(buf_copy(in, buf));
+ if(!buf_copy(in, buf))
+ {
+ msg(D_MULTI_DROPPED,
+ "Incoming control channel packet too big, dropping.");
+ goto error;
+ }
reliable_mark_active_incoming(ks->rec_reliable, in, id, op);
}
@@ -4058,7 +4106,8 @@ tls_peer_info_ncp_ver(const char *peer_info)
}
bool
-tls_check_ncp_cipher_list(const char *list) {
+tls_check_ncp_cipher_list(const char *list)
+{
bool unsupported_cipher_found = false;
ASSERT(list);
@@ -4201,8 +4250,16 @@ done:
return BSTR(&out);
}
+void
+delayed_auth_pass_purge(void)
+{
+ auth_user_pass.wait_for_push = false;
+ purge_user_pass(&auth_user_pass, false);
+}
+
#else /* if defined(ENABLE_CRYPTO) */
static void
-dummy(void) {
+dummy(void)
+{
}
#endif /* ENABLE_CRYPTO */