Make improvements to redbean

The following Lua APIs have been added:

  - IsDaemon() → bool
  - ProgramPidPath(str)

The following Lua hooks have been added:

  - OnClientConnection(ip:int,port:int,serverip:int,serverport:int) → bool
  - OnProcessCreate(pid:int,ip:int,port:int,serverip:int,serverport:int)
  - OnProcessDestroy(pid:int)
  - OnServerStart()
  - OnServerStop()
  - OnWorkerStart()
  - OnWorkerStop()

redbean now does a better job at applying gzip on the fly from the local
filesystem, using a streaming chunked api with constant memory, which is
useful for doing things like serving a 4gb text file off NFS, and having
it start transmitting in milliseconds. redbean will also compute entropy
on the beginnings of files to determine if compression is profitable.

This change pays off technical debts relating to memory, such as relying
on exit() to free() allocations. That's now mostly fixed so it should be
easier now to spot memory leaks in malloc traces.

This change also fixes bugs and makes improvements to our SSL support.
Uniprocess mode failed handshakes are no longer an issue. Token Alpn is
offered so curl -v looks less weird. Hybrid SSL certificate loading is
now smarter about naming conflicts. Self-signed CA root anchors will no
longer be delivered to the client during the handshake.
This commit is contained in:
Justine Tunney 2021-07-10 15:02:03 -07:00
parent 98c674d915
commit 8c4cce043c
25 changed files with 22326 additions and 359 deletions

View file

@ -30,6 +30,7 @@
#include "libc/sysv/consts/exit.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/shut.h"
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/sol.h"
@ -175,6 +176,7 @@ static int AppendFmt(struct Buffer *b, const char *fmt, ...) {
int main(int argc, char *argv[]) {
if (!NoDebug()) showcrashreports();
xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0);
/*
* Read flags.
@ -282,7 +284,6 @@ int main(int argc, char *argv[]) {
"Connection: close\r\n"
"User-Agent: %s\r\n",
kHttpMethod[method], _gc(EncodeUrl(&url, 0)), host, port, agent);
fprintf(stderr, "%`'.*s\n", request.i, request.p);
for (int i = 0; i < headers.n; ++i) {
AppendFmt(&request, "%s\r\n", headers.p[i]);
}
@ -459,6 +460,7 @@ Finished:
mbedtls_ssl_free(&ssl);
mbedtls_ctr_drbg_free(&drbg);
mbedtls_ssl_config_free(&conf);
mbedtls_ctr_drbg_free(&drbg);
}
return 0;

View file

@ -112,7 +112,7 @@ struct AsanGlobal {
struct AsanMorgue {
unsigned i;
void *p[16];
void *p[32];
};
static struct AsanMorgue __asan_morgue;

View file

@ -78,7 +78,6 @@ int PrintBacktraceUsingSymbols(int fd, const struct StackFrame *bp,
} else {
p = stpcpy(p, "UNKNOWN");
}
*p++ = '\r';
*p++ = '\n';
if (write(fd, buf, p - buf) == -1) {
return -1;

View file

@ -58,7 +58,7 @@ static const char kGregNames[17][4] forcealign(1) = {
static const char kCpuFlags[12] forcealign(1) = "CVPRAKZSTIDO";
static const char kFpuExceptions[6] forcealign(1) = "IDZOUP";
static const char kCrashSigNames[8][5] forcealign(1) = {
"QUIT", "FPE", "ILL", "SEGV", "TRAP", "ABRT", "BUS"};
"QUIT", "FPE", "ILL", "SEGV", "TRAP", "ABRT", "BUS", "PIPE"};
hidden int kCrashSigs[8];
hidden struct sigaction g_oldcrashacts[8];

View file

@ -27,6 +27,12 @@
static bool once;
static void PutEnvDestroy(void) {
char **a;
for (a = environ; *a; ++a) free(*a);
free(environ);
}
static void PutEnvInit(void) {
char **pin, **pout;
pin = environ;
@ -34,6 +40,7 @@ static void PutEnvInit(void) {
environ = pout;
while (*pin) *pout++ = strdup(*pin++);
*pout = NULL;
atexit(PutEnvDestroy);
}
int PutEnvImpl(char *s, bool overwrite) {

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -16,39 +16,37 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/itoa.h"
#include "libc/runtime/runtime.h"
#include "libc/math.h"
#include "libc/rand/rand.h"
#include "libc/str/str.h"
#include "third_party/dlmalloc/dlmalloc.internal.h"
static uintptr_t lastfree_;
void *AddressBirthAction(void *addr) {
char buf[64], *p;
p = buf;
p = stpcpy(p, __FUNCTION__);
p = stpcpy(p, ": 0x");
p += uint64toarray_radix16((uintptr_t)addr, p);
*p++ = '\n';
__print(buf, p - buf);
if (lastfree_ == (uintptr_t)addr) {
lastfree_ = 0;
/**
* Returns number between 0 and 8.
*
* This gives you an idea of the density of information. Cryptographic
* random should be in the ballpark of 7.9 whereas plaintext will be
* more like 4.5.
*
* @param p is treated as binary octets
* @param n should be at least 1000
*/
double MeasureEntropy(const char *p, size_t n) {
size_t i;
double e, x;
long h[256];
e = 0;
if (n) {
memset(h, 0, sizeof(h));
for (i = 0; i < n; ++i) {
++h[p[i] & 255];
}
for (i = 0; i < 256; i++) {
if (h[i]) {
x = h[i];
x /= n;
e += x * log2(1 / x);
}
}
}
return addr;
}
void *AddressDeathAction(void *addr) {
char buf[64], *p;
p = buf;
p = stpcpy(p, __FUNCTION__);
p = stpcpy(p, ": 0x");
p += uint64toarray_radix16((uintptr_t)addr, p);
if (lastfree_ != (uintptr_t)addr) {
lastfree_ = (uintptr_t)addr;
} else {
p = stpcpy(p, " [OBVIOUS DOUBLE FREE]");
}
*p++ = '\n';
__print(buf, p - buf);
return addr;
return e;
}

View file

@ -26,6 +26,7 @@ char *initstate(unsigned, char *, size_t);
char *setstate(char *);
long random(void);
void srandom(unsigned);
double MeasureEntropy(const char *, size_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -55,8 +55,7 @@ static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
void *memccpy(void *dst, const void *src, int c, size_t n) {
size_t i;
uint64_t v, w;
unsigned char *d;
unsigned char *pd;
unsigned char *d, *q;
const unsigned char *s;
i = 0;
d = dst;
@ -72,15 +71,15 @@ void *memccpy(void *dst, const void *src, int c, size_t n) {
if (~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080) {
break;
} else {
pd = d + i;
pd[0] = (w >> 000) & 255;
pd[1] = (w >> 010) & 255;
pd[2] = (w >> 020) & 255;
pd[3] = (w >> 030) & 255;
pd[4] = (w >> 040) & 255;
pd[5] = (w >> 050) & 255;
pd[6] = (w >> 060) & 255;
pd[7] = (w >> 070) & 255;
q = d + i;
q[0] = (w & 0x00000000000000ff) >> 000;
q[1] = (w & 0x000000000000ff00) >> 010;
q[2] = (w & 0x0000000000ff0000) >> 020;
q[3] = (w & 0x00000000ff000000) >> 030;
q[4] = (w & 0x000000ff00000000) >> 040;
q[5] = (w & 0x0000ff0000000000) >> 050;
q[6] = (w & 0x00ff000000000000) >> 060;
q[7] = (w & 0xff00000000000000) >> 070;
}
}
for (; i < n; ++i) {

View file

@ -28,6 +28,35 @@
* data from modifying memory without authorization; the memccpy()
* function can be used for that purpose.
*
* Here's an example of the only use case we know of for strncpy:
*
* static const struct People {
* char name[8];
* int age;
* } kPeople[] = {
* {"alice", 29}, //
* {"bob", 42}, //
* };
*
* int GetAge(const char *name) {
* char k[8];
* int m, l, r;
* l = 0;
* r = ARRAYLEN(kPeople) - 1;
* strncpy(k, name, 8);
* while (l <= r) {
* m = (l + r) >> 1;
* if (READ64BE(kPeople[m].name) < READ64BE(k)) {
* l = m + 1;
* } else if (READ64BE(kPeople[m].name) > READ64BE(k)) {
* r = m - 1;
* } else {
* return kPeople[m].age;
* }
* }
* return -1;
* }
*
* @return dest
* @see stpncpy(), memccpy()
* @asyncsignalsafe

View file

@ -7,6 +7,10 @@ extern size_t kHyperionSize;
extern char kHyperion[];
extern uint8_t kHyperionZip[];
extern size_t kMobySize;
extern char kMoby[];
extern uint8_t kMobyZip[];
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TESTLIB_HYPERION_H_ */

32
libc/testlib/moby.S Normal file
View file

@ -0,0 +1,32 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
.rodata
// Nontrivial NUL-terminated string test vector.
.align 1
kMoby:
0: .incbin "libc/testlib/moby.txt"
1: .byte 0
.endobj kMoby,globl
.align 8
kMobySize:
.quad 1b-0b
.endobj kMobySize,globl

12
libc/testlib/moby.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef COSMOPOLITAN_LIBC_TESTLIB_MOBY_H_
#define COSMOPOLITAN_LIBC_TESTLIB_MOBY_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern size_t kMobySize;
extern char kMoby[];
extern uint8_t kMobyZip[];
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TESTLIB_MOBY_H_ */

21257
libc/testlib/moby.txt Normal file

File diff suppressed because it is too large Load diff

View file

@ -13,22 +13,25 @@ LIBC_TESTLIB_A = o/$(MODE)/libc/testlib/testlib.a
LIBC_TESTLIB_A_CHECKS = $(LIBC_TESTLIB_A).pkg
LIBC_TESTLIB_A_ASSETS = \
libc/testlib/blocktronics.txt \
libc/testlib/hyperion.txt \
libc/testlib/blocktronics.txt
libc/testlib/moby.txt
LIBC_TESTLIB_A_HDRS = \
libc/testlib/bench.h \
libc/testlib/ezbench.h \
libc/testlib/blocktronics.h \
libc/testlib/ezbench.h \
libc/testlib/hyperion.h \
libc/testlib/moby.h \
libc/testlib/testlib.h
LIBC_TESTLIB_A_SRCS_S = \
libc/testlib/bench.S \
libc/testlib/blocktronics.S \
libc/testlib/combo.S \
libc/testlib/fixture.S \
libc/testlib/blocktronics.S \
libc/testlib/hyperion.S \
libc/testlib/moby.S \
libc/testlib/testcase.S \
libc/testlib/thrashcodecache.S \
libc/testlib/thunks/assert_eq.S \
@ -44,32 +47,32 @@ LIBC_TESTLIB_A_SRCS_S = \
LIBC_TESTLIB_A_SRCS_C = \
libc/testlib/almostequallongdouble.c \
libc/testlib/hexequals.c \
libc/testlib/benchrunner.c \
libc/testlib/binequals.c \
libc/testlib/clearxmmregisters.c \
libc/testlib/formatbool.c \
libc/testlib/formatrange.c \
libc/testlib/globals.c \
libc/testlib/incrementfailed.c \
libc/testlib/formatfloat.c \
libc/testlib/comborunner.c \
libc/testlib/contains.c \
libc/testlib/endswith.c \
libc/testlib/ezbenchcontrol.c \
libc/testlib/ezbenchreport.c \
libc/testlib/fixturerunner.c \
libc/testlib/formatbinaryasglyphs.c \
libc/testlib/formatbinaryashex.c \
libc/testlib/formatbool.c \
libc/testlib/formatfloat.c \
libc/testlib/formatint.c \
libc/testlib/formatrange.c \
libc/testlib/formatstr.c \
libc/testlib/globals.c \
libc/testlib/hexequals.c \
libc/testlib/incrementfailed.c \
libc/testlib/shoulddebugbreak.c \
libc/testlib/showerror.c \
libc/testlib/showerror_.c \
libc/testlib/strequals.c \
libc/testlib/startswith.c \
libc/testlib/endswith.c \
libc/testlib/contains.c \
libc/testlib/strcaseequals.c \
libc/testlib/benchrunner.c \
libc/testlib/testrunner.c \
libc/testlib/comborunner.c \
libc/testlib/fixturerunner.c \
libc/testlib/ezbenchreport.c \
libc/testlib/ezbenchcontrol.c
libc/testlib/strequals.c \
libc/testlib/testrunner.c
LIBC_TESTLIB_A_SRCS = \
$(LIBC_TESTLIB_A_SRCS_S) \

View file

@ -16,13 +16,17 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/log/check.h"
#include "libc/math.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/rand/lcg.internal.h"
#include "libc/rand/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/grnd.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/hyperion.h"
#include "libc/testlib/testlib.h"
/* JustReturnZero */
@ -134,6 +138,18 @@ uint64_t SixthEditionLowByte(void) {
return x;
}
uint64_t MobyDick(void) {
static int i;
if ((i += 8) > kMobySize) i = 8;
return READ64LE(kMoby + i);
}
uint64_t ExecutableImage(void) {
static int i;
if ((i += 8) > _end - _base) i = 8;
return READ64LE(_base + i);
}
uint32_t SeventhEditionRand(void) {
return ((randx = randx * 1103515245 + 12345) >> 16) & 077777;
}
@ -197,6 +213,8 @@ static const struct RandomFunction {
} kRandomFunctions[] = {
{"JustReturnZero", JustReturnZero, false}, //
{"JustIncrement", JustIncrement, false}, //
{"MobyDick", MobyDick, false}, //
{"ExecutableImage", ExecutableImage, false}, //
{"SixthEditionLowByte", SixthEditionLowByte, false}, //
{"SeventhEditionLowByte", SeventhEditionLowByte, false}, //
{"KnuthLcg", KnuthLcg, false}, //
@ -210,7 +228,7 @@ static const struct RandomFunction {
TEST(getrandom, sanityTest) {
uint64_t q;
size_t i, j, k;
double montepi, chip, scc, ent, mean, chisq;
double montepi, chip, scc, mean, chisq, ent;
for (k = 0; k < 1; ++k) {
for (j = 0; j < ARRAYLEN(kRandomFunctions); ++j) {
rt_init(0);
@ -240,3 +258,126 @@ TEST(getrandom, sanityTest) {
}
}
}
TEST(MeasureEntropy, test) {
MeasureEntropy(kMoby, 1000);
EXPECT_EQ(00, lroundl(10 * MeasureEntropy(" ", 12)));
EXPECT_EQ(16, lroundl(10 * MeasureEntropy("abcabcabcabc", 12)));
EXPECT_EQ(36, lroundl(10 * MeasureEntropy("abcdefghijkl", 12)));
EXPECT_EQ(49, lroundl(10 * MeasureEntropy(kMoby, 512)));
}
TEST(MeasureEntropy, testElfExecutable) {
EXPECT_EQ(19, lroundl(10 * MeasureEntropy("\
\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x03\x00\x3e\x00\x01\x00\x00\x00\x18\xd7\x00\x00\x00\x00\x00\x00\
\x40\x00\x00\x00\x00\x00\x00\x00\xc8\xd0\x0c\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x40\x00\x38\x00\x09\x00\x40\x00\x16\x00\x15\x00\
\x06\x00\x00\x00\x04\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\
\x40\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\
\xf8\x01\x00\x00\x00\x00\x00\x00\xf8\x01\x00\x00\x00\x00\x00\x00\
\x08\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\
\x38\x02\x00\x00\x00\x00\x00\x00\x38\x02\x00\x00\x00\x00\x00\x00\
\x38\x02\x00\x00\x00\x00\x00\x00\x19\x00\x00\x00\x00\x00\x00\x00\
\x19\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\
\x01\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x90\xbc\x00\x00\x00\x00\x00\x00\x90\xbc\x00\x00\x00\x00\x00\x00\
\x00\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\
\x00\xc0\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\
\x00\xc0\x00\x00\x00\x00\x00\x00\x62\xb2\x09\x00\x00\x00\x00\x00\
\x62\xb2\x09\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\
\x01\x00\x00\x00\x04\x00\x00\x00\x00\x80\x0a\x00\x00\x00\x00\x00\
\x00\x80\x0a\x00\x00\x00\x00\x00\x00\x80\x0a\x00\x00\x00\x00\x00\
\xe4\x09\x02\x00\x00\x00\x00\x00\xe4\x09\x02\x00\x00\x00\x00\x00\
\x00\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\
\xc0\x95\x0c\x00\x00\x00\x00\x00\xc0\xa5\x0c\x00\x00\x00\x00\x00\
\xc0\xa5\x0c\x00\x00\x00\x00\x00\x64\x3a\x00\x00\x00\x00\x00\x00\
\xa8\x42\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\
\x02\x00\x00\x00\x06\x00\x00\x00\xa0\xc2\x0c\x00\x00\x00\x00\x00\
\xa0\xd2\x0c\x00\x00\x00\x00\x00\xa0\xd2\x0c\x00\x00\x00\x00\x00\
\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\
\x08\x00\x00\x00\x00\x00\x00\x00\x51\xe5\x74\x64\x06\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00",
512)));
}
TEST(MeasureEntropy, testApeExecutable) {
EXPECT_EQ(53, lroundl(10 * MeasureEntropy("\
\x7f\x45\x4c\x46\x02\x01\x01\x09\x00\x00\x00\x00\x00\x00\x00\x00\
\x02\x00\x3e\x00\x01\x00\x00\x00\x0a\x11\x40\x00\x00\x00\x00\x00\
\xe0\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x40\x00\x38\x00\x04\x00\x00\x00\x00\x00\x00\x00\
\xb2\x40\xeb\x00\xeb\x14\x90\x90\xeb\x06\x48\x83\xec\x08\x31\xd2\
\xbd\x00\x00\xeb\x05\xe9\xb0\x10\x00\x00\xfc\x0f\x1f\x87\x3e\xe0\
\xbf\x00\x70\x31\xc9\x8e\xc1\xfa\x8e\xd7\x89\xcc\xfb\x0e\x1f\xe8\
\x00\x00\x5e\x81\xee\x72\x00\xb8\x00\x02\x50\x50\x07\x31\xff\xb9\
\x00\x02\xf3\xa4\x0f\x1f\x87\xd2\xff\xea\x8e\x20\x00\x00\x8e\xd9\
\xb9\x00\x1b\xb8\x50\x00\x8e\xc0\x31\xc0\x31\xff\xf3\xaa\x80\xfa\
\x40\x74\x13\xe8\x15\x00\x07\xb0\x01\x31\xc9\x30\xf6\xbf\x40\x03\
\xe8\x48\x00\x4f\x75\xfa\xea\x20\x25\x00\x00\x53\x52\xb4\x08\xcd\
\x13\x72\x2c\x88\xcf\x80\xe7\x3f\x80\xe1\xc0\xd0\xc1\xd0\xc1\x86\
\xcd\x1e\x06\x1f\x31\xf6\x8e\xc6\xbe\x10\x15\x87\xf7\xa5\xa5\xa5\
\xa5\xa5\xa4\x1f\x93\xab\x91\xab\x92\xab\x58\xaa\x92\x5b\xc3\x5a\
\x80\xf2\x80\x31\xc0\xcd\x13\x72\xf7\xeb\xc1\x50\x51\x86\xcd\xd0\
\xc9\xd0\xc9\x08\xc1\x31\xdb\xb0\x01\xb4\x02\xcd\x13\x59\x58\x72\
\x1d\x8c\xc6\x83\xc6\x20\x8e\xc6\xfe\xc0\x3a\x06\x1c\x15\x76\x0d\
\xb0\x01\xfe\xc6\x3a\x36\x20\x15\x76\x03\x30\xf6\x41\xc3\x50\x31\
\xc0\xcd\x13\x58\xeb\xc5\x89\xfe\xac\x84\xc0\x74\x09\xbb\x07\x00\
\xb4\x0e\xcd\x10\xeb\xf2\xc3\x57\xbf\x78\x24\xe8\xe8\xff\x5f\xe8\
\xe4\xff\xbf\x80\x24\xe8\xde\xff\xf3\x90\xeb\xfc\xb9\x04\x00\xbe\
\x00\x04\xad\x85\xc0\x74\x0b\x51\x56\x97\xbe\x9e\x24\xe8\x05\x00\
\x5e\x59\xe2\xee\xc3\x89\xfa\x85\xd2\x74\x14\x52\x56\x31\xc9\xb1\
\x03\x01\xca\xac\x5e\x0c\x80\xee\x5a\xac\xee\x42\x49\x79\xfa\xc3\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\xaa",
512)));
}
TEST(MeasureEntropy, testDevUrandom) {
EXPECT_EQ(76, lroundl(10 * MeasureEntropy("\
\x67\xa6\x8f\x6f\x6f\x01\xa4\x60\xa5\x5a\x6a\xfa\x06\xfd\xbb\xbe\
\xe4\x73\x2f\xc4\x20\x25\xd9\xb2\x78\x7d\x9f\xaf\x5d\x03\x49\x01\
\x90\x94\x8a\xc0\x33\x78\xe0\x65\xd8\x9c\x19\x96\x25\x90\xc8\x6e\
\xf2\x65\xac\x72\xd9\x8e\x58\x05\x26\x22\xa3\x58\x41\x40\xee\x3c\
\x3a\xb0\x08\x7c\x70\x0e\x23\xdc\x52\x10\x21\x5c\xb7\x3d\x3a\xce\
\x7c\xd7\x2a\x8c\x35\x0c\x21\x2b\x03\x75\xbe\x0c\x49\x5b\xdb\x7a\
\x7e\xeb\x27\x03\x56\xca\x9f\xf8\x00\xb4\x4d\x5b\xd6\xde\x41\xd6\
\x86\x7b\x3c\x13\xd4\x2d\xd4\xe9\x79\x05\x48\xcc\xa5\x17\xf8\xb6\
\x74\xdf\x39\x70\x32\x64\x70\x10\xfb\x53\x06\x87\xef\xff\x9f\x4c\
\x07\xee\x09\x54\xb8\xda\x1a\x49\x9b\x12\x3a\xf9\xc3\x55\xbc\xa5\
\xad\x6c\x3d\x1f\x39\x84\xc6\xac\x45\x14\x4f\xa9\xfc\xd6\xfb\xce\
\x41\xf8\x78\x85\xe5\x72\x9c\x0c\xd3\x81\x9b\xa4\x72\xc9\xd5\xc8\
\xc2\x3c\xcc\x36\x58\xf6\x23\x2a\x2e\x9c\x38\xea\x73\x17\xf0\x72\
\x2d\x57\xf8\xc5\x62\x84\xb7\xce\x24\x7b\x46\x65\xc7\xf3\x78\x88\
\x77\x36\x93\x25\x5d\x78\xc9\xfb\x24\xbb\xec\x2f\x77\x4f\x82\xd8\
\x63\x23\xd1\x39\x54\x78\x14\x7d\x24\xc8\x1a\xed\x32\x2d\x7b\xdc\
\xf4\x92\xb1\xaf\x0d\x9b\xba\xb6\x72\xfb\xb2\x7f\x8f\xd5\x4c\x5e\
\x05\xa7\x05\x15\xc5\x51\xd0\x86\x0a\xce\x04\x84\x1e\xba\x44\xf3\
\xbc\x09\xa9\x4e\xc1\xc7\xbd\x7e\x45\x38\x04\xa3\x6c\xfa\x46\x57\
\x40\x93\xbf\xdd\x12\x05\x6c\xb0\xee\x08\x40\x74\xc9\xda\xe7\x30\
\xfa\x1f\x12\xc8\x31\x33\x53\xe4\x65\x2a\xe8\xbf\x2b\x3c\xd6\xcc\
\xec\x8f\x9a\x6f\xe1\xe0\xe6\x81\x0a\xf5\x46\x07\xeb\xcd\xba\xcb\
\xa1\xe5\x4a\x42\xd6\x20\xce\xb6\x16\xcf\x73\x30\x25\x17\xe3\x00\
\x2b\x58\x93\x86\x74\x57\x48\x8b\x2a\x35\x88\xc7\x84\x18\x53\x23\
\xba\xc3\x06\x0a\xd7\x09\xf2\xcb\xe1\xb1\x39\x07\xaf\x2d\xb2\xbc\
\x7d\x71\x91\x6f\x71\x53\x82\xed\x51\x96\xbf\x90\xb4\x4a\x9a\x20\
\x21\x8a\x72\xa3\xbc\xfc\xb9\xcd\x47\x5e\x38\x9c\xd2\xf9\xae\x7f\
\xb2\x1a\x2a\x81\x68\x31\x53\xb2\x11\xfa\x80\x71\x31\xdd\xde\x56\
\x9c\x5f\x3f\x50\xb5\x5f\x99\x5d\x36\x34\x23\x13\xa9\xf0\x04\x3d\
\xa0\xee\x1c\xe5\xe3\x8d\x60\x76\x62\x5a\xd2\xa3\xa2\x51\xea\x75\
\xab\x1f\x2f\xc4\x08\x35\x5d\xf3\x28\x5d\x59\x67\x88\xf0\x61\x6c\
\x8b\x5f\xaf\x90\xa9\x90\xfe\x36\x29\xcc\x02\xf7\x2f\xa7\x19\x0e",
512)));
}
BENCH(getrandom, bench) {
EZBENCH2("MeasureEntropy", donothing, MeasureEntropy(kMoby, 512));
}

View file

@ -37,9 +37,11 @@ TEST_LIBC_STDIO_DIRECTDEPS = \
LIBC_SYSV \
LIBC_TESTLIB \
LIBC_TIME \
LIBC_LOG \
LIBC_UNICODE \
LIBC_X \
LIBC_ZIPOS
LIBC_ZIPOS \
THIRD_PARTY_ZLIB
TEST_LIBC_STDIO_DEPS := \
$(call uniq,$(foreach x,$(TEST_LIBC_STDIO_DIRECTDEPS),$($(x))))

View file

@ -24,7 +24,7 @@ size_t bulk_free(void *array[], size_t nelem) {
for (a = array; a != fence; ++a) {
void *mem = *a;
if (mem != 0) {
mchunkptr p = mem2chunk(ADDRESS_DEATH_ACTION(mem));
mchunkptr p = mem2chunk(AddressDeathAction(mem));
size_t psize = chunksize(p);
#if FOOTERS
if (get_mstate_for(p) != g_dlmalloc) {

View file

@ -74,14 +74,14 @@ static void **ialloc(mstate m, size_t n_elements, size_t *sizes, int opts,
size_t array_chunk_size;
array_chunk = chunk_plus_offset(p, contents_size);
array_chunk_size = remainder_size - contents_size;
marray = ADDRESS_BIRTH_ACTION((void **)(chunk2mem(array_chunk)));
marray = AddressBirthAction((void **)(chunk2mem(array_chunk)));
set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size);
remainder_size = contents_size;
}
/* split out elements */
for (i = 0;; ++i) {
marray[i] = ADDRESS_BIRTH_ACTION(chunk2mem(p));
marray[i] = AddressBirthAction(chunk2mem(p));
if (i != n_elements - 1) {
if (element_size != 0)
size = element_size;

View file

@ -578,7 +578,7 @@ static void *tmalloc_large(mstate m, size_t nb) {
return 0;
}
void *dlmalloc(size_t bytes) {
void *dlmalloc_impl(size_t bytes, bool takeaction) {
/*
Basic algorithm:
If a small request (< 256 bytes minus per-chunk overhead):
@ -708,12 +708,16 @@ void *dlmalloc(size_t bytes) {
postaction:
POSTACTION(g_dlmalloc);
return ADDRESS_BIRTH_ACTION(mem);
return takeaction ? AddressBirthAction(mem) : mem;
}
return 0;
}
void *dlmalloc(size_t bytes) {
return dlmalloc_impl(bytes, true);
}
void dlfree(void *mem) {
/*
Consolidate freed chunks with preceeding or succeeding bordering
@ -721,7 +725,7 @@ void dlfree(void *mem) {
with special cases for top, dv, mmapped chunks, and usage errors.
*/
if (mem != 0) {
mem = ADDRESS_DEATH_ACTION(mem);
mem = AddressDeathAction(mem);
mchunkptr p = mem2chunk(mem);
#if FOOTERS
@ -887,7 +891,7 @@ void *dlmemalign$impl(mstate m, size_t alignment, size_t bytes) {
} else {
size_t nb = request2size(bytes);
size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD;
mem = dlmalloc(req);
mem = dlmalloc_impl(req, false);
if (mem != 0) {
mchunkptr p = mem2chunk(mem);
if (PREACTION(m)) return 0;
@ -936,7 +940,7 @@ void *dlmemalign$impl(mstate m, size_t alignment, size_t bytes) {
POSTACTION(m);
}
}
return ADDRESS_BIRTH_ACTION(mem);
return AddressBirthAction(mem);
}
void *dlmemalign(size_t alignment, size_t bytes) {

View file

@ -3,9 +3,12 @@
#ifndef __STRICT_ANSI__
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/log/backtrace.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#if 0
@ -674,15 +677,64 @@ extern struct MallocState g_dlmalloc[1];
/* ─────────────────────────────── Hooks ──────────────────────────────── */
#ifdef MTRACE /* TODO(jart): Add --mtrace flag for this */
void *AddressBirthAction(void *);
void *AddressDeathAction(void *);
#define ADDRESS_BIRTH_ACTION(A) AddressBirthAction(A)
#define ADDRESS_DEATH_ACTION(A) AddressDeathAction(A)
#else
#define ADDRESS_BIRTH_ACTION(A) (A)
#define ADDRESS_DEATH_ACTION(A) (A)
/*
d = {}
lines = open("log").read().split('\n')
def bad(i):
while i < len(lines):
if lines[i].startswith(('BIRTH', 'DEATH')):
break
print lines[i]
i += 1
for i, line in enumerate(lines):
i += 1
x = line.split()
if len(x) != 2: continue
if x[0] == 'DEATH':
b = int(x[1], 16)
if b in d:
if d[b] < 0:
print "OH NO", i, d[b]
else:
d[b] = -d[b]
else:
print "wut", i
elif x[0] == 'BIRTH':
b = int(x[1], 16)
if b in d:
if d[b] > 0:
print "bad malloc", i, d[b]
d[b] = i
else:
d[b] = i
for k,v in d.items():
if v > 0:
print "unfreed", v
bad(v)
*/
#define MALLOC_TRACE 0
static inline void *AddressBirthAction(void *p) {
#if MALLOC_TRACE
(dprintf)(2, "BIRTH %p\n", p);
if (weaken(PrintBacktraceUsingSymbols) && weaken(GetSymbolTable)) {
weaken(PrintBacktraceUsingSymbols)(2, __builtin_frame_address(0),
weaken(GetSymbolTable)());
}
#endif
return p;
}
static inline void *AddressDeathAction(void *p) {
#if MALLOC_TRACE
(dprintf)(2, "DEATH %p\n", p);
if (weaken(PrintBacktraceUsingSymbols) && weaken(GetSymbolTable)) {
weaken(PrintBacktraceUsingSymbols)(2, __builtin_frame_address(0),
weaken(GetSymbolTable)());
}
#endif
return p;
}
/*
PREACTION should be defined to return 0 on success, and nonzero on
@ -907,7 +959,7 @@ extern struct MallocParams g_mparams;
#else /* GNUC */
#define RTCHECK(e) (e)
#endif /* GNUC */
#else /* !IsTrustworthy() */
#else /* !IsTrustworthy() */
#define RTCHECK(e) (1)
#endif /* !IsTrustworthy() */

View file

@ -643,7 +643,7 @@
*
* Uncomment this macro to respect client's ciphersuite order
*/
/*#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE*/
#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
/**
* \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
@ -661,7 +661,7 @@
*
* Comment this macro to disable support for ALPN.
*/
/*#define MBEDTLS_SSL_ALPN*/
#define MBEDTLS_SSL_ALPN
#ifdef MBEDTLS_SSL_PROTO_DTLS
/**

View file

@ -722,25 +722,17 @@ static const struct DisArg {
{"Yvqp", DisYvqp}, //
};
static int CompareString8(const char a[8], const char b[8]) {
uint64_t x, y;
x = READ64BE(a);
y = READ64BE(b);
return x > y ? 1 : x < y ? -1 : 0;
}
char *DisArg(struct Dis *d, char *p, const char *s) {
char key[8];
int c, m, l, r;
char k[8];
int m, l, r;
l = 0;
r = ARRAYLEN(kDisArgs) - 1;
strncpy(key, s, 8);
strncpy(k, s, 8);
while (l <= r) {
m = (l + r) >> 1;
c = CompareString8(kDisArgs[m].s, key);
if (c < 0) {
if (READ64BE(kDisArgs[m].s) < READ64BE(k)) {
l = m + 1;
} else if (c > 0) {
} else if (READ64BE(kDisArgs[m].s) > READ64BE(k)) {
r = m - 1;
} else {
return kDisArgs[m].f(d, d->xedd->op.rde, p);

View file

@ -192,6 +192,45 @@ SECURITY
-addext 'keyUsage = critical,cRLSign,keyCertSign'
sudo ./redbean.com -C ca.crt -K .ca.key -p 80 -p 443
Let's say you're migrating away from NGINX and you use Let's Encrypt.
In that case you'll likely want something like the following:
certbot certonly --nginx --key-type ecdsa \
--cert-name redbean-ecdsa -d redbean.dev -d www.redbean.dev
certbot certonly --nginx --key-type rsa \
--cert-name redbean-rsa -d redbean.dev -d www.redbean.dev
You can then program /var/www/html/.init.lua as such:
ProgramPrivateKey(Slurp('/etc/letsencrypt/live/redbean-ecdsa/privkey.pem'))
ProgramCertificate(Slurp('/etc/letsencrypt/live/redbean-ecdsa/fullchain.pem'))
ProgramPrivateKey(Slurp('/etc/letsencrypt/live/redbean-rsa/privkey.pem'))
ProgramCertificate(Slurp('/etc/letsencrypt/live/redbean-rsa/fullchain.pem'))
if IsDaemon() then
ProgramUid(33) # see `vipw` to get appropriate number
ProgramGid(33) # see `vigr` to get appropriate number
ProgramPort(80)
ProgramPort(443)
ProgramLogPath('/var/log/redbean.log')
ProgramPidPath('/var/run/redbean.pid')
end
function OnHttpRequest()
path = GetPath()
if path == '/favicon.ico' or
path == '/site.webmanifest' or
path == '/favicon-16x16.png' or
path == '/favicon-32x32.png' or
path == '/apple-touch-icon' then
SetLogLevel(kLogWarn)
end
Route()
SetHeader('Content-Language', 'en-US')
end
You'd then run redbean as follows:
redbean.com -dD /var/www/html
SSL verbosity is controlled as follows for troubleshooting:
-V log ssl errors
@ -295,13 +334,51 @@ GLOBALS
HOOKS
OnHttpRequest
OnHttpRequest()
If this function is defined in the global scope by your /.init.lua
then redbean will call it at the ealiest possible moment to
handover control for all messages (with the exception of OPTIONS
*). See functions like Route which asks redbean to do its default
thing from the handler.
OnClientConnection(ip:int,port:int,serverip:int,serverport:int) → bool
If this function is defined it'll be called from the main process
each time redbean accepts a new client connection. If it returns
true then redbean will close the connection without calling fork.
OnProcessCreate(pid:int,ip:int,port:int,serverip:int,serverport:int)
If this function is defined it'll be called from the main process
each time redbean forks a connection handler worker process. The
ip/port of the remote client is provided, along with the ip/port
of the listening interface that accepted the connection. This may
be used to create a server activity dashboard, in which case the
data provider handler should set SetHeader('Connection','Close').
This won't be called in unprocess mode.
OnProcessDestroy(pid:int)
If this function is defined it'll be called from the main process
each time redbean reaps a child connection process using wait4().
This won't be called in unprocess mode.
OnServerStart()
If this function is defined it'll be called from the main process
right before the main event loop starts.
OnServerStop()
If this function is defined it'll be called from the main process
after all the connection processes have been reaped and exit() is
ready to be called.
OnWorkerStart()
If this function is defined it'll be called from the child worker
process after it's been forked and before messages are handled.
This won't be called in unprocess mode.
OnWorkerStop()
If this function is defined it'll be called from the child worker
process once _exit() is ready to be called. This won't be called
in unprocess mode.
FUNCTIONS
Write(data:str)
@ -708,6 +785,9 @@ FUNCTIONS
ProgramPrivateKey(Slurp("/etc/letsencrypt/fullchain.pem")) for
local file system only.
IsDaemon() → bool
Returns true if -d flag was passed to redbean.
ProgramUid(int)
Same as the -U flag if called from .init.lua for setuid()
@ -736,6 +816,16 @@ FUNCTIONS
space then redbean will truncate the log file if has access to
change the log file after daemonizing.
ProgramPidPath(str)
Same as the -P flag if called from .init.lua for setting the pid
file path on the local file system. It's useful for reloading
daemonized redbean using `kill -HUP $(cat /var/run/redbean.pid)`
or terminating redbean with `kill $(cat /var/run/redbean.pid)`
which will gracefully terminate all clients. Sending the TERM
signal twice will cause a forceful shutdown, which might make
someone with a slow internet connection who's downloading big
files unhappy.
Slurp(filename:str) → str
Reads file data from local file system.
@ -792,21 +882,39 @@ FUNCTIONS
Underlong(str) → str
Canonicalizes overlong encodings.
bsf(x:int) → int
Crc32(initial:int,data:str) → int
Computes 32-bit CRC-32 used by zip/zlib/gzip/etc.
Crc32c(initial:int,data:str) → int
Computes 32-bit Castagnoli Cyclic Redundancy Check.
Md5(str) → str
Computes MD5 checksum, returning 16 bytes of binary.
Sha1(str) → str
Computes SHA1 checksum, returning 20 bytes of binary.
Sha224(str) → str
Computes SHA224 checksum, returning 28 bytes of binary.
Sha256(str) → str
Computes SHA256 checksum, returning 32 bytes of binary.
Sha384(str) → str
Computes SHA384 checksum, returning 48 bytes of binary.
Sha512(str) → str
Computes SHA512 checksum, returning 64 bytes of binary.
Bsf(x:int) → int
Returns position of first bit set. Passing 0 will raise an error.
Same as the Intel x86 instruction BSF.
bsr(x:int) → int
Bsr(x:int) → int
Returns binary logarithm of 𝑥. Passing 0 will raise an error. Same
as the Intel x86 instruction BSR.
crc32(initial:int,data:str) → int
Computes Phil Katz CRC-32 used by zip/zlib/gzip/etc.
crc32c(initial:int,data:str) → int
Computes 32-bit Castagnoli Cyclic Redundancy Check.
popcnt(x:int) → int
Popcnt(x:int) → int
Returns number of bits set in integer.
LSQLITE3 MODULE

File diff suppressed because it is too large Load diff

93
tool/viz/dumphexc.c Normal file
View file

@ -0,0 +1,93 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/fmt.h"
#include "libc/macros.internal.h"
#include "libc/stdio/stdio.h"
struct Append {
size_t i, n;
char *p;
};
int AppendFmt(struct Append *b, const char *fmt, ...) {
int n;
char *p;
va_list va, vb;
va_start(va, fmt);
va_copy(vb, va);
n = vsnprintf(b->p + b->i, b->n - b->i, fmt, va);
if (n >= b->n - b->i) {
do {
if (b->n) {
b->n += b->n >> 1; /* this is the important line */
} else {
b->n = 16;
}
} while (b->i + n + 1 > b->n);
b->p = realloc(b->p, b->n);
vsnprintf(b->p + b->i, b->n - b->i, fmt, vb);
}
va_end(vb);
va_end(va);
b->i += n;
return n;
}
char *DumpHexc(const char *data, size_t size, size_t *z) {
long o;
int b, i, n;
char A[128], *p;
struct Append buf;
if (size == -1) size = data ? strlen(data) : 0;
buf.i = 0;
buf.n = 256;
buf.p = calloc(1, 256);
AppendFmt(&buf, "\"\\\n");
for (b = o = 0; (n = MIN(16, size)); data += n, size -= n) {
p = A;
for (i = 0; i < n; ++i) {
*p++ = '\\';
*p++ = 'x';
*p++ = "0123456789abcdef"[(data[i] & 0xF0) >> 4];
*p++ = "0123456789abcdef"[(data[i] & 0x0F) >> 0];
}
if (o) AppendFmt(&buf, "\\\n");
AppendFmt(&buf, "%.*s", p - A, A);
o += n;
}
AppendFmt(&buf, "\"");
if (z) *z = buf.i;
return buf.p;
}
int main(int argc, char *argv[]) {
char *p;
size_t n, g;
char buf[512];
struct Append b = {0};
while ((g = fread(buf, 1, sizeof(buf), stdin))) {
AppendFmt(&b, "%.*s", g, buf);
}
if (!ferror(stdin)) {
p = DumpHexc(b.p, b.i, &n);
fwrite(p, 1, n, stdout);
}
printf("\n");
return ferror(stdin) || ferror(stdout) ? 1 : 0;
}