Use same timestamp for all chunks in chunked signature (#2908)

master
Krishnan Parthasarathi 8 years ago committed by Harshavardhana
parent f0538dbb5c
commit a5921b5743
  1. 28
      cmd/object-handlers_test.go
  2. 56
      cmd/test-utils_test.go

@ -228,6 +228,7 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
malformedEncoding malformedEncoding
unexpectedEOF unexpectedEOF
signatureMismatch signatureMismatch
chunkDateMismatch
) )
// byte data for PutObject. // byte data for PutObject.
@ -364,16 +365,41 @@ func testAPIPutObjectStreamSigV4Handler(obj ObjectLayer, instanceType, bucketNam
shouldPass: false, shouldPass: false,
fault: signatureMismatch, fault: signatureMismatch,
}, },
// Test case - 9
// Different date (timestamps) used in seed signature calculation
// and chunks signature calculation.
{
bucketName: bucketName,
objectName: objectName,
data: oneKData,
dataLen: 1024,
chunkSize: 1024,
expectedContent: []byte{},
expectedRespStatus: http.StatusForbidden,
accessKey: credentials.AccessKeyID,
secretKey: credentials.SecretAccessKey,
shouldPass: false,
fault: chunkDateMismatch,
},
} }
// Iterating over the cases, fetching the object validating the response. // Iterating over the cases, fetching the object validating the response.
for i, testCase := range testCases { for i, testCase := range testCases {
// initialize HTTP NewRecorder, this records any mutations to response writer inside the handler. // initialize HTTP NewRecorder, this records any mutations to response writer inside the handler.
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
// construct HTTP request for Put Object end point. // construct HTTP request for Put Object end point.
req, err := newTestStreamingSignedRequest("PUT", var req *http.Request
if testCase.fault == chunkDateMismatch {
req, err = newTestStreamingSignedBadChunkDateRequest("PUT",
getPutObjectURL("", testCase.bucketName, testCase.objectName),
int64(testCase.dataLen), testCase.chunkSize, bytes.NewReader(testCase.data),
testCase.accessKey, testCase.secretKey)
} else {
req, err = newTestStreamingSignedRequest("PUT",
getPutObjectURL("", testCase.bucketName, testCase.objectName), getPutObjectURL("", testCase.bucketName, testCase.objectName),
int64(testCase.dataLen), testCase.chunkSize, bytes.NewReader(testCase.data), int64(testCase.dataLen), testCase.chunkSize, bytes.NewReader(testCase.data),
testCase.accessKey, testCase.secretKey) testCase.accessKey, testCase.secretKey)
}
if err != nil { if err != nil {
t.Fatalf("Test %d: Failed to create HTTP request for Put Object: <ERROR> %v", i+1, err) t.Fatalf("Test %d: Failed to create HTTP request for Put Object: <ERROR> %v", i+1, err)
} }

@ -399,14 +399,13 @@ func malformChunkSizeSigV4(req *http.Request, badSize int64) (*http.Request, err
} }
// Sign given request using Signature V4. // Sign given request using Signature V4.
func signStreamingRequest(req *http.Request, accessKey, secretKey string) (string, error) { func signStreamingRequest(req *http.Request, accessKey, secretKey string, currTime time.Time) (string, error) {
// Get hashed payload. // Get hashed payload.
hashedPayload := req.Header.Get("x-amz-content-sha256") hashedPayload := req.Header.Get("x-amz-content-sha256")
if hashedPayload == "" { if hashedPayload == "" {
return "", fmt.Errorf("Invalid hashed payload.") return "", fmt.Errorf("Invalid hashed payload.")
} }
currTime := time.Now().UTC()
// Set x-amz-date. // Set x-amz-date.
req.Header.Set("x-amz-date", currTime.Format(iso8601Format)) req.Header.Set("x-amz-date", currTime.Format(iso8601Format))
@ -540,20 +539,10 @@ func newTestStreamingRequest(method, urlStr string, dataLength, chunkSize int64,
return req, nil return req, nil
} }
// Returns new HTTP request object signed with streaming signature v4. func assembleStreamingChunks(req *http.Request, body io.ReadSeeker, chunkSize int64,
func newTestStreamingSignedRequest(method, urlStr string, contentLength, chunkSize int64, body io.ReadSeeker, accessKey, secretKey string) (*http.Request, error) { secretKey, signature string, currTime time.Time) (*http.Request, error) {
req, err := newTestStreamingRequest(method, urlStr, contentLength, chunkSize, body)
if err != nil {
return nil, err
}
signature, err := signStreamingRequest(req, accessKey, secretKey)
if err != nil {
return nil, err
}
regionStr := serverConfig.GetRegion() regionStr := serverConfig.GetRegion()
var stream []byte var stream []byte
var buffer []byte var buffer []byte
body.Seek(0, 0) body.Seek(0, 0)
@ -564,7 +553,6 @@ func newTestStreamingSignedRequest(method, urlStr string, contentLength, chunkSi
return nil, err return nil, err
} }
currTime := time.Now().UTC()
// Get scope. // Get scope.
scope := strings.Join([]string{ scope := strings.Join([]string{
currTime.Format(yyyymmdd), currTime.Format(yyyymmdd),
@ -596,11 +584,47 @@ func newTestStreamingSignedRequest(method, urlStr string, contentLength, chunkSi
} }
} }
req.Body = ioutil.NopCloser(bytes.NewReader(stream)) req.Body = ioutil.NopCloser(bytes.NewReader(stream))
return req, nil return req, nil
} }
func newTestStreamingSignedBadChunkDateRequest(method, urlStr string, contentLength, chunkSize int64, body io.ReadSeeker, accessKey, secretKey string) (*http.Request, error) {
req, err := newTestStreamingRequest(method, urlStr, contentLength, chunkSize, body)
if err != nil {
return nil, err
}
currTime := time.Now().UTC()
fmt.Println("now: ", currTime)
signature, err := signStreamingRequest(req, accessKey, secretKey, currTime)
if err != nil {
return nil, err
}
// skew the time between the chunk signature calculation and seed signature.
currTime = currTime.Add(1 * time.Second)
fmt.Println("later: ", currTime)
req, err = assembleStreamingChunks(req, body, chunkSize, secretKey, signature, currTime)
return req, nil
}
// Returns new HTTP request object signed with streaming signature v4.
func newTestStreamingSignedRequest(method, urlStr string, contentLength, chunkSize int64, body io.ReadSeeker, accessKey, secretKey string) (*http.Request, error) {
req, err := newTestStreamingRequest(method, urlStr, contentLength, chunkSize, body)
if err != nil {
return nil, err
}
currTime := time.Now().UTC()
signature, err := signStreamingRequest(req, accessKey, secretKey, currTime)
if err != nil {
return nil, err
}
req, err = assembleStreamingChunks(req, body, chunkSize, secretKey, signature, currTime)
return req, nil
}
// Replaces any occurring '/' in string, into its encoded representation. // Replaces any occurring '/' in string, into its encoded representation.
func percentEncodeSlash(s string) string { func percentEncodeSlash(s string) string {
return strings.Replace(s, "/", "%2F", -1) return strings.Replace(s, "/", "%2F", -1)

Loading…
Cancel
Save