signV4: Move pkg/signature to pkg/s3/signature4

Cleanup and move this to relevant path.
This commit is contained in:
Harshavardhana 2016-02-21 17:57:05 -08:00
parent d3966d1dde
commit 653ceee9ee
16 changed files with 210 additions and 190 deletions

View File

@ -16,13 +16,88 @@
package main package main
import "net/http" import (
"crypto/sha256"
"encoding/hex"
"net/http"
"strings"
"github.com/minio/minio/pkg/s3/signature4"
)
const ( const (
signV4Algorithm = "AWS4-HMAC-SHA256" signV4Algorithm = "AWS4-HMAC-SHA256"
jwtAlgorithm = "Bearer" jwtAlgorithm = "Bearer"
) )
// Verify if request has JWT.
func isRequestJWT(r *http.Request) bool {
if _, ok := r.Header["Authorization"]; ok {
if strings.HasPrefix(r.Header.Get("Authorization"), jwtAlgorithm) {
return true
}
}
return false
}
// Verify if request has AWS Signature Version '4'.
func isRequestSignatureV4(r *http.Request) bool {
if _, ok := r.Header["Authorization"]; ok {
if strings.HasPrefix(r.Header.Get("Authorization"), signV4Algorithm) {
return true
}
}
return false
}
// Verify if request has AWS Presignature Version '4'.
func isRequestPresignedSignatureV4(r *http.Request) bool {
if _, ok := r.URL.Query()["X-Amz-Credential"]; ok {
return true
}
return false
}
// Verify if request has AWS Post policy Signature Version '4'.
func isRequestPostPolicySignatureV4(r *http.Request) bool {
if _, ok := r.Header["Content-Type"]; ok {
if strings.Contains(r.Header.Get("Content-Type"), "multipart/form-data") {
return true
}
}
return false
}
// Verify if request requires ACL check.
func isRequestRequiresACLCheck(r *http.Request) bool {
if isRequestSignatureV4(r) || isRequestPresignedSignatureV4(r) || isRequestPostPolicySignatureV4(r) {
return false
}
return true
}
// Verify if request has valid AWS Signature Version '4'.
func isSignV4ReqAuthenticated(sign *signature4.Sign, r *http.Request) bool {
auth := sign.SetHTTPRequestToVerify(r)
if isRequestSignatureV4(r) {
dummyPayload := sha256.Sum256([]byte(""))
ok, err := auth.DoesSignatureMatch(hex.EncodeToString(dummyPayload[:]))
if err != nil {
errorIf(err.Trace(), "Signature verification failed.", nil)
return false
}
return ok
} else if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch()
if err != nil {
errorIf(err.Trace(), "Presigned signature verification failed.", nil)
return false
}
return ok
}
return false
}
// authHandler - handles all the incoming authorization headers and // authHandler - handles all the incoming authorization headers and
// validates them if possible. // validates them if possible.
type authHandler struct { type authHandler struct {

View File

@ -24,11 +24,11 @@ import (
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"github.com/gorilla/mux" mux "github.com/gorilla/mux"
"github.com/minio/minio/pkg/crypto/sha256" "github.com/minio/minio/pkg/crypto/sha256"
"github.com/minio/minio/pkg/fs" "github.com/minio/minio/pkg/fs"
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
signV4 "github.com/minio/minio/pkg/signature" "github.com/minio/minio/pkg/s3/signature4"
) )
// GetBucketLocationHandler - GET Bucket location. // GetBucketLocationHandler - GET Bucket location.
@ -368,7 +368,7 @@ func (api storageAPI) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Req
writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path) writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
return return
} }
if err = signV4.ApplyPolicyCond(formValues); err != nil { if err = signature4.ApplyPolicyCond(formValues); err != nil {
errorIf(err.Trace(), "Invalid request, policy doesn't match with the endpoint.", nil) errorIf(err.Trace(), "Invalid request, policy doesn't match with the endpoint.", nil)
writeErrorResponse(w, r, MalformedPOSTRequest, r.URL.Path) writeErrorResponse(w, r, MalformedPOSTRequest, r.URL.Path)
return return

View File

@ -39,7 +39,7 @@ import (
"github.com/minio/minio/pkg/disk" "github.com/minio/minio/pkg/disk"
"github.com/minio/minio/pkg/mimedb" "github.com/minio/minio/pkg/mimedb"
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
signV4 "github.com/minio/minio/pkg/signature" "github.com/minio/minio/pkg/s3/signature4"
) )
// isValidUploadID - is upload id. // isValidUploadID - is upload id.
@ -297,7 +297,7 @@ func (a partNumber) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a partNumber) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber } func (a partNumber) Less(i, j int) bool { return a[i].PartNumber < a[j].PartNumber }
// CreateObjectPart - create a part in a multipart session // CreateObjectPart - create a part in a multipart session
func (fs Filesystem) CreateObjectPart(bucket, object, uploadID, expectedMD5Sum string, partID int, size int64, data io.Reader, signature *signV4.Signature) (string, *probe.Error) { func (fs Filesystem) CreateObjectPart(bucket, object, uploadID, expectedMD5Sum string, partID int, size int64, data io.Reader, signature *signature4.Sign) (string, *probe.Error) {
di, err := disk.GetInfo(fs.path) di, err := disk.GetInfo(fs.path)
if err != nil { if err != nil {
return "", probe.NewError(err) return "", probe.NewError(err)
@ -431,7 +431,7 @@ func (fs Filesystem) CreateObjectPart(bucket, object, uploadID, expectedMD5Sum s
} }
// CompleteMultipartUpload - complete a multipart upload and persist the data // CompleteMultipartUpload - complete a multipart upload and persist the data
func (fs Filesystem) CompleteMultipartUpload(bucket, object, uploadID string, data io.Reader, signature *signV4.Signature) (ObjectMetadata, *probe.Error) { func (fs Filesystem) CompleteMultipartUpload(bucket, object, uploadID string, data io.Reader, signature *signature4.Sign) (ObjectMetadata, *probe.Error) {
// Check bucket name is valid. // Check bucket name is valid.
if !IsValidBucketName(bucket) { if !IsValidBucketName(bucket) {
return ObjectMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket}) return ObjectMetadata{}, probe.NewError(BucketNameInvalid{Bucket: bucket})

View File

@ -34,7 +34,7 @@ import (
"github.com/minio/minio/pkg/ioutils" "github.com/minio/minio/pkg/ioutils"
"github.com/minio/minio/pkg/mimedb" "github.com/minio/minio/pkg/mimedb"
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
signV4 "github.com/minio/minio/pkg/signature" "github.com/minio/minio/pkg/s3/signature4"
) )
/// Object Operations /// Object Operations
@ -199,7 +199,7 @@ func isMD5SumEqual(expectedMD5Sum, actualMD5Sum string) bool {
} }
// CreateObject - create an object. // CreateObject - create an object.
func (fs Filesystem) CreateObject(bucket, object, expectedMD5Sum string, size int64, data io.Reader, sig *signV4.Signature) (ObjectMetadata, *probe.Error) { func (fs Filesystem) CreateObject(bucket, object, expectedMD5Sum string, size int64, data io.Reader, sig *signature4.Sign) (ObjectMetadata, *probe.Error) {
di, e := disk.GetInfo(fs.path) di, e := disk.GetInfo(fs.path)
if e != nil { if e != nil {
return ObjectMetadata{}, probe.NewError(e) return ObjectMetadata{}, probe.NewError(e)
@ -294,7 +294,7 @@ func (fs Filesystem) CreateObject(bucket, object, expectedMD5Sum string, size in
} }
if !ok { if !ok {
file.CloseAndPurge() file.CloseAndPurge()
return ObjectMetadata{}, signV4.ErrSignDoesNotMath("Signature does not match") return ObjectMetadata{}, probe.NewError(SignDoesNotMatch{})
} }
} }
file.Close() file.Close()

View File

@ -1,5 +1,5 @@
/* /*
* Minio Cloud Storage, (C) 2015 Minio, Inc. * Minio Cloud Storage, (C) 2015, 2016 Minio, Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package signature package signature4
import ( import (
"fmt" "fmt"
@ -24,13 +24,14 @@ import (
type errFunc func(msg string, a ...string) *probe.Error type errFunc func(msg string, a ...string) *probe.Error
// generic error factory which wraps around probe.NewError()
func errFactory() errFunc { func errFactory() errFunc {
return func(msg string, a ...string) *probe.Error { return func(msg string, a ...string) *probe.Error {
return probe.NewError(fmt.Errorf("%s, Args: %s", msg, a)).Untrace() return probe.NewError(fmt.Errorf("%s, Args: %s", msg, a)).Untrace()
} }
} }
// Various errors. // Various signature v4 errors.
var ( var (
ErrPolicyAlreadyExpired = errFactory() ErrPolicyAlreadyExpired = errFactory()
ErrInvalidRegion = errFactory() ErrInvalidRegion = errFactory()

View File

@ -1,4 +1,20 @@
package signature /*
* Minio Cloud Storage, (C) 2015 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package signature4
import ( import (
"net/url" "net/url"
@ -8,7 +24,9 @@ import (
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
) )
type credScope struct { // credential data type represents structured form of Credential
// string from authorization header.
type credential struct {
accessKeyID string accessKeyID string
scope struct { scope struct {
date time.Time date time.Time
@ -18,45 +36,46 @@ type credScope struct {
} }
} }
func parseCredential(credElement string) (credScope, *probe.Error) { // parse credential string into its structured form.
func parseCredential(credElement string) (credential, *probe.Error) {
creds := strings.Split(strings.TrimSpace(credElement), "=") creds := strings.Split(strings.TrimSpace(credElement), "=")
if len(creds) != 2 { if len(creds) != 2 {
return credScope{}, ErrMissingFields("Credential tag has missing fields.", credElement).Trace(credElement) return credential{}, ErrMissingFields("Credential tag has missing fields.", credElement).Trace(credElement)
} }
if creds[0] != "Credential" { if creds[0] != "Credential" {
return credScope{}, ErrMissingCredTag("Missing credentials tag.", credElement).Trace(credElement) return credential{}, ErrMissingCredTag("Missing credentials tag.", credElement).Trace(credElement)
} }
credElements := strings.Split(strings.TrimSpace(creds[1]), "/") credElements := strings.Split(strings.TrimSpace(creds[1]), "/")
if len(credElements) != 5 { if len(credElements) != 5 {
return credScope{}, ErrCredMalformed("Credential values malformed.", credElement).Trace(credElement) return credential{}, ErrCredMalformed("Credential values malformed.", credElement).Trace(credElement)
} }
if !isValidAccessKey.MatchString(credElements[0]) { if !isValidAccessKey.MatchString(credElements[0]) {
return credScope{}, ErrInvalidAccessKeyID("Invalid access key id.", credElement).Trace(credElement) return credential{}, ErrInvalidAccessKeyID("Invalid access key id.", credElement).Trace(credElement)
} }
cred := credScope{ cred := credential{
accessKeyID: credElements[0], accessKeyID: credElements[0],
} }
var e error var e error
cred.scope.date, e = time.Parse(yyyymmdd, credElements[1]) cred.scope.date, e = time.Parse(yyyymmdd, credElements[1])
if e != nil { if e != nil {
return credScope{}, ErrInvalidDateFormat("Invalid date format.", credElement).Trace(credElement) return credential{}, ErrInvalidDateFormat("Invalid date format.", credElement).Trace(credElement)
} }
if credElements[2] == "" { if credElements[2] == "" {
return credScope{}, ErrRegionISEmpty("Region is empty.", credElement).Trace(credElement) return credential{}, ErrRegionISEmpty("Region is empty.", credElement).Trace(credElement)
} }
cred.scope.region = credElements[2] cred.scope.region = credElements[2]
if credElements[3] != "s3" { if credElements[3] != "s3" {
return credScope{}, ErrInvalidService("Invalid service detected.", credElement).Trace(credElement) return credential{}, ErrInvalidService("Invalid service detected.", credElement).Trace(credElement)
} }
cred.scope.service = credElements[3] cred.scope.service = credElements[3]
if credElements[4] != "aws4_request" { if credElements[4] != "aws4_request" {
return credScope{}, ErrInvalidRequestVersion("Invalid request version detected.", credElement).Trace(credElement) return credential{}, ErrInvalidRequestVersion("Invalid request version detected.", credElement).Trace(credElement)
} }
cred.scope.request = credElements[4] cred.scope.request = credElements[4]
return cred, nil return cred, nil
} }
// parse signature. // Parse signature string.
func parseSignature(signElement string) (string, *probe.Error) { func parseSignature(signElement string) (string, *probe.Error) {
signFields := strings.Split(strings.TrimSpace(signElement), "=") signFields := strings.Split(strings.TrimSpace(signElement), "=")
if len(signFields) != 2 { if len(signFields) != 2 {
@ -69,7 +88,7 @@ func parseSignature(signElement string) (string, *probe.Error) {
return signature, nil return signature, nil
} }
// parse signed headers. // Parse signed headers string.
func parseSignedHeaders(signedHdrElement string) ([]string, *probe.Error) { func parseSignedHeaders(signedHdrElement string) ([]string, *probe.Error) {
signedHdrFields := strings.Split(strings.TrimSpace(signedHdrElement), "=") signedHdrFields := strings.Split(strings.TrimSpace(signedHdrElement), "=")
if len(signedHdrFields) != 2 { if len(signedHdrFields) != 2 {
@ -82,14 +101,14 @@ func parseSignedHeaders(signedHdrElement string) ([]string, *probe.Error) {
return signedHeaders, nil return signedHeaders, nil
} }
// structured version of AWS Signature V4 header. // signValues data type represents structured form of AWS Signature V4 header.
type signValues struct { type signValues struct {
Creds credScope Credential credential
SignedHeaders []string SignedHeaders []string
Signature string Signature string
} }
// structued version of AWS Signature V4 query string. // preSignValues data type represents structued form of AWS Signature V4 query string.
type preSignValues struct { type preSignValues struct {
signValues signValues
Date time.Time Date time.Time
@ -115,8 +134,8 @@ func parsePreSignV4(query url.Values) (preSignValues, *probe.Error) {
preSignV4Values := preSignValues{} preSignV4Values := preSignValues{}
var err *probe.Error var err *probe.Error
// Save credentail values. // Save credential.
preSignV4Values.Creds, err = parseCredential("Credential=" + query.Get("X-Amz-Credential")) preSignV4Values.Credential, err = parseCredential("Credential=" + query.Get("X-Amz-Credential"))
if err != nil { if err != nil {
return preSignValues{}, err.Trace(query.Get("X-Amz-Credential")) return preSignValues{}, err.Trace(query.Get("X-Amz-Credential"))
} }
@ -181,7 +200,7 @@ func parseSignV4(v4Auth string) (signValues, *probe.Error) {
var err *probe.Error var err *probe.Error
// Save credentail values. // Save credentail values.
signV4Values.Creds, err = parseCredential(authFields[0]) signV4Values.Credential, err = parseCredential(authFields[0])
if err != nil { if err != nil {
return signValues{}, err.Trace(v4Auth) return signValues{}, err.Trace(v4Auth)
} }

View File

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package signature package signature4
import ( import (
"encoding/base64" "encoding/base64"

View File

@ -14,7 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
package signature // Package signature4 implements helper functions to validate AWS
// Signature Version '4' authorization header.
//
// This package provides comprehensive helpers for following signature
// types.
// - Based on Authorization header.
// - Based on Query parameters.
// - Based on Form POST policy.
package signature4
import ( import (
"bytes" "bytes"
@ -30,8 +38,8 @@ import (
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
) )
// Signature - local variables // Sign - local variables
type Signature struct { type Sign struct {
accessKeyID string accessKeyID string
secretAccessKey string secretAccessKey string
region string region string
@ -39,6 +47,7 @@ type Signature struct {
extractedSignedHeaders http.Header extractedSignedHeaders http.Header
} }
// AWS Signature Version '4' constants.
const ( const (
signV4Algorithm = "AWS4-HMAC-SHA256" signV4Algorithm = "AWS4-HMAC-SHA256"
iso8601Format = "20060102T150405Z" iso8601Format = "20060102T150405Z"
@ -46,7 +55,7 @@ const (
) )
// New - initialize a new authorization checkes. // New - initialize a new authorization checkes.
func New(accessKeyID, secretAccessKey, region string) (*Signature, *probe.Error) { func New(accessKeyID, secretAccessKey, region string) (*Sign, *probe.Error) {
if !isValidAccessKey.MatchString(accessKeyID) { if !isValidAccessKey.MatchString(accessKeyID) {
return nil, ErrInvalidAccessKeyID("Invalid access key id.", accessKeyID).Trace(accessKeyID) return nil, ErrInvalidAccessKeyID("Invalid access key id.", accessKeyID).Trace(accessKeyID)
} }
@ -56,7 +65,7 @@ func New(accessKeyID, secretAccessKey, region string) (*Signature, *probe.Error)
if region == "" { if region == "" {
return nil, ErrRegionISEmpty("Region is empty.").Trace() return nil, ErrRegionISEmpty("Region is empty.").Trace()
} }
signature := &Signature{ signature := &Sign{
accessKeyID: accessKeyID, accessKeyID: accessKeyID,
secretAccessKey: secretAccessKey, secretAccessKey: secretAccessKey,
region: region, region: region,
@ -65,7 +74,7 @@ func New(accessKeyID, secretAccessKey, region string) (*Signature, *probe.Error)
} }
// SetHTTPRequestToVerify - sets the http request which needs to be verified. // SetHTTPRequestToVerify - sets the http request which needs to be verified.
func (s *Signature) SetHTTPRequestToVerify(r *http.Request) *Signature { func (s *Sign) SetHTTPRequestToVerify(r *http.Request) *Sign {
// Do not set http request if its 'nil'. // Do not set http request if its 'nil'.
if r == nil { if r == nil {
return s return s
@ -75,7 +84,7 @@ func (s *Signature) SetHTTPRequestToVerify(r *http.Request) *Signature {
} }
// getCanonicalHeaders generate a list of request headers with their values // getCanonicalHeaders generate a list of request headers with their values
func (s Signature) getCanonicalHeaders(signedHeaders http.Header) string { func (s Sign) getCanonicalHeaders(signedHeaders http.Header) string {
var headers []string var headers []string
vals := make(http.Header) vals := make(http.Header)
for k, vv := range signedHeaders { for k, vv := range signedHeaders {
@ -107,7 +116,7 @@ func (s Signature) getCanonicalHeaders(signedHeaders http.Header) string {
} }
// getSignedHeaders generate a string i.e alphabetically sorted, semicolon-separated list of lowercase request header names // getSignedHeaders generate a string i.e alphabetically sorted, semicolon-separated list of lowercase request header names
func (s Signature) getSignedHeaders(signedHeaders http.Header) string { func (s Sign) getSignedHeaders(signedHeaders http.Header) string {
var headers []string var headers []string
for k := range signedHeaders { for k := range signedHeaders {
headers = append(headers, strings.ToLower(k)) headers = append(headers, strings.ToLower(k))
@ -127,7 +136,7 @@ func (s Signature) getSignedHeaders(signedHeaders http.Header) string {
// <SignedHeaders>\n // <SignedHeaders>\n
// <HashedPayload> // <HashedPayload>
// //
func (s *Signature) getCanonicalRequest() string { func (s *Sign) getCanonicalRequest() string {
payload := s.httpRequest.Header.Get(http.CanonicalHeaderKey("x-amz-content-sha256")) payload := s.httpRequest.Header.Get(http.CanonicalHeaderKey("x-amz-content-sha256"))
s.httpRequest.URL.RawQuery = strings.Replace(s.httpRequest.URL.Query().Encode(), "+", "%20", -1) s.httpRequest.URL.RawQuery = strings.Replace(s.httpRequest.URL.Query().Encode(), "+", "%20", -1)
encodedPath := getURLEncodedName(s.httpRequest.URL.Path) encodedPath := getURLEncodedName(s.httpRequest.URL.Path)
@ -154,7 +163,7 @@ func (s *Signature) getCanonicalRequest() string {
// <SignedHeaders>\n // <SignedHeaders>\n
// <HashedPayload> // <HashedPayload>
// //
func (s Signature) getPresignedCanonicalRequest(presignedQuery string) string { func (s Sign) getPresignedCanonicalRequest(presignedQuery string) string {
rawQuery := strings.Replace(presignedQuery, "+", "%20", -1) rawQuery := strings.Replace(presignedQuery, "+", "%20", -1)
encodedPath := getURLEncodedName(s.httpRequest.URL.Path) encodedPath := getURLEncodedName(s.httpRequest.URL.Path)
// Convert any space strings back to "+". // Convert any space strings back to "+".
@ -171,7 +180,7 @@ func (s Signature) getPresignedCanonicalRequest(presignedQuery string) string {
} }
// getScope generate a string of a specific date, an AWS region, and a service. // getScope generate a string of a specific date, an AWS region, and a service.
func (s Signature) getScope(t time.Time) string { func (s Sign) getScope(t time.Time) string {
scope := strings.Join([]string{ scope := strings.Join([]string{
t.Format(yyyymmdd), t.Format(yyyymmdd),
s.region, s.region,
@ -182,7 +191,7 @@ func (s Signature) getScope(t time.Time) string {
} }
// getStringToSign a string based on selected query values. // getStringToSign a string based on selected query values.
func (s Signature) getStringToSign(canonicalRequest string, t time.Time) string { func (s Sign) getStringToSign(canonicalRequest string, t time.Time) string {
stringToSign := signV4Algorithm + "\n" + t.Format(iso8601Format) + "\n" stringToSign := signV4Algorithm + "\n" + t.Format(iso8601Format) + "\n"
stringToSign = stringToSign + s.getScope(t) + "\n" stringToSign = stringToSign + s.getScope(t) + "\n"
canonicalRequestBytes := sha256.Sum256([]byte(canonicalRequest)) canonicalRequestBytes := sha256.Sum256([]byte(canonicalRequest))
@ -191,7 +200,7 @@ func (s Signature) getStringToSign(canonicalRequest string, t time.Time) string
} }
// getSigningKey hmac seed to calculate final signature. // getSigningKey hmac seed to calculate final signature.
func (s Signature) getSigningKey(t time.Time) []byte { func (s Sign) getSigningKey(t time.Time) []byte {
secret := s.secretAccessKey secret := s.secretAccessKey
date := sumHMAC([]byte("AWS4"+secret), []byte(t.Format(yyyymmdd))) date := sumHMAC([]byte("AWS4"+secret), []byte(t.Format(yyyymmdd)))
region := sumHMAC(date, []byte(s.region)) region := sumHMAC(date, []byte(s.region))
@ -201,27 +210,27 @@ func (s Signature) getSigningKey(t time.Time) []byte {
} }
// getSignature final signature in hexadecimal form. // getSignature final signature in hexadecimal form.
func (s Signature) getSignature(signingKey []byte, stringToSign string) string { func (s Sign) getSignature(signingKey []byte, stringToSign string) string {
return hex.EncodeToString(sumHMAC(signingKey, []byte(stringToSign))) return hex.EncodeToString(sumHMAC(signingKey, []byte(stringToSign)))
} }
// DoesPolicySignatureMatch - Verify query headers with post policy // DoesPolicySignatureMatch - Verify query headers with post policy
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html // - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html
// returns true if matches, false otherwise. if error is not nil then it is always false // returns true if matches, false otherwise. if error is not nil then it is always false
func (s *Signature) DoesPolicySignatureMatch(formValues map[string]string) (bool, *probe.Error) { func (s *Sign) DoesPolicySignatureMatch(formValues map[string]string) (bool, *probe.Error) {
// Parse credential tag. // Parse credential tag.
creds, err := parseCredential("Credential=" + formValues["X-Amz-Credential"]) credential, err := parseCredential("Credential=" + formValues["X-Amz-Credential"])
if err != nil { if err != nil {
return false, err.Trace(formValues["X-Amz-Credential"]) return false, err.Trace(formValues["X-Amz-Credential"])
} }
// Verify if the access key id matches. // Verify if the access key id matches.
if creds.accessKeyID != s.accessKeyID { if credential.accessKeyID != s.accessKeyID {
return false, ErrInvalidAccessKeyID("Access key id does not match with our records.", creds.accessKeyID).Trace(creds.accessKeyID) return false, ErrInvalidAccessKeyID("Access key id does not match with our records.", credential.accessKeyID).Trace(credential.accessKeyID)
} }
// Verify if the region is valid. // Verify if the region is valid.
reqRegion := creds.scope.region reqRegion := credential.scope.region
if !isValidRegion(reqRegion, s.region) { if !isValidRegion(reqRegion, s.region) {
return false, ErrInvalidRegion("Requested region is not recognized.", reqRegion).Trace(reqRegion) return false, ErrInvalidRegion("Requested region is not recognized.", reqRegion).Trace(reqRegion)
} }
@ -245,20 +254,20 @@ func (s *Signature) DoesPolicySignatureMatch(formValues map[string]string) (bool
// DoesPresignedSignatureMatch - Verify query headers with presigned signature // DoesPresignedSignatureMatch - Verify query headers with presigned signature
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html // - http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html
// returns true if matches, false otherwise. if error is not nil then it is always false // returns true if matches, false otherwise. if error is not nil then it is always false
func (s *Signature) DoesPresignedSignatureMatch() (bool, *probe.Error) { func (s *Sign) DoesPresignedSignatureMatch() (bool, *probe.Error) {
// Parse request query string. // Parse request query string.
preSignV4Values, err := parsePreSignV4(s.httpRequest.URL.Query()) preSignValues, err := parsePreSignV4(s.httpRequest.URL.Query())
if err != nil { if err != nil {
return false, err.Trace(s.httpRequest.URL.String()) return false, err.Trace(s.httpRequest.URL.String())
} }
// Verify if the access key id matches. // Verify if the access key id matches.
if preSignV4Values.Creds.accessKeyID != s.accessKeyID { if preSignValues.Credential.accessKeyID != s.accessKeyID {
return false, ErrInvalidAccessKeyID("Access key id does not match with our records.", preSignV4Values.Creds.accessKeyID).Trace(preSignV4Values.Creds.accessKeyID) return false, ErrInvalidAccessKeyID("Access key id does not match with our records.", preSignValues.Credential.accessKeyID).Trace(preSignValues.Credential.accessKeyID)
} }
// Verify if region is valid. // Verify if region is valid.
reqRegion := preSignV4Values.Creds.scope.region reqRegion := preSignValues.Credential.scope.region
if !isValidRegion(reqRegion, s.region) { if !isValidRegion(reqRegion, s.region) {
return false, ErrInvalidRegion("Requested region is not recognized.", reqRegion).Trace(reqRegion) return false, ErrInvalidRegion("Requested region is not recognized.", reqRegion).Trace(reqRegion)
} }
@ -267,19 +276,19 @@ func (s *Signature) DoesPresignedSignatureMatch() (bool, *probe.Error) {
s.region = reqRegion s.region = reqRegion
// Extract all the signed headers along with its values. // Extract all the signed headers along with its values.
s.extractedSignedHeaders = extractSignedHeaders(preSignV4Values.SignedHeaders, s.httpRequest.Header) s.extractedSignedHeaders = extractSignedHeaders(preSignValues.SignedHeaders, s.httpRequest.Header)
// Construct new query. // Construct new query.
query := make(url.Values) query := make(url.Values)
query.Set("X-Amz-Algorithm", signV4Algorithm) query.Set("X-Amz-Algorithm", signV4Algorithm)
if time.Now().UTC().Sub(preSignV4Values.Date) > time.Duration(preSignV4Values.Expires) { if time.Now().UTC().Sub(preSignValues.Date) > time.Duration(preSignValues.Expires) {
return false, ErrExpiredPresignRequest("Presigned request already expired, please initiate a new request.") return false, ErrExpiredPresignRequest("Presigned request already expired, please initiate a new request.")
} }
// Save the date and expires. // Save the date and expires.
t := preSignV4Values.Date t := preSignValues.Date
expireSeconds := int(time.Duration(preSignV4Values.Expires) / time.Second) expireSeconds := int(time.Duration(preSignValues.Expires) / time.Second)
// Construct the query. // Construct the query.
query.Set("X-Amz-Date", t.Format(iso8601Format)) query.Set("X-Amz-Date", t.Format(iso8601Format))
@ -325,7 +334,7 @@ func (s *Signature) DoesPresignedSignatureMatch() (bool, *probe.Error) {
// DoesSignatureMatch - Verify authorization header with calculated header in accordance with // DoesSignatureMatch - Verify authorization header with calculated header in accordance with
// - http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html // - http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
// returns true if matches, false otherwise. if error is not nil then it is always false // returns true if matches, false otherwise. if error is not nil then it is always false
func (s *Signature) DoesSignatureMatch(hashedPayload string) (bool, *probe.Error) { func (s *Sign) DoesSignatureMatch(hashedPayload string) (bool, *probe.Error) {
// Save authorization header. // Save authorization header.
v4Auth := s.httpRequest.Header.Get("Authorization") v4Auth := s.httpRequest.Header.Get("Authorization")
@ -339,12 +348,12 @@ func (s *Signature) DoesSignatureMatch(hashedPayload string) (bool, *probe.Error
s.extractedSignedHeaders = extractSignedHeaders(signV4Values.SignedHeaders, s.httpRequest.Header) s.extractedSignedHeaders = extractSignedHeaders(signV4Values.SignedHeaders, s.httpRequest.Header)
// Verify if the access key id matches. // Verify if the access key id matches.
if signV4Values.Creds.accessKeyID != s.accessKeyID { if signV4Values.Credential.accessKeyID != s.accessKeyID {
return false, ErrInvalidAccessKeyID("Access key id does not match with our records.", signV4Values.Creds.accessKeyID).Trace(signV4Values.Creds.accessKeyID) return false, ErrInvalidAccessKeyID("Access key id does not match with our records.", signV4Values.Credential.accessKeyID).Trace(signV4Values.Credential.accessKeyID)
} }
// Verify if region is valid. // Verify if region is valid.
reqRegion := signV4Values.Creds.scope.region reqRegion := signV4Values.Credential.scope.region
if !isValidRegion(reqRegion, s.region) { if !isValidRegion(reqRegion, s.region) {
return false, ErrInvalidRegion("Requested region is not recognized.", reqRegion).Trace(reqRegion) return false, ErrInvalidRegion("Requested region is not recognized.", reqRegion).Trace(reqRegion)
} }

View File

@ -1,4 +1,20 @@
package signature /*
* Minio Cloud Storage, (C) 2015, 2016 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package signature4
import ( import (
"crypto/hmac" "crypto/hmac"
@ -11,12 +27,6 @@ import (
"github.com/minio/minio/pkg/crypto/sha256" "github.com/minio/minio/pkg/crypto/sha256"
) )
// AccessID and SecretID length in bytes
const (
MinioAccessID = 20
MinioSecretID = 40
)
/// helpers /// helpers
// isValidSecretKey - validate secret key. // isValidSecretKey - validate secret key.

View File

@ -34,7 +34,7 @@ import (
"github.com/minio/minio/pkg/crypto/sha256" "github.com/minio/minio/pkg/crypto/sha256"
"github.com/minio/minio/pkg/crypto/sha512" "github.com/minio/minio/pkg/crypto/sha512"
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
signV4 "github.com/minio/minio/pkg/signature" "github.com/minio/minio/pkg/s3/signature4"
"github.com/minio/minio/pkg/xl/block" "github.com/minio/minio/pkg/xl/block"
) )
@ -236,7 +236,7 @@ func (b bucket) ReadObject(objectName string) (reader io.ReadCloser, size int64,
} }
// WriteObject - write a new object into bucket // WriteObject - write a new object into bucket
func (b bucket) WriteObject(objectName string, objectData io.Reader, size int64, expectedMD5Sum string, metadata map[string]string, signature *signV4.Signature) (ObjectMetadata, *probe.Error) { func (b bucket) WriteObject(objectName string, objectData io.Reader, size int64, expectedMD5Sum string, metadata map[string]string, signature *signature4.Sign) (ObjectMetadata, *probe.Error) {
b.lock.Lock() b.lock.Lock()
defer b.lock.Unlock() defer b.lock.Unlock()
if objectName == "" || objectData == nil { if objectName == "" || objectData == nil {

View File

@ -20,7 +20,7 @@ import (
"io" "io"
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
signV4 "github.com/minio/minio/pkg/signature" "github.com/minio/minio/pkg/s3/signature4"
) )
// Collection of XL specification interfaces // Collection of XL specification interfaces
@ -37,7 +37,7 @@ type CloudStorage interface {
GetBucketMetadata(bucket string) (BucketMetadata, *probe.Error) GetBucketMetadata(bucket string) (BucketMetadata, *probe.Error)
SetBucketMetadata(bucket string, metadata map[string]string) *probe.Error SetBucketMetadata(bucket string, metadata map[string]string) *probe.Error
ListBuckets() ([]BucketMetadata, *probe.Error) ListBuckets() ([]BucketMetadata, *probe.Error)
MakeBucket(bucket string, ACL string, location io.Reader, signature *signV4.Signature) *probe.Error MakeBucket(bucket string, ACL string, location io.Reader, signature *signature4.Sign) *probe.Error
// Bucket operations // Bucket operations
ListObjects(string, BucketResourcesMetadata) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error) ListObjects(string, BucketResourcesMetadata) ([]ObjectMetadata, BucketResourcesMetadata, *probe.Error)
@ -46,7 +46,7 @@ type CloudStorage interface {
GetObject(w io.Writer, bucket, object string, start, length int64) (int64, *probe.Error) GetObject(w io.Writer, bucket, object string, start, length int64) (int64, *probe.Error)
GetObjectMetadata(bucket, object string) (ObjectMetadata, *probe.Error) GetObjectMetadata(bucket, object string) (ObjectMetadata, *probe.Error)
// bucket, object, expectedMD5Sum, size, reader, metadata, signature // bucket, object, expectedMD5Sum, size, reader, metadata, signature
CreateObject(string, string, string, int64, io.Reader, map[string]string, *signV4.Signature) (ObjectMetadata, *probe.Error) CreateObject(string, string, string, int64, io.Reader, map[string]string, *signature4.Sign) (ObjectMetadata, *probe.Error)
Multipart Multipart
} }
@ -55,8 +55,8 @@ type CloudStorage interface {
type Multipart interface { type Multipart interface {
NewMultipartUpload(bucket, key, contentType string) (string, *probe.Error) NewMultipartUpload(bucket, key, contentType string) (string, *probe.Error)
AbortMultipartUpload(bucket, key, uploadID string) *probe.Error AbortMultipartUpload(bucket, key, uploadID string) *probe.Error
CreateObjectPart(string, string, string, int, string, string, int64, io.Reader, *signV4.Signature) (string, *probe.Error) CreateObjectPart(string, string, string, int, string, string, int64, io.Reader, *signature4.Sign) (string, *probe.Error)
CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *signV4.Signature) (ObjectMetadata, *probe.Error) CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *signature4.Sign) (ObjectMetadata, *probe.Error)
ListMultipartUploads(string, BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, *probe.Error) ListMultipartUploads(string, BucketMultipartResourcesMetadata) (BucketMultipartResourcesMetadata, *probe.Error)
ListObjectParts(string, string, ObjectResourcesMetadata) (ObjectResourcesMetadata, *probe.Error) ListObjectParts(string, string, ObjectResourcesMetadata) (ObjectResourcesMetadata, *probe.Error)
} }

View File

@ -35,7 +35,7 @@ import (
"github.com/minio/minio/pkg/crypto/sha256" "github.com/minio/minio/pkg/crypto/sha256"
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
signV4 "github.com/minio/minio/pkg/signature" "github.com/minio/minio/pkg/s3/signature4"
"github.com/minio/minio/pkg/xl/cache/data" "github.com/minio/minio/pkg/xl/cache/data"
) )
@ -109,7 +109,7 @@ func (xl API) AbortMultipartUpload(bucket, key, uploadID string) *probe.Error {
} }
// CreateObjectPart - create a part in a multipart session // CreateObjectPart - create a part in a multipart session
func (xl API) CreateObjectPart(bucket, key, uploadID string, partID int, contentType, expectedMD5Sum string, size int64, data io.Reader, signature *signV4.Signature) (string, *probe.Error) { func (xl API) CreateObjectPart(bucket, key, uploadID string, partID int, contentType, expectedMD5Sum string, size int64, data io.Reader, signature *signature4.Sign) (string, *probe.Error) {
xl.lock.Lock() xl.lock.Lock()
etag, err := xl.createObjectPart(bucket, key, uploadID, partID, "", expectedMD5Sum, size, data, signature) etag, err := xl.createObjectPart(bucket, key, uploadID, partID, "", expectedMD5Sum, size, data, signature)
xl.lock.Unlock() xl.lock.Unlock()
@ -120,7 +120,7 @@ func (xl API) CreateObjectPart(bucket, key, uploadID string, partID int, content
} }
// createObject - internal wrapper function called by CreateObjectPart // createObject - internal wrapper function called by CreateObjectPart
func (xl API) createObjectPart(bucket, key, uploadID string, partID int, contentType, expectedMD5Sum string, size int64, data io.Reader, signature *signV4.Signature) (string, *probe.Error) { func (xl API) createObjectPart(bucket, key, uploadID string, partID int, contentType, expectedMD5Sum string, size int64, data io.Reader, signature *signature4.Sign) (string, *probe.Error) {
if !IsValidBucket(bucket) { if !IsValidBucket(bucket) {
return "", probe.NewError(BucketNameInvalid{Bucket: bucket}) return "", probe.NewError(BucketNameInvalid{Bucket: bucket})
} }
@ -289,7 +289,7 @@ func (xl API) mergeMultipart(parts *CompleteMultipartUpload, uploadID string, fu
} }
// CompleteMultipartUpload - complete a multipart upload and persist the data // CompleteMultipartUpload - complete a multipart upload and persist the data
func (xl API) CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *signV4.Signature) (ObjectMetadata, *probe.Error) { func (xl API) CompleteMultipartUpload(bucket, key, uploadID string, data io.Reader, signature *signature4.Sign) (ObjectMetadata, *probe.Error) {
xl.lock.Lock() xl.lock.Lock()
defer xl.lock.Unlock() defer xl.lock.Unlock()
size := int64(xl.multiPartObjects[uploadID].Stats().Bytes) size := int64(xl.multiPartObjects[uploadID].Stats().Bytes)
@ -307,7 +307,7 @@ func (xl API) CompleteMultipartUpload(bucket, key, uploadID string, data io.Read
return objectMetadata, nil return objectMetadata, nil
} }
func (xl API) completeMultipartUploadV2(bucket, key, uploadID string, data io.Reader, signature *signV4.Signature) (io.Reader, *probe.Error) { func (xl API) completeMultipartUploadV2(bucket, key, uploadID string, data io.Reader, signature *signature4.Sign) (io.Reader, *probe.Error) {
if !IsValidBucket(bucket) { if !IsValidBucket(bucket) {
return nil, probe.NewError(BucketNameInvalid{Bucket: bucket}) return nil, probe.NewError(BucketNameInvalid{Bucket: bucket})
} }

View File

@ -35,7 +35,7 @@ import (
"github.com/minio/minio/pkg/crypto/sha256" "github.com/minio/minio/pkg/crypto/sha256"
"github.com/minio/minio/pkg/crypto/sha512" "github.com/minio/minio/pkg/crypto/sha512"
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
signV4 "github.com/minio/minio/pkg/signature" "github.com/minio/minio/pkg/s3/signature4"
"github.com/minio/minio/pkg/xl/block" "github.com/minio/minio/pkg/xl/block"
) )
@ -128,7 +128,7 @@ func (xl API) listObjects(bucket, prefix, marker, delimiter string, maxkeys int)
} }
// putObject - put object // putObject - put object
func (xl API) putObject(bucket, object, expectedMD5Sum string, reader io.Reader, size int64, metadata map[string]string, signature *signV4.Signature) (ObjectMetadata, *probe.Error) { func (xl API) putObject(bucket, object, expectedMD5Sum string, reader io.Reader, size int64, metadata map[string]string, signature *signature4.Sign) (ObjectMetadata, *probe.Error) {
if bucket == "" || strings.TrimSpace(bucket) == "" { if bucket == "" || strings.TrimSpace(bucket) == "" {
return ObjectMetadata{}, probe.NewError(InvalidArgument{}) return ObjectMetadata{}, probe.NewError(InvalidArgument{})
} }
@ -160,7 +160,7 @@ func (xl API) putObject(bucket, object, expectedMD5Sum string, reader io.Reader,
} }
// putObject - put object // putObject - put object
func (xl API) putObjectPart(bucket, object, expectedMD5Sum, uploadID string, partID int, reader io.Reader, size int64, metadata map[string]string, signature *signV4.Signature) (PartMetadata, *probe.Error) { func (xl API) putObjectPart(bucket, object, expectedMD5Sum, uploadID string, partID int, reader io.Reader, size int64, metadata map[string]string, signature *signature4.Sign) (PartMetadata, *probe.Error) {
if bucket == "" || strings.TrimSpace(bucket) == "" { if bucket == "" || strings.TrimSpace(bucket) == "" {
return PartMetadata{}, probe.NewError(InvalidArgument{}) return PartMetadata{}, probe.NewError(InvalidArgument{})
} }
@ -337,7 +337,7 @@ func (xl API) listObjectParts(bucket, object string, resources ObjectResourcesMe
} }
// completeMultipartUpload complete an incomplete multipart upload // completeMultipartUpload complete an incomplete multipart upload
func (xl API) completeMultipartUpload(bucket, object, uploadID string, data io.Reader, signature *signV4.Signature) (ObjectMetadata, *probe.Error) { func (xl API) completeMultipartUpload(bucket, object, uploadID string, data io.Reader, signature *signature4.Sign) (ObjectMetadata, *probe.Error) {
if bucket == "" || strings.TrimSpace(bucket) == "" { if bucket == "" || strings.TrimSpace(bucket) == "" {
return ObjectMetadata{}, probe.NewError(InvalidArgument{}) return ObjectMetadata{}, probe.NewError(InvalidArgument{})
} }

View File

@ -34,7 +34,7 @@ import (
"github.com/minio/minio/pkg/crypto/sha256" "github.com/minio/minio/pkg/crypto/sha256"
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
"github.com/minio/minio/pkg/quick" "github.com/minio/minio/pkg/quick"
signV4 "github.com/minio/minio/pkg/signature" "github.com/minio/minio/pkg/s3/signature4"
"github.com/minio/minio/pkg/xl/cache/data" "github.com/minio/minio/pkg/xl/cache/data"
"github.com/minio/minio/pkg/xl/cache/metadata" "github.com/minio/minio/pkg/xl/cache/metadata"
) )
@ -267,7 +267,7 @@ func isMD5SumEqual(expectedMD5Sum, actualMD5Sum string) *probe.Error {
} }
// CreateObject - create an object // CreateObject - create an object
func (xl API) CreateObject(bucket, key, expectedMD5Sum string, size int64, data io.Reader, metadata map[string]string, signature *signV4.Signature) (ObjectMetadata, *probe.Error) { func (xl API) CreateObject(bucket, key, expectedMD5Sum string, size int64, data io.Reader, metadata map[string]string, signature *signature4.Sign) (ObjectMetadata, *probe.Error) {
xl.lock.Lock() xl.lock.Lock()
defer xl.lock.Unlock() defer xl.lock.Unlock()
@ -280,7 +280,7 @@ func (xl API) CreateObject(bucket, key, expectedMD5Sum string, size int64, data
} }
// createObject - PUT object to cache buffer // createObject - PUT object to cache buffer
func (xl API) createObject(bucket, key, contentType, expectedMD5Sum string, size int64, data io.Reader, signature *signV4.Signature) (ObjectMetadata, *probe.Error) { func (xl API) createObject(bucket, key, contentType, expectedMD5Sum string, size int64, data io.Reader, signature *signature4.Sign) (ObjectMetadata, *probe.Error) {
if len(xl.config.NodeDiskMap) == 0 { if len(xl.config.NodeDiskMap) == 0 {
if size > int64(xl.config.MaxSize) { if size > int64(xl.config.MaxSize) {
generic := GenericObjectError{Bucket: bucket, Object: key} generic := GenericObjectError{Bucket: bucket, Object: key}
@ -414,7 +414,7 @@ func (xl API) createObject(bucket, key, contentType, expectedMD5Sum string, size
} }
// MakeBucket - create bucket in cache // MakeBucket - create bucket in cache
func (xl API) MakeBucket(bucketName, acl string, location io.Reader, signature *signV4.Signature) *probe.Error { func (xl API) MakeBucket(bucketName, acl string, location io.Reader, signature *signature4.Sign) *probe.Error {
xl.lock.Lock() xl.lock.Lock()
defer xl.lock.Unlock() defer xl.lock.Unlock()

View File

@ -27,7 +27,7 @@ import (
"github.com/minio/minio-go" "github.com/minio/minio-go"
"github.com/minio/minio/pkg/fs" "github.com/minio/minio/pkg/fs"
"github.com/minio/minio/pkg/probe" "github.com/minio/minio/pkg/probe"
signV4 "github.com/minio/minio/pkg/signature" "github.com/minio/minio/pkg/s3/signature4"
) )
// storageAPI container for S3 compatible API. // storageAPI container for S3 compatible API.
@ -37,7 +37,7 @@ type storageAPI struct {
// Filesystem instance. // Filesystem instance.
Filesystem fs.Filesystem Filesystem fs.Filesystem
// Signature instance. // Signature instance.
Signature *signV4.Signature Signature *signature4.Sign
// Region instance. // Region instance.
Region string Region string
} }
@ -141,7 +141,7 @@ func initAPI(conf cloudServerConfig) storageAPI {
fs, err := fs.New(conf.Path, conf.MinFreeDisk) fs, err := fs.New(conf.Path, conf.MinFreeDisk)
fatalIf(err.Trace(), "Initializing filesystem failed.", nil) fatalIf(err.Trace(), "Initializing filesystem failed.", nil)
sign, err := signV4.New(conf.AccessKeyID, conf.SecretAccessKey, conf.Region) sign, err := signature4.New(conf.AccessKeyID, conf.SecretAccessKey, conf.Region)
fatalIf(err.Trace(conf.AccessKeyID, conf.SecretAccessKey, conf.Region), "Initializing signature version '4' failed.", nil) fatalIf(err.Trace(conf.AccessKeyID, conf.SecretAccessKey, conf.Region), "Initializing signature version '4' failed.", nil)
return storageAPI{ return storageAPI{

View File

@ -1,94 +0,0 @@
/*
* Minio Cloud Storage, (C) 2015, 2016 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import (
"crypto/sha256"
"encoding/hex"
"net/http"
"strings"
signV4 "github.com/minio/minio/pkg/signature"
)
// Verify if request has JWT.
func isRequestJWT(r *http.Request) bool {
if _, ok := r.Header["Authorization"]; ok {
if strings.HasPrefix(r.Header.Get("Authorization"), jwtAlgorithm) {
return ok
}
}
return false
}
// Verify if request has AWS Signature Version '4'.
func isRequestSignatureV4(r *http.Request) bool {
if _, ok := r.Header["Authorization"]; ok {
if strings.HasPrefix(r.Header.Get("Authorization"), signV4Algorithm) {
return ok
}
}
return false
}
// Verify if request has AWS Presignature Version '4'.
func isRequestPresignedSignatureV4(r *http.Request) bool {
if _, ok := r.URL.Query()["X-Amz-Credential"]; ok {
return ok
}
return false
}
// Verify if request has AWS Post policy Signature Version '4'.
func isRequestPostPolicySignatureV4(r *http.Request) bool {
if _, ok := r.Header["Content-Type"]; ok {
if strings.Contains(r.Header.Get("Content-Type"), "multipart/form-data") {
return true
}
}
return false
}
// Verify if request requires ACL check.
func isRequestRequiresACLCheck(r *http.Request) bool {
if isRequestSignatureV4(r) || isRequestPresignedSignatureV4(r) || isRequestPostPolicySignatureV4(r) {
return false
}
return true
}
// Verify if request has valid AWS Signature Version '4'.
func isSignV4ReqAuthenticated(sign *signV4.Signature, r *http.Request) bool {
auth := sign.SetHTTPRequestToVerify(r)
if isRequestSignatureV4(r) {
dummyPayload := sha256.Sum256([]byte(""))
ok, err := auth.DoesSignatureMatch(hex.EncodeToString(dummyPayload[:]))
if err != nil {
errorIf(err.Trace(), "Signature verification failed.", nil)
return false
}
return ok
} else if isRequestPresignedSignatureV4(r) {
ok, err := auth.DoesPresignedSignatureMatch()
if err != nil {
errorIf(err.Trace(), "Presigned signature verification failed.", nil)
return false
}
return ok
}
return false
}