forked from solderpunk/molly-brown
Merge CGI and SCGI variable preparation.
This commit is contained in:
parent
d78c840056
commit
54ed1ab265
87
handler.go
87
handler.go
|
@ -5,7 +5,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
|
||||||
"errors"
|
"errors"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -85,7 +84,7 @@ func handleGeminiRequest(conn net.Conn, config Config, logEntries chan LogEntry)
|
||||||
matched, err := regexp.Match(scgi_url, []byte(URL.Path))
|
matched, err := regexp.Match(scgi_url, []byte(URL.Path))
|
||||||
if matched && err == nil {
|
if matched && err == nil {
|
||||||
fmt.Println("Matched:", scgi_url, scgi_socket)
|
fmt.Println("Matched:", scgi_url, scgi_socket)
|
||||||
handleSCGI(scgi_socket, config, URL, clientCerts, log, conn)
|
handleSCGI(scgi_socket, config, URL, log, conn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +141,7 @@ func handleGeminiRequest(conn net.Conn, config Config, logEntries chan LogEntry)
|
||||||
// If this file is executable, get dynamic content
|
// If this file is executable, get dynamic content
|
||||||
inCGIPath, err := regexp.Match(config.CGIPath, []byte(path))
|
inCGIPath, err := regexp.Match(config.CGIPath, []byte(path))
|
||||||
if inCGIPath && info.Mode().Perm() & 0111 == 0111 {
|
if inCGIPath && info.Mode().Perm() & 0111 == 0111 {
|
||||||
handleCGI(config, path, URL, clientCerts, log, conn)
|
handleCGI(config, path, URL, log, conn)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,35 +244,16 @@ func serveFile(path string, log LogEntry, conn net.Conn) {
|
||||||
conn.Write(contents)
|
conn.Write(contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleCGI(config Config, path string, URL *url.URL, clientCerts []*x509.Certificate, log LogEntry, conn net.Conn) {
|
func handleCGI(config Config, path string, URL *url.URL, log LogEntry, conn net.Conn) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
cmd := exec.CommandContext(ctx, path)
|
cmd := exec.CommandContext(ctx, path)
|
||||||
// Set environment variables
|
|
||||||
cmd.Env = []string{
|
|
||||||
"GATEWAY_INTERFACE=CGI/1.1",
|
|
||||||
"PATH_INFO=/",
|
|
||||||
"QUERY_STRING=" + URL.RawQuery,
|
|
||||||
"REMOTE_ADDR=" + conn.RemoteAddr().String(),
|
|
||||||
"REQUEST_METHOD=",
|
|
||||||
"SCRIPT_PATH=" + path,
|
|
||||||
"SERVER_NAME=" + config.Hostname,
|
|
||||||
"SERVER_PORT=" + strconv.Itoa(config.Port),
|
|
||||||
"SERVER_PROTOCL=GEMINI",
|
|
||||||
"SERVER_SOFTWARE=MOLLY_BROWN",
|
|
||||||
}
|
|
||||||
// Add client cert variables
|
|
||||||
if len(clientCerts) > 0 {
|
|
||||||
cert := clientCerts[0]
|
|
||||||
fingerprint := sha256.Sum256(cert.Raw)
|
|
||||||
cmd.Env = append(cmd.Env,
|
|
||||||
"TLS_CLIENT_HASH=" + hex.EncodeToString(fingerprint[:]),
|
|
||||||
"TLS_CLIENT_ISSUER=" + cert.Issuer.String(),
|
|
||||||
"TLS_CLIENT_ISSUER_CN=" + cert.Issuer.CommonName,
|
|
||||||
"TLS_CLIENT_SUBJECT=" + cert.Subject.String(),
|
|
||||||
"TLS_CLIENT_SUBJECT_CN=" + cert.Subject.CommonName,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
// Set environment variables
|
||||||
|
vars := prepareCGIVariables(config, URL, conn, path)
|
||||||
|
cmd.Env = []string{ }
|
||||||
|
for key, value := range vars {
|
||||||
|
cmd.Env = append(cmd.Env, key + "=" + value)
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := cmd.Output()
|
response, err := cmd.Output()
|
||||||
|
@ -300,7 +280,7 @@ func handleCGI(config Config, path string, URL *url.URL, clientCerts []*x509.Cer
|
||||||
conn.Write(response)
|
conn.Write(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSCGI(socket_path string, config Config, URL *url.URL, clientCerts []*x509.Certificate, log LogEntry, conn net.Conn) {
|
func handleSCGI(socket_path string, config Config, URL *url.URL, log LogEntry, conn net.Conn) {
|
||||||
|
|
||||||
// Connect to socket
|
// Connect to socket
|
||||||
socket, err := net.Dial("unix", socket_path)
|
socket, err := net.Dial("unix", socket_path)
|
||||||
|
@ -312,9 +292,7 @@ func handleSCGI(socket_path string, config Config, URL *url.URL, clientCerts []*
|
||||||
defer socket.Close()
|
defer socket.Close()
|
||||||
|
|
||||||
// Send variables
|
// Send variables
|
||||||
vars := make(map[string]string)
|
vars := prepareSCGIVariables(config, URL, conn)
|
||||||
vars["SCGI"] = "1"
|
|
||||||
vars["CONTENT_LENGTH"] = "0"
|
|
||||||
length := 0
|
length := 0
|
||||||
for key, value := range(vars) {
|
for key, value := range(vars) {
|
||||||
length += len(key)
|
length += len(key)
|
||||||
|
@ -361,3 +339,48 @@ func handleSCGI(socket_path string, config Config, URL *url.URL, clientCerts []*
|
||||||
conn.Write(buffer[:n])
|
conn.Write(buffer[:n])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func prepareCGIVariables(config Config, URL *url.URL, conn net.Conn, path string) map[string]string {
|
||||||
|
vars := prepareGatewayVariables(config, URL, conn)
|
||||||
|
vars["GATEWAY_INTERFACE"] = "CGI/1.1"
|
||||||
|
vars["SCRIPT_PATH"] = path
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareSCGIVariables(config Config, URL *url.URL, conn net.Conn) map[string]string {
|
||||||
|
vars := prepareGatewayVariables(config, URL, conn)
|
||||||
|
vars["SCGI"] = "1"
|
||||||
|
vars["CONTENT_LENGTH"] = "0"
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareGatewayVariables(config Config, URL *url.URL, conn net.Conn) map[string]string {
|
||||||
|
vars := make(map[string]string)
|
||||||
|
vars["PATH_INFO"] = "/"
|
||||||
|
vars["QUERY_STRING"] = URL.RawQuery
|
||||||
|
vars["REMOTE_ADDR"] = conn.RemoteAddr().String()
|
||||||
|
vars["REQUEST_METHOD"] = ""
|
||||||
|
vars["SERVER_NAME"] = config.Hostname
|
||||||
|
vars["SERVER_PORT"] = strconv.Itoa(config.Port)
|
||||||
|
vars["SERVER_PROTOCL"] = "GEMINI"
|
||||||
|
vars["SERVER_SOFTWARE"] = "MOLLY_BROWN"
|
||||||
|
|
||||||
|
// Add TLS variables
|
||||||
|
var tlsConn (*tls.Conn) = conn.(*tls.Conn)
|
||||||
|
connState := tlsConn.ConnectionState()
|
||||||
|
// vars["TLS_CIPHER"] = CipherSuiteName(connState.CipherSuite)
|
||||||
|
|
||||||
|
// Add client cert variables
|
||||||
|
clientCerts := connState.PeerCertificates
|
||||||
|
if len(clientCerts) > 0 {
|
||||||
|
cert := clientCerts[0]
|
||||||
|
fingerprint := sha256.Sum256(cert.Raw)
|
||||||
|
vars["TLS_CLIENT_HASH"] = hex.EncodeToString(fingerprint[:])
|
||||||
|
vars["TLS_CLIENT_ISSUER"] = cert.Issuer.String()
|
||||||
|
vars["TLS_CLIENT_ISSUER_CN"] = cert.Issuer.CommonName
|
||||||
|
vars["TLS_CLIENT_SUBJECT"] = cert.Subject.String()
|
||||||
|
vars["TLS_CLIENT_SUBJECT_CN"] = cert.Subject.CommonName
|
||||||
|
}
|
||||||
|
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue