mirror of https://github.com/minio/minio.git
Merge pull request #734 from harshavardhana/pr_out_do_not_reply_on_ignoredheaders_for_server_rely_on_signedheaders_sent_as_part_of_authorization_header
This commit is contained in:
commit
0a8ea1aca5
|
@ -102,13 +102,10 @@ func urlEncodeName(name string) (string, error) {
|
|||
}
|
||||
|
||||
// getCanonicalHeaders generate a list of request headers with their values
|
||||
func (r *Signature) getCanonicalHeaders() string {
|
||||
func (r *Signature) getCanonicalHeaders(signedHeaders map[string][]string) string {
|
||||
var headers []string
|
||||
vals := make(map[string][]string)
|
||||
for k, vv := range r.Request.Header {
|
||||
if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
|
||||
continue // ignored header
|
||||
}
|
||||
for k, vv := range signedHeaders {
|
||||
headers = append(headers, strings.ToLower(k))
|
||||
vals[strings.ToLower(k)] = vv
|
||||
}
|
||||
|
@ -137,12 +134,9 @@ func (r *Signature) getCanonicalHeaders() string {
|
|||
}
|
||||
|
||||
// getSignedHeaders generate a string i.e alphabetically sorted, semicolon-separated list of lowercase request header names
|
||||
func (r *Signature) getSignedHeaders() string {
|
||||
func (r *Signature) getSignedHeaders(signedHeaders map[string][]string) string {
|
||||
var headers []string
|
||||
for k := range r.Request.Header {
|
||||
if _, ok := ignoredHeaders[http.CanonicalHeaderKey(k)]; ok {
|
||||
continue // ignored header
|
||||
}
|
||||
for k := range signedHeaders {
|
||||
headers = append(headers, strings.ToLower(k))
|
||||
}
|
||||
headers = append(headers, "host")
|
||||
|
@ -150,6 +144,22 @@ func (r *Signature) getSignedHeaders() string {
|
|||
return strings.Join(headers, ";")
|
||||
}
|
||||
|
||||
// extractSignedHeaders extract signed headers from Authorization header
|
||||
func (r *Signature) extractSignedHeaders() map[string][]string {
|
||||
authFields := strings.Split(strings.TrimSpace(r.AuthHeader), ",")
|
||||
extractedHeaders := strings.Split(strings.Split(strings.TrimSpace(authFields[1]), "=")[1], ";")
|
||||
extractedSignedHeadersMap := make(map[string][]string)
|
||||
for _, header := range extractedHeaders {
|
||||
val, ok := r.Request.Header[http.CanonicalHeaderKey(header)]
|
||||
if !ok {
|
||||
// if not found continue, we will fail later
|
||||
continue
|
||||
}
|
||||
extractedSignedHeadersMap[header] = val
|
||||
}
|
||||
return extractedSignedHeadersMap
|
||||
}
|
||||
|
||||
// getCanonicalRequest generate a canonical request of style
|
||||
//
|
||||
// canonicalRequest =
|
||||
|
@ -169,9 +179,9 @@ func (r *Signature) getCanonicalRequest() string {
|
|||
r.Request.Method,
|
||||
encodedPath,
|
||||
r.Request.URL.RawQuery,
|
||||
r.getCanonicalHeaders(),
|
||||
r.getSignedHeaders(),
|
||||
r.Request.Header.Get("x-amz-content-sha256"),
|
||||
r.getCanonicalHeaders(r.extractSignedHeaders()),
|
||||
r.getSignedHeaders(r.extractSignedHeaders()),
|
||||
r.Request.Header.Get(http.CanonicalHeaderKey("x-amz-content-sha256")),
|
||||
}, "\n")
|
||||
return canonicalRequest
|
||||
}
|
||||
|
@ -214,11 +224,11 @@ func (r *Signature) getSignature(signingKey []byte, stringToSign string) string
|
|||
// returns true if matches, false other wise if error is not nil then it is always false
|
||||
func (r *Signature) DoesSignatureMatch(hashedPayload string) (bool, error) {
|
||||
// set new calulated payload
|
||||
r.Request.Header.Set("x-amz-content-sha256", hashedPayload)
|
||||
r.Request.Header.Set("X-Amz-Content-Sha256", hashedPayload)
|
||||
|
||||
// Add date if not present
|
||||
var date string
|
||||
if date = r.Request.Header.Get("x-amz-date"); date == "" {
|
||||
if date = r.Request.Header.Get(http.CanonicalHeaderKey("x-amz-date")); date == "" {
|
||||
if date = r.Request.Header.Get("Date"); date == "" {
|
||||
return false, iodine.New(MissingDateHeader{}, nil)
|
||||
}
|
||||
|
|
|
@ -405,7 +405,8 @@ func (api Minio) HeadBucketHandler(w http.ResponseWriter, req *http.Request) {
|
|||
case nil:
|
||||
writeSuccessResponse(w, acceptsContentType)
|
||||
case donut.SignatureDoesNotMatch:
|
||||
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
|
||||
error := getErrorCode(SignatureDoesNotMatch)
|
||||
w.WriteHeader(error.HTTPStatusCode)
|
||||
case donut.BucketNotFound:
|
||||
error := getErrorCode(NoSuchBucket)
|
||||
w.WriteHeader(error.HTTPStatusCode)
|
||||
|
|
|
@ -45,7 +45,7 @@ const (
|
|||
)
|
||||
|
||||
func parseDate(req *http.Request) (time.Time, error) {
|
||||
amzDate := req.Header.Get("x-amz-date")
|
||||
amzDate := req.Header.Get(http.CanonicalHeaderKey("x-amz-date"))
|
||||
switch {
|
||||
case amzDate != "":
|
||||
if _, err := time.Parse(time.RFC1123, amzDate); err == nil {
|
||||
|
@ -97,7 +97,7 @@ func (h timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
acceptsContentType := getContentType(r)
|
||||
// Verify if date headers are set, if not reject the request
|
||||
if r.Header.Get("Authorization") != "" {
|
||||
if r.Header.Get("x-amz-date") == "" && r.Header.Get("Date") == "" {
|
||||
if r.Header.Get(http.CanonicalHeaderKey("x-amz-date")) == "" && r.Header.Get("Date") == "" {
|
||||
// there is no way to knowing if this is a valid request, could be a attack reject such clients
|
||||
writeErrorResponse(w, r, RequestTimeTooSkewed, acceptsContentType, r.URL.Path)
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue