sftp.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. /*
  2. * sftp.c: SFTP generic client code.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include <limits.h>
  9. #include "misc.h"
  10. #include "tree234.h"
  11. #include "sftp.h"
  12. static const char *fxp_error_message;
  13. static int fxp_errtype;
  14. static void fxp_internal_error(const char *msg);
  15. /* ----------------------------------------------------------------------
  16. * Client-specific parts of the send- and receive-packet system.
  17. */
  18. static bool sftp_send(struct sftp_packet *pkt)
  19. {
  20. bool ret;
  21. sftp_send_prepare(pkt);
  22. ret = sftp_senddata(pkt->data, pkt->length);
  23. sftp_pkt_free(pkt);
  24. return ret;
  25. }
  26. struct sftp_packet *sftp_recv(void)
  27. {
  28. struct sftp_packet *pkt;
  29. char x[4];
  30. if (!sftp_recvdata(x, 4))
  31. return NULL;
  32. /* Impose _some_ upper bound on packet size. We never expect to
  33. * receive more than 32K of data in response to an FXP_READ,
  34. * because we decide how much data to ask for. FXP_READDIR and
  35. * pathname-returning things like FXP_REALPATH don't have an
  36. * explicit bound, so I suppose we just have to trust the server
  37. * to be sensible. */
  38. unsigned pktlen = GET_32BIT_MSB_FIRST(x);
  39. if (pktlen > (1<<20))
  40. return NULL;
  41. pkt = sftp_recv_prepare(pktlen);
  42. if (!sftp_recvdata(pkt->data, pkt->length)) {
  43. sftp_pkt_free(pkt);
  44. return NULL;
  45. }
  46. if (!sftp_recv_finish(pkt)) {
  47. sftp_pkt_free(pkt);
  48. return NULL;
  49. }
  50. return pkt;
  51. }
  52. /* ----------------------------------------------------------------------
  53. * Request ID allocation and temporary dispatch routines.
  54. */
  55. #define REQUEST_ID_OFFSET 256
  56. struct sftp_request {
  57. unsigned id;
  58. bool registered;
  59. void *userdata;
  60. };
  61. static int sftp_reqcmp(void *av, void *bv)
  62. {
  63. struct sftp_request *a = (struct sftp_request *)av;
  64. struct sftp_request *b = (struct sftp_request *)bv;
  65. if (a->id < b->id)
  66. return -1;
  67. if (a->id > b->id)
  68. return +1;
  69. return 0;
  70. }
  71. static int sftp_reqfind(void *av, void *bv)
  72. {
  73. unsigned *a = (unsigned *) av;
  74. struct sftp_request *b = (struct sftp_request *)bv;
  75. if (*a < b->id)
  76. return -1;
  77. if (*a > b->id)
  78. return +1;
  79. return 0;
  80. }
  81. static tree234 *sftp_requests;
  82. static struct sftp_request *sftp_alloc_request(void)
  83. {
  84. unsigned low, high, mid;
  85. int tsize;
  86. struct sftp_request *r;
  87. if (sftp_requests == NULL)
  88. sftp_requests = newtree234(sftp_reqcmp);
  89. /*
  90. * First-fit allocation of request IDs: always pick the lowest
  91. * unused one. To do this, binary-search using the counted
  92. * B-tree to find the largest ID which is in a contiguous
  93. * sequence from the beginning. (Precisely everything in that
  94. * sequence must have ID equal to its tree index plus
  95. * REQUEST_ID_OFFSET.)
  96. */
  97. tsize = count234(sftp_requests);
  98. low = -1;
  99. high = tsize;
  100. while (high - low > 1) {
  101. mid = (high + low) / 2;
  102. r = index234(sftp_requests, mid);
  103. if (r->id == mid + REQUEST_ID_OFFSET)
  104. low = mid; /* this one is fine */
  105. else
  106. high = mid; /* this one is past it */
  107. }
  108. /*
  109. * Now low points to either -1, or the tree index of the
  110. * largest ID in the initial sequence.
  111. */
  112. {
  113. unsigned i = low + 1 + REQUEST_ID_OFFSET;
  114. assert(NULL == find234(sftp_requests, &i, sftp_reqfind));
  115. }
  116. /*
  117. * So the request ID we need to create is
  118. * low + 1 + REQUEST_ID_OFFSET.
  119. */
  120. r = snew(struct sftp_request);
  121. r->id = low + 1 + REQUEST_ID_OFFSET;
  122. r->registered = false;
  123. r->userdata = NULL;
  124. add234(sftp_requests, r);
  125. return r;
  126. }
  127. void sftp_cleanup_request(void)
  128. {
  129. if (sftp_requests != NULL) {
  130. freetree234(sftp_requests);
  131. sftp_requests = NULL;
  132. }
  133. }
  134. void sftp_register(struct sftp_request *req)
  135. {
  136. req->registered = true;
  137. }
  138. struct sftp_request *sftp_find_request(struct sftp_packet *pktin)
  139. {
  140. unsigned id;
  141. struct sftp_request *req;
  142. if (!pktin) {
  143. fxp_internal_error("did not receive a valid SFTP packet\n");
  144. return NULL;
  145. }
  146. id = get_uint32(pktin);
  147. if (get_err(pktin)) {
  148. fxp_internal_error("did not receive a valid SFTP packet\n");
  149. return NULL;
  150. }
  151. req = find234(sftp_requests, &id, sftp_reqfind);
  152. if (!req || !req->registered) {
  153. fxp_internal_error("request ID mismatch\n");
  154. return NULL;
  155. }
  156. del234(sftp_requests, req);
  157. return req;
  158. }
  159. /* ----------------------------------------------------------------------
  160. * SFTP primitives.
  161. */
  162. /*
  163. * Deal with (and free) an FXP_STATUS packet. Return 1 if
  164. * SSH_FX_OK, 0 if SSH_FX_EOF, and -1 for anything else (error).
  165. * Also place the status into fxp_errtype.
  166. */
  167. static int fxp_got_status(struct sftp_packet *pktin)
  168. {
  169. static const char *const messages[] = {
  170. /* SSH_FX_OK. The only time we will display a _message_ for this
  171. * is if we were expecting something other than FXP_STATUS on
  172. * success, so this is actually an error message! */
  173. "unexpected OK response",
  174. "end of file",
  175. "no such file or directory",
  176. "permission denied",
  177. "failure",
  178. "bad message",
  179. "no connection",
  180. "connection lost",
  181. "operation unsupported",
  182. };
  183. if (pktin->type != SSH_FXP_STATUS) {
  184. fxp_error_message = "expected FXP_STATUS packet";
  185. fxp_errtype = -1;
  186. } else {
  187. fxp_errtype = get_uint32(pktin);
  188. if (get_err(pktin)) {
  189. fxp_error_message = "malformed FXP_STATUS packet";
  190. fxp_errtype = -1;
  191. } else {
  192. if (fxp_errtype < 0 || fxp_errtype >= lenof(messages))
  193. fxp_error_message = "unknown error code";
  194. else
  195. fxp_error_message = messages[fxp_errtype];
  196. }
  197. }
  198. if (fxp_errtype == SSH_FX_OK)
  199. return 1;
  200. else if (fxp_errtype == SSH_FX_EOF)
  201. return 0;
  202. else
  203. return -1;
  204. }
  205. static void fxp_internal_error(const char *msg)
  206. {
  207. fxp_error_message = msg;
  208. fxp_errtype = -1;
  209. }
  210. const char *fxp_error(void)
  211. {
  212. return fxp_error_message;
  213. }
  214. int fxp_error_type(void)
  215. {
  216. return fxp_errtype;
  217. }
  218. /*
  219. * Perform exchange of init/version packets. Return 0 on failure.
  220. */
  221. bool fxp_init(void)
  222. {
  223. struct sftp_packet *pktout, *pktin;
  224. unsigned long remotever;
  225. pktout = sftp_pkt_init(SSH_FXP_INIT);
  226. put_uint32(pktout, SFTP_PROTO_VERSION);
  227. sftp_send(pktout);
  228. pktin = sftp_recv();
  229. if (!pktin) {
  230. fxp_internal_error("could not connect");
  231. return false;
  232. }
  233. if (pktin->type != SSH_FXP_VERSION) {
  234. fxp_internal_error("did not receive FXP_VERSION");
  235. sftp_pkt_free(pktin);
  236. return false;
  237. }
  238. remotever = get_uint32(pktin);
  239. if (get_err(pktin)) {
  240. fxp_internal_error("malformed FXP_VERSION packet");
  241. sftp_pkt_free(pktin);
  242. return false;
  243. }
  244. if (remotever > SFTP_PROTO_VERSION) {
  245. fxp_internal_error("remote protocol is more advanced than we support");
  246. sftp_pkt_free(pktin);
  247. return false;
  248. }
  249. /*
  250. * In principle, this packet might also contain extension-
  251. * string pairs. We should work through them and look for any
  252. * we recognise. In practice we don't currently do so because
  253. * we know we don't recognise _any_.
  254. */
  255. sftp_pkt_free(pktin);
  256. return true;
  257. }
  258. /*
  259. * Canonify a pathname.
  260. */
  261. struct sftp_request *fxp_realpath_send(const char *path)
  262. {
  263. struct sftp_request *req = sftp_alloc_request();
  264. struct sftp_packet *pktout;
  265. pktout = sftp_pkt_init(SSH_FXP_REALPATH);
  266. put_uint32(pktout, req->id);
  267. put_stringz(pktout, path);
  268. sftp_send(pktout);
  269. return req;
  270. }
  271. char *fxp_realpath_recv(struct sftp_packet *pktin, struct sftp_request *req)
  272. {
  273. sfree(req);
  274. if (pktin->type == SSH_FXP_NAME) {
  275. unsigned long count;
  276. char *path;
  277. ptrlen name;
  278. count = get_uint32(pktin);
  279. if (get_err(pktin) || count != 1) {
  280. fxp_internal_error("REALPATH did not return name count of 1\n");
  281. sftp_pkt_free(pktin);
  282. return NULL;
  283. }
  284. name = get_string(pktin);
  285. if (get_err(pktin)) {
  286. fxp_internal_error("REALPATH returned malformed FXP_NAME\n");
  287. sftp_pkt_free(pktin);
  288. return NULL;
  289. }
  290. path = mkstr(name);
  291. sftp_pkt_free(pktin);
  292. return path;
  293. } else {
  294. fxp_got_status(pktin);
  295. sftp_pkt_free(pktin);
  296. return NULL;
  297. }
  298. }
  299. /*
  300. * Open a file.
  301. */
  302. struct sftp_request *fxp_open_send(const char *path, int type,
  303. const struct fxp_attrs *attrs)
  304. {
  305. struct sftp_request *req = sftp_alloc_request();
  306. struct sftp_packet *pktout;
  307. pktout = sftp_pkt_init(SSH_FXP_OPEN);
  308. put_uint32(pktout, req->id);
  309. put_stringz(pktout, path);
  310. put_uint32(pktout, type);
  311. put_fxp_attrs(pktout, attrs ? *attrs : no_attrs);
  312. sftp_send(pktout);
  313. return req;
  314. }
  315. static struct fxp_handle *fxp_got_handle(struct sftp_packet *pktin)
  316. {
  317. ptrlen id;
  318. struct fxp_handle *handle;
  319. id = get_string(pktin);
  320. if (get_err(pktin)) {
  321. fxp_internal_error("received malformed FXP_HANDLE");
  322. sftp_pkt_free(pktin);
  323. return NULL;
  324. }
  325. handle = snew(struct fxp_handle);
  326. handle->hstring = mkstr(id);
  327. handle->hlen = id.len;
  328. sftp_pkt_free(pktin);
  329. return handle;
  330. }
  331. struct fxp_handle *fxp_open_recv(struct sftp_packet *pktin,
  332. struct sftp_request *req)
  333. {
  334. sfree(req);
  335. if (pktin->type == SSH_FXP_HANDLE) {
  336. return fxp_got_handle(pktin);
  337. } else {
  338. fxp_got_status(pktin);
  339. sftp_pkt_free(pktin);
  340. return NULL;
  341. }
  342. }
  343. /*
  344. * Open a directory.
  345. */
  346. struct sftp_request *fxp_opendir_send(const char *path)
  347. {
  348. struct sftp_request *req = sftp_alloc_request();
  349. struct sftp_packet *pktout;
  350. pktout = sftp_pkt_init(SSH_FXP_OPENDIR);
  351. put_uint32(pktout, req->id);
  352. put_stringz(pktout, path);
  353. sftp_send(pktout);
  354. return req;
  355. }
  356. struct fxp_handle *fxp_opendir_recv(struct sftp_packet *pktin,
  357. struct sftp_request *req)
  358. {
  359. sfree(req);
  360. if (pktin->type == SSH_FXP_HANDLE) {
  361. return fxp_got_handle(pktin);
  362. } else {
  363. fxp_got_status(pktin);
  364. sftp_pkt_free(pktin);
  365. return NULL;
  366. }
  367. }
  368. /*
  369. * Close a file/dir.
  370. */
  371. struct sftp_request *fxp_close_send(struct fxp_handle *handle)
  372. {
  373. struct sftp_request *req = sftp_alloc_request();
  374. struct sftp_packet *pktout;
  375. pktout = sftp_pkt_init(SSH_FXP_CLOSE);
  376. put_uint32(pktout, req->id);
  377. put_string(pktout, handle->hstring, handle->hlen);
  378. sftp_send(pktout);
  379. sfree(handle->hstring);
  380. sfree(handle);
  381. return req;
  382. }
  383. bool fxp_close_recv(struct sftp_packet *pktin, struct sftp_request *req)
  384. {
  385. sfree(req);
  386. fxp_got_status(pktin);
  387. sftp_pkt_free(pktin);
  388. return fxp_errtype == SSH_FX_OK;
  389. }
  390. struct sftp_request *fxp_mkdir_send(const char *path,
  391. const struct fxp_attrs *attrs)
  392. {
  393. struct sftp_request *req = sftp_alloc_request();
  394. struct sftp_packet *pktout;
  395. pktout = sftp_pkt_init(SSH_FXP_MKDIR);
  396. put_uint32(pktout, req->id);
  397. put_stringz(pktout, path);
  398. put_fxp_attrs(pktout, attrs ? *attrs : no_attrs);
  399. sftp_send(pktout);
  400. return req;
  401. }
  402. bool fxp_mkdir_recv(struct sftp_packet *pktin, struct sftp_request *req)
  403. {
  404. int id;
  405. sfree(req);
  406. id = fxp_got_status(pktin);
  407. sftp_pkt_free(pktin);
  408. return id == 1;
  409. }
  410. struct sftp_request *fxp_rmdir_send(const char *path)
  411. {
  412. struct sftp_request *req = sftp_alloc_request();
  413. struct sftp_packet *pktout;
  414. pktout = sftp_pkt_init(SSH_FXP_RMDIR);
  415. put_uint32(pktout, req->id);
  416. put_stringz(pktout, path);
  417. sftp_send(pktout);
  418. return req;
  419. }
  420. bool fxp_rmdir_recv(struct sftp_packet *pktin, struct sftp_request *req)
  421. {
  422. int id;
  423. sfree(req);
  424. id = fxp_got_status(pktin);
  425. sftp_pkt_free(pktin);
  426. return id == 1;
  427. }
  428. struct sftp_request *fxp_remove_send(const char *fname)
  429. {
  430. struct sftp_request *req = sftp_alloc_request();
  431. struct sftp_packet *pktout;
  432. pktout = sftp_pkt_init(SSH_FXP_REMOVE);
  433. put_uint32(pktout, req->id);
  434. put_stringz(pktout, fname);
  435. sftp_send(pktout);
  436. return req;
  437. }
  438. bool fxp_remove_recv(struct sftp_packet *pktin, struct sftp_request *req)
  439. {
  440. int id;
  441. sfree(req);
  442. id = fxp_got_status(pktin);
  443. sftp_pkt_free(pktin);
  444. return id == 1;
  445. }
  446. struct sftp_request *fxp_rename_send(const char *srcfname,
  447. const char *dstfname)
  448. {
  449. struct sftp_request *req = sftp_alloc_request();
  450. struct sftp_packet *pktout;
  451. pktout = sftp_pkt_init(SSH_FXP_RENAME);
  452. put_uint32(pktout, req->id);
  453. put_stringz(pktout, srcfname);
  454. put_stringz(pktout, dstfname);
  455. sftp_send(pktout);
  456. return req;
  457. }
  458. bool fxp_rename_recv(struct sftp_packet *pktin, struct sftp_request *req)
  459. {
  460. int id;
  461. sfree(req);
  462. id = fxp_got_status(pktin);
  463. sftp_pkt_free(pktin);
  464. return id == 1;
  465. }
  466. /*
  467. * Retrieve the attributes of a file. We have fxp_stat which works
  468. * on filenames, and fxp_fstat which works on open file handles.
  469. */
  470. struct sftp_request *fxp_stat_send(const char *fname)
  471. {
  472. struct sftp_request *req = sftp_alloc_request();
  473. struct sftp_packet *pktout;
  474. pktout = sftp_pkt_init(SSH_FXP_STAT);
  475. put_uint32(pktout, req->id);
  476. put_stringz(pktout, fname);
  477. sftp_send(pktout);
  478. return req;
  479. }
  480. static bool fxp_got_attrs(struct sftp_packet *pktin, struct fxp_attrs *attrs)
  481. {
  482. get_fxp_attrs(pktin, attrs);
  483. if (get_err(pktin)) {
  484. fxp_internal_error("malformed SSH_FXP_ATTRS packet");
  485. sftp_pkt_free(pktin);
  486. return false;
  487. }
  488. sftp_pkt_free(pktin);
  489. return true;
  490. }
  491. bool fxp_stat_recv(struct sftp_packet *pktin, struct sftp_request *req,
  492. struct fxp_attrs *attrs)
  493. {
  494. sfree(req);
  495. if (pktin->type == SSH_FXP_ATTRS) {
  496. return fxp_got_attrs(pktin, attrs);
  497. } else {
  498. fxp_got_status(pktin);
  499. sftp_pkt_free(pktin);
  500. return false;
  501. }
  502. }
  503. struct sftp_request *fxp_fstat_send(struct fxp_handle *handle)
  504. {
  505. struct sftp_request *req = sftp_alloc_request();
  506. struct sftp_packet *pktout;
  507. pktout = sftp_pkt_init(SSH_FXP_FSTAT);
  508. put_uint32(pktout, req->id);
  509. put_string(pktout, handle->hstring, handle->hlen);
  510. sftp_send(pktout);
  511. return req;
  512. }
  513. bool fxp_fstat_recv(struct sftp_packet *pktin, struct sftp_request *req,
  514. struct fxp_attrs *attrs)
  515. {
  516. sfree(req);
  517. if (pktin->type == SSH_FXP_ATTRS) {
  518. return fxp_got_attrs(pktin, attrs);
  519. } else {
  520. fxp_got_status(pktin);
  521. sftp_pkt_free(pktin);
  522. return false;
  523. }
  524. }
  525. /*
  526. * Set the attributes of a file.
  527. */
  528. struct sftp_request *fxp_setstat_send(const char *fname,
  529. struct fxp_attrs attrs)
  530. {
  531. struct sftp_request *req = sftp_alloc_request();
  532. struct sftp_packet *pktout;
  533. pktout = sftp_pkt_init(SSH_FXP_SETSTAT);
  534. put_uint32(pktout, req->id);
  535. put_stringz(pktout, fname);
  536. put_fxp_attrs(pktout, attrs);
  537. sftp_send(pktout);
  538. return req;
  539. }
  540. bool fxp_setstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
  541. {
  542. int id;
  543. sfree(req);
  544. id = fxp_got_status(pktin);
  545. sftp_pkt_free(pktin);
  546. return id == 1;
  547. }
  548. struct sftp_request *fxp_fsetstat_send(struct fxp_handle *handle,
  549. struct fxp_attrs attrs)
  550. {
  551. struct sftp_request *req = sftp_alloc_request();
  552. struct sftp_packet *pktout;
  553. pktout = sftp_pkt_init(SSH_FXP_FSETSTAT);
  554. put_uint32(pktout, req->id);
  555. put_string(pktout, handle->hstring, handle->hlen);
  556. put_fxp_attrs(pktout, attrs);
  557. sftp_send(pktout);
  558. return req;
  559. }
  560. bool fxp_fsetstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
  561. {
  562. int id;
  563. sfree(req);
  564. id = fxp_got_status(pktin);
  565. sftp_pkt_free(pktin);
  566. return id == 1;
  567. }
  568. /*
  569. * Read from a file. Returns the number of bytes read, or -1 on an
  570. * error, or possibly 0 if EOF. (I'm not entirely sure whether it
  571. * will return 0 on EOF, or return -1 and store SSH_FX_EOF in the
  572. * error indicator. It might even depend on the SFTP server.)
  573. */
  574. struct sftp_request *fxp_read_send(struct fxp_handle *handle,
  575. uint64_t offset, int len)
  576. {
  577. struct sftp_request *req = sftp_alloc_request();
  578. struct sftp_packet *pktout;
  579. pktout = sftp_pkt_init(SSH_FXP_READ);
  580. put_uint32(pktout, req->id);
  581. put_string(pktout, handle->hstring, handle->hlen);
  582. put_uint64(pktout, offset);
  583. put_uint32(pktout, len);
  584. sftp_send(pktout);
  585. return req;
  586. }
  587. int fxp_read_recv(struct sftp_packet *pktin, struct sftp_request *req,
  588. char *buffer, int len)
  589. {
  590. sfree(req);
  591. if (pktin->type == SSH_FXP_DATA) {
  592. ptrlen data;
  593. data = get_string(pktin);
  594. if (get_err(pktin)) {
  595. fxp_internal_error("READ returned malformed SSH_FXP_DATA packet");
  596. sftp_pkt_free(pktin);
  597. return -1;
  598. }
  599. if (data.len > len) {
  600. fxp_internal_error("READ returned more bytes than requested");
  601. sftp_pkt_free(pktin);
  602. return -1;
  603. }
  604. memcpy(buffer, data.ptr, data.len);
  605. sftp_pkt_free(pktin);
  606. return data.len;
  607. } else {
  608. fxp_got_status(pktin);
  609. sftp_pkt_free(pktin);
  610. return -1;
  611. }
  612. }
  613. /*
  614. * Read from a directory.
  615. */
  616. struct sftp_request *fxp_readdir_send(struct fxp_handle *handle)
  617. {
  618. struct sftp_request *req = sftp_alloc_request();
  619. struct sftp_packet *pktout;
  620. pktout = sftp_pkt_init(SSH_FXP_READDIR);
  621. put_uint32(pktout, req->id);
  622. put_string(pktout, handle->hstring, handle->hlen);
  623. sftp_send(pktout);
  624. return req;
  625. }
  626. struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin,
  627. struct sftp_request *req)
  628. {
  629. sfree(req);
  630. if (pktin->type == SSH_FXP_NAME) {
  631. struct fxp_names *names;
  632. unsigned long i;
  633. i = get_uint32(pktin);
  634. /*
  635. * Sanity-check the number of names. Minimum is obviously
  636. * zero. Maximum is the remaining space in the packet
  637. * divided by the very minimum length of a name, which is
  638. * 12 bytes (4 for an empty filename, 4 for an empty
  639. * longname, 4 for a set of attribute flags indicating that
  640. * no other attributes are supplied).
  641. */
  642. if (get_err(pktin) || i > get_avail(pktin) / 12) {
  643. fxp_internal_error("malformed FXP_NAME packet");
  644. sftp_pkt_free(pktin);
  645. return NULL;
  646. }
  647. /*
  648. * Ensure the implicit multiplication in the snewn() call
  649. * doesn't suffer integer overflow and cause us to malloc
  650. * too little space.
  651. */
  652. if (i > INT_MAX / sizeof(struct fxp_name)) {
  653. fxp_internal_error("unreasonably large FXP_NAME packet");
  654. sftp_pkt_free(pktin);
  655. return NULL;
  656. }
  657. names = snew(struct fxp_names);
  658. names->nnames = i;
  659. names->names = snewn(names->nnames, struct fxp_name);
  660. for (i = 0; i < (unsigned long)names->nnames; i++) {
  661. names->names[i].filename = mkstr(get_string(pktin));
  662. names->names[i].longname = mkstr(get_string(pktin));
  663. get_fxp_attrs(pktin, &names->names[i].attrs);
  664. }
  665. if (get_err(pktin)) {
  666. fxp_internal_error("malformed FXP_NAME packet");
  667. for (i = 0; i < (unsigned long)names->nnames; i++) {
  668. sfree(names->names[i].filename);
  669. sfree(names->names[i].longname);
  670. }
  671. sfree(names->names);
  672. sfree(names);
  673. sfree(pktin);
  674. return NULL;
  675. }
  676. sftp_pkt_free(pktin);
  677. return names;
  678. } else {
  679. fxp_got_status(pktin);
  680. sftp_pkt_free(pktin);
  681. return NULL;
  682. }
  683. }
  684. /*
  685. * Write to a file. Returns 0 on error, 1 on OK.
  686. */
  687. struct sftp_request *fxp_write_send(struct fxp_handle *handle,
  688. void *buffer, uint64_t offset, int len)
  689. {
  690. struct sftp_request *req = sftp_alloc_request();
  691. struct sftp_packet *pktout;
  692. pktout = sftp_pkt_init(SSH_FXP_WRITE);
  693. put_uint32(pktout, req->id);
  694. put_string(pktout, handle->hstring, handle->hlen);
  695. put_uint64(pktout, offset);
  696. put_string(pktout, buffer, len);
  697. sftp_send(pktout);
  698. return req;
  699. }
  700. bool fxp_write_recv(struct sftp_packet *pktin, struct sftp_request *req)
  701. {
  702. sfree(req);
  703. fxp_got_status(pktin);
  704. sftp_pkt_free(pktin);
  705. return fxp_errtype == SSH_FX_OK;
  706. }
  707. /*
  708. * Free up an fxp_names structure.
  709. */
  710. void fxp_free_names(struct fxp_names *names)
  711. {
  712. int i;
  713. for (i = 0; i < names->nnames; i++) {
  714. sfree(names->names[i].filename);
  715. sfree(names->names[i].longname);
  716. }
  717. sfree(names->names);
  718. sfree(names);
  719. }
  720. /*
  721. * Duplicate an fxp_name structure.
  722. */
  723. struct fxp_name *fxp_dup_name(struct fxp_name *orig)
  724. {
  725. struct fxp_name *copy;
  726. copy = snew(struct fxp_name);
  727. copy->filename = dupstr(orig->filename);
  728. copy->longname = dupstr(orig->longname);
  729. copy->attrs = orig->attrs; /* structure copy */
  730. return copy;
  731. }
  732. /*
  733. * Free up an fxp_name structure.
  734. */
  735. void fxp_free_name(struct fxp_name *name)
  736. {
  737. sfree(name->filename);
  738. sfree(name->longname);
  739. sfree(name);
  740. }
  741. /*
  742. * Store user data in an sftp_request structure.
  743. */
  744. void *fxp_get_userdata(struct sftp_request *req)
  745. {
  746. return req->userdata;
  747. }
  748. void fxp_set_userdata(struct sftp_request *req, void *data)
  749. {
  750. req->userdata = data;
  751. }
  752. /*
  753. * A wrapper to go round fxp_read_* and fxp_write_*, which manages
  754. * the queueing of multiple read/write requests.
  755. */
  756. struct req {
  757. char *buffer;
  758. int len, retlen, complete;
  759. uint64_t offset;
  760. struct req *next, *prev;
  761. };
  762. struct fxp_xfer {
  763. uint64_t offset, furthestdata, filesize;
  764. int req_totalsize, req_maxsize;
  765. bool eof, err;
  766. struct fxp_handle *fh;
  767. struct req *head, *tail;
  768. };
  769. static struct fxp_xfer *xfer_init(struct fxp_handle *fh, uint64_t offset)
  770. {
  771. struct fxp_xfer *xfer = snew(struct fxp_xfer);
  772. xfer->fh = fh;
  773. xfer->offset = offset;
  774. xfer->head = xfer->tail = NULL;
  775. xfer->req_totalsize = 0;
  776. xfer->req_maxsize = 1048576;
  777. xfer->err = false;
  778. xfer->filesize = UINT64_MAX;
  779. xfer->furthestdata = 0;
  780. return xfer;
  781. }
  782. bool xfer_done(struct fxp_xfer *xfer)
  783. {
  784. /*
  785. * We're finished if we've seen EOF _and_ there are no
  786. * outstanding requests.
  787. */
  788. return (xfer->eof || xfer->err) && !xfer->head;
  789. }
  790. void xfer_download_queue(struct fxp_xfer *xfer)
  791. {
  792. while (xfer->req_totalsize < xfer->req_maxsize &&
  793. !xfer->eof && !xfer->err) {
  794. /*
  795. * Queue a new read request.
  796. */
  797. struct req *rr;
  798. struct sftp_request *req;
  799. rr = snew(struct req);
  800. rr->offset = xfer->offset;
  801. rr->complete = 0;
  802. if (xfer->tail) {
  803. xfer->tail->next = rr;
  804. rr->prev = xfer->tail;
  805. } else {
  806. xfer->head = rr;
  807. rr->prev = NULL;
  808. }
  809. xfer->tail = rr;
  810. rr->next = NULL;
  811. rr->len = 32768;
  812. rr->buffer = snewn(rr->len, char);
  813. sftp_register(req = fxp_read_send(xfer->fh, rr->offset, rr->len));
  814. fxp_set_userdata(req, rr);
  815. xfer->offset += rr->len;
  816. xfer->req_totalsize += rr->len;
  817. #ifdef DEBUG_DOWNLOAD
  818. printf("queueing read request %p at %"PRIu64"\n", rr, rr->offset);
  819. #endif
  820. }
  821. }
  822. struct fxp_xfer *xfer_download_init(struct fxp_handle *fh, uint64_t offset)
  823. {
  824. struct fxp_xfer *xfer = xfer_init(fh, offset);
  825. xfer->eof = false;
  826. xfer_download_queue(xfer);
  827. return xfer;
  828. }
  829. /*
  830. * Returns INT_MIN to indicate that it didn't even get as far as
  831. * fxp_read_recv and hence has not freed pktin.
  832. */
  833. int xfer_download_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
  834. {
  835. struct sftp_request *rreq;
  836. struct req *rr;
  837. rreq = sftp_find_request(pktin);
  838. if (!rreq)
  839. return INT_MIN; /* this packet doesn't even make sense */
  840. rr = (struct req *)fxp_get_userdata(rreq);
  841. if (!rr) {
  842. fxp_internal_error("request ID is not part of the current download");
  843. return INT_MIN; /* this packet isn't ours */
  844. }
  845. rr->retlen = fxp_read_recv(pktin, rreq, rr->buffer, rr->len);
  846. #ifdef DEBUG_DOWNLOAD
  847. printf("read request %p has returned [%d]\n", rr, rr->retlen);
  848. #endif
  849. if ((rr->retlen < 0 && fxp_error_type()==SSH_FX_EOF) || rr->retlen == 0) {
  850. xfer->eof = true;
  851. rr->retlen = 0;
  852. rr->complete = -1;
  853. #ifdef DEBUG_DOWNLOAD
  854. printf("setting eof\n");
  855. #endif
  856. } else if (rr->retlen < 0) {
  857. /* some error other than EOF; signal it back to caller */
  858. xfer_set_error(xfer);
  859. rr->complete = -1;
  860. return -1;
  861. }
  862. rr->complete = 1;
  863. /*
  864. * Special case: if we have received fewer bytes than we
  865. * actually read, we should do something. For the moment I'll
  866. * just throw an ersatz FXP error to signal this; the SFTP
  867. * draft I've got says that it can't happen except on special
  868. * files, in which case seeking probably has very little
  869. * meaning and so queueing an additional read request to fill
  870. * up the gap sounds like the wrong answer. I'm not sure what I
  871. * should be doing here - if it _was_ a special file, I suspect
  872. * I simply shouldn't have been queueing multiple requests in
  873. * the first place...
  874. */
  875. if (rr->retlen > 0 && xfer->furthestdata < rr->offset) {
  876. xfer->furthestdata = rr->offset;
  877. #ifdef DEBUG_DOWNLOAD
  878. printf("setting furthestdata = %"PRIu64"\n", xfer->furthestdata);
  879. #endif
  880. }
  881. if (rr->retlen < rr->len) {
  882. uint64_t filesize = rr->offset + (rr->retlen < 0 ? 0 : rr->retlen);
  883. #ifdef DEBUG_DOWNLOAD
  884. printf("short block! trying filesize = %"PRIu64"\n", filesize);
  885. #endif
  886. if (xfer->filesize > filesize) {
  887. xfer->filesize = filesize;
  888. #ifdef DEBUG_DOWNLOAD
  889. printf("actually changing filesize\n");
  890. #endif
  891. }
  892. }
  893. if (xfer->furthestdata > xfer->filesize) {
  894. fxp_error_message = "received a short buffer from FXP_READ, but not"
  895. " at EOF";
  896. fxp_errtype = -1;
  897. xfer_set_error(xfer);
  898. return -1;
  899. }
  900. return 1;
  901. }
  902. void xfer_set_error(struct fxp_xfer *xfer)
  903. {
  904. xfer->err = true;
  905. }
  906. bool xfer_download_data(struct fxp_xfer *xfer, void **buf, int *len)
  907. {
  908. void *retbuf = NULL;
  909. int retlen = 0;
  910. /*
  911. * Discard anything at the head of the rr queue with complete <
  912. * 0; return the first thing with complete > 0.
  913. */
  914. while (xfer->head && xfer->head->complete && !retbuf) {
  915. struct req *rr = xfer->head;
  916. if (rr->complete > 0) {
  917. retbuf = rr->buffer;
  918. retlen = rr->retlen;
  919. #ifdef DEBUG_DOWNLOAD
  920. printf("handing back data from read request %p\n", rr);
  921. #endif
  922. }
  923. #ifdef DEBUG_DOWNLOAD
  924. else
  925. printf("skipping failed read request %p\n", rr);
  926. #endif
  927. xfer->head = xfer->head->next;
  928. if (xfer->head)
  929. xfer->head->prev = NULL;
  930. else
  931. xfer->tail = NULL;
  932. xfer->req_totalsize -= rr->len;
  933. sfree(rr);
  934. }
  935. if (retbuf) {
  936. *buf = retbuf;
  937. *len = retlen;
  938. return true;
  939. } else
  940. return false;
  941. }
  942. struct fxp_xfer *xfer_upload_init(struct fxp_handle *fh, uint64_t offset)
  943. {
  944. struct fxp_xfer *xfer = xfer_init(fh, offset);
  945. /*
  946. * We set `eof' to 1 because this will cause xfer_done() to
  947. * return true iff there are no outstanding requests. During an
  948. * upload, our caller will be responsible for working out
  949. * whether all the data has been sent, so all it needs to know
  950. * from us is whether the outstanding requests have been
  951. * handled once that's done.
  952. */
  953. xfer->eof = true;
  954. return xfer;
  955. }
  956. bool xfer_upload_ready(struct fxp_xfer *xfer)
  957. {
  958. return sftp_sendbuffer() == 0;
  959. }
  960. void xfer_upload_data(struct fxp_xfer *xfer, char *buffer, int len)
  961. {
  962. struct req *rr;
  963. struct sftp_request *req;
  964. rr = snew(struct req);
  965. rr->offset = xfer->offset;
  966. rr->complete = 0;
  967. if (xfer->tail) {
  968. xfer->tail->next = rr;
  969. rr->prev = xfer->tail;
  970. } else {
  971. xfer->head = rr;
  972. rr->prev = NULL;
  973. }
  974. xfer->tail = rr;
  975. rr->next = NULL;
  976. rr->len = len;
  977. rr->buffer = NULL;
  978. sftp_register(req = fxp_write_send(xfer->fh, buffer, rr->offset, len));
  979. fxp_set_userdata(req, rr);
  980. xfer->offset += rr->len;
  981. xfer->req_totalsize += rr->len;
  982. #ifdef DEBUG_UPLOAD
  983. printf("queueing write request %p at %"PRIu64" [len %d]\n",
  984. rr, rr->offset, len);
  985. #endif
  986. }
  987. /*
  988. * Returns INT_MIN to indicate that it didn't even get as far as
  989. * fxp_write_recv and hence has not freed pktin.
  990. */
  991. int xfer_upload_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
  992. {
  993. struct sftp_request *rreq;
  994. struct req *rr, *prev, *next;
  995. bool ret;
  996. rreq = sftp_find_request(pktin);
  997. if (!rreq)
  998. return INT_MIN; /* this packet doesn't even make sense */
  999. rr = (struct req *)fxp_get_userdata(rreq);
  1000. if (!rr) {
  1001. fxp_internal_error("request ID is not part of the current upload");
  1002. return INT_MIN; /* this packet isn't ours */
  1003. }
  1004. ret = fxp_write_recv(pktin, rreq);
  1005. #ifdef DEBUG_UPLOAD
  1006. printf("write request %p has returned [%d]\n", rr, ret ? 1 : 0);
  1007. #endif
  1008. /*
  1009. * Remove this one from the queue.
  1010. */
  1011. prev = rr->prev;
  1012. next = rr->next;
  1013. if (prev)
  1014. prev->next = next;
  1015. else
  1016. xfer->head = next;
  1017. if (next)
  1018. next->prev = prev;
  1019. else
  1020. xfer->tail = prev;
  1021. xfer->req_totalsize -= rr->len;
  1022. sfree(rr);
  1023. if (!ret)
  1024. return -1;
  1025. return 1;
  1026. }
  1027. void xfer_cleanup(struct fxp_xfer *xfer)
  1028. {
  1029. struct req *rr;
  1030. while (xfer->head) {
  1031. rr = xfer->head;
  1032. xfer->head = xfer->head->next;
  1033. sfree(rr->buffer);
  1034. sfree(rr);
  1035. }
  1036. sfree(xfer);
  1037. }