Browse code

make tls-auth and tls-crypt per-connection-block options

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>

Antonio Quartulli authored on 2018/07/07 18:04:21
Showing 4 changed files
... ...
@@ -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