Replace CMake with GNU Make.
There was previously support for both build systems, but ndhc is undemanding and there is no point in maintaining a complex CMake build.
This commit is contained in:
18
nk/copy_cmdarg.h
Normal file
18
nk/copy_cmdarg.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef NCMLIB_COPY_CMDARG_H_
|
||||
#define NCMLIB_COPY_CMDARG_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "nk/log.h"
|
||||
|
||||
static inline void copy_cmdarg(char *dest, const char *src,
|
||||
size_t destlen, const char *argname)
|
||||
{
|
||||
ssize_t olen = snprintf(dest, destlen, "%s", src);
|
||||
if (olen < 0)
|
||||
suicide("snprintf failed on %s; your system is broken?", argname);
|
||||
if ((size_t)olen >= destlen)
|
||||
suicide("snprintf would truncate %s arg; it's too long", argname);
|
||||
}
|
||||
|
||||
#endif /* NCMLIB_COPY_CMDARG_H_ */
|
128
nk/hwrng.c
Normal file
128
nk/hwrng.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/* hwrng.c - access to system CRNG
|
||||
*
|
||||
* Copyright 2013-2018 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "nk/hwrng.h"
|
||||
#include "nk/log.h"
|
||||
#include "nk/io.h"
|
||||
|
||||
#ifdef NK_USE_GETRANDOM_SYSCALL
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/random.h>
|
||||
static bool nk_getrandom(char *seed, size_t len)
|
||||
{
|
||||
size_t fetched = 0;
|
||||
while (fetched < len) {
|
||||
int r = syscall(SYS_getrandom, seed + fetched, len - fetched, 0);
|
||||
if (r <= 0) {
|
||||
if (r == 0) {
|
||||
// Failsafe to guard against infinite loops.
|
||||
log_line("%s: getrandom() returned no entropy", __func__);
|
||||
return false;
|
||||
}
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
log_line("%s: getrandom() failed: %s", __func__, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
fetched += (size_t)r;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static bool nk_getrandom(char *seed, size_t len)
|
||||
{
|
||||
(void)seed;
|
||||
(void)len;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
static bool nk_get_rnd_clk(char *seed, size_t len)
|
||||
{
|
||||
struct timespec ts;
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
int r = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
if (r < 0) {
|
||||
log_line("%s: Could not call clock_gettime(CLOCK_REALTIME): %s",
|
||||
__func__, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
char *p = (char *)&ts.tv_sec;
|
||||
char *q = (char *)&ts.tv_nsec;
|
||||
for (size_t j = 0; j < sizeof ts.tv_sec; ++j)
|
||||
seed[i] ^= p[j];
|
||||
for (size_t j = 0; j < sizeof ts.tv_nsec; ++j)
|
||||
seed[i] ^= q[j];
|
||||
// Force some scheduler jitter.
|
||||
static const struct timespec st = { .tv_sec=0, .tv_nsec=1 };
|
||||
nanosleep(&st, (struct timespec *)0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool nk_get_urandom(char *seed, size_t len)
|
||||
{
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
log_line("%s: Could not open /dev/urandom: %s", __func__,
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
bool ret = true;
|
||||
int r = safe_read(fd, seed, len);
|
||||
if (r < 0) {
|
||||
ret = false;
|
||||
log_line("%s: Could not read /dev/urandom: %s",
|
||||
__func__, strerror(errno));
|
||||
}
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void nk_get_hwrng(void *seed, size_t len)
|
||||
{
|
||||
char *s = (char *)seed;
|
||||
if (nk_getrandom(s, len))
|
||||
return;
|
||||
if (nk_get_urandom(s, len))
|
||||
return;
|
||||
log_line("%s: Seeding PRNG via system clock. May be predictable.",
|
||||
__func__);
|
||||
if (nk_get_rnd_clk(s, len))
|
||||
return;
|
||||
suicide("%s: All methods to seed PRNG failed. Exiting.", __func__);
|
||||
}
|
||||
|
37
nk/hwrng.h
Normal file
37
nk/hwrng.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* hwrng.h - access to system CRNG
|
||||
*
|
||||
* Copyright 2016 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef NCMLIB_HWCRNG__
|
||||
#define NCMLIB_HWCRNG__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void nk_get_hwrng(void *seed, size_t len);
|
||||
|
||||
#endif
|
||||
|
||||
|
140
nk/io.c
Normal file
140
nk/io.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/* io.c - light wrappers for POSIX i/o functions
|
||||
*
|
||||
* Copyright 2010-2018 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include "nk/io.h"
|
||||
#include <limits.h>
|
||||
|
||||
// POSIX says read/write/etc() with len param > SSIZE_MAX is implementation defined.
|
||||
// So we avoid implementation-defined behavior with the bounding in each safe_* fn.
|
||||
|
||||
/* returns -1 on error, >= 0 and equal to # chars read on success */
|
||||
ssize_t safe_read(int fd, char *buf, size_t len)
|
||||
{
|
||||
size_t s = 0;
|
||||
if (len > SSIZE_MAX) len = SSIZE_MAX;
|
||||
while (s < len) {
|
||||
ssize_t r = read(fd, buf + s, len - s);
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else if ((errno == EAGAIN || errno == EWOULDBLOCK) && s > 0)
|
||||
return (ssize_t)s;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
s += (size_t)r;
|
||||
}
|
||||
return (ssize_t)s;
|
||||
}
|
||||
|
||||
/* returns -1 on error, >= 0 and equal to # chars written on success */
|
||||
ssize_t safe_write(int fd, const char *buf, size_t len)
|
||||
{
|
||||
size_t s = 0;
|
||||
if (len > SSIZE_MAX) len = SSIZE_MAX;
|
||||
while (s < len) {
|
||||
ssize_t r = write(fd, buf + s, len - s);
|
||||
if (r < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else if ((errno == EAGAIN || errno == EWOULDBLOCK) && s > 0)
|
||||
return (ssize_t)s;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
s += (size_t)r;
|
||||
}
|
||||
return (ssize_t)s;
|
||||
}
|
||||
|
||||
/* returns -1 on error, >= 0 and equal to # chars written on success */
|
||||
ssize_t safe_sendto(int fd, const char *buf, size_t len, int flags,
|
||||
const struct sockaddr *dest_addr, socklen_t addrlen)
|
||||
{
|
||||
size_t s = 0;
|
||||
if (len > SSIZE_MAX) len = SSIZE_MAX;
|
||||
while (s < len) {
|
||||
ssize_t r = sendto(fd, buf + s, len - s, flags, dest_addr, addrlen);
|
||||
if (r < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else if ((errno == EAGAIN || errno == EWOULDBLOCK) && s > 0)
|
||||
return (ssize_t)s;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
s += (size_t)r;
|
||||
}
|
||||
return (ssize_t)s;
|
||||
}
|
||||
|
||||
ssize_t safe_recv(int fd, char *buf, size_t len, int flags)
|
||||
{
|
||||
size_t s = 0;
|
||||
if (len > SSIZE_MAX) len = SSIZE_MAX;
|
||||
while (s < len) {
|
||||
ssize_t r = recv(fd, buf + s, len - s, flags);
|
||||
if (r == 0)
|
||||
break;
|
||||
if (r < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else if ((errno == EAGAIN || errno == EWOULDBLOCK) && s > 0)
|
||||
return (ssize_t)s;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
s += (size_t)r;
|
||||
}
|
||||
return (ssize_t)s;
|
||||
}
|
||||
|
||||
ssize_t safe_recvmsg(int fd, struct msghdr *msg, int flags)
|
||||
{
|
||||
ssize_t r;
|
||||
for (;;) {
|
||||
r = recvmsg(fd, msg, flags);
|
||||
if (r >= 0 || errno != EINTR) break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int safe_ftruncate(int fd, off_t length)
|
||||
{
|
||||
int r;
|
||||
for (;;) {
|
||||
r = ftruncate(fd, length);
|
||||
if (!r || errno != EINTR) break;
|
||||
}
|
||||
return r;
|
||||
}
|
42
nk/io.h
Normal file
42
nk/io.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* io.h - light wrappers for POSIX i/o functions
|
||||
*
|
||||
* Copyright 2010-2015 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NCM_IO_H_
|
||||
#define NCM_IO_H_
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
ssize_t safe_read(int fd, char *buf, size_t len);
|
||||
ssize_t safe_write(int fd, const char *buf, size_t len);
|
||||
ssize_t safe_sendto(int fd, const char *buf, size_t len, int flags,
|
||||
const struct sockaddr *dest_addr, socklen_t addrlen);
|
||||
ssize_t safe_recv(int fd, char *buf, size_t len, int flags);
|
||||
ssize_t safe_recvmsg(int fd, struct msghdr *msg, int flags);
|
||||
int safe_ftruncate(int fd, off_t length);
|
||||
|
||||
#endif /* NCM_IO_H_ */
|
53
nk/log.h
Normal file
53
nk/log.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* log.h - simple logging support
|
||||
*
|
||||
* Copyright 2003-2020 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NCM_LOG_H_
|
||||
#define NCM_LOG_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define log_line(...) do { \
|
||||
dprintf(2, __VA_ARGS__); \
|
||||
dprintf(2, "\n"); } while (0)
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define log_debug(...) do { \
|
||||
dprintf(2, __VA_ARGS__); \
|
||||
dprintf(2, "\n"); } while (0)
|
||||
#else
|
||||
#define log_debug(...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define suicide(...) do { \
|
||||
dprintf(2, __VA_ARGS__); \
|
||||
dprintf(2, "\n"); \
|
||||
exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
#endif
|
||||
|
57
nk/net_checksum16.h
Normal file
57
nk/net_checksum16.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef NCMLIB_NET_CHECKSUM16_H
|
||||
#define NCMLIB_NET_CHECKSUM16_H
|
||||
|
||||
// RFC 1071 is still a good reference.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// When summing ones-complement 16-bit values using a 32-bit unsigned
|
||||
// representation, fold the carry bits that have spilled into the upper
|
||||
// 16-bits of the 32-bit unsigned value back into the 16-bit ones-complement
|
||||
// binary value.
|
||||
static inline uint16_t net_checksum16_foldcarry(uint32_t v)
|
||||
{
|
||||
v = (v >> 16) + (v & 0xffff);
|
||||
v += v >> 16;
|
||||
return v;
|
||||
}
|
||||
|
||||
// Produces the correct result on little endian in the sense that
|
||||
// the binary value returned, when stored to memory, will match
|
||||
// the result on big endian; if the numeric value returned
|
||||
// must match big endian results, then call ntohs() on the result.
|
||||
static uint16_t net_checksum16(const void *buf, size_t size)
|
||||
{
|
||||
const char *b = (const char *)buf;
|
||||
const char *bend = b + size;
|
||||
uint32_t sum = 0, t = 0;
|
||||
uint8_t z[4] = { 0 };
|
||||
switch (size & 3) {
|
||||
case 3: z[2] = (uint8_t)*--bend;
|
||||
case 2: z[1] = (uint8_t)*--bend;
|
||||
case 1: z[0] = (uint8_t)*--bend;
|
||||
default: break;
|
||||
}
|
||||
memcpy(&t, z, 4);
|
||||
sum += t & 0xffffu;
|
||||
sum += (t >> 16);
|
||||
for (; b < bend; b += 4) {
|
||||
memcpy(&t, b, 4);
|
||||
sum += t & 0xffffu;
|
||||
sum += (t >> 16);
|
||||
}
|
||||
return ~net_checksum16_foldcarry(sum);
|
||||
}
|
||||
|
||||
// For two sequences of bytes A and B that return checksums CS(A) and CS(B),
|
||||
// this function will calculate the checksum CS(AB) of the concatenated value
|
||||
// AB given the checksums of the individual parts CS(A) and CS(B).
|
||||
static inline uint16_t net_checksum16_add(uint16_t a, uint16_t b)
|
||||
{
|
||||
const uint32_t A = a;
|
||||
const uint32_t B = b;
|
||||
return ~net_checksum16_foldcarry((~A & 0xffffu) + (~B & 0xffffu));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
224
nk/privs.c
Normal file
224
nk/privs.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/* privs.c - uid/gid, chroot, and capability handling
|
||||
*
|
||||
* Copyright 2005-2018 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#ifdef __linux__
|
||||
#include <sys/capability.h>
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
#include "nk/privs.h"
|
||||
#include "nk/log.h"
|
||||
|
||||
void nk_set_chroot(const char *chroot_dir)
|
||||
{
|
||||
if (chroot(chroot_dir))
|
||||
suicide("%s: chroot('%s') failed: %s", __func__, chroot_dir,
|
||||
strerror(errno));
|
||||
if (chdir("/"))
|
||||
suicide("%s: chdir('/') failed: %s", __func__, strerror(errno));
|
||||
}
|
||||
|
||||
#ifdef NK_USE_CAPABILITY
|
||||
static size_t nk_get_capability_vinfo(uint32_t *version)
|
||||
{
|
||||
struct __user_cap_header_struct hdr;
|
||||
memset(&hdr, 0, sizeof hdr);
|
||||
if (capget(&hdr, (cap_user_data_t)0) < 0) {
|
||||
if (errno != EINVAL)
|
||||
suicide("%s: capget failed: %s", __func__, strerror(errno));
|
||||
}
|
||||
switch (hdr.version) {
|
||||
case _LINUX_CAPABILITY_VERSION_1:
|
||||
*version = _LINUX_CAPABILITY_VERSION_1;
|
||||
return _LINUX_CAPABILITY_U32S_1;
|
||||
case _LINUX_CAPABILITY_VERSION_2:
|
||||
*version = _LINUX_CAPABILITY_VERSION_2;
|
||||
return _LINUX_CAPABILITY_U32S_2;
|
||||
default: log_line("%s: unknown capability version %x, using %x",
|
||||
__func__, *version, _LINUX_CAPABILITY_VERSION_3);
|
||||
case _LINUX_CAPABILITY_VERSION_3:
|
||||
*version = _LINUX_CAPABILITY_VERSION_3;
|
||||
return _LINUX_CAPABILITY_U32S_3;
|
||||
}
|
||||
}
|
||||
static size_t nk_set_capability_prologue(const unsigned char *caps,
|
||||
size_t caplen,
|
||||
uint32_t *cversion)
|
||||
{
|
||||
if (!caps || !caplen)
|
||||
return 0;
|
||||
size_t csize = nk_get_capability_vinfo(cversion);
|
||||
if (prctl(PR_SET_KEEPCAPS, 1))
|
||||
suicide("%s: prctl failed: %s", __func__, strerror(errno));
|
||||
return csize;
|
||||
}
|
||||
static void nk_set_capability_epilogue(const unsigned char *caps,
|
||||
size_t caplen, uint32_t cversion,
|
||||
size_t csize)
|
||||
{
|
||||
if (!caps || !caplen)
|
||||
return;
|
||||
struct __user_cap_header_struct hdr = {
|
||||
.version = cversion,
|
||||
.pid = 0,
|
||||
};
|
||||
struct __user_cap_data_struct data[csize];
|
||||
uint32_t mask[csize];
|
||||
memset(mask, 0, sizeof mask);
|
||||
for (size_t i = 0; i < caplen; ++i) {
|
||||
size_t j = caps[i] / 32;
|
||||
if (j >= csize)
|
||||
suicide("%s: caps[%zu] == %d, which is >= %zu and out of range",
|
||||
__func__, i, caps[i], csize * 32);
|
||||
mask[j] |= (uint32_t)CAP_TO_MASK(caps[i] - 32 * j);
|
||||
}
|
||||
for (size_t i = 0; i < csize; ++i) {
|
||||
data[i].effective = mask[i];
|
||||
data[i].permitted = mask[i];
|
||||
data[i].inheritable = 0;
|
||||
}
|
||||
if (capset(&hdr, (cap_user_data_t)&data) < 0)
|
||||
suicide("%s: capset failed: %s", __func__, strerror(errno));
|
||||
}
|
||||
#else
|
||||
static size_t nk_set_capability_prologue(const unsigned char *caps,
|
||||
size_t caplen,
|
||||
uint32_t *cversion)
|
||||
{ (void)caps; (void)caplen; (void)cversion; return 0; }
|
||||
static void nk_set_capability_epilogue(const unsigned char *caps,
|
||||
size_t caplen, uint32_t cversion,
|
||||
size_t csize)
|
||||
{ (void)caps; (void)caplen; (void)cversion; (void)csize; }
|
||||
#endif
|
||||
|
||||
#ifdef NK_USE_NO_NEW_PRIVS
|
||||
static void nk_set_no_new_privs(void)
|
||||
{
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
|
||||
suicide("%s: prctl failed: %s", __func__, strerror(errno));
|
||||
}
|
||||
#else
|
||||
static void nk_set_no_new_privs(void) {}
|
||||
#endif
|
||||
|
||||
void nk_set_uidgid(uid_t uid, gid_t gid, const unsigned char *caps,
|
||||
size_t caplen)
|
||||
{
|
||||
uint32_t cversion = 0;
|
||||
size_t csize = nk_set_capability_prologue(caps, caplen, &cversion);
|
||||
if (setgroups(1, &gid))
|
||||
suicide("%s: setgroups failed: %s", __func__, strerror(errno));
|
||||
if (setresgid(gid, gid, gid))
|
||||
suicide("%s: setresgid failed: %s", __func__, strerror(errno));
|
||||
if (setresuid(uid, uid, uid))
|
||||
suicide("%s: setresuid failed: %s", __func__, strerror(errno));
|
||||
uid_t ruid, euid, suid;
|
||||
if (getresuid(&ruid, &euid, &suid))
|
||||
suicide("%s: getresuid failed: %s", __func__, strerror(errno));
|
||||
if (ruid != uid || euid != uid || suid != uid)
|
||||
suicide("%s: getresuid failed; the OS or libc is broken", __func__);
|
||||
gid_t rgid, egid, sgid;
|
||||
if (getresgid(&rgid, &egid, &sgid))
|
||||
suicide("%s: getresgid failed: %s", __func__, strerror(errno));
|
||||
if (rgid != gid || egid != gid || sgid != gid)
|
||||
suicide("%s: getresgid failed; the OS or libc is broken", __func__);
|
||||
if (uid && setreuid((uid_t)-1, 0) == 0)
|
||||
suicide("%s: OS or libc broken; able to restore privs after drop",
|
||||
__func__);
|
||||
nk_set_capability_epilogue(caps, caplen, cversion, csize);
|
||||
nk_set_no_new_privs();
|
||||
}
|
||||
|
||||
uid_t nk_uidgidbyname(const char *username, uid_t *uid, gid_t *gid)
|
||||
{
|
||||
if (!username)
|
||||
return (uid_t)-1;
|
||||
struct passwd *pws = getpwnam(username);
|
||||
if (!pws) {
|
||||
for (size_t i = 0; username[i]; ++i) {
|
||||
if (!isdigit(username[i]))
|
||||
return (uid_t)-1;
|
||||
}
|
||||
char *p;
|
||||
long lt = strtol(username, &p, 10);
|
||||
if (errno == ERANGE && (lt == LONG_MIN || lt == LONG_MAX))
|
||||
return (uid_t)-1;
|
||||
if (lt < 0 || lt > (long)UINT_MAX)
|
||||
return (uid_t)-1;
|
||||
if (p == username)
|
||||
return (uid_t)-1;
|
||||
pws = getpwuid((uid_t)lt);
|
||||
if (!pws)
|
||||
return (uid_t)-1;
|
||||
}
|
||||
if (gid)
|
||||
*gid = pws->pw_gid;
|
||||
if (uid)
|
||||
*uid = pws->pw_uid;
|
||||
return (uid_t)0;
|
||||
}
|
||||
|
||||
gid_t nk_gidbyname(const char *groupname, gid_t *gid)
|
||||
{
|
||||
if (!groupname)
|
||||
return (gid_t)-1;
|
||||
struct group *grp = getgrnam(groupname);
|
||||
if (!grp) {
|
||||
for (size_t i = 0; groupname[i]; ++i) {
|
||||
if (!isdigit(groupname[i]))
|
||||
return (gid_t)-1;
|
||||
}
|
||||
char *p;
|
||||
long lt = strtol(groupname, &p, 10);
|
||||
if (errno == ERANGE && (lt == LONG_MIN || lt == LONG_MAX))
|
||||
return (gid_t)-1;
|
||||
if (lt < 0 || lt > (long)UINT_MAX)
|
||||
return (gid_t)-1;
|
||||
if (p == groupname)
|
||||
return (gid_t)-1;
|
||||
grp = getgrgid((gid_t)lt);
|
||||
if (!grp)
|
||||
return (gid_t)-1;
|
||||
}
|
||||
if (gid)
|
||||
return grp->gr_gid;
|
||||
return (gid_t)0;
|
||||
}
|
||||
|
44
nk/privs.h
Normal file
44
nk/privs.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* privs.h - uid/gid, chroot, and capability handling
|
||||
*
|
||||
* Copyright 2005-2014 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NCM_PRIVS_H_
|
||||
#define NCM_PRIVS_H_
|
||||
|
||||
#include <unistd.h>
|
||||
#ifdef __linux__
|
||||
#include <sys/capability.h>
|
||||
#endif
|
||||
|
||||
void nk_set_chroot(const char *chroot_dir);
|
||||
void nk_set_uidgid(uid_t uid, gid_t gid, const unsigned char *caps,
|
||||
size_t caplen);
|
||||
uid_t nk_uidgidbyname(const char *username, uid_t *uid, gid_t *gid);
|
||||
gid_t nk_gidbyname(const char *groupname, gid_t *gid);
|
||||
|
||||
#endif
|
||||
|
62
nk/random.c
Normal file
62
nk/random.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/* random.c - non-cryptographic fast PRNG
|
||||
*
|
||||
* Copyright 2013-2018 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nk/hwrng.h"
|
||||
#include "nk/random.h"
|
||||
|
||||
// GJrand64: https://gjrand.sourceforge.net
|
||||
|
||||
void nk_random_init(struct nk_random_state *s)
|
||||
{
|
||||
nk_get_hwrng(s->seed, sizeof(uint64_t) * 2);
|
||||
s->seed[2] = 2000001;
|
||||
s->seed[3] = 0;
|
||||
for (size_t i = 0; i < 14; ++i) nk_random_u64(s);
|
||||
}
|
||||
|
||||
static inline uint64_t rotl64(const uint64_t x, int k) {
|
||||
return (x << k) | (x >> (64 - k));
|
||||
}
|
||||
|
||||
uint64_t nk_random_u64(struct nk_random_state *s)
|
||||
{
|
||||
s->seed[1] += s->seed[2];
|
||||
s->seed[0] = rotl64(s->seed[0], 32);
|
||||
s->seed[2] ^= s->seed[1];
|
||||
s->seed[3] += 0x55aa96a5;
|
||||
s->seed[0] += s->seed[1];
|
||||
s->seed[2] = rotl64(s->seed[2], 23);
|
||||
s->seed[1] ^= s->seed[0];
|
||||
s->seed[0] += s->seed[2];
|
||||
s->seed[1] = rotl64(s->seed[1], 19);
|
||||
s->seed[2] += s->seed[0];
|
||||
s->seed[1] += s->seed[3];
|
||||
return s->seed[0];
|
||||
}
|
||||
|
45
nk/random.h
Normal file
45
nk/random.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* random.h - non-cryptographic fast PRNG
|
||||
*
|
||||
* Copyright 2013-2018 Nicholas J. Kain <njkain at gmail dot com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef NCMLIB_RANDOM__
|
||||
#define NCMLIB_RANDOM__
|
||||
#include <stdint.h>
|
||||
|
||||
struct nk_random_state {
|
||||
uint64_t seed[4];
|
||||
};
|
||||
|
||||
void nk_random_init(struct nk_random_state *s);
|
||||
uint64_t nk_random_u64(struct nk_random_state *s);
|
||||
static inline uint32_t nk_random_u32(struct nk_random_state *s)
|
||||
{
|
||||
// Discard lower bits as they have less linear complexity.
|
||||
return nk_random_u64(s) >> 32;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user