Merge branch 'bc/csprng-mktemps'
Pick a better random number generator and use it when we prepare temporary filenames. * bc/csprng-mktemps: wrapper: use a CSPRNG to generate random file names wrapper: add a helper to generate numbers from a CSPRNG
This commit is contained in:
commit
d073bdc6a0
34
Makefile
34
Makefile
@ -234,6 +234,14 @@ all::
|
||||
# Define NO_TRUSTABLE_FILEMODE if your filesystem may claim to support
|
||||
# the executable mode bit, but doesn't really do so.
|
||||
#
|
||||
# Define CSPRNG_METHOD to "arc4random" if your system has arc4random and
|
||||
# arc4random_buf, "libbsd" if your system has those functions from libbsd,
|
||||
# "getrandom" if your system has getrandom, "getentropy" if your system has
|
||||
# getentropy, "rtlgenrandom" for RtlGenRandom (Windows only), or "openssl" if
|
||||
# you'd want to use the OpenSSL CSPRNG. You may set multiple options with
|
||||
# spaces, in which case a suitable option will be chosen. If unset or set to
|
||||
# anything else, defaults to using "/dev/urandom".
|
||||
#
|
||||
# Define NEEDS_MODE_TRANSLATION if your OS strays from the typical file type
|
||||
# bits in mode values (e.g. z/OS defines I_SFMT to 0xFF000000 as opposed to the
|
||||
# usual 0xF000).
|
||||
@ -693,6 +701,7 @@ TEST_BUILTINS_OBJS += test-bloom.o
|
||||
TEST_BUILTINS_OBJS += test-chmtime.o
|
||||
TEST_BUILTINS_OBJS += test-config.o
|
||||
TEST_BUILTINS_OBJS += test-crontab.o
|
||||
TEST_BUILTINS_OBJS += test-csprng.o
|
||||
TEST_BUILTINS_OBJS += test-ctype.o
|
||||
TEST_BUILTINS_OBJS += test-date.o
|
||||
TEST_BUILTINS_OBJS += test-delta.o
|
||||
@ -1909,6 +1918,31 @@ ifdef HAVE_GETDELIM
|
||||
BASIC_CFLAGS += -DHAVE_GETDELIM
|
||||
endif
|
||||
|
||||
ifneq ($(findstring arc4random,$(CSPRNG_METHOD)),)
|
||||
BASIC_CFLAGS += -DHAVE_ARC4RANDOM
|
||||
endif
|
||||
|
||||
ifneq ($(findstring libbsd,$(CSPRNG_METHOD)),)
|
||||
BASIC_CFLAGS += -DHAVE_ARC4RANDOM_LIBBSD
|
||||
EXTLIBS += -lbsd
|
||||
endif
|
||||
|
||||
ifneq ($(findstring getrandom,$(CSPRNG_METHOD)),)
|
||||
BASIC_CFLAGS += -DHAVE_GETRANDOM
|
||||
endif
|
||||
|
||||
ifneq ($(findstring getentropy,$(CSPRNG_METHOD)),)
|
||||
BASIC_CFLAGS += -DHAVE_GETENTROPY
|
||||
endif
|
||||
|
||||
ifneq ($(findstring rtlgenrandom,$(CSPRNG_METHOD)),)
|
||||
BASIC_CFLAGS += -DHAVE_RTLGENRANDOM
|
||||
endif
|
||||
|
||||
ifneq ($(findstring openssl,$(CSPRNG_METHOD)),)
|
||||
BASIC_CFLAGS += -DHAVE_OPENSSL_CSPRNG
|
||||
endif
|
||||
|
||||
ifneq ($(PROCFS_EXECUTABLE_PATH),)
|
||||
procfs_executable_path_SQ = $(subst ','\'',$(PROCFS_EXECUTABLE_PATH))
|
||||
BASIC_CFLAGS += '-DPROCFS_EXECUTABLE_PATH="$(procfs_executable_path_SQ)"'
|
||||
|
@ -3,6 +3,12 @@
|
||||
*/
|
||||
|
||||
#undef NOGDI
|
||||
|
||||
/*
|
||||
* Including the appropriate header file for RtlGenRandom causes MSVC to see a
|
||||
* redefinition of types in an incompatible way when including headers below.
|
||||
*/
|
||||
#undef HAVE_RTLGENRANDOM
|
||||
#include "../git-compat-util.h"
|
||||
#include <wingdi.h>
|
||||
#include <winreg.h>
|
||||
|
@ -146,6 +146,7 @@ ifeq ($(uname_S),Darwin)
|
||||
HAVE_BSD_SYSCTL = YesPlease
|
||||
FREAD_READS_DIRECTORIES = UnfortunatelyYes
|
||||
HAVE_NS_GET_EXECUTABLE_PATH = YesPlease
|
||||
CSPRNG_METHOD = arc4random
|
||||
|
||||
# Workaround for `gettext` being keg-only and not even being linked via
|
||||
# `brew link --force gettext`, should be obsolete as of
|
||||
@ -261,6 +262,7 @@ ifeq ($(uname_S),FreeBSD)
|
||||
HAVE_PATHS_H = YesPlease
|
||||
HAVE_BSD_SYSCTL = YesPlease
|
||||
HAVE_BSD_KERN_PROC_SYSCTL = YesPlease
|
||||
CSPRNG_METHOD = arc4random
|
||||
PAGER_ENV = LESS=FRX LV=-c MORE=FRX
|
||||
FREAD_READS_DIRECTORIES = UnfortunatelyYes
|
||||
FILENO_IS_A_MACRO = UnfortunatelyYes
|
||||
@ -279,6 +281,7 @@ ifeq ($(uname_S),OpenBSD)
|
||||
HAVE_PATHS_H = YesPlease
|
||||
HAVE_BSD_SYSCTL = YesPlease
|
||||
HAVE_BSD_KERN_PROC_SYSCTL = YesPlease
|
||||
CSPRNG_METHOD = arc4random
|
||||
PROCFS_EXECUTABLE_PATH = /proc/curproc/file
|
||||
FREAD_READS_DIRECTORIES = UnfortunatelyYes
|
||||
FILENO_IS_A_MACRO = UnfortunatelyYes
|
||||
@ -290,6 +293,7 @@ ifeq ($(uname_S),MirBSD)
|
||||
NEEDS_LIBICONV = YesPlease
|
||||
HAVE_PATHS_H = YesPlease
|
||||
HAVE_BSD_SYSCTL = YesPlease
|
||||
CSPRNG_METHOD = arc4random
|
||||
endif
|
||||
ifeq ($(uname_S),NetBSD)
|
||||
ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2)
|
||||
@ -301,6 +305,7 @@ ifeq ($(uname_S),NetBSD)
|
||||
HAVE_PATHS_H = YesPlease
|
||||
HAVE_BSD_SYSCTL = YesPlease
|
||||
HAVE_BSD_KERN_PROC_SYSCTL = YesPlease
|
||||
CSPRNG_METHOD = arc4random
|
||||
PROCFS_EXECUTABLE_PATH = /proc/curproc/exe
|
||||
endif
|
||||
ifeq ($(uname_S),AIX)
|
||||
@ -430,6 +435,7 @@ ifeq ($(uname_S),Windows)
|
||||
NO_STRTOUMAX = YesPlease
|
||||
NO_MKDTEMP = YesPlease
|
||||
NO_INTTYPES_H = YesPlease
|
||||
CSPRNG_METHOD = rtlgenrandom
|
||||
# VS2015 with UCRT claims that snprintf and friends are C99 compliant,
|
||||
# so we don't need this:
|
||||
#
|
||||
@ -599,6 +605,7 @@ ifeq ($(uname_S),NONSTOP_KERNEL)
|
||||
NO_MMAP = YesPlease
|
||||
NO_POLL = YesPlease
|
||||
NO_INTPTR_T = UnfortunatelyYes
|
||||
CSPRNG_METHOD = openssl
|
||||
SANE_TOOL_PATH = /usr/coreutils/bin:/usr/local/bin
|
||||
SHELL_PATH = /usr/coreutils/bin/bash
|
||||
endif
|
||||
@ -634,6 +641,7 @@ ifeq ($(uname_S),MINGW)
|
||||
NO_POSIX_GOODIES = UnfortunatelyYes
|
||||
DEFAULT_HELP_FORMAT = html
|
||||
HAVE_PLATFORM_PROCINFO = YesPlease
|
||||
CSPRNG_METHOD = rtlgenrandom
|
||||
BASIC_LDFLAGS += -municode
|
||||
COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
|
||||
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
|
||||
|
@ -260,7 +260,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
_CONSOLE DETECT_MSYS_TTY STRIP_EXTENSION=".exe" NO_SYMLINK_HEAD UNRELIABLE_FSTAT
|
||||
NOGDI OBJECT_CREATION_MODE=1 __USE_MINGW_ANSI_STDIO=0
|
||||
USE_NED_ALLOCATOR OVERRIDE_STRDUP MMAP_PREVENTS_DELETE USE_WIN32_MMAP
|
||||
UNICODE _UNICODE HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET)
|
||||
UNICODE _UNICODE HAVE_WPGMPTR ENSURE_MSYSTEM_IS_SET HAVE_RTLGENRANDOM)
|
||||
list(APPEND compat_SOURCES compat/mingw.c compat/winansi.c compat/win32/path-utils.c
|
||||
compat/win32/pthread.c compat/win32mmap.c compat/win32/syslog.c
|
||||
compat/win32/trace2_win32_process_info.c compat/win32/dirent.c
|
||||
|
@ -197,6 +197,12 @@
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#define GIT_WINDOWS_NATIVE
|
||||
#ifdef HAVE_RTLGENRANDOM
|
||||
/* This is required to get access to RtlGenRandom. */
|
||||
#define SystemFunction036 NTAPI SystemFunction036
|
||||
#include <NTSecAPI.h>
|
||||
#undef SystemFunction036
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
@ -267,6 +273,12 @@
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARC4RANDOM_LIBBSD
|
||||
#include <bsd/stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_GETRANDOM
|
||||
#include <sys/random.h>
|
||||
#endif
|
||||
#ifdef NO_INTPTR_T
|
||||
/*
|
||||
* On I16LP32, ILP32 and LP64 "long" is the safe bet, however
|
||||
@ -1432,4 +1444,11 @@ static inline void *container_of_or_null_offset(void *ptr, size_t offset)
|
||||
|
||||
void sleep_millisec(int millisec);
|
||||
|
||||
/*
|
||||
* Generate len bytes from the system cryptographically secure PRNG.
|
||||
* Returns 0 on success and -1 on error, setting errno. The inability to
|
||||
* satisfy the full request is an error.
|
||||
*/
|
||||
int csprng_bytes(void *buf, size_t len);
|
||||
|
||||
#endif
|
||||
|
29
t/helper/test-csprng.c
Normal file
29
t/helper/test-csprng.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include "test-tool.h"
|
||||
#include "git-compat-util.h"
|
||||
|
||||
|
||||
int cmd__csprng(int argc, const char **argv)
|
||||
{
|
||||
unsigned long count;
|
||||
unsigned char buf[1024];
|
||||
|
||||
if (argc > 2) {
|
||||
fprintf(stderr, "usage: %s [<size>]\n", argv[0]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
count = (argc == 2) ? strtoul(argv[1], NULL, 0) : -1L;
|
||||
|
||||
while (count) {
|
||||
unsigned long chunk = count < sizeof(buf) ? count : sizeof(buf);
|
||||
if (csprng_bytes(buf, chunk) < 0) {
|
||||
perror("failed to read");
|
||||
return 5;
|
||||
}
|
||||
if (fwrite(buf, chunk, 1, stdout) != chunk)
|
||||
return 1;
|
||||
count -= chunk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -20,6 +20,7 @@ static struct test_cmd cmds[] = {
|
||||
{ "chmtime", cmd__chmtime },
|
||||
{ "config", cmd__config },
|
||||
{ "crontab", cmd__crontab },
|
||||
{ "csprng", cmd__csprng },
|
||||
{ "ctype", cmd__ctype },
|
||||
{ "date", cmd__date },
|
||||
{ "delta", cmd__delta },
|
||||
|
@ -10,6 +10,7 @@ int cmd__bloom(int argc, const char **argv);
|
||||
int cmd__chmtime(int argc, const char **argv);
|
||||
int cmd__config(int argc, const char **argv);
|
||||
int cmd__crontab(int argc, const char **argv);
|
||||
int cmd__csprng(int argc, const char **argv);
|
||||
int cmd__ctype(int argc, const char **argv);
|
||||
int cmd__date(int argc, const char **argv);
|
||||
int cmd__delta(int argc, const char **argv);
|
||||
|
81
wrapper.c
81
wrapper.c
@ -463,8 +463,6 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode)
|
||||
static const int num_letters = ARRAY_SIZE(letters) - 1;
|
||||
static const char x_pattern[] = "XXXXXX";
|
||||
static const int num_x = ARRAY_SIZE(x_pattern) - 1;
|
||||
uint64_t value;
|
||||
struct timeval tv;
|
||||
char *filename_template;
|
||||
size_t len;
|
||||
int fd, count;
|
||||
@ -485,12 +483,13 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode)
|
||||
* Replace pattern's XXXXXX characters with randomness.
|
||||
* Try TMP_MAX different filenames.
|
||||
*/
|
||||
gettimeofday(&tv, NULL);
|
||||
value = ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec ^ getpid();
|
||||
filename_template = &pattern[len - num_x - suffix_len];
|
||||
for (count = 0; count < TMP_MAX; ++count) {
|
||||
uint64_t v = value;
|
||||
int i;
|
||||
uint64_t v;
|
||||
if (csprng_bytes(&v, sizeof(v)) < 0)
|
||||
return error_errno("unable to get random bytes for temporary file");
|
||||
|
||||
/* Fill in the random bits. */
|
||||
for (i = 0; i < num_x; i++) {
|
||||
filename_template[i] = letters[v % num_letters];
|
||||
@ -506,12 +505,6 @@ int git_mkstemps_mode(char *pattern, int suffix_len, int mode)
|
||||
*/
|
||||
if (errno != EEXIST)
|
||||
break;
|
||||
/*
|
||||
* This is a random value. It is only necessary that
|
||||
* the next TMP_MAX values generated by adding 7777 to
|
||||
* VALUE are different with (module 2^32).
|
||||
*/
|
||||
value += 7777;
|
||||
}
|
||||
/* We return the null string if we can't find a unique file name. */
|
||||
pattern[0] = '\0';
|
||||
@ -702,3 +695,69 @@ int open_nofollow(const char *path, int flags)
|
||||
return open(path, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
int csprng_bytes(void *buf, size_t len)
|
||||
{
|
||||
#if defined(HAVE_ARC4RANDOM) || defined(HAVE_ARC4RANDOM_LIBBSD)
|
||||
/* This function never returns an error. */
|
||||
arc4random_buf(buf, len);
|
||||
return 0;
|
||||
#elif defined(HAVE_GETRANDOM)
|
||||
ssize_t res;
|
||||
char *p = buf;
|
||||
while (len) {
|
||||
res = getrandom(p, len, 0);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
len -= res;
|
||||
p += res;
|
||||
}
|
||||
return 0;
|
||||
#elif defined(HAVE_GETENTROPY)
|
||||
int res;
|
||||
char *p = buf;
|
||||
while (len) {
|
||||
/* getentropy has a maximum size of 256 bytes. */
|
||||
size_t chunk = len < 256 ? len : 256;
|
||||
res = getentropy(p, chunk);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
len -= chunk;
|
||||
p += chunk;
|
||||
}
|
||||
return 0;
|
||||
#elif defined(HAVE_RTLGENRANDOM)
|
||||
if (!RtlGenRandom(buf, len))
|
||||
return -1;
|
||||
return 0;
|
||||
#elif defined(HAVE_OPENSSL_CSPRNG)
|
||||
int res = RAND_bytes(buf, len);
|
||||
if (res == 1)
|
||||
return 0;
|
||||
if (res == -1)
|
||||
errno = ENOTSUP;
|
||||
else
|
||||
errno = EIO;
|
||||
return -1;
|
||||
#else
|
||||
ssize_t res;
|
||||
char *p = buf;
|
||||
int fd, err;
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
while (len) {
|
||||
res = xread(fd, p, len);
|
||||
if (res < 0) {
|
||||
err = errno;
|
||||
close(fd);
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
len -= res;
|
||||
p += res;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user