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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

View file

@ -21,9 +21,11 @@
#include "libc/rand/rand.h"
#include "libc/runtime/gc.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/stdio.h"
#include "libc/str/slice.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/dt.h"
@ -63,32 +65,11 @@
#define HeaderEqualCase(H, S) \
SlicesEqualCase(S, strlen(S), HeaderData(H), HeaderLength(H))
static inline bool SlicesEqualCase(const char *a, size_t n, const char *b,
size_t m) {
return n == m && !memcasecmp(a, b, n);
}
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;
NOISEF("begin send %zu", n);
@ -119,35 +100,11 @@ static int TlsRecv(void *c, unsigned char *p, size_t n, uint32_t o) {
return MIN(n, r);
}
static void TlsDebug(void *c, int v, const char *f, int l, const char *s) {
flogf(v, f, l, 0, "TLS %s", s);
}
static char *TlsError(int r) {
static char b[128];
mbedtls_strerror(r, b, sizeof(b));
return b;
}
static wontreturn void PrintUsage(FILE *f, int rc) {
fprintf(f, "usage: %s [-ksvV] URL\n", program_invocation_name);
exit(rc);
}
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 int GetEntropy(void *c, unsigned char *p, size_t n) {
CHECK_EQ(n, getrandom(p, n, 0));
return 0;
}
int main(int argc, char *argv[]) {
if (!NoDebug()) showcrashreports();
xsigaction(SIGPIPE, SIG_IGN, 0, 0, 0);
@ -302,8 +259,9 @@ int main(int argc, char *argv[]) {
* Connect to server.
*/
int ret, sock;
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,
&(struct timeval){-60})));
CHECK_NE(-1, connect(sock, addr->ai_addr, addr->ai_addrlen));
freeaddrinfo(addr);
if (usessl) {

39
libc/calls/addrusage.c Normal file
View file

@ -0,0 +1,39 @@
/*-*- 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/calls/math.h"
#include "libc/macros.internal.h"
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;
}

28
libc/calls/addtimeval.c Normal file
View file

@ -0,0 +1,28 @@
/*-*- 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/calls/math.h"
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;
}
}

13
libc/calls/math.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_MATH_H_
#define COSMOPOLITAN_LIBC_CALLS_MATH_H_
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/timeval.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void AddTimeval(struct timeval *, const struct timeval *);
void AddRusage(struct rusage *, const struct rusage *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_MATH_H_ */

View file

@ -39,6 +39,7 @@ long sizetol(const char *, long) paramsnonnull() libcesque;
cosmopolitan § conversion » time
*/
struct timespec WindowsTimeToTime(uint64_t);
int64_t DosDateTimeToUnix(unsigned, unsigned);
struct timespec FileTimeToTimeSpec(struct NtFileTime);
struct NtFileTime TimeSpecToFileTime(struct timespec);
@ -48,6 +49,11 @@ void FileTimeToTimeVal(struct timeval *, struct NtFileTime) nothrow;
struct NtFileTime TimeValToFileTime(const struct timeval *) nosideeffect;
long convertmicros(const struct timeval *, long) paramsnonnull() nosideeffect;
/* forceinline struct timespec WindowsTimeToTime(uint64_t x) { */
/* return (struct timespec){x / HECTONANOSECONDS - MODERNITYSECONDS, */
/* x % HECTONANOSECONDS * 100}; */
/* } */
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § conversion » manipulation
*/

View file

@ -58,6 +58,7 @@ $(LIBC_FMT_A_OBJS): \
OVERRIDE_CFLAGS += \
-fno-jump-tables
o/$(MODE)/libc/fmt/windowstimetotime.o \
o/$(MODE)/libc/fmt/dosdatetimetounix.o \
o/$(MODE)/libc/fmt/itoa64radix10.greg.o \
o/$(MODE)/libc/fmt/timetofiletime.o \

59
libc/sock/goodsocket.c Normal file
View file

@ -0,0 +1,59 @@
/*-*- 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/calls/struct/timeval.h"
#include "libc/sock/goodsocket.internal.h"
#include "libc/sock/sock.h"
#include "libc/sysv/consts/so.h"
#include "libc/sysv/consts/sol.h"
#include "libc/sysv/consts/tcp.h"
static bool Tune(int fd, int a, int b, int x) {
if (!b) return false;
return setsockopt(fd, a, b, &x, sizeof(x)) != -1;
}
/**
* Returns new socket with modern goodness enabled.
*/
int GoodSocket(int family, int type, int protocol, bool isserver,
const struct timeval *timeout) {
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) {
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;
}

View file

@ -0,0 +1,11 @@
#ifndef COSMOPOLITAN_LIBC_SOCK_GOODSOCKET_H_
#define COSMOPOLITAN_LIBC_SOCK_GOODSOCKET_H_
#include "libc/calls/struct/timeval.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int GoodSocket(int, int, int, bool, const struct timeval *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_SOCK_GOODSOCKET_H_ */

28
libc/str/compareslices.c Normal file
View file

@ -0,0 +1,28 @@
/*-*- 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/macros.internal.h"
#include "libc/str/slice.h"
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;
}

View file

@ -0,0 +1,28 @@
/*-*- 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/macros.internal.h"
#include "libc/str/slice.h"
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;
}

View file

@ -0,0 +1,101 @@
/*-*- 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/conv.h"
#include "libc/zip.h"
static inline int pop(int x) {
return !!(x & 1) + !!(x & 2) + !!(x & 4);
}
/**
* Extracts modified/access/creation timestamps from zip entry.
*
* @param cf is pointer to central directory header for file
* @param mtim optionally receives last modified timestamp
* @param atim optionally receives modified timestamp
* @param ctim optionally receives creation timestamp
* @param gmtoff is seconds adjustment for legacy dos timestamps
*/
void GetZipCfileTimestamps(const uint8_t *cf, struct timespec *mtim,
struct timespec *atim, struct timespec *ctim,
int gmtoff) {
const uint8_t *p, *pe;
if (mtim) *mtim = (struct timespec){0};
if (atim) *atim = (struct timespec){0};
if (ctim) *ctim = (struct timespec){0};
for (p = ZIP_CFILE_EXTRA(cf), pe = p + ZIP_CFILE_EXTRASIZE(cf); 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) {
if (mtim) {
*mtim = WindowsTimeToTime(READ64LE(ZIP_EXTRA_CONTENT(p) + 8));
}
if (atim && ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4 + 8 * 2 &&
READ16LE(ZIP_EXTRA_CONTENT(p) + 6) >= 16) {
*atim = WindowsTimeToTime(READ64LE(ZIP_EXTRA_CONTENT(p) + 8 * 2));
}
if (ctim && ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4 + 8 * 3 &&
READ16LE(ZIP_EXTRA_CONTENT(p) + 6) >= 24) {
*ctim = WindowsTimeToTime(READ64LE(ZIP_EXTRA_CONTENT(p) + 8 * 3));
}
return;
}
}
for (p = ZIP_CFILE_EXTRA(cf), pe = p + ZIP_CFILE_EXTRASIZE(cf); p + 4 <= pe;
p += ZIP_EXTRA_SIZE(p)) {
if (ZIP_EXTRA_HEADERID(p) == kZipExtraExtendedTimestamp &&
ZIP_EXTRA_CONTENTSIZE(p) > 1 &&
ZIP_EXTRA_CONTENTSIZE(p) == 1 + 4 * pop(*ZIP_EXTRA_CONTENT(p) & 7)) {
if (mtim) {
if (*ZIP_EXTRA_CONTENT(p) & 1) {
mtim->tv_sec = (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 1);
} else {
mtim->tv_sec = DosDateTimeToUnix(ZIP_CFILE_LASTMODIFIEDDATE(cf),
ZIP_CFILE_LASTMODIFIEDTIME(cf)) -
gmtoff;
}
}
if (atim && (*ZIP_EXTRA_CONTENT(p) & 2)) {
atim->tv_sec = (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 1 +
4 * (*ZIP_EXTRA_CONTENT(p) & 1));
}
if (ctim && (*ZIP_EXTRA_CONTENT(p) & 4)) {
ctim->tv_sec = (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 1 +
4 * pop(*ZIP_EXTRA_CONTENT(p) & 3));
}
return;
}
}
for (p = ZIP_CFILE_EXTRA(cf), pe = p + ZIP_CFILE_EXTRASIZE(cf); p + 4 <= pe;
p += ZIP_EXTRA_SIZE(p)) {
if (ZIP_EXTRA_HEADERID(p) == kZipExtraUnix &&
ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4) {
if (atim) atim->tv_sec = (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 0);
if (mtim) mtim->tv_sec = (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 4);
return;
}
}
if (mtim) {
mtim->tv_sec = DosDateTimeToUnix(ZIP_CFILE_LASTMODIFIEDDATE(cf),
ZIP_CFILE_LASTMODIFIEDTIME(cf)) -
gmtoff;
}
}

