1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- package certutil
- import (
- "crypto/x509"
- "encoding/json"
- "encoding/pem"
- "fmt"
- "strings"
- )
- type namedTunnelToken struct {
- ZoneID string `json:"zoneID"`
- AccountID string `json:"accountID"`
- ServiceKey string `json:"serviceKey"`
- }
- type OriginCert struct {
- PrivateKey interface{}
- Cert *x509.Certificate
- ZoneID string
- ServiceKey string
- AccountID string
- }
- func DecodeOriginCert(blocks []byte) (*OriginCert, error) {
- if len(blocks) == 0 {
- return nil, fmt.Errorf("Cannot decode empty certificate")
- }
- originCert := OriginCert{}
- block, rest := pem.Decode(blocks)
- for {
- if block == nil {
- break
- }
- switch block.Type {
- case "PRIVATE KEY":
- if originCert.PrivateKey != nil {
- return nil, fmt.Errorf("Found multiple private key in the certificate")
- }
- // RSA private key
- privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
- if err != nil {
- return nil, fmt.Errorf("Cannot parse private key")
- }
- originCert.PrivateKey = privateKey
- case "CERTIFICATE":
- if originCert.Cert != nil {
- return nil, fmt.Errorf("Found multiple certificates in the certificate")
- }
- cert, err := x509.ParseCertificates(block.Bytes)
- if err != nil {
- return nil, fmt.Errorf("Cannot parse certificate")
- } else if len(cert) > 1 {
- return nil, fmt.Errorf("Found multiple certificates in the certificate")
- }
- originCert.Cert = cert[0]
- case "WARP TOKEN", "ARGO TUNNEL TOKEN":
- if originCert.ZoneID != "" || originCert.ServiceKey != "" {
- return nil, fmt.Errorf("Found multiple tokens in the certificate")
- }
- // The token is a string,
- // Try the newer JSON format
- ntt := namedTunnelToken{}
- if err := json.Unmarshal(block.Bytes, &ntt); err == nil {
- originCert.ZoneID = ntt.ZoneID
- originCert.ServiceKey = ntt.ServiceKey
- originCert.AccountID = ntt.AccountID
- } else {
- // Try the older format, where the zoneID and service key are seperated by
- // a new line character
- token := string(block.Bytes)
- s := strings.Split(token, "\n")
- if len(s) != 2 {
- return nil, fmt.Errorf("Cannot parse token")
- }
- originCert.ZoneID = s[0]
- originCert.ServiceKey = s[1]
- }
- default:
- return nil, fmt.Errorf("Unknown block %s in the certificate", block.Type)
- }
- block, rest = pem.Decode(rest)
- }
- if originCert.PrivateKey == nil {
- return nil, fmt.Errorf("Missing private key in the certificate")
- } else if originCert.Cert == nil {
- return nil, fmt.Errorf("Missing certificate in the certificate")
- } else if originCert.ZoneID == "" || originCert.ServiceKey == "" {
- return nil, fmt.Errorf("Missing token in the certificate")
- }
- return &originCert, nil
- }
|