func doResponses(conn *tao.Conn) { defer conn.Close() var peer *string if conn.Peer() != nil { peer = proto.String(conn.Peer().String()) verbose.Printf("Processing connection requests for peer %s\n", *peer) netlog.Log("rendezvous: connection from peer %s", *peer) } else { verbose.Printf("Processing connection requests for anonymous peer\n") netlog.Log("rendezvous: connection from anonymous") } for { var req rendezvous.Request if err := conn.ReadMessage(&req); err != nil { if err != io.EOF { doError(conn, err, rendezvous.ResponseStatus_RENDEZVOUS_BAD_REQUEST, "failed to read request") } break } doResponse(&req, conn, peer) } lock.Lock() for k, v := range bindings { if v.expiration.IsZero() && v.conn == conn { delete(bindings, k) verbose.Printf("Expired binding upon close: %s\n", k) } } lock.Unlock() verbose.Println("Done processing connection requests") if peer == nil { netlog.Log("rendezvous: connection closed from anonymous") } else { netlog.Log("rendezvous: connection closed from peer %s", *peer) } }
func main() { verbose.Set(true) options.Parse() if *options.String["config"] != "" && !*options.Bool["init"] { err := options.Load(*options.String["config"]) options.FailIf(err, "Can't load configuration") } if *options.Bool["init"] { cpath := *options.String["config"] if cpath == "" { options.Fail(nil, "Option -init requires option -config") } fmt.Println("Initializing configuration file: " + cpath) err := options.Save(cpath, "Tao rendezvous configuration", "persistent") options.FailIf(err, "Can't save configuration") } fmt.Println("Cloudproxy Rendezvous Service") if tao.Parent() == nil { options.Fail(nil, "can't continue: no host Tao available") } allowAnon = *options.Bool["anon"] manualMode = *options.Bool["manual"] fcfsMode = *options.Bool["fcfs"] addr := *options.String["addr"] netlog.Log("rendezvous: init") netlog.Log("rendezvous: allow anon? %v", allowAnon) netlog.Log("rendezvous: manual? %v", manualMode) netlog.Log("rendezvous: fcfs? %v", fcfsMode) netlog.Log("rendezvous: addr = %v", addr) // TODO(kwalsh) extend tao name with operating mode and policy err := tao.NewOpenServer(tao.ConnHandlerFunc(doResponses)).ListenAndServe(addr) options.FailIf(err, "server died") netlog.Log("rendezvous: done") }
func main() { verbose.Set(true) options.Parse() profiling.ProfilePath = *options.String["profile"] if !verbose.Enabled { taoca.ConfirmNames = false } if *options.String["config"] != "" && !*options.Bool["init"] { err := options.Load(*options.String["config"]) options.FailIf(err, "Can't load configuration") } fmt.Println("https/tls Certificate Authority") manualMode = *options.Bool["manual"] learnMode = *options.Bool["learn"] if !manualMode && tao.Parent() == nil { options.Fail(nil, "can't continue: automatic mode, but no host Tao available") } if *options.Bool["root"] == (*options.String["subsidiary"] != "") { options.Usage("must supply exactly one of -root or -subsidiary options") } host := *options.String["host"] port := *options.String["port"] addr := net.JoinHostPort(host, port) // TODO(kwalsh) extend tao name with operating mode and policy cpath := *options.String["config"] kdir := *options.String["keys"] if kdir == "" && cpath != "" { kdir = path.Dir(cpath) } else if kdir == "" { options.Fail(nil, "Option -keys or -config is required") } ppath := path.Join(kdir, "policy") var err error if *options.Bool["init"] { if cpath != "" { err := options.Save(cpath, "HTTPS/TLS certificate authority configuration", "persistent") options.FailIf(err, "Can't save configuration") } fmt.Println("" + "Initializing fresh HTTP/TLS CA signing key. Provide the following information,\n" + "to be include in the CA's own x509 certificate. Leave the response blank to\n" + "accept the default value.\n" + "\n" + "Configuration file: " + cpath + "\n" + "Keys directory: " + kdir + "\n") var caName *pkix.Name if taoca.ConfirmNames { if *options.Bool["root"] { caName = taoca.ConfirmName(caRootName) } else { caName = taoca.ConfirmName(caSubsidiaryName) } } else { if *options.Bool["root"] { caName = caRootName } else { caName = caSubsidiaryName } } if manualMode { pwd := options.Password("Choose an HTTPS/TLS CA signing key password", "pass") caKeys, err = tao.InitOnDiskPBEKeys(tao.Signing, pwd, kdir, caName) tao.ZeroBytes(pwd) } else { caKeys, err = tao.InitOnDiskTaoSealedKeys(tao.Signing, caName, tao.Parent(), kdir, tao.SealPolicyDefault) } options.FailIf(err, "Can't initialize fresh HTTPS/TLS CA signing key") if *options.Bool["root"] { fmt.Printf(""+ "Note: To install this CA's key in the Chrome browser, go to\n"+ " 'Settings', 'Show advanced settings...', 'Manage Certificates...', 'Authorities'\n"+ " then import the following file:\n"+ " %s\n"+ " Select 'Trust this certificate for identifying websites' and/or other\n"+ " options, then click 'OK'\n", caKeys.X509Path("default")) } else { csr := taoca.NewCertificateSigningRequest(caKeys.VerifyingKey, caName) *csr.IsCa = true srv := *options.String["subsidiary"] taoca.DefaultServerName = srv taoca.SubmitAndInstall(caKeys, csr) } if !manualMode { f, err := os.Open(ppath) if err == nil { f.Close() fmt.Printf("Using existing certificate-granting policy: %s\n", ppath) } else { fmt.Printf("Creating default certificate-granting policy: %s\n", ppath) fmt.Printf("Edit that file to define the certificate-granting policy.\n") err := util.WritePath(ppath, []byte(policy.Default), 0755, 0755) options.FailIf(err, "Can't save policy rules") } } } else { if manualMode { pwd := options.Password("HTTPS/TLS CA signing key password", "pass") caKeys, err = tao.LoadOnDiskPBEKeys(tao.Signing, pwd, kdir) tao.ZeroBytes(pwd) } else { caKeys, err = tao.LoadOnDiskTaoSealedKeys(tao.Signing, tao.Parent(), kdir, tao.SealPolicyDefault) } options.FailIf(err, "Can't load HTTP/TLS CA signing key") } netlog.Log("https_ca: start") netlog.Log("https_ca: manual? %v", manualMode) if !manualMode { guard, err = policy.Load(ppath) options.FailIf(err, "Can't load certificate-granting policy") } var prin auth.Prin if tao.Parent() != nil { prin, err = tao.Parent().GetTaoName() options.FailIf(err, "Can't get tao name") } else { rendezvous.DefaultServer.Connect(caKeys) prin = caKeys.SigningKey.ToPrincipal() } name := *options.String["name"] if name != "" { err = rendezvous.Register(rendezvous.Binding{ Name: proto.String(name), Host: proto.String(host), Port: proto.String(port), Protocol: proto.String("protoc/rpc/https_ca"), Principal: proto.String(prin.String()), }) options.FailIf(err, "Can't register with rendezvous service") } statsdelay := *options.String["stats"] var srv *tao.Server if statsdelay != "" { go profiling.ShowStats(&stats, statsdelay, "sign certificates") srv = tao.NewOpenServer(tao.ConnHandlerFunc(doResponseWithStats)) } else { srv = tao.NewOpenServer(tao.ConnHandlerFunc(doResponseWithoutStats)) } srv.Keys = caKeys fmt.Printf("Listening at %s using Tao-authenticated channels\n", addr) err = srv.ListenAndServe(addr) options.FailIf(err, "server died") fmt.Println("Server Done") netlog.Log("https_ca: done") }
func doResponse(conn *tao.Conn) bool { // conn.Trace = tao.NewTrace(6, 1) T := profiling.NewTrace(10, 1) T.Start() defer conn.Close() var req taoca.Request if err := conn.ReadMessage(&req); err != nil { doError(conn, err, taoca.ResponseStatus_TAOCA_BAD_REQUEST, "failed to read request") return false } T.Sample("got msg") // 1 peer := "anonymous" if conn.Peer() != nil { peer = conn.Peer().String() } T.Sample("got peer") // 2 var errmsg string // Check whether the CSR is well-formed name := req.CSR.Name sanitize(name.Country, "Country", &errmsg) sanitize(name.State, "State/Province", &errmsg) sanitize(name.City, "City/Locality", &errmsg) sanitize(name.Organization, "Organization", &errmsg) ou := sanitize(name.OrganizationalUnit, "OrganizationalUnit", &errmsg) cn := sanitize(name.CommonName, "CommonName", &errmsg) years := *req.CSR.Years if years <= 0 { errmsg = "invalid validity period" } if errmsg != "" { doError(conn, nil, taoca.ResponseStatus_TAOCA_BAD_REQUEST, errmsg) return false } T.Sample("sanitized") // 3 var ck tao.CryptoKey if err := proto.Unmarshal(req.CSR.PublicKey, &ck); err != nil { doError(conn, err, taoca.ResponseStatus_TAOCA_BAD_REQUEST, "can't unmarshal key") return false } subjectKey, err := tao.UnmarshalVerifierProto(&ck) if err != nil { doError(conn, err, taoca.ResponseStatus_TAOCA_BAD_REQUEST, "can't unmarshal key") return false } T.Sample("got subject") // 4 // TODO(kwalsh) more robust generation of serial numbers? var serial int64 if err := binary.Read(rand.Reader, binary.LittleEndian, &serial); err != nil { doError(conn, err, taoca.ResponseStatus_TAOCA_ERROR, "could not generate random serial number") } if serial < 0 { serial = ^serial } T.Sample("made serial") // 5 if verbose.Enabled { printRequest(&req, subjectKey, serial, peer) } var cps, unotice string if manualMode { lock.Lock() var ok string for { ok = options.Confirm("Approve this request?", "no") if ok == "yes" || ok == "no" { break } fmt.Printf("I don't understand %q. Please type yes or no.\n", ok) } lock.Unlock() if ok != "yes" { doError(conn, nil, taoca.ResponseStatus_TAOCA_REQUEST_DENIED, "request is denied") return false } fmt.Printf("Issuing certificate.\n") cps = cpsTemplate + cpsManual } else { // Consult guard to enforce policy. if conn.Peer() == nil { doError(conn, nil, taoca.ResponseStatus_TAOCA_REQUEST_DENIED, "anonymous request is denied") return false } if learnMode { prin := *conn.Peer() if len(prin.Ext) > 0 { last := prin.Ext[len(prin.Ext)-1] tail := auth.PrinTail{ Ext: auth.SubPrin([]auth.PrinExt{last}), } prinHash := fmt.Sprintf("Known(%v)", tail) if !knownHashes[prinHash] { fmt.Printf("Learned: %s\n", prinHash) knownHashes[prinHash] = true if err := guard.AddRule(prinHash); err != nil { fmt.Println("Error adding rule: %s\n", err) } } } } if !guard.IsAuthorized(*conn.Peer(), "ClaimCertificate", []string{*name.OrganizationalUnit, *name.CommonName}) && !guard.IsAuthorized(*conn.Peer(), "ClaimCertificate", nil) { fmt.Printf("Policy (as follows) does not allow this request\n") fmt.Printf("%s\n", guard.String()) doError(conn, nil, taoca.ResponseStatus_TAOCA_REQUEST_DENIED, "request is denied") return false } if _, ok := guard.(*tao.ACLGuard); ok { cps = cpsTemplate + cpsACL } else { cps = cpsTemplate + cpsDatalog } cps += "\n" + guard.String() } T.Sample("authenticated") // 6 if conn.Peer() != nil { unotice = fmt.Sprintf(unoticeTemplate+ "* The certificate was requested by the following Tao principal:\n\n %v\n", *conn.Peer()) } else { unotice = fmt.Sprintf(unoticeTemplate + "* The certificate was requested anonymously.\n") } cpsUrl, err := publish([]byte(cps)) unoticeUrl, err := publish([]byte(unotice)) // ext, err := taoca.NewUserNotice("Hello user, how are you?") ext, err := taoca.NewCertficationPolicy(cpsUrl, unoticeUrl) if err != nil { doError(conn, err, taoca.ResponseStatus_TAOCA_ERROR, "failed to generate certificate policy extension") return false } T.Sample("made cps") // 7 netlog.Log("https_ca: issuing certificate for ou=%q cn=%q to %s", ou, cn, peer) template := caKeys.SigningKey.X509Template(NewX509Name(name), ext) template.IsCA = *req.CSR.IsCa template.SerialNumber.SetInt64(serial) cert, err := caKeys.CreateSignedX509(subjectKey, template, "default") if err != nil { doError(conn, err, taoca.ResponseStatus_TAOCA_ERROR, "failed to generate certificate") return false } T.Sample("signed cert") // 8 status := taoca.ResponseStatus_TAOCA_OK resp := &taoca.Response{ Status: &status, Cert: []*taoca.Cert{&taoca.Cert{X509Cert: cert.Raw}}, } for _, parent := range caKeys.CertChain("default") { resp.Cert = append(resp.Cert, &taoca.Cert{X509Cert: parent.Raw}) } T.Sample("built response") // 9 sendResponse(conn, resp) T.Sample("sent response") // 10 //fmt.Println(T) return true }