Compare commits

...

20 Commits

Author SHA1 Message Date
Omar Polo c9ea70a36f regress: add test_ipv6_server 2024-05-29 09:06:45 +00:00
Omar Polo 7c723cf05f regress: add a knob to disable test_ipv6_addr
at least on the CI is failing with "can't connect to ::1:10965:
Address not available" which suggests IPv6 is broken there.
2024-05-29 09:05:06 +00:00
Omar Polo b5dd7091ad typo 2024-05-29 08:58:12 +00:00
Omar Polo 5b549c2805 regress: rename ipv4 test and add another with ipv6 2024-05-29 08:56:10 +00:00
Omar Polo b00f71ba97 iri: add support for raw IPv6 addresses 2024-05-29 08:52:25 +00:00
Omar Polo 6ff8de1f8a gg: unbreak -n 2024-05-29 08:37:39 +00:00
Omar Polo 9f675805d0 regress: run test_ip_addr with host=127.0.0.1 2024-05-29 08:33:36 +00:00
Omar Polo a91b0892bf explain why we disable runtime tests on macos 2024-05-29 08:12:51 +00:00
Omar Polo 610a4666cd regress: use the new gg -q to reduce the blabbering 2024-05-29 08:09:25 +00:00
Omar Polo 2f4926259f gg: add -q to avoid printing "Server says" 2024-05-29 08:08:36 +00:00
Omar Polo cd12ad1132 pretty-print the socket address at configuration parsing time
saves a getnameinfo(NI_NUMERICHOST) at runtime, even if it's pretty
cheap.
2024-05-29 08:03:59 +00:00
Omar Polo b2782022c9 add regress that hit gmid via a raw IPv4 address 2024-05-29 07:54:03 +00:00
Omar Polo 1ef0cd0cdb relax the SNI requirement
There are legitimate cases where SNI can't be used, for example
when connecting via an IPv6 address, so don't rejects those requests.
Instead, fill the requested domain with the address (literal) of
the socket they're connected to and attempt to match on it.

This possibly still incur in a "won't proxy" error if the client
then requests a different hostname.

See the github issue https://github.com/omar-polo/gmid/issues/25
2024-05-29 07:52:13 +00:00
Omar Polo 42e2af25ae github: add workflow to build images for ghcr.io 2024-05-27 15:16:38 +00:00
Omar Polo 89dca7ab54 s/MIN/MINIMUM/g 2024-05-25 17:44:35 +00:00
Omar Polo 359c56ce35 contrib/gmid.service: remove User and Group
May cause weird errors (status=216/GROUP) on some distros, and
running as root is already the default, so remove the two lines.
Reported by and debugged together with leandro del Flug, thanks!
2024-04-27 17:12:09 +00:00
Omar Polo c2dcb5fa6e contrib/gmid.service: start as root by default
Various techniques used by gmid are effective only when the daemon
is started as root.  Strongly suggest to do so by switching the
sample configuration.  This way, provided that a local user is
created as well, the chroot configuration will work out-of-the-box
and the TLS certificates can be readable only by root.
2024-04-27 16:17:37 +00:00
Omar Polo 5d12e6a104 improve the description for -f 2024-04-27 16:10:46 +00:00
Omar Polo 0d8eb9b60c typo: semicolors -> semicolons 2024-04-11 09:42:15 +00:00
Omar Polo 5864f3ce3c set next version 2024-04-04 19:28:14 +00:00
18 changed files with 193 additions and 50 deletions

View File

