generate certificate if none provided
This commit is contained in:
parent
60ec412b65
commit
5d0ae92896
2 changed files with 87 additions and 7 deletions
47
gemini/gencert.go
Normal file
47
gemini/gencert.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package gemini
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GenX509KeyPair generates a TLS keypair with one week validity.
|
||||
func GenX509KeyPair(host string) (tls.Certificate, error) {
|
||||
now := time.Now()
|
||||
template := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(now.Unix()),
|
||||
Subject: pkix.Name{
|
||||
CommonName: host,
|
||||
Organization: []string{host},
|
||||
},
|
||||
NotBefore: now,
|
||||
NotAfter: now.AddDate(0, 0, 7),
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment |
|
||||
x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
}
|
||||
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, err
|
||||
}
|
||||
|
||||
cert, err := x509.CreateCertificate(rand.Reader, template, template,
|
||||
priv.Public(), priv)
|
||||
if err != nil {
|
||||
return tls.Certificate{}, err
|
||||
}
|
||||
|
||||
var out tls.Certificate
|
||||
out.Certificate = append(out.Certificate, cert)
|
||||
out.PrivateKey = priv
|
||||
|
||||
return out, nil
|
||||
}
|
47
main.go
47
main.go
|
@ -17,6 +17,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/n0x1m/gmifs/gemini"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -50,26 +52,55 @@ const (
|
|||
DefaultMaxConns = 256
|
||||
DefaultTimeout = 10
|
||||
DefaultRootPath = "/var/www/htdocs/gemini"
|
||||
DefaultCertPath = "cert.pem"
|
||||
DefaultKeyPath = "key.rsa"
|
||||
DefaultCN = ""
|
||||
DefaultCertPath = ""
|
||||
DefaultKeyPath = ""
|
||||
)
|
||||
|
||||
func main() {
|
||||
var address, root, crt, key string
|
||||
var address, root, crt, key, cn string
|
||||
var maxconns, timeout int
|
||||
|
||||
flag.StringVar(&address, "address", DefaultAddress, "address to listen on. E.g. 127.0.0.1:1965")
|
||||
flag.IntVar(&maxconns, "max-conns", DefaultMaxConns, "maximum number of concurrently open connections")
|
||||
flag.IntVar(&timeout, "timeout", DefaultTimeout, "connection timeout in seconds")
|
||||
flag.StringVar(&root, "root", DefaultRootPath, "server root directory to serve from")
|
||||
flag.StringVar(&cn, "cn", DefaultCN, "x509 Common Name when using temporary self-signed certs")
|
||||
flag.StringVar(&crt, "cert", DefaultCertPath, "TLS chain of one or more certificates")
|
||||
flag.StringVar(&key, "key", DefaultKeyPath, "TLS private key")
|
||||
flag.Parse()
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(crt, key)
|
||||
if err != nil {
|
||||
log.Fatalf("server: loadkeys: %s", err)
|
||||
var err error
|
||||
var cert tls.Certificate
|
||||
if crt != "" && key != "" {
|
||||
log.Println("loading certificate from", crt)
|
||||
cert, err = tls.LoadX509KeyPair(crt, key)
|
||||
if err != nil {
|
||||
log.Fatalf("server: loadkeys: %s", err)
|
||||
}
|
||||
} else if cn != "" {
|
||||
log.Println("generating self-signed temporary certificate")
|
||||
cert, err = gemini.GenX509KeyPair(cn)
|
||||
if err != nil {
|
||||
log.Fatalf("server: loadkeys: %s", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "need either a keypair with cert and key or a common name (hostname)\n")
|
||||
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
||||
flag.PrintDefaults()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
/*
|
||||
hup := make(chan os.Signal, 1)
|
||||
signal.Notify(hup, syscall.SIGHUP)
|
||||
go func() {
|
||||
for {
|
||||
<-hup
|
||||
}
|
||||
}()
|
||||
*/
|
||||
|
||||
config := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
Rand: rand.Reader,
|
||||
|
@ -109,7 +140,9 @@ func main() {
|
|||
var gmierr *GmiError
|
||||
if err != nil && errors.As(err, &gmierr) {
|
||||
if gmierr.Code == RedirectPermanent || gmierr.Code == RedirectTemporary {
|
||||
sendError(conn, gmierr.Code, err.Error())
|
||||
// error is relative path if redirect
|
||||
redirect := "gemini://" + cn + err.Error()
|
||||
sendError(conn, gmierr.Code, redirect)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue