func TestBundleFromRemoteFlavor(t *testing.T) { b := newBundler(t) ubiquity.Platforms = nil ubiquity.LoadPlatforms(testMetadata) bundle, err := b.BundleFromRemote(ECCCertSite, "", Ubiquitous) if err != nil { t.Errorf("expected no error. but an error occurred: %s", err.Error()) } if len(bundle.Chain) != 3 { t.Error("expected 3-cert bundle. Got ", len(bundle.Chain)) } if len(bundle.Status.Untrusted) != 0 { t.Error("expected no untrusted platforms. Got ", bundle.Status.Untrusted) } bundle, err = b.BundleFromRemote(ECCCertSite, "", Optimal) if err != nil { t.Errorf("expected no error. but an error occurred: %s", err.Error()) } if len(bundle.Chain) != 2 { t.Error("expected 2-cert bundle. Got ", len(bundle.Chain)) } }
// serverMain is the command line entry point to the API server. It sets up a // new HTTP server to handle sign, bundle, and validate requests. func serverMain(args []string, c cli.Config) error { conf = c // serve doesn't support arguments. if len(args) > 0 { return errors.New("argument is provided but not defined; please refer to the usage by flag -h") } bundler.IntermediateStash = conf.IntDir var err error if err = ubiquity.LoadPlatforms(conf.Metadata); err != nil { return err } log.Info("Initializing signer") if s, err = sign.SignerFromConfig(c); err != nil { log.Warningf("couldn't initialize signer: %v", err) } if ocspSigner, err = ocspsign.SignerFromConfig(c); err != nil { log.Warningf("couldn't initialize ocsp signer: %v", err) } registerHandlers() addr := net.JoinHostPort(conf.Address, strconv.Itoa(conf.Port)) log.Info("Now listening on ", addr) return http.ListenAndServe(addr, nil) }
// Regression test on ubiquity. // It is to make sure ubiquitous bundles are generated so they can be trusted by Android 2.2 // and its variants. // // Leaf certs from SurveyGizmo.com and DraftKings.com are issued by a GoDaddy intermediate cert, // which in turn is issued by a GoDaddy Root Certificate (CN: Go Daddy Root Certificate Authority // G2). The NSS library includes this root cert. So optimal bundle should only have two certs. // However, that root cert is not present in trust stores of Android <= 2.2. Ubiquitous bundling // should be able to recognize this scenario and produces a bundle that includes the GoDaddy Root // cert as an intermediate, which is verified by older trust roots. // Also, lazada.com.ph (mentioned in CFSSL-48) is having a similar problem with GeoTrust CA. func TestAndroidUbiquitousBundle(t *testing.T) { leafs := []string{sgizmoPEM, draftkingsPEM, lazadaPEM} for _, leaf := range leafs { b := newCustomizedBundlerFromFile(t, testNSSRootBundle, testIntCaBundle, "") ubiquity.Platforms = nil ubiquity.LoadPlatforms(testMetadata) // Optimal bundle algorithm will use the Godaddy Root/GeoTrust CA. optimalBundle, err := b.BundleFromFile(leaf, "", Optimal) if err != nil { t.Fatal("Optimal bundle failed:", err) } if len(optimalBundle.Chain) != 2 { t.Fatal("Optimal bundle failed") } checkUbiquityWarningAndCode(t, optimalBundle, true) // Ubiquitous bundle will include a 2nd intermediate CA. ubiquitousBundle, err := b.BundleFromFile(leaf, "", Ubiquitous) if err != nil { t.Fatal("Ubiquitous bundle failed") } if len(ubiquitousBundle.Chain) != 3 { t.Fatal("Ubiquitous bundle failed") } if len(ubiquitousBundle.Status.Untrusted) != 0 { t.Fatal("Regression: Ubiquitous bundle has untrusted platforms: ", ubiquitousBundle.Status.Untrusted) } checkUbiquityWarningAndCode(t, ubiquitousBundle, false) } }
func TestMetadataFormat(t *testing.T) { for _, file := range metadataFiles { if err := ubiquity.LoadPlatforms(file); err != nil { t.Fatal(err) } } }
// bundlerMain is the main CLI of bundler functionality. func bundlerMain(args []string, c cli.Config) (err error) { bundler.IntermediateStash = c.IntDir ubiquity.LoadPlatforms(c.Metadata) flavor := bundler.BundleFlavor(c.Flavor) var b *bundler.Bundler // If it is a force bundle, don't require ca bundle and intermediate bundle // Otherwise, initialize a bundler with CA bundle and intermediate bundle. if flavor == bundler.Force { b = &bundler.Bundler{} } else { b, err = bundler.NewBundler(c.CABundleFile, c.IntBundleFile) if err != nil { return } } var bundle *bundler.Bundle if c.CertFile != "" { if c.CertFile == "-" { var certPEM, keyPEM []byte certPEM, err = cli.ReadStdin(c.CertFile) if err != nil { return } if c.KeyFile != "" { keyPEM, err = cli.ReadStdin(c.KeyFile) if err != nil { return } } bundle, err = b.BundleFromPEMorDER(certPEM, keyPEM, flavor, "") if err != nil { return } } else { // Bundle the client cert bundle, err = b.BundleFromFile(c.CertFile, c.KeyFile, flavor, c.Password) if err != nil { return } } } else if c.Domain != "" { bundle, err = b.BundleFromRemote(c.Domain, c.IP, flavor) if err != nil { return } } else { return errors.New("Must specify bundle target through -cert or -domain") } marshaled, err := bundle.MarshalJSON() if err != nil { return } fmt.Printf("%s", marshaled) return }
// serverMain is the command line entry point to the API server. It sets up a // new HTTP server to handle sign, bundle, and validate requests. func serverMain(args []string) error { // serve doesn't support arguments. if len(args) > 0 { return errors.New("Arguments is provided but not defined. Please refer to the usage by flag -h.") } bundler.IntermediateStash = Config.intDir ubiquity.LoadPlatforms(Config.metadata) err := registerHandlers() if err != nil { return err } addr := fmt.Sprintf("%s:%d", Config.address, Config.port) log.Info("Now listening on ", addr) return http.ListenAndServe(addr, nil) }
// bundlerMain is the main CLI of bundler functionality. // TODO(zi): Decide whether to drop the argument list and only use flags to specify all the inputs. // There are debates on whether flag or arg is more appropriate for required parameters. func bundlerMain(args []string) (err error) { // Grab cert file through args only if flag values for cert and domain are absent if Config.certFile == "" && Config.domain == "" { Config.certFile, args, err = popFirstArgument(args) if err != nil { return } } ubiquity.LoadPlatforms(Config.metadata) flavor := bundler.BundleFlavor(Config.flavor) // Initialize a bundler with CA bundle and intermediate bundle. b, err := bundler.NewBundler(Config.caBundleFile, Config.intBundleFile) if err != nil { return } var bundle *bundler.Bundle if Config.certFile != "" { // Bundle the client cert bundle, err = b.BundleFromFile(Config.certFile, Config.keyFile, flavor) if err != nil { return } } else if Config.domain != "" { bundle, err = b.BundleFromRemote(Config.domain, Config.ip) if err != nil { return } } marshaled, err := bundle.MarshalJSON() if err != nil { return } fmt.Printf("%s", marshaled) return }
// serverMain is the command line entry point to the API server. It sets up a // new HTTP server to handle sign, bundle, and validate requests. func serverMain(args []string, c cli.Config) error { conf = c // serve doesn't support arguments. if len(args) > 0 { return errors.New("argument is provided but not defined; please refer to the usage by flag -h") } bundler.IntermediateStash = conf.IntDir var err error if err = ubiquity.LoadPlatforms(conf.Metadata); err != nil { return err } if c.DBConfigFile != "" { db, err = dbconf.DBFromConfig(c.DBConfigFile) if err != nil { return err } } log.Info("Initializing signer") if s, err = sign.SignerFromConfigAndDB(c, db); err != nil { log.Warningf("couldn't initialize signer: %v", err) } if ocspSigner, err = ocspsign.SignerFromConfig(c); err != nil { log.Warningf("couldn't initialize ocsp signer: %v", err) } registerHandlers() addr := net.JoinHostPort(conf.Address, strconv.Itoa(conf.Port)) if conf.TLSCertFile == "" || conf.TLSKeyFile == "" { log.Info("Now listening on ", addr) return http.ListenAndServe(addr, nil) } if conf.MutualTLSCAFile != "" { clientPool, err := helpers.LoadPEMCertPool(conf.MutualTLSCAFile) if err != nil { return fmt.Errorf("failed to load mutual TLS CA file: %s", err) } server := http.Server{ Addr: addr, TLSConfig: &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: clientPool, }, } if conf.MutualTLSCNRegex != "" { log.Debugf(`Requiring CN matches regex "%s" for client connections`, conf.MutualTLSCNRegex) re, err := regexp.Compile(conf.MutualTLSCNRegex) if err != nil { return fmt.Errorf("malformed CN regex: %s", err) } server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r != nil && r.TLS != nil && len(r.TLS.PeerCertificates) > 0 { if re.MatchString(r.TLS.PeerCertificates[0].Subject.CommonName) { http.DefaultServeMux.ServeHTTP(w, r) return } log.Warningf(`Rejected client cert CN "%s" does not match regex %s`, r.TLS.PeerCertificates[0].Subject.CommonName, conf.MutualTLSCNRegex) } http.Error(w, "Invalid CN", http.StatusForbidden) }) } log.Info("Now listening with mutual TLS on https://", addr) return server.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile) } log.Info("Now listening on https://", addr) return http.ListenAndServeTLS(addr, conf.TLSCertFile, conf.TLSKeyFile, nil) }
// serverMain is the command line entry point to the API server. It sets up a // new HTTP server to handle sign, bundle, and validate requests. func serverMain(args []string, c cli.Config) error { conf = c // serve doesn't support arguments. if len(args) > 0 { return errors.New("argument is provided but not defined; please refer to the usage by flag -h") } bundler.IntermediateStash = conf.IntDir var err error if err = ubiquity.LoadPlatforms(conf.Metadata); err != nil { return err } if c.DBConfigFile != "" { db, err = certdb.DBFromConfig(c.DBConfigFile) if err != nil { return err } } log.Info("Initializing signer") if s, err = sign.SignerFromConfigAndDB(c, db); err != nil { log.Warningf("couldn't initialize signer: %v", err) } if ocspSigner, err = ocspsign.SignerFromConfig(c); err != nil { log.Warningf("couldn't initialize ocsp signer: %v", err) } registerHandlers(conf.Stats) addr := net.JoinHostPort(conf.Address, strconv.Itoa(conf.Port)) if conf.TLSCertFile == "" || conf.TLSKeyFile == "" { log.Info("Now listening on ", addr) return http.ListenAndServe(addr, nil) } log.Info("Now listening on https://", addr) if !conf.RequireClientTLSCertificates { fmt.Printf("Client certificates are not required.\n") return http.ListenAndServeTLS(addr, conf.TLSCertFile, conf.TLSKeyFile, nil) } else { server := &http.Server{ Addr: addr, TLSConfig: &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, }, } fmt.Printf("Client certificates are required.\n") if conf.TrustAnchorFile != "" { fmt.Printf(" tls trust anchors: %s\n", conf.TrustAnchorFile) pem, err := ioutil.ReadFile(conf.TrustAnchorFile) if err != nil { return err } pool := x509.NewCertPool() if !pool.AppendCertsFromPEM(pem) { return fmt.Errorf("Failed to load: %s\n", conf.TrustAnchorFile) } server.TLSConfig.ClientCAs = pool } else { fmt.Printf(" tls trust anchors: <from system>\n") } return server.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile) } }