Add more helper functions

This commit is contained in:
adnano 2020-09-27 21:13:42 -04:00
parent fdf6bbc62f
commit 3c9821d812
4 changed files with 72 additions and 34 deletions

View File

@ -85,7 +85,7 @@ func login(rw *gmi.ResponseWriter, req *gmi.Request) {
rw.WriteHeader(gmi.StatusRedirect, "/login/password") rw.WriteHeader(gmi.StatusRedirect, "/login/password")
} }
} else { } else {
rw.WriteHeader(gmi.StatusClientCertificateRequired, "Certificate required") rw.WriteHeader(gmi.StatusCertificateRequired, "Certificate required")
} }
} }
@ -93,7 +93,7 @@ func loginPassword(rw *gmi.ResponseWriter, req *gmi.Request) {
if len(req.TLS.PeerCertificates) > 0 { if len(req.TLS.PeerCertificates) > 0 {
session, ok := getSession(req.TLS.PeerCertificates[0]) session, ok := getSession(req.TLS.PeerCertificates[0])
if !ok { if !ok {
rw.WriteHeader(gmi.StatusCertificateNotAuthorised, "Not authorized") rw.WriteHeader(gmi.StatusCertificateNotAuthorized, "Not authorized")
return return
} }
@ -109,7 +109,7 @@ func loginPassword(rw *gmi.ResponseWriter, req *gmi.Request) {
} }
} }
} else { } else {
rw.WriteHeader(gmi.StatusClientCertificateRequired, "Certificate required") rw.WriteHeader(gmi.StatusCertificateRequired, "Certificate required")
} }
} }
@ -126,7 +126,7 @@ func profile(rw *gmi.ResponseWriter, req *gmi.Request) {
if len(req.TLS.PeerCertificates) > 0 { if len(req.TLS.PeerCertificates) > 0 {
session, ok := getSession(req.TLS.PeerCertificates[0]) session, ok := getSession(req.TLS.PeerCertificates[0])
if !ok { if !ok {
rw.WriteHeader(gmi.StatusCertificateNotAuthorised, "Certificate not authorized") rw.WriteHeader(gmi.StatusCertificateNotAuthorized, "Certificate not authorized")
return return
} }
user := logins[session.username] user := logins[session.username]
@ -134,7 +134,7 @@ func profile(rw *gmi.ResponseWriter, req *gmi.Request) {
rw.WriteHeader(gmi.StatusSuccess, "text/gemini") rw.WriteHeader(gmi.StatusSuccess, "text/gemini")
rw.Write([]byte(profile)) rw.Write([]byte(profile))
} else { } else {
rw.WriteHeader(gmi.StatusClientCertificateRequired, "Certificate required") rw.WriteHeader(gmi.StatusCertificateRequired, "Certificate required")
} }
} }
@ -142,17 +142,17 @@ func admin(rw *gmi.ResponseWriter, req *gmi.Request) {
if len(req.TLS.PeerCertificates) > 0 { if len(req.TLS.PeerCertificates) > 0 {
session, ok := getSession(req.TLS.PeerCertificates[0]) session, ok := getSession(req.TLS.PeerCertificates[0])
if !ok { if !ok {
rw.WriteHeader(gmi.StatusCertificateNotAuthorised, "Certificate not authorized") rw.WriteHeader(gmi.StatusCertificateNotAuthorized, "Certificate not authorized")
return return
} }
user := logins[session.username] user := logins[session.username]
if !user.admin { if !user.admin {
rw.WriteHeader(gmi.StatusCertificateNotAuthorised, "Admins only!") rw.WriteHeader(gmi.StatusCertificateNotAuthorized, "Admins only!")
return return
} }
rw.WriteHeader(gmi.StatusSuccess, "text/gemini") rw.WriteHeader(gmi.StatusSuccess, "text/gemini")
rw.Write([]byte("Welcome to the admin portal.\n")) rw.Write([]byte("Welcome to the admin portal.\n"))
} else { } else {
rw.WriteHeader(gmi.StatusClientCertificateRequired, "Certificate required") rw.WriteHeader(gmi.StatusCertificateRequired, "Certificate required")
} }
} }

View File

