/// <summary> /// Cleanups after a user project. /// </summary> private static void CleanUp(UserProjectSecurityChecker userProject, ProjectShim mainProjectShim) { String mainProject = String.Empty; if (userProject != null) { userProject.Dispose(); userProject = null; } if (mainProjectShim != null) { mainProject = mainProjectShim.FullFileName; mainProjectShim.ParentEngine.UnloadProject(mainProjectShim); mainProjectShim = null; } if (!String.IsNullOrEmpty(mainProject)) { try { File.Delete(mainProject); File.Delete(mainProject + ".user"); } catch (IOException) { } } }
/// <summary> /// Creates a project shim from a project file. /// </summary> /// <param name="file">The path to the project file.</param> /// <returns>The project shim</returns> private static ProjectShim CreateProjectShim(string file) { EngineShim engine = new EngineShim(); ProjectShim projectShim = engine.CreateNewProject(); projectShim.Load(file); return(projectShim); }
public void TestImportOnUserProject() { UIThreadInvoker.Invoke((ThreadInvoker) delegate() { //Get the global service provider and the dte IServiceProvider sp = VsIdeTestHostContext.ServiceProvider; DTE dte = (DTE)sp.GetService(typeof(DTE)); string importedProjFilename = CreateTempFileOnDisk(@" <Project xmlns=`msbuildnamespace`> <PropertyGroup> <ReferencePath>c:\foobar</ReferencePath> </PropertyGroup> </Project> " ); string mainProject = CreateTempFileOnDisk(@" <Project DefaultTargets=`Build` xmlns=`msbuildnamespace`> <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets`/> </Project> " ); ProjectShim mainProjectShim = null; UserProjectSecurityChecker userProject = null; try { mainProjectShim = CreateProjectShim(mainProject); userProject = CreateUserProjectSecurityChecker(sp, String.Format(@" <Project DefaultTargets=`Build` xmlns=`msbuildnamespace`> <Import Project=`{0}`/> </Project> " , importedProjFilename), mainProjectShim); MethodInfo mi = userProject.GetType().GetMethod("IsProjectSafeWithImports", BindingFlags.Instance | BindingFlags.NonPublic); string[] message = new string[1] { String.Empty }; bool result = (bool)mi.Invoke(userProject, message); Assert.IsTrue(!result && !String.IsNullOrEmpty(message[0]), "A user project contained imports and was not considered unsafe."); } finally { TestProjectForSecurity.CleanUp(userProject, mainProjectShim); File.Delete(importedProjFilename); } }); }
public void TestMultipleFailuresOnUserProject() { UIThreadInvoker.Invoke((ThreadInvoker) delegate() { //Get the global service provider and the dte IServiceProvider sp = VsIdeTestHostContext.ServiceProvider; DTE dte = (DTE)sp.GetService(typeof(DTE)); string importedProjFilename = CreateTempFileOnDisk(@" <Project xmlns=`msbuildnamespace`> <PropertyGroup> <ReferencePath>c:\foobar</ReferencePath> </PropertyGroup> </Project> " ); string mainProject = CreateTempFileOnDisk(@" <Project DefaultTargets=`Build` xmlns=`msbuildnamespace`> <Import Project=`$(MSBuildBinPath)\Microsoft.CSharp.targets`/> </Project> " ); ProjectShim mainProjectShim = null; UserProjectSecurityChecker userProject = null; try { mainProjectShim = CreateProjectShim(mainProject); userProject = CreateUserProjectSecurityChecker(sp, String.Format(@" <Project DefaultTargets=`Build` xmlns=`msbuildnamespace`> <ItemGroup> <AppConfigFileDestination Include=`$(OutDir)$(TargetFileName).config`/> </ItemGroup> <Import Project=`{0}`/> </Project> " , importedProjFilename), mainProjectShim); string errorMessage; userProject.IsProjectSafeAtLoadTime(out errorMessage); Assert.IsTrue(errorMessage.Contains("1:") && errorMessage.Contains("2:"), "The error string returning from a project with multiple failures should contain the listed failures"); } finally { TestProjectForSecurity.CleanUp(userProject, mainProjectShim); File.Delete(importedProjFilename); } }); }
/// <summary> /// Overloaded Constructor /// </summary> /// <param name="projectFilePath">path to the project file</param> /// <param name="serviceProvider">A service provider.</param> public ProjectSecurityChecker(IServiceProvider serviceProvider, string projectFilePath) { if (serviceProvider == null) { throw new ArgumentNullException("serviceProvider"); } if (String.IsNullOrEmpty(projectFilePath)) { throw new ArgumentException(SR.GetString(SR.ParameterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "projectFilePath"); } this.serviceProvider = serviceProvider; // Instantiate a new project shim that we are going to use for security checkings. EngineShim engine = new EngineShim(); this.projectShim = engine.CreateNewProject(); this.projectShim.Load(projectFilePath); }
/// <summary> /// Checks whether a set of project items described by the LoadTimeCheckItemLocation are in a safe location. /// </summary> /// <param name="projectShim">The project shim containing the items to be checked.</param> /// <param name="itemsToCheck">The list of items to check if they are in the project cone.</param> /// <param name="reasonForFailure">The reason for failure if any of the files fails</param> /// <returns>true if all project items are in the project cone. Otherwise false.</returns> internal bool CheckItemsSecurity(ProjectShim projectShim, IList<string> itemsToCheck, out string reasonForFailure) { reasonForFailure = String.Empty; // If nothing to check assume that everything is ok. if(itemsToCheck == null) { return true; } Debug.Assert(projectShim != null, "Cannot check the items if no project has been defined!"); foreach(string itemName in itemsToCheck) { BuildItemGroupShim group = projectShim.GetEvaluatedItemsByNameIgnoringCondition(itemName); if(group != null) { IEnumerator enumerator = group.GetEnumerator(); while(enumerator.MoveNext()) { BuildItemShim item = enumerator.Current as BuildItemShim; string finalItem = item.FinalItemSpec; if(!String.IsNullOrEmpty(finalItem)) { // Perform the actual check - start with normalizing the path. Relative paths // should be treated as relative to the project file. string fullPath = this.GetFullPath(finalItem); // If the fullpath of the item is suspiciously short do not check it. if(fullPath.Length >= 3) { Uri uri = null; // If we cannot create a uri from the item path return with the error if(!Uri.TryCreate(fullPath, UriKind.Absolute, out uri)) { reasonForFailure = fullPath; return false; } // Check if the item points to a network share if(uri.IsUnc) { reasonForFailure = fullPath; return false; } // Check if the item is located in a drive root directory if(uri.Segments.Length == 3 && uri.Segments[1] == ":" && uri.Segments[2][0] == Path.DirectorySeparatorChar) { reasonForFailure = fullPath; return false; } //Check if the item is not in a special folder. foreach(Uri specialFolder in this.specialFolders) { if(ItemSecurityChecker.IsItemInCone(uri, specialFolder)) { reasonForFailure = fullPath; return false; } } } else { reasonForFailure = fullPath; return false; } } } } } return true; }
/// <summary> /// Overloaded Constructor /// </summary> /// <param name="projectFilePath">path to the project file</param> /// <param name="serviceProvider">A service provider.</param> public ProjectSecurityChecker(IServiceProvider serviceProvider, string projectFilePath) { if(serviceProvider == null) { throw new ArgumentNullException("serviceProvider"); } if(String.IsNullOrEmpty(projectFilePath)) { throw new ArgumentException(SR.GetString(SR.ParameterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "projectFilePath"); } this.serviceProvider = serviceProvider; // Instantiate a new project shim that we are going to use for security checkings. EngineShim engine = new EngineShim(); this.projectShim = engine.CreateNewProject(); this.projectShim.Load(projectFilePath); }
/// <summary> /// Create a user security checker object that has its main project setup. /// </summary> internal static UserProjectSecurityChecker CreateUserProjectSecurityChecker(IServiceProvider sp, string fileContents, ProjectShim mainProjectShim) { string fileName = mainProjectShim.FullFileName + ".user"; File.WriteAllText(fileName, CleanupProjectXml(fileContents)); UserProjectSecurityChecker userProjectSecurityChecker = new UserProjectSecurityChecker(sp, fileName); PropertyInfo pi = userProjectSecurityChecker.GetType().GetProperty("MainProjectShim", BindingFlags.Instance | BindingFlags.NonPublic); pi.SetValue(userProjectSecurityChecker, mainProjectShim, new object[] { }); return(userProjectSecurityChecker); }
/// <summary> /// Cleanups after a user project. /// </summary> private static void CleanUp(UserProjectSecurityChecker userProject, ProjectShim mainProjectShim) { String mainProject = String.Empty; if(userProject != null) { userProject.Dispose(); userProject = null; } if(mainProjectShim != null) { mainProject = mainProjectShim.FullFileName; mainProjectShim.ParentEngine.UnloadProject(mainProjectShim); mainProjectShim = null; } if(!String.IsNullOrEmpty(mainProject)) { try { File.Delete(mainProject); File.Delete(mainProject + ".user"); } catch(IOException) { } } }
/// <summary> /// Create a user security checker object that has its main project setup. /// </summary> internal static UserProjectSecurityChecker CreateUserProjectSecurityChecker(IServiceProvider sp, string fileContents, ProjectShim mainProjectShim) { string fileName = mainProjectShim.FullFileName + ".user"; File.WriteAllText(fileName, CleanupProjectXml(fileContents)); UserProjectSecurityChecker userProjectSecurityChecker = new UserProjectSecurityChecker(sp, fileName); PropertyInfo pi = userProjectSecurityChecker.GetType().GetProperty("MainProjectShim", BindingFlags.Instance | BindingFlags.NonPublic); pi.SetValue(userProjectSecurityChecker, mainProjectShim, new object[] { }); return userProjectSecurityChecker; }
/// <summary> /// Checks whether a set of project items described by the LoadTimeCheckItemLocation are in a safe location. /// </summary> /// <param name="projectShim">The project shim containing the items to be checked.</param> /// <param name="itemsToCheck">The list of items to check if they are in the project cone.</param> /// <param name="reasonForFailure">The reason for failure if any of the files fails</param> /// <returns>true if all project items are in the project cone. Otherwise false.</returns> internal bool CheckItemsSecurity(ProjectShim projectShim, IList <string> itemsToCheck, out string reasonForFailure) { reasonForFailure = String.Empty; // If nothing to check assume that everything is ok. if (itemsToCheck == null) { return(true); } Debug.Assert(projectShim != null, "Cannot check the items if no project has been defined!"); foreach (string itemName in itemsToCheck) { BuildItemGroupShim group = projectShim.GetEvaluatedItemsByNameIgnoringCondition(itemName); if (group != null) { IEnumerator enumerator = group.GetEnumerator(); while (enumerator.MoveNext()) { BuildItemShim item = enumerator.Current as BuildItemShim; string finalItem = item.FinalItemSpec; if (!String.IsNullOrEmpty(finalItem)) { // Perform the actual check - start with normalizing the path. Relative paths // should be treated as relative to the project file. string fullPath = this.GetFullPath(finalItem); // If the fullpath of the item is suspiciously short do not check it. if (fullPath.Length >= 3) { Uri uri = null; // If we cannot create a uri from the item path return with the error if (!Uri.TryCreate(fullPath, UriKind.Absolute, out uri)) { reasonForFailure = fullPath; return(false); } // Check if the item points to a network share if (uri.IsUnc) { reasonForFailure = fullPath; return(false); } // Check if the item is located in a drive root directory if (uri.Segments.Length == 3 && uri.Segments[1] == ":" && uri.Segments[2][0] == Path.DirectorySeparatorChar) { reasonForFailure = fullPath; return(false); } //Check if the item is not in a special folder. foreach (Uri specialFolder in this.specialFolders) { if (ItemSecurityChecker.IsItemInCone(uri, specialFolder)) { reasonForFailure = fullPath; return(false); } } } else { reasonForFailure = fullPath; return(false); } } } } } return(true); }