Browse code

Implement inlining of crl files

While crl files can change regulary and it is usually not a good idea to
statically include them into config files, handling multiple files and
updating files on mobile devices is tiresome/problematic. Inlining a static
version of the crl file is better in these use cases than to use no crl at
all.

OpenVPN 3 already supports inlining crl-verify, so <crl-verify> is already
used in config files.

V2: Fixed PolarSSL and made formatting respect the 80 column limit
V3: Accidentally reverted one change too much in V2
Acked-by: Steffan Karger <steffan.karger@fox-it.com>
Message-Id: <1457293149-10526-1-git-send-email-arne@rfc2549.org>
URL: http://article.gmane.org/gmane.network.openvpn.devel/11337

Signed-off-by: Gert Doering <gert@greenie.muc.de>

Arne Schwabe authored on 2016/03/07 04:39:09
Showing 9 changed files
... ...
@@ -6490,7 +6490,8 @@ X509_1_C=KG
6490 6490
 .\"*********************************************************
6491 6491
 .SH INLINE FILE SUPPORT
6492 6492
 OpenVPN allows including files in the main configuration for the
6493
-.B \-\-ca, \-\-cert, \-\-dh, \-\-extra\-certs, \-\-key, \-\-pkcs12, \-\-secret
6493
+.B \-\-ca, \-\-cert, \-\-dh, \-\-extra\-certs, \-\-key, \-\-pkcs12, \-\-secret,
6494
+.B \-\-crl-verify
6494 6495
 and
6495 6496
 .B \-\-tls\-auth
6496 6497
 options.
... ...
@@ -2323,6 +2323,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
2323 2323
   to.verify_x509_type = (options->verify_x509_type & 0xff);
2324 2324
   to.verify_x509_name = options->verify_x509_name;
2325 2325
   to.crl_file = options->crl_file;
2326
+  to.crl_file_inline = options->crl_file_inline;
2326 2327
   to.ssl_flags = options->ssl_flags;
2327 2328
   to.ns_cert_type = options->ns_cert_type;
2328 2329
   memmove (to.remote_cert_ku, options->remote_cert_ku, sizeof (to.remote_cert_ku));
... ...
@@ -2747,8 +2747,8 @@ options_postprocess_filechecks (struct options *options)
2747 2747
     errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->crl_file, R_OK|X_OK,
2748 2748
                                "--crl-verify directory");
2749 2749
   else
2750
-    errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->crl_file, R_OK,
2751
-                               "--crl-verify");
2750
+    errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE|CHKACC_INLINE,
2751
+                                      options->crl_file, R_OK, "--crl-verify");
2752 2752
 
2753 2753
   errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->tls_auth_file, R_OK,
2754 2754
                              "--tls-auth");
... ...
@@ -6783,12 +6783,17 @@ add_option (struct options *options,
6783 6783
       VERIFY_PERMISSION (OPT_P_GENERAL);
6784 6784
       options->cipher_list = p[1];
6785 6785
     }
6786
-  else if (streq (p[0], "crl-verify") && p[1] && ((p[2] && streq(p[2], "dir")) || !p[2]) && !p[3])
6786
+  else if (streq (p[0], "crl-verify") && p[1] && ((p[2] && streq(p[2], "dir"))
6787
+		  || (p[2] && streq (p[1], INLINE_FILE_TAG) ) || !p[2]) && !p[3])
6787 6788
     {
6788 6789
       VERIFY_PERMISSION (OPT_P_GENERAL);
6789 6790
       if (p[2] && streq(p[2], "dir"))
6790 6791
 	options->ssl_flags |= SSLF_CRL_VERIFY_DIR;
6791 6792
       options->crl_file = p[1];
6793
+      if (streq (p[1], INLINE_FILE_TAG) && p[2])
6794
+	{
6795
+	  options->crl_file_inline = p[2];
6796
+	}
6792 6797
     }
6793 6798
   else if (streq (p[0], "tls-verify") && p[1])
6794 6799
     {
... ...
@@ -511,6 +511,7 @@ struct options
511 511
   const char *ca_file_inline;
512 512
   const char *cert_file_inline;
513 513
   const char *extra_certs_file_inline;
514
+  const char *crl_file_inline;
514 515
   char *priv_key_file_inline;
515 516
   const char *dh_file_inline;
516 517
   const char *pkcs12_file_inline; /* contains the base64 encoding of pkcs12 file */
... ...
@@ -247,6 +247,7 @@ struct tls_options
247 247
   int verify_x509_type;
248 248
   const char *verify_x509_name;
249 249
   const char *crl_file;
250
+  const char *crl_file_inline;
250 251
   int ns_cert_type;
251 252
   unsigned remote_cert_ku[MAX_PARMS];
252 253
   const char *remote_cert_eku;
... ...
@@ -690,7 +690,7 @@ verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_dep
690 690
       }
