Example #1
0
// PutBucketHandler - PUT Bucket
// ----------
// This implementation of the PUT operation creates a new bucket for authenticated request
func (api CloudStorageAPI) PutBucketHandler(w http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	bucket := vars["bucket"]

	if !api.Anonymous {
		if isRequestRequiresACLCheck(req) {
			writeErrorResponse(w, req, AccessDenied, req.URL.Path)
			return
		}
	}

	// read from 'x-amz-acl'
	aclType := getACLType(req)
	if aclType == unsupportedACLType {
		writeErrorResponse(w, req, NotImplemented, req.URL.Path)
		return
	}

	var signature *fs.Signature
	if !api.Anonymous {
		// Init signature V4 verification
		if isRequestSignatureV4(req) {
			var err *probe.Error
			signature, err = initSignatureV4(req)
			if err != nil {
				switch err.ToGoError() {
				case errInvalidRegion:
					errorIf(err.Trace(), "Unknown region in authorization header.", nil)
					writeErrorResponse(w, req, AuthorizationHeaderMalformed, req.URL.Path)
					return
				case errAccessKeyIDInvalid:
					errorIf(err.Trace(), "Invalid access key id.", nil)
					writeErrorResponse(w, req, InvalidAccessKeyID, req.URL.Path)
					return
				default:
					errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
					writeErrorResponse(w, req, InternalError, req.URL.Path)
					return
				}
			}
		}
	}

	// if body of request is non-nil then check for validity of Content-Length
	if req.Body != nil {
		/// if Content-Length is unknown/missing, deny the request
		if req.ContentLength == -1 {
			writeErrorResponse(w, req, MissingContentLength, req.URL.Path)
			return
		}
		if signature != nil {
			locationBytes, err := ioutil.ReadAll(req.Body)
			if err != nil {
				sh := sha256.New()
				sh.Write(locationBytes)
				ok, perr := signature.DoesSignatureMatch(hex.EncodeToString(sh.Sum(nil)))
				if perr != nil {
					errorIf(perr.Trace(), "MakeBucket failed.", nil)
					writeErrorResponse(w, req, InternalError, req.URL.Path)
					return
				}
				if !ok {
					writeErrorResponse(w, req, SignatureDoesNotMatch, req.URL.Path)
					return
				}
			}
		}
	}

	err := api.Filesystem.MakeBucket(bucket, getACLTypeString(aclType))
	if err != nil {
		errorIf(err.Trace(), "MakeBucket failed.", nil)
		switch err.ToGoError().(type) {
		case fs.BucketNameInvalid:
			writeErrorResponse(w, req, InvalidBucketName, req.URL.Path)
		case fs.BucketExists:
			writeErrorResponse(w, req, BucketAlreadyExists, req.URL.Path)
		default:
			writeErrorResponse(w, req, InternalError, req.URL.Path)
		}
		return
	}
	// Make sure to add Location information here only for bucket
	w.Header().Set("Location", "/"+bucket)
	writeSuccessResponse(w, nil)
}
func (s signatureHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if isRequestPostPolicySignatureV4(r) && r.Method == "POST" {
		s.handler.ServeHTTP(w, r)
		return
	}
	var signature *fs.Signature
	if isRequestSignatureV4(r) {
		// For PUT and POST requests with payload, send the call upwards for verification.
		// Or PUT and POST requests without payload, verify here.
		if (r.Body == nil && (r.Method == "PUT" || r.Method == "POST")) || (r.Method != "PUT" && r.Method != "POST") {
			// Init signature V4 verification
			var err *probe.Error
			signature, err = initSignatureV4(r)
			if err != nil {
				switch err.ToGoError() {
				case errInvalidRegion:
					errorIf(err.Trace(), "Unknown region in authorization header.", nil)
					writeErrorResponse(w, r, AuthorizationHeaderMalformed, r.URL.Path)
					return
				case errAccessKeyIDInvalid:
					errorIf(err.Trace(), "Invalid access key id.", nil)
					writeErrorResponse(w, r, InvalidAccessKeyID, r.URL.Path)
					return
				default:
					errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
					writeErrorResponse(w, r, InternalError, r.URL.Path)
					return
				}
			}
			ok, err := signature.DoesSignatureMatch(hex.EncodeToString(sha256.Sum256([]byte(""))))
			if err != nil {
				errorIf(err.Trace(), "Unable to verify signature.", nil)
				writeErrorResponse(w, r, InternalError, r.URL.Path)
				return
			}
			if !ok {
				writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
				return
			}
		}
		s.handler.ServeHTTP(w, r)
		return
	}
	if isRequestPresignedSignatureV4(r) {
		var err *probe.Error
		signature, err = initPresignedSignatureV4(r)
		if err != nil {
			switch err.ToGoError() {
			case errAccessKeyIDInvalid:
				errorIf(err.Trace(), "Invalid access key id requested.", nil)
				writeErrorResponse(w, r, InvalidAccessKeyID, r.URL.Path)
				return
			default:
				errorIf(err.Trace(), "Initializing signature v4 failed.", nil)
				writeErrorResponse(w, r, InternalError, r.URL.Path)
				return
			}
		}
		ok, err := signature.DoesPresignedSignatureMatch()
		if err != nil {
			errorIf(err.Trace(), "Unable to verify signature.", nil)
			writeErrorResponse(w, r, InternalError, r.URL.Path)
			return
		}
		if !ok {
			writeErrorResponse(w, r, SignatureDoesNotMatch, r.URL.Path)
			return
		}
		s.handler.ServeHTTP(w, r)
		return
	}
	// call goes up from here, let ACL's verify the validity of the request
	s.handler.ServeHTTP(w, r)
}