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  }