func (a *InternalAPIEngine) checkSessionExpired(arg APIArg, status *jsonw.Wrapper) error { code, err := status.AtKey("code").GetInt() if err != nil { return fmt.Errorf("Cannot find status 'code' in reply") } if code != SCBadSession { return nil } var loggedIn bool if arg.SessionR != nil { loggedIn = arg.SessionR.IsLoggedIn() } else { loggedIn = a.G().LoginState().LoggedIn() } if !loggedIn { return nil } a.G().Log.Debug("local session -> is logged in, remote -> not logged in. invalidating local session:") if arg.SessionR != nil { arg.SessionR.Invalidate() } else { a.G().LoginState().LocalSession(func(s *Session) { s.Invalidate() }, "api - checkSessionExpired") } return LoginRequiredError{Context: "your session has expired."} }
func (a *InternalAPIEngine) checkAppStatus(arg APIArg, jw *jsonw.Wrapper) (string, error) { var set []string resName, err := jw.AtKey("name").GetString() if err != nil { err = fmt.Errorf("Cannot find status name in reply") return "", err } if arg.AppStatus == nil || len(arg.AppStatus) == 0 { set = []string{"OK"} } else { set = arg.AppStatus } for _, status := range set { if resName == status { return resName, nil } } // check if there was a bad session error: if err := a.checkSessionExpired(arg, jw); err != nil { return "", err } return "", NewAppStatusError(jw) }
func NewSigHint(jw *jsonw.Wrapper) (sh *SigHint, err error) { sh = &SigHint{} sh.sigID, err = GetSigID(jw.AtKey("sig_id"), true) sh.remoteID, _ = jw.AtKey("remote_id").GetString() sh.apiURL, _ = jw.AtKey("api_url").GetString() sh.humanURL, _ = jw.AtKey("human_url").GetString() sh.checkText, _ = jw.AtKey("proof_text_check").GetString() return }
func ImportLinkFromServer(g *GlobalContext, parent *SigChain, jw *jsonw.Wrapper, selfUID keybase1.UID) (ret *ChainLink, err error) { var id LinkID GetLinkIDVoid(jw.AtKey("payload_hash"), &id, &err) if err != nil { return } ret = NewChainLink(g, parent, id, jw) if err = ret.Unpack(false, selfUID); err != nil { ret = nil } return }
func remoteProofToTrackingStatement(s RemoteProofChainLink, base *jsonw.Wrapper) error { typS := s.TableKey() i, found := RemoteServiceTypes[typS] if !found { return fmt.Errorf("No service type found for %q in proof %d", typS, s.GetSeqno()) } base.AtKey("remote_key_proof").SetKey("proof_type", jsonw.NewInt(int(i))) base.AtKey("remote_key_proof").SetKey("check_data_json", s.CheckDataJSON()) base.SetKey("sig_type", jsonw.NewInt(SigTypeRemoteProof)) return nil }
func trackedKeyFromJSON(jw *jsonw.Wrapper) (TrackedKey, error) { var ret TrackedKey kid, err := GetKID(jw.AtKey("kid")) if err != nil { return TrackedKey{}, err } ret.KID = kid // It's ok if key_fingerprint doesn't exist. But if it does, then include it: fp, err := GetPGPFingerprint(jw.AtKey("key_fingerprint")) if err == nil && fp != nil { ret.Fingerprint = fp } return ret, nil }
func pathStepFromJSON(jw *jsonw.Wrapper) (ps *PathStep, err error) { var prefix string pw := jw.AtKey("prefix") if !pw.IsNil() { var s string if s, err = pw.GetString(); err != nil { return } prefix = s } node, err := jw.AtKey("node").AtKey("val").GetString() if err != nil { return } ps = &PathStep{prefix, node} return }
func trackedKeyFromJSON(jw *jsonw.Wrapper) (TrackedKey, error) { var ret TrackedKey kid, err := GetKID(jw.AtKey("kid")) if err != nil { return TrackedKey{}, err } ret.KID = kid // TODO: Should we tolerate missing fingerprints? Will "body.track.key" // ever be a non-PGP key, for example? I'm *very* hesitant about defining a // new type that's basically a FOKID, right after we did all that work to // delete FOKID. fp, err := GetPGPFingerprint(jw.AtKey("key_fingerprint")) if err != nil { return TrackedKey{}, err } ret.Fingerprint = *fp return ret, nil }
func checkAppStatus(arg APIArg, jw *jsonw.Wrapper) (string, error) { var set []string resName, err := jw.AtKey("name").GetString() if err != nil { err = fmt.Errorf("Cannot find status name in reply") return "", err } if arg.AppStatus == nil || len(arg.AppStatus) == 0 { set = []string{"OK"} } else { set = arg.AppStatus } for _, status := range set { if resName == status { return resName, nil } } return "", NewAppStatusError(jw) }
func (sh *SigHints) PopulateWith(jw *jsonw.Wrapper) (err error) { if jw == nil || jw.IsNil() { return } jw.AtKey("version").GetIntVoid(&sh.version, &err) if err != nil { return } sh.hints = make(map[keybase1.SigID]*SigHint) var n int n, err = jw.AtKey("hints").Len() if err != nil { return } for i := 0; i < n; i++ { hint, tmpe := NewSigHint(jw.AtKey("hints").AtIndex(i)) if tmpe != nil { sh.G().Log.Warning("Bad SigHint Loaded: %s", tmpe) } else { sh.hints[hint.sigID] = hint } } return }
func NewCheckResult(jw *jsonw.Wrapper) (res *CheckResult, err error) { var t int64 var code int var desc string jw.AtKey("time").GetInt64Void(&t, &err) status := jw.AtKey("status") var pe ProofError if !status.IsNil() { status.AtKey("desc").GetStringVoid(&desc, &err) status.AtKey("code").GetIntVoid(&code, &err) pe = NewProofError(keybase1.ProofStatus(code), desc) } if err == nil { res = &CheckResult{ Status: pe, Time: time.Unix(t, 0), } } return }
func ParseServiceBlock(jw *jsonw.Wrapper) (sb *ServiceBlock, err error) { var social bool var typ, id string if prot, e1 := jw.AtKey("protocol").GetString(); e1 == nil { var hostname string jw.AtKey("hostname").GetStringVoid(&hostname, &e1) if e1 == nil { switch prot { case "http:": typ, id = "http", hostname case "https:": typ, id = "https", hostname } } else if domain, e2 := jw.AtKey("domain").GetString(); e2 == nil && prot == "dns" { typ, id = "dns", domain } } else { var e2 error jw.AtKey("name").GetStringVoid(&typ, &e2) jw.AtKey("username").GetStringVoid(&id, &e2) if e2 != nil { id, typ = "", "" } else { social = true } } if len(typ) == 0 { err = fmt.Errorf("Unrecognized Web proof @%s", jw.MarshalToDebug()) } sb = &ServiceBlock{social: social, typ: typ, id: id} return }
func (path PathSteps) VerifyPath(curr NodeHash, uidS string) (juser *jsonw.Wrapper, err error) { bpath := uidS pos := 0 lastTyp := 0 for i, step := range path { payload := step.node if !curr.Check(payload) { err = fmt.Errorf("Hash mismatch at level=%d", i) break } var jw *jsonw.Wrapper jw, err = jsonw.Unmarshal([]byte(payload)) if err != nil { err = fmt.Errorf("Can't parse JSON at level=%d: %s", i, err) break } plen := len(step.prefix) epos := pos + plen if bpath[pos:epos] != step.prefix { err = fmt.Errorf("Path mismatch at level %d: %s != %s", i, bpath[pos:epos], step.prefix) break } pos = epos lastTyp, err = jw.AtKey("type").GetInt() if err != nil { err = fmt.Errorf("At level %d, failed to get a valid 'type'", i) break } if lastTyp == MerkleTreeNode { if plen == 0 { err = fmt.Errorf("Empty prefix len at level=%d", i) return } curr, err = GetNodeHash(jw.AtKey("tab").AtKey(step.prefix)) if err != nil { err = MerkleNotFoundError{uidS, err.Error()} break } juser = nil } else { juser = jw.AtKey("tab").AtKey(uidS) } } if err == nil && juser == nil { err = MerkleNotFoundError{uidS, "tree path didn't end in a leaf"} } return }
func (rc *RedditChecker) CheckData(h SigHint, dat *jsonw.Wrapper) ProofError { sigBody, sigID, err := OpenSig(rc.proof.GetArmoredSig()) if err != nil { return NewProofError(keybase1.ProofStatus_BAD_SIGNATURE, "Bad signature: %s", err) } var subreddit, author, selftext, title string dat.AtKey("subreddit").GetStringVoid(&subreddit, &err) dat.AtKey("author").GetStringVoid(&author, &err) dat.AtKey("selftext").GetStringVoid(&selftext, &err) dat.AtKey("title").GetStringVoid(&title, &err) if err != nil { return NewProofError(keybase1.ProofStatus_CONTENT_MISSING, "content missing: %s", err) } if strings.ToLower(subreddit) != "keybaseproofs" { return NewProofError(keybase1.ProofStatus_SERVICE_ERROR, "the post must be to /r/KeybaseProofs") } if wanted := rc.proof.GetRemoteUsername(); !rc.ScreenNameCompare(author, wanted) { return NewProofError(keybase1.ProofStatus_BAD_USERNAME, "Bad post author; wanted '%s' but got '%s'", wanted, author) } if psid := sigID.ToMediumID(); !strings.Contains(title, psid) { return NewProofError(keybase1.ProofStatus_TITLE_NOT_FOUND, "Missing signature ID (%s) in post title ('%s')", psid, title) } if !FindBase64Block(selftext, sigBody, false) { return NewProofError(keybase1.ProofStatus_TEXT_NOT_FOUND, "signature not found in body") } return nil }
func NewAppStatusError(jw *jsonw.Wrapper) AppStatusError { code, _ := jw.AtKey("code").GetInt64() desc, _ := jw.AtKey("desc").GetString() name, _ := jw.AtKey("name").GetString() tab := make(map[string]string) fields := jw.AtKey("fields") if keys, _ := fields.Keys(); keys != nil && len(keys) > 0 { for _, k := range keys { tab[k], _ = fields.AtKey(k).GetString() } } return AppStatusError{ Code: int(code), Name: name, Desc: desc, Fields: tab, } }
func NewMerkleRootFromJSON(jw *jsonw.Wrapper, g *GlobalContext) (ret *MerkleRoot, err error) { var seqno int64 var sigs *jsonw.Wrapper var payloadJSONString string var pj *jsonw.Wrapper var fp PGPFingerprint var rh, lurh NodeHash var ctime int64 if sigs, err = jw.AtKey("sigs").ToDictionary(); err != nil { return } if payloadJSONString, err = jw.AtKey("payload_json").GetString(); err != nil { return } if pj, err = jsonw.Unmarshal([]byte(payloadJSONString)); err != nil { return } GetPGPFingerprintVoid(pj.AtPath("body.key.fingerprint"), &fp, &err) pj.AtPath("body.seqno").GetInt64Void(&seqno, &err) GetNodeHashVoid(pj.AtPath("body.root"), &rh, &err) lurh, _ = GetNodeHash(pj.AtPath("body.legacy_uid_root")) pj.AtKey("ctime").GetInt64Void(&ctime, &err) if err != nil { return } ret = &MerkleRoot{ seqno: Seqno(seqno), pgpFingerprint: fp, sigs: sigs, payloadJSONString: payloadJSONString, payloadJSON: pj, rootHash: rh, legacyUIDRootHash: lurh, ctime: ctime, Contextified: NewContextified(g), } return }
func NewUser(g *GlobalContext, o *jsonw.Wrapper) (*User, error) { uid, err := GetUID(o.AtKey("id")) if err != nil { return nil, fmt.Errorf("user object lacks an ID: %s", err) } name, err := o.AtKey("basics").AtKey("username").GetString() if err != nil { return nil, fmt.Errorf("user object for %s lacks a name", uid) } kf, err := ParseKeyFamily(o.AtKey("public_keys")) if err != nil { return nil, err } return &User{ basics: o.AtKey("basics"), publicKeys: o.AtKey("public_keys"), sigs: o.AtKey("sigs"), pictures: o.AtKey("pictures"), keyFamily: kf, id: uid, name: name, dirty: false, Contextified: NewContextified(g), }, nil }