Example #1
0
func doResponse(conn *tao.Conn) {
	defer conn.Close()

	if conn.Peer() == nil {
		verbose.Printf("netlog: connection from anonymous\n")
	} else {
		verbose.Printf("netlog: connection from peer %s\n", *conn.Peer())
	}

	for {
		req, err := conn.ReadString()
		if err == io.EOF {
			fmt.Fprintf(os.Stderr, "netlog: connection closed\n")
			break
		}
		if err != nil {
			fmt.Fprintf(os.Stderr, "netlog: can't read: %s\n", err)
			break
		}

		verbose.Printf("netlog: got %s request\n", req)

		if req == "POST" {
			if conn.Peer() == nil {
				conn.WriteString("DENIED")
				break
			}
			verbose.Printf("netlog: peer is %s\n", *conn.Peer())
			msg, err := conn.ReadString()
			if err != nil {
				conn.WriteString("BAD")
				break
			}
			e := &netlog.LogEntry{Prin: *conn.Peer(), Msg: msg}
			lock.Lock()
			log = append(log, e)
			lock.Unlock()
			conn.WriteString("OK")
		} else if req == "GET" {
			lock.RLock()
			t := log
			lock.RUnlock()
			conn.WriteString("OK")
			conn.WriteInt(len(t))
			for _, e := range t {
				conn.WriteString(e.Prin.String())
				conn.WriteString(e.Msg)
			}
		} else {
			conn.WriteString("BAD")
			break
		}
	}

	if conn.Peer() == nil {
		verbose.Printf("netlog: connection closed from anonymous\n")
	} else {
		verbose.Printf("netlog: connection closed from peer %s\n", *conn.Peer())
	}
}
Example #2
0
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)
	}
}
Example #3
0
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
}