Example #1
0
func ConfirmName(n *pkix.Name) *pkix.Name {
	return &pkix.Name{
		Country:            options.ConfirmN("Country", n.Country),
		Province:           options.ConfirmN("State or Province Name", n.Province),
		Locality:           options.ConfirmN("City or Locality Name", n.Locality),
		Organization:       options.ConfirmN("Organization Name (e.g. company)", n.Organization),
		OrganizationalUnit: options.ConfirmN("Organization UnitName (e.g. section)", n.OrganizationalUnit),
		CommonName:         options.Confirm("Common Name", n.CommonName),
	}
}
Example #2
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
}