1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
7 using System.Runtime.CompilerServices;
9 namespace BadCheckedAdd1
13 internal enum SniContext
17 Snix_PreLoginBeforeSuccessfullWrite,
32 internal static class ADP
34 [MethodImpl(MethodImplOptions.NoInlining)]
35 static internal bool IsCatchableExceptionType(Exception e)
42 sealed internal class SQL
44 [MethodImpl(MethodImplOptions.NoInlining)]
45 static internal Exception InvalidSSPIPacketSize()
52 sealed internal class SqlLogin
54 internal int timeout; // login timeout
55 internal bool userInstance = false; // user instance
56 internal string hostName = ""; // client machine name
57 internal string userName = ""; // user id
58 internal string password = ""; // password
59 internal string applicationName = ""; // application name
60 internal string serverName = ""; // server name
61 internal string language = ""; // initial language
62 internal string database = ""; // initial database
63 internal string attachDBFilename = ""; // DB filename to be attached
64 internal string newPassword = ""; // new password for reset password
65 internal bool useReplication = false; // user login for replication
66 internal bool useSSPI = false; // use integrated security
67 internal int packetSize = 8000; // packet size
71 internal sealed class TdsParserStaticMethods
73 [MethodImpl(MethodImplOptions.NoInlining)]
74 static internal byte[] GetNetworkPhysicalAddressForTdsLoginOnly()
79 [MethodImpl(MethodImplOptions.NoInlining)]
80 static internal Byte[] EncryptPassword(string password)
91 0x36, 0xa5, 0x22, 0xa5,
92 0x33, 0xa5, 0xb3, 0xa5,
93 0xb2, 0xa5, 0x77, 0xa5,
94 0xb6, 0xa5, 0x92, 0xa5
101 sealed internal class TdsParserStateObject
103 public uint ReadDwordFromPostHeaderContentAtByteOffset(int offset)
107 using (var reader = new BinaryReader(new MemoryStream(this._outBuff, offset, 4)))
109 return reader.ReadUInt32();
113 internal byte[] _bTmp = new byte[8];
114 internal byte[] _outBuff = new Byte[1000];
115 internal int _outBytesUsed = 8;
116 internal readonly int _outputHeaderLen = 8;
117 internal byte _outputMessageType = 0;
118 internal byte _outputPacketNumber = 1;
119 internal bool _pendingData = false;
120 private int _timeoutSeconds;
121 private long _timeoutTime;
122 internal int _traceChangePasswordOffset = 0;
123 internal int _traceChangePasswordLength = 0;
124 internal int _tracePasswordOffset = 0;
125 internal int _tracePasswordLength = 0;
128 private SniContext _sniContext = SniContext.Undefined;
130 internal SniContext SniContext
132 get { return _sniContext; }
133 set { _sniContext = value; }
137 internal void SetTimeoutSeconds(int timeout)
139 _timeoutSeconds = timeout;
142 _timeoutTime = Int64.MaxValue;
147 internal void ResetBuffer()
149 this._outBytesUsed = this._outputHeaderLen;
154 [MethodImpl(MethodImplOptions.NoInlining)]
155 internal void WritePacket(byte flushMode)
162 internal class TdsParser
164 internal TdsParserStateObject _physicalStateObj = new TdsParserStateObject();
166 private volatile static UInt32 s_maxSSPILength = 0;
168 private static byte[] s_nicAddress;
171 [MethodImpl(MethodImplOptions.NoInlining)]
172 private void SSPIData(byte[] receivedBuff, UInt32 receivedLength, byte[] sendBuff, ref UInt32 sendLength)
178 internal void WriteByte(byte b, TdsParserStateObject stateObj)
180 if (stateObj._outBytesUsed == stateObj._outBuff.Length)
182 stateObj.WritePacket(0);
185 stateObj._outBuff[stateObj._outBytesUsed++] = b;
188 internal void WriteByteArray(Byte[] b, int len, int offsetBuffer, TdsParserStateObject stateObj)
190 int offset = offsetBuffer;
194 if ((stateObj._outBytesUsed + len) > stateObj._outBuff.Length)
196 int remainder = stateObj._outBuff.Length - stateObj._outBytesUsed;
198 Buffer.BlockCopy(b, offset, stateObj._outBuff, stateObj._outBytesUsed, remainder);
201 stateObj._outBytesUsed += remainder;
203 if (stateObj._outBytesUsed == stateObj._outBuff.Length)
205 stateObj.WritePacket(0);
212 Buffer.BlockCopy(b, offset, stateObj._outBuff, stateObj._outBytesUsed, len);
214 stateObj._outBytesUsed += len;
221 internal void WriteShort(int v, TdsParserStateObject stateObj)
223 if ((stateObj._outBytesUsed + 2) > stateObj._outBuff.Length)
225 WriteByte((byte)(v & 0xff), stateObj);
226 WriteByte((byte)((v >> 8) & 0xff), stateObj);
230 stateObj._outBuff[stateObj._outBytesUsed++] = (byte)(v & 0xFF);
231 stateObj._outBuff[stateObj._outBytesUsed++] = (byte)((v >> 8) & 0xFF);
235 internal void WriteInt(int v, TdsParserStateObject stateObj)
237 WriteByteArray(BitConverter.GetBytes(v), 4, 0, stateObj);
240 private unsafe static void CopyStringToBytes(string source, int sourceOffset, byte[] dest, int destOffset, int charLength)
242 int byteLength = checked(charLength * 2);
244 fixed (char* sourcePtr = source)
246 char* srcPtr = sourcePtr;
247 srcPtr += sourceOffset;
248 fixed (byte* destinationPtr = dest)
250 byte* destPtr = destinationPtr;
251 destPtr += destOffset;
253 byte* destByteAddress = destPtr;
254 byte* srcByteAddress = (byte*)srcPtr;
256 for (int index = 0; index < byteLength; index++)
258 *destByteAddress = *srcByteAddress;
266 internal void WriteString(string s, int length, int offset, TdsParserStateObject stateObj)
268 int cBytes = 2 * length;
270 if (cBytes < (stateObj._outBuff.Length - stateObj._outBytesUsed))
272 CopyStringToBytes(s, offset, stateObj._outBuff, stateObj._outBytesUsed, length);
273 stateObj._outBytesUsed += cBytes;
277 if (stateObj._bTmp == null || stateObj._bTmp.Length < cBytes)
279 stateObj._bTmp = new byte[cBytes];
282 CopyStringToBytes(s, offset, stateObj._bTmp, 0, length);
283 WriteByteArray(stateObj._bTmp, cBytes, 0, stateObj);
287 private void WriteString(string s, TdsParserStateObject stateObj)
289 WriteString(s, s.Length, 0, stateObj);
293 [MethodImpl(MethodImplOptions.NoInlining)]
294 internal void TdsLogin(SqlLogin rec)
296 _physicalStateObj.SetTimeoutSeconds(rec.timeout);
298 byte[] encryptedPassword = null;
299 encryptedPassword = TdsParserStaticMethods.EncryptPassword(rec.password);
301 byte[] encryptedChangePassword = null;
302 encryptedChangePassword = TdsParserStaticMethods.EncryptPassword(rec.newPassword);
304 _physicalStateObj._outputMessageType = 16;
308 string clientInterfaceName = ".Net SqlClient Data Provider";
312 length += (rec.hostName.Length + rec.applicationName.Length +
313 rec.serverName.Length + clientInterfaceName.Length +
314 rec.language.Length + rec.database.Length +
315 rec.attachDBFilename.Length) * 2;
318 byte[] outSSPIBuff = null;
319 UInt32 outSSPILength = 0;
325 length += (rec.userName.Length * 2) + encryptedPassword.Length
326 + encryptedChangePassword.Length;
333 outSSPIBuff = new byte[s_maxSSPILength];
334 outSSPILength = s_maxSSPILength;
336 _physicalStateObj.SniContext = SniContext.Snix_LoginSspi;
338 SSPIData(null, 0, outSSPIBuff, ref outSSPILength);
340 if (outSSPILength > Int32.MaxValue)
342 throw SQL.InvalidSSPIPacketSize(); // SqlBu 332503
345 _physicalStateObj.SniContext = SniContext.Snix_Login;
349 length += (Int32)outSSPILength;
356 WriteInt(length, _physicalStateObj);
357 WriteInt(0x730a0003, _physicalStateObj);
358 WriteInt(rec.packetSize, _physicalStateObj);
359 WriteInt(0x06000000, _physicalStateObj);
360 WriteInt(0xa10, _physicalStateObj);
361 WriteInt(0, _physicalStateObj);
363 WriteByte(0xe0, _physicalStateObj);
364 WriteByte(0x3, _physicalStateObj);
365 WriteByte(0, _physicalStateObj);
366 WriteByte(0, _physicalStateObj);
367 WriteInt(0, _physicalStateObj);
368 WriteInt(0, _physicalStateObj);
374 WriteShort(offset, _physicalStateObj);
375 WriteShort(rec.hostName.Length, _physicalStateObj);
376 offset += rec.hostName.Length * 2;
379 if (rec.useSSPI == false)
381 WriteShort(offset, _physicalStateObj);
382 WriteShort(rec.userName.Length, _physicalStateObj);
383 offset += rec.userName.Length * 2;
385 WriteShort(offset, _physicalStateObj);
386 WriteShort(encryptedPassword.Length / 2, _physicalStateObj);
387 offset += encryptedPassword.Length;
391 WriteShort(0, _physicalStateObj);
392 WriteShort(0, _physicalStateObj);
393 WriteShort(0, _physicalStateObj);
394 WriteShort(0, _physicalStateObj);
398 WriteShort(offset, _physicalStateObj);
399 WriteShort(rec.applicationName.Length, _physicalStateObj);
400 offset += rec.applicationName.Length * 2;
403 WriteShort(offset, _physicalStateObj);
404 WriteShort(rec.serverName.Length, _physicalStateObj);
405 offset += rec.serverName.Length * 2;
408 WriteShort(offset, _physicalStateObj);
409 WriteShort(0, _physicalStateObj);
412 WriteShort(offset, _physicalStateObj);
413 WriteShort(clientInterfaceName.Length, _physicalStateObj);
414 offset += clientInterfaceName.Length * 2;
417 WriteShort(offset, _physicalStateObj);
418 WriteShort(rec.language.Length, _physicalStateObj);
419 offset += rec.language.Length * 2;
422 WriteShort(offset, _physicalStateObj);
423 WriteShort(rec.database.Length, _physicalStateObj);
424 offset += rec.database.Length * 2;
427 if (null == s_nicAddress)
429 s_nicAddress = TdsParserStaticMethods.GetNetworkPhysicalAddressForTdsLoginOnly();
432 WriteByteArray(s_nicAddress, s_nicAddress.Length, 0, _physicalStateObj);
435 WriteShort(offset, _physicalStateObj);
439 WriteShort((int)outSSPILength, _physicalStateObj);
440 offset += (int)outSSPILength;
444 WriteShort(0, _physicalStateObj);
448 WriteShort(offset, _physicalStateObj);
449 WriteShort(rec.attachDBFilename.Length, _physicalStateObj);
450 offset += rec.attachDBFilename.Length * 2;
453 WriteShort(offset, _physicalStateObj);
454 WriteShort(encryptedChangePassword.Length / 2, _physicalStateObj);
457 WriteInt(0, _physicalStateObj);
460 WriteString(rec.hostName, _physicalStateObj);
465 WriteString(rec.userName, _physicalStateObj);
467 _physicalStateObj._tracePasswordOffset = _physicalStateObj._outBytesUsed;
468 _physicalStateObj._tracePasswordLength = encryptedPassword.Length;
470 WriteByteArray(encryptedPassword, encryptedPassword.Length, 0, _physicalStateObj);
474 WriteString(rec.applicationName, _physicalStateObj);
475 WriteString(rec.serverName, _physicalStateObj);
476 WriteString(clientInterfaceName, _physicalStateObj);
477 WriteString(rec.language, _physicalStateObj);
478 WriteString(rec.database, _physicalStateObj);
483 WriteByteArray(outSSPIBuff, (int)outSSPILength, 0, _physicalStateObj);
487 WriteString(rec.attachDBFilename, _physicalStateObj);
492 _physicalStateObj._traceChangePasswordOffset = _physicalStateObj._outBytesUsed;
493 _physicalStateObj._traceChangePasswordLength = encryptedChangePassword.Length;
494 WriteByteArray(encryptedChangePassword, encryptedChangePassword.Length, 0, _physicalStateObj);
499 if (ADP.IsCatchableExceptionType(e))
501 _physicalStateObj._outputPacketNumber = 1;
502 _physicalStateObj.ResetBuffer();
508 _physicalStateObj.WritePacket(1);
509 _physicalStateObj._pendingData = true;
514 internal static class App
516 private static SqlLogin MakeSqlLoginForRepro()
518 var login = new SqlLogin();
520 login.hostName = "CHRISAHNA1";
521 login.userName = "etcmuser";
522 login.password = "29xiaq-1s";
523 login.applicationName = ".Net SqlClient Data Provider";
524 login.serverName = "csetcmdb.redmond.corp.microsoft.com";
526 login.database = "Tcm_Global";
527 login.attachDBFilename = "";
528 login.newPassword = "";
534 private static int Main()
536 var tdsParser = new TdsParser();
538 tdsParser.TdsLogin(App.MakeSqlLoginForRepro());
540 uint computedLengthValue = tdsParser._physicalStateObj.ReadDwordFromPostHeaderContentAtByteOffset(0x0);
542 if (computedLengthValue == 0x15e)
544 Console.WriteLine("Test passed.");
549 Console.WriteLine("Test failed: ComputedLength=({0:x8})", computedLengthValue);