DcerpcHandle.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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 (
  203. (msg.Flags & (DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag))
  204. != (DcerpcConstants.DcerpcFirstFrag | DcerpcConstants.DcerpcLastFrag)
  205. )
  206. {
  207. buf.Start = off;
  208. buf.Reset();
  209. msg.Encode_header(buf);
  210. buf.Enc_ndr_long(msg.AllocHint);
  211. buf.Enc_ndr_short(0);
  212. buf.Enc_ndr_short(msg.GetOpnum());
  213. }
  214. DoSendFragment(stub, off, msg.Length, isDirect);
  215. off += n;
  216. }
  217. DoReceiveFragment(stub, isDirect);
  218. buf.Reset();
  219. buf.SetIndex(8);
  220. buf.SetLength(buf.Dec_ndr_short());
  221. if (SecurityProvider != null)
  222. {
  223. SecurityProvider.Unwrap(buf);
  224. }
  225. buf.SetIndex(0);
  226. msg.Decode_header(buf);
  227. off = 24;
  228. if (msg.Ptype == 2 && msg.IsFlagSet(DcerpcConstants.DcerpcLastFrag) == false)
  229. {
  230. off = msg.Length;
  231. }
  232. frag = null;
  233. fbuf = null;
  234. while (msg.IsFlagSet(DcerpcConstants.DcerpcLastFrag) == false)
  235. {
  236. int stubFragLen;
  237. if (frag == null)
  238. {
  239. frag = new byte[MaxRecv];
  240. fbuf = new NdrBuffer(frag, 0);
  241. }
  242. DoReceiveFragment(frag, isDirect);
  243. fbuf.Reset();
  244. fbuf.SetIndex(8);
  245. fbuf.SetLength(fbuf.Dec_ndr_short());
  246. if (SecurityProvider != null)
  247. {
  248. SecurityProvider.Unwrap(fbuf);
  249. }
  250. fbuf.Reset();
  251. msg.Decode_header(fbuf);
  252. stubFragLen = msg.Length - 24;
  253. if ((off + stubFragLen) > stub.Length)
  254. {
  255. // shouldn't happen if alloc_hint is correct or greater
  256. byte[] tmp = new byte[off + stubFragLen];
  257. Array.Copy(stub, 0, tmp, 0, off);
  258. stub = tmp;
  259. }
  260. Array.Copy(frag, 24, stub, off, stubFragLen);
  261. off += stubFragLen;
  262. }
  263. buf = new NdrBuffer(stub, 0);
  264. msg.Decode(buf);
  265. }
  266. finally
  267. {
  268. BufferCache.ReleaseBuffer(stub);
  269. }
  270. if ((de = msg.GetResult()) != null)
  271. {
  272. throw de;
  273. }
  274. }
  275. public virtual void SetDcerpcSecurityProvider(IDcerpcSecurityProvider securityProvider
  276. )
  277. {
  278. this.SecurityProvider = securityProvider;
  279. }
  280. public virtual string GetServer()
  281. {
  282. if (this is DcerpcPipeHandle)
  283. {
  284. return ((DcerpcPipeHandle)this).Pipe.GetServer();
  285. }
  286. return null;
  287. }
  288. public virtual Principal GetPrincipal()
  289. {
  290. if (this is DcerpcPipeHandle)
  291. {
  292. return ((DcerpcPipeHandle)this).Pipe.GetPrincipal();
  293. }
  294. return null;
  295. }
  296. public override string ToString()
  297. {
  298. return Binding.ToString();
  299. }
  300. /// <exception cref="System.IO.IOException"></exception>
  301. protected internal abstract void DoSendFragment(byte[] buf, int off, int length, bool isDirect);
  302. /// <exception cref="System.IO.IOException"></exception>
  303. protected internal abstract void DoReceiveFragment(byte[] buf, bool isDirect);
  304. /// <exception cref="System.IO.IOException"></exception>
  305. public abstract void Close();
  306. public DcerpcHandle()
  307. {
  308. MaxRecv = MaxXmit;
  309. }
  310. }
  311. }