github.com/cs3org/reva/v2@v2.27.7/pkg/auth/scope/publicshare.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 package scope 20 21 import ( 22 "context" 23 "strings" 24 25 appprovider "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1" 26 appregistry "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1" 27 authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1" 28 gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" 29 userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 30 permissionsv1beta1 "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1" 31 collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" 32 link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" 33 provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 34 registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1" 35 types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" 36 "github.com/cs3org/reva/v2/pkg/errtypes" 37 "github.com/cs3org/reva/v2/pkg/utils" 38 "github.com/rs/zerolog" 39 ) 40 41 // PublicStorageProviderID is the space id used for the public links storage space 42 const PublicStorageProviderID = "7993447f-687f-490d-875c-ac95e89a62a4" 43 44 func publicshareScope(ctx context.Context, scope *authpb.Scope, resource interface{}, logger *zerolog.Logger) (bool, error) { 45 var share link.PublicShare 46 err := utils.UnmarshalJSONToProtoV1(scope.Resource.Value, &share) 47 if err != nil { 48 return false, err 49 } 50 51 switch v := resource.(type) { 52 // Viewer role 53 case *registry.GetStorageProvidersRequest: 54 return checkStorageRef(ctx, &share, v.GetRef()), nil 55 case *registry.ListStorageProvidersRequest: 56 ref := &provider.Reference{} 57 if v.Opaque != nil && v.Opaque.Map != nil { 58 if e, ok := v.Opaque.Map["storage_id"]; ok { 59 if ref.ResourceId == nil { 60 ref.ResourceId = &provider.ResourceId{} 61 } 62 ref.ResourceId.StorageId = string(e.Value) 63 } 64 if e, ok := v.Opaque.Map["space_id"]; ok { 65 if ref.ResourceId == nil { 66 ref.ResourceId = &provider.ResourceId{} 67 } 68 ref.ResourceId.SpaceId = string(e.Value) 69 } 70 if e, ok := v.Opaque.Map["opaque_id"]; ok { 71 if ref.ResourceId == nil { 72 ref.ResourceId = &provider.ResourceId{} 73 } 74 ref.ResourceId.OpaqueId = string(e.Value) 75 } 76 if e, ok := v.Opaque.Map["path"]; ok { 77 ref.Path = string(e.Value) 78 } 79 } 80 return checkStorageRef(ctx, &share, ref), nil 81 case *provider.CreateHomeRequest: 82 return false, nil 83 case *provider.GetPathRequest: 84 return checkStorageRef(ctx, &share, &provider.Reference{ResourceId: v.GetResourceId()}), nil 85 case *provider.StatRequest: 86 return checkStorageRef(ctx, &share, v.GetRef()), nil 87 case *provider.GetLockRequest: 88 return checkStorageRef(ctx, &share, v.GetRef()), nil 89 case *provider.UnlockRequest: 90 return checkStorageRef(ctx, &share, v.GetRef()), nil 91 case *provider.RefreshLockRequest: 92 return checkStorageRef(ctx, &share, v.GetRef()), nil 93 case *provider.SetLockRequest: 94 return checkStorageRef(ctx, &share, v.GetRef()), nil 95 case *provider.ListContainerRequest: 96 return checkStorageRef(ctx, &share, v.GetRef()), nil 97 case *provider.InitiateFileDownloadRequest: 98 return checkStorageRef(ctx, &share, v.GetRef()), nil 99 case *appprovider.OpenInAppRequest: 100 return checkStorageRef(ctx, &share, &provider.Reference{ResourceId: v.ResourceInfo.Id}), nil 101 case *gateway.OpenInAppRequest: 102 return checkStorageRef(ctx, &share, v.GetRef()), nil 103 case *permissionsv1beta1.CheckPermissionRequest: 104 return true, nil 105 106 // Editor role 107 // need to return appropriate status codes in the ocs/ocdav layers. 108 case *provider.CreateContainerRequest: 109 return hasRoleEditor(scope) && checkStorageRef(ctx, &share, v.GetRef()), nil 110 case *provider.TouchFileRequest: 111 return hasRoleEditor(scope) && checkStorageRef(ctx, &share, v.GetRef()), nil 112 case *provider.DeleteRequest: 113 return hasRoleEditor(scope) && checkStorageRef(ctx, &share, v.GetRef()), nil 114 case *provider.MoveRequest: 115 return hasRoleEditor(scope) && checkStorageRef(ctx, &share, v.GetSource()) && checkStorageRef(ctx, &share, v.GetDestination()), nil 116 case *provider.InitiateFileUploadRequest: 117 return hasRoleEditor(scope) && checkStorageRef(ctx, &share, v.GetRef()), nil 118 case *provider.SetArbitraryMetadataRequest: 119 return hasRoleEditor(scope) && checkStorageRef(ctx, &share, v.GetRef()), nil 120 case *provider.UnsetArbitraryMetadataRequest: 121 return hasRoleEditor(scope) && checkStorageRef(ctx, &share, v.GetRef()), nil 122 123 // App provider requests 124 case *appregistry.GetDefaultAppProviderForMimeTypeRequest: 125 return true, nil 126 127 case *appregistry.GetAppProvidersRequest: 128 return true, nil 129 case *userv1beta1.GetUserByClaimRequest: 130 return true, nil 131 case *userv1beta1.GetUserRequest: 132 return true, nil 133 134 case *provider.ListStorageSpacesRequest: 135 return true, nil 136 case *link.GetPublicShareRequest: 137 return checkPublicShareRef(&share, v.GetRef()), nil 138 case *link.ListPublicSharesRequest: 139 // public links must not leak info about other links 140 return false, nil 141 142 case *collaboration.ListReceivedSharesRequest: 143 // public links must not leak info about collaborative shares 144 return false, nil 145 case string: 146 return checkResourcePath(v), nil 147 } 148 149 msg := "public resource type assertion failed" 150 logger.Debug().Str("scope", "publicshareScope").Interface("resource", resource).Msg(msg) 151 return false, errtypes.InternalError(msg) 152 } 153 154 func checkStorageRef(ctx context.Context, s *link.PublicShare, r *provider.Reference) bool { 155 // r: <resource_id:<storage_id:$storageID space_id:$spaceID opaque_id:$opaqueID> path:$path > > 156 if utils.ResourceIDEqual(s.ResourceId, r.GetResourceId()) { 157 return true 158 } 159 160 // r: <path:"/public/$token" > 161 if strings.HasPrefix(r.GetPath(), "/public/"+s.Token) || strings.HasPrefix(r.GetPath(), "./"+s.Token) { 162 return true 163 } 164 165 // r: <resource_id:<storage_id: space_id: opaque_id:$token> path:$path> 166 if id := r.GetResourceId(); id.GetStorageId() == PublicStorageProviderID { 167 // access to /public 168 if id.GetOpaqueId() == PublicStorageProviderID { 169 return true 170 } 171 // access relative to /public/$token 172 if id.GetOpaqueId() == s.Token { 173 return true 174 } 175 } 176 return false 177 } 178 179 func checkPublicShareRef(s *link.PublicShare, ref *link.PublicShareReference) bool { 180 // ref: <token:$token > 181 return ref.GetToken() == s.Token 182 } 183 184 // AddPublicShareScope adds the scope to allow access to a public share and 185 // the shared resource. 186 func AddPublicShareScope(share *link.PublicShare, role authpb.Role, scopes map[string]*authpb.Scope) (map[string]*authpb.Scope, error) { 187 // Create a new "scope share" to only expose the required fields `ResourceId` and `Token` to the scope. 188 scopeShare := &link.PublicShare{ResourceId: share.ResourceId, Token: share.Token} 189 val, err := utils.MarshalProtoV1ToJSON(scopeShare) 190 if err != nil { 191 return nil, err 192 } 193 if scopes == nil { 194 scopes = make(map[string]*authpb.Scope) 195 } 196 scopes["publicshare:"+share.Id.OpaqueId] = &authpb.Scope{ 197 Resource: &types.OpaqueEntry{ 198 Decoder: "json", 199 Value: val, 200 }, 201 Role: role, 202 } 203 return scopes, nil 204 }