32
libc/str/istext.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- 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/str/str.h"
/**
* Returns true if buffer is most likely plaintext.
*/
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;
}

38
libc/str/isutf8.c Normal file
View file

@ -0,0 +1,38 @@
/*-*- 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/str/str.h"
/**
* Returns true if text data is most likely utf-8.
*
* This function will return false if a pure ascii string is passed.
*/
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;
}

22
libc/str/slice.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef COSMOPOLITAN_LIBC_STR_SLICE_H_
#define COSMOPOLITAN_LIBC_STR_SLICE_H_
#include "libc/str/str.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
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);
}
int CompareSlices(const char *, size_t, const char *, size_t);
int CompareSlicesCase(const char *, size_t, const char *, size_t);
bool StartsWithIgnoreCase(const char *, const char *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_STR_SLICE_H_ */

27
libc/str/startswithi.c Normal file
View file

@ -0,0 +1,27 @@
/*-*- 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/str/str.h"
bool startswithi(const char *s, const char *prefix) {
for (;;) {
if (!*prefix) return true;
if (!*s) return false;
if (kToLower[*s++ & 255] != (*prefix++ & 255)) return false;
}
}

View file

@ -171,6 +171,7 @@ wchar_t *wcstok(wchar_t *, const wchar_t *, wchar_t **) paramsnonnull((2, 3));
char *wstrtrunc(uint16_t *) memcpyesque;
char *wstrntrunc(uint16_t *, size_t) memcpyesque;
bool startswith(const char *, const char *) strlenesque;
bool startswithi(const char *, const char *) strlenesque;
bool startswith16(const char16_t *, const char16_t *) strlenesque;
bool wcsstartswith(const wchar_t *, const wchar_t *) strlenesque;
bool endswith(const char *, const char *) strlenesque;
@ -197,6 +198,8 @@ char *strtoupper(char *) paramsnonnull();
char *chomp(char *);
char16_t *chomp16(char16_t *);
wchar_t *wchomp(wchar_t *);
bool IsText(const void *, size_t);
bool IsUtf8(const void *, size_t);
bool escapedos(char16_t *, unsigned, const char16_t *, unsigned);

View file

@ -48,6 +48,14 @@ o/$(MODE)/libc/str/memmem.o: \
OVERRIDE_CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED
o//libc/str/bzero.o: \
OVERRIDE_CFLAGS += \
-O2
o/$(MODE)/libc/str/dosdatetimetounix.o: \
OVERRIDE_CFLAGS += \
-O3
o/$(MODE)/libc/str/getzipcdir.o \
o/$(MODE)/libc/str/getzipcdircomment.o \
o/$(MODE)/libc/str/getzipcdircommentsize.o \
@ -58,20 +66,21 @@ o/$(MODE)/libc/str/getzipcfilemode.o \
o/$(MODE)/libc/str/getzipcfileoffset.o \
o/$(MODE)/libc/str/getzipcfileuncompressedsize.o \
o/$(MODE)/libc/str/getziplfilecompressedsize.o \
o/$(MODE)/libc/str/getziplfileuncompressedsize.o: \
o/$(MODE)/libc/str/getziplfileuncompressedsize.o \
o/$(MODE)/libc/str/getzipcfiletimestamps.o: \
OVERRIDE_CFLAGS += \
-Os
o//libc/str/bzero.o: \
OVERRIDE_CFLAGS += \
-O2
o/$(MODE)/libc/str/iswpunct.o \
o/$(MODE)/libc/str/iswupper.o \
o/$(MODE)/libc/str/iswlower.o: \
OVERRIDE_CFLAGS += \
-fno-jump-tables
o/$(MODE)/libc/str/windowstimetotime.o: \
OVERRIDE_CFLAGS += \
-O3
LIBC_STR_LIBS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)))
LIBC_STR_SRCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_SRCS))
LIBC_STR_HDRS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_HDRS))

View file

@ -0,0 +1,24 @@
/*-*- 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/conv.h"
struct timespec WindowsTimeToTime(uint64_t x) {
return (struct timespec){x / HECTONANOSECONDS - MODERNITYSECONDS,
x % HECTONANOSECONDS * 100};
}

View file

@ -1,6 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_ZIP_H_
#define COSMOPOLITAN_LIBC_ZIP_H_
#include "libc/bits/bits.h"
#include "libc/calls/struct/timespec.h"
#include "libc/macros.internal.h"
#include "libc/str/str.h"
@ -199,6 +200,8 @@ uint64_t GetZipCfileOffset(const uint8_t *);
uint64_t GetZipLfileUncompressedSize(const uint8_t *);
uint64_t GetZipLfileCompressedSize(const uint8_t *);
uint8_t *zipfindcentraldir(const uint8_t *, size_t);
void GetZipCfileTimestamps(const uint8_t *, struct timespec *,
struct timespec *, struct timespec *, int);
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_ZIP_H_ */

View file

@ -18,75 +18,12 @@
*/
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/fmt/conv.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
#include "libc/zip.h"
#include "libc/zipos/zipos.internal.h"
static int popcnt3(int x) {
return !!(x & 1) + !!(x & 2) + !!(x & 4);
}
static struct timespec WindowsTimeToTime(uint64_t x) {
return (struct timespec){x / HECTONANOSECONDS - MODERNITYSECONDS,
x % HECTONANOSECONDS * 100};
}
static void GetZipCfileTimestamps(const uint8_t *zcf, struct stat *st) {
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) {
st->st_mtim = WindowsTimeToTime(READ64LE(ZIP_EXTRA_CONTENT(p) + 8));
if (ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4 + 8 * 2 &&
READ16LE(ZIP_EXTRA_CONTENT(p) + 6) >= 16) {
st->st_atim = WindowsTimeToTime(READ64LE(ZIP_EXTRA_CONTENT(p) + 8 * 2));
}
if (ZIP_EXTRA_CONTENTSIZE(p) >= 4 + 4 + 8 * 3 &&
READ16LE(ZIP_EXTRA_CONTENT(p) + 6) >= 24) {
st->st_ctim = WindowsTimeToTime(READ64LE(ZIP_EXTRA_CONTENT(p) + 8 * 3));
}
return;
}
}
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_CONTENTSIZE(p) ==
1 + 4 * popcnt3(*ZIP_EXTRA_CONTENT(p) & 7)) {
if (*ZIP_EXTRA_CONTENT(p) & 1) {
st->st_mtim.tv_sec = READ32LE(ZIP_EXTRA_CONTENT(p) + 1);
}
if (*ZIP_EXTRA_CONTENT(p) & 2) {
st->st_atim.tv_sec = READ32LE(ZIP_EXTRA_CONTENT(p) + 1 +
4 * (*ZIP_EXTRA_CONTENT(p) & 1));
}
if (*ZIP_EXTRA_CONTENT(p) & 4) {
st->st_ctim.tv_sec = READ32LE(ZIP_EXTRA_CONTENT(p) + 1 +
4 * popcnt3(*ZIP_EXTRA_CONTENT(p) & 3));
}
return;
}
}
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) {
st->st_atim.tv_sec = (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 0);
st->st_mtim.tv_sec = (int32_t)READ32LE(ZIP_EXTRA_CONTENT(p) + 4);
return;
}
}
st->st_mtim.tv_sec = DosDateTimeToUnix(ZIP_CFILE_LASTMODIFIEDDATE(zcf),
ZIP_CFILE_LASTMODIFIEDTIME(zcf));
}
int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) {
size_t lf;
if (zipos && st) {
@ -100,7 +37,8 @@ int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) {
st->st_size = GetZipLfileUncompressedSize(zipos->map + lf);
st->st_blocks =
roundup(GetZipLfileCompressedSize(zipos->map + lf), 512) / 512;
GetZipCfileTimestamps(zipos->map + cf, st);
GetZipCfileTimestamps(zipos->map + cf, &st->st_mtim, &st->st_atim,
&st->st_ctim, 0);
return 0;
} else {
return einval();

32
net/https/certhashost.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- 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/str/slice.h"
#include "net/https/https.h"
bool CertHasHost(const mbedtls_x509_crt *cert, const void *s, size_t n) {
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(s, n, cur->buf.p, cur->buf.len)) {
return true;
}
}
return false;
}

32
net/https/certhasip.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- 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/bits/bits.h"
#include "net/https/https.h"
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;
}

View file

@ -0,0 +1,35 @@
/*-*- 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/log/log.h"
#include "libc/runtime/gc.internal.h"
#include "net/https/https.h"
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;
}
}

View file

@ -0,0 +1,33 @@
/*-*- 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/time/struct/tm.h"
#include "libc/time/time.h"
#include "net/https/https.h"
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));
}

View file

@ -0,0 +1,46 @@
/*-*- 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/log/log.h"
#include "libc/runtime/gc.internal.h"
#include "libc/x/x.h"
#include "net/https/https.h"
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};
}

View file

@ -0,0 +1,26 @@
/*-*- 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/log/check.h"
#include "net/https/https.h"
char *FormatX509Name(mbedtls_x509_name *name) {
char *s = calloc(1, 1000);
CHECK_GT(mbedtls_x509_dn_gets(s, 1000, name), 0);
return s;
}

View file

@ -0,0 +1,30 @@
/*-*- 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 "net/https/https.h"
#include "third_party/mbedtls/bignum.h"
#include "third_party/mbedtls/ctr_drbg.h"
void GenerateCertificateSerial(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);
}

26
net/https/getentropy.c Normal file
View file

@ -0,0 +1,26 @@
/*-*- 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/log/check.h"
#include "libc/rand/rand.h"
#include "net/https/https.h"
int GetEntropy(void *c, unsigned char *p, size_t n) {
CHECK_EQ(n, getrandom(p, n, 0));
return 0;
}

View file

@ -1,14 +1,44 @@
#ifndef COSMOPOLITAN_NET_HTTPS_HTTPS_H_
#define COSMOPOLITAN_NET_HTTPS_HTTPS_H_
#include "libc/time/struct/tm.h"
#include "third_party/mbedtls/ctr_drbg.h"
#include "third_party/mbedtls/ecp.h"
#include "third_party/mbedtls/md.h"
#include "third_party/mbedtls/pk.h"
#include "third_party/mbedtls/ssl_ciphersuites.h"
#include "third_party/mbedtls/x509_crt.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct Cert {
mbedtls_x509_crt *cert;
mbedtls_pk_context *key;
};
char *TlsError(int);
char *DescribeSslVerifyFailure(int);
mbedtls_x509_crt *GetSslRoots(void);
void InitializeRng(mbedtls_ctr_drbg_context *);
int GetEntropy(void *, unsigned char *, size_t);
void FormatSslTime(char[restrict hasatleast 16], struct tm *);
void ChooseCertificateLifetime(char[16], char[16]);
void LogCertificate(const char *, mbedtls_x509_crt *);
bool IsSelfSigned(mbedtls_x509_crt *);
char *FormatX509Name(mbedtls_x509_name *);
void TlsDie(const char *, int) wontreturn;
bool ChainCertificate(mbedtls_x509_crt *, mbedtls_x509_crt *);
bool CertHasIp(const mbedtls_x509_crt *, uint32_t);
bool CertHasHost(const mbedtls_x509_crt *, const void *, size_t);
bool CertHasCommonName(const mbedtls_x509_crt *, const void *, size_t);
bool IsServerCert(const struct Cert *, mbedtls_pk_type_t);
void TlsDebug(void *, int, const char *, int, const char *);
void GenerateCertificateSerial(mbedtls_x509write_cert *,
mbedtls_ctr_drbg_context *);
mbedtls_pk_context *InitializeKey(struct Cert *, mbedtls_x509write_cert *,
mbedtls_md_type_t, int);
struct Cert FinishCertificate(struct Cert *, mbedtls_x509write_cert *,
mbedtls_ctr_drbg_context *, mbedtls_pk_context *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -27,11 +27,13 @@ NET_HTTPS_A_DIRECTDEPS = \
LIBC_LOG \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_RAND \
LIBC_RUNTIME \
LIBC_STDIO \
LIBC_STR \
LIBC_STUBS \
LIBC_SYSV \
LIBC_TIME \
LIBC_X \
LIBC_ZIPOS \
THIRD_PARTY_MBEDTLS

35
net/https/initializekey.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- 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/log/check.h"
#include "net/https/https.h"
mbedtls_pk_context *InitializeKey(struct Cert *ca,
mbedtls_x509write_cert *wcert,
mbedtls_md_type_t md_alg, 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, md_alg);
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;
}

30
net/https/initializerng.c Normal file
View file

@ -0,0 +1,30 @@
/*-*- 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/log/check.h"
#include "libc/rand/rand.h"
#include "net/https/https.h"
#include "third_party/mbedtls/ctr_drbg.h"
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);
}

23
net/https/isselfsigned.c Normal file
View file

@ -0,0 +1,23 @@
/*-*- 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 "net/https/https.h"
bool IsSelfSigned(mbedtls_x509_crt *cert) {
return !mbedtls_x509_name_cmp(&cert->issuer, &cert->subject);
}

29
net/https/isservercert.c Normal file
View file

@ -0,0 +1,29 @@
/*-*- 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 "net/https/https.h"
#include "third_party/mbedtls/asn1.h"
#include "third_party/mbedtls/oid.h"
bool IsServerCert(const struct Cert *cert, mbedtls_pk_type_t type) {
return cert->cert && cert->key && !cert->cert->ca_istrue &&
mbedtls_pk_get_type(cert->key) == type &&
!mbedtls_x509_crt_check_extended_key_usage(
cert->cert, MBEDTLS_OID_SERVER_AUTH,
MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH));
}

View file

@ -0,0 +1,33 @@
/*-*- 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/log/log.h"
#include "net/https/https.h"
void LogCertificate(const char *msg, mbedtls_x509_crt *cert) {
char *s;
size_t n;
if (LOGGABLE(kLogDebug)) {
if ((s = malloc((n = 15000)))) {
if (mbedtls_x509_crt_info(s, n, " ", cert) > 0) {
DEBUGF("%s\n%s", msg, chomp(s));
}
free(s);
}
}
}

24
net/https/tlsdebug.c Normal file
View file

@ -0,0 +1,24 @@
/*-*- 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/log/log.h"
#include "net/https/https.h"
void TlsDebug(void *c, int v, const char *f, int l, const char *s) {
flogf(v, f, l, 0, "TLS %s", s);
}

28
net/https/tlsdie.c Normal file
View file

@ -0,0 +1,28 @@
/*-*- 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 "net/https/https.h"
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);
}

26
net/https/tlserror.c Normal file
View file

@ -0,0 +1,26 @@
/*-*- 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 "net/https/https.h"
#include "third_party/mbedtls/error.h"
char *TlsError(int r) {
static char b[128];
mbedtls_strerror(r, b, sizeof(b));
return b;
}

View file

@ -22,6 +22,7 @@
#include "libc/log/check.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/stdio.h"
#include "libc/sysv/consts/af.h"
@ -60,18 +61,8 @@ void SetUpOnce(void) {
close(fdin);
}
void Tune(int fd, int a, int b, int x) {
if (!b) return;
setsockopt(fd, a, b, &x, sizeof(x));
}
int Socket(void) {
int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1) {
Tune(fd, IPPROTO_TCP, TCP_CORK, 0);
Tune(fd, IPPROTO_TCP, TCP_NODELAY, 1);
}
return fd;
return GoodSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, false, 0);
}
char *SendHttpRequest(const char *s) {

View file

@ -156,9 +156,10 @@ int getopt(int nargc, char *const nargv[], const char *ostr) {
/* option-argument absent */
getopt_place = kGetoptEmsg;
if (*ostr == ':') return (BADARG);
if (opterr)
if (opterr) {
fprintf(stderr, "%s%s%c\n", program_invocation_name,
": option requires an argument -- ", optopt);
}
return (BADCH);
}
getopt_place = kGetoptEmsg;

View file

@ -1,5 +1,3 @@
#ifndef MBEDTLS_CHECK_H
#define MBEDTLS_CHECK_H
/* clang-format off */
#if defined(TARGET_LIKE_MBED) && \
@ -16,10 +14,6 @@
#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense"
#endif
#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_AESNI_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C)
#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites"
#endif
@ -283,10 +277,6 @@
#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites"
#endif
#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C)
#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites"
#endif
@ -525,11 +515,6 @@
#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously"
#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */
#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \
defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously"
#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */
#if defined(MBEDTLS_SSL_PROTO_SSL3)
#if defined(MBEDTLS_DEPRECATED_REMOVED)
#error "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS"
@ -707,5 +692,3 @@
* #if defined(MBEDTLS_xxx_C) that results in empty translation units.
*/
typedef int mbedtls_iso_c_forbids_empty_translation_units;
#endif /* MBEDTLS_CHECK_H */

View file

@ -109,13 +109,12 @@
#define MBEDTLS_ENTROPY_MAX_SOURCES 4
#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8
#ifndef TINY
/*
* Boosts performance from 230k qps to 330k
* Hardens against against sbox side channels
*/
#define MBEDTLS_AESNI_C
#define MBEDTLS_HAVE_ASM
#ifndef TINY
#define MBEDTLS_HAVE_X86_64
#define MBEDTLS_HAVE_SSE2
#endif
@ -1263,5 +1262,5 @@
#define MBEDTLS_HAVE_UDBL
#include "libc/dce.h"
#include "third_party/mbedtls/check.h"
#include "third_party/mbedtls/check.inc"
#endif /* MBEDTLS_CONFIG_H_ */

View file

@ -22,6 +22,7 @@
#include "third_party/mbedtls/bignum.h"
#include "third_party/mbedtls/bignum_internal.h"
#include "third_party/mbedtls/common.h"
#include "third_party/mbedtls/config.h"
#include "third_party/mbedtls/ctr_drbg.h"
#include "third_party/mbedtls/ecp.h"
#include "third_party/mbedtls/ecp_internal.h"
@ -3656,10 +3657,6 @@ cleanup:
return( ret );
}
#ifndef MBEDTLS_ECP_DP_SECP192R1_ENABLED
#undef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED /* >:\ */
#endif
/**
* \brief The ECP checkup routine.
*

View file

@ -689,7 +689,6 @@ void test_get_sequence_of( const data_t *input, int tag,
mbedtls_test_set_step( step );
TEST_ASSERT( cur != NULL );
TEST_EQUAL( cur->buf.tag, tag );
printf("yo %`'s\n", rest);
n = strtoul( rest, (char **) &rest, 0 );
TEST_EQUAL( n, (size_t)( cur->buf.p - input->x ) );
++rest;

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;
}