Files
X11Proxy/auth.go

116 lines
2.7 KiB
Go

package main
import (
"fmt"
"net"
"os"
"os/exec"
"path"
"strconv"
"strings"
"x11proxy/x11probe"
)
func resolveDisplay(display string) (x11probe.ConnType, string) {
var dispNum int
var err error
if strings.HasPrefix(display, ":") {
dispNum, err = strconv.Atoi(strings.Split(display[1:], ".")[0])
} else {
parts := strings.Split(display, ":")
dispNum, err = strconv.Atoi(strings.Split(parts[1], ".")[0])
}
if err != nil {
dispNum = 0
}
unixPath := path.Join("/tmp/.X11-unix", fmt.Sprintf("X%d", dispNum))
if _, err := os.Stat(unixPath); err == nil {
return x11probe.Unix, unixPath
}
tcpAddr := fmt.Sprintf("127.0.0.1:%d", 6000+dispNum)
conn, err := net.Dial("tcp", tcpAddr)
if err == nil {
conn.Close()
return x11probe.TCP, tcpAddr
}
return x11probe.Unix, unixPath
}
func getXAuthCookie(display string) ([]byte, error) {
out, err := exec.Command("xauth", "list").Output()
if err != nil {
return nil, err
}
var dispNum string
if strings.HasPrefix(display, ":") {
dispNum = strings.Split(display[1:], ".")[0]
} else {
parts := strings.Split(display, ":")
dispNum = strings.Split(parts[1], ".")[0]
}
lines := strings.Split(string(out), "\n")
for _, line := range lines {
fields := strings.Fields(line)
if len(fields) >= 3 && fields[1] == "MIT-MAGIC-COOKIE-1" {
entry := fields[0]
if strings.Contains(entry, ":"+dispNum) {
fmt.Printf("Using XAuth cookie from entry: %s\n", entry)
return parseHexCookie(fields[2]), nil
}
}
}
return nil, fmt.Errorf("no matching cookie found for display %s", display)
}
func parseHexCookie(hexStr string) []byte {
var cookie []byte
for i := 0; i < len(hexStr); i += 2 {
var val byte
fmt.Sscanf(hexStr[i:i+2], "%02x", &val)
cookie = append(cookie, val)
}
return cookie
}
func PatchAuth(data []byte, cookie []byte) []byte {
isLittleEndian := data[0] == 'l'
var authProtoLen, authDataLen int
if isLittleEndian {
authProtoLen = int(data[7])<<8 | int(data[6])
authDataLen = int(data[9])<<8 | int(data[8])
} else {
authProtoLen = int(data[6])<<8 | int(data[7])
authDataLen = int(data[8])<<8 | int(data[9])
}
headerLen := 12
authProtoPad := (authProtoLen + 3) & ^3
authDataPad := (authDataLen + 3) & ^3
authDataStart := headerLen + authProtoPad
// Replace cookie and update length
patched := make([]byte, headerLen+authProtoPad+authDataPad)
copy(patched, data[:headerLen+authProtoPad])
copy(patched[authDataStart:], cookie)
// Update authDataLen to match cookie length
cookieLen := len(cookie)
if isLittleEndian {
patched[8] = byte(cookieLen)
patched[9] = byte(cookieLen >> 8)
} else {
patched[8] = byte(cookieLen >> 8)
patched[9] = byte(cookieLen)
}
return patched
}