Browse code

In init_ssl, open the correct CRL path pre-chroot

When using the chroot option, the init_ssl function can be called before
entering the chroot or, when OpenVPN receives a SIGHUP, afterwards. This
commit ensures that OpenVPN tries to open the correct path for the CRL
file in either situation.

This commit does not address key and certificate files. For these, the
--persist-key option should be used.

Signed-off-by: Max Fillinger <maximilian.fillinger@foxcrypto.com>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <20210415091248.18149-1-maximilian.fillinger@foxcrypto.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg22117.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit 21a0b2494e7f4f1c6325b2972743158acad4f394)

Max Fillinger authored on 2021/04/15 18:12:48
Showing 6 changed files
... ...
@@ -2734,7 +2734,7 @@ do_init_crypto_tls_c1(struct context *c)
2734 2734
          * Initialize the OpenSSL library's global
2735 2735
          * SSL context.
2736 2736
          */
2737
-        init_ssl(options, &(c->c1.ks.ssl_ctx));
2737
+        init_ssl(options, &(c->c1.ks.ssl_ctx), c->c0 && c->c0->uid_gid_chroot_set);
2738 2738
         if (!tls_ctx_initialised(&c->c1.ks.ssl_ctx))
2739 2739
         {
2740 2740
 #if P2MP
... ...
@@ -787,3 +787,14 @@ get_num_elements(const char *string, char delimiter)
787 787
 
788 788
     return element_count;
789 789
 }
790
+
791
+struct buffer
792
+prepend_dir(const char *dir, const char *path, struct gc_arena *gc)
793
+{
794
+    size_t len = strlen(dir) + strlen(PATH_SEPARATOR_STR) + strlen(path) + 1;
795
+    struct buffer combined_path = alloc_buf_gc(len, gc);
796
+    buf_printf(&combined_path, "%s%s%s", dir, PATH_SEPARATOR_STR, path);
797
+    ASSERT(combined_path.len > 0);
798
+
799
+    return combined_path;
800
+}
... ...
@@ -197,4 +197,10 @@ void output_peer_info_env(struct env_set *es, const char *peer_info);
197 197
 int
198 198
 get_num_elements(const char *string, char delimiter);
199 199
 
200
+/**
201
+ * Prepend a directory to a path.
202
+ */
203
+struct buffer
204
+prepend_dir(const char *dir, const char *path, struct gc_arena *gc);
205
+
200 206
 #endif /* ifndef MISC_H */
... ...
@@ -3328,14 +3328,8 @@ check_file_access_chroot(const char *chroot, const int type, const char *file, c
3328 3328
     {
3329 3329
         struct gc_arena gc = gc_new();
3330 3330
         struct buffer chroot_file;
3331
-        int len = 0;
3332
-
3333
-        /* Build up a new full path including chroot directory */
3334
-        len = strlen(chroot) + strlen(PATH_SEPARATOR_STR) + strlen(file) + 1;
3335
-        chroot_file = alloc_buf_gc(len, &gc);
3336
-        buf_printf(&chroot_file, "%s%s%s", chroot, PATH_SEPARATOR_STR, file);
3337
-        ASSERT(chroot_file.len > 0);
3338 3331
 
3332
+        chroot_file = prepend_dir(chroot, file, &gc);
3339 3333
         ret = check_file_access(type, BSTR(&chroot_file), mode, opt);
3340 3334
         gc_free(&gc);
3341 3335
     }
... ...
@@ -583,7 +583,7 @@ tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file,
583 583
  * All files are in PEM format.
584 584
  */
585 585
 void
586
-init_ssl(const struct options *options, struct tls_root_ctx *new_ctx)
586
+init_ssl(const struct options *options, struct tls_root_ctx *new_ctx, bool in_chroot)
587 587
 {
588 588
     ASSERT(NULL != new_ctx);
589 589
 
... ...
@@ -701,7 +701,24 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx)
701 701
     /* Read CRL */
702 702
     if (options->crl_file && !(options->ssl_flags & SSLF_CRL_VERIFY_DIR))
703 703
     {
704
-        tls_ctx_reload_crl(new_ctx, options->crl_file, options->crl_file_inline);
704
+        /* If we're running with the chroot option, we may run init_ssl() before
705
+         * and after chroot-ing. We can use the crl_file path as-is if we're
706
+         * not going to chroot, or if we already are inside the chroot.
707
+         *
708
+         * If we're going to chroot later, we need to prefix the path of the
709
+         * chroot directory to crl_file.
710
+         */
711
+        if (!options->chroot_dir || in_chroot || options->crl_file_inline)
712
+        {
713
+            tls_ctx_reload_crl(new_ctx, options->crl_file, options->crl_file_inline);
714
+        }
715
+        else
716
+        {
717
+            struct gc_arena gc = gc_new();
718
+            struct buffer crl_file_buf = prepend_dir(options->chroot_dir, options->crl_file, &gc);
719
+            tls_ctx_reload_crl(new_ctx, BSTR(&crl_file_buf), options->crl_file_inline);
720
+            gc_free(&gc);
721
+        }
705 722
     }
706 723
 
707 724
     /* Once keys and cert are loaded, load ECDH parameters */
... ...
@@ -154,7 +154,7 @@ void free_ssl_lib(void);
154 154
  * Build master SSL context object that serves for the whole of OpenVPN
155 155
  * instantiation
156 156
  */
157
-void init_ssl(const struct options *options, struct tls_root_ctx *ctx);
157
+void init_ssl(const struct options *options, struct tls_root_ctx *ctx, bool in_chroot);
158 158
 
159 159
 /** @addtogroup control_processor
160 160
  *  @{ */