oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1package docs
2
3import (
4 "bytes"
5 "encoding/base64"
6 "encoding/json"
7 "math"
8 "net/http"
9
10 "amadan.net/oficina/home/handoff"
11)
12
13const homeReturnCookie = "__Host-oficina-docs-home-return"
14const homeReturnLimit = 4096
15
16type homeReturnIntent struct {
17 Path string `json:"path"`
18 Issued int64 `json:"issued"`
19 Expires int64 `json:"expires"`
20}
21
22// Resource navigation is separate from the fixed-action local reauth marker.
23// Neither cookie authorizes linking or access to the requested document.
24func (n *localLinkNavigation) rememberReturn(w http.ResponseWriter, path string) bool {
25 if !handoff.SafePath(path) {
26 path = "/"
27 }
28 now := n.now().Unix()
29 if now <= 0 || now > math.MaxInt64-localLinkNavigationLifetime {
30 return false
31 }
32 raw, err := json.Marshal(homeReturnIntent{path, now, now + localLinkNavigationLifetime})
33 if err != nil {
34 return false
35 }
36 sealed, err := n.sealer.Seal("docs.home-return.v1:"+n.origin, raw)
37 if err != nil {
38 return false
39 }
40 value := base64.RawURLEncoding.EncodeToString(sealed)
41 if len(value) > homeReturnLimit {
42 return false
43 }
44 localNavigationCookie(w, homeReturnCookie, value, int(localLinkNavigationLifetime))
45 return true
46}
47
48func (n *localLinkNavigation) returnPath(r *http.Request) string {
49 value := ""
50 if cookieCount(r, homeReturnCookie) != 1 {
51 return "/"
52 }
53 cookie, err := r.Cookie(homeReturnCookie)
54 if err != nil {
55 return "/"
56 }
57 value = cookie.Value
58 if value == "" || len(value) > homeReturnLimit {
59 return "/"
60 }
61 sealed, err := base64.RawURLEncoding.Strict().DecodeString(value)
62 if err != nil || base64.RawURLEncoding.EncodeToString(sealed) != value {
63 return "/"
64 }
65 raw, err := n.sealer.Open("docs.home-return.v1:"+n.origin, sealed)
66 if err != nil || len(raw) > homeReturnLimit {
67 return "/"
68 }
69 var intent homeReturnIntent
70 if json.Unmarshal(raw, &intent) != nil {
71 return "/"
72 }
73 canonical, _ := json.Marshal(intent)
74 now := n.now().Unix()
75 if !bytes.Equal(raw, canonical) || intent.Issued <= 0 || intent.Issued > now || intent.Expires <= now || intent.Expires <= intent.Issued || intent.Expires-intent.Issued > localLinkNavigationLifetime || !handoff.SafePath(intent.Path) {
76 return "/"
77 }
78 return intent.Path
79}
80