Different VPN servers may use different tls-auth/crypt keys.
For this reason it is convenient to make tls-auth/crypt
per-connection-block options so that the user is allowed to
specify one key per remote.
If no tls-auth/crypt option is specified in a given connection
block, the global settings, if any, are used.
Trac: #720
Cc: Steffan Karger <steffan@karger.me>
Signed-off-by: Antonio Quartulli <a@unstable.cc>
Acked-by: Steffan Karger <steffan.karger@fox-it.com>
Message-Id: <20180707090421.25953-2-a@unstable.cc>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg17226.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
... | ... |
@@ -361,6 +361,7 @@ block: |
361 | 361 |
.B fragment, |
362 | 362 |
.B http\-proxy, |
363 | 363 |
.B http\-proxy\-option, |
364 |
+.B key\-direction, |
|
364 | 365 |
.B link\-mtu, |
365 | 366 |
.B local, |
366 | 367 |
.B lport, |
... | ... |
@@ -372,6 +373,8 @@ block: |
372 | 372 |
.B remote, |
373 | 373 |
.B rport, |
374 | 374 |
.B socks\-proxy, |
375 |
+.B tls\-auth, |
|
376 |
+.B tls\-crypt, |
|
375 | 377 |
.B tun\-mtu and |
376 | 378 |
.B tun\-mtu\-extra. |
377 | 379 |
|
... | ... |
@@ -2508,7 +2508,7 @@ do_init_tls_wrap_key(struct context *c) |
2508 | 2508 |
const struct options *options = &c->options; |
2509 | 2509 |
|
2510 | 2510 |
/* TLS handshake authentication (--tls-auth) */ |
2511 |
- if (options->tls_auth_file) |
|
2511 |
+ if (options->ce.tls_auth_file) |
|
2512 | 2512 |
{ |
2513 | 2513 |
/* Initialize key_type for tls-auth with auth only */ |
2514 | 2514 |
CLEAR(c->c1.ks.tls_auth_key_type); |
... | ... |
@@ -2526,18 +2526,18 @@ do_init_tls_wrap_key(struct context *c) |
2526 | 2526 |
|
2527 | 2527 |
crypto_read_openvpn_key(&c->c1.ks.tls_auth_key_type, |
2528 | 2528 |
&c->c1.ks.tls_wrap_key, |
2529 |
- options->tls_auth_file, |
|
2530 |
- options->tls_auth_file_inline, |
|
2531 |
- options->key_direction, |
|
2529 |
+ options->ce.tls_auth_file, |
|
2530 |
+ options->ce.tls_auth_file_inline, |
|
2531 |
+ options->ce.key_direction, |
|
2532 | 2532 |
"Control Channel Authentication", "tls-auth"); |
2533 | 2533 |
} |
2534 | 2534 |
|
2535 | 2535 |
/* TLS handshake encryption+authentication (--tls-crypt) */ |
2536 |
- if (options->tls_crypt_file) |
|
2536 |
+ if (options->ce.tls_crypt_file) |
|
2537 | 2537 |
{ |
2538 | 2538 |
tls_crypt_init_key(&c->c1.ks.tls_wrap_key, |
2539 |
- options->tls_crypt_file, |
|
2540 |
- options->tls_crypt_inline, options->tls_server); |
|
2539 |
+ options->ce.tls_crypt_file, |
|
2540 |
+ options->ce.tls_crypt_inline, options->tls_server); |
|
2541 | 2541 |
} |
2542 | 2542 |
} |
2543 | 2543 |
|
... | ... |
@@ -2807,7 +2807,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags) |
2807 | 2807 |
#endif |
2808 | 2808 |
|
2809 | 2809 |
/* TLS handshake authentication (--tls-auth) */ |
2810 |
- if (options->tls_auth_file) |
|
2810 |
+ if (options->ce.tls_auth_file) |
|
2811 | 2811 |
{ |
2812 | 2812 |
to.tls_wrap.mode = TLS_WRAP_AUTH; |
2813 | 2813 |
to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key; |
... | ... |
@@ -2818,7 +2818,7 @@ do_init_crypto_tls(struct context *c, const unsigned int flags) |
2818 | 2818 |
} |
2819 | 2819 |
|
2820 | 2820 |
/* TLS handshake encryption (--tls-crypt) */ |
2821 |
- if (options->tls_crypt_file) |
|
2821 |
+ if (options->ce.tls_crypt_file) |
|
2822 | 2822 |
{ |
2823 | 2823 |
to.tls_wrap.mode = TLS_WRAP_CRYPT; |
2824 | 2824 |
to.tls_wrap.opt.key_ctx_bi = c->c1.ks.tls_wrap_key; |
... | ... |
@@ -1507,6 +1507,11 @@ show_connection_entry(const struct connection_entry *o) |
1507 | 1507 |
#ifdef ENABLE_OCC |
1508 | 1508 |
SHOW_INT(explicit_exit_notification); |
1509 | 1509 |
#endif |
1510 |
+ |
|
1511 |
+ SHOW_STR(tls_auth_file); |
|
1512 |
+ SHOW_PARM(key_direction, keydirection2ascii(o->key_direction, false, true), |
|
1513 |
+ "%s"); |
|
1514 |
+ SHOW_STR(tls_crypt_file); |
|
1510 | 1515 |
} |
1511 | 1516 |
|
1512 | 1517 |
|
... | ... |
@@ -1787,9 +1792,6 @@ show_settings(const struct options *o) |
1787 | 1787 |
SHOW_BOOL(push_peer_info); |
1788 | 1788 |
SHOW_BOOL(tls_exit); |
1789 | 1789 |
|
1790 |
- SHOW_STR(tls_auth_file); |
|
1791 |
- SHOW_STR(tls_crypt_file); |
|
1792 |
- |
|
1793 | 1790 |
#ifdef ENABLE_PKCS11 |
1794 | 1791 |
{ |
1795 | 1792 |
int i; |
... | ... |
@@ -2724,7 +2726,7 @@ options_postprocess_verify_ce(const struct options *options, const struct connec |
2724 | 2724 |
notnull(options->priv_key_file, "private key file (--key) or PKCS#12 file (--pkcs12)"); |
2725 | 2725 |
} |
2726 | 2726 |
} |
2727 |
- if (options->tls_auth_file && options->tls_crypt_file) |
|
2727 |
+ if (ce->tls_auth_file && ce->tls_crypt_file) |
|
2728 | 2728 |
{ |
2729 | 2729 |
msg(M_USAGE, "--tls-auth and --tls-crypt are mutually exclusive"); |
2730 | 2730 |
} |
... | ... |
@@ -2870,6 +2872,49 @@ options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce) |
2870 | 2870 |
} |
2871 | 2871 |
} |
2872 | 2872 |
|
2873 |
+ /* |
|
2874 |
+ * Set per-connection block tls-auth/crypt fields if undefined. |
|
2875 |
+ * |
|
2876 |
+ * At the end only one of the two will be really set because the parser |
|
2877 |
+ * logic prevents configurations where both are set. |
|
2878 |
+ */ |
|
2879 |
+ if (!ce->tls_auth_file && !ce->tls_crypt_file) |
|
2880 |
+ { |
|
2881 |
+ ce->tls_auth_file = o->tls_auth_file; |
|
2882 |
+ ce->tls_auth_file_inline = o->tls_auth_file_inline; |
|
2883 |
+ ce->key_direction = o->key_direction; |
|
2884 |
+ |
|
2885 |
+ ce->tls_crypt_file = o->tls_crypt_file; |
|
2886 |
+ ce->tls_crypt_inline = o->tls_crypt_inline; |
|
2887 |
+ } |
|
2888 |
+ |
|
2889 |
+ /* pre-cache tls-auth/crypt key file if persist-key was specified and keys |
|
2890 |
+ * were not already embedded in the config file |
|
2891 |
+ */ |
|
2892 |
+ if (o->persist_key) |
|
2893 |
+ { |
|
2894 |
+ if (ce->tls_auth_file && !ce->tls_auth_file_inline) |
|
2895 |
+ { |
|
2896 |
+ struct buffer in = buffer_read_from_file(o->tls_auth_file, &o->gc); |
|
2897 |
+ if (!buf_valid(&in)) |
|
2898 |
+ msg(M_FATAL, "Cannot pre-load tls-auth keyfile (%s)", |
|
2899 |
+ o->tls_auth_file); |
|
2900 |
+ |
|
2901 |
+ ce->tls_auth_file = INLINE_FILE_TAG; |
|
2902 |
+ ce->tls_auth_file_inline = (char *)in.data; |
|
2903 |
+ } |
|
2904 |
+ |
|
2905 |
+ if (ce->tls_crypt_file && !ce->tls_crypt_inline) |
|
2906 |
+ { |
|
2907 |
+ struct buffer in = buffer_read_from_file(o->tls_crypt_file, &o->gc); |
|
2908 |
+ if (!buf_valid(&in)) |
|
2909 |
+ msg(M_FATAL, "Cannot pre-load tls-crypt keyfile (%s)", |
|
2910 |
+ o->tls_auth_file); |
|
2911 |
+ |
|
2912 |
+ ce->tls_crypt_file = INLINE_FILE_TAG; |
|
2913 |
+ ce->tls_crypt_inline = (char *)in.data; |
|
2914 |
+ } |
|
2915 |
+ } |
|
2873 | 2916 |
} |
2874 | 2917 |
|
2875 | 2918 |
#ifdef _WIN32 |
... | ... |
@@ -3020,32 +3065,6 @@ options_postprocess_mutate(struct options *o) |
3020 | 3020 |
options_postprocess_mutate_ce(o, o->connection_list->array[i]); |
3021 | 3021 |
} |
3022 | 3022 |
|
3023 |
- /* pre-cache tls-auth/crypt key file if persist-key was specified */ |
|
3024 |
- if (o->persist_key) |
|
3025 |
- { |
|
3026 |
- if (o->tls_auth_file && !o->tls_auth_file_inline) |
|
3027 |
- { |
|
3028 |
- struct buffer in = buffer_read_from_file(o->tls_auth_file, &o->gc); |
|
3029 |
- if (!buf_valid(&in)) |
|
3030 |
- msg(M_FATAL, "Cannot pre-load tls-auth keyfile (%s)", |
|
3031 |
- o->tls_auth_file); |
|
3032 |
- |
|
3033 |
- o->tls_auth_file = INLINE_FILE_TAG; |
|
3034 |
- o->tls_auth_file_inline = (char *)in.data; |
|
3035 |
- } |
|
3036 |
- |
|
3037 |
- if (o->tls_crypt_file && !o->tls_crypt_inline) |
|
3038 |
- { |
|
3039 |
- struct buffer in = buffer_read_from_file(o->tls_crypt_file, &o->gc); |
|
3040 |
- if (!buf_valid(&in)) |
|
3041 |
- msg(M_FATAL, "Cannot pre-load tls-crypt keyfile (%s)", |
|
3042 |
- o->tls_auth_file); |
|
3043 |
- |
|
3044 |
- o->tls_crypt_file = INLINE_FILE_TAG; |
|
3045 |
- o->tls_crypt_inline = (char *)in.data; |
|
3046 |
- } |
|
3047 |
- } |
|
3048 |
- |
|
3049 | 3023 |
if (o->tls_server) |
3050 | 3024 |
{ |
3051 | 3025 |
/* Check that DH file is specified, or explicitly disabled */ |
... | ... |
@@ -3312,12 +3331,22 @@ options_postprocess_filechecks(struct options *options) |
3312 | 3312 |
options->crl_file, R_OK, "--crl-verify"); |
3313 | 3313 |
} |
3314 | 3314 |
|
3315 |
- errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, |
|
3316 |
- options->tls_auth_file, R_OK, "--tls-auth"); |
|
3317 |
- errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, |
|
3318 |
- options->tls_crypt_file, R_OK, "--tls-crypt"); |
|
3315 |
+ ASSERT(options->connection_list); |
|
3316 |
+ for (int i = 0; i < options->connection_list->len; ++i) |
|
3317 |
+ { |
|
3318 |
+ struct connection_entry *ce = options->connection_list->array[i]; |
|
3319 |
+ |
|
3320 |
+ errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, |
|
3321 |
+ ce->tls_auth_file, R_OK, "--tls-auth"); |
|
3322 |
+ |
|
3323 |
+ errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, |
|
3324 |
+ ce->tls_crypt_file, R_OK, "--tls-crypt"); |
|
3325 |
+ |
|
3326 |
+ } |
|
3327 |
+ |
|
3319 | 3328 |
errs |= check_file_access(CHKACC_FILE|CHKACC_INLINE|CHKACC_PRIVATE, |
3320 | 3329 |
options->shared_secret_file, R_OK, "--secret"); |
3330 |
+ |
|
3321 | 3331 |
errs |= check_file_access(CHKACC_DIRPATH|CHKACC_FILEXSTWR, |
3322 | 3332 |
options->packet_id_file, R_OK|W_OK, "--replay-persist"); |
3323 | 3333 |
|
... | ... |
@@ -3674,7 +3703,7 @@ options_string(const struct options *o, |
3674 | 3674 |
{ |
3675 | 3675 |
if (TLS_CLIENT || TLS_SERVER) |
3676 | 3676 |
{ |
3677 |
- if (o->tls_auth_file) |
|
3677 |
+ if (o->ce.tls_auth_file) |
|
3678 | 3678 |
{ |
3679 | 3679 |
buf_printf(&out, ",tls-auth"); |
3680 | 3680 |
} |
... | ... |
@@ -7447,10 +7476,19 @@ add_option(struct options *options, |
7447 | 7447 |
{ |
7448 | 7448 |
int key_direction; |
7449 | 7449 |
|
7450 |
+ VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION); |
|
7451 |
+ |
|
7450 | 7452 |
key_direction = ascii2keydirection(msglevel, p[1]); |
7451 | 7453 |
if (key_direction >= 0) |
7452 | 7454 |
{ |
7453 |
- options->key_direction = key_direction; |
|
7455 |
+ if (permission_mask & OPT_P_GENERAL) |
|
7456 |
+ { |
|
7457 |
+ options->key_direction = key_direction; |
|
7458 |
+ } |
|
7459 |
+ else if (permission_mask & OPT_P_CONNECTION) |
|
7460 |
+ { |
|
7461 |
+ options->ce.key_direction = key_direction; |
|
7462 |
+ } |
|
7454 | 7463 |
} |
7455 | 7464 |
else |
7456 | 7465 |
{ |
... | ... |
@@ -8019,35 +8057,66 @@ add_option(struct options *options, |
8019 | 8019 |
} |
8020 | 8020 |
else if (streq(p[0], "tls-auth") && p[1] && !p[3]) |
8021 | 8021 |
{ |
8022 |
- VERIFY_PERMISSION(OPT_P_GENERAL); |
|
8023 |
- if (streq(p[1], INLINE_FILE_TAG) && p[2]) |
|
8022 |
+ int key_direction = -1; |
|
8023 |
+ |
|
8024 |
+ VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION); |
|
8025 |
+ |
|
8026 |
+ if (permission_mask & OPT_P_GENERAL) |
|
8024 | 8027 |
{ |
8025 |
- options->tls_auth_file_inline = p[2]; |
|
8028 |
+ if (streq(p[1], INLINE_FILE_TAG) && p[2]) |
|
8029 |
+ { |
|
8030 |
+ options->tls_auth_file_inline = p[2]; |
|
8031 |
+ } |
|
8032 |
+ else if (p[2]) |
|
8033 |
+ { |
|
8034 |
+ key_direction = ascii2keydirection(msglevel, p[2]); |
|
8035 |
+ if (key_direction < 0) |
|
8036 |
+ { |
|
8037 |
+ goto err; |
|
8038 |
+ } |
|
8039 |
+ options->key_direction = key_direction; |
|
8040 |
+ } |
|
8041 |
+ options->tls_auth_file = p[1]; |
|
8026 | 8042 |
} |
8027 |
- else if (p[2]) |
|
8043 |
+ else if (permission_mask & OPT_P_CONNECTION) |
|
8028 | 8044 |
{ |
8029 |
- int key_direction; |
|
8030 |
- |
|
8031 |
- key_direction = ascii2keydirection(msglevel, p[2]); |
|
8032 |
- if (key_direction >= 0) |
|
8045 |
+ options->ce.key_direction = KEY_DIRECTION_BIDIRECTIONAL; |
|
8046 |
+ if (streq(p[1], INLINE_FILE_TAG) && p[2]) |
|
8033 | 8047 |
{ |
8034 |
- options->key_direction = key_direction; |
|
8048 |
+ options->ce.tls_auth_file_inline = p[2]; |
|
8035 | 8049 |
} |
8036 |
- else |
|
8050 |
+ else if (p[2]) |
|
8037 | 8051 |
{ |
8038 |
- goto err; |
|
8052 |
+ key_direction = ascii2keydirection(msglevel, p[2]); |
|
8053 |
+ if (key_direction < 0) |
|
8054 |
+ { |
|
8055 |
+ goto err; |
|
8056 |
+ } |
|
8057 |
+ options->ce.key_direction = key_direction; |
|
8039 | 8058 |
} |
8059 |
+ options->ce.tls_auth_file = p[1]; |
|
8040 | 8060 |
} |
8041 |
- options->tls_auth_file = p[1]; |
|
8042 | 8061 |
} |
8043 | 8062 |
else if (streq(p[0], "tls-crypt") && p[1] && !p[3]) |
8044 | 8063 |
{ |
8045 |
- VERIFY_PERMISSION(OPT_P_GENERAL); |
|
8046 |
- if (streq(p[1], INLINE_FILE_TAG) && p[2]) |
|
8064 |
+ VERIFY_PERMISSION(OPT_P_GENERAL|OPT_P_CONNECTION); |
|
8065 |
+ if (permission_mask & OPT_P_GENERAL) |
|
8047 | 8066 |
{ |
8048 |
- options->tls_crypt_inline = p[2]; |
|
8067 |
+ if (streq(p[1], INLINE_FILE_TAG) && p[2]) |
|
8068 |
+ { |
|
8069 |
+ options->tls_crypt_inline = p[2]; |
|
8070 |
+ } |
|
8071 |
+ options->tls_crypt_file = p[1]; |
|
8072 |
+ } |
|
8073 |
+ else if (permission_mask & OPT_P_CONNECTION) |
|
8074 |
+ { |
|
8075 |
+ if (streq(p[1], INLINE_FILE_TAG) && p[2]) |
|
8076 |
+ { |
|
8077 |
+ options->ce.tls_crypt_inline = p[2]; |
|
8078 |
+ } |
|
8079 |
+ options->ce.tls_crypt_file = p[1]; |
|
8080 |
+ |
|
8049 | 8081 |
} |
8050 |
- options->tls_crypt_file = p[1]; |
|
8051 | 8082 |
} |
8052 | 8083 |
else if (streq(p[0], "key-method") && p[1] && !p[2]) |
8053 | 8084 |
{ |
... | ... |
@@ -130,6 +130,15 @@ struct connection_entry |
130 | 130 |
#define CE_MAN_QUERY_REMOTE_MASK (0x07) |
131 | 131 |
#define CE_MAN_QUERY_REMOTE_SHIFT (2) |
132 | 132 |
unsigned int flags; |
133 |
+ |
|
134 |
+ /* Shared secret used for TLS control channel authentication */ |
|
135 |
+ const char *tls_auth_file; |
|
136 |
+ const char *tls_auth_file_inline; |
|
137 |
+ int key_direction; |
|
138 |
+ |
|
139 |
+ /* Shared secret used for TLS control channel authenticated encryption */ |
|
140 |
+ const char *tls_crypt_file; |
|
141 |
+ const char *tls_crypt_inline; |
|
133 | 142 |
}; |
134 | 143 |
|
135 | 144 |
struct remote_entry |