You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
189
mcs/class/referencesource/System.Web/ImpersonationContext.cs
Normal file
189
mcs/class/referencesource/System.Web/ImpersonationContext.cs
Normal file
@ -0,0 +1,189 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ImpersonationContext.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web {
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Permissions;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Util;
|
||||
|
||||
internal class ImpersonationContext : IDisposable {
|
||||
private HandleRef _savedToken;
|
||||
private bool _reverted;
|
||||
private bool _impersonating;
|
||||
|
||||
// arg-less ctor creates dummy context
|
||||
internal ImpersonationContext() {
|
||||
}
|
||||
|
||||
// ctor that takes a token impersonates that token
|
||||
internal ImpersonationContext(IntPtr token) {
|
||||
ImpersonateToken(new HandleRef(this, token));
|
||||
}
|
||||
|
||||
// IDisposable pattern
|
||||
|
||||
~ImpersonationContext() {
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose() {
|
||||
Undo();
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing) {
|
||||
if (_savedToken.Handle != IntPtr.Zero) {
|
||||
try {} finally {
|
||||
UnsafeNativeMethods.CloseHandle(_savedToken.Handle);
|
||||
_savedToken = new HandleRef(this, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impersonate a given token
|
||||
protected void ImpersonateToken(HandleRef token) {
|
||||
try {
|
||||
// first revert
|
||||
_savedToken = new HandleRef(this, GetCurrentToken());
|
||||
|
||||
if (_savedToken.Handle != IntPtr.Zero) {
|
||||
if (UnsafeNativeMethods.RevertToSelf() != 0) {
|
||||
_reverted = true;
|
||||
}
|
||||
}
|
||||
|
||||
// impersonate token if not zero
|
||||
if (token.Handle != IntPtr.Zero) {
|
||||
if (UnsafeNativeMethods.SetThreadToken(IntPtr.Zero, token.Handle) == 0) {
|
||||
throw new HttpException(SR.GetString(SR.Cannot_impersonate));
|
||||
}
|
||||
|
||||
_impersonating = true;
|
||||
}
|
||||
}
|
||||
catch {
|
||||
RestoreImpersonation();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// restore impersonation to the original state
|
||||
private void RestoreImpersonation() {
|
||||
// first revert before reimpersonating
|
||||
if (_impersonating) {
|
||||
UnsafeNativeMethods.RevertToSelf();
|
||||
_impersonating = false;
|
||||
}
|
||||
|
||||
// second reimpersonate the orignal saved identity (if exists)
|
||||
if (_savedToken.Handle != IntPtr.Zero) {
|
||||
if (_reverted) {
|
||||
if (UnsafeNativeMethods.SetThreadToken(IntPtr.Zero, _savedToken.Handle) == 0) {
|
||||
throw new HttpException(SR.GetString(SR.Cannot_impersonate));
|
||||
}
|
||||
}
|
||||
|
||||
_reverted = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 'public' version of Dispose
|
||||
internal void Undo() {
|
||||
RestoreImpersonation();
|
||||
|
||||
// free unmanaged resources
|
||||
Dispose(true);
|
||||
System.GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// helper to get the currently impersonated token
|
||||
private static IntPtr GetCurrentToken() {
|
||||
IntPtr token = IntPtr.Zero;
|
||||
|
||||
if (UnsafeNativeMethods.OpenThreadToken(
|
||||
UnsafeNativeMethods.GetCurrentThread(),
|
||||
UnsafeNativeMethods.TOKEN_READ | UnsafeNativeMethods.TOKEN_IMPERSONATE,
|
||||
true,
|
||||
ref token) == 0) {
|
||||
|
||||
// if the last error is ERROR_NO_TOKEN it is ok, otherwise throw
|
||||
if (Marshal.GetLastWin32Error() != UnsafeNativeMethods.ERROR_NO_TOKEN) {
|
||||
throw new HttpException(SR.GetString(SR.Cannot_impersonate));
|
||||
}
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
// helper to check if there is a current token
|
||||
internal static bool CurrentThreadTokenExists {
|
||||
get {
|
||||
bool impersonating = false;
|
||||
|
||||
try {} finally {
|
||||
IntPtr token = GetCurrentToken();
|
||||
|
||||
if (token != IntPtr.Zero) {
|
||||
impersonating = true;
|
||||
UnsafeNativeMethods.CloseHandle(token);
|
||||
}
|
||||
}
|
||||
|
||||
return impersonating;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ProcessImpersonationContext : ImpersonationContext {
|
||||
internal ProcessImpersonationContext() {
|
||||
ImpersonateToken(new HandleRef(this, IntPtr.Zero));
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ApplicationImpersonationContext : ImpersonationContext {
|
||||
internal ApplicationImpersonationContext() {
|
||||
ImpersonateToken(new HandleRef(this, HostingEnvironment.ApplicationIdentityToken));
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ClientImpersonationContext : ImpersonationContext {
|
||||
internal ClientImpersonationContext(HttpContext context) {
|
||||
Start(context, true);
|
||||
}
|
||||
|
||||
internal ClientImpersonationContext(HttpContext context, bool throwOnError) {
|
||||
Start(context, throwOnError);
|
||||
}
|
||||
|
||||
private void Start(HttpContext context, bool throwOnError) {
|
||||
IntPtr token = IntPtr.Zero;
|
||||
|
||||
try {
|
||||
if (context != null) {
|
||||
token = context.ImpersonationToken;
|
||||
}
|
||||
else {
|
||||
// by default use app identity
|
||||
token = HostingEnvironment.ApplicationIdentityToken;
|
||||
}
|
||||
}
|
||||
catch {
|
||||
if (throwOnError) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// only impersonate if there is a token
|
||||
// this is to optimize for the default case of impersonation="false"
|
||||
// and no UNC identity, when requests run under process identity
|
||||
if (token != IntPtr.Zero) {
|
||||
ImpersonateToken(new HandleRef(this, token));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user