github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/assertion_test.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  	"strings"
     9  	"testing"
    10  
    11  	"github.com/stretchr/testify/require"
    12  	"golang.org/x/net/context"
    13  )
    14  
    15  type testAssertionContext struct{}
    16  
    17  func (t testAssertionContext) Ctx() context.Context { return context.Background() }
    18  
    19  func (t testAssertionContext) NormalizeSocialName(service string, username string) (string, error) {
    20  	return strings.ToLower(username), nil
    21  }
    22  
    23  type testAlwaysFailAssertionContext struct{}
    24  
    25  const failAssertionContextErr = "Unknown social network BECAUSE IT'S A TEST"
    26  
    27  func (t testAlwaysFailAssertionContext) Ctx() context.Context { return context.Background() }
    28  
    29  func (t testAlwaysFailAssertionContext) NormalizeSocialName(service string, username string) (string, error) {
    30  	return "", fmt.Errorf("%s: %s", failAssertionContextErr, service)
    31  }
    32  
    33  func TestUsername(t *testing.T) {
    34  	a := "max"
    35  	expr, err := AssertionParse(testAssertionContext{}, a)
    36  	require.NoError(t, err)
    37  	require.IsType(t, AssertionKeybase{}, expr)
    38  	require.Equal(t, expr.String(), a)
    39  	proofset := NewProofSet([]Proof{
    40  		{"keybase", "max"},
    41  	})
    42  	require.True(t, expr.MatchSet(*proofset))
    43  }
    44  
    45  func TestUsernameMultiple(t *testing.T) {
    46  	a := "max,chris"
    47  	expr, err := AssertionParse(testAssertionContext{}, a)
    48  	require.NoError(t, err)
    49  
    50  	usernameSet := func(username string) ProofSet {
    51  		return *NewProofSet([]Proof{
    52  			{"keybase", username},
    53  		})
    54  	}
    55  	require.True(t, expr.MatchSet(usernameSet("max")))
    56  	require.True(t, expr.MatchSet(usernameSet("chris")))
    57  	require.False(t, expr.MatchSet(usernameSet("sam")))
    58  }
    59  
    60  func TestSuccess1(t *testing.T) {
    61  	a := "web://maxk.org && twitter://maxtaco"
    62  	expr, err := AssertionParse(testAssertionContext{}, a)
    63  	proofs := NewProofSet([]Proof{
    64  		{"http", "maxk.org"},
    65  		{"reddit", "maxtaco"},
    66  		{"twitter", "maxtaco"},
    67  	})
    68  	require.NoError(t, err)
    69  	require.True(t, expr.MatchSet(*proofs))
    70  }
    71  
    72  func TestAssertions1(t *testing.T) {
    73  	a := "web://maxk.org && (https://foo.com || http://bar.com) && (bb@twitter || max || pgp://aabbcc) && (keybear@octodon.social || gubble.social:keybear)"
    74  	goodProofsets := []ProofSet{
    75  		*NewProofSet([]Proof{
    76  			{"dns", "maxk.org"},
    77  			{"https", "bar.com"},
    78  			{"twitter", "bb"},
    79  			{"github", "xxx"},
    80  			{"keybase", "yyy"},
    81  			{"gubble.social", "keybear"},
    82  		}),
    83  		*NewProofSet([]Proof{
    84  			{"https", "maxk.org"},
    85  			{"https", "foo.com"},
    86  			{"keybase", "max"},
    87  			{"octodon.social", "keybear"},
    88  		}),
    89  		*NewProofSet([]Proof{
    90  			{"http", "maxk.org"},
    91  			{"https", "foo.com"},
    92  			{"pgp", "00aabbcc"},
    93  			{"gubble.social", "keybear"},
    94  		}),
    95  		*NewProofSet([]Proof{
    96  			{"http", "maxk.org"},
    97  			{"https", "foo.com"},
    98  			{"twitter", "bb"},
    99  			{"octodon.social", "keybear"},
   100  		}),
   101  		*NewProofSet([]Proof{
   102  			{"http", "maxk.org"},
   103  			{"http", "bar.com"},
   104  			{"twitter", "bb"},
   105  			{"octodon.social", "keybear"},
   106  		}),
   107  	}
   108  
   109  	badProofsets := []ProofSet{
   110  		*NewProofSet([]Proof{
   111  			{"dns", "max.org"},
   112  			{"http", "bar.com"},
   113  			{"twitter", "bb"},
   114  			{"github", "xxx"},
   115  			{"keybase", "yyy"},
   116  			{"gubble", "keybear"},
   117  		}),
   118  		*NewProofSet([]Proof{
   119  			{"https", "maxk.org"},
   120  			{"http", "foo.com"},
   121  			{"keybase", "maxi"},
   122  			{"gubble.social", "keybase"},
   123  		}),
   124  		*NewProofSet([]Proof{
   125  			{"http", "maxk.org"},
   126  			{"http", "foo.com"},
   127  			{"pgp", "00aabbcc"},
   128  			{"octodon.social", "keybase"},
   129  		}),
   130  		*NewProofSet([]Proof{
   131  			{"http", "maxk.org"},
   132  			{"https", "foo.com"},
   133  		}),
   134  		*NewProofSet([]Proof{
   135  			{"http", "maxk.org"},
   136  			{"https", "foo.com"},
   137  			{"pgp", "00aabbcce"},
   138  			{"pentagon.social", "keybear"},
   139  		}),
   140  		*NewProofSet([]Proof{
   141  			{"gubble.social", "keybear"},
   142  			{"octodon.social", "keybear"},
   143  		}),
   144  	}
   145  	expr, err := AssertionParse(testAssertionContext{}, a)
   146  	require.NoError(t, err)
   147  	for _, proofset := range goodProofsets {
   148  		require.True(t, expr.MatchSet(proofset))
   149  	}
   150  	for _, proofset := range badProofsets {
   151  		require.False(t, expr.MatchSet(proofset))
   152  	}
   153  }
   154  
   155  func TestAssertions2(t *testing.T) {
   156  	// Coyne-style grammar
   157  	a := "web:maxk.org+max,malgorithms+https:nutflex.com+pgp:aabbcc,samwise+dns:match.com"
   158  	goodProofsets := []ProofSet{
   159  		*NewProofSet([]Proof{
   160  			{"https", "maxk.org"},
   161  			{"keybase", "max"},
   162  		}),
   163  		*NewProofSet([]Proof{
   164  			{"https", "nutflex.com"},
   165  			{"pgp", "2233aabbcc"},
   166  			{"keybase", "malgorithms"},
   167  		}),
   168  		*NewProofSet([]Proof{
   169  			{"keybase", "samwise"},
   170  			{"dns", "match.com"},
   171  		}),
   172  	}
   173  	expr, err := AssertionParse(testAssertionContext{}, a)
   174  	require.NoError(t, err)
   175  	for _, proofset := range goodProofsets {
   176  		require.True(t, expr.MatchSet(proofset), "matching to %+v", proofset)
   177  	}
   178  }
   179  
   180  func TestAssertions3(t *testing.T) {
   181  	a := "t_bob+twitter:kbtester1"
   182  	goodProofsets := []ProofSet{
   183  		*NewProofSet([]Proof{
   184  			{"twitter", "kbtester1"},
   185  			{"keybase", "t_bob"},
   186  		}),
   187  	}
   188  	expr, err := AssertionParseAndOnly(testAssertionContext{}, a)
   189  	require.NoError(t, err)
   190  	for _, proofset := range goodProofsets {
   191  		require.True(t, expr.MatchSet(proofset))
   192  	}
   193  }
   194  
   195  func TestAssertions4(t *testing.T) {
   196  	// Coyne-style grammar (2), now with 100% more paramproof assertions
   197  	a := "alice@rooter+alice@cat.cafe+alice,https:nutflex.com+bob,jun@gubblers.eu+aabbcc@pgp"
   198  	goodProofsets := []ProofSet{
   199  		*NewProofSet([]Proof{
   200  			{"rooter", "alice"},
   201  			{"cat.cafe", "alice"},
   202  			{"keybase", "alice"},
   203  		}),
   204  		*NewProofSet([]Proof{
   205  			{"https", "nutflex.com"},
   206  			{"keybase", "bob"},
   207  		}),
   208  		*NewProofSet([]Proof{
   209  			{"gubblers.eu", "jun"},
   210  			{"pgp", "2233aabbcc"},
   211  		}),
   212  	}
   213  	badProofsets := []ProofSet{
   214  		*NewProofSet([]Proof{
   215  			{"cat.cafe", "alice"},
   216  		}),
   217  		*NewProofSet([]Proof{
   218  			{"keybase", "bob"},
   219  		}),
   220  		*NewProofSet([]Proof{
   221  			{"gubblers.eu", "jun"},
   222  			{"cat.cafe", "alice"}, // alice, no! your cat.cafe account got compromised!
   223  		}),
   224  	}
   225  	expr, err := AssertionParse(testAssertionContext{}, a)
   226  	require.NoError(t, err)
   227  	for _, proofset := range goodProofsets {
   228  		require.True(t, expr.MatchSet(proofset), "matching to %+v", proofset)
   229  	}
   230  	for _, proofset := range badProofsets {
   231  		require.False(t, expr.MatchSet(proofset), "matching to %+v", proofset)
   232  	}
   233  }
   234  
   235  func TestAssertionsUsernames(t *testing.T) {
   236  	exprs := []string{"x_", "A2", "ed", "bob", "o_o"}
   237  	fmts := []string{"%s", "%s@keybase", "keybase:%s"}
   238  	for _, str := range exprs {
   239  		for _, f := range fmts {
   240  			expr, err := AssertionParse(testAssertionContext{}, fmt.Sprintf(f, str))
   241  			require.NoError(t, err)
   242  			require.IsType(t, AssertionKeybase{}, expr)
   243  			require.Equal(t, strings.ToLower(str), expr.String())
   244  		}
   245  	}
   246  }
   247  
   248  func TestProofSetEmail(t *testing.T) {
   249  	exprs := []string{
   250  		"[m@keybasers.de]@email",
   251  		"email:[m@keybasers.de]",
   252  		"email://[m@keybasers.de]",
   253  	}
   254  	proofset := *NewProofSet([]Proof{
   255  		{"email", "m@keybasers.de"},
   256  	})
   257  	for _, expr := range exprs {
   258  		expr, err := AssertionParse(testAssertionContext{}, expr)
   259  		require.NoError(t, err)
   260  		require.Equal(t, "[m@keybasers.de]@email", expr.String())
   261  		require.True(t, expr.MatchSet(proofset), "when checking %q", expr)
   262  	}
   263  }
   264  
   265  func TestEmailAssertions(t *testing.T) {
   266  	exprs := []string{
   267  		"[m.a.x+2@kb.eu]@email",
   268  		"email:[h.e.l.l.o@kb.eu]",
   269  		"email://[test+spam@kb.eu]",
   270  		"email://[test+spam@kb.eu]+[other@example.com]@email",
   271  	}
   272  	for _, expr := range exprs {
   273  		_, err := AssertionParse(testAssertionContext{}, expr)
   274  		require.NoError(t, err)
   275  	}
   276  }
   277  
   278  func TestAssertionEmailsMultiple(t *testing.T) {
   279  	exprs := []string{
   280  		"[m@keybasers.de]@email,max",
   281  		"max,[m@keybasers.de]@email",
   282  		"email:[m@keybasers.de],max",
   283  		"max,email:[m@keybasers.de]",
   284  		"max,email://[m@keybasers.de]",
   285  		"(max||[max@keybase.io]@email),email://[m@keybasers.de]",
   286  	}
   287  	goodProofsets := []ProofSet{
   288  		*NewProofSet([]Proof{
   289  			{"email", "m@keybasers.de"},
   290  		}),
   291  		*NewProofSet([]Proof{
   292  			{"keybase", "max"},
   293  		}),
   294  		*NewProofSet([]Proof{
   295  			{"email", "m@keybasers.de"},
   296  			{"keybase", "m"},
   297  		}),
   298  	}
   299  	badProofsets := []ProofSet{
   300  		*NewProofSet([]Proof{
   301  			{"keybase", "m"},
   302  		}),
   303  		*NewProofSet([]Proof{
   304  			{"https", "keybase.io"},
   305  		}),
   306  		*NewProofSet([]Proof{
   307  			{"http", "keybase.io"},
   308  		}),
   309  	}
   310  	for _, expr := range exprs {
   311  		ret, err := AssertionParse(testAssertionContext{}, expr)
   312  		require.NoError(t, err, "when parsing %q", expr)
   313  		for _, proofset := range goodProofsets {
   314  			require.True(t, ret.MatchSet(proofset), "when checking %q with pset: %v", expr, proofset)
   315  		}
   316  		for _, proofset := range badProofsets {
   317  			require.False(t, ret.MatchSet(proofset), "when checking %q with pset: %v", expr, proofset)
   318  		}
   319  	}
   320  }
   321  
   322  func TestNeedsParens(t *testing.T) {
   323  	tests := []struct {
   324  		expr        string
   325  		needsParens bool
   326  	}{
   327  		{"max+foo@twitter,chris+chris@keybase", false},
   328  		{"max+foo@twitter+(chris,bob)", true},
   329  		{"max+foo@twitter+(chris)", false},
   330  		{"max+foo@twitter+((chris))", false},
   331  		{"max+foo@twitter+(chris+sam)", false},
   332  		{"max", false},
   333  	}
   334  
   335  	for _, test := range tests {
   336  		expr, err := AssertionParse(testAssertionContext{}, test.expr)
   337  		require.NoError(t, err)
   338  		require.Equal(t, expr.NeedsParens(), test.needsParens)
   339  	}
   340  }
   341  
   342  func TestAssertionCtxFailures(t *testing.T) {
   343  	a := "michal@twitter,mark@zapu.net"
   344  	_, err := AssertionParse(testAlwaysFailAssertionContext{}, a)
   345  	require.Error(t, err)
   346  	require.Contains(t, err.Error(), failAssertionContextErr)
   347  	require.Contains(t, err.Error(), "zapu.net")
   348  }