@ -1,6 +1,9 @@
# gcc' -Werror=use-after-free gets tripped by vis.c: it sees a use # gcc' -Werror=use-after-free gets tripped by vis.c: it sees a use
# after free where it's not possible and breaks the CI. # after free where it's not possible and breaks the CI.
# seems that inside the CI it's not currently possible to bind to ::1
# so set HAVE_IPV6=no.
linux_amd64_task: linux_amd64_task:
container: container:
image: alpine:latest image: alpine:latest
@ -8,7 +11,7 @@ linux_amd64_task:
- apk add alpine-sdk linux-headers bison libretls-dev libevent-dev - apk add alpine-sdk linux-headers bison libretls-dev libevent-dev
- ./configure CFLAGS='-O2 -pipe -Wno-deprecated-declarations -Wno-use-after-free' -Werror - ./configure CFLAGS='-O2 -pipe -Wno-deprecated-declarations -Wno-use-after-free' -Werror
- make - make
- make regress REGRESS_HOST="*" - make regress REGRESS_HOST="*" HAVE_IPV6=no
linux_arm_task: linux_arm_task:
arm_container: arm_container:
@ -17,7 +20,7 @@ linux_arm_task:
- apk add alpine-sdk linux-headers bison libretls-dev libevent-dev - apk add alpine-sdk linux-headers bison libretls-dev libevent-dev
- ./configure CFLAGS='-O2 -pipe -Wno-deprecated-declarations -Wno-use-after-free' -Werror - ./configure CFLAGS='-O2 -pipe -Wno-deprecated-declarations -Wno-use-after-free' -Werror
- make - make
- make regress REGRESS_HOST="*" - make regress REGRESS_HOST="*" HAVE_IPV6=no
freebsd_14_task: freebsd_14_task:
freebsd_instance: freebsd_instance:
@ -26,8 +29,13 @@ freebsd_14_task:
script: script:
- ./configure CFLAGS='-O2 -pipe -Wno-deprecated-declarations' -Werror - ./configure CFLAGS='-O2 -pipe -Wno-deprecated-declarations' -Werror
- make - make
- make regress - make regress HAVE_IPV6=no
#
# There are some issues with imsg fd passing on macos at the moment that
# seem to be triggered only in applications that do a heavy use of them,
# like gmid or opensmtpd. Still, keep macos to ensure gmid builds here.
#
mac_task: mac_task:
macos_instance: macos_instance:
image: ghcr.io/cirruslabs/macos-sonoma-xcode:latest image: ghcr.io/cirruslabs/macos-sonoma-xcode:latest

33
.github/workflows/alpine-release.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: release docker image
on:
push:
tags:
env:
IMAGE_NAME: "gmid"
jobs:
build:
permissions: write-all
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: build the image
run: docker build -f contrib/Dockerfile -t gmid:alpine .
- name: login to ghcr.io
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: push the image
run: |
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
IMAGE_ID=$(echo $IMAGE_ID | tr A-Z a-z)
# strip git ref prefix from version
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
echo IMAGE_ID=$IMAGE_ID
echo VERSION=$VERSION
docker tag gmid:alpine $IMAGE_ID:$VERSION
docker push $IMAGE_ID:$VERSION

2
configure vendored
View File

