main.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package main
  2. import (
  3. "encoding/csv"
  4. "io"
  5. "net/http"
  6. "os"
  7. "strings"
  8. "github.com/sagernet/sing-box/log"
  9. "golang.org/x/exp/slices"
  10. )
  11. func main() {
  12. err := updateMozillaIncludedRootCAs()
  13. if err != nil {
  14. log.Error(err)
  15. }
  16. err = updateChromeIncludedRootCAs()
  17. if err != nil {
  18. log.Error(err)
  19. }
  20. }
  21. func updateMozillaIncludedRootCAs() error {
  22. response, err := http.Get("https://ccadb.my.salesforce-sites.com/mozilla/IncludedCACertificateReportPEMCSV")
  23. if err != nil {
  24. return err
  25. }
  26. defer response.Body.Close()
  27. reader := csv.NewReader(response.Body)
  28. header, err := reader.Read()
  29. if err != nil {
  30. return err
  31. }
  32. geoIndex := slices.Index(header, "Geographic Focus")
  33. nameIndex := slices.Index(header, "Common Name or Certificate Name")
  34. certIndex := slices.Index(header, "PEM Info")
  35. generated := strings.Builder{}
  36. generated.WriteString(`// Code generated by 'make update_certificates'. DO NOT EDIT.
  37. package certificate
  38. import "crypto/x509"
  39. var mozillaIncluded *x509.CertPool
  40. func init() {
  41. mozillaIncluded = x509.NewCertPool()
  42. `)
  43. for {
  44. record, err := reader.Read()
  45. if err == io.EOF {
  46. break
  47. } else if err != nil {
  48. return err
  49. }
  50. if record[geoIndex] == "China" {
  51. continue
  52. }
  53. generated.WriteString("\n // ")
  54. generated.WriteString(record[nameIndex])
  55. generated.WriteString("\n")
  56. generated.WriteString(" mozillaIncluded.AppendCertsFromPEM([]byte(`")
  57. cert := record[certIndex]
  58. // Remove single quotes
  59. cert = cert[1 : len(cert)-1]
  60. generated.WriteString(cert)
  61. generated.WriteString("`))\n")
  62. }
  63. generated.WriteString("}\n")
  64. return os.WriteFile("common/certificate/mozilla.go", []byte(generated.String()), 0o644)
  65. }
  66. func fetchChinaFingerprints() (map[string]bool, error) {
  67. response, err := http.Get("https://ccadb.my.salesforce-sites.com/ccadb/AllCertificateRecordsCSVFormatv4")
  68. if err != nil {
  69. return nil, err
  70. }
  71. defer response.Body.Close()
  72. reader := csv.NewReader(response.Body)
  73. header, err := reader.Read()
  74. if err != nil {
  75. return nil, err
  76. }
  77. countryIndex := slices.Index(header, "Country")
  78. fingerprintIndex := slices.Index(header, "SHA-256 Fingerprint")
  79. chinaFingerprints := make(map[string]bool)
  80. for {
  81. record, err := reader.Read()
  82. if err == io.EOF {
  83. break
  84. } else if err != nil {
  85. return nil, err
  86. }
  87. if record[countryIndex] == "China" {
  88. chinaFingerprints[record[fingerprintIndex]] = true
  89. }
  90. }
  91. return chinaFingerprints, nil
  92. }
  93. func updateChromeIncludedRootCAs() error {
  94. chinaFingerprints, err := fetchChinaFingerprints()
  95. if err != nil {
  96. return err
  97. }
  98. response, err := http.Get("https://ccadb.my.salesforce-sites.com/ccadb/RootCACertificatesIncludedByRSReportCSV")
  99. if err != nil {
  100. return err
  101. }
  102. defer response.Body.Close()
  103. reader := csv.NewReader(response.Body)
  104. header, err := reader.Read()
  105. if err != nil {
  106. return err
  107. }
  108. subjectIndex := slices.Index(header, "Subject")
  109. statusIndex := slices.Index(header, "Google Chrome Status")
  110. certIndex := slices.Index(header, "X.509 Certificate (PEM)")
  111. fingerprintIndex := slices.Index(header, "SHA-256 Fingerprint")
  112. generated := strings.Builder{}
  113. generated.WriteString(`// Code generated by 'make update_certificates'. DO NOT EDIT.
  114. package certificate
  115. import "crypto/x509"
  116. var chromeIncluded *x509.CertPool
  117. func init() {
  118. chromeIncluded = x509.NewCertPool()
  119. `)
  120. for {
  121. record, err := reader.Read()
  122. if err == io.EOF {
  123. break
  124. } else if err != nil {
  125. return err
  126. }
  127. if record[statusIndex] != "Included" {
  128. continue
  129. }
  130. if chinaFingerprints[record[fingerprintIndex]] {
  131. continue
  132. }
  133. generated.WriteString("\n // ")
  134. generated.WriteString(record[subjectIndex])
  135. generated.WriteString("\n")
  136. generated.WriteString(" chromeIncluded.AppendCertsFromPEM([]byte(`")
  137. cert := record[certIndex]
  138. // Remove single quotes if present
  139. if len(cert) > 0 && cert[0] == '\'' {
  140. cert = cert[1 : len(cert)-1]
  141. }
  142. generated.WriteString(cert)
  143. generated.WriteString("`))\n")
  144. }
  145. generated.WriteString("}\n")
  146. return os.WriteFile("common/certificate/chrome.go", []byte(generated.String()), 0o644)
  147. }