diff --git a/cmd/nanomdm/main.go b/cmd/nanomdm/main.go index 60fb3ea..cebcfbf 100644 --- a/cmd/nanomdm/main.go +++ b/cmd/nanomdm/main.go @@ -4,7 +4,6 @@ import ( "crypto/x509" "flag" "fmt" - "io/ioutil" stdlog "log" "math/rand" "net/http" @@ -72,6 +71,7 @@ func main() { flDMURLPfx = flag.String("dm", "", "URL to send Declarative Management requests to") flAuthProxy = flag.String("auth-proxy-url", "", "Reverse proxy URL target for MDM-authenticated HTTP requests") flUAZLChal = flag.Bool("ua-zl-dc", false, "reply with zero-length DigestChallenge for UserAuthenticate") + flVerify = flag.String("verify", "pool", "device identity verification type") ) flag.Parse() @@ -89,20 +89,40 @@ func main() { if *flRootsPath == "" { stdlog.Fatal("must supply CA cert path flag") } - caPEM, err := ioutil.ReadFile(*flRootsPath) + caPEM, err := os.ReadFile(*flRootsPath) if err != nil { - stdlog.Fatal(err) + stdlog.Fatal(fmt.Errorf("reading root CA: %w", err)) } - var intsPEM []byte - if *flIntsPath != "" { - intsPEM, err = os.ReadFile(*flIntsPath) + + var verifier certverify.CertVerifier + switch *flVerify { + case "pool": + var intsPEM []byte + if *flIntsPath != "" { + intsPEM, err = os.ReadFile(*flIntsPath) + if err != nil { + stdlog.Fatal(fmt.Errorf("reading intermediate CA: %w", err)) + } + } + verifier, err = certverify.NewPoolVerifier(caPEM, intsPEM, x509.ExtKeyUsageClientAuth) if err != nil { stdlog.Fatal(err) } - } - verifier, err := certverify.NewPoolVerifier(caPEM, intsPEM, x509.ExtKeyUsageClientAuth) - if err != nil { - stdlog.Fatal(err) + case "signature-only": + if *flIntsPath != "" { + stdlog.Fatal("intermediate cannot be used with signature-only verification") + } + verifier, err = certverify.NewSignatureVerifier(caPEM) + if err != nil { + stdlog.Fatal(err) + } + logger.Info( + "msg", "reduced security: signature-only verifier", + // double up and use a err in case that key is used for reporting + "err", "reduced security: signature-only verifier", + ) + default: + stdlog.Fatal(fmt.Errorf("invalid verify flag: %s", *flVerify)) } mdmStorage, err := cliStorage.Parse(logger) diff --git a/docs/operations-guide.md b/docs/operations-guide.md index 258c281..4b218a0 100644 --- a/docs/operations-guide.md +++ b/docs/operations-guide.md @@ -177,6 +177,17 @@ By default NanoMDM will respond to a `UserAuthenticate` message with an HTTP 410 Note that the `UserAuthenticate` message is only for "directory" MDM users and not the "primary" MDM user enrollment. See also [Apple's discussion of UserAthenticate](https://developer.apple.com/documentation/devicemanagement/userauthenticate#discussion) for more information. +### -verify string + +* device identity verification type (default "pool") + +Selects which verifier to use to verify the device identity certificate: + +* `pool`: uses the "pool" verifier which can configure multiple CAs and intermediate certificates. +* `signature-only`: uses the "signature" verifier which only verifies a device identity certificate was signed by a single CA. Notably it does not check identity certificate validity (expiry). **WARNING**: this *reduces security* of the signature checking. + +*Example:* `-verify pool` + ## HTTP endpoints & APIs ### MDM