Don't depend on external ncmlib.
This commit is contained in:
parent
4575f74164
commit
f1e20305ba
@ -1,5 +1,3 @@
|
||||
project(ndhc)
|
||||
|
||||
cmake_minimum_required(VERSION 3.3)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.12)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
@ -7,6 +5,8 @@ else()
|
||||
cmake_policy(VERSION 3.12)
|
||||
endif()
|
||||
|
||||
project (ndhc DESCRIPTION "dhcp4 client" LANGUAGES C)
|
||||
|
||||
####################################
|
||||
|
||||
# Computes the realtionship between two version strings. A version
|
||||
@ -101,6 +101,31 @@ if (NOT (${OSNAME} STREQUAL "Linux"))
|
||||
return()
|
||||
endif()
|
||||
|
||||
if (${OSNAME} STREQUAL "Linux")
|
||||
execute_process(
|
||||
COMMAND uname -r
|
||||
COMMAND tr "\n" " "
|
||||
COMMAND sed "s/ //"
|
||||
OUTPUT_VARIABLE LINUX_VERSION
|
||||
)
|
||||
COMPARE_VERSION_STRINGS(${LINUX_VERSION} "3.5" LINUX_HAS_NO_NEW_PRIVS)
|
||||
if (NOT ${LINUX_HAS_NO_NEW_PRIVS} LESS 0)
|
||||
message("ncmlib: Enabling use of prctl SET_NO_NEW_PRIVS.")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNK_USE_NO_NEW_PRIVS")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNK_USE_NO_NEW_PRIVS")
|
||||
else()
|
||||
message("ncmlib: prctl SET_NO_NEW_PRIVS not available.")
|
||||
endif()
|
||||
COMPARE_VERSION_STRINGS(${LINUX_VERSION} "3.17" LINUX_HAS_GETRANDOM_SYSCALL)
|
||||
if (NOT ${LINUX_HAS_GETRANDOM_SYSCALL} LESS 0)
|
||||
message("ncmlib: Enabling use of getrandom syscall.")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNK_USE_GETRANDOM_SYSCALL")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNK_USE_GETRANDOM_SYSCALL")
|
||||
else()
|
||||
message("ncmlib: getrandom syscall not available.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_CROSSCOMPILING)
|
||||
set(GLIBC_DETECT_TEST_C
|
||||
"
|
||||
@ -139,5 +164,66 @@ else()
|
||||
set(MACHINENAME $ENV{CROSSCOMPILE_MACHINENAME})
|
||||
endif()
|
||||
|
||||
add_subdirectory(ncmlib)
|
||||
add_subdirectory(src)
|
||||
add_executable(ndhc "")
|
||||
|
||||
set(RAGEL_IFCHD_PARSE ${CMAKE_CURRENT_BINARY_DIR}/ifchd-parse.c)
|
||||
set(RAGEL_CFG_PARSE ${CMAKE_CURRENT_BINARY_DIR}/cfg.c)
|
||||
|
||||
find_program(RAGEL ragel)
|
||||
|
||||
set(RAGEL_PRINT_COMMENT "Compiling Ragel state machine: FILE")
|
||||
file(GLOB_RECURSE RAGEL_FILES
|
||||
"src/ifchd-parse.rl"
|
||||
"src/cfg.rl"
|
||||
)
|
||||
foreach(RAGEL_FILE ${RAGEL_FILES})
|
||||
string(REGEX REPLACE "^[^/]*[/]" "" RAGEL_FILE_BASE ${RAGEL_FILE})
|
||||
string(REGEX REPLACE ${RAGEL_FILE_BASE} "" RAGEL_FILE_PATH ${RAGEL_FILE})
|
||||
string(REGEX REPLACE "[.]rl$" ".c" RAGEL_FILE_C ${RAGEL_FILE_BASE})
|
||||
string(REGEX REPLACE "FILE$" ${RAGEL_FILE_BASE} RAGEL_COMMENT ${RAGEL_PRINT_COMMENT})
|
||||
set(RAGEL_FILE_C_OUT ${CMAKE_CURRENT_BINARY_DIR}/${RAGEL_FILE_C})
|
||||
list(APPEND RAGEL_C_FILES ${RAGEL_FILE_C_OUT})
|
||||
add_custom_command(
|
||||
OUTPUT ${RAGEL_FILE_C_OUT}
|
||||
COMMAND ${RAGEL} -T0 ${RAGEL_ERRFMT_ARG} -o ${RAGEL_FILE_C_OUT} ${RAGEL_FILE_BASE}
|
||||
MAIN_DEPENDENCY ${RAGEL_FILE}
|
||||
WORKING_DIRECTORY ${RAGEL_FILE_PATH}
|
||||
COMMENT ${RAGEL_COMMENT}
|
||||
VERBATIM
|
||||
)
|
||||
set_property(SOURCE ${RAGEL_FILE_C_OUT} APPEND PROPERTY GENERATED TRUE)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set_property(SOURCE ${RAGEL_FILE_C_OUT} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-unused-const-variable")
|
||||
endif()
|
||||
set_source_files_properties(${RAGEL_FILE_C_OUT} PROPERTIES GENERATED true)
|
||||
target_sources(ndhc PRIVATE ${RAGEL_FILE_C_OUT})
|
||||
endforeach(RAGEL_FILE)
|
||||
add_custom_target(ndhc_ragel DEPENDS ${RAGEL_C_FILES})
|
||||
add_dependencies(ndhc ndhc_ragel)
|
||||
|
||||
target_sources(ndhc PRIVATE
|
||||
"src/lib/io.c"
|
||||
"src/lib/log.c"
|
||||
"src/lib/hwrng.c"
|
||||
"src/lib/random.c"
|
||||
"src/lib/privs.c"
|
||||
${RAGEL_C_FILES}
|
||||
"src/arp.c"
|
||||
"src/ifchd.c"
|
||||
"src/netlink.c"
|
||||
"src/sockd.c"
|
||||
"src/dhcp.c"
|
||||
"src/ifset.c"
|
||||
"src/nl.c"
|
||||
"src/state.c"
|
||||
"src/duiaid.c"
|
||||
"src/leasefile.c"
|
||||
"src/options.c"
|
||||
"src/sys.c"
|
||||
"src/ifchange.c"
|
||||
"src/ndhc.c"
|
||||
"src/rfkill.c"
|
||||
)
|
||||
target_include_directories(ndhc PRIVATE
|
||||
"${PROJECT_SOURCE_DIR}/src"
|
||||
)
|
||||
|
22
Makefile
22
Makefile
@ -2,48 +2,42 @@
|
||||
# for distros that want to avoid build dependencies. Produced exes will be
|
||||
# at './build/ndhc'.
|
||||
|
||||
NCM_SRCS = $(sort $(wildcard ncmlib/*.c))
|
||||
NCM_SRCS = $(sort $(wildcard src/lib/*.c))
|
||||
NDHC_SRCS = $(sort $(wildcard src/*.c))
|
||||
NCM_OBJS = $(NCM_SRCS:.c=.o)
|
||||
NDHC_OBJS = $(NDHC_SRCS:.c=.o)
|
||||
NCM_INC = -I./ncmlib
|
||||
NDHC_INC = -I./src
|
||||
BUILD_DIR = build
|
||||
OBJ_DIR = $(BUILD_DIR)/objs
|
||||
|
||||
CC = gcc
|
||||
AR = ar
|
||||
RANLIB = ranlib
|
||||
CFLAGS = -O2 -s -std=gnu99 -pedantic -Wall -D_GNU_SOURCE
|
||||
# Not required for glibc >= 2.17, but older glibcs are still common.
|
||||
# The CMake build script will perform detection, but this Makefile is simple.
|
||||
LINK_LIBS = -lrt
|
||||
|
||||
all: makedir ifchd-parse.o cfg.o ncmlib.a ndhc
|
||||
all: makedir ifchd-parse.o cfg.o ndhc
|
||||
|
||||
clean:
|
||||
rm -Rf $(BUILD_DIR)
|
||||
|
||||
makedir:
|
||||
mkdir -p $(BUILD_DIR) $(OBJ_DIR)/src $(OBJ_DIR)/ncmlib
|
||||
mkdir -p $(BUILD_DIR) $(OBJ_DIR)/src
|
||||
|
||||
ifchd-parse.o:
|
||||
ragel -G2 -o $(BUILD_DIR)/ifchd-parse.c src/ifchd-parse.rl
|
||||
$(CC) $(CFLAGS) $(NCM_INC) $(NDHC_INC) -c -o $(OBJ_DIR)/src/$@ $(BUILD_DIR)/ifchd-parse.c
|
||||
$(CC) $(CFLAGS) $(NDHC_INC) -c -o $(OBJ_DIR)/src/$@ $(BUILD_DIR)/ifchd-parse.c
|
||||
|
||||
cfg.o:
|
||||
ragel -G2 -o $(BUILD_DIR)/cfg.c src/cfg.rl
|
||||
$(CC) $(CFLAGS) $(NCM_INC) $(NDHC_INC) -c -o $(OBJ_DIR)/src/$@ $(BUILD_DIR)/cfg.c
|
||||
$(CC) $(CFLAGS) $(NDHC_INC) -c -o $(OBJ_DIR)/src/$@ $(BUILD_DIR)/cfg.c
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $(NCM_INC) -c -o $(OBJ_DIR)/$@ $<
|
||||
$(CC) $(CFLAGS) -c -o $(OBJ_DIR)/$@ $<
|
||||
|
||||
ncmlib.a: $(NCM_OBJS)
|
||||
$(AR) rc $(BUILD_DIR)/$@ $(subst ncmlib/,$(OBJ_DIR)/ncmlib/,$(NCM_OBJS))
|
||||
$(RANLIB) $(BUILD_DIR)/$@
|
||||
|
||||
ndhc: $(NDHC_OBJS) ifchd-parse.o cfg.o
|
||||
$(CC) $(CFLAGS) $(NCM_INC) -o $(BUILD_DIR)/$@ $(subst src/,$(OBJ_DIR)/src/,$(NDHC_OBJS)) $(BUILD_DIR)/ncmlib.a $(BUILD_DIR)/objs/src/ifchd-parse.o $(BUILD_DIR)/objs/src/cfg.o $(LINK_LIBS)
|
||||
ndhc: $(NCM_OBJS) $(NDHC_OBJS) ifchd-parse.o cfg.o
|
||||
$(CC) $(CFLAGS) -o $(BUILD_DIR)/$@ $(subst src/,$(OBJ_DIR)/src/,$(NDHC_OBJS)) $(BUILD_DIR)/objs/src/ifchd-parse.o $(BUILD_DIR)/objs/src/cfg.o $(LINK_LIBS)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
|
@ -88,15 +88,9 @@ new one.
|
||||
* Linux kernel
|
||||
* GNU Make or CMake
|
||||
* [Ragel 6](https://www.colm.net/open-source/ragel)
|
||||
* [ncmlib](https://github.com/niklata/ncmlib)
|
||||
|
||||
## Installation
|
||||
|
||||
Make sure that ncmlib is present in the ndhc source directory:
|
||||
```
|
||||
$ ls
|
||||
CMakeLists.txt LICENSE Makefile ncmlib README src
|
||||
```
|
||||
Compile and install ndhc.
|
||||
* Create a build directory: `mkdir build && cd build`
|
||||
* Create the makefiles: `cmake ..`
|
||||
|
@ -1,54 +0,0 @@
|
||||
project (ndhc DESCRIPTION "dhcp4 client" LANGUAGES C)
|
||||
|
||||
set(RAGEL_IFCHD_PARSE ${CMAKE_CURRENT_BINARY_DIR}/ifchd-parse.c)
|
||||
set(RAGEL_CFG_PARSE ${CMAKE_CURRENT_BINARY_DIR}/cfg.c)
|
||||
|
||||
find_program(RAGEL ragel)
|
||||
add_custom_command(
|
||||
OUTPUT ${RAGEL_IFCHD_PARSE}
|
||||
COMMAND ${RAGEL} -G2 -o ${RAGEL_IFCHD_PARSE} ifchd-parse.rl
|
||||
DEPENDS ifchd-parse.rl
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Compiling Ragel state machine: ifchd-parse.rl"
|
||||
VERBATIM
|
||||
)
|
||||
set_property(SOURCE ${RAGEL_IFCHD_PARSE} APPEND PROPERTY GENERATED TRUE)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set_property(SOURCE ${RAGEL_IFCHD_PARSE} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-unused-const-variable")
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT ${RAGEL_CFG_PARSE}
|
||||
COMMAND ${RAGEL} -G2 -o ${RAGEL_CFG_PARSE} cfg.rl
|
||||
DEPENDS cfg.rl
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMENT "Compiling Ragel state machine: cfg.rl"
|
||||
VERBATIM
|
||||
)
|
||||
set_property(SOURCE ${RAGEL_CFG_PARSE} APPEND PROPERTY GENERATED TRUE)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set_property(SOURCE ${RAGEL_CFG_PARSE} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-unused-const-variable")
|
||||
endif()
|
||||
|
||||
add_executable(ndhc ${RAGEL_CFG_PARSE} ${RAGEL_IFCHD_PARSE})
|
||||
target_sources(ndhc PRIVATE
|
||||
"arp.c"
|
||||
"ifchd.c"
|
||||
"netlink.c"
|
||||
"sockd.c"
|
||||
"dhcp.c"
|
||||
"ifset.c"
|
||||
"nl.c"
|
||||
"state.c"
|
||||
"duiaid.c"
|
||||
"leasefile.c"
|
||||
"options.c"
|
||||
"sys.c"
|
||||
"ifchange.c"
|
||||
"ndhc.c"
|
||||
"rfkill.c"
|
||||
)
|
||||
target_include_directories(ndhc PRIVATE
|
||||
"${PROJECT_SOURCE_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}/../ncmlib"
|
||||
)
|
||||
target_link_libraries(ndhc PUBLIC ncmlib)
|
@ -12,7 +12,7 @@
|
||||
#include "ifchd.h"
|
||||
#include "sockd.h"
|
||||
#include "nk/log.h"
|
||||
#include "nk/privilege.h"
|
||||
#include "nk/privs.h"
|
||||
#include "nk/copy_cmdarg.h"
|
||||
#include "nk/io.h"
|
||||
|
||||
|
@ -84,7 +84,7 @@ static int perform_ip4set(const char buf[static 1], size_t len)
|
||||
const char *p = buf;
|
||||
const char *pe = p + len;
|
||||
const char *eof = pe;
|
||||
const char *arg_start;
|
||||
const char *arg_start = p;
|
||||
int cs = 0;
|
||||
bool have_ip = false;
|
||||
bool have_subnet = false;
|
||||
@ -211,7 +211,7 @@ int execute_buffer(const char newbuf[static 1])
|
||||
size_t init_siz = strlen(buf);
|
||||
const char *p = buf;
|
||||
const char *pe = p + init_siz;
|
||||
const char *arg_start;
|
||||
const char *arg_start = p;
|
||||
size_t arg_len = 0;
|
||||
int cs = 0;
|
||||
|
||||
|
@ -41,8 +41,7 @@
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include "nk/log.h"
|
||||
#include "nk/privilege.h"
|
||||
#include "nk/signals.h"
|
||||
#include "nk/privs.h"
|
||||
#include "nk/io.h"
|
||||
|
||||
#include "ifchd.h"
|
||||
@ -368,9 +367,8 @@ static void do_ifch_work(void)
|
||||
}
|
||||
}
|
||||
|
||||
// If we are requested to update resolv.conf, preopen the fd before
|
||||
// we drop root privileges, making sure that if we create
|
||||
// resolv.conf, it will be world-readable.
|
||||
// If we are requested to update resolv.conf, preopen the fd before we drop
|
||||
// root, making sure that if we create resolv.conf, it will be world-readable.
|
||||
static void setup_resolv_conf(void)
|
||||
{
|
||||
if (strncmp(resolv_conf_d, "", sizeof resolv_conf_d)) {
|
||||
|
128
src/lib/hwrng.c
Normal file
128
src/lib/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_warning("%s: getrandom() returned no entropy", __func__);
|
||||
return false;
|
||||
}
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
log_warning("%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_warning("%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_warning("%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_warning("%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_warning("%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__);
|
||||
}
|
||||
|
131
src/lib/io.c
Normal file
131
src/lib/io.c
Normal file
@ -0,0 +1,131 @@
|
||||
/* 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;
|
||||
retry:
|
||||
r = recvmsg(fd, msg, flags);
|
||||
if (r < 0 && errno == EINTR)
|
||||
goto retry;
|
||||
return r;
|
||||
}
|
||||
|
82
src/lib/log.c
Normal file
82
src/lib/log.c
Normal file
@ -0,0 +1,82 @@
|
||||
/* log.c - simple logging support
|
||||
*
|
||||
* Copyright 2003-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 <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include "nk/log.h"
|
||||
|
||||
/* global logging flags */
|
||||
int gflags_quiet = 0;
|
||||
int gflags_detach = 0;
|
||||
int gflags_debug = 0;
|
||||
char *gflags_log_name = 0;
|
||||
|
||||
#define log_syslog(level) do { \
|
||||
openlog(gflags_log_name, LOG_PID, LOG_DAEMON); \
|
||||
va_start(argp, format); \
|
||||
vsyslog(level | LOG_DAEMON, format, argp); \
|
||||
va_end(argp); \
|
||||
closelog(); } while(0)
|
||||
|
||||
#define log_stdio() do { \
|
||||
va_start(argp, format); \
|
||||
vfprintf(stderr, format, argp); \
|
||||
fprintf(stderr, "\n"); \
|
||||
va_end(argp); } while(0)
|
||||
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
void log_line_l(int level, const char format[static 1], ...)
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
if (gflags_quiet)
|
||||
return;
|
||||
|
||||
if (gflags_detach)
|
||||
log_syslog(level);
|
||||
else
|
||||
log_stdio();
|
||||
}
|
||||
|
||||
__attribute__ ((format (printf, 1, 2)))
|
||||
void __attribute__((noreturn)) suicide(const char format[static 1], ...)
|
||||
{
|
||||
va_list argp;
|
||||
|
||||
if (gflags_detach)
|
||||
log_syslog(LOG_ERR);
|
||||
else
|
||||
log_stdio();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#undef log_syslog
|
||||
#undef log_stdio
|
||||
|
224
src/lib/privs.c
Normal file
224
src/lib/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[static 1])
|
||||
{
|
||||
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_warning("%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[static 1])
|
||||
{
|
||||
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] == %u, which is >= %u and out of range",
|
||||
__func__, 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[static 1])
|
||||
{ (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;
|
||||
}
|
||||
|
62
src/lib/random.c
Normal file
62
src/lib/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];
|
||||
}
|
||||
|
@ -48,8 +48,7 @@
|
||||
#include <grp.h>
|
||||
#include <limits.h>
|
||||
#include "nk/log.h"
|
||||
#include "nk/privilege.h"
|
||||
#include "nk/pidfile.h"
|
||||
#include "nk/privs.h"
|
||||
#include "nk/io.h"
|
||||
#include "nk/copy_cmdarg.h"
|
||||
|
||||
@ -153,9 +152,9 @@ void show_usage(void)
|
||||
" -n, --now Exit with failure if lease cannot be\n"
|
||||
" immediately negotiated.\n"
|
||||
" -r, --request=IP IP address to request (default: none)\n"
|
||||
" -u, --user=USER Change ndhc privileges to this user\n"
|
||||
" -U, --ifch-user=USER Change ndhc-ifch privileges to this user\n"
|
||||
" -D, --sockd-user=USER Change ndhc-sockd privileges to this user\n"
|
||||
" -u, --user=USER ndhc runs as this user\n"
|
||||
" -U, --ifch-user=USER ndhc-ifch runs as this user\n"
|
||||
" -D, --sockd-user=USER ndhc-sockd runs as this user\n"
|
||||
" -C, --chroot=DIR Chroot to this directory\n"
|
||||
" -s, --state-dir=DIR State storage dir (default: /etc/ndhc)\n"
|
||||
" -d, --relentless-defense Never back off in defending IP against\n"
|
||||
|
18
src/nk/copy_cmdarg.h
Normal file
18
src/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_ */
|
37
src/nk/hwrng.h
Normal file
37
src/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
|
||||
|
||||
|
41
src/nk/io.h
Normal file
41
src/nk/io.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* 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);
|
||||
|
||||
#endif /* NCM_IO_H_ */
|
48
src/nk/log.h
Normal file
48
src/nk/log.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* log.h - simple logging support
|
||||
*
|
||||
* Copyright 2003-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_LOG_H_
|
||||
#define NCM_LOG_H_
|
||||
|
||||
#include <syslog.h>
|
||||
|
||||
extern int gflags_quiet;
|
||||
extern int gflags_detach;
|
||||
extern int gflags_debug;
|
||||
extern char *gflags_log_name;
|
||||
|
||||
#define log_line(...) log_line_l(LOG_INFO, __VA_ARGS__)
|
||||
#define log_debug(...) if (gflags_debug) log_line_l(LOG_DEBUG, __VA_ARGS__)
|
||||
#define log_warning(...) log_line_l(LOG_WARNING, __VA_ARGS__)
|
||||
#define log_error(...) log_line_l(LOG_ERR, __VA_ARGS__)
|
||||
|
||||
void log_line_l(int level, const char *format, ...);
|
||||
void __attribute__((noreturn)) suicide(const char *format, ...);
|
||||
|
||||
#endif
|
||||
|
54
src/nk/net_checksum.h
Normal file
54
src/nk/net_checksum.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef NCMLIB_NET_CHECKSUM_H
|
||||
#define NCMLIB_NET_CHECKSUM_H
|
||||
|
||||
#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_checksum161c_foldcarry(uint32_t v)
|
||||
{
|
||||
v = (v >> 16) + (v & 0xffff);
|
||||
v += v >> 16;
|
||||
return v;
|
||||
}
|
||||
|
||||
// This function is not suitable for summing buffers that are greater than
|
||||
// 128k bytes in length: failure case will be incorrect checksums via
|
||||
// unsigned overflow, which is a defined operation and is safe. This limit
|
||||
// should not be an issue for IPv4 or IPv6 packet, which are limited to
|
||||
// at most 64k bytes.
|
||||
static uint16_t net_checksum161c(const void *buf, size_t size)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
int odd = size & 0x01;
|
||||
size_t i;
|
||||
size &= ~((size_t)0x01);
|
||||
size >>= 1;
|
||||
const uint8_t *b = (const uint8_t *)buf;
|
||||
for (i = 0; i < size; ++i) {
|
||||
uint16_t hi = b[i*2];
|
||||
uint16_t lo = b[i*2+1];
|
||||
sum += ntohs((lo + (hi << 8)));
|
||||
}
|
||||
if (odd) {
|
||||
uint16_t hi = b[i*2];
|
||||
uint16_t lo = 0;
|
||||
sum += ntohs((lo + (hi << 8)));
|
||||
}
|
||||
return ~net_checksum161c_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_checksum161c_add(uint16_t a, uint16_t b)
|
||||
{
|
||||
const uint32_t A = a;
|
||||
const uint32_t B = b;
|
||||
return ~net_checksum161c_foldcarry((~A & 0xffffu) + (~B & 0xffffu));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
44
src/nk/privs.h
Normal file
44
src/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
|
||||
|
45
src/nk/random.h
Normal file
45
src/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
|
||||
|
@ -50,7 +50,7 @@
|
||||
#include <grp.h>
|
||||
#include "nk/log.h"
|
||||
#include "nk/io.h"
|
||||
#include "nk/privilege.h"
|
||||
#include "nk/privs.h"
|
||||
|
||||
#include "sockd.h"
|
||||
#include "ndhc-defines.h"
|
||||
|
Loading…
Reference in New Issue
Block a user