1
0
Fork 0
mirror of https://git.sr.ht/~adnano/go-gemini synced 2024-06-01 13:46:07 +02:00

server: Populate (*Request).Certificate field

This commit is contained in:
Adnan Maolood 2020-11-01 16:25:59 -05:00
parent cc372e8768
commit b6475aa7d9
3 changed files with 38 additions and 39 deletions

View File

@ -3,9 +3,11 @@
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"log"
"time"
"git.sr.ht/~adnano/go-gemini"
)
@ -44,6 +46,12 @@ func main() {
if err := server.Certificates.Load("/var/lib/gemini/certs"); err != nil {
log.Fatal(err)
}
server.CreateCertificate = func(hostname string) (tls.Certificate, error) {
return gemini.CreateCertificate(gemini.CertificateOptions{
DNSNames: []string{hostname},
Duration: time.Hour,
})
}
server.Register("localhost", &mux)
if err := server.ListenAndServe(); err != nil {
@ -58,8 +66,7 @@ func getSession(cert *x509.Certificate) (*session, bool) {
}
func login(w *gemini.ResponseWriter, r *gemini.Request) {
cert := gemini.Certificate(r)
if cert == nil {
if r.Certificate == nil {
w.WriteStatus(gemini.StatusCertificateRequired)
return
}
@ -68,7 +75,7 @@ func login(w *gemini.ResponseWriter, r *gemini.Request) {
w.WriteHeader(gemini.StatusInput, "Username")
return
}
fingerprint := gemini.Fingerprint(cert)
fingerprint := gemini.Fingerprint(r.Certificate.Leaf)
sessions[fingerprint] = &session{
username: username,
}
@ -76,12 +83,11 @@ func login(w *gemini.ResponseWriter, r *gemini.Request) {
}
func loginPassword(w *gemini.ResponseWriter, r *gemini.Request) {
cert := gemini.Certificate(r)
if cert == nil {
if r.Certificate == nil {
w.WriteStatus(gemini.StatusCertificateRequired)
return
}
session, ok := getSession(cert)
session, ok := getSession(r.Certificate.Leaf)
if !ok {
w.WriteStatus(gemini.StatusCertificateNotAuthorized)
return
@ -102,23 +108,21 @@ func loginPassword(w *gemini.ResponseWriter, r *gemini.Request) {
}
func logout(w *gemini.ResponseWriter, r *gemini.Request) {
cert := gemini.Certificate(r)
if cert == nil {
if r.Certificate == nil {
w.WriteStatus(gemini.StatusCertificateRequired)
return
}
fingerprint := gemini.Fingerprint(cert)
fingerprint := gemini.Fingerprint(r.Certificate.Leaf)
delete(sessions, fingerprint)
fmt.Fprintln(w, "Successfully logged out.")
}
func profile(w *gemini.ResponseWriter, r *gemini.Request) {
cert := gemini.Certificate(r)
if cert == nil {
if r.Certificate == nil {
w.WriteStatus(gemini.StatusCertificateRequired)
return
}
session, ok := getSession(cert)
session, ok := getSession(r.Certificate.Leaf)
if !ok {
w.WriteStatus(gemini.StatusCertificateNotAuthorized)
return
@ -130,12 +134,11 @@ func profile(w *gemini.ResponseWriter, r *gemini.Request) {
}
func admin(w *gemini.ResponseWriter, r *gemini.Request) {
cert := gemini.Certificate(r)
if cert == nil {
if r.Certificate == nil {
w.WriteStatus(gemini.StatusCertificateRequired)
return
}
session, ok := getSession(cert)
session, ok := getSession(r.Certificate.Leaf)
if !ok {
w.WriteStatus(gemini.StatusCertificateNotAuthorized)
return

View File

@ -19,7 +19,9 @@ type Request struct {
// Certificate specifies the TLS certificate to use for the request.
// Request certificates take precedence over client certificates.
// This field is ignored by the server.
//
// On the server side, if the client provided a certificate then
// Certificate.Leaf is guaranteed to be non-nil.
Certificate *tls.Certificate
// RemoteAddr allows servers and other software to record the network

View File

@ -3,7 +3,6 @@ package gemini
import (
"bufio"
"crypto/tls"
"crypto/x509"
"log"
"net"
"net/url"
@ -199,10 +198,24 @@ func (s *Server) respond(conn net.Conn) {
if url.Scheme == "" {
url.Scheme = "gemini"
}
// Store information about the TLS connection
connState := conn.(*tls.Conn).ConnectionState()
var cert *tls.Certificate
if len(connState.PeerCertificates) > 0 {
peerCert := connState.PeerCertificates[0]
// Store the TLS certificate
cert = &tls.Certificate{
Certificate: [][]byte{peerCert.Raw},
Leaf: peerCert,
}
}
req := &Request{
URL: url,
RemoteAddr: conn.RemoteAddr(),
TLS: conn.(*tls.Conn).ConnectionState(),
URL: url,
RemoteAddr: conn.RemoteAddr(),
TLS: connState,
Certificate: cert,
}
resp := s.responder(req)
if resp != nil {
@ -330,22 +343,3 @@ func Input(r *Request) (query string, ok bool) {
}
return "", false
}
// Certificate returns the request certificate.
// It returns nil if no certificate was provided.
//
// Example:
//
// cert := gemini.Certificate(req)
// if cert == nil {
// w.WriteStatus(gemini.StatusCertificateRequired)
// return
// }
// // ...
//
func Certificate(r *Request) *x509.Certificate {
if len(r.TLS.PeerCertificates) == 0 {
return nil
}
return r.TLS.PeerCertificates[0]
}