diff options
author | Peter Harris <pharris@opentext.com> | 2011-02-15 14:40:32 -0500 |
---|---|---|
committer | Peter Harris <pharris@opentext.com> | 2011-02-15 14:40:32 -0500 |
commit | fd93ba09f760a785337bbed4cc0a79348dc6f451 (patch) | |
tree | ab8d68fe44abcf0acd3c36d1191e287b3b28a8ba | |
parent | f8704f0486606a0d16fb1dbe28b6a8bc7ff425b0 (diff) |
Add Auth support
MIT-MAGIC-COOKIE only so far. The XDM auth is considerably more complex.
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | xgob.go | 186 |
2 files changed, 180 insertions, 7 deletions
@@ -13,6 +13,7 @@ all: test noop xlsclients # Dependencies +xgob.6: xau.6 xgob/util/atom.6: xgob/xproto.6 xgob.6 xgob/xproto.6: xgob.6 xmu.6: xgob/util/atom.6 xgob/xproto.6 xgob.6 @@ -9,6 +9,7 @@ import ( "strconv" "strings" "sync" + "xau" ) const X_TCP_PORT = 6000 @@ -18,6 +19,14 @@ const ( MSBFirst = iota ) +const ( + FamilyInternet uint16 = 0 + FamilyDECNet = 1 + FamilyCHAOS = 2 + FamilyServerInterpreted = 5 + FamilyInternet6 = 6 +) + type Format struct { Depth, BitsPerPixel, ScanlinePad uint8 } @@ -216,7 +225,7 @@ func Pad(i int) int { return (-i) & 3 } -func (c *Connection) write_setup(name string, data string) { +func (c *Connection) write_setup(name string, data []byte) { buf := make([]byte, 0, 100) buf = append(buf, 'B') // Big endian. @@ -233,8 +242,7 @@ func (c *Connection) write_setup(name string, data string) { for i := 0; i < Pad(len(name)); i++ { buf = append(buf, 0) } - n = bytes.NewBufferString(data) - buf = append(buf, n.Bytes()...) + buf = append(buf, data...) for i := 0; i < Pad(len(data)); i++ { buf = append(buf, 0) } @@ -503,7 +511,7 @@ func (c *Connection) read(in *bufio.Reader) { } } -func (c *Connection) connect_auth(name string, data string) { +func (c *Connection) connect_auth(name string, data []byte) { c.write_setup(name, data) in := bufio.NewReader(c.conn) if !c.read_setup(in) { @@ -518,7 +526,160 @@ func (c *Connection) connect_auth(name string, data string) { go c.read(in) } -func Connect(dpy string) (conn *Connection, screen int) { +type AuthInfo struct { + Name string + Data []byte +} + +// AUTH starts + +const authXDM = "XDM-AUTHORIZATION-1" +const authCookie = "MIT-MAGIC-COOKIE-1" + +type addresser interface { + LocalAddr() net.Addr + RemoteAddr() net.Addr +} + +func getAuthPtr(a net.Addr, display int) *xau.Xauth { + family := xau.FamilyLocal + addr := []byte{0, 0, 0, 0} + + switch a.Network() { + case "unix": + if name, err := os.Hostname(); err == nil { + addr = []byte(name) + } + case "tcp", "tcp4", "tcp6": + if tcp, ok := a.(*net.TCPAddr); ok { + ip4 := tcp.IP.To4() + if ip4 != nil { + addr = []byte(ip4) + if addr[0] == 127 { + // Loopback - use FamilyLocal + if name, err := os.Hostname(); err == nil { + addr = []byte(name) + } + } else { + family = FamilyInternet + } + } else { + ip6 := tcp.IP.To16() + if ip6 != nil { + addr = []byte(tcp.IP) + if bytes.Equal(addr, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}) { + // Loopback - use FamilyLocal + if name, err := os.Hostname(); err == nil { + addr = []byte(name) + } + } else { + family = FamilyInternet6 + } + } else { + return nil + } + } + } else { + return nil + } + default: + return nil + } + + disp := []byte(strconv.Itoa(display)) + return xau.GetBestAuthByAddr(family, addr, disp, []string{ /*authXDM,*/ authCookie}) +} + +func appendUint32(buf []byte, val uint32) []byte { + buf = append(buf, byte(val>>32)) + buf = append(buf, byte(val>>24)) + buf = append(buf, byte(val>>8)) + buf = append(buf, byte(val&0xFF)) + return buf +} + +func computeAuth(auth *xau.Xauth, sockaddr net.Addr) *AuthInfo { + switch auth.Name { + case authCookie: + return &AuthInfo{auth.Name, auth.Data} + case authXDM: + var info AuthInfo + info.Data = make([]byte, 8, 192/8) + copy(info.Data, auth.Data) + switch sockaddr.Network() { + case "tcp", "tcp4", "tcp6": + if tcp, ok := sockaddr.(*net.TCPAddr); ok { + if ip4 := tcp.IP.To4(); ip4 != nil { + info.Data = append(info.Data, []byte(ip4)...) + info.Data = append(info.Data, byte(tcp.Port>>8)) + info.Data = append(info.Data, byte(tcp.Port&0xFF)) + } else if ip6 := tcp.IP.To16(); ip6 != nil { + /* XDM-AUTHORIZATION-1 does not handle IPv6 correctly. Do the + same thing Xlib does: use all zeroes for the 4-byte address + and 2-byte port number. */ + info.Data = append(info.Data, 0, 0, 0, 0, 0, 0) + } + } + case "unix": + info.Data = appendUint32(info.Data, 0xFFFFFFFF) // TODO: -next_nonce() + pid := os.Getpid() + info.Data = append(info.Data, byte(pid>>8)) + info.Data = append(info.Data, byte(pid&0xFF)) + default: + return nil + } + time, _, _ := os.Time() + info.Data = appendUint32(info.Data, uint32(time)) + for len(info.Data) < 192/8 { + info.Data = append(info.Data, 0) + } + panic("TODO: XdmcpWrap") + } + return nil +} + +func (c *Connection) getAuthInfo(display int) *AuthInfo { + // code adapted from libXCB/xcb_auth.c + addr, ok := c.conn.(addresser) + if !ok { + return nil + } + + var gotsockname bool + /* Some systems like hpux or Hurd do not expose peer names + * for UNIX Domain Sockets, but this is irrelevant, + * since compute_auth() ignores the peer name in this + * case anyway.*/ + a := addr.RemoteAddr() + if a.String() == "" { + a = addr.LocalAddr() + if a.String() == "" { + return nil + } + if a.Network() != "unix" { + return nil + } + gotsockname = true + } + + auth := getAuthPtr(a, display) + if auth == nil { + return nil + } + + if !gotsockname { + a = addr.LocalAddr() + if a.String() == "" { + return nil + } + } + + return computeAuth(auth, a) +} + +// AUTH ends + +func ConnectWithAuth(dpy string, info *AuthInfo) (conn *Connection, screen int) { host, proto, display, screen := parse_display(dpy) var c Connection @@ -528,13 +689,24 @@ func Connect(dpy string) (conn *Connection, screen int) { return } - // TODO: name, data := c.get_auth_info() - name, data := "", "" + var name string + data := make([]byte, 0) + if info == nil { + info = c.getAuthInfo(display) + } + if info != nil { + name = info.Name + data = info.Data + } c.connect_auth(name, data) conn = &c return } +func Connect(dpy string) (conn *Connection, screen int) { + return ConnectWithAuth(dpy, nil) +} + func (c *Connection) Disconnect() { c.conn.Close() c.conn = nil |