diff --git a/cmd/sts-errors.go b/cmd/sts-errors.go index 159331e8e..c68b68f1d 100644 --- a/cmd/sts-errors.go +++ b/cmd/sts-errors.go @@ -81,6 +81,7 @@ const ( ErrSTSMalformedPolicyDocument ErrSTSInsecureConnection ErrSTSInvalidClientCertificate + ErrSTSTooManyIntermediateCAs ErrSTSNotInitialized ErrSTSIAMNotInitialized ErrSTSUpstreamError @@ -145,6 +146,11 @@ var stsErrCodes = stsErrorCodeMap{ Description: "The provided client certificate is invalid. Retry with a different certificate.", HTTPStatusCode: http.StatusBadRequest, }, + ErrSTSTooManyIntermediateCAs: { + Code: "TooManyIntermediateCAs", + Description: "The provided client certificate contains too many intermediate CA certificates", + HTTPStatusCode: http.StatusBadRequest, + }, ErrSTSNotInitialized: { Code: "STSNotInitialized", Description: "STS API not initialized, please try again.", diff --git a/cmd/sts-handlers.go b/cmd/sts-handlers.go index 10621d064..c2b1fa172 100644 --- a/cmd/sts-handlers.go +++ b/cmd/sts-handlers.go @@ -780,12 +780,26 @@ func (sts *stsAPIHandlers) AssumeRoleWithCertificate(w http.ResponseWriter, r *h // policy mapping would be ambiguous. // However, we can filter all CA certificates and only check // whether they client has sent exactly one (non-CA) leaf certificate. - peerCertificates := make([]*x509.Certificate, 0, len(r.TLS.PeerCertificates)) + const MaxIntermediateCAs = 10 + var ( + peerCertificates = make([]*x509.Certificate, 0, len(r.TLS.PeerCertificates)) + intermediates *x509.CertPool + numIntermediates int + ) for _, cert := range r.TLS.PeerCertificates { if cert.IsCA { - continue + numIntermediates++ + if numIntermediates > MaxIntermediateCAs { + writeSTSErrorResponse(ctx, w, ErrSTSTooManyIntermediateCAs, fmt.Errorf("client certificate contains more than %d intermediate CAs", MaxIntermediateCAs)) + return + } + if intermediates == nil { + intermediates = x509.NewCertPool() + } + intermediates.AddCert(cert) + } else { + peerCertificates = append(peerCertificates, cert) } - peerCertificates = append(peerCertificates, cert) } r.TLS.PeerCertificates = peerCertificates @@ -806,7 +820,8 @@ func (sts *stsAPIHandlers) AssumeRoleWithCertificate(w http.ResponseWriter, r *h KeyUsages: []x509.ExtKeyUsage{ x509.ExtKeyUsageClientAuth, }, - Roots: globalRootCAs, + Intermediates: intermediates, + Roots: globalRootCAs, }) if err != nil { writeSTSErrorResponse(ctx, w, ErrSTSInvalidClientCertificate, err) diff --git a/cmd/stserrorcode_string.go b/cmd/stserrorcode_string.go index 1774e98cb..b11928350 100644 --- a/cmd/stserrorcode_string.go +++ b/cmd/stserrorcode_string.go @@ -18,15 +18,16 @@ func _() { _ = x[ErrSTSMalformedPolicyDocument-7] _ = x[ErrSTSInsecureConnection-8] _ = x[ErrSTSInvalidClientCertificate-9] - _ = x[ErrSTSNotInitialized-10] - _ = x[ErrSTSIAMNotInitialized-11] - _ = x[ErrSTSUpstreamError-12] - _ = x[ErrSTSInternalError-13] + _ = x[ErrSTSTooManyIntermediateCAs-10] + _ = x[ErrSTSNotInitialized-11] + _ = x[ErrSTSIAMNotInitialized-12] + _ = x[ErrSTSUpstreamError-13] + _ = x[ErrSTSInternalError-14] } -const _STSErrorCode_name = "STSNoneSTSAccessDeniedSTSMissingParameterSTSInvalidParameterValueSTSWebIdentityExpiredTokenSTSClientGrantsExpiredTokenSTSInvalidClientGrantsTokenSTSMalformedPolicyDocumentSTSInsecureConnectionSTSInvalidClientCertificateSTSNotInitializedSTSIAMNotInitializedSTSUpstreamErrorSTSInternalError" +const _STSErrorCode_name = "STSNoneSTSAccessDeniedSTSMissingParameterSTSInvalidParameterValueSTSWebIdentityExpiredTokenSTSClientGrantsExpiredTokenSTSInvalidClientGrantsTokenSTSMalformedPolicyDocumentSTSInsecureConnectionSTSInvalidClientCertificateSTSTooManyIntermediateCAsSTSNotInitializedSTSIAMNotInitializedSTSUpstreamErrorSTSInternalError" -var _STSErrorCode_index = [...]uint16{0, 7, 22, 41, 65, 91, 118, 145, 171, 192, 219, 236, 256, 272, 288} +var _STSErrorCode_index = [...]uint16{0, 7, 22, 41, 65, 91, 118, 145, 171, 192, 219, 244, 261, 281, 297, 313} func (i STSErrorCode) String() string { if i < 0 || i >= STSErrorCode(len(_STSErrorCode_index)-1) {