WhereaboutsReader.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Transactions
  5. {
  6. using System;
  7. using System.Diagnostics.CodeAnalysis;
  8. using System.IO;
  9. using System.Net;
  10. using System.Runtime;
  11. using System.Security.Permissions;
  12. using System.Text;
  13. using Microsoft.Transactions.Wsat.Protocol;
  14. using Microsoft.Transactions.Wsat.Recovery;
  15. class WhereaboutsReader
  16. {
  17. string hostName;
  18. ProtocolInformationReader protocolInfo;
  19. // Whereabouts internals
  20. static Guid GuidWhereaboutsInfo = new Guid("{2adb4462-bd41-11d0-b12e-00c04fc2f3ef}");
  21. const long STmToTmProtocolSize = 4 + 4;
  22. enum TmProtocol
  23. {
  24. TmProtocolNone = 0,
  25. TmProtocolTip = 1,
  26. TmProtocolMsdtcV1 = 2,
  27. TmProtocolMsdtcV2 = 3, // unicode host names in nameobject blobs etc
  28. TmProtocolExtended = 4 // other stuff (e.g., WS-AT)
  29. }
  30. public WhereaboutsReader(byte[] whereabouts)
  31. {
  32. MemoryStream mem = new MemoryStream(whereabouts,
  33. 0,
  34. whereabouts.Length,
  35. false,
  36. true); // Enable calls to GetBuffer()
  37. DeserializeWhereabouts(mem);
  38. }
  39. public string HostName
  40. {
  41. get { return this.hostName; }
  42. }
  43. public ProtocolInformationReader ProtocolInformation
  44. {
  45. get { return this.protocolInfo; }
  46. }
  47. [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to SerializationException and SerializationUtils are safe.")]
  48. void DeserializeWhereabouts(MemoryStream mem)
  49. {
  50. // guidSignature
  51. Guid signature = SerializationUtils.ReadGuid(mem);
  52. if (signature != GuidWhereaboutsInfo)
  53. {
  54. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  55. new SerializationException(SR.GetString(SR.WhereaboutsSignatureMissing)));
  56. }
  57. // cTmToTmProtocols
  58. uint cTmToTmProtocols = SerializationUtils.ReadUInt(mem);
  59. // Make sure that cTmToTmProtocols is at least plausible
  60. if (cTmToTmProtocols * STmToTmProtocolSize > mem.Length - mem.Position)
  61. {
  62. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  63. new SerializationException(SR.GetString(SR.WhereaboutsImplausibleProtocolCount)));
  64. }
  65. // Loop through each protocol
  66. for (uint i = 0; i < cTmToTmProtocols; i++)
  67. {
  68. DeserializeWhereaboutsProtocol(mem);
  69. }
  70. // Require a host name
  71. if (string.IsNullOrEmpty(this.hostName))
  72. {
  73. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  74. new SerializationException(SR.GetString(SR.WhereaboutsNoHostName)));
  75. }
  76. }
  77. [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to SerializationUtils are safe.")]
  78. void DeserializeWhereaboutsProtocol(MemoryStream mem)
  79. {
  80. // tmprotDescribed
  81. TmProtocol tmprotDescribed = (TmProtocol)SerializationUtils.ReadInt(mem);
  82. // cbTmProtocolData
  83. uint cbTmProtocolData = SerializationUtils.ReadUInt(mem);
  84. switch (tmprotDescribed)
  85. {
  86. case TmProtocol.TmProtocolMsdtcV2:
  87. ReadMsdtcV2Protocol(mem, cbTmProtocolData);
  88. break;
  89. case TmProtocol.TmProtocolExtended:
  90. ReadExtendedProtocol(mem, cbTmProtocolData);
  91. break;
  92. default:
  93. // We don't care about this protocol
  94. SerializationUtils.IncrementPosition(mem, cbTmProtocolData);
  95. break;
  96. }
  97. // Align the cursor to a 4-byte boundary
  98. SerializationUtils.AlignPosition(mem, 4);
  99. }
  100. [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to SerializationException and SerializationUtils are safe.")]
  101. void ReadMsdtcV2Protocol(MemoryStream mem, uint cbTmProtocolData)
  102. {
  103. const int MaxComputerName = 15;
  104. //
  105. // The host name is encoded in unicode format
  106. // It is followed by a null-terminating unicode character,
  107. // plus some padding to align on 4
  108. //
  109. // Reject host names of disproportionate size
  110. if (cbTmProtocolData > (MaxComputerName + 1) * 2)
  111. {
  112. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  113. new SerializationException(SR.GetString(SR.WhereaboutsImplausibleHostNameByteCount)));
  114. }
  115. byte[] chars = SerializationUtils.ReadBytes(mem, (int)cbTmProtocolData);
  116. // Count the bytes until the first null terminating character
  117. int cbString = 0;
  118. while (cbString < cbTmProtocolData - 1 &&
  119. (chars[cbString] != 0 || chars[cbString + 1] != 0))
  120. {
  121. cbString += 2;
  122. }
  123. if (cbString == 0)
  124. {
  125. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  126. new SerializationException(SR.GetString(SR.WhereaboutsInvalidHostName)));
  127. }
  128. try
  129. {
  130. this.hostName = Encoding.Unicode.GetString(chars, 0, cbString);
  131. }
  132. catch (ArgumentException e)
  133. {
  134. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  135. new SerializationException(SR.GetString(SR.WhereaboutsInvalidHostName), e));
  136. }
  137. }
  138. // The demand is not added now (in 4.5), to avoid a breaking change. To be considered in the next version.
  139. /*
  140. [PermissionSet(SecurityAction.Demand, Unrestricted = true)] // because we use ProtocolInformationReader, which is defined in a non-APTCA assembly; WSATs are not supported in partial trust, so customers should not be broken by this demand
  141. */
  142. void ReadExtendedProtocol(MemoryStream mem, uint cbTmProtocolData)
  143. {
  144. // Read the WSAT1.0 protoocol identifier
  145. Guid guid = SerializationUtils.ReadGuid(mem);
  146. if (guid == PluggableProtocol10.ProtocolGuid || guid == PluggableProtocol11.ProtocolGuid)
  147. {
  148. // This is the WS-AT extended whereabouts blob
  149. this.protocolInfo = new ProtocolInformationReader(mem);
  150. }
  151. else
  152. {
  153. // Some other gateway protocol... Skip the rest of the data
  154. SerializationUtils.IncrementPosition(mem, cbTmProtocolData - 16);
  155. }
  156. }
  157. }
  158. }