Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / ComIntegration / ComPlusAuthorization.cs / 1 / ComPlusAuthorization.cs
//---------------------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------------------- namespace System.ServiceModel.ComIntegration { using System; using System.ServiceModel; using System.ServiceModel.Diagnostics; using System.Security; using System.Net.Security; using System.Security.AccessControl; using System.Security.Principal; using System.ServiceModel.Security; using System.Runtime.InteropServices; using System.ComponentModel; using System.Collections.Generic; using System.Threading; using SafeCloseHandle = System.IdentityModel.SafeCloseHandle; using SafeHGlobalHandle = System.IdentityModel.SafeHGlobalHandle; internal static class SecurityUtils { static WindowsIdentity anonymousIdentity; static WindowsIdentity processIdentity; static object lockObject = new object(); public static SafeHandle GetTokenInformation(SafeCloseHandle token, TOKEN_INFORMATION_CLASS infoClass) { uint length; if (!SafeNativeMethods.GetTokenInformation(token, infoClass, SafeHGlobalHandle.InvalidHandle, 0, out length)) { int error = Marshal.GetLastWin32Error(); if (error != (int)Win32Error.ERROR_INSUFFICIENT_BUFFER) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error, SR.GetString(SR.GetTokenInfoFailed, error))); } } SafeHandle buffer = SafeHGlobalHandle.AllocHGlobal(length); try { if (!SafeNativeMethods.GetTokenInformation(token, infoClass, buffer, length, out length)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error, SR.GetString(SR.GetTokenInfoFailed, error))); } } catch { buffer.Dispose(); throw; } return buffer; } internal static bool IsAtleastImpersonationToken(SafeCloseHandle token) { using (SafeHandle buffer = GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TokenImpersonationLevel)) { int level = Marshal.ReadInt32(buffer.DangerousGetHandle()); if (level < (int)SecurityImpersonationLevel.Impersonation) return false; else return true; } } internal static bool IsPrimaryToken(SafeCloseHandle token) { using (SafeHandle buffer = GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TokenType)) { int level = Marshal.ReadInt32(buffer.DangerousGetHandle()); return (level == (int)TokenType.TokenPrimary); } } internal static LUID GetModifiedIDLUID(SafeCloseHandle token) { using (SafeHandle buffer = GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TokenStatistics)) { TOKEN_STATISTICS tokenStats = (TOKEN_STATISTICS) Marshal.PtrToStructure(buffer.DangerousGetHandle(), typeof(TOKEN_STATISTICS)); return tokenStats.ModifiedId; } } public static WindowsIdentity GetAnonymousIdentity() { SafeCloseHandle tokenHandle = null; bool isImpersonating = false; lock (lockObject) { if (anonymousIdentity == null) { try { try { if (!SafeNativeMethods.ImpersonateAnonymousUserOnCurrentThread(SafeNativeMethods.GetCurrentThread())) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error, SR.GetString(SR.ImpersonateAnonymousTokenFailed, error))); } isImpersonating = true; bool revertSuccess; bool isSuccess = SafeNativeMethods.OpenCurrentThreadToken(SafeNativeMethods.GetCurrentThread(), TokenAccessLevels.Query, true, out tokenHandle); if (!isSuccess) { int error = Marshal.GetLastWin32Error(); revertSuccess = SafeNativeMethods.RevertToSelf(); if (false == revertSuccess) { error = Marshal.GetLastWin32Error(); //this requires a failfast since failure to revert impersonation compromises security DiagnosticUtility.FailFast("RevertToSelf() failed with " + error); } isImpersonating = false; Utility.CloseInvalidOutSafeHandle(tokenHandle); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error, SR.GetString(SR.OpenThreadTokenFailed, error))); } revertSuccess = SafeNativeMethods.RevertToSelf(); if (false == revertSuccess) { int error = Marshal.GetLastWin32Error(); //this requires a failfast since failure to revert impersonation compromises security DiagnosticUtility.FailFast("RevertToSelf() failed with " + error); } isImpersonating = false; using (tokenHandle) { anonymousIdentity = new WindowsIdentity(tokenHandle.DangerousGetHandle()); } } finally { if (isImpersonating) { bool revertSuccess = SafeNativeMethods.RevertToSelf(); if (false == revertSuccess) { int error = Marshal.GetLastWin32Error(); //this requires a failfast since failure to revert impersonation compromises security DiagnosticUtility.FailFast("RevertToSelf() failed with " + error); } } } } catch { // Force the finally to run before leaving the method. throw; } } } return anonymousIdentity; } public static WindowsIdentity GetProcessIdentity() { SafeCloseHandle tokenHandle = null; lock (lockObject) { try { bool isSuccess = SafeNativeMethods.GetCurrentProcessToken(SafeNativeMethods.GetCurrentProcess(), TokenAccessLevels.Query, out tokenHandle); if (!isSuccess) { int error = Marshal.GetLastWin32Error(); Utility.CloseInvalidOutSafeHandle(tokenHandle); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error, SR.GetString(SR.OpenProcessTokenFailed, error))); } processIdentity = new WindowsIdentity(tokenHandle.DangerousGetHandle()); } finally { if (tokenHandle != null) tokenHandle.Dispose(); } } return processIdentity; } } internal sealed class ComPlusAuthorization { string[] serviceRoleMembers = null; string[] contractRoleMembers = null; string[] operationRoleMembers = null; CommonSecurityDescriptor securityDescriptor = null; static SecurityIdentifier sidAdministrators = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null); DictionaryaccessCheckCache = new Dictionary (); public ComPlusAuthorization(string[] serviceRoleMembers, string[] contractRoleMembers, string[] operationRoleMembers) { this.serviceRoleMembers = serviceRoleMembers; this.contractRoleMembers = contractRoleMembers; this.operationRoleMembers = operationRoleMembers; } private void BuildSecurityDescriptor() { DiagnosticUtility.DebugAssert((null == securityDescriptor), "SecurityDescriptor must be NULL"); NTAccount name; SecurityIdentifier sid; CommonAce ace; RawAcl acl = new RawAcl(GenericAcl.AclRevision, 1); int index = 0; if (operationRoleMembers != null) { foreach (string userName in operationRoleMembers) { name = new NTAccount(userName); sid = (SecurityIdentifier)name.Translate(typeof(SecurityIdentifier)); ace = new CommonAce(AceFlags.None, AceQualifier.AccessAllowed, (int)ComRights.EXECUTE, sid, false, null); acl.InsertAce(index, ace); index++; } } if (contractRoleMembers != null) { foreach (string userName in contractRoleMembers) { name = new NTAccount(userName); sid = (SecurityIdentifier)name.Translate(typeof(SecurityIdentifier)); ace = new CommonAce(AceFlags.None, AceQualifier.AccessAllowed, (int)ComRights.EXECUTE, sid, false, null); acl.InsertAce(index, ace); index++; } } if (serviceRoleMembers != null) { foreach (string userName in serviceRoleMembers) { name = new NTAccount(userName); sid = (SecurityIdentifier)name.Translate(typeof(SecurityIdentifier)); ace = new CommonAce(AceFlags.None, AceQualifier.AccessAllowed, (int)ComRights.EXECUTE, sid, false, null); acl.InsertAce(index, ace); index++; } } DiscretionaryAcl dacl = new DiscretionaryAcl(true, false, acl); securityDescriptor = new CommonSecurityDescriptor(true, false, ControlFlags.DiscretionaryAclPresent, sidAdministrators, sidAdministrators, null, dacl); } private bool IsAccessCached(LUID luidModifiedID, out bool isAccessAllowed) { if (null == accessCheckCache) { DiagnosticUtility.DebugAssert("AcessCheckCache must not be NULL"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(true); } bool retValue = false; lock(this) { retValue = accessCheckCache.TryGetValue(luidModifiedID, out isAccessAllowed); } return retValue; } private void CacheAccessCheck(LUID luidModifiedID, bool isAccessAllowed) { if (null == accessCheckCache) { DiagnosticUtility.DebugAssert("AcessCheckCache must not be NULL"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(true); } lock (this) { accessCheckCache[luidModifiedID] = isAccessAllowed; } } private void CheckAccess(WindowsIdentity clientIdentity, out bool IsAccessAllowed) { if (null == securityDescriptor) { DiagnosticUtility.DebugAssert("Security Descriptor must not be NULL"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(true); } IsAccessAllowed = false; byte[] BinaryForm = new byte[securityDescriptor.BinaryLength]; securityDescriptor.GetBinaryForm(BinaryForm, 0); SafeCloseHandle ImpersonationToken = null; SafeCloseHandle clientIdentityToken = new SafeCloseHandle(clientIdentity.Token, false); try { if (SecurityUtils.IsPrimaryToken(clientIdentityToken)) { if (!SafeNativeMethods.DuplicateTokenEx(clientIdentityToken, TokenAccessLevels.Query, IntPtr.Zero, SecurityImpersonationLevel.Identification, TokenType.TokenImpersonation, out ImpersonationToken)) { int error = Marshal.GetLastWin32Error(); Utility.CloseInvalidOutSafeHandle(ImpersonationToken); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error, SR.GetString(SR.DuplicateTokenExFailed, error))); } } GENERIC_MAPPING GenericMapping = new GENERIC_MAPPING(); PRIVILEGE_SET PrivilegeSet = new PRIVILEGE_SET(); uint PrivilegeSetLength = (uint)Marshal.SizeOf(PrivilegeSet); uint GrantedAccess = 0; if (!SafeNativeMethods.AccessCheck(BinaryForm, (ImpersonationToken != null) ? ImpersonationToken : clientIdentityToken, (int)ComRights.EXECUTE, GenericMapping, out PrivilegeSet, ref PrivilegeSetLength, out GrantedAccess, out IsAccessAllowed)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new Win32Exception(error, SR.GetString(SR.AccessCheckFailed, error))); } } finally { if (ImpersonationToken != null) ImpersonationToken.Dispose(); } } public string[] ServiceRoleMembers { get { return serviceRoleMembers; } } public string[] ContractRoleMembers { get { return contractRoleMembers; } } public string[] OperationRoleMembers { get { return operationRoleMembers; } } public CommonSecurityDescriptor SecurityDescriptor { get { return securityDescriptor; } } public bool IsAuthorizedForOperation(WindowsIdentity clientIdentity) { bool IsAccessAllowed = false; if (null == clientIdentity) { DiagnosticUtility.DebugAssert("NULL Identity"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } if (IntPtr.Zero == clientIdentity.Token) { DiagnosticUtility.DebugAssert("Token handle cannot be zero"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } lock (this) { if (securityDescriptor == null) { BuildSecurityDescriptor(); } } LUID luidModified = SecurityUtils.GetModifiedIDLUID(new SafeCloseHandle(clientIdentity.Token, false)); if (IsAccessCached(luidModified, out IsAccessAllowed)) return IsAccessAllowed; CheckAccess(clientIdentity, out IsAccessAllowed); CacheAccessCheck(luidModified, IsAccessAllowed); return IsAccessAllowed; } } internal sealed class ComPlusServerSecurity : IContextSecurityPerimeter, IServerSecurity, IDisposable { WindowsIdentity clientIdentity = null; IntPtr oldSecurityObject = IntPtr.Zero; WindowsImpersonationContext impersonateContext = null; bool isImpersonating = false; bool shouldUseCallContext = false; const uint RPC_C_AUTHN_GSS_NEGOTIATE = 9; const uint RPC_C_AUTHN_WINNT = 10; const uint RPC_C_AUTHN_GSS_KERBEROS = 16; const uint RPC_C_AUTHN_DEFAULT = unchecked((uint)0xFFFFFFFF); const uint RPC_C_AUTHZ_NONE = 0; const uint RPC_C_AUTHN_LEVEL_DEFAULT = 0; const uint RPC_C_AUTHN_LEVEL_NONE = 1; const uint RPC_C_AUTHN_LEVEL_CONNECT = 2; const uint RPC_C_AUTHN_LEVEL_CALL = 3; const uint RPC_C_AUTHN_LEVEL_PKT = 4; const uint RPC_C_AUTHN_LEVEL_PKT_INTEGRITY = 5; const uint RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6; public ComPlusServerSecurity(WindowsIdentity clientIdentity, bool shouldUseCallContext) { if (null == clientIdentity) { DiagnosticUtility.DebugAssert("NULL Identity"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } if (IntPtr.Zero == clientIdentity.Token) { DiagnosticUtility.DebugAssert("Token handle cannot be zero"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); } this.shouldUseCallContext = shouldUseCallContext; this.clientIdentity = clientIdentity; IntPtr secCtx = Marshal.GetIUnknownForObject(this); try { oldSecurityObject = SafeNativeMethods.CoSwitchCallContext(secCtx); } catch { Marshal.Release(secCtx); throw; } } ~ComPlusServerSecurity() { Dispose(false); } public bool GetPerimeterFlag() { return shouldUseCallContext; } public void SetPerimeterFlag(bool flag) { shouldUseCallContext = flag; } public void QueryBlanket ( IntPtr authnSvc, IntPtr authzSvc, IntPtr serverPrincipalName, IntPtr authnLevel, IntPtr impLevel, IntPtr clientPrincipalName, IntPtr Capabilities ) { // Convert to RPC'isms. if (authnSvc != IntPtr.Zero) { uint tempAuthnSvc = RPC_C_AUTHN_DEFAULT; // Try to convert the clientIdentity.AuthenticationType to an RPC constant. // This is a best case attempt. string authenticationType = clientIdentity.AuthenticationType; if (authenticationType.ToUpperInvariant() == "NTLM") tempAuthnSvc = RPC_C_AUTHN_WINNT; else if (authenticationType.ToUpperInvariant() == "KERBEROS") tempAuthnSvc = RPC_C_AUTHN_GSS_KERBEROS; else if (authenticationType.ToUpperInvariant() == "NEGOTIATE") tempAuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE; Marshal.WriteInt32(authnSvc, (int)tempAuthnSvc); } if (authzSvc != IntPtr.Zero) { Marshal.WriteInt32(authzSvc, (int)RPC_C_AUTHZ_NONE); } if (serverPrincipalName != IntPtr.Zero) { IntPtr str = Marshal.StringToCoTaskMemUni(SecurityUtils.GetProcessIdentity().Name); Marshal.WriteIntPtr(serverPrincipalName, str); } // There is no equivalent for the RPC authn level. It can only be // approximated, in the best case. Use default. if (authnLevel != IntPtr.Zero) { Marshal.WriteInt32(authnLevel, (int)RPC_C_AUTHN_LEVEL_DEFAULT); } if (impLevel != IntPtr.Zero) { Marshal.WriteInt32(impLevel, 0); } if (clientPrincipalName != IntPtr.Zero) { IntPtr str = Marshal.StringToCoTaskMemUni(clientIdentity.Name); Marshal.WriteIntPtr(clientPrincipalName, str); } if (Capabilities != IntPtr.Zero) { Marshal.WriteInt32(Capabilities, 0); } } public int ImpersonateClient() { // We want to return known COM hresults here rather than random CLR-Exception mapped HRESULTS. Also, // we don't want CLR to set the ErrorInfo object. int hresult = HR.E_FAIL; try { impersonateContext = WindowsIdentity.Impersonate(clientIdentity.Token); isImpersonating = true; hresult = HR.S_OK; } catch (SecurityException) { // Special case anonymous impersonation failure. // Unmanaged callers to ImpersonateClient expect this hresult. hresult = HR.RPC_NT_BINDING_HAS_NO_AUTH; } catch(Exception e) { if(DiagnosticUtility.IsFatal(e)) throw; } return hresult; } public int RevertToSelf() { // We want to return known COM hresults here rather than random CLR-Exception mapped HRESULTS. Also, // we don't want CLR to set the ErrorInfo object. int hresult = HR.E_FAIL; if (isImpersonating) { try { impersonateContext.Undo(); isImpersonating = false; hresult = HR.S_OK; } catch (Exception e) { if (DiagnosticUtility.IsFatal(e)) throw; } } return hresult; } public bool IsImpersonating() { return isImpersonating; } void IDisposable.Dispose() { Dispose(true); GC.SuppressFinalize(this); } public void Dispose(bool disposing) { RevertToSelf(); IntPtr secCtx = SafeNativeMethods.CoSwitchCallContext(oldSecurityObject); if (IntPtr.Zero == secCtx) { // this has to be a failfast since not having a security context can compromise security DiagnosticUtility.FailFast("Security Context was should not be null"); } if (Marshal.GetObjectForIUnknown(secCtx) != this) { // this has to be a failfast since being in the wrong security context can compromise security DiagnosticUtility.FailFast("Security Context was modified from underneath us"); } Marshal.Release(secCtx); if (disposing) { clientIdentity = null; if (impersonateContext != null) impersonateContext.Dispose(); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CrossSiteScriptingValidation.cs
- AttributeQuery.cs
- SelectionChangedEventArgs.cs
- QueryRewriter.cs
- XmlQueryTypeFactory.cs
- Listbox.cs
- TreeViewHitTestInfo.cs
- TableItemStyle.cs
- MouseEvent.cs
- TableLayoutSettings.cs
- WebControlsSection.cs
- ColorInterpolationModeValidation.cs
- TemplateParser.cs
- SBCSCodePageEncoding.cs
- PersistenceException.cs
- DecoratedNameAttribute.cs
- Constraint.cs
- XpsLiterals.cs
- MessageBodyDescription.cs
- XmlNode.cs
- Typography.cs
- GZipDecoder.cs
- JournalNavigationScope.cs
- FixedNode.cs
- ApplyTemplatesAction.cs
- WindowsGraphicsWrapper.cs
- TraceHandlerErrorFormatter.cs
- MeasureData.cs
- GeometryGroup.cs
- JsonByteArrayDataContract.cs
- GenericUriParser.cs
- FramingChannels.cs
- Int32CAMarshaler.cs
- ModelTreeEnumerator.cs
- XmlEntityReference.cs
- LookupBindingPropertiesAttribute.cs
- FlowLayout.cs
- ChildChangedEventArgs.cs
- EntityProviderFactory.cs
- ObservableDictionary.cs
- HuffCodec.cs
- ReaderWriterLockWrapper.cs
- wgx_sdk_version.cs
- DoubleLink.cs
- Graph.cs
- EventDescriptor.cs
- EntityContainerEmitter.cs
- ComponentTray.cs
- WebPartConnection.cs
- XmlHierarchyData.cs
- DataGridViewRowCollection.cs
- SqlClientPermission.cs
- ProtocolViolationException.cs
- Pair.cs
- ExtensibleClassFactory.cs
- AnnotationResourceChangedEventArgs.cs
- InternalConfigSettingsFactory.cs
- WaitForChangedResult.cs
- WebControlsSection.cs
- Table.cs
- DataGridViewRowPrePaintEventArgs.cs
- DesignSurfaceServiceContainer.cs
- QilName.cs
- FieldToken.cs
- SafeBitVector32.cs
- precedingsibling.cs
- StylusPointProperty.cs
- login.cs
- InkCanvasSelection.cs
- RecognizerStateChangedEventArgs.cs
- FileVersion.cs
- SelectionItemProviderWrapper.cs
- XmlStreamNodeWriter.cs
- ColorContext.cs
- ImageResources.Designer.cs
- ParameterBuilder.cs
- Compensation.cs
- ListView.cs
- ArraySet.cs
- LogSwitch.cs
- X509Certificate2Collection.cs
- ProfileBuildProvider.cs
- TargetParameterCountException.cs
- DataSvcMapFileSerializer.cs
- WsdlBuildProvider.cs
- HideDisabledControlAdapter.cs
- Ipv6Element.cs
- SmtpSection.cs
- filewebrequest.cs
- IndexingContentUnit.cs
- RowToFieldTransformer.cs
- ModifiableIteratorCollection.cs
- GraphicsContainer.cs
- DataGridViewCellLinkedList.cs
- ThreadStaticAttribute.cs
- RoleGroupCollection.cs
- CodeComment.cs
- SchemaImporterExtension.cs
- WebPartEditorOkVerb.cs
- OleDbCommandBuilder.cs