@ -54,6 +54,7 @@ func sendRequest(req *gmi.Request) error {
return err return err
} }
// TODO: More fine-grained analysis of the status code.
switch resp.Status / 10 { switch resp.Status / 10 {
case gmi.StatusClassInput: case gmi.StatusClassInput:
fmt.Printf("%s: ", resp.Meta) fmt.Printf("%s: ", resp.Meta)
@ -78,7 +79,7 @@ func sendRequest(req *gmi.Request) error {
return fmt.Errorf("Temporary failure: %s", resp.Meta) return fmt.Errorf("Temporary failure: %s", resp.Meta)
case gmi.StatusClassPermanentFailure: case gmi.StatusClassPermanentFailure:
return fmt.Errorf("Permanent failure: %s", resp.Meta) return fmt.Errorf("Permanent failure: %s", resp.Meta)
case gmi.StatusClassClientCertificateRequired: case gmi.StatusClassCertificateRequired:
fmt.Println("Generating client certificate for", req.Hostname()) fmt.Println("Generating client certificate for", req.Hostname())
return nil // TODO: Generate and store client certificate return nil // TODO: Generate and store client certificate
} }

View File

@ -7,34 +7,34 @@ import (
// Status codes. // Status codes.
const ( const (
StatusInput = 10 StatusInput = 10
StatusSensitiveInput = 11 StatusSensitiveInput = 11
StatusSuccess = 20 StatusSuccess = 20
StatusRedirect = 30 StatusRedirect = 30
StatusRedirectPermanent = 31 StatusRedirectPermanent = 31
StatusTemporaryFailure = 40 StatusTemporaryFailure = 40
StatusServerUnavailable = 41 StatusServerUnavailable = 41
StatusCGIError = 42 StatusCGIError = 42
StatusProxyError = 43 StatusProxyError = 43
StatusSlowDown = 44 StatusSlowDown = 44
StatusPermanentFailure = 50 StatusPermanentFailure = 50
StatusNotFound = 51 StatusNotFound = 51
StatusGone = 52 StatusGone = 52
StatusProxyRequestRefused = 53 StatusProxyRequestRefused = 53
StatusBadRequest = 59 StatusBadRequest = 59
StatusClientCertificateRequired = 60 StatusCertificateRequired = 60
StatusCertificateNotAuthorised = 61 StatusCertificateNotAuthorized = 61
StatusCertificateNotValid = 62 StatusCertificateNotValid = 62
) )
// Status code categories. // Status code categories.
const ( const (
StatusClassInput = 1 StatusClassInput = 1
StatusClassSuccess = 2 StatusClassSuccess = 2
StatusClassRedirect = 3 StatusClassRedirect = 3
StatusClassTemporaryFailure = 4 StatusClassTemporaryFailure = 4
StatusClassPermanentFailure = 5 StatusClassPermanentFailure = 5
StatusClassClientCertificateRequired = 6 StatusClassCertificateRequired = 6
) )
var ( var (

View File

@ -174,7 +174,7 @@ type Handler interface {
Serve(*ResponseWriter, *Request) Serve(*ResponseWriter, *Request)
} }
// NotFound replies to the request with a NotFound status code. // NotFound replies to the request with the NotFound status code.
func NotFound(rw *ResponseWriter, req *Request) { func NotFound(rw *ResponseWriter, req *Request) {
rw.WriteHeader(StatusNotFound, "Not found") rw.WriteHeader(StatusNotFound, "Not found")
} }
@ -185,6 +185,17 @@ func NotFoundHandler() Handler {
return HandlerFunc(NotFound) return HandlerFunc(NotFound)
} }
// Gone replies to the request with the Gone status code.
func Gone(rw *ResponseWriter, req *Request) {
rw.WriteHeader(StatusGone, "Gone")
}
// GoneHandler returns a simple handler that responds to each request with
// the status code Gone.
func GoneHandler() Handler {
return HandlerFunc(Gone)
}
// Redirect replies to the request with a redirect to the given url. // Redirect replies to the request with a redirect to the given url.
// If permanent is true, Redirect will respond with a permanent redirect. // If permanent is true, Redirect will respond with a permanent redirect.
func Redirect(rw *ResponseWriter, req *Request, url string, permanent bool) { func Redirect(rw *ResponseWriter, req *Request, url string, permanent bool) {
@ -217,6 +228,32 @@ func InputHandler(prompt string) Handler {
}) })
} }
// Sensitive responds to the request with a request for sensitive input
// using the given prompt.
func SensitiveInput(rw *ResponseWriter, req *Request, prompt string) {
rw.WriteHeader(StatusSensitiveInput, prompt)
}
// SensitiveInputHandler returns a simpler handler that responds to each request
// with a request for sensitive input.
func SensitiveInputHandler(prompt string) Handler {
return HandlerFunc(func(rw *ResponseWriter, req *Request) {
SensitiveInput(rw, req, prompt)
})
}
// CertificateRequired responds to the request with the CertificateRequired
// status code.
func CertificateRequired(rw *ResponseWriter, req *Request) {
rw.WriteHeader(StatusCertificateRequired, "Certificate required")
}
// CertificateNotAuthorized responds to the request with
// the CertificateNotAuthorized status code.
func CertificateNotAuthorized(rw *ResponseWriter, req *Request) {
rw.WriteHeader(StatusCertificateNotAuthorized, "Certificate not authorized")
}
// ServeMux is a Gemini request multiplexer. // ServeMux is a Gemini request multiplexer.
// It matches the URL of each incoming request against a list of registered // It matches the URL of each incoming request against a list of registered
// patterns and calls the handler for the pattern that most closesly matches // patterns and calls the handler for the pattern that most closesly matches