Implement mdmcert.download support in mdmctl (#401)

This commit is contained in:
Jesse Peterson
2018-05-02 22:05:32 -07:00
committed by GitHub
parent 3cb96ac30c
commit 5661b62021
5 changed files with 357 additions and 9 deletions

View File

@@ -8,11 +8,12 @@ import (
"encoding/asn1"
"encoding/pem"
"errors"
"fmt"
"io/ioutil"
"math/big"
"os"
"time"
"strings"
"time"
)
func GenerateRandomCertificateSerialNumber() (*big.Int, error) {
@@ -66,6 +67,11 @@ func ReadPEMCertificateFile(path string) (*x509.Certificate, error) {
return certs[0], nil
}
const (
rsaPrivateKeyPEMBlockType = "RSA PRIVATE KEY"
certificatePEMBlockType = "CERTIFICATE"
)
func ReadPEMCertificatesFile(path string) ([]*x509.Certificate, error) {
pemData, err := ioutil.ReadFile(path)
if err != nil {
@@ -76,7 +82,7 @@ func ReadPEMCertificatesFile(path string) ([]*x509.Certificate, error) {
for {
var block *pem.Block
block, rest = pem.Decode(rest)
if block == nil || block.Type != "CERTIFICATE" {
if block == nil || block.Type != certificatePEMBlockType {
return nil, errors.New("failed to decode PEM block containing certificate")
}
asn1data = append(asn1data, block.Bytes...)
@@ -87,6 +93,40 @@ func ReadPEMCertificatesFile(path string) ([]*x509.Certificate, error) {
return x509.ParseCertificates(asn1data)
}
func ReadPEMRSAKeyFile(path string) (*rsa.PrivateKey, error) {
return ReadEncryptedPEMRSAKeyFile(path, nil)
}
func ReadEncryptedPEMRSAKeyFile(path string, password []byte) (*rsa.PrivateKey, error) {
pemData, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
pemBlock, _ := pem.Decode(pemData)
if pemBlock == nil {
return nil, errors.New("PEM decode failed")
}
if pemBlock.Type != rsaPrivateKeyPEMBlockType {
return nil, fmt.Errorf("expecting PEM type of %s, but got %s", rsaPrivateKeyPEMBlockType, pemBlock.Type)
}
if x509.IsEncryptedPEMBlock(pemBlock) {
if password == nil {
return nil, errors.New("no supplied password for encrypted PEM")
}
derBytes, err := x509.DecryptPEMBlock(pemBlock, password)
if err != nil {
return nil, err
}
return x509.ParsePKCS1PrivateKey(derBytes)
} else if password != nil {
return nil, errors.New("supplied PEM password, but not encrypted")
}
return x509.ParsePKCS1PrivateKey(pemBlock.Bytes)
}
func WritePEMCertificateFile(cert *x509.Certificate, path string) error {
file, err := os.Create(path)
if err != nil {
@@ -97,7 +137,7 @@ func WritePEMCertificateFile(cert *x509.Certificate, path string) error {
return pem.Encode(
file,
&pem.Block{
Type: "CERTIFICATE",
Type: certificatePEMBlockType,
Bytes: cert.Raw,
})
}
@@ -112,11 +152,31 @@ func WritePEMRSAKeyFile(key *rsa.PrivateKey, path string) error {
return pem.Encode(
file,
&pem.Block{
Type: "RSA PRIVATE KEY",
Type: rsaPrivateKeyPEMBlockType,
Bytes: x509.MarshalPKCS1PrivateKey(key),
})
}
func WriteEncryptedPEMRSAKeyFile(key *rsa.PrivateKey, password []byte, path string) error {
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0700)
if err != nil {
return err
}
defer file.Close()
encPemBlock, err := x509.EncryptPEMBlock(
rand.Reader,
rsaPrivateKeyPEMBlockType,
x509.MarshalPKCS1PrivateKey(key),
password,
x509.PEMCipher3DES)
if err != nil {
return err
}
return pem.Encode(file, encPemBlock)
}
// TopicFromCert extracts the push certificate topic from the provided certificate.
func TopicFromCert(cert *x509.Certificate) (string, error) {
var oidASN1UserID = asn1.ObjectIdentifier{0, 9, 2342, 19200300, 100, 1, 1}

View File

@@ -43,11 +43,11 @@ func CreateCSR(req *CSRConfig) error {
return err
}
derBytes, err := newCSR(key, strings.ToLower(req.Email), strings.ToUpper(req.Country), req.CommonName)
derBytes, err := NewCSR(key, strings.ToLower(req.Email), strings.ToUpper(req.Country), req.CommonName)
if err != nil {
return err
}
pemCSR := pemCSR(derBytes)
pemCSR := PemCSR(derBytes)
return ioutil.WriteFile(req.CSRPath, pemCSR, 0600)
}
@@ -145,7 +145,7 @@ const (
)
// create a CSR using the same parameters as Keychain Access would produce
func newCSR(priv *rsa.PrivateKey, email, country, cname string) ([]byte, error) {
func NewCSR(priv *rsa.PrivateKey, email, country, cname string) ([]byte, error) {
subj := pkix.Name{
Country: []string{country},
CommonName: cname,
@@ -161,7 +161,7 @@ func newCSR(priv *rsa.PrivateKey, email, country, cname string) ([]byte, error)
}
// convert DER to PEM format
func pemCSR(derBytes []byte) []byte {
func PemCSR(derBytes []byte) []byte {
pemBlock := &pem.Block{
Type: csrPEMBlockType,
Headers: nil,