github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/pvl/helpers_test.go (about) 1 // Copyright 2016 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package pvl 5 6 import ( 7 b64 "encoding/base64" 8 "log" 9 "strings" 10 "testing" 11 12 "github.com/PuerkitoBio/goquery" 13 keybase1 "github.com/keybase/client/go/protocol/keybase1" 14 ) 15 16 func check(err error) { 17 if err != nil { 18 log.Panicf("checked err: %v", err) 19 } 20 } 21 22 func sampleState() scriptState { 23 sigBody := []byte{1, 2, 3, 4, 5} 24 25 var sampleState = scriptState{ 26 WhichScript: 0, 27 PC: 0, 28 Service: keybase1.ProofType_TWITTER, 29 Regs: *newNamedRegsStore(), 30 Sig: sigBody, 31 HasFetched: false, 32 FetchResult: nil, 33 } 34 35 check(sampleState.Regs.Set("username_service", "kronk")) 36 check(sampleState.Regs.Set("username_keybase", "kronk_on_kb")) 37 check(sampleState.Regs.Set("sig", b64.StdEncoding.EncodeToString(sigBody))) 38 check(sampleState.Regs.Set("sig_id_medium", "sig%{sig_id_medium}.*$(^)\\/")) 39 check(sampleState.Regs.Set("sig_id_short", "000")) 40 check(sampleState.Regs.Set("hostname", "%{sig_id_medium}")) 41 check(sampleState.Regs.Set("protocol", "http")) 42 check(sampleState.Regs.Ban("banned")) 43 check(sampleState.Regs.Set("restuff", "[(x)]")) 44 45 return sampleState 46 } 47 48 type serviceToStringTest struct { 49 service keybase1.ProofType 50 name string 51 shouldwork bool 52 status keybase1.ProofStatus 53 } 54 55 var serviceToStringTests = []serviceToStringTest{ 56 {keybase1.ProofType_DNS, "dns", true, keybase1.ProofStatus_NONE}, 57 {keybase1.ProofType_GENERIC_WEB_SITE, "generic_web_site", true, 0}, 58 {keybase1.ProofType(-12), "", false, keybase1.ProofStatus_INVALID_PVL}, 59 } 60 61 func TestServiceToString(t *testing.T) { 62 for i, test := range serviceToStringTests { 63 name, err := serviceToString(test.service) 64 switch { 65 case (err == nil) != test.shouldwork: 66 t.Fatalf("%v err %v", i, err) 67 case !test.shouldwork && (err.GetProofStatus() != test.status): 68 t.Fatalf("%v status %v", i, err.GetProofStatus()) 69 case test.name != name: 70 t.Fatalf("%v name %v %v", i, test.name, name) 71 } 72 } 73 } 74 75 var substituteTests = []struct { 76 shouldwork bool 77 regexEscape bool 78 service keybase1.ProofType 79 a, b string 80 }{ 81 {true, true, keybase1.ProofType_TWITTER, 82 "%{username_service}", "kronk"}, 83 {true, true, keybase1.ProofType_GENERIC_WEB_SITE, 84 "%{hostname}", "%\\{sig_id_medium\\}"}, 85 {true, true, keybase1.ProofType_TWITTER, 86 "x%{username_service}y%{sig_id_short}z", "xkronky000z"}, 87 {true, true, keybase1.ProofType_TWITTER, 88 "http://git(?:hub)?%{username_service}/%20%%{sig_id_short}}{}", "http://git(?:hub)?kronk/%20%000}{}"}, 89 {true, true, keybase1.ProofType_DNS, 90 "^%{hostname}/(?:.well-known/keybase.txt|keybase.txt)$", "^%\\{sig_id_medium\\}/(?:.well-known/keybase.txt|keybase.txt)$"}, 91 {true, true, keybase1.ProofType_TWITTER, 92 "^.*%{sig_id_short}.*$", "^.*000.*$"}, 93 {true, true, keybase1.ProofType_TWITTER, 94 "^keybase-site-verification=%{sig_id_short}$", "^keybase-site-verification=000$"}, 95 {true, true, keybase1.ProofType_TWITTER, 96 "^%{sig_id_medium}$", "^sig%\\{sig_id_medium\\}\\.\\*\\$\\(\\^\\)\\\\/$"}, 97 {true, true, keybase1.ProofType_TWITTER, 98 "%{username_keybase}:%{sig}", "kronk_on_kb:AQIDBAU="}, 99 100 {false, true, keybase1.ProofType_TWITTER, 101 "%{}", "%{}"}, 102 {false, true, keybase1.ProofType_TWITTER, 103 "%{unset}", ""}, 104 105 {false, true, keybase1.ProofType_TWITTER, 106 "%{banned}", ""}, 107 108 // regex escape 109 {true, true, keybase1.ProofType_TWITTER, 110 "%{restuff}", "\\[\\(x\\)\\]"}, 111 {true, false, keybase1.ProofType_TWITTER, 112 "%{restuff}", "[(x)]"}, 113 } 114 115 func TestSubstitute(t *testing.T) { 116 for i, test := range substituteTests { 117 state := sampleState() 118 state.Service = test.service 119 var res string 120 var err error 121 if test.regexEscape { 122 res, err = substituteReEscape(test.a, state) 123 } else { 124 res, err = substituteExact(test.a, state) 125 } 126 if (err == nil) != test.shouldwork { 127 t.Fatalf("%v error mismatch: %v ; %v ; '%v'", i, test.shouldwork, err, res) 128 } 129 if err == nil && res != test.b { 130 t.Logf("%v lens: %v %v", i, len(res), len(test.b)) 131 t.Fatalf("%v wrong substitute result\n%v\n%v\n%v", 132 i, test.a, res, test.b) 133 } 134 } 135 } 136 137 var selectionContentsDocument = makeHTMLDangerous(` 138 <html> 139 <head></head><div>a<span class="x" data-foo="y">b</span></div><div data-foo="z">c</div> 140 <p>hea<!--vy han-->ded</p> 141 </html> 142 `) 143 144 type selectionContentsTest struct { 145 html *goquery.Document 146 selector string 147 contents bool 148 attr string 149 data bool 150 out string 151 } 152 153 var selectionContentsTests = []selectionContentsTest{ 154 {selectionContentsDocument, "div", false, "", false, "ab c"}, 155 {selectionContentsDocument, "span", false, "", false, "b"}, 156 {selectionContentsDocument, "span", false, "data-foo", false, "y"}, 157 {selectionContentsDocument, "div", false, "data-foo", false, "z"}, 158 {selectionContentsDocument, "span", false, "data-bar", false, ""}, 159 {selectionContentsDocument, "div", false, "data-baz", false, ""}, 160 {selectionContentsDocument, "p", false, "", false, "headed"}, 161 {selectionContentsDocument, "p", true, "", true, "hea vy han ded"}, 162 } 163 164 func TestSelectionContents(t *testing.T) { 165 for i, test := range selectionContentsTests { 166 sel := test.html.Find(test.selector) 167 if test.contents { 168 sel = sel.Contents() 169 } 170 var out string 171 switch { 172 case test.attr != "": 173 out = selectionAttr(sel, test.attr) 174 case test.data: 175 out = selectionData(sel) 176 default: 177 out = selectionText(sel) 178 } 179 if out != test.out { 180 t.Fatalf("%v mismatch\n'%v'\n'%v'", i, out, test.out) 181 } 182 } 183 } 184 185 func TestValidateDomain(t *testing.T) { 186 tests := []struct { 187 s string 188 ok bool 189 }{ 190 // allow domains 191 {"example.com", true}, 192 {"www.example.com", true}, 193 {"com.", true}, 194 {"0x0f.example.com", true}, 195 196 // disallow ports, paths, protocols, and other junk 197 {"example.com:8080", false}, 198 {"www.example.com:8080", false}, 199 {"http://example.com", false}, 200 {"example.com/", false}, 201 {"example.com/123", false}, 202 {"example.com?a=b", false}, 203 {"example.com#2", false}, 204 {"http://http://", false}, 205 {"http://http://example.com", false}, 206 {"http://http:/example.com", false}, 207 {"http://ht$%$&$tp:/example.com", false}, 208 209 // disallow ips, even when weirdly formatted 210 {"8.8.8.8", false}, 211 {"8.8.8.8.", false}, 212 {"8.8.8.00008", false}, 213 {"8.8.8.", false}, 214 {"8.8.8.8/24", false}, 215 {"8.8.8/24", false}, 216 {"8.", false}, 217 {"8", false}, 218 {"8.8.8", false}, 219 {"2001:db8:a0b:12f0::1", false}, 220 {"::21", false}, 221 {":21:", false}, 222 {":21:", false}, 223 {"2001:db8:a0b:12f0::1%eth0", false}, 224 {"[2001:db8:a0b:12f0::1]:21", false}, 225 } 226 227 for i, test := range tests { 228 ans := validateDomain(test.s) 229 if ans != test.ok { 230 t.Fatalf("%v mismatch: %v\ngot : %v\nexpected : %v\n", i, test.s, ans, test.ok) 231 } 232 } 233 } 234 235 func TestValidateProtocol(t *testing.T) { 236 tests := []struct { 237 s string 238 allowed []string 239 expected string 240 ok bool 241 }{ 242 {"http", []string{"http", "https"}, "http", true}, 243 {"http:", []string{"http", "https"}, "http", true}, 244 {"https:", []string{"http", "https"}, "https", true}, 245 246 {"http", []string{"https"}, "http", false}, 247 {"dns", []string{"http", "https"}, "dns", false}, 248 249 {"spdy", []string{"http", "https"}, "", false}, 250 } 251 252 for i, test := range tests { 253 a, b := validateProtocol(test.s, test.allowed) 254 if !(a == test.expected && b == test.ok) { 255 t.Fatalf("%v mismatch: %v\ngot : %v %v\nexpected : %v %v\n", 256 i, test.s, test.expected, test.ok, a, b) 257 } 258 } 259 } 260 261 // Test helpers 262 263 func makeHTMLDangerous(html string) *goquery.Document { 264 reader := strings.NewReader(html) 265 d, err := goquery.NewDocumentFromReader(reader) 266 if err != nil { 267 log.Panic(err) 268 } 269 return d 270 }