// SendMessage divides a message into cells and sends each cell over the network // connection. A message is signaled to the receiver by the first byte of the // first cell. The next few bytes encode the total number of bytes in the // message. func (p *ProxyContext) SendMessage(c *Conn, msg []byte) error { msgBytes := len(msg) cell := make([]byte, CellBytes) cell[0] = msgCell n := binary.PutUvarint(cell[1:], uint64(msgBytes)) bytes := copy(cell[1+n:], msg) if _, err := c.Write(cell); err != nil { return err } for bytes < msgBytes { tao.ZeroBytes(cell) cell[0] = msgCell bytes += copy(cell[1:], msg[bytes:]) if _, err := c.Write(cell); err != nil { return err } } return nil }
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 main() { caAddr := flag.String("caAddr", "localhost:8124", "The address of the CA for setting up a certificate signed by the policy key") hostcfg := flag.String("hostconfig", "tao.config", "path to host tao configuration") serverHost := flag.String("host", "localhost", "address for client/server") serverPort := flag.String("port", "8123", "port for client/server") fileServerPath := flag.String("fileserver_files", "fileserver_files/", "fileserver directory") fileServerFilePath := flag.String("stored_files", "fileserver_files/stored_files/", "fileserver directory") country := flag.String("country", "US", "The country for the fileclient certificate") org := flag.String("organization", "Google", "The organization for the fileclient certificate") flag.Parse() serverAddr := net.JoinHostPort(*serverHost, *serverPort) hostDomain, err := tao.LoadDomain(*hostcfg, nil) if err != nil { log.Fatalln("fileserver: can't LoadDomain") } var policyCert []byte if hostDomain.Keys.Cert != nil { policyCert = hostDomain.Keys.Cert.Raw } if policyCert == nil { log.Fatalln("fileserver: can't retrieve policy cert") } parentTao := tao.Parent() if err := hostDomain.ExtendTaoName(parentTao); err != nil { log.Fatalln("fileserver: can't extend the Tao with the policy key") } e := auth.PrinExt{Name: "fileserver_version_1"} if err = parentTao.ExtendTaoName(auth.SubPrin{e}); err != nil { log.Fatalln("fileserver: couldn't extend the Tao name") } taoName, err := parentTao.GetTaoName() if err != nil { log.Fatalln("fileserver: couldn't get tao name") } // Create or read the keys for fileclient. fsKeys, err := tao.NewOnDiskTaoSealedKeys(tao.Signing|tao.Crypting, parentTao, *fileServerPath, tao.SealPolicyDefault) if err != nil { log.Fatalln("fileserver: couldn't set up the Tao-sealed keys:", err) } // Set up a temporary cert for communication with keyNegoServer. fsKeys.Cert, err = fsKeys.SigningKey.CreateSelfSignedX509(tao.NewX509Name(&tao.X509Details{ Country: proto.String(*country), Organization: proto.String(*org), CommonName: proto.String(taoName.String()), })) if err != nil { log.Fatalln("fileserver: couldn't create a self-signed cert for fileclient keys:", err) } // Contact keyNegoServer for the certificate. if err := fileproxy.EstablishCert("tcp", *caAddr, fsKeys, hostDomain.Keys.VerifyingKey); err != nil { log.Fatalf("fileserver: couldn't establish a cert signed by the policy key: %s", err) } symKeysPath := path.Join(*fileServerPath, "sealedEncKeys") symKeys, err := fsKeys.NewSecret(symKeysPath, fileproxy.SymmetricKeySize) if err != nil { log.Fatalln("fileserver: couldn't get the file encryption keys") } tao.ZeroBytes(symKeys) progPolicy := fileproxy.NewProgramPolicy(policyCert, taoName.String(), fsKeys, symKeys, fsKeys.Cert.Raw) // Set up the file storage path if it doesn't exist. if _, err := os.Stat(*fileServerFilePath); err != nil { if err := os.MkdirAll(*fileServerFilePath, 0700); err != nil { log.Fatalln("fileserver: couldn't create a file storage directory:", err) } } if err := serve(serverAddr, *fileServerFilePath, policyCert, fsKeys, progPolicy); err != nil { log.Fatalln("fileserver: couldn't serve connections:", err) } log.Printf("fileserver: done\n") }
// HandleProxy reads a directive or a message from a proxy. func (hp *RouterContext) HandleProxy(c *Conn) error { var err error cell := make([]byte, CellBytes) if _, err = c.Read(cell); err != nil && err != io.EOF { return err } hp.replyQueue.SetConn(c.id, c) hp.replyQueue.SetAddr(c.id, c.RemoteAddr().String()) if cell[0] == msgCell { // If this router is an exit point, then read cells until the whole // message is assembled and add it to sendQueue. If this router is // a relay (not implemented), then just add the cell to the // sendQueue. msgBytes, n := binary.Uvarint(cell[1:]) if msgBytes > MaxMsgBytes { if err = hp.SendError(c, errMsgLength); err != nil { return err } return nil } msg := make([]byte, msgBytes) bytes := copy(msg, cell[1+n:]) // While the connection is open and the message is incomplete, read // the next cell. for err != io.EOF && uint64(bytes) < msgBytes { if _, err = c.Read(cell); err != nil && err != io.EOF { return err } else if cell[0] != msgCell { return errCellType } bytes += copy(msg[bytes:], cell[1:]) } // Wait for a message from the destination, divide it into cells, // and add the cells to replyQueue. reply := make(chan []byte) hp.sendQueue.EnqueueMsgReply(c.id, msg, reply) msg = <-reply if msg != nil { tao.ZeroBytes(cell) msgBytes := len(msg) cell[0] = msgCell n := binary.PutUvarint(cell[1:], uint64(msgBytes)) bytes := copy(cell[1+n:], msg) hp.replyQueue.EnqueueMsg(c.id, cell) for bytes < msgBytes { tao.ZeroBytes(cell) cell[0] = msgCell bytes += copy(cell[1:], msg[bytes:]) hp.replyQueue.EnqueueMsg(c.id, cell) } } } else if cell[0] == dirCell { // Handle a directive. dirBytes, n := binary.Uvarint(cell[1:]) var d Directive if err := proto.Unmarshal(cell[1+n:1+n+int(dirBytes)], &d); err != nil { return err } if *d.Type == DirectiveType_CREATE { // Add next hop for this circuit to sendQueue and send a CREATED // directive to sender to inform the sender. TODO(cjpatton) For // now, only single hop circuits are supported. if len(d.Addrs) == 0 { if err = hp.SendError(c, errBadDirective); err != nil { return err } return nil } if len(d.Addrs) > 1 { if err = hp.SendError(c, errors.New("multi-hop circuits not implemented")); err != nil { return err } return nil } hp.sendQueue.SetAddr(c.id, d.Addrs[0]) cell, err = marshalDirective(dirCreated) if err != nil { return err } hp.replyQueue.EnqueueMsg(c.id, cell) } else if *d.Type == DirectiveType_DESTROY { // TODO(cjpatton) when multi-hop circuits are implemented, send // a DESTROY directive to the next hop and wait for DESTROYED in // response. For now, just close the connection to the circuit. hp.sendQueue.Close(c.id) hp.replyQueue.Close(c.id) return io.EOF } } else { // Unknown cell type, return an error. if err = hp.SendError(c, errBadCellType); err != nil { return err } } return nil }