Пример #1
0
// 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
}
Пример #2
0
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")
}
Пример #3
0
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")
}
Пример #4
0
// 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
}