aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2005-12-08 18:29:38 +0000
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2005-12-08 18:29:38 +0000
commitc959fc742eb10c516261765718a761536b0b8f4a (patch)
tree6cc92545c1c6df6338ad6ab07b6619e094e36f93
parentFixed some gcc 4 warnings in misc.c. (diff)
downloadopenvpn-c959fc742eb10c516261765718a761536b0b8f4a.tar.xz
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
-rw-r--r--common.h8
-rw-r--r--crypto.c225
-rw-r--r--crypto.h8
-rw-r--r--init.c34
-rw-r--r--misc.c21
-rw-r--r--options.c24
-rw-r--r--options.h10
7 files changed, 215 insertions, 115 deletions
diff --git a/common.h b/common.h
index ffaa165..e7320f3 100644
--- a/common.h
+++ b/common.h
@@ -64,4 +64,12 @@ typedef unsigned long ptr_type;
*/
#define TLS_CHANNEL_BUF_SIZE 1024
+/*
+ * A sort of pseudo-filename for data provided inline within
+ * the configuration file.
+ */
+#if ENABLE_INLINE_FILES
+#define INLINE_FILE_TAG "[[INLINE]]"
+#endif
+
#endif
diff --git a/crypto.c b/crypto.c
index 4f07651..5ddc269 100644
--- a/crypto.c
+++ b/crypto.c
@@ -905,11 +905,12 @@ test_crypto (const struct crypto_options *co, struct frame* frame)
}
#ifdef USE_SSL
+
void
get_tls_handshake_key (const struct key_type *key_type,
struct key_ctx_bi *ctx,
const char *passphrase_file,
- bool key_direction)
+ const unsigned int flags)
{
if (passphrase_file && key_type->hmac_length)
{
@@ -921,40 +922,55 @@ get_tls_handshake_key (const struct key_type *key_type,
kt.cipher_length = 0;
kt.cipher = NULL;
- /* first try to parse as an OpenVPN static key file */
- read_key_file (&key2, passphrase_file, false);
-
- /* succeeded? */
- if (key2.n == 2)
+#if ENABLE_INLINE_FILES
+ if (flags & GHK_INLINE)
{
- msg (M_INFO,
- "Control Channel Authentication: using '%s' as a " PACKAGE_NAME " static key file",
- passphrase_file);
+ /* key was specified inline, key text is in passphrase_file */
+ read_key_file (&key2, passphrase_file, RKF_INLINE|RKF_MUST_SUCCEED);
+
+ /* succeeded? */
+ if (key2.n == 2)
+ msg (M_INFO, "Control Channel Authentication: tls-auth using INLINE static key file");
+ else
+ msg (M_FATAL, "INLINE tls-auth file lacks the requisite 2 keys");
}
else
- {
- int hash_size;
+#endif
+ {
+ /* first try to parse as an OpenVPN static key file */
+ read_key_file (&key2, passphrase_file, 0);
- CLEAR (key2);
+ /* succeeded? */
+ if (key2.n == 2)
+ {
+ msg (M_INFO,
+ "Control Channel Authentication: using '%s' as a " PACKAGE_NAME " static key file",
+ passphrase_file);
+ }
+ else
+ {
+ int hash_size;
- /* failed, now try to get hash from a freeform file */
- hash_size = read_passphrase_hash (passphrase_file,
- kt.digest,
- key2.keys[0].hmac,
- MAX_HMAC_KEY_LENGTH);
- ASSERT (hash_size == kt.hmac_length);
+ CLEAR (key2);
- /* suceeded */
- key2.n = 1;
+ /* failed, now try to get hash from a freeform file */
+ hash_size = read_passphrase_hash (passphrase_file,
+ kt.digest,
+ key2.keys[0].hmac,
+ MAX_HMAC_KEY_LENGTH);
+ ASSERT (hash_size == kt.hmac_length);
- msg (M_INFO,
- "Control Channel Authentication: using '%s' as a free-form passphrase file",
- passphrase_file);
- }
+ /* suceeded */
+ key2.n = 1;
+ msg (M_INFO,
+ "Control Channel Authentication: using '%s' as a free-form passphrase file",
+ passphrase_file);
+ }
+ }
/* handle key direction */
- key_direction_state_init (&kds, key_direction);
+ key_direction_state_init (&kds, BOOL_CAST (flags & GHK_KEY_DIR));
must_have_n_keys (passphrase_file, "tls-auth", &key2, kds.need_keys);
/* initialize hmac key in both directions */
@@ -984,13 +1000,15 @@ static const char unprintable_char_fmt[] =
"Non-Hex, unprintable character (0x%02x) found at line %d in key file '%s' (%d/%d/%d bytes found/min/max)";
/* read key from file */
+
void
-read_key_file (struct key2 *key2, const char *filename, bool must_succeed)
+read_key_file (struct key2 *key2, const char *file, const unsigned int flags)
{
struct gc_arena gc = gc_new ();
- struct buffer in = alloc_buf_gc (64, &gc);
+ struct buffer in;
int fd, size;
uint8_t hex_byte[3] = {0, 0, 0};
+ const char *error_filename = file;
/* parse info */
int hb_index = 0;
@@ -1019,96 +1037,111 @@ read_key_file (struct key2 *key2, const char *filename, bool must_succeed)
CLEAR (*key2);
- fd = open (filename, O_RDONLY);
- if (fd == -1)
- msg (M_ERR, "Cannot open file key file '%s'", filename);
+ /*
+ * Key can be provided as a filename in 'file' or if RKF_INLINE
+ * is set, the actual key data itself in ascii form.
+ */
+#if ENABLE_INLINE_FILES
+ if (flags & RKF_INLINE) /* 'file' is a string containing ascii representation of key */
+ {
+ size = strlen (file) + 1;
+ buf_set_read (&in, (const uint8_t *)file, size);
+ error_filename = INLINE_FILE_TAG;
+ }
+ else /* 'file' is a filename which refers to a file containing the ascii key */
+#endif
+ {
+ in = alloc_buf_gc (2048, &gc);
+ fd = open (file, O_RDONLY);
+ if (fd == -1)
+ msg (M_ERR, "Cannot open file key file '%s'", file);
+ size = read (fd, in.data, in.capacity);
+ if (size == in.capacity)
+ msg (M_FATAL, "Key file ('%s') can be a maximum of %d bytes", file, (int)in.capacity);
+ close (fd);
+ }
- while ((size = read (fd, in.data, in.capacity)))
+ const char *cp = (char *)in.data;
+ while (size)
{
- const char *cp = (char *)in.data;
- while (size)
- {
- const char c = *cp;
+ const char c = *cp;
#if 0
- msg (M_INFO, "char='%c' s=%d ln=%d li=%d m=%d c=%d",
- c, state, line_num, line_index, match, count);
+ msg (M_INFO, "char='%c' s=%d ln=%d li=%d m=%d c=%d",
+ c, state, line_num, line_index, match, count);
#endif
- if (c == '\n')
+ if (c == '\n')
+ {
+ line_index = match = 0;
+ ++line_num;
+ }
+ else
+ {
+ /* first char of new line */
+ if (!line_index)
{
- line_index = match = 0;
- ++line_num;
+ /* first char of line after header line? */
+ if (state == PARSE_HEAD)
+ state = PARSE_DATA;
+
+ /* first char of footer */
+ if ((state == PARSE_DATA || state == PARSE_DATA_COMPLETE) && c == '-')
+ state = PARSE_FOOT;
}
- else
+
+ /* compare read chars with header line */
+ if (state == PARSE_INITIAL)
{
- /* first char of new line */
- if (!line_index)
+ if (line_index < hlen && c == static_key_head[line_index])
{
- /* first char of line after header line? */
- if (state == PARSE_HEAD)
- state = PARSE_DATA;
-
- /* first char of footer */
- if ((state == PARSE_DATA || state == PARSE_DATA_COMPLETE) && c == '-')
- state = PARSE_FOOT;
+ if (++match == hlen)
+ state = PARSE_HEAD;
}
+ }
- /* compare read chars with header line */
- if (state == PARSE_INITIAL)
+ /* compare read chars with footer line */
+ if (state == PARSE_FOOT)
+ {
+ if (line_index < flen && c == static_key_foot[line_index])
{
- if (line_index < hlen && c == static_key_head[line_index])
- {
- if (++match == hlen)
- state = PARSE_HEAD;
- }
+ if (++match == flen)
+ state = PARSE_FINISHED;
}
+ }
- /* compare read chars with footer line */
- if (state == PARSE_FOOT)
+ /* reading key */
+ if (state == PARSE_DATA)
+ {
+ if (isxdigit(c))
{
- if (line_index < flen && c == static_key_foot[line_index])
+ ASSERT (hb_index >= 0 && hb_index < 2);
+ hex_byte[hb_index++] = c;
+ if (hb_index == 2)
{
- if (++match == flen)
- state = PARSE_FINISHED;
+ unsigned int u;
+ ASSERT(sscanf((const char *)hex_byte, "%x", &u) == 1);
+ *out++ = u;
+ hb_index = 0;
+ if (++count == keylen)
+ state = PARSE_DATA_COMPLETE;
}
}
-
- /* reading key */
- if (state == PARSE_DATA)
+ else if (isspace(c))
+ ;
+ else
{
- if (isxdigit(c))
- {
- ASSERT (hb_index >= 0 && hb_index < 2);
- hex_byte[hb_index++] = c;
- if (hb_index == 2)
- {
- unsigned int u;
- ASSERT(sscanf((const char *)hex_byte, "%x", &u) == 1);
- *out++ = u;
- hb_index = 0;
- if (++count == keylen)
- state = PARSE_DATA_COMPLETE;
- }
- }
- else if (isspace(c))
- ;
- else
- {
- msg (M_FATAL,
- (isprint (c) ? printable_char_fmt : unprintable_char_fmt),
- c, line_num, filename, count, onekeylen, keylen);
- }
+ msg (M_FATAL,
+ (isprint (c) ? printable_char_fmt : unprintable_char_fmt),
+ c, line_num, error_filename, count, onekeylen, keylen);
}
- ++line_index;
}
- ++cp;
- --size;
+ ++line_index;
}
+ ++cp;
+ --size;
}
- close (fd);
-
/*
* Normally we will read either 1 or 2 keys from file.
*/
@@ -1116,22 +1149,22 @@ read_key_file (struct key2 *key2, const char *filename, bool must_succeed)
ASSERT (key2->n >= 0 && key2->n <= (int) SIZE (key2->keys));
- if (must_succeed)
+ if (flags & RKF_MUST_SUCCEED)
{
if (!key2->n)
msg (M_FATAL, "Insufficient key material or header text not found found in file '%s' (%d/%d/%d bytes found/min/max)",
- filename, count, onekeylen, keylen);
+ error_filename, count, onekeylen, keylen);
if (state != PARSE_FINISHED)
msg (M_FATAL, "Footer text not found in file '%s' (%d/%d/%d bytes found/min/max)",
- filename, count, onekeylen, keylen);
+ error_filename, count, onekeylen, keylen);
}
/* zero file read buffer */
buf_clear (&in);
if (key2->n)
- warn_if_group_others_accessible (filename);
+ warn_if_group_others_accessible (error_filename);
#if 0
/* DEBUGGING */
diff --git a/crypto.h b/crypto.h
index bf81595..e658e73 100644
--- a/crypto.h
+++ b/crypto.h
@@ -270,7 +270,9 @@ void init_key_type (struct key_type *kt, const char *ciphername,
bool authname_defined, int keysize,
bool cfb_ofb_allowed, bool warn);
-void read_key_file (struct key2 *key2, const char *filename, bool must_succeed);
+#define RKF_MUST_SUCCEED (1<<0)
+#define RKF_INLINE (1<<1)
+void read_key_file (struct key2 *key2, const char *file, const unsigned int flags);
int write_key_file (const int nkeys, const char *filename);
@@ -367,10 +369,12 @@ void openssl_dmalloc_init (void);
#ifdef USE_SSL
+#define GHK_KEY_DIR (1<<0)
+#define GHK_INLINE (1<<1)
void get_tls_handshake_key (const struct key_type *key_type,
struct key_ctx_bi *ctx,
const char *passphrase_file,
- bool key_direction);
+ const unsigned int flags);
#else
diff --git a/init.c b/init.c
index b4ff6cd..ea1acc3 100644
--- a/init.c
+++ b/init.c
@@ -1276,7 +1276,19 @@ do_init_crypto_static (struct context *c, const unsigned int flags)
options->test_crypto, true);
/* Read cipher and hmac keys from shared secret file */
- read_key_file (&key2, options->shared_secret_file, true);
+ {
+ unsigned int rkf_flags = RKF_MUST_SUCCEED;
+ const char *rkf_file = options->shared_secret_file;
+
+#if ENABLE_INLINE_FILES
+ if (options->shared_secret_file_inline)
+ {
+ rkf_file = options->shared_secret_file_inline;
+ rkf_flags |= RKF_INLINE;
+ }
+#endif
+ read_key_file (&key2, rkf_file, rkf_flags);
+ }
/* Check for and fix highly unlikely key problems */
verify_fix_key2 (&key2, &c->c1.ks.key_type,
@@ -1361,10 +1373,22 @@ do_init_crypto_tls_c1 (struct context *c)
/* TLS handshake authentication (--tls-auth) */
if (options->tls_auth_file)
- get_tls_handshake_key (&c->c1.ks.key_type,
- &c->c1.ks.tls_auth_key,
- options->tls_auth_file,
- options->key_direction);
+ {
+ unsigned int flags = options->key_direction ? GHK_KEY_DIR : 0;
+ const char *file = options->tls_auth_file;
+
+#if ENABLE_INLINE_FILES
+ if (options->tls_auth_file_inline)
+ {
+ flags |= GHK_INLINE;
+ file = options->tls_auth_file_inline;
+ }
+#endif
+ get_tls_handshake_key (&c->c1.ks.key_type,
+ &c->c1.ks.tls_auth_key,
+ file,
+ flags);
+ }
#if ENABLE_INLINE_FILES
if (options->priv_key_file_inline)
diff --git a/misc.c b/misc.c
index 349a608..6184208 100644
--- a/misc.c
+++ b/misc.c
@@ -433,15 +433,20 @@ void
warn_if_group_others_accessible (const char* filename)
{
#ifdef HAVE_STAT
- struct stat st;
- if (stat (filename, &st))
- {
- msg (M_WARN | M_ERRNO, "WARNING: cannot stat file '%s'", filename);
- }
- else
+#if ENABLE_INLINE_FILES
+ if (strcmp (filename, INLINE_FILE_TAG))
+#endif
{
- if (st.st_mode & (S_IRWXG|S_IRWXO))
- msg (M_WARN, "WARNING: file '%s' is group or others accessible", filename);
+ struct stat st;
+ if (stat (filename, &st))
+ {
+ msg (M_WARN | M_ERRNO, "WARNING: cannot stat file '%s'", filename);
+ }
+ else
+ {
+ if (st.st_mode & (S_IRWXG|S_IRWXO))
+ msg (M_WARN, "WARNING: file '%s' is group or others accessible", filename);
+ }
}
#endif
}
diff --git a/options.c b/options.c
index 72e2f4f..9e38da6 100644
--- a/options.c
+++ b/options.c
@@ -4538,9 +4538,26 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_GENERAL);
options->show_engines = true;
}
+ else if (streq (p[0], "key-direction") && p[1])
+ {
+ int key_direction;
+
+ key_direction = ascii2keydirection (msglevel, p[1]);
+ if (key_direction >= 0)
+ options->key_direction = key_direction;
+ else
+ goto err;
+ }
else if (streq (p[0], "secret") && p[1])
{
VERIFY_PERMISSION (OPT_P_GENERAL);
+#if ENABLE_INLINE_FILES
+ if (streq (p[1], INLINE_FILE_TAG) && p[2])
+ {
+ options->shared_secret_file_inline = p[2];
+ }
+ else
+#endif
if (p[2])
{
int key_direction;
@@ -4889,6 +4906,13 @@ add_option (struct options *options,
else if (streq (p[0], "tls-auth") && p[1])
{
VERIFY_PERMISSION (OPT_P_GENERAL);
+#if ENABLE_INLINE_FILES
+ if (streq (p[1], INLINE_FILE_TAG) && p[2])
+ {
+ options->tls_auth_file_inline = p[2];
+ }
+ else
+#endif
if (p[2])
{
int key_direction;
diff --git a/options.h b/options.h
index 3c3c202..21484b7 100644
--- a/options.h
+++ b/options.h
@@ -82,10 +82,6 @@ struct options_pre_pull
#endif
-#if ENABLE_INLINE_FILES
-#define INLINE_FILE_TAG "[[INLINE]]"
-#endif
-
/* Command line options */
struct options
{
@@ -356,6 +352,9 @@ struct options
#ifdef USE_CRYPTO
/* Cipher parms */
const char *shared_secret_file;
+#if ENABLE_INLINE_FILES
+ const char *shared_secret_file_inline;
+#endif
int key_direction;
bool ciphername_defined;
const char *ciphername;
@@ -433,6 +432,9 @@ struct options
/* Special authentication MAC for TLS control channel */
const char *tls_auth_file; /* shared secret */
+#if ENABLE_INLINE_FILES
+ const char *tls_auth_file_inline;
+#endif
/* Allow only one session */
bool single_session;