github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/services.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package libkb 5 6 import ( 7 "fmt" 8 "regexp" 9 "strings" 10 "sync" 11 12 keybase1 "github.com/keybase/client/go/protocol/keybase1" 13 jsonw "github.com/keybase/go-jsonw" 14 "golang.org/x/net/context" 15 ) 16 17 // ============================================================================= 18 19 func MakeProofChecker(mctx MetaContext, c ExternalServicesCollector, l RemoteProofChainLink) (ProofChecker, ProofError) { 20 if c == nil { 21 return nil, NewProofError(keybase1.ProofStatus_UNKNOWN_TYPE, 22 "No proof services configured") 23 } 24 k := l.TableKey() 25 st := c.GetServiceType(mctx.Ctx(), k) 26 if st == nil { 27 return nil, NewProofError(keybase1.ProofStatus_UNKNOWN_TYPE, 28 "No proof service for type: %s", k) 29 } 30 pc := st.MakeProofChecker(l) 31 if pc == nil { 32 return nil, NewProofError(keybase1.ProofStatus_UNKNOWN_TYPE, 33 "No proof checker for type: %s", k) 34 } 35 return pc, nil 36 } 37 38 // ============================================================================= 39 40 type BaseServiceType struct { 41 sync.Mutex 42 displayConf *keybase1.ServiceDisplayConfig 43 } 44 45 func (t *BaseServiceType) SetDisplayConfig(displayConf *keybase1.ServiceDisplayConfig) { 46 t.Lock() 47 defer t.Unlock() 48 t.displayConf = displayConf 49 } 50 51 func (t *BaseServiceType) BaseCheckProofTextShort(text string, id keybase1.SigID, med bool) error { 52 blocks := FindBase64Snippets(text) 53 var target string 54 if med { 55 target = id.ToMediumID() 56 } else { 57 target = id.ToShortID() 58 } 59 for _, b := range blocks { 60 if len(b) < len(target) { 61 continue 62 } 63 if b != target { 64 return WrongSigError{b} 65 } 66 // found match: 67 return nil 68 } 69 return NotFoundError{"Couldn't find signature ID " + target + " in text"} 70 } 71 72 func (t *BaseServiceType) BaseRecheckProofPosting(tryNumber int, status keybase1.ProofStatus) (warning *Markup, err error) { 73 warning = FmtMarkup("Couldn't find posted proof.") 74 return 75 } 76 77 func (t *BaseServiceType) BaseToServiceJSON(st ServiceType, un string) *jsonw.Wrapper { 78 ret := jsonw.NewDictionary() 79 _ = ret.SetKey("name", jsonw.NewString(st.GetTypeName())) 80 _ = ret.SetKey("username", jsonw.NewString(un)) 81 return ret 82 } 83 84 func (t *BaseServiceType) BaseGetProofType(st ServiceType) string { 85 return "web_service_binding." + st.GetTypeName() 86 } 87 88 func (t *BaseServiceType) LastWriterWins() bool { return true } 89 func (t *BaseServiceType) PreProofCheck(MetaContext, string) (*Markup, error) { return nil, nil } 90 func (t *BaseServiceType) PreProofWarning(remotename string) *Markup { return nil } 91 92 func (t *BaseServiceType) FormatProofText(m MetaContext, ppr *PostProofRes, 93 kbUsername, remoteUsername string, sigID keybase1.SigID) (string, error) { 94 return ppr.Text, nil 95 } 96 97 func (t *BaseServiceType) BaseCheckProofTextFull(text string, id keybase1.SigID, sig string) (err error) { 98 blocks := FindBase64Blocks(text) 99 target := FindFirstBase64Block(sig) 100 if len(target) == 0 { 101 err = BadSigError{"Generated sig was invalid"} 102 return 103 } 104 found := false 105 for _, b := range blocks { 106 if len(b) < 80 { 107 continue 108 } 109 if b != target { 110 err = WrongSigError{b} 111 return 112 } 113 found = true 114 } 115 if !found { 116 err = NotFoundError{"Couldn't find signature ID " + target + " in text"} 117 } 118 return 119 } 120 121 var urlRxx = regexp.MustCompile(`https://(\S+)`) 122 123 func (t *BaseServiceType) BaseCheckProofForURL(text string, id keybase1.SigID) (err error) { 124 target := id.ToMediumID() 125 urls := urlRxx.FindAllString(text, -1) 126 found := false 127 for _, u := range urls { 128 if strings.HasSuffix(u, target) { 129 found = true 130 } 131 } 132 if !found { 133 err = NotFoundError{"Didn't find a URL with suffix '" + target + "'"} 134 } 135 return 136 } 137 138 func (t *BaseServiceType) GetAPIArgKey() string { 139 return "remote_username" 140 } 141 142 func (t *BaseServiceType) IsDevelOnly() bool { return false } 143 144 func (t *BaseServiceType) GetLogoKey() string { 145 t.Lock() 146 defer t.Unlock() 147 if t.displayConf == nil { 148 return "" 149 } 150 if t.displayConf.LogoKey != "" { 151 return t.displayConf.LogoKey 152 } 153 return t.displayConf.Key 154 } 155 156 func (t *BaseServiceType) DisplayPriority() int { 157 t.Lock() 158 defer t.Unlock() 159 if t.displayConf == nil { 160 return 0 161 } 162 return t.displayConf.Priority 163 } 164 165 func (t *BaseServiceType) DisplayGroup() string { 166 t.Lock() 167 defer t.Unlock() 168 if t.displayConf == nil || t.displayConf.Group == nil { 169 return "" 170 } 171 return *t.displayConf.Group 172 } 173 174 func (t *BaseServiceType) CanMakeNewProofs(mctx MetaContext) bool { 175 return t.canMakeNewProofsHelper(mctx, false) 176 } 177 178 func (t *BaseServiceType) CanMakeNewProofsSkipFeatureFlag(mctx MetaContext) bool { 179 return t.canMakeNewProofsHelper(mctx, true) 180 } 181 182 func (t *BaseServiceType) canMakeNewProofsHelper(mctx MetaContext, skipFeatureFlag bool) bool { 183 t.Lock() 184 defer t.Unlock() 185 if mctx.G().GetEnv().GetProveBypass() { 186 return true 187 } 188 if t.displayConf == nil { 189 return true 190 } 191 if !skipFeatureFlag { 192 if mctx.G().FeatureFlags.Enabled(mctx, ExperimentalGenericProofs) { 193 return true 194 } 195 } 196 return !t.displayConf.CreationDisabled 197 } 198 199 func (t *BaseServiceType) IsNew(mctx MetaContext) bool { 200 if t.displayConf == nil { 201 return false 202 } 203 return t.displayConf.New 204 } 205 206 // ============================================================================= 207 208 type assertionContext struct { 209 mctx MetaContext 210 esc ExternalServicesCollector 211 } 212 213 func MakeAssertionContext(mctx MetaContext, s ExternalServicesCollector) AssertionContext { 214 return assertionContext{mctx: mctx, esc: s} 215 } 216 217 func (a assertionContext) Ctx() context.Context { return a.mctx.Ctx() } 218 219 func (a assertionContext) NormalizeSocialName(service string, username string) (string, error) { 220 st := a.esc.GetServiceType(a.Ctx(), service) 221 if st == nil { 222 return "", fmt.Errorf("Unknown social network: %s", service) 223 } 224 return st.NormalizeUsername(username) 225 }