691 691
       else
692 692
       {
693
-	if (SUCCESS != x509_verify_crl(opt->crl_file, cert, subject))
693
+	if (SUCCESS != x509_verify_crl(opt->crl_file, opt->crl_file_inline, cert, subject))
694 694
 	  goto cleanup;
695 695
       }
696 696
     }
... ...
@@ -248,13 +248,14 @@ result_t x509_write_pem(FILE *peercert_file, openvpn_x509_cert_t *peercert);
248 248
  *
249 249
  * @param crl_file	File name of the CRL file
250 250
  * @param cert		Certificate to verify
251
+ * @param crl_inline	Contents of the crl file if it is inlined
251 252
  * @param subject	Subject of the given certificate
252 253
  *
253 254
  * @return 		\c SUCCESS if the CRL was not signed by the issuer of the
254 255
  * 			certificate or does not contain an entry for it.
255 256
  * 			\c FAILURE otherwise.
256 257
  */
257
-result_t x509_verify_crl(const char *crl_file, openvpn_x509_cert_t *cert,
258
-    const char *subject);
258
+result_t x509_verify_crl(const char *crl_file, const char *crl_inline,
259
+                         openvpn_x509_cert_t *cert, const char *subject);
259 260
 
260 261
 #endif /* SSL_VERIFY_BACKEND_H_ */
... ...
@@ -613,7 +613,8 @@ x509_write_pem(FILE *peercert_file, X509 *peercert)
613 613
  * check peer cert against CRL
614 614
  */
615 615
 result_t
616
-x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject)
616
+x509_verify_crl(const char *crl_file, const char* crl_inline,
617
+                X509 *peer_cert, const char *subject)
617 618
 {
618 619
   X509_CRL *crl=NULL;
619 620
   X509_REVOKED *revoked;
... ...
@@ -623,7 +624,10 @@ x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject)
623 623
   struct gc_arena gc = gc_new();
624 624
   char *serial;
625 625
 
626
-  in = BIO_new_file (crl_file, "r");
626
+  if (!strcmp (crl_file, INLINE_FILE_TAG) && crl_inline)
627
+    in = BIO_new_mem_buf ((char *)crl_inline, -1);
628
+  else
629
+    in = BIO_new_file (crl_file, "r");
627 630
 
628 631
   if (in == NULL) {
629 632
     msg (M_WARN, "CRL: cannot read: %s", crl_file);
... ...
@@ -359,18 +359,30 @@ x509_write_pem(FILE *peercert_file, x509_crt *peercert)
359 359
  * check peer cert against CRL
360 360
  */
361 361
 result_t
362
-x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject)
362
+x509_verify_crl(const char *crl_file, const char* crl_inline,
363
+                x509_crt *cert, const char *subject)
363 364
 {
364 365
   result_t retval = FAILURE;
365 366
   x509_crl crl = {0};
366 367
   struct gc_arena gc = gc_new();
367 368
   char *serial;
368 369
 
369
-  if (!polar_ok(x509_crl_parse_file(&crl, crl_file)))
370
+  if (!strcmp (crl_file, INLINE_FILE_TAG) && crl_inline)
370 371
     {
371
-      msg (M_WARN, "CRL: cannot read CRL from file %s", crl_file);
372
-      goto end;
372
+      if (!polar_ok(x509_crl_parse(&crl, crl_inline, strlen(crl_inline))))
373
+        {
374
+           msg (M_WARN, "CRL: cannot parse inline CRL");
375
+           goto end;
376
+        }
373 377
     }
378
+  else
379
+    {
380
+      if (!polar_ok(x509_crl_parse_file(&crl, crl_file)))
381
+      {
382
+          msg (M_WARN, "CRL: cannot read CRL from file %s", crl_file);
383
+          goto end;
384
+      }
385
+  }
374 386
 
375 387
   if(cert->issuer_raw.len != crl.issuer_raw.len ||
376 388
       memcmp(crl.issuer_raw.p, cert->issuer_raw.p, crl.issuer_raw.len) != 0)