Merge CGI and SCGI variable preparation.

This commit is contained in:
Solderpunk 2020-06-06 11:33:00 +02:00
parent d78c840056
commit 54ed1ab265
1 changed files with 55 additions and 32 deletions

View File

@ -5,7 +5,6 @@ import (
"context"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"errors"
"encoding/hex"
"fmt"
@ -85,7 +84,7 @@ func handleGeminiRequest(conn net.Conn, config Config, logEntries chan LogEntry)
matched, err := regexp.Match(scgi_url, []byte(URL.Path))
if matched && err == nil {
fmt.Println("Matched:", scgi_url, scgi_socket)
handleSCGI(scgi_socket, config, URL, clientCerts, log, conn)
handleSCGI(scgi_socket, config, URL, log, conn)
return
}
}
@ -142,7 +141,7 @@ func handleGeminiRequest(conn net.Conn, config Config, logEntries chan LogEntry)
// If this file is executable, get dynamic content
inCGIPath, err := regexp.Match(config.CGIPath, []byte(path))
if inCGIPath && info.Mode().Perm() & 0111 == 0111 {
handleCGI(config, path, URL, clientCerts, log, conn)
handleCGI(config, path, URL, log, conn)
return
}
@ -245,35 +244,16 @@ func serveFile(path string, log LogEntry, conn net.Conn) {
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)
defer cancel()
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()
@ -300,7 +280,7 @@ func handleCGI(config Config, path string, URL *url.URL, clientCerts []*x509.Cer
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
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()
// Send variables
vars := make(map[string]string)
vars["SCGI"] = "1"
vars["CONTENT_LENGTH"] = "0"
vars := prepareSCGIVariables(config, URL, conn)
length := 0
for key, value := range(vars) {
length += len(key)
@ -361,3 +339,48 @@ func handleSCGI(socket_path string, config Config, URL *url.URL, clientCerts []*
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
}