From patchwork Sun Aug 5 22:02:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steffan Karger X-Patchwork-Id: 438 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net (Dovecot) with LMTP id 2whzOFsBaFtabAAAIUCqbw for ; Mon, 06 Aug 2018 04:05:47 -0400 Received: from proxy15.mail.ord1d.rsapps.net ([172.30.191.6]) by director7.mail.ord1d.rsapps.net (Dovecot) with LMTP id p48YC1sBaFs4DgAAovjBpQ ; Mon, 06 Aug 2018 04:05:47 -0400 Received: from smtp7.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy15.mail.ord1d.rsapps.net with LMTP id kPUPOFsBaFuRZgAAAY1PeQ ; Mon, 06 Aug 2018 04:05:47 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp7.gate.ord1d.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=fox-it.com X-Suspicious-Flag: YES X-Classification-ID: 867a1d8c-994f-11e8-8664-525400d28ed9-1-1 Received: from [216.105.38.7] ([216.105.38.7:46814] helo=lists.sourceforge.net) by smtp7.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 66/F3-26547-B51086B5; Mon, 06 Aug 2018 04:05:47 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1fmaVU-0006L6-8d; Mon, 06 Aug 2018 08:04:48 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1fmaVO-0006Kz-5t for openvpn-devel@lists.sourceforge.net; Mon, 06 Aug 2018 08:04:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Type:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=3d4wiss5YVts++d0lXqd9YsA4yxbDaF5bL/Pf44FP1g=; b=VCxfSHXDDfKU1MGfLcSr+r+Zj2 LAM1G2pmGTxnZ9c5eLxGLUiuc9A7CA3w9v8CDzyB4RqbhV+6UhaKiskAyYaHBvA2DH0Wg4fxRVlKI gw5WyV1BBvTKncqg7YkZjzOuVpPWrVKVz4/4PpWbUIo1gjpeS5inIxHrhq/ZDe9ZMrs8=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject: CC:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=3d4wiss5YVts++d0lXqd9YsA4yxbDaF5bL/Pf44FP1g=; b=WyyQvxPMwobrK4LysurW4ebvri ouCz45dhn5OirmMAA+7NoA1LAVcCypwm8SZAOzYaivskKaUHwi1Ucx6DL8hVzh6ozPI4+S2lPaYOL 0doGpvRer4AtD57wlRHj+NiCzkiCw16WWnLNKnvE1NvWCJz3pCCDQIkniEACEXYrkNV8=; Received: from ns2.fox-it.com ([178.250.144.131]) by sfi-mx-3.v28.lw.sourceforge.com with esmtps (TLSv1:ECDHE-RSA-AES256-SHA:256) (Exim 4.90_1) id 1fmaVM-009VCO-GO for openvpn-devel@lists.sourceforge.net; Mon, 06 Aug 2018 08:04:42 +0000 Received: from FOXDFT52.FOX.local (unknown [10.0.0.129]) by ns2.fox-it.com (Postfix) with ESMTPS id 5CC7E1AF843 for ; Mon, 6 Aug 2018 10:04:32 +0200 (CEST) Received: from steffan-fox.fox.local (10.0.3.178) by FOXDFT52.FOX.local (10.0.0.129) with Microsoft SMTP Server (TLS) id 15.0.1293.2; Mon, 6 Aug 2018 10:04:32 +0200 From: Steffan Karger To: Date: Mon, 6 Aug 2018 10:02:33 +0200 Message-ID: <1533542553-7383-1-git-send-email-steffan.karger@fox-it.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <4ff9b515-b65c-ddb4-30e5-03660cd9f245@unstable.cc> References: <4ff9b515-b65c-ddb4-30e5-03660cd9f245@unstable.cc> MIME-Version: 1.0 X-ClientProxiedBy: FOXDFT52.FOX.local (10.0.0.129) To FOXDFT52.FOX.local (10.0.0.129) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -0.0 SPF_PASS SPF: sender matches SPF record X-Headers-End: 1fmaVM-009VCO-GO Subject: [Openvpn-devel] [PATCH v5 1/7] Introduce buffer_write_file() X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox 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 Acked-by: Antonio Quartulli Tested-by: Antonio Quartulli --- v3: split change out of "generate client key", reuse in write_key_file() v4: improve doxygen and error handling (thanks to ordex) v5: do not print close error if open fails (thanks to ordex) src/openvpn/buffer.c | 31 ++++++++++++++++++++++++------- src/openvpn/buffer.h | 12 ++++++++---- src/openvpn/crypto.c | 33 ++++++--------------------------- src/openvpn/crypto.h | 5 +++++ src/openvpn/init.c | 4 ++++ 5 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c index 0972139..7630ff7 100644 --- a/src/openvpn/buffer.c +++ b/src/openvpn/buffer.c @@ -343,16 +343,33 @@ convert_to_one_line(struct buffer *buf) } } -/* NOTE: requires that string be null terminated */ -void -buf_write_string_file(const struct buffer *buf, const char *filename, int fd) +bool +buffer_write_file(const char *filename, const struct buffer *buf) { - const int len = strlen((char *) BPTR(buf)); - const int size = write(fd, BPTR(buf), len); - if (size != len) + bool ret = false; + int fd = platform_open(filename, O_CREAT | O_TRUNC | O_WRONLY, + S_IRUSR | S_IWUSR); + if (fd == -1) + { + msg(M_ERRNO, "Cannot open file '%s' for write", filename); + return false; + } + + const int size = write(fd, BPTR(buf), BLEN(buf)); + if (size != BLEN(buf)) { - msg(M_ERR, "Write error on file '%s'", filename); + msg(M_ERRNO, "Write error on file '%s'", filename); + goto cleanup; + } + + ret = true; +cleanup: + if (close(fd) < 0) + { + msg(M_ERRNO, "Close error on file %s", filename); + ret = false; } + return ret; } /* diff --git a/src/openvpn/buffer.h b/src/openvpn/buffer.h index 6b6025e..704129a 100644 --- a/src/openvpn/buffer.h +++ b/src/openvpn/buffer.h @@ -469,11 +469,15 @@ const char *skip_leading_whitespace(const char *str); void string_null_terminate(char *str, int len, int capacity); -/* - * Write string in buf to file descriptor fd. - * NOTE: requires that string be null terminated. +/** + * Write buffer contents to file. + * + * @param filename The filename to write the buffer to. + * @param buf Thu buffer to write to the file. + * + * @return true on success, false otherwise. */ -void buf_write_string_file(const struct buffer *buf, const char *filename, int fd); +bool buffer_write_file(const char *filename, const struct buffer *buf); /* * write a string to the end of a buffer that was diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index 5381ef2..c8d95f3 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -1418,36 +1418,24 @@ read_key_file(struct key2 *key2, const char *file, const unsigned int flags) gc_free(&gc); } -/* - * Write key to file, return number of random bits - * written. - */ int write_key_file(const int nkeys, const char *filename) { struct gc_arena gc = gc_new(); - int fd, i; - int nbits = 0; + int nbits = nkeys * sizeof(struct key) * 8; /* must be large enough to hold full key file */ struct buffer out = alloc_buf_gc(2048, &gc); - struct buffer nbits_head_text = alloc_buf_gc(128, &gc); /* how to format the ascii file representation of key */ const int bytes_per_line = 16; - /* open key file */ - fd = platform_open(filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR); - - if (fd == -1) - { - msg(M_ERR, "Cannot open shared secret file '%s' for write", filename); - } - + /* write header */ + buf_printf(&out, "#\n# %d bit OpenVPN static key\n#\n", nbits); buf_printf(&out, "%s\n", static_key_head); - for (i = 0; i < nkeys; ++i) + for (int i = 0; i < nkeys; ++i) { struct key key; char *fmt; @@ -1463,9 +1451,6 @@ write_key_file(const int nkeys, const char *filename) "\n", &gc); - /* increment random bits counter */ - nbits += sizeof(key) * 8; - /* write to holding buffer */ buf_printf(&out, "%s\n", fmt); @@ -1476,16 +1461,10 @@ write_key_file(const int nkeys, const char *filename) buf_printf(&out, "%s\n", static_key_foot); - /* write number of bits */ - buf_printf(&nbits_head_text, "#\n# %d bit OpenVPN static key\n#\n", nbits); - buf_write_string_file(&nbits_head_text, filename, fd); - /* write key file, now formatted in out, to file */ - buf_write_string_file(&out, filename, fd); - - if (close(fd)) + if(!buffer_write_file(filename, &out)) { - msg(M_ERR, "Close error on shared secret file %s", filename); + nbits = -1; } /* zero memory which held file content (memory will be freed by GC) */ diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h index 9417fa1..0dc597f 100644 --- a/src/openvpn/crypto.h +++ b/src/openvpn/crypto.h @@ -271,6 +271,11 @@ struct crypto_options #define RKF_INLINE (1<<1) void read_key_file(struct key2 *key2, const char *file, const unsigned int flags); +/** + * Write nkeys 1024-bits keys to file. + * + * @returns number of random bits written, or -1 on failure. + */ int write_key_file(const int nkeys, const char *filename); int read_passphrase_hash(const char *passphrase_file, diff --git a/src/openvpn/init.c b/src/openvpn/init.c index f432106..2933d55 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -1041,6 +1041,10 @@ do_genkey(const struct options *options) } nbits_written = write_key_file(2, options->shared_secret_file); + if (nbits_written < 0) + { + msg(M_FATAL, "Failed to write key file"); + } msg(D_GENKEY | M_NOPREFIX, "Randomly generated %d bit key written to %s", nbits_written,