@@ -445,7 +445,8 @@ function _checkPrincipals(canonicalID, arn, principal, bucketOwnerCanonicalID) {
445445// └───────┼──────────────────┘ │
446446// └──────────────────────────────────────────┘
447447//
448- function checkBucketPolicy ( policy , requestType , canonicalID , arn , bucketOwner , log , request , actionImplicitDenies ) {
448+ function checkBucketPolicy ( policy , requestType , canonicalID , arn , bucketOwner , log , request , actionImplicitDenies ,
449+ policyTarget ) {
449450 let permission = checkBucketPolicyResult . DEFAULT_DENY ;
450451 // if requester is user within bucket owner account, actions should be
451452 // allowed unless explicitly denied (assumes allowed by IAM policy)
@@ -454,10 +455,18 @@ function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, l
454455 }
455456 let copiedStatement = JSON . parse ( JSON . stringify ( policy . Statement ) ) ;
456457
458+ // The policy target, when set, is the resource being authorized when it
459+ // differs from the one the request targets (e.g. the source of a copy)
460+ let bucketName = request ?. bucketName ;
461+ let objectKey = request ?. objectKey ;
462+ if ( policyTarget ) {
463+ bucketName = policyTarget . bucketName ;
464+ objectKey = policyTarget . objectKey ;
465+ }
457466 const ip = request ? requestUtils . getClientIp ( request , config ) : undefined ;
458467 const isSecure = request ? requestUtils . getHttpProtocolSecurity ( request , config ) : undefined ;
459468 const requestContext = request ? new RequestContext ( request . headers , request . query ,
460- request . bucketName , request . objectKey , ip ,
469+ bucketName , objectKey , ip ,
461470 isSecure , request . resourceType , 's3' , null , null ,
462471 null , null , null , null , null , null , null , null , null ,
463472 request . objectLockRetentionDays ) : undefined ;
@@ -506,7 +515,7 @@ function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, l
506515}
507516
508517function processBucketPolicy ( requestType , bucket , canonicalID , arn , bucketOwner , log ,
509- request , aclPermission , results , actionImplicitDenies ) {
518+ request , aclPermission , results , actionImplicitDenies , policyTarget ) {
510519 const bucketPolicy = bucket . getBucketPolicy ( ) ;
511520 let processedResult = results [ requestType ] ;
512521 let aclRequired = false ;
@@ -515,7 +524,7 @@ function processBucketPolicy(requestType, bucket, canonicalID, arn, bucketOwner,
515524 aclRequired = true ;
516525 } else {
517526 const bucketPolicyPermission = checkBucketPolicy ( bucketPolicy , requestType , canonicalID , arn ,
518- bucketOwner , log , request , actionImplicitDenies ) ;
527+ bucketOwner , log , request , actionImplicitDenies , policyTarget ) ;
519528
520529 if ( bucketPolicyPermission === checkBucketPolicyResult . EXPLICIT_DENY ) {
521530 processedResult = false ;
@@ -534,7 +543,7 @@ function processBucketPolicy(requestType, bucket, canonicalID, arn, bucketOwner,
534543}
535544
536545function isBucketAuthorized ( bucket , requestTypesInput , canonicalID , authInfo , log , request ,
537- actionImplicitDeniesInput = { } , isWebsite = false ) {
546+ actionImplicitDeniesInput = { } , isWebsite = false , policyTarget = undefined ) {
538547 const requestTypes = Array . isArray ( requestTypesInput ) ? requestTypesInput : [ requestTypesInput ] ;
539548 const actionImplicitDenies = ! actionImplicitDeniesInput ? { } : actionImplicitDeniesInput ;
540549 const mainApiCall = requestTypes [ 0 ] ;
@@ -568,7 +577,7 @@ function isBucketAuthorized(bucket, requestTypesInput, canonicalID, authInfo, lo
568577 actionImplicitDenies . objectGet = actionImplicitDenies . objectGet || false ;
569578 }
570579 const { allowed, aclRequired } = processBucketPolicy ( _requestType , bucket , canonicalID , arn ,
571- bucket . getOwner ( ) , log , request , aclPermission , results , actionImplicitDenies ) ;
580+ bucket . getOwner ( ) , log , request , aclPermission , results , actionImplicitDenies , policyTarget ) ;
572581 if ( aclRequired && request ?. serverAccessLog ) {
573582 // eslint-disable-next-line no-param-reassign
574583 request . serverAccessLog . aclRequired = 'Yes' ;
@@ -597,7 +606,7 @@ function evaluateBucketPolicyWithIAM(bucket, requestTypesInput, canonicalID, aut
597606}
598607
599608function isObjAuthorized ( bucket , objectMD , requestTypesInput , canonicalID , authInfo , log , request ,
600- actionImplicitDeniesInput = { } , isWebsite = false ) {
609+ actionImplicitDeniesInput = { } , isWebsite = false , policyTarget = undefined ) {
601610 const requestTypes = Array . isArray ( requestTypesInput ) ? requestTypesInput : [ requestTypesInput ] ;
602611 const actionImplicitDenies = ! actionImplicitDeniesInput ? { } : actionImplicitDeniesInput ;
603612 const results = { } ;
@@ -617,7 +626,7 @@ function isObjAuthorized(bucket, objectMD, requestTypesInput, canonicalID, authI
617626 permission = 'objectPut' ;
618627 }
619628 results [ _requestType ] = isBucketAuthorized ( bucket , permission , canonicalID , authInfo , log , request ,
620- actionImplicitDenies , isWebsite ) ;
629+ actionImplicitDenies , isWebsite , policyTarget ) ;
621630 // User is already authorized on the bucket for FULL_CONTROL or WRITE or
622631 // bucket has canned ACL public-read-write
623632 if ( ( parsedMethodName === 'objectPut' || parsedMethodName === 'objectDelete' )
@@ -651,7 +660,7 @@ function isObjAuthorized(bucket, objectMD, requestTypesInput, canonicalID, authI
651660 const aclPermission = checkObjectAcls ( bucket , objectMD , parsedMethodName ,
652661 canonicalID , requesterIsNotUser , isUserUnauthenticated , mainApiCall ) ;
653662 const { allowed, aclRequired } = processBucketPolicy ( _requestType , bucket , canonicalID , arn , bucketOwner ,
654- log , request , aclPermission , results , actionImplicitDenies ) ;
663+ log , request , aclPermission , results , actionImplicitDenies , policyTarget ) ;
655664 if ( aclRequired && request ?. serverAccessLog ) {
656665 // eslint-disable-next-line no-param-reassign
657666 request . serverAccessLog . aclRequired = 'Yes' ;
0 commit comments