1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.ComponentModel; 6 using System.Diagnostics; 7 using System.Globalization; 8 using System.Net.Security; 9 using System.Runtime.InteropServices; 10 11 namespace System.Net 12 { 13 internal static class SSPIWrapper 14 { EnumerateSecurityPackages(SSPIInterface secModule)15 internal static SecurityPackageInfoClass[] EnumerateSecurityPackages(SSPIInterface secModule) 16 { 17 if (NetEventSource.IsEnabled) NetEventSource.Enter(null); 18 19 if (secModule.SecurityPackages == null) 20 { 21 lock (secModule) 22 { 23 if (secModule.SecurityPackages == null) 24 { 25 int moduleCount = 0; 26 SafeFreeContextBuffer arrayBaseHandle = null; 27 try 28 { 29 int errorCode = secModule.EnumerateSecurityPackages(out moduleCount, out arrayBaseHandle); 30 if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"arrayBase: {arrayBaseHandle}"); 31 if (errorCode != 0) 32 { 33 throw new Win32Exception(errorCode); 34 } 35 36 var securityPackages = new SecurityPackageInfoClass[moduleCount]; 37 38 int i; 39 for (i = 0; i < moduleCount; i++) 40 { 41 securityPackages[i] = new SecurityPackageInfoClass(arrayBaseHandle, i); 42 if (NetEventSource.IsEnabled) NetEventSource.Log.EnumerateSecurityPackages(securityPackages[i].Name); 43 } 44 45 secModule.SecurityPackages = securityPackages; 46 } 47 finally 48 { 49 if (arrayBaseHandle != null) 50 { 51 arrayBaseHandle.Dispose(); 52 } 53 } 54 } 55 } 56 } 57 58 if (NetEventSource.IsEnabled) NetEventSource.Exit(null); 59 return secModule.SecurityPackages; 60 } 61 GetVerifyPackageInfo(SSPIInterface secModule, string packageName)62 internal static SecurityPackageInfoClass GetVerifyPackageInfo(SSPIInterface secModule, string packageName) 63 { 64 return GetVerifyPackageInfo(secModule, packageName, false); 65 } 66 GetVerifyPackageInfo(SSPIInterface secModule, string packageName, bool throwIfMissing)67 internal static SecurityPackageInfoClass GetVerifyPackageInfo(SSPIInterface secModule, string packageName, bool throwIfMissing) 68 { 69 SecurityPackageInfoClass[] supportedSecurityPackages = EnumerateSecurityPackages(secModule); 70 if (supportedSecurityPackages != null) 71 { 72 for (int i = 0; i < supportedSecurityPackages.Length; i++) 73 { 74 if (string.Compare(supportedSecurityPackages[i].Name, packageName, StringComparison.OrdinalIgnoreCase) == 0) 75 { 76 return supportedSecurityPackages[i]; 77 } 78 } 79 } 80 81 if (NetEventSource.IsEnabled) NetEventSource.Log.SspiPackageNotFound(packageName); 82 83 if (throwIfMissing) 84 { 85 throw new NotSupportedException(SR.net_securitypackagesupport); 86 } 87 88 return null; 89 } 90 AcquireDefaultCredential(SSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent)91 public static SafeFreeCredentials AcquireDefaultCredential(SSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent) 92 { 93 if (NetEventSource.IsEnabled) 94 { 95 NetEventSource.Enter(null, package); 96 NetEventSource.Log.AcquireDefaultCredential(package, intent); 97 } 98 99 SafeFreeCredentials outCredential = null; 100 int errorCode = secModule.AcquireDefaultCredential(package, intent, out outCredential); 101 102 if (errorCode != 0) 103 { 104 if (NetEventSource.IsEnabled) NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_with_error, nameof(AcquireDefaultCredential), $"0x{errorCode:X}")); 105 throw new Win32Exception(errorCode); 106 } 107 return outCredential; 108 } 109 AcquireCredentialsHandle(SSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent, ref Interop.SspiCli.SEC_WINNT_AUTH_IDENTITY_W authdata)110 public static SafeFreeCredentials AcquireCredentialsHandle(SSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent, ref Interop.SspiCli.SEC_WINNT_AUTH_IDENTITY_W authdata) 111 { 112 if (NetEventSource.IsEnabled) 113 { 114 NetEventSource.Enter(null, package); 115 NetEventSource.Log.AcquireCredentialsHandle(package, intent, authdata); 116 } 117 118 SafeFreeCredentials credentialsHandle = null; 119 int errorCode = secModule.AcquireCredentialsHandle(package, 120 intent, 121 ref authdata, 122 out credentialsHandle); 123 124 if (errorCode != 0) 125 { 126 if (NetEventSource.IsEnabled) NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_with_error, nameof(AcquireCredentialsHandle), $"0x{errorCode:X}")); 127 128 throw new Win32Exception(errorCode); 129 } 130 return credentialsHandle; 131 } 132 AcquireCredentialsHandle(SSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent, ref SafeSspiAuthDataHandle authdata)133 public static SafeFreeCredentials AcquireCredentialsHandle(SSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent, ref SafeSspiAuthDataHandle authdata) 134 { 135 if (NetEventSource.IsEnabled) NetEventSource.Log.AcquireCredentialsHandle(package, intent, authdata); 136 137 SafeFreeCredentials credentialsHandle = null; 138 int errorCode = secModule.AcquireCredentialsHandle(package, intent, ref authdata, out credentialsHandle); 139 140 if (errorCode != 0) 141 { 142 if (NetEventSource.IsEnabled) NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_with_error, nameof(AcquireCredentialsHandle), $"0x{errorCode:X}")); 143 throw new Win32Exception(errorCode); 144 } 145 146 return credentialsHandle; 147 } 148 AcquireCredentialsHandle(SSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent, Interop.SspiCli.SCHANNEL_CRED scc)149 public static SafeFreeCredentials AcquireCredentialsHandle(SSPIInterface secModule, string package, Interop.SspiCli.CredentialUse intent, Interop.SspiCli.SCHANNEL_CRED scc) 150 { 151 if (NetEventSource.IsEnabled) 152 { 153 NetEventSource.Enter(null, package); 154 NetEventSource.Log.AcquireCredentialsHandle(package, intent, scc); 155 } 156 157 SafeFreeCredentials outCredential = null; 158 int errorCode = secModule.AcquireCredentialsHandle( 159 package, 160 intent, 161 ref scc, 162 out outCredential); 163 164 if (errorCode != 0) 165 { 166 if (NetEventSource.IsEnabled) NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_with_error, nameof(AcquireCredentialsHandle), $"0x{errorCode:X}")); 167 throw new Win32Exception(errorCode); 168 } 169 170 if (NetEventSource.IsEnabled) NetEventSource.Exit(null, outCredential); 171 return outCredential; 172 } 173 InitializeSecurityContext(SSPIInterface secModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags)174 internal static int InitializeSecurityContext(SSPIInterface secModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags) 175 { 176 if (NetEventSource.IsEnabled) NetEventSource.Log.InitializeSecurityContext(credential, context, targetName, inFlags); 177 178 int errorCode = secModule.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, datarep, inputBuffer, outputBuffer, ref outFlags); 179 180 if (NetEventSource.IsEnabled) NetEventSource.Log.SecurityContextInputBuffer(nameof(InitializeSecurityContext), inputBuffer?.size ?? 0, outputBuffer.size, (Interop.SECURITY_STATUS)errorCode); 181 182 return errorCode; 183 } 184 InitializeSecurityContext(SSPIInterface secModule, SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags)185 internal static int InitializeSecurityContext(SSPIInterface secModule, SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags) 186 { 187 if (NetEventSource.IsEnabled) NetEventSource.Log.InitializeSecurityContext(credential, context, targetName, inFlags); 188 189 int errorCode = secModule.InitializeSecurityContext(credential, ref context, targetName, inFlags, datarep, inputBuffers, outputBuffer, ref outFlags); 190 191 if (NetEventSource.IsEnabled) NetEventSource.Log.SecurityContextInputBuffers(nameof(InitializeSecurityContext), inputBuffers?.Length ?? 0, outputBuffer.size, (Interop.SECURITY_STATUS)errorCode); 192 193 return errorCode; 194 } 195 AcceptSecurityContext(SSPIInterface secModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags)196 internal static int AcceptSecurityContext(SSPIInterface secModule, ref SafeFreeCredentials credential, ref SafeDeleteContext context, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags) 197 { 198 if (NetEventSource.IsEnabled) NetEventSource.Log.AcceptSecurityContext(credential, context, inFlags); 199 200 int errorCode = secModule.AcceptSecurityContext(ref credential, ref context, inputBuffer, inFlags, datarep, outputBuffer, ref outFlags); 201 202 if (NetEventSource.IsEnabled) NetEventSource.Log.SecurityContextInputBuffer(nameof(AcceptSecurityContext), inputBuffer?.size ?? 0, outputBuffer.size, (Interop.SECURITY_STATUS)errorCode); 203 204 return errorCode; 205 } 206 AcceptSecurityContext(SSPIInterface secModule, SafeFreeCredentials credential, ref SafeDeleteContext context, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags)207 internal static int AcceptSecurityContext(SSPIInterface secModule, SafeFreeCredentials credential, ref SafeDeleteContext context, Interop.SspiCli.ContextFlags inFlags, Interop.SspiCli.Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref Interop.SspiCli.ContextFlags outFlags) 208 { 209 if (NetEventSource.IsEnabled) NetEventSource.Log.AcceptSecurityContext(credential, context, inFlags); 210 211 int errorCode = secModule.AcceptSecurityContext(credential, ref context, inputBuffers, inFlags, datarep, outputBuffer, ref outFlags); 212 213 if (NetEventSource.IsEnabled) NetEventSource.Log.SecurityContextInputBuffers(nameof(AcceptSecurityContext), inputBuffers?.Length ?? 0, outputBuffer.size, (Interop.SECURITY_STATUS)errorCode); 214 215 return errorCode; 216 } 217 CompleteAuthToken(SSPIInterface secModule, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers)218 internal static int CompleteAuthToken(SSPIInterface secModule, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers) 219 { 220 int errorCode = secModule.CompleteAuthToken(ref context, inputBuffers); 221 222 if (NetEventSource.IsEnabled) NetEventSource.Log.OperationReturnedSomething(nameof(CompleteAuthToken), (Interop.SECURITY_STATUS)errorCode); 223 224 return errorCode; 225 } 226 ApplyControlToken(SSPIInterface secModule, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers)227 internal static int ApplyControlToken(SSPIInterface secModule, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers) 228 { 229 int errorCode = secModule.ApplyControlToken(ref context, inputBuffers); 230 231 if (NetEventSource.IsEnabled) NetEventSource.Log.OperationReturnedSomething(nameof(ApplyControlToken), (Interop.SECURITY_STATUS)errorCode); 232 233 return errorCode; 234 } 235 QuerySecurityContextToken(SSPIInterface secModule, SafeDeleteContext context, out SecurityContextTokenHandle token)236 public static int QuerySecurityContextToken(SSPIInterface secModule, SafeDeleteContext context, out SecurityContextTokenHandle token) 237 { 238 return secModule.QuerySecurityContextToken(context, out token); 239 } 240 EncryptMessage(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber)241 public static int EncryptMessage(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) 242 { 243 return EncryptDecryptHelper(OP.Encrypt, secModule, context, input, sequenceNumber); 244 } 245 DecryptMessage(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber)246 public static int DecryptMessage(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) 247 { 248 return EncryptDecryptHelper(OP.Decrypt, secModule, context, input, sequenceNumber); 249 } 250 MakeSignature(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber)251 internal static int MakeSignature(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) 252 { 253 return EncryptDecryptHelper(OP.MakeSignature, secModule, context, input, sequenceNumber); 254 } 255 VerifySignature(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber)256 public static int VerifySignature(SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) 257 { 258 return EncryptDecryptHelper(OP.VerifySignature, secModule, context, input, sequenceNumber); 259 } 260 261 private enum OP 262 { 263 Encrypt = 1, 264 Decrypt, 265 MakeSignature, 266 VerifySignature 267 } 268 EncryptDecryptHelper(OP op, SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber)269 private static unsafe int EncryptDecryptHelper(OP op, SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber) 270 { 271 Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(input.Length); 272 var unmanagedBuffer = new Interop.SspiCli.SecBuffer[input.Length]; 273 274 fixed (Interop.SspiCli.SecBuffer* unmanagedBufferPtr = unmanagedBuffer) 275 { 276 sdcInOut.pBuffers = unmanagedBufferPtr; 277 GCHandle[] pinnedBuffers = new GCHandle[input.Length]; 278 byte[][] buffers = new byte[input.Length][]; 279 try 280 { 281 for (int i = 0; i < input.Length; i++) 282 { 283 SecurityBuffer iBuffer = input[i]; 284 unmanagedBuffer[i].cbBuffer = iBuffer.size; 285 unmanagedBuffer[i].BufferType = iBuffer.type; 286 if (iBuffer.token == null || iBuffer.token.Length == 0) 287 { 288 unmanagedBuffer[i].pvBuffer = IntPtr.Zero; 289 } 290 else 291 { 292 pinnedBuffers[i] = GCHandle.Alloc(iBuffer.token, GCHandleType.Pinned); 293 unmanagedBuffer[i].pvBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(iBuffer.token, iBuffer.offset); 294 buffers[i] = iBuffer.token; 295 } 296 } 297 298 // The result is written in the input Buffer passed as type=BufferType.Data. 299 int errorCode; 300 switch (op) 301 { 302 case OP.Encrypt: 303 errorCode = secModule.EncryptMessage(context, ref sdcInOut, sequenceNumber); 304 break; 305 306 case OP.Decrypt: 307 errorCode = secModule.DecryptMessage(context, ref sdcInOut, sequenceNumber); 308 break; 309 310 case OP.MakeSignature: 311 errorCode = secModule.MakeSignature(context, ref sdcInOut, sequenceNumber); 312 break; 313 314 case OP.VerifySignature: 315 errorCode = secModule.VerifySignature(context, ref sdcInOut, sequenceNumber); 316 break; 317 318 default: 319 NetEventSource.Fail(null, $"Unknown OP: {op}"); 320 throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); 321 } 322 323 // Marshalling back returned sizes / data. 324 for (int i = 0; i < input.Length; i++) 325 { 326 SecurityBuffer iBuffer = input[i]; 327 iBuffer.size = unmanagedBuffer[i].cbBuffer; 328 iBuffer.type = unmanagedBuffer[i].BufferType; 329 330 if (iBuffer.size == 0) 331 { 332 iBuffer.offset = 0; 333 iBuffer.token = null; 334 } 335 else 336 { 337 checked 338 { 339 // Find the buffer this is inside of. Usually they all point inside buffer 0. 340 int j; 341 for (j = 0; j < input.Length; j++) 342 { 343 if (buffers[j] == null) 344 { 345 continue; 346 } 347 348 byte* bufferAddress = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers[j], 0); 349 if ((byte*)unmanagedBuffer[i].pvBuffer >= bufferAddress && 350 (byte*)unmanagedBuffer[i].pvBuffer + iBuffer.size <= bufferAddress + buffers[j].Length) 351 { 352 iBuffer.offset = (int)((byte*)unmanagedBuffer[i].pvBuffer - bufferAddress); 353 iBuffer.token = buffers[j]; 354 break; 355 } 356 } 357 358 if (j >= input.Length) 359 { 360 NetEventSource.Fail(null, "Output buffer out of range."); 361 iBuffer.size = 0; 362 iBuffer.offset = 0; 363 iBuffer.token = null; 364 } 365 } 366 } 367 368 // Backup validate the new sizes. 369 if (iBuffer.offset < 0 || iBuffer.offset > (iBuffer.token == null ? 0 : iBuffer.token.Length)) 370 { 371 NetEventSource.Fail(null, $"'offset' out of range. [{iBuffer.offset}]"); 372 } 373 374 if (iBuffer.size < 0 || iBuffer.size > (iBuffer.token == null ? 0 : iBuffer.token.Length - iBuffer.offset)) 375 { 376 NetEventSource.Fail(null, $"'size' out of range. [{iBuffer.size}]"); 377 } 378 } 379 380 if (NetEventSource.IsEnabled && errorCode != 0) 381 { 382 if (errorCode == Interop.SspiCli.SEC_I_RENEGOTIATE) 383 { 384 NetEventSource.Error(null, SR.Format(SR.event_OperationReturnedSomething, op, "SEC_I_RENEGOTIATE")); 385 } 386 else 387 { 388 NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_with_error, op, $"0x{0:X}")); 389 } 390 } 391 392 return errorCode; 393 } 394 finally 395 { 396 for (int i = 0; i < pinnedBuffers.Length; ++i) 397 { 398 if (pinnedBuffers[i].IsAllocated) 399 { 400 pinnedBuffers[i].Free(); 401 } 402 } 403 } 404 } 405 } 406 QueryContextChannelBinding(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.SspiCli.ContextAttribute contextAttribute)407 public static SafeFreeContextBufferChannelBinding QueryContextChannelBinding(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.SspiCli.ContextAttribute contextAttribute) 408 { 409 if (NetEventSource.IsEnabled) NetEventSource.Enter(null, contextAttribute); 410 411 SafeFreeContextBufferChannelBinding result; 412 int errorCode = secModule.QueryContextChannelBinding(securityContext, contextAttribute, out result); 413 if (errorCode != 0) 414 { 415 if (NetEventSource.IsEnabled) NetEventSource.Exit(null, $"ERROR = {ErrorDescription(errorCode)}"); 416 return null; 417 } 418 419 if (NetEventSource.IsEnabled) NetEventSource.Exit(null, result); 420 return result; 421 } 422 QueryContextAttributes(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.SspiCli.ContextAttribute contextAttribute)423 public static object QueryContextAttributes(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.SspiCli.ContextAttribute contextAttribute) 424 { 425 int errorCode; 426 return QueryContextAttributes(secModule, securityContext, contextAttribute, out errorCode); 427 } 428 QueryContextAttributes(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.SspiCli.ContextAttribute contextAttribute, out int errorCode)429 public static object QueryContextAttributes(SSPIInterface secModule, SafeDeleteContext securityContext, Interop.SspiCli.ContextAttribute contextAttribute, out int errorCode) 430 { 431 if (NetEventSource.IsEnabled) NetEventSource.Enter(null, contextAttribute); 432 433 int nativeBlockSize = IntPtr.Size; 434 Type handleType = null; 435 436 switch (contextAttribute) 437 { 438 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES: 439 nativeBlockSize = SecPkgContext_Sizes.SizeOf; 440 break; 441 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_STREAM_SIZES: 442 nativeBlockSize = SecPkgContext_StreamSizes.SizeOf; 443 break; 444 445 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NAMES: 446 handleType = typeof(SafeFreeContextBuffer); 447 break; 448 449 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_PACKAGE_INFO: 450 handleType = typeof(SafeFreeContextBuffer); 451 break; 452 453 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NEGOTIATION_INFO: 454 handleType = typeof(SafeFreeContextBuffer); 455 nativeBlockSize = Marshal.SizeOf<SecPkgContext_NegotiationInfoW>(); 456 break; 457 458 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CLIENT_SPECIFIED_TARGET: 459 handleType = typeof(SafeFreeContextBuffer); 460 break; 461 462 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_REMOTE_CERT_CONTEXT: 463 handleType = typeof(SafeFreeCertContext); 464 break; 465 466 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_LOCAL_CERT_CONTEXT: 467 handleType = typeof(SafeFreeCertContext); 468 break; 469 470 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_ISSUER_LIST_EX: 471 nativeBlockSize = Marshal.SizeOf<Interop.SspiCli.SecPkgContext_IssuerListInfoEx>(); 472 handleType = typeof(SafeFreeContextBuffer); 473 break; 474 475 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CONNECTION_INFO: 476 nativeBlockSize = Marshal.SizeOf<SecPkgContext_ConnectionInfo>(); 477 break; 478 479 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_APPLICATION_PROTOCOL: 480 nativeBlockSize = Marshal.SizeOf<Interop.SecPkgContext_ApplicationProtocol>(); 481 break; 482 483 default: 484 throw new ArgumentException(SR.Format(SR.net_invalid_enum, nameof(contextAttribute)), nameof(contextAttribute)); 485 } 486 487 SafeHandle sspiHandle = null; 488 object attribute = null; 489 490 try 491 { 492 var nativeBuffer = new byte[nativeBlockSize]; 493 errorCode = secModule.QueryContextAttributes(securityContext, contextAttribute, nativeBuffer, handleType, out sspiHandle); 494 if (errorCode != 0) 495 { 496 if (NetEventSource.IsEnabled) NetEventSource.Exit(null, $"ERROR = {ErrorDescription(errorCode)}"); 497 return null; 498 } 499 500 switch (contextAttribute) 501 { 502 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES: 503 attribute = new SecPkgContext_Sizes(nativeBuffer); 504 break; 505 506 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_STREAM_SIZES: 507 attribute = new SecPkgContext_StreamSizes(nativeBuffer); 508 break; 509 510 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NAMES: 511 attribute = Marshal.PtrToStringUni(sspiHandle.DangerousGetHandle()); 512 break; 513 514 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_PACKAGE_INFO: 515 attribute = new SecurityPackageInfoClass(sspiHandle, 0); 516 break; 517 518 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_NEGOTIATION_INFO: 519 unsafe 520 { 521 fixed (void* ptr = &nativeBuffer[0]) 522 { 523 attribute = new NegotiationInfoClass(sspiHandle, Marshal.ReadInt32(new IntPtr(ptr), SecPkgContext_NegotiationInfoW.NegotiationStateOffest)); 524 } 525 } 526 break; 527 528 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CLIENT_SPECIFIED_TARGET: 529 attribute = Marshal.PtrToStringUni(sspiHandle.DangerousGetHandle()); 530 break; 531 532 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_LOCAL_CERT_CONTEXT: 533 // Fall-through to RemoteCertificate is intentional. 534 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_REMOTE_CERT_CONTEXT: 535 attribute = sspiHandle; 536 sspiHandle = null; 537 break; 538 539 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_ISSUER_LIST_EX: 540 attribute = new Interop.SspiCli.SecPkgContext_IssuerListInfoEx(sspiHandle, nativeBuffer); 541 sspiHandle = null; 542 break; 543 544 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CONNECTION_INFO: 545 attribute = new SecPkgContext_ConnectionInfo(nativeBuffer); 546 break; 547 548 case Interop.SspiCli.ContextAttribute.SECPKG_ATTR_APPLICATION_PROTOCOL: 549 unsafe 550 { 551 fixed (void *ptr = nativeBuffer) 552 { 553 attribute = Marshal.PtrToStructure<Interop.SecPkgContext_ApplicationProtocol>(new IntPtr(ptr)); 554 } 555 } 556 break; 557 558 default: 559 // Will return null. 560 break; 561 } 562 } 563 finally 564 { 565 if (sspiHandle != null) 566 { 567 sspiHandle.Dispose(); 568 } 569 } 570 571 if (NetEventSource.IsEnabled) NetEventSource.Exit(null, attribute); 572 return attribute; 573 } 574 ErrorDescription(int errorCode)575 public static string ErrorDescription(int errorCode) 576 { 577 if (errorCode == -1) 578 { 579 return "An exception when invoking Win32 API"; 580 } 581 582 switch ((Interop.SECURITY_STATUS)errorCode) 583 { 584 case Interop.SECURITY_STATUS.InvalidHandle: 585 return "Invalid handle"; 586 case Interop.SECURITY_STATUS.InvalidToken: 587 return "Invalid token"; 588 case Interop.SECURITY_STATUS.ContinueNeeded: 589 return "Continue needed"; 590 case Interop.SECURITY_STATUS.IncompleteMessage: 591 return "Message incomplete"; 592 case Interop.SECURITY_STATUS.WrongPrincipal: 593 return "Wrong principal"; 594 case Interop.SECURITY_STATUS.TargetUnknown: 595 return "Target unknown"; 596 case Interop.SECURITY_STATUS.PackageNotFound: 597 return "Package not found"; 598 case Interop.SECURITY_STATUS.BufferNotEnough: 599 return "Buffer not enough"; 600 case Interop.SECURITY_STATUS.MessageAltered: 601 return "Message altered"; 602 case Interop.SECURITY_STATUS.UntrustedRoot: 603 return "Untrusted root"; 604 default: 605 return "0x" + errorCode.ToString("x", NumberFormatInfo.InvariantInfo); 606 } 607 } 608 } // class SSPIWrapper 609 } 610