ssh.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2007, Daniel Stenberg, <[email protected]>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at http://curl.haxx.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * $Id$
  22. ***************************************************************************/
  23. /* #define CURL_LIBSSH2_DEBUG */
  24. #include "setup.h"
  25. #ifdef USE_LIBSSH2
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <stdarg.h>
  30. #include <ctype.h>
  31. #include <limits.h>
  32. #include <libssh2.h>
  33. #include <libssh2_sftp.h>
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. #ifdef HAVE_FCNTL_H
  38. #include <fcntl.h>
  39. #endif
  40. #ifdef HAVE_SYS_TYPES_H
  41. #include <sys/types.h>
  42. #endif
  43. #ifdef HAVE_SYS_STAT_H
  44. #include <sys/stat.h>
  45. #endif
  46. #ifdef HAVE_TIME_H
  47. #include <time.h>
  48. #endif
  49. #ifdef WIN32
  50. #else /* probably some kind of unix */
  51. #ifdef HAVE_SYS_SOCKET_H
  52. #include <sys/socket.h>
  53. #endif
  54. #include <sys/types.h>
  55. #ifdef HAVE_NETINET_IN_H
  56. #include <netinet/in.h>
  57. #endif
  58. #ifdef HAVE_ARPA_INET_H
  59. #include <arpa/inet.h>
  60. #endif
  61. #ifdef HAVE_UTSNAME_H
  62. #include <sys/utsname.h>
  63. #endif
  64. #ifdef HAVE_NETDB_H
  65. #include <netdb.h>
  66. #endif
  67. #ifdef VMS
  68. #include <in.h>
  69. #include <inet.h>
  70. #endif
  71. #endif
  72. #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
  73. #undef in_addr_t
  74. #define in_addr_t unsigned long
  75. #endif
  76. #include <curl/curl.h>
  77. #include "urldata.h"
  78. #include "sendf.h"
  79. #include "easyif.h" /* for Curl_convert_... prototypes */
  80. #include "if2ip.h"
  81. #include "hostip.h"
  82. #include "progress.h"
  83. #include "transfer.h"
  84. #include "escape.h"
  85. #include "http.h" /* for HTTP proxy tunnel stuff */
  86. #include "ssh.h"
  87. #include "url.h"
  88. #include "speedcheck.h"
  89. #include "getinfo.h"
  90. #include "strtoofft.h"
  91. #include "strequal.h"
  92. #include "sslgen.h"
  93. #include "connect.h"
  94. #include "strerror.h"
  95. #include "memory.h"
  96. #include "inet_ntop.h"
  97. #include "select.h"
  98. #include "parsedate.h" /* for the week day and month names */
  99. #include "sockaddr.h" /* required for Curl_sockaddr_storage */
  100. #include "multiif.h"
  101. #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
  102. #include "inet_ntoa_r.h"
  103. #endif
  104. #define _MPRINTF_REPLACE /* use our functions only */
  105. #include <curl/mprintf.h>
  106. #if defined(WIN32) || defined(MSDOS) || defined(__EMX__)
  107. #define DIRSEP '\\'
  108. #else
  109. #define DIRSEP '/'
  110. #endif
  111. #define _MPRINTF_REPLACE /* use our functions only */
  112. #include <curl/mprintf.h>
  113. /* The last #include file should be: */
  114. #ifdef CURLDEBUG
  115. #include "memdebug.h"
  116. #endif
  117. #ifndef LIBSSH2_SFTP_S_IRUSR
  118. /* Here's a work-around for those of you who happend to run a libssh2 version
  119. that is 0.14 or older. We should remove this kludge as soon as we can
  120. require a more recent libssh2 release. */
  121. #ifndef S_IRGRP
  122. #define S_IRGRP 0
  123. #endif
  124. #ifndef S_IROTH
  125. #define S_IROTH 0
  126. #endif
  127. #define LIBSSH2_SFTP_S_IRUSR S_IRUSR
  128. #define LIBSSH2_SFTP_S_IWUSR S_IWUSR
  129. #define LIBSSH2_SFTP_S_IRGRP S_IRGRP
  130. #define LIBSSH2_SFTP_S_IROTH S_IROTH
  131. #define LIBSSH2_SFTP_S_IRUSR S_IRUSR
  132. #define LIBSSH2_SFTP_S_IWUSR S_IWUSR
  133. #define LIBSSH2_SFTP_S_IRGRP S_IRGRP
  134. #define LIBSSH2_SFTP_S_IROTH S_IROTH
  135. #define LIBSSH2_SFTP_S_IFMT S_IFMT
  136. #define LIBSSH2_SFTP_S_IFDIR S_IFDIR
  137. #define LIBSSH2_SFTP_S_IFLNK S_IFLNK
  138. #define LIBSSH2_SFTP_S_IFSOCK S_IFSOCK
  139. #define LIBSSH2_SFTP_S_IFCHR S_IFCHR
  140. #define LIBSSH2_SFTP_S_IFBLK S_IFBLK
  141. #define LIBSSH2_SFTP_S_IXUSR S_IXUSR
  142. #define LIBSSH2_SFTP_S_IWGRP S_IWGRP
  143. #define LIBSSH2_SFTP_S_IXGRP S_IXGRP
  144. #define LIBSSH2_SFTP_S_IWOTH S_IWOTH
  145. #define LIBSSH2_SFTP_S_IXOTH S_IXOTH
  146. #endif
  147. static LIBSSH2_ALLOC_FUNC(libssh2_malloc);
  148. static LIBSSH2_REALLOC_FUNC(libssh2_realloc);
  149. static LIBSSH2_FREE_FUNC(libssh2_free);
  150. static void
  151. kbd_callback(const char *name, int name_len, const char *instruction,
  152. int instruction_len, int num_prompts,
  153. const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
  154. LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
  155. void **abstract)
  156. {
  157. struct SSHPROTO *ssh = (struct SSHPROTO *)*abstract;
  158. #ifdef CURL_LIBSSH2_DEBUG
  159. fprintf(stderr, "name=%s\n", name);
  160. fprintf(stderr, "name_len=%d\n", name_len);
  161. fprintf(stderr, "instruction=%s\n", instruction);
  162. fprintf(stderr, "instruction_len=%d\n", instruction_len);
  163. fprintf(stderr, "num_prompts=%d\n", num_prompts);
  164. #else
  165. (void)name;
  166. (void)name_len;
  167. (void)instruction;
  168. (void)instruction_len;
  169. #endif /* CURL_LIBSSH2_DEBUG */
  170. if (num_prompts == 1) {
  171. responses[0].text = strdup(ssh->passwd);
  172. responses[0].length = strlen(ssh->passwd);
  173. }
  174. (void)prompts;
  175. (void)abstract;
  176. } /* kbd_callback */
  177. static CURLcode libssh2_error_to_CURLE(struct connectdata *conn)
  178. {
  179. int errorcode;
  180. struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
  181. /* Get the libssh2 error code and string */
  182. errorcode = libssh2_session_last_error(scp->ssh_session, &scp->errorstr,
  183. NULL, 0);
  184. if (errorcode == LIBSSH2_FX_OK)
  185. return CURLE_OK;
  186. infof(conn->data, "libssh2 error %d, '%s'\n", errorcode, scp->errorstr);
  187. /* TODO: map some of the libssh2 errors to the more appropriate CURLcode
  188. error code, and possibly add a few new SSH-related one. We must however
  189. not return or even depend on libssh2 errors in the public libcurl API */
  190. return CURLE_SSH;
  191. }
  192. static LIBSSH2_ALLOC_FUNC(libssh2_malloc)
  193. {
  194. return malloc(count);
  195. (void)abstract;
  196. }
  197. static LIBSSH2_REALLOC_FUNC(libssh2_realloc)
  198. {
  199. return realloc(ptr, count);
  200. (void)abstract;
  201. }
  202. static LIBSSH2_FREE_FUNC(libssh2_free)
  203. {
  204. free(ptr);
  205. (void)abstract;
  206. }
  207. static CURLcode ssh_init(struct connectdata *conn)
  208. {
  209. struct SessionHandle *data = conn->data;
  210. struct SSHPROTO *ssh;
  211. if (data->reqdata.proto.ssh)
  212. return CURLE_OK;
  213. ssh = (struct SSHPROTO *)calloc(sizeof(struct SSHPROTO), 1);
  214. if (!ssh)
  215. return CURLE_OUT_OF_MEMORY;
  216. data->reqdata.proto.ssh = ssh;
  217. /* get some initial data into the ssh struct */
  218. ssh->bytecountp = &data->reqdata.keep.bytecount;
  219. /* no need to duplicate them, this connectdata struct won't change */
  220. ssh->user = conn->user;
  221. ssh->passwd = conn->passwd;
  222. ssh->errorstr = NULL;
  223. ssh->ssh_session = NULL;
  224. ssh->ssh_channel = NULL;
  225. ssh->sftp_session = NULL;
  226. ssh->sftp_handle = NULL;
  227. return CURLE_OK;
  228. }
  229. /*
  230. * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
  231. * do protocol-specific actions at connect-time.
  232. */
  233. CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
  234. {
  235. int i;
  236. struct SSHPROTO *ssh;
  237. const char *fingerprint;
  238. const char *authlist;
  239. char *home;
  240. char rsa_pub[PATH_MAX];
  241. char rsa[PATH_MAX];
  242. char tempHome[PATH_MAX];
  243. curl_socket_t sock;
  244. char *real_path;
  245. char *working_path;
  246. int working_path_len;
  247. bool authed = FALSE;
  248. CURLcode result;
  249. struct SessionHandle *data = conn->data;
  250. rsa_pub[0] = rsa[0] = '\0';
  251. result = ssh_init(conn);
  252. if (result)
  253. return result;
  254. ssh = data->reqdata.proto.ssh;
  255. working_path = curl_easy_unescape(data, data->reqdata.path, 0,
  256. &working_path_len);
  257. if (!working_path)
  258. return CURLE_OUT_OF_MEMORY;
  259. #ifdef CURL_LIBSSH2_DEBUG
  260. if (ssh->user) {
  261. infof(data, "User: %s\n", ssh->user);
  262. }
  263. if (ssh->passwd) {
  264. infof(data, "Password: %s\n", ssh->passwd);
  265. }
  266. #endif /* CURL_LIBSSH2_DEBUG */
  267. sock = conn->sock[FIRSTSOCKET];
  268. ssh->ssh_session = libssh2_session_init_ex(libssh2_malloc, libssh2_free,
  269. libssh2_realloc, ssh);
  270. if (ssh->ssh_session == NULL) {
  271. failf(data, "Failure initialising ssh session\n");
  272. Curl_safefree(ssh->path);
  273. return CURLE_FAILED_INIT;
  274. }
  275. #ifdef CURL_LIBSSH2_DEBUG
  276. infof(data, "SSH socket: %d\n", sock);
  277. #endif /* CURL_LIBSSH2_DEBUG */
  278. if (libssh2_session_startup(ssh->ssh_session, sock)) {
  279. failf(data, "Failure establishing ssh session\n");
  280. libssh2_session_free(ssh->ssh_session);
  281. ssh->ssh_session = NULL;
  282. Curl_safefree(ssh->path);
  283. return CURLE_FAILED_INIT;
  284. }
  285. /*
  286. * Before we authenticate we should check the hostkey's fingerprint against
  287. * our known hosts. How that is handled (reading from file, whatever) is
  288. * up to us. As for know not much is implemented, besides showing how to
  289. * get the fingerprint.
  290. */
  291. fingerprint = libssh2_hostkey_hash(ssh->ssh_session,
  292. LIBSSH2_HOSTKEY_HASH_MD5);
  293. #ifdef CURL_LIBSSH2_DEBUG
  294. /* The fingerprint points to static storage (!), don't free() it. */
  295. infof(data, "Fingerprint: ");
  296. for (i = 0; i < 16; i++) {
  297. infof(data, "%02X ", (unsigned char) fingerprint[i]);
  298. }
  299. infof(data, "\n");
  300. #endif /* CURL_LIBSSH2_DEBUG */
  301. /* TBD - methods to check the host keys need to be done */
  302. /*
  303. * Figure out authentication methods
  304. * NB: As soon as we have provided a username to an openssh server we must
  305. * never change it later. Thus, always specify the correct username here,
  306. * even though the libssh2 docs kind of indicate that it should be possible
  307. * to get a 'generic' list (not user-specific) of authentication methods,
  308. * presumably with a blank username. That won't work in my experience.
  309. * So always specify it here.
  310. */
  311. authlist = libssh2_userauth_list(ssh->ssh_session, ssh->user,
  312. strlen(ssh->user));
  313. /*
  314. * Check the supported auth types in the order I feel is most secure with the
  315. * requested type of authentication
  316. */
  317. if ((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
  318. (strstr(authlist, "publickey") != NULL)) {
  319. /* To ponder about: should really the lib be messing about with the HOME
  320. environment variable etc? */
  321. home = curl_getenv("HOME");
  322. if (data->set.ssh_public_key)
  323. snprintf(rsa_pub, sizeof(rsa_pub), "%s", data->set.ssh_public_key);
  324. else if (home)
  325. snprintf(rsa_pub, sizeof(rsa_pub), "%s/.ssh/id_dsa.pub", home);
  326. if (data->set.ssh_private_key)
  327. snprintf(rsa, sizeof(rsa), "%s", data->set.ssh_private_key);
  328. else if (home)
  329. snprintf(rsa, sizeof(rsa), "%s/.ssh/id_dsa", home);
  330. curl_free(home);
  331. if (rsa_pub[0]) {
  332. /* The function below checks if the files exists, no need to stat() here.
  333. */
  334. if (libssh2_userauth_publickey_fromfile(ssh->ssh_session, ssh->user,
  335. rsa_pub, rsa, "") == 0) {
  336. authed = TRUE;
  337. }
  338. }
  339. }
  340. if (!authed &&
  341. (data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
  342. (strstr(authlist, "password") != NULL)) {
  343. if (!libssh2_userauth_password(ssh->ssh_session, ssh->user, ssh->passwd))
  344. authed = TRUE;
  345. }
  346. if (!authed && (data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
  347. (strstr(authlist, "hostbased") != NULL)) {
  348. }
  349. if (!authed && (data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
  350. && (strstr(authlist, "keyboard-interactive") != NULL)) {
  351. /* Authentication failed. Continue with keyboard-interactive now. */
  352. if (libssh2_userauth_keyboard_interactive_ex(ssh->ssh_session, ssh->user,
  353. strlen(ssh->user),
  354. &kbd_callback) == 0) {
  355. authed = TRUE;
  356. }
  357. }
  358. if (!authed) {
  359. failf(data, "Authentication failure\n");
  360. libssh2_session_free(ssh->ssh_session);
  361. ssh->ssh_session = NULL;
  362. Curl_safefree(ssh->path);
  363. return CURLE_FAILED_INIT;
  364. }
  365. /*
  366. * At this point we have an authenticated ssh session.
  367. */
  368. conn->sockfd = sock;
  369. conn->writesockfd = CURL_SOCKET_BAD;
  370. if (conn->protocol == PROT_SFTP) {
  371. /*
  372. * Start the libssh2 sftp session
  373. */
  374. ssh->sftp_session = libssh2_sftp_init(ssh->ssh_session);
  375. if (ssh->sftp_session == NULL) {
  376. failf(data, "Failure initialising sftp session\n");
  377. libssh2_sftp_shutdown(ssh->sftp_session);
  378. ssh->sftp_session = NULL;
  379. libssh2_session_free(ssh->ssh_session);
  380. ssh->ssh_session = NULL;
  381. return CURLE_FAILED_INIT;
  382. }
  383. /*
  384. * Get the "home" directory
  385. */
  386. i = libssh2_sftp_realpath(ssh->sftp_session, ".", tempHome, PATH_MAX-1);
  387. if (i > 0) {
  388. /* It seems that this string is not always NULL terminated */
  389. tempHome[i] = '\0';
  390. ssh->homedir = (char *)strdup(tempHome);
  391. if (!ssh->homedir) {
  392. libssh2_sftp_shutdown(ssh->sftp_session);
  393. ssh->sftp_session = NULL;
  394. libssh2_session_free(ssh->ssh_session);
  395. ssh->ssh_session = NULL;
  396. return CURLE_OUT_OF_MEMORY;
  397. }
  398. }
  399. else {
  400. /* Return the error type */
  401. i = libssh2_sftp_last_error(ssh->sftp_session);
  402. DEBUGF(infof(data, "error = %d\n", i));
  403. }
  404. }
  405. /* Check for /~/ , indicating realative to the users home directory */
  406. if (conn->protocol == PROT_SCP) {
  407. real_path = (char *)malloc(working_path_len+1);
  408. if (real_path == NULL) {
  409. Curl_safefree(working_path);
  410. libssh2_session_free(ssh->ssh_session);
  411. ssh->ssh_session = NULL;
  412. return CURLE_OUT_OF_MEMORY;
  413. }
  414. if (working_path[1] == '~')
  415. /* It is referenced to the home directory, so strip the leading '/' */
  416. memcpy(real_path, working_path+1, 1 + working_path_len-1);
  417. else
  418. memcpy(real_path, working_path, 1 + working_path_len);
  419. }
  420. else if (conn->protocol == PROT_SFTP) {
  421. if (working_path[1] == '~') {
  422. real_path = (char *)malloc(strlen(ssh->homedir) +
  423. working_path_len + 1);
  424. if (real_path == NULL) {
  425. libssh2_sftp_shutdown(ssh->sftp_session);
  426. ssh->sftp_session = NULL;
  427. libssh2_session_free(ssh->ssh_session);
  428. ssh->ssh_session = NULL;
  429. Curl_safefree(working_path);
  430. return CURLE_OUT_OF_MEMORY;
  431. }
  432. /* It is referenced to the home directory, so strip the leading '/' */
  433. memcpy(real_path, ssh->homedir, strlen(ssh->homedir));
  434. real_path[strlen(ssh->homedir)] = '/';
  435. real_path[strlen(ssh->homedir)+1] = '\0';
  436. if (working_path_len > 3) {
  437. memcpy(real_path+strlen(ssh->homedir)+1, working_path + 3,
  438. 1 + working_path_len -3);
  439. }
  440. }
  441. else {
  442. real_path = (char *)malloc(working_path_len+1);
  443. if (real_path == NULL) {
  444. libssh2_session_free(ssh->ssh_session);
  445. ssh->ssh_session = NULL;
  446. Curl_safefree(working_path);
  447. return CURLE_OUT_OF_MEMORY;
  448. }
  449. memcpy(real_path, working_path, 1+working_path_len);
  450. }
  451. }
  452. else
  453. return CURLE_FAILED_INIT;
  454. Curl_safefree(working_path);
  455. ssh->path = real_path;
  456. *done = TRUE;
  457. return CURLE_OK;
  458. }
  459. CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
  460. {
  461. struct stat sb;
  462. struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
  463. CURLcode res = CURLE_OK;
  464. *done = TRUE; /* unconditionally */
  465. if (conn->data->set.upload) {
  466. /*
  467. * NOTE!!! libssh2 requires that the destination path is a full path
  468. * that includes the destination file and name OR ends in a "/" .
  469. * If this is not done the destination file will be named the
  470. * same name as the last directory in the path.
  471. */
  472. scp->ssh_channel = libssh2_scp_send_ex(scp->ssh_session, scp->path,
  473. LIBSSH2_SFTP_S_IRUSR|
  474. LIBSSH2_SFTP_S_IWUSR|
  475. LIBSSH2_SFTP_S_IRGRP|
  476. LIBSSH2_SFTP_S_IROTH,
  477. conn->data->set.infilesize, 0, 0);
  478. if (!scp->ssh_channel)
  479. return CURLE_FAILED_INIT;
  480. /* upload data */
  481. res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
  482. }
  483. else {
  484. /*
  485. * We must check the remote file, if it is a directory no vaules will
  486. * be set in sb
  487. */
  488. curl_off_t bytecount;
  489. memset(&sb, 0, sizeof(struct stat));
  490. scp->ssh_channel = libssh2_scp_recv(scp->ssh_session, scp->path, &sb);
  491. if (!scp->ssh_channel) {
  492. if ((sb.st_mode == 0) && (sb.st_atime == 0) && (sb.st_mtime == 0) &&
  493. (sb.st_size == 0)) {
  494. /* Since sb is still empty, it is likely the file was not found */
  495. return CURLE_REMOTE_FILE_NOT_FOUND;
  496. }
  497. return libssh2_error_to_CURLE(conn);
  498. }
  499. /* download data */
  500. bytecount = (curl_off_t) sb.st_size;
  501. conn->data->reqdata.maxdownload = (curl_off_t) sb.st_size;
  502. res = Curl_setup_transfer(conn, FIRSTSOCKET,
  503. bytecount, FALSE, NULL, -1, NULL);
  504. }
  505. return res;
  506. }
  507. CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
  508. bool premature)
  509. {
  510. struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
  511. (void)premature; /* not used */
  512. Curl_safefree(scp->path);
  513. scp->path = NULL;
  514. if (scp->ssh_channel) {
  515. if (libssh2_channel_close(scp->ssh_channel) < 0) {
  516. infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
  517. }
  518. }
  519. if (scp->ssh_session) {
  520. libssh2_session_disconnect(scp->ssh_session, "Shutdown");
  521. libssh2_session_free(scp->ssh_session);
  522. scp->ssh_session = NULL;
  523. }
  524. free(conn->data->reqdata.proto.ssh);
  525. conn->data->reqdata.proto.ssh = NULL;
  526. Curl_pgrsDone(conn);
  527. (void)status; /* unused */
  528. return CURLE_OK;
  529. }
  530. /* return number of received (decrypted) bytes */
  531. ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
  532. void *mem, size_t len)
  533. {
  534. ssize_t nwrite;
  535. /* libssh2_channel_write() returns int
  536. *
  537. * NOTE: we should not store nor rely on connection-related data to be
  538. * in the SessionHandle struct
  539. */
  540. nwrite = (ssize_t)
  541. libssh2_channel_write(conn->data->reqdata.proto.ssh->ssh_channel,
  542. mem, len);
  543. (void)sockindex;
  544. return nwrite;
  545. }
  546. /*
  547. * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
  548. * a regular CURLcode value.
  549. */
  550. ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
  551. char *mem, size_t len)
  552. {
  553. ssize_t nread;
  554. /* libssh2_channel_read() returns int
  555. *
  556. * NOTE: we should not store nor rely on connection-related data to be
  557. * in the SessionHandle struct
  558. */
  559. nread = (ssize_t)
  560. libssh2_channel_read(conn->data->reqdata.proto.ssh->ssh_channel,
  561. mem, len);
  562. (void)sockindex;
  563. return nread;
  564. }
  565. /*
  566. * =============== SFTP ===============
  567. */
  568. CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
  569. {
  570. LIBSSH2_SFTP_ATTRIBUTES attrs;
  571. struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
  572. CURLcode res = CURLE_OK;
  573. struct SessionHandle *data = conn->data;
  574. curl_off_t bytecount = 0;
  575. char *buf = data->state.buffer;
  576. *done = TRUE; /* unconditionally */
  577. if (data->set.upload) {
  578. /*
  579. * NOTE!!! libssh2 requires that the destination path is a full path
  580. * that includes the destination file and name OR ends in a "/" .
  581. * If this is not done the destination file will be named the
  582. * same name as the last directory in the path.
  583. */
  584. sftp->sftp_handle =
  585. libssh2_sftp_open(sftp->sftp_session, sftp->path,
  586. LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT,
  587. LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
  588. LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
  589. if (!sftp->sftp_handle)
  590. return CURLE_FAILED_INIT;
  591. /* upload data */
  592. res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
  593. }
  594. else {
  595. if (sftp->path[strlen(sftp->path)-1] == '/') {
  596. /*
  597. * This is a directory that we are trying to get, so produce a
  598. * directory listing
  599. *
  600. * **BLOCKING behaviour** This should be made into a state machine and
  601. * get a separate function called from Curl_sftp_recv() when there is
  602. * data to read from the network, instead of "hanging" here.
  603. */
  604. char filename[PATH_MAX+1];
  605. int len, totalLen, currLen;
  606. char *line;
  607. sftp->sftp_handle =
  608. libssh2_sftp_opendir(sftp->sftp_session, sftp->path);
  609. if (!sftp->sftp_handle)
  610. return CURLE_SSH;
  611. while ((len = libssh2_sftp_readdir(sftp->sftp_handle, filename,
  612. PATH_MAX, &attrs)) > 0) {
  613. filename[len] = '\0';
  614. if (data->set.ftp_list_only) {
  615. if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
  616. ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
  617. LIBSSH2_SFTP_S_IFDIR)) {
  618. infof(data, "%s\n", filename);
  619. }
  620. }
  621. else {
  622. totalLen = 80 + len;
  623. line = (char *)malloc(totalLen);
  624. if (!line)
  625. return CURLE_OUT_OF_MEMORY;
  626. if (!(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID))
  627. attrs.uid = attrs.gid =0;
  628. currLen = snprintf(line, totalLen, "---------- 1 %5d %5d",
  629. attrs.uid, attrs.gid);
  630. if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
  631. if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
  632. LIBSSH2_SFTP_S_IFDIR) {
  633. line[0] = 'd';
  634. }
  635. else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
  636. LIBSSH2_SFTP_S_IFLNK) {
  637. line[0] = 'l';
  638. }
  639. else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
  640. LIBSSH2_SFTP_S_IFSOCK) {
  641. line[0] = 's';
  642. }
  643. else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
  644. LIBSSH2_SFTP_S_IFCHR) {
  645. line[0] = 'c';
  646. }
  647. else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
  648. LIBSSH2_SFTP_S_IFBLK) {
  649. line[0] = 'b';
  650. }
  651. if (attrs.permissions & LIBSSH2_SFTP_S_IRUSR) {
  652. line[1] = 'r';
  653. }
  654. if (attrs.permissions & LIBSSH2_SFTP_S_IWUSR) {
  655. line[2] = 'w';
  656. }
  657. if (attrs.permissions & LIBSSH2_SFTP_S_IXUSR) {
  658. line[3] = 'x';
  659. }
  660. if (attrs.permissions & LIBSSH2_SFTP_S_IRGRP) {
  661. line[4] = 'r';
  662. }
  663. if (attrs.permissions & LIBSSH2_SFTP_S_IWGRP) {
  664. line[5] = 'w';
  665. }
  666. if (attrs.permissions & LIBSSH2_SFTP_S_IXGRP) {
  667. line[6] = 'x';
  668. }
  669. if (attrs.permissions & LIBSSH2_SFTP_S_IROTH) {
  670. line[7] = 'r';
  671. }
  672. if (attrs.permissions & LIBSSH2_SFTP_S_IWOTH) {
  673. line[8] = 'w';
  674. }
  675. if (attrs.permissions & LIBSSH2_SFTP_S_IXOTH) {
  676. line[9] = 'x';
  677. }
  678. }
  679. if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
  680. currLen += snprintf(line+currLen, totalLen-currLen, "%11lld",
  681. attrs.filesize);
  682. }
  683. if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
  684. const char *months[12] = {
  685. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  686. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  687. struct tm *nowParts;
  688. time_t now, remoteTime;
  689. now = time(NULL);
  690. remoteTime = (time_t)attrs.mtime;
  691. nowParts = localtime(&remoteTime);
  692. if ((time_t)attrs.mtime > (now - (3600 * 24 * 180))) {
  693. currLen += snprintf(line+currLen, totalLen-currLen,
  694. " %s %2d %2d:%02d", months[nowParts->tm_mon],
  695. nowParts->tm_mday, nowParts->tm_hour,
  696. nowParts->tm_min);
  697. }
  698. else {
  699. currLen += snprintf(line+currLen, totalLen-currLen,
  700. " %s %2d %5d", months[nowParts->tm_mon],
  701. nowParts->tm_mday, 1900+nowParts->tm_year);
  702. }
  703. }
  704. currLen += snprintf(line+currLen, totalLen-currLen, " %s", filename);
  705. if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
  706. ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
  707. LIBSSH2_SFTP_S_IFLNK)) {
  708. char linkPath[PATH_MAX + 1];
  709. snprintf(linkPath, PATH_MAX, "%s%s", sftp->path, filename);
  710. len = libssh2_sftp_readlink(sftp->sftp_session, linkPath, filename,
  711. PATH_MAX);
  712. line = realloc(line, totalLen + 4 + len);
  713. if (!line)
  714. return CURLE_OUT_OF_MEMORY;
  715. currLen += snprintf(line+currLen, totalLen-currLen, " -> %s",
  716. filename);
  717. }
  718. currLen += snprintf(line+currLen, totalLen-currLen, "\n");
  719. res = Curl_client_write(conn, CLIENTWRITE_BODY, line, 0);
  720. free(line);
  721. }
  722. }
  723. libssh2_sftp_closedir(sftp->sftp_handle);
  724. sftp->sftp_handle = NULL;
  725. /* no data to transfer */
  726. res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
  727. }
  728. else {
  729. /*
  730. * Work on getting the specified file
  731. */
  732. sftp->sftp_handle =
  733. libssh2_sftp_open(sftp->sftp_session, sftp->path, LIBSSH2_FXF_READ,
  734. LIBSSH2_SFTP_S_IRUSR|LIBSSH2_SFTP_S_IWUSR|
  735. LIBSSH2_SFTP_S_IRGRP|LIBSSH2_SFTP_S_IROTH);
  736. if (!sftp->sftp_handle)
  737. return CURLE_SSH;
  738. if (libssh2_sftp_stat(sftp->sftp_session, sftp->path, &attrs)) {
  739. /*
  740. * libssh2_sftp_open() didn't return an error, so maybe the server
  741. * just doesn't support stat()
  742. */
  743. data->reqdata.size = -1;
  744. data->reqdata.maxdownload = -1;
  745. }
  746. else {
  747. data->reqdata.size = attrs.filesize;
  748. data->reqdata.maxdownload = attrs.filesize;
  749. Curl_pgrsSetDownloadSize(data, attrs.filesize);
  750. }
  751. Curl_pgrsTime(data, TIMER_STARTTRANSFER);
  752. /* Now download data. The libssh2 0.14 doesn't offer any way to do this
  753. without using this BLOCKING approach, so here's room for improvement
  754. once libssh2 can return EWOULDBLOCK to us. */
  755. #if 0
  756. /* code left here just because this is what this function will use the
  757. day libssh2 is improved */
  758. res = Curl_setup_transfer(conn, FIRSTSOCKET,
  759. bytecount, FALSE, NULL, -1, NULL);
  760. #endif
  761. while (res == CURLE_OK) {
  762. size_t nread;
  763. /* NOTE: most *read() functions return ssize_t but this returns size_t
  764. which normally is unsigned! */
  765. nread = libssh2_sftp_read(data->reqdata.proto.ssh->sftp_handle,
  766. buf, BUFSIZE-1);
  767. if (nread > 0)
  768. buf[nread] = 0;
  769. /* this check can be changed to a <= 0 when nread is changed to a
  770. signed variable type */
  771. if ((nread == 0) || (nread == (size_t)~0))
  772. break;
  773. bytecount += nread;
  774. res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
  775. if(res)
  776. return res;
  777. Curl_pgrsSetDownloadCounter(data, bytecount);
  778. if(Curl_pgrsUpdate(conn))
  779. res = CURLE_ABORTED_BY_CALLBACK;
  780. else {
  781. struct timeval now = Curl_tvnow();
  782. res = Curl_speedcheck(data, now);
  783. }
  784. }
  785. if(Curl_pgrsUpdate(conn))
  786. res = CURLE_ABORTED_BY_CALLBACK;
  787. /* no (more) data to transfer */
  788. res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
  789. }
  790. }
  791. return res;
  792. }
  793. CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
  794. bool premature)
  795. {
  796. struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
  797. (void)premature; /* not used */
  798. Curl_safefree(sftp->path);
  799. sftp->path = NULL;
  800. Curl_safefree(sftp->homedir);
  801. sftp->homedir = NULL;
  802. if (sftp->sftp_handle) {
  803. if (libssh2_sftp_close(sftp->sftp_handle) < 0) {
  804. infof(conn->data, "Failed to close libssh2 file\n");
  805. }
  806. }
  807. if (sftp->sftp_session) {
  808. if (libssh2_sftp_shutdown(sftp->sftp_session) < 0) {
  809. infof(conn->data, "Failed to stop libssh2 sftp subsystem\n");
  810. }
  811. }
  812. if (sftp->ssh_channel) {
  813. if (libssh2_channel_close(sftp->ssh_channel) < 0) {
  814. infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
  815. }
  816. }
  817. if (sftp->ssh_session) {
  818. libssh2_session_disconnect(sftp->ssh_session, "Shutdown");
  819. libssh2_session_free(sftp->ssh_session);
  820. sftp->ssh_session = NULL;
  821. }
  822. free(conn->data->reqdata.proto.ssh);
  823. conn->data->reqdata.proto.ssh = NULL;
  824. Curl_pgrsDone(conn);
  825. (void)status; /* unused */
  826. return CURLE_OK;
  827. }
  828. /* return number of received (decrypted) bytes */
  829. ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
  830. void *mem, size_t len)
  831. {
  832. ssize_t nwrite;
  833. /* libssh2_sftp_write() returns size_t !*/
  834. nwrite = (ssize_t)
  835. libssh2_sftp_write(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
  836. (void)sockindex;
  837. return nwrite;
  838. }
  839. /*
  840. * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
  841. * a regular CURLcode value.
  842. */
  843. ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
  844. char *mem, size_t len)
  845. {
  846. ssize_t nread;
  847. /* libssh2_sftp_read() returns size_t !*/
  848. nread = (ssize_t)
  849. libssh2_sftp_read(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
  850. (void)sockindex;
  851. return nread;
  852. }
  853. #endif /* USE_LIBSSH2 */