1 // 2 // ChannelProtectionRequirements.cs 3 // 4 // Author: 5 // Atsushi Enomoto <atsushi@ximian.com> 6 // 7 // Copyright (C) 2005-2006 Novell, Inc. http://www.novell.com 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining 10 // a copy of this software and associated documentation files (the 11 // "Software"), to deal in the Software without restriction, including 12 // without limitation the rights to use, copy, modify, merge, publish, 13 // distribute, sublicense, and/or sell copies of the Software, and to 14 // permit persons to whom the Software is furnished to do so, subject to 15 // the following conditions: 16 // 17 // The above copyright notice and this permission notice shall be 18 // included in all copies or substantial portions of the Software. 19 // 20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 // 28 using System; 29 using System.Net.Security; 30 using System.Collections.Generic; 31 using System.ServiceModel; 32 using System.ServiceModel.Description; 33 using System.Xml; 34 35 namespace System.ServiceModel.Security 36 { 37 // Represents sp:SignedParts and sp:EncryptedParts in 38 // sp:SupportingTokens/ws:Policy/. 39 public class ChannelProtectionRequirements 40 { 41 bool is_readonly; 42 ScopedMessagePartSpecification in_enc, in_sign, out_enc, out_sign; 43 ChannelProtectionRequirements()44 public ChannelProtectionRequirements () 45 { 46 in_enc = new ScopedMessagePartSpecification (); 47 out_enc = new ScopedMessagePartSpecification (); 48 in_sign = new ScopedMessagePartSpecification (); 49 out_sign = new ScopedMessagePartSpecification (); 50 } 51 ChannelProtectionRequirements( ChannelProtectionRequirements other)52 public ChannelProtectionRequirements ( 53 ChannelProtectionRequirements other) 54 { 55 if (other == null) 56 throw new ArgumentNullException ("other"); 57 in_enc = new ScopedMessagePartSpecification (other.in_enc); 58 out_enc = new ScopedMessagePartSpecification (other.out_enc); 59 in_sign = new ScopedMessagePartSpecification (other.in_sign); 60 out_sign = new ScopedMessagePartSpecification (other.out_sign); 61 } 62 63 public bool IsReadOnly { 64 get { return is_readonly; } 65 } 66 67 public ScopedMessagePartSpecification IncomingEncryptionParts { 68 get { return in_enc; } 69 } 70 71 public ScopedMessagePartSpecification IncomingSignatureParts { 72 get { return in_sign; } 73 } 74 75 public ScopedMessagePartSpecification OutgoingEncryptionParts { 76 get { return out_enc; } 77 } 78 79 public ScopedMessagePartSpecification OutgoingSignatureParts { 80 get { return out_sign; } 81 } 82 Add( ChannelProtectionRequirements protectionRequirements)83 public void Add ( 84 ChannelProtectionRequirements protectionRequirements) 85 { 86 Add (protectionRequirements, false); 87 } 88 Add( ChannelProtectionRequirements protectionRequirements, bool channelScopeOnly)89 public void Add ( 90 ChannelProtectionRequirements protectionRequirements, 91 bool channelScopeOnly) 92 { 93 if (is_readonly) 94 throw new InvalidOperationException ("This ChannelProtectionRequirements is read-only."); 95 96 AddScopedParts ( 97 protectionRequirements.IncomingEncryptionParts, 98 IncomingEncryptionParts, 99 channelScopeOnly); 100 AddScopedParts ( 101 protectionRequirements.IncomingSignatureParts, 102 IncomingSignatureParts, 103 channelScopeOnly); 104 AddScopedParts ( 105 protectionRequirements.OutgoingEncryptionParts, 106 OutgoingEncryptionParts, 107 channelScopeOnly); 108 AddScopedParts ( 109 protectionRequirements.OutgoingSignatureParts, 110 OutgoingSignatureParts, 111 channelScopeOnly); 112 } 113 AddScopedParts(ScopedMessagePartSpecification src, ScopedMessagePartSpecification dst, bool channelOnly)114 void AddScopedParts (ScopedMessagePartSpecification src, ScopedMessagePartSpecification dst, bool channelOnly) 115 { 116 dst.AddParts (src.ChannelParts); 117 if (channelOnly) 118 return; 119 120 foreach (string a in src.Actions) { 121 MessagePartSpecification m; 122 src.TryGetParts (a, out m); 123 src.AddParts (m); 124 } 125 } 126 CreateInverse()127 public ChannelProtectionRequirements CreateInverse () 128 { 129 ChannelProtectionRequirements r = 130 new ChannelProtectionRequirements (); 131 AddScopedParts (in_enc, r.out_enc, false); 132 AddScopedParts (in_sign, r.out_sign, false); 133 AddScopedParts (out_enc, r.in_enc, false); 134 AddScopedParts (out_sign, r.in_sign, false); 135 return r; 136 } 137 MakeReadOnly()138 public void MakeReadOnly () 139 { 140 is_readonly = true; 141 in_enc.MakeReadOnly (); 142 in_sign.MakeReadOnly (); 143 out_enc.MakeReadOnly (); 144 out_sign.MakeReadOnly (); 145 } 146 CreateFromContract(ContractDescription cd)147 internal static ChannelProtectionRequirements CreateFromContract (ContractDescription cd) 148 { 149 ChannelProtectionRequirements cp = 150 new ChannelProtectionRequirements (); 151 List<XmlQualifiedName> enc = new List<XmlQualifiedName> (); 152 List<XmlQualifiedName> sig = new List<XmlQualifiedName> (); 153 if (cd.HasProtectionLevel) { 154 switch (cd.ProtectionLevel) { 155 case ProtectionLevel.EncryptAndSign: 156 cp.IncomingEncryptionParts.ChannelParts.IsBodyIncluded = true; 157 cp.OutgoingEncryptionParts.ChannelParts.IsBodyIncluded = true; 158 goto case ProtectionLevel.Sign; 159 case ProtectionLevel.Sign: 160 cp.IncomingSignatureParts.ChannelParts.IsBodyIncluded = true; 161 cp.OutgoingSignatureParts.ChannelParts.IsBodyIncluded = true; 162 break; 163 } 164 } 165 foreach (OperationDescription od in cd.Operations) { 166 foreach (MessageDescription md in od.Messages) { 167 enc.Clear (); 168 sig.Clear (); 169 ProtectionLevel mplv = 170 md.HasProtectionLevel ? md.ProtectionLevel : 171 od.HasProtectionLevel ? od.ProtectionLevel : 172 ProtectionLevel.EncryptAndSign; // default 173 foreach (MessageHeaderDescription hd in md.Headers) 174 AddPartProtectionRequirements (enc, sig, hd, cp); 175 176 ScopedMessagePartSpecification spec; 177 bool includeBodyEnc = mplv == ProtectionLevel.EncryptAndSign; 178 bool includeBodySig = mplv != ProtectionLevel.None; 179 180 // enc 181 spec = md.Direction == MessageDirection.Input ? 182 cp.IncomingEncryptionParts : 183 cp.OutgoingEncryptionParts; 184 spec.AddParts (new MessagePartSpecification (includeBodyEnc, enc.ToArray ()), md.Action); 185 // sig 186 spec = md.Direction == MessageDirection.Input ? 187 cp.IncomingSignatureParts : 188 cp.OutgoingSignatureParts; 189 spec.AddParts (new MessagePartSpecification (includeBodySig, sig.ToArray ()), md.Action); 190 } 191 } 192 return cp; 193 } 194 AddPartProtectionRequirements(List<XmlQualifiedName> enc, List<XmlQualifiedName> sig, MessageHeaderDescription pd, ChannelProtectionRequirements cp)195 static void AddPartProtectionRequirements (List<XmlQualifiedName> enc, 196 List<XmlQualifiedName> sig, 197 MessageHeaderDescription pd, 198 ChannelProtectionRequirements cp) 199 { 200 if (!pd.HasProtectionLevel) 201 return; // no specific part indication 202 switch (pd.ProtectionLevel) { 203 case ProtectionLevel.EncryptAndSign: 204 enc.Add (new XmlQualifiedName (pd.Name, pd.Namespace)); 205 goto case ProtectionLevel.Sign; 206 case ProtectionLevel.Sign: 207 sig.Add (new XmlQualifiedName (pd.Name, pd.Namespace)); 208 break; 209 } 210 } 211 } 212 } 213