1 2 namespace System.IdentityModel.Diagnostics 3 { 4 using System; 5 using System.Collections.Generic; 6 using System.Linq; 7 using System.Text; 8 using System.IdentityModel.Diagnostics; 9 using System.Diagnostics; 10 using System.Runtime.Diagnostics; 11 using System.Security.Authentication.ExtendedProtection; 12 using System.IO; 13 using System.Runtime.Serialization.Formatters.Binary; 14 using System.ServiceModel.Diagnostics; 15 using System.Xml; 16 using System.IdentityModel.Tokens; 17 using System.Security.Cryptography; 18 19 class SecurityTraceRecord : TraceRecord 20 { 21 String traceName; SecurityTraceRecord(String traceName)22 internal SecurityTraceRecord(String traceName) 23 { 24 if (string.IsNullOrEmpty(traceName)) 25 this.traceName = "Empty"; 26 else 27 this.traceName = traceName; 28 } 29 30 internal override string EventId { get { return BuildEventId(traceName); } } 31 } 32 33 internal static class SecurityTraceRecordHelper 34 { TraceServiceNameBindingOnServer(string serviceBindingNameSentByClient, string defaultServiceBindingNameOfServer, ServiceNameCollection serviceNameCollectionConfiguredOnServer)35 internal static void TraceServiceNameBindingOnServer(string serviceBindingNameSentByClient, string defaultServiceBindingNameOfServer, ServiceNameCollection serviceNameCollectionConfiguredOnServer) 36 { 37 TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.ServiceBindingCheck, SR.GetString(SR.TraceCodeServiceBindingCheck), new ServiceBindingNameTraceRecord(serviceBindingNameSentByClient, defaultServiceBindingNameOfServer, serviceNameCollectionConfiguredOnServer), null, null); 38 } 39 TraceChannelBindingInformation(ExtendedProtectionPolicyHelper policyHelper, bool isServer, ChannelBinding channelBinding)40 internal static void TraceChannelBindingInformation(ExtendedProtectionPolicyHelper policyHelper, bool isServer, ChannelBinding channelBinding) 41 { 42 TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.ChannelBindingCheck, SR.GetString(SR.TraceCodeChannelBindingCheck), new ChannelBindingNameTraceRecord(policyHelper, isServer, channelBinding), null, null); 43 } 44 45 class ServiceBindingNameTraceRecord : SecurityTraceRecord 46 { 47 string serviceBindingNameSentByClient; 48 string defaultServiceBindingNameOfServer; 49 ServiceNameCollection serviceNameCollectionConfiguredOnServer; 50 ServiceBindingNameTraceRecord(string serviceBindingNameSentByClient, string defaultServiceBindingNameOfServer, ServiceNameCollection serviceNameCollectionConfiguredOnServer)51 public ServiceBindingNameTraceRecord(string serviceBindingNameSentByClient, string defaultServiceBindingNameOfServer, ServiceNameCollection serviceNameCollectionConfiguredOnServer) 52 : base("ServiceBindingCheckAfterSpNego") 53 { 54 this.serviceBindingNameSentByClient = serviceBindingNameSentByClient; 55 this.defaultServiceBindingNameOfServer = defaultServiceBindingNameOfServer; 56 this.serviceNameCollectionConfiguredOnServer = serviceNameCollectionConfiguredOnServer; 57 } 58 WriteTo(XmlWriter xml)59 internal override void WriteTo(XmlWriter xml) 60 { 61 if (xml == null) 62 return; 63 64 xml.WriteComment(SR.GetString(SR.ServiceNameFromClient)); 65 xml.WriteElementString("ServiceName", this.serviceBindingNameSentByClient); 66 67 xml.WriteComment(SR.GetString(SR.ServiceNameOnService)); 68 xml.WriteStartElement("ServiceNameCollection"); 69 if (this.serviceNameCollectionConfiguredOnServer == null || this.serviceNameCollectionConfiguredOnServer.Count < 1) 70 { 71 xml.WriteElementString("ServiceName", this.defaultServiceBindingNameOfServer); 72 } 73 else 74 { 75 foreach (string serviceName in this.serviceNameCollectionConfiguredOnServer) 76 { 77 xml.WriteElementString("ServiceName", serviceName); 78 } 79 } 80 81 xml.WriteFullEndElement(); 82 83 } 84 } 85 86 class ChannelBindingNameTraceRecord : SecurityTraceRecord 87 { 88 ExtendedProtectionPolicyHelper policyHelper; 89 bool isServer; 90 bool channelBindingUsed; 91 ChannelBinding channelBinding; 92 ChannelBindingNameTraceRecord(ExtendedProtectionPolicyHelper policyHelper, bool isServer, ChannelBinding channelBinding)93 public ChannelBindingNameTraceRecord(ExtendedProtectionPolicyHelper policyHelper, bool isServer, ChannelBinding channelBinding) 94 : base("SpNegoChannelBindingInformation") 95 { 96 this.policyHelper = policyHelper; 97 this.isServer = isServer; 98 this.channelBindingUsed = false; 99 this.channelBinding = channelBinding; 100 } 101 WriteTo(XmlWriter xml)102 internal override void WriteTo(XmlWriter xml) 103 { 104 if (xml == null) 105 return; 106 if (this.policyHelper != null) 107 { 108 xml.WriteElementString("PolicyEnforcement", this.policyHelper.PolicyEnforcement.ToString()); 109 xml.WriteElementString("ProtectionScenario", this.policyHelper.ProtectionScenario.ToString()); 110 111 xml.WriteStartElement("ServiceNameCollection"); 112 113 if (this.policyHelper.ServiceNameCollection != null && this.policyHelper.ServiceNameCollection.Count > 0) 114 { 115 foreach (string serviceName in this.policyHelper.ServiceNameCollection) 116 { 117 xml.WriteElementString("ServiceName", serviceName); 118 } 119 } 120 121 xml.WriteFullEndElement(); 122 123 if (this.isServer) 124 { 125 this.channelBindingUsed = this.policyHelper.ShouldAddChannelBindingToASC(); 126 } 127 else 128 { 129 this.channelBindingUsed = this.policyHelper.ChannelBinding != null; 130 } 131 132 xml.WriteElementString("ChannelBindingUsed", this.channelBindingUsed.ToString()); 133 134 if (this.channelBinding != null && this.policyHelper.PolicyEnforcement != PolicyEnforcement.Never && this.channelBindingUsed == true) 135 { 136 ExtendedProtectionPolicy extendedProtection = new ExtendedProtectionPolicy(policyHelper.PolicyEnforcement, channelBinding); 137 xml.WriteElementString("ChannelBindingData", GetBase64EncodedChannelBindingData(extendedProtection)); 138 } 139 } 140 else 141 { 142 // This is the case for KerberosRequestorSecurityToken where policyHelper is null. 143 if (this.channelBinding != null) 144 { 145 xml.WriteElementString("ChannelBindingUsed", "true"); 146 147 // We do not know the PolicyEnforcement value here on the client side and we can not pass Never 148 //as ExtendedProtectionPolicy constructor would throw on PolicyEnforcement.Never 149 ExtendedProtectionPolicy extendedProtection = new ExtendedProtectionPolicy(PolicyEnforcement.WhenSupported, channelBinding); 150 xml.WriteElementString("ChannelBindingData", GetBase64EncodedChannelBindingData(extendedProtection)); 151 } 152 else 153 { 154 xml.WriteElementString("ChannelBindingUsed", "false"); 155 xml.WriteElementString("ChannelBindingData", null); 156 } 157 } 158 159 } 160 GetBase64EncodedChannelBindingData(ExtendedProtectionPolicy extendedProtectionPolicy)161 internal string GetBase64EncodedChannelBindingData(ExtendedProtectionPolicy extendedProtectionPolicy) 162 { 163 MemoryStream ms = new MemoryStream(); 164 BinaryFormatter formatter = new BinaryFormatter(); 165 formatter.Serialize(ms, extendedProtectionPolicy); 166 byte[] channelBindingData = ms.GetBuffer(); 167 return Convert.ToBase64String(channelBindingData, Base64FormattingOptions.None); 168 } 169 } 170 171 /// <summary> 172 /// Used to serialize a token to the trace. Used in multiple places. 173 /// </summary> 174 internal class TokenTraceRecord : SecurityTraceRecord 175 { 176 const string ElementName = "TokenTraceRecord"; 177 178 SecurityToken _securityToken; 179 TokenTraceRecord(SecurityToken securityToken)180 public TokenTraceRecord(SecurityToken securityToken) 181 : base(ElementName) 182 { 183 _securityToken = securityToken; 184 } 185 WriteSessionToken(XmlWriter writer, SessionSecurityToken sessionToken)186 void WriteSessionToken(XmlWriter writer, SessionSecurityToken sessionToken) 187 { 188 SessionSecurityTokenHandler ssth = GetOrCreateSessionSecurityTokenHandler(); 189 190 XmlDictionaryWriter dictionaryWriter = XmlDictionaryWriter.CreateDictionaryWriter(writer); 191 ssth.WriteToken(dictionaryWriter, sessionToken); 192 } 193 GetOrCreateSessionSecurityTokenHandler()194 private static SessionSecurityTokenHandler GetOrCreateSessionSecurityTokenHandler() 195 { 196 SecurityTokenHandlerCollection defaultHandlers = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection(); 197 SessionSecurityTokenHandler ssth = defaultHandlers[typeof(SessionSecurityToken)] as SessionSecurityTokenHandler; 198 199 if (ssth == null) 200 { 201 ssth = new SessionSecurityTokenHandler(); 202 defaultHandlers.AddOrReplace(ssth); 203 } 204 205 return ssth; 206 } 207 WriteTo(XmlWriter writer)208 internal override void WriteTo(XmlWriter writer) 209 { 210 writer.WriteStartElement(ElementName); 211 writer.WriteAttributeString(DiagnosticStrings.NamespaceTag, EventId); 212 213 writer.WriteStartElement("SecurityToken"); 214 writer.WriteAttributeString("Type", _securityToken.GetType().ToString()); 215 216 if (_securityToken is SessionSecurityToken) 217 { 218 WriteSessionToken(writer, _securityToken as SessionSecurityToken); 219 } 220 else 221 { 222 SecurityTokenHandlerCollection sthc = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection(); 223 if (sthc.CanWriteToken(_securityToken)) 224 { 225 { 226 sthc.WriteToken(writer, _securityToken); 227 } 228 } 229 else 230 { 231 writer.WriteElementString("Warning", SR.GetString(SR.TraceUnableToWriteToken, _securityToken.GetType().ToString())); 232 } 233 } 234 235 writer.WriteEndElement(); 236 } 237 } 238 } 239 } 240