Initial port.

This commit is contained in:
Chris Ross 2014-02-07 17:01:08 -08:00
commit 251630590d
198 changed files with 37324 additions and 0 deletions

50
.gitattributes vendored Normal file
View File

@ -0,0 +1,50 @@
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
*.jpg binary
*.png binary
*.gif binary
*.cs text=auto diff=csharp
*.vb text=auto
*.resx text=auto
*.c text=auto
*.cpp text=auto
*.cxx text=auto
*.h text=auto
*.hxx text=auto
*.py text=auto
*.rb text=auto
*.java text=auto
*.html text=auto
*.htm text=auto
*.css text=auto
*.scss text=auto
*.sass text=auto
*.less text=auto
*.js text=auto
*.lisp text=auto
*.clj text=auto
*.sql text=auto
*.php text=auto
*.lua text=auto
*.m text=auto
*.asm text=auto
*.erl text=auto
*.fs text=auto
*.fsx text=auto
*.hs text=auto
*.csproj text=auto
*.vbproj text=auto
*.fsproj text=auto
*.dbproj text=auto
*.sln text=auto eol=crlf

22
.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
[Oo]bj/
[Bb]in/
TestResults/
.nuget/
_ReSharper.*/
packages/
artifacts/
PublishProfiles/
*.user
*.suo
*.cache
*.docstates
_ReSharper.*
nuget.exe
*net45.csproj
*k10.csproj
*.psess
*.vsp
*.pidb
*.userprefs
*DS_Store
*.ncrunchsolution

94
KatanaInternal.sln Normal file
View File

@ -0,0 +1,94 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30110.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClient", "samples\TestClient\TestClient.csproj", "{8B828433-B333-4C19-96AE-00BFFF9D8841}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Server.WebListener.k10", "src\Microsoft.AspNet.Server.WebListener\Microsoft.AspNet.Server.WebListener.k10.csproj", "{6D9D3023-3ED7-4C95-80F0-347843ABD759}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Server.WebListener.net45", "src\Microsoft.AspNet.Server.WebListener\Microsoft.AspNet.Server.WebListener.net45.csproj", "{253B9134-B6EB-4E59-8725-D983FD941A21}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.WebSockets.net45", "src\Microsoft.AspNet.WebSockets\Microsoft.AspNet.WebSockets.net45.csproj", "{00C6A882-1FE2-4769-901C-023D8DC175C4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{99D5E5F3-88F5-4CCF-8D8C-717C8925DF09}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E183C826-1360-4DFF-9994-F33CED5C8525}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{3A1E31E3-2794-4CA3-B8E2-253E96BDE514}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld.net45", "samples\HelloWorld\HelloWorld.net45.csproj", "{BF335732-BB09-49A1-8676-F074047E7DB2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SelfHostServer.net45", "samples\SelfHostServer\SelfHostServer.net45.csproj", "{96C67B2F-9913-4E8D-B2E8-969BE66B71B6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Server.WebListener.Test.net45", "test\Microsoft.AspNet.Server.WebListener.Test\Microsoft.AspNet.Server.WebListener.Test.net45.csproj", "{485DAC59-A1F1-4D47-98BF-B448C994E05B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld.k10", "samples\HelloWorld\HelloWorld.k10.csproj", "{A1F2CA12-3F08-4DE2-B3D9-52DBE267936B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Security.Windows.net45", "src\Microsoft.AspNet.Security.Windows\Microsoft.AspNet.Security.Windows.net45.csproj", "{8B4EF749-251D-4222-AD18-DE5A1E7D321A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Security.Windows.Test.net45", "test\Microsoft.AspNet.Security.Windows.Test\Microsoft.AspNet.Security.Windows.Test.net45.csproj", "{3EC418D5-C8FD-47AA-BFED-F524358EC3DD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8B828433-B333-4C19-96AE-00BFFF9D8841}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B828433-B333-4C19-96AE-00BFFF9D8841}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B828433-B333-4C19-96AE-00BFFF9D8841}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B828433-B333-4C19-96AE-00BFFF9D8841}.Release|Any CPU.Build.0 = Release|Any CPU
{6D9D3023-3ED7-4C95-80F0-347843ABD759}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D9D3023-3ED7-4C95-80F0-347843ABD759}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D9D3023-3ED7-4C95-80F0-347843ABD759}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D9D3023-3ED7-4C95-80F0-347843ABD759}.Release|Any CPU.Build.0 = Release|Any CPU
{253B9134-B6EB-4E59-8725-D983FD941A21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{253B9134-B6EB-4E59-8725-D983FD941A21}.Debug|Any CPU.Build.0 = Debug|Any CPU
{253B9134-B6EB-4E59-8725-D983FD941A21}.Release|Any CPU.ActiveCfg = Release|Any CPU
{253B9134-B6EB-4E59-8725-D983FD941A21}.Release|Any CPU.Build.0 = Release|Any CPU
{00C6A882-1FE2-4769-901C-023D8DC175C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{00C6A882-1FE2-4769-901C-023D8DC175C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00C6A882-1FE2-4769-901C-023D8DC175C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00C6A882-1FE2-4769-901C-023D8DC175C4}.Release|Any CPU.Build.0 = Release|Any CPU
{BF335732-BB09-49A1-8676-F074047E7DB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF335732-BB09-49A1-8676-F074047E7DB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF335732-BB09-49A1-8676-F074047E7DB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF335732-BB09-49A1-8676-F074047E7DB2}.Release|Any CPU.Build.0 = Release|Any CPU
{96C67B2F-9913-4E8D-B2E8-969BE66B71B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96C67B2F-9913-4E8D-B2E8-969BE66B71B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96C67B2F-9913-4E8D-B2E8-969BE66B71B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96C67B2F-9913-4E8D-B2E8-969BE66B71B6}.Release|Any CPU.Build.0 = Release|Any CPU
{485DAC59-A1F1-4D47-98BF-B448C994E05B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{485DAC59-A1F1-4D47-98BF-B448C994E05B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{485DAC59-A1F1-4D47-98BF-B448C994E05B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{485DAC59-A1F1-4D47-98BF-B448C994E05B}.Release|Any CPU.Build.0 = Release|Any CPU
{A1F2CA12-3F08-4DE2-B3D9-52DBE267936B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1F2CA12-3F08-4DE2-B3D9-52DBE267936B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1F2CA12-3F08-4DE2-B3D9-52DBE267936B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1F2CA12-3F08-4DE2-B3D9-52DBE267936B}.Release|Any CPU.Build.0 = Release|Any CPU
{8B4EF749-251D-4222-AD18-DE5A1E7D321A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B4EF749-251D-4222-AD18-DE5A1E7D321A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B4EF749-251D-4222-AD18-DE5A1E7D321A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B4EF749-251D-4222-AD18-DE5A1E7D321A}.Release|Any CPU.Build.0 = Release|Any CPU
{3EC418D5-C8FD-47AA-BFED-F524358EC3DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3EC418D5-C8FD-47AA-BFED-F524358EC3DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3EC418D5-C8FD-47AA-BFED-F524358EC3DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3EC418D5-C8FD-47AA-BFED-F524358EC3DD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{485DAC59-A1F1-4D47-98BF-B448C994E05B} = {E183C826-1360-4DFF-9994-F33CED5C8525}
{3EC418D5-C8FD-47AA-BFED-F524358EC3DD} = {E183C826-1360-4DFF-9994-F33CED5C8525}
{8B828433-B333-4C19-96AE-00BFFF9D8841} = {3A1E31E3-2794-4CA3-B8E2-253E96BDE514}
{BF335732-BB09-49A1-8676-F074047E7DB2} = {3A1E31E3-2794-4CA3-B8E2-253E96BDE514}
{96C67B2F-9913-4E8D-B2E8-969BE66B71B6} = {3A1E31E3-2794-4CA3-B8E2-253E96BDE514}
{A1F2CA12-3F08-4DE2-B3D9-52DBE267936B} = {3A1E31E3-2794-4CA3-B8E2-253E96BDE514}
{6D9D3023-3ED7-4C95-80F0-347843ABD759} = {99D5E5F3-88F5-4CCF-8D8C-717C8925DF09}
{253B9134-B6EB-4E59-8725-D983FD941A21} = {99D5E5F3-88F5-4CCF-8D8C-717C8925DF09}
{00C6A882-1FE2-4769-901C-023D8DC175C4} = {99D5E5F3-88F5-4CCF-8D8C-717C8925DF09}
{8B4EF749-251D-4222-AD18-DE5A1E7D321A} = {99D5E5F3-88F5-4CCF-8D8C-717C8925DF09}
EndGlobalSection
EndGlobal

13
NuGet.Config Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetvnext/" />
<add key="NuGet.org" value="https://nuget.org/api/v2/" />
</packageSources>
<packageSourceCredentials>
<AspNetVNext>
<add key="Username" value="aspnetreadonly" />
<add key="ClearTextPassword" value="4d8a2d9c-7b80-4162-9978-47e918c9658c" />
</AspNetVNext>
</packageSourceCredentials>
</configuration>

23
build.cmd Normal file
View File

@ -0,0 +1,23 @@
@echo off
cd %~dp0
SETLOCAL
SET CACHED_NUGET=%LocalAppData%\NuGet\NuGet.exe
IF EXIST %CACHED_NUGET% goto copynuget
echo Downloading latest version of NuGet.exe...
IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://www.nuget.org/nuget.exe' -OutFile '%CACHED_NUGET%'"
:copynuget
IF EXIST .nuget\nuget.exe goto restore
md .nuget
copy %CACHED_NUGET% .nuget\nuget.exe > nul
:restore
IF EXIST packages\KoreBuild goto run
.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion
:run
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*

3
global.json Normal file
View File

@ -0,0 +1,3 @@
{
"sources": ["src"]
}

7
makefile.shade Normal file
View File

@ -0,0 +1,7 @@
var VERSION='0.1'
var FULL_VERSION='0.1'
var AUTHORS='Microsoft'
use-standard-lifecycle
k-standard-goals

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Server.WebListener;
using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;
public class Program
{
public static void Main(string[] args)
{
using (CreateServer(new AppFunc(HelloWorldApp)))
{
Console.WriteLine("Running, press enter to exit...");
Console.ReadLine();
}
}
private static IDisposable CreateServer(AppFunc app)
{
IDictionary<string, object> properties = new Dictionary<string, object>();
IList<IDictionary<string, object>> addresses = new List<IDictionary<string, object>>();
properties["host.Addresses"] = addresses;
IDictionary<string, object> address = new Dictionary<string, object>();
addresses.Add(address);
address["scheme"] = "http";
address["host"] = "localhost";
address["port"] = "8080";
address["path"] = string.Empty;
return OwinServerFactory.Create(app, properties);
}
public static Task HelloWorldApp(IDictionary<string, object> environment)
{
string responseText = "Hello World";
byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);
// See http://owin.org/spec/owin-1.0.0.html for standard environment keys.
Stream responseStream = (Stream)environment["owin.ResponseBody"];
IDictionary<string, string[]> responseHeaders =
(IDictionary<string, string[]>)environment["owin.ResponseHeaders"];
responseHeaders["Content-Length"] = new string[] { responseBytes.Length.ToString(CultureInfo.InvariantCulture) };
responseHeaders["Content-Type"] = new string[] { "text/plain" };
return responseStream.WriteAsync(responseBytes, 0, responseBytes.Length);
}
}

View File

@ -0,0 +1,10 @@
{
"version" : "0.1-alpha-*",
"dependencies": {
"Microsoft.AspNet.Server.WebListener" : ""
},
"configurations": {
"net45": { },
"k10" : { }
}
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>

View File

@ -0,0 +1,138 @@
// -----------------------------------------------------------------------
// <copyright file="Program.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.AspNet.Server.WebListener;
using Microsoft.Owin.Hosting;
using Owin;
namespace SelfHostServer
{
// http://owin.org/extensions/owin-WebSocket-Extension-v0.4.0.htm
using WebSocketAccept = Action<IDictionary<string, object>, // options
Func<IDictionary<string, object>, Task>>; // callback
using WebSocketCloseAsync =
Func<int /* closeStatus */,
string /* closeDescription */,
CancellationToken /* cancel */,
Task>;
using WebSocketReceiveAsync =
Func<ArraySegment<byte> /* data */,
CancellationToken /* cancel */,
Task<Tuple<int /* messageType */,
bool /* endOfMessage */,
int /* count */>>>;
using WebSocketReceiveResult = Tuple<int, // type
bool, // end of message?
int>; // count
using WebSocketSendAsync =
Func<ArraySegment<byte> /* data */,
int /* messageType */,
bool /* endOfMessage */,
CancellationToken /* cancel */,
Task>;
public class Program
{
private static byte[] Data = new byte[1024];
public static void Main(string[] args)
{
using (WebApp.Start<Program>(new StartOptions(
// "http://localhost:5000/"
"https://localhost:9090/"
)
{
ServerFactory = "Microsoft.AspNet.Server.WebListener"
}))
{
Console.WriteLine("Running, press any key to exit");
// System.Diagnostics.Process.Start("http://localhost:5000/");
Console.ReadKey();
}
}
public void Configuration(IAppBuilder app)
{
OwinWebListener listener = (OwinWebListener)app.Properties["Microsoft.AspNet.Server.WebListener.OwinWebListener"];
listener.AuthenticationManager.AuthenticationTypes =
AuthenticationType.Basic |
AuthenticationType.Digest |
AuthenticationType.Negotiate |
AuthenticationType.Ntlm |
AuthenticationType.Kerberos;
app.Use((context, next) =>
{
Console.WriteLine("Request: " + context.Request.Uri);
return next();
});
app.Use((context, next) =>
{
if (context.Request.User == null)
{
context.Response.StatusCode = 401;
return Task.FromResult(0);
}
else
{
Console.WriteLine(context.Request.User.Identity.AuthenticationType);
}
return next();
});
app.UseWebSockets();
app.Use(UpgradeToWebSockets);
app.Run(Invoke);
}
public Task Invoke(IOwinContext context)
{
context.Response.ContentLength = Data.Length;
return context.Response.WriteAsync(Data);
}
// Run once per request
private Task UpgradeToWebSockets(IOwinContext context, Func<Task> next)
{
WebSocketAccept accept = context.Get<WebSocketAccept>("websocket.Accept");
if (accept == null)
{
// Not a websocket request
return next();
}
accept(null, WebSocketEcho);
return Task.FromResult<object>(null);
}
private async Task WebSocketEcho(IDictionary<string, object> websocketContext)
{
var sendAsync = (WebSocketSendAsync)websocketContext["websocket.SendAsync"];
var receiveAsync = (WebSocketReceiveAsync)websocketContext["websocket.ReceiveAsync"];
var closeAsync = (WebSocketCloseAsync)websocketContext["websocket.CloseAsync"];
var callCancelled = (CancellationToken)websocketContext["websocket.CallCancelled"];
byte[] buffer = new byte[1024];
WebSocketReceiveResult received = await receiveAsync(new ArraySegment<byte>(buffer), callCancelled);
object status;
while (!websocketContext.TryGetValue("websocket.ClientCloseStatus", out status) || (int)status == 0)
{
// Echo anything we receive
await sendAsync(new ArraySegment<byte>(buffer, 0, received.Item3), received.Item1, received.Item2, callCancelled);
received = await receiveAsync(new ArraySegment<byte>(buffer), callCancelled);
}
await closeAsync((int)websocketContext["websocket.ClientCloseStatus"], (string)websocketContext["websocket.ClientCloseDescription"], callCancelled);
}
}
}

View File

@ -0,0 +1,42 @@
// -----------------------------------------------------------------------
// <copyright file="AssemblyInfo.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SelfHostServer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SelfHostServer")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ec50ddb4-9ec6-4cbd-96ac-15de948247cc")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("0.5")]
[assembly: AssemblyVersion("0.5")]
[assembly: AssemblyFileVersion("0.5.40117.0")]

View File

@ -0,0 +1 @@
asdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfqweruoiasdfnsngdfioenrglknsgilhasdgha;gu;agnaknusgnjkadfgnknjksdfk asdhfhasdf nklasdgnasg njagnjasdfasdfasdfasdfasdfasd

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.FileSystems" version="2.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Hosting" version="2.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.StaticFiles" version="2.1.0" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
</packages>

View File

@ -0,0 +1,19 @@
{
"version" : "0.1-alpha-*",
"dependencies": {
"Microsoft.AspNet.Server.WebListener" : "",
"Microsoft.AspNet.WebSockets" : ""
},
"configurations": {
"net45": {
"dependencies": {
"Owin": "1.0",
"Microsoft.Owin": "2.1.0",
"Microsoft.Owin.Diagnostics": "2.1.0",
"Microsoft.Owin.Hosting": "2.1.0",
"Microsoft.Owin.Host.HttpListener": "2.1.0",
"Microsoft.AspNet.AppBuilderSupport": "0.1-alpha-*"
}
}
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>

View File

@ -0,0 +1,78 @@
using System;
using System.Net;
using System.Net.Http;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TestClient
{
public class Program
{
private const string Address =
// "http://localhost:5000/public/1kb.txt";
"https://localhost:9090/public/1kb.txt";
public static void Main(string[] args)
{
WebRequestHandler handler = new WebRequestHandler();
handler.ServerCertificateValidationCallback = (_, __, ___, ____) => true;
// handler.UseDefaultCredentials = true;
handler.Credentials = new NetworkCredential(@"redmond\chrross", "passwird");
HttpClient client = new HttpClient(handler);
/*
int completionCount = 0;
int itterations = 30000;
for (int i = 0; i < itterations; i++)
{
client.GetAsync(Address)
.ContinueWith(t => Interlocked.Increment(ref completionCount));
}
while (completionCount < itterations)
{
Thread.Sleep(10);
}*/
while (true)
{
Console.WriteLine("Press any key to send request");
Console.ReadKey();
var result = client.GetAsync(Address).Result;
Console.WriteLine(result);
}
// RunWebSocketClient().Wait();
Console.WriteLine("Done");
Console.ReadKey();
}
public static async Task RunWebSocketClient()
{
ClientWebSocket websocket = new ClientWebSocket();
string url = "ws://localhost:5000/";
Console.WriteLine("Connecting to: " + url);
await websocket.ConnectAsync(new Uri(url), CancellationToken.None);
string message = "Hello World";
Console.WriteLine("Sending message: " + message);
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
await websocket.SendAsync(new ArraySegment<byte>(messageBytes), WebSocketMessageType.Text, true, CancellationToken.None);
byte[] incomingData = new byte[1024];
WebSocketReceiveResult result = await websocket.ReceiveAsync(new ArraySegment<byte>(incomingData), CancellationToken.None);
if (result.CloseStatus.HasValue)
{
Console.WriteLine("Closed; Status: " + result.CloseStatus + ", " + result.CloseStatusDescription);
}
else
{
Console.WriteLine("Received message: " + Encoding.UTF8.GetString(incomingData, 0, result.Count));
}
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TestClient")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TestClient")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("8db62eb3-48c0-4049-b33e-271c738140a0")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("0.5")]
[assembly: AssemblyVersion("0.5")]
[assembly: AssemblyFileVersion("0.5.40117.0")]

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{8B828433-B333-4C19-96AE-00BFFF9D8841}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestClient</RootNamespace>
<AssemblyName>TestClient</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,37 @@
// -----------------------------------------------------------------------
// <copyright file="AuthTypes.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
namespace Microsoft.AspNet.Security.Windows
{
/// <summary>
/// Types of Windows Authentication supported.
/// </summary>
[Flags]
public enum AuthTypes
{
/// <summary>
/// Default
/// </summary>
None = 0,
/// <summary>
/// Digest authentication using Windows credentials
/// </summary>
Digest = 1,
/// <summary>
/// Negotiates Kerberos or NTLM
/// </summary>
Negotiate = 2,
/// <summary>
/// NTLM Windows authentication
/// </summary>
Ntlm = 4,
}
}

View File

@ -0,0 +1,38 @@
// -----------------------------------------------------------------------
// <copyright file="ComNetOS.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Runtime.Versioning;
using System.Security.Permissions;
namespace Microsoft.AspNet.Security.Windows
{
internal static class ComNetOS
{
// Minimum support for Windows 2008 is assumed.
internal static readonly bool IsWin7orLater; // Is Windows 7 or later
internal static readonly bool IsWin8orLater; // Is Windows 8 or later
// We use it safe so assert
[EnvironmentPermission(SecurityAction.Assert, Unrestricted = true)]
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain)]
static ComNetOS()
{
OperatingSystem operatingSystem = Environment.OSVersion;
GlobalLog.Print("ComNetOS::.ctor(): " + operatingSystem.ToString());
Debug.Assert(operatingSystem.Platform != PlatformID.Win32Windows, "Windows 9x is not supported");
var Win7Version = new Version(6, 1);
var Win8Version = new Version(6, 2);
IsWin7orLater = (operatingSystem.Version >= Win7Version);
IsWin8orLater = (operatingSystem.Version >= Win8Version);
}
}
}

View File

@ -0,0 +1,44 @@
// -----------------------------------------------------------------------
// <copyright file="Constants.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.AspNet.Security.Windows
{
internal static class Constants
{
internal const string VersionKey = "owin.Version";
internal const string OwinVersion = "1.0";
internal const string CallCancelledKey = "owin.CallCancelled";
internal const string RequestBodyKey = "owin.RequestBody";
internal const string RequestHeadersKey = "owin.RequestHeaders";
internal const string RequestSchemeKey = "owin.RequestScheme";
internal const string RequestMethodKey = "owin.RequestMethod";
internal const string RequestPathBaseKey = "owin.RequestPathBase";
internal const string RequestPathKey = "owin.RequestPath";
internal const string RequestQueryStringKey = "owin.RequestQueryString";
internal const string HttpRequestProtocolKey = "owin.RequestProtocol";
internal const string HttpResponseProtocolKey = "owin.ResponseProtocol";
internal const string ResponseStatusCodeKey = "owin.ResponseStatusCode";
internal const string ResponseReasonPhraseKey = "owin.ResponseReasonPhrase";
internal const string ResponseHeadersKey = "owin.ResponseHeaders";
internal const string ResponseBodyKey = "owin.ResponseBody";
internal const string ClientCertifiateKey = "ssl.ClientCertificate";
internal const string SslSpnKey = "ssl.Spn";
internal const string SslChannelBindingKey = "ssl.ChannelBinding";
internal const string RemoteIpAddressKey = "server.RemoteIpAddress";
internal const string RemotePortKey = "server.RemotePort";
internal const string LocalIpAddressKey = "server.LocalIpAddress";
internal const string LocalPortKey = "server.LocalPort";
internal const string IsLocalKey = "server.IsLocal";
internal const string ServerOnSendingHeadersKey = "server.OnSendingHeaders";
internal const string ServerUserKey = "server.User";
internal const string ServerConnectionIdKey = "server.ConnectionId";
internal const string ServerConnectionDisconnectKey = "server.ConnectionDisconnect";
}
}

View File

@ -0,0 +1,67 @@
// -----------------------------------------------------------------------
// <copyright file="DictionaryExtensions.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Linq;
using System.Text;
namespace System.Collections.Generic
{
internal static class DictionaryExtensions
{
internal static void Append(this IDictionary<string, string[]> dictionary, string key, string value)
{
string[] orriginalValues;
if (dictionary.TryGetValue(key, out orriginalValues))
{
string[] newValues = new string[orriginalValues.Length + 1];
orriginalValues.CopyTo(newValues, 0);
newValues[newValues.Length - 1] = value;
dictionary[key] = newValues;
}
else
{
dictionary[key] = new string[] { value };
}
}
internal static void Append(this IDictionary<string, string[]> dictionary, string key, IList<string> values)
{
string[] orriginalValues;
if (dictionary.TryGetValue(key, out orriginalValues))
{
string[] newValues = new string[orriginalValues.Length + values.Count];
orriginalValues.CopyTo(newValues, 0);
values.CopyTo(newValues, orriginalValues.Length);
dictionary[key] = newValues;
}
else
{
dictionary[key] = values.ToArray();
}
}
internal static string Get(this IDictionary<string, string[]> dictionary, string key)
{
string[] values;
if (dictionary.TryGetValue(key, out values))
{
return string.Join(", ", values);
}
return null;
}
internal static T Get<T>(this IDictionary<string, object> dictionary, string key, T fallback = default(T))
{
object values;
if (dictionary.TryGetValue(key, out values))
{
return (T)values;
}
return fallback;
}
}
}

View File

@ -0,0 +1,153 @@
// -----------------------------------------------------------------------
// <copyright file="DigestCache.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Collections;
using System.Threading;
namespace Microsoft.AspNet.Security.Windows
{
// Saves generated digest challenges so that they are still valid when the authenticated request arrives.
internal class DigestCache : IDisposable
{
private const int DigestLifetimeSeconds = 300;
private const int MaximumDigests = 1024; // Must be a power of two.
private const int MinimumDigestLifetimeSeconds = 10;
private DigestContext[] _savedDigests;
private ArrayList _extraSavedDigests;
private ArrayList _extraSavedDigestsBaking;
private int _extraSavedDigestsTimestamp;
private int _newestContext;
private int _oldestContext;
internal DigestCache()
{
}
internal void SaveDigestContext(NTAuthentication digestContext)
{
if (_savedDigests == null)
{
Interlocked.CompareExchange<DigestContext[]>(ref _savedDigests, new DigestContext[MaximumDigests], null);
}
// We want to actually close the contexts outside the lock.
NTAuthentication oldContext = null;
ArrayList digestsToClose = null;
lock (_savedDigests)
{
int now = ((now = Environment.TickCount) == 0 ? 1 : now);
_newestContext = (_newestContext + 1) & (MaximumDigests - 1);
int oldTimestamp = _savedDigests[_newestContext].timestamp;
oldContext = _savedDigests[_newestContext].context;
_savedDigests[_newestContext].timestamp = now;
_savedDigests[_newestContext].context = digestContext;
// May need to move this up.
if (_oldestContext == _newestContext)
{
_oldestContext = (_newestContext + 1) & (MaximumDigests - 1);
}
// Delete additional contexts older than five minutes.
while (unchecked(now - _savedDigests[_oldestContext].timestamp) >= DigestLifetimeSeconds && _savedDigests[_oldestContext].context != null)
{
if (digestsToClose == null)
{
digestsToClose = new ArrayList();
}
digestsToClose.Add(_savedDigests[_oldestContext].context);
_savedDigests[_oldestContext].context = null;
_oldestContext = (_oldestContext + 1) & (MaximumDigests - 1);
}
// If the old context is younger than 10 seconds, put it in the backup pile.
if (oldContext != null && unchecked(now - oldTimestamp) <= MinimumDigestLifetimeSeconds * 1000)
{
// Use a two-tier ArrayList system to guarantee each entry lives at least 10 seconds.
if (_extraSavedDigests == null ||
unchecked(now - _extraSavedDigestsTimestamp) > MinimumDigestLifetimeSeconds * 1000)
{
digestsToClose = _extraSavedDigestsBaking;
_extraSavedDigestsBaking = _extraSavedDigests;
_extraSavedDigestsTimestamp = now;
_extraSavedDigests = new ArrayList();
}
_extraSavedDigests.Add(oldContext);
oldContext = null;
}
}
if (oldContext != null)
{
oldContext.CloseContext();
}
if (digestsToClose != null)
{
for (int i = 0; i < digestsToClose.Count; i++)
{
((NTAuthentication)digestsToClose[i]).CloseContext();
}
}
}
private void ClearDigestCache()
{
if (_savedDigests == null)
{
return;
}
ArrayList[] toClose = new ArrayList[3];
lock (_savedDigests)
{
toClose[0] = _extraSavedDigestsBaking;
_extraSavedDigestsBaking = null;
toClose[1] = _extraSavedDigests;
_extraSavedDigests = null;
_newestContext = 0;
_oldestContext = 0;
toClose[2] = new ArrayList();
for (int i = 0; i < MaximumDigests; i++)
{
if (_savedDigests[i].context != null)
{
toClose[2].Add(_savedDigests[i].context);
_savedDigests[i].context = null;
}
_savedDigests[i].timestamp = 0;
}
}
for (int j = 0; j < toClose.Length; j++)
{
if (toClose[j] != null)
{
for (int k = 0; k < toClose[j].Count; k++)
{
((NTAuthentication)toClose[j][k]).CloseContext();
}
}
}
}
public void Dispose()
{
ClearDigestCache();
}
private struct DigestContext
{
internal NTAuthentication context;
internal int timestamp;
}
}
}

View File

@ -0,0 +1,93 @@
// -----------------------------------------------------------------------
// <copyright file="DisconnectAsyncResult.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Security.Principal;
using System.Threading;
namespace Microsoft.AspNet.Security.Windows
{
// Keeps NTLM/Negotiate auth contexts alive until the connection is broken.
internal class DisconnectAsyncResult
{
private const string NTLM = "NTLM";
private object _connectionId;
private WindowsAuthMiddleware _winAuth;
private CancellationTokenRegistration _disconnectRegistration;
private WindowsPrincipal _authenticatedUser;
private NTAuthentication _session;
internal DisconnectAsyncResult(WindowsAuthMiddleware winAuth, object connectionId, CancellationToken connectionDisconnect)
{
GlobalLog.Print("DisconnectAsyncResult#" + ValidationHelper.HashString(this) + "::.ctor() httpListener#" + ValidationHelper.HashString(winAuth) + " connectionId:" + connectionId);
_winAuth = winAuth;
_connectionId = connectionId;
_winAuth.DisconnectResults[_connectionId] = this;
// Register with a connection specific CancellationToken. Without this notification, the contexts will leak indefinitely.
// Alternatively we could attempt some kind of LRU storage, but this will either have to be larger than your expected connection limit,
// or will fail at unexpected moments under stress.
try
{
_disconnectRegistration = connectionDisconnect.Register(HandleDisconnect);
}
catch (ObjectDisposedException)
{
_winAuth.DisconnectResults.Remove(_connectionId);
}
}
internal WindowsPrincipal AuthenticatedUser
{
get
{
return _authenticatedUser;
}
set
{
// The previous value can't be disposed because it may be in use by the app.
_authenticatedUser = value;
}
}
internal NTAuthentication Session
{
get
{
return _session;
}
set
{
_session = value;
}
}
private void HandleDisconnect()
{
GlobalLog.Print("DisconnectAsyncResult#" + ValidationHelper.HashString(this) + "::HandleDisconnect() DisconnectResults#" + ValidationHelper.HashString(_winAuth.DisconnectResults) + " removing for m_ConnectionId:" + _connectionId);
_winAuth.DisconnectResults.Remove(_connectionId);
if (_session != null)
{
_session.CloseContext();
}
// Clean up the identity. This is for scenarios where identity was not cleaned up before due to
// identity caching for unsafe ntlm authentication
IDisposable identity = _authenticatedUser == null ? null : _authenticatedUser.Identity as IDisposable;
if ((identity != null) &&
(NTLM.Equals(_authenticatedUser.Identity.AuthenticationType, StringComparison.OrdinalIgnoreCase)) &&
(_winAuth.UnsafeConnectionNtlmAuthentication))
{
identity.Dispose();
}
_disconnectRegistration.Dispose();
}
}
}

View File

@ -0,0 +1,139 @@
//------------------------------------------------------------------------------
// <copyright file="WebHeaderCollection.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Text;
namespace Microsoft.AspNet.Security.Windows
{
// we use this static class as a helper class to encode/decode HTTP headers.
// what we need is a 1-1 correspondence between a char in the range U+0000-U+00FF
// and a byte in the range 0x00-0xFF (which is the range that can hit the network).
// The Latin-1 encoding (ISO-88591-1) (GetEncoding(28591)) works for byte[] to string, but is a little slow.
// It doesn't work for string -> byte[] because of best-fit-mapping problems.
internal static class HeaderEncoding
{
internal static unsafe string GetString(byte[] bytes, int byteIndex, int byteCount)
{
fixed (byte* pBytes = bytes)
return GetString(pBytes + byteIndex, byteCount);
}
internal static unsafe string GetString(byte* pBytes, int byteCount)
{
if (byteCount < 1)
{
return string.Empty;
}
string s = new String('\0', byteCount);
fixed (char* pStr = s)
{
char* pString = pStr;
while (byteCount >= 8)
{
pString[0] = (char)pBytes[0];
pString[1] = (char)pBytes[1];
pString[2] = (char)pBytes[2];
pString[3] = (char)pBytes[3];
pString[4] = (char)pBytes[4];
pString[5] = (char)pBytes[5];
pString[6] = (char)pBytes[6];
pString[7] = (char)pBytes[7];
pString += 8;
pBytes += 8;
byteCount -= 8;
}
for (int i = 0; i < byteCount; i++)
{
pString[i] = (char)pBytes[i];
}
}
return s;
}
internal static int GetByteCount(string myString)
{
return myString.Length;
}
internal static unsafe void GetBytes(string myString, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
if (myString.Length == 0)
{
return;
}
fixed (byte* bufferPointer = bytes)
{
byte* newBufferPointer = bufferPointer + byteIndex;
int finalIndex = charIndex + charCount;
while (charIndex < finalIndex)
{
*newBufferPointer++ = (byte)myString[charIndex++];
}
}
}
internal static unsafe byte[] GetBytes(string myString)
{
byte[] bytes = new byte[myString.Length];
if (myString.Length != 0)
{
GetBytes(myString, 0, myString.Length, bytes, 0);
}
return bytes;
}
// The normal client header parser just casts bytes to chars (see GetString).
// Check if those bytes were actually utf-8 instead of ASCII.
// If not, just return the input value.
internal static string DecodeUtf8FromString(string input)
{
if (string.IsNullOrWhiteSpace(input))
{
return input;
}
bool possibleUtf8 = false;
for (int i = 0; i < input.Length; i++)
{
if (input[i] > (char)255)
{
return input; // This couldn't have come from the wire, someone assigned it directly.
}
else if (input[i] > (char)127)
{
possibleUtf8 = true;
break;
}
}
if (possibleUtf8)
{
byte[] rawBytes = new byte[input.Length];
for (int i = 0; i < input.Length; i++)
{
if (input[i] > (char)255)
{
return input; // This couldn't have come from the wire, someone assigned it directly.
}
rawBytes[i] = (byte)input[i];
}
try
{
// We don't want '?' replacement characters, just fail.
Encoding decoder = Encoding.GetEncoding("utf-8", EncoderFallback.ExceptionFallback,
DecoderFallback.ExceptionFallback);
return decoder.GetString(rawBytes);
}
catch (ArgumentException)
{
} // Not actually Utf-8
}
return input;
}
}
}

View File

@ -0,0 +1,75 @@
// -----------------------------------------------------------------------
// <copyright file="HttpKnownHeaderNames.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.AspNet.Security.Windows
{
internal static class HttpKnownHeaderNames
{
public const string CacheControl = "Cache-Control";
public const string Connection = "Connection";
public const string Date = "Date";
public const string KeepAlive = "Keep-Alive";
public const string Pragma = "Pragma";
public const string ProxyConnection = "Proxy-Connection";
public const string Trailer = "Trailer";
public const string TransferEncoding = "Transfer-Encoding";
public const string Upgrade = "Upgrade";
public const string Via = "Via";
public const string Warning = "Warning";
public const string ContentLength = "Content-Length";
public const string ContentType = "Content-Type";
public const string ContentDisposition = "Content-Disposition";
public const string ContentEncoding = "Content-Encoding";
public const string ContentLanguage = "Content-Language";
public const string ContentLocation = "Content-Location";
public const string ContentRange = "Content-Range";
public const string Expires = "Expires";
public const string LastModified = "Last-Modified";
public const string Age = "Age";
public const string Location = "Location";
public const string ProxyAuthenticate = "Proxy-Authenticate";
public const string RetryAfter = "Retry-After";
public const string Server = "Server";
public const string SetCookie = "Set-Cookie";
public const string SetCookie2 = "Set-Cookie2";
public const string Vary = "Vary";
public const string WWWAuthenticate = "WWW-Authenticate";
public const string Accept = "Accept";
public const string AcceptCharset = "Accept-Charset";
public const string AcceptEncoding = "Accept-Encoding";
public const string AcceptLanguage = "Accept-Language";
public const string Authorization = "Authorization";
public const string Cookie = "Cookie";
public const string Cookie2 = "Cookie2";
public const string Expect = "Expect";
public const string From = "From";
public const string Host = "Host";
public const string IfMatch = "If-Match";
public const string IfModifiedSince = "If-Modified-Since";
public const string IfNoneMatch = "If-None-Match";
public const string IfRange = "If-Range";
public const string IfUnmodifiedSince = "If-Unmodified-Since";
public const string MaxForwards = "Max-Forwards";
public const string ProxyAuthorization = "Proxy-Authorization";
public const string Referer = "Referer";
public const string Range = "Range";
public const string UserAgent = "User-Agent";
public const string ContentMD5 = "Content-MD5";
public const string ETag = "ETag";
public const string TE = "TE";
public const string Allow = "Allow";
public const string AcceptRanges = "Accept-Ranges";
public const string P3P = "P3P";
public const string XPoweredBy = "X-Powered-By";
public const string XAspNetVersion = "X-AspNet-Version";
public const string SecWebSocketKey = "Sec-WebSocket-Key";
public const string SecWebSocketExtensions = "Sec-WebSocket-Extensions";
public const string SecWebSocketAccept = "Sec-WebSocket-Accept";
public const string Origin = "Origin";
public const string SecWebSocketProtocol = "Sec-WebSocket-Protocol";
public const string SecWebSocketVersion = "Sec-WebSocket-Version";
}
}

View File

@ -0,0 +1,314 @@
//------------------------------------------------------------------------------
// <copyright file="HttpStatusCode.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace Microsoft.AspNet.Security.Windows
{
// Redirect Status code numbers that need to be defined.
/// <devdoc>
/// <para>Contains the values of status
/// codes defined for the HTTP protocol.</para>
/// </devdoc>
// UEUE : Any int can be cast to a HttpStatusCode to allow checking for non http1.1 codes.
internal enum HttpStatusCode
{
// Informational 1xx
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Continue = 100,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
SwitchingProtocols = 101,
// Successful 2xx
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
OK = 200,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Created = 201,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Accepted = 202,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
NonAuthoritativeInformation = 203,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
NoContent = 204,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
ResetContent = 205,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
PartialContent = 206,
// Redirection 3xx
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
MultipleChoices = 300,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Ambiguous = 300,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
MovedPermanently = 301,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Moved = 301,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Found = 302,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Redirect = 302,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
SeeOther = 303,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
RedirectMethod = 303,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
NotModified = 304,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
UseProxy = 305,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Unused = 306,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
TemporaryRedirect = 307,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
RedirectKeepVerb = 307,
// Client Error 4xx
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
BadRequest = 400,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Unauthorized = 401,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
PaymentRequired = 402,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Forbidden = 403,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
NotFound = 404,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
MethodNotAllowed = 405,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
NotAcceptable = 406,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
ProxyAuthenticationRequired = 407,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
RequestTimeout = 408,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Conflict = 409,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Gone = 410,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
LengthRequired = 411,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
PreconditionFailed = 412,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
RequestEntityTooLarge = 413,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
RequestUriTooLong = 414,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
UnsupportedMediaType = 415,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
RequestedRangeNotSatisfiable = 416,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
ExpectationFailed = 417,
UpgradeRequired = 426,
// Server Error 5xx
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
InternalServerError = 500,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
NotImplemented = 501,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
BadGateway = 502,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
ServiceUnavailable = 503,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
GatewayTimeout = 504,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
HttpVersionNotSupported = 505,
} // enum HttpStatusCode
/*
Fielding, et al. Standards Track [Page 3]
RFC 2616 HTTP/1.1 June 1999
10.1 Informational 1xx ...........................................57
10.1.1 100 Continue .............................................58
10.1.2 101 Switching Protocols ..................................58
10.2 Successful 2xx ..............................................58
10.2.1 200 OK ...................................................58
10.2.2 201 Created ..............................................59
10.2.3 202 Accepted .............................................59
10.2.4 203 Non-Authoritative Information ........................59
10.2.5 204 No Content ...........................................60
10.2.6 205 Reset Content ........................................60
10.2.7 206 Partial Content ......................................60
10.3 Redirection 3xx .............................................61
10.3.1 300 Multiple Choices .....................................61
10.3.2 301 Moved Permanently ....................................62
10.3.3 302 Found ................................................62
10.3.4 303 See Other ............................................63
10.3.5 304 Not Modified .........................................63
10.3.6 305 Use Proxy ............................................64
10.3.7 306 (Unused) .............................................64
10.3.8 307 Temporary Redirect ...................................65
10.4 Client Error 4xx ............................................65
10.4.1 400 Bad Request .........................................65
10.4.2 401 Unauthorized ........................................66
10.4.3 402 Payment Required ....................................66
10.4.4 403 Forbidden ...........................................66
10.4.5 404 Not Found ...........................................66
10.4.6 405 Method Not Allowed ..................................66
10.4.7 406 Not Acceptable ......................................67
10.4.8 407 Proxy Authentication Required .......................67
10.4.9 408 Request Timeout .....................................67
10.4.10 409 Conflict ............................................67
10.4.11 410 Gone ................................................68
10.4.12 411 Length Required .....................................68
10.4.13 412 Precondition Failed .................................68
10.4.14 413 Request Entity Too Large ............................69
10.4.15 414 Request-URI Too Long ................................69
10.4.16 415 Unsupported Media Type ..............................69
10.4.17 416 Requested Range Not Satisfiable .....................69
10.4.18 417 Expectation Failed ..................................70
10.5 Server Error 5xx ............................................70
10.5.1 500 Internal Server Error ................................70
10.5.2 501 Not Implemented ......................................70
10.5.3 502 Bad Gateway ..........................................70
10.5.4 503 Service Unavailable ..................................70
10.5.5 504 Gateway Timeout ......................................71
10.5.6 505 HTTP Version Not Supported ...........................71
*/
} // namespace System.Net

View File

@ -0,0 +1,133 @@
// -----------------------------------------------------------------------
// <copyright file="CaseInsensitiveAscii.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System.Collections;
namespace Microsoft.AspNet.Security.Windows
{
internal class CaseInsensitiveAscii : IEqualityComparer, IComparer
{
// ASCII char ToLower table
internal static readonly byte[] AsciiToLower = new byte[]
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 97, 98, 99, 100, 101, // 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, // 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
122, 91, 92, 93, 94, 95, 96, 97, 98, 99, // 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
250, 251, 252, 253, 254, 255
};
// ASCII string case insensitive hash function
public int GetHashCode(object myObject)
{
string myString = myObject as string;
if (myObject == null)
{
return 0;
}
int myHashCode = myString.Length;
if (myHashCode == 0)
{
return 0;
}
myHashCode ^= AsciiToLower[(byte)myString[0]] << 24 ^ AsciiToLower[(byte)myString[myHashCode - 1]] << 16;
return myHashCode;
}
// ASCII string case insensitive comparer
public int Compare(object firstObject, object secondObject)
{
string firstString = firstObject as string;
string secondString = secondObject as string;
if (firstString == null)
{
return secondString == null ? 0 : -1;
}
if (secondString == null)
{
return 1;
}
int result = firstString.Length - secondString.Length;
int comparisons = result > 0 ? secondString.Length : firstString.Length;
int difference, index = 0;
while (index < comparisons)
{
difference = (int)(AsciiToLower[firstString[index]] - AsciiToLower[secondString[index]]);
if (difference != 0)
{
result = difference;
break;
}
index++;
}
return result;
}
// ASCII string case insensitive hash function
private int FastGetHashCode(string myString)
{
int myHashCode = myString.Length;
if (myHashCode != 0)
{
myHashCode ^= AsciiToLower[(byte)myString[0]] << 24 ^ AsciiToLower[(byte)myString[myHashCode - 1]] << 16;
}
return myHashCode;
}
// ASCII string case insensitive comparer
public new bool Equals(object firstObject, object secondObject)
{
string firstString = firstObject as string;
string secondString = secondObject as string;
if (firstString == null)
{
return secondString == null;
}
if (secondString != null)
{
int index = firstString.Length;
if (index == secondString.Length)
{
if (FastGetHashCode(firstString) == FastGetHashCode(secondString))
{
int comparisons = firstString.Length;
while (index > 0)
{
index--;
if (AsciiToLower[firstString[index]] != AsciiToLower[secondString[index]])
{
return false;
}
}
return true;
}
}
}
return false;
}
}
}

View File

@ -0,0 +1,689 @@
// -----------------------------------------------------------------------
// <copyright file="GlobalLog.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.AspNet.Security.Windows
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.Net;
using System.Runtime.ConstrainedExecution;
using System.Security.Permissions;
using System.Threading;
/// <internalonly/>
/// <devdoc>
/// </devdoc>
internal static class GlobalLog
{
// Logging Initalization - I need to disable Logging code, and limit
// the effect it has when it is dissabled, so I use a bool here.
//
// This can only be set when the logging code is built and enabled.
// By specifing the "CSC_DEFINES=/D:TRAVE" in the build environment,
// this code will be built and then checks against an enviroment variable
// and a BooleanSwitch to see if any of the two have enabled logging.
private static BaseLoggingObject Logobject = GlobalLog.LoggingInitialize();
#if TRAVE
internal static LocalDataStoreSlot s_ThreadIdSlot;
internal static bool s_UseThreadId;
internal static bool s_UseTimeSpan;
internal static bool s_DumpWebData;
internal static bool s_UsePerfCounter;
internal static bool s_DebugCallNesting;
internal static bool s_DumpToConsole;
internal static int s_MaxDumpSize;
internal static string s_RootDirectory;
//
// Logging Config Variables - below are list of consts that can be used to config
// the logging,
//
// Max number of lines written into a buffer, before a save is invoked
// s_DumpToConsole disables.
public const int MaxLinesBeforeSave = 0;
#endif
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
private static BaseLoggingObject LoggingInitialize()
{
#if DEBUG
if (GetSwitchValue("SystemNetLogging", "System.Net logging module", false) &&
GetSwitchValue("SystemNetLog_ConnectionMonitor", "System.Net connection monitor thread", false))
{
InitConnectionMonitor();
}
#endif // DEBUG
#if TRAVE
// by default we'll log to c:\temp\ so that non interactive services (like w3wp.exe) that don't have environment
// variables can easily be debugged, note that the ACLs of the directory might need to be adjusted
if (!GetSwitchValue("SystemNetLog_OverrideDefaults", "System.Net log override default settings", false)) {
s_ThreadIdSlot = Thread.AllocateDataSlot();
s_UseThreadId = true;
s_UseTimeSpan = true;
s_DumpWebData = true;
s_MaxDumpSize = 256;
s_UsePerfCounter = true;
s_DebugCallNesting = true;
s_DumpToConsole = false;
s_RootDirectory = "C:\\Temp\\";
return new LoggingObject();
}
if (GetSwitchValue("SystemNetLogging", "System.Net logging module", false)) {
s_ThreadIdSlot = Thread.AllocateDataSlot();
s_UseThreadId = GetSwitchValue("SystemNetLog_UseThreadId", "System.Net log display system thread id", false);
s_UseTimeSpan = GetSwitchValue("SystemNetLog_UseTimeSpan", "System.Net log display ticks as TimeSpan", false);
s_DumpWebData = GetSwitchValue("SystemNetLog_DumpWebData", "System.Net log display HTTP send/receive data", false);
s_MaxDumpSize = GetSwitchValue("SystemNetLog_MaxDumpSize", "System.Net log max size of display data", 256);
s_UsePerfCounter = GetSwitchValue("SystemNetLog_UsePerfCounter", "System.Net log use QueryPerformanceCounter() to get ticks ", false);
s_DebugCallNesting = GetSwitchValue("SystemNetLog_DebugCallNesting", "System.Net used to debug call nesting", false);
s_DumpToConsole = GetSwitchValue("SystemNetLog_DumpToConsole", "System.Net log to console", false);
s_RootDirectory = GetSwitchValue("SystemNetLog_RootDirectory", "System.Net root directory of log file", string.Empty);
return new LoggingObject();
}
#endif // TRAVE
return new BaseLoggingObject();
}
#if TRAVE
private static string GetSwitchValue(string switchName, string switchDescription, string defaultValue) {
new EnvironmentPermission(PermissionState.Unrestricted).Assert();
try {
defaultValue = Environment.GetEnvironmentVariable(switchName);
}
finally {
EnvironmentPermission.RevertAssert();
}
return defaultValue;
}
private static int GetSwitchValue(string switchName, string switchDescription, int defaultValue) {
IntegerSwitch theSwitch = new IntegerSwitch(switchName, switchDescription);
if (theSwitch.Enabled) {
return theSwitch.Value;
}
new EnvironmentPermission(PermissionState.Unrestricted).Assert();
try {
string environmentVar = Environment.GetEnvironmentVariable(switchName);
if (environmentVar!=null) {
defaultValue = Int32.Parse(environmentVar.Trim(), CultureInfo.InvariantCulture);
}
}
finally {
EnvironmentPermission.RevertAssert();
}
return defaultValue;
}
#endif
#if TRAVE || DEBUG
private static bool GetSwitchValue(string switchName, string switchDescription, bool defaultValue)
{
BooleanSwitch theSwitch = new BooleanSwitch(switchName, switchDescription);
new EnvironmentPermission(PermissionState.Unrestricted).Assert();
try
{
if (theSwitch.Enabled)
{
return true;
}
string environmentVar = Environment.GetEnvironmentVariable(switchName);
defaultValue = environmentVar != null && environmentVar.Trim() == "1";
}
catch (ConfigurationException)
{
}
finally
{
EnvironmentPermission.RevertAssert();
}
return defaultValue;
}
#endif // TRAVE || DEBUG
// Enables thread tracing, detects mis-use of threads.
#if DEBUG
[ThreadStatic]
private static Stack<ThreadKinds> t_ThreadKindStack;
private static Stack<ThreadKinds> ThreadKindStack
{
get
{
if (t_ThreadKindStack == null)
{
t_ThreadKindStack = new Stack<ThreadKinds>();
}
return t_ThreadKindStack;
}
}
#endif
internal static ThreadKinds CurrentThreadKind
{
get
{
#if DEBUG
return ThreadKindStack.Count > 0 ? ThreadKindStack.Peek() : ThreadKinds.Other;
#else
return ThreadKinds.Unknown;
#endif
}
}
private static bool HasShutdownStarted
{
get
{
return Environment.HasShutdownStarted || AppDomain.CurrentDomain.IsFinalizingForUnload();
}
}
#if DEBUG
// ifdef'd instead of conditional since people are forced to handle the return value.
// [Conditional("DEBUG")]
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
internal static IDisposable SetThreadKind(ThreadKinds kind)
{
if ((kind & ThreadKinds.SourceMask) != ThreadKinds.Unknown)
{
throw new InvalidOperationException();
}
// Ignore during shutdown.
if (HasShutdownStarted)
{
return null;
}
ThreadKinds threadKind = CurrentThreadKind;
ThreadKinds source = threadKind & ThreadKinds.SourceMask;
#if TRAVE
// Special warnings when doing dangerous things on a thread.
if ((threadKind & ThreadKinds.User) != 0 && (kind & ThreadKinds.System) != 0)
{
Print("WARNING: Thread changed from User to System; user's thread shouldn't be hijacked.");
}
if ((threadKind & ThreadKinds.Async) != 0 && (kind & ThreadKinds.Sync) != 0)
{
Print("WARNING: Thread changed from Async to Sync, may block an Async thread.");
}
else if ((threadKind & (ThreadKinds.Other | ThreadKinds.CompletionPort)) == 0 && (kind & ThreadKinds.Sync) != 0)
{
Print("WARNING: Thread from a limited resource changed to Sync, may deadlock or bottleneck.");
}
#endif
ThreadKindStack.Push(
(((kind & ThreadKinds.OwnerMask) == 0 ? threadKind : kind) & ThreadKinds.OwnerMask) |
(((kind & ThreadKinds.SyncMask) == 0 ? threadKind : kind) & ThreadKinds.SyncMask) |
(kind & ~(ThreadKinds.OwnerMask | ThreadKinds.SyncMask)) |
source);
#if TRAVE
if (CurrentThreadKind != threadKind)
{
Print("Thread becomes:(" + CurrentThreadKind.ToString() + ")");
}
#endif
return new ThreadKindFrame();
}
private class ThreadKindFrame : IDisposable
{
private int m_FrameNumber;
internal ThreadKindFrame()
{
m_FrameNumber = ThreadKindStack.Count;
}
void IDisposable.Dispose()
{
// Ignore during shutdown.
if (GlobalLog.HasShutdownStarted)
{
return;
}
if (m_FrameNumber != ThreadKindStack.Count)
{
throw new InvalidOperationException();
}
ThreadKinds previous = ThreadKindStack.Pop();
#if TRAVE
if (CurrentThreadKind != previous)
{
Print("Thread reverts:(" + CurrentThreadKind.ToString() + ")");
}
#endif
}
}
#endif
[Conditional("DEBUG")]
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
internal static void SetThreadSource(ThreadKinds source)
{
#if DEBUG
if ((source & ThreadKinds.SourceMask) != source || source == ThreadKinds.Unknown)
{
throw new ArgumentException("Must specify the thread source.", "source");
}
if (ThreadKindStack.Count == 0)
{
ThreadKindStack.Push(source);
return;
}
if (ThreadKindStack.Count > 1)
{
Print("WARNING: SetThreadSource must be called at the base of the stack, or the stack has been corrupted.");
while (ThreadKindStack.Count > 1)
{
ThreadKindStack.Pop();
}
}
if (ThreadKindStack.Peek() != source)
{
// SQL can fail to clean up the stack, leaving the default Other at the bottom. Replace it.
Print("WARNING: The stack has been corrupted.");
ThreadKinds last = ThreadKindStack.Pop() & ThreadKinds.SourceMask;
Assert(last == source || last == ThreadKinds.Other, "Thread source changed.|Was:({0}) Now:({1})", last, source);
ThreadKindStack.Push(source);
}
#endif
}
[Conditional("DEBUG")]
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
internal static void ThreadContract(ThreadKinds kind, string errorMsg)
{
ThreadContract(kind, ThreadKinds.SafeSources, errorMsg);
}
[Conditional("DEBUG")]
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
internal static void ThreadContract(ThreadKinds kind, ThreadKinds allowedSources, string errorMsg)
{
if ((kind & ThreadKinds.SourceMask) != ThreadKinds.Unknown || (allowedSources & ThreadKinds.SourceMask) != allowedSources)
{
throw new InvalidOperationException();
}
ThreadKinds threadKind = CurrentThreadKind;
Assert((threadKind & allowedSources) != 0, errorMsg, "Thread Contract Violation.|Expected source:({0}) Actual source:({1})", allowedSources, threadKind & ThreadKinds.SourceMask);
Assert((threadKind & kind) == kind, errorMsg, "Thread Contract Violation.|Expected kind:({0}) Actual kind:({1})", kind, threadKind & ~ThreadKinds.SourceMask);
}
#if DEBUG
// Enables auto-hang detection, which will "snap" a log on hang
internal static bool EnableMonitorThread = false;
// Default value for hang timer
#if FEATURE_PAL // ROTORTODO - after speedups (like real JIT and GC) remove this
public const int DefaultTickValue = 1000*60*5; // 5 minutes
#else
public const int DefaultTickValue = 1000 * 60; // 60 secs
#endif // FEATURE_PAL
#endif // DEBUG
[System.Diagnostics.Conditional("TRAVE")]
public static void AddToArray(string msg)
{
#if TRAVE
GlobalLog.Logobject.PrintLine(msg);
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Ignore(object msg)
{
}
[System.Diagnostics.Conditional("TRAVE")]
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
public static void Print(string msg)
{
#if TRAVE
GlobalLog.Logobject.PrintLine(msg);
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void PrintHex(string msg, object value)
{
#if TRAVE
GlobalLog.Logobject.PrintLine(msg+TraveHelper.ToHex(value));
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Enter(string func)
{
#if TRAVE
GlobalLog.Logobject.EnterFunc(func + "(*none*)");
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Enter(string func, string parms)
{
#if TRAVE
GlobalLog.Logobject.EnterFunc(func + "(" + parms + ")");
#endif
}
[Conditional("DEBUG")]
[Conditional("_FORCE_ASSERTS")]
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
public static void Assert(bool condition, string messageFormat, params object[] data)
{
if (!condition)
{
string fullMessage = string.Format(CultureInfo.InvariantCulture, messageFormat, data);
int pipeIndex = fullMessage.IndexOf('|');
if (pipeIndex == -1)
{
Assert(fullMessage);
}
else
{
int detailLength = fullMessage.Length - pipeIndex - 1;
Assert(fullMessage.Substring(0, pipeIndex), detailLength > 0 ? fullMessage.Substring(pipeIndex + 1, detailLength) : null);
}
}
}
[Conditional("DEBUG")]
[Conditional("_FORCE_ASSERTS")]
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
public static void Assert(string message)
{
Assert(message, null);
}
[Conditional("DEBUG")]
[Conditional("_FORCE_ASSERTS")]
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
public static void Assert(string message, string detailMessage)
{
try
{
Print("Assert: " + message + (!string.IsNullOrEmpty(detailMessage) ? ": " + detailMessage : string.Empty));
Print("*******");
Logobject.DumpArray(false);
}
finally
{
#if DEBUG && !STRESS
Debug.Assert(false, message, detailMessage);
#endif
}
}
[System.Diagnostics.Conditional("TRAVE")]
public static void LeaveException(string func, Exception exception)
{
#if TRAVE
GlobalLog.Logobject.LeaveFunc(func + " exception " + ((exception!=null) ? exception.Message : String.Empty));
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Leave(string func)
{
#if TRAVE
GlobalLog.Logobject.LeaveFunc(func + " returns ");
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Leave(string func, string result)
{
#if TRAVE
GlobalLog.Logobject.LeaveFunc(func + " returns " + result);
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Leave(string func, int returnval)
{
#if TRAVE
GlobalLog.Logobject.LeaveFunc(func + " returns " + returnval.ToString());
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Leave(string func, bool returnval)
{
#if TRAVE
GlobalLog.Logobject.LeaveFunc(func + " returns " + returnval.ToString());
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void DumpArray()
{
#if TRAVE
GlobalLog.Logobject.DumpArray(true);
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Dump(byte[] buffer)
{
#if TRAVE
Logobject.Dump(buffer, 0, buffer!=null ? buffer.Length : -1);
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Dump(byte[] buffer, int length)
{
#if TRAVE
Logobject.Dump(buffer, 0, length);
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Dump(byte[] buffer, int offset, int length)
{
#if TRAVE
Logobject.Dump(buffer, offset, length);
#endif
}
[System.Diagnostics.Conditional("TRAVE")]
public static void Dump(IntPtr buffer, int offset, int length)
{
#if TRAVE
Logobject.Dump(buffer, offset, length);
#endif
}
#if DEBUG
private class HttpWebRequestComparer : IComparer
{
public int Compare(
object x1,
object y1)
{
HttpWebRequest x = (HttpWebRequest)x1;
HttpWebRequest y = (HttpWebRequest)y1;
if (x.GetHashCode() == y.GetHashCode())
{
return 0;
}
else if (x.GetHashCode() < y.GetHashCode())
{
return -1;
}
else if (x.GetHashCode() > y.GetHashCode())
{
return 1;
}
return 0;
}
}
/*
private class ConnectionMonitorEntry {
public HttpWebRequest m_Request;
public int m_Flags;
public DateTime m_TimeAdded;
public Connection m_Connection;
public ConnectionMonitorEntry(HttpWebRequest request, Connection connection, int flags) {
m_Request = request;
m_Connection = connection;
m_Flags = flags;
m_TimeAdded = DateTime.Now;
}
}
*/
private static volatile ManualResetEvent s_ShutdownEvent;
private static volatile SortedList s_RequestList;
internal const int WaitingForReadDoneFlag = 0x1;
#endif
/*
#if DEBUG
private static void ConnectionMonitor() {
while(! s_ShutdownEvent.WaitOne(DefaultTickValue, false)) {
if (GlobalLog.EnableMonitorThread) {
#if TRAVE
GlobalLog.Logobject.LoggingMonitorTick();
#endif
}
int hungCount = 0;
lock (s_RequestList) {
DateTime dateNow = DateTime.Now;
DateTime dateExpired = dateNow.AddSeconds(-DefaultTickValue);
foreach (ConnectionMonitorEntry monitorEntry in s_RequestList.GetValueList() ) {
if (monitorEntry != null &&
(dateExpired > monitorEntry.m_TimeAdded))
{
hungCount++;
#if TRAVE
GlobalLog.Print("delay:" + (dateNow - monitorEntry.m_TimeAdded).TotalSeconds +
" req#" + monitorEntry.m_Request.GetHashCode() +
" cnt#" + monitorEntry.m_Connection.GetHashCode() +
" flags:" + monitorEntry.m_Flags);
#endif
monitorEntry.m_Connection.Debug(monitorEntry.m_Request.GetHashCode());
}
}
}
Assert(hungCount == 0, "Warning: Hang Detected on Connection(s) of greater than {0} ms. {1} request(s) hung.|Please Dump System.Net.GlobalLog.s_RequestList for pending requests, make sure your streams are calling Close(), and that your destination server is up.", DefaultTickValue, hungCount);
}
}
#endif // DEBUG
**/
#if DEBUG
[ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.None)]
internal static void AppDomainUnloadEvent(object sender, EventArgs e)
{
s_ShutdownEvent.Set();
}
#endif
#if DEBUG
[System.Diagnostics.Conditional("DEBUG")]
private static void InitConnectionMonitor()
{
s_RequestList = new SortedList(new HttpWebRequestComparer(), 10);
s_ShutdownEvent = new ManualResetEvent(false);
AppDomain.CurrentDomain.DomainUnload += new EventHandler(AppDomainUnloadEvent);
AppDomain.CurrentDomain.ProcessExit += new EventHandler(AppDomainUnloadEvent);
// Thread threadMonitor = new Thread(new ThreadStart(ConnectionMonitor));
// threadMonitor.IsBackground = true;
// threadMonitor.Start();
}
#endif
/*
[System.Diagnostics.Conditional("DEBUG")]
internal static void DebugAddRequest(HttpWebRequest request, Connection connection, int flags) {
#if DEBUG
// null if the connection monitor is off
if(s_RequestList == null)
return;
lock(s_RequestList) {
Assert(!s_RequestList.ContainsKey(request), "s_RequestList.ContainsKey(request)|A HttpWebRequest should not be submitted twice.");
ConnectionMonitorEntry requestEntry =
new ConnectionMonitorEntry(request, connection, flags);
try {
s_RequestList.Add(request, requestEntry);
} catch {
}
}
#endif
}
*/
/*
[System.Diagnostics.Conditional("DEBUG")]
internal static void DebugRemoveRequest(HttpWebRequest request) {
#if DEBUG
// null if the connection monitor is off
if(s_RequestList == null)
return;
lock(s_RequestList) {
Assert(s_RequestList.ContainsKey(request), "!s_RequestList.ContainsKey(request)|A HttpWebRequest should not be removed twice.");
try {
s_RequestList.Remove(request);
} catch {
}
}
#endif
}
*/
/*
[System.Diagnostics.Conditional("DEBUG")]
internal static void DebugUpdateRequest(HttpWebRequest request, Connection connection, int flags) {
#if DEBUG
// null if the connection monitor is off
if(s_RequestList == null)
return;
lock(s_RequestList) {
if(!s_RequestList.ContainsKey(request)) {
return;
}
ConnectionMonitorEntry requestEntry =
new ConnectionMonitorEntry(request, connection, flags);
try {
s_RequestList.Remove(request);
s_RequestList.Add(request, requestEntry);
} catch {
}
}
#endif
}*/
}
}

View File

@ -0,0 +1,67 @@
//------------------------------------------------------------------------------
// <copyright file="HttpListenerContext.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Security.Principal;
namespace Microsoft.AspNet.Security.Windows
{
// TODO: At what point does a user need to be cleaned up?
internal sealed class HttpListenerContext
{
private WindowsAuthMiddleware _winAuth;
private IPrincipal _user = null;
internal const string NTLM = "NTLM";
internal HttpListenerContext(WindowsAuthMiddleware httpListener)
{
_winAuth = httpListener;
}
internal void Close()
{
if (Logging.On)
{
Logging.Enter(Logging.HttpListener, this, "Close()", string.Empty);
}
IDisposable user = _user == null ? null : _user.Identity as IDisposable;
// TODO: At what point does a user need to be cleaned up?
// For unsafe connection ntlm auth we dont dispose this identity as yet since its cached
if ((user != null) &&
(_user.Identity.AuthenticationType != NTLM) &&
(!_winAuth.UnsafeConnectionNtlmAuthentication))
{
user.Dispose();
}
if (Logging.On)
{
Logging.Exit(Logging.HttpListener, this, "Close", string.Empty);
}
}
internal void Abort()
{
if (Logging.On)
{
Logging.Enter(Logging.HttpListener, this, "Abort", string.Empty);
}
IDisposable user = _user == null ? null : _user.Identity as IDisposable;
if (user != null)
{
user.Dispose();
}
if (Logging.On)
{
Logging.Exit(Logging.HttpListener, this, "Abort", string.Empty);
}
}
}
}

View File

@ -0,0 +1,286 @@
//------------------------------------------------------------------------------
// <copyright file="Internal.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
namespace Microsoft.AspNet.Security.Windows
{
internal enum SecurityStatus
{
// Success / Informational
OK = 0x00000000,
ContinueNeeded = unchecked((int)0x00090312),
CompleteNeeded = unchecked((int)0x00090313),
CompAndContinue = unchecked((int)0x00090314),
ContextExpired = unchecked((int)0x00090317),
CredentialsNeeded = unchecked((int)0x00090320),
Renegotiate = unchecked((int)0x00090321),
// Errors
OutOfMemory = unchecked((int)0x80090300),
InvalidHandle = unchecked((int)0x80090301),
Unsupported = unchecked((int)0x80090302),
TargetUnknown = unchecked((int)0x80090303),
InternalError = unchecked((int)0x80090304),
PackageNotFound = unchecked((int)0x80090305),
NotOwner = unchecked((int)0x80090306),
CannotInstall = unchecked((int)0x80090307),
InvalidToken = unchecked((int)0x80090308),
CannotPack = unchecked((int)0x80090309),
QopNotSupported = unchecked((int)0x8009030A),
NoImpersonation = unchecked((int)0x8009030B),
LogonDenied = unchecked((int)0x8009030C),
UnknownCredentials = unchecked((int)0x8009030D),
NoCredentials = unchecked((int)0x8009030E),
MessageAltered = unchecked((int)0x8009030F),
OutOfSequence = unchecked((int)0x80090310),
NoAuthenticatingAuthority = unchecked((int)0x80090311),
IncompleteMessage = unchecked((int)0x80090318),
IncompleteCredentials = unchecked((int)0x80090320),
BufferNotEnough = unchecked((int)0x80090321),
WrongPrincipal = unchecked((int)0x80090322),
TimeSkew = unchecked((int)0x80090324),
UntrustedRoot = unchecked((int)0x80090325),
IllegalMessage = unchecked((int)0x80090326),
CertUnknown = unchecked((int)0x80090327),
CertExpired = unchecked((int)0x80090328),
AlgorithmMismatch = unchecked((int)0x80090331),
SecurityQosFailed = unchecked((int)0x80090332),
SmartcardLogonRequired = unchecked((int)0x8009033E),
UnsupportedPreauth = unchecked((int)0x80090343),
BadBinding = unchecked((int)0x80090346)
}
internal enum ContextAttribute
{
// look into <sspi.h> and <schannel.h>
Sizes = 0x00,
Names = 0x01,
Lifespan = 0x02,
DceInfo = 0x03,
StreamSizes = 0x04,
// KeyInfo = 0x05, must not be used, see ConnectionInfo instead
Authority = 0x06,
// SECPKG_ATTR_PROTO_INFO = 7,
// SECPKG_ATTR_PASSWORD_EXPIRY = 8,
// SECPKG_ATTR_SESSION_KEY = 9,
PackageInfo = 0x0A,
// SECPKG_ATTR_USER_FLAGS = 11,
NegotiationInfo = 0x0C,
// SECPKG_ATTR_NATIVE_NAMES = 13,
// SECPKG_ATTR_FLAGS = 14,
// SECPKG_ATTR_USE_VALIDATED = 15,
// SECPKG_ATTR_CREDENTIAL_NAME = 16,
// SECPKG_ATTR_TARGET_INFORMATION = 17,
// SECPKG_ATTR_ACCESS_TOKEN = 18,
// SECPKG_ATTR_TARGET = 19,
// SECPKG_ATTR_AUTHENTICATION_ID = 20,
UniqueBindings = 0x19,
EndpointBindings = 0x1A,
ClientSpecifiedSpn = 0x1B, // SECPKG_ATTR_CLIENT_SPECIFIED_TARGET = 27
RemoteCertificate = 0x53,
LocalCertificate = 0x54,
RootStore = 0x55,
IssuerListInfoEx = 0x59,
ConnectionInfo = 0x5A,
// SECPKG_ATTR_EAP_KEY_BLOCK 0x5b // returns SecPkgContext_EapKeyBlock
// SECPKG_ATTR_MAPPED_CRED_ATTR 0x5c // returns SecPkgContext_MappedCredAttr
// SECPKG_ATTR_SESSION_INFO 0x5d // returns SecPkgContext_SessionInfo
// SECPKG_ATTR_APP_DATA 0x5e // sets/returns SecPkgContext_SessionAppData
// SECPKG_ATTR_REMOTE_CERTIFICATES 0x5F // returns SecPkgContext_Certificates
// SECPKG_ATTR_CLIENT_CERT_POLICY 0x60 // sets SecPkgCred_ClientCertCtlPolicy
// SECPKG_ATTR_CC_POLICY_RESULT 0x61 // returns SecPkgContext_ClientCertPolicyResult
// SECPKG_ATTR_USE_NCRYPT 0x62 // Sets the CRED_FLAG_USE_NCRYPT_PROVIDER FLAG on cred group
// SECPKG_ATTR_LOCAL_CERT_INFO 0x63 // returns SecPkgContext_CertInfo
// SECPKG_ATTR_CIPHER_INFO 0x64 // returns new CNG SecPkgContext_CipherInfo
// SECPKG_ATTR_EAP_PRF_INFO 0x65 // sets SecPkgContext_EapPrfInfo
// SECPKG_ATTR_SUPPORTED_SIGNATURES 0x66 // returns SecPkgContext_SupportedSignatures
// SECPKG_ATTR_REMOTE_CERT_CHAIN 0x67 // returns PCCERT_CONTEXT
UiInfo = 0x68, // sets SEcPkgContext_UiInfo
}
internal enum Endianness
{
Network = 0x00,
Native = 0x10,
}
internal enum CredentialUse
{
Inbound = 0x1,
Outbound = 0x2,
Both = 0x3,
}
internal enum BufferType
{
Empty = 0x00,
Data = 0x01,
Token = 0x02,
Parameters = 0x03,
Missing = 0x04,
Extra = 0x05,
Trailer = 0x06,
Header = 0x07,
Padding = 0x09, // non-data padding
Stream = 0x0A,
ChannelBindings = 0x0E,
TargetHost = 0x10,
ReadOnlyFlag = unchecked((int)0x80000000),
ReadOnlyWithChecksum = 0x10000000
}
// SecPkgContext_IssuerListInfoEx
[StructLayout(LayoutKind.Sequential)]
internal struct IssuerListInfoEx
{
public SafeHandle aIssuers;
public uint cIssuers;
public unsafe IssuerListInfoEx(SafeHandle handle, byte[] nativeBuffer)
{
aIssuers = handle;
fixed (byte* voidPtr = nativeBuffer)
{
// if this breaks on 64 bit, do the sizeof(IntPtr) trick
cIssuers = *((uint*)(voidPtr + IntPtr.Size));
}
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct SecureCredential
{
/*
typedef struct _SCHANNEL_CRED
{
DWORD dwVersion; // always SCHANNEL_CRED_VERSION
DWORD cCreds;
PCCERT_CONTEXT *paCred;
HCERTSTORE hRootStore;
DWORD cMappers;
struct _HMAPPER **aphMappers;
DWORD cSupportedAlgs;
ALG_ID * palgSupportedAlgs;
DWORD grbitEnabledProtocols;
DWORD dwMinimumCipherStrength;
DWORD dwMaximumCipherStrength;
DWORD dwSessionLifespan;
DWORD dwFlags;
DWORD reserved;
} SCHANNEL_CRED, *PSCHANNEL_CRED;
*/
public const int CurrentVersion = 0x4;
public int version;
public int cCreds;
// ptr to an array of pointers
// There is a hack done with this field. AcquireCredentialsHandle requires an array of
// certificate handles; we only ever use one. In order to avoid pinning a one element array,
// we copy this value onto the stack, create a pointer on the stack to the copied value,
// and replace this field with the pointer, during the call to AcquireCredentialsHandle.
// Then we fix it up afterwards. Fine as long as all the SSPI credentials are not
// supposed to be threadsafe.
public IntPtr certContextArray;
private readonly IntPtr rootStore; // == always null, OTHERWISE NOT RELIABLE
public int cMappers;
private readonly IntPtr phMappers; // == always null, OTHERWISE NOT RELIABLE
public int cSupportedAlgs;
private readonly IntPtr palgSupportedAlgs; // == always null, OTHERWISE NOT RELIABLE
public SchProtocols grbitEnabledProtocols;
public int dwMinimumCipherStrength;
public int dwMaximumCipherStrength;
public int dwSessionLifespan;
public SecureCredential.Flags dwFlags;
public int reserved;
public SecureCredential(int version, X509Certificate certificate, SecureCredential.Flags flags, SchProtocols protocols, EncryptionPolicy policy)
{
// default values required for a struct
rootStore = phMappers = palgSupportedAlgs = certContextArray = IntPtr.Zero;
cCreds = cMappers = cSupportedAlgs = 0;
if (policy == EncryptionPolicy.RequireEncryption)
{
// Prohibit null encryption cipher
dwMinimumCipherStrength = 0;
dwMaximumCipherStrength = 0;
}
else if (policy == EncryptionPolicy.AllowNoEncryption)
{
// Allow null encryption cipher in addition to other ciphers
dwMinimumCipherStrength = -1;
dwMaximumCipherStrength = 0;
}
else if (policy == EncryptionPolicy.NoEncryption)
{
// Suppress all encryption and require null encryption cipher only
dwMinimumCipherStrength = -1;
dwMaximumCipherStrength = -1;
}
else
{
throw new ArgumentException(SR.GetString(SR.net_invalid_enum, "EncryptionPolicy"), "policy");
}
dwSessionLifespan = reserved = 0;
this.version = version;
dwFlags = flags;
grbitEnabledProtocols = protocols;
if (certificate != null)
{
certContextArray = certificate.Handle;
cCreds = 1;
}
}
[Flags]
public enum Flags
{
Zero = 0,
NoSystemMapper = 0x02,
NoNameCheck = 0x04,
ValidateManual = 0x08,
NoDefaultCred = 0x10,
ValidateAuto = 0x20
}
} // SecureCredential
[SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable",
Justification = "This structure does not own the native resource.")]
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct SecurityBufferStruct
{
public int count;
public BufferType type;
public IntPtr token;
public static readonly int Size = sizeof(SecurityBufferStruct);
}
internal static class IntPtrHelper
{
internal static IntPtr Add(IntPtr a, int b)
{
return (IntPtr)((long)a + (long)b);
}
}
}

View File

@ -0,0 +1,657 @@
//------------------------------------------------------------------------------
// <copyright file="Logging.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security;
using System.Threading;
namespace Microsoft.AspNet.Security.Windows
{
internal class Logging
{
private const string AttributeNameMaxSize = "maxdatasize";
private const string AttributeNameTraceMode = "tracemode";
private const string AttributeValueProtocolOnly = "protocolonly";
// private const string AttributeValueIncludeHex = "includehex";
private const int DefaultMaxDumpSize = 1024;
private const bool DefaultUseProtocolTextOnly = false;
private const string TraceSourceWebName = "System.Net";
private const string TraceSourceHttpListenerName = "System.Net.HttpListener";
private static readonly string[] SupportedAttributes = new string[] { AttributeNameMaxSize, AttributeNameTraceMode };
private static volatile bool s_LoggingEnabled = true;
private static volatile bool s_LoggingInitialized;
private static volatile bool s_AppDomainShutdown;
private static TraceSource s_WebTraceSource;
private static TraceSource s_HttpListenerTraceSource;
private static object s_InternalSyncObject;
private Logging()
{
}
private static object InternalSyncObject
{
get
{
if (s_InternalSyncObject == null)
{
object o = new Object();
Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
}
internal static bool On
{
get
{
if (!s_LoggingInitialized)
{
InitializeLogging();
}
return s_LoggingEnabled;
}
}
internal static bool IsVerbose(TraceSource traceSource)
{
return ValidateSettings(traceSource, TraceEventType.Verbose);
}
internal static TraceSource Web
{
get
{
if (!s_LoggingInitialized)
{
InitializeLogging();
}
if (!s_LoggingEnabled)
{
return null;
}
return s_WebTraceSource;
}
}
internal static TraceSource HttpListener
{
get
{
if (!s_LoggingInitialized)
{
InitializeLogging();
}
if (!s_LoggingEnabled)
{
return null;
}
return s_HttpListenerTraceSource;
}
}
private static bool GetUseProtocolTextSetting(TraceSource traceSource)
{
bool useProtocolTextOnly = DefaultUseProtocolTextOnly;
if (traceSource.Attributes[AttributeNameTraceMode] == AttributeValueProtocolOnly)
{
useProtocolTextOnly = true;
}
return useProtocolTextOnly;
}
private static int GetMaxDumpSizeSetting(TraceSource traceSource)
{
int maxDumpSize = DefaultMaxDumpSize;
if (traceSource.Attributes.ContainsKey(AttributeNameMaxSize))
{
try
{
maxDumpSize = Int32.Parse(traceSource.Attributes[AttributeNameMaxSize], NumberFormatInfo.InvariantInfo);
}
catch (Exception exception)
{
if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException)
{
throw;
}
traceSource.Attributes[AttributeNameMaxSize] = maxDumpSize.ToString(NumberFormatInfo.InvariantInfo);
}
}
return maxDumpSize;
}
/// <devdoc>
/// <para>Sets up internal config settings for logging. (MUST be called under critsec) </para>
/// </devdoc>
private static void InitializeLogging()
{
lock (InternalSyncObject)
{
if (!s_LoggingInitialized)
{
bool loggingEnabled = false;
s_WebTraceSource = new NclTraceSource(TraceSourceWebName);
s_HttpListenerTraceSource = new NclTraceSource(TraceSourceHttpListenerName);
GlobalLog.Print("Initalizating tracing");
try
{
loggingEnabled = (s_WebTraceSource.Switch.ShouldTrace(TraceEventType.Critical) ||
s_HttpListenerTraceSource.Switch.ShouldTrace(TraceEventType.Critical));
}
catch (SecurityException)
{
// These may throw if the caller does not have permission to hook up trace listeners.
// We treat this case as though logging were disabled.
Close();
loggingEnabled = false;
}
if (loggingEnabled)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler);
currentDomain.DomainUnload += new EventHandler(AppDomainUnloadEvent);
currentDomain.ProcessExit += new EventHandler(ProcessExitEvent);
}
s_LoggingEnabled = loggingEnabled;
s_LoggingInitialized = true;
}
}
}
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Logging functions must work in partial trust mode")]
private static void Close()
{
if (s_WebTraceSource != null)
{
s_WebTraceSource.Close();
}
if (s_HttpListenerTraceSource != null)
{
s_HttpListenerTraceSource.Close();
}
}
/// <devdoc>
/// <para>Logs any unhandled exception through this event handler</para>
/// </devdoc>
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
Exception(Web, sender, "UnhandledExceptionHandler", e);
}
private static void ProcessExitEvent(object sender, EventArgs e)
{
Close();
s_AppDomainShutdown = true;
}
/// <devdoc>
/// <para>Called when the system is shutting down, used to prevent additional logging post-shutdown</para>
/// </devdoc>
private static void AppDomainUnloadEvent(object sender, EventArgs e)
{
Close();
s_AppDomainShutdown = true;
}
/// <devdoc>
/// <para>Confirms logging is enabled, given current logging settings</para>
/// </devdoc>
private static bool ValidateSettings(TraceSource traceSource, TraceEventType traceLevel)
{
if (!s_LoggingEnabled)
{
return false;
}
if (!s_LoggingInitialized)
{
InitializeLogging();
}
if (traceSource == null || !traceSource.Switch.ShouldTrace(traceLevel))
{
return false;
}
if (s_AppDomainShutdown)
{
return false;
}
return true;
}
/// <devdoc>
/// <para>Converts an object to a normalized string that can be printed
/// takes System.Net.ObjectNamedFoo and coverts to ObjectNamedFoo,
/// except IPAddress, IPEndPoint, and Uri, which return ToString()
/// </para>
/// </devdoc>
private static string GetObjectName(object obj)
{
if (obj is Uri || obj is System.Net.IPAddress || obj is System.Net.IPEndPoint)
{
return obj.ToString();
}
else
{
return obj.GetType().Name;
}
}
internal static uint GetThreadId()
{
uint threadId = UnsafeNclNativeMethods.GetCurrentThreadId();
if (threadId == 0)
{
threadId = (uint)Thread.CurrentThread.GetHashCode();
}
return threadId;
}
internal static void PrintLine(TraceSource traceSource, TraceEventType eventType, int id, string msg)
{
string logHeader = "[" + GetThreadId().ToString("d4", CultureInfo.InvariantCulture) + "] ";
traceSource.TraceEvent(eventType, id, logHeader + msg);
}
/// <devdoc>
/// <para>Indicates that two objects are getting used with one another</para>
/// </devdoc>
internal static void Associate(TraceSource traceSource, object objA, object objB)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
string lineA = GetObjectName(objA) + "#" + ValidationHelper.HashString(objA);
string lineB = GetObjectName(objB) + "#" + ValidationHelper.HashString(objB);
PrintLine(traceSource, TraceEventType.Information, 0, "Associating " + lineA + " with " + lineB);
}
/// <devdoc>
/// <para>Logs entrance to a function</para>
/// </devdoc>
internal static void Enter(TraceSource traceSource, object obj, string method, string param)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
Enter(traceSource, GetObjectName(obj) + "#" + ValidationHelper.HashString(obj), method, param);
}
/// <devdoc>
/// <para>Logs entrance to a function</para>
/// </devdoc>
internal static void Enter(TraceSource traceSource, object obj, string method, object paramObject)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
Enter(traceSource, GetObjectName(obj) + "#" + ValidationHelper.HashString(obj), method, paramObject);
}
/// <devdoc>
/// <para>Logs entrance to a function</para>
/// </devdoc>
internal static void Enter(TraceSource traceSource, string obj, string method, string param)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
Enter(traceSource, obj + "::" + method + "(" + param + ")");
}
/// <devdoc>
/// <para>Logs entrance to a function</para>
/// </devdoc>
internal static void Enter(TraceSource traceSource, string obj, string method, object paramObject)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
string paramObjectValue = string.Empty;
if (paramObject != null)
{
paramObjectValue = GetObjectName(paramObject) + "#" + ValidationHelper.HashString(paramObject);
}
Enter(traceSource, obj + "::" + method + "(" + paramObjectValue + ")");
}
/// <devdoc>
/// <para>Logs entrance to a function, indents and points that out</para>
/// </devdoc>
internal static void Enter(TraceSource traceSource, string method, string parameters)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
Enter(traceSource, method + "(" + parameters + ")");
}
/// <devdoc>
/// <para>Logs entrance to a function, indents and points that out</para>
/// </devdoc>
internal static void Enter(TraceSource traceSource, string msg)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
// Trace.CorrelationManager.StartLogicalOperation();
PrintLine(traceSource, TraceEventType.Verbose, 0, msg);
}
/// <devdoc>
/// <para>Logs exit from a function</para>
/// </devdoc>
internal static void Exit(TraceSource traceSource, object obj, string method, object retObject)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
string retValue = string.Empty;
if (retObject != null)
{
retValue = GetObjectName(retObject) + "#" + ValidationHelper.HashString(retObject);
}
Exit(traceSource, obj, method, retValue);
}
/// <devdoc>
/// <para>Logs exit from a function</para>
/// </devdoc>
internal static void Exit(TraceSource traceSource, string obj, string method, object retObject)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
string retValue = string.Empty;
if (retObject != null)
{
retValue = GetObjectName(retObject) + "#" + ValidationHelper.HashString(retObject);
}
Exit(traceSource, obj, method, retValue);
}
/// <devdoc>
/// <para>Logs exit from a function</para>
/// </devdoc>
internal static void Exit(TraceSource traceSource, object obj, string method, string retValue)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
Exit(traceSource, GetObjectName(obj) + "#" + ValidationHelper.HashString(obj), method, retValue);
}
/// <devdoc>
/// <para>Logs exit from a function</para>
/// </devdoc>
internal static void Exit(TraceSource traceSource, string obj, string method, string retValue)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
if (!string.IsNullOrEmpty(retValue))
{
retValue = "\t-> " + retValue;
}
Exit(traceSource, obj + "::" + method + "() " + retValue);
}
/// <devdoc>
/// <para>Logs exit from a function</para>
/// </devdoc>
internal static void Exit(TraceSource traceSource, string method, string parameters)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
Exit(traceSource, method + "() " + parameters);
}
/// <devdoc>
/// <para>Logs exit from a function</para>
/// </devdoc>
internal static void Exit(TraceSource traceSource, string msg)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
PrintLine(traceSource, TraceEventType.Verbose, 0, "Exiting " + msg);
// Trace.CorrelationManager.StopLogicalOperation();
}
/// <devdoc>
/// <para>Logs Exception, restores indenting</para>
/// </devdoc>
internal static void Exception(TraceSource traceSource, object obj, string method, Exception e)
{
if (!ValidateSettings(traceSource, TraceEventType.Error))
{
return;
}
string infoLine = SR.GetString(SR.net_log_exception, GetObjectLogHash(obj), method, e.Message);
if (!string.IsNullOrEmpty(e.StackTrace))
{
infoLine += "\r\n" + e.StackTrace;
}
PrintLine(traceSource, TraceEventType.Error, 0, infoLine);
}
/// <devdoc>
/// <para>Logs an Info line</para>
/// </devdoc>
internal static void PrintInfo(TraceSource traceSource, string msg)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
PrintLine(traceSource, TraceEventType.Information, 0, msg);
}
/// <devdoc>
/// <para>Logs an Info line</para>
/// </devdoc>
internal static void PrintInfo(TraceSource traceSource, object obj, string msg)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
PrintLine(traceSource, TraceEventType.Information, 0,
GetObjectName(obj) + "#" + ValidationHelper.HashString(obj)
+ " - " + msg);
}
/// <devdoc>
/// <para>Logs an Info line</para>
/// </devdoc>
internal static void PrintInfo(TraceSource traceSource, object obj, string method, string param)
{
if (!ValidateSettings(traceSource, TraceEventType.Information))
{
return;
}
PrintLine(traceSource, TraceEventType.Information, 0,
GetObjectName(obj) + "#" + ValidationHelper.HashString(obj)
+ "::" + method + "(" + param + ")");
}
/// <devdoc>
/// <para>Logs a Warning line</para>
/// </devdoc>
internal static void PrintWarning(TraceSource traceSource, string msg)
{
if (!ValidateSettings(traceSource, TraceEventType.Warning))
{
return;
}
PrintLine(traceSource, TraceEventType.Warning, 0, msg);
}
/// <devdoc>
/// <para>Logs a Warning line</para>
/// </devdoc>
internal static void PrintWarning(TraceSource traceSource, object obj, string method, string msg)
{
if (!ValidateSettings(traceSource, TraceEventType.Warning))
{
return;
}
PrintLine(traceSource, TraceEventType.Warning, 0,
GetObjectName(obj) + "#" + ValidationHelper.HashString(obj)
+ "::" + method + "() - " + msg);
}
/// <devdoc>
/// <para>Logs an Error line</para>
/// </devdoc>
internal static void PrintError(TraceSource traceSource, string msg)
{
if (!ValidateSettings(traceSource, TraceEventType.Error))
{
return;
}
PrintLine(traceSource, TraceEventType.Error, 0, msg);
}
/// <devdoc>
/// <para>Logs an Error line</para>
/// </devdoc>
internal static void PrintError(TraceSource traceSource, object obj, string method, string msg)
{
if (!ValidateSettings(traceSource, TraceEventType.Error))
{
return;
}
PrintLine(traceSource, TraceEventType.Error, 0,
GetObjectName(obj) + "#" + ValidationHelper.HashString(obj)
+ "::" + method + "() - " + msg);
}
internal static string GetObjectLogHash(object obj)
{
return GetObjectName(obj) + "#" + ValidationHelper.HashString(obj);
}
/// <devdoc>
/// <para>Marhsalls a buffer ptr to an array and then dumps the byte array to the log</para>
/// </devdoc>
internal static void Dump(TraceSource traceSource, object obj, string method, IntPtr bufferPtr, int length)
{
if (!ValidateSettings(traceSource, TraceEventType.Verbose) || bufferPtr == IntPtr.Zero || length < 0)
{
return;
}
byte[] buffer = new byte[length];
Marshal.Copy(bufferPtr, buffer, 0, length);
Dump(traceSource, obj, method, buffer, 0, length);
}
/// <devdoc>
/// <para>Dumps a byte array to the log</para>
/// </devdoc>
internal static void Dump(TraceSource traceSource, object obj, string method, byte[] buffer, int offset, int length)
{
if (!ValidateSettings(traceSource, TraceEventType.Verbose))
{
return;
}
if (buffer == null)
{
PrintLine(traceSource, TraceEventType.Verbose, 0, "(null)");
return;
}
if (offset > buffer.Length)
{
PrintLine(traceSource, TraceEventType.Verbose, 0, "(offset out of range)");
return;
}
PrintLine(traceSource, TraceEventType.Verbose, 0, "Data from " + GetObjectName(obj) + "#" + ValidationHelper.HashString(obj) + "::" + method);
int maxDumpSize = GetMaxDumpSizeSetting(traceSource);
if (length > maxDumpSize)
{
PrintLine(traceSource, TraceEventType.Verbose, 0, "(printing " + maxDumpSize.ToString(NumberFormatInfo.InvariantInfo) + " out of " + length.ToString(NumberFormatInfo.InvariantInfo) + ")");
length = maxDumpSize;
}
if ((length < 0) || (length > buffer.Length - offset))
{
length = buffer.Length - offset;
}
if (GetUseProtocolTextSetting(traceSource))
{
string output = "<<" + HeaderEncoding.GetString(buffer, offset, length) + ">>";
PrintLine(traceSource, TraceEventType.Verbose, 0, output);
return;
}
do
{
int n = Math.Min(length, 16);
string disp = String.Format(CultureInfo.CurrentCulture, "{0:X8} : ", offset);
for (int i = 0; i < n; ++i)
{
disp += String.Format(CultureInfo.CurrentCulture, "{0:X2}", buffer[offset + i]) + ((i == 7) ? '-' : ' ');
}
for (int i = n; i < 16; ++i)
{
disp += " ";
}
disp += ": ";
for (int i = 0; i < n; ++i)
{
disp += ((buffer[offset + i] < 0x20) || (buffer[offset + i] > 0x7e))
? '.'
: (char)(buffer[offset + i]);
}
PrintLine(traceSource, TraceEventType.Verbose, 0, disp);
offset += n;
length -= n;
}
while (length > 0);
}
private class NclTraceSource : TraceSource
{
internal NclTraceSource(string name) : base(name)
{
}
/*
protected internal override string[] GetSupportedAttributes()
{
return Logging.SupportedAttributes;
}*/
}
}
}

View File

@ -0,0 +1,580 @@
//------------------------------------------------------------------------------
// <copyright file="_LoggingObject.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
// We have function based stack and thread based logging of basic behavior. We
// also now have the ability to run a "watch thread" which does basic hang detection
// and error-event based logging. The logging code buffers the callstack/picture
// of all COMNET threads, and upon error from an assert or a hang, it will open a file
// and dump the snapsnot. Future work will allow this to be configed by registry and
// to use Runtime based logging. We'd also like to have different levels of logging.
namespace Microsoft.AspNet.Security.Windows
{
using System;
// BaseLoggingObject - used to disable logging,
// this is just a base class that does nothing.
[Flags]
internal enum ThreadKinds
{
Unknown = 0x0000,
// Mutually exclusive.
User = 0x0001, // Thread has entered via an API.
System = 0x0002, // Thread has entered via a system callback (e.g. completion port) or is our own thread.
// Mutually exclusive.
Sync = 0x0004, // Thread should block.
Async = 0x0008, // Thread should not block.
// Mutually exclusive, not always known for a user thread. Never changes.
Timer = 0x0010, // Thread is the timer thread. (Can't call user code.)
CompletionPort = 0x0020, // Thread is a ThreadPool completion-port thread.
Worker = 0x0040, // Thread is a ThreadPool worker thread.
Finalization = 0x0080, // Thread is the finalization thread.
Other = 0x0100, // Unknown source.
OwnerMask = User | System,
SyncMask = Sync | Async,
SourceMask = Timer | CompletionPort | Worker | Finalization | Other,
// Useful "macros"
SafeSources = SourceMask & ~(Timer | Finalization), // Methods that "unsafe" sources can call must be explicitly marked.
ThreadPool = CompletionPort | Worker, // Like Thread.CurrentThread.IsThreadPoolThread
}
internal class BaseLoggingObject
{
internal BaseLoggingObject()
{
}
internal virtual void EnterFunc(string funcname)
{
}
internal virtual void LeaveFunc(string funcname)
{
}
internal virtual void DumpArrayToConsole()
{
}
internal virtual void PrintLine(string msg)
{
}
internal virtual void DumpArray(bool shouldClose)
{
}
internal virtual void DumpArrayToFile(bool shouldClose)
{
}
internal virtual void Flush()
{
}
internal virtual void Flush(bool close)
{
}
internal virtual void LoggingMonitorTick()
{
}
internal virtual void Dump(byte[] buffer)
{
}
internal virtual void Dump(byte[] buffer, int length)
{
}
internal virtual void Dump(byte[] buffer, int offset, int length)
{
}
internal virtual void Dump(IntPtr pBuffer, int offset, int length)
{
}
} // class BaseLoggingObject
#if TRAVE
/// <internalonly/>
/// <devdoc>
/// </devdoc>
internal class LoggingObject : BaseLoggingObject {
public ArrayList _Logarray;
private Hashtable _ThreadNesting;
private int _AddCount;
private StreamWriter _Stream;
private int _IamAlive;
private int _LastIamAlive;
private bool _Finalized = false;
private double _NanosecondsPerTick;
private int _StartMilliseconds;
private long _StartTicks;
internal LoggingObject() : base() {
_Logarray = new ArrayList();
_ThreadNesting = new Hashtable();
_AddCount = 0;
_IamAlive = 0;
_LastIamAlive = -1;
if (GlobalLog.s_UsePerfCounter) {
long ticksPerSecond;
SafeNativeMethods.QueryPerformanceFrequency(out ticksPerSecond);
_NanosecondsPerTick = 10000000.0/(double)ticksPerSecond;
SafeNativeMethods.QueryPerformanceCounter(out _StartTicks);
} else {
_StartMilliseconds = Environment.TickCount;
}
}
//
// LoggingMonitorTick - this function is run from the monitor thread,
// and used to check to see if there any hangs, ie no logging
// activitity
//
internal override void LoggingMonitorTick() {
if ( _LastIamAlive == _IamAlive ) {
PrintLine("================= Error TIMEOUT - HANG DETECTED =================");
DumpArray(true);
}
_LastIamAlive = _IamAlive;
}
internal override void EnterFunc(string funcname) {
if (_Finalized) {
return;
}
IncNestingCount();
ValidatePush(funcname);
PrintLine(funcname);
}
internal override void LeaveFunc(string funcname) {
if (_Finalized) {
return;
}
PrintLine(funcname);
DecNestingCount();
ValidatePop(funcname);
}
internal override void DumpArrayToConsole() {
for (int i=0; i < _Logarray.Count; i++) {
Console.WriteLine((string) _Logarray[i]);
}
}
internal override void PrintLine(string msg) {
if (_Finalized) {
return;
}
string spc = "";
_IamAlive++;
spc = GetNestingString();
string tickString = "";
if (GlobalLog.s_UsePerfCounter) {
long nowTicks;
SafeNativeMethods.QueryPerformanceCounter(out nowTicks);
if (_StartTicks>nowTicks) { // counter reset, restart from 0
_StartTicks = nowTicks;
}
nowTicks -= _StartTicks;
if (GlobalLog.s_UseTimeSpan) {
tickString = new TimeSpan((long)(nowTicks*_NanosecondsPerTick)).ToString();
// note: TimeSpan().ToString() doesn't return the uSec part
// if its 0. .ToString() returns [H*]HH:MM:SS:uuuuuuu, hence 16
if (tickString.Length < 16) {
tickString += ".0000000";
}
}
else {
tickString = ((double)nowTicks*_NanosecondsPerTick/10000).ToString("f3");
}
}
else {
int nowMilliseconds = Environment.TickCount;
if (_StartMilliseconds>nowMilliseconds) {
_StartMilliseconds = nowMilliseconds;
}
nowMilliseconds -= _StartMilliseconds;
if (GlobalLog.s_UseTimeSpan) {
tickString = new TimeSpan(nowMilliseconds*10000).ToString();
// note: TimeSpan().ToString() doesn't return the uSec part
// if its 0. .ToString() returns [H*]HH:MM:SS:uuuuuuu, hence 16
if (tickString.Length < 16) {
tickString += ".0000000";
}
}
else {
tickString = nowMilliseconds.ToString();
}
}
uint threadId = 0;
if (GlobalLog.s_UseThreadId) {
try {
object threadData = Thread.GetData(GlobalLog.s_ThreadIdSlot);
if (threadData!= null) {
threadId = (uint)threadData;
}
}
catch(Exception exception) {
if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
throw;
}
}
if (threadId == 0) {
threadId = UnsafeNclNativeMethods.GetCurrentThreadId();
Thread.SetData(GlobalLog.s_ThreadIdSlot, threadId);
}
}
if (threadId == 0) {
threadId = (uint)Thread.CurrentThread.GetHashCode();
}
string str = "[" + threadId.ToString("x8") + "]" + " (" +tickString+ ") " + spc + msg;
lock(this) {
_AddCount++;
_Logarray.Add(str);
int MaxLines = GlobalLog.s_DumpToConsole ? 0 : GlobalLog.MaxLinesBeforeSave;
if (_AddCount > MaxLines) {
_AddCount = 0;
DumpArray(false);
_Logarray = new ArrayList();
}
}
}
internal override void DumpArray(bool shouldClose) {
if ( GlobalLog.s_DumpToConsole ) {
DumpArrayToConsole();
} else {
DumpArrayToFile(shouldClose);
}
}
internal unsafe override void Dump(byte[] buffer, int offset, int length) {
//if (!GlobalLog.s_DumpWebData) {
// return;
//}
if (buffer==null) {
PrintLine("(null)");
return;
}
if (offset > buffer.Length) {
PrintLine("(offset out of range)");
return;
}
if (length > GlobalLog.s_MaxDumpSize) {
PrintLine("(printing " + GlobalLog.s_MaxDumpSize.ToString() + " out of " + length.ToString() + ")");
length = GlobalLog.s_MaxDumpSize;
}
if ((length < 0) || (length > buffer.Length - offset)) {
length = buffer.Length - offset;
}
fixed (byte* pBuffer = buffer) {
Dump((IntPtr)pBuffer, offset, length);
}
}
internal unsafe override void Dump(IntPtr pBuffer, int offset, int length) {
//if (!GlobalLog.s_DumpWebData) {
// return;
//}
if (pBuffer==IntPtr.Zero || length<0) {
PrintLine("(null)");
return;
}
if (length > GlobalLog.s_MaxDumpSize) {
PrintLine("(printing " + GlobalLog.s_MaxDumpSize.ToString() + " out of " + length.ToString() + ")");
length = GlobalLog.s_MaxDumpSize;
}
byte* buffer = (byte*)pBuffer + offset;
Dump(buffer, length);
}
unsafe void Dump(byte* buffer, int length) {
do {
int offset = 0;
int n = Math.Min(length, 16);
string disp = ((IntPtr)buffer).ToString("X8") + " : " + offset.ToString("X8") + " : ";
byte current;
for (int i = 0; i < n; ++i) {
current = *(buffer + i);
disp += current.ToString("X2") + ((i == 7) ? '-' : ' ');
}
for (int i = n; i < 16; ++i) {
disp += " ";
}
disp += ": ";
for (int i = 0; i < n; ++i) {
current = *(buffer + i);
disp += ((current < 0x20) || (current > 0x7e)) ? '.' : (char)current;
}
PrintLine(disp);
offset += n;
buffer += n;
length -= n;
} while (length > 0);
}
// SECURITY: This is dev-debugging class and we need some permissions
// to use it under trust-restricted environment as well.
[PermissionSet(SecurityAction.Assert, Name="FullTrust")]
internal override void DumpArrayToFile(bool shouldClose) {
lock (this) {
if (!shouldClose) {
if (_Stream==null) {
string mainLogFileRoot = GlobalLog.s_RootDirectory + "System.Net";
string mainLogFile = mainLogFileRoot;
for (int k=0; k<20; k++) {
if (k>0) {
mainLogFile = mainLogFileRoot + "." + k.ToString();
}
string fileName = mainLogFile + ".log";
if (!File.Exists(fileName)) {
try {
_Stream = new StreamWriter(fileName);
break;
}
catch (Exception exception) {
if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
throw;
}
if (exception is SecurityException || exception is UnauthorizedAccessException) {
// can't be CAS (we assert) this is an ACL issue
break;
}
}
}
}
if (_Stream==null) {
_Stream = StreamWriter.Null;
}
// write a header with information about the Process and the AppDomain
_Stream.Write("# MachineName: " + Environment.MachineName + "\r\n");
_Stream.Write("# ProcessName: " + Process.GetCurrentProcess().ProcessName + " (pid: " + Process.GetCurrentProcess().Id + ")\r\n");
_Stream.Write("# AppDomainId: " + AppDomain.CurrentDomain.Id + "\r\n");
_Stream.Write("# CurrentIdentity: " + WindowsIdentity.GetCurrent().Name + "\r\n");
_Stream.Write("# CommandLine: " + Environment.CommandLine + "\r\n");
_Stream.Write("# ClrVersion: " + Environment.Version + "\r\n");
_Stream.Write("# CreationDate: " + DateTime.Now.ToString("g") + "\r\n");
}
}
try {
if (_Logarray!=null) {
for (int i=0; i<_Logarray.Count; i++) {
_Stream.Write((string)_Logarray[i]);
_Stream.Write("\r\n");
}
if (_Logarray.Count > 0 && _Stream != null)
_Stream.Flush();
}
}
catch (Exception exception) {
if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) {
throw;
}
}
if (shouldClose && _Stream!=null) {
try {
_Stream.Close();
}
catch (ObjectDisposedException) { }
_Stream = null;
}
}
}
internal override void Flush() {
Flush(false);
}
internal override void Flush(bool close) {
lock (this) {
if (!GlobalLog.s_DumpToConsole) {
DumpArrayToFile(close);
_AddCount = 0;
}
}
}
private class ThreadInfoData {
public ThreadInfoData(string indent) {
Indent = indent;
NestingStack = new Stack();
}
public string Indent;
public Stack NestingStack;
};
string IndentString {
get {
string indent = " ";
Object obj = _ThreadNesting[Thread.CurrentThread.GetHashCode()];
if (!GlobalLog.s_DebugCallNesting) {
if (obj == null) {
_ThreadNesting[Thread.CurrentThread.GetHashCode()] = indent;
} else {
indent = (String) obj;
}
} else {
ThreadInfoData threadInfo = obj as ThreadInfoData;
if (threadInfo == null) {
threadInfo = new ThreadInfoData(indent);
_ThreadNesting[Thread.CurrentThread.GetHashCode()] = threadInfo;
}
indent = threadInfo.Indent;
}
return indent;
}
set {
Object obj = _ThreadNesting[Thread.CurrentThread.GetHashCode()];
if (obj == null) {
return;
}
if (!GlobalLog.s_DebugCallNesting) {
_ThreadNesting[Thread.CurrentThread.GetHashCode()] = value;
} else {
ThreadInfoData threadInfo = obj as ThreadInfoData;
if (threadInfo == null) {
threadInfo = new ThreadInfoData(value);
_ThreadNesting[Thread.CurrentThread.GetHashCode()] = threadInfo;
}
threadInfo.Indent = value;
}
}
}
[System.Diagnostics.Conditional("TRAVE")]
private void IncNestingCount() {
IndentString = IndentString + " ";
}
[System.Diagnostics.Conditional("TRAVE")]
private void DecNestingCount() {
string indent = IndentString;
if (indent.Length>1) {
try {
indent = indent.Substring(1);
}
catch {
indent = string.Empty;
}
}
if (indent.Length==0) {
indent = "< ";
}
IndentString = indent;
}
private string GetNestingString() {
return IndentString;
}
[System.Diagnostics.Conditional("TRAVE")]
private void ValidatePush(string name) {
if (GlobalLog.s_DebugCallNesting) {
Object obj = _ThreadNesting[Thread.CurrentThread.GetHashCode()];
ThreadInfoData threadInfo = obj as ThreadInfoData;
if (threadInfo == null) {
return;
}
threadInfo.NestingStack.Push(name);
}
}
[System.Diagnostics.Conditional("TRAVE")]
private void ValidatePop(string name) {
if (GlobalLog.s_DebugCallNesting) {
try {
Object obj = _ThreadNesting[Thread.CurrentThread.GetHashCode()];
ThreadInfoData threadInfo = obj as ThreadInfoData;
if (threadInfo == null) {
return;
}
if (threadInfo.NestingStack.Count == 0) {
PrintLine("++++====" + "Poped Empty Stack for :"+name);
}
string popedName = (string) threadInfo.NestingStack.Pop();
string [] parsedList = popedName.Split(new char [] {'(',')',' ','.',':',',','#'});
foreach (string element in parsedList) {
if (element != null && element.Length > 1 && name.IndexOf(element) != -1) {
return;
}
}
PrintLine("++++====" + "Expected:" + popedName + ": got :" + name + ": StackSize:"+threadInfo.NestingStack.Count);
// relevel the stack
while(threadInfo.NestingStack.Count>0) {
string popedName2 = (string) threadInfo.NestingStack.Pop();
string [] parsedList2 = popedName2.Split(new char [] {'(',')',' ','.',':',',','#'});
foreach (string element2 in parsedList2) {
if (element2 != null && element2.Length > 1 && name.IndexOf(element2) != -1) {
return;
}
}
}
}
catch {
PrintLine("++++====" + "ValidatePop failed for: "+name);
}
}
}
~LoggingObject() {
if(!_Finalized) {
_Finalized = true;
lock(this) {
DumpArray(true);
}
}
}
} // class LoggingObject
internal static class TraveHelper {
private static readonly string Hexizer = "0x{0:x}";
internal static string ToHex(object value) {
return String.Format(Hexizer, value);
}
}
#endif // TRAVE
#if TRAVE
internal class IntegerSwitch : BooleanSwitch {
public IntegerSwitch(string switchName, string switchDescription) : base(switchName, switchDescription) {
}
public new int Value {
get {
return base.SwitchSetting;
}
}
}
#endif
// class GlobalLog
} // namespace System.Net

View File

@ -0,0 +1,630 @@
// -----------------------------------------------------------------------
// <copyright file="SR.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace System
{
using System;
using System.Reflection;
using System.Globalization;
using System.Resources;
using System.Text;
using System.Threading;
using System.Security.Permissions;
using System.ComponentModel;
/// <summary>
/// AutoGenerated resource class. Usage:
/// string s = SR.GetString(SR.MyIdenfitier);
/// </summary>
internal sealed class SR
{
internal const string security_ExtendedProtection_NoOSSupport = "security_ExtendedProtection_NoOSSupport";
internal const string net_nonClsCompliantException = "net_nonClsCompliantException";
internal const string net_illegalConfigWith = "net_illegalConfigWith";
internal const string net_illegalConfigWithout = "net_illegalConfigWithout";
internal const string net_baddate = "net_baddate";
internal const string net_writestarted = "net_writestarted";
internal const string net_clsmall = "net_clsmall";
internal const string net_reqsubmitted = "net_reqsubmitted";
internal const string net_rspsubmitted = "net_rspsubmitted";
internal const string net_ftp_no_http_cmd = "net_ftp_no_http_cmd";
internal const string net_ftp_invalid_method_name = "net_ftp_invalid_method_name";
internal const string net_ftp_invalid_renameto = "net_ftp_invalid_renameto";
internal const string net_ftp_no_defaultcreds = "net_ftp_no_defaultcreds";
internal const string net_ftpnoresponse = "net_ftpnoresponse";
internal const string net_ftp_response_invalid_format = "net_ftp_response_invalid_format";
internal const string net_ftp_no_offsetforhttp = "net_ftp_no_offsetforhttp";
internal const string net_ftp_invalid_uri = "net_ftp_invalid_uri";
internal const string net_ftp_invalid_status_response = "net_ftp_invalid_status_response";
internal const string net_ftp_server_failed_passive = "net_ftp_server_failed_passive";
internal const string net_ftp_active_address_different = "net_ftp_active_address_different";
internal const string net_ftp_proxy_does_not_support_ssl = "net_ftp_proxy_does_not_support_ssl";
internal const string net_ftp_invalid_response_filename = "net_ftp_invalid_response_filename";
internal const string net_ftp_unsupported_method = "net_ftp_unsupported_method";
internal const string net_resubmitcanceled = "net_resubmitcanceled";
internal const string net_redirect_perm = "net_redirect_perm";
internal const string net_resubmitprotofailed = "net_resubmitprotofailed";
internal const string net_needchunked = "net_needchunked";
internal const string net_nochunked = "net_nochunked";
internal const string net_nochunkuploadonhttp10 = "net_nochunkuploadonhttp10";
internal const string net_connarg = "net_connarg";
internal const string net_no100 = "net_no100";
internal const string net_fromto = "net_fromto";
internal const string net_rangetoosmall = "net_rangetoosmall";
internal const string net_entitytoobig = "net_entitytoobig";
internal const string net_invalidversion = "net_invalidversion";
internal const string net_invalidstatus = "net_invalidstatus";
internal const string net_toosmall = "net_toosmall";
internal const string net_toolong = "net_toolong";
internal const string net_connclosed = "net_connclosed";
internal const string net_noseek = "net_noseek";
internal const string net_servererror = "net_servererror";
internal const string net_nouploadonget = "net_nouploadonget";
internal const string net_mutualauthfailed = "net_mutualauthfailed";
internal const string net_invasync = "net_invasync";
internal const string net_inasync = "net_inasync";
internal const string net_mustbeuri = "net_mustbeuri";
internal const string net_format_shexp = "net_format_shexp";
internal const string net_cannot_load_proxy_helper = "net_cannot_load_proxy_helper";
internal const string net_invalid_host = "net_invalid_host";
internal const string net_repcall = "net_repcall";
internal const string net_wrongversion = "net_wrongversion";
internal const string net_badmethod = "net_badmethod";
internal const string net_io_notenoughbyteswritten = "net_io_notenoughbyteswritten";
internal const string net_io_timeout_use_ge_zero = "net_io_timeout_use_ge_zero";
internal const string net_io_timeout_use_gt_zero = "net_io_timeout_use_gt_zero";
internal const string net_io_no_0timeouts = "net_io_no_0timeouts";
internal const string net_requestaborted = "net_requestaborted";
internal const string net_tooManyRedirections = "net_tooManyRedirections";
internal const string net_authmodulenotregistered = "net_authmodulenotregistered";
internal const string net_authschemenotregistered = "net_authschemenotregistered";
internal const string net_proxyschemenotsupported = "net_proxyschemenotsupported";
internal const string net_maxsrvpoints = "net_maxsrvpoints";
internal const string net_unknown_prefix = "net_unknown_prefix";
internal const string net_notconnected = "net_notconnected";
internal const string net_notstream = "net_notstream";
internal const string net_timeout = "net_timeout";
internal const string net_nocontentlengthonget = "net_nocontentlengthonget";
internal const string net_contentlengthmissing = "net_contentlengthmissing";
internal const string net_nonhttpproxynotallowed = "net_nonhttpproxynotallowed";
internal const string net_nottoken = "net_nottoken";
internal const string net_rangetype = "net_rangetype";
internal const string net_need_writebuffering = "net_need_writebuffering";
internal const string net_securitypackagesupport = "net_securitypackagesupport";
internal const string net_securityprotocolnotsupported = "net_securityprotocolnotsupported";
internal const string net_nodefaultcreds = "net_nodefaultcreds";
internal const string net_stopped = "net_stopped";
internal const string net_udpconnected = "net_udpconnected";
internal const string net_readonlystream = "net_readonlystream";
internal const string net_writeonlystream = "net_writeonlystream";
internal const string net_no_concurrent_io_allowed = "net_no_concurrent_io_allowed";
internal const string net_needmorethreads = "net_needmorethreads";
internal const string net_MethodNotImplementedException = "net_MethodNotImplementedException";
internal const string net_PropertyNotImplementedException = "net_PropertyNotImplementedException";
internal const string net_MethodNotSupportedException = "net_MethodNotSupportedException";
internal const string net_PropertyNotSupportedException = "net_PropertyNotSupportedException";
internal const string net_ProtocolNotSupportedException = "net_ProtocolNotSupportedException";
internal const string net_SelectModeNotSupportedException = "net_SelectModeNotSupportedException";
internal const string net_InvalidSocketHandle = "net_InvalidSocketHandle";
internal const string net_InvalidAddressFamily = "net_InvalidAddressFamily";
internal const string net_InvalidEndPointAddressFamily = "net_InvalidEndPointAddressFamily";
internal const string net_InvalidSocketAddressSize = "net_InvalidSocketAddressSize";
internal const string net_invalidAddressList = "net_invalidAddressList";
internal const string net_invalidPingBufferSize = "net_invalidPingBufferSize";
internal const string net_cant_perform_during_shutdown = "net_cant_perform_during_shutdown";
internal const string net_cant_create_environment = "net_cant_create_environment";
internal const string net_completed_result = "net_completed_result";
internal const string net_protocol_invalid_family = "net_protocol_invalid_family";
internal const string net_protocol_invalid_multicast_family = "net_protocol_invalid_multicast_family";
internal const string net_empty_osinstalltype = "net_empty_osinstalltype";
internal const string net_unknown_osinstalltype = "net_unknown_osinstalltype";
internal const string net_cant_determine_osinstalltype = "net_cant_determine_osinstalltype";
internal const string net_osinstalltype = "net_osinstalltype";
internal const string net_entire_body_not_written = "net_entire_body_not_written";
internal const string net_must_provide_request_body = "net_must_provide_request_body";
internal const string net_ssp_dont_support_cbt = "net_ssp_dont_support_cbt";
internal const string net_sockets_zerolist = "net_sockets_zerolist";
internal const string net_sockets_blocking = "net_sockets_blocking";
internal const string net_sockets_useblocking = "net_sockets_useblocking";
internal const string net_sockets_select = "net_sockets_select";
internal const string net_sockets_toolarge_select = "net_sockets_toolarge_select";
internal const string net_sockets_empty_select = "net_sockets_empty_select";
internal const string net_sockets_mustbind = "net_sockets_mustbind";
internal const string net_sockets_mustlisten = "net_sockets_mustlisten";
internal const string net_sockets_mustnotlisten = "net_sockets_mustnotlisten";
internal const string net_sockets_mustnotbebound = "net_sockets_mustnotbebound";
internal const string net_sockets_namedmustnotbebound = "net_sockets_namedmustnotbebound";
internal const string net_sockets_invalid_socketinformation = "net_sockets_invalid_socketinformation";
internal const string net_sockets_invalid_ipaddress_length = "net_sockets_invalid_ipaddress_length";
internal const string net_sockets_invalid_optionValue = "net_sockets_invalid_optionValue";
internal const string net_sockets_invalid_optionValue_all = "net_sockets_invalid_optionValue_all";
internal const string net_sockets_invalid_dnsendpoint = "net_sockets_invalid_dnsendpoint";
internal const string net_sockets_disconnectedConnect = "net_sockets_disconnectedConnect";
internal const string net_sockets_disconnectedAccept = "net_sockets_disconnectedAccept";
internal const string net_tcplistener_mustbestopped = "net_tcplistener_mustbestopped";
internal const string net_sockets_no_duplicate_async = "net_sockets_no_duplicate_async";
internal const string net_socketopinprogress = "net_socketopinprogress";
internal const string net_buffercounttoosmall = "net_buffercounttoosmall";
internal const string net_multibuffernotsupported = "net_multibuffernotsupported";
internal const string net_ambiguousbuffers = "net_ambiguousbuffers";
internal const string net_sockets_ipv6only = "net_sockets_ipv6only";
internal const string net_perfcounter_initialized_success = "net_perfcounter_initialized_success";
internal const string net_perfcounter_initialized_error = "net_perfcounter_initialized_error";
internal const string net_perfcounter_nocategory = "net_perfcounter_nocategory";
internal const string net_perfcounter_initialization_started = "net_perfcounter_initialization_started";
internal const string net_perfcounter_cant_queue_workitem = "net_perfcounter_cant_queue_workitem";
internal const string net_config_proxy = "net_config_proxy";
internal const string net_config_proxy_module_not_public = "net_config_proxy_module_not_public";
internal const string net_config_authenticationmodules = "net_config_authenticationmodules";
internal const string net_config_webrequestmodules = "net_config_webrequestmodules";
internal const string net_config_requestcaching = "net_config_requestcaching";
internal const string net_config_section_permission = "net_config_section_permission";
internal const string net_config_element_permission = "net_config_element_permission";
internal const string net_config_property_permission = "net_config_property_permission";
internal const string net_WebResponseParseError_InvalidHeaderName = "net_WebResponseParseError_InvalidHeaderName";
internal const string net_WebResponseParseError_InvalidContentLength = "net_WebResponseParseError_InvalidContentLength";
internal const string net_WebResponseParseError_IncompleteHeaderLine = "net_WebResponseParseError_IncompleteHeaderLine";
internal const string net_WebResponseParseError_CrLfError = "net_WebResponseParseError_CrLfError";
internal const string net_WebResponseParseError_InvalidChunkFormat = "net_WebResponseParseError_InvalidChunkFormat";
internal const string net_WebResponseParseError_UnexpectedServerResponse = "net_WebResponseParseError_UnexpectedServerResponse";
internal const string net_webstatus_Success = "net_webstatus_Success";
internal const string net_webstatus_NameResolutionFailure = "net_webstatus_NameResolutionFailure";
internal const string net_webstatus_ConnectFailure = "net_webstatus_ConnectFailure";
internal const string net_webstatus_ReceiveFailure = "net_webstatus_ReceiveFailure";
internal const string net_webstatus_SendFailure = "net_webstatus_SendFailure";
internal const string net_webstatus_PipelineFailure = "net_webstatus_PipelineFailure";
internal const string net_webstatus_RequestCanceled = "net_webstatus_RequestCanceled";
internal const string net_webstatus_ConnectionClosed = "net_webstatus_ConnectionClosed";
internal const string net_webstatus_TrustFailure = "net_webstatus_TrustFailure";
internal const string net_webstatus_SecureChannelFailure = "net_webstatus_SecureChannelFailure";
internal const string net_webstatus_ServerProtocolViolation = "net_webstatus_ServerProtocolViolation";
internal const string net_webstatus_KeepAliveFailure = "net_webstatus_KeepAliveFailure";
internal const string net_webstatus_ProxyNameResolutionFailure = "net_webstatus_ProxyNameResolutionFailure";
internal const string net_webstatus_MessageLengthLimitExceeded = "net_webstatus_MessageLengthLimitExceeded";
internal const string net_webstatus_CacheEntryNotFound = "net_webstatus_CacheEntryNotFound";
internal const string net_webstatus_RequestProhibitedByCachePolicy = "net_webstatus_RequestProhibitedByCachePolicy";
internal const string net_webstatus_Timeout = "net_webstatus_Timeout";
internal const string net_webstatus_RequestProhibitedByProxy = "net_webstatus_RequestProhibitedByProxy";
internal const string net_InvalidStatusCode = "net_InvalidStatusCode";
internal const string net_ftpstatuscode_ServiceNotAvailable = "net_ftpstatuscode_ServiceNotAvailable";
internal const string net_ftpstatuscode_CantOpenData = "net_ftpstatuscode_CantOpenData";
internal const string net_ftpstatuscode_ConnectionClosed = "net_ftpstatuscode_ConnectionClosed";
internal const string net_ftpstatuscode_ActionNotTakenFileUnavailableOrBusy = "net_ftpstatuscode_ActionNotTakenFileUnavailableOrBusy";
internal const string net_ftpstatuscode_ActionAbortedLocalProcessingError = "net_ftpstatuscode_ActionAbortedLocalProcessingError";
internal const string net_ftpstatuscode_ActionNotTakenInsufficentSpace = "net_ftpstatuscode_ActionNotTakenInsufficentSpace";
internal const string net_ftpstatuscode_CommandSyntaxError = "net_ftpstatuscode_CommandSyntaxError";
internal const string net_ftpstatuscode_ArgumentSyntaxError = "net_ftpstatuscode_ArgumentSyntaxError";
internal const string net_ftpstatuscode_CommandNotImplemented = "net_ftpstatuscode_CommandNotImplemented";
internal const string net_ftpstatuscode_BadCommandSequence = "net_ftpstatuscode_BadCommandSequence";
internal const string net_ftpstatuscode_NotLoggedIn = "net_ftpstatuscode_NotLoggedIn";
internal const string net_ftpstatuscode_AccountNeeded = "net_ftpstatuscode_AccountNeeded";
internal const string net_ftpstatuscode_ActionNotTakenFileUnavailable = "net_ftpstatuscode_ActionNotTakenFileUnavailable";
internal const string net_ftpstatuscode_ActionAbortedUnknownPageType = "net_ftpstatuscode_ActionAbortedUnknownPageType";
internal const string net_ftpstatuscode_FileActionAborted = "net_ftpstatuscode_FileActionAborted";
internal const string net_ftpstatuscode_ActionNotTakenFilenameNotAllowed = "net_ftpstatuscode_ActionNotTakenFilenameNotAllowed";
internal const string net_httpstatuscode_NoContent = "net_httpstatuscode_NoContent";
internal const string net_httpstatuscode_NonAuthoritativeInformation = "net_httpstatuscode_NonAuthoritativeInformation";
internal const string net_httpstatuscode_ResetContent = "net_httpstatuscode_ResetContent";
internal const string net_httpstatuscode_PartialContent = "net_httpstatuscode_PartialContent";
internal const string net_httpstatuscode_MultipleChoices = "net_httpstatuscode_MultipleChoices";
internal const string net_httpstatuscode_Ambiguous = "net_httpstatuscode_Ambiguous";
internal const string net_httpstatuscode_MovedPermanently = "net_httpstatuscode_MovedPermanently";
internal const string net_httpstatuscode_Moved = "net_httpstatuscode_Moved";
internal const string net_httpstatuscode_Found = "net_httpstatuscode_Found";
internal const string net_httpstatuscode_Redirect = "net_httpstatuscode_Redirect";
internal const string net_httpstatuscode_SeeOther = "net_httpstatuscode_SeeOther";
internal const string net_httpstatuscode_RedirectMethod = "net_httpstatuscode_RedirectMethod";
internal const string net_httpstatuscode_NotModified = "net_httpstatuscode_NotModified";
internal const string net_httpstatuscode_UseProxy = "net_httpstatuscode_UseProxy";
internal const string net_httpstatuscode_TemporaryRedirect = "net_httpstatuscode_TemporaryRedirect";
internal const string net_httpstatuscode_RedirectKeepVerb = "net_httpstatuscode_RedirectKeepVerb";
internal const string net_httpstatuscode_BadRequest = "net_httpstatuscode_BadRequest";
internal const string net_httpstatuscode_Unauthorized = "net_httpstatuscode_Unauthorized";
internal const string net_httpstatuscode_PaymentRequired = "net_httpstatuscode_PaymentRequired";
internal const string net_httpstatuscode_Forbidden = "net_httpstatuscode_Forbidden";
internal const string net_httpstatuscode_NotFound = "net_httpstatuscode_NotFound";
internal const string net_httpstatuscode_MethodNotAllowed = "net_httpstatuscode_MethodNotAllowed";
internal const string net_httpstatuscode_NotAcceptable = "net_httpstatuscode_NotAcceptable";
internal const string net_httpstatuscode_ProxyAuthenticationRequired = "net_httpstatuscode_ProxyAuthenticationRequired";
internal const string net_httpstatuscode_RequestTimeout = "net_httpstatuscode_RequestTimeout";
internal const string net_httpstatuscode_Conflict = "net_httpstatuscode_Conflict";
internal const string net_httpstatuscode_Gone = "net_httpstatuscode_Gone";
internal const string net_httpstatuscode_LengthRequired = "net_httpstatuscode_LengthRequired";
internal const string net_httpstatuscode_InternalServerError = "net_httpstatuscode_InternalServerError";
internal const string net_httpstatuscode_NotImplemented = "net_httpstatuscode_NotImplemented";
internal const string net_httpstatuscode_BadGateway = "net_httpstatuscode_BadGateway";
internal const string net_httpstatuscode_ServiceUnavailable = "net_httpstatuscode_ServiceUnavailable";
internal const string net_httpstatuscode_GatewayTimeout = "net_httpstatuscode_GatewayTimeout";
internal const string net_httpstatuscode_HttpVersionNotSupported = "net_httpstatuscode_HttpVersionNotSupported";
internal const string net_uri_BadScheme = "net_uri_BadScheme";
internal const string net_uri_BadFormat = "net_uri_BadFormat";
internal const string net_uri_BadUserPassword = "net_uri_BadUserPassword";
internal const string net_uri_BadHostName = "net_uri_BadHostName";
internal const string net_uri_BadAuthority = "net_uri_BadAuthority";
internal const string net_uri_BadAuthorityTerminator = "net_uri_BadAuthorityTerminator";
internal const string net_uri_EmptyUri = "net_uri_EmptyUri";
internal const string net_uri_BadString = "net_uri_BadString";
internal const string net_uri_MustRootedPath = "net_uri_MustRootedPath";
internal const string net_uri_BadPort = "net_uri_BadPort";
internal const string net_uri_SizeLimit = "net_uri_SizeLimit";
internal const string net_uri_SchemeLimit = "net_uri_SchemeLimit";
internal const string net_uri_NotAbsolute = "net_uri_NotAbsolute";
internal const string net_uri_PortOutOfRange = "net_uri_PortOutOfRange";
internal const string net_uri_UserDrivenParsing = "net_uri_UserDrivenParsing";
internal const string net_uri_AlreadyRegistered = "net_uri_AlreadyRegistered";
internal const string net_uri_NeedFreshParser = "net_uri_NeedFreshParser";
internal const string net_uri_CannotCreateRelative = "net_uri_CannotCreateRelative";
internal const string net_uri_InvalidUriKind = "net_uri_InvalidUriKind";
internal const string net_uri_BadUnicodeHostForIdn = "net_uri_BadUnicodeHostForIdn";
internal const string net_uri_GenericAuthorityNotDnsSafe = "net_uri_GenericAuthorityNotDnsSafe";
internal const string net_uri_NotJustSerialization = "net_uri_NotJustSerialization";
internal const string net_emptystringset = "net_emptystringset";
internal const string net_emptystringcall = "net_emptystringcall";
internal const string net_headers_req = "net_headers_req";
internal const string net_headers_rsp = "net_headers_rsp";
internal const string net_headers_toolong = "net_headers_toolong";
internal const string net_WebHeaderInvalidControlChars = "net_WebHeaderInvalidControlChars";
internal const string net_WebHeaderInvalidCRLFChars = "net_WebHeaderInvalidCRLFChars";
internal const string net_WebHeaderInvalidHeaderChars = "net_WebHeaderInvalidHeaderChars";
internal const string net_WebHeaderInvalidNonAsciiChars = "net_WebHeaderInvalidNonAsciiChars";
internal const string net_WebHeaderMissingColon = "net_WebHeaderMissingColon";
internal const string net_headerrestrict = "net_headerrestrict";
internal const string net_io_completionportwasbound = "net_io_completionportwasbound";
internal const string net_io_writefailure = "net_io_writefailure";
internal const string net_io_readfailure = "net_io_readfailure";
internal const string net_io_connectionclosed = "net_io_connectionclosed";
internal const string net_io_transportfailure = "net_io_transportfailure";
internal const string net_io_internal_bind = "net_io_internal_bind";
internal const string net_io_invalidasyncresult = "net_io_invalidasyncresult";
internal const string net_io_invalidnestedcall = "net_io_invalidnestedcall";
internal const string net_io_invalidendcall = "net_io_invalidendcall";
internal const string net_io_must_be_rw_stream = "net_io_must_be_rw_stream";
internal const string net_io_header_id = "net_io_header_id";
internal const string net_io_out_range = "net_io_out_range";
internal const string net_io_encrypt = "net_io_encrypt";
internal const string net_io_decrypt = "net_io_decrypt";
internal const string net_io_read = "net_io_read";
internal const string net_io_write = "net_io_write";
internal const string net_io_eof = "net_io_eof";
internal const string net_io_async_result = "net_io_async_result";
internal const string net_listener_mustcall = "net_listener_mustcall";
internal const string net_listener_mustcompletecall = "net_listener_mustcompletecall";
internal const string net_listener_callinprogress = "net_listener_callinprogress";
internal const string net_listener_scheme = "net_listener_scheme";
internal const string net_listener_host = "net_listener_host";
internal const string net_listener_slash = "net_listener_slash";
internal const string net_listener_repcall = "net_listener_repcall";
internal const string net_listener_invalid_cbt_type = "net_listener_invalid_cbt_type";
internal const string net_listener_no_spns = "net_listener_no_spns";
internal const string net_listener_cannot_set_custom_cbt = "net_listener_cannot_set_custom_cbt";
internal const string net_listener_cbt_not_supported = "net_listener_cbt_not_supported";
internal const string net_listener_detach_error = "net_listener_detach_error";
internal const string net_listener_close_urlgroup_error = "net_listener_close_urlgroup_error";
internal const string net_tls_version = "net_tls_version";
internal const string net_perm_target = "net_perm_target";
internal const string net_perm_both_regex = "net_perm_both_regex";
internal const string net_perm_none = "net_perm_none";
internal const string net_perm_attrib_count = "net_perm_attrib_count";
internal const string net_perm_invalid_val = "net_perm_invalid_val";
internal const string net_perm_attrib_multi = "net_perm_attrib_multi";
internal const string net_perm_epname = "net_perm_epname";
internal const string net_perm_invalid_val_in_element = "net_perm_invalid_val_in_element";
internal const string net_invalid_ip_addr = "net_invalid_ip_addr";
internal const string dns_bad_ip_address = "dns_bad_ip_address";
internal const string net_bad_mac_address = "net_bad_mac_address";
internal const string net_ping = "net_ping";
internal const string net_bad_ip_address_prefix = "net_bad_ip_address_prefix";
internal const string net_max_ip_address_list_length_exceeded = "net_max_ip_address_list_length_exceeded";
internal const string net_ipv4_not_installed = "net_ipv4_not_installed";
internal const string net_ipv6_not_installed = "net_ipv6_not_installed";
internal const string net_webclient = "net_webclient";
internal const string net_webclient_ContentType = "net_webclient_ContentType";
internal const string net_webclient_Multipart = "net_webclient_Multipart";
internal const string net_webclient_no_concurrent_io_allowed = "net_webclient_no_concurrent_io_allowed";
internal const string net_webclient_invalid_baseaddress = "net_webclient_invalid_baseaddress";
internal const string net_container_add_cookie = "net_container_add_cookie";
internal const string net_cookie_invalid = "net_cookie_invalid";
internal const string net_cookie_size = "net_cookie_size";
internal const string net_cookie_parse_header = "net_cookie_parse_header";
internal const string net_cookie_attribute = "net_cookie_attribute";
internal const string net_cookie_format = "net_cookie_format";
internal const string net_cookie_exists = "net_cookie_exists";
internal const string net_cookie_capacity_range = "net_cookie_capacity_range";
internal const string net_set_token = "net_set_token";
internal const string net_revert_token = "net_revert_token";
internal const string net_ssl_io_async_context = "net_ssl_io_async_context";
internal const string net_ssl_io_encrypt = "net_ssl_io_encrypt";
internal const string net_ssl_io_decrypt = "net_ssl_io_decrypt";
internal const string net_ssl_io_context_expired = "net_ssl_io_context_expired";
internal const string net_ssl_io_handshake_start = "net_ssl_io_handshake_start";
internal const string net_ssl_io_handshake = "net_ssl_io_handshake";
internal const string net_ssl_io_frame = "net_ssl_io_frame";
internal const string net_ssl_io_corrupted = "net_ssl_io_corrupted";
internal const string net_ssl_io_cert_validation = "net_ssl_io_cert_validation";
internal const string net_ssl_io_invalid_end_call = "net_ssl_io_invalid_end_call";
internal const string net_ssl_io_invalid_begin_call = "net_ssl_io_invalid_begin_call";
internal const string net_ssl_io_no_server_cert = "net_ssl_io_no_server_cert";
internal const string net_auth_bad_client_creds = "net_auth_bad_client_creds";
internal const string net_auth_bad_client_creds_or_target_mismatch = "net_auth_bad_client_creds_or_target_mismatch";
internal const string net_auth_context_expectation = "net_auth_context_expectation";
internal const string net_auth_context_expectation_remote = "net_auth_context_expectation_remote";
internal const string net_auth_supported_impl_levels = "net_auth_supported_impl_levels";
internal const string net_auth_no_anonymous_support = "net_auth_no_anonymous_support";
internal const string net_auth_reauth = "net_auth_reauth";
internal const string net_auth_noauth = "net_auth_noauth";
internal const string net_auth_client_server = "net_auth_client_server";
internal const string net_auth_noencryption = "net_auth_noencryption";
internal const string net_auth_SSPI = "net_auth_SSPI";
internal const string net_auth_failure = "net_auth_failure";
internal const string net_auth_eof = "net_auth_eof";
internal const string net_auth_alert = "net_auth_alert";
internal const string net_auth_ignored_reauth = "net_auth_ignored_reauth";
internal const string net_auth_empty_read = "net_auth_empty_read";
internal const string net_auth_message_not_encrypted = "net_auth_message_not_encrypted";
internal const string net_auth_must_specify_extended_protection_scheme = "net_auth_must_specify_extended_protection_scheme";
internal const string net_frame_size = "net_frame_size";
internal const string net_frame_read_io = "net_frame_read_io";
internal const string net_frame_read_size = "net_frame_read_size";
internal const string net_frame_max_size = "net_frame_max_size";
internal const string net_jscript_load = "net_jscript_load";
internal const string net_proxy_not_gmt = "net_proxy_not_gmt";
internal const string net_proxy_invalid_dayofweek = "net_proxy_invalid_dayofweek";
internal const string net_proxy_invalid_url_format = "net_proxy_invalid_url_format";
internal const string net_param_not_string = "net_param_not_string";
internal const string net_value_cannot_be_negative = "net_value_cannot_be_negative";
internal const string net_invalid_offset = "net_invalid_offset";
internal const string net_offset_plus_count = "net_offset_plus_count";
internal const string net_cannot_be_false = "net_cannot_be_false";
internal const string net_invalid_enum = "net_invalid_enum";
internal const string net_listener_already = "net_listener_already";
internal const string net_cache_shadowstream_not_writable = "net_cache_shadowstream_not_writable";
internal const string net_cache_validator_fail = "net_cache_validator_fail";
internal const string net_cache_access_denied = "net_cache_access_denied";
internal const string net_cache_validator_result = "net_cache_validator_result";
internal const string net_cache_retrieve_failure = "net_cache_retrieve_failure";
internal const string net_cache_not_supported_body = "net_cache_not_supported_body";
internal const string net_cache_not_supported_command = "net_cache_not_supported_command";
internal const string net_cache_not_accept_response = "net_cache_not_accept_response";
internal const string net_cache_method_failed = "net_cache_method_failed";
internal const string net_cache_key_failed = "net_cache_key_failed";
internal const string net_cache_no_stream = "net_cache_no_stream";
internal const string net_cache_unsupported_partial_stream = "net_cache_unsupported_partial_stream";
internal const string net_cache_not_configured = "net_cache_not_configured";
internal const string net_cache_non_seekable_stream_not_supported = "net_cache_non_seekable_stream_not_supported";
internal const string net_invalid_cast = "net_invalid_cast";
internal const string net_collection_readonly = "net_collection_readonly";
internal const string net_not_ipermission = "net_not_ipermission";
internal const string net_no_classname = "net_no_classname";
internal const string net_no_typename = "net_no_typename";
internal const string net_array_too_small = "net_array_too_small";
internal const string net_servicePointAddressNotSupportedInHostMode = "net_servicePointAddressNotSupportedInHostMode";
internal const string net_Websockets_AlreadyOneOutstandingOperation = "net_Websockets_AlreadyOneOutstandingOperation";
internal const string net_Websockets_WebSocketBaseFaulted = "net_Websockets_WebSocketBaseFaulted";
internal const string net_WebSockets_NativeSendResponseHeaders = "net_WebSockets_NativeSendResponseHeaders";
internal const string net_WebSockets_Generic = "net_WebSockets_Generic";
internal const string net_WebSockets_NotAWebSocket_Generic = "net_WebSockets_NotAWebSocket_Generic";
internal const string net_WebSockets_UnsupportedWebSocketVersion_Generic = "net_WebSockets_UnsupportedWebSocketVersion_Generic";
internal const string net_WebSockets_HeaderError_Generic = "net_WebSockets_HeaderError_Generic";
internal const string net_WebSockets_UnsupportedProtocol_Generic = "net_WebSockets_UnsupportedProtocol_Generic";
internal const string net_WebSockets_UnsupportedPlatform = "net_WebSockets_UnsupportedPlatform";
internal const string net_WebSockets_AcceptNotAWebSocket = "net_WebSockets_AcceptNotAWebSocket";
internal const string net_WebSockets_AcceptUnsupportedWebSocketVersion = "net_WebSockets_AcceptUnsupportedWebSocketVersion";
internal const string net_WebSockets_AcceptHeaderNotFound = "net_WebSockets_AcceptHeaderNotFound";
internal const string net_WebSockets_AcceptUnsupportedProtocol = "net_WebSockets_AcceptUnsupportedProtocol";
internal const string net_WebSockets_ClientAcceptingNoProtocols = "net_WebSockets_ClientAcceptingNoProtocols";
internal const string net_WebSockets_ClientSecWebSocketProtocolsBlank = "net_WebSockets_ClientSecWebSocketProtocolsBlank";
internal const string net_WebSockets_ArgumentOutOfRange_TooSmall = "net_WebSockets_ArgumentOutOfRange_TooSmall";
internal const string net_WebSockets_ArgumentOutOfRange_InternalBuffer = "net_WebSockets_ArgumentOutOfRange_InternalBuffer";
internal const string net_WebSockets_ArgumentOutOfRange_TooBig = "net_WebSockets_ArgumentOutOfRange_TooBig";
internal const string net_WebSockets_InvalidState_Generic = "net_WebSockets_InvalidState_Generic";
internal const string net_WebSockets_InvalidState_ClosedOrAborted = "net_WebSockets_InvalidState_ClosedOrAborted";
internal const string net_WebSockets_InvalidState = "net_WebSockets_InvalidState";
internal const string net_WebSockets_ReceiveAsyncDisallowedAfterCloseAsync = "net_WebSockets_ReceiveAsyncDisallowedAfterCloseAsync";
internal const string net_WebSockets_InvalidMessageType = "net_WebSockets_InvalidMessageType";
internal const string net_WebSockets_InvalidBufferType = "net_WebSockets_InvalidBufferType";
internal const string net_WebSockets_InvalidMessageType_Generic = "net_WebSockets_InvalidMessageType_Generic";
internal const string net_WebSockets_Argument_InvalidMessageType = "net_WebSockets_Argument_InvalidMessageType";
internal const string net_WebSockets_ConnectionClosedPrematurely_Generic = "net_WebSockets_ConnectionClosedPrematurely_Generic";
internal const string net_WebSockets_InvalidCharInProtocolString = "net_WebSockets_InvalidCharInProtocolString";
internal const string net_WebSockets_InvalidEmptySubProtocol = "net_WebSockets_InvalidEmptySubProtocol";
internal const string net_WebSockets_ReasonNotNull = "net_WebSockets_ReasonNotNull";
internal const string net_WebSockets_InvalidCloseStatusCode = "net_WebSockets_InvalidCloseStatusCode";
internal const string net_WebSockets_InvalidCloseStatusDescription = "net_WebSockets_InvalidCloseStatusDescription";
internal const string net_WebSockets_Scheme = "net_WebSockets_Scheme";
internal const string net_WebSockets_AlreadyStarted = "net_WebSockets_AlreadyStarted";
internal const string net_WebSockets_Connect101Expected = "net_WebSockets_Connect101Expected";
internal const string net_WebSockets_InvalidResponseHeader = "net_WebSockets_InvalidResponseHeader";
internal const string net_WebSockets_NotConnected = "net_WebSockets_NotConnected";
internal const string net_WebSockets_InvalidRegistration = "net_WebSockets_InvalidRegistration";
internal const string net_WebSockets_NoDuplicateProtocol = "net_WebSockets_NoDuplicateProtocol";
internal const string net_log_exception = "net_log_exception";
internal const string net_log_listener_delegate_exception = "net_log_listener_delegate_exception";
internal const string net_log_listener_unsupported_authentication_scheme = "net_log_listener_unsupported_authentication_scheme";
internal const string net_log_listener_unmatched_authentication_scheme = "net_log_listener_unmatched_authentication_scheme";
internal const string net_log_listener_create_valid_identity_failed = "net_log_listener_create_valid_identity_failed";
internal const string net_log_listener_httpsys_registry_null = "net_log_listener_httpsys_registry_null";
internal const string net_log_listener_httpsys_registry_error = "net_log_listener_httpsys_registry_error";
internal const string net_log_listener_cant_convert_raw_path = "net_log_listener_cant_convert_raw_path";
internal const string net_log_listener_cant_convert_percent_value = "net_log_listener_cant_convert_percent_value";
internal const string net_log_listener_cant_convert_bytes = "net_log_listener_cant_convert_bytes";
internal const string net_log_listener_cant_convert_to_utf8 = "net_log_listener_cant_convert_to_utf8";
internal const string net_log_listener_cant_create_uri = "net_log_listener_cant_create_uri";
internal const string net_log_listener_no_cbt_disabled = "net_log_listener_no_cbt_disabled";
internal const string net_log_listener_no_cbt_http = "net_log_listener_no_cbt_http";
internal const string net_log_listener_no_cbt_platform = "net_log_listener_no_cbt_platform";
internal const string net_log_listener_no_cbt_trustedproxy = "net_log_listener_no_cbt_trustedproxy";
internal const string net_log_listener_cbt = "net_log_listener_cbt";
internal const string net_log_listener_no_spn_kerberos = "net_log_listener_no_spn_kerberos";
internal const string net_log_listener_no_spn_disabled = "net_log_listener_no_spn_disabled";
internal const string net_log_listener_no_spn_cbt = "net_log_listener_no_spn_cbt";
internal const string net_log_listener_no_spn_platform = "net_log_listener_no_spn_platform";
internal const string net_log_listener_no_spn_whensupported = "net_log_listener_no_spn_whensupported";
internal const string net_log_listener_no_spn_loopback = "net_log_listener_no_spn_loopback";
internal const string net_log_listener_spn = "net_log_listener_spn";
internal const string net_log_listener_spn_passed = "net_log_listener_spn_passed";
internal const string net_log_listener_spn_failed = "net_log_listener_spn_failed";
internal const string net_log_listener_spn_failed_always = "net_log_listener_spn_failed_always";
internal const string net_log_listener_spn_failed_empty = "net_log_listener_spn_failed_empty";
internal const string net_log_listener_spn_failed_dump = "net_log_listener_spn_failed_dump";
internal const string net_log_listener_spn_add = "net_log_listener_spn_add";
internal const string net_log_listener_spn_not_add = "net_log_listener_spn_not_add";
internal const string net_log_listener_spn_remove = "net_log_listener_spn_remove";
internal const string net_log_listener_spn_not_remove = "net_log_listener_spn_not_remove";
internal const string net_log_sspi_enumerating_security_packages = "net_log_sspi_enumerating_security_packages";
internal const string net_log_sspi_security_package_not_found = "net_log_sspi_security_package_not_found";
internal const string net_log_sspi_security_context_input_buffer = "net_log_sspi_security_context_input_buffer";
internal const string net_log_sspi_security_context_input_buffers = "net_log_sspi_security_context_input_buffers";
internal const string net_log_sspi_selected_cipher_suite = "net_log_sspi_selected_cipher_suite";
internal const string net_log_remote_certificate = "net_log_remote_certificate";
internal const string net_log_locating_private_key_for_certificate = "net_log_locating_private_key_for_certificate";
internal const string net_log_cert_is_of_type_2 = "net_log_cert_is_of_type_2";
internal const string net_log_found_cert_in_store = "net_log_found_cert_in_store";
internal const string net_log_did_not_find_cert_in_store = "net_log_did_not_find_cert_in_store";
internal const string net_log_open_store_failed = "net_log_open_store_failed";
internal const string net_log_got_certificate_from_delegate = "net_log_got_certificate_from_delegate";
internal const string net_log_no_delegate_and_have_no_client_cert = "net_log_no_delegate_and_have_no_client_cert";
internal const string net_log_no_delegate_but_have_client_cert = "net_log_no_delegate_but_have_client_cert";
internal const string net_log_attempting_restart_using_cert = "net_log_attempting_restart_using_cert";
internal const string net_log_no_issuers_try_all_certs = "net_log_no_issuers_try_all_certs";
internal const string net_log_server_issuers_look_for_matching_certs = "net_log_server_issuers_look_for_matching_certs";
internal const string net_log_selected_cert = "net_log_selected_cert";
internal const string net_log_n_certs_after_filtering = "net_log_n_certs_after_filtering";
internal const string net_log_finding_matching_certs = "net_log_finding_matching_certs";
internal const string net_log_using_cached_credential = "net_log_using_cached_credential";
internal const string net_log_remote_cert_user_declared_valid = "net_log_remote_cert_user_declared_valid";
internal const string net_log_remote_cert_user_declared_invalid = "net_log_remote_cert_user_declared_invalid";
internal const string net_log_remote_cert_has_no_errors = "net_log_remote_cert_has_no_errors";
internal const string net_log_remote_cert_has_errors = "net_log_remote_cert_has_errors";
internal const string net_log_remote_cert_not_available = "net_log_remote_cert_not_available";
internal const string net_log_remote_cert_name_mismatch = "net_log_remote_cert_name_mismatch";
internal const string net_log_proxy_autodetect_script_location_parse_error = "net_log_proxy_autodetect_script_location_parse_error";
internal const string net_log_proxy_autodetect_failed = "net_log_proxy_autodetect_failed";
internal const string net_log_proxy_script_execution_error = "net_log_proxy_script_execution_error";
internal const string net_log_proxy_script_download_compile_error = "net_log_proxy_script_download_compile_error";
internal const string net_log_proxy_system_setting_update = "net_log_proxy_system_setting_update";
internal const string net_log_proxy_update_due_to_ip_config_change = "net_log_proxy_update_due_to_ip_config_change";
internal const string net_log_proxy_called_with_null_parameter = "net_log_proxy_called_with_null_parameter";
internal const string net_log_proxy_called_with_invalid_parameter = "net_log_proxy_called_with_invalid_parameter";
internal const string net_log_proxy_ras_supported = "net_log_proxy_ras_supported";
internal const string net_log_proxy_ras_notsupported_exception = "net_log_proxy_ras_notsupported_exception";
internal const string net_log_proxy_winhttp_cant_open_session = "net_log_proxy_winhttp_cant_open_session";
internal const string net_log_proxy_winhttp_getproxy_failed = "net_log_proxy_winhttp_getproxy_failed";
internal const string net_log_proxy_winhttp_timeout_error = "net_log_proxy_winhttp_timeout_error";
internal const string net_log_digest_hash_algorithm_not_supported = "net_log_digest_hash_algorithm_not_supported";
internal const string net_log_digest_qop_not_supported = "net_log_digest_qop_not_supported";
internal const string net_log_digest_requires_nonce = "net_log_digest_requires_nonce";
internal const string net_log_auth_invalid_challenge = "net_log_auth_invalid_challenge";
internal const string net_log_unknown = "net_log_unknown";
internal const string net_log_operation_returned_something = "net_log_operation_returned_something";
internal const string net_log_operation_failed_with_error = "net_log_operation_failed_with_error";
internal const string net_log_buffered_n_bytes = "net_log_buffered_n_bytes";
internal const string net_log_method_equal = "net_log_method_equal";
internal const string net_log_releasing_connection = "net_log_releasing_connection";
internal const string net_log_unexpected_exception = "net_log_unexpected_exception";
internal const string net_log_server_response_error_code = "net_log_server_response_error_code";
internal const string net_log_resubmitting_request = "net_log_resubmitting_request";
internal const string net_log_retrieving_localhost_exception = "net_log_retrieving_localhost_exception";
internal const string net_log_resolved_servicepoint_may_not_be_remote_server = "net_log_resolved_servicepoint_may_not_be_remote_server";
internal const string net_log_closed_idle = "net_log_closed_idle";
internal const string net_log_received_status_line = "net_log_received_status_line";
internal const string net_log_sending_headers = "net_log_sending_headers";
internal const string net_log_received_headers = "net_log_received_headers";
internal const string net_log_shell_expression_pattern_format_warning = "net_log_shell_expression_pattern_format_warning";
internal const string net_log_exception_in_callback = "net_log_exception_in_callback";
internal const string net_log_sending_command = "net_log_sending_command";
internal const string net_log_received_response = "net_log_received_response";
internal const string net_log_socket_connected = "net_log_socket_connected";
internal const string net_log_socket_accepted = "net_log_socket_accepted";
internal const string net_log_socket_not_logged_file = "net_log_socket_not_logged_file";
internal const string net_log_socket_connect_dnsendpoint = "net_log_socket_connect_dnsendpoint";
internal const string SSPIInvalidHandleType = "SSPIInvalidHandleType";
private static SR loader = null;
private ResourceManager resources;
internal SR()
{
resources = new System.Resources.ResourceManager("System", this.GetType().Assembly);
}
private static SR GetLoader()
{
if (loader == null)
{
SR sr = new SR();
Interlocked.CompareExchange(ref loader, sr, null);
}
return loader;
}
private static CultureInfo Culture
{
get { return null/*use ResourceManager default, CultureInfo.CurrentUICulture*/; }
}
public static ResourceManager Resources
{
get
{
return GetLoader().resources;
}
}
public static string GetString(string name, params object[] args)
{
SR sys = GetLoader();
if (sys == null)
{
return null;
}
string res = sys.resources.GetString(name, SR.Culture);
if (args != null && args.Length > 0)
{
for (int i = 0; i < args.Length; i++)
{
String value = args[i] as String;
if (value != null && value.Length > 1024)
{
args[i] = value.Substring(0, 1024 - 3) + "...";
}
}
return String.Format(CultureInfo.CurrentCulture, res, args);
}
else
{
return res;
}
}
public static string GetString(string name)
{
SR sys = GetLoader();
if (sys == null)
{
return null;
}
return sys.resources.GetString(name, SR.Culture);
}
public static string GetString(string name, out bool usedFallback)
{
// always false for this version of gensr
usedFallback = false;
return GetString(name);
}
public static object GetObject(string name)
{
SR sys = GetLoader();
if (sys == null)
{
return null;
}
return sys.resources.GetObject(name, SR.Culture);
}
}
}

View File

@ -0,0 +1,74 @@
// -----------------------------------------------------------------------
// <copyright file="ValidationHelper.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.AspNet.Security.Windows
{
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
internal static class ValidationHelper
{
public static string ExceptionMessage(Exception exception)
{
if (exception == null)
{
return string.Empty;
}
if (exception.InnerException == null)
{
return exception.Message;
}
return exception.Message + " (" + ExceptionMessage(exception.InnerException) + ")";
}
public static string ToString(object objectValue)
{
if (objectValue == null)
{
return "(null)";
}
else if (objectValue is string && ((string)objectValue).Length == 0)
{
return "(string.empty)";
}
else if (objectValue is Exception)
{
return ExceptionMessage(objectValue as Exception);
}
else if (objectValue is IntPtr)
{
return "0x" + ((IntPtr)objectValue).ToString("x");
}
else
{
return objectValue.ToString();
}
}
public static string HashString(object objectValue)
{
if (objectValue == null)
{
return "(null)";
}
else if (objectValue is string && ((string)objectValue).Length == 0)
{
return "(string.empty)";
}
else
{
return objectValue.GetHashCode().ToString(NumberFormatInfo.InvariantInfo);
}
}
}
}

View File

@ -0,0 +1,721 @@
//------------------------------------------------------------------------------
// <copyright file="_NTAuthentication.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Net;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Threading;
namespace Microsoft.AspNet.Security.Windows
{
internal class NTAuthentication
{
private static readonly ContextCallback Callback = new ContextCallback(InitializeCallback);
private static ISSPIInterface SSPIAuth = new SSPIAuthType();
private bool _isServer;
private SafeFreeCredentials _credentialsHandle;
private SafeDeleteContext _securityContext;
private string _spn;
private string _clientSpecifiedSpn;
private int _tokenSize;
private ContextFlags _requestedContextFlags;
private ContextFlags _contextFlags;
private string _uniqueUserId;
private bool _isCompleted;
private string _protocolName;
private SecSizes _sizes;
private string _lastProtocolName;
private string _package;
private ChannelBinding _channelBinding;
// This overload does not attmept to impersonate because the caller either did it already or the original thread context is still preserved
internal NTAuthentication(bool isServer, string package, NetworkCredential credential, string spn, ContextFlags requestedContextFlags, ChannelBinding channelBinding)
{
Initialize(isServer, package, credential, spn, requestedContextFlags, channelBinding);
}
// This overload always uses the default credentials for the process.
[SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)]
internal NTAuthentication(bool isServer, string package, string spn, ContextFlags requestedContextFlags, ChannelBinding channelBinding)
{
try
{
using (WindowsIdentity.Impersonate(IntPtr.Zero))
{
Initialize(isServer, package, CredentialCache.DefaultNetworkCredentials, spn, requestedContextFlags, channelBinding);
}
}
catch
{
// Avoid exception filter attacks.
throw;
}
}
// The semantic of this propoerty is "Don't call me again".
// It can be completed either with success or error
// The latest case is signalled by IsValidContext==false
internal bool IsCompleted
{
get
{
return _isCompleted;
}
}
internal bool IsValidContext
{
get
{
return !(_securityContext == null || _securityContext.IsInvalid);
}
}
internal string AssociatedName
{
get
{
if (!(IsValidContext && IsCompleted))
{
throw new Win32Exception((int)SecurityStatus.InvalidHandle);
}
string name = SSPIWrapper.QueryContextAttributes(SSPIAuth, _securityContext, ContextAttribute.Names) as string;
GlobalLog.Print("NTAuthentication: The context is associated with [" + name + "]");
return name;
}
}
internal bool IsConfidentialityFlag
{
get
{
return (_contextFlags & ContextFlags.Confidentiality) != 0;
}
}
internal bool IsIntegrityFlag
{
get
{
return (_contextFlags & (_isServer ? ContextFlags.AcceptIntegrity : ContextFlags.InitIntegrity)) != 0;
}
}
internal bool IsMutualAuthFlag
{
get
{
return (_contextFlags & ContextFlags.MutualAuth) != 0;
}
}
internal bool IsDelegationFlag
{
get
{
return (_contextFlags & ContextFlags.Delegate) != 0;
}
}
internal bool IsIdentifyFlag
{
get
{
return (_contextFlags & (_isServer ? ContextFlags.AcceptIdentify : ContextFlags.InitIdentify)) != 0;
}
}
internal string Spn
{
get
{
return _spn;
}
}
internal string ClientSpecifiedSpn
{
get
{
if (_clientSpecifiedSpn == null)
{
_clientSpecifiedSpn = GetClientSpecifiedSpn();
}
return _clientSpecifiedSpn;
}
}
// True indicates this instance is for Server and will use AcceptSecurityContext SSPI API
internal bool IsServer
{
get
{
return _isServer;
}
}
internal bool IsKerberos
{
get
{
if (_lastProtocolName == null)
{
_lastProtocolName = ProtocolName;
}
return (object)_lastProtocolName == (object)NegotiationInfoClass.Kerberos;
}
}
internal bool IsNTLM
{
get
{
if (_lastProtocolName == null)
{
_lastProtocolName = ProtocolName;
}
return (object)_lastProtocolName == (object)NegotiationInfoClass.NTLM;
}
}
internal string Package
{
get
{
return _package;
}
}
internal string ProtocolName
{
get
{
// NB: May return string.Empty if the auth is not done yet or failed
if (_protocolName == null)
{
NegotiationInfoClass negotiationInfo = null;
if (IsValidContext)
{
negotiationInfo = SSPIWrapper.QueryContextAttributes(SSPIAuth, _securityContext, ContextAttribute.NegotiationInfo) as NegotiationInfoClass;
if (IsCompleted)
{
if (negotiationInfo != null)
{
// cache it only when it's completed
_protocolName = negotiationInfo.AuthenticationPackage;
}
}
}
return negotiationInfo == null ? string.Empty : negotiationInfo.AuthenticationPackage;
}
return _protocolName;
}
}
internal SecSizes Sizes
{
get
{
GlobalLog.Assert(IsCompleted && IsValidContext, "NTAuthentication#{0}::MaxDataSize|The context is not completed or invalid.", ValidationHelper.HashString(this));
if (_sizes == null)
{
_sizes = SSPIWrapper.QueryContextAttributes(
SSPIAuth,
_securityContext,
ContextAttribute.Sizes) as SecSizes;
}
return _sizes;
}
}
internal ChannelBinding ChannelBinding
{
get { return _channelBinding; }
}
private static void InitializeCallback(object state)
{
InitializeCallbackContext context = (InitializeCallbackContext)state;
context.ThisPtr.Initialize(context.IsServer, context.Package, context.Credential, context.Spn, context.RequestedContextFlags, context.ChannelBinding);
}
private void Initialize(bool isServer, string package, NetworkCredential credential, string spn, ContextFlags requestedContextFlags, ChannelBinding channelBinding)
{
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::.ctor() package:" + ValidationHelper.ToString(package) + " spn:" + ValidationHelper.ToString(spn) + " flags :" + requestedContextFlags.ToString());
_tokenSize = SSPIWrapper.GetVerifyPackageInfo(SSPIAuth, package, true).MaxToken;
_isServer = isServer;
_spn = spn;
_securityContext = null;
_requestedContextFlags = requestedContextFlags;
_package = package;
_channelBinding = channelBinding;
GlobalLog.Print("Peer SPN-> '" + _spn + "'");
// check if we're using DefaultCredentials
if (credential == CredentialCache.DefaultNetworkCredentials)
{
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::.ctor(): using DefaultCredentials");
_credentialsHandle = SSPIWrapper.AcquireDefaultCredential(
SSPIAuth,
package,
(_isServer ? CredentialUse.Inbound : CredentialUse.Outbound));
_uniqueUserId = "/S"; // save off for unique connection marking ONLY used by HTTP client
}
else if (ComNetOS.IsWin7orLater)
{
unsafe
{
SafeSspiAuthDataHandle authData = null;
try
{
SecurityStatus result = UnsafeNclNativeMethods.SspiHelper.SspiEncodeStringsAsAuthIdentity(
credential.UserName/*InternalGetUserName()*/, credential.Domain/*InternalGetDomain()*/,
credential.Password/*InternalGetPassword()*/, out authData);
if (result != SecurityStatus.OK)
{
if (Logging.On)
{
Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "SspiEncodeStringsAsAuthIdentity()", String.Format(CultureInfo.CurrentCulture, "0x{0:X}", (int)result)));
}
throw new Win32Exception((int)result);
}
_credentialsHandle = SSPIWrapper.AcquireCredentialsHandle(SSPIAuth,
package, (_isServer ? CredentialUse.Inbound : CredentialUse.Outbound), ref authData);
}
finally
{
if (authData != null)
{
authData.Dispose();
}
}
}
}
else
{
// we're not using DefaultCredentials, we need a
// AuthIdentity struct to contain credentials
// SECREVIEW:
// we'll save username/domain in temp strings, to avoid decrypting multiple times.
// password is only used once
string username = credential.UserName; // InternalGetUserName();
string domain = credential.Domain; // InternalGetDomain();
// ATTN:
// NetworkCredential class does not differentiate between null and "" but SSPI packages treat these cases differently
// For NTLM we want to keep "" for Wdigest.Dll we should use null.
AuthIdentity authIdentity = new AuthIdentity(username, credential.Password/*InternalGetPassword()*/, (object)package == (object)NegotiationInfoClass.WDigest && (domain == null || domain.Length == 0) ? null : domain);
_uniqueUserId = domain + "/" + username + "/U"; // save off for unique connection marking ONLY used by HTTP client
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::.ctor(): using authIdentity:" + authIdentity.ToString());
_credentialsHandle = SSPIWrapper.AcquireCredentialsHandle(
SSPIAuth,
package,
(_isServer ? CredentialUse.Inbound : CredentialUse.Outbound),
ref authIdentity);
}
}
// This will return an client token when conducted authentication on server side'
// This token can be used ofr impersanation
// We use it to create a WindowsIdentity and hand it out to the server app.
internal SafeCloseHandle GetContextToken(out SecurityStatus status)
{
GlobalLog.Assert(IsCompleted && IsValidContext, "NTAuthentication#{0}::GetContextToken|Should be called only when completed with success, currently is not!", ValidationHelper.HashString(this));
GlobalLog.Assert(IsServer, "NTAuthentication#{0}::GetContextToken|The method must not be called by the client side!", ValidationHelper.HashString(this));
if (!IsValidContext)
{
throw new Win32Exception((int)SecurityStatus.InvalidHandle);
}
SafeCloseHandle token = null;
status = (SecurityStatus)SSPIWrapper.QuerySecurityContextToken(
SSPIAuth,
_securityContext,
out token);
return token;
}
internal SafeCloseHandle GetContextToken()
{
SecurityStatus status;
SafeCloseHandle token = GetContextToken(out status);
if (status != SecurityStatus.OK)
{
throw new Win32Exception((int)status);
}
return token;
}
internal void CloseContext()
{
if (_securityContext != null && !_securityContext.IsClosed)
{
_securityContext.Dispose();
}
}
// NTAuth::GetOutgoingBlob()
// Created: 12-01-1999: L.M.
// Description:
// Accepts an incoming binary security blob and returns
// an outgoing binary security blob
internal byte[] GetOutgoingBlob(byte[] incomingBlob, bool throwOnError, out SecurityStatus statusCode)
{
GlobalLog.Enter("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob", ((incomingBlob == null) ? "0" : incomingBlob.Length.ToString(NumberFormatInfo.InvariantInfo)) + " bytes");
List<SecurityBuffer> list = new List<SecurityBuffer>(2);
if (incomingBlob != null)
{
list.Add(new SecurityBuffer(incomingBlob, BufferType.Token));
}
if (_channelBinding != null)
{
list.Add(new SecurityBuffer(_channelBinding));
}
SecurityBuffer[] inSecurityBufferArray = null;
if (list.Count > 0)
{
inSecurityBufferArray = list.ToArray();
}
SecurityBuffer outSecurityBuffer = new SecurityBuffer(_tokenSize, BufferType.Token);
bool firstTime = _securityContext == null;
try
{
if (!_isServer)
{
// client session
statusCode = (SecurityStatus)SSPIWrapper.InitializeSecurityContext(
SSPIAuth,
_credentialsHandle,
ref _securityContext,
_spn,
_requestedContextFlags,
Endianness.Network,
inSecurityBufferArray,
outSecurityBuffer,
ref _contextFlags);
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob() SSPIWrapper.InitializeSecurityContext() returns statusCode:0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + " (" + statusCode.ToString() + ")");
if (statusCode == SecurityStatus.CompleteNeeded)
{
SecurityBuffer[] inSecurityBuffers = new SecurityBuffer[1];
inSecurityBuffers[0] = outSecurityBuffer;
statusCode = (SecurityStatus)SSPIWrapper.CompleteAuthToken(
SSPIAuth,
ref _securityContext,
inSecurityBuffers);
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob() SSPIWrapper.CompleteAuthToken() returns statusCode:0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + " (" + statusCode.ToString() + ")");
outSecurityBuffer.token = null;
}
}
else
{
// server session
statusCode = (SecurityStatus)SSPIWrapper.AcceptSecurityContext(
SSPIAuth,
_credentialsHandle,
ref _securityContext,
_requestedContextFlags,
Endianness.Network,
inSecurityBufferArray,
outSecurityBuffer,
ref _contextFlags);
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob() SSPIWrapper.AcceptSecurityContext() returns statusCode:0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + " (" + statusCode.ToString() + ")");
}
}
finally
{
// Assuming the ISC or ASC has referenced the credential on the first successful call,
// we want to decrement the effective ref count by "disposing" it.
// The real dispose will happen when the security context is closed.
// Note if the first call was not successfull the handle is physically destroyed here
if (firstTime && _credentialsHandle != null)
{
_credentialsHandle.Dispose();
}
}
if (((int)statusCode & unchecked((int)0x80000000)) != 0)
{
CloseContext();
_isCompleted = true;
if (throwOnError)
{
Win32Exception exception = new Win32Exception((int)statusCode);
GlobalLog.Leave("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob", "Win32Exception:" + exception);
throw exception;
}
GlobalLog.Leave("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob", "null statusCode:0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + " (" + statusCode.ToString() + ")");
return null;
}
else if (firstTime && _credentialsHandle != null)
{
// cache until it is pushed out by newly incoming handles
SSPIHandleCache.CacheCredential(_credentialsHandle);
}
// the return value from SSPI will tell us correctly if the
// handshake is over or not: http://msdn.microsoft.com/library/psdk/secspi/sspiref_67p0.htm
// we also have to consider the case in which SSPI formed a new context, in this case we're done as well.
if (statusCode == SecurityStatus.OK)
{
// we're sucessfully done
GlobalLog.Assert(statusCode == SecurityStatus.OK, "NTAuthentication#{0}::GetOutgoingBlob()|statusCode:[0x{1:x8}] ({2}) m_SecurityContext#{3}::Handle:[{4}] [STATUS != OK]", ValidationHelper.HashString(this), (int)statusCode, statusCode, ValidationHelper.HashString(_securityContext), ValidationHelper.ToString(_securityContext));
_isCompleted = true;
}
else
{
// we need to continue
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob() need continue statusCode:[0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + "] (" + statusCode.ToString() + ") m_SecurityContext#" + ValidationHelper.HashString(_securityContext) + "::Handle:" + ValidationHelper.ToString(_securityContext) + "]");
}
// GlobalLog.Print("out token = " + outSecurityBuffer.ToString());
// GlobalLog.Dump(outSecurityBuffer.token);
GlobalLog.Leave("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingBlob", "IsCompleted:" + IsCompleted.ToString());
return outSecurityBuffer.token;
}
// for Server side (IIS 6.0) see: \\netindex\Sources\inetsrv\iis\iisrearc\iisplus\ulw3\digestprovider.cxx
// for Client side (HTTP.SYS) see: \\netindex\Sources\net\http\sys\ucauth.c
internal string GetOutgoingDigestBlob(string incomingBlob, string requestMethod, string requestedUri, string realm, bool isClientPreAuth, bool throwOnError, out SecurityStatus statusCode)
{
GlobalLog.Enter("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob", incomingBlob);
// second time call with 3 incoming buffers to select HTTP client.
// we should get back a SecurityStatus.OK and a non null outgoingBlob.
SecurityBuffer[] inSecurityBuffers = null;
SecurityBuffer outSecurityBuffer = new SecurityBuffer(_tokenSize, isClientPreAuth ? BufferType.Parameters : BufferType.Token);
bool firstTime = _securityContext == null;
try
{
if (!_isServer)
{
// client session
if (!isClientPreAuth)
{
if (incomingBlob != null)
{
List<SecurityBuffer> list = new List<SecurityBuffer>(5);
list.Add(new SecurityBuffer(HeaderEncoding.GetBytes(incomingBlob), BufferType.Token));
list.Add(new SecurityBuffer(HeaderEncoding.GetBytes(requestMethod), BufferType.Parameters));
list.Add(new SecurityBuffer(null, BufferType.Parameters));
list.Add(new SecurityBuffer(Encoding.Unicode.GetBytes(_spn), BufferType.TargetHost));
if (_channelBinding != null)
{
list.Add(new SecurityBuffer(_channelBinding));
}
inSecurityBuffers = list.ToArray();
}
statusCode = (SecurityStatus)SSPIWrapper.InitializeSecurityContext(
SSPIAuth,
_credentialsHandle,
ref _securityContext,
requestedUri, // this must match the Uri in the HTTP status line for the current request
_requestedContextFlags,
Endianness.Network,
inSecurityBuffers,
outSecurityBuffer,
ref _contextFlags);
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob() SSPIWrapper.InitializeSecurityContext() returns statusCode:0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + " (" + statusCode.ToString() + ")");
}
else
{
#if WDIGEST_PREAUTH
inSecurityBuffers = new SecurityBuffer[] {
new SecurityBuffer(null, BufferType.Token),
new SecurityBuffer(WebHeaderCollection.HeaderEncoding.GetBytes(requestMethod), BufferType.Parameters),
new SecurityBuffer(WebHeaderCollection.HeaderEncoding.GetBytes(requestedUri), BufferType.Parameters),
new SecurityBuffer(null, BufferType.Parameters),
outSecurityBuffer,
};
statusCode = (SecurityStatus) SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, m_SecurityContext, inSecurityBuffers, 0);
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob() SSPIWrapper.MakeSignature() returns statusCode:0x" + ((int) statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + " (" + statusCode.ToString() + ")");
#else
statusCode = SecurityStatus.OK;
GlobalLog.Assert("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob()", "Invalid code path.");
#endif
}
}
else
{
// server session
List<SecurityBuffer> list = new List<SecurityBuffer>(6);
list.Add(incomingBlob == null ? new SecurityBuffer(0, BufferType.Token) : new SecurityBuffer(HeaderEncoding.GetBytes(incomingBlob), BufferType.Token));
list.Add(requestMethod == null ? new SecurityBuffer(0, BufferType.Parameters) : new SecurityBuffer(HeaderEncoding.GetBytes(requestMethod), BufferType.Parameters));
list.Add(requestedUri == null ? new SecurityBuffer(0, BufferType.Parameters) : new SecurityBuffer(HeaderEncoding.GetBytes(requestedUri), BufferType.Parameters));
list.Add(new SecurityBuffer(0, BufferType.Parameters));
list.Add(realm == null ? new SecurityBuffer(0, BufferType.Parameters) : new SecurityBuffer(Encoding.Unicode.GetBytes(realm), BufferType.Parameters));
if (_channelBinding != null)
{
list.Add(new SecurityBuffer(_channelBinding));
}
inSecurityBuffers = list.ToArray();
statusCode = (SecurityStatus)SSPIWrapper.AcceptSecurityContext(
SSPIAuth,
_credentialsHandle,
ref _securityContext,
_requestedContextFlags,
Endianness.Network,
inSecurityBuffers,
outSecurityBuffer,
ref _contextFlags);
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob() SSPIWrapper.AcceptSecurityContext() returns statusCode:0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + " (" + statusCode.ToString() + ")");
if (statusCode == SecurityStatus.CompleteNeeded)
{
inSecurityBuffers[4] = outSecurityBuffer;
statusCode = (SecurityStatus)SSPIWrapper.CompleteAuthToken(
SSPIAuth,
ref _securityContext,
inSecurityBuffers);
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob() SSPIWrapper.CompleteAuthToken() returns statusCode:0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + " (" + statusCode.ToString() + ")");
outSecurityBuffer.token = null;
}
}
}
finally
{
// Assuming the ISC or ASC has referenced the credential on the first successful call,
// we want to decrement the effective ref count by "disposing" it.
// The real dispose will happen when the security context is closed.
// Note if the first call was not successfull the handle is physically destroyed here
if (firstTime && _credentialsHandle != null)
{
_credentialsHandle.Dispose();
}
}
if (((int)statusCode & unchecked((int)0x80000000)) != 0)
{
CloseContext();
if (throwOnError)
{
Win32Exception exception = new Win32Exception((int)statusCode);
GlobalLog.Leave("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob", "Win32Exception:" + exception);
throw exception;
}
GlobalLog.Leave("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob", "null statusCode:0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + " (" + statusCode.ToString() + ")");
return null;
}
else if (firstTime && _credentialsHandle != null)
{
// cache until it is pushed out by newly incoming handles
SSPIHandleCache.CacheCredential(_credentialsHandle);
}
// the return value from SSPI will tell us correctly if the
// handshake is over or not: http://msdn.microsoft.com/library/psdk/secspi/sspiref_67p0.htm
if (statusCode == SecurityStatus.OK)
{
// we're done, cleanup
_isCompleted = true;
}
else
{
// we need to continue
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob() need continue statusCode:[0x" + ((int)statusCode).ToString("x8", NumberFormatInfo.InvariantInfo) + "] (" + statusCode.ToString() + ") m_SecurityContext#" + ValidationHelper.HashString(_securityContext) + "::Handle:" + ValidationHelper.ToString(_securityContext) + "]");
}
GlobalLog.Print("out token = " + outSecurityBuffer.ToString());
GlobalLog.Dump(outSecurityBuffer.token);
GlobalLog.Print("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob() IsCompleted:" + IsCompleted.ToString());
byte[] decodedOutgoingBlob = outSecurityBuffer.token;
string outgoingBlob = null;
if (decodedOutgoingBlob != null && decodedOutgoingBlob.Length > 0)
{
outgoingBlob = HeaderEncoding.GetString(decodedOutgoingBlob, 0, outSecurityBuffer.size);
}
GlobalLog.Leave("NTAuthentication#" + ValidationHelper.HashString(this) + "::GetOutgoingDigestBlob", outgoingBlob);
return outgoingBlob;
}
private string GetClientSpecifiedSpn()
{
GlobalLog.Assert(IsValidContext && IsCompleted, "NTAuthentication: Trying to get the client SPN before handshaking is done!");
string spn = SSPIWrapper.QueryContextAttributes(SSPIAuth, _securityContext,
ContextAttribute.ClientSpecifiedSpn) as string;
GlobalLog.Print("NTAuthentication: The client specified SPN is [" + spn + "]");
return spn;
}
private class InitializeCallbackContext
{
internal readonly NTAuthentication ThisPtr;
internal readonly bool IsServer;
internal readonly string Package;
internal readonly NetworkCredential Credential;
internal readonly string Spn;
internal readonly ContextFlags RequestedContextFlags;
internal readonly ChannelBinding ChannelBinding;
internal InitializeCallbackContext(NTAuthentication thisPtr, bool isServer, string package, NetworkCredential credential, string spn, ContextFlags requestedContextFlags, ChannelBinding channelBinding)
{
this.ThisPtr = thisPtr;
this.IsServer = isServer;
this.Package = package;
this.Credential = credential;
this.Spn = spn;
this.RequestedContextFlags = requestedContextFlags;
this.ChannelBinding = channelBinding;
}
}
}
}

View File

@ -0,0 +1,40 @@
// -----------------------------------------------------------------------
// <copyright file="AuthIdentity.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal struct AuthIdentity
{
// see SEC_WINNT_AUTH_IDENTITY_W
internal string UserName;
internal int UserNameLength;
internal string Domain;
internal int DomainLength;
internal string Password;
internal int PasswordLength;
internal int Flags;
internal AuthIdentity(string userName, string password, string domain)
{
UserName = userName;
UserNameLength = userName == null ? 0 : userName.Length;
Password = password;
PasswordLength = password == null ? 0 : password.Length;
Domain = domain;
DomainLength = domain == null ? 0 : domain.Length;
// Flags are 2 for Unicode and 1 for ANSI. We use 2 on NT and 1 on Win9x.
Flags = 2;
}
public override string ToString()
{
return ValidationHelper.ToString(Domain) + "\\" + ValidationHelper.ToString(UserName);
}
}
}

View File

@ -0,0 +1,124 @@
// -----------------------------------------------------------------------
// <copyright file="ContextFlags.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
namespace Microsoft.AspNet.Security.Windows
{
// #define ISC_REQ_DELEGATE 0x00000001
// #define ISC_REQ_MUTUAL_AUTH 0x00000002
// #define ISC_REQ_REPLAY_DETECT 0x00000004
// #define ISC_REQ_SEQUENCE_DETECT 0x00000008
// #define ISC_REQ_CONFIDENTIALITY 0x00000010
// #define ISC_REQ_USE_SESSION_KEY 0x00000020
// #define ISC_REQ_PROMPT_FOR_CREDS 0x00000040
// #define ISC_REQ_USE_SUPPLIED_CREDS 0x00000080
// #define ISC_REQ_ALLOCATE_MEMORY 0x00000100
// #define ISC_REQ_USE_DCE_STYLE 0x00000200
// #define ISC_REQ_DATAGRAM 0x00000400
// #define ISC_REQ_CONNECTION 0x00000800
// #define ISC_REQ_CALL_LEVEL 0x00001000
// #define ISC_REQ_FRAGMENT_SUPPLIED 0x00002000
// #define ISC_REQ_EXTENDED_ERROR 0x00004000
// #define ISC_REQ_STREAM 0x00008000
// #define ISC_REQ_INTEGRITY 0x00010000
// #define ISC_REQ_IDENTIFY 0x00020000
// #define ISC_REQ_NULL_SESSION 0x00040000
// #define ISC_REQ_MANUAL_CRED_VALIDATION 0x00080000
// #define ISC_REQ_RESERVED1 0x00100000
// #define ISC_REQ_FRAGMENT_TO_FIT 0x00200000
// #define ISC_REQ_HTTP 0x10000000
// Win7 SP1 +
// #define ISC_REQ_UNVERIFIED_TARGET_NAME 0x20000000
// #define ASC_REQ_DELEGATE 0x00000001
// #define ASC_REQ_MUTUAL_AUTH 0x00000002
// #define ASC_REQ_REPLAY_DETECT 0x00000004
// #define ASC_REQ_SEQUENCE_DETECT 0x00000008
// #define ASC_REQ_CONFIDENTIALITY 0x00000010
// #define ASC_REQ_USE_SESSION_KEY 0x00000020
// #define ASC_REQ_ALLOCATE_MEMORY 0x00000100
// #define ASC_REQ_USE_DCE_STYLE 0x00000200
// #define ASC_REQ_DATAGRAM 0x00000400
// #define ASC_REQ_CONNECTION 0x00000800
// #define ASC_REQ_CALL_LEVEL 0x00001000
// #define ASC_REQ_EXTENDED_ERROR 0x00008000
// #define ASC_REQ_STREAM 0x00010000
// #define ASC_REQ_INTEGRITY 0x00020000
// #define ASC_REQ_LICENSING 0x00040000
// #define ASC_REQ_IDENTIFY 0x00080000
// #define ASC_REQ_ALLOW_NULL_SESSION 0x00100000
// #define ASC_REQ_ALLOW_NON_USER_LOGONS 0x00200000
// #define ASC_REQ_ALLOW_CONTEXT_REPLAY 0x00400000
// #define ASC_REQ_FRAGMENT_TO_FIT 0x00800000
// #define ASC_REQ_FRAGMENT_SUPPLIED 0x00002000
// #define ASC_REQ_NO_TOKEN 0x01000000
// #define ASC_REQ_HTTP 0x10000000
[Flags]
internal enum ContextFlags
{
Zero = 0,
// The server in the transport application can
// build new security contexts impersonating the
// client that will be accepted by other servers
// as the client's contexts.
Delegate = 0x00000001,
// The communicating parties must authenticate
// their identities to each other. Without MutualAuth,
// the client authenticates its identity to the server.
// With MutualAuth, the server also must authenticate
// its identity to the client.
MutualAuth = 0x00000002,
// The security package detects replayed packets and
// notifies the caller if a packet has been replayed.
// The use of this flag implies all of the conditions
// specified by the Integrity flag.
ReplayDetect = 0x00000004,
// The context must be allowed to detect out-of-order
// delivery of packets later through the message support
// functions. Use of this flag implies all of the
// conditions specified by the Integrity flag.
SequenceDetect = 0x00000008,
// The context must protect data while in transit.
// Confidentiality is supported for NTLM with Microsoft
// Windows NT version 4.0, SP4 and later and with the
// Kerberos protocol in Microsoft Windows 2000 and later.
Confidentiality = 0x00000010,
UseSessionKey = 0x00000020,
AllocateMemory = 0x00000100,
// Connection semantics must be used.
Connection = 0x00000800,
// Client applications requiring extended error messages specify the
// ISC_REQ_EXTENDED_ERROR flag when calling the InitializeSecurityContext
// Server applications requiring extended error messages set
// the ASC_REQ_EXTENDED_ERROR flag when calling AcceptSecurityContext.
InitExtendedError = 0x00004000,
AcceptExtendedError = 0x00008000,
// A transport application requests stream semantics
// by setting the ISC_REQ_STREAM and ASC_REQ_STREAM
// flags in the calls to the InitializeSecurityContext
// and AcceptSecurityContext functions
InitStream = 0x00008000,
AcceptStream = 0x00010000,
// Buffer integrity can be verified; however, replayed
// and out-of-sequence messages will not be detected
InitIntegrity = 0x00010000, // ISC_REQ_INTEGRITY
AcceptIntegrity = 0x00020000, // ASC_REQ_INTEGRITY
InitManualCredValidation = 0x00080000, // ISC_REQ_MANUAL_CRED_VALIDATION
InitUseSuppliedCreds = 0x00000080, // ISC_REQ_USE_SUPPLIED_CREDS
InitIdentify = 0x00020000, // ISC_REQ_IDENTIFY
AcceptIdentify = 0x00080000, // ASC_REQ_IDENTIFY
ProxyBindings = 0x04000000, // ASC_REQ_PROXY_BINDINGS
AllowMissingBindings = 0x10000000, // ASC_REQ_ALLOW_MISSING_BINDINGS
UnverifiedTargetName = 0x20000000, // ISC_REQ_UNVERIFIED_TARGET_NAME
}
}

View File

@ -0,0 +1,42 @@
//------------------------------------------------------------------------------
// <copyright file="_NativeSSPI.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
// used to define the interface for security to use.
internal interface ISSPIInterface
{
SecurityPackageInfoClass[] SecurityPackages { get; set; }
int EnumerateSecurityPackages(out int pkgnum, out SafeFreeContextBuffer pkgArray);
int AcquireCredentialsHandle(string moduleName, CredentialUse usage, ref AuthIdentity authdata, out SafeFreeCredentials outCredential);
int AcquireCredentialsHandle(string moduleName, CredentialUse usage, ref SafeSspiAuthDataHandle authdata, out SafeFreeCredentials outCredential);
int AcquireDefaultCredential(string moduleName, CredentialUse usage, out SafeFreeCredentials outCredential);
int AcquireCredentialsHandle(string moduleName, CredentialUse usage, ref SecureCredential authdata, out SafeFreeCredentials outCredential);
int AcceptSecurityContext(ref SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer inputBuffer, ContextFlags inFlags,
Endianness endianness, SecurityBuffer outputBuffer, ref ContextFlags outFlags);
int AcceptSecurityContext(SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers, ContextFlags inFlags,
Endianness endianness, SecurityBuffer outputBuffer, ref ContextFlags outFlags);
int InitializeSecurityContext(ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlags inFlags,
Endianness endianness, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags);
int InitializeSecurityContext(SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlags inFlags,
Endianness endianness, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags);
int EncryptMessage(SafeDeleteContext context, SecurityBufferDescriptor inputOutput, uint sequenceNumber);
int DecryptMessage(SafeDeleteContext context, SecurityBufferDescriptor inputOutput, uint sequenceNumber);
int MakeSignature(SafeDeleteContext context, SecurityBufferDescriptor inputOutput, uint sequenceNumber);
int VerifySignature(SafeDeleteContext context, SecurityBufferDescriptor inputOutput, uint sequenceNumber);
int QueryContextChannelBinding(SafeDeleteContext phContext, ContextAttribute attribute, out SafeFreeContextBufferChannelBinding refHandle);
int QueryContextAttributes(SafeDeleteContext phContext, ContextAttribute attribute, byte[] buffer, Type handleType, out SafeHandle refHandle);
int SetContextAttributes(SafeDeleteContext phContext, ContextAttribute attribute, byte[] buffer);
int QuerySecurityContextToken(SafeDeleteContext phContext, out SafeCloseHandle phToken);
int CompleteAuthToken(ref SafeDeleteContext refContext, SecurityBuffer[] inputBuffers);
}
}

View File

@ -0,0 +1,302 @@
// -----------------------------------------------------------------------
// <copyright file="SSPIAuthType.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
internal class SSPIAuthType : ISSPIInterface
{
private static volatile SecurityPackageInfoClass[] _securityPackages;
public SecurityPackageInfoClass[] SecurityPackages
{
get
{
return _securityPackages;
}
set
{
_securityPackages = value;
}
}
public int EnumerateSecurityPackages(out int pkgnum, out SafeFreeContextBuffer pkgArray)
{
GlobalLog.Print("SSPIAuthType::EnumerateSecurityPackages()");
return SafeFreeContextBuffer.EnumeratePackages(out pkgnum, out pkgArray);
}
public int AcquireCredentialsHandle(string moduleName, CredentialUse usage, ref AuthIdentity authdata, out SafeFreeCredentials outCredential)
{
return SafeFreeCredentials.AcquireCredentialsHandle(moduleName, usage, ref authdata, out outCredential);
}
public int AcquireCredentialsHandle(string moduleName, CredentialUse usage, ref SafeSspiAuthDataHandle authdata, out SafeFreeCredentials outCredential)
{
return SafeFreeCredentials.AcquireCredentialsHandle(moduleName, usage, ref authdata, out outCredential);
}
public int AcquireDefaultCredential(string moduleName, CredentialUse usage, out SafeFreeCredentials outCredential)
{
return SafeFreeCredentials.AcquireDefaultCredential(moduleName, usage, out outCredential);
}
public int AcquireCredentialsHandle(string moduleName, CredentialUse usage, ref SecureCredential authdata, out SafeFreeCredentials outCredential)
{
return SafeFreeCredentials.AcquireCredentialsHandle(moduleName, usage, ref authdata, out outCredential);
}
public int AcceptSecurityContext(ref SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer inputBuffer, ContextFlags inFlags, Endianness endianness, SecurityBuffer outputBuffer, ref ContextFlags outFlags)
{
return SafeDeleteContext.AcceptSecurityContext(ref credential, ref context, inFlags, endianness, inputBuffer, null, outputBuffer, ref outFlags);
}
public int AcceptSecurityContext(SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers, ContextFlags inFlags, Endianness endianness, SecurityBuffer outputBuffer, ref ContextFlags outFlags)
{
return SafeDeleteContext.AcceptSecurityContext(ref credential, ref context, inFlags, endianness, null, inputBuffers, outputBuffer, ref outFlags);
}
public int InitializeSecurityContext(ref SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlags inFlags, Endianness endianness, SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, ref ContextFlags outFlags)
{
return SafeDeleteContext.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, endianness, inputBuffer, null, outputBuffer, ref outFlags);
}
public int InitializeSecurityContext(SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlags inFlags, Endianness endianness, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags)
{
return SafeDeleteContext.InitializeSecurityContext(ref credential, ref context, targetName, inFlags, endianness, null, inputBuffers, outputBuffer, ref outFlags);
}
public int EncryptMessage(SafeDeleteContext context, SecurityBufferDescriptor inputOutput, uint sequenceNumber)
{
int status = (int)SecurityStatus.InvalidHandle;
bool b = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
context.DangerousAddRef(ref b);
}
catch (Exception e)
{
if (b)
{
context.DangerousRelease();
b = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
if (b)
{
status = UnsafeNclNativeMethods.NativeNTSSPI.EncryptMessage(ref context._handle, 0, inputOutput, sequenceNumber);
context.DangerousRelease();
}
}
return status;
}
public unsafe int DecryptMessage(SafeDeleteContext context, SecurityBufferDescriptor inputOutput, uint sequenceNumber)
{
int status = (int)SecurityStatus.InvalidHandle;
bool b = false;
uint qop = 0;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
context.DangerousAddRef(ref b);
}
catch (Exception e)
{
if (b)
{
context.DangerousRelease();
b = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
if (b)
{
status = UnsafeNclNativeMethods.NativeNTSSPI.DecryptMessage(ref context._handle, inputOutput, sequenceNumber, &qop);
context.DangerousRelease();
}
}
const uint SECQOP_WRAP_NO_ENCRYPT = 0x80000001;
if (status == 0 && qop == SECQOP_WRAP_NO_ENCRYPT)
{
GlobalLog.Assert("NativeNTSSPI.DecryptMessage", "Expected qop = 0, returned value = " + qop.ToString("x", CultureInfo.InvariantCulture));
throw new InvalidOperationException(SR.GetString(SR.net_auth_message_not_encrypted));
}
return status;
}
public int MakeSignature(SafeDeleteContext context, SecurityBufferDescriptor inputOutput, uint sequenceNumber)
{
int status = (int)SecurityStatus.InvalidHandle;
bool b = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
context.DangerousAddRef(ref b);
}
catch (Exception e)
{
if (b)
{
context.DangerousRelease();
b = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
if (b)
{
const uint SECQOP_WRAP_NO_ENCRYPT = 0x80000001;
status = UnsafeNclNativeMethods.NativeNTSSPI.EncryptMessage(ref context._handle, SECQOP_WRAP_NO_ENCRYPT, inputOutput, sequenceNumber);
context.DangerousRelease();
}
}
return status;
}
public unsafe int VerifySignature(SafeDeleteContext context, SecurityBufferDescriptor inputOutput, uint sequenceNumber)
{
int status = (int)SecurityStatus.InvalidHandle;
bool b = false;
uint qop = 0;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
context.DangerousAddRef(ref b);
}
catch (Exception e)
{
if (b)
{
context.DangerousRelease();
b = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
if (b)
{
status = UnsafeNclNativeMethods.NativeNTSSPI.DecryptMessage(ref context._handle, inputOutput, sequenceNumber, &qop);
context.DangerousRelease();
}
}
return status;
}
public int QueryContextChannelBinding(SafeDeleteContext context, ContextAttribute attribute, out SafeFreeContextBufferChannelBinding binding)
{
// Querying an auth SSP for a CBT doesn't make sense
binding = null;
throw new NotSupportedException();
}
public unsafe int QueryContextAttributes(SafeDeleteContext context, ContextAttribute attribute, byte[] buffer, Type handleType, out SafeHandle refHandle)
{
refHandle = null;
if (handleType != null)
{
if (handleType == typeof(SafeFreeContextBuffer))
{
refHandle = SafeFreeContextBuffer.CreateEmptyHandle();
}
else if (handleType == typeof(SafeFreeCertContext))
{
refHandle = new SafeFreeCertContext();
}
else
{
throw new ArgumentException(SR.GetString(SR.SSPIInvalidHandleType, handleType.FullName), "handleType");
}
}
fixed (byte* bufferPtr = buffer)
{
return SafeFreeContextBuffer.QueryContextAttributes(context, attribute, bufferPtr, refHandle);
}
}
public int SetContextAttributes(SafeDeleteContext context, ContextAttribute attribute, byte[] buffer)
{
throw new NotImplementedException();
}
public int QuerySecurityContextToken(SafeDeleteContext phContext, out SafeCloseHandle phToken)
{
return GetSecurityContextToken(phContext, out phToken);
}
public int CompleteAuthToken(ref SafeDeleteContext refContext, SecurityBuffer[] inputBuffers)
{
return SafeDeleteContext.CompleteAuthToken(ref refContext, inputBuffers);
}
private static int GetSecurityContextToken(SafeDeleteContext phContext, out SafeCloseHandle safeHandle)
{
int status = (int)SecurityStatus.InvalidHandle;
bool b = false;
safeHandle = null;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
phContext.DangerousAddRef(ref b);
}
catch (Exception e)
{
if (b)
{
phContext.DangerousRelease();
b = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
if (b)
{
status = UnsafeNclNativeMethods.SafeNetHandles.QuerySecurityContextToken(ref phContext._handle, out safeHandle);
phContext.DangerousRelease();
}
}
return status;
}
}
}

View File

@ -0,0 +1,36 @@
// -----------------------------------------------------------------------
// <copyright file="SSPIHandle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct SSPIHandle
{
private IntPtr HandleHi;
private IntPtr HandleLo;
public bool IsZero
{
get { return HandleHi == IntPtr.Zero && HandleLo == IntPtr.Zero; }
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal void SetToInvalid()
{
HandleHi = IntPtr.Zero;
HandleLo = IntPtr.Zero;
}
public override string ToString()
{
return HandleHi.ToString("x") + ":" + HandleLo.ToString("x");
}
}
}

View File

@ -0,0 +1,49 @@
// -----------------------------------------------------------------------
// <copyright file="SSPIHandleCache.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
/*
Abstract:
The file implements trivial SSPI credential caching mechanism based on lru list
*/
using System;
using System.Threading;
namespace Microsoft.AspNet.Security.Windows
{
// Implements delayed SSPI handle release, like a finalizable object though the handles are kept alive until being pushed out
// by the newly incoming ones.
internal static class SSPIHandleCache
{
private const int MaxCacheSize = 0x1F; // must a (power of 2) - 1
private static SafeCredentialReference[] _cacheSlots = new SafeCredentialReference[MaxCacheSize + 1];
private static int _current = -1;
internal static void CacheCredential(SafeFreeCredentials newHandle)
{
try
{
SafeCredentialReference newRef = SafeCredentialReference.CreateReference(newHandle);
if (newRef == null)
{
return;
}
unchecked
{
int index = Interlocked.Increment(ref _current) & MaxCacheSize;
newRef = Interlocked.Exchange<SafeCredentialReference>(ref _cacheSlots[index], newRef);
}
if (newRef != null)
{
newRef.Dispose();
}
}
catch (Exception e)
{
GlobalLog.Assert("SSPIHandlCache", "Attempted to throw: " + e.ToString());
}
}
}
}

View File

@ -0,0 +1,462 @@
//------------------------------------------------------------------------------
// <copyright file="_SSPIWrapper.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
// From Schannel.h
[StructLayout(LayoutKind.Sequential)]
internal struct NegotiationInfo
{
// see SecPkgContext_NegotiationInfoW in <sspi.h>
// [MarshalAs(UnmanagedType.LPStruct)] internal SecurityPackageInfo PackageInfo;
internal IntPtr PackageInfo;
internal uint NegotiationState;
internal static readonly int Size = Marshal.SizeOf(typeof(NegotiationInfo));
internal static readonly int NegotiationStateOffest = (int)Marshal.OffsetOf(typeof(NegotiationInfo), "NegotiationState");
}
// we keep it simple since we use this only to know if NTLM or
// Kerberos are used in the context of a Negotiate handshake
[StructLayout(LayoutKind.Sequential)]
internal struct SecurityPackageInfo
{
// see SecPkgInfoW in <sspi.h>
internal int Capabilities;
internal short Version;
internal short RPCID;
internal int MaxToken;
internal IntPtr Name;
internal IntPtr Comment;
internal static readonly int Size = Marshal.SizeOf(typeof(SecurityPackageInfo));
internal static readonly int NameOffest = (int)Marshal.OffsetOf(typeof(SecurityPackageInfo), "Name");
}
[StructLayout(LayoutKind.Sequential)]
internal struct Bindings
{
// see SecPkgContext_Bindings in <sspi.h>
internal int BindingsLength;
internal IntPtr pBindings;
}
internal static class SSPIWrapper
{
internal static SecurityPackageInfoClass[] EnumerateSecurityPackages(ISSPIInterface secModule)
{
GlobalLog.Enter("EnumerateSecurityPackages");
if (secModule.SecurityPackages == null)
{
lock (secModule)
{
if (secModule.SecurityPackages == null)
{
int moduleCount = 0;
SafeFreeContextBuffer arrayBaseHandle = null;
try
{
int errorCode = secModule.EnumerateSecurityPackages(out moduleCount, out arrayBaseHandle);
GlobalLog.Print("SSPIWrapper::arrayBase: " + (arrayBaseHandle.DangerousGetHandle().ToString("x")));
if (errorCode != 0)
{
throw new Win32Exception(errorCode);
}
SecurityPackageInfoClass[] securityPackages = new SecurityPackageInfoClass[moduleCount];
if (Logging.On)
{
Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_enumerating_security_packages));
}
int i;
for (i = 0; i < moduleCount; i++)
{
securityPackages[i] = new SecurityPackageInfoClass(arrayBaseHandle, i);
if (Logging.On)
{
Logging.PrintInfo(Logging.Web, " " + securityPackages[i].Name);
}
}
secModule.SecurityPackages = securityPackages;
}
finally
{
if (arrayBaseHandle != null)
{
arrayBaseHandle.Dispose();
}
}
}
}
}
GlobalLog.Leave("EnumerateSecurityPackages");
return secModule.SecurityPackages;
}
internal static SecurityPackageInfoClass GetVerifyPackageInfo(ISSPIInterface secModule, string packageName, bool throwIfMissing)
{
SecurityPackageInfoClass[] supportedSecurityPackages = EnumerateSecurityPackages(secModule);
if (supportedSecurityPackages != null)
{
for (int i = 0; i < supportedSecurityPackages.Length; i++)
{
if (string.Compare(supportedSecurityPackages[i].Name, packageName, StringComparison.OrdinalIgnoreCase) == 0)
{
return supportedSecurityPackages[i];
}
}
}
if (Logging.On)
{
Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_package_not_found, packageName));
}
// error
if (throwIfMissing)
{
throw new NotSupportedException(SR.GetString(SR.net_securitypackagesupport));
}
return null;
}
public static SafeFreeCredentials AcquireDefaultCredential(ISSPIInterface secModule, string package, CredentialUse intent)
{
GlobalLog.Print("SSPIWrapper::AcquireDefaultCredential(): using " + package);
if (Logging.On)
{
Logging.PrintInfo(Logging.Web,
"AcquireDefaultCredential(" +
"package = " + package + ", " +
"intent = " + intent + ")");
}
SafeFreeCredentials outCredential = null;
int errorCode = secModule.AcquireDefaultCredential(package, intent, out outCredential);
if (errorCode != 0)
{
#if TRAVE
GlobalLog.Print("SSPIWrapper::AcquireDefaultCredential(): error " + SecureChannel.MapSecurityStatus((uint)errorCode));
#endif
if (Logging.On)
{
Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "AcquireDefaultCredential()", String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode)));
}
throw new Win32Exception(errorCode);
}
return outCredential;
}
public static SafeFreeCredentials AcquireCredentialsHandle(ISSPIInterface secModule, string package, CredentialUse intent, ref AuthIdentity authdata)
{
GlobalLog.Print("SSPIWrapper::AcquireCredentialsHandle#2(): using " + package);
if (Logging.On)
{
Logging.PrintInfo(Logging.Web,
"AcquireCredentialsHandle(" +
"package = " + package + ", " +
"intent = " + intent + ", " +
"authdata = " + authdata + ")");
}
SafeFreeCredentials credentialsHandle = null;
int errorCode = secModule.AcquireCredentialsHandle(package,
intent,
ref authdata,
out credentialsHandle);
if (errorCode != 0)
{
if (Logging.On)
{
Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "AcquireCredentialsHandle()", String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode)));
}
throw new Win32Exception(errorCode);
}
return credentialsHandle;
}
public static SafeFreeCredentials AcquireCredentialsHandle(ISSPIInterface secModule, string package, CredentialUse intent, ref SafeSspiAuthDataHandle authdata)
{
if (Logging.On)
{
Logging.PrintInfo(Logging.Web,
"AcquireCredentialsHandle(" +
"package = " + package + ", " +
"intent = " + intent + ", " +
"authdata = " + authdata + ")");
}
SafeFreeCredentials credentialsHandle = null;
int errorCode = secModule.AcquireCredentialsHandle(package, intent, ref authdata, out credentialsHandle);
if (errorCode != 0)
{
if (Logging.On)
{
Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_operation_failed_with_error, "AcquireCredentialsHandle()", String.Format(CultureInfo.CurrentCulture, "0X{0:X}", errorCode)));
}
throw new Win32Exception(errorCode);
}
return credentialsHandle;
}
internal static int InitializeSecurityContext(ISSPIInterface secModule, SafeFreeCredentials credential, ref SafeDeleteContext context, string targetName, ContextFlags inFlags, Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags)
{
if (Logging.On)
{
Logging.PrintInfo(Logging.Web,
"InitializeSecurityContext(" +
"credential = " + credential.ToString() + ", " +
"context = " + ValidationHelper.ToString(context) + ", " +
"targetName = " + targetName + ", " +
"inFlags = " + inFlags + ")");
}
int errorCode = secModule.InitializeSecurityContext(credential, ref context, targetName, inFlags, datarep, inputBuffers, outputBuffer, ref outFlags);
if (Logging.On)
{
Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffers, "InitializeSecurityContext", (inputBuffers == null ? 0 : inputBuffers.Length), outputBuffer.size, (SecurityStatus)errorCode));
}
return errorCode;
}
internal static int AcceptSecurityContext(ISSPIInterface secModule, SafeFreeCredentials credential, ref SafeDeleteContext context, ContextFlags inFlags, Endianness datarep, SecurityBuffer[] inputBuffers, SecurityBuffer outputBuffer, ref ContextFlags outFlags)
{
if (Logging.On)
{
Logging.PrintInfo(Logging.Web,
"AcceptSecurityContext(" +
"credential = " + credential.ToString() + ", " +
"context = " + ValidationHelper.ToString(context) + ", " +
"inFlags = " + inFlags + ")");
}
int errorCode = secModule.AcceptSecurityContext(credential, ref context, inputBuffers, inFlags, datarep, outputBuffer, ref outFlags);
if (Logging.On)
{
Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_sspi_security_context_input_buffers, "AcceptSecurityContext", (inputBuffers == null ? 0 : inputBuffers.Length), outputBuffer.size, (SecurityStatus)errorCode));
}
return errorCode;
}
internal static int CompleteAuthToken(ISSPIInterface secModule, ref SafeDeleteContext context, SecurityBuffer[] inputBuffers)
{
int errorCode = secModule.CompleteAuthToken(ref context, inputBuffers);
if (Logging.On)
{
Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_log_operation_returned_something, "CompleteAuthToken()", (SecurityStatus)errorCode));
}
return errorCode;
}
public static int QuerySecurityContextToken(ISSPIInterface secModule, SafeDeleteContext context, out SafeCloseHandle token)
{
return secModule.QuerySecurityContextToken(context, out token);
}
public static SafeFreeContextBufferChannelBinding QueryContextChannelBinding(ISSPIInterface secModule, SafeDeleteContext securityContext, ContextAttribute contextAttribute)
{
GlobalLog.Enter("QueryContextChannelBinding", contextAttribute.ToString());
SafeFreeContextBufferChannelBinding result;
int errorCode = secModule.QueryContextChannelBinding(securityContext, contextAttribute, out result);
if (errorCode != 0)
{
GlobalLog.Leave("QueryContextChannelBinding", "ERROR = " + ErrorDescription(errorCode));
return null;
}
GlobalLog.Leave("QueryContextChannelBinding", ValidationHelper.HashString(result));
return result;
}
public static object QueryContextAttributes(ISSPIInterface secModule, SafeDeleteContext securityContext, ContextAttribute contextAttribute)
{
int errorCode;
return QueryContextAttributes(secModule, securityContext, contextAttribute, out errorCode);
}
public static object QueryContextAttributes(ISSPIInterface secModule, SafeDeleteContext securityContext, ContextAttribute contextAttribute, out int errorCode)
{
GlobalLog.Enter("QueryContextAttributes", contextAttribute.ToString());
int nativeBlockSize = IntPtr.Size;
Type handleType = null;
switch (contextAttribute)
{
case ContextAttribute.Sizes:
nativeBlockSize = SecSizes.SizeOf;
break;
case ContextAttribute.StreamSizes:
nativeBlockSize = StreamSizes.SizeOf;
break;
case ContextAttribute.Names:
handleType = typeof(SafeFreeContextBuffer);
break;
case ContextAttribute.PackageInfo:
handleType = typeof(SafeFreeContextBuffer);
break;
case ContextAttribute.NegotiationInfo:
handleType = typeof(SafeFreeContextBuffer);
nativeBlockSize = Marshal.SizeOf(typeof(NegotiationInfo));
break;
case ContextAttribute.ClientSpecifiedSpn:
handleType = typeof(SafeFreeContextBuffer);
break;
case ContextAttribute.RemoteCertificate:
handleType = typeof(SafeFreeCertContext);
break;
case ContextAttribute.LocalCertificate:
handleType = typeof(SafeFreeCertContext);
break;
case ContextAttribute.IssuerListInfoEx:
nativeBlockSize = Marshal.SizeOf(typeof(IssuerListInfoEx));
handleType = typeof(SafeFreeContextBuffer);
break;
case ContextAttribute.ConnectionInfo:
nativeBlockSize = Marshal.SizeOf(typeof(SslConnectionInfo));
break;
default:
throw new ArgumentException(SR.GetString(SR.net_invalid_enum, "ContextAttribute"), "contextAttribute");
}
SafeHandle SspiHandle = null;
object attribute = null;
try
{
byte[] nativeBuffer = new byte[nativeBlockSize];
errorCode = secModule.QueryContextAttributes(securityContext, contextAttribute, nativeBuffer, handleType, out SspiHandle);
if (errorCode != 0)
{
GlobalLog.Leave("Win32:QueryContextAttributes", "ERROR = " + ErrorDescription(errorCode));
return null;
}
switch (contextAttribute)
{
case ContextAttribute.Sizes:
attribute = new SecSizes(nativeBuffer);
break;
case ContextAttribute.StreamSizes:
attribute = new StreamSizes(nativeBuffer);
break;
case ContextAttribute.Names:
attribute = Marshal.PtrToStringUni(SspiHandle.DangerousGetHandle());
break;
case ContextAttribute.PackageInfo:
attribute = new SecurityPackageInfoClass(SspiHandle, 0);
break;
case ContextAttribute.NegotiationInfo:
unsafe
{
fixed (void* ptr = nativeBuffer)
{
attribute = new NegotiationInfoClass(SspiHandle, Marshal.ReadInt32(new IntPtr(ptr), NegotiationInfo.NegotiationStateOffest));
}
}
break;
case ContextAttribute.ClientSpecifiedSpn:
attribute = Marshal.PtrToStringUni(SspiHandle.DangerousGetHandle());
break;
case ContextAttribute.LocalCertificate:
goto case ContextAttribute.RemoteCertificate;
case ContextAttribute.RemoteCertificate:
attribute = SspiHandle;
SspiHandle = null;
break;
case ContextAttribute.IssuerListInfoEx:
attribute = new IssuerListInfoEx(SspiHandle, nativeBuffer);
SspiHandle = null;
break;
case ContextAttribute.ConnectionInfo:
attribute = new SslConnectionInfo(nativeBuffer);
break;
default:
// will return null
break;
}
}
finally
{
if (SspiHandle != null)
{
SspiHandle.Dispose();
}
}
GlobalLog.Leave("QueryContextAttributes", ValidationHelper.ToString(attribute));
return attribute;
}
public static string ErrorDescription(int errorCode)
{
if (errorCode == -1)
{
return "An exception when invoking Win32 API";
}
switch ((SecurityStatus)errorCode)
{
case SecurityStatus.InvalidHandle:
return "Invalid handle";
case SecurityStatus.InvalidToken:
return "Invalid token";
case SecurityStatus.ContinueNeeded:
return "Continue needed";
case SecurityStatus.IncompleteMessage:
return "Message incomplete";
case SecurityStatus.WrongPrincipal:
return "Wrong principal";
case SecurityStatus.TargetUnknown:
return "Target unknown";
case SecurityStatus.PackageNotFound:
return "Package not found";
case SecurityStatus.BufferNotEnough:
return "Buffer not enough";
case SecurityStatus.MessageAltered:
return "Message altered";
case SecurityStatus.UntrustedRoot:
return "Untrusted root";
default:
return "0x" + errorCode.ToString("x", NumberFormatInfo.InvariantInfo);
}
}
} // class SSPIWrapper
}

View File

@ -0,0 +1,51 @@
// -----------------------------------------------------------------------
// <copyright file="SafeCloseHandle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.ConstrainedExecution;
using System.Security;
using System.Threading;
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Security.Windows
{
[SuppressUnmanagedCodeSecurity]
internal sealed class SafeCloseHandle : CriticalHandleZeroOrMinusOneIsInvalid
{
private int _disposed;
private SafeCloseHandle()
: base()
{
}
internal IntPtr DangerousGetHandle()
{
return handle;
}
protected override bool ReleaseHandle()
{
if (!IsInvalid)
{
if (Interlocked.Increment(ref _disposed) == 1)
{
return UnsafeNclNativeMethods.SafeNetHandles.CloseHandle(handle);
}
}
return true;
}
// This method will bypass refCount check done by VM
// Means it will force handle release if has a valid value
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal void Abort()
{
ReleaseHandle();
SetHandleAsInvalid();
}
}
}

View File

@ -0,0 +1,69 @@
// -----------------------------------------------------------------------
// <copyright file="SafeCredentialReference.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.CompilerServices;
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Security.Windows
{
internal sealed class SafeCredentialReference : CriticalHandleMinusOneIsInvalid
{
// Static cache will return the target handle if found the reference in the table.
internal SafeFreeCredentials _Target;
private SafeCredentialReference(SafeFreeCredentials target)
: base()
{
// Bumps up the refcount on Target to signify that target handle is statically cached so
// its dispose should be postponed
bool b = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
target.DangerousAddRef(ref b);
}
catch
{
if (b)
{
target.DangerousRelease();
b = false;
}
}
finally
{
if (b)
{
_Target = target;
SetHandle(new IntPtr(0)); // make this handle valid
}
}
}
internal static SafeCredentialReference CreateReference(SafeFreeCredentials target)
{
SafeCredentialReference result = new SafeCredentialReference(target);
if (result.IsInvalid)
{
return null;
}
return result;
}
protected override bool ReleaseHandle()
{
SafeFreeCredentials target = _Target;
if (target != null)
{
target.DangerousRelease();
}
_Target = null;
return true;
}
}
}

View File

@ -0,0 +1,707 @@
// -----------------------------------------------------------------------
// <copyright file="SafeDeleteContext.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
internal sealed class SafeDeleteContext : SafeHandle
{
private const string DummyStr = " ";
private static readonly byte[] DummyBytes = new byte[] { 0 };
// ATN: _handle is internal since it is used on PInvokes by other wrapper methods.
// However all such wrappers MUST manually and reliably adjust refCounter of SafeDeleteContext handle.
internal SSPIHandle _handle;
private SafeFreeCredentials _effectiveCredential;
private SafeDeleteContext()
: base(IntPtr.Zero, true)
{
_handle = new SSPIHandle();
}
public override bool IsInvalid
{
get
{
return IsClosed || _handle.IsZero;
}
}
public override string ToString()
{
return _handle.ToString();
}
//-------------------------------------------------------------------
internal static unsafe int InitializeSecurityContext(ref SafeFreeCredentials inCredentials, ref SafeDeleteContext refContext,
string targetName, ContextFlags inFlags, Endianness endianness, SecurityBuffer inSecBuffer, SecurityBuffer[] inSecBuffers,
SecurityBuffer outSecBuffer, ref ContextFlags outFlags)
{
GlobalLog.Assert(outSecBuffer != null, "SafeDeleteContext::InitializeSecurityContext()|outSecBuffer != null");
GlobalLog.Assert(inSecBuffer == null || inSecBuffers == null, "SafeDeleteContext::InitializeSecurityContext()|inSecBuffer == null || inSecBuffers == null");
if (inCredentials == null)
{
throw new ArgumentNullException("inCredentials");
}
SecurityBufferDescriptor inSecurityBufferDescriptor = null;
if (inSecBuffer != null)
{
inSecurityBufferDescriptor = new SecurityBufferDescriptor(1);
}
else if (inSecBuffers != null)
{
inSecurityBufferDescriptor = new SecurityBufferDescriptor(inSecBuffers.Length);
}
SecurityBufferDescriptor outSecurityBufferDescriptor = new SecurityBufferDescriptor(1);
// actually this is returned in outFlags
bool isSspiAllocated = (inFlags & ContextFlags.AllocateMemory) != 0 ? true : false;
int errorCode = -1;
SSPIHandle contextHandle = new SSPIHandle();
if (refContext != null)
{
contextHandle = refContext._handle;
}
// these are pinned user byte arrays passed along with SecurityBuffers
GCHandle[] pinnedInBytes = null;
GCHandle pinnedOutBytes = new GCHandle();
// optional output buffer that may need to be freed
SafeFreeContextBuffer outFreeContextBuffer = null;
try
{
pinnedOutBytes = GCHandle.Alloc(outSecBuffer.token, GCHandleType.Pinned);
SecurityBufferStruct[] inUnmanagedBuffer = new SecurityBufferStruct[inSecurityBufferDescriptor == null ? 1 : inSecurityBufferDescriptor.Count];
fixed (void* inUnmanagedBufferPtr = inUnmanagedBuffer)
{
if (inSecurityBufferDescriptor != null)
{
// Fix Descriptor pointer that points to unmanaged SecurityBuffers
inSecurityBufferDescriptor.UnmanagedPointer = inUnmanagedBufferPtr;
pinnedInBytes = new GCHandle[inSecurityBufferDescriptor.Count];
SecurityBuffer securityBuffer;
for (int index = 0; index < inSecurityBufferDescriptor.Count; ++index)
{
securityBuffer = inSecBuffer != null ? inSecBuffer : inSecBuffers[index];
if (securityBuffer != null)
{
// Copy the SecurityBuffer content into unmanaged place holder
inUnmanagedBuffer[index].count = securityBuffer.size;
inUnmanagedBuffer[index].type = securityBuffer.type;
// use the unmanaged token if it's not null; otherwise use the managed buffer
if (securityBuffer.unmanagedToken != null)
{
inUnmanagedBuffer[index].token = securityBuffer.unmanagedToken.DangerousGetHandle();
}
else if (securityBuffer.token == null || securityBuffer.token.Length == 0)
{
inUnmanagedBuffer[index].token = IntPtr.Zero;
}
else
{
pinnedInBytes[index] = GCHandle.Alloc(securityBuffer.token, GCHandleType.Pinned);
inUnmanagedBuffer[index].token = Marshal.UnsafeAddrOfPinnedArrayElement(securityBuffer.token, securityBuffer.offset);
}
}
}
}
SecurityBufferStruct[] outUnmanagedBuffer = new SecurityBufferStruct[1];
fixed (void* outUnmanagedBufferPtr = outUnmanagedBuffer)
{
// Fix Descriptor pointer that points to unmanaged SecurityBuffers
outSecurityBufferDescriptor.UnmanagedPointer = outUnmanagedBufferPtr;
outUnmanagedBuffer[0].count = outSecBuffer.size;
outUnmanagedBuffer[0].type = outSecBuffer.type;
if (outSecBuffer.token == null || outSecBuffer.token.Length == 0)
{
outUnmanagedBuffer[0].token = IntPtr.Zero;
}
else
{
outUnmanagedBuffer[0].token = Marshal.UnsafeAddrOfPinnedArrayElement(outSecBuffer.token, outSecBuffer.offset);
}
if (isSspiAllocated)
{
outFreeContextBuffer = SafeFreeContextBuffer.CreateEmptyHandle();
}
if (refContext == null || refContext.IsInvalid)
{
refContext = new SafeDeleteContext();
}
if (targetName == null || targetName.Length == 0)
{
targetName = DummyStr;
}
fixed (char* namePtr = targetName)
{
errorCode = MustRunInitializeSecurityContext(
ref inCredentials,
contextHandle.IsZero ? null : &contextHandle,
(byte*)(((object)targetName == (object)DummyStr) ? null : namePtr),
inFlags,
endianness,
inSecurityBufferDescriptor,
refContext,
outSecurityBufferDescriptor,
ref outFlags,
outFreeContextBuffer);
}
GlobalLog.Print("SafeDeleteContext:InitializeSecurityContext Marshalling OUT buffer");
// Get unmanaged buffer with index 0 as the only one passed into PInvoke
outSecBuffer.size = outUnmanagedBuffer[0].count;
outSecBuffer.type = outUnmanagedBuffer[0].type;
if (outSecBuffer.size > 0)
{
outSecBuffer.token = new byte[outSecBuffer.size];
Marshal.Copy(outUnmanagedBuffer[0].token, outSecBuffer.token, 0, outSecBuffer.size);
}
else
{
outSecBuffer.token = null;
}
}
}
}
finally
{
if (pinnedInBytes != null)
{
for (int index = 0; index < pinnedInBytes.Length; index++)
{
if (pinnedInBytes[index].IsAllocated)
{
pinnedInBytes[index].Free();
}
}
}
if (pinnedOutBytes.IsAllocated)
{
pinnedOutBytes.Free();
}
if (outFreeContextBuffer != null)
{
outFreeContextBuffer.Dispose();
}
}
GlobalLog.Leave("SafeDeleteContext::InitializeSecurityContext() unmanaged InitializeSecurityContext()", "errorCode:0x" + errorCode.ToString("x8") + " refContext:" + ValidationHelper.ToString(refContext));
return errorCode;
}
// After PINvoke call the method will fix the handleTemplate.handle with the returned value.
// The caller is responsible for creating a correct SafeFreeContextBuffer_XXX flavour or null can be passed if no handle is returned.
//
// Since it has a CER, this method can't have any references to imports from DLLs that may not exist on the system.
private static unsafe int MustRunInitializeSecurityContext(
ref SafeFreeCredentials inCredentials,
void* inContextPtr,
byte* targetName,
ContextFlags inFlags,
Endianness endianness,
SecurityBufferDescriptor inputBuffer,
SafeDeleteContext outContext,
SecurityBufferDescriptor outputBuffer,
ref ContextFlags attributes,
SafeFreeContextBuffer handleTemplate)
{
int errorCode = (int)SecurityStatus.InvalidHandle;
bool b1 = false;
bool b2 = false;
// Run the body of this method as a non-interruptible block.
RuntimeHelpers.PrepareConstrainedRegions();
try
{
inCredentials.DangerousAddRef(ref b1);
outContext.DangerousAddRef(ref b2);
}
catch (Exception e)
{
if (b1)
{
inCredentials.DangerousRelease();
b1 = false;
}
if (b2)
{
outContext.DangerousRelease();
b2 = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
SSPIHandle credentialHandle = inCredentials._handle;
long timeStamp;
if (!b1)
{
// caller should retry
inCredentials = null;
}
else if (b1 && b2)
{
errorCode = UnsafeNclNativeMethods.SafeNetHandles.InitializeSecurityContextW(
ref credentialHandle,
inContextPtr,
targetName,
inFlags,
0,
endianness,
inputBuffer,
0,
ref outContext._handle,
outputBuffer,
ref attributes,
out timeStamp);
// When a credential handle is first associated with the context we keep credential
// ref count bumped up to ensure ordered finalization.
// If the credential handle has been changed we de-ref the old one and associate the
// context with the new cred handle but only if the call was successful.
if (outContext._effectiveCredential != inCredentials && (errorCode & 0x80000000) == 0)
{
// Disassociate the previous credential handle
if (outContext._effectiveCredential != null)
{
outContext._effectiveCredential.DangerousRelease();
}
outContext._effectiveCredential = inCredentials;
}
else
{
inCredentials.DangerousRelease();
}
outContext.DangerousRelease();
// The idea is that SSPI has allocated a block and filled up outUnmanagedBuffer+8 slot with the pointer.
if (handleTemplate != null)
{
handleTemplate.Set(((SecurityBufferStruct*)outputBuffer.UnmanagedPointer)->token); // ATTN: on 64 BIT that is still +8 cause of 2* c++ unsigned long == 8 bytes
if (handleTemplate.IsInvalid)
{
handleTemplate.SetHandleAsInvalid();
}
}
}
if (inContextPtr == null && (errorCode & 0x80000000) != 0)
{
// an error on the first call, need to set the out handle to invalid value
outContext._handle.SetToInvalid();
}
}
return errorCode;
}
//-------------------------------------------------------------------
internal static unsafe int AcceptSecurityContext(ref SafeFreeCredentials inCredentials, ref SafeDeleteContext refContext,
ContextFlags inFlags, Endianness endianness, SecurityBuffer inSecBuffer, SecurityBuffer[] inSecBuffers, SecurityBuffer outSecBuffer,
ref ContextFlags outFlags)
{
GlobalLog.Assert(outSecBuffer != null, "SafeDeleteContext::AcceptSecurityContext()|outSecBuffer != null");
GlobalLog.Assert(inSecBuffer == null || inSecBuffers == null, "SafeDeleteContext::AcceptSecurityContext()|inSecBuffer == null || inSecBuffers == null");
if (inCredentials == null)
{
throw new ArgumentNullException("inCredentials");
}
SecurityBufferDescriptor inSecurityBufferDescriptor = null;
if (inSecBuffer != null)
{
inSecurityBufferDescriptor = new SecurityBufferDescriptor(1);
}
else if (inSecBuffers != null)
{
inSecurityBufferDescriptor = new SecurityBufferDescriptor(inSecBuffers.Length);
}
SecurityBufferDescriptor outSecurityBufferDescriptor = new SecurityBufferDescriptor(1);
// actually this is returned in outFlags
bool isSspiAllocated = (inFlags & ContextFlags.AllocateMemory) != 0 ? true : false;
int errorCode = -1;
SSPIHandle contextHandle = new SSPIHandle();
if (refContext != null)
{
contextHandle = refContext._handle;
}
// these are pinned user byte arrays passed along with SecurityBuffers
GCHandle[] pinnedInBytes = null;
GCHandle pinnedOutBytes = new GCHandle();
// optional output buffer that may need to be freed
SafeFreeContextBuffer outFreeContextBuffer = null;
try
{
pinnedOutBytes = GCHandle.Alloc(outSecBuffer.token, GCHandleType.Pinned);
SecurityBufferStruct[] inUnmanagedBuffer = new SecurityBufferStruct[inSecurityBufferDescriptor == null ? 1 : inSecurityBufferDescriptor.Count];
fixed (void* inUnmanagedBufferPtr = inUnmanagedBuffer)
{
if (inSecurityBufferDescriptor != null)
{
// Fix Descriptor pointer that points to unmanaged SecurityBuffers
inSecurityBufferDescriptor.UnmanagedPointer = inUnmanagedBufferPtr;
pinnedInBytes = new GCHandle[inSecurityBufferDescriptor.Count];
SecurityBuffer securityBuffer;
for (int index = 0; index < inSecurityBufferDescriptor.Count; ++index)
{
securityBuffer = inSecBuffer != null ? inSecBuffer : inSecBuffers[index];
if (securityBuffer != null)
{
// Copy the SecurityBuffer content into unmanaged place holder
inUnmanagedBuffer[index].count = securityBuffer.size;
inUnmanagedBuffer[index].type = securityBuffer.type;
// use the unmanaged token if it's not null; otherwise use the managed buffer
if (securityBuffer.unmanagedToken != null)
{
inUnmanagedBuffer[index].token = securityBuffer.unmanagedToken.DangerousGetHandle();
}
else if (securityBuffer.token == null || securityBuffer.token.Length == 0)
{
inUnmanagedBuffer[index].token = IntPtr.Zero;
}
else
{
pinnedInBytes[index] = GCHandle.Alloc(securityBuffer.token, GCHandleType.Pinned);
inUnmanagedBuffer[index].token = Marshal.UnsafeAddrOfPinnedArrayElement(securityBuffer.token, securityBuffer.offset);
}
}
}
}
SecurityBufferStruct[] outUnmanagedBuffer = new SecurityBufferStruct[1];
fixed (void* outUnmanagedBufferPtr = outUnmanagedBuffer)
{
// Fix Descriptor pointer that points to unmanaged SecurityBuffers
outSecurityBufferDescriptor.UnmanagedPointer = outUnmanagedBufferPtr;
// Copy the SecurityBuffer content into unmanaged place holder
outUnmanagedBuffer[0].count = outSecBuffer.size;
outUnmanagedBuffer[0].type = outSecBuffer.type;
if (outSecBuffer.token == null || outSecBuffer.token.Length == 0)
{
outUnmanagedBuffer[0].token = IntPtr.Zero;
}
else
{
outUnmanagedBuffer[0].token = Marshal.UnsafeAddrOfPinnedArrayElement(outSecBuffer.token, outSecBuffer.offset);
}
if (isSspiAllocated)
{
outFreeContextBuffer = SafeFreeContextBuffer.CreateEmptyHandle();
}
if (refContext == null || refContext.IsInvalid)
{
refContext = new SafeDeleteContext();
}
errorCode = MustRunAcceptSecurityContext(
ref inCredentials,
contextHandle.IsZero ? null : &contextHandle,
inSecurityBufferDescriptor,
inFlags,
endianness,
refContext,
outSecurityBufferDescriptor,
ref outFlags,
outFreeContextBuffer);
GlobalLog.Print("SafeDeleteContext:AcceptSecurityContext Marshalling OUT buffer");
// Get unmanaged buffer with index 0 as the only one passed into PInvoke
outSecBuffer.size = outUnmanagedBuffer[0].count;
outSecBuffer.type = outUnmanagedBuffer[0].type;
if (outSecBuffer.size > 0)
{
outSecBuffer.token = new byte[outSecBuffer.size];
Marshal.Copy(outUnmanagedBuffer[0].token, outSecBuffer.token, 0, outSecBuffer.size);
}
else
{
outSecBuffer.token = null;
}
}
}
}
finally
{
if (pinnedInBytes != null)
{
for (int index = 0; index < pinnedInBytes.Length; index++)
{
if (pinnedInBytes[index].IsAllocated)
{
pinnedInBytes[index].Free();
}
}
}
if (pinnedOutBytes.IsAllocated)
{
pinnedOutBytes.Free();
}
if (outFreeContextBuffer != null)
{
outFreeContextBuffer.Dispose();
}
}
GlobalLog.Leave("SafeDeleteContext::AcceptSecurityContex() unmanaged AcceptSecurityContex()", "errorCode:0x" + errorCode.ToString("x8") + " refContext:" + ValidationHelper.ToString(refContext));
return errorCode;
}
// After PINvoke call the method will fix the handleTemplate.handle with the returned value.
// The caller is responsible for creating a correct SafeFreeContextBuffer_XXX flavour or null can be passed if no handle is returned.
//
// Since it has a CER, this method can't have any references to imports from DLLs that may not exist on the system.
private static unsafe int MustRunAcceptSecurityContext(
ref SafeFreeCredentials inCredentials,
void* inContextPtr,
SecurityBufferDescriptor inputBuffer,
ContextFlags inFlags,
Endianness endianness,
SafeDeleteContext outContext,
SecurityBufferDescriptor outputBuffer,
ref ContextFlags outFlags,
SafeFreeContextBuffer handleTemplate)
{
int errorCode = (int)SecurityStatus.InvalidHandle;
bool b1 = false;
bool b2 = false;
// Run the body of this method as a non-interruptible block.
RuntimeHelpers.PrepareConstrainedRegions();
try
{
inCredentials.DangerousAddRef(ref b1);
outContext.DangerousAddRef(ref b2);
}
catch (Exception e)
{
if (b1)
{
inCredentials.DangerousRelease();
b1 = false;
}
if (b2)
{
outContext.DangerousRelease();
b2 = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
SSPIHandle credentialHandle = inCredentials._handle;
long timeStamp;
if (!b1)
{
// caller should retry
inCredentials = null;
}
else if (b1 && b2)
{
errorCode = UnsafeNclNativeMethods.SafeNetHandles.AcceptSecurityContext(
ref credentialHandle,
inContextPtr,
inputBuffer,
inFlags,
endianness,
ref outContext._handle,
outputBuffer,
ref outFlags,
out timeStamp);
// When a credential handle is first associated with the context we keep credential
// ref count bumped up to ensure ordered finalization.
// If the credential handle has been changed we de-ref the old one and associate the
// context with the new cred handle but only if the call was successful.
if (outContext._effectiveCredential != inCredentials && (errorCode & 0x80000000) == 0)
{
// Disassociate the previous credential handle
if (outContext._effectiveCredential != null)
{
outContext._effectiveCredential.DangerousRelease();
}
outContext._effectiveCredential = inCredentials;
}
else
{
inCredentials.DangerousRelease();
}
outContext.DangerousRelease();
// The idea is that SSPI has allocated a block and filled up outUnmanagedBuffer+8 slot with the pointer.
if (handleTemplate != null)
{
handleTemplate.Set(((SecurityBufferStruct*)outputBuffer.UnmanagedPointer)->token); // ATTN: on 64 BIT that is still +8 cause of 2* c++ unsigned long == 8 bytes
if (handleTemplate.IsInvalid)
{
handleTemplate.SetHandleAsInvalid();
}
}
}
if (inContextPtr == null && (errorCode & 0x80000000) != 0)
{
// an error on the first call, need to set the out handle to invalid value
outContext._handle.SetToInvalid();
}
}
return errorCode;
}
internal static unsafe int CompleteAuthToken(ref SafeDeleteContext refContext, SecurityBuffer[] inSecBuffers)
{
GlobalLog.Enter("SafeDeleteContext::CompleteAuthToken");
GlobalLog.Print(" refContext = " + ValidationHelper.ToString(refContext));
GlobalLog.Assert(inSecBuffers != null, "SafeDeleteContext::CompleteAuthToken()|inSecBuffers == null");
SecurityBufferDescriptor inSecurityBufferDescriptor = new SecurityBufferDescriptor(inSecBuffers.Length);
int errorCode = (int)SecurityStatus.InvalidHandle;
// these are pinned user byte arrays passed along with SecurityBuffers
GCHandle[] pinnedInBytes = null;
SecurityBufferStruct[] inUnmanagedBuffer = new SecurityBufferStruct[inSecurityBufferDescriptor.Count];
fixed (void* inUnmanagedBufferPtr = inUnmanagedBuffer)
{
// Fix Descriptor pointer that points to unmanaged SecurityBuffers
inSecurityBufferDescriptor.UnmanagedPointer = inUnmanagedBufferPtr;
pinnedInBytes = new GCHandle[inSecurityBufferDescriptor.Count];
SecurityBuffer securityBuffer;
for (int index = 0; index < inSecurityBufferDescriptor.Count; ++index)
{
securityBuffer = inSecBuffers[index];
if (securityBuffer != null)
{
inUnmanagedBuffer[index].count = securityBuffer.size;
inUnmanagedBuffer[index].type = securityBuffer.type;
// use the unmanaged token if it's not null; otherwise use the managed buffer
if (securityBuffer.unmanagedToken != null)
{
inUnmanagedBuffer[index].token = securityBuffer.unmanagedToken.DangerousGetHandle();
}
else if (securityBuffer.token == null || securityBuffer.token.Length == 0)
{
inUnmanagedBuffer[index].token = IntPtr.Zero;
}
else
{
pinnedInBytes[index] = GCHandle.Alloc(securityBuffer.token, GCHandleType.Pinned);
inUnmanagedBuffer[index].token = Marshal.UnsafeAddrOfPinnedArrayElement(securityBuffer.token, securityBuffer.offset);
}
}
}
SSPIHandle contextHandle = new SSPIHandle();
if (refContext != null)
{
contextHandle = refContext._handle;
}
try
{
if (refContext == null || refContext.IsInvalid)
{
refContext = new SafeDeleteContext();
}
bool b = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
refContext.DangerousAddRef(ref b);
}
catch (Exception e)
{
if (b)
{
refContext.DangerousRelease();
b = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
if (b)
{
errorCode = UnsafeNclNativeMethods.SafeNetHandles.CompleteAuthToken(contextHandle.IsZero ? null : &contextHandle, inSecurityBufferDescriptor);
refContext.DangerousRelease();
}
}
}
finally
{
if (pinnedInBytes != null)
{
for (int index = 0; index < pinnedInBytes.Length; index++)
{
if (pinnedInBytes[index].IsAllocated)
{
pinnedInBytes[index].Free();
}
}
}
}
}
GlobalLog.Leave("SafeDeleteContext::CompleteAuthToken() unmanaged CompleteAuthToken()", "errorCode:0x" + errorCode.ToString("x8") + " refContext:" + ValidationHelper.ToString(refContext));
return errorCode;
}
protected override bool ReleaseHandle()
{
if (this._effectiveCredential != null)
{
this._effectiveCredential.DangerousRelease();
}
return UnsafeNclNativeMethods.SafeNetHandles.DeleteSecurityContext(ref _handle) == 0;
}
}
}

View File

@ -0,0 +1,35 @@
// -----------------------------------------------------------------------
// <copyright file="SafeFreeCertContext.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.ConstrainedExecution;
using System.Security;
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Security.Windows
{
[SuppressUnmanagedCodeSecurity]
internal sealed class SafeFreeCertContext : SafeHandleZeroOrMinusOneIsInvalid
{
internal SafeFreeCertContext()
: base(true)
{
}
// This must be ONLY called from this file within a CER.
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal unsafe void Set(IntPtr value)
{
this.handle = value;
}
protected override bool ReleaseHandle()
{
UnsafeNclNativeMethods.SafeNetHandles.CertFreeCertificateContext(handle);
return true;
}
}
}

View File

@ -0,0 +1,148 @@
// -----------------------------------------------------------------------
// <copyright file="SafeFreeContextBuffer.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Security.Windows
{
[SuppressUnmanagedCodeSecurity]
internal sealed class SafeFreeContextBuffer : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeFreeContextBuffer()
: base(true)
{
}
// This must be ONLY called from this file and in the context of a CER
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal unsafe void Set(IntPtr value)
{
this.handle = value;
}
internal static int EnumeratePackages(out int pkgnum, out SafeFreeContextBuffer pkgArray)
{
int res = -1;
res = UnsafeNclNativeMethods.SafeNetHandles.EnumerateSecurityPackagesW(out pkgnum, out pkgArray);
if (res != 0 && pkgArray != null)
{
pkgArray.SetHandleAsInvalid();
}
return res;
}
internal static SafeFreeContextBuffer CreateEmptyHandle()
{
return new SafeFreeContextBuffer();
}
// After PINvoke call the method will fix the refHandle.handle with the returned value.
// The caller is responsible for creating a correct SafeHandle template or null can be passed if no handle is returned.
//
// This method switches between three non-interruptible helper methods. (This method can't be both non-interruptible and
// reference imports from all three DLLs - doing so would cause all three DLLs to try to be bound to.)
public static unsafe int QueryContextAttributes(SafeDeleteContext phContext, ContextAttribute contextAttribute, byte* buffer, SafeHandle refHandle)
{
int status = (int)SecurityStatus.InvalidHandle;
bool b = false;
// We don't want to be interrupted by thread abort exceptions or unexpected out-of-memory errors failing to jit
// one of the following methods. So run within a CER non-interruptible block.
RuntimeHelpers.PrepareConstrainedRegions();
try
{
phContext.DangerousAddRef(ref b);
}
catch (Exception e)
{
if (b)
{
phContext.DangerousRelease();
b = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
if (b)
{
status = UnsafeNclNativeMethods.SafeNetHandles.QueryContextAttributesW(ref phContext._handle, contextAttribute, buffer);
phContext.DangerousRelease();
}
if (status == 0 && refHandle != null)
{
if (refHandle is SafeFreeContextBuffer)
{
((SafeFreeContextBuffer)refHandle).Set(*(IntPtr*)buffer);
}
else
{
((SafeFreeCertContext)refHandle).Set(*(IntPtr*)buffer);
}
}
if (status != 0 && refHandle != null)
{
refHandle.SetHandleAsInvalid();
}
}
return status;
}
public static int SetContextAttributes(SafeDeleteContext phContext, ContextAttribute contextAttribute, byte[] buffer)
{
int status = (int)SecurityStatus.InvalidHandle;
bool b = false;
// We don't want to be interrupted by thread abort exceptions or unexpected out-of-memory errors failing
// to jit one of the following methods. So run within a CER non-interruptible block.
RuntimeHelpers.PrepareConstrainedRegions();
try
{
phContext.DangerousAddRef(ref b);
}
catch (Exception e)
{
if (b)
{
phContext.DangerousRelease();
b = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
if (b)
{
status = UnsafeNclNativeMethods.SafeNetHandles.SetContextAttributesW(
ref phContext._handle, contextAttribute, buffer, buffer.Length);
phContext.DangerousRelease();
}
}
return status;
}
protected override bool ReleaseHandle()
{
return UnsafeNclNativeMethods.SafeNetHandles.FreeContextBuffer(handle) == 0;
}
}
}

View File

@ -0,0 +1,89 @@
// -----------------------------------------------------------------------
// <copyright file="SafeFreeContextBufferChannelBinding.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Security;
using System.Security.Authentication.ExtendedProtection;
namespace Microsoft.AspNet.Security.Windows
{
[SuppressUnmanagedCodeSecurity]
internal sealed class SafeFreeContextBufferChannelBinding : ChannelBinding
{
private int size;
public override int Size
{
get { return size; }
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal unsafe void Set(IntPtr value)
{
this.handle = value;
}
internal static SafeFreeContextBufferChannelBinding CreateEmptyHandle()
{
return new SafeFreeContextBufferChannelBinding();
}
public static unsafe int QueryContextChannelBinding(SafeDeleteContext phContext, ContextAttribute contextAttribute, Bindings* buffer,
SafeFreeContextBufferChannelBinding refHandle)
{
int status = (int)SecurityStatus.InvalidHandle;
bool b = false;
// We don't want to be interrupted by thread abort exceptions or unexpected out-of-memory errors failing to jit
// one of the following methods. So run within a CER non-interruptible block.
RuntimeHelpers.PrepareConstrainedRegions();
try
{
phContext.DangerousAddRef(ref b);
}
catch (Exception e)
{
if (b)
{
phContext.DangerousRelease();
b = false;
}
if (!(e is ObjectDisposedException))
{
throw;
}
}
finally
{
if (b)
{
status = UnsafeNclNativeMethods.SafeNetHandles.QueryContextAttributesW(ref phContext._handle, contextAttribute, buffer);
phContext.DangerousRelease();
}
if (status == 0 && refHandle != null)
{
refHandle.Set((*buffer).pBindings);
refHandle.size = (*buffer).BindingsLength;
}
if (status != 0 && refHandle != null)
{
refHandle.SetHandleAsInvalid();
}
}
return status;
}
protected override bool ReleaseHandle()
{
return UnsafeNclNativeMethods.SafeNetHandles.FreeContextBuffer(handle) == 0;
}
}
}

View File

@ -0,0 +1,199 @@
// -----------------------------------------------------------------------
// <copyright file="SafeFreeCredentials.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
internal sealed class SafeFreeCredentials : SafeHandle
{
internal SSPIHandle _handle; // should be always used as by ref in PINvokes parameters
private SafeFreeCredentials()
: base(IntPtr.Zero, true)
{
_handle = new SSPIHandle();
}
public override bool IsInvalid
{
get { return IsClosed || _handle.IsZero; }
}
protected override bool ReleaseHandle()
{
return UnsafeNclNativeMethods.SafeNetHandles.FreeCredentialsHandle(ref _handle) == 0;
}
public static unsafe int AcquireCredentialsHandle(string package, CredentialUse intent, ref AuthIdentity authdata,
out SafeFreeCredentials outCredential)
{
GlobalLog.Print("SafeFreeCredentials::AcquireCredentialsHandle#1("
+ package + ", "
+ intent + ", "
+ authdata + ")");
int errorCode = -1;
long timeStamp;
outCredential = new SafeFreeCredentials();
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
errorCode = UnsafeNclNativeMethods.SafeNetHandles.AcquireCredentialsHandleW(
null,
package,
(int)intent,
null,
ref authdata,
null,
null,
ref outCredential._handle,
out timeStamp);
}
if (errorCode != 0)
{
outCredential.SetHandleAsInvalid();
}
return errorCode;
}
public static unsafe int AcquireDefaultCredential(string package, CredentialUse intent, out SafeFreeCredentials outCredential)
{
GlobalLog.Print("SafeFreeCredentials::AcquireDefaultCredential("
+ package + ", "
+ intent + ")");
int errorCode = -1;
long timeStamp;
outCredential = new SafeFreeCredentials();
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
errorCode = UnsafeNclNativeMethods.SafeNetHandles.AcquireCredentialsHandleW(
null,
package,
(int)intent,
null,
IntPtr.Zero,
null,
null,
ref outCredential._handle,
out timeStamp);
}
if (errorCode != 0)
{
outCredential.SetHandleAsInvalid();
}
return errorCode;
}
// This overload is only called on Win7+ where SspiEncodeStringsAsAuthIdentity() was used to
// create the authData blob.
public static unsafe int AcquireCredentialsHandle(
string package,
CredentialUse intent,
ref SafeSspiAuthDataHandle authdata,
out SafeFreeCredentials outCredential)
{
int errorCode = -1;
long timeStamp;
outCredential = new SafeFreeCredentials();
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
errorCode = UnsafeNclNativeMethods.SafeNetHandles.AcquireCredentialsHandleW(
null,
package,
(int)intent,
null,
authdata,
null,
null,
ref outCredential._handle,
out timeStamp);
}
if (errorCode != 0)
{
outCredential.SetHandleAsInvalid();
}
return errorCode;
}
public static unsafe int AcquireCredentialsHandle(string package, CredentialUse intent, ref SecureCredential authdata,
out SafeFreeCredentials outCredential)
{
GlobalLog.Print("SafeFreeCredentials::AcquireCredentialsHandle#2("
+ package + ", "
+ intent + ", "
+ authdata + ")");
int errorCode = -1;
long timeStamp;
// If there is a certificate, wrap it into an array.
// Not threadsafe.
IntPtr copiedPtr = authdata.certContextArray;
try
{
IntPtr certArrayPtr = new IntPtr(&copiedPtr);
if (copiedPtr != IntPtr.Zero)
{
authdata.certContextArray = certArrayPtr;
}
outCredential = new SafeFreeCredentials();
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
errorCode = UnsafeNclNativeMethods.SafeNetHandles.AcquireCredentialsHandleW(
null,
package,
(int)intent,
null,
ref authdata,
null,
null,
ref outCredential._handle,
out timeStamp);
}
}
finally
{
authdata.certContextArray = copiedPtr;
}
if (errorCode != 0)
{
outCredential.SetHandleAsInvalid();
}
return errorCode;
}
}
}

View File

@ -0,0 +1,48 @@
// -----------------------------------------------------------------------
// <copyright file="SafeLocalFree.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Security;
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Security.Windows
{
[SuppressUnmanagedCodeSecurity]
internal sealed class SafeLocalFree : SafeHandleZeroOrMinusOneIsInvalid
{
private const int LmemFixed = 0;
private const int NULL = 0;
// This returned handle cannot be modified by the application.
public static SafeLocalFree Zero = new SafeLocalFree(false);
private SafeLocalFree()
: base(true)
{
}
private SafeLocalFree(bool ownsHandle)
: base(ownsHandle)
{
}
public static SafeLocalFree LocalAlloc(int cb)
{
SafeLocalFree result = UnsafeNclNativeMethods.SafeNetHandles.LocalAlloc(LmemFixed, (UIntPtr)cb);
if (result.IsInvalid)
{
result.SetHandleAsInvalid();
throw new OutOfMemoryException();
}
return result;
}
protected override bool ReleaseHandle()
{
return UnsafeNclNativeMethods.SafeNetHandles.LocalFree(handle) == IntPtr.Zero;
}
}
}

View File

@ -0,0 +1,32 @@
// -----------------------------------------------------------------------
// <copyright file="SafeSspiAuthDataHandle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.AspNet.Security.Windows
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Authentication.ExtendedProtection;
using System.Threading;
using Microsoft.Win32.SafeHandles;
[SuppressUnmanagedCodeSecurity]
internal sealed class SafeSspiAuthDataHandle : SafeHandleZeroOrMinusOneIsInvalid
{
public SafeSspiAuthDataHandle()
: base(true)
{
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
protected override bool ReleaseHandle()
{
return UnsafeNclNativeMethods.SspiHelper.SspiFreeAuthIdentity(handle) == SecurityStatus.OK;
}
}
}

View File

@ -0,0 +1,41 @@
// -----------------------------------------------------------------------
// <copyright file="SchProtocols.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
namespace Microsoft.AspNet.Security.Windows
{
// From Schannel.h
[Flags]
internal enum SchProtocols
{
Zero = 0,
PctClient = 0x00000002,
PctServer = 0x00000001,
Pct = (PctClient | PctServer),
Ssl2Client = 0x00000008,
Ssl2Server = 0x00000004,
Ssl2 = (Ssl2Client | Ssl2Server),
Ssl3Client = 0x00000020,
Ssl3Server = 0x00000010,
Ssl3 = (Ssl3Client | Ssl3Server),
Tls10Client = 0x00000080,
Tls10Server = 0x00000040,
Tls10 = (Tls10Client | Tls10Server),
Tls11Client = 0x00000200,
Tls11Server = 0x00000100,
Tls11 = (Tls11Client | Tls11Server),
Tls12Client = 0x00000800,
Tls12Server = 0x00000400,
Tls12 = (Tls12Client | Tls12Server),
Ssl3Tls = (Ssl3 | Tls10),
UniClient = unchecked((int)0x80000000),
UniServer = 0x40000000,
Unified = (UniClient | UniServer),
ClientMask = (PctClient | Ssl2Client | Ssl3Client | Tls10Client | Tls11Client | Tls12Client | UniClient),
ServerMask = (PctServer | Ssl2Server | Ssl3Server | Tls10Server | Tls11Server | Tls12Server | UniServer)
}
}

View File

@ -0,0 +1,44 @@
// -----------------------------------------------------------------------
// <copyright file="SecSizes.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.AspNet.Security.Windows
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
internal class SecSizes
{
public readonly int MaxToken;
public readonly int MaxSignature;
public readonly int BlockSize;
public readonly int SecurityTrailer;
internal unsafe SecSizes(byte[] memory)
{
fixed (void* voidPtr = memory)
{
IntPtr unmanagedAddress = new IntPtr(voidPtr);
try
{
MaxToken = (int)checked((uint)Marshal.ReadInt32(unmanagedAddress));
MaxSignature = (int)checked((uint)Marshal.ReadInt32(unmanagedAddress, 4));
BlockSize = (int)checked((uint)Marshal.ReadInt32(unmanagedAddress, 8));
SecurityTrailer = (int)checked((uint)Marshal.ReadInt32(unmanagedAddress, 12));
}
catch (OverflowException)
{
GlobalLog.Assert(false, "SecSizes::.ctor", "Negative size.");
throw;
}
}
}
public static readonly int SizeOf = Marshal.SizeOf(typeof(SecSizes));
}
}

View File

@ -0,0 +1,56 @@
// -----------------------------------------------------------------------
// <copyright file="SecurityBuffer.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security.Authentication.ExtendedProtection;
namespace Microsoft.AspNet.Security.Windows
{
internal class SecurityBuffer
{
public int size;
public BufferType type;
public byte[] token;
public SafeHandle unmanagedToken;
public int offset;
public SecurityBuffer(byte[] data, int offset, int size, BufferType tokentype)
{
GlobalLog.Assert(offset >= 0 && offset <= (data == null ? 0 : data.Length), "SecurityBuffer::.ctor", "'offset' out of range. [" + offset + "]");
GlobalLog.Assert(size >= 0 && size <= (data == null ? 0 : data.Length - offset), "SecurityBuffer::.ctor", "'size' out of range. [" + size + "]");
this.offset = data == null || offset < 0 ? 0 : Math.Min(offset, data.Length);
this.size = data == null || size < 0 ? 0 : Math.Min(size, data.Length - this.offset);
this.type = tokentype;
this.token = size == 0 ? null : data;
}
public SecurityBuffer(byte[] data, BufferType tokentype)
{
this.size = data == null ? 0 : data.Length;
this.type = tokentype;
this.token = size == 0 ? null : data;
}
public SecurityBuffer(int size, BufferType tokentype)
{
GlobalLog.Assert(size >= 0, "SecurityBuffer::.ctor", "'size' out of range. [" + size.ToString(NumberFormatInfo.InvariantInfo) + "]");
this.size = size;
this.type = tokentype;
this.token = size == 0 ? null : new byte[size];
}
public SecurityBuffer(ChannelBinding binding)
{
this.size = (binding == null ? 0 : binding.Size);
this.type = BufferType.ChannelBindings;
this.unmanagedToken = binding;
}
}
}

View File

@ -0,0 +1,33 @@
// -----------------------------------------------------------------------
// <copyright file="SecurityBufferDescriptor.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe class SecurityBufferDescriptor
{
/*
typedef struct _SecBufferDesc {
ULONG ulVersion;
ULONG cBuffers;
PSecBuffer pBuffers;
} SecBufferDesc, * PSecBufferDesc;
*/
public readonly int Version;
public readonly int Count;
public void* UnmanagedPointer;
public SecurityBufferDescriptor(int count)
{
Version = 0;
Count = count;
UnmanagedPointer = null;
}
}
}

View File

@ -0,0 +1,80 @@
// -----------------------------------------------------------------------
// <copyright file="SecurityPackageInfoClass.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Globalization;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
internal class SecurityPackageInfoClass
{
private int _capabilities = 0;
private short _version = 0;
private short _rpcid = 0;
private int _maxToken = 0;
private string _name = null;
private string _comment = null;
/*
* This is to support SSL under semi trusted environment.
* Note that it is only for SSL with no client cert
*/
internal SecurityPackageInfoClass(SafeHandle safeHandle, int index)
{
if (safeHandle.IsInvalid)
{
GlobalLog.Print("SecurityPackageInfoClass::.ctor() the pointer is invalid: " + (safeHandle.DangerousGetHandle()).ToString("x"));
return;
}
IntPtr unmanagedAddress = IntPtrHelper.Add(safeHandle.DangerousGetHandle(), SecurityPackageInfo.Size * index);
GlobalLog.Print("SecurityPackageInfoClass::.ctor() unmanagedPointer: " + ((long)unmanagedAddress).ToString("x"));
_capabilities = Marshal.ReadInt32(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo), "Capabilities"));
_version = Marshal.ReadInt16(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo), "Version"));
_rpcid = Marshal.ReadInt16(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo), "RPCID"));
_maxToken = Marshal.ReadInt32(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo), "MaxToken"));
IntPtr unmanagedString;
unmanagedString = Marshal.ReadIntPtr(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo), "Name"));
if (unmanagedString != IntPtr.Zero)
{
_name = Marshal.PtrToStringUni(unmanagedString);
GlobalLog.Print("Name: " + Name);
}
unmanagedString = Marshal.ReadIntPtr(unmanagedAddress, (int)Marshal.OffsetOf(typeof(SecurityPackageInfo), "Comment"));
if (unmanagedString != IntPtr.Zero)
{
_comment = Marshal.PtrToStringUni(unmanagedString);
GlobalLog.Print("Comment: " + _comment);
}
GlobalLog.Print("SecurityPackageInfoClass::.ctor(): " + ToString());
}
internal int MaxToken
{
get { return _maxToken; }
}
internal string Name
{
get { return _name; }
}
public override string ToString()
{
return "Capabilities:" + String.Format(CultureInfo.InvariantCulture, "0x{0:x}", _capabilities)
+ " Version:" + _version.ToString(NumberFormatInfo.InvariantInfo)
+ " RPCID:" + _rpcid.ToString(NumberFormatInfo.InvariantInfo)
+ " MaxToken:" + MaxToken.ToString(NumberFormatInfo.InvariantInfo)
+ " Name:" + ((Name == null) ? "(null)" : Name)
+ " Comment:" + ((_comment == null) ? "(null)" : _comment);
}
}
}

View File

@ -0,0 +1,38 @@
// -----------------------------------------------------------------------
// <copyright file="SslConnectionInfo.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
[StructLayout(LayoutKind.Sequential)]
internal class SslConnectionInfo
{
public readonly int Protocol;
public readonly int DataCipherAlg;
public readonly int DataKeySize;
public readonly int DataHashAlg;
public readonly int DataHashKeySize;
public readonly int KeyExchangeAlg;
public readonly int KeyExchKeySize;
internal unsafe SslConnectionInfo(byte[] nativeBuffer)
{
fixed (void* voidPtr = nativeBuffer)
{
IntPtr unmanagedAddress = new IntPtr(voidPtr);
Protocol = Marshal.ReadInt32(unmanagedAddress);
DataCipherAlg = Marshal.ReadInt32(unmanagedAddress, 4);
DataKeySize = Marshal.ReadInt32(unmanagedAddress, 8);
DataHashAlg = Marshal.ReadInt32(unmanagedAddress, 12);
DataHashKeySize = Marshal.ReadInt32(unmanagedAddress, 16);
KeyExchangeAlg = Marshal.ReadInt32(unmanagedAddress, 20);
KeyExchKeySize = Marshal.ReadInt32(unmanagedAddress, 24);
}
}
}
}

View File

@ -0,0 +1,43 @@
// -----------------------------------------------------------------------
// <copyright file="StreamSizes.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Security.Windows
{
[StructLayout(LayoutKind.Sequential)]
internal class StreamSizes
{
public int header;
public int trailer;
public int maximumMessage;
public int buffersCount;
public int blockSize;
internal unsafe StreamSizes(byte[] memory)
{
fixed (void* voidPtr = memory)
{
IntPtr unmanagedAddress = new IntPtr(voidPtr);
try
{
header = (int)checked((uint)Marshal.ReadInt32(unmanagedAddress));
trailer = (int)checked((uint)Marshal.ReadInt32(unmanagedAddress, 4));
maximumMessage = (int)checked((uint)Marshal.ReadInt32(unmanagedAddress, 8));
buffersCount = (int)checked((uint)Marshal.ReadInt32(unmanagedAddress, 12));
blockSize = (int)checked((uint)Marshal.ReadInt32(unmanagedAddress, 16));
}
catch (OverflowException)
{
GlobalLog.Assert(false, "StreamSizes::.ctor", "Negative size.");
throw;
}
}
}
public static readonly int SizeOf = Marshal.SizeOf(typeof(StreamSizes));
}
}

View File

@ -0,0 +1,222 @@
//------------------------------------------------------------------------------
// <copyright file="UnsafeNativeMethods.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
namespace Microsoft.AspNet.Security.Windows
{
[System.Security.SuppressUnmanagedCodeSecurityAttribute]
internal static class UnsafeNclNativeMethods
{
private const string KERNEL32 = "kernel32.dll";
private const string SECUR32 = "secur32.dll";
private const string CRYPT32 = "crypt32.dll";
[DllImport(KERNEL32, ExactSpelling = true, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
internal static extern uint GetCurrentThreadId();
[System.Security.SuppressUnmanagedCodeSecurityAttribute]
internal static class SafeNetHandles
{
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern int FreeContextBuffer(
[In] IntPtr contextBuffer);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern int FreeCredentialsHandle(
ref SSPIHandle handlePtr);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern int DeleteSecurityContext(
ref SSPIHandle handlePtr);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static unsafe extern int AcceptSecurityContext(
ref SSPIHandle credentialHandle,
[In] void* inContextPtr,
[In] SecurityBufferDescriptor inputBuffer,
[In] ContextFlags inFlags,
[In] Endianness endianness,
ref SSPIHandle outContextPtr,
[In, Out] SecurityBufferDescriptor outputBuffer,
[In, Out] ref ContextFlags attributes,
out long timeStamp);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static unsafe extern int QueryContextAttributesW(
ref SSPIHandle contextHandle,
[In] ContextAttribute attribute,
[In] void* buffer);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static unsafe extern int SetContextAttributesW(
ref SSPIHandle contextHandle,
[In] ContextAttribute attribute,
[In] byte[] buffer,
[In] int bufferSize);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
internal static extern int EnumerateSecurityPackagesW(
[Out] out int pkgnum,
[Out] out SafeFreeContextBuffer handle);
[DllImport(SECUR32, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
internal static unsafe extern int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
[In] void* logonID,
[In] ref AuthIdentity authdata,
[In] void* keyCallback,
[In] void* keyArgument,
ref SSPIHandle handlePtr,
[Out] out long timeStamp);
[DllImport(SECUR32, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
internal static unsafe extern int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
[In] void* logonID,
[In] IntPtr zero,
[In] void* keyCallback,
[In] void* keyArgument,
ref SSPIHandle handlePtr,
[Out] out long timeStamp);
// Win7+
[DllImport(SECUR32, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
internal static unsafe extern int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
[In] void* logonID,
[In] SafeSspiAuthDataHandle authdata,
[In] void* keyCallback,
[In] void* keyArgument,
ref SSPIHandle handlePtr,
[Out] out long timeStamp);
[DllImport(SECUR32, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
internal static unsafe extern int AcquireCredentialsHandleW(
[In] string principal,
[In] string moduleName,
[In] int usage,
[In] void* logonID,
[In] ref SecureCredential authData,
[In] void* keyCallback,
[In] void* keyArgument,
ref SSPIHandle handlePtr,
[Out] out long timeStamp);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static unsafe extern int InitializeSecurityContextW(
ref SSPIHandle credentialHandle,
[In] void* inContextPtr,
[In] byte* targetName,
[In] ContextFlags inFlags,
[In] int reservedI,
[In] Endianness endianness,
[In] SecurityBufferDescriptor inputBuffer,
[In] int reservedII,
ref SSPIHandle outContextPtr,
[In, Out] SecurityBufferDescriptor outputBuffer,
[In, Out] ref ContextFlags attributes,
out long timeStamp);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static unsafe extern int CompleteAuthToken(
[In] void* inContextPtr,
[In, Out] SecurityBufferDescriptor inputBuffers);
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
internal static extern int QuerySecurityContextToken(ref SSPIHandle phContext, [Out] out SafeCloseHandle handle);
[DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern bool CloseHandle(IntPtr handle);
[DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)]
internal static extern SafeLocalFree LocalAlloc(int uFlags, UIntPtr sizetdwBytes);
[DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern IntPtr LocalFree(IntPtr handle);
[DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern unsafe bool FreeLibrary([In] IntPtr hModule);
[DllImport(CRYPT32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern void CertFreeCertificateChain(
[In] IntPtr pChainContext);
[DllImport(CRYPT32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern void CertFreeCertificateChainList(
[In] IntPtr ppChainContext);
[DllImport(CRYPT32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern bool CertFreeCertificateContext( // Suppressing returned status check, it's always==TRUE,
[In] IntPtr certContext);
[DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern IntPtr GlobalFree(IntPtr handle);
}
[System.Security.SuppressUnmanagedCodeSecurityAttribute]
internal static class NativeNTSSPI
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
internal static extern int EncryptMessage(
ref SSPIHandle contextHandle,
[In] uint qualityOfProtection,
[In, Out] SecurityBufferDescriptor inputOutput,
[In] uint sequenceNumber);
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
internal static unsafe extern int DecryptMessage(
[In] ref SSPIHandle contextHandle,
[In, Out] SecurityBufferDescriptor inputOutput,
[In] uint sequenceNumber,
uint* qualityOfProtection);
} // class UnsafeNclNativeMethods.NativeNTSSPI
[SuppressUnmanagedCodeSecurityAttribute]
internal static class SspiHelper
{
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
internal static unsafe extern SecurityStatus SspiFreeAuthIdentity(
[In] IntPtr authData);
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage", Justification = "Implementation requires unmanaged code usage")]
[DllImport(SECUR32, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)]
internal static unsafe extern SecurityStatus SspiEncodeStringsAsAuthIdentity(
[In] string userName,
[In] string domainName,
[In] string password,
[Out] out SafeSspiAuthDataHandle authData);
}
}
}

View File

@ -0,0 +1,70 @@
// -----------------------------------------------------------------------
// <copyright file="NegotiationInfoClass.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.AspNet.Security.Windows
{
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
internal class NegotiationInfoClass
{
internal const string NTLM = "NTLM";
internal const string Kerberos = "Kerberos";
internal const string WDigest = "WDigest";
internal const string Digest = "Digest";
internal const string Negotiate = "Negotiate";
internal string AuthenticationPackage;
internal NegotiationInfoClass(SafeHandle safeHandle, int negotiationState)
{
if (safeHandle.IsInvalid)
{
GlobalLog.Print("NegotiationInfoClass::.ctor() the handle is invalid:" + (safeHandle.DangerousGetHandle()).ToString("x"));
return;
}
IntPtr packageInfo = safeHandle.DangerousGetHandle();
GlobalLog.Print("NegotiationInfoClass::.ctor() packageInfo:" + packageInfo.ToString("x8") + " negotiationState:" + negotiationState.ToString("x8"));
const int SECPKG_NEGOTIATION_COMPLETE = 0;
const int SECPKG_NEGOTIATION_OPTIMISTIC = 1;
// const int SECPKG_NEGOTIATION_IN_PROGRESS = 2;
// const int SECPKG_NEGOTIATION_DIRECT = 3;
// const int SECPKG_NEGOTIATION_TRY_MULTICRED = 4;
if (negotiationState == SECPKG_NEGOTIATION_COMPLETE || negotiationState == SECPKG_NEGOTIATION_OPTIMISTIC)
{
IntPtr unmanagedString = Marshal.ReadIntPtr(packageInfo, SecurityPackageInfo.NameOffest);
string name = null;
if (unmanagedString != IntPtr.Zero)
{
name = Marshal.PtrToStringUni(unmanagedString);
}
GlobalLog.Print("NegotiationInfoClass::.ctor() packageInfo:" + packageInfo.ToString("x8") + " negotiationState:" + negotiationState.ToString("x8") + " name:" + ValidationHelper.ToString(name));
// an optimization for future string comparisons
if (string.Compare(name, Kerberos, StringComparison.OrdinalIgnoreCase) == 0)
{
AuthenticationPackage = Kerberos;
}
else if (string.Compare(name, NTLM, StringComparison.OrdinalIgnoreCase) == 0)
{
AuthenticationPackage = NTLM;
}
else if (string.Compare(name, WDigest, StringComparison.OrdinalIgnoreCase) == 0)
{
AuthenticationPackage = WDigest;
}
else
{
AuthenticationPackage = name;
}
}
}
}
}

View File

@ -0,0 +1,109 @@
// -----------------------------------------------------------------------
// <copyright file="HttpListenerPrefixCollection.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
namespace Microsoft.AspNet.Security.Windows
{
internal class PrefixCollection : ICollection<string>
{
private WindowsAuthMiddleware _winAuth;
internal PrefixCollection(WindowsAuthMiddleware winAuth)
{
_winAuth = winAuth;
}
public int Count
{
get
{
return _winAuth._uriPrefixes.Count;
}
}
public bool IsSynchronized
{
get
{
return false;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public void CopyTo(Array array, int offset)
{
if (Count > array.Length)
{
throw new ArgumentOutOfRangeException("array", SR.GetString(SR.net_array_too_small));
}
if (offset + Count > array.Length)
{
throw new ArgumentOutOfRangeException("offset");
}
int index = 0;
foreach (string uriPrefix in _winAuth._uriPrefixes.Keys)
{
array.SetValue(uriPrefix, offset + index++);
}
}
public void CopyTo(string[] array, int offset)
{
if (Count > array.Length)
{
throw new ArgumentOutOfRangeException("array", SR.GetString(SR.net_array_too_small));
}
if (offset + Count > array.Length)
{
throw new ArgumentOutOfRangeException("offset");
}
int index = 0;
foreach (string uriPrefix in _winAuth._uriPrefixes.Keys)
{
array[offset + index++] = uriPrefix;
}
}
public void Add(string uriPrefix)
{
_winAuth.AddPrefix(uriPrefix);
}
public bool Contains(string uriPrefix)
{
return _winAuth._uriPrefixes.Contains(uriPrefix);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerator<string> GetEnumerator()
{
return new PrefixEnumerator(_winAuth._uriPrefixes.Keys.GetEnumerator());
}
public bool Remove(string uriPrefix)
{
return _winAuth.RemovePrefix(uriPrefix);
}
public void Clear()
{
_winAuth.RemoveAll(true);
}
}
}

View File

@ -0,0 +1,51 @@
//------------------------------------------------------------------------------
// <copyright file="PrefixEnumerator.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System.Collections;
using System.Collections.Generic;
namespace Microsoft.AspNet.Security.Windows
{
internal class PrefixEnumerator : IEnumerator<string>
{
private IEnumerator enumerator;
internal PrefixEnumerator(IEnumerator enumerator)
{
this.enumerator = enumerator;
}
public string Current
{
get
{
return (string)enumerator.Current;
}
}
object System.Collections.IEnumerator.Current
{
get
{
return enumerator.Current;
}
}
public bool MoveNext()
{
return enumerator.MoveNext();
}
public void Dispose()
{
}
void System.Collections.IEnumerator.Reset()
{
enumerator.Reset();
}
}
}

View File

@ -0,0 +1,42 @@
// -----------------------------------------------------------------------
// <copyright file="AssemblyInfo.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Microsoft.AspNet.Security.Windows")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Microsoft.AspNet.Security.Windows")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("1f471909-581f-4060-a147-430891e9c3c1")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("0.5")]
[assembly: AssemblyVersion("0.5")]
[assembly: AssemblyFileVersion("0.5.40117.0")]

View File

@ -0,0 +1,368 @@
// -----------------------------------------------------------------------
// <copyright file="ServiceNameStore.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Net;
using System.Security.Authentication.ExtendedProtection;
namespace Microsoft.AspNet.Security.Windows
{
internal class ServiceNameStore
{
private List<string> serviceNames;
private ServiceNameCollection serviceNameCollection;
public ServiceNameStore()
{
serviceNames = new List<string>();
serviceNameCollection = null; // set only when needed (due to expensive item-by-item copy)
}
public ServiceNameCollection ServiceNames
{
get
{
if (serviceNameCollection == null)
{
serviceNameCollection = new ServiceNameCollection(serviceNames);
}
return serviceNameCollection;
}
}
private bool AddSingleServiceName(string spn)
{
spn = NormalizeServiceName(spn);
if (Contains(spn))
{
return false;
}
else
{
serviceNames.Add(spn);
return true;
}
}
public bool Add(string uriPrefix)
{
Debug.Assert(!String.IsNullOrEmpty(uriPrefix));
string[] newServiceNames = BuildServiceNames(uriPrefix);
bool addedAny = false;
foreach (string spn in newServiceNames)
{
if (AddSingleServiceName(spn))
{
addedAny = true;
if (Logging.On)
{
Logging.PrintInfo(Logging.HttpListener, "ServiceNameStore#" +
ValidationHelper.HashString(this) + "::Add() "
+ SR.GetString(SR.net_log_listener_spn_add, spn, uriPrefix));
}
}
}
if (addedAny)
{
serviceNameCollection = null;
}
else if (Logging.On)
{
Logging.PrintInfo(Logging.HttpListener, "ServiceNameStore#" +
ValidationHelper.HashString(this) + "::Add() "
+ SR.GetString(SR.net_log_listener_spn_not_add, uriPrefix));
}
return addedAny;
}
public bool Remove(string uriPrefix)
{
Debug.Assert(!String.IsNullOrEmpty(uriPrefix));
string newServiceName = BuildSimpleServiceName(uriPrefix);
newServiceName = NormalizeServiceName(newServiceName);
bool needToRemove = Contains(newServiceName);
if (needToRemove)
{
serviceNames.Remove(newServiceName);
serviceNameCollection = null; // invalidate (readonly) ServiceNameCollection
}
if (Logging.On)
{
if (needToRemove)
{
Logging.PrintInfo(Logging.HttpListener, "ServiceNameStore#" +
ValidationHelper.HashString(this) + "::Remove() "
+ SR.GetString(SR.net_log_listener_spn_remove, newServiceName, uriPrefix));
}
else
{
Logging.PrintInfo(Logging.HttpListener, "ServiceNameStore#" +
ValidationHelper.HashString(this) + "::Remove() "
+ SR.GetString(SR.net_log_listener_spn_not_remove, uriPrefix));
}
}
return needToRemove;
}
// Assumes already normalized
private bool Contains(string newServiceName)
{
if (newServiceName == null)
{
return false;
}
return Contains(newServiceName, serviceNames);
}
// Assumes searchServiceName and serviceNames have already been normalized
internal static bool Contains(string searchServiceName, ICollection serviceNames)
{
Debug.Assert(serviceNames != null);
Debug.Assert(!String.IsNullOrEmpty(searchServiceName));
foreach (string serviceName in serviceNames)
{
if (Match(serviceName, searchServiceName))
{
return true;
}
}
return false;
}
// Assumes already normalized
internal static bool Match(string serviceName1, string serviceName2)
{
return (String.Compare(serviceName1, serviceName2, StringComparison.OrdinalIgnoreCase) == 0);
}
public void Clear()
{
serviceNames.Clear();
serviceNameCollection = null; // invalidate (readonly) ServiceNameCollection
}
private string ExtractHostname(string uriPrefix, bool allowInvalidUriStrings)
{
if (Uri.IsWellFormedUriString(uriPrefix, UriKind.Absolute))
{
Uri hostUri = new Uri(uriPrefix);
return hostUri.Host;
}
else if (allowInvalidUriStrings)
{
int i = uriPrefix.IndexOf("://") + 3;
int j = i;
bool inSquareBrackets = false;
while (j < uriPrefix.Length && uriPrefix[j] != '/' && (uriPrefix[j] != ':' || inSquareBrackets))
{
if (uriPrefix[j] == '[')
{
if (inSquareBrackets)
{
j = i;
break;
}
inSquareBrackets = true;
}
if (inSquareBrackets && uriPrefix[j] == ']')
{
inSquareBrackets = false;
}
j++;
}
return uriPrefix.Substring(i, j - i);
}
return null;
}
public string BuildSimpleServiceName(string uriPrefix)
{
string hostname = ExtractHostname(uriPrefix, false);
if (hostname != null)
{
return "HTTP/" + hostname;
}
else
{
return null;
}
}
public string[] BuildServiceNames(string uriPrefix)
{
string hostname = ExtractHostname(uriPrefix, true);
IPAddress ipAddress = null;
if (String.Compare(hostname, "*", StringComparison.InvariantCultureIgnoreCase) == 0 ||
String.Compare(hostname, "+", StringComparison.InvariantCultureIgnoreCase) == 0 ||
IPAddress.TryParse(hostname, out ipAddress))
{
// for a wildcard, register the machine name. If the caller doesn't have DNS permission
// or the query fails for some reason, don't add an SPN.
try
{
string machineName = Dns.GetHostEntry(String.Empty).HostName;
return new string[] { "HTTP/" + machineName };
}
catch (System.Net.Sockets.SocketException)
{
return new string[0];
}
catch (System.Security.SecurityException)
{
return new string[0];
}
}
else if (!hostname.Contains("."))
{
// for a dotless name, try to resolve the FQDN. If the caller doesn't have DNS permission
// or the query fails for some reason, add only the dotless name.
try
{
string fqdn = Dns.GetHostEntry(hostname).HostName;
return new string[] { "HTTP/" + hostname, "HTTP/" + fqdn };
}
catch (System.Net.Sockets.SocketException)
{
return new string[] { "HTTP/" + hostname };
}
catch (System.Security.SecurityException)
{
return new string[] { "HTTP/" + hostname };
}
}
else
{
return new string[] { "HTTP/" + hostname };
}
}
// Normalizes any punycode to unicode in an Service Name (SPN) host.
// If the algorithm fails at any point then the original input is returned.
// ServiceName is in one of the following forms:
// prefix/host
// prefix/host:port
// prefix/host/DistinguishedName
// prefix/host:port/DistinguishedName
internal static string NormalizeServiceName(string inputServiceName)
{
if (string.IsNullOrWhiteSpace(inputServiceName))
{
return inputServiceName;
}
// Separate out the prefix
int shashIndex = inputServiceName.IndexOf('/');
if (shashIndex < 0)
{
return inputServiceName;
}
string prefix = inputServiceName.Substring(0, shashIndex + 1); // Includes slash
string hostPortAndDistinguisher = inputServiceName.Substring(shashIndex + 1); // Excludes slash
if (string.IsNullOrWhiteSpace(hostPortAndDistinguisher))
{
return inputServiceName;
}
string host = hostPortAndDistinguisher;
string port = string.Empty;
string distinguisher = string.Empty;
// Check for the absence of a port or distinguisher.
UriHostNameType hostType = Uri.CheckHostName(hostPortAndDistinguisher);
if (hostType == UriHostNameType.Unknown)
{
string hostAndPort = hostPortAndDistinguisher;
// Check for distinguisher
int nextSlashIndex = hostPortAndDistinguisher.IndexOf('/');
if (nextSlashIndex >= 0)
{
// host:port/distinguisher or host/distinguisher
hostAndPort = hostPortAndDistinguisher.Substring(0, nextSlashIndex); // Excludes Slash
distinguisher = hostPortAndDistinguisher.Substring(nextSlashIndex); // Includes Slash
host = hostAndPort; // We don't know if there is a port yet.
// No need to validate the distinguisher
}
// Check for port
int colonIndex = hostAndPort.LastIndexOf(':'); // Allow IPv6 addresses
if (colonIndex >= 0)
{
// host:port
host = hostAndPort.Substring(0, colonIndex); // Excludes colon
port = hostAndPort.Substring(colonIndex + 1); // Excludes colon
// Loosely validate the port just to make sure it was a port and not something else
UInt16 portValue;
if (!UInt16.TryParse(port, NumberStyles.Integer, CultureInfo.InvariantCulture, out portValue))
{
return inputServiceName;
}
// Re-include the colon for the final output. Do not change the port format.
port = hostAndPort.Substring(colonIndex);
}
hostType = Uri.CheckHostName(host); // Revaidate the host
}
if (hostType != UriHostNameType.Dns)
{
// UriHostNameType.IPv4, UriHostNameType.IPv6: Do not normalize IPv4/6 hosts.
// UriHostNameType.Basic: This is never returned by CheckHostName today
// UriHostNameType.Unknown: Nothing recognizable to normalize
// default Some new UriHostNameType?
return inputServiceName;
}
// Now we have a valid DNS host, normalize it.
Uri constructedUri;
// This shouldn't fail, but we need to avoid any unexpected exceptions on this code path.
if (!Uri.TryCreate(Uri.UriSchemeHttp + Uri.SchemeDelimiter + host, UriKind.Absolute, out constructedUri))
{
return inputServiceName;
}
string normalizedHost = constructedUri.GetComponents(
UriComponents.NormalizedHost, UriFormat.SafeUnescaped);
string normalizedServiceName = string.Format(CultureInfo.InvariantCulture,
"{0}{1}{2}{3}", prefix, normalizedHost, port, distinguisher);
// Don't return the new one unless we absolutely have to. It may have only changed casing.
if (String.Compare(inputServiceName, normalizedServiceName, StringComparison.OrdinalIgnoreCase) == 0)
{
return inputServiceName;
}
return normalizedServiceName;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Owin" version="1.0" targetFramework="net45" />
</packages>

View File

@ -0,0 +1,14 @@
{
"version": "0.1-alpha-*",
"dependencies": {
},
"compilationOptions" : { "allowUnsafe": true },
"configurations":
{
"net45" : {
"dependencies": {
"Owin": "1.0"
}
}
}
}

View File

@ -0,0 +1,224 @@
//------------------------------------------------------------------------------
// <copyright file="_ListenerAsyncResult.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Server.WebListener
{
internal unsafe class AsyncAcceptContext : IAsyncResult, IDisposable
{
internal static readonly IOCompletionCallback IOCallback = new IOCompletionCallback(IOWaitCallback);
private TaskCompletionSource<RequestContext> _tcs;
private OwinWebListener _server;
private NativeRequestContext _nativeRequestContext;
internal AsyncAcceptContext(OwinWebListener server)
{
_server = server;
_tcs = new TaskCompletionSource<RequestContext>();
_nativeRequestContext = new NativeRequestContext(this);
}
internal Task<RequestContext> Task
{
get
{
return _tcs.Task;
}
}
private TaskCompletionSource<RequestContext> Tcs
{
get
{
return _tcs;
}
}
private OwinWebListener Server
{
get
{
return _server;
}
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Redirecting to callback")]
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by callback")]
private static void IOCompleted(AsyncAcceptContext asyncResult, uint errorCode, uint numBytes)
{
bool complete = false;
try
{
if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
{
asyncResult.Tcs.TrySetException(new WebListenerException((int)errorCode));
complete = true;
}
else
{
OwinWebListener server = asyncResult.Server;
if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{
// at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
// points to it we need to hook up our authentication handling code here.
bool stoleBlob = false;
try
{
if (server.ValidateRequest(asyncResult._nativeRequestContext))
{
stoleBlob = true;
RequestContext requestContext = new RequestContext(server, asyncResult._nativeRequestContext);
asyncResult.Tcs.TrySetResult(requestContext);
complete = true;
}
}
finally
{
if (stoleBlob)
{
// The request has been handed to the user, which means this code can't reuse the blob. Reset it here.
asyncResult._nativeRequestContext = complete ? null : new NativeRequestContext(asyncResult);
}
else
{
asyncResult._nativeRequestContext.Reset(0, 0);
}
}
}
else
{
asyncResult._nativeRequestContext.Reset(asyncResult._nativeRequestContext.RequestBlob->RequestId, numBytes);
}
// We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
if (!complete)
{
uint statusCode = asyncResult.QueueBeginGetContext();
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
{
// someother bad error, possible(?) return values are:
// ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
asyncResult.Tcs.TrySetException(new WebListenerException((int)statusCode));
complete = true;
}
}
if (!complete)
{
return;
}
}
if (complete)
{
asyncResult.Dispose();
}
}
catch (Exception exception)
{
// Logged by caller
asyncResult.Tcs.TrySetException(exception);
asyncResult.Dispose();
}
}
private static unsafe void IOWaitCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
{
// take the ListenerAsyncResult object from the state
Overlapped callbackOverlapped = Overlapped.Unpack(nativeOverlapped);
AsyncAcceptContext asyncResult = (AsyncAcceptContext)callbackOverlapped.AsyncResult;
IOCompleted(asyncResult, errorCode, numBytes);
}
internal uint QueueBeginGetContext()
{
uint statusCode = UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS;
bool retry;
do
{
retry = false;
uint bytesTransferred = 0;
statusCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveHttpRequest(
Server.RequestQueueHandle,
_nativeRequestContext.RequestBlob->RequestId,
(uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY,
_nativeRequestContext.RequestBlob,
_nativeRequestContext.Size,
&bytesTransferred,
_nativeRequestContext.NativeOverlapped);
if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_INVALID_PARAMETER && _nativeRequestContext.RequestBlob->RequestId != 0)
{
// we might get this if somebody stole our RequestId,
// set RequestId to 0 and start all over again with the buffer we just allocated
// BUGBUG: how can someone steal our request ID? seems really bad and in need of fix.
_nativeRequestContext.RequestBlob->RequestId = 0;
retry = true;
}
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
{
// the buffer was not big enough to fit the headers, we need
// to read the RequestId returned, allocate a new buffer of the required size
_nativeRequestContext.Reset(_nativeRequestContext.RequestBlob->RequestId, bytesTransferred);
retry = true;
}
else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS
&& OwinWebListener.SkipIOCPCallbackOnSuccess)
{
// IO operation completed synchronously - callback won't be called to signal completion.
IOCompleted(this, statusCode, bytesTransferred);
}
}
while (retry);
return statusCode;
}
public object AsyncState
{
get { return _tcs.Task.AsyncState; }
}
public WaitHandle AsyncWaitHandle
{
get { return ((IAsyncResult)_tcs.Task).AsyncWaitHandle; }
}
public bool CompletedSynchronously
{
get { return ((IAsyncResult)_tcs.Task).CompletedSynchronously; }
}
public bool IsCompleted
{
get { return _tcs.Task.IsCompleted; }
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_nativeRequestContext != null)
{
_nativeRequestContext.ReleasePins();
_nativeRequestContext.Dispose();
}
}
}
}
}

View File

@ -0,0 +1,129 @@
// -----------------------------------------------------------------------
// <copyright file="AuthenticationManager.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Server.WebListener
{
// See the native HTTP_SERVER_AUTHENTICATION_INFO structure documentation for additional information.
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364638(v=vs.85).aspx
/// <summary>
/// Exposes the Http.Sys authentication configurations.
/// </summary>
public sealed class AuthenticationManager
{
#if NET45
private static readonly int AuthInfoSize =
Marshal.SizeOf(typeof(UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_AUTHENTICATION_INFO));
#else
private static readonly int AuthInfoSize =
Marshal.SizeOf<UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_AUTHENTICATION_INFO>();
#endif
private OwinWebListener _server;
AuthenticationType _authTypes;
internal AuthenticationManager(OwinWebListener context)
{
_server = context;
_authTypes = AuthenticationType.None;
}
#region Properties
public AuthenticationType AuthenticationTypes
{
get
{
return _authTypes;
}
set
{
_authTypes = value;
SetServerSecurity();
}
}
#endregion Properties
private unsafe void SetServerSecurity()
{
UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_AUTHENTICATION_INFO authInfo =
new UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_AUTHENTICATION_INFO();
authInfo.Flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
authInfo.AuthSchemes = (UnsafeNclNativeMethods.HttpApi.HTTP_AUTH_TYPES)_authTypes;
// TODO:
// NTLM auth sharing (on by default?) DisableNTLMCredentialCaching
// Kerberos auth sharing (off by default?) HTTP_AUTH_EX_FLAG_ENABLE_KERBEROS_CREDENTIAL_CACHING
// Mutual Auth - ReceiveMutualAuth
// Digest domain and realm - HTTP_SERVER_AUTHENTICATION_DIGEST_PARAMS
// Basic realm - HTTP_SERVER_AUTHENTICATION_BASIC_PARAMS
IntPtr infoptr = new IntPtr(&authInfo);
_server.SetUrlGroupProperty(
UnsafeNclNativeMethods.HttpApi.HTTP_SERVER_PROPERTY.HttpServerAuthenticationProperty,
infoptr, (uint)AuthInfoSize);
}
internal void SetAuthenticationChallenge(Response response)
{
if (_authTypes == AuthenticationType.None)
{
return;
}
IList<string> challenges = new List<string>();
// Order by strength.
if ((_authTypes & AuthenticationType.Kerberos) == AuthenticationType.Kerberos)
{
challenges.Add("Kerberos");
}
if ((_authTypes & AuthenticationType.Negotiate) == AuthenticationType.Negotiate)
{
challenges.Add("Negotiate");
}
if ((_authTypes & AuthenticationType.Ntlm) == AuthenticationType.Ntlm)
{
challenges.Add("NTLM");
}
if ((_authTypes & AuthenticationType.Digest) == AuthenticationType.Digest)
{
// TODO:
throw new NotImplementedException("Digest challenge generation has not been implemented.");
// challenges.Add("Digest");
}
if ((_authTypes & AuthenticationType.Basic) == AuthenticationType.Basic)
{
// TODO: Realm
challenges.Add("Basic");
}
// Append to the existing header, if any. Some clients (IE, Chrome) require each challenges to be sent on their own line/header.
string[] oldValues;
string[] newValues;
if (response.Headers.TryGetValue(HttpKnownHeaderNames.WWWAuthenticate, out oldValues))
{
newValues = new string[oldValues.Length + challenges.Count];
Array.Copy(oldValues, newValues, oldValues.Length);
challenges.CopyTo(newValues, oldValues.Length);
}
else
{
newValues = new string[challenges.Count];
challenges.CopyTo(newValues, 0);
}
response.Headers[HttpKnownHeaderNames.WWWAuthenticate] = newValues;
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Server.WebListener
{
[Flags]
public enum AuthenticationType
{
None = 0x0,
Basic = 0x1,
Digest = 0x2,
Ntlm = 0x4,
Negotiate = 0x8,
Kerberos = 0x10,
}
}

View File

@ -0,0 +1,63 @@
// -----------------------------------------------------------------------
// <copyright file="Constants.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
namespace Microsoft.AspNet.Server.WebListener
{
internal static class Constants
{
internal const string VersionKey = "owin.Version";
internal const string OwinVersion = "1.0";
internal const string CallCancelledKey = "owin.CallCancelled";
internal const string ServerCapabilitiesKey = "server.Capabilities";
internal const string RequestBodyKey = "owin.RequestBody";
internal const string RequestHeadersKey = "owin.RequestHeaders";
internal const string RequestSchemeKey = "owin.RequestScheme";
internal const string RequestMethodKey = "owin.RequestMethod";
internal const string RequestPathBaseKey = "owin.RequestPathBase";
internal const string RequestPathKey = "owin.RequestPath";
internal const string RequestQueryStringKey = "owin.RequestQueryString";
internal const string HttpRequestProtocolKey = "owin.RequestProtocol";
internal const string HttpResponseProtocolKey = "owin.ResponseProtocol";
internal const string ResponseStatusCodeKey = "owin.ResponseStatusCode";
internal const string ResponseReasonPhraseKey = "owin.ResponseReasonPhrase";
internal const string ResponseHeadersKey = "owin.ResponseHeaders";
internal const string ResponseBodyKey = "owin.ResponseBody";
internal const string ClientCertifiateKey = "ssl.ClientCertificate";
internal const string RemoteIpAddressKey = "server.RemoteIpAddress";
internal const string RemotePortKey = "server.RemotePort";
internal const string LocalIpAddressKey = "server.LocalIpAddress";
internal const string LocalPortKey = "server.LocalPort";
internal const string IsLocalKey = "server.IsLocal";
internal const string ServerOnSendingHeadersKey = "server.OnSendingHeaders";
internal const string ServerLoggerFactoryKey = "server.LoggerFactory";
internal const string OpaqueVersionKey = "opaque.Version";
internal const string OpaqueVersion = "1.0";
internal const string OpaqueFuncKey = "opaque.Upgrade";
internal const string OpaqueStreamKey = "opaque.Stream";
internal const string OpaqueCallCancelledKey = "opaque.CallCancelled";
internal const string SendFileVersionKey = "sendfile.Version";
internal const string SendFileVersion = "1.0";
internal const string SendFileSupportKey = "sendfile.Support";
internal const string SendFileConcurrencyKey = "sendfile.Concurrency";
internal const string Overlapped = "Overlapped";
internal const string HttpScheme = "http";
internal const string HttpsScheme = "https";
internal const string SchemeDelimiter = "://";
internal static Version V1_0 = new Version(1, 0);
internal static Version V1_1 = new Version(1, 1);
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<Dictionary>
<Words>
<Recognized>
<Word>Owin</Word>
</Recognized>
</Words>
</Dictionary>

View File

@ -0,0 +1,51 @@
// -----------------------------------------------------------------------
// <copyright file="DictionaryExtensions.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Linq;
using System.Text;
namespace System.Collections.Generic
{
internal static class DictionaryExtensions
{
internal static void Append(this IDictionary<string, string[]> dictionary, string key, string value)
{
string[] orriginalValues;
if (dictionary.TryGetValue(key, out orriginalValues))
{
string[] newValues = new string[orriginalValues.Length + 1];
orriginalValues.CopyTo(newValues, 0);
newValues[newValues.Length - 1] = value;
dictionary[key] = newValues;
}
else
{
dictionary[key] = new string[] { value };
}
}
internal static string Get(this IDictionary<string, string[]> dictionary, string key)
{
string[] values;
if (dictionary.TryGetValue(key, out values))
{
return string.Join(", ", values);
}
return null;
}
internal static T Get<T>(this IDictionary<string, object> dictionary, string key, T fallback = default(T))
{
object values;
if (dictionary.TryGetValue(key, out values))
{
return (T)values;
}
return fallback;
}
}
}

View File

@ -0,0 +1,29 @@
// -----------------------------------------------------------------------
// <copyright file="Helpers.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Server.WebListener
{
internal static class Helpers
{
internal static Task CompletedTask()
{
return Task.FromResult<object>(null);
}
internal static ConfiguredTaskAwaitable SupressContext(this Task task)
{
return task.ConfigureAwait(continueOnCapturedContext: false);
}
internal static ConfiguredTaskAwaitable<T> SupressContext<T>(this Task<T> task)
{
return task.ConfigureAwait(continueOnCapturedContext: false);
}
}
}

View File

@ -0,0 +1,82 @@
//------------------------------------------------------------------------------
// <copyright file="HttpListener.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Globalization;
namespace Microsoft.AspNet.Server.WebListener
{
using LoggerFactoryFunc = Func<string, Func<TraceEventType, int, object, Exception, Func<object, Exception, string>, bool>>;
using LoggerFunc = Func<TraceEventType, int, object, Exception, Func<object, Exception, string>, bool>;
internal static class LogHelper
{
private static readonly Func<object, Exception, string> LogState =
(state, error) => Convert.ToString(state, CultureInfo.CurrentCulture);
private static readonly Func<object, Exception, string> LogStateAndError =
(state, error) => string.Format(CultureInfo.CurrentCulture, "{0}\r\n{1}", state, error);
internal static LoggerFunc CreateLogger(LoggerFactoryFunc factory, Type type)
{
if (factory == null)
{
return null;
}
return factory(type.FullName);
}
internal static void LogInfo(LoggerFunc logger, string data)
{
if (logger == null)
{
Debug.WriteLine(data);
}
else
{
logger(TraceEventType.Information, 0, data, null, LogState);
}
}
internal static void LogVerbose(LoggerFunc logger, string data)
{
if (logger == null)
{
Debug.WriteLine(data);
}
else
{
logger(TraceEventType.Verbose, 0, data, null, LogState);
}
}
internal static void LogException(LoggerFunc logger, string location, Exception exception)
{
if (logger == null)
{
Debug.WriteLine(exception);
}
else
{
logger(TraceEventType.Error, 0, location, exception, LogStateAndError);
}
}
internal static void LogError(LoggerFunc logger, string location, string message)
{
if (logger == null)
{
Debug.WriteLine(message);
}
else
{
logger(TraceEventType.Error, 0, location + ": " + message, null, LogState);
}
}
}
}

View File

@ -0,0 +1,172 @@
//------------------------------------------------------------------------------
// <copyright file="AddressFamily.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace Microsoft.AspNet.Server.WebListener
{
/// <devdoc>
/// <para>
/// Specifies the address families that an instance of the <see cref='System.Net.Sockets.Socket'/>
/// class can use.
/// </para>
/// </devdoc>
internal enum AddressFamily
{
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Unknown = -1, // Unknown
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Unspecified = 0, // unspecified
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Unix = 1, // local to host (pipes, portals)
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
InterNetwork = 2, // internetwork: UDP, TCP, etc.
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
ImpLink = 3, // arpanet imp addresses
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Pup = 4, // pup protocols: e.g. BSP
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Chaos = 5, // mit CHAOS protocols
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
NS = 6, // XEROX NS protocols
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Ipx = NS, // IPX and SPX
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Iso = 7, // ISO protocols
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Osi = Iso, // OSI is ISO
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Ecma = 8, // european computer manufacturers
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
DataKit = 9, // datakit protocols
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Ccitt = 10, // CCITT protocols, X.25 etc
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Sna = 11, // IBM SNA
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
DecNet = 12, // DECnet
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
DataLink = 13, // Direct data link interface
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Lat = 14, // LAT
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
HyperChannel = 15, // NSC Hyperchannel
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
AppleTalk = 16, // AppleTalk
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
NetBios = 17, // NetBios-style addresses
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
VoiceView = 18, // VoiceView
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
FireFox = 19, // FireFox
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Banyan = 21, // Banyan
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Atm = 22, // Native ATM Services
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
InterNetworkV6 = 23, // Internetwork Version 6
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Cluster = 24, // Microsoft Wolfpack
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Ieee12844 = 25, // IEEE 1284.4 WG AF
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Irda = 26, // IrDA
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
NetworkDesigners = 28, // Network Designers OSI & gateway enabled protocols
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Max = 29, // Max
}; // enum AddressFamily
}

View File

@ -0,0 +1,26 @@
// -----------------------------------------------------------------------
// <copyright file="ComNetOS.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
namespace Microsoft.AspNet.Server.WebListener
{
internal static class ComNetOS
{
// Minimum support for Windows 7 is assumed.
internal static readonly bool IsWin8orLater;
static ComNetOS()
{
#if NET45
var win8Version = new Version(6, 2);
IsWin8orLater = (Environment.OSVersion.Version >= win8Version);
#else
IsWin8orLater = true;
#endif
}
}
}

View File

@ -0,0 +1,56 @@
// -----------------------------------------------------------------------
// <copyright file="ContextAttribute.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.AspNet.Server.WebListener
{
internal enum ContextAttribute
{
// look into <sspi.h> and <schannel.h>
Sizes = 0x00,
Names = 0x01,
Lifespan = 0x02,
DceInfo = 0x03,
StreamSizes = 0x04,
// KeyInfo = 0x05, must not be used, see ConnectionInfo instead
Authority = 0x06,
// SECPKG_ATTR_PROTO_INFO = 7,
// SECPKG_ATTR_PASSWORD_EXPIRY = 8,
// SECPKG_ATTR_SESSION_KEY = 9,
PackageInfo = 0x0A,
// SECPKG_ATTR_USER_FLAGS = 11,
NegotiationInfo = 0x0C,
// SECPKG_ATTR_NATIVE_NAMES = 13,
// SECPKG_ATTR_FLAGS = 14,
// SECPKG_ATTR_USE_VALIDATED = 15,
// SECPKG_ATTR_CREDENTIAL_NAME = 16,
// SECPKG_ATTR_TARGET_INFORMATION = 17,
// SECPKG_ATTR_ACCESS_TOKEN = 18,
// SECPKG_ATTR_TARGET = 19,
// SECPKG_ATTR_AUTHENTICATION_ID = 20,
UniqueBindings = 0x19,
EndpointBindings = 0x1A,
ClientSpecifiedSpn = 0x1B, // SECPKG_ATTR_CLIENT_SPECIFIED_TARGET = 27
RemoteCertificate = 0x53,
LocalCertificate = 0x54,
RootStore = 0x55,
IssuerListInfoEx = 0x59,
ConnectionInfo = 0x5A,
// SECPKG_ATTR_EAP_KEY_BLOCK 0x5b // returns SecPkgContext_EapKeyBlock
// SECPKG_ATTR_MAPPED_CRED_ATTR 0x5c // returns SecPkgContext_MappedCredAttr
// SECPKG_ATTR_SESSION_INFO 0x5d // returns SecPkgContext_SessionInfo
// SECPKG_ATTR_APP_DATA 0x5e // sets/returns SecPkgContext_SessionAppData
// SECPKG_ATTR_REMOTE_CERTIFICATES 0x5F // returns SecPkgContext_Certificates
// SECPKG_ATTR_CLIENT_CERT_POLICY 0x60 // sets SecPkgCred_ClientCertCtlPolicy
// SECPKG_ATTR_CC_POLICY_RESULT 0x61 // returns SecPkgContext_ClientCertPolicyResult
// SECPKG_ATTR_USE_NCRYPT 0x62 // Sets the CRED_FLAG_USE_NCRYPT_PROVIDER FLAG on cred group
// SECPKG_ATTR_LOCAL_CERT_INFO 0x63 // returns SecPkgContext_CertInfo
// SECPKG_ATTR_CIPHER_INFO 0x64 // returns new CNG SecPkgContext_CipherInfo
// SECPKG_ATTR_EAP_PRF_INFO 0x65 // sets SecPkgContext_EapPrfInfo
// SECPKG_ATTR_SUPPORTED_SIGNATURES 0x66 // returns SecPkgContext_SupportedSignatures
// SECPKG_ATTR_REMOTE_CERT_CHAIN 0x67 // returns PCCERT_CONTEXT
UiInfo = 0x68, // sets SEcPkgContext_UiInfo
}
}

View File

@ -0,0 +1,25 @@
// -----------------------------------------------------------------------
// <copyright file="HttpRequestQueueV2Handle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Server.WebListener
{
// This class is a wrapper for Http.sys V2 request queue handle.
internal sealed class HttpRequestQueueV2Handle : SafeHandleZeroOrMinusOneIsInvalid
{
private HttpRequestQueueV2Handle()
: base(true)
{
}
protected override bool ReleaseHandle()
{
return (UnsafeNclNativeMethods.SafeNetHandles.HttpCloseRequestQueue(handle) ==
UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS);
}
}
}

View File

@ -0,0 +1,48 @@
// -----------------------------------------------------------------------
// <copyright file="HttpServerSessionHandle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Threading;
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Server.WebListener
{
internal sealed class HttpServerSessionHandle : CriticalHandleZeroOrMinusOneIsInvalid
{
private int disposed;
private ulong serverSessionId;
internal HttpServerSessionHandle(ulong id)
: base()
{
serverSessionId = id;
// This class uses no real handle so we need to set a dummy handle. Otherwise, IsInvalid always remains
// true.
SetHandle(new IntPtr(1));
}
internal ulong DangerousGetServerSessionId()
{
return serverSessionId;
}
protected override bool ReleaseHandle()
{
if (!IsInvalid)
{
if (Interlocked.Increment(ref disposed) == 1)
{
// Closing server session also closes all open url groups under that server session.
return (UnsafeNclNativeMethods.HttpApi.HttpCloseServerSession(serverSessionId) ==
UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS);
}
}
return true;
}
}
}

View File

@ -0,0 +1,54 @@
//------------------------------------------------------------------------------
// <copyright file="HttpRequestHeader.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace Microsoft.AspNet.Server.WebListener
{
internal enum HttpSysRequestHeader
{
CacheControl = 0, // general-header [section 4.5]
Connection = 1, // general-header [section 4.5]
Date = 2, // general-header [section 4.5]
KeepAlive = 3, // general-header [not in rfc]
Pragma = 4, // general-header [section 4.5]
Trailer = 5, // general-header [section 4.5]
TransferEncoding = 6, // general-header [section 4.5]
Upgrade = 7, // general-header [section 4.5]
Via = 8, // general-header [section 4.5]
Warning = 9, // general-header [section 4.5]
Allow = 10, // entity-header [section 7.1]
ContentLength = 11, // entity-header [section 7.1]
ContentType = 12, // entity-header [section 7.1]
ContentEncoding = 13, // entity-header [section 7.1]
ContentLanguage = 14, // entity-header [section 7.1]
ContentLocation = 15, // entity-header [section 7.1]
ContentMd5 = 16, // entity-header [section 7.1]
ContentRange = 17, // entity-header [section 7.1]
Expires = 18, // entity-header [section 7.1]
LastModified = 19, // entity-header [section 7.1]
Accept = 20, // request-header [section 5.3]
AcceptCharset = 21, // request-header [section 5.3]
AcceptEncoding = 22, // request-header [section 5.3]
AcceptLanguage = 23, // request-header [section 5.3]
Authorization = 24, // request-header [section 5.3]
Cookie = 25, // request-header [not in rfc]
Expect = 26, // request-header [section 5.3]
From = 27, // request-header [section 5.3]
Host = 28, // request-header [section 5.3]
IfMatch = 29, // request-header [section 5.3]
IfModifiedSince = 30, // request-header [section 5.3]
IfNoneMatch = 31, // request-header [section 5.3]
IfRange = 32, // request-header [section 5.3]
IfUnmodifiedSince = 33, // request-header [section 5.3]
MaxForwards = 34, // request-header [section 5.3]
ProxyAuthorization = 35, // request-header [section 5.3]
Referer = 36, // request-header [section 5.3]
Range = 37, // request-header [section 5.3]
Te = 38, // request-header [section 5.3]
Translate = 39, // request-header [webDAV, not in rfc 2518]
UserAgent = 40, // request-header [section 5.3]
}
}

View File

@ -0,0 +1,43 @@
//------------------------------------------------------------------------------
// <copyright file="HttpResponseHeader.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace Microsoft.AspNet.Server.WebListener
{
internal enum HttpSysResponseHeader
{
CacheControl = 0, // general-header [section 4.5]
Connection = 1, // general-header [section 4.5]
Date = 2, // general-header [section 4.5]
KeepAlive = 3, // general-header [not in rfc]
Pragma = 4, // general-header [section 4.5]
Trailer = 5, // general-header [section 4.5]
TransferEncoding = 6, // general-header [section 4.5]
Upgrade = 7, // general-header [section 4.5]
Via = 8, // general-header [section 4.5]
Warning = 9, // general-header [section 4.5]
Allow = 10, // entity-header [section 7.1]
ContentLength = 11, // entity-header [section 7.1]
ContentType = 12, // entity-header [section 7.1]
ContentEncoding = 13, // entity-header [section 7.1]
ContentLanguage = 14, // entity-header [section 7.1]
ContentLocation = 15, // entity-header [section 7.1]
ContentMd5 = 16, // entity-header [section 7.1]
ContentRange = 17, // entity-header [section 7.1]
Expires = 18, // entity-header [section 7.1]
LastModified = 19, // entity-header [section 7.1]
AcceptRanges = 20, // response-header [section 6.2]
Age = 21, // response-header [section 6.2]
ETag = 22, // response-header [section 6.2]
Location = 23, // response-header [section 6.2]
ProxyAuthenticate = 24, // response-header [section 6.2]
RetryAfter = 25, // response-header [section 6.2]
Server = 26, // response-header [section 6.2]
SetCookie = 27, // response-header [not in rfc]
Vary = 28, // response-header [section 6.2]
WwwAuthenticate = 29, // response-header [section 6.2]
}
}

View File

@ -0,0 +1,125 @@
// -----------------------------------------------------------------------
// <copyright file="HttpSysSettings.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Security;
#if NET45
using Microsoft.Win32;
#endif
namespace Microsoft.AspNet.Server.WebListener
{
internal static class HttpSysSettings
{
#if NET45
private const string HttpSysParametersKey = @"System\CurrentControlSet\Services\HTTP\Parameters";
#endif
private const bool EnableNonUtf8Default = true;
private const bool FavorUtf8Default = true;
private const string EnableNonUtf8Name = "EnableNonUtf8";
private const string FavorUtf8Name = "FavorUtf8";
private static volatile bool enableNonUtf8 = EnableNonUtf8Default;
private static volatile bool favorUtf8 = FavorUtf8Default;
static HttpSysSettings()
{
ReadHttpSysRegistrySettings();
}
internal static bool EnableNonUtf8
{
get { return enableNonUtf8; }
}
internal static bool FavorUtf8
{
get { return favorUtf8; }
}
private static void ReadHttpSysRegistrySettings()
#if !NET45
{
}
#else
{
try
{
RegistryKey httpSysParameters = Registry.LocalMachine.OpenSubKey(HttpSysParametersKey);
if (httpSysParameters == null)
{
LogWarning("ReadHttpSysRegistrySettings", "The Http.Sys registry key is null.",
HttpSysParametersKey);
}
else
{
using (httpSysParameters)
{
enableNonUtf8 = ReadRegistryValue(httpSysParameters, EnableNonUtf8Name, EnableNonUtf8Default);
favorUtf8 = ReadRegistryValue(httpSysParameters, FavorUtf8Name, FavorUtf8Default);
}
}
}
catch (SecurityException e)
{
LogRegistryException("ReadHttpSysRegistrySettings", e);
}
catch (ObjectDisposedException e)
{
LogRegistryException("ReadHttpSysRegistrySettings", e);
}
}
private static bool ReadRegistryValue(RegistryKey key, string valueName, bool defaultValue)
{
Debug.Assert(key != null, "'key' must not be null");
try
{
if (key.GetValue(valueName) != null && key.GetValueKind(valueName) == RegistryValueKind.DWord)
{
// At this point we know the Registry value exists and it must be valid (any DWORD value
// can be converted to a bool).
return Convert.ToBoolean(key.GetValue(valueName), CultureInfo.InvariantCulture);
}
}
catch (UnauthorizedAccessException e)
{
LogRegistryException("ReadRegistryValue", e);
}
catch (IOException e)
{
LogRegistryException("ReadRegistryValue", e);
}
catch (SecurityException e)
{
LogRegistryException("ReadRegistryValue", e);
}
catch (ObjectDisposedException e)
{
LogRegistryException("ReadRegistryValue", e);
}
return defaultValue;
}
private static void LogRegistryException(string methodName, Exception e)
{
LogWarning(methodName, "Unable to access the Http.Sys registry value.", HttpSysParametersKey, e);
}
private static void LogWarning(string methodName, string message, params object[] args)
{
// TODO: log
// Logging.PrintWarning(Logging.HttpListener, typeof(HttpSysSettings), methodName, SR.GetString(message, args));
}
#endif
}
}

View File

@ -0,0 +1,23 @@
//------------------------------------------------------------------------------
// <copyright file="Internal.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
namespace Microsoft.AspNet.Server.WebListener
{
internal static class IntPtrHelper
{
internal static IntPtr Add(IntPtr a, int b)
{
return (IntPtr)((long)a + (long)b);
}
internal static long Subtract(IntPtr a, IntPtr b)
{
return ((long)a - (long)b);
}
}
}

View File

@ -0,0 +1,25 @@
// -----------------------------------------------------------------------
// <copyright file="NclUtilities.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
namespace Microsoft.AspNet.Server.WebListener
{
internal static class NclUtilities
{
internal static bool HasShutdownStarted
{
get
{
return Environment.HasShutdownStarted
#if NET45
|| AppDomain.CurrentDomain.IsFinalizingForUnload()
#endif
;
}
}
}
}

View File

@ -0,0 +1,34 @@
// -----------------------------------------------------------------------
// <copyright file="SSPIHandle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
namespace Microsoft.AspNet.Server.WebListener
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct SSPIHandle
{
private IntPtr handleHi;
private IntPtr handleLo;
public bool IsZero
{
get { return handleHi == IntPtr.Zero && handleLo == IntPtr.Zero; }
}
internal void SetToInvalid()
{
handleHi = IntPtr.Zero;
handleLo = IntPtr.Zero;
}
public override string ToString()
{
return handleHi.ToString("x") + ":" + handleLo.ToString("x");
}
}
}

View File

@ -0,0 +1,42 @@
// -----------------------------------------------------------------------
// <copyright file="SafeLoadLibrary.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Server.WebListener
{
internal sealed class SafeLoadLibrary : SafeHandleZeroOrMinusOneIsInvalid
{
private const string KERNEL32 = "kernel32.dll";
public static readonly SafeLoadLibrary Zero = new SafeLoadLibrary(false);
private SafeLoadLibrary()
: base(true)
{
}
private SafeLoadLibrary(bool ownsHandle)
: base(ownsHandle)
{
}
public static unsafe SafeLoadLibrary LoadLibraryEx(string library)
{
SafeLoadLibrary result = UnsafeNclNativeMethods.SafeNetHandles.LoadLibraryExW(library, null, 0);
if (result.IsInvalid)
{
result.SetHandleAsInvalid();
}
return result;
}
protected override bool ReleaseHandle()
{
return UnsafeNclNativeMethods.SafeNetHandles.FreeLibrary(handle);
}
}
}

View File

@ -0,0 +1,46 @@
// -----------------------------------------------------------------------
// <copyright file="SafeLocalFree.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Server.WebListener
{
internal sealed class SafeLocalFree : SafeHandleZeroOrMinusOneIsInvalid
{
private const int LMEM_FIXED = 0;
private const int NULL = 0;
// This returned handle cannot be modified by the application.
public static SafeLocalFree Zero = new SafeLocalFree(false);
private SafeLocalFree()
: base(true)
{
}
private SafeLocalFree(bool ownsHandle)
: base(ownsHandle)
{
}
public static SafeLocalFree LocalAlloc(int cb)
{
SafeLocalFree result = UnsafeNclNativeMethods.SafeNetHandles.LocalAlloc(LMEM_FIXED, (UIntPtr)cb);
if (result.IsInvalid)
{
result.SetHandleAsInvalid();
throw new OutOfMemoryException();
}
return result;
}
protected override bool ReleaseHandle()
{
return UnsafeNclNativeMethods.SafeNetHandles.LocalFree(handle) == IntPtr.Zero;
}
}
}

View File

@ -0,0 +1,42 @@
// -----------------------------------------------------------------------
// <copyright file="SafeLocalFreeChannelBinding.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Security.Authentication.ExtendedProtection;
namespace Microsoft.AspNet.Server.WebListener
{
internal class SafeLocalFreeChannelBinding : ChannelBinding
{
private const int LMEM_FIXED = 0;
private int size;
public override int Size
{
get { return size; }
}
public static SafeLocalFreeChannelBinding LocalAlloc(int cb)
{
SafeLocalFreeChannelBinding result;
result = UnsafeNclNativeMethods.SafeNetHandles.LocalAllocChannelBinding(LMEM_FIXED, (UIntPtr)cb);
if (result.IsInvalid)
{
result.SetHandleAsInvalid();
throw new OutOfMemoryException();
}
result.size = cb;
return result;
}
protected override bool ReleaseHandle()
{
return UnsafeNclNativeMethods.SafeNetHandles.LocalFree(handle) == IntPtr.Zero;
}
}
}

View File

@ -0,0 +1,30 @@
// -----------------------------------------------------------------------
// <copyright file="SafeLocalMemHandle.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using Microsoft.Win32.SafeHandles;
namespace Microsoft.AspNet.Server.WebListener
{
internal sealed class SafeLocalMemHandle : SafeHandleZeroOrMinusOneIsInvalid
{
internal SafeLocalMemHandle()
: base(true)
{
}
internal SafeLocalMemHandle(IntPtr existingHandle, bool ownsHandle)
: base(ownsHandle)
{
SetHandle(existingHandle);
}
protected override bool ReleaseHandle()
{
return UnsafeNclNativeMethods.SafeNetHandles.LocalFree(handle) == IntPtr.Zero;
}
}
}

View File

@ -0,0 +1,68 @@
// -----------------------------------------------------------------------
// <copyright file="SafeNativeOverlapped.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
using System.Threading;
namespace Microsoft.AspNet.Server.WebListener
{
internal class SafeNativeOverlapped : SafeHandle
{
internal static readonly SafeNativeOverlapped Zero = new SafeNativeOverlapped();
internal SafeNativeOverlapped()
: this(IntPtr.Zero)
{
}
internal unsafe SafeNativeOverlapped(NativeOverlapped* handle)
: this((IntPtr)handle)
{
}
internal SafeNativeOverlapped(IntPtr handle)
: base(IntPtr.Zero, true)
{
SetHandle(handle);
}
public override bool IsInvalid
{
get { return handle == IntPtr.Zero; }
}
public void ReinitializeNativeOverlapped()
{
IntPtr handleSnapshot = handle;
if (handleSnapshot != IntPtr.Zero)
{
unsafe
{
((NativeOverlapped*)handleSnapshot)->InternalHigh = IntPtr.Zero;
((NativeOverlapped*)handleSnapshot)->InternalLow = IntPtr.Zero;
((NativeOverlapped*)handleSnapshot)->EventHandle = IntPtr.Zero;
}
}
}
protected override bool ReleaseHandle()
{
IntPtr oldHandle = Interlocked.Exchange(ref handle, IntPtr.Zero);
// Do not call free durring AppDomain shutdown, there may be an outstanding operation.
// Overlapped will take care calling free when the native callback completes.
if (oldHandle != IntPtr.Zero && !NclUtilities.HasShutdownStarted)
{
unsafe
{
Overlapped.Free((NativeOverlapped*)oldHandle);
}
}
return true;
}
}
}

View File

@ -0,0 +1,51 @@
//------------------------------------------------------------------------------
// <copyright file="_SSPIWrapper.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
namespace Microsoft.AspNet.Server.WebListener
{
using System;
using System.Globalization;
using System.Runtime.InteropServices;
// From Schannel.h
[Flags]
internal enum SchProtocols
{
Zero = 0,
PctClient = 0x00000002,
PctServer = 0x00000001,
Pct = (PctClient | PctServer),
Ssl2Client = 0x00000008,
Ssl2Server = 0x00000004,
Ssl2 = (Ssl2Client | Ssl2Server),
Ssl3Client = 0x00000020,
Ssl3Server = 0x00000010,
Ssl3 = (Ssl3Client | Ssl3Server),
Tls10Client = 0x00000080,
Tls10Server = 0x00000040,
Tls10 = (Tls10Client | Tls10Server),
Tls11Client = 0x00000200,
Tls11Server = 0x00000100,
Tls11 = (Tls11Client | Tls11Server),
Tls12Client = 0x00000800,
Tls12Server = 0x00000400,
Tls12 = (Tls12Client | Tls12Server),
Ssl3Tls = (Ssl3 | Tls10),
UniClient = unchecked((int)0x80000000),
UniServer = 0x40000000,
Unified = (UniClient | UniServer),
ClientMask = (PctClient | Ssl2Client | Ssl3Client | Tls10Client | Tls11Client | Tls12Client | UniClient),
ServerMask = (PctServer | Ssl2Server | Ssl3Server | Tls10Server | Tls11Server | Tls12Server | UniServer)
}
[StructLayout(LayoutKind.Sequential)]
internal struct Bindings
{
// see SecPkgContext_Bindings in <sspi.h>
internal int BindingsLength;
internal IntPtr bindings;
}
}

View File

@ -0,0 +1,54 @@
// -----------------------------------------------------------------------
// <copyright file="SecurityStatus.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
namespace Microsoft.AspNet.Server.WebListener
{
internal enum SecurityStatus
{
// Success / Informational
OK = 0x00000000,
ContinueNeeded = unchecked((int)0x00090312),
CompleteNeeded = unchecked((int)0x00090313),
CompAndContinue = unchecked((int)0x00090314),
ContextExpired = unchecked((int)0x00090317),
CredentialsNeeded = unchecked((int)0x00090320),
Renegotiate = unchecked((int)0x00090321),
// Errors
OutOfMemory = unchecked((int)0x80090300),
InvalidHandle = unchecked((int)0x80090301),
Unsupported = unchecked((int)0x80090302),
TargetUnknown = unchecked((int)0x80090303),
InternalError = unchecked((int)0x80090304),
PackageNotFound = unchecked((int)0x80090305),
NotOwner = unchecked((int)0x80090306),
CannotInstall = unchecked((int)0x80090307),
InvalidToken = unchecked((int)0x80090308),
CannotPack = unchecked((int)0x80090309),
QopNotSupported = unchecked((int)0x8009030A),
NoImpersonation = unchecked((int)0x8009030B),
LogonDenied = unchecked((int)0x8009030C),
UnknownCredentials = unchecked((int)0x8009030D),
NoCredentials = unchecked((int)0x8009030E),
MessageAltered = unchecked((int)0x8009030F),
OutOfSequence = unchecked((int)0x80090310),
NoAuthenticatingAuthority = unchecked((int)0x80090311),
IncompleteMessage = unchecked((int)0x80090318),
IncompleteCredentials = unchecked((int)0x80090320),
BufferNotEnough = unchecked((int)0x80090321),
WrongPrincipal = unchecked((int)0x80090322),
TimeSkew = unchecked((int)0x80090324),
UntrustedRoot = unchecked((int)0x80090325),
IllegalMessage = unchecked((int)0x80090326),
CertUnknown = unchecked((int)0x80090327),
CertExpired = unchecked((int)0x80090328),
AlgorithmMismatch = unchecked((int)0x80090331),
SecurityQosFailed = unchecked((int)0x80090332),
SmartcardLogonRequired = unchecked((int)0x8009033E),
UnsupportedPreauth = unchecked((int)0x80090343),
BadBinding = unchecked((int)0x80090346)
}
}

View File

@ -0,0 +1,342 @@
//------------------------------------------------------------------------------
// <copyright file="SocketAddress.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Text;
namespace Microsoft.AspNet.Server.WebListener
{
// a little perf app measured these times when comparing the internal
// buffer implemented as a managed byte[] or unmanaged memory IntPtr
// that's why we use byte[]
// byte[] total ms:19656
// IntPtr total ms:25671
/// <devdoc>
/// <para>
/// This class is used when subclassing EndPoint, and provides indication
/// on how to format the memory buffers that winsock uses for network addresses.
/// </para>
/// </devdoc>
internal class SocketAddress
{
private const int NumberOfIPv6Labels = 8;
// Lower case hex, no leading zeros
private const string IPv6NumberFormat = "{0:x}";
private const string IPv6StringSeparator = ":";
private const string IPv4StringFormat = "{0:d}.{1:d}.{2:d}.{3:d}";
internal const int IPv6AddressSize = 28;
internal const int IPv4AddressSize = 16;
private const int WriteableOffset = 2;
private int _size;
private byte[] _buffer;
private int _hash;
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public SocketAddress(AddressFamily family, int size)
{
if (size < WriteableOffset)
{
// it doesn't make sense to create a socket address with less tha
// 2 bytes, that's where we store the address family.
throw new ArgumentOutOfRangeException("size");
}
_size = size;
_buffer = new byte[((size / IntPtr.Size) + 2) * IntPtr.Size]; // sizeof DWORD
#if BIGENDIAN
m_Buffer[0] = unchecked((byte)((int)family>>8));
m_Buffer[1] = unchecked((byte)((int)family ));
#else
_buffer[0] = unchecked((byte)((int)family));
_buffer[1] = unchecked((byte)((int)family >> 8));
#endif
}
internal byte[] Buffer
{
get { return _buffer; }
}
internal AddressFamily Family
{
get
{
int family;
#if BIGENDIAN
family = ((int)m_Buffer[0]<<8) | m_Buffer[1];
#else
family = _buffer[0] | ((int)_buffer[1] << 8);
#endif
return (AddressFamily)family;
}
}
internal int Size
{
get
{
return _size;
}
}
// access to unmanaged serialized data. this doesn't
// allow access to the first 2 bytes of unmanaged memory
// that are supposed to contain the address family which
// is readonly.
//
// <SECREVIEW> you can still use negative offsets as a back door in case
// winsock changes the way it uses SOCKADDR. maybe we want to prohibit it?
// maybe we should make the class sealed to avoid potentially dangerous calls
// into winsock with unproperly formatted data? </SECREVIEW>
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
private byte this[int offset]
{
get
{
// access
if (offset < 0 || offset >= Size)
{
throw new ArgumentOutOfRangeException("offset");
}
return _buffer[offset];
}
}
internal int GetPort()
{
return (int)((_buffer[2] << 8 & 0xFF00) | (_buffer[3]));
}
public override bool Equals(object comparand)
{
SocketAddress castedComparand = comparand as SocketAddress;
if (castedComparand == null || this.Size != castedComparand.Size)
{
return false;
}
for (int i = 0; i < this.Size; i++)
{
if (this[i] != castedComparand[i])
{
return false;
}
}
return true;
}
public override int GetHashCode()
{
if (_hash == 0)
{
int i;
int size = Size & ~3;
for (i = 0; i < size; i += 4)
{
_hash ^= (int)_buffer[i]
| ((int)_buffer[i + 1] << 8)
| ((int)_buffer[i + 2] << 16)
| ((int)_buffer[i + 3] << 24);
}
if ((Size & 3) != 0)
{
int remnant = 0;
int shift = 0;
for (; i < Size; ++i)
{
remnant |= ((int)_buffer[i]) << shift;
shift += 8;
}
_hash ^= remnant;
}
}
return _hash;
}
public override string ToString()
{
StringBuilder bytes = new StringBuilder();
for (int i = WriteableOffset; i < this.Size; i++)
{
if (i > WriteableOffset)
{
bytes.Append(",");
}
bytes.Append(this[i].ToString(NumberFormatInfo.InvariantInfo));
}
return Family.ToString() + ":" + Size.ToString(NumberFormatInfo.InvariantInfo) + ":{" + bytes.ToString() + "}";
}
internal string GetIPAddressString()
{
if (Family == AddressFamily.InterNetworkV6)
{
return GetIpv6AddressString();
}
else if (Family == AddressFamily.InterNetwork)
{
return GetIPv4AddressString();
}
else
{
return null;
}
}
private string GetIPv4AddressString()
{
Contract.Assert(Size >= IPv4AddressSize);
return string.Format(CultureInfo.InvariantCulture, IPv4StringFormat,
_buffer[4], _buffer[5], _buffer[6], _buffer[7]);
}
// TODO: Does scope ID ever matter?
private unsafe string GetIpv6AddressString()
{
Contract.Assert(Size >= IPv6AddressSize);
fixed (byte* rawBytes = _buffer)
{
// Convert from bytes to shorts.
ushort* rawShorts = stackalloc ushort[NumberOfIPv6Labels];
int numbersOffset = 0;
// The address doesn't start at the beginning of the buffer.
for (int i = 8; i < ((NumberOfIPv6Labels * 2) + 8); i += 2)
{
rawShorts[numbersOffset++] = (ushort)(rawBytes[i] << 8 | rawBytes[i + 1]);
}
return GetIPv6AddressString(rawShorts);
}
}
private static unsafe string GetIPv6AddressString(ushort* numbers)
{
// RFC 5952 Sections 4 & 5 - Compressed, lower case, with possible embedded IPv4 addresses.
// Start to finish, inclusive. <-1, -1> for no compression
KeyValuePair<int, int> range = FindCompressionRange(numbers);
bool ipv4Embedded = ShouldHaveIpv4Embedded(numbers);
StringBuilder builder = new StringBuilder();
for (int i = 0; i < NumberOfIPv6Labels; i++)
{
if (ipv4Embedded && i == (NumberOfIPv6Labels - 2))
{
// Write the remaining digits as an IPv4 address
builder.Append(IPv6StringSeparator);
builder.Append(string.Format(CultureInfo.InvariantCulture, IPv4StringFormat,
numbers[i] >> 8, numbers[i] & 0xFF, numbers[i + 1] >> 8, numbers[i + 1] & 0xFF));
break;
}
// Compression; 1::1, ::1, 1::
if (range.Key == i)
{
// Start compression, add :
builder.Append(IPv6StringSeparator);
}
if (range.Key <= i && range.Value == (NumberOfIPv6Labels - 1))
{
// Remainder compressed; 1::
builder.Append(IPv6StringSeparator);
break;
}
if (range.Key <= i && i <= range.Value)
{
continue; // Compressed
}
if (i != 0)
{
builder.Append(IPv6StringSeparator);
}
builder.Append(string.Format(CultureInfo.InvariantCulture, IPv6NumberFormat, numbers[i]));
}
return builder.ToString();
}
// RFC 5952 Section 4.2.3
// Longest consecutive sequence of zero segments, minimum 2.
// On equal, first sequence wins.
// <-1, -1> for no compression.
private static unsafe KeyValuePair<int, int> FindCompressionRange(ushort* numbers)
{
int longestSequenceLength = 0;
int longestSequenceStart = -1;
int currentSequenceLength = 0;
for (int i = 0; i < NumberOfIPv6Labels; i++)
{
if (numbers[i] == 0)
{
// In a sequence
currentSequenceLength++;
if (currentSequenceLength > longestSequenceLength)
{
longestSequenceLength = currentSequenceLength;
longestSequenceStart = i - currentSequenceLength + 1;
}
}
else
{
currentSequenceLength = 0;
}
}
if (longestSequenceLength >= 2)
{
return new KeyValuePair<int, int>(longestSequenceStart,
longestSequenceStart + longestSequenceLength - 1);
}
return new KeyValuePair<int, int>(-1, -1); // No compression
}
// Returns true if the IPv6 address should be formated with an embedded IPv4 address:
// ::192.168.1.1
private static unsafe bool ShouldHaveIpv4Embedded(ushort* numbers)
{
// 0:0 : 0:0 : x:x : x.x.x.x
if (numbers[0] == 0 && numbers[1] == 0 && numbers[2] == 0 && numbers[3] == 0 && numbers[6] != 0)
{
// RFC 5952 Section 5 - 0:0 : 0:0 : 0:[0 | FFFF] : x.x.x.x
if (numbers[4] == 0 && (numbers[5] == 0 || numbers[5] == 0xFFFF))
{
return true;
// SIIT - 0:0 : 0:0 : FFFF:0 : x.x.x.x
}
else if (numbers[4] == 0xFFFF && numbers[5] == 0)
{
return true;
}
}
// ISATAP
if (numbers[4] == 0 && numbers[5] == 0x5EFE)
{
return true;
}
return false;
}
} // class SocketAddress
} // namespace System.Net

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
// -----------------------------------------------------------------------
// <copyright file="ServerFactory.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
// Copyright 2011-2012 Katana contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Server.WebListener
{
using AppFunc = Func<IDictionary<string, object>, Task>;
using LoggerFactoryFunc = Func<string, Func<TraceEventType, int, object, Exception, Func<object, Exception, string>, bool>>;
/// <summary>
/// Implements the Katana setup pattern for this server.
/// </summary>
public static class OwinServerFactory
{
/// <summary>
/// Populates the server capabilities.
/// Also included is a configurable instance of the server.
/// </summary>
/// <param name="properties"></param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by caller")]
public static void Initialize(IDictionary<string, object> properties)
{
if (properties == null)
{
throw new ArgumentNullException("properties");
}
properties[Constants.VersionKey] = Constants.OwinVersion;
IDictionary<string, object> capabilities =
properties.Get<IDictionary<string, object>>(Constants.ServerCapabilitiesKey)
?? new Dictionary<string, object>();
properties[Constants.ServerCapabilitiesKey] = capabilities;
// SendFile
capabilities[Constants.SendFileVersionKey] = Constants.SendFileVersion;
IDictionary<string, object> sendfileSupport = new Dictionary<string, object>();
sendfileSupport[Constants.SendFileConcurrencyKey] = Constants.Overlapped;
capabilities[Constants.SendFileSupportKey] = sendfileSupport;
// Opaque
if (ComNetOS.IsWin8orLater)
{
capabilities[Constants.OpaqueVersionKey] = Constants.OpaqueVersion;
}
// Directly expose the server for advanced configuration.
properties[typeof(OwinWebListener).FullName] = new OwinWebListener();
}
/// <summary>
/// Creates a server and starts listening on the given addresses.
/// </summary>
/// <param name="app">The application entry point.</param>
/// <param name="properties">The configuration.</param>
/// <returns>The server. Invoke Dispose to shut down.</returns>
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "By design")]
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed by caller")]
public static IDisposable Create(AppFunc app, IDictionary<string, object> properties)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
if (properties == null)
{
throw new ArgumentNullException("properties");
}
var addresses = properties.Get<IList<IDictionary<string, object>>>("host.Addresses")
?? new List<IDictionary<string, object>>();
OwinWebListener server = properties.Get<OwinWebListener>(typeof(OwinWebListener).FullName)
?? new OwinWebListener();
var capabilities =
properties.Get<IDictionary<string, object>>(Constants.ServerCapabilitiesKey)
?? new Dictionary<string, object>();
var loggerFactory = properties.Get<LoggerFactoryFunc>(Constants.ServerLoggerFactoryKey);
server.Start(app, addresses, capabilities, loggerFactory);
return server;
}
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More