signhandler.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. // Package signhandler provides the handlers for signers.
  2. package signhandler
  3. import (
  4. "encoding/json"
  5. "io/ioutil"
  6. "math/big"
  7. "net/http"
  8. "github.com/cloudflare/cfssl/api"
  9. "github.com/cloudflare/cfssl/auth"
  10. "github.com/cloudflare/cfssl/bundler"
  11. "github.com/cloudflare/cfssl/errors"
  12. "github.com/cloudflare/cfssl/log"
  13. "github.com/cloudflare/cfssl/signer"
  14. )
  15. // NoBundlerMessage is used to alert the user that the server does not have a bundler initialized.
  16. const NoBundlerMessage = `This request requires a bundler, but one is not initialized for the API server.`
  17. // A Handler accepts requests with a hostname and certficate
  18. // parameter (which should be PEM-encoded) and returns a new signed
  19. // certificate. It includes upstream servers indexed by their
  20. // profile name.
  21. type Handler struct {
  22. signer signer.Signer
  23. bundler *bundler.Bundler
  24. }
  25. // NewHandlerFromSigner generates a new Handler directly from
  26. // an existing signer.
  27. func NewHandlerFromSigner(signer signer.Signer) (h *api.HTTPHandler, err error) {
  28. policy := signer.Policy()
  29. if policy == nil {
  30. err = errors.New(errors.PolicyError, errors.InvalidPolicy)
  31. return
  32. }
  33. // Sign will only respond for profiles that have no auth provider.
  34. // So if all of the profiles require authentication, we return an error.
  35. haveUnauth := (policy.Default.Provider == nil)
  36. for _, profile := range policy.Profiles {
  37. haveUnauth = haveUnauth || (profile.Provider == nil)
  38. }
  39. if !haveUnauth {
  40. err = errors.New(errors.PolicyError, errors.InvalidPolicy)
  41. return
  42. }
  43. return &api.HTTPHandler{
  44. Handler: &Handler{
  45. signer: signer,
  46. },
  47. Methods: []string{"POST"},
  48. }, nil
  49. }
  50. // SetBundler allows injecting an optional Bundler into the Handler.
  51. func (h *Handler) SetBundler(caBundleFile, intBundleFile string) (err error) {
  52. h.bundler, err = bundler.NewBundler(caBundleFile, intBundleFile)
  53. return err
  54. }
  55. // This type is meant to be unmarshalled from JSON so that there can be a
  56. // hostname field in the API
  57. // TODO: Change the API such that the normal struct can be used.
  58. type jsonSignRequest struct {
  59. Hostname string `json:"hostname"`
  60. Hosts []string `json:"hosts"`
  61. Request string `json:"certificate_request"`
  62. Subject *signer.Subject `json:"subject,omitempty"`
  63. Profile string `json:"profile"`
  64. Label string `json:"label"`
  65. Serial *big.Int `json:"serial,omitempty"`
  66. Bundle bool `json:"bundle"`
  67. }
  68. func jsonReqToTrue(js jsonSignRequest) signer.SignRequest {
  69. sub := new(signer.Subject)
  70. if js.Subject == nil {
  71. sub = nil
  72. } else {
  73. // make a copy
  74. *sub = *js.Subject
  75. }
  76. if js.Hostname != "" {
  77. return signer.SignRequest{
  78. Hosts: signer.SplitHosts(js.Hostname),
  79. Subject: sub,
  80. Request: js.Request,
  81. Profile: js.Profile,
  82. Label: js.Label,
  83. Serial: js.Serial,
  84. }
  85. }
  86. return signer.SignRequest{
  87. Hosts: js.Hosts,
  88. Subject: sub,
  89. Request: js.Request,
  90. Profile: js.Profile,
  91. Label: js.Label,
  92. Serial: js.Serial,
  93. }
  94. }
  95. // Handle responds to requests for the CA to sign the certificate request
  96. // present in the "certificate_request" parameter for the host named
  97. // in the "hostname" parameter. The certificate should be PEM-encoded. If
  98. // provided, subject information from the "subject" parameter will be used
  99. // in place of the subject information from the CSR.
  100. func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
  101. log.Info("signature request received")
  102. body, err := ioutil.ReadAll(r.Body)
  103. if err != nil {
  104. return err
  105. }
  106. r.Body.Close()
  107. var req jsonSignRequest
  108. err = json.Unmarshal(body, &req)
  109. if err != nil {
  110. return errors.NewBadRequestString("Unable to parse sign request")
  111. }
  112. signReq := jsonReqToTrue(req)
  113. if req.Request == "" {
  114. return errors.NewBadRequestString("missing parameter 'certificate_request'")
  115. }
  116. var cert []byte
  117. profile, err := signer.Profile(h.signer, req.Profile)
  118. if err != nil {
  119. return err
  120. }
  121. if profile.Provider != nil {
  122. log.Error("profile requires authentication")
  123. return errors.NewBadRequestString("authentication required")
  124. }
  125. cert, err = h.signer.Sign(signReq)
  126. if err != nil {
  127. log.Warningf("failed to sign request: %v", err)
  128. return err
  129. }
  130. result := map[string]interface{}{"certificate": string(cert)}
  131. if req.Bundle {
  132. if h.bundler == nil {
  133. return api.SendResponseWithMessage(w, result, NoBundlerMessage,
  134. errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
  135. }
  136. bundle, err := h.bundler.BundleFromPEMorDER(cert, nil, bundler.Optimal, "")
  137. if err != nil {
  138. return err
  139. }
  140. result["bundle"] = bundle
  141. }
  142. log.Info("wrote response")
  143. return api.SendResponse(w, result)
  144. }
  145. // An AuthHandler verifies and signs incoming signature requests.
  146. type AuthHandler struct {
  147. signer signer.Signer
  148. bundler *bundler.Bundler
  149. }
  150. // NewAuthHandlerFromSigner creates a new AuthHandler from the signer
  151. // that is passed in.
  152. func NewAuthHandlerFromSigner(signer signer.Signer) (http.Handler, error) {
  153. policy := signer.Policy()
  154. if policy == nil {
  155. return nil, errors.New(errors.PolicyError, errors.InvalidPolicy)
  156. }
  157. if policy.Default == nil && policy.Profiles == nil {
  158. return nil, errors.New(errors.PolicyError, errors.InvalidPolicy)
  159. }
  160. // AuthSign will not respond for profiles that have no auth provider.
  161. // So if there are no profiles with auth providers in this policy,
  162. // we return an error.
  163. haveAuth := (policy.Default.Provider != nil)
  164. for _, profile := range policy.Profiles {
  165. if haveAuth {
  166. break
  167. }
  168. haveAuth = (profile.Provider != nil)
  169. }
  170. if !haveAuth {
  171. return nil, errors.New(errors.PolicyError, errors.InvalidPolicy)
  172. }
  173. return &api.HTTPHandler{
  174. Handler: &AuthHandler{
  175. signer: signer,
  176. },
  177. Methods: []string{"POST"},
  178. }, nil
  179. }
  180. // SetBundler allows injecting an optional Bundler into the Handler.
  181. func (h *AuthHandler) SetBundler(caBundleFile, intBundleFile string) (err error) {
  182. h.bundler, err = bundler.NewBundler(caBundleFile, intBundleFile)
  183. return err
  184. }
  185. // Handle receives the incoming request, validates it, and processes it.
  186. func (h *AuthHandler) Handle(w http.ResponseWriter, r *http.Request) error {
  187. log.Info("signature request received")
  188. body, err := ioutil.ReadAll(r.Body)
  189. if err != nil {
  190. log.Errorf("failed to read response body: %v", err)
  191. return err
  192. }
  193. r.Body.Close()
  194. var aReq auth.AuthenticatedRequest
  195. err = json.Unmarshal(body, &aReq)
  196. if err != nil {
  197. log.Errorf("failed to unmarshal authenticated request: %v", err)
  198. return errors.NewBadRequest(err)
  199. }
  200. var req jsonSignRequest
  201. err = json.Unmarshal(aReq.Request, &req)
  202. if err != nil {
  203. log.Errorf("failed to unmarshal request from authenticated request: %v", err)
  204. return errors.NewBadRequestString("Unable to parse authenticated sign request")
  205. }
  206. // Sanity checks to ensure that we have a valid policy. This
  207. // should have been checked in NewAuthHandler.
  208. policy := h.signer.Policy()
  209. if policy == nil {
  210. log.Critical("signer was initialised without a signing policy")
  211. return errors.NewBadRequestString("invalid policy")
  212. }
  213. profile, err := signer.Profile(h.signer, req.Profile)
  214. if err != nil {
  215. return err
  216. }
  217. if profile.Provider == nil {
  218. log.Error("profile has no authentication provider")
  219. return errors.NewBadRequestString("no authentication provider")
  220. }
  221. validAuth := false
  222. if profile.Provider.Verify(&aReq) {
  223. validAuth = true
  224. } else if profile.PrevProvider != nil && profile.PrevProvider.Verify(&aReq) {
  225. validAuth = true
  226. }
  227. if !validAuth {
  228. log.Warning("received authenticated request with invalid token")
  229. return errors.NewBadRequestString("invalid token")
  230. }
  231. signReq := jsonReqToTrue(req)
  232. if signReq.Request == "" {
  233. return errors.NewBadRequestString("missing parameter 'certificate_request'")
  234. }
  235. cert, err := h.signer.Sign(signReq)
  236. if err != nil {
  237. log.Errorf("signature failed: %v", err)
  238. return err
  239. }
  240. result := map[string]interface{}{"certificate": string(cert)}
  241. if req.Bundle {
  242. if h.bundler == nil {
  243. return api.SendResponseWithMessage(w, result, NoBundlerMessage,
  244. errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
  245. }
  246. bundle, err := h.bundler.BundleFromPEMorDER(cert, nil, bundler.Optimal, "")
  247. if err != nil {
  248. return err
  249. }
  250. result["bundle"] = bundle
  251. }
  252. log.Info("wrote response")
  253. return api.SendResponse(w, result)
  254. }