package acme import ( "crypto/sha256" "encoding/hex" "time" ) // Challege ... type Challenge struct { Resource Resource `json:"resource"` // challenge Type ChalType `json:"type"` Token string `json:"token,omitempty"` Status Status `json:"status,omitempty"` // e.g. valid URI string `json:"uri,omitempty"` Validated *time.Time `json:"validated,omitempty"` KeyAuthorization string `json:"keyAuthorization,omitempty"` Err *Problem `json:"error,omitempty"` } const AcmeInvalid = `.acme.invalid` // SNIName returns a new SNI name based on KeyAuthorization func (c Challenge) SNIName() string { hash := sha256.Sum256([]byte(c.KeyAuthorization)) z := hex.EncodeToString(hash[:]) return z[:32] + "." + z[32:] + AcmeInvalid } // Status of request type Status string // Statuses const ( StatusUnknown Status = "unknown" StatusPending Status = "pending" StatusProcessing Status = "processing" StatusValid Status = "valid" StatusInvalid Status = "invalid" StatusRevoked Status = "revoked" ) type ChalType string const ( ChallengeHTTP ChalType = "http-01" ChallengeTLS ChalType = "tls-sni-01" ChallengePOP ChalType = "proofOfPossession-01" ChallengeDNS ChalType = "dns-01" ) func (p *Provider) Solve(ch Challenge, sol Solver) error { // update challenge ch.Resource = ResChallenge ch.KeyAuthorization = p.KeyAuth(ch.Token) // prepare solver if err := sol.Solve(ch); err != nil { return err } defer sol.Solved() resp, err := p.postJson(ch.URI, ch) if err != nil { return err } ns := parseHeader(resp) return p.pollStatus(ns.Location) } func (p *Provider) pollStatus(uri string) error { t := time.NewTicker(poll) defer t.Stop() for range t.C { resp, err := p.Get(uri) if err != nil { return err } req := new(Challenge) err = parseJson(resp, req) if err != nil { return err } if req.Err != nil { return req.Err } if req.Status == StatusValid { return nil } } return nil }