2010-06-03 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.ServiceModel / Mono.Security.Protocol.Ntlm / Type2Message.cs
blob76c9022ed2344a0e52545f194653c0e76394fcb9
1 //
2 // Mono.Security.Protocol.Ntlm.Type2Message - Challenge
3 //
4 // Author:
5 // Sebastien Pouliot <sebastien@ximian.com>
6 // Atsushi Enomoto <atsushi@ximian.com>
7 //
8 // Copyright (C) 2003 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) 2004, 2007 Novell, Inc (http://www.novell.com)
11 // References
12 // a. NTLM Authentication Scheme for HTTP, Ronald Tschalär
13 // http://www.innovation.ch/java/ntlm.html
14 // b. The NTLM Authentication Protocol, Copyright © 2003 Eric Glass
15 // http://davenport.sourceforge.net/ntlm.html
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
24 //
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
27 //
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 using System;
38 using System.Security.Cryptography;
39 using System.Text;
41 namespace Mono.Security.Protocol.Ntlm {
43 public class Type2Message : MessageBase {
45 private byte[] _nonce;
46 private byte[] _context;
47 private NtlmTargetInformation _target;
48 private string _target_name;
50 public Type2Message () : this (NtlmVersion.Version1)
54 public Type2Message (NtlmVersion version) : base (2, version)
56 _nonce = new byte [8];
57 RandomNumberGenerator rng = RandomNumberGenerator.Create ();
58 rng.GetBytes (_nonce);
59 // default values
60 Flags = (NtlmFlags) 0x8201;
61 if (Version != NtlmVersion.Version1) {
62 _context = new byte [8];
63 _target = new NtlmTargetInformation ();
67 public Type2Message (byte[] message) : this (message, NtlmVersion.Version1)
71 public Type2Message (byte[] message, NtlmVersion version) : base (2, version)
73 _nonce = new byte [8];
74 Decode (message);
77 ~Type2Message ()
79 if (_nonce != null)
80 Array.Clear (_nonce, 0, _nonce.Length);
83 // properties
85 public byte[] Context {
86 get { return (byte[]) _context.Clone (); }
87 set {
88 if (value == null)
89 throw new ArgumentNullException ("Nonce");
90 if (value.Length != 8) {
91 string msg = Locale.GetText ("Invalid Nonce Length (should be 8 bytes).");
92 throw new ArgumentException (msg, "Nonce");
94 _context = (byte[]) value.Clone ();
98 public byte[] Nonce {
99 get { return (byte[]) _nonce.Clone (); }
100 set {
101 if (value == null)
102 throw new ArgumentNullException ("Nonce");
103 if (value.Length != 8) {
104 string msg = Locale.GetText ("Invalid Nonce Length (should be 8 bytes).");
105 throw new ArgumentException (msg, "Nonce");
107 _nonce = (byte[]) value.Clone ();
111 public NtlmTargetInformation Target {
112 get { return _target; }
115 public string TargetName {
116 get { return _target_name; }
117 set { _target_name = value; }
120 // methods
122 protected override void Decode (byte[] message)
124 base.Decode (message);
126 short targetNameSize = BitConverterLE.ToInt16 (message, 12);
127 int targetNameOffset = BitConverterLE.ToInt32 (message, 16);
129 Flags = (NtlmFlags) BitConverterLE.ToUInt32 (message, 20);
131 Buffer.BlockCopy (message, 24, _nonce, 0, 8);
133 if (Version == NtlmVersion.Version1)
134 return;
136 Buffer.BlockCopy (message, 32, _context, 0, 8);
137 short targetInfoSize = BitConverterLE.ToInt16 (message, 40);
138 int targetInfoOffset = BitConverterLE.ToInt32 (message, 44);
140 if (Version == NtlmVersion.Version3)
141 Buffer.BlockCopy (OSVersion, 0, message, 48, OSVersion.Length);
143 Encoding enc = (Flags & NtlmFlags.NegotiateUnicode) != 0 ? Encoding.Unicode : Encoding.UTF8;
144 if (targetNameSize > 0)
145 TargetName = enc.GetString (message, targetNameOffset, targetNameSize);
147 _target.Decode (message, targetInfoOffset, targetInfoSize);
150 public override byte[] GetBytes ()
152 byte [] name_bytes = null, target = null;
153 short name_len = 0, target_len = 0;
154 if (TargetName != null) {
155 Encoding enc = (Flags & NtlmFlags.NegotiateUnicode) != 0 ? Encoding.Unicode : Encoding.UTF8;
156 name_bytes = enc.GetBytes (TargetName);
157 name_len = (short) name_bytes.Length;
159 if (Version != NtlmVersion.Version1) {
160 target = _target.ToBytes ();
161 target_len = (short) target.Length;
164 uint name_offset = (uint) (Version == NtlmVersion.Version3 ? 56 : 40);
166 int size = (int) name_offset +
167 (name_len > 0 ? name_len + 8 : 0) +
168 (target_len > 0 ? target_len + 8 : 0);
169 byte[] data = PrepareMessage (size);
171 // target name
172 data [12] = (byte) name_len;
173 data [13] = (byte) (name_len >> 8);
174 data [14] = data [12];
175 data [15] = data [13];
176 data [16] = (byte) name_offset;
177 data [17] = (byte) (name_offset >> 8);
178 data [18] = (byte) (name_offset >> 16);
179 data [19] = (byte) (name_offset >> 24);
181 // flags
182 data [20] = (byte) Flags;
183 data [21] = (byte)((uint)Flags >> 8);
184 data [22] = (byte)((uint)Flags >> 16);
185 data [23] = (byte)((uint)Flags >> 24);
187 Buffer.BlockCopy (_nonce, 0, data, 24, _nonce.Length);
189 if (Version == NtlmVersion.Version1)
190 return data;
192 // context
193 Buffer.BlockCopy (_context, 0, data, 32, 8);
195 // target information
196 data [40] = (byte) target_len;
197 data [41] = (byte) (target_len >> 8);
198 data [42] = data [40];
199 data [43] = data [41];
200 uint info_offset = (uint) (name_offset + name_bytes.Length);
201 data [44] = (byte) info_offset;
202 data [45] = (byte) (info_offset >> 8);
203 data [46] = (byte) (info_offset >> 16);
204 data [47] = (byte) (info_offset >> 24);
206 if (Version == NtlmVersion.Version3)
207 Buffer.BlockCopy (OSVersion, 0, data, 48, OSVersion.Length);
209 Buffer.BlockCopy (name_bytes, 0, data, (int) name_offset, name_len);
210 Buffer.BlockCopy (target, 0, data, (int) info_offset, target.Length);
212 return data;