Initial commit
[mono.git] / mcs / class / referencesource / mscorlib / system / security / policy / applicationsecurityinfo.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 // <OWNER>[....]</OWNER>
7 // 
8
9 //
10 // ApplicationSecurityInfo.cs
11 //
12 // The application security info holds all the security related information pertinent
13 // to the application. In some sense, it is the CLR public representation of the security
14 // information held in the manifest.
15 //
16
17 namespace System.Security.Policy {
18     using System.Collections;
19     using System.Deployment.Internal.Isolation;
20     using System.Deployment.Internal.Isolation.Manifest;
21     using System.Globalization;
22     using System.Runtime.InteropServices;
23     using System.Security.Cryptography;
24     using System.Security.Permissions;
25     using System.Security.Policy;
26     using System.Security.Util;
27     using System.Threading;
28     using System.Runtime.Versioning;
29     using System.Runtime.Hosting;
30     using System.Diagnostics.Contracts;
31     
32     [System.Security.SecurityCritical]  // auto-generated
33     [SecurityPermissionAttribute(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)]
34     [System.Runtime.InteropServices.ComVisible(true)]
35     public sealed class ApplicationSecurityInfo {
36         private ActivationContext m_context;
37         private object m_appId;
38         private object m_deployId;
39         private object m_defaultRequest;
40         private object m_appEvidence;
41
42         internal ApplicationSecurityInfo () {}
43
44         //
45         // Public.
46         //
47
48         public ApplicationSecurityInfo (ActivationContext activationContext) {
49             if (activationContext == null)
50                 throw new ArgumentNullException("activationContext");
51             Contract.EndContractBlock();
52             m_context = activationContext;
53         }
54
55         public ApplicationId ApplicationId {
56             get {
57                 if (m_appId == null && m_context != null) {
58                     ICMS appManifest = m_context.ApplicationComponentManifest;
59                     ApplicationId appId = ParseApplicationId(appManifest);
60                     Interlocked.CompareExchange(ref m_appId, appId, null);
61                 }
62                 return m_appId as ApplicationId;
63             }
64             set {
65                 if (value == null)
66                     throw new ArgumentNullException("value");
67                 Contract.EndContractBlock();
68                 m_appId = value;
69             }
70         }
71
72         public ApplicationId DeploymentId {
73             get {
74                 if (m_deployId == null && m_context != null) {
75                     ICMS deplManifest = m_context.DeploymentComponentManifest;
76                     ApplicationId deplId = ParseApplicationId(deplManifest);
77                     Interlocked.CompareExchange(ref m_deployId, deplId, null);
78                 }
79                 return m_deployId as ApplicationId;
80             }
81             set {
82                 if (value == null)
83                     throw new ArgumentNullException("value");
84                 Contract.EndContractBlock();
85                 m_deployId = value;
86             }
87         }
88
89         public PermissionSet DefaultRequestSet {
90             [ResourceExposure(ResourceScope.None)]
91             [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
92             get {
93                 if (m_defaultRequest == null) {
94                     PermissionSet defaultRequest = new PermissionSet(PermissionState.None);
95                     if (m_context != null) {
96                         // read the default request from the app manifest.
97                         ICMS appManifest = m_context.ApplicationComponentManifest;
98                         string defaultPSetId = ((IMetadataSectionEntry) appManifest.MetadataSectionEntry).defaultPermissionSetID;
99                         object permissionSetObj = null;
100                         if (defaultPSetId != null && defaultPSetId.Length > 0) {
101                             ((ISectionWithStringKey) appManifest.PermissionSetSection).Lookup(defaultPSetId, out permissionSetObj);
102                             IPermissionSetEntry defaultPSet = permissionSetObj as IPermissionSetEntry;
103                             if (defaultPSet != null) {
104                                 SecurityElement seDefaultPS = SecurityElement.FromString(defaultPSet.AllData.XmlSegment);
105                                 string unrestricted = seDefaultPS.Attribute("temp:Unrestricted");
106                                 if (unrestricted != null)
107                                     seDefaultPS.AddAttribute("Unrestricted", unrestricted);
108
109                                 // Look for "SameSite" request.
110                                 string sameSite = seDefaultPS.Attribute("SameSite");
111                                 if (String.Compare(sameSite, "Site", StringComparison.OrdinalIgnoreCase) == 0) {
112                                     Url url = new Url(m_context.Identity.CodeBase);
113                                     URLString urlString = url.GetURLString();
114
115                                     // Create a same site web permission for HTTP deployed applications. We'll
116                                     // always use a v2.0 WebPermission for this because this XML is loadable
117                                     // on all versions of the framework that support ClickOnce.  This allows
118                                     // newer versions of the framework to create ApplicationSecurityInfo objects
119                                     // that may eventually be used by applications running against older versions
120                                     // of the framework.
121                                     NetCodeGroup netCodeGroup = new NetCodeGroup(new AllMembershipCondition());
122                                     SecurityElement webPermission =
123                                         netCodeGroup.CreateWebPermission(urlString.Host,
124                                                                          urlString.Scheme,
125                                                                          urlString.Port,
126                                                                          "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken);
127
128                                     if (webPermission != null) {
129                                         seDefaultPS.AddChild(webPermission);
130                                     }
131
132                                     if (String.Compare("file:", 0, m_context.Identity.CodeBase, 0, 5, StringComparison.OrdinalIgnoreCase) == 0) {
133                                         FileCodeGroup fileCodeGroup = new FileCodeGroup(new AllMembershipCondition(), FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery);
134                                         PolicyStatement ps = fileCodeGroup.CalculatePolicy(url);
135                                         if (ps != null) {
136                                             PermissionSet filePermissionSet = ps.PermissionSet;
137                                             if (filePermissionSet != null) {
138                                                 seDefaultPS.AddChild(filePermissionSet.GetPermission(typeof(FileIOPermission)).ToXml());
139                                             }
140                                         }
141                                     }
142                                 }
143
144                                 // We need to use a ReadOnlyPermissionSet to ensure that any permissions in
145                                 // the manifest which were created on a previous runtime are stored back to
146                                 // the application store in a format that the previous runtime can understand.
147                                 defaultRequest = new ReadOnlyPermissionSet(seDefaultPS);
148                             }
149                         }
150                     }
151                     Interlocked.CompareExchange(ref m_defaultRequest, defaultRequest, null);
152                 }
153                 return m_defaultRequest as PermissionSet;
154             }
155             set {
156                 if (value == null)
157                     throw new ArgumentNullException("value");
158                 Contract.EndContractBlock();
159                 m_defaultRequest = value;
160             }
161         }
162
163         public Evidence ApplicationEvidence {
164             [ResourceExposure(ResourceScope.None)]
165             [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
166             get {
167                 if (m_appEvidence == null) {
168                     Evidence appEvidence = new Evidence();
169                     if (m_context != null) {
170                         appEvidence = new Evidence();
171                         Url deploymentUrl = new Url(m_context.Identity.CodeBase);
172                         appEvidence.AddHostEvidence(deploymentUrl);
173                         appEvidence.AddHostEvidence(Zone.CreateFromUrl(m_context.Identity.CodeBase));
174                         if (String.Compare("file:", 0, m_context.Identity.CodeBase, 0, 5, StringComparison.OrdinalIgnoreCase) != 0) {
175                             appEvidence.AddHostEvidence(Site.CreateFromUrl(m_context.Identity.CodeBase));
176                         }
177                         appEvidence.AddHostEvidence(new StrongName(new StrongNamePublicKeyBlob(DeploymentId.m_publicKeyToken),
178                                                                    DeploymentId.Name,
179                                                                    DeploymentId.Version));
180                         appEvidence.AddHostEvidence(new ActivationArguments(m_context));
181                     }
182                     Interlocked.CompareExchange(ref m_appEvidence, appEvidence, null);
183                 }
184                 return m_appEvidence as Evidence;
185             }
186             set {
187                 if (value == null)
188                     throw new ArgumentNullException("value");
189                 Contract.EndContractBlock();
190                 m_appEvidence = value;
191             }
192         }
193
194         //
195         // Internal.
196         //
197
198         private static ApplicationId ParseApplicationId (ICMS manifest) {
199             if (manifest.Identity == null)
200                 return null;
201
202             return new ApplicationId(Hex.DecodeHexString(manifest.Identity.GetAttribute("", "publicKeyToken")),
203                                      manifest.Identity.GetAttribute("", "name"),
204                                      new Version(manifest.Identity.GetAttribute("", "version")),
205                                      manifest.Identity.GetAttribute("", "processorArchitecture"),
206                                      manifest.Identity.GetAttribute("", "culture"));
207         }
208     }
209 }