package acme import ( "crypto/rand" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/base64" "os" "syscall" ) type Desire struct { altnames []string key *rsa.PrivateKey cert []*x509.Certificate solver map[ChallengeType]Solver webroot string } func NewDesire(altnames []string, webroot string, size int) (*Desire, error) { key, err := rsa.GenerateKey(rand.Reader, size) if err != nil { return nil, err } return &Desire{ key: key, altnames: altnames, solver: make(map[ChallengeType]Solver), webroot: webroot, }, nil } func (d *Desire) RegisterSolver(c ChallengeType, s Solver) { d.solver[c] = s } func backup(fname string) error { err := os.Rename(fname, fname+".bak") if err != nil && err.(*os.LinkError).Err == syscall.ENOENT { return nil } return err } func (d *Desire) Save(cert, key string) error { if err := d.SaveKey(key); err != nil { return err } return d.SaveCert(cert) } func (d *Desire) SaveKey(fname string) error { if err := backup(fname); err != nil { return err } fd, err := CreatePrivFile(fname) if err != nil { return err } defer fd.Close() return SaveKey(fd, d.key) } func (d *Desire) SaveCert(fname string) error { if err := backup(fname); err != nil { return err } fd, err := CreatePubFile(fname) if err != nil { return err } defer fd.Close() for _, crt := range d.cert { if err := SaveCert(fd, crt); err != nil { return err } } return nil } func (d *Desire) newCSR() (string, error) { tmpl := x509.CertificateRequest{ Subject: pkix.Name{CommonName: d.altnames[0]}, } if len(d.altnames) > 1 { tmpl.DNSNames = d.altnames } der, err := x509.CreateCertificateRequest(rand.Reader, &tmpl, d.key) if err != nil { return "", err } return base64.RawURLEncoding.EncodeToString(der), nil } func (d Desire) satisficed(c []Challenge, com []int) bool { for _, n := range com { if _, ok := d.solver[c[n].Type]; !ok { return false } } return true } func (d Desire) pick(a *Authorization) []Challenge { var c []Challenge for _, com := range a.Combinations { if d.satisficed(a.Challenges, com) { for _, n := range com { ch := a.Challenges[n] ch.Solver = d.solver[ch.Type] a.Challenges[n] = ch c = append(c, ch) } return c } } return c }