Skip to content

Commit 124f269

Browse files
committed
Added SNI with wildcard certs support.
Just applied bumptech#126. Original pull request message: ---- Added a function to do basic wildcard matching when deciding which cert to use under SNI. Also added some comments to the default config clarifying how to list multiple cert files. ----
1 parent 02fdb53 commit 124f269

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

configuration.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -957,8 +957,11 @@ void config_print_default (FILE *fd, stud_config *cfg) {
957957
fprintf(fd, "\n");
958958

959959
fprintf(fd, "# SSL x509 certificate file. REQUIRED.\n");
960-
fprintf(fd, "# List multiple certs to use SNI. Certs are used in the order they\n");
961-
fprintf(fd, "# are listed; the last cert listed will be used if none of the others match\n");
960+
fprintf(fd, "# List multiple certs to use SNI like so:\n");
961+
fprintf(fd, "#pem-file=\"/my/pem/file1.pem\"\n");
962+
fprintf(fd, "#pem-file=\"/my/pem/file2.pem\"\n");
963+
fprintf(fd, "# Certs are used in the order they are listed; \n");
964+
fprintf(fd, "# the last cert listed will be used if none of the others match\n");
962965
fprintf(fd, "#\n");
963966
fprintf(fd, "# type: string\n");
964967
fprintf(fd, FMT_QSTR, CFG_PEM_FILE, "");

stud.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,22 @@ RSA *load_rsa_privatekey(SSL_CTX *ctx, const char *file) {
483483
}
484484

485485
#ifndef OPENSSL_NO_TLSEXT
486+
487+
int is_servername_match(const char *servername, char *certname) {
488+
if (strcasecmp(servername, certname) == 0) {
489+
return 1;
490+
} else {
491+
if (strlen(certname) > 2 && strstr(certname, "*.") == certname) {
492+
char *dot = strstr(servername, ".");
493+
char *after_subdomain = strcasestr(servername, &certname[1]);
494+
if (dot && dot == after_subdomain && strlen(after_subdomain) == strlen(&certname[1])) {
495+
return 1;
496+
}
497+
}
498+
}
499+
return 0;
500+
}
501+
486502
/*
487503
* Switch the context of the current SSL object to the most appropriate one
488504
* based on the SNI header
@@ -499,7 +515,7 @@ int sni_switch_ctx(SSL *ssl, int *al, void *data) {
499515
// For now, just compare servernames as case insensitive strings. Someday,
500516
// it might be nice to Do The Right Thing around star certs.
501517
for (cl = sni_ctxs; cl != NULL; cl = cl->next) {
502-
if (strcasecmp(servername, cl->servername) == 0) {
518+
if (is_servername_match(servername, cl->servername)) {
503519
SSL_set_SSL_CTX(ssl, cl->ctx);
504520
return SSL_TLSEXT_ERR_NOACK;
505521
}
@@ -817,6 +833,13 @@ static void shutdown_proxy(proxystate *ps, SHUTDOWN_REQUESTOR req) {
817833
close(ps->fd_up);
818834
close(ps->fd_down);
819835

836+
// Clear the SSL error queue - it might contain details
837+
// of errors that we haven't consumed for whatever reason.
838+
// If we don't, future calls to SSL_get_error will lead to
839+
// weird/confusing results that can throw off the handling
840+
// of normal conditions like SSL_ERROR_WANT_READ.
841+
ERR_clear_error();
842+
820843
SSL_set_shutdown(ps->ssl, SSL_SENT_SHUTDOWN);
821844
SSL_free(ps->ssl);
822845

@@ -1136,7 +1159,14 @@ static void client_handshake(struct ev_loop *loop, ev_io *w, int revents) {
11361159
shutdown_proxy(ps, SHUTDOWN_SSL);
11371160
}
11381161
else {
1139-
LOG("{%s} Unexpected SSL error (in handshake): %d\n", w->fd == ps->fd_up ? "client" : "backend", err);
1162+
// Try and get more detail on the error from the SSL
1163+
// error queue. ERR_error_string requires a char buffer
1164+
// of 120 bytes.
1165+
unsigned long err_detail = ERR_get_error();
1166+
char err_msg[120];
1167+
ERR_error_string(err_detail, err_msg);
1168+
1169+
LOG("{%s} Unexpected SSL error (in handshake): %d, %s\n", w->fd == ps->fd_up ? "client" : "backend", err, err_msg);
11401170
shutdown_proxy(ps, SHUTDOWN_SSL);
11411171
}
11421172
}

0 commit comments

Comments
 (0)