@ -19,7 +19,7 @@
set -e set -e
RELEASE=no RELEASE=no
VERSION=2.0.2 VERSION=2.0.2-current
usage() usage()
{ {

View File

@ -6,8 +6,6 @@ Wants=network-online.target
[Service] [Service]
Type=simple Type=simple
User=gmid
Group=nobody
ExecStart=/usr/local/bin/gmid -f -c /etc/gmid.conf ExecStart=/usr/local/bin/gmid -f -c /etc/gmid.conf
ExecStop=/bin/kill -TERM $MAINPID ExecStop=/bin/kill -TERM $MAINPID
ExecReload=/bin/kill -HUP $MAINPID ExecReload=/bin/kill -HUP $MAINPID

4
gg.1
View File

@ -20,7 +20,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Bk -words .Bk -words
.Op Fl 23Nn .Op Fl 23Nnq
.Op Fl C Ar cert .Op Fl C Ar cert
.Op Fl d Ar mode .Op Fl d Ar mode
.Op Fl H Ar sni .Op Fl H Ar sni
@ -82,6 +82,8 @@ and
to do the request instead of the ones extracted by the IRI. to do the request instead of the ones extracted by the IRI.
.Ar port .Ar port
is by default 1965. is by default 1965.
.It Fl q
Don't print server error messages to standard error.
.It Fl T Ar seconds .It Fl T Ar seconds
Kill Kill
.Nm .Nm

15
gg.c
View File

@ -41,6 +41,7 @@ int flag3;
int nop; int nop;
int redirects = 5; int redirects = 5;
int timer; int timer;
int quiet;
const char *cert; const char *cert;
const char *key; const char *key;
const char *proxy_host; const char *proxy_host;
@ -308,8 +309,11 @@ get(const char *r)
assert(t != NULL); assert(t != NULL);
if (code < 20 || code >= 30) { if (code < 20 || code >= 30) {
*t = '\0'; *t = '\0';
fprintf(stderr, "Server says: "); if (!quiet) {
safeprint(stderr, buf + 3); /* skip return code */ fprintf(stderr, "Server says: ");
/* skip return code */
safeprint(stderr, buf + 3);
}
} }
t += 2; /* skip \r\n */ t += 2; /* skip \r\n */
len -= t - buf; len -= t - buf;
@ -335,7 +339,7 @@ static void __attribute__((noreturn))
usage(void) usage(void)
{ {
fprintf(stderr, "version: " GG_STRING "\n"); fprintf(stderr, "version: " GG_STRING "\n");
fprintf(stderr, "usage: %s [-23Nn] [-C cert] [-d mode] [-H sni] " fprintf(stderr, "usage: %s [-23Nnq] [-C cert] [-d mode] [-H sni] "
"[-K key] [-P host[:port]]\n", "[-K key] [-P host[:port]]\n",
getprogname()); getprogname());
fprintf(stderr, " [-T seconds] gemini://...\n"); fprintf(stderr, " [-T seconds] gemini://...\n");
@ -385,7 +389,7 @@ main(int argc, char **argv)
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
while ((ch = getopt(argc, argv, "23C:d:H:K:NP:T:")) != -1) { while ((ch = getopt(argc, argv, "23C:d:H:K:nNP:qT:")) != -1) {
switch (ch) { switch (ch) {
case '2': case '2':
flag2 = 1; flag2 = 1;
@ -415,6 +419,9 @@ main(int argc, char **argv)
parse_proxy(optarg); parse_proxy(optarg);
dont_verify_name = 1; dont_verify_name = 1;
break; break;
case 'q':
quiet = 1;
break;
case 'T': case 'T':
timer = strtonum(optarg, 1, 1000, &errstr); timer = strtonum(optarg, 1, 1000, &errstr);
if (errstr != NULL) if (errstr != NULL)

7
gmid.8
View File

@ -1,4 +1,4 @@
.\" Copyright (c) 2021, 2022, 2023 Omar Polo <op@omarpolo.com> .\" Copyright (c) 2021, 2022, 2023, 2024 Omar Polo <op@omarpolo.com>
.\" .\"
.\" Permission to use, copy, modify, and distribute this software for any .\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above .\" purpose with or without fee is hereby granted, provided that the above
@ -11,7 +11,7 @@
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.Dd October 20, 2023 .Dd April 27, 2024
.Dt GMID 8 .Dt GMID 8
.Os .Os
.Sh NAME .Sh NAME
@ -52,7 +52,8 @@ Overrides the definition of
.Ar macro .Ar macro
in the config file if present. in the config file if present.
.It Fl f .It Fl f
Stays and logs on the foreground. Do not daemonize.
Stay and log in the foreground.
.It Fl h , Fl -help .It Fl h , Fl -help
Print the usage and exit. Print the usage and exit.
.It Fl n .It Fl n

3
gmid.h
View File

@ -114,6 +114,9 @@ struct address {
socklen_t slen; socklen_t slen;
int16_t port; int16_t port;
/* pretty-printed version of `ss' */
char pp[NI_MAXHOST];
/* used in the server */ /* used in the server */
struct conf *conf; struct conf *conf;
int sock; int sock;

48
iri.c
View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, 2022 Omar Polo <op@omarpolo.com> * Copyright (c) 2020, 2022, 2024 Omar Polo <op@omarpolo.com>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -177,25 +177,47 @@ parse_port(struct parser *p)
return 1; return 1;
} }
/* TODO: add support for ip-literal and ipv4addr ? */
/* *( unreserved / sub-delims / pct-encoded ) */ /* *( unreserved / sub-delims / pct-encoded ) */
static int static int
parse_authority(struct parser *p) parse_authority(struct parser *p)
{ {
p->parsed->host = p->iri; struct addrinfo hints, *ai;
char *end;
int err;
while (unreserved(*p->iri) if (*p->iri == '[') {
|| sub_delimiters(*p->iri)
|| parse_pct_encoded(p)
|| valid_multibyte_utf8(p)) {
/* normalize the host name. */
if (*p->iri < 0x7F)
*p->iri = tolower(*p->iri);
p->iri++; p->iri++;
} p->parsed->host = p->iri;
if ((end = strchr(p->iri, ']')) == NULL) {
p->err = "invalid IPv6 address";
return 0;
}
*end++ = '\0';
p->iri = end;
if (p->err != NULL) memset(&hints, 0, sizeof(hints));
return 0; hints.ai_flags = AI_NUMERICHOST;
err = getaddrinfo(p->parsed->host, NULL, &hints, &ai);
if (err != 0) {
p->err = "invalid IPv6 address";
return 0;
}
freeaddrinfo(ai);
} else {
p->parsed->host = p->iri;
while (unreserved(*p->iri)
|| sub_delimiters(*p->iri)
|| parse_pct_encoded(p)
|| valid_multibyte_utf8(p)) {
/* normalize the host name. */
if (*p->iri < 0x7F)
*p->iri = tolower(*p->iri);
p->iri++;
}
if (p->err != NULL)
return 0;
}
if (*p->iri == ':') { if (*p->iri == ':') {
*p->iri = '\0'; *p->iri = '\0';

14
parse.y
View File

@ -1280,7 +1280,7 @@ getservice(const char *n)
} }
static void static void
add_to_addr_queue(struct addrhead *a, struct addrinfo *ai) add_to_addr_queue(struct addrhead *a, struct addrinfo *ai, const char *pp)
{ {
struct address *addr; struct address *addr;
struct sockaddr_in *sin; struct sockaddr_in *sin;
@ -1306,6 +1306,7 @@ add_to_addr_queue(struct addrhead *a, struct addrinfo *ai)
addr->ai_protocol = ai->ai_protocol; addr->ai_protocol = ai->ai_protocol;
addr->slen = ai->ai_addrlen; addr->slen = ai->ai_addrlen;
memcpy(&addr->ss, ai->ai_addr, ai->ai_addrlen); memcpy(&addr->ss, ai->ai_addr, ai->ai_addrlen);
strlcpy(addr->pp, pp, sizeof(addr->pp));
/* for commodity */ /* for commodity */
switch (addr->ai_family) { switch (addr->ai_family) {
@ -1330,6 +1331,7 @@ void
listen_on(const char *hostname, const char *servname) listen_on(const char *hostname, const char *servname)
{ {
struct addrinfo hints, *res, *res0; struct addrinfo hints, *res, *res0;
char pp[NI_MAXHOST];
int error; int error;
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
@ -1344,8 +1346,14 @@ listen_on(const char *hostname, const char *servname)
} }
for (res = res0; res; res = res->ai_next) { for (res = res0; res; res = res->ai_next) {
add_to_addr_queue(&host->addrs, res); if (getnameinfo(res->ai_addr, res->ai_addrlen, pp, sizeof(pp),
add_to_addr_queue(&conf->addrs, res); NULL, 0, NI_NUMERICHOST) == -1) {
yyerror("getnameinfo failed: %s", strerror(errno));
break;
}
add_to_addr_queue(&host->addrs, res, pp);
add_to_addr_queue(&conf->addrs, res, pp);
} }
freeaddrinfo(res0); freeaddrinfo(res0);

View File

@ -22,7 +22,7 @@
#include "log.h" #include "log.h"
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MINIMUM(a, b) ((a) < (b) ? (a) : (b))
static const struct timeval handshake_timeout = { 5, 0 }; static const struct timeval handshake_timeout = { 5, 0 };
@ -50,7 +50,7 @@ proxy_tls_readcb(int fd, short event, void *d)
} }
if (bufev->wm_read.high != 0) if (bufev->wm_read.high != 0)
howmuch = MIN(sizeof(buf), bufev->wm_read.high); howmuch = MINIMUM(sizeof(buf), bufev->wm_read.high);
switch (ret = tls_read(c->proxyctx, buf, howmuch)) { switch (ret = tls_read(c->proxyctx, buf, howmuch)) {
case TLS_WANT_POLLIN: case TLS_WANT_POLLIN:

View File

@ -7,6 +7,9 @@ GENCERT_FLAGS=
# host to bind to during regress # host to bind to during regress
REGRESS_HOST = localhost REGRESS_HOST = localhost
# set to no if don't have IPv6 working (need to listen on ::1)
HAVE_IPV6 = yes
DISTFILES = Makefile \ DISTFILES = Makefile \
env \ env \
err \ err \
@ -39,7 +42,7 @@ IRI_OBJS = ${IRI_SRCS:.c=.o} ${REG_COMPATS}
.PHONY: all data clean dist .PHONY: all data clean dist
all: data puny-test iri_test fcgi-test all: data puny-test iri_test fcgi-test
env REGRESS_HOST="${REGRESS_HOST}" ./regress ${TESTS} env HAVE_IPV6="${HAVE_IPV6}" REGRESS_HOST="${REGRESS_HOST}" ./regress ${TESTS}
data: testdata localhost.pem testca.pem valid.crt invalid.pem data: testdata localhost.pem testca.pem valid.crt invalid.pem

View File

@ -162,6 +162,14 @@ main(void)
PASS, PASS,
IRI("gemini", "naïve.omarpolo.com", "", "", "", ""), IRI("gemini", "naïve.omarpolo.com", "", "", "", ""),
"Can percent decode hostnames"); "Can percent decode hostnames");
TEST("gemini://100.64.3.27/",
PASS,
IRI("gemini", "100.64.3.27", "", "", "", ""),
"Accepts IPv4 addresses");
TEST("gemini://[::1]/",
PASS,
IRI("gemini", "::1", "", "", "", ""),
"Accepts IPv6 addresses");
/* path */ /* path */
TEST("gemini://omarpolo.com/foo/bar/baz", TEST("gemini://omarpolo.com/foo/bar/baz",

View File

@ -6,9 +6,12 @@ gemexp="./../gemexp"
gg="./../gg" gg="./../gg"
gmid="./../gmid" gmid="./../gmid"
current_test= current_test=
server_name=
gghost=
run_test() { run_test() {
ggflags= ggflags=
host="$REGRESS_HOST"
port=10965 port=10965
config_common="log syslog off" config_common="log syslog off"
hdr= hdr=
@ -18,9 +21,15 @@ run_test() {
ran_no=$((ran_no + 1)) ran_no=$((ran_no + 1))
current_test=$1 current_test=$1
server_name=localhost
gghost=localhost
rm -f reg.conf rm -f reg.conf
if ! $1; then if [ "$2" = "need_ipv6" -a "$HAVE_IPV6" != "yes" ]; then
echo "$1 skipped (needs HAVE_IPV6='yes')"
return
elif ! $1; then
echo "$1 failed" echo "$1 failed"
failed="$failed $1" failed="$failed $1"
failed_no=$((failed_no + 1)) failed_no=$((failed_no + 1))
@ -58,11 +67,11 @@ gen_config() {
cat <<EOF > reg.conf cat <<EOF > reg.conf
$config_common $config_common
$1 $1
server "localhost" { server "$server_name" {
cert "$PWD/localhost.pem" cert "$PWD/localhost.pem"
key "$PWD/localhost.key" key "$PWD/localhost.key"
root "$PWD/testdata" root "$PWD/testdata"
listen on $REGRESS_HOST port $port listen on $host port $port
$2 $2
} }
EOF EOF
@ -77,7 +86,7 @@ set_proxy() {
server "localhost.local" { server "localhost.local" {
cert "$PWD/localhost.pem" cert "$PWD/localhost.pem"
key "$PWD/localhost.key" key "$PWD/localhost.key"
listen on $REGRESS_HOST port $port listen on $host port $port
proxy { proxy {
relay-to localhost port $port relay-to localhost port $port
$1 $1
@ -108,13 +117,13 @@ setup_simple_test() {
# usage: get <path> # usage: get <path>
# return the body of the request on stdout # return the body of the request on stdout
get() { get() {
$gg -T10 $ggflags "gemini://localhost:10965/$1" || true $gg -q -T10 $ggflags "gemini://$gghost:10965/$1" || true
} }
# usage: head <path> # usage: head <path>
# return the meta response line on stdout # return the meta response line on stdout
head() { head() {
$gg -T10 -d header $ggflags "gemini://localhost:10965/$1" || true $gg -q -T10 -d header $ggflags "gemini://$gghost:10965/$1" || true
} }
# usage: fetch <path> # usage: fetch <path>

View File

@ -62,6 +62,9 @@ run_test test_proxy_with_certs
# run_test test_unknown_host # XXX: breaks on some distro # run_test test_unknown_host # XXX: breaks on some distro
run_test test_include_mime run_test test_include_mime
run_test test_log_file run_test test_log_file
run_test test_ipv4_addr
run_test test_ipv6_addr need_ipv6
run_test test_ipv6_server need_ipv6
# TODO: add test that uses only a TLSv1.2 or TLSv1.3 # TODO: add test that uses only a TLSv1.2 or TLSv1.3
# TODO: add a test that attempt to serve a non-regular file # TODO: add a test that attempt to serve a non-regular file

View File

@ -322,7 +322,7 @@ server "localhost" {
cert \$pwd "/localhost.pem" cert \$pwd "/localhost.pem"
key \$pwd "/localhost.key" key \$pwd "/localhost.key"
root \$pwd "/testdata" root \$pwd "/testdata"
listen on $REGRESS_HOST port $port listen on $host port $port
@common @common
} }
EOF EOF
@ -430,3 +430,36 @@ log style legacy'
rm -f log log.edited rm -f log log.edited
return 0 return 0
} }
test_ipv4_addr() {
server_name="*"
host="127.0.0.1"
gghost=127.0.0.1
ggflags=-N
setup_simple_test
fetch /
check_reply "20 text/gemini" "# hello world" || return 1
}
test_ipv6_addr() {
server_name="*"
host="::1"
gghost="[::1]"
ggflags=-N
setup_simple_test
fetch /
check_reply "20 text/gemini" "# hello world" || return 1
}
test_ipv6_server() {
server_name="::1"
host="::1"
gghost="[::1]"
ggflags=-N
setup_simple_test
fetch /
check_reply "20 text/gemini" "# hello world" || return 1
}

View File

@ -31,7 +31,7 @@
#include "log.h" #include "log.h"
#include "proc.h" #include "proc.h"
#define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MINIMUM(a, b) ((a) < (b) ? (a) : (b))
#ifndef nitems #ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
@ -119,6 +119,9 @@ match_host(struct vhost *v, struct client *c)
if (addr == NULL) if (addr == NULL)
return 0; return 0;
if (*c->domain == '\0')
strlcpy(c->domain, addr->pp, sizeof(c->domain));
if (matches(v->domain, c->domain)) if (matches(v->domain, c->domain))
return 1; return 1;
@ -403,16 +406,19 @@ handle_handshake(int fd, short ev, void *d)
evbuffer_unfreeze(c->bev->output, 1); evbuffer_unfreeze(c->bev->output, 1);
#endif #endif
if ((servname = tls_conn_servername(c->ctx)) == NULL) { if ((servname = tls_conn_servername(c->ctx)) == NULL)
log_debug("handshake: missing SNI"); log_debug("handshake: missing SNI");
goto err;
}
if (!puny_decode(servname, c->domain, sizeof(c->domain), &parse_err)) { if (!puny_decode(servname, c->domain, sizeof(c->domain), &parse_err)) {
log_info("puny_decode: %s", parse_err); log_info("puny_decode: %s", parse_err);
goto err; start_reply(c, BAD_REQUEST, "Wrong/malformed host");
return;
} }
/*
* match_addr will serialize the (matching) address if c->domain
* is empty, so that we can support requests for raw IPv6 address
* that can't have a SNI.
*/
TAILQ_FOREACH(h, &conf->hosts, vhosts) TAILQ_FOREACH(h, &conf->hosts, vhosts)
if (match_host(h, c)) if (match_host(h, c))
break; break;
@ -428,8 +434,7 @@ handle_handshake(int fd, short ev, void *d)
return; return;
} }
err: start_reply(c, BAD_REQUEST, "Wrong/malformed host");
start_reply(c, BAD_REQUEST, "Wrong/malformed host or missing SNI");
} }
static void static void
@ -853,7 +858,7 @@ client_tls_readcb(int fd, short event, void *d)
} }
if (bufev->wm_read.high != 0) if (bufev->wm_read.high != 0)
howmuch = MIN(sizeof(buf), bufev->wm_read.high); howmuch = MINIMUM(sizeof(buf), bufev->wm_read.high);
switch (ret = tls_read(client->ctx, buf, howmuch)) { switch (ret = tls_read(client->ctx, buf, howmuch)) {
case TLS_WANT_POLLIN: case TLS_WANT_POLLIN:

View File

@ -4,7 +4,7 @@
- fix `log access path' with `chroot' enabled. - fix `log access path' with `chroot' enabled.
- fix config dumping (-nn). - fix config dumping (-nn).
- rework grammar to allow semicolors after top-level statements. - rework grammar to allow semicolons after top-level statements.
- don't make the log styles reserved keywords. - don't make the log styles reserved keywords.
- contrib/vim: fixed indent, from Anna “CyberTailor”, thanks! - contrib/vim: fixed indent, from Anna “CyberTailor”, thanks!