IsLocalhost reports whether the requesting connection is from this machine and has the same owner as this process.
(req *http.Request)
| 34 | // IsLocalhost reports whether the requesting connection is from this machine |
| 35 | // and has the same owner as this process. |
| 36 | func IsLocalhost(req *http.Request) bool { |
| 37 | uid := os.Getuid() |
| 38 | from, err := netutil.HostPortToIP(req.RemoteAddr, nil) |
| 39 | if err != nil { |
| 40 | return false |
| 41 | } |
| 42 | to, err := netutil.HostPortToIP(req.Host, from) |
| 43 | if err != nil { |
| 44 | return false |
| 45 | } |
| 46 | |
| 47 | // If our OS doesn't support uid. |
| 48 | // TODO(bradfitz): netutil on OS X uses "lsof" to figure out |
| 49 | // ownership of tcp connections, but when fuse is mounted and a |
| 50 | // request is outstanding (for instance, a fuse request that's |
| 51 | // making a request to perkeepd and landing in this code |
| 52 | // path), lsof then blocks forever waiting on a lock held by the |
| 53 | // VFS, leading to a deadlock. Instead, on darwin, just trust |
| 54 | // any localhost connection here, which is kinda lame, but |
| 55 | // whatever. Macs aren't very multi-user anyway. |
| 56 | if uid == -1 || runtime.GOOS == "darwin" { |
| 57 | return from.IP.IsLoopback() && to.IP.IsLoopback() |
| 58 | } |
| 59 | if uid == 0 { |
| 60 | log.Printf("perkeepd running as root. Don't do that.") |
| 61 | return false |
| 62 | } |
| 63 | if uid > 0 { |
| 64 | connUID, err := netutil.AddrPairUserid(from, to) |
| 65 | if err == nil { |
| 66 | if uid == connUID || connUID == 0 { |
| 67 | // If it's the same user who's running the server, allow it. |
| 68 | // Also allow root, so users can "sudo pk-put" files. |
| 69 | // Allowing root isn't a security problem because if root wants |
| 70 | // to mess with the local user, they already can. This whole mechanism |
| 71 | // is about protecting regular users from other regular users |
| 72 | // on shared computers. |
| 73 | return true |
| 74 | } |
| 75 | log.Printf("auth: local connection uid %d doesn't match server uid %d", connUID, uid) |
| 76 | } |
| 77 | } |
| 78 | return false |
| 79 | } |
| 80 | |
| 81 | // BasicAuth parses the Authorization header on req |
| 82 | // If absent or invalid, an error is returned. |