Browse code

Added new "extra-certs" and "verify-hash" options (see man page for details).

Increase the timeout after SIGUSR1 restart when restart is not
due to server_poll_timeout.

Version 2.1.3v


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@7215 e7ae566f-a301-0410-adde-c780ea21d3b5

James Yonan authored on 2011/04/25 13:58:34
Showing 7 changed files
... ...
@@ -1706,9 +1706,11 @@ socket_restart_pause (struct context *c)
1706 1706
   if (auth_retry_get () == AR_NOINTERACT)
1707 1707
     sec = 10;
1708 1708
 
1709
+#if 0 /* not really needed because of c->persist.restart_sleep_seconds */
1709 1710
   if (c->options.server_poll_timeout && sec > 1)
1710 1711
     sec = 1;
1711 1712
 #endif
1713
+#endif
1712 1714
 
1713 1715
   if (c->persist.restart_sleep_seconds > 0 && c->persist.restart_sleep_seconds > sec)
1714 1716
     sec = c->persist.restart_sleep_seconds;
... ...
@@ -2057,6 +2059,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
2057 2057
   to.ns_cert_type = options->ns_cert_type;
2058 2058
   memmove (to.remote_cert_ku, options->remote_cert_ku, sizeof (to.remote_cert_ku));
2059 2059
   to.remote_cert_eku = options->remote_cert_eku;
2060
+  to.verify_hash = options->verify_hash;
2060 2061
   to.es = c->c2.es;
2061 2062
 
2062 2063
 #ifdef ENABLE_DEBUG
... ...
@@ -3887,6 +3887,22 @@ that for certificate authority functions, you must set up the files
3887 3887
 ).
3888 3888
 .\"*********************************************************
3889 3889
 .TP
3890
+.B --extra-certs file
3891
+Specify a
3892
+.B file
3893
+containing one or more PEM certs (concatenated together)
3894
+that complete the
3895
+local certificate chain.
3896
+
3897
+This option is useful for "split" CAs, where the CA for server
3898
+certs is different than the CA for client certs.  Putting certs
3899
+in this file allows them to be used to complete the local
3900
+certificate chain without trusting them to verify the peer-submitted
3901
+certificate, as would be the case if the certs were placed in the
3902
+.B ca
3903
+file.
3904
+.\"*********************************************************
3905
+.TP
3890 3906
 .B --key file
3891 3907
 Local peer's private key in .pem format.  Use the private key which was generated
3892 3908
 when you built your peer's certificate (see
... ...
@@ -3903,6 +3919,17 @@ and
3903 3903
 .B --key.
3904 3904
 .\"*********************************************************
3905 3905
 .TP
3906
+.B --verify-hash hash
3907
+Specify SHA1 fingerprint for level-1 cert.  The level-1 cert is the
3908
+CA (or intermediate cert) that signs the leaf certificate, and is
3909
+one removed from the leaf certificate in the direction of the root.
3910
+When accepting a connection from a peer, the level-1 cert
3911
+fingerprint must match
3912
+.B hash
3913
+or certificate verification will fail.  Hash is specified
3914
+as XX:XX:...  For example: AD:B0:95:D8:09:C8:36:45:12:A9:89:C8:90:09:CB:13:72:A6:AD:16
3915
+.\"*********************************************************
3916
+.TP
3906 3917
 .B --pkcs11-cert-private [0|1]...
3907 3918
 Set if access to certificate object should be performed after login.
3908 3919
 Every provider has its own setting.
... ...
@@ -507,9 +507,11 @@ static const char usage_message[] =
507 507
   "                  Use \"openssl dhparam -out dh1024.pem 1024\" to generate.\n"
508 508
   "--cert file     : Local certificate in .pem format -- must be signed\n"
509 509
   "                  by a Certificate Authority in --ca file.\n"
510
+  "--extra-certs file : one or more PEM certs that complete the cert chain.\n"
510 511
   "--key file      : Local private key in .pem format.\n"
511 512
   "--pkcs12 file   : PKCS#12 file containing local private key, local certificate\n"
512 513
   "                  and optionally the root CA certificate.\n"
514
+  "--verify-hash   : Specify SHA1 fingerprint for level-1 cert.\n"
513 515
 #ifdef WIN32
514 516
   "--cryptoapicert select-string : Load the certificate and private key from the\n"
515 517
   "                  Windows Certificate System Store.\n"
... ...
@@ -894,6 +896,40 @@ is_stateful_restart (const struct options *o)
894 894
   return is_persist_option (o) || connection_list_defined (o);
895 895
 }
896 896
 
897
+#ifdef USE_SSL
898
+static uint8_t *
899
+parse_hash_fingerprint(const char *str, int nbytes, int msglevel, struct gc_arena *gc)
900
+{
901
+  int i;
902
+  const char *cp = str;
903
+  uint8_t *ret = (uint8_t *) gc_malloc (nbytes, true, gc);
904
+  char term = 1;
905
+  int byte;
906
+  char bs[3];
907
+
908
+  for (i = 0; i < nbytes; ++i)
909
+    {
910
+      if (strlen(cp) < 2)
911
+	msg (msglevel, "format error in hash fingerprint: %s", str);
912
+      bs[0] = *cp++;
913
+      bs[1] = *cp++;
914
+      bs[2] = 0;
915
+      byte = 0;
916
+      if (sscanf(bs, "%x", &byte) != 1)
917
+	msg (msglevel, "format error in hash fingerprint hex byte: %s", str);
918
+      ret[i] = (uint8_t)byte;
919
+      term = *cp++;
920
+      if (term != ':' && term != 0)
921
+	msg (msglevel, "format error in hash fingerprint delimiter: %s", str);
922
+      if (term == 0)
923
+	break;
924
+    }
925
+  if (term != 0 || i != nbytes-1)
926
+    msg (msglevel, "hash fingerprint is different length than expected (%d bytes): %s", nbytes, str);
927
+  return ret;
928
+}
929
+#endif
930
+
897 931
 #ifdef WIN32
898 932
 
899 933
 #ifdef ENABLE_DEBUG
... ...
@@ -5758,6 +5794,22 @@ add_option (struct options *options,
5758 5758
 	}
5759 5759
 #endif
5760 5760
     }
5761
+  else if (streq (p[0], "extra-certs") && p[1])
5762
+    {
5763
+      VERIFY_PERMISSION (OPT_P_GENERAL);
5764
+      options->extra_certs_file = p[1];
5765
+#if ENABLE_INLINE_FILES
5766
+      if (streq (p[1], INLINE_FILE_TAG) && p[2])
5767
+	{
5768
+	  options->extra_certs_file_inline = p[2];
5769
+	}
5770
+#endif
5771
+    }
5772
+  else if (streq (p[0], "verify-hash") && p[1])
5773
+    {
5774
+      VERIFY_PERMISSION (OPT_P_GENERAL);
5775
+      options->verify_hash = parse_hash_fingerprint(p[1], SHA_DIGEST_LENGTH, msglevel, &options->gc);
5776
+    }
5761 5777
 #ifdef WIN32
5762 5778
   else if (streq (p[0], "cryptoapicert") && p[1])
5763 5779
     {
... ...
@@ -477,6 +477,7 @@ struct options
477 477
   const char *ca_path;
478 478
   const char *dh_file;
479 479
   const char *cert_file;
480
+  const char *extra_certs_file;
480 481
   const char *priv_key_file;
481 482
   const char *pkcs12_file;
482 483
   const char *cipher_list;
... ...
@@ -487,6 +488,7 @@ struct options
487 487
 #if ENABLE_INLINE_FILES
488 488
   const char *ca_file_inline;
489 489
   const char *cert_file_inline;
490
+  const char *extra_certs_file_inline;
490 491
   char *priv_key_file_inline;
491 492
   const char *dh_file_inline;
492 493
   const char *pkcs12_file_inline; /* contains the base64 encoding of pkcs12 file */
... ...
@@ -495,6 +497,7 @@ struct options
495 495
   int ns_cert_type; /* set to 0, NS_SSL_SERVER, or NS_SSL_CLIENT */
496 496
   unsigned remote_cert_ku[MAX_PARMS];
497 497
   const char *remote_cert_eku;
498
+  uint8_t *verify_hash;
498 499
 
499 500
 #ifdef ENABLE_PKCS11
500 501
   const char *pkcs11_providers[MAX_PARMS];
... ...
@@ -910,6 +910,16 @@ verify_callback (int preverify_ok, X509_STORE_CTX * ctx)
910 910
       goto err;			/* Reject connection */
911 911
     }
912 912
 
913
+  /* verify level 1 cert, i.e. the CA that signed our leaf cert */
914
+  if (ctx->error_depth == 1 && opt->verify_hash)
915
+    {
916
+      if (memcmp (ctx->current_cert->sha1_hash, opt->verify_hash, SHA_DIGEST_LENGTH))
917
+	{
918
+	  msg (D_TLS_ERRORS, "TLS Error: level-1 certificate hash verification failed");
919
+	  goto err;
920
+	}
921
+    }
922
+
913 923
   /* save common name in session object */
914 924
   if (ctx->error_depth == 0)
915 925
     set_common_name (session, common_name);
... ...
@@ -2140,6 +2150,37 @@ init_ssl (const struct options *options)
2140 2140
 	msg (M_SSLERR, "Cannot load certificate chain file %s (SSL_use_certificate_chain_file)", options->cert_file);
2141 2141
     }
2142 2142
 
2143
+  /* Load extra certificates that are part of our own certificate
2144
+     chain but shouldn't be included in the verify chain */
2145
+  if (options->extra_certs_file || options->extra_certs_file_inline)
2146
+    {
2147
+      BIO *bio;
2148
+      X509 *cert;
2149
+#if ENABLE_INLINE_FILES
2150
+      if (!strcmp (options->extra_certs_file, INLINE_FILE_TAG) && options->extra_certs_file_inline)
2151
+	{
2152
+	  bio = BIO_new_mem_buf ((char *)options->extra_certs_file_inline, -1);
2153
+	}
2154
+      else
2155
+#endif
2156
+	{
2157
+	  bio = BIO_new(BIO_s_file());
2158
+	  if (BIO_read_filename(bio, options->extra_certs_file) <= 0)
2159
+	    msg (M_SSLERR, "Cannot load extra-certs file: %s", options->extra_certs_file);
2160
+	}
2161
+      for (;;)
2162
+	{
2163
+	  cert = NULL;
2164
+	  if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */
2165
+	    break;
2166
+	  if (!cert)
2167
+	    msg (M_SSLERR, "Error reading extra-certs certificate");
2168
+	  if (SSL_CTX_add_extra_chain_cert(ctx, cert) != 1)
2169
+	    msg (M_SSLERR, "Error adding extra-certs certificate");
2170
+	}
2171
+      BIO_free (bio);
2172
+    }
2173
+
2143 2174
   /* Require peer certificate verification */
2144 2175
 #if P2MP_SERVER
2145 2176
   if (options->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)
... ...
@@ -466,6 +466,7 @@ struct tls_options
466 466
   int ns_cert_type;
467 467
   unsigned remote_cert_ku[MAX_PARMS];
468 468
   const char *remote_cert_eku;
469
+  uint8_t *verify_hash;
469 470
 
470 471
   /* allow openvpn config info to be
471 472
      passed over control channel */
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1.3u])
2
+define(PRODUCT_VERSION,[2.1.3v])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])