Browse code

Inline file capability now works for --secret and --tls-auth. For example:

<secret>
[ascii key data]
</secret>


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

james authored on 2005/12/09 03:29:38
Showing 7 changed files
... ...
@@ -64,4 +64,12 @@ typedef unsigned long ptr_type;
64 64
  */
65 65
 #define TLS_CHANNEL_BUF_SIZE 1024
66 66
 
67
+/*
68
+ * A sort of pseudo-filename for data provided inline within
69
+ * the configuration file.
70
+ */
71
+#if ENABLE_INLINE_FILES
72
+#define INLINE_FILE_TAG "[[INLINE]]"
73
+#endif
74
+
67 75
 #endif
... ...
@@ -905,11 +905,12 @@ test_crypto (const struct crypto_options *co, struct frame* frame)
905 905
 }
906 906
 
907 907
 #ifdef USE_SSL
908
+
908 909
 void
909 910
 get_tls_handshake_key (const struct key_type *key_type,
910 911
 		       struct key_ctx_bi *ctx,
911 912
 		       const char *passphrase_file,
912
-		       bool key_direction)
913
+		       const unsigned int flags)
913 914
 {
914 915
   if (passphrase_file && key_type->hmac_length)
915 916
     {
... ...
@@ -921,40 +922,55 @@ get_tls_handshake_key (const struct key_type *key_type,
921 921
       kt.cipher_length = 0;
922 922
       kt.cipher = NULL;
923 923
 
924
-      /* first try to parse as an OpenVPN static key file */
925
-      read_key_file (&key2, passphrase_file, false);
926
-
927
-      /* succeeded? */
928
-      if (key2.n == 2)
924
+#if ENABLE_INLINE_FILES
925
+      if (flags & GHK_INLINE)
929 926
 	{
930
-	  msg (M_INFO,
931
-	       "Control Channel Authentication: using '%s' as a " PACKAGE_NAME " static key file",
932
-	       passphrase_file);
927
+	  /* key was specified inline, key text is in passphrase_file */
928
+	  read_key_file (&key2, passphrase_file, RKF_INLINE|RKF_MUST_SUCCEED);
929
+
930
+	  /* succeeded? */
931
+	  if (key2.n == 2)
932
+	    msg (M_INFO, "Control Channel Authentication: tls-auth using INLINE static key file");
933
+	  else
934
+	    msg (M_FATAL, "INLINE tls-auth file lacks the requisite 2 keys");
933 935
 	}
934 936
       else
935
-	{
936
-	  int hash_size;
937
+#endif
938
+      {
939
+	/* first try to parse as an OpenVPN static key file */
940
+	read_key_file (&key2, passphrase_file, 0);
937 941
 
938
-	  CLEAR (key2);
942
+	/* succeeded? */
943
+	if (key2.n == 2)
944
+	  {
945
+	    msg (M_INFO,
946
+		 "Control Channel Authentication: using '%s' as a " PACKAGE_NAME " static key file",
947
+		 passphrase_file);
948
+	  }
949
+	else
950
+	  {
951
+	    int hash_size;
939 952
 
940
-	  /* failed, now try to get hash from a freeform file */
941
-	  hash_size = read_passphrase_hash (passphrase_file,
942
-					    kt.digest,
943
-					    key2.keys[0].hmac,
944
-					    MAX_HMAC_KEY_LENGTH);
945
-	  ASSERT (hash_size == kt.hmac_length);
953
+	    CLEAR (key2);
946 954
 
947
-	  /* suceeded */
948
-	  key2.n = 1;
955
+	    /* failed, now try to get hash from a freeform file */
956
+	    hash_size = read_passphrase_hash (passphrase_file,
957
+					      kt.digest,
958
+					      key2.keys[0].hmac,
959
+					      MAX_HMAC_KEY_LENGTH);
960
+	    ASSERT (hash_size == kt.hmac_length);
949 961
 
950
-	  msg (M_INFO,
951
-	       "Control Channel Authentication: using '%s' as a free-form passphrase file",
952
-	       passphrase_file);
953
-	}
962
+	    /* suceeded */
963
+	    key2.n = 1;
954 964
 
965
+	    msg (M_INFO,
966
+		 "Control Channel Authentication: using '%s' as a free-form passphrase file",
967
+		 passphrase_file);
968
+	  }
969
+      }
955 970
       /* handle key direction */
956 971
 
957
-      key_direction_state_init (&kds, key_direction);
972
+      key_direction_state_init (&kds, BOOL_CAST (flags & GHK_KEY_DIR));
958 973
       must_have_n_keys (passphrase_file, "tls-auth", &key2, kds.need_keys);
959 974
 
960 975
       /* initialize hmac key in both directions */
... ...
@@ -984,13 +1000,15 @@ static const char unprintable_char_fmt[] =
984 984
   "Non-Hex, unprintable character (0x%02x) found at line %d in key file '%s' (%d/%d/%d bytes found/min/max)";
985 985
 
986 986
 /* read key from file */
987
+
987 988
 void
988
-read_key_file (struct key2 *key2, const char *filename, bool must_succeed)
989
+read_key_file (struct key2 *key2, const char *file, const unsigned int flags)
989 990
 {
990 991
   struct gc_arena gc = gc_new ();
991
-  struct buffer in = alloc_buf_gc (64, &gc);
992
+  struct buffer in;
992 993
   int fd, size;
993 994
   uint8_t hex_byte[3] = {0, 0, 0};
995
+  const char *error_filename = file;
994 996
 
995 997
   /* parse info */
996 998
   int hb_index = 0;
... ...
@@ -1019,96 +1037,111 @@ read_key_file (struct key2 *key2, const char *filename, bool must_succeed)
1019 1019
 
1020 1020
   CLEAR (*key2);
1021 1021
 
1022
-  fd = open (filename, O_RDONLY);
1023
-  if (fd == -1)
1024
-    msg (M_ERR, "Cannot open file key file '%s'", filename);
1022
+  /*
1023
+   * Key can be provided as a filename in 'file' or if RKF_INLINE
1024
+   * is set, the actual key data itself in ascii form.
1025
+   */
1026
+#if ENABLE_INLINE_FILES
1027
+  if (flags & RKF_INLINE) /* 'file' is a string containing ascii representation of key */
1028
+    {
1029
+      size = strlen (file) + 1;
1030
+      buf_set_read (&in, (const uint8_t *)file, size);
1031
+      error_filename = INLINE_FILE_TAG;
1032
+    }
1033
+  else /* 'file' is a filename which refers to a file containing the ascii key */
1034
+#endif
1035
+    {
1036
+      in = alloc_buf_gc (2048, &gc);
1037
+      fd = open (file, O_RDONLY);
1038
+      if (fd == -1)
1039
+	msg (M_ERR, "Cannot open file key file '%s'", file);
1040
+      size = read (fd, in.data, in.capacity);
1041
+      if (size == in.capacity)
1042
+	msg (M_FATAL, "Key file ('%s') can be a maximum of %d bytes", file, (int)in.capacity);
1043
+      close (fd);
1044
+    }
1025 1045
 
1026
-  while ((size = read (fd, in.data, in.capacity)))
1046
+  const char *cp = (char *)in.data;
1047
+  while (size)
1027 1048
     {
1028
-      const char *cp = (char *)in.data;
1029
-      while (size)
1030
-	{
1031
-	  const char c = *cp;
1049
+      const char c = *cp;
1032 1050
 
1033 1051
 #if 0
1034
-	  msg (M_INFO, "char='%c' s=%d ln=%d li=%d m=%d c=%d",
1035
-	       c, state, line_num, line_index, match, count);
1052
+      msg (M_INFO, "char='%c' s=%d ln=%d li=%d m=%d c=%d",
1053
+	   c, state, line_num, line_index, match, count);
1036 1054
 #endif
1037 1055
 
1038
-	  if (c == '\n')
1056
+      if (c == '\n')
1057
+	{
1058
+	  line_index = match = 0;
1059
+	  ++line_num;	      
1060
+	}
1061
+      else
1062
+	{
1063
+	  /* first char of new line */
1064
+	  if (!line_index)
1039 1065
 	    {
1040
-	      line_index = match = 0;
1041
-	      ++line_num;	      
1066
+	      /* first char of line after header line? */
1067
+	      if (state == PARSE_HEAD)
1068
+		state = PARSE_DATA;
1069
+
1070
+	      /* first char of footer */
1071
+	      if ((state == PARSE_DATA || state == PARSE_DATA_COMPLETE) && c == '-')
1072
+		state = PARSE_FOOT;
1042 1073
 	    }
1043
-	  else
1074
+
1075
+	  /* compare read chars with header line */
1076
+	  if (state == PARSE_INITIAL)
1044 1077
 	    {
1045
-	      /* first char of new line */
1046
-	      if (!line_index)
1078
+	      if (line_index < hlen && c == static_key_head[line_index])
1047 1079
 		{
1048
-		  /* first char of line after header line? */
1049
-		  if (state == PARSE_HEAD)
1050
-		    state = PARSE_DATA;
1051
-
1052
-		  /* first char of footer */
1053
-		  if ((state == PARSE_DATA || state == PARSE_DATA_COMPLETE) && c == '-')
1054
-		    state = PARSE_FOOT;
1080
+		  if (++match == hlen)
1081
+		    state = PARSE_HEAD;
1055 1082
 		}
1083
+	    }
1056 1084
 
1057
-	      /* compare read chars with header line */
1058
-	      if (state == PARSE_INITIAL)
1085
+	  /* compare read chars with footer line */
1086
+	  if (state == PARSE_FOOT)
1087
+	    {
1088
+	      if (line_index < flen && c == static_key_foot[line_index])
1059 1089
 		{
1060
-		  if (line_index < hlen && c == static_key_head[line_index])
1061
-		    {
1062
-		      if (++match == hlen)
1063
-			state = PARSE_HEAD;
1064
-		    }
1090
+		  if (++match == flen)
1091
+		    state = PARSE_FINISHED;
1065 1092
 		}
1093
+	    }
1066 1094
 
1067
-	      /* compare read chars with footer line */
1068
-	      if (state == PARSE_FOOT)
1095
+	  /* reading key */
1096
+	  if (state == PARSE_DATA)
1097
+	    {
1098
+	      if (isxdigit(c))
1069 1099
 		{
1070
-		  if (line_index < flen && c == static_key_foot[line_index])
1100
+		  ASSERT (hb_index >= 0 && hb_index < 2);
1101
+		  hex_byte[hb_index++] = c;
1102
+		  if (hb_index == 2)
1071 1103
 		    {
1072
-		      if (++match == flen)
1073
-			state = PARSE_FINISHED;
1104
+		      unsigned int u;
1105
+		      ASSERT(sscanf((const char *)hex_byte, "%x", &u) == 1);
1106
+		      *out++ = u;
1107
+		      hb_index = 0;
1108
+		      if (++count == keylen)
1109
+			state = PARSE_DATA_COMPLETE;
1074 1110
 		    }
1075 1111
 		}
1076
-
1077
-	      /* reading key */
1078
-	      if (state == PARSE_DATA)
1112
+	      else if (isspace(c))
1113
+		;
1114
+	      else
1079 1115
 		{
1080
-		  if (isxdigit(c))
1081
-		    {
1082
-		      ASSERT (hb_index >= 0 && hb_index < 2);
1083
-		      hex_byte[hb_index++] = c;
1084
-		      if (hb_index == 2)
1085
-			{
1086
-			  unsigned int u;
1087
-			  ASSERT(sscanf((const char *)hex_byte, "%x", &u) == 1);
1088
-			  *out++ = u;
1089
-			  hb_index = 0;
1090
-			  if (++count == keylen)
1091
-			    state = PARSE_DATA_COMPLETE;
1092
-			}
1093
-		    }
1094
-		  else if (isspace(c))
1095
-		    ;
1096
-		  else
1097
-		    {
1098
-		      msg (M_FATAL,
1099
-			   (isprint (c) ? printable_char_fmt : unprintable_char_fmt),
1100
-			   c, line_num, filename, count, onekeylen, keylen);
1101
-		    }
1116
+		  msg (M_FATAL,
1117
+		       (isprint (c) ? printable_char_fmt : unprintable_char_fmt),
1118
+		       c, line_num, error_filename, count, onekeylen, keylen);
1102 1119
 		}
1103
-	      ++line_index;
1104 1120
 	    }
1105
-	  ++cp;
1106
-	  --size;
1121
+	  ++line_index;
1107 1122
 	}
1123
+      ++cp;
1124
+      --size;
1108 1125
     }
1109 1126
 
1110
-  close (fd);
1111
-
1112 1127
   /*
1113 1128
    * Normally we will read either 1 or 2 keys from file.
1114 1129
    */
... ...
@@ -1116,22 +1149,22 @@ read_key_file (struct key2 *key2, const char *filename, bool must_succeed)
1116 1116
 
1117 1117
   ASSERT (key2->n >= 0 && key2->n <= (int) SIZE (key2->keys));
1118 1118
 
1119
-  if (must_succeed)
1119
+  if (flags & RKF_MUST_SUCCEED)
1120 1120
     {
1121 1121
       if (!key2->n)
1122 1122
 	msg (M_FATAL, "Insufficient key material or header text not found found in file '%s' (%d/%d/%d bytes found/min/max)",
1123
-	     filename, count, onekeylen, keylen);
1123
+	     error_filename, count, onekeylen, keylen);
1124 1124
 
1125 1125
       if (state != PARSE_FINISHED)
1126 1126
 	msg (M_FATAL, "Footer text not found in file '%s' (%d/%d/%d bytes found/min/max)",
1127
-	     filename, count, onekeylen, keylen);
1127
+	     error_filename, count, onekeylen, keylen);
1128 1128
     }
1129 1129
 
1130 1130
   /* zero file read buffer */
1131 1131
   buf_clear (&in);
1132 1132
 
1133 1133
   if (key2->n)
1134
-    warn_if_group_others_accessible (filename);
1134
+    warn_if_group_others_accessible (error_filename);
1135 1135
 
1136 1136
 #if 0
1137 1137
   /* DEBUGGING */
... ...
@@ -270,7 +270,9 @@ void init_key_type (struct key_type *kt, const char *ciphername,
270 270
 		    bool authname_defined, int keysize,
271 271
 		    bool cfb_ofb_allowed, bool warn);
272 272
 
273
-void read_key_file (struct key2 *key2, const char *filename, bool must_succeed);
273
+#define RKF_MUST_SUCCEED (1<<0)
274
+#define RKF_INLINE       (1<<1)
275
+void read_key_file (struct key2 *key2, const char *file, const unsigned int flags);
274 276
 
275 277
 int write_key_file (const int nkeys, const char *filename);
276 278
 
... ...
@@ -367,10 +369,12 @@ void openssl_dmalloc_init (void);
367 367
 
368 368
 #ifdef USE_SSL
369 369
 
370
+#define GHK_KEY_DIR (1<<0)
371
+#define GHK_INLINE  (1<<1)
370 372
 void get_tls_handshake_key (const struct key_type *key_type,
371 373
 			    struct key_ctx_bi *ctx,
372 374
 			    const char *passphrase_file,
373
-			    bool key_direction);
375
+			    const unsigned int flags);
374 376
 
375 377
 #else
376 378
 
... ...
@@ -1276,7 +1276,19 @@ do_init_crypto_static (struct context *c, const unsigned int flags)
1276 1276
 		     options->test_crypto, true);
1277 1277
 
1278 1278
       /* Read cipher and hmac keys from shared secret file */
1279
-      read_key_file (&key2, options->shared_secret_file, true);
1279
+      {
1280
+	unsigned int rkf_flags = RKF_MUST_SUCCEED;
1281
+	const char *rkf_file = options->shared_secret_file;
1282
+
1283
+#if ENABLE_INLINE_FILES
1284
+	if (options->shared_secret_file_inline)
1285
+	  {
1286
+	    rkf_file = options->shared_secret_file_inline;
1287
+	    rkf_flags |= RKF_INLINE;
1288
+	  }
1289
+#endif
1290
+	read_key_file (&key2, rkf_file, rkf_flags);
1291
+      }
1280 1292
 
1281 1293
       /* Check for and fix highly unlikely key problems */
1282 1294
       verify_fix_key2 (&key2, &c->c1.ks.key_type,
... ...
@@ -1361,10 +1373,22 @@ do_init_crypto_tls_c1 (struct context *c)
1361 1361
 
1362 1362
       /* TLS handshake authentication (--tls-auth) */
1363 1363
       if (options->tls_auth_file)
1364
-	get_tls_handshake_key (&c->c1.ks.key_type,
1365
-			       &c->c1.ks.tls_auth_key,
1366
-			       options->tls_auth_file,
1367
-			       options->key_direction);
1364
+	{
1365
+	  unsigned int flags = options->key_direction ? GHK_KEY_DIR : 0;
1366
+	  const char *file = options->tls_auth_file;
1367
+
1368
+#if ENABLE_INLINE_FILES
1369
+	  if (options->tls_auth_file_inline)
1370
+	    {
1371
+	      flags |= GHK_INLINE;
1372
+	      file = options->tls_auth_file_inline;
1373
+	    }
1374
+#endif
1375
+	  get_tls_handshake_key (&c->c1.ks.key_type,
1376
+				 &c->c1.ks.tls_auth_key,
1377
+				 file,
1378
+				 flags);
1379
+	}
1368 1380
 
1369 1381
 #if ENABLE_INLINE_FILES
1370 1382
       if (options->priv_key_file_inline)
... ...
@@ -433,15 +433,20 @@ void
433 433
 warn_if_group_others_accessible (const char* filename)
434 434
 {
435 435
 #ifdef HAVE_STAT
436
-  struct stat st;
437
-  if (stat (filename, &st))
438
-    {
439
-      msg (M_WARN | M_ERRNO, "WARNING: cannot stat file '%s'", filename);
440
-    }
441
-  else
436
+#if ENABLE_INLINE_FILES
437
+  if (strcmp (filename, INLINE_FILE_TAG))
438
+#endif
442 439
     {
443
-      if (st.st_mode & (S_IRWXG|S_IRWXO))
444
-	msg (M_WARN, "WARNING: file '%s' is group or others accessible", filename);
440
+      struct stat st;
441
+      if (stat (filename, &st))
442
+	{
443
+	  msg (M_WARN | M_ERRNO, "WARNING: cannot stat file '%s'", filename);
444
+	}
445
+      else
446
+	{
447
+	  if (st.st_mode & (S_IRWXG|S_IRWXO))
448
+	    msg (M_WARN, "WARNING: file '%s' is group or others accessible", filename);
449
+	}
445 450
     }
446 451
 #endif
447 452
 }
... ...
@@ -4538,9 +4538,26 @@ add_option (struct options *options,
4538 4538
       VERIFY_PERMISSION (OPT_P_GENERAL);
4539 4539
       options->show_engines = true;
4540 4540
     }
4541
+  else if (streq (p[0], "key-direction") && p[1])
4542
+    {
4543
+      int key_direction;
4544
+
4545
+      key_direction = ascii2keydirection (msglevel, p[1]);
4546
+      if (key_direction >= 0)
4547
+	options->key_direction = key_direction;
4548
+      else
4549
+	goto err;
4550
+    }
4541 4551
   else if (streq (p[0], "secret") && p[1])
4542 4552
     {
4543 4553
       VERIFY_PERMISSION (OPT_P_GENERAL);
4554
+#if ENABLE_INLINE_FILES
4555
+      if (streq (p[1], INLINE_FILE_TAG) && p[2])
4556
+	{
4557
+	  options->shared_secret_file_inline = p[2];
4558
+	}
4559
+      else
4560
+#endif
4544 4561
       if (p[2])
4545 4562
 	{
4546 4563
 	  int key_direction;
... ...
@@ -4889,6 +4906,13 @@ add_option (struct options *options,
4889 4889
   else if (streq (p[0], "tls-auth") && p[1])
4890 4890
     {
4891 4891
       VERIFY_PERMISSION (OPT_P_GENERAL);
4892
+#if ENABLE_INLINE_FILES
4893
+      if (streq (p[1], INLINE_FILE_TAG) && p[2])
4894
+	{
4895
+	  options->tls_auth_file_inline = p[2];
4896
+	}
4897
+      else
4898
+#endif
4892 4899
       if (p[2])
4893 4900
 	{
4894 4901
 	  int key_direction;
... ...
@@ -82,10 +82,6 @@ struct options_pre_pull
82 82
 
83 83
 #endif
84 84
 
85
-#if ENABLE_INLINE_FILES
86
-#define INLINE_FILE_TAG "[[INLINE]]"
87
-#endif
88
-
89 85
 /* Command line options */
90 86
 struct options
91 87
 {
... ...
@@ -356,6 +352,9 @@ struct options
356 356
 #ifdef USE_CRYPTO
357 357
   /* Cipher parms */
358 358
   const char *shared_secret_file;
359
+#if ENABLE_INLINE_FILES
360
+  const char *shared_secret_file_inline;
361
+#endif
359 362
   int key_direction;
360 363
   bool ciphername_defined;
361 364
   const char *ciphername;
... ...
@@ -433,6 +432,9 @@ struct options
433 433
 
434 434
   /* Special authentication MAC for TLS control channel */
435 435
   const char *tls_auth_file;		/* shared secret */
436
+#if ENABLE_INLINE_FILES
437
+  const char *tls_auth_file_inline;
438
+#endif
436 439
 
437 440
   /* Allow only one session */
438 441
   bool single_session;