summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortjpcc <tjp@ctrl-c.club>2023-10-31 08:16:11 -0600
committertjpcc <tjp@ctrl-c.club>2023-10-31 08:22:51 -0600
commit9d102cb910fe9687b94235da04125329cd787054 (patch)
treedd3bde6932a3b59e529725b5bddf7f795eacfc1b
parent9a20e4b1da629a3ce1fc217304acd1a2a394341a (diff)
use MultiTLS to support separate TLS configs when virtualhosting gemini
fixes #10
-rw-r--r--README.gmi8
-rw-r--r--README.md8
-rw-r--r--gemini.go24
3 files changed, 17 insertions, 23 deletions
diff --git a/README.gmi b/README.gmi
index d4bfc34..2a2de46 100644
--- a/README.gmi
+++ b/README.gmi
@@ -423,7 +423,7 @@ Gopher templates also have three additional functions defined:
## Gemini Templates
-The gemini git router defines these routes:
+The gemini and spartan git routers define these routes:
* / - gemtext listing of the repos in the directory, rendered by repo_root.gmi
* /:repository/ - gemtext overview of the repository, rendered by repo_home.gmi
* /:repository/branches - gemtext list of branches/heads, rendered by branch_list.gmi
@@ -520,13 +520,13 @@ gemini {
# "code.mydomain.com" does the git hosting defined here
host code.mydomain.com
+ servertls key /etc/ssl/code.mydomain.pem cert /etc/ssl/code.mydomain.pem
+
git /var/repos at /
}
```
-Currently a gemini server on a single IP:port can only use a single set of server TLS credentials, so the "servertls" directive is only required on one of the servers and will be used for all of them. That's why the second "gemini" server in the example above has no "servertls" directive. This is the only situation in which servertls is not required in a gemini server (it's already provided in another one with the same IP:port).
-
-=> https://tildegit.org/tjp/sr-71/issues/10 sr-71 issue to use SNI to enable separate TLS certs by domain
+TLS negotiation is done before the request is sent, but sr-71 can use SNI to select the correct certificate to use. So separate gemini servers, even when listening on the same IP and port, can have separate "servertls" directives.
# Extended Gophermap Parsing
diff --git a/README.md b/README.md
index a77fd8f..0c00004 100644
--- a/README.md
+++ b/README.md
@@ -436,7 +436,7 @@ Gopher templates also have three additional functions defined:
## Gemini Templates
-The gemini git router defines these routes:
+The gemini and spartan git routers define these routes:
* / - gemtext listing of the repos in the directory, rendered by repo_root.gmi
* /:repository/ - gemtext overview of the repository, rendered by repo_home.gmi
@@ -536,13 +536,13 @@ gemini {
# "code.mydomain.com" does the git hosting defined here
host code.mydomain.com
+ servertls key /etc/ssl/code.mydomain.pem cert /etc/ssl/code.mydomain.pem
+
git /var/repos at /
}
```
-Currently a gemini server on a single IP:port can only use a single set of server TLS credentials, so the "servertls" directive is only required on one of the servers and will be used for all of them. That's why the second "gemini" server in the example above has no "servertls" directive. This is the only situation in which servertls is not required in a gemini server (it's already provided in another one with the same IP:port).
-
-=> [sr-71 issue to use SNI to enable separate TLS certs by domain](https://tildegit.org/tjp/sr-71/issues/10)
+TLS negotiation is done before the request is sent, but sr-71 can use SNI to select the correct certificate to use. So separate gemini servers, even when listening on the same IP and port, can have separate "servertls" directives.
# Extended Gophermap Parsing
diff --git a/gemini.go b/gemini.go
index e2896dc..cbf3e79 100644
--- a/gemini.go
+++ b/gemini.go
@@ -3,7 +3,6 @@ package main
import (
"context"
"crypto/tls"
- "errors"
"fmt"
"strings"
@@ -58,23 +57,18 @@ func buildGeminiServers(servers []Server, config *Configuration) ([]sr.Server, e
}
}
- var tlsConfig *tls.Config
- var keyfile, certfile string
+ tlsConfigs := map[string]*tls.Config{}
+ var fallback *tls.Config = nil
for _, config := range configs {
- if (keyfile != "" && config.tlsKeyFile == keyfile) || (certfile != "" && config.tlsCertFile == certfile) {
- return nil, errors.New("conflicting 'servertls' directives for gemini server")
- }
-
- if config.TLS != nil {
- tlsConfig = config.TLS
- keyfile = config.tlsKeyFile
- certfile = config.tlsCertFile
- break
+ if len(config.Hostnames) > 0 && config.TLS != nil {
+ for _, hostname := range config.Hostnames {
+ tlsConfigs[hostname] = config.TLS
+ }
+ } else {
+ fallback = config.TLS
}
}
- if tlsConfig == nil {
- return nil, errors.New("gemini server must have a servertls directive")
- }
+ tlsConfig := gemini.MultiTLS(tlsConfigs, fallback)
gemsrv, err := gemini.NewServer(
context.Background(),