Browse code

Introduce buffer_write_file()

Rewrite buf_write_string_file to buffer_write_file, which is simpler to
use and can deal with not-null-terminated strings. Mostly implemented so
this can be easily reused for tls-crypt-v2 (client) key files.

Signed-off-by: Steffan Karger <steffan.karger@fox-it.com>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Tested-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <1533542553-7383-1-git-send-email-steffan.karger@fox-it.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg17371.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Steffan Karger authored on 2018/08/06 17:02:33
Showing 5 changed files
... ...
@@ -343,16 +343,33 @@ convert_to_one_line(struct buffer *buf)
343 343
     }
344 344
 }
345 345
 
346
-/* NOTE: requires that string be null terminated */
347
-void
348
-buf_write_string_file(const struct buffer *buf, const char *filename, int fd)
346
+bool
347
+buffer_write_file(const char *filename, const struct buffer *buf)
349 348
 {
350
-    const int len = strlen((char *) BPTR(buf));
351
-    const int size = write(fd, BPTR(buf), len);
352
-    if (size != len)
349
+    bool ret = false;
350
+    int fd = platform_open(filename, O_CREAT | O_TRUNC | O_WRONLY,
351
+                           S_IRUSR | S_IWUSR);
352
+    if (fd == -1)
353
+    {
354
+        msg(M_ERRNO, "Cannot open file '%s' for write", filename);
355
+        return false;
356
+    }
357
+
358
+    const int size = write(fd, BPTR(buf), BLEN(buf));
359
+    if (size != BLEN(buf))
353 360
     {
354
-        msg(M_ERR, "Write error on file '%s'", filename);
361
+        msg(M_ERRNO, "Write error on file '%s'", filename);
362
+        goto cleanup;
363
+    }
364
+
365
+    ret = true;
366
+cleanup:
367
+    if (close(fd) < 0)
368
+    {
369
+        msg(M_ERRNO, "Close error on file %s", filename);
370
+        ret = false;
355 371
     }
372
+    return ret;
356 373
 }
357 374
 
358 375
 /*
... ...
@@ -469,11 +469,15 @@ const char *skip_leading_whitespace(const char *str);
469 469
 
470 470
 void string_null_terminate(char *str, int len, int capacity);
471 471
 
472
-/*
473
- * Write string in buf to file descriptor fd.
474
- * NOTE: requires that string be null terminated.
472
+/**
473
+ * Write buffer contents to file.
474
+ *
475
+ * @param filename  The filename to write the buffer to.
476
+ * @param buf       The buffer to write to the file.
477
+ *
478
+ * @return true on success, false otherwise.
475 479
  */
476
-void buf_write_string_file(const struct buffer *buf, const char *filename, int fd);
480
+bool buffer_write_file(const char *filename, const struct buffer *buf);
477 481
 
478 482
 /*
479 483
  * write a string to the end of a buffer that was
... ...
@@ -1418,36 +1418,24 @@ read_key_file(struct key2 *key2, const char *file, const unsigned int flags)
1418 1418
     gc_free(&gc);
1419 1419
 }
1420 1420
 
1421
-/*
1422
- * Write key to file, return number of random bits
1423
- * written.
1424
- */
1425 1421
 int
1426 1422
 write_key_file(const int nkeys, const char *filename)
1427 1423
 {
1428 1424
     struct gc_arena gc = gc_new();
1429 1425
 
1430
-    int fd, i;
1431
-    int nbits = 0;
1426
+    int nbits = nkeys * sizeof(struct key) * 8;
1432 1427
 
1433 1428
     /* must be large enough to hold full key file */
1434 1429
     struct buffer out = alloc_buf_gc(2048, &gc);
1435
-    struct buffer nbits_head_text = alloc_buf_gc(128, &gc);
1436 1430
 
1437 1431
     /* how to format the ascii file representation of key */
1438 1432
     const int bytes_per_line = 16;
1439 1433
 
1440
-    /* open key file */
1441
-    fd = platform_open(filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
1442
-
1443
-    if (fd == -1)
1444
-    {
1445
-        msg(M_ERR, "Cannot open shared secret file '%s' for write", filename);
1446
-    }
1447
-
1434
+    /* write header */
1435
+    buf_printf(&out, "#\n# %d bit OpenVPN static key\n#\n", nbits);
1448 1436
     buf_printf(&out, "%s\n", static_key_head);
1449 1437
 
1450
-    for (i = 0; i < nkeys; ++i)
1438
+    for (int i = 0; i < nkeys; ++i)
1451 1439
     {
1452 1440
         struct key key;
1453 1441
         char *fmt;
... ...
@@ -1463,9 +1451,6 @@ write_key_file(const int nkeys, const char *filename)
1463 1463
                             "\n",
1464 1464
                             &gc);
1465 1465
 
1466
-        /* increment random bits counter */
1467
-        nbits += sizeof(key) * 8;
1468
-
1469 1466
         /* write to holding buffer */
1470 1467
         buf_printf(&out, "%s\n", fmt);
1471 1468
 
... ...
@@ -1476,16 +1461,10 @@ write_key_file(const int nkeys, const char *filename)
1476 1476
 
1477 1477
     buf_printf(&out, "%s\n", static_key_foot);
1478 1478
 
1479
-    /* write number of bits */
1480
-    buf_printf(&nbits_head_text, "#\n# %d bit OpenVPN static key\n#\n", nbits);
1481
-    buf_write_string_file(&nbits_head_text, filename, fd);
1482
-
1483 1479
     /* write key file, now formatted in out, to file */
1484
-    buf_write_string_file(&out, filename, fd);
1485
-
1486
-    if (close(fd))
1480
+    if(!buffer_write_file(filename, &out))
1487 1481
     {
1488
-        msg(M_ERR, "Close error on shared secret file %s", filename);
1482
+        nbits = -1;
1489 1483
     }
1490 1484
 
1491 1485
     /* zero memory which held file content (memory will be freed by GC) */
... ...
@@ -271,6 +271,11 @@ struct crypto_options
271 271
 #define RKF_INLINE       (1<<1)
272 272
 void read_key_file(struct key2 *key2, const char *file, const unsigned int flags);
273 273
 
274
+/**
275
+ * Write nkeys 1024-bits keys to file.
276
+ *
277
+ * @returns number of random bits written, or -1 on failure.
278
+ */
274 279
 int write_key_file(const int nkeys, const char *filename);
275 280
 
276 281
 int read_passphrase_hash(const char *passphrase_file,
... ...
@@ -1041,6 +1041,10 @@ do_genkey(const struct options *options)
1041 1041
         }
1042 1042
 
1043 1043
         nbits_written = write_key_file(2, options->shared_secret_file);
1044
+        if (nbits_written < 0)
1045
+        {
1046
+            msg(M_FATAL, "Failed to write key file");
1047
+        }
1044 1048
 
1045 1049
         msg(D_GENKEY | M_NOPREFIX,
1046 1050
             "Randomly generated %d bit key written to %s", nbits_written,