request.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. package fp
  2. import (
  3. "bytes"
  4. "fmt"
  5. "sort"
  6. "strconv"
  7. "strings"
  8. )
  9. // Client request signature and fingerprint strings have the format
  10. // <version>:<cipher>:<extension>:<curve>:<ecpointfmt>:<header>:<quirk>
  11. //
  12. // For fingerprints the parts have the formats
  13. // <version>:
  14. // <vers>
  15. // <cipher>, <extension>, <curve>, <ecpointfmt>:
  16. // <int-list>
  17. // <header>, <quirk>:
  18. // <str-list>
  19. // where <vers> is a TLS version ('', '2.0', '3.0', '3.1', '3.2', '3.3', '3.4')
  20. // <int-list> is a comma-separated list of hex-encoded ints, and <str-list> is
  21. // a comma-separated list of strings.
  22. //
  23. // and for signatures the parts have the formats
  24. // <version>:
  25. // [<exp>|<min>,<exp>,<max>]
  26. // <cipher>, <extension>, <curve>, <ecpointfmt>:
  27. // [*~][<[!?+]int-list>]
  28. // <header>, <quirk>:
  29. // [*~][<[!?+]str-list>]
  30. // where items in enclosed in square brackets are optional,
  31. // <exp> is the expected TLS version, <min> is the minimum TLS version, <max> is the maximum TLS version,
  32. // '*' and '~' are optional list prefixes, and '!' and '?' are optional list element prefixes.
  33. //
  34. // A list prefix can be one of the following options:
  35. // '*' means to allow extra items and any ordering of items
  36. // '~' means to allow any ordering of items
  37. // '' means to enforce ordering of items (default)
  38. //
  39. // An item prefix can be one of the following options:
  40. // '!' means the item is possible, but not expected (unlikely)
  41. // '?' means the item is expected, but not required (optional)
  42. // '^' means the item is excluded, and not possible (excluded)
  43. // '' means the item is required (default)
  44. const (
  45. requestFieldCount int = 7
  46. requestFieldSep string = ":"
  47. fieldElemSep string = ","
  48. )
  49. const (
  50. flagAnyItems byte = '*'
  51. flagAnyOrder byte = '~'
  52. flagUnlikely byte = '!'
  53. flagOptional byte = '?'
  54. flagExcluded byte = '^'
  55. )
  56. // A RequestFingerprint represents the features of a client request, including client
  57. // hello features, http headers, and any additional quirks.
  58. type RequestFingerprint struct {
  59. Version Version
  60. Cipher IntList
  61. Extension IntList
  62. Curve IntList
  63. EcPointFmt IntList
  64. Header StringList
  65. Quirk StringList
  66. }
  67. // NewRequestFingerprint is a wrapper around RequestFingerprint.Parse
  68. func NewRequestFingerprint(s string) (RequestFingerprint, error) {
  69. var a RequestFingerprint
  70. err := a.Parse(s)
  71. return a, err
  72. }
  73. // Parse a fingerprint from a string and return an error on failure.
  74. func (a *RequestFingerprint) Parse(s string) error {
  75. fields := strings.Split(s, requestFieldSep)
  76. if len(fields) != requestFieldCount {
  77. return fmt.Errorf("bad request field count '%s': exp %d, got %d", s, requestFieldCount, len(fields))
  78. }
  79. fieldIdx := 0
  80. if err := a.Version.Parse(fields[fieldIdx]); err != nil {
  81. return err
  82. }
  83. fieldIdx++
  84. if err := a.Cipher.Parse(fields[fieldIdx]); err != nil {
  85. return err
  86. }
  87. fieldIdx++
  88. if err := a.Extension.Parse(fields[fieldIdx]); err != nil {
  89. return err
  90. }
  91. fieldIdx++
  92. if err := a.Curve.Parse(fields[fieldIdx]); err != nil {
  93. return err
  94. }
  95. fieldIdx++
  96. if err := a.EcPointFmt.Parse(fields[fieldIdx]); err != nil {
  97. return err
  98. }
  99. fieldIdx++
  100. if err := a.Header.Parse(fields[fieldIdx]); err != nil {
  101. return err
  102. }
  103. fieldIdx++
  104. if err := a.Quirk.Parse(fields[fieldIdx]); err != nil {
  105. return err
  106. }
  107. return nil
  108. }
  109. // String returns a string representation of the fingerprint.
  110. func (a RequestFingerprint) String() string {
  111. return strings.Join([]string{
  112. a.Version.String(),
  113. a.Cipher.String(),
  114. a.Extension.String(),
  115. a.Curve.String(),
  116. a.EcPointFmt.String(),
  117. a.Header.String(),
  118. a.Quirk.String(),
  119. }, requestFieldSep)
  120. }
  121. // A RequestSignature represents a set of client request fingerprints. Many TLS/HTTPS
  122. // implementations can be uniquely identified by their signatures.
  123. type RequestSignature struct {
  124. Version VersionSignature
  125. Cipher IntSignature
  126. Extension IntSignature
  127. Curve IntSignature
  128. EcPointFmt IntSignature
  129. Header StringSignature
  130. Quirk StringSignature
  131. // non-exported fields
  132. pfs bool
  133. pfsCached bool
  134. grade Grade
  135. gradeCached bool
  136. }
  137. // A VersionSignature is a signature for a TLS version.
  138. type VersionSignature struct {
  139. Min Version
  140. Exp Version
  141. Max Version
  142. }
  143. // An IntSignature is a signature on a list of integers.
  144. type IntSignature struct {
  145. OrderedList IntList
  146. RequiredSet *IntSet
  147. OptionalSet *IntSet
  148. UnlikelySet *IntSet
  149. ExcludedSet *IntSet
  150. }
  151. // A StringSignature is a signature on a list of strings.
  152. type StringSignature struct {
  153. OrderedList StringList
  154. RequiredSet StringSet
  155. OptionalSet StringSet
  156. UnlikelySet StringSet
  157. ExcludedSet StringSet
  158. }
  159. // NewRequestSignature is a wrapper around RequestSignature.Parse
  160. func NewRequestSignature(s string) (RequestSignature, error) {
  161. var a RequestSignature
  162. err := a.Parse(s)
  163. return a, err
  164. }
  165. // Parse a signature from a string and return an error on failure.
  166. func (a *RequestSignature) Parse(s string) error {
  167. fields := strings.Split(s, requestFieldSep)
  168. if len(fields) != requestFieldCount {
  169. return fmt.Errorf("bad request field count '%s': exp %d, got %d", s, requestFieldCount, len(fields))
  170. }
  171. fieldIdx := 0
  172. if err := a.Version.Parse(fields[fieldIdx]); err != nil {
  173. return err
  174. }
  175. fieldIdx++
  176. if err := a.Cipher.Parse(fields[fieldIdx]); err != nil {
  177. return err
  178. }
  179. fieldIdx++
  180. if err := a.Extension.Parse(fields[fieldIdx]); err != nil {
  181. return err
  182. }
  183. fieldIdx++
  184. if err := a.Curve.Parse(fields[fieldIdx]); err != nil {
  185. return err
  186. }
  187. fieldIdx++
  188. if err := a.EcPointFmt.Parse(fields[fieldIdx]); err != nil {
  189. return err
  190. }
  191. fieldIdx++
  192. if err := a.Header.Parse(fields[fieldIdx]); err != nil {
  193. return err
  194. }
  195. fieldIdx++
  196. if err := a.Quirk.Parse(fields[fieldIdx]); err != nil {
  197. return err
  198. }
  199. return nil
  200. }
  201. // Grade returns the security grade for the request signature.
  202. func (a *RequestSignature) Grade() Grade {
  203. if !a.gradeCached {
  204. a.grade = GlobalCipherCheck.Grade(a.Cipher.OrderedList)
  205. a.gradeCached = true
  206. }
  207. return a.grade
  208. }
  209. // IsPfs returns true if the request signature has perfect forward secrecy.
  210. func (a *RequestSignature) IsPfs() bool {
  211. if !a.pfsCached {
  212. a.pfs = GlobalCipherCheck.IsFirstPfs(a.Cipher.OrderedList)
  213. a.pfsCached = true
  214. }
  215. return a.pfs
  216. }
  217. // Parse a version signature from a string and return an error on failure.
  218. func (a *VersionSignature) Parse(s string) error {
  219. a.Min, a.Exp, a.Max = VersionEmpty, VersionEmpty, VersionEmpty
  220. if len(s) == 0 {
  221. return nil
  222. }
  223. fields := strings.Split(s, fieldElemSep)
  224. var err error
  225. switch len(fields) {
  226. case 1:
  227. if err = a.Min.Parse(fields[0]); err != nil {
  228. return err
  229. }
  230. a.Exp = a.Min
  231. a.Max = a.Min
  232. case 3:
  233. if err = a.Min.Parse(fields[0]); err != nil {
  234. return err
  235. }
  236. if err = a.Exp.Parse(fields[1]); err != nil {
  237. return err
  238. }
  239. if err = a.Max.Parse(fields[2]); err != nil {
  240. return err
  241. }
  242. default:
  243. return fmt.Errorf("invalid version format: '%s'", s)
  244. }
  245. // sanity check
  246. if a.Min != VersionEmpty {
  247. if a.Exp != VersionEmpty && a.Min > a.Exp {
  248. return fmt.Errorf("version: Min > Exp")
  249. }
  250. if a.Max != VersionEmpty && a.Min > a.Max {
  251. return fmt.Errorf("version: Min > Max")
  252. }
  253. }
  254. if a.Exp != VersionEmpty {
  255. if a.Max != VersionEmpty && a.Exp > a.Max {
  256. return fmt.Errorf("version: Exp > Max")
  257. }
  258. }
  259. return nil
  260. }
  261. // NewVersionSignature returns a new int signature parsed from a string.
  262. func NewVersionSignature(s string) (VersionSignature, error) {
  263. var a VersionSignature
  264. err := a.Parse(s)
  265. return a, err
  266. }
  267. // NewIntSignature returns a new int signature parsed from a string.
  268. func NewIntSignature(s string) (IntSignature, error) {
  269. var a IntSignature
  270. err := a.Parse(s)
  271. return a, err
  272. }
  273. // NewStringSignature returns a new string signature parsed from a string.
  274. func NewStringSignature(s string) (StringSignature, error) {
  275. var a StringSignature
  276. err := a.Parse(s)
  277. return a, err
  278. }
  279. // Parse an int signature from a string and return an error on failure.
  280. func (a *IntSignature) Parse(s string) error {
  281. a.OrderedList = IntList{}
  282. a.ExcludedSet = new(IntSet)
  283. a.UnlikelySet = new(IntSet)
  284. a.OptionalSet = new(IntSet)
  285. a.RequiredSet = new(IntSet)
  286. if len(s) == 0 {
  287. return nil
  288. }
  289. anyItems, anyOrder := false, false
  290. switch s[0] {
  291. case flagAnyItems:
  292. anyItems = true
  293. s = s[1:]
  294. case flagAnyOrder:
  295. anyOrder = true
  296. s = s[1:]
  297. }
  298. var split []string
  299. if len(s) > 0 {
  300. split = strings.Split(s, fieldElemSep)
  301. }
  302. for _, v := range split {
  303. if len(v) == 0 {
  304. return fmt.Errorf("invalid int signature format: '%s'", s)
  305. }
  306. flag := v[0]
  307. switch flag {
  308. case flagOptional, flagUnlikely, flagExcluded:
  309. v = v[1:]
  310. }
  311. elem64bit, err := strconv.ParseUint(v, 16, 16)
  312. elem := int(elem64bit)
  313. if err != nil {
  314. return err
  315. }
  316. switch flag {
  317. case flagOptional:
  318. a.OptionalSet.Insert(elem)
  319. case flagUnlikely:
  320. a.UnlikelySet.Insert(elem)
  321. case flagExcluded:
  322. a.ExcludedSet.Insert(elem)
  323. continue // do not add to ordered list
  324. default:
  325. a.RequiredSet.Insert(elem)
  326. }
  327. a.OrderedList = append(a.OrderedList, elem)
  328. }
  329. if anyItems {
  330. // allow any order and any optional items
  331. // still check for required, unlikely, and excluded items
  332. a.OrderedList = nil
  333. a.OptionalSet.Clear()
  334. }
  335. if anyOrder {
  336. // allow any order
  337. a.OrderedList = nil
  338. }
  339. return nil
  340. }
  341. // Parse a string signature from a string and return an error on failure.
  342. func (a *StringSignature) Parse(s string) error {
  343. a.OrderedList = StringList{}
  344. a.UnlikelySet = make(StringSet)
  345. a.OptionalSet = make(StringSet)
  346. a.ExcludedSet = make(StringSet)
  347. a.RequiredSet = make(StringSet)
  348. if len(s) == 0 {
  349. return nil
  350. }
  351. anyItems, anyOrder := false, false
  352. switch s[0] {
  353. case flagAnyItems:
  354. anyItems = true
  355. s = s[1:]
  356. case flagAnyOrder:
  357. anyOrder = true
  358. s = s[1:]
  359. }
  360. var split []string
  361. if len(s) > 0 {
  362. split = strings.Split(s, fieldElemSep)
  363. }
  364. for _, v := range split {
  365. if len(v) == 0 {
  366. return fmt.Errorf("invalid int signature format: '%s'", s)
  367. }
  368. flag := v[0]
  369. switch flag {
  370. case flagOptional, flagUnlikely, flagExcluded:
  371. v = v[1:]
  372. }
  373. switch flag {
  374. case flagOptional:
  375. a.OptionalSet[v] = true
  376. case flagUnlikely:
  377. a.UnlikelySet[v] = true
  378. case flagExcluded:
  379. a.ExcludedSet[v] = true
  380. continue // do not add to ordered list
  381. default:
  382. a.RequiredSet[v] = true
  383. }
  384. a.OrderedList = append(a.OrderedList, v)
  385. }
  386. if anyItems {
  387. // allow any order and any optional items
  388. // still check for required, unlikely, and excluded items
  389. a.OrderedList = nil
  390. a.OptionalSet = nil
  391. }
  392. if anyOrder {
  393. // allow any order
  394. a.OrderedList = nil
  395. }
  396. return nil
  397. }
  398. // Returns a string representation of the signature.
  399. func (a RequestSignature) String() string {
  400. return strings.Join([]string{
  401. a.Version.String(),
  402. a.Cipher.String(),
  403. a.Extension.String(),
  404. a.Curve.String(),
  405. a.EcPointFmt.String(),
  406. a.Header.String(),
  407. a.Quirk.String(),
  408. }, requestFieldSep)
  409. }
  410. // Return a string representation of the version signature.
  411. func (a VersionSignature) String() string {
  412. if a.Min == a.Exp && a.Max == a.Exp {
  413. return a.Exp.String()
  414. }
  415. return strings.Join([]string{
  416. a.Exp.String(),
  417. a.Min.String(),
  418. a.Max.String(),
  419. }, fieldElemSep)
  420. }
  421. // String returns a string representation of the int signature.
  422. func (a IntSignature) String() string {
  423. var buf bytes.Buffer
  424. var list IntList
  425. if a.OrderedList != nil {
  426. // element ordering is strict
  427. list = a.OrderedList
  428. } else {
  429. if a.RequiredSet.IsEmpty() {
  430. buf.WriteByte(flagAnyItems)
  431. } else {
  432. buf.WriteByte(flagAnyOrder)
  433. }
  434. list = append(list, a.RequiredSet.List()...)
  435. list = append(list, a.OptionalSet.List()...)
  436. list = append(list, a.UnlikelySet.List()...)
  437. }
  438. list = append(list, a.ExcludedSet.List()...)
  439. if a.OrderedList == nil {
  440. sort.Slice(list, func(a, b int) bool { return list[a] < list[b] })
  441. }
  442. for idx, elem := range list {
  443. if idx != 0 {
  444. buf.WriteString(fieldElemSep)
  445. }
  446. switch {
  447. case a.OptionalSet.Has(elem):
  448. buf.WriteByte(flagOptional)
  449. case a.UnlikelySet.Has(elem):
  450. buf.WriteByte(flagUnlikely)
  451. case a.ExcludedSet.Has(elem):
  452. buf.WriteByte(flagExcluded)
  453. }
  454. buf.WriteString(fmt.Sprintf("%x", elem))
  455. }
  456. return buf.String()
  457. }
  458. // String returns a string representation of the string signature.
  459. func (a StringSignature) String() string {
  460. var buf bytes.Buffer
  461. var list StringList
  462. if a.OrderedList != nil {
  463. // element ordering is strict
  464. list = a.OrderedList
  465. } else {
  466. if a.OptionalSet == nil {
  467. buf.WriteByte(flagAnyItems)
  468. } else {
  469. buf.WriteByte(flagAnyOrder)
  470. }
  471. list = append(list, a.RequiredSet.List()...)
  472. list = append(list, a.OptionalSet.List()...)
  473. list = append(list, a.UnlikelySet.List()...)
  474. }
  475. list = append(list, a.ExcludedSet.List()...)
  476. if a.OrderedList == nil {
  477. sort.Slice(list, func(a, b int) bool { return list[a] < list[b] })
  478. }
  479. for idx, elem := range list {
  480. if idx != 0 {
  481. buf.WriteString(fieldElemSep)
  482. }
  483. switch {
  484. case a.OptionalSet[elem]:
  485. buf.WriteByte(flagOptional)
  486. case a.UnlikelySet[elem]:
  487. buf.WriteByte(flagUnlikely)
  488. case a.ExcludedSet[elem]:
  489. buf.WriteByte(flagExcluded)
  490. }
  491. buf.WriteString(elem)
  492. }
  493. return buf.String()
  494. }
  495. // Merge signatures a and b to match fingerprints from both.
  496. func (a RequestSignature) Merge(b RequestSignature) (merged RequestSignature) {
  497. merged.Version = a.Version.Merge(b.Version)
  498. merged.Cipher = a.Cipher.Merge(b.Cipher)
  499. merged.Extension = a.Extension.Merge(b.Extension)
  500. merged.Curve = a.Curve.Merge(b.Curve)
  501. merged.EcPointFmt = a.EcPointFmt.Merge(b.EcPointFmt)
  502. merged.Header = a.Header.Merge(b.Header)
  503. merged.Quirk = a.Quirk.Merge(b.Quirk)
  504. merged.pfsCached = false
  505. merged.gradeCached = false
  506. return
  507. }
  508. // Merge version signatures a and b to match fingerprints from both.
  509. func (a VersionSignature) Merge(b VersionSignature) (merged VersionSignature) {
  510. merged = a
  511. if a.Exp != VersionEmpty {
  512. if b.Exp == VersionEmpty || b.Exp < a.Exp {
  513. merged.Exp = b.Exp
  514. }
  515. }
  516. if a.Min != VersionEmpty {
  517. if b.Min == VersionEmpty || b.Min < a.Min {
  518. merged.Min = b.Min
  519. }
  520. }
  521. if a.Max != VersionEmpty {
  522. if b.Max == VersionEmpty || b.Max > a.Max {
  523. merged.Max = b.Max
  524. }
  525. }
  526. return
  527. }
  528. // Merge int signatures a and b to match fingerprints from both.
  529. func (a IntSignature) Merge(b IntSignature) (merged IntSignature) {
  530. // Merge lists according to the following rules:
  531. // 1) The merged list should not have any duplicate elements.
  532. // 2) The order of elements in a and b must remain the same.
  533. // 3) If there exists elements e1, e2 that appear in different orders
  534. // in a and b, the merged list should be nil (accept any ordering).
  535. merged = IntSignature{
  536. IntList{},
  537. new(IntSet),
  538. new(IntSet),
  539. new(IntSet),
  540. new(IntSet),
  541. }
  542. anyOrder := false
  543. if a.OrderedList == nil || b.OrderedList == nil {
  544. anyOrder = true
  545. } else {
  546. var mergedSet IntSet
  547. var bSet IntSet
  548. bSet.Copy(b.RequiredSet.Union(b.OptionalSet).Union(b.UnlikelySet))
  549. bIdx := 0
  550. bLen := len(b.OrderedList)
  551. for _, elem := range a.OrderedList {
  552. // check if elem is already merged
  553. if mergedSet.Has(elem) {
  554. // elem is already merged, so abort and accept any ordering
  555. anyOrder = true
  556. break
  557. }
  558. // check if b contains elem
  559. if bSet.Has(elem) {
  560. // add all elems of b up to elem
  561. for ; bIdx < bLen && b.OrderedList[bIdx] != elem; bIdx++ {
  562. merged.OrderedList = append(merged.OrderedList, b.OrderedList[bIdx])
  563. mergedSet.Insert(b.OrderedList[bIdx])
  564. }
  565. // skip past elem since it is added below
  566. bIdx++
  567. }
  568. // add elem to merged list and set
  569. merged.OrderedList = append(merged.OrderedList, elem)
  570. mergedSet.Insert(elem)
  571. }
  572. // add remaining elems of b to merged list
  573. merged.OrderedList = append(merged.OrderedList, b.OrderedList[bIdx:bLen]...)
  574. }
  575. // Clear ordered list if any ordering is accepted
  576. if anyOrder {
  577. merged.OrderedList = nil
  578. }
  579. // Take intersection of required elems
  580. if !a.RequiredSet.IsEmpty()|| !b.RequiredSet.IsEmpty() {
  581. merged.RequiredSet.Copy(a.RequiredSet.Inter(b.RequiredSet))
  582. }
  583. // Take intersection of excluded elems
  584. if !a.ExcludedSet.IsEmpty() || !b.ExcludedSet.IsEmpty() {
  585. merged.ExcludedSet.Copy(a.ExcludedSet.Inter(b.ExcludedSet))
  586. }
  587. // If intersection of a and b's RequiredSets is not empty (=> wildcard), then take union of optional elems
  588. if !a.RequiredSet.IsEmpty() && !b.RequiredSet.IsEmpty() {
  589. merged.OptionalSet.Copy(a.OptionalSet.Union(b.OptionalSet).Union(a.RequiredSet).Union(b.RequiredSet).Diff(merged.RequiredSet))
  590. }
  591. // If intersection of optional sets is not empty, then let the unmerged optional variables be considered unlikely
  592. // variables.
  593. if !a.OptionalSet.IsEmpty() && !b.OptionalSet.IsEmpty() {
  594. merged.UnlikelySet.Copy(a.UnlikelySet.Union(b.UnlikelySet).Union(a.OptionalSet).Union(b.OptionalSet).Diff(merged.OptionalSet))
  595. }
  596. return
  597. }
  598. // Merge string signatures a and b to match fingerprints from both.
  599. func (a StringSignature) Merge(b StringSignature) (merged StringSignature) {
  600. // Merge lists according to the following rules:
  601. // 1) The merged list should not have any duplicate elements.
  602. // 2) The order of elements in a and b must remain the same.
  603. // 3) If there exists elements e1, e2 that appear in different orders
  604. // in a and b, the merged list should be nil (accept any ordering).
  605. anyOrder := false
  606. if a.OrderedList == nil || b.OrderedList == nil {
  607. anyOrder = true
  608. } else {
  609. mergedSet := make(StringSet)
  610. merged.OrderedList = StringList{}
  611. bSet := b.RequiredSet.Union(b.OptionalSet).Union(b.UnlikelySet)
  612. bIdx := 0
  613. bLen := len(b.OrderedList)
  614. for _, elem := range a.OrderedList {
  615. // check if elem is already merged
  616. if mergedSet[elem] {
  617. // elem is already merged, so abort and accept any ordering
  618. anyOrder = true
  619. break
  620. }
  621. // check if b contains elem
  622. if bSet[elem] {
  623. // add all elems of b up to elem
  624. for ; bIdx < bLen && b.OrderedList[bIdx] != elem; bIdx++ {
  625. merged.OrderedList = append(merged.OrderedList, b.OrderedList[bIdx])
  626. mergedSet[b.OrderedList[bIdx]] = true
  627. }
  628. // skip past elem since it is added below
  629. bIdx++
  630. }
  631. // add elem to merged list/set
  632. merged.OrderedList = append(merged.OrderedList, elem)
  633. mergedSet[elem] = true
  634. }
  635. // add remaining elems of b to merged list
  636. merged.OrderedList = append(merged.OrderedList, b.OrderedList[bIdx:bLen]...)
  637. }
  638. // Clear ordered list if any ordering is accepted
  639. if anyOrder {
  640. merged.OrderedList = nil
  641. }
  642. // Take intersection of required elems
  643. if a.RequiredSet != nil || b.RequiredSet != nil {
  644. merged.RequiredSet = a.RequiredSet.Inter(b.RequiredSet)
  645. }
  646. // Take intersection of excluded elems
  647. if a.ExcludedSet != nil || b.ExcludedSet != nil {
  648. merged.ExcludedSet = a.ExcludedSet.Inter(b.ExcludedSet)
  649. }
  650. // Take union of optional elems
  651. if a.OptionalSet == nil || b.OptionalSet == nil {
  652. merged.OptionalSet = nil
  653. } else {
  654. merged.OptionalSet = a.OptionalSet.Union(b.OptionalSet).Union(a.RequiredSet).Union(b.RequiredSet).Diff(merged.RequiredSet)
  655. }
  656. // Take union of unlikely elems
  657. if a.UnlikelySet == nil || b.UnlikelySet == nil {
  658. merged.UnlikelySet = nil
  659. } else {
  660. merged.UnlikelySet = a.UnlikelySet.Union(b.UnlikelySet).Union(a.OptionalSet).Union(b.OptionalSet).Diff(merged.OptionalSet)
  661. }
  662. return
  663. }
  664. // Match a fingerprint against the signature.
  665. // Returns MatchImpossible if no match is possible, MatchUnlikely if the match
  666. // is possible with an unlikely configuration, and MatchPossible otherwise.
  667. func (a RequestSignature) Match(fingerprint RequestFingerprint) (Match, int) {
  668. matchMap, similarity := a.MatchMap(fingerprint)
  669. for _, v := range matchMap {
  670. if v == MatchImpossible {
  671. return MatchImpossible, similarity
  672. }
  673. }
  674. for _, v := range matchMap {
  675. if v == MatchUnlikely {
  676. return MatchUnlikely, similarity
  677. }
  678. }
  679. return MatchPossible, similarity
  680. }
  681. // MatchMap returns (1) a map of the match results of the fingerprint against the signature,
  682. // and (2) the count of overlapping cipher, extension, curve, and ecpointfmt values.
  683. // The second value helps a caller deduce the closest matching record in the case there is no "MatchPossible" match.
  684. func (a RequestSignature) MatchMap(fingerprint RequestFingerprint) (map[string]Match, int) {
  685. matchMap := make(map[string]Match)
  686. var similarity int
  687. var matchCount int
  688. matchMap["version"] = a.Version.Match(fingerprint.Version)
  689. matchMap["cipher"], matchCount = a.Cipher.Match(fingerprint.Cipher)
  690. similarity += matchCount
  691. matchMap["extension"], matchCount = a.Extension.Match(fingerprint.Extension)
  692. similarity += matchCount
  693. matchMap["curve"], matchCount = a.Curve.Match(fingerprint.Curve)
  694. similarity += matchCount
  695. matchMap["ecpointfmt"], matchCount = a.EcPointFmt.Match(fingerprint.EcPointFmt)
  696. similarity += matchCount
  697. matchMap["header"] = a.Header.Match(fingerprint.Header)
  698. matchMap["quirk"] = a.Quirk.Match(fingerprint.Quirk)
  699. return matchMap, similarity
  700. }
  701. // Match a version against the version signature.
  702. // Returns MatchImpossible if no match is possible, MatchUnlikely if the match
  703. // is possible with an unlikely configuration, and MatchPossible otherwise.
  704. func (a VersionSignature) Match(version Version) Match {
  705. if a.Min != VersionEmpty && version < a.Min {
  706. return MatchImpossible
  707. }
  708. if a.Max != VersionEmpty && version > a.Max {
  709. return MatchImpossible
  710. }
  711. if a.Exp != VersionEmpty && version < a.Exp {
  712. return MatchUnlikely
  713. }
  714. return MatchPossible
  715. }
  716. // Match an int list against the int signature.
  717. // Returns MatchImpossible if no match is possible, MatchUnlikely if the match
  718. // is possible with an unlikely configuration, and MatchPossible otherwise.
  719. func (a IntSignature) Match(list IntList) (Match, int) {
  720. set := list.Set()
  721. // Compute number of overlapping values between a and set to use as a "best match" metric if no exact match
  722. similarity := set.Inter(a.RequiredSet).Len() + set.Inter(a.OptionalSet).Len()
  723. // check if the ordered list matches
  724. if a.OrderedList != nil && !a.OrderedList.Contains(list) {
  725. return MatchImpossible, similarity
  726. }
  727. // check that the set does not contain any excluded items
  728. if !set.Inter(a.ExcludedSet).IsEmpty() {
  729. return MatchImpossible, similarity
  730. }
  731. // check that the set has all required items
  732. if !a.RequiredSet.Diff(set).IsEmpty() {
  733. return MatchImpossible, similarity
  734. }
  735. // see if there's anything left after removing required and optional items
  736. set.Copy(set.Diff(a.RequiredSet).Diff(a.OptionalSet))
  737. if !a.OptionalSet.IsEmpty() && !set.IsEmpty() {
  738. // check if the remaining items are unlikely or impossible
  739. if !a.UnlikelySet.IsEmpty() && !set.Diff(a.UnlikelySet).IsEmpty() {
  740. return MatchImpossible, similarity
  741. }
  742. return MatchUnlikely, similarity
  743. }
  744. // check if the set has any unlikely items
  745. if !set.Inter(a.UnlikelySet).IsEmpty() {
  746. return MatchUnlikely, similarity
  747. }
  748. return MatchPossible, similarity
  749. }
  750. // Match a string list against the string signature.
  751. // Returns MatchImpossible if no match is possible, MatchUnlikely if the match
  752. // is possible with an unlikely configuration, and MatchPossible otherwise.
  753. func (a StringSignature) Match(list StringList) Match {
  754. set := list.Set()
  755. // check if the ordered list matches
  756. if a.OrderedList != nil && !a.OrderedList.Contains(list) {
  757. return MatchImpossible
  758. }
  759. // check that the set does not contain any excluded items
  760. if len(set.Inter(a.ExcludedSet)) > 0 {
  761. return MatchImpossible
  762. }
  763. // check that the set has all required items
  764. if len(a.RequiredSet.Diff(set)) > 0 {
  765. return MatchImpossible
  766. }
  767. // see if there's anything left after removing required and optional items
  768. set = set.Diff(a.RequiredSet).Diff(a.OptionalSet)
  769. if len(a.OptionalSet) != 0 && len(set) > 0 {
  770. // check if the remaining items are unlikely or impossible
  771. if a.UnlikelySet != nil && len(set.Diff(a.UnlikelySet)) > 0 {
  772. return MatchImpossible
  773. }
  774. return MatchUnlikely
  775. }
  776. // check if the set has any unlikely items
  777. if len(set.Inter(a.UnlikelySet)) > 0 {
  778. return MatchUnlikely
  779. }
  780. return MatchPossible
  781. }