Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added OCSP worker to retrieve certificate status #286

Closed
wants to merge 12 commits into from
Closed

Added OCSP worker to retrieve certificate status #286

wants to merge 12 commits into from

Conversation

ghost
Copy link

@ghost ghost commented Jan 5, 2018

This is one of my first go projects, so any constructive feedback is appreciated. I know the OCSP code works, but I am not sure if I implemented the worker-releated code correctly.

res <- worker.Result{
Success: false,
WorkerName: workerName,
Result: out,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Errors should be in the Errors field of the worker.Result struct. In case of error Result is nil.

defer conn.Close()

issuerCertificate := conn.ConnectionState().PeerCertificates[1]
certificate := conn.ConnectionState().PeerCertificates[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worker.Input contains all the certificates so the established connection above and all certificate retrieval code is not needed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the worker.Input.CertificateChain.Certs is a string array. How do you covert the strings in the array to a x509 certificate? I need to pass in the website/issuer cert as a x509 when creating the ocsp request.

Copy link
Contributor

@0xdiba 0xdiba Jan 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each entry in the array is a base64 encoding of the raw certificate so all you have to do is :

raw := base64.DecodeString(c) // c being a Certs element
cert := x509.ParseCertificate(raw)

if err != nil {w.error(res, "Could not create OCSP request: %s", err)}

httpResponse, err := http.Post(certificate.OCSPServer[0], "application/ocsp-request", bytes.NewReader(req))
if err != nil {log.Fatal(err)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lose the log.Fatal, report this as an error.


opts := &ocsp.RequestOptions{Hash: crypto.SHA256}
req, err := ocsp.CreateRequest(certificate, issuerCertificate, opts)
if err != nil {w.error(res, "Could not create OCSP request: %s", err)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expand the error handler to multiple lines.
You should also return after the error reporting, so you don't continue to the rest of the code in case of error.

}
}

func (w ocspStatusWorker) error(res chan worker.Result, messageFormat string, args ...interface{}) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think a separate error function is needed.
You could just initialize a new worker.Result in the beginning, in case of error just append to the Errors slice and in case of success just marshal the result in.

@ghost
Copy link
Author

ghost commented Feb 27, 2018

How's this?

Copy link
Contributor

@jvehent jvehent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good. The only comments I have are around coding best practices. The logic is sound.

@@ -0,0 +1,81 @@
package ocspStatusWorker
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove "Worker" from the name, it's already under /worker/

res := worker.Result{WorkerName: workerName, Success:false}

rawCert, _ := base64.StdEncoding.DecodeString(in.CertificateChain.Certs[0])
certificate, _ := x509.ParseCertificate(rawCert)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the end entity is already parsed in in.Certificate

rawCert, _ := base64.StdEncoding.DecodeString(in.CertificateChain.Certs[0])
certificate, _ := x509.ParseCertificate(rawCert)
rawIssuerCert, _ := base64.StdEncoding.DecodeString(in.CertificateChain.Certs[1])
issuerCertificate, _ := x509.ParseCertificate(rawIssuerCert)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should check for errors here.

It might also be worthwhile to make sure the issuer is the right one (that it sign the end-entity) because ordering isn't always guaranteed. You can use CheckSignatureFrom from the x509 package for this.

opts := &ocsp.RequestOptions{Hash: crypto.SHA256}
req, err := ocsp.CreateRequest(certificate, issuerCertificate, opts)
if err != nil {
res.Errors = append(res.Errors, err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errors need to be inserted into the response channel, otherwise they will be dropped. Something like this:

func (w runner) error(res chan worker.Result, messageFormat string, args ...interface{}) {
        out, _ := json.Marshal(fmt.Sprintf(messageFormat, args...))
        res <- worker.Result{
                Success:    false,
                WorkerName: workerName,
                Result:     out,
        }
}

and use it as follows:

        if err != nil {
                w.error(res, "there was an error: %v", err)
                return
        }

res.Errors = append(res.Errors, err.Error())
return
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a defer httpResponse.Body.Close()


status := OCSPStatus{ Status:OCSPResponse.Status, RevokedAt:OCSPResponse.RevokedAt }

out, _ := json.Marshal(status)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't ignore errors, you never know what the OCSP response will contain

@ghost
Copy link
Author

ghost commented Mar 2, 2018

@jvehent It's read to be looked over again.

@jvehent
Copy link
Contributor

jvehent commented Mar 12, 2018

@fr0zenbits : you say it's ready to be reviewed again but I'm not seeing any changes following my review. Are there missing commits?

@adamdecaf adamdecaf mentioned this pull request Apr 14, 2018
@adamdecaf
Copy link
Contributor

@fr0zenbits hey! I took your work in this PR and finished out the OCSP status worker. Hope that's ok. See #336

@ghost ghost closed this Apr 24, 2018
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants