DcerpcHandle.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // This code is derived from jcifs smb client library <jcifs at samba dot org>
  2. // Ported by J. Arturo <webmaster at komodosoft dot net>
  3. //
  4. // This library is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public
  6. // License as published by the Free Software Foundation; either
  7. // version 2.1 of the License, or (at your option) any later version.
  8. //
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. // Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public
  15. // License along with this library; if not, write to the Free Software
  16. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. using System;
  18. using System.IO;
  19. using SharpCifs.Dcerpc.Ndr;
  20. using SharpCifs.Smb;
  21. using SharpCifs.Util.Sharpen;
  22. namespace SharpCifs.Dcerpc
  23. {
  24. public abstract class DcerpcHandle
  25. {
  26. /// <exception cref="SharpCifs.Dcerpc.DcerpcException"></exception>
  27. protected internal static DcerpcBinding ParseBinding(string str)
  28. {
  29. int state;
  30. int mark;
  31. int si;
  32. char[] arr = str.ToCharArray();
  33. string proto = null;
  34. string key = null;
  35. DcerpcBinding binding = null;
  36. state = mark = si = 0;
  37. do
  38. {
  39. char ch = arr[si];
  40. switch (state)
  41. {
  42. case 0:
  43. {
  44. if (ch == ':')
  45. {
  46. proto = Runtime.Substring(str, mark, si);
  47. mark = si + 1;
  48. state = 1;
  49. }
  50. break;
  51. }
  52. case 1:
  53. {
  54. if (ch == '\\')
  55. {
  56. mark = si + 1;
  57. break;
  58. }
  59. state = 2;
  60. goto case 2;
  61. }
  62. case 2:
  63. {
  64. if (ch == '[')
  65. {
  66. string server = Runtime.Substring(str, mark, si).Trim();
  67. if (server.Length == 0)
  68. {
  69. server = "127.0.0.1";
  70. }
  71. binding = new DcerpcBinding(proto, Runtime.Substring(str, mark, si));
  72. mark = si + 1;
  73. state = 5;
  74. }
  75. break;
  76. }
  77. case 5:
  78. {
  79. if (ch == '=')
  80. {
  81. key = Runtime.Substring(str, mark, si).Trim();
  82. mark = si + 1;
  83. }
  84. else
  85. {
  86. if (ch == ',' || ch == ']')
  87. {
  88. string val = Runtime.Substring(str, mark, si).Trim();
  89. if (key == null)
  90. {
  91. key = "endpoint";
  92. }
  93. binding.SetOption(key, val);
  94. key = null;
  95. }
  96. }
  97. break;
  98. }
  99. default:
  100. {
  101. si = arr.Length;
  102. break;
  103. }
  104. }
  105. si++;
  106. }
  107. while (si < arr.Length);
  108. if (binding == null || binding.Endpoint == null)
  109. {
  110. throw new DcerpcException("Invalid binding URL: " + str);
  111. }
  112. return binding;
  113. }
  114. protected internal DcerpcBinding Binding;
  115. protected internal int MaxXmit = 4280;
  116. protected internal int MaxRecv;
  117. protected internal int State;
  118. protected internal IDcerpcSecurityProvider SecurityProvider;
  119. private static int _callId = 1;
  120. /// <exception cref="UnknownHostException"></exception>
  121. /// <exception cref="System.UriFormatException"></exception>
  122. /// <exception cref="SharpCifs.Dcerpc.DcerpcException"></exception>
  123. public static DcerpcHandle GetHandle(string url, NtlmPasswordAuthentication auth)
  124. {
  125. if (url.StartsWith("ncacn_np:"))
  126. {
  127. return new DcerpcPipeHandle(url, auth);
  128. }
  129. throw new DcerpcException("DCERPC transport not supported: " + url);
  130. }
  131. /// <exception cref="SharpCifs.Dcerpc.DcerpcException"></exception>
  132. /// <exception cref="System.IO.IOException"></exception>
  133. public virtual void Bind()
  134. {
  135. lock (this)
  136. {
  137. try
  138. {
  139. State = 1;
  140. DcerpcMessage bind = new DcerpcBind(Binding, this);
  141. Sendrecv(bind);
  142. }
  143. catch (IOException ioe)
  144. {
  145. State = 0;
  146. throw;
  147. }
  148. }
  149. }
  150. /// <exception cref="SharpCifs.Dcerpc.DcerpcException"></exception>
  151. /// <exception cref="System.IO.IOException"></exception>
  152. public virtual void Sendrecv(DcerpcMessage msg)
  153. {
  154. byte[] stub;
  155. byte[] frag;
  156. NdrBuffer buf;
  157. NdrBuffer fbuf;
  158. bool isLast;
  159. bool isDirect;
  160. DcerpcException de;
  161. if (State == 0)
  162. {
  163. Bind();
  164. }
  165. isDirect = true;
  166. stub = BufferCache.GetBuffer();
  167. try
  168. {
  169. int off;
  170. int tot;
  171. int n;
  172. buf = new NdrBuffer(stub, 0);
  173. msg.Flags = DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag;
  174. msg.CallId = _callId++;
  175. msg.Encode(buf);
  176. if (SecurityProvider != null)
  177. {
  178. buf.SetIndex(0);
  179. SecurityProvider.Wrap(buf);
  180. }
  181. tot = buf.GetLength() - 24;
  182. off = 0;
  183. while (off < tot)
  184. {
  185. n = tot - off;
  186. if ((24 + n) > MaxXmit)
  187. {
  188. msg.Flags &= ~DcerpcConstants.DcerpcLastFrag;
  189. n = MaxXmit - 24;
  190. }
  191. else
  192. {
  193. msg.Flags |= DcerpcConstants.DcerpcLastFrag;
  194. isDirect = false;
  195. msg.AllocHint = n;
  196. }
  197. msg.Length = 24 + n;
  198. if (off > 0)
  199. {
  200. msg.Flags &= ~DcerpcConstants.DcerpcFirstFrag;
  201. }
  202. if ((msg.Flags & (DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag)) != (DcerpcConstants.DcerpcFirstFrag |
  203. DcerpcConstants.DcerpcLastFrag))
  204. {
  205. buf.Start = off;
  206. buf.Reset();
  207. msg.Encode_header(buf);
  208. buf.Enc_ndr_long(msg.AllocHint);
  209. buf.Enc_ndr_short(0);
  210. buf.Enc_ndr_short(msg.GetOpnum());
  211. }
  212. DoSendFragment(stub, off, msg.Length, isDirect);
  213. off += n;
  214. }
  215. DoReceiveFragment(stub, isDirect);
  216. buf.Reset();
  217. buf.SetIndex(8);
  218. buf.SetLength(buf.Dec_ndr_short());
  219. if (SecurityProvider != null)
  220. {
  221. SecurityProvider.Unwrap(buf);
  222. }
  223. buf.SetIndex(0);
  224. msg.Decode_header(buf);
  225. off = 24;
  226. if (msg.Ptype == 2 && msg.IsFlagSet(DcerpcConstants.DcerpcLastFrag) == false)
  227. {
  228. off = msg.Length;
  229. }
  230. frag = null;
  231. fbuf = null;
  232. while (msg.IsFlagSet(DcerpcConstants.DcerpcLastFrag) == false)
  233. {
  234. int stubFragLen;
  235. if (frag == null)
  236. {
  237. frag = new byte[MaxRecv];
  238. fbuf = new NdrBuffer(frag, 0);
  239. }
  240. DoReceiveFragment(frag, isDirect);
  241. fbuf.Reset();
  242. fbuf.SetIndex(8);
  243. fbuf.SetLength(fbuf.Dec_ndr_short());
  244. if (SecurityProvider != null)
  245. {
  246. SecurityProvider.Unwrap(fbuf);
  247. }
  248. fbuf.Reset();
  249. msg.Decode_header(fbuf);
  250. stubFragLen = msg.Length - 24;
  251. if ((off + stubFragLen) > stub.Length)
  252. {
  253. // shouldn't happen if alloc_hint is correct or greater
  254. byte[] tmp = new byte[off + stubFragLen];
  255. Array.Copy(stub, 0, tmp, 0, off);
  256. stub = tmp;
  257. }
  258. Array.Copy(frag, 24, stub, off, stubFragLen);
  259. off += stubFragLen;
  260. }
  261. buf = new NdrBuffer(stub, 0);
  262. msg.Decode(buf);
  263. }
  264. finally
  265. {
  266. BufferCache.ReleaseBuffer(stub);
  267. }
  268. if ((de = msg.GetResult()) != null)
  269. {
  270. throw de;
  271. }
  272. }
  273. public virtual void SetDcerpcSecurityProvider(IDcerpcSecurityProvider securityProvider
  274. )
  275. {
  276. this.SecurityProvider = securityProvider;
  277. }
  278. public virtual string GetServer()
  279. {
  280. if (this is DcerpcPipeHandle)
  281. {
  282. return ((DcerpcPipeHandle)this).Pipe.GetServer();
  283. }
  284. return null;
  285. }
  286. public virtual Principal GetPrincipal()
  287. {
  288. if (this is DcerpcPipeHandle)
  289. {
  290. return ((DcerpcPipeHandle)this).Pipe.GetPrincipal();
  291. }
  292. return null;
  293. }
  294. public override string ToString()
  295. {
  296. return Binding.ToString();
  297. }
  298. /// <exception cref="System.IO.IOException"></exception>
  299. protected internal abstract void DoSendFragment(byte[] buf, int off, int length,
  300. bool isDirect);
  301. /// <exception cref="System.IO.IOException"></exception>
  302. protected internal abstract void DoReceiveFragment(byte[] buf, bool isDirect);
  303. /// <exception cref="System.IO.IOException"></exception>
  304. public abstract void Close();
  305. public DcerpcHandle()
  306. {
  307. MaxRecv = MaxXmit;
  308. }
  309. }
  310. }