ssl_certs.nim 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2017 Nim contributors
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Scan for SSL/TLS CA certificates on disk
  10. ## The default locations can be overridden using the SSL_CERT_FILE and
  11. ## SSL_CERT_DIR environment variables.
  12. import os, strutils
  13. # FWIW look for files before scanning entire dirs.
  14. when defined(macosx):
  15. const certificatePaths = [
  16. "/etc/ssl/cert.pem",
  17. "/System/Library/OpenSSL/certs/cert.pem"
  18. ]
  19. elif defined(linux):
  20. const certificatePaths = [
  21. # Debian, Ubuntu, Arch: maintained by update-ca-certificates, SUSE, Gentoo
  22. # NetBSD (security/mozilla-rootcerts)
  23. # SLES10/SLES11, https://golang.org/issue/12139
  24. "/etc/ssl/certs/ca-certificates.crt",
  25. # OpenSUSE
  26. "/etc/ssl/ca-bundle.pem",
  27. # Red Hat 5+, Fedora, Centos
  28. "/etc/pki/tls/certs/ca-bundle.crt",
  29. # Red Hat 4
  30. "/usr/share/ssl/certs/ca-bundle.crt",
  31. # Fedora/RHEL
  32. "/etc/pki/tls/certs",
  33. # Android
  34. "/data/data/com.termux/files/usr/etc/tls/cert.pem",
  35. "/system/etc/security/cacerts",
  36. ]
  37. elif defined(bsd):
  38. const certificatePaths = [
  39. # Debian, Ubuntu, Arch: maintained by update-ca-certificates, SUSE, Gentoo
  40. # NetBSD (security/mozilla-rootcerts)
  41. # SLES10/SLES11, https://golang.org/issue/12139
  42. "/etc/ssl/certs/ca-certificates.crt",
  43. # FreeBSD (security/ca-root-nss package)
  44. "/usr/local/share/certs/ca-root-nss.crt",
  45. # OpenBSD, FreeBSD (optional symlink)
  46. "/etc/ssl/cert.pem",
  47. # FreeBSD
  48. "/usr/local/share/certs",
  49. # NetBSD
  50. "/etc/openssl/certs",
  51. ]
  52. else:
  53. const certificatePaths = [
  54. # Debian, Ubuntu, Arch: maintained by update-ca-certificates, SUSE, Gentoo
  55. # NetBSD (security/mozilla-rootcerts)
  56. # SLES10/SLES11, https://golang.org/issue/12139
  57. "/etc/ssl/certs/ca-certificates.crt",
  58. # OpenSUSE
  59. "/etc/ssl/ca-bundle.pem",
  60. # Red Hat 5+, Fedora, Centos
  61. "/etc/pki/tls/certs/ca-bundle.crt",
  62. # Red Hat 4
  63. "/usr/share/ssl/certs/ca-bundle.crt",
  64. # FreeBSD (security/ca-root-nss package)
  65. "/usr/local/share/certs/ca-root-nss.crt",
  66. # CentOS/RHEL 7
  67. "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem",
  68. # OpenBSD, FreeBSD (optional symlink)
  69. "/etc/ssl/cert.pem",
  70. # Fedora/RHEL
  71. "/etc/pki/tls/certs",
  72. # Android
  73. "/system/etc/security/cacerts",
  74. # FreeBSD
  75. "/usr/local/share/certs",
  76. # NetBSD
  77. "/etc/openssl/certs",
  78. ]
  79. when defined(haiku):
  80. const
  81. B_FIND_PATH_EXISTING_ONLY = 0x4
  82. B_FIND_PATH_DATA_DIRECTORY = 6
  83. proc find_paths_etc(architecture: cstring, baseDirectory: cint,
  84. subPath: cstring, flags: uint32,
  85. paths: var ptr UncheckedArray[cstring],
  86. pathCount: var csize_t): int32
  87. {.importc, header: "<FindDirectory.h>".}
  88. proc free(p: pointer) {.importc, header: "<stdlib.h>".}
  89. iterator scanSSLCertificates*(useEnvVars = false): string =
  90. ## Scan for SSL/TLS CA certificates on disk.
  91. ##
  92. ## if `useEnvVars` is true, the SSL_CERT_FILE and SSL_CERT_DIR
  93. ## environment variables can be used to override the certificate
  94. ## directories to scan or specify a CA certificate file.
  95. if useEnvVars and existsEnv("SSL_CERT_FILE"):
  96. yield getEnv("SSL_CERT_FILE")
  97. elif useEnvVars and existsEnv("SSL_CERT_DIR"):
  98. let p = getEnv("SSL_CERT_DIR")
  99. for fn in joinPath(p, "*").walkFiles():
  100. yield fn
  101. else:
  102. when defined(windows):
  103. const cacert = "cacert.pem"
  104. let pem = getAppDir() / cacert
  105. if fileExists(pem):
  106. yield pem
  107. else:
  108. let path = getEnv("PATH")
  109. for candidate in split(path, PathSep):
  110. if candidate.len != 0:
  111. let x = (if candidate[0] == '"' and candidate[^1] == '"':
  112. substr(candidate, 1, candidate.len-2) else: candidate) / cacert
  113. if fileExists(x):
  114. yield x
  115. elif not defined(haiku):
  116. for p in certificatePaths:
  117. if p.endsWith(".pem") or p.endsWith(".crt"):
  118. if fileExists(p):
  119. yield p
  120. elif dirExists(p):
  121. # check if it's a dir where each cert is one file
  122. # named by it's hasg
  123. for fn in joinPath(p, "*.0").walkFiles:
  124. yield p.normalizePathEnd(true)
  125. break
  126. for fn in joinPath(p, "*").walkFiles():
  127. yield fn
  128. else:
  129. var
  130. paths: ptr UncheckedArray[cstring]
  131. size: csize_t
  132. let err = find_paths_etc(
  133. nil, B_FIND_PATH_DATA_DIRECTORY, "ssl/CARootCertificates.pem",
  134. B_FIND_PATH_EXISTING_ONLY, paths, size
  135. )
  136. if err == 0:
  137. defer: free(paths)
  138. for i in 0 ..< size:
  139. yield $paths[i]
  140. # Certificates management on windows
  141. # when defined(windows) or defined(nimdoc):
  142. #
  143. # import openssl
  144. #
  145. # type
  146. # PCCertContext {.final, pure.} = pointer
  147. # X509 {.final, pure.} = pointer
  148. # CertStore {.final, pure.} = pointer
  149. #
  150. # # OpenSSL cert store
  151. #
  152. # {.push stdcall, dynlib: "kernel32", importc.}
  153. #
  154. # proc CertOpenSystemStore*(hprov: pointer=nil, szSubsystemProtocol: cstring): CertStore
  155. #
  156. # proc CertEnumCertificatesInStore*(hCertStore: CertStore, pPrevCertContext: PCCertContext): pointer
  157. #
  158. # proc CertFreeCertificateContext*(pContext: PCCertContext): bool
  159. #
  160. # proc CertCloseStore*(hCertStore:CertStore, flags:cint): bool
  161. #
  162. # {.pop.}