188 lines
4.7 KiB
Go
188 lines
4.7 KiB
Go
// Copyright 2015 ISRG. All rights reserved
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package sa
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"math"
|
|
"time"
|
|
|
|
jose "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/go-jose"
|
|
"github.com/letsencrypt/boulder/core"
|
|
)
|
|
|
|
var mediumBlobSize = int(math.Pow(2, 24))
|
|
|
|
// regModel is the description of a core.Registration in the database.
|
|
type regModel struct {
|
|
ID int64 `db:"id"`
|
|
Key []byte `db:"jwk"`
|
|
KeySHA256 string `db:"jwk_sha256"`
|
|
Contact []*core.AcmeURL `db:"contact"`
|
|
Agreement string `db:"agreement"`
|
|
LockCol int64
|
|
}
|
|
|
|
// challModel is the description of a core.Challenge in the database
|
|
type challModel struct {
|
|
ID int64 `db:"id"`
|
|
AuthorizationID string `db:"authorizationID"`
|
|
|
|
Type string `db:"type"`
|
|
Status core.AcmeStatus `db:"status"`
|
|
Error []byte `db:"error"`
|
|
Validated *time.Time `db:"validated"`
|
|
URI string `db:"uri"`
|
|
Token string `db:"token"`
|
|
TLS *bool `db:"tls"`
|
|
Validation []byte `db:"validation"`
|
|
ValidationRecord []byte `db:"validationRecord"`
|
|
AccountKey []byte `db:"accountKey"`
|
|
|
|
LockCol int64
|
|
}
|
|
|
|
// newReg creates a reg model object from a core.Registration
|
|
func registrationToModel(r *core.Registration) (*regModel, error) {
|
|
key, err := json.Marshal(r.Key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sha, err := core.KeyDigest(r.Key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rm := ®Model{
|
|
ID: r.ID,
|
|
Key: key,
|
|
KeySHA256: sha,
|
|
Contact: r.Contact,
|
|
Agreement: r.Agreement,
|
|
}
|
|
return rm, nil
|
|
}
|
|
|
|
func modelToRegistration(rm *regModel) (core.Registration, error) {
|
|
k := &jose.JsonWebKey{}
|
|
err := json.Unmarshal(rm.Key, k)
|
|
if err != nil {
|
|
err = fmt.Errorf("unable to unmarshal JsonWebKey in db: %s", err)
|
|
return core.Registration{}, err
|
|
}
|
|
r := core.Registration{
|
|
ID: rm.ID,
|
|
Key: *k,
|
|
Contact: rm.Contact,
|
|
Agreement: rm.Agreement,
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func challengeToModel(c *core.Challenge, authID string) (*challModel, error) {
|
|
cm := challModel{
|
|
AuthorizationID: authID,
|
|
Type: c.Type,
|
|
Status: c.Status,
|
|
Validated: c.Validated,
|
|
Token: c.Token,
|
|
TLS: c.TLS,
|
|
}
|
|
if c.Validation != nil {
|
|
cm.Validation = []byte(c.Validation.FullSerialize())
|
|
if len(cm.Validation) > mediumBlobSize {
|
|
return nil, fmt.Errorf("Validation object is too large to store in the database")
|
|
}
|
|
}
|
|
if c.Error != nil {
|
|
errJSON, err := json.Marshal(c.Error)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(errJSON) > mediumBlobSize {
|
|
return nil, fmt.Errorf("Error object is too large to store in the database")
|
|
}
|
|
cm.Error = errJSON
|
|
}
|
|
if c.URI != nil {
|
|
if len(c.URI.String()) > 255 {
|
|
return nil, fmt.Errorf("URI is too long to store in the database")
|
|
}
|
|
cm.URI = c.URI.String()
|
|
}
|
|
if len(c.ValidationRecord) > 0 {
|
|
vrJSON, err := json.Marshal(c.ValidationRecord)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(vrJSON) > mediumBlobSize {
|
|
return nil, fmt.Errorf("Validation Record object is too large to store in the database")
|
|
}
|
|
cm.ValidationRecord = vrJSON
|
|
}
|
|
if c.AccountKey != nil {
|
|
akJSON, err := json.Marshal(c.AccountKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(akJSON) > mediumBlobSize {
|
|
return nil, fmt.Errorf("Account key object is too large to store in the database")
|
|
}
|
|
cm.AccountKey = akJSON
|
|
}
|
|
return &cm, nil
|
|
}
|
|
|
|
func modelToChallenge(cm *challModel) (core.Challenge, error) {
|
|
c := core.Challenge{
|
|
Type: cm.Type,
|
|
Status: cm.Status,
|
|
Validated: cm.Validated,
|
|
Token: cm.Token,
|
|
TLS: cm.TLS,
|
|
}
|
|
if len(cm.URI) > 0 {
|
|
uri, err := core.ParseAcmeURL(cm.URI)
|
|
if err != nil {
|
|
return core.Challenge{}, err
|
|
}
|
|
c.URI = uri
|
|
}
|
|
if len(cm.Validation) > 0 {
|
|
val, err := jose.ParseSigned(string(cm.Validation))
|
|
if err != nil {
|
|
return core.Challenge{}, err
|
|
}
|
|
c.Validation = val
|
|
}
|
|
if len(cm.Error) > 0 {
|
|
var problem core.ProblemDetails
|
|
err := json.Unmarshal(cm.Error, &problem)
|
|
if err != nil {
|
|
return core.Challenge{}, err
|
|
}
|
|
c.Error = &problem
|
|
}
|
|
if len(cm.ValidationRecord) > 0 {
|
|
var vr []core.ValidationRecord
|
|
err := json.Unmarshal(cm.ValidationRecord, &vr)
|
|
if err != nil {
|
|
return core.Challenge{}, err
|
|
}
|
|
c.ValidationRecord = vr
|
|
}
|
|
if len(cm.AccountKey) > 0 {
|
|
var ak jose.JsonWebKey
|
|
err := json.Unmarshal(cm.AccountKey, &ak)
|
|
if err != nil {
|
|
return core.Challenge{}, err
|
|
}
|
|
c.AccountKey = &ak
|
|
}
|
|
return c, nil
|
|
}
|