mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
fc3304c902
#15557 Following the precedent that Lucas used for other similar PRs, the best way to review is probably by commits. * The first one simply copies over the files from the fork to the monorepo * Second one adjusts all import paths * Third one tidies up the `go.mod` files * Last one fixes the linter issues in the nanomdm package # Checklist for submitter - ~~Changes file added for user-visible changes in `changes/` or `orbit/changes/`.~~ (not a user-visible change) - [x] Manual QA for all new/changed functionality (ran test suite, re-generated mocks) I also verified that our Go test suite did run the newly moved `nanomdm` package steps: ``` ok github.com/fleetdm/fleet/v4/server/mdm/nanomdm/cryptoutil 0.003s coverage: 0.0% of statements in github.com/fleetdm/fleet/v4/... ok github.com/fleetdm/fleet/v4/server/mdm/nanomdm/mdm 0.005s coverage: 46.2% of statements in github.com/fleetdm/fleet/v4/... ok github.com/fleetdm/fleet/v4/server/mdm/nanomdm/service/certauth 1.320s coverage: 20.7% of statements in github.com/fleetdm/fleet/v4/... ok github.com/fleetdm/fleet/v4/server/mdm/nanomdm/storage/file 0.007s coverage: 24.1% of statements in github.com/fleetdm/fleet/v4/... ```
127 lines
3.2 KiB
Go
127 lines
3.2 KiB
Go
package apple_mdm
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"encoding/binary"
|
|
"encoding/pem"
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"net/url"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/fleet"
|
|
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/mdm"
|
|
)
|
|
|
|
// Note Apple rejects CSRs if the key size is not 2048.
|
|
const rsaKeySize = 2048
|
|
|
|
// newPrivateKey creates an RSA private key
|
|
func newPrivateKey() (*rsa.PrivateKey, error) {
|
|
return rsa.GenerateKey(rand.Reader, rsaKeySize)
|
|
}
|
|
|
|
// EncodeCertPEM returns PEM-endcoded certificate data.
|
|
func EncodeCertPEM(cert *x509.Certificate) []byte {
|
|
block := pem.Block{
|
|
Type: "CERTIFICATE",
|
|
Bytes: cert.Raw,
|
|
}
|
|
return pem.EncodeToMemory(&block)
|
|
}
|
|
|
|
func DecodeCertPEM(encoded []byte) (*x509.Certificate, error) {
|
|
block, _ := pem.Decode(encoded)
|
|
if block == nil {
|
|
return nil, errors.New("no PEM-encoded data found")
|
|
}
|
|
if block.Type != "CERTIFICATE" {
|
|
return nil, fmt.Errorf("unexpected block type %s", block.Type)
|
|
}
|
|
|
|
return x509.ParseCertificate(block.Bytes)
|
|
}
|
|
|
|
func EncodeCertRequestPEM(cert *x509.CertificateRequest) []byte {
|
|
pemBlock := &pem.Block{
|
|
Type: "CERTIFICATE REQUEST",
|
|
Headers: nil,
|
|
Bytes: cert.Raw,
|
|
}
|
|
|
|
return pem.EncodeToMemory(pemBlock)
|
|
}
|
|
|
|
// EncodePrivateKeyPEM returns PEM-encoded private key data
|
|
func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte {
|
|
block := pem.Block{
|
|
Type: "RSA PRIVATE KEY",
|
|
Bytes: x509.MarshalPKCS1PrivateKey(key),
|
|
}
|
|
return pem.EncodeToMemory(&block)
|
|
}
|
|
|
|
// DecodePrivateKeyPEM decodes PEM-encoded private key data.
|
|
func DecodePrivateKeyPEM(encoded []byte) (*rsa.PrivateKey, error) {
|
|
block, _ := pem.Decode(encoded)
|
|
if block == nil {
|
|
return nil, errors.New("no PEM-encoded data found")
|
|
}
|
|
if block.Type != "RSA PRIVATE KEY" {
|
|
return nil, fmt.Errorf("unexpected block type %s", block.Type)
|
|
}
|
|
|
|
return x509.ParsePKCS1PrivateKey(block.Bytes)
|
|
}
|
|
|
|
// GenerateRandomPin generates a `lenght`-digit PIN number that takes into
|
|
// account the current time as described in rfc4226 (for one time passwords)
|
|
//
|
|
// The implementation details have been mostly taken from https://github.com/pquerna/otp
|
|
func GenerateRandomPin(length int) string {
|
|
counter := uint64(time.Now().Unix())
|
|
buf := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(buf, counter)
|
|
m := sha256.New()
|
|
m.Write(buf)
|
|
sum := m.Sum(nil)
|
|
offset := sum[len(sum)-1] & 0xf
|
|
value := int64(((int(sum[offset]) & 0x7f) << 24) |
|
|
((int(sum[offset+1] & 0xff)) << 16) |
|
|
((int(sum[offset+2] & 0xff)) << 8) |
|
|
(int(sum[offset+3]) & 0xff))
|
|
v := int32(value % int64(math.Pow10(length)))
|
|
f := fmt.Sprintf("%%0%dd", length)
|
|
return fmt.Sprintf(f, v)
|
|
}
|
|
|
|
func FmtErrorChain(chain []mdm.ErrorChain) string {
|
|
var sb strings.Builder
|
|
for _, mdmErr := range chain {
|
|
desc := mdmErr.USEnglishDescription
|
|
if desc == "" {
|
|
desc = mdmErr.LocalizedDescription
|
|
}
|
|
sb.WriteString(fmt.Sprintf("%s (%d): %s\n", mdmErr.ErrorDomain, mdmErr.ErrorCode, desc))
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
func EnrollURL(token string, appConfig *fleet.AppConfig) (string, error) {
|
|
enrollURL, err := url.Parse(appConfig.ServerSettings.ServerURL)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
enrollURL.Path = path.Join(enrollURL.Path, EnrollPath)
|
|
q := enrollURL.Query()
|
|
q.Set("token", token)
|
|
enrollURL.RawQuery = q.Encode()
|
|
return enrollURL.String(), nil
|
|
}
|