validators_cert.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package validators
  15. import (
  16. "context"
  17. "crypto"
  18. "crypto/ecdsa"
  19. "crypto/rsa"
  20. "crypto/sha256"
  21. "crypto/x509"
  22. "encoding/hex"
  23. "encoding/pem"
  24. "fmt"
  25. "reflect"
  26. "strings"
  27. "yunion.io/x/jsonutils"
  28. api "yunion.io/x/onecloud/pkg/apis/compute"
  29. "yunion.io/x/onecloud/pkg/httperrors"
  30. )
  31. type ValidatorPEM struct {
  32. Validator
  33. Blocks []*pem.Block
  34. }
  35. func NewPEMValidator(key string) *ValidatorPEM {
  36. v := &ValidatorPEM{
  37. Validator: Validator{Key: key},
  38. }
  39. v.SetParent(v)
  40. return v
  41. }
  42. func (v *ValidatorPEM) getValue() interface{} {
  43. return v.Blocks
  44. }
  45. func (v *ValidatorPEM) parseFromString(s string) []*pem.Block {
  46. blocks := []*pem.Block{}
  47. for d := []byte(s); ; {
  48. block, rest := pem.Decode(d)
  49. if block == nil {
  50. if len(rest) > 0 {
  51. return nil
  52. }
  53. break
  54. }
  55. blocks = append(blocks, block)
  56. d = rest
  57. }
  58. return blocks
  59. }
  60. func (v *ValidatorPEM) setDefault(data *jsonutils.JSONDict) bool {
  61. if v.defaultVal == nil {
  62. return false
  63. }
  64. s, ok := v.defaultVal.(string)
  65. if !ok {
  66. return false
  67. }
  68. blocks := v.parseFromString(s)
  69. if blocks != nil {
  70. value := jsonutils.NewString(s)
  71. v.value = value
  72. data.Set(v.Key, value)
  73. v.Blocks = blocks
  74. return true
  75. }
  76. return false
  77. }
  78. func (v *ValidatorPEM) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  79. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  80. return err
  81. }
  82. s, err := v.value.GetString()
  83. if err != nil {
  84. return newInvalidTypeError(v.Key, "pem", err)
  85. }
  86. v.Blocks = v.parseFromString(s)
  87. return nil
  88. }
  89. type ValidatorCertificate struct {
  90. ValidatorPEM
  91. Certificates []*x509.Certificate
  92. }
  93. func NewCertificateValidator(key string) *ValidatorCertificate {
  94. v := &ValidatorCertificate{
  95. ValidatorPEM: *NewPEMValidator(key),
  96. }
  97. v.SetParent(v)
  98. return v
  99. }
  100. func (v *ValidatorCertificate) getValue() interface{} {
  101. return v.Certificates
  102. }
  103. func (v *ValidatorCertificate) parseFromBlocks(blocks []*pem.Block) []*x509.Certificate {
  104. certs := []*x509.Certificate{}
  105. for i, block := range blocks {
  106. cert, err := x509.ParseCertificate(block.Bytes)
  107. if err != nil {
  108. return nil
  109. }
  110. if i > 0 {
  111. certSub := certs[i-1]
  112. if err := certSub.CheckSignatureFrom(cert); err != nil {
  113. return nil
  114. }
  115. }
  116. certs = append(certs, cert)
  117. }
  118. return certs
  119. }
  120. func (v *ValidatorCertificate) parseFromString(s string) []*x509.Certificate {
  121. blocks := v.ValidatorPEM.parseFromString(s)
  122. if blocks == nil {
  123. return nil
  124. }
  125. v.Blocks = blocks
  126. certs := v.parseFromBlocks(blocks)
  127. return certs
  128. }
  129. func (v *ValidatorCertificate) setDefault(data *jsonutils.JSONDict) bool {
  130. if v.defaultVal == nil {
  131. return false
  132. }
  133. s, ok := v.defaultVal.(string)
  134. if !ok {
  135. return false
  136. }
  137. certs := v.parseFromString(s)
  138. if certs != nil {
  139. v.setCertificates(certs, data)
  140. return true
  141. }
  142. return false
  143. }
  144. func (v *ValidatorCertificate) setCertificates(certs []*x509.Certificate, data *jsonutils.JSONDict) {
  145. pems := []byte{}
  146. for _, block := range v.Blocks {
  147. d := pem.EncodeToMemory(block)
  148. pems = append(pems, d...)
  149. }
  150. value := jsonutils.NewString(string(pems))
  151. v.value = value
  152. data.Set(v.Key, value)
  153. v.Certificates = certs
  154. }
  155. func (v *ValidatorCertificate) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  156. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  157. return err
  158. }
  159. s, err := v.value.GetString()
  160. if err != nil {
  161. return newInvalidTypeError(v.Key, "certificate", err)
  162. }
  163. certs := v.parseFromString(s)
  164. if !v.optional && len(certs) == 0 {
  165. return newInvalidValueError(v.Key, "empty certificate chain")
  166. }
  167. if len(certs) > 0 {
  168. for _, block := range v.Blocks {
  169. if block.Type != "CERTIFICATE" {
  170. err := fmt.Errorf("wrong PEM type: %s", block.Type)
  171. return newInvalidTypeError(v.Key, "certificate", err)
  172. }
  173. }
  174. for i := 0; i < len(certs)-1; i++ {
  175. cert := certs[i]
  176. certP := certs[i+1]
  177. err := cert.CheckSignatureFrom(certP)
  178. if err != nil {
  179. msg := fmt.Sprintf("cannot verify signature of certificate %d in the chain", i+1)
  180. return newInvalidValueError(v.Key, msg)
  181. }
  182. }
  183. v.setCertificates(certs, data)
  184. return nil
  185. }
  186. return nil
  187. }
  188. func (v *ValidatorCertificate) FingerprintSha256() []byte {
  189. csum := sha256.Sum256(v.Certificates[0].Raw)
  190. return csum[:]
  191. }
  192. func (v *ValidatorCertificate) FingerprintSha256String() string {
  193. fp := v.FingerprintSha256()
  194. s := hex.EncodeToString(fp)
  195. return s
  196. }
  197. func (v *ValidatorCertificate) PublicKeyBitLen() int {
  198. cert := v.Certificates[0]
  199. pubkey := cert.PublicKey
  200. switch pub := pubkey.(type) {
  201. case *rsa.PublicKey:
  202. return pub.N.BitLen()
  203. case *ecdsa.PublicKey:
  204. return pub.X.BitLen()
  205. default:
  206. return 0
  207. }
  208. }
  209. type ValidatorPrivateKey struct {
  210. ValidatorPEM
  211. PrivateKey crypto.PrivateKey
  212. }
  213. func NewPrivateKeyValidator(key string) *ValidatorPrivateKey {
  214. v := &ValidatorPrivateKey{
  215. ValidatorPEM: *NewPEMValidator(key),
  216. }
  217. v.SetParent(v)
  218. return v
  219. }
  220. func (v *ValidatorPrivateKey) getValue() interface{} {
  221. return v.PrivateKey
  222. }
  223. func (v *ValidatorPrivateKey) parseFromBlock(block *pem.Block) (crypto.PrivateKey, error) {
  224. const RSA_PRIVATE_KEY = "RSA PRIVATE KEY"
  225. const EC_PRIVATE_KEY = "EC PRIVATE KEY"
  226. const PKCS8_PRIVATE_KEY = "PRIVATE KEY"
  227. var fuzz bool
  228. switch block.Type {
  229. case PKCS8_PRIVATE_KEY:
  230. goto parsePkcs8
  231. case RSA_PRIVATE_KEY:
  232. goto parseRsa
  233. case EC_PRIVATE_KEY:
  234. goto parseEc
  235. default:
  236. }
  237. fuzz = true
  238. parsePkcs8:
  239. {
  240. pkey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
  241. if err == nil {
  242. switch pkey1 := pkey.(type) {
  243. case *rsa.PrivateKey:
  244. block.Type = RSA_PRIVATE_KEY
  245. block.Bytes = x509.MarshalPKCS1PrivateKey(pkey1)
  246. return pkey1, nil
  247. case *ecdsa.PrivateKey:
  248. block.Type = EC_PRIVATE_KEY
  249. block.Bytes, _ = x509.MarshalECPrivateKey(pkey1)
  250. return pkey1, nil
  251. default:
  252. return nil, newInvalidValueError(v.Key, "unknown private key type")
  253. }
  254. }
  255. if !fuzz {
  256. return nil, newInvalidValueError(v.Key, fmt.Sprintf("invalid pkcs8 private key: %s", err))
  257. }
  258. }
  259. parseRsa:
  260. {
  261. pkey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
  262. if err == nil {
  263. block.Type = RSA_PRIVATE_KEY
  264. return pkey, nil
  265. }
  266. if !fuzz {
  267. return nil, newInvalidValueError(v.Key, fmt.Sprintf("invalid rsa private key: %s", err))
  268. }
  269. }
  270. parseEc:
  271. {
  272. pkey, err := x509.ParseECPrivateKey(block.Bytes)
  273. if err == nil {
  274. block.Type = EC_PRIVATE_KEY
  275. return pkey, nil
  276. }
  277. if !fuzz {
  278. return nil, newInvalidValueError(v.Key, fmt.Sprintf("invalid ec private key: %s", err))
  279. }
  280. }
  281. return nil, newInvalidValueError(v.Key, "invalid private key")
  282. }
  283. func (v *ValidatorPrivateKey) parseFromString(s string) (crypto.PrivateKey, error) {
  284. blocks := v.ValidatorPEM.parseFromString(s)
  285. if len(blocks) != 1 {
  286. return nil, newInvalidValueError(v.Key, fmt.Sprintf("found %d pem blocks, expecting 1", len(blocks)))
  287. }
  288. v.Blocks = blocks
  289. pkey, err := v.parseFromBlock(blocks[0])
  290. return pkey, err
  291. }
  292. func (v *ValidatorPrivateKey) setDefault(data *jsonutils.JSONDict) bool {
  293. if v.defaultVal == nil {
  294. return false
  295. }
  296. s, ok := v.defaultVal.(string)
  297. if !ok {
  298. return false
  299. }
  300. pkey, err := v.parseFromString(s)
  301. if err != nil {
  302. return false
  303. }
  304. v.setPrivateKey(pkey, data)
  305. return true
  306. }
  307. func (v *ValidatorPrivateKey) setPrivateKey(pkey crypto.PrivateKey, data *jsonutils.JSONDict) {
  308. d := pem.EncodeToMemory(v.Blocks[0])
  309. value := jsonutils.NewString(string(d))
  310. v.value = value
  311. data.Set(v.Key, value)
  312. v.PrivateKey = pkey
  313. }
  314. func (v *ValidatorPrivateKey) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  315. if err, isSet := v.Validator.validateEx(data); err != nil || !isSet {
  316. return err
  317. }
  318. s, err := v.value.GetString()
  319. if err != nil {
  320. return newInvalidTypeError(v.Key, "privateKey", err)
  321. }
  322. pkey, err := v.parseFromString(s)
  323. if err != nil {
  324. return err
  325. }
  326. v.setPrivateKey(pkey, data)
  327. return nil
  328. }
  329. func (v *ValidatorPrivateKey) MatchCertificate(cert *x509.Certificate) error {
  330. switch pkey := v.PrivateKey.(type) {
  331. case *rsa.PrivateKey:
  332. pubkey0 := pkey.Public()
  333. pubkey1, _ := cert.PublicKey.(crypto.PublicKey) // safe conversion
  334. if !reflect.DeepEqual(pubkey0, pubkey1) {
  335. return newInvalidValueError(v.Key, "certificate and rsa key do not match")
  336. }
  337. case *ecdsa.PrivateKey:
  338. pubkey0 := pkey.Public()
  339. pubkey1, _ := cert.PublicKey.(crypto.PublicKey)
  340. if !reflect.DeepEqual(pubkey0, pubkey1) {
  341. return newInvalidValueError(v.Key, "certificate and ec key do not match")
  342. }
  343. default:
  344. // should never happen
  345. return newInvalidValueError(v.Key, "unknown private key type")
  346. }
  347. return nil
  348. }
  349. type ValidatorCertKey struct {
  350. *ValidatorCertificate
  351. *ValidatorPrivateKey
  352. certPubKeyAlgo string
  353. }
  354. func NewCertKeyValidator(cert, key string) *ValidatorCertKey {
  355. return &ValidatorCertKey{
  356. ValidatorCertificate: NewCertificateValidator(cert),
  357. ValidatorPrivateKey: NewPrivateKeyValidator(key),
  358. }
  359. }
  360. func (v *ValidatorCertKey) Validate(ctx context.Context, data *jsonutils.JSONDict) error {
  361. keyV := map[string]IValidator{
  362. "certificate": v.ValidatorCertificate,
  363. "private_key": v.ValidatorPrivateKey,
  364. }
  365. for _, v := range keyV {
  366. if err := v.Validate(ctx, data); err != nil {
  367. return err
  368. }
  369. }
  370. cert := v.ValidatorCertificate.Certificates[0]
  371. var certPubKeyAlgo string
  372. {
  373. // x509.PublicKeyAlgorithm.String() is only available since go1.10
  374. switch cert.PublicKeyAlgorithm {
  375. case x509.RSA:
  376. certPubKeyAlgo = api.LB_TLS_CERT_PUBKEY_ALGO_RSA
  377. case x509.ECDSA:
  378. certPubKeyAlgo = api.LB_TLS_CERT_PUBKEY_ALGO_ECDSA
  379. default:
  380. certPubKeyAlgo = fmt.Sprintf("algo %#v", cert.PublicKeyAlgorithm)
  381. }
  382. if !api.LB_TLS_CERT_PUBKEY_ALGOS.Has(certPubKeyAlgo) {
  383. return httperrors.NewInputParameterError("invalid cert pubkey algorithm: %s, want %s",
  384. certPubKeyAlgo, api.LB_TLS_CERT_PUBKEY_ALGOS.String())
  385. }
  386. }
  387. v.certPubKeyAlgo = certPubKeyAlgo
  388. if err := v.ValidatorPrivateKey.MatchCertificate(cert); err != nil {
  389. return err
  390. }
  391. return nil
  392. }
  393. func (v *ValidatorCertKey) UpdateCertKeyInfo(ctx context.Context, data *jsonutils.JSONDict) *jsonutils.JSONDict {
  394. cert := v.ValidatorCertificate.Certificates[0]
  395. // NOTE subject alternative names also includes email, url, ip addresses,
  396. // but we ignore them here.
  397. //
  398. // NOTE we use white space to separate names
  399. data.Set("common_name", jsonutils.NewString(cert.Subject.CommonName))
  400. data.Set("subject_alternative_names", jsonutils.NewString(strings.Join(cert.DNSNames, " ")))
  401. data.Set("not_before", jsonutils.NewTimeString(cert.NotBefore))
  402. data.Set("not_after", jsonutils.NewTimeString(cert.NotAfter))
  403. data.Set("public_key_algorithm", jsonutils.NewString(v.certPubKeyAlgo))
  404. data.Set("public_key_bit_len", jsonutils.NewInt(int64(v.ValidatorCertificate.PublicKeyBitLen())))
  405. data.Set("signature_algorithm", jsonutils.NewString(cert.SignatureAlgorithm.String()))
  406. data.Set("fingerprint", jsonutils.NewString(api.LB_TLS_CERT_FINGERPRINT_ALGO_SHA256+":"+v.ValidatorCertificate.FingerprintSha256String()))
  407. return data
  408. }