PageRenderTime 426ms CodeModel.GetById 42ms RepoModel.GetById 11ms app.codeStats 0ms

/curl-7.28.0/lib/ssh.c

https://bitbucket.org/vlaznev/curl
C | 3306 lines | 2470 code | 404 blank | 432 comment | 541 complexity | f29f1861526b8cac41100067716edfc0 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, 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. ***************************************************************************/
  22. /* #define CURL_LIBSSH2_DEBUG */
  23. #include "setup.h"
  24. #ifdef USE_LIBSSH2
  25. #ifdef HAVE_LIMITS_H
  26. # include <limits.h>
  27. #endif
  28. #include <libssh2.h>
  29. #include <libssh2_sftp.h>
  30. #ifdef HAVE_UNISTD_H
  31. #include <unistd.h>
  32. #endif
  33. #ifdef HAVE_FCNTL_H
  34. #include <fcntl.h>
  35. #endif
  36. #ifdef HAVE_SYS_SOCKET_H
  37. #include <sys/socket.h>
  38. #endif
  39. #ifdef HAVE_NETINET_IN_H
  40. #include <netinet/in.h>
  41. #endif
  42. #ifdef HAVE_ARPA_INET_H
  43. #include <arpa/inet.h>
  44. #endif
  45. #ifdef HAVE_UTSNAME_H
  46. #include <sys/utsname.h>
  47. #endif
  48. #ifdef HAVE_NETDB_H
  49. #include <netdb.h>
  50. #endif
  51. #ifdef __VMS
  52. #include <in.h>
  53. #include <inet.h>
  54. #endif
  55. #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
  56. #undef in_addr_t
  57. #define in_addr_t unsigned long
  58. #endif
  59. #include <curl/curl.h>
  60. #include "urldata.h"
  61. #include "sendf.h"
  62. #include "hostip.h"
  63. #include "progress.h"
  64. #include "transfer.h"
  65. #include "escape.h"
  66. #include "http.h" /* for HTTP proxy tunnel stuff */
  67. #include "ssh.h"
  68. #include "url.h"
  69. #include "speedcheck.h"
  70. #include "getinfo.h"
  71. #include "strequal.h"
  72. #include "sslgen.h"
  73. #include "connect.h"
  74. #include "strerror.h"
  75. #include "inet_ntop.h"
  76. #include "parsedate.h" /* for the week day and month names */
  77. #include "sockaddr.h" /* required for Curl_sockaddr_storage */
  78. #include "strtoofft.h"
  79. #include "multiif.h"
  80. #include "select.h"
  81. #include "warnless.h"
  82. #define _MPRINTF_REPLACE /* use our functions only */
  83. #include <curl/mprintf.h>
  84. #include "curl_memory.h"
  85. /* The last #include file should be: */
  86. #include "memdebug.h"
  87. #ifdef WIN32
  88. # undef PATH_MAX
  89. # define PATH_MAX MAX_PATH
  90. #endif
  91. #ifndef PATH_MAX
  92. #define PATH_MAX 1024 /* just an extra precaution since there are systems that
  93. have their definition hidden well */
  94. #endif
  95. #define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s))
  96. #define sftp_libssh2_realpath(s,p,t,m) \
  97. libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
  98. (t), (m), LIBSSH2_SFTP_REALPATH)
  99. /* Local functions: */
  100. static const char *sftp_libssh2_strerror(int err);
  101. static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
  102. static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
  103. static LIBSSH2_FREE_FUNC(my_libssh2_free);
  104. static CURLcode get_pathname(const char **cpp, char **path);
  105. static CURLcode ssh_connect(struct connectdata *conn, bool *done);
  106. static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
  107. static CURLcode ssh_do(struct connectdata *conn, bool *done);
  108. static CURLcode ssh_getworkingpath(struct connectdata *conn,
  109. char *homedir, /* when SFTP is used */
  110. char **path);
  111. static CURLcode scp_done(struct connectdata *conn,
  112. CURLcode, bool premature);
  113. static CURLcode scp_doing(struct connectdata *conn,
  114. bool *dophase_done);
  115. static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
  116. static CURLcode sftp_done(struct connectdata *conn,
  117. CURLcode, bool premature);
  118. static CURLcode sftp_doing(struct connectdata *conn,
  119. bool *dophase_done);
  120. static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
  121. static
  122. CURLcode sftp_perform(struct connectdata *conn,
  123. bool *connected,
  124. bool *dophase_done);
  125. static int ssh_getsock(struct connectdata *conn,
  126. curl_socket_t *sock, /* points to numsocks number
  127. of sockets */
  128. int numsocks);
  129. static int ssh_perform_getsock(const struct connectdata *conn,
  130. curl_socket_t *sock, /* points to numsocks
  131. number of sockets */
  132. int numsocks);
  133. /*
  134. * SCP protocol handler.
  135. */
  136. const struct Curl_handler Curl_handler_scp = {
  137. "SCP", /* scheme */
  138. ZERO_NULL, /* setup_connection */
  139. ssh_do, /* do_it */
  140. scp_done, /* done */
  141. ZERO_NULL, /* do_more */
  142. ssh_connect, /* connect_it */
  143. ssh_multi_statemach, /* connecting */
  144. scp_doing, /* doing */
  145. ssh_getsock, /* proto_getsock */
  146. ssh_getsock, /* doing_getsock */
  147. ZERO_NULL, /* domore_getsock */
  148. ssh_perform_getsock, /* perform_getsock */
  149. scp_disconnect, /* disconnect */
  150. ZERO_NULL, /* readwrite */
  151. PORT_SSH, /* defport */
  152. CURLPROTO_SCP, /* protocol */
  153. PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
  154. | PROTOPT_NOURLQUERY /* flags */
  155. };
  156. /*
  157. * SFTP protocol handler.
  158. */
  159. const struct Curl_handler Curl_handler_sftp = {
  160. "SFTP", /* scheme */
  161. ZERO_NULL, /* setup_connection */
  162. ssh_do, /* do_it */
  163. sftp_done, /* done */
  164. ZERO_NULL, /* do_more */
  165. ssh_connect, /* connect_it */
  166. ssh_multi_statemach, /* connecting */
  167. sftp_doing, /* doing */
  168. ssh_getsock, /* proto_getsock */
  169. ssh_getsock, /* doing_getsock */
  170. ZERO_NULL, /* domore_getsock */
  171. ssh_perform_getsock, /* perform_getsock */
  172. sftp_disconnect, /* disconnect */
  173. ZERO_NULL, /* readwrite */
  174. PORT_SSH, /* defport */
  175. CURLPROTO_SFTP, /* protocol */
  176. PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
  177. | PROTOPT_NOURLQUERY /* flags */
  178. };
  179. static void
  180. kbd_callback(const char *name, int name_len, const char *instruction,
  181. int instruction_len, int num_prompts,
  182. const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
  183. LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
  184. void **abstract)
  185. {
  186. struct connectdata *conn = (struct connectdata *)*abstract;
  187. #ifdef CURL_LIBSSH2_DEBUG
  188. fprintf(stderr, "name=%s\n", name);
  189. fprintf(stderr, "name_len=%d\n", name_len);
  190. fprintf(stderr, "instruction=%s\n", instruction);
  191. fprintf(stderr, "instruction_len=%d\n", instruction_len);
  192. fprintf(stderr, "num_prompts=%d\n", num_prompts);
  193. #else
  194. (void)name;
  195. (void)name_len;
  196. (void)instruction;
  197. (void)instruction_len;
  198. #endif /* CURL_LIBSSH2_DEBUG */
  199. if(num_prompts == 1) {
  200. responses[0].text = strdup(conn->passwd);
  201. responses[0].length = curlx_uztoui(strlen(conn->passwd));
  202. }
  203. (void)prompts;
  204. (void)abstract;
  205. } /* kbd_callback */
  206. static CURLcode sftp_libssh2_error_to_CURLE(int err)
  207. {
  208. switch (err) {
  209. case LIBSSH2_FX_OK:
  210. return CURLE_OK;
  211. case LIBSSH2_FX_NO_SUCH_FILE:
  212. case LIBSSH2_FX_NO_SUCH_PATH:
  213. return CURLE_REMOTE_FILE_NOT_FOUND;
  214. case LIBSSH2_FX_PERMISSION_DENIED:
  215. case LIBSSH2_FX_WRITE_PROTECT:
  216. case LIBSSH2_FX_LOCK_CONFlICT:
  217. return CURLE_REMOTE_ACCESS_DENIED;
  218. case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
  219. case LIBSSH2_FX_QUOTA_EXCEEDED:
  220. return CURLE_REMOTE_DISK_FULL;
  221. case LIBSSH2_FX_FILE_ALREADY_EXISTS:
  222. return CURLE_REMOTE_FILE_EXISTS;
  223. case LIBSSH2_FX_DIR_NOT_EMPTY:
  224. return CURLE_QUOTE_ERROR;
  225. default:
  226. break;
  227. }
  228. return CURLE_SSH;
  229. }
  230. static CURLcode libssh2_session_error_to_CURLE(int err)
  231. {
  232. switch (err) {
  233. /* Ordered by order of appearance in libssh2.h */
  234. case LIBSSH2_ERROR_NONE:
  235. return CURLE_OK;
  236. case LIBSSH2_ERROR_SOCKET_NONE:
  237. return CURLE_COULDNT_CONNECT;
  238. case LIBSSH2_ERROR_ALLOC:
  239. return CURLE_OUT_OF_MEMORY;
  240. case LIBSSH2_ERROR_SOCKET_SEND:
  241. return CURLE_SEND_ERROR;
  242. case LIBSSH2_ERROR_HOSTKEY_INIT:
  243. case LIBSSH2_ERROR_HOSTKEY_SIGN:
  244. case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
  245. case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
  246. return CURLE_PEER_FAILED_VERIFICATION;
  247. case LIBSSH2_ERROR_PASSWORD_EXPIRED:
  248. return CURLE_LOGIN_DENIED;
  249. case LIBSSH2_ERROR_SOCKET_TIMEOUT:
  250. case LIBSSH2_ERROR_TIMEOUT:
  251. return CURLE_OPERATION_TIMEDOUT;
  252. case LIBSSH2_ERROR_EAGAIN:
  253. return CURLE_AGAIN;
  254. }
  255. /* TODO: map some more of the libssh2 errors to the more appropriate CURLcode
  256. error code, and possibly add a few new SSH-related one. We must however
  257. not return or even depend on libssh2 errors in the public libcurl API */
  258. return CURLE_SSH;
  259. }
  260. static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
  261. {
  262. (void)abstract; /* arg not used */
  263. return malloc(count);
  264. }
  265. static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
  266. {
  267. (void)abstract; /* arg not used */
  268. return realloc(ptr, count);
  269. }
  270. static LIBSSH2_FREE_FUNC(my_libssh2_free)
  271. {
  272. (void)abstract; /* arg not used */
  273. if(ptr) /* ssh2 agent sometimes call free with null ptr */
  274. free(ptr);
  275. }
  276. /*
  277. * SSH State machine related code
  278. */
  279. /* This is the ONLY way to change SSH state! */
  280. static void state(struct connectdata *conn, sshstate nowstate)
  281. {
  282. #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  283. /* for debug purposes */
  284. static const char * const names[] = {
  285. "SSH_STOP",
  286. "SSH_INIT",
  287. "SSH_S_STARTUP",
  288. "SSH_HOSTKEY",
  289. "SSH_AUTHLIST",
  290. "SSH_AUTH_PKEY_INIT",
  291. "SSH_AUTH_PKEY",
  292. "SSH_AUTH_PASS_INIT",
  293. "SSH_AUTH_PASS",
  294. "SSH_AUTH_AGENT_INIT",
  295. "SSH_AUTH_AGENT_LIST",
  296. "SSH_AUTH_AGENT",
  297. "SSH_AUTH_HOST_INIT",
  298. "SSH_AUTH_HOST",
  299. "SSH_AUTH_KEY_INIT",
  300. "SSH_AUTH_KEY",
  301. "SSH_AUTH_DONE",
  302. "SSH_SFTP_INIT",
  303. "SSH_SFTP_REALPATH",
  304. "SSH_SFTP_QUOTE_INIT",
  305. "SSH_SFTP_POSTQUOTE_INIT",
  306. "SSH_SFTP_QUOTE",
  307. "SSH_SFTP_NEXT_QUOTE",
  308. "SSH_SFTP_QUOTE_STAT",
  309. "SSH_SFTP_QUOTE_SETSTAT",
  310. "SSH_SFTP_QUOTE_SYMLINK",
  311. "SSH_SFTP_QUOTE_MKDIR",
  312. "SSH_SFTP_QUOTE_RENAME",
  313. "SSH_SFTP_QUOTE_RMDIR",
  314. "SSH_SFTP_QUOTE_UNLINK",
  315. "SSH_SFTP_TRANS_INIT",
  316. "SSH_SFTP_UPLOAD_INIT",
  317. "SSH_SFTP_CREATE_DIRS_INIT",
  318. "SSH_SFTP_CREATE_DIRS",
  319. "SSH_SFTP_CREATE_DIRS_MKDIR",
  320. "SSH_SFTP_READDIR_INIT",
  321. "SSH_SFTP_READDIR",
  322. "SSH_SFTP_READDIR_LINK",
  323. "SSH_SFTP_READDIR_BOTTOM",
  324. "SSH_SFTP_READDIR_DONE",
  325. "SSH_SFTP_DOWNLOAD_INIT",
  326. "SSH_SFTP_DOWNLOAD_STAT",
  327. "SSH_SFTP_CLOSE",
  328. "SSH_SFTP_SHUTDOWN",
  329. "SSH_SCP_TRANS_INIT",
  330. "SSH_SCP_UPLOAD_INIT",
  331. "SSH_SCP_DOWNLOAD_INIT",
  332. "SSH_SCP_DONE",
  333. "SSH_SCP_SEND_EOF",
  334. "SSH_SCP_WAIT_EOF",
  335. "SSH_SCP_WAIT_CLOSE",
  336. "SSH_SCP_CHANNEL_FREE",
  337. "SSH_SESSION_DISCONNECT",
  338. "SSH_SESSION_FREE",
  339. "QUIT"
  340. };
  341. #endif
  342. struct ssh_conn *sshc = &conn->proto.sshc;
  343. #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  344. if(sshc->state != nowstate) {
  345. infof(conn->data, "SFTP %p state change from %s to %s\n",
  346. sshc, names[sshc->state], names[nowstate]);
  347. }
  348. #endif
  349. sshc->state = nowstate;
  350. }
  351. /* figure out the path to work with in this particular request */
  352. static CURLcode ssh_getworkingpath(struct connectdata *conn,
  353. char *homedir, /* when SFTP is used */
  354. char **path) /* returns the allocated
  355. real path to work with */
  356. {
  357. struct SessionHandle *data = conn->data;
  358. char *real_path = NULL;
  359. char *working_path;
  360. int working_path_len;
  361. working_path = curl_easy_unescape(data, data->state.path, 0,
  362. &working_path_len);
  363. if(!working_path)
  364. return CURLE_OUT_OF_MEMORY;
  365. /* Check for /~/ , indicating relative to the user's home directory */
  366. if(conn->handler->protocol & CURLPROTO_SCP) {
  367. real_path = malloc(working_path_len+1);
  368. if(real_path == NULL) {
  369. free(working_path);
  370. return CURLE_OUT_OF_MEMORY;
  371. }
  372. if((working_path_len > 1) && (working_path[1] == '~'))
  373. /* It is referenced to the home directory, so strip the leading '/' */
  374. memcpy(real_path, working_path+1, 1 + working_path_len-1);
  375. else
  376. memcpy(real_path, working_path, 1 + working_path_len);
  377. }
  378. else if(conn->handler->protocol & CURLPROTO_SFTP) {
  379. if((working_path_len > 1) && (working_path[1] == '~')) {
  380. size_t homelen = strlen(homedir);
  381. real_path = malloc(homelen + working_path_len + 1);
  382. if(real_path == NULL) {
  383. free(working_path);
  384. return CURLE_OUT_OF_MEMORY;
  385. }
  386. /* It is referenced to the home directory, so strip the
  387. leading '/' */
  388. memcpy(real_path, homedir, homelen);
  389. real_path[homelen] = '/';
  390. real_path[homelen+1] = '\0';
  391. if(working_path_len > 3) {
  392. memcpy(real_path+homelen+1, working_path + 3,
  393. 1 + working_path_len -3);
  394. }
  395. }
  396. else {
  397. real_path = malloc(working_path_len+1);
  398. if(real_path == NULL) {
  399. free(working_path);
  400. return CURLE_OUT_OF_MEMORY;
  401. }
  402. memcpy(real_path, working_path, 1+working_path_len);
  403. }
  404. }
  405. free(working_path);
  406. /* store the pointer for the caller to receive */
  407. *path = real_path;
  408. return CURLE_OK;
  409. }
  410. #ifdef HAVE_LIBSSH2_KNOWNHOST_API
  411. static int sshkeycallback(CURL *easy,
  412. const struct curl_khkey *knownkey, /* known */
  413. const struct curl_khkey *foundkey, /* found */
  414. enum curl_khmatch match,
  415. void *clientp)
  416. {
  417. (void)easy;
  418. (void)knownkey;
  419. (void)foundkey;
  420. (void)clientp;
  421. /* we only allow perfect matches, and we reject everything else */
  422. return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE;
  423. }
  424. #endif
  425. /*
  426. * Earlier libssh2 versions didn't have the ability to seek to 64bit positions
  427. * with 32bit size_t.
  428. */
  429. #ifdef HAVE_LIBSSH2_SFTP_SEEK64
  430. #define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
  431. #else
  432. #define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
  433. #endif
  434. /*
  435. * Earlier libssh2 versions didn't do SCP properly beyond 32bit sizes on 32bit
  436. * architectures so we check of the necessary function is present.
  437. */
  438. #ifndef HAVE_LIBSSH2_SCP_SEND64
  439. #define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
  440. #else
  441. #define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \
  442. (libssh2_uint64_t)d, 0, 0)
  443. #endif
  444. /*
  445. * libssh2 1.2.8 fixed the problem with 32bit ints used for sockets on win64.
  446. */
  447. #ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
  448. #define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
  449. #endif
  450. static CURLcode ssh_knownhost(struct connectdata *conn)
  451. {
  452. CURLcode result = CURLE_OK;
  453. #ifdef HAVE_LIBSSH2_KNOWNHOST_API
  454. struct SessionHandle *data = conn->data;
  455. if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
  456. /* we're asked to verify the host against a file */
  457. struct ssh_conn *sshc = &conn->proto.sshc;
  458. int rc;
  459. int keytype;
  460. size_t keylen;
  461. const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
  462. &keylen, &keytype);
  463. int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
  464. int keybit = 0;
  465. if(remotekey) {
  466. /*
  467. * A subject to figure out is what host name we need to pass in here.
  468. * What host name does OpenSSH store in its file if an IDN name is
  469. * used?
  470. */
  471. struct libssh2_knownhost *host;
  472. enum curl_khmatch keymatch;
  473. curl_sshkeycallback func =
  474. data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
  475. struct curl_khkey knownkey;
  476. struct curl_khkey *knownkeyp = NULL;
  477. struct curl_khkey foundkey;
  478. keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
  479. LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS;
  480. keycheck = libssh2_knownhost_check(sshc->kh,
  481. conn->host.name,
  482. remotekey, keylen,
  483. LIBSSH2_KNOWNHOST_TYPE_PLAIN|
  484. LIBSSH2_KNOWNHOST_KEYENC_RAW|
  485. keybit,
  486. &host);
  487. infof(data, "SSH host check: %d, key: %s\n", keycheck,
  488. (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
  489. host->key:"<none>");
  490. /* setup 'knownkey' */
  491. if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
  492. knownkey.key = host->key;
  493. knownkey.len = 0;
  494. knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
  495. CURLKHTYPE_RSA : CURLKHTYPE_DSS;
  496. knownkeyp = &knownkey;
  497. }
  498. /* setup 'foundkey' */
  499. foundkey.key = remotekey;
  500. foundkey.len = keylen;
  501. foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
  502. CURLKHTYPE_RSA : CURLKHTYPE_DSS;
  503. /*
  504. * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
  505. * curl_khmatch enum are ever modified, we need to introduce a
  506. * translation table here!
  507. */
  508. keymatch = (enum curl_khmatch)keycheck;
  509. /* Ask the callback how to behave */
  510. rc = func(data, knownkeyp, /* from the knownhosts file */
  511. &foundkey, /* from the remote host */
  512. keymatch, data->set.ssh_keyfunc_userp);
  513. }
  514. else
  515. /* no remotekey means failure! */
  516. rc = CURLKHSTAT_REJECT;
  517. switch(rc) {
  518. default: /* unknown return codes will equal reject */
  519. case CURLKHSTAT_REJECT:
  520. state(conn, SSH_SESSION_FREE);
  521. case CURLKHSTAT_DEFER:
  522. /* DEFER means bail out but keep the SSH_HOSTKEY state */
  523. result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
  524. break;
  525. case CURLKHSTAT_FINE:
  526. case CURLKHSTAT_FINE_ADD_TO_FILE:
  527. /* proceed */
  528. if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
  529. /* the found host+key didn't match but has been told to be fine
  530. anyway so we add it in memory */
  531. int addrc = libssh2_knownhost_add(sshc->kh,
  532. conn->host.name, NULL,
  533. remotekey, keylen,
  534. LIBSSH2_KNOWNHOST_TYPE_PLAIN|
  535. LIBSSH2_KNOWNHOST_KEYENC_RAW|
  536. keybit, NULL);
  537. if(addrc)
  538. infof(data, "Warning adding the known host %s failed!\n",
  539. conn->host.name);
  540. else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
  541. /* now we write the entire in-memory list of known hosts to the
  542. known_hosts file */
  543. int wrc =
  544. libssh2_knownhost_writefile(sshc->kh,
  545. data->set.str[STRING_SSH_KNOWNHOSTS],
  546. LIBSSH2_KNOWNHOST_FILE_OPENSSH);
  547. if(wrc) {
  548. infof(data, "Warning, writing %s failed!\n",
  549. data->set.str[STRING_SSH_KNOWNHOSTS]);
  550. }
  551. }
  552. }
  553. break;
  554. }
  555. }
  556. #else /* HAVE_LIBSSH2_KNOWNHOST_API */
  557. (void)conn;
  558. #endif
  559. return result;
  560. }
  561. static CURLcode ssh_check_fingerprint(struct connectdata *conn)
  562. {
  563. struct ssh_conn *sshc = &conn->proto.sshc;
  564. struct SessionHandle *data = conn->data;
  565. const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
  566. char md5buffer[33];
  567. int i;
  568. const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
  569. LIBSSH2_HOSTKEY_HASH_MD5);
  570. if(fingerprint) {
  571. /* The fingerprint points to static storage (!), don't free() it. */
  572. for(i = 0; i < 16; i++)
  573. snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
  574. infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
  575. }
  576. /* Before we authenticate we check the hostkey's MD5 fingerprint
  577. * against a known fingerprint, if available.
  578. */
  579. if(pubkey_md5 && strlen(pubkey_md5) == 32) {
  580. if(!fingerprint || !strequal(md5buffer, pubkey_md5)) {
  581. if(fingerprint)
  582. failf(data,
  583. "Denied establishing ssh session: mismatch md5 fingerprint. "
  584. "Remote %s is not equal to %s", md5buffer, pubkey_md5);
  585. else
  586. failf(data,
  587. "Denied establishing ssh session: md5 fingerprint not available");
  588. state(conn, SSH_SESSION_FREE);
  589. sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
  590. return sshc->actualcode;
  591. }
  592. else {
  593. infof(data, "MD5 checksum match!\n");
  594. /* as we already matched, we skip the check for known hosts */
  595. return CURLE_OK;
  596. }
  597. }
  598. else
  599. return ssh_knownhost(conn);
  600. }
  601. /*
  602. * ssh_statemach_act() runs the SSH state machine as far as it can without
  603. * blocking and without reaching the end. The data the pointer 'block' points
  604. * to will be set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
  605. * meaning it wants to be called again when the socket is ready
  606. */
  607. static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
  608. {
  609. CURLcode result = CURLE_OK;
  610. struct SessionHandle *data = conn->data;
  611. struct SSHPROTO *sftp_scp = data->state.proto.ssh;
  612. struct ssh_conn *sshc = &conn->proto.sshc;
  613. curl_socket_t sock = conn->sock[FIRSTSOCKET];
  614. char *new_readdir_line;
  615. int rc = LIBSSH2_ERROR_NONE;
  616. int err;
  617. int seekerr = CURL_SEEKFUNC_OK;
  618. *block = 0; /* we're not blocking by default */
  619. do {
  620. switch(sshc->state) {
  621. case SSH_INIT:
  622. sshc->secondCreateDirs = 0;
  623. sshc->nextstate = SSH_NO_STATE;
  624. sshc->actualcode = CURLE_OK;
  625. /* Set libssh2 to non-blocking, since everything internally is
  626. non-blocking */
  627. libssh2_session_set_blocking(sshc->ssh_session, 0);
  628. state(conn, SSH_S_STARTUP);
  629. /* fall-through */
  630. case SSH_S_STARTUP:
  631. rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
  632. if(rc == LIBSSH2_ERROR_EAGAIN) {
  633. break;
  634. }
  635. else if(rc) {
  636. failf(data, "Failure establishing ssh session");
  637. state(conn, SSH_SESSION_FREE);
  638. sshc->actualcode = CURLE_FAILED_INIT;
  639. break;
  640. }
  641. state(conn, SSH_HOSTKEY);
  642. /* fall-through */
  643. case SSH_HOSTKEY:
  644. /*
  645. * Before we authenticate we should check the hostkey's fingerprint
  646. * against our known hosts. How that is handled (reading from file,
  647. * whatever) is up to us.
  648. */
  649. result = ssh_check_fingerprint(conn);
  650. if(result == CURLE_OK)
  651. state(conn, SSH_AUTHLIST);
  652. break;
  653. case SSH_AUTHLIST:
  654. /*
  655. * Figure out authentication methods
  656. * NB: As soon as we have provided a username to an openssh server we
  657. * must never change it later. Thus, always specify the correct username
  658. * here, even though the libssh2 docs kind of indicate that it should be
  659. * possible to get a 'generic' list (not user-specific) of authentication
  660. * methods, presumably with a blank username. That won't work in my
  661. * experience.
  662. * So always specify it here.
  663. */
  664. sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
  665. conn->user,
  666. curlx_uztoui(strlen(conn->user)));
  667. if(!sshc->authlist) {
  668. if((err = libssh2_session_last_errno(sshc->ssh_session)) ==
  669. LIBSSH2_ERROR_EAGAIN) {
  670. rc = LIBSSH2_ERROR_EAGAIN;
  671. break;
  672. }
  673. else {
  674. state(conn, SSH_SESSION_FREE);
  675. sshc->actualcode = libssh2_session_error_to_CURLE(err);
  676. break;
  677. }
  678. }
  679. infof(data, "SSH authentication methods available: %s\n",
  680. sshc->authlist);
  681. state(conn, SSH_AUTH_PKEY_INIT);
  682. break;
  683. case SSH_AUTH_PKEY_INIT:
  684. /*
  685. * Check the supported auth types in the order I feel is most secure
  686. * with the requested type of authentication
  687. */
  688. sshc->authed = FALSE;
  689. if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
  690. (strstr(sshc->authlist, "publickey") != NULL)) {
  691. char *home = NULL;
  692. bool rsa_pub_empty_but_ok = FALSE;
  693. sshc->rsa_pub = sshc->rsa = NULL;
  694. /* To ponder about: should really the lib be messing about with the
  695. HOME environment variable etc? */
  696. home = curl_getenv("HOME");
  697. if(data->set.str[STRING_SSH_PUBLIC_KEY] &&
  698. !*data->set.str[STRING_SSH_PUBLIC_KEY])
  699. rsa_pub_empty_but_ok = true;
  700. else if(data->set.str[STRING_SSH_PUBLIC_KEY])
  701. sshc->rsa_pub = aprintf("%s", data->set.str[STRING_SSH_PUBLIC_KEY]);
  702. else if(home)
  703. sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home);
  704. else
  705. /* as a final resort, try current dir! */
  706. sshc->rsa_pub = strdup("id_dsa.pub");
  707. if(!rsa_pub_empty_but_ok && (sshc->rsa_pub == NULL)) {
  708. Curl_safefree(home);
  709. state(conn, SSH_SESSION_FREE);
  710. sshc->actualcode = CURLE_OUT_OF_MEMORY;
  711. break;
  712. }
  713. if(data->set.str[STRING_SSH_PRIVATE_KEY])
  714. sshc->rsa = aprintf("%s", data->set.str[STRING_SSH_PRIVATE_KEY]);
  715. else if(home)
  716. sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
  717. else
  718. /* as a final resort, try current dir! */
  719. sshc->rsa = strdup("id_dsa");
  720. if(sshc->rsa == NULL) {
  721. Curl_safefree(home);
  722. Curl_safefree(sshc->rsa_pub);
  723. state(conn, SSH_SESSION_FREE);
  724. sshc->actualcode = CURLE_OUT_OF_MEMORY;
  725. break;
  726. }
  727. sshc->passphrase = data->set.str[STRING_KEY_PASSWD];
  728. if(!sshc->passphrase)
  729. sshc->passphrase = "";
  730. Curl_safefree(home);
  731. infof(data, "Using ssh public key file %s\n", sshc->rsa_pub);
  732. infof(data, "Using ssh private key file %s\n", sshc->rsa);
  733. state(conn, SSH_AUTH_PKEY);
  734. }
  735. else {
  736. state(conn, SSH_AUTH_PASS_INIT);
  737. }
  738. break;
  739. case SSH_AUTH_PKEY:
  740. /* The function below checks if the files exists, no need to stat() here.
  741. */
  742. rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
  743. conn->user,
  744. curlx_uztoui(
  745. strlen(conn->user)),
  746. sshc->rsa_pub,
  747. sshc->rsa, sshc->passphrase);
  748. if(rc == LIBSSH2_ERROR_EAGAIN) {
  749. break;
  750. }
  751. Curl_safefree(sshc->rsa_pub);
  752. Curl_safefree(sshc->rsa);
  753. if(rc == 0) {
  754. sshc->authed = TRUE;
  755. infof(data, "Initialized SSH public key authentication\n");
  756. state(conn, SSH_AUTH_DONE);
  757. }
  758. else {
  759. char *err_msg;
  760. (void)libssh2_session_last_error(sshc->ssh_session,
  761. &err_msg, NULL, 0);
  762. infof(data, "SSH public key authentication failed: %s\n", err_msg);
  763. state(conn, SSH_AUTH_PASS_INIT);
  764. }
  765. break;
  766. case SSH_AUTH_PASS_INIT:
  767. if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
  768. (strstr(sshc->authlist, "password") != NULL)) {
  769. state(conn, SSH_AUTH_PASS);
  770. }
  771. else {
  772. state(conn, SSH_AUTH_HOST_INIT);
  773. }
  774. break;
  775. case SSH_AUTH_PASS:
  776. rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
  777. curlx_uztoui(strlen(conn->user)),
  778. conn->passwd,
  779. curlx_uztoui(strlen(conn->passwd)),
  780. NULL);
  781. if(rc == LIBSSH2_ERROR_EAGAIN) {
  782. break;
  783. }
  784. else if(rc == 0) {
  785. sshc->authed = TRUE;
  786. infof(data, "Initialized password authentication\n");
  787. state(conn, SSH_AUTH_DONE);
  788. }
  789. else {
  790. state(conn, SSH_AUTH_HOST_INIT);
  791. }
  792. break;
  793. case SSH_AUTH_HOST_INIT:
  794. if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
  795. (strstr(sshc->authlist, "hostbased") != NULL)) {
  796. state(conn, SSH_AUTH_HOST);
  797. }
  798. else {
  799. state(conn, SSH_AUTH_AGENT_INIT);
  800. }
  801. break;
  802. case SSH_AUTH_HOST:
  803. state(conn, SSH_AUTH_AGENT_INIT);
  804. break;
  805. case SSH_AUTH_AGENT_INIT:
  806. #ifdef HAVE_LIBSSH2_AGENT_API
  807. if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
  808. && (strstr(sshc->authlist, "publickey") != NULL)) {
  809. /* Connect to the ssh-agent */
  810. /* The agent could be shared by a curl thread i believe
  811. but nothing obvious as keys can be added/removed at any time */
  812. if(!sshc->ssh_agent) {
  813. sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
  814. if(!sshc->ssh_agent) {
  815. infof(data, "Could not create agent object\n");
  816. state(conn, SSH_AUTH_KEY_INIT);
  817. }
  818. }
  819. rc = libssh2_agent_connect(sshc->ssh_agent);
  820. if(rc == LIBSSH2_ERROR_EAGAIN)
  821. break;
  822. if(rc < 0) {
  823. infof(data, "Failure connecting to agent\n");
  824. state(conn, SSH_AUTH_KEY_INIT);
  825. }
  826. else {
  827. state(conn, SSH_AUTH_AGENT_LIST);
  828. }
  829. }
  830. else
  831. #endif /* HAVE_LIBSSH2_AGENT_API */
  832. state(conn, SSH_AUTH_KEY_INIT);
  833. break;
  834. case SSH_AUTH_AGENT_LIST:
  835. #ifdef HAVE_LIBSSH2_AGENT_API
  836. rc = libssh2_agent_list_identities(sshc->ssh_agent);
  837. if(rc == LIBSSH2_ERROR_EAGAIN)
  838. break;
  839. if(rc < 0) {
  840. infof(data, "Failure requesting identities to agent\n");
  841. state(conn, SSH_AUTH_KEY_INIT);
  842. }
  843. else {
  844. state(conn, SSH_AUTH_AGENT);
  845. sshc->sshagent_prev_identity = NULL;
  846. }
  847. #endif
  848. break;
  849. case SSH_AUTH_AGENT:
  850. #ifdef HAVE_LIBSSH2_AGENT_API
  851. /* as prev_identity evolves only after an identity user auth finished we
  852. can safely request it again as long as EAGAIN is returned here or by
  853. libssh2_agent_userauth */
  854. rc = libssh2_agent_get_identity(sshc->ssh_agent,
  855. &sshc->sshagent_identity,
  856. sshc->sshagent_prev_identity);
  857. if(rc == LIBSSH2_ERROR_EAGAIN)
  858. break;
  859. if(rc == 0) {
  860. rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
  861. sshc->sshagent_identity);
  862. if(rc < 0) {
  863. if(rc != LIBSSH2_ERROR_EAGAIN) {
  864. /* tried and failed? go to next identity */
  865. sshc->sshagent_prev_identity = sshc->sshagent_identity;
  866. }
  867. break;
  868. }
  869. }
  870. if(rc < 0)
  871. infof(data, "Failure requesting identities to agent\n");
  872. else if(rc == 1)
  873. infof(data, "No identity would match\n");
  874. if(rc == LIBSSH2_ERROR_NONE) {
  875. sshc->authed = TRUE;
  876. infof(data, "Agent based authentication successful\n");
  877. state(conn, SSH_AUTH_DONE);
  878. }
  879. else
  880. state(conn, SSH_AUTH_KEY_INIT);
  881. #endif
  882. break;
  883. case SSH_AUTH_KEY_INIT:
  884. if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
  885. && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
  886. state(conn, SSH_AUTH_KEY);
  887. }
  888. else {
  889. state(conn, SSH_AUTH_DONE);
  890. }
  891. break;
  892. case SSH_AUTH_KEY:
  893. /* Authentication failed. Continue with keyboard-interactive now. */
  894. rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
  895. conn->user,
  896. curlx_uztoui(
  897. strlen(conn->user)),
  898. &kbd_callback);
  899. if(rc == LIBSSH2_ERROR_EAGAIN) {
  900. break;
  901. }
  902. else if(rc == 0) {
  903. sshc->authed = TRUE;
  904. infof(data, "Initialized keyboard interactive authentication\n");
  905. }
  906. state(conn, SSH_AUTH_DONE);
  907. break;
  908. case SSH_AUTH_DONE:
  909. if(!sshc->authed) {
  910. failf(data, "Authentication failure");
  911. state(conn, SSH_SESSION_FREE);
  912. sshc->actualcode = CURLE_LOGIN_DENIED;
  913. break;
  914. }
  915. /*
  916. * At this point we have an authenticated ssh session.
  917. */
  918. infof(data, "Authentication complete\n");
  919. Curl_pgrsTime(conn->data, TIMER_APPCONNECT); /* SSH is connected */
  920. conn->sockfd = sock;
  921. conn->writesockfd = CURL_SOCKET_BAD;
  922. if(conn->handler->protocol == CURLPROTO_SFTP) {
  923. state(conn, SSH_SFTP_INIT);
  924. break;
  925. }
  926. infof(data, "SSH CONNECT phase done\n");
  927. state(conn, SSH_STOP);
  928. break;
  929. case SSH_SFTP_INIT:
  930. /*
  931. * Start the libssh2 sftp session
  932. */
  933. sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
  934. if(!sshc->sftp_session) {
  935. if(libssh2_session_last_errno(sshc->ssh_session) ==
  936. LIBSSH2_ERROR_EAGAIN) {
  937. rc = LIBSSH2_ERROR_EAGAIN;
  938. break;
  939. }
  940. else {
  941. char *err_msg;
  942. (void)libssh2_session_last_error(sshc->ssh_session,
  943. &err_msg, NULL, 0);
  944. failf(data, "Failure initializing sftp session: %s", err_msg);
  945. state(conn, SSH_SESSION_FREE);
  946. sshc->actualcode = CURLE_FAILED_INIT;
  947. break;
  948. }
  949. }
  950. state(conn, SSH_SFTP_REALPATH);
  951. break;
  952. case SSH_SFTP_REALPATH:
  953. {
  954. char tempHome[PATH_MAX];
  955. /*
  956. * Get the "home" directory
  957. */
  958. rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
  959. tempHome, PATH_MAX-1);
  960. if(rc == LIBSSH2_ERROR_EAGAIN) {
  961. break;
  962. }
  963. else if(rc > 0) {
  964. /* It seems that this string is not always NULL terminated */
  965. tempHome[rc] = '\0';
  966. sshc->homedir = strdup(tempHome);
  967. if(!sshc->homedir) {
  968. state(conn, SSH_SFTP_CLOSE);
  969. sshc->actualcode = CURLE_OUT_OF_MEMORY;
  970. break;
  971. }
  972. conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
  973. }
  974. else {
  975. /* Return the error type */
  976. err = sftp_libssh2_last_error(sshc->sftp_session);
  977. result = sftp_libssh2_error_to_CURLE(err);
  978. sshc->actualcode = result?result:CURLE_SSH;
  979. DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
  980. err, (int)result));
  981. state(conn, SSH_STOP);
  982. break;
  983. }
  984. }
  985. /* This is the last step in the SFTP connect phase. Do note that while
  986. we get the homedir here, we get the "workingpath" in the DO action
  987. since the homedir will remain the same between request but the
  988. working path will not. */
  989. DEBUGF(infof(data, "SSH CONNECT phase done\n"));
  990. state(conn, SSH_STOP);
  991. break;
  992. case SSH_SFTP_QUOTE_INIT:
  993. result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
  994. if(result) {
  995. sshc->actualcode = result;
  996. state(conn, SSH_STOP);
  997. break;
  998. }
  999. if(data->set.quote) {
  1000. infof(data, "Sending quote commands\n");
  1001. sshc->quote_item = data->set.quote;
  1002. state(conn, SSH_SFTP_QUOTE);
  1003. }
  1004. else {
  1005. state(conn, SSH_SFTP_TRANS_INIT);
  1006. }
  1007. break;
  1008. case SSH_SFTP_POSTQUOTE_INIT:
  1009. if(data->set.postquote) {
  1010. infof(data, "Sending quote commands\n");
  1011. sshc->quote_item = data->set.postquote;
  1012. state(conn, SSH_SFTP_QUOTE);
  1013. }
  1014. else {
  1015. state(conn, SSH_STOP);
  1016. }
  1017. break;
  1018. case SSH_SFTP_QUOTE:
  1019. /* Send any quote commands */
  1020. {
  1021. const char *cp;
  1022. /*
  1023. * Support some of the "FTP" commands
  1024. */
  1025. char *cmd = sshc->quote_item->data;
  1026. sshc->acceptfail = FALSE;
  1027. /* if a command starts with an asterisk, which a legal SFTP command never
  1028. can, the command will be allowed to fail without it causing any
  1029. aborts or cancels etc. It will cause libcurl to act as if the command
  1030. is successful, whatever the server reponds. */
  1031. if(cmd[0] == '*') {
  1032. cmd++;
  1033. sshc->acceptfail = TRUE;
  1034. }
  1035. if(curl_strequal("pwd", cmd)) {
  1036. /* output debug output if that is requested */
  1037. char *tmp = aprintf("257 \"%s\" is current directory.\n",
  1038. sftp_scp->path);
  1039. if(!tmp) {
  1040. result = CURLE_OUT_OF_MEMORY;
  1041. state(conn, SSH_SFTP_CLOSE);
  1042. sshc->nextstate = SSH_NO_STATE;
  1043. break;
  1044. }
  1045. if(data->set.verbose) {
  1046. Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
  1047. Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
  1048. }
  1049. /* this sends an FTP-like "header" to the header callback so that the
  1050. current directory can be read very similar to how it is read when
  1051. using ordinary FTP. */
  1052. result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
  1053. free(tmp);
  1054. state(conn, SSH_SFTP_NEXT_QUOTE);
  1055. break;
  1056. }
  1057. else if(cmd) {
  1058. /*
  1059. * the arguments following the command must be separated from the
  1060. * command with a space so we can check for it unconditionally
  1061. */
  1062. cp = strchr(cmd, ' ');
  1063. if(cp == NULL) {
  1064. failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
  1065. state(conn, SSH_SFTP_CLOSE);
  1066. sshc->nextstate = SSH_NO_STATE;
  1067. sshc->actualcode = CURLE_QUOTE_ERROR;
  1068. break;
  1069. }
  1070. /*
  1071. * also, every command takes at least one argument so we get that
  1072. * first argument right now
  1073. */
  1074. result = get_pathname(&cp, &sshc->quote_path1);
  1075. if(result) {
  1076. if(result == CURLE_OUT_OF_MEMORY)
  1077. failf(data, "Out of memory");
  1078. else
  1079. failf(data, "Syntax error: Bad first parameter");
  1080. state(conn, SSH_SFTP_CLOSE);
  1081. sshc->nextstate = SSH_NO_STATE;
  1082. sshc->actualcode = result;
  1083. break;
  1084. }
  1085. /*
  1086. * SFTP is a binary protocol, so we don't send text commands to
  1087. * the server. Instead, we scan for commands for commands used by
  1088. * OpenSSH's sftp program and call the appropriate libssh2
  1089. * functions.
  1090. */
  1091. if(curl_strnequal(cmd, "chgrp ", 6) ||
  1092. curl_strnequal(cmd, "chmod ", 6) ||
  1093. curl_strnequal(cmd, "chown ", 6) ) {
  1094. /* attribute change */
  1095. /* sshc->quote_path1 contains the mode to set */
  1096. /* get the destination */
  1097. result = get_pathname(&cp, &sshc->quote_path2);
  1098. if(result) {
  1099. if(result == CURLE_OUT_OF_MEMORY)
  1100. failf(data, "Out of memory");
  1101. else
  1102. failf(data, "Syntax error in chgrp/chmod/chown: "
  1103. "Bad second parameter");
  1104. Curl_safefree(sshc->quote_path1);
  1105. state(conn, SSH_SFTP_CLOSE);
  1106. sshc->nextstate = SSH_NO_STATE;
  1107. sshc->actualcode = result;
  1108. break;
  1109. }
  1110. memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
  1111. state(conn, SSH_SFTP_QUOTE_STAT);
  1112. break;
  1113. }
  1114. else if(curl_strnequal(cmd, "ln ", 3) ||
  1115. curl_strnequal(cmd, "symlink ", 8)) {
  1116. /* symbolic linking */
  1117. /* sshc->quote_path1 is the source */
  1118. /* get the destination */
  1119. result = get_pathname(&cp, &sshc->quote_path2);
  1120. if(result) {
  1121. if(result == CURLE_OUT_OF_MEMORY)
  1122. failf(data, "Out of memory");
  1123. else
  1124. failf(data,
  1125. "Syntax error in ln/symlink: Bad second parameter");
  1126. Curl_safefree(sshc->quote_path1);
  1127. state(conn, SSH_SFTP_CLOSE);
  1128. sshc->nextstate = SSH_NO_STATE;
  1129. sshc->actualcode = result;
  1130. break;
  1131. }
  1132. state(conn, SSH_SFTP_QUOTE_SYMLINK);
  1133. break;
  1134. }
  1135. else if(curl_strnequal(cmd, "mkdir ", 6)) {
  1136. /* create dir */
  1137. state(conn, SSH_SFTP_QUOTE_MKDIR);
  1138. break;
  1139. }
  1140. else if(curl_strnequal(cmd, "rename ", 7)) {
  1141. /* rename file */
  1142. /* first param is the source path */
  1143. /* second param is the dest. path */
  1144. result = get_pathname(&cp, &sshc->quote_path2);
  1145. if(result) {
  1146. if(result == CURLE_OUT_OF_MEMORY)
  1147. failf(data, "Out of memory");
  1148. else
  1149. failf(data, "Syntax error in rename: Bad second parameter");
  1150. Curl_safefree(sshc->quote_path1);
  1151. state(conn, SSH_SFTP_CLOSE);
  1152. sshc->nextstate = SSH_NO_STATE;
  1153. sshc->actualcode = result;
  1154. break;
  1155. }
  1156. state(conn, SSH_SFTP_QUOTE_RENAME);
  1157. break;
  1158. }
  1159. else if(curl_strnequal(cmd, "rmdir ", 6)) {
  1160. /* delete dir */
  1161. state(conn, SSH_SFTP_QUOTE_RMDIR);
  1162. break;
  1163. }
  1164. else if(curl_strnequal(cmd, "rm ", 3)) {
  1165. state(conn, SSH_SFTP_QUOTE_UNLINK);
  1166. break;
  1167. }
  1168. failf(data, "Unknown SFTP command");
  1169. Curl_safefree(sshc->quote_path1);
  1170. Curl_safefree(sshc->quote_path2);
  1171. state(conn, SSH_SFTP_CLOSE);
  1172. sshc->nextstate = SSH_NO_STATE;
  1173. sshc->actualcode = CURLE_QUOTE_ERROR;
  1174. break;
  1175. }
  1176. }
  1177. if(!sshc->quote_item) {
  1178. state(conn, SSH_SFTP_TRANS_INIT);
  1179. }
  1180. break;
  1181. case SSH_SFTP_NEXT_QUOTE:
  1182. Curl_safefree(sshc->quote_path1);
  1183. Curl_safefree(sshc->quote_path2);
  1184. sshc->quote_item = sshc->quote_item->next;
  1185. if(sshc->quote_item) {
  1186. state(conn, SSH_SFTP_QUOTE);
  1187. }
  1188. else {
  1189. if(sshc->nextstate != SSH_NO_STATE) {
  1190. state(conn, sshc->nextstate);
  1191. sshc->nextstate = SSH_NO_STATE;
  1192. }
  1193. else {
  1194. state(conn, SSH_SFTP_TRANS_INIT);
  1195. }
  1196. }
  1197. break;
  1198. case SSH_SFTP_QUOTE_STAT:
  1199. {
  1200. char *cmd = sshc->quote_item->data;
  1201. sshc->acceptfail = FALSE;
  1202. /* if a command starts with an asterisk, which a legal SFTP command never
  1203. can, the command will be allowed to fail without it causing any
  1204. aborts or cancels etc. It will cause libcurl to act as if the command
  1205. is successful, whatever the server reponds. */
  1206. if(cmd[0] == '*') {
  1207. cmd++;
  1208. sshc->acceptfail = TRUE;
  1209. }
  1210. if(!curl_strnequal(cmd, "chmod", 5)) {
  1211. /* Since chown and chgrp only set owner OR group but libssh2 wants to
  1212. * set them both at once, we need to obtain the current ownership
  1213. * first. This takes an extra protocol round trip.
  1214. */
  1215. rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
  1216. curlx_uztoui(strlen(sshc->quote_path2)),
  1217. LIBSSH2_SFTP_STAT,
  1218. &sshc->quote_attrs);
  1219. if(rc == LIBSSH2_ERROR_EAGAIN) {
  1220. break;
  1221. }
  1222. else if(rc != 0 && !sshc->acceptfail) { /* get those attributes */
  1223. err = sftp_libssh2_last_error(sshc->sftp_session);
  1224. Curl_safefree(sshc->quote_path1);
  1225. Curl_safefree(sshc->quote_path2);
  1226. failf(data, "Attempt to get SFTP stats failed: %s",
  1227. sftp_libssh2_strerror(err));
  1228. state(conn, SSH_SFTP_CLOSE);
  1229. sshc->nextstate = SSH_NO_STATE;
  1230. sshc->actualcode = CURLE_QUOTE_ERROR;
  1231. break;
  1232. }
  1233. }
  1234. /* Now set the new attributes... */
  1235. if(curl_strnequal(cmd, "chgrp", 5)) {
  1236. sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
  1237. sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
  1238. if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
  1239. !sshc->acceptfail) {
  1240. Curl_safefree(sshc->quote_path1);
  1241. Curl_safefree(sshc->quote_path2);
  1242. failf(data, "Syntax error: chgrp gid not a number");
  1243. state(conn, SSH_SFTP_CLOSE);
  1244. sshc->nextstate = SSH_NO_STATE;
  1245. sshc->actualcode = CURLE_QUOTE_ERROR;
  1246. break;
  1247. }
  1248. }
  1249. else if(curl_strnequal(cmd, "chmod", 5)) {
  1250. sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
  1251. sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
  1252. /* permissions are octal */
  1253. if(sshc->quote_attrs.permissions == 0 &&
  1254. !ISDIGIT(sshc->quote_path1[0])) {
  1255. Curl_safefree(sshc->quote_path1);
  1256. Curl_safefree(sshc->quote_path2);
  1257. failf(data, "Syntax error: chmod permissions not a number");
  1258. state(conn, SSH_SFTP_CLOSE);
  1259. sshc->nextstate = SSH_NO_STATE;
  1260. sshc->actualcode = CURLE_QUOTE_ERROR;
  1261. break;
  1262. }
  1263. }
  1264. else if(curl_strnequal(cmd, "chown", 5)) {
  1265. sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
  1266. sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
  1267. if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
  1268. !sshc->acceptfail) {
  1269. Curl_safefree(sshc->quote_path1);
  1270. Curl_safefree(sshc->quote_path2);
  1271. failf(data, "Syntax error: chown uid not a number");
  1272. state(conn, SSH_SFTP_CLOSE);
  1273. sshc->nextstate = SSH_NO_STATE;
  1274. sshc->actualcode = CURLE_QUOTE_ERROR;
  1275. break;
  1276. }
  1277. }
  1278. /* Now send the completed structure... */
  1279. state(conn, SSH_SFTP_QUOTE_SETSTAT);
  1280. break;
  1281. }
  1282. case SSH_SFTP_QUOTE_SETSTAT:
  1283. rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
  1284. curlx_uztoui(strlen(sshc->quote_path2)),
  1285. LIBSSH2_SFTP_SETSTAT,
  1286. &sshc->quote_attrs);
  1287. if(rc == LIBSSH2_ERROR_EAGAIN) {
  1288. break;
  1289. }
  1290. else if(rc != 0 && !sshc->acceptfail) {
  1291. err = sftp_libssh2_last_error(sshc->sftp_session);
  1292. Curl_safefree(sshc->quote_path1);
  1293. Curl_safefree(sshc->quote_path2);
  1294. failf(data, "Attempt to set SFTP stats failed: %s",
  1295. sftp_libssh2_strerror(err));
  1296. state(conn, SSH_SFTP_CLOSE);
  1297. sshc->nextstate = SSH_NO_STATE;
  1298. sshc->actualcode = CURLE_QUOTE_ERROR;
  1299. break;
  1300. }
  1301. state(conn, SSH_SFTP_NEXT_QUOTE);
  1302. break;
  1303. case SSH_SFTP_QUOTE_SYMLINK:
  1304. rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
  1305. curlx_uztoui(strlen(sshc->quote_path1)),
  1306. sshc->quote_path2,
  1307. curlx_uztoui(strlen(sshc->quote_path2)),
  1308. LIBSSH2_SFTP_SYMLINK);
  1309. if(rc == LIBSSH2_ERROR_EAGAIN) {
  1310. break;
  1311. }
  1312. else if(rc != 0 && !sshc->acceptfail) {
  1313. err = sftp_libssh2_last_error(sshc->sftp_session);
  1314. Curl_safefree(sshc->quote_path1);
  1315. Curl_safefree(sshc->quote_path2);
  1316. failf(data, "symlink command failed: %s",
  1317. sftp_libssh2_strerror(err));
  1318. state(conn, SSH_SFTP_CLOSE);
  1319. sshc->nextstate = SSH_NO_STATE;
  1320. sshc->actualcode = CURLE_QUOTE_ERROR;
  1321. break;
  1322. }
  1323. state(conn, SSH_SFTP_NEXT_QUOTE);
  1324. break;
  1325. case SSH_SFTP_QUOTE_MKDIR:
  1326. rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
  1327. curlx_uztoui(strlen(sshc->quote_path1)),
  1328. data->set.new_directory_perms);
  1329. if(rc == LIBSSH2_ERROR_EAGAIN) {
  1330. break;
  1331. }
  1332. else if(rc != 0 && !sshc->acceptfail) {
  1333. err = sftp_libssh2_last_error(sshc->sftp_session);
  1334. Curl_safefree(sshc->quote_path1);
  1335. failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
  1336. state(conn, SSH_SFTP_CLOSE);
  1337. sshc->nextstate = SSH_NO_STATE;
  1338. sshc->actualcode = CURLE_QUOTE_ERROR;
  1339. break;
  1340. }
  1341. state(conn, SSH_SFTP_NEXT_QUOTE);
  1342. break;
  1343. case SSH_SFTP_QUOTE_RENAME:
  1344. rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
  1345. curlx_uztoui(strlen(sshc->quote_path1)),
  1346. sshc->quote_path2,
  1347. curlx_uztoui(strlen(sshc->quote_path2)),
  1348. LIBSSH2_SFTP_RENAME_OVERWRITE |
  1349. LIBSSH2_SFTP_RENAME_ATOMIC |
  1350. LIBSSH2_SFTP_RENAME_NATIVE);
  1351. if(rc == LIBSSH2_ERROR_EAGAIN) {
  1352. break;
  1353. }
  1354. else if(rc != 0 && !sshc->acceptfail) {
  1355. err = sftp_libssh2_last_error(sshc->sftp_session);
  1356. Curl_safefree(sshc->quote_path1);
  1357. Curl_safefree(sshc->quote_path2);
  1358. failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
  1359. state(conn, SSH_SFT

Large files files are truncated, but you can click here to view the full file