Refactor out some duplicated code

This commit is contained in:
Justine Tunney 2021-08-14 06:17:56 -07:00
parent e963d9c8e3
commit 579b597ded
58 changed files with 1110 additions and 3214 deletions

View file

@ -36,8 +36,8 @@ TOOL_BUILD_DIRECTDEPS = \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_KERNEL32 \
LIBC_NT_WS2_32 \
LIBC_NT_USER32 \
LIBC_NT_WS2_32 \
LIBC_RAND \
LIBC_RUNTIME \
LIBC_SOCK \
@ -50,12 +50,13 @@ TOOL_BUILD_DIRECTDEPS = \
LIBC_TINYMATH \
LIBC_UNICODE \
LIBC_X \
NET_HTTPS \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_STB \
THIRD_PARTY_XED \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_ZLIB \
TOOL_BUILD_LIB

View file

@ -33,6 +33,7 @@
#include "libc/nexgen32e/kcpuids.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/append.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/rlimit.h"
#include "libc/sysv/consts/sig.h"
@ -353,7 +354,7 @@ int main(int argc, char *argv[]) {
/*
* parse prefix arguments
*/
while ((opt = getopt(argc, argv, "?hntC:M:F:A:T:V:")) != -1) {
while ((opt = getopt(argc, argv, "hntC:M:F:A:T:V:")) != -1) {
switch (opt) {
case 'n':
exit(0);
@ -378,17 +379,16 @@ int main(int argc, char *argv[]) {
case 'F':
fszquota = sizetol(optarg, 1000);
break;
case '?':
case 'h':
write(1, MANUAL, sizeof(MANUAL) - 1);
fputs(MANUAL, stdout);
exit(0);
default:
write(2, MANUAL, sizeof(MANUAL) - 1);
fputs(MANUAL, stderr);
exit(1);
}
}
if (optind == argc) {
write(2, MANUAL, sizeof(MANUAL) - 1);
fputs("error: missing arguments\n", stderr);
exit(1);
}

View file

@ -45,6 +45,7 @@ TOOL_BUILD_LIB_A_DIRECTDEPS = \
LIBC_TINYMATH \
LIBC_UNICODE \
LIBC_X \
NET_HTTPS \
THIRD_PARTY_COMPILER_RT \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_XED

View file

@ -25,9 +25,11 @@
#include "libc/sock/sock.h"
#include "libc/sysv/consts/sig.h"
#include "libc/x/x.h"
#include "net/https/https.h"
#include "third_party/mbedtls/ctr_drbg.h"
#include "third_party/mbedtls/ecp.h"
#include "third_party/mbedtls/error.h"
#include "third_party/mbedtls/platform.h"
#include "third_party/mbedtls/ssl.h"
#include "tool/build/lib/eztls.h"
#include "tool/build/lib/psk.h"
@ -37,34 +39,6 @@ mbedtls_ssl_config ezconf;
mbedtls_ssl_context ezssl;
mbedtls_ctr_drbg_context ezrng;
static char *EzTlsError(int r) {
static char b[128];
mbedtls_strerror(r, b, sizeof(b));
return b;
}
void EzTlsDie(const char *s, int r) {
if (IsTiny()) {
fprintf(stderr, "error: %s (-0x%04x %s)\n", s, -r, EzTlsError(r));
} else {
fprintf(stderr, "error: %s (grep -0x%04x)\n", s, -r);
}
exit(1);
}
static int EzGetEntropy(void *c, unsigned char *p, size_t n) {
CHECK_EQ(n, getrandom(p, n, 0));
return 0;
}
static void EzInitializeRng(mbedtls_ctr_drbg_context *r) {
volatile unsigned char b[64];
mbedtls_ctr_drbg_init(r);
CHECK(getrandom(b, 64, 0) == 64);
CHECK(!mbedtls_ctr_drbg_seed(r, EzGetEntropy, 0, b, 64));
mbedtls_platform_zeroize(b, 64);
}
static ssize_t EzWritevAll(int fd, struct iovec *iov, int iovlen) {
int i;
ssize_t rc;
@ -165,34 +139,38 @@ static int EzTlsRecv(void *ctx, unsigned char *buf, size_t len, uint32_t tmo) {
return EzTlsRecvImpl(ctx, buf, len, tmo);
}
void EzFd(int fd) {
mbedtls_ssl_session_reset(&ezssl);
mbedtls_platform_zeroize(&ezbio, sizeof(ezbio));
ezbio.fd = fd;
}
void EzHandshake(void) {
int rc;
while ((rc = mbedtls_ssl_handshake(&ezssl))) {
if (rc != MBEDTLS_ERR_SSL_WANT_READ) {
EzTlsDie("handshake failed", rc);
TlsDie("handshake failed", rc);
}
}
while ((rc = EzTlsFlush(&ezbio, 0, 0))) {
if (rc != MBEDTLS_ERR_SSL_WANT_READ) {
EzTlsDie("handshake flush failed", rc);
TlsDie("handshake flush failed", rc);
}
}
}
/*
* openssl s_client -connect 127.0.0.1:31337 \
* -psk $(hex <~/.runit.psk) \
* -psk_identity runit
*/
void SetupPresharedKeySsl(int endpoint) {
void EzInitialize(void) {
xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0);
EzInitializeRng(&ezrng);
ezconf.disable_compression = 1; /* TODO(jart): Why does it behave weirdly? */
mbedtls_ssl_config_defaults(&ezconf, endpoint, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_SUITEC);
InitializeRng(&ezrng);
}
void EzSetup(char psk[32]) {
int rc;
mbedtls_ssl_conf_rng(&ezconf, mbedtls_ctr_drbg_random, &ezrng);
DCHECK_EQ(0, mbedtls_ssl_conf_psk(&ezconf, GetRunitPsk(), 32, "runit", 5));
DCHECK_EQ(0, mbedtls_ssl_setup(&ezssl, &ezconf));
if ((rc = mbedtls_ssl_conf_psk(&ezconf, psk, 32, "runit", 5)) ||
(rc = mbedtls_ssl_setup(&ezssl, &ezconf))) {
TlsDie("EzSetup", rc);
}
mbedtls_ssl_set_bio(&ezssl, &ezbio, EzTlsSend, 0, EzTlsRecv);
}

View file

@ -2,6 +2,7 @@
#define COSMOPOLITAN_TOOL_BUILD_LIB_EZTLS_H_
#include "third_party/mbedtls/ctr_drbg.h"
#include "third_party/mbedtls/ssl.h"
#include "third_party/mbedtls/x509_crt.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -17,11 +18,24 @@ extern mbedtls_ssl_config ezconf;
extern mbedtls_ssl_context ezssl;
extern mbedtls_ctr_drbg_context ezrng;
void EzFd(int);
void EzHandshake(void);
void SetupPresharedKeySsl(int);
void EzTlsDie(const char *, int) wontreturn;
void EzSetup(char[32]);
void EzInitialize(void);
int EzTlsFlush(struct EzTlsBio *, const unsigned char *, size_t);
/*
* openssl s_client -connect 127.0.0.1:31337 \
* -psk $(hex <~/.runit.psk) \
* -psk_identity runit
*/
forceinline void SetupPresharedKeySsl(int endpoint, char psk[32]) {
EzInitialize();
mbedtls_ssl_config_defaults(&ezconf, endpoint, MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_SUITEC);
EzSetup(psk);
}
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_EZTLS_H_ */

View file

@ -42,8 +42,10 @@
#include "libc/sysv/consts/sock.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "net/https/https.h"
#include "third_party/mbedtls/ssl.h"
#include "tool/build/lib/eztls.h"
#include "tool/build/lib/psk.h"
#include "tool/build/runit.h"
/**
@ -336,7 +338,7 @@ bool Recv(unsigned char *p, size_t n) {
usleep((backoff = (backoff + 1000) * 2));
return false;
} else if (rc < 0) {
EzTlsDie("read response failed", rc);
TlsDie("read response failed", rc);
}
}
return true;
@ -387,9 +389,8 @@ int RunOnHost(char *spec) {
1);
if (!strchr(g_hostname, '.')) strcat(g_hostname, ".test.");
do {
mbedtls_ssl_session_reset(&ezssl);
Connect();
ezbio.fd = g_sock;
EzFd(g_sock);
EzHandshake();
SendRequest();
} while ((rc = ReadResponse()) == -1);
@ -454,7 +455,7 @@ int RunRemoteTestsInParallel(char *hosts[], int count) {
int main(int argc, char *argv[]) {
showcrashreports();
SetupPresharedKeySsl(MBEDTLS_SSL_IS_CLIENT);
SetupPresharedKeySsl(MBEDTLS_SSL_IS_CLIENT, GetRunitPsk());
/* __log_level = kLogDebug; */
if (argc > 1 &&
(strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)) {

View file

@ -45,9 +45,11 @@
#include "libc/sysv/consts/w.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "net/https/https.h"
#include "third_party/getopt/getopt.h"
#include "third_party/mbedtls/ssl.h"
#include "tool/build/lib/eztls.h"
#include "tool/build/lib/psk.h"
#include "tool/build/runit.h"
/**
@ -264,13 +266,13 @@ void HandleClient(void) {
close(g_clifd);
return;
}
ezbio.fd = g_clifd;
EzFd(g_clifd);
EzHandshake();
addrstr = gc(DescribeAddress(&addr));
DEBUGF("%s %s %s", gc(DescribeAddress(&g_servaddr)), "accepted", addrstr);
while ((got = mbedtls_ssl_read(&ezssl, (p = g_buf), sizeof(g_buf))) < 0) {
if (got != MBEDTLS_ERR_SSL_WANT_READ) {
EzTlsDie("ssl read failed", got);
TlsDie("ssl read failed", got);
}
}
CHECK_GE(got, kMinMsgSize);
@ -302,7 +304,7 @@ void HandleClient(void) {
while (remaining) {
while ((got = mbedtls_ssl_read(&ezssl, g_buf, sizeof(g_buf))) < 0) {
if (got != MBEDTLS_ERR_SSL_WANT_READ) {
EzTlsDie("ssl read failed", got);
TlsDie("ssl read failed", got);
}
}
CHECK_LE(got, remaining);
@ -443,7 +445,7 @@ void Daemonize(void) {
int main(int argc, char *argv[]) {
showcrashreports();
SetupPresharedKeySsl(MBEDTLS_SSL_IS_SERVER);
SetupPresharedKeySsl(MBEDTLS_SSL_IS_SERVER, GetRunitPsk());
/* __log_level = kLogDebug; */
GetOpts(argc, argv);
CHECK_NE(-1, (g_devnullfd = open("/dev/null", O_RDWR)));

View file

@ -124,34 +124,10 @@ void GetOpts(int *argc, char ***argv) {
CHECK_NOTNULL(outpath_);
}
bool IsUtf8(const void *data, size_t size) {
const unsigned char *p, *pe;
for (p = data, pe = p + size; p + 2 <= pe; ++p) {
if (p[0] >= 0300) {
if (p[1] >= 0200 && p[1] < 0300) {
return true;
} else {
return false;
}
}
}
return false;
}
bool IsText(const void *data, size_t size) {
const unsigned char *p, *pe;
for (p = data, pe = p + size; p < pe; ++p) {
if (*p <= 3) {
return false;
}
}
return true;
}
bool ShouldCompress(const char *name, size_t namesize,
const unsigned char *data, size_t datasize) {
return !nocompress_ && datasize >= 64 && !IsNoCompressExt(name, namesize) &&
(datasize < 1000 || MeasureEntropy((void *)data, 1000) < 6);
(datasize < 1000 || MeasureEntropy((void *)data, 1000) < 7);
}
void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,

View file

@ -21,6 +21,7 @@
#include "libc/bits/popcnt.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/math.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/flock.h"
@ -50,10 +51,12 @@
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/goodsocket.internal.h"
#include "libc/sock/sock.h"
#include "libc/stdio/append.internal.h"
#include "libc/stdio/hex.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/slice.h"
#include "libc/str/str.h"
#include "libc/str/undeflate.h"
#include "libc/sysv/consts/af.h"
@ -106,6 +109,7 @@
#include "third_party/mbedtls/entropy_poll.h"
#include "third_party/mbedtls/error.h"
#include "third_party/mbedtls/iana.h"
#include "third_party/mbedtls/md.h"
#include "third_party/mbedtls/md5.h"
#include "third_party/mbedtls/oid.h"
#include "third_party/mbedtls/pk.h"
@ -267,10 +271,7 @@ static struct Suites {
static struct Certs {
size_t n;
struct Cert {
mbedtls_x509_crt *cert;
mbedtls_pk_context *key;
} * p;
struct Cert *p;
} certs;
static struct Redirects {
@ -480,39 +481,6 @@ static long ParseInt(const char *s) {
return strtol(s, 0, 0);
}
forceinline bool SlicesEqual(const char *a, size_t n, const char *b, size_t m) {
return n == m && !memcmp(a, b, n);
}
forceinline bool SlicesEqualCase(const void *a, size_t n, const void *b,
size_t m) {
return n == m && !memcasecmp(a, b, n);
}
static int CompareSlices(const char *a, size_t n, const char *b, size_t m) {
int c;
if ((c = memcmp(a, b, MIN(n, m)))) return c;
if (n < m) return -1;
if (n > m) return +1;
return 0;
}
static int CompareSlicesCase(const char *a, size_t n, const char *b, size_t m) {
int c;
if ((c = memcasecmp(a, b, MIN(n, m)))) return c;
if (n < m) return -1;
if (n > m) return +1;
return 0;
}
static bool StartsWithIgnoreCase(const char *s, const char *prefix) {
for (;;) {
if (!*prefix) return true;
if (!*s) return false;
if (kToLower[*s++ & 255] != (*prefix++ & 255)) return false;
}
}
static void *FreeLater(void *p) {
if (p) {
if (++freelist.n > freelist.c) {
@ -587,28 +555,6 @@ static long FindRedirect(const char *s, size_t n) {
return -1;
}
static void LogCertificate(const char *msg, mbedtls_x509_crt *cert) {
char *s;
size_t n;
if (LOGGABLE(kLogDebug)) {
if ((s = gc(malloc((n = 15000))))) {
if (mbedtls_x509_crt_info(s, n, " ", cert) > 0) {
DEBUGF("%s\n%s", msg, chomp(s));
}
}
}
}
static char *FormatX509Name(mbedtls_x509_name *name) {
char *s = calloc(1, 1000);
CHECK_GT(mbedtls_x509_dn_gets(s, 1000, name), 0);
return s;
}
static bool IsSelfSigned(mbedtls_x509_crt *cert) {
return !mbedtls_x509_name_cmp(&cert->issuer, &cert->subject);
}
static mbedtls_x509_crt *GetTrustedCertificate(mbedtls_x509_name *name) {
size_t i;
for (i = 0; i < certs.n; ++i) {
@ -628,20 +574,6 @@ static void UseCertificate(mbedtls_ssl_config *c, struct Cert *kp,
CHECK_EQ(0, mbedtls_ssl_conf_own_cert(c, kp->cert, kp->key));
}
static bool ChainCertificate(mbedtls_x509_crt *cert, mbedtls_x509_crt *parent) {
if (!mbedtls_x509_crt_check_signature(cert, parent, 0)) {
DEBUGF("chaining %`'s to %`'s", gc(FormatX509Name(&cert->subject)),
gc(FormatX509Name(&parent->subject)));
cert->next = parent;
return true;
} else {
WARNF("signature check failed for %`'s -> %`'s",
gc(FormatX509Name(&cert->subject)),
gc(FormatX509Name(&parent->subject)));
return false;
}
}
static void AppendCert(mbedtls_x509_crt *cert, mbedtls_pk_context *key) {
certs.p = realloc(certs.p, ++certs.n * sizeof(*certs.p));
certs.p[certs.n - 1].cert = cert;
@ -1179,34 +1111,6 @@ static void ReportWorkerExit(int pid, int ws) {
}
}
static void AddTimeval(struct timeval *x, const struct timeval *y) {
x->tv_sec += y->tv_sec;
x->tv_usec += y->tv_usec;
if (x->tv_usec >= 1000000) {
x->tv_usec -= 1000000;
x->tv_sec += 1;
}
}
static void AddRusage(struct rusage *x, const struct rusage *y) {
AddTimeval(&x->ru_utime, &y->ru_utime);
AddTimeval(&x->ru_stime, &y->ru_stime);
x->ru_maxrss = MAX(x->ru_maxrss, y->ru_maxrss);
x->ru_ixrss += y->ru_ixrss;
x->ru_idrss += y->ru_idrss;
x->ru_isrss += y->ru_isrss;
x->ru_minflt += y->ru_minflt;
x->ru_majflt += y->ru_majflt;
x->ru_nswap += y->ru_nswap;
x->ru_inblock += y->ru_inblock;
x->ru_oublock += y->ru_oublock;
x->ru_msgsnd += y->ru_msgsnd;
x->ru_msgrcv += y->ru_msgrcv;
x->ru_nsignals += y->ru_nsignals;
x->ru_nvcsw += y->ru_nvcsw;
x->ru_nivcsw += y->ru_nivcsw;
}
static void ReportWorkerResources(int pid, struct rusage *ru) {
char *s, *b = 0;
if (logrusage || LOGGABLE(kLogDebug)) {
@ -1389,11 +1293,6 @@ static int TlsRecv(void *ctx, unsigned char *buf, size_t len, uint32_t tmo) {
return TlsRecvImpl(ctx, buf, len, tmo);
}
static void TlsDebug(void *ctx, int level, const char *file, int line,
const char *message) {
flogf(level, file, line, 0, "TLS %s", message);
}
static ssize_t SslRead(int fd, void *buf, size_t size) {
int rc;
rc = mbedtls_ssl_read(&ssl, buf, size);
@ -1473,12 +1372,11 @@ static void WipeServingKeys(void) {
}
}
static bool CertHasCommonName(const mbedtls_x509_crt *cert,
const unsigned char *host, size_t size) {
bool CertHasCommonName(const mbedtls_x509_crt *cert, const void *s, size_t n) {
const mbedtls_x509_name *name;
for (name = &cert->subject; name; name = name->next) {
if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) {
if (SlicesEqualCase(host, size, name->val.p, name->val.len)) {
if (SlicesEqualCase(s, n, name->val.p, name->val.len)) {
return true;
}
break;
@ -1487,44 +1385,11 @@ static bool CertHasCommonName(const mbedtls_x509_crt *cert,
return false;
}
static bool CertHasHost(const mbedtls_x509_crt *cert, const unsigned char *host,
size_t size) {
const mbedtls_x509_sequence *cur;
for (cur = &cert->subject_alt_names; cur; cur = cur->next) {
if ((cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) ==
MBEDTLS_X509_SAN_DNS_NAME &&
SlicesEqualCase(host, size, cur->buf.p, cur->buf.len)) {
return true;
}
}
return false;
}
static bool CertHasIp(const mbedtls_x509_crt *cert, uint32_t ip) {
const mbedtls_x509_sequence *cur;
for (cur = &cert->subject_alt_names; cur; cur = cur->next) {
if ((cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) ==
MBEDTLS_X509_SAN_IP_ADDRESS &&
cur->buf.len == 4 && ip == READ32BE(cur->buf.p)) {
return true;
}
}
return false;
}
static bool IsServerCert(mbedtls_pk_type_t type, int i) {
return certs.p[i].cert && certs.p[i].key && !certs.p[i].cert->ca_istrue &&
mbedtls_pk_get_type(certs.p[i].key) == type &&
!mbedtls_x509_crt_check_extended_key_usage(
certs.p[i].cert, MBEDTLS_OID_SERVER_AUTH,
MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH));
}
static bool TlsRouteFind(mbedtls_pk_type_t type, mbedtls_ssl_context *ssl,
const unsigned char *host, size_t size, int64_t ip) {
int i;
for (i = 0; i < certs.n; ++i) {
if (IsServerCert(type, i) &&
if (IsServerCert(certs.p + i, type) &&
(((certs.p[i].cert->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) &&
(ip == -1 ? CertHasHost(certs.p[i].cert, host, size)
: CertHasIp(certs.p[i].cert, ip))) ||
@ -1543,7 +1408,7 @@ static bool TlsRouteFind(mbedtls_pk_type_t type, mbedtls_ssl_context *ssl,
static bool TlsRouteFirst(mbedtls_pk_type_t type, mbedtls_ssl_context *ssl) {
int i;
for (i = 0; i < certs.n; ++i) {
if (IsServerCert(type, i)) {
if (IsServerCert(certs.p + i, type)) {
CHECK_EQ(
0, mbedtls_ssl_set_hs_own_cert(ssl, certs.p[i].cert, certs.p[i].key));
DEBUGF("TlsRoute(%s) %s %`'s", mbedtls_pk_type_name(type),
@ -1679,40 +1544,6 @@ static bool TlsSetup(void) {
}
}
static int GetEntropy(void *c, unsigned char *p, size_t n) {
CHECK_EQ(n, getrandom(p, n, 0));
return 0;
}
static void InitializeRng(mbedtls_ctr_drbg_context *r) {
volatile unsigned char b[64];
mbedtls_ctr_drbg_init(r);
CHECK(getrandom(b, 64, 0) == 64);
CHECK(!mbedtls_ctr_drbg_seed(r, GetEntropy, 0, b, 64));
mbedtls_platform_zeroize(b, 64);
}
static void GenerateSerial(mbedtls_x509write_cert *wcert,
mbedtls_ctr_drbg_context *kr) {
mbedtls_mpi x;
mbedtls_mpi_init(&x);
mbedtls_mpi_fill_random(&x, 128 / 8, mbedtls_ctr_drbg_random, kr);
mbedtls_x509write_crt_set_serial(wcert, &x);
mbedtls_mpi_free(&x);
}
static void ChooseCertificateLifetime(char notbefore[16], char notafter[16]) {
struct tm tm;
int64_t past, now, future, lifetime, tolerance;
tolerance = 60 * 60 * 24;
lifetime = 60 * 60 * 24 * 365;
now = nowl();
past = now - tolerance;
future = now + tolerance + lifetime;
FormatSslTime(notbefore, gmtime_r(&past, &tm));
FormatSslTime(notafter, gmtime_r(&future, &tm));
}
static void ConfigureCertificate(mbedtls_x509write_cert *cw, struct Cert *ca,
int usage, int type) {
int r;
@ -1766,8 +1597,10 @@ static void ConfigureCertificate(mbedtls_x509write_cert *cw, struct Cert *ca,
if ((r = mbedtls_x509write_crt_set_subject_alternative_name(cw, san, nsan)) ||
(r = mbedtls_x509write_crt_set_validity(cw, notbefore, notafter)) ||
(r = mbedtls_x509write_crt_set_basic_constraints(cw, false, -1)) ||
#if defined(MBEDTLS_SHA1_C)
(r = mbedtls_x509write_crt_set_subject_key_identifier(cw)) ||
(r = mbedtls_x509write_crt_set_authority_key_identifier(cw)) ||
#endif
(r = mbedtls_x509write_crt_set_key_usage(cw, usage)) ||
(r = mbedtls_x509write_crt_set_ext_key_usage(cw, type)) ||
(r = mbedtls_x509write_crt_set_subject_name(cw, subject)) ||
@ -1794,57 +1627,18 @@ static struct Cert GetKeySigningKey(void) {
return (struct Cert){0};
}
static mbedtls_pk_context *InitializeKey(struct Cert *ca,
mbedtls_x509write_cert *wcert,
int type) {
mbedtls_pk_context *k;
mbedtls_ctr_drbg_context kr;
k = calloc(1, sizeof(mbedtls_pk_context));
mbedtls_x509write_crt_init(wcert);
mbedtls_x509write_crt_set_issuer_key(wcert, ca ? ca->key : k);
mbedtls_x509write_crt_set_subject_key(wcert, k);
mbedtls_x509write_crt_set_md_alg(
wcert, suiteb ? MBEDTLS_MD_SHA384 : MBEDTLS_MD_SHA256);
mbedtls_x509write_crt_set_version(wcert, MBEDTLS_X509_CRT_VERSION_3);
CHECK_EQ(0, mbedtls_pk_setup(k, mbedtls_pk_info_from_type(type)));
return k;
}
static struct Cert FinishCertificate(struct Cert *ca,
mbedtls_x509write_cert *wcert,
mbedtls_ctr_drbg_context *kr,
mbedtls_pk_context *key) {
int i, n, rc;
unsigned char *p;
mbedtls_x509_crt *cert;
p = malloc((n = FRAMESIZE));
i = mbedtls_x509write_crt_der(wcert, p, n, mbedtls_ctr_drbg_random, kr);
if (i < 0) FATALF("write key (grep -0x%04x)", -i);
cert = calloc(1, sizeof(mbedtls_x509_crt));
mbedtls_x509_crt_parse(cert, p + n - i, i);
if (ca) cert->next = ca->cert;
mbedtls_x509write_crt_free(wcert);
mbedtls_ctr_drbg_free(kr);
free(p);
if ((rc = mbedtls_pk_check_pair(&cert->pk, key))) {
FATALF("generate key (grep -0x%04x)", -rc);
}
LogCertificate(
gc(xasprintf("generated %s certificate", mbedtls_pk_get_name(&cert->pk))),
cert);
return (struct Cert){cert, key};
}
static struct Cert GenerateEcpCertificate(struct Cert *ca) {
mbedtls_pk_context *key;
mbedtls_md_type_t md_alg;
mbedtls_ctr_drbg_context kr;
mbedtls_x509write_cert wcert;
InitializeRng(&kr);
key = InitializeKey(ca, &wcert, MBEDTLS_PK_ECKEY);
md_alg = suiteb ? MBEDTLS_MD_SHA384 : MBEDTLS_MD_SHA256;
key = InitializeKey(ca, &wcert, md_alg, MBEDTLS_PK_ECKEY);
CHECK_EQ(0, mbedtls_ecp_gen_key(
suiteb ? MBEDTLS_ECP_DP_SECP384R1 : MBEDTLS_ECP_DP_SECP256R1,
mbedtls_pk_ec(*key), mbedtls_ctr_drbg_random, &kr));
GenerateSerial(&wcert, &kr);
GenerateCertificateSerial(&wcert, &kr);
ConfigureCertificate(&wcert, ca, MBEDTLS_X509_KU_DIGITAL_SIGNATURE,
MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER |
MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT);
@ -1853,13 +1647,15 @@ static struct Cert GenerateEcpCertificate(struct Cert *ca) {
static struct Cert GenerateRsaCertificate(struct Cert *ca) {
mbedtls_pk_context *key;
mbedtls_md_type_t md_alg;
mbedtls_ctr_drbg_context kr;
mbedtls_x509write_cert wcert;
InitializeRng(&kr);
key = InitializeKey(ca, &wcert, MBEDTLS_PK_RSA);
md_alg = suiteb ? MBEDTLS_MD_SHA384 : MBEDTLS_MD_SHA256;
key = InitializeKey(ca, &wcert, md_alg, MBEDTLS_PK_RSA);
CHECK_EQ(0, mbedtls_rsa_gen_key(mbedtls_pk_rsa(*key), mbedtls_ctr_drbg_random,
&kr, suiteb ? 4096 : 2048, 65537));
GenerateSerial(&wcert, &kr);
GenerateCertificateSerial(&wcert, &kr);
ConfigureCertificate(
&wcert, ca,
MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_ENCIPHERMENT,
@ -1942,65 +1738,6 @@ static int64_t GetGmtOffset(int64_t t) {
return tm.tm_gmtoff;
}
static int64_t LocoTimeToZulu(int64_t x) {
return x - gmtoff;
}
static int64_t GetZipCfileLastModified(const uint8_t *zcf) {
const uint8_t *p, *pe;
for (p = ZIP_CFILE_EXTRA(zcf), pe = p + ZIP_CFILE_EXTRASIZE(zcf); p + 4 <= pe;
p += ZIP_EXTRA_SIZE(p)) {
if (ZIP_EXTRA_HEADERID(p) == kZipExtraNtfs &&
ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4 + 8 &&
READ16LE(ZIP_EXTRA_CONTENT(p) + 4) == 1 &&
READ16LE(ZIP_EXTRA_CONTENT(p) + 6) >= 8) {
return READ64LE(ZIP_EXTRA_CONTENT(p) + 8) / HECTONANOSECONDS -
MODERNITYSECONDS; /* TODO(jart): update access time */
}
}
for (p = ZIP_CFILE_EXTRA(zcf), pe = p + ZIP_CFILE_EXTRASIZE(zcf); p + 4 <= pe;
p += ZIP_EXTRA_SIZE(p)) {
if (ZIP_EXTRA_HEADERID(p) == kZipExtraExtendedTimestamp &&
ZIP_EXTRA_CONTENTSIZE(p) >= 1 + 4 && (*ZIP_EXTRA_CONTENT(p) & 1)) {
return (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 1);
}
}
for (p = ZIP_CFILE_EXTRA(zcf), pe = p + ZIP_CFILE_EXTRASIZE(zcf); p + 4 <= pe;
p += ZIP_EXTRA_SIZE(p)) {
if (ZIP_EXTRA_HEADERID(p) == kZipExtraUnix &&
ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4) {
return (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 4);
}
}
return LocoTimeToZulu(DosDateTimeToUnix(ZIP_CFILE_LASTMODIFIEDDATE(zcf),
ZIP_CFILE_LASTMODIFIEDTIME(zcf)));
}
static int64_t GetZipCfileCreation(const uint8_t *zcf) {
const uint8_t *p, *pe;
for (p = ZIP_CFILE_EXTRA(zcf), pe = p + ZIP_CFILE_EXTRASIZE(zcf); p + 4 <= pe;
p += ZIP_EXTRA_SIZE(p)) {
if (ZIP_EXTRA_HEADERID(p) == kZipExtraNtfs &&
ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4 + 8 * 3 &&
READ16LE(ZIP_EXTRA_CONTENT(p) + 4) == 1 &&
READ16LE(ZIP_EXTRA_CONTENT(p) + 6) >= 24) {
return READ64LE(ZIP_EXTRA_CONTENT(p) + 8 + 8 + 8) / HECTONANOSECONDS -
MODERNITYSECONDS;
}
}
for (p = ZIP_CFILE_EXTRA(zcf), pe = p + ZIP_CFILE_EXTRASIZE(zcf); p + 4 <= pe;
p += ZIP_EXTRA_SIZE(p)) {
if (ZIP_EXTRA_HEADERID(p) == kZipExtraExtendedTimestamp &&
ZIP_EXTRA_CONTENTSIZE(p) >= 1 && (*ZIP_EXTRA_CONTENT(p) & 4) &&
ZIP_EXTRA_CONTENTSIZE(p) >=
1 + popcnt((*ZIP_EXTRA_CONTENT(p) & 7)) * 4) {
return (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 1 +
popcnt((*ZIP_EXTRA_CONTENT(p) & 3)) * 4);
}
}
return GetZipCfileLastModified(zcf);
}
forceinline bool IsCompressed(struct Asset *a) {
return !a->file &&
ZIP_LFILE_COMPRESSIONMETHOD(zbase + a->lf) == kZipCompressionDeflate;
@ -2054,9 +1791,9 @@ static void FreeStrings(struct Strings *l) {
}
static void IndexAssets(void) {
int64_t lm;
uint64_t cf;
struct Asset *p;
struct timespec lm;
uint32_t i, n, m, step, hash;
DEBUGF("indexing assets (inode %#lx)", zst.st_ino);
CHECK_GE(HASH_LOAD_FACTOR, 2);
@ -2080,13 +1817,13 @@ static void IndexAssets(void) {
i = (hash + (step * (step + 1)) >> 1) & (m - 1);
++step;
} while (p[i].hash);
lm = GetZipCfileLastModified(zbase + cf);
GetZipCfileTimestamps(zbase + cf, &lm, 0, 0, gmtoff);
p[i].hash = hash;
p[i].cf = cf;
p[i].lf = GetZipCfileOffset(zbase + cf);
p[i].istext = !!(ZIP_CFILE_INTERNALATTRIBUTES(zbase + cf) & kZipIattrText);
p[i].lastmodified = lm;
p[i].lastmodifiedstr = FormatUnixHttpDateTime(xmalloc(30), lm);
p[i].lastmodified = lm.tv_sec;
p[i].lastmodifiedstr = FormatUnixHttpDateTime(xmalloc(30), lm.tv_sec);
}
assets.p = p;
assets.n = m;
@ -2891,9 +2628,9 @@ static char *ServeListing(void) {
uint8_t *zcf;
struct tm tm;
const char *and;
int64_t lastmod;
struct rusage ru;
char *p, *q, *path;
struct timespec lastmod;
char rb[8], tb[20], *rp[6];
size_t i, n, pathlen, rn[6];
LockInc(&shared->c.listingrequests);
@ -2951,8 +2688,8 @@ td { padding-right: 3em; }\r\n\
ZIP_CFILE_COMMENT(zcf),
strnlen(ZIP_CFILE_COMMENT(zcf), ZIP_CFILE_COMMENTSIZE(zcf)), &rn[3]);
rp[4] = EscapeHtml(rp[0], rn[0], &rn[4]);
lastmod = GetZipCfileLastModified(zcf);
localtime_r(&lastmod, &tm);
GetZipCfileTimestamps(zcf, &lastmod, 0, 0, gmtoff);
localtime_r(&lastmod.tv_sec, &tm);
iso8601(tb, &tm);
if (IsCompressionMethodSupported(ZIP_CFILE_COMPRESSIONMETHOD(zcf)) &&
IsAcceptablePath(path, pathlen)) {
@ -3421,30 +3158,6 @@ static void GetDosLocalTime(int64_t utcunixts, uint16_t *out_time,
*out_date = DOS_DATE(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday + 1);
}
static bool IsUtf8(const void *data, size_t size) {
const unsigned char *p, *pe;
for (p = data, pe = p + size; p + 2 <= pe; ++p) {
if (p[0] >= 0300) {
if (p[1] >= 0200 && p[1] < 0300) {
return true;
} else {
return false;
}
}
}
return false;
}
static bool IsText(const void *data, size_t size) {
const unsigned char *p, *pe;
for (p = data, pe = p + size; p < pe; ++p) {
if (*p <= 3) {
return false;
}
}
return true;
}
static int LuaStoreAsset(lua_State *L) {
int64_t ft;
int i, mode;
@ -3646,12 +3359,6 @@ static void ReseedRng(mbedtls_ctr_drbg_context *r, const char *s) {
#endif
}
static char *TlsError(int r) {
static char b[128];
mbedtls_strerror(r, b, sizeof(b));
return b;
}
static wontreturn void LuaThrowTlsError(lua_State *L, const char *s, int r) {
const char *code;
code = gc(xasprintf("-0x%04x", -r));
@ -3663,35 +3370,6 @@ static wontreturn void LuaThrowTlsError(lua_State *L, const char *s, int r) {
unreachable;
}
static bool Tune(int fd, int a, int b, int x) {
if (!b) return false;
return setsockopt(fd, a, b, &x, sizeof(x)) != -1;
}
static int Socket(int family, int type, int protocol, bool isserver) {
int fd;
if ((fd = socket(family, type, protocol)) != -1) {
if (isserver) {
Tune(fd, SOL_TCP, TCP_FASTOPEN, 100);
Tune(fd, SOL_SOCKET, SO_REUSEADDR, 1);
} else {
Tune(fd, SOL_TCP, TCP_FASTOPEN_CONNECT, 1);
}
if (!Tune(fd, SOL_TCP, TCP_QUICKACK, 1)) {
Tune(fd, SOL_TCP, TCP_NODELAY, 1);
}
if (timeout.tv_sec < 0) {
Tune(fd, SOL_SOCKET, SO_KEEPALIVE, 1);
Tune(fd, SOL_TCP, TCP_KEEPIDLE, -timeout.tv_sec);
Tune(fd, SOL_TCP, TCP_KEEPINTVL, -timeout.tv_sec);
} else {
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
}
}
return fd;
}
static char *FoldHeader(struct HttpMessage *msg, char *b, int h, size_t *z) {
char *p;
size_t i, n, m;
@ -3924,8 +3602,8 @@ static int LuaFetch(lua_State *L) {
ip = ntohl(((struct sockaddr_in *)addr->ai_addr)->sin_addr.s_addr);
DEBUGF("client connecting %hhu.%hhu.%hhu.%hhu:%d", ip >> 24, ip >> 16,
ip >> 8, ip, ntohs(((struct sockaddr_in *)addr->ai_addr)->sin_port));
CHECK_NE(-1, (sock = Socket(addr->ai_family, addr->ai_socktype,
addr->ai_protocol, false)));
CHECK_NE(-1, (sock = GoodSocket(addr->ai_family, addr->ai_socktype,
addr->ai_protocol, false, &timeout)));
if (connect(sock, addr->ai_addr, addr->ai_addrlen) == -1) {
close(sock);
luaL_error(L, "connect(%s:%s) failed: %s", host, port, strerror(errno));
@ -5168,13 +4846,17 @@ static int LuaGetLastModifiedTime(lua_State *L) {
size_t pathlen;
struct Asset *a;
const char *path;
struct timespec lm;
int64_t zuluseconds;
path = LuaCheckPath(L, 1, &pathlen);
if ((a = GetAsset(path, pathlen))) {
if (a->file) {
lua_pushinteger(L, a->file->st.st_mtim.tv_sec);
zuluseconds = a->file->st.st_mtim.tv_sec;
} else {
lua_pushinteger(L, GetZipCfileLastModified(zbase + a->cf));
GetZipCfileTimestamps(zbase + a->cf, &lm, 0, 0, gmtoff);
zuluseconds = lm.tv_sec;
}
lua_pushinteger(L, zuluseconds);
} else {
lua_pushnil(L);
}
@ -6216,8 +5898,8 @@ static char *ServeAsset(struct Asset *a, const char *path, size_t pathlen) {
}
} else if (!IsTiny() && msg.method != kHttpHead && !IsSslCompressed() &&
ClientAcceptsGzip() &&
((contentlength >= 100 && StartsWithIgnoreCase(ct, "text/")) ||
(contentlength >= 1000 && MeasureEntropy(content, 1000) < 6))) {
((contentlength >= 100 && startswithi(ct, "text/")) ||
(contentlength >= 1000 && MeasureEntropy(content, 1000) < 7))) {
p = ServeAssetCompressed(a);
} else {
p = ServeAssetIdentity(a, ct);
@ -6725,8 +6407,8 @@ static void Listen(void) {
servers.p[n].addr.sin_family = AF_INET;
servers.p[n].addr.sin_port = htons(ports.p[j]);
servers.p[n].addr.sin_addr.s_addr = htonl(ips.p[i]);
if ((servers.p[n].fd = Socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC,
IPPROTO_TCP, true)) == -1) {
if ((servers.p[n].fd = GoodSocket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC,
IPPROTO_TCP, true, &timeout)) == -1) {
perror("socket");
exit(1);
}

View file

@ -27,9 +27,11 @@
#include "libc/mem/mem.h"
#include "libc/rand/rand.h"
#include "libc/runtime/gc.internal.h"
#include "libc/sock/goodsocket.internal.h"
#include "libc/sock/sock.h"
#include "libc/stdio/append.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/slice.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ex.h"
@ -109,37 +111,6 @@ void OnInt(int sig) {
isdone = true;
}
static inline bool SlicesEqualCase(const char *a, size_t n, const char *b,
size_t m) {
return n == m && !memcasecmp(a, b, n);
}
static int GetEntropy(void *c, unsigned char *p, size_t n) {
rngset(p, n, rand64, -1);
return 0;
}
static bool TuneSocket(int fd, int a, int b, int x) {
if (!b) return false;
return setsockopt(fd, a, b, &x, sizeof(x)) != -1;
}
static int Socket(int family, int type, int protocol) {
int fd;
if ((fd = socket(family, type, protocol)) != -1) {
/* TuneSocket(fd, SOL_SOCKET, SO_KEEPALIVE, 1); */
/* if (protocol == SOL_TCP) { */
/* TuneSocket(fd, SOL_TCP, TCP_KEEPIDLE, 60); */
/* TuneSocket(fd, SOL_TCP, TCP_KEEPINTVL, 60); */
/* TuneSocket(fd, SOL_TCP, TCP_FASTOPEN_CONNECT, 1); */
/* if (!TuneSocket(fd, SOL_TCP, TCP_QUICKACK, 1)) { */
/* TuneSocket(fd, SOL_TCP, TCP_NODELAY, 1); */
/* } */
/* } */
}
return fd;
}
static int TlsSend(void *c, const unsigned char *p, size_t n) {
int rc;
if ((rc = write(*(int *)c, p, n)) == -1) {
@ -174,21 +145,6 @@ static int TlsRecv(void *c, unsigned char *p, size_t n, uint32_t o) {
return r;
}
static char *TlsError(int r) {
static char b[128];
mbedtls_strerror(r, b, sizeof(b));
return b;
}
static wontreturn void TlsDie(const char *s, int r) {
if (IsTiny()) {
fprintf(stderr, "error: %s (-0x%04x %s)\n", s, -r, TlsError(r));
} else {
fprintf(stderr, "error: %s (grep -0x%04x)\n", s, -r);
}
exit(1);
}
static wontreturn void PrintUsage(FILE *f, int rc) {
fprintf(f, "usage: %s [-ksvV] URL\n", program_invocation_name);
exit(rc);
@ -219,8 +175,8 @@ int fetch(void) {
*/
InitHttpMessage(&msg, kHttpResponse);
ip = ntohl(((struct sockaddr_in *)addr->ai_addr)->sin_addr.s_addr);
CHECK_NE(-1, (sock = Socket(addr->ai_family, addr->ai_socktype,
addr->ai_protocol)));
CHECK_NE(-1, (sock = GoodSocket(addr->ai_family, addr->ai_socktype,
addr->ai_protocol, false, 0)));
if (connect(sock, addr->ai_addr, addr->ai_addrlen) == -1) {
goto TransportError;
}