/// Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Globalization;
using System.IO;
using Microsoft.VisualStudio.Build.ComInteropWrapper;
namespace Microsoft.VisualStudio.Project
{
///
/// Does security validation of a user project before loading the project.
///
public class UserProjectSecurityChecker : ProjectSecurityChecker
{
#region fields
///
/// The project shim for the main project file.
/// We need this otherwise the msbuild API cannot check the user file.
///
private ProjectShim mainProjectShim;
#endregion
#region ctors
///
/// Overloaded Constructor
///
/// path to the project file
/// A service provider.
public UserProjectSecurityChecker(IServiceProvider serviceProvider, string projectFilePath) :
base(serviceProvider, projectFilePath)
{
}
#endregion
#region properties
///
/// The main projects' shim.
///
internal protected ProjectShim MainProjectShim
{
get
{
return this.mainProjectShim;
}
internal set
{
this.mainProjectShim = value;
}
}
#endregion
#region overridden method
///
/// Checks if the user file is safe with imports. If it has then the user file is considered unsafe.
///
/// At return describes the reason why the projects is not considered safe.
/// true if the user project is safe regarding imports.
protected override bool IsProjectSafeWithImports(out string securityErrorMessage)
{
securityErrorMessage = String.Empty;
string[] directImports = this.SecurityCheckHelper.GetDirectlyImportedProjects(this.ProjectShim);
if(directImports != null && directImports.Length > 0)
{
securityErrorMessage = String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.DetailsUserImport, CultureInfo.CurrentUICulture), Path.GetFileName(this.ProjectShim.FullFileName), directImports[0]);
return false;
}
return true;
}
///
/// Checks if the project is safe regarding properties.
///
/// At return describes the reason why the projects is not considered safe.
/// true if the project has only safe properties.
protected override bool IsProjectSafeWithProperties(out string securityErrorMessage)
{
securityErrorMessage = String.Empty;
// Now ask the security check heper for the safe properties.
string reasonForFailure;
bool isUserFile;
bool isProjectSafe = this.SecurityCheckHelper.IsProjectSafe(ProjectSecurityChecker.DangerousPropertyProperty,
ProjectSecurityChecker.DefaultDangerousProperties,
this.mainProjectShim,
this.ProjectShim,
SecurityCheckPass.Properties,
out reasonForFailure,
out isUserFile);
// Main project gets precedence over the user project.
// Do not report that since this is only for the user file.
if(!isUserFile)
{
return true;
}
if(!isProjectSafe)
{
securityErrorMessage = this.GetMessageString(reasonForFailure, SR.DetailsProperty);
}
return isProjectSafe;
}
///
/// Checks if the project is safe regarding targets.
///
/// At return describes the reason why the projects is not considered safe.
/// true if the project has only safe targets.
protected override bool IsProjectSafeWithTargets(out string securityErrorMessage)
{
securityErrorMessage = String.Empty;
// Now ask the security check heper for the safe targets.
string reasonForFailure;
bool isUserFile;
bool isProjectSafe = this.SecurityCheckHelper.IsProjectSafe(ProjectSecurityChecker.DangerousTargetProperty,
ProjectSecurityChecker.DefaultDangerousTargets,
this.mainProjectShim,
this.ProjectShim,
SecurityCheckPass.Targets,
out reasonForFailure,
out isUserFile);
// Main project gets precedence over the user project.
// Do not report that since this is only for the user file.
if(!isUserFile)
{
return true;
}
if(!isProjectSafe)
{
securityErrorMessage = this.GetMessageString(reasonForFailure, SR.DetailsTarget);
}
return isProjectSafe;
}
///
/// Checks if the project is safe regarding items.
///
/// At return describes the reason why the projects is not considered safe.
/// true if the project has only safe items.
protected override bool IsProjectSafeWithItems(out string securityErrorMessage)
{
securityErrorMessage = String.Empty;
// Now ask the security check heper for the safe items.
string reasonForFailure;
bool isUserFile;
bool isProjectSafe = this.SecurityCheckHelper.IsProjectSafe(ProjectSecurityChecker.DangerousItemsProperty,
ProjectSecurityChecker.DefaultDangerousItems,
this.mainProjectShim,
this.ProjectShim,
SecurityCheckPass.Items,
out reasonForFailure,
out isUserFile);
// Main project gets precedence over the user project.
// Do not report that since this is only for the user file.
if(!isUserFile)
{
return true;
}
if(!isProjectSafe)
{
securityErrorMessage = this.GetMessageString(reasonForFailure, SR.DetailsItem);
}
return isProjectSafe;
}
#endregion
}
}