From af7f7da0aad29ff9bf5adad288b512d31954b36e Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 12 May 2015 23:15:50 -0400 Subject: [PATCH] Windows: AFSGetConnectionInfo partial match validation AFSGetConnectionInfo() is called to respond to NPGetResourceInformation and NPGetConnectionPerformance WNet API requests. The former permits the requestor to provide a path containing components that are not processed by the file system represented by the called network provider. As such partial matches are permitted BUT they must consist of full components. In other words, \\afs\sh is not a valid partial match for \\afs\share but \\afs\share is a valid partial match for \\afs\share\dir. This change adds validation checks to enforce full component comparisons. It also cleans up some of the associated comparisons and trace output. Change-Id: Ia736030f554f9770b201227c4dce26d7d45fe0d2 Reviewed-on: http://gerrit.openafs.org/11887 Tested-by: BuildBot Reviewed-by: Jeffrey Altman --- .../kernel/lib/AFSNetworkProviderSupport.cpp | 52 ++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/src/WINNT/afsrdr/kernel/lib/AFSNetworkProviderSupport.cpp b/src/WINNT/afsrdr/kernel/lib/AFSNetworkProviderSupport.cpp index 559545e20..37f6175d1 100644 --- a/src/WINNT/afsrdr/kernel/lib/AFSNetworkProviderSupport.cpp +++ b/src/WINNT/afsrdr/kernel/lib/AFSNetworkProviderSupport.cpp @@ -1483,7 +1483,6 @@ AFSGetConnectionInfo( IN AFSNetworkProviderConnectionCB *ConnectCB, NTSTATUS ntStatus = STATUS_SUCCESS; AFSProviderConnectionCB *pConnection = NULL, *pBestMatch = NULL; UNICODE_STRING uniRemoteName, uniServerName, uniShareName, uniRemainingPath, uniFullName, uniRemainingPathLocal; - USHORT usNameLen = 0, usMaxNameLen = 0; BOOLEAN bEnumerationEntry = FALSE; AFSDeviceExt *pRDRDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; @@ -1665,9 +1664,22 @@ AFSGetConnectionInfo( IN AFSNetworkProviderConnectionCB *ConnectCB, else { - // - // See if we can locate it on our connection list - // + USHORT usNameLen = 0, usMaxNameLen = 0; + + // + // AFSGetConnectionInfo() is called to generate responses for + // NPGetResourceInformation and NPGetConnectionPerformance. + // The former can be called with a Connection->RemoteName that + // consists of \\server\share\dir1\dir2\...\dirN where one or + // all of the directories do not have to be processed by the + // network provider. For example, one of the directories might + // be a reparse point that redirects to another network provider. + // It might also be the case that a directory might be in the + // \\afs file namespace but not be accessible with the current + // credentials. That doesn't make the connection invalid. + // As such the network provider is not required to validate the + // entire RemoteName. This can result in false positives. + // pConnection = pRDRDevExt->Specific.RDR.ProviderConnectionList; @@ -1676,19 +1688,27 @@ AFSGetConnectionInfo( IN AFSNetworkProviderConnectionCB *ConnectCB, "AFSGetConnectionInfo Searching for full name %wZ\n", &uniFullName)); - while( pConnection != NULL) + while (pConnection != NULL) { - if( usMaxNameLen < pConnection->RemoteName.Length && - pConnection->RemoteName.Length <= uniFullName.Length) + // + // A partial match can be valid but it must occur on a + // component boundary. + // + + if (pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart && + usMaxNameLen < pConnection->RemoteName.Length && + (pConnection->RemoteName.Length == uniFullName.Length || + pConnection->RemoteName.Length < uniFullName.Length && + (uniFullName.Buffer[pConnection->RemoteName.Length/sizeof(WCHAR)] == L'\\' || + uniFullName.Buffer[pConnection->RemoteName.Length/sizeof(WCHAR)] == L'/'))) { usNameLen = uniFullName.Length; uniFullName.Length = pConnection->RemoteName.Length; - if( pConnection->AuthenticationId.QuadPart == ConnectCB->AuthenticationId.QuadPart && - RtlCompareUnicodeString( &uniFullName, + if (RtlCompareUnicodeString( &uniFullName, &pConnection->RemoteName, TRUE) == 0) { @@ -1721,8 +1741,7 @@ AFSGetConnectionInfo( IN AFSNetworkProviderConnectionCB *ConnectCB, "AFSGetConnectionInfo Using best match for %wZ\n", &pConnection->RemoteName)); } - - if( pConnection == NULL) + else { // @@ -1730,7 +1749,16 @@ AFSGetConnectionInfo( IN AFSNetworkProviderConnectionCB *ConnectCB, // pConnection = AFSLocateEnumRootEntry( &uniShareName); - } + + if (pConnection != NULL) + { + + AFSDbgTrace(( AFS_SUBSYSTEM_NETWORK_PROVIDER, + AFS_TRACE_LEVEL_VERBOSE, + "AFSGetConnectionInfo Using share connection %wZ\n", + &pConnection->RemoteName)); + } + } } if( pConnection == NULL) -- 2.39.5