e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
325 lines
11 KiB
C#
325 lines
11 KiB
C#
//------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------
|
|
|
|
namespace System.ServiceModel.Security
|
|
{
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Channels;
|
|
using System.Collections.ObjectModel;
|
|
using System.Collections.Generic;
|
|
using System.IdentityModel.Claims;
|
|
using System.IdentityModel.Policy;
|
|
using System.IdentityModel.Tokens;
|
|
using System.ServiceModel.Security.Tokens;
|
|
using System.Net.Security;
|
|
|
|
public class SecurityMessageProperty : IMessageProperty, IDisposable
|
|
{
|
|
// This is the list of outgoing supporting tokens
|
|
Collection<SupportingTokenSpecification> outgoingSupportingTokens;
|
|
Collection<SupportingTokenSpecification> incomingSupportingTokens;
|
|
SecurityTokenSpecification transportToken;
|
|
SecurityTokenSpecification protectionToken;
|
|
SecurityTokenSpecification initiatorToken;
|
|
SecurityTokenSpecification recipientToken;
|
|
|
|
ServiceSecurityContext securityContext;
|
|
ReadOnlyCollection<IAuthorizationPolicy> externalAuthorizationPolicies;
|
|
string senderIdPrefix = "_";
|
|
bool disposed = false;
|
|
|
|
public SecurityMessageProperty()
|
|
{
|
|
this.securityContext = ServiceSecurityContext.Anonymous;
|
|
}
|
|
|
|
public ServiceSecurityContext ServiceSecurityContext
|
|
{
|
|
get
|
|
{
|
|
ThrowIfDisposed();
|
|
return this.securityContext;
|
|
}
|
|
set
|
|
{
|
|
ThrowIfDisposed();
|
|
this.securityContext = value;
|
|
}
|
|
}
|
|
|
|
public ReadOnlyCollection<IAuthorizationPolicy> ExternalAuthorizationPolicies
|
|
{
|
|
get
|
|
{
|
|
return this.externalAuthorizationPolicies;
|
|
}
|
|
set
|
|
{
|
|
this.externalAuthorizationPolicies = value;
|
|
}
|
|
}
|
|
|
|
public SecurityTokenSpecification ProtectionToken
|
|
{
|
|
get
|
|
{
|
|
ThrowIfDisposed();
|
|
return this.protectionToken;
|
|
}
|
|
set
|
|
{
|
|
ThrowIfDisposed();
|
|
this.protectionToken = value;
|
|
}
|
|
}
|
|
|
|
public SecurityTokenSpecification InitiatorToken
|
|
{
|
|
get
|
|
{
|
|
ThrowIfDisposed();
|
|
return this.initiatorToken;
|
|
}
|
|
set
|
|
{
|
|
ThrowIfDisposed();
|
|
this.initiatorToken = value;
|
|
}
|
|
}
|
|
|
|
public SecurityTokenSpecification RecipientToken
|
|
{
|
|
get
|
|
{
|
|
ThrowIfDisposed();
|
|
return this.recipientToken;
|
|
}
|
|
set
|
|
{
|
|
ThrowIfDisposed();
|
|
this.recipientToken = value;
|
|
}
|
|
}
|
|
|
|
public SecurityTokenSpecification TransportToken
|
|
{
|
|
get
|
|
{
|
|
ThrowIfDisposed();
|
|
return this.transportToken;
|
|
}
|
|
set
|
|
{
|
|
ThrowIfDisposed();
|
|
this.transportToken = value;
|
|
}
|
|
}
|
|
|
|
|
|
public string SenderIdPrefix
|
|
{
|
|
get
|
|
{
|
|
return this.senderIdPrefix;
|
|
}
|
|
set
|
|
{
|
|
XmlHelper.ValidateIdPrefix(value);
|
|
this.senderIdPrefix = value;
|
|
}
|
|
}
|
|
|
|
public bool HasIncomingSupportingTokens
|
|
{
|
|
get
|
|
{
|
|
ThrowIfDisposed();
|
|
return ((this.incomingSupportingTokens != null) && (this.incomingSupportingTokens.Count > 0));
|
|
}
|
|
}
|
|
|
|
public Collection<SupportingTokenSpecification> IncomingSupportingTokens
|
|
{
|
|
get
|
|
{
|
|
ThrowIfDisposed();
|
|
if (this.incomingSupportingTokens == null)
|
|
{
|
|
this.incomingSupportingTokens = new Collection<SupportingTokenSpecification>();
|
|
}
|
|
return this.incomingSupportingTokens;
|
|
}
|
|
}
|
|
|
|
public Collection<SupportingTokenSpecification> OutgoingSupportingTokens
|
|
{
|
|
get
|
|
{
|
|
if (this.outgoingSupportingTokens == null)
|
|
{
|
|
this.outgoingSupportingTokens = new Collection<SupportingTokenSpecification>();
|
|
}
|
|
return this.outgoingSupportingTokens;
|
|
}
|
|
}
|
|
|
|
internal bool HasOutgoingSupportingTokens
|
|
{
|
|
get
|
|
{
|
|
return ((this.outgoingSupportingTokens != null) && (this.outgoingSupportingTokens.Count > 0));
|
|
}
|
|
}
|
|
|
|
public IMessageProperty CreateCopy()
|
|
{
|
|
ThrowIfDisposed();
|
|
SecurityMessageProperty result = new SecurityMessageProperty();
|
|
|
|
if (this.HasOutgoingSupportingTokens)
|
|
{
|
|
for (int i = 0; i < this.outgoingSupportingTokens.Count; ++i)
|
|
{
|
|
result.OutgoingSupportingTokens.Add(this.outgoingSupportingTokens[i]);
|
|
}
|
|
}
|
|
|
|
if (this.HasIncomingSupportingTokens)
|
|
{
|
|
for (int i = 0; i < this.incomingSupportingTokens.Count; ++i)
|
|
{
|
|
result.IncomingSupportingTokens.Add(this.incomingSupportingTokens[i]);
|
|
}
|
|
}
|
|
|
|
result.securityContext = this.securityContext;
|
|
result.externalAuthorizationPolicies = this.externalAuthorizationPolicies;
|
|
result.senderIdPrefix = this.senderIdPrefix;
|
|
|
|
result.protectionToken = this.protectionToken;
|
|
result.initiatorToken = this.initiatorToken;
|
|
result.recipientToken = this.recipientToken;
|
|
result.transportToken = this.transportToken;
|
|
|
|
return result;
|
|
}
|
|
|
|
public static SecurityMessageProperty GetOrCreate(Message message)
|
|
{
|
|
if (message == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
|
|
|
|
SecurityMessageProperty result = null;
|
|
if (message.Properties != null)
|
|
result = message.Properties.Security;
|
|
|
|
if (result == null)
|
|
{
|
|
result = new SecurityMessageProperty();
|
|
message.Properties.Security = result;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void AddAuthorizationPolicies(SecurityTokenSpecification spec, Collection<IAuthorizationPolicy> policies)
|
|
{
|
|
if (spec != null && spec.SecurityTokenPolicies != null && spec.SecurityTokenPolicies.Count > 0)
|
|
{
|
|
for (int i = 0; i < spec.SecurityTokenPolicies.Count; ++i)
|
|
{
|
|
policies.Add(spec.SecurityTokenPolicies[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal ReadOnlyCollection<IAuthorizationPolicy> GetInitiatorTokenAuthorizationPolicies()
|
|
{
|
|
return GetInitiatorTokenAuthorizationPolicies(true);
|
|
}
|
|
|
|
internal ReadOnlyCollection<IAuthorizationPolicy> GetInitiatorTokenAuthorizationPolicies(bool includeTransportToken)
|
|
{
|
|
return GetInitiatorTokenAuthorizationPolicies(includeTransportToken, null);
|
|
}
|
|
|
|
internal ReadOnlyCollection<IAuthorizationPolicy> GetInitiatorTokenAuthorizationPolicies(bool includeTransportToken, SecurityContextSecurityToken supportingSessionTokenToExclude)
|
|
{
|
|
// fast path
|
|
if (!this.HasIncomingSupportingTokens)
|
|
{
|
|
if (this.transportToken != null && this.initiatorToken == null && this.protectionToken == null)
|
|
{
|
|
if (includeTransportToken && this.transportToken.SecurityTokenPolicies != null)
|
|
{
|
|
return this.transportToken.SecurityTokenPolicies;
|
|
}
|
|
else
|
|
{
|
|
return EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
|
|
}
|
|
}
|
|
else if (this.transportToken == null && this.initiatorToken != null && this.protectionToken == null)
|
|
{
|
|
return this.initiatorToken.SecurityTokenPolicies ?? EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
|
|
}
|
|
else if (this.transportToken == null && this.initiatorToken == null && this.protectionToken != null)
|
|
{
|
|
return this.protectionToken.SecurityTokenPolicies ?? EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
|
|
}
|
|
}
|
|
|
|
Collection<IAuthorizationPolicy> policies = new Collection<IAuthorizationPolicy>();
|
|
if (includeTransportToken)
|
|
{
|
|
AddAuthorizationPolicies(this.transportToken, policies);
|
|
}
|
|
AddAuthorizationPolicies(this.initiatorToken, policies);
|
|
AddAuthorizationPolicies(this.protectionToken, policies);
|
|
if (this.HasIncomingSupportingTokens)
|
|
{
|
|
for (int i = 0; i < this.incomingSupportingTokens.Count; ++i)
|
|
{
|
|
if (supportingSessionTokenToExclude != null)
|
|
{
|
|
SecurityContextSecurityToken sct = this.incomingSupportingTokens[i].SecurityToken as SecurityContextSecurityToken;
|
|
if (sct != null && sct.ContextId == supportingSessionTokenToExclude.ContextId)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
SecurityTokenAttachmentMode attachmentMode = this.incomingSupportingTokens[i].SecurityTokenAttachmentMode;
|
|
// a safety net in case more attachment modes get added to the product without
|
|
// reviewing this code.
|
|
if (attachmentMode == SecurityTokenAttachmentMode.Endorsing
|
|
|| attachmentMode == SecurityTokenAttachmentMode.Signed
|
|
|| attachmentMode == SecurityTokenAttachmentMode.SignedEncrypted
|
|
|| attachmentMode == SecurityTokenAttachmentMode.SignedEndorsing)
|
|
{
|
|
AddAuthorizationPolicies(this.incomingSupportingTokens[i], policies);
|
|
}
|
|
}
|
|
}
|
|
return new ReadOnlyCollection<IAuthorizationPolicy>(policies);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
// do no-op for future V2
|
|
if (!this.disposed)
|
|
{
|
|
this.disposed = true;
|
|
}
|
|
}
|
|
|
|
void ThrowIfDisposed()
|
|
{
|
|
if (this.disposed)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName));
|
|
}
|
|
}
|
|
}
|
|
}
|