diff options
| author | Brad Fitzpatrick <bradfitz@tailscale.com> | 2021-04-16 10:57:46 -0700 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@tailscale.com> | 2021-04-16 10:58:19 -0700 |
| commit | b993d9802a2a59fc8b97ad4e783e8c331df5fe60 (patch) | |
| tree | d3a1151569fc0efed973a1c51d86bd70d0cd5d73 /ipn | |
| parent | 2f422434aa6f89d9c4e3437ce50dda78a9e680b5 (diff) | |
| download | tailscale-b993d9802a2a59fc8b97ad4e783e8c331df5fe60.tar.xz tailscale-b993d9802a2a59fc8b97ad4e783e8c331df5fe60.zip | |
ipn/ipnlocal, etc: require file sharing capability to send/recv files
tailscale/corp#1582
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Diffstat (limited to 'ipn')
| -rw-r--r-- | ipn/ipnlocal/local.go | 24 | ||||
| -rw-r--r-- | ipn/ipnlocal/peerapi.go | 4 | ||||
| -rw-r--r-- | ipn/ipnstate/ipnstate.go | 3 | ||||
| -rw-r--r-- | ipn/localapi/localapi.go | 15 |
4 files changed, 44 insertions, 2 deletions
diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 51761bc19..18d8b310f 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -2215,12 +2215,36 @@ func (b *LocalBackend) OpenFile(name string) (rc io.ReadCloser, size int64, err return apiSrv.OpenFile(name) } +// hasCapFileSharing reports whether the current node has the file +// sharing capability enabled. +func (b *LocalBackend) hasCapFileSharing() bool { + b.mu.Lock() + defer b.mu.Unlock() + return b.hasCapFileSharingLocked() +} + +func (b *LocalBackend) hasCapFileSharingLocked() bool { + nm := b.netMap + if nm == nil || nm.SelfNode == nil { + return false + } + for _, c := range nm.SelfNode.Capabilities { + if c == tailcfg.CapabilityFileSharing { + return true + } + } + return false +} + // FileTargets lists nodes that the current node can send files to. func (b *LocalBackend) FileTargets() ([]*apitype.FileTarget, error) { var ret []*apitype.FileTarget b.mu.Lock() defer b.mu.Unlock() + if !b.hasCapFileSharingLocked() { + return nil, errors.New("file sharing not enabled by Tailscale admin") + } nm := b.netMap if b.state != ipn.Running || nm == nil { return nil, errors.New("not connected") diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 2af91f234..b1a43b3c2 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -410,6 +410,10 @@ func (h *peerAPIHandler) put(w http.ResponseWriter, r *http.Request) { http.Error(w, "not owner", http.StatusForbidden) return } + if !h.ps.b.hasCapFileSharing() { + http.Error(w, "file sharing not enabled by Tailscale admin", http.StatusForbidden) + return + } if r.Method != "PUT" { http.Error(w, "not method PUT", http.StatusMethodNotAllowed) return diff --git a/ipn/ipnstate/ipnstate.go b/ipn/ipnstate/ipnstate.go index a748f3271..cbc3413ca 100644 --- a/ipn/ipnstate/ipnstate.go +++ b/ipn/ipnstate/ipnstate.go @@ -88,7 +88,8 @@ type PeerStatus struct { KeepAlive bool ExitNode bool // true if this is the currently selected exit node. - PeerAPIURL []string + PeerAPIURL []string + Capabilities []string `json:",omitempty"` // ShareeNode indicates this node exists in the netmap because // it's owned by a shared-to user and that node might connect diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index 8e57f85e1..f8adb188b 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -9,6 +9,7 @@ import ( "crypto/rand" "encoding/hex" "encoding/json" + "errors" "fmt" "io" "net" @@ -299,6 +300,18 @@ func (h *Handler) serveFiles(w http.ResponseWriter, r *http.Request) { io.Copy(w, rc) } +func writeErrorJSON(w http.ResponseWriter, err error) { + if err == nil { + err = errors.New("unexpected nil error") + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(500) + type E struct { + Error string `json:"error"` + } + json.NewEncoder(w).Encode(E{err.Error()}) +} + func (h *Handler) serveFileTargets(w http.ResponseWriter, r *http.Request) { if !h.PermitRead { http.Error(w, "access denied", http.StatusForbidden) @@ -310,7 +323,7 @@ func (h *Handler) serveFileTargets(w http.ResponseWriter, r *http.Request) { } fts, err := h.b.FileTargets() if err != nil { - http.Error(w, err.Error(), 500) + writeErrorJSON(w, err) return } makeNonNil(&fts) |
