@@ -21,9 +21,7 @@ import (
2121
2222 "github.com/letsencrypt/cactus/ca"
2323 "github.com/letsencrypt/cactus/cert"
24- "github.com/letsencrypt/cactus/landmark"
2524 cactusmetrics "github.com/letsencrypt/cactus/metrics"
26- "github.com/letsencrypt/cactus/tlogx"
2725)
2826
2927// ChallengeMode controls how challenges are validated.
@@ -52,31 +50,15 @@ type Config struct {
5250 // "invalid" on failure. Optional.
5351 OrdersByStatus cactusmetrics.CounterVec
5452
55- // Landmarks, if non-nil, enables the alternate-URL
56- // switchover: GET /cert/{id}/alternate returns a real
57- // landmark-relative cert once a covering landmark exists.
58- // Otherwise the alternate URL keeps the §9-permitted 503 stub.
59- Landmarks * landmark.Sequence
60-
61- // SubtreeProof, if set, is used to compute inclusion proofs for
62- // landmark-relative cert assembly. Must be set whenever
63- // Landmarks is. Typically `(*log.Log).SubtreeProof`.
64- SubtreeProof func (start , end , index uint64 ) (tlogx.Hash , []tlogx.Hash , error )
65-
66- // LogID is the issuance log's trust anchor ID (§5.2). Required
67- // only when Landmarks is set (and for the standalone-cert
68- // `trust_anchor_id` property emitted in
69- // application/pem-certificate-chain-with-properties).
53+ // LogID is the issuance log's trust anchor ID (§5.2). Used as the
54+ // fallback for the standalone-cert `trust_anchor_id` property
55+ // emitted in application/pem-certificate-chain-with-properties when
56+ // CAID is unset.
7057 LogID cert.TrustAnchorID
7158
72- // CAID is the CA's CA ID (§5.1). Required whenever Landmarks is set;
73- // landmark trust anchor IDs are derived from it and LogNumber
74- // (CA-ID.1.logNumber.L, §6.3.1).
59+ // CAID is the CA's CA ID (§5.1). Emitted as the standalone cert's
60+ // `trust_anchor_id` property (draft-04 §8.1).
7561 CAID cert.TrustAnchorID
76-
77- // LogNumber is the issuance log's number (§5.2). Required whenever
78- // Landmarks is set.
79- LogNumber uint16
8062}
8163
8264// Server is the ACME HTTP server.
@@ -130,7 +112,6 @@ func (s *Server) Handler() http.Handler {
130112 mux .HandleFunc ("POST /order/{id}" , s .handleOrder )
131113 mux .HandleFunc ("POST /finalize/{id}" , s .handleFinalize )
132114 mux .HandleFunc ("POST /cert/{id}" , s .handleCert )
133- mux .HandleFunc ("POST /cert/{id}/alternate" , s .handleCertAlternate )
134115 return mux
135116}
136117
@@ -975,7 +956,6 @@ func (s *Server) handleFinalize(w http.ResponseWriter, r *http.Request) {
975956 w .Header ().Set ("Location" , loc )
976957 s .issueNonce (w )
977958 w .Header ().Set ("Content-Type" , "application/json" )
978- w .Header ().Set ("Link" , `<` + s .urlFor ("/cert/" + certID + "/alternate" )+ `>;rel="alternate"` )
979959 _ = json .NewEncoder (w ).Encode (s .orderJSON (o ))
980960}
981961
@@ -1005,7 +985,6 @@ func (s *Server) handleCert(w http.ResponseWriter, r *http.Request) {
1005985 }
1006986 s .issueNonce (w )
1007987 accept := r .Header .Get ("Accept" )
1008- w .Header ().Set ("Link" , `<` + s .urlFor ("/cert/" + id + "/alternate" )+ `>;rel="alternate"` )
1009988 if strings .Contains (accept , "application/pem-certificate-chain-with-properties" ) {
1010989 w .Header ().Set ("Content-Type" , "application/pem-certificate-chain-with-properties" )
1011990 // Standalone cert: the trust_anchor_id property naming the CA
@@ -1037,126 +1016,6 @@ func (s *Server) handleCert(w http.ResponseWriter, r *http.Request) {
10371016 pem .Encode (w , & pem.Block {Type : "CERTIFICATE" , Bytes : der })
10381017}
10391018
1040- // handleCertAlternate returns the landmark-relative cert for
1041- // the given cert id, falling back to 503 + Retry-After (the
1042- // §9-permitted stub) when a covering landmark hasn't been allocated yet
1043- // or when landmark mode is disabled.
1044- func (s * Server ) handleCertAlternate (w http.ResponseWriter , r * http.Request ) {
1045- id := r .PathValue ("id" )
1046- parsed , acct , err := s .readJWS (r , true )
1047- if err != nil {
1048- s .writeJWSError (w , err )
1049- return
1050- }
1051- if ! EmptyPayloadOK (parsed .Payload ) {
1052- s .problem (w , http .StatusBadRequest , "urn:ietf:params:acme:error:malformed" ,
1053- "cert download must be POST-as-GET (empty payload)" )
1054- return
1055- }
1056- s .state .mu .Lock ()
1057- standalone , ok := s .certs [id ]
1058- s .state .mu .Unlock ()
1059- if ! ok {
1060- s .problem (w , http .StatusNotFound , "urn:ietf:params:acme:error:malformed" , "no certificate" )
1061- return
1062- }
1063- if ! s .certBelongsToAccount (id , acct .ID ) {
1064- s .problem (w , http .StatusUnauthorized , "urn:ietf:params:acme:error:unauthorized" ,
1065- "certificate does not belong to this account" )
1066- return
1067- }
1068- s .issueNonce (w )
1069-
1070- // Pull the serial out of the standalone cert and split off the log
1071- // index: draft-04 §6.1, serial = (log_number << 48) | index.
1072- tbs , _ , _ , err := cert .SplitCertificate (standalone )
1073- if err != nil {
1074- http .Error (w , "split cert: " + err .Error (), http .StatusInternalServerError )
1075- return
1076- }
1077- _ , serial , err := cert .RebuildLogEntryFromTBS (tbs , nil )
1078- if err != nil {
1079- http .Error (w , "decode TBS: " + err .Error (), http .StatusInternalServerError )
1080- return
1081- }
1082- _ , index , err := cert .SplitSerial (serial )
1083- if err != nil {
1084- http .Error (w , "decode serial: " + err .Error (), http .StatusInternalServerError )
1085- return
1086- }
1087-
1088- if s .cfg .Landmarks == nil || s .cfg .SubtreeProof == nil {
1089- s .serveAltStub (w )
1090- return
1091- }
1092-
1093- lm , ok := s .cfg .Landmarks .ContainingIndex (index )
1094- if ! ok {
1095- s .serveAltStub (w )
1096- return
1097- }
1098-
1099- // Pick the §4.5 covering subtree of [prev_treeSize, lm.TreeSize)
1100- // that contains the entry index.
1101- subtrees := s .cfg .Landmarks .LandmarkSubtrees (lm )
1102- var chosen tlogx.Subtree
1103- for _ , st := range subtrees {
1104- if index >= st .Start && index < st .End {
1105- chosen = st
1106- break
1107- }
1108- }
1109- if chosen .End == 0 {
1110- // Inconsistent state: ContainingIndex said yes but no covering
1111- // subtree contains the index. Treat as not-yet-available.
1112- s .serveAltStub (w )
1113- return
1114- }
1115-
1116- subtreeHash , proof , err := s .cfg .SubtreeProof (chosen .Start , chosen .End , index )
1117- if err != nil {
1118- http .Error (w , "subtree proof: " + err .Error (), http .StatusInternalServerError )
1119- return
1120- }
1121-
1122- mtcSubtree := cert.MTCSubtree {
1123- LogID : s .cfg .LogID ,
1124- Start : chosen .Start , End : chosen .End ,
1125- Hash : subtreeHash ,
1126- }
1127- der , err := cert .BuildLandmarkRelativeCert (standalone , s .cfg .LogID , mtcSubtree , proof )
1128- if err != nil {
1129- http .Error (w , "build landmark cert: " + err .Error (), http .StatusInternalServerError )
1130- return
1131- }
1132-
1133- accept := r .Header .Get ("Accept" )
1134- if strings .Contains (accept , "application/pem-certificate-chain-with-properties" ) {
1135- w .Header ().Set ("Content-Type" , "application/pem-certificate-chain-with-properties" )
1136- // draft-04 §8.2: a landmark-relative certificate's trust anchor
1137- // ID is the individual landmark ID (CA-ID.1.logNumber.L).
1138- // Relying parties advertise a landmark group (§8.2.1) instead.
1139- props := []cert.CertificateProperty {
1140- {Type : cert .PropertyTrustAnchorID , TrustAnchorID : lm .TrustAnchorID (s .cfg .CAID , s .cfg .LogNumber )},
1141- }
1142- pl , err := cert .BuildPropertyList (props )
1143- if err != nil {
1144- http .Error (w , "build properties: " + err .Error (), http .StatusInternalServerError )
1145- return
1146- }
1147- w .Write (cert .EncodePEMWithProperties (der , pl ))
1148- return
1149- }
1150- w .Header ().Set ("Content-Type" , "application/pem-certificate-chain" )
1151- pem .Encode (w , & pem.Block {Type : "CERTIFICATE" , Bytes : der })
1152- }
1153-
1154- // serveAltStub is the §9-permitted "not yet available" response.
1155- func (s * Server ) serveAltStub (w http.ResponseWriter ) {
1156- w .Header ().Set ("Retry-After" , "3600" )
1157- http .Error (w , "landmark-relative certificate not yet available" , http .StatusServiceUnavailable )
1158- }
1159-
11601019// certBelongsToAccount returns true if the cert with the given id is
11611020// the certificate produced for an order whose AccountID matches.
11621021func (s * Server ) certBelongsToAccount (certID , accountID string ) bool {
0 commit comments