Browse Source

validate tags on copy object and add regex for validating tags

pull/3200/head
Lapshin Vitaliy 3 years ago
parent
commit
5f5fd0bc48
  1. 26
      weed/s3api/s3api_object_copy_handlers.go
  2. 2
      weed/s3api/s3api_object_copy_handlers_test.go
  3. 18
      weed/s3api/s3api_object_tagging_handlers.go
  4. 40
      weed/s3api/tags.go

26
weed/s3api/s3api_object_copy_handlers.go

@ -45,7 +45,11 @@ func (s3a *S3ApiServer) CopyObjectHandler(w http.ResponseWriter, r *http.Request
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidCopySource) s3err.WriteErrorResponse(w, r, s3err.ErrInvalidCopySource)
return return
} }
entry.Extended = processMetadataBytes(r.Header, entry.Extended, replaceMeta, replaceTagging)
entry.Extended, err = processMetadataBytes(r.Header, entry.Extended, replaceMeta, replaceTagging)
if err != nil {
glog.Errorf("CopyObjectHandler ValidateTags error %s: %v", r.URL, err)
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidTag)
}
err = s3a.touch(dir, name, entry) err = s3a.touch(dir, name, entry)
if err != nil { if err != nil {
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidCopySource) s3err.WriteErrorResponse(w, r, s3err.ErrInvalidCopySource)
@ -252,7 +256,7 @@ func processMetadata(reqHeader, existing http.Header, replaceMeta, replaceTaggin
return return
} }
func processMetadataBytes(reqHeader http.Header, existing map[string][]byte, replaceMeta, replaceTagging bool) (metadata map[string][]byte) {
func processMetadataBytes(reqHeader http.Header, existing map[string][]byte, replaceMeta, replaceTagging bool) (metadata map[string][]byte, err error) {
metadata = make(map[string][]byte) metadata = make(map[string][]byte)
if sc := existing[s3_constants.AmzStorageClass]; len(sc) > 0 { if sc := existing[s3_constants.AmzStorageClass]; len(sc) > 0 {
@ -277,16 +281,18 @@ func processMetadataBytes(reqHeader http.Header, existing map[string][]byte, rep
} }
} }
} }
if replaceTagging { if replaceTagging {
if tags := reqHeader.Get(s3_constants.AmzObjectTagging); tags != "" { if tags := reqHeader.Get(s3_constants.AmzObjectTagging); tags != "" {
for _, v := range strings.Split(tags, "&") {
tag := strings.Split(v, "=")
if len(tag) == 2 {
metadata[s3_constants.AmzObjectTagging+"-"+tag[0]] = []byte(tag[1])
} else if len(tag) == 1 {
metadata[s3_constants.AmzObjectTagging+"-"+tag[0]] = nil
}
parsedTags, err := parseTagsHeader(tags)
if err != nil {
return nil, err
}
err = validateTags(parsedTags)
if err != nil {
return nil, err
}
for k, v := range parsedTags {
metadata[s3_constants.AmzObjectTagging+"-"+k] = []byte(v)
} }
} }
} else { } else {

2
weed/s3api/s3api_object_copy_handlers_test.go

@ -367,7 +367,7 @@ func TestProcessMetadataBytes(t *testing.T) {
reqHeader := transferHToHeader(tc.request) reqHeader := transferHToHeader(tc.request)
existing := transferHToBytesArr(tc.existing) existing := transferHToBytesArr(tc.existing)
replaceMeta, replaceTagging := replaceDirective(reqHeader) replaceMeta, replaceTagging := replaceDirective(reqHeader)
extends := processMetadataBytes(reqHeader, existing, replaceMeta, replaceTagging)
extends, _ := processMetadataBytes(reqHeader, existing, replaceMeta, replaceTagging)
result := transferBytesArrToH(extends) result := transferBytesArrToH(extends)
fmtTagging(result, tc.want) fmtTagging(result, tc.want)

18
weed/s3api/s3api_object_tagging_handlers.go

@ -62,22 +62,10 @@ func (s3a *S3ApiServer) PutObjectTaggingHandler(w http.ResponseWriter, r *http.R
return return
} }
tags := tagging.ToTags() tags := tagging.ToTags()
if len(tags) > 10 {
glog.Errorf("PutObjectTaggingHandler tags %s: %d tags more than 10", r.URL, len(tags))
err = validateTags(tags)
if err != nil {
glog.Errorf("PutObjectTaggingHandler ValidateTags error %s: %v", r.URL, err)
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidTag) s3err.WriteErrorResponse(w, r, s3err.ErrInvalidTag)
return
}
for k, v := range tags {
if len(k) > 128 {
glog.Errorf("PutObjectTaggingHandler tags %s: tag key %s longer than 128", r.URL, k)
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidTag)
return
}
if len(v) > 256 {
glog.Errorf("PutObjectTaggingHandler tags %s: tag value %s longer than 256", r.URL, v)
s3err.WriteErrorResponse(w, r, s3err.ErrInvalidTag)
return
}
} }
if err = s3a.setTags(dir, name, tagging.ToTags()); err != nil { if err = s3a.setTags(dir, name, tagging.ToTags()); err != nil {

40
weed/s3api/tags.go

@ -2,6 +2,9 @@ package s3api
import ( import (
"encoding/xml" "encoding/xml"
"fmt"
"regexp"
"strings"
) )
type Tag struct { type Tag struct {
@ -37,3 +40,40 @@ func FromTags(tags map[string]string) (t *Tagging) {
} }
return return
} }
func parseTagsHeader(tags string) (map[string]string, error) {
var parsedTags map[string]string
for _, v := range strings.Split(tags, "&") {
tag := strings.Split(v, "=")
if len(tag) == 2 {
parsedTags[tag[0]] = tag[1]
} else if len(tag) == 1 {
parsedTags[tag[0]] = ""
}
}
return nil, nil
}
func validateTags(tags map[string]string) error {
if len(tags) > 10 {
return fmt.Errorf("validate tags: %d tags more than 10", len(tags))
}
for k, v := range tags {
if len(k) > 128 {
return fmt.Errorf("validate tags: tag key %s longer than 128", k)
}
validateKey, err := regexp.MatchString(`^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`, k)
if !validateKey && err != nil {
return fmt.Errorf("validate tags key %s error %w ", k, err)
}
if len(v) > 256 {
return fmt.Errorf("validate tags: tag value %s longer than 256", v)
}
validateValue, err := regexp.MatchString(`^([\p{L}\p{Z}\p{N}_.:/=+\-@]*)$`, v)
if !validateValue && err != nil {
return fmt.Errorf("validate tags value %s error %w ", v, err)
}
}
return nil
}
Loading…
Cancel
Save