libssh.c 87 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 2017 - 2022 Red Hat, Inc.
  9. *
  10. * Authors: Nikos Mavrogiannopoulos, Tomas Mraz, Stanislav Zidek,
  11. * Robert Kolcun, Andreas Schneider
  12. *
  13. * This software is licensed as described in the file COPYING, which
  14. * you should have received as part of this distribution. The terms
  15. * are also available at https://curl.se/docs/copyright.html.
  16. *
  17. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  18. * copies of the Software, and permit persons to whom the Software is
  19. * furnished to do so, under the terms of the COPYING file.
  20. *
  21. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  22. * KIND, either express or implied.
  23. *
  24. * SPDX-License-Identifier: curl
  25. *
  26. ***************************************************************************/
  27. #include "curl_setup.h"
  28. #ifdef USE_LIBSSH
  29. #include <limits.h>
  30. #include <libssh/libssh.h>
  31. #include <libssh/sftp.h>
  32. #ifdef HAVE_NETINET_IN_H
  33. #include <netinet/in.h>
  34. #endif
  35. #ifdef HAVE_ARPA_INET_H
  36. #include <arpa/inet.h>
  37. #endif
  38. #ifdef HAVE_UTSNAME_H
  39. #include <sys/utsname.h>
  40. #endif
  41. #ifdef HAVE_NETDB_H
  42. #include <netdb.h>
  43. #endif
  44. #ifdef __VMS
  45. #include <in.h>
  46. #include <inet.h>
  47. #endif
  48. #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
  49. #undef in_addr_t
  50. #define in_addr_t unsigned long
  51. #endif
  52. #include <curl/curl.h>
  53. #include "urldata.h"
  54. #include "sendf.h"
  55. #include "hostip.h"
  56. #include "progress.h"
  57. #include "transfer.h"
  58. #include "escape.h"
  59. #include "http.h" /* for HTTP proxy tunnel stuff */
  60. #include "ssh.h"
  61. #include "url.h"
  62. #include "speedcheck.h"
  63. #include "getinfo.h"
  64. #include "strdup.h"
  65. #include "strcase.h"
  66. #include "vtls/vtls.h"
  67. #include "connect.h"
  68. #include "inet_ntop.h"
  69. #include "parsedate.h" /* for the week day and month names */
  70. #include "sockaddr.h" /* required for Curl_sockaddr_storage */
  71. #include "strtoofft.h"
  72. #include "multiif.h"
  73. #include "select.h"
  74. #include "warnless.h"
  75. #include "curl_path.h"
  76. #ifdef HAVE_SYS_STAT_H
  77. #include <sys/stat.h>
  78. #endif
  79. #ifdef HAVE_UNISTD_H
  80. #include <unistd.h>
  81. #endif
  82. #ifdef HAVE_FCNTL_H
  83. #include <fcntl.h>
  84. #endif
  85. /* The last 3 #include files should be in this order */
  86. #include "curl_printf.h"
  87. #include "curl_memory.h"
  88. #include "memdebug.h"
  89. /* in 0.10.0 or later, ignore deprecated warnings */
  90. #if defined(__GNUC__) && \
  91. (LIBSSH_VERSION_MINOR >= 10) || \
  92. (LIBSSH_VERSION_MAJOR > 0)
  93. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  94. #endif
  95. /* A recent macro provided by libssh. Or make our own. */
  96. #ifndef SSH_STRING_FREE_CHAR
  97. #define SSH_STRING_FREE_CHAR(x) \
  98. do { \
  99. if(x) { \
  100. ssh_string_free_char(x); \
  101. x = NULL; \
  102. } \
  103. } while(0)
  104. #endif
  105. /* These stat values may not be the same as the user's S_IFMT / S_IFLNK */
  106. #ifndef SSH_S_IFMT
  107. #define SSH_S_IFMT 00170000
  108. #endif
  109. #ifndef SSH_S_IFLNK
  110. #define SSH_S_IFLNK 0120000
  111. #endif
  112. /* Local functions: */
  113. static CURLcode myssh_connect(struct Curl_easy *data, bool *done);
  114. static CURLcode myssh_multi_statemach(struct Curl_easy *data,
  115. bool *done);
  116. static CURLcode myssh_do_it(struct Curl_easy *data, bool *done);
  117. static CURLcode scp_done(struct Curl_easy *data,
  118. CURLcode, bool premature);
  119. static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done);
  120. static CURLcode scp_disconnect(struct Curl_easy *data,
  121. struct connectdata *conn,
  122. bool dead_connection);
  123. static CURLcode sftp_done(struct Curl_easy *data,
  124. CURLcode, bool premature);
  125. static CURLcode sftp_doing(struct Curl_easy *data,
  126. bool *dophase_done);
  127. static CURLcode sftp_disconnect(struct Curl_easy *data,
  128. struct connectdata *conn,
  129. bool dead);
  130. static
  131. CURLcode sftp_perform(struct Curl_easy *data,
  132. bool *connected,
  133. bool *dophase_done);
  134. static void sftp_quote(struct Curl_easy *data);
  135. static void sftp_quote_stat(struct Curl_easy *data);
  136. static int myssh_getsock(struct Curl_easy *data,
  137. struct connectdata *conn, curl_socket_t *sock);
  138. static CURLcode myssh_setup_connection(struct Curl_easy *data,
  139. struct connectdata *conn);
  140. /*
  141. * SCP protocol handler.
  142. */
  143. const struct Curl_handler Curl_handler_scp = {
  144. "SCP", /* scheme */
  145. myssh_setup_connection, /* setup_connection */
  146. myssh_do_it, /* do_it */
  147. scp_done, /* done */
  148. ZERO_NULL, /* do_more */
  149. myssh_connect, /* connect_it */
  150. myssh_multi_statemach, /* connecting */
  151. scp_doing, /* doing */
  152. myssh_getsock, /* proto_getsock */
  153. myssh_getsock, /* doing_getsock */
  154. ZERO_NULL, /* domore_getsock */
  155. myssh_getsock, /* perform_getsock */
  156. scp_disconnect, /* disconnect */
  157. ZERO_NULL, /* readwrite */
  158. ZERO_NULL, /* connection_check */
  159. ZERO_NULL, /* attach connection */
  160. PORT_SSH, /* defport */
  161. CURLPROTO_SCP, /* protocol */
  162. CURLPROTO_SCP, /* family */
  163. PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */
  164. };
  165. /*
  166. * SFTP protocol handler.
  167. */
  168. const struct Curl_handler Curl_handler_sftp = {
  169. "SFTP", /* scheme */
  170. myssh_setup_connection, /* setup_connection */
  171. myssh_do_it, /* do_it */
  172. sftp_done, /* done */
  173. ZERO_NULL, /* do_more */
  174. myssh_connect, /* connect_it */
  175. myssh_multi_statemach, /* connecting */
  176. sftp_doing, /* doing */
  177. myssh_getsock, /* proto_getsock */
  178. myssh_getsock, /* doing_getsock */
  179. ZERO_NULL, /* domore_getsock */
  180. myssh_getsock, /* perform_getsock */
  181. sftp_disconnect, /* disconnect */
  182. ZERO_NULL, /* readwrite */
  183. ZERO_NULL, /* connection_check */
  184. ZERO_NULL, /* attach connection */
  185. PORT_SSH, /* defport */
  186. CURLPROTO_SFTP, /* protocol */
  187. CURLPROTO_SFTP, /* family */
  188. PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
  189. | PROTOPT_NOURLQUERY /* flags */
  190. };
  191. static CURLcode sftp_error_to_CURLE(int err)
  192. {
  193. switch(err) {
  194. case SSH_FX_OK:
  195. return CURLE_OK;
  196. case SSH_FX_NO_SUCH_FILE:
  197. case SSH_FX_NO_SUCH_PATH:
  198. return CURLE_REMOTE_FILE_NOT_FOUND;
  199. case SSH_FX_PERMISSION_DENIED:
  200. case SSH_FX_WRITE_PROTECT:
  201. return CURLE_REMOTE_ACCESS_DENIED;
  202. case SSH_FX_FILE_ALREADY_EXISTS:
  203. return CURLE_REMOTE_FILE_EXISTS;
  204. default:
  205. break;
  206. }
  207. return CURLE_SSH;
  208. }
  209. #ifndef DEBUGBUILD
  210. #define state(x,y) mystate(x,y)
  211. #else
  212. #define state(x,y) mystate(x,y, __LINE__)
  213. #endif
  214. /*
  215. * SSH State machine related code
  216. */
  217. /* This is the ONLY way to change SSH state! */
  218. static void mystate(struct Curl_easy *data, sshstate nowstate
  219. #ifdef DEBUGBUILD
  220. , int lineno
  221. #endif
  222. )
  223. {
  224. struct connectdata *conn = data->conn;
  225. struct ssh_conn *sshc = &conn->proto.sshc;
  226. #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
  227. /* for debug purposes */
  228. static const char *const names[] = {
  229. "SSH_STOP",
  230. "SSH_INIT",
  231. "SSH_S_STARTUP",
  232. "SSH_HOSTKEY",
  233. "SSH_AUTHLIST",
  234. "SSH_AUTH_PKEY_INIT",
  235. "SSH_AUTH_PKEY",
  236. "SSH_AUTH_PASS_INIT",
  237. "SSH_AUTH_PASS",
  238. "SSH_AUTH_AGENT_INIT",
  239. "SSH_AUTH_AGENT_LIST",
  240. "SSH_AUTH_AGENT",
  241. "SSH_AUTH_HOST_INIT",
  242. "SSH_AUTH_HOST",
  243. "SSH_AUTH_KEY_INIT",
  244. "SSH_AUTH_KEY",
  245. "SSH_AUTH_GSSAPI",
  246. "SSH_AUTH_DONE",
  247. "SSH_SFTP_INIT",
  248. "SSH_SFTP_REALPATH",
  249. "SSH_SFTP_QUOTE_INIT",
  250. "SSH_SFTP_POSTQUOTE_INIT",
  251. "SSH_SFTP_QUOTE",
  252. "SSH_SFTP_NEXT_QUOTE",
  253. "SSH_SFTP_QUOTE_STAT",
  254. "SSH_SFTP_QUOTE_SETSTAT",
  255. "SSH_SFTP_QUOTE_SYMLINK",
  256. "SSH_SFTP_QUOTE_MKDIR",
  257. "SSH_SFTP_QUOTE_RENAME",
  258. "SSH_SFTP_QUOTE_RMDIR",
  259. "SSH_SFTP_QUOTE_UNLINK",
  260. "SSH_SFTP_QUOTE_STATVFS",
  261. "SSH_SFTP_GETINFO",
  262. "SSH_SFTP_FILETIME",
  263. "SSH_SFTP_TRANS_INIT",
  264. "SSH_SFTP_UPLOAD_INIT",
  265. "SSH_SFTP_CREATE_DIRS_INIT",
  266. "SSH_SFTP_CREATE_DIRS",
  267. "SSH_SFTP_CREATE_DIRS_MKDIR",
  268. "SSH_SFTP_READDIR_INIT",
  269. "SSH_SFTP_READDIR",
  270. "SSH_SFTP_READDIR_LINK",
  271. "SSH_SFTP_READDIR_BOTTOM",
  272. "SSH_SFTP_READDIR_DONE",
  273. "SSH_SFTP_DOWNLOAD_INIT",
  274. "SSH_SFTP_DOWNLOAD_STAT",
  275. "SSH_SFTP_CLOSE",
  276. "SSH_SFTP_SHUTDOWN",
  277. "SSH_SCP_TRANS_INIT",
  278. "SSH_SCP_UPLOAD_INIT",
  279. "SSH_SCP_DOWNLOAD_INIT",
  280. "SSH_SCP_DOWNLOAD",
  281. "SSH_SCP_DONE",
  282. "SSH_SCP_SEND_EOF",
  283. "SSH_SCP_WAIT_EOF",
  284. "SSH_SCP_WAIT_CLOSE",
  285. "SSH_SCP_CHANNEL_FREE",
  286. "SSH_SESSION_DISCONNECT",
  287. "SSH_SESSION_FREE",
  288. "QUIT"
  289. };
  290. if(sshc->state != nowstate) {
  291. infof(data, "SSH %p state change from %s to %s (line %d)",
  292. (void *) sshc, names[sshc->state], names[nowstate],
  293. lineno);
  294. }
  295. #endif
  296. sshc->state = nowstate;
  297. }
  298. /* Multiple options:
  299. * 1. data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] is set with an MD5
  300. * hash (90s style auth, not sure we should have it here)
  301. * 2. data->set.ssh_keyfunc callback is set. Then we do trust on first
  302. * use. We even save on knownhosts if CURLKHSTAT_FINE_ADD_TO_FILE
  303. * is returned by it.
  304. * 3. none of the above. We only accept if it is present on known hosts.
  305. *
  306. * Returns SSH_OK or SSH_ERROR.
  307. */
  308. static int myssh_is_known(struct Curl_easy *data)
  309. {
  310. int rc;
  311. struct connectdata *conn = data->conn;
  312. struct ssh_conn *sshc = &conn->proto.sshc;
  313. ssh_key pubkey;
  314. size_t hlen;
  315. unsigned char *hash = NULL;
  316. char *found_base64 = NULL;
  317. char *known_base64 = NULL;
  318. int vstate;
  319. enum curl_khmatch keymatch;
  320. struct curl_khkey foundkey;
  321. struct curl_khkey *knownkeyp = NULL;
  322. curl_sshkeycallback func =
  323. data->set.ssh_keyfunc;
  324. #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
  325. struct ssh_knownhosts_entry *knownhostsentry = NULL;
  326. struct curl_khkey knownkey;
  327. #endif
  328. #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
  329. rc = ssh_get_server_publickey(sshc->ssh_session, &pubkey);
  330. #else
  331. rc = ssh_get_publickey(sshc->ssh_session, &pubkey);
  332. #endif
  333. if(rc != SSH_OK)
  334. return rc;
  335. if(data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]) {
  336. int i;
  337. char md5buffer[33];
  338. const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
  339. rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5,
  340. &hash, &hlen);
  341. if(rc != SSH_OK || hlen != 16) {
  342. failf(data,
  343. "Denied establishing ssh session: md5 fingerprint not available");
  344. goto cleanup;
  345. }
  346. for(i = 0; i < 16; i++)
  347. msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char)hash[i]);
  348. infof(data, "SSH MD5 fingerprint: %s", md5buffer);
  349. if(!strcasecompare(md5buffer, pubkey_md5)) {
  350. failf(data,
  351. "Denied establishing ssh session: mismatch md5 fingerprint. "
  352. "Remote %s is not equal to %s", md5buffer, pubkey_md5);
  353. rc = SSH_ERROR;
  354. goto cleanup;
  355. }
  356. rc = SSH_OK;
  357. goto cleanup;
  358. }
  359. if(data->set.ssl.primary.verifyhost != TRUE) {
  360. rc = SSH_OK;
  361. goto cleanup;
  362. }
  363. #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
  364. /* Get the known_key from the known hosts file */
  365. vstate = ssh_session_get_known_hosts_entry(sshc->ssh_session,
  366. &knownhostsentry);
  367. /* Case an entry was found in a known hosts file */
  368. if(knownhostsentry) {
  369. if(knownhostsentry->publickey) {
  370. rc = ssh_pki_export_pubkey_base64(knownhostsentry->publickey,
  371. &known_base64);
  372. if(rc != SSH_OK) {
  373. goto cleanup;
  374. }
  375. knownkey.key = known_base64;
  376. knownkey.len = strlen(known_base64);
  377. switch(ssh_key_type(knownhostsentry->publickey)) {
  378. case SSH_KEYTYPE_RSA:
  379. knownkey.keytype = CURLKHTYPE_RSA;
  380. break;
  381. case SSH_KEYTYPE_RSA1:
  382. knownkey.keytype = CURLKHTYPE_RSA1;
  383. break;
  384. case SSH_KEYTYPE_ECDSA:
  385. case SSH_KEYTYPE_ECDSA_P256:
  386. case SSH_KEYTYPE_ECDSA_P384:
  387. case SSH_KEYTYPE_ECDSA_P521:
  388. knownkey.keytype = CURLKHTYPE_ECDSA;
  389. break;
  390. case SSH_KEYTYPE_ED25519:
  391. knownkey.keytype = CURLKHTYPE_ED25519;
  392. break;
  393. case SSH_KEYTYPE_DSS:
  394. knownkey.keytype = CURLKHTYPE_DSS;
  395. break;
  396. default:
  397. rc = SSH_ERROR;
  398. goto cleanup;
  399. }
  400. knownkeyp = &knownkey;
  401. }
  402. }
  403. switch(vstate) {
  404. case SSH_KNOWN_HOSTS_OK:
  405. keymatch = CURLKHMATCH_OK;
  406. break;
  407. case SSH_KNOWN_HOSTS_OTHER:
  408. /* fallthrough */
  409. case SSH_KNOWN_HOSTS_NOT_FOUND:
  410. /* fallthrough */
  411. case SSH_KNOWN_HOSTS_UNKNOWN:
  412. /* fallthrough */
  413. case SSH_KNOWN_HOSTS_ERROR:
  414. keymatch = CURLKHMATCH_MISSING;
  415. break;
  416. default:
  417. keymatch = CURLKHMATCH_MISMATCH;
  418. break;
  419. }
  420. #else
  421. vstate = ssh_is_server_known(sshc->ssh_session);
  422. switch(vstate) {
  423. case SSH_SERVER_KNOWN_OK:
  424. keymatch = CURLKHMATCH_OK;
  425. break;
  426. case SSH_SERVER_FILE_NOT_FOUND:
  427. /* fallthrough */
  428. case SSH_SERVER_NOT_KNOWN:
  429. keymatch = CURLKHMATCH_MISSING;
  430. break;
  431. default:
  432. keymatch = CURLKHMATCH_MISMATCH;
  433. break;
  434. }
  435. #endif
  436. if(func) { /* use callback to determine action */
  437. rc = ssh_pki_export_pubkey_base64(pubkey, &found_base64);
  438. if(rc != SSH_OK)
  439. goto cleanup;
  440. foundkey.key = found_base64;
  441. foundkey.len = strlen(found_base64);
  442. switch(ssh_key_type(pubkey)) {
  443. case SSH_KEYTYPE_RSA:
  444. foundkey.keytype = CURLKHTYPE_RSA;
  445. break;
  446. case SSH_KEYTYPE_RSA1:
  447. foundkey.keytype = CURLKHTYPE_RSA1;
  448. break;
  449. case SSH_KEYTYPE_ECDSA:
  450. #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
  451. case SSH_KEYTYPE_ECDSA_P256:
  452. case SSH_KEYTYPE_ECDSA_P384:
  453. case SSH_KEYTYPE_ECDSA_P521:
  454. #endif
  455. foundkey.keytype = CURLKHTYPE_ECDSA;
  456. break;
  457. #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,7,0)
  458. case SSH_KEYTYPE_ED25519:
  459. foundkey.keytype = CURLKHTYPE_ED25519;
  460. break;
  461. #endif
  462. case SSH_KEYTYPE_DSS:
  463. foundkey.keytype = CURLKHTYPE_DSS;
  464. break;
  465. default:
  466. rc = SSH_ERROR;
  467. goto cleanup;
  468. }
  469. Curl_set_in_callback(data, true);
  470. rc = func(data, knownkeyp, /* from the knownhosts file */
  471. &foundkey, /* from the remote host */
  472. keymatch, data->set.ssh_keyfunc_userp);
  473. Curl_set_in_callback(data, false);
  474. switch(rc) {
  475. case CURLKHSTAT_FINE_ADD_TO_FILE:
  476. #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,8,0)
  477. rc = ssh_session_update_known_hosts(sshc->ssh_session);
  478. #else
  479. rc = ssh_write_knownhost(sshc->ssh_session);
  480. #endif
  481. if(rc != SSH_OK) {
  482. goto cleanup;
  483. }
  484. break;
  485. case CURLKHSTAT_FINE:
  486. break;
  487. default: /* REJECT/DEFER */
  488. rc = SSH_ERROR;
  489. goto cleanup;
  490. }
  491. }
  492. else {
  493. if(keymatch != CURLKHMATCH_OK) {
  494. rc = SSH_ERROR;
  495. goto cleanup;
  496. }
  497. }
  498. rc = SSH_OK;
  499. cleanup:
  500. if(found_base64) {
  501. (free)(found_base64);
  502. }
  503. if(known_base64) {
  504. (free)(known_base64);
  505. }
  506. if(hash)
  507. ssh_clean_pubkey_hash(&hash);
  508. ssh_key_free(pubkey);
  509. #if LIBSSH_VERSION_INT >= SSH_VERSION_INT(0,9,0)
  510. if(knownhostsentry) {
  511. ssh_knownhosts_entry_free(knownhostsentry);
  512. }
  513. #endif
  514. return rc;
  515. }
  516. #define MOVE_TO_ERROR_STATE(_r) do { \
  517. state(data, SSH_SESSION_DISCONNECT); \
  518. sshc->actualcode = _r; \
  519. rc = SSH_ERROR; \
  520. } while(0)
  521. #define MOVE_TO_SFTP_CLOSE_STATE() do { \
  522. state(data, SSH_SFTP_CLOSE); \
  523. sshc->actualcode = \
  524. sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); \
  525. rc = SSH_ERROR; \
  526. } while(0)
  527. #define MOVE_TO_LAST_AUTH do { \
  528. if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \
  529. rc = SSH_OK; \
  530. state(data, SSH_AUTH_PASS_INIT); \
  531. } \
  532. else { \
  533. MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \
  534. } \
  535. } while(0)
  536. #define MOVE_TO_TERTIARY_AUTH do { \
  537. if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \
  538. rc = SSH_OK; \
  539. state(data, SSH_AUTH_KEY_INIT); \
  540. } \
  541. else { \
  542. MOVE_TO_LAST_AUTH; \
  543. } \
  544. } while(0)
  545. #define MOVE_TO_SECONDARY_AUTH do { \
  546. if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \
  547. rc = SSH_OK; \
  548. state(data, SSH_AUTH_GSSAPI); \
  549. } \
  550. else { \
  551. MOVE_TO_TERTIARY_AUTH; \
  552. } \
  553. } while(0)
  554. static
  555. int myssh_auth_interactive(struct connectdata *conn)
  556. {
  557. int rc;
  558. struct ssh_conn *sshc = &conn->proto.sshc;
  559. int nprompts;
  560. restart:
  561. switch(sshc->kbd_state) {
  562. case 0:
  563. rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
  564. if(rc == SSH_AUTH_AGAIN)
  565. return SSH_AGAIN;
  566. if(rc != SSH_AUTH_INFO)
  567. return SSH_ERROR;
  568. nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
  569. if(nprompts != 1)
  570. return SSH_ERROR;
  571. rc = ssh_userauth_kbdint_setanswer(sshc->ssh_session, 0, conn->passwd);
  572. if(rc < 0)
  573. return SSH_ERROR;
  574. /* FALLTHROUGH */
  575. case 1:
  576. sshc->kbd_state = 1;
  577. rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
  578. if(rc == SSH_AUTH_AGAIN)
  579. return SSH_AGAIN;
  580. else if(rc == SSH_AUTH_SUCCESS)
  581. rc = SSH_OK;
  582. else if(rc == SSH_AUTH_INFO) {
  583. nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session);
  584. if(nprompts)
  585. return SSH_ERROR;
  586. sshc->kbd_state = 2;
  587. goto restart;
  588. }
  589. else
  590. rc = SSH_ERROR;
  591. break;
  592. case 2:
  593. sshc->kbd_state = 2;
  594. rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL);
  595. if(rc == SSH_AUTH_AGAIN)
  596. return SSH_AGAIN;
  597. else if(rc == SSH_AUTH_SUCCESS)
  598. rc = SSH_OK;
  599. else
  600. rc = SSH_ERROR;
  601. break;
  602. default:
  603. return SSH_ERROR;
  604. }
  605. sshc->kbd_state = 0;
  606. return rc;
  607. }
  608. /*
  609. * ssh_statemach_act() runs the SSH state machine as far as it can without
  610. * blocking and without reaching the end. The data the pointer 'block' points
  611. * to will be set to TRUE if the libssh function returns SSH_AGAIN
  612. * meaning it wants to be called again when the socket is ready
  613. */
  614. static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
  615. {
  616. CURLcode result = CURLE_OK;
  617. struct connectdata *conn = data->conn;
  618. struct SSHPROTO *protop = data->req.p.ssh;
  619. struct ssh_conn *sshc = &conn->proto.sshc;
  620. curl_socket_t sock = conn->sock[FIRSTSOCKET];
  621. int rc = SSH_NO_ERROR, err;
  622. char *new_readdir_line;
  623. int seekerr = CURL_SEEKFUNC_OK;
  624. const char *err_msg;
  625. *block = 0; /* we're not blocking by default */
  626. do {
  627. switch(sshc->state) {
  628. case SSH_INIT:
  629. sshc->secondCreateDirs = 0;
  630. sshc->nextstate = SSH_NO_STATE;
  631. sshc->actualcode = CURLE_OK;
  632. #if 0
  633. ssh_set_log_level(SSH_LOG_PROTOCOL);
  634. #endif
  635. /* Set libssh to non-blocking, since everything internally is
  636. non-blocking */
  637. ssh_set_blocking(sshc->ssh_session, 0);
  638. state(data, SSH_S_STARTUP);
  639. /* FALLTHROUGH */
  640. case SSH_S_STARTUP:
  641. rc = ssh_connect(sshc->ssh_session);
  642. if(rc == SSH_AGAIN)
  643. break;
  644. if(rc != SSH_OK) {
  645. failf(data, "Failure establishing ssh session");
  646. MOVE_TO_ERROR_STATE(CURLE_FAILED_INIT);
  647. break;
  648. }
  649. state(data, SSH_HOSTKEY);
  650. /* FALLTHROUGH */
  651. case SSH_HOSTKEY:
  652. rc = myssh_is_known(data);
  653. if(rc != SSH_OK) {
  654. MOVE_TO_ERROR_STATE(CURLE_PEER_FAILED_VERIFICATION);
  655. break;
  656. }
  657. state(data, SSH_AUTHLIST);
  658. /* FALLTHROUGH */
  659. case SSH_AUTHLIST:{
  660. sshc->authed = FALSE;
  661. rc = ssh_userauth_none(sshc->ssh_session, NULL);
  662. if(rc == SSH_AUTH_AGAIN) {
  663. rc = SSH_AGAIN;
  664. break;
  665. }
  666. if(rc == SSH_AUTH_SUCCESS) {
  667. sshc->authed = TRUE;
  668. infof(data, "Authenticated with none");
  669. state(data, SSH_AUTH_DONE);
  670. break;
  671. }
  672. else if(rc == SSH_AUTH_ERROR) {
  673. MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
  674. break;
  675. }
  676. sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
  677. if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
  678. state(data, SSH_AUTH_PKEY_INIT);
  679. infof(data, "Authentication using SSH public key file");
  680. }
  681. else if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) {
  682. state(data, SSH_AUTH_GSSAPI);
  683. }
  684. else if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) {
  685. state(data, SSH_AUTH_KEY_INIT);
  686. }
  687. else if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) {
  688. state(data, SSH_AUTH_PASS_INIT);
  689. }
  690. else { /* unsupported authentication method */
  691. MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
  692. break;
  693. }
  694. break;
  695. }
  696. case SSH_AUTH_PKEY_INIT:
  697. if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) {
  698. MOVE_TO_SECONDARY_AUTH;
  699. break;
  700. }
  701. /* Two choices, (1) private key was given on CMD,
  702. * (2) use the "default" keys. */
  703. if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
  704. if(sshc->pubkey && !data->set.ssl.key_passwd) {
  705. rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL,
  706. sshc->pubkey);
  707. if(rc == SSH_AUTH_AGAIN) {
  708. rc = SSH_AGAIN;
  709. break;
  710. }
  711. if(rc != SSH_OK) {
  712. MOVE_TO_SECONDARY_AUTH;
  713. break;
  714. }
  715. }
  716. rc = ssh_pki_import_privkey_file(data->
  717. set.str[STRING_SSH_PRIVATE_KEY],
  718. data->set.ssl.key_passwd, NULL,
  719. NULL, &sshc->privkey);
  720. if(rc != SSH_OK) {
  721. failf(data, "Could not load private key file %s",
  722. data->set.str[STRING_SSH_PRIVATE_KEY]);
  723. MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
  724. break;
  725. }
  726. state(data, SSH_AUTH_PKEY);
  727. break;
  728. }
  729. else {
  730. rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL,
  731. data->set.ssl.key_passwd);
  732. if(rc == SSH_AUTH_AGAIN) {
  733. rc = SSH_AGAIN;
  734. break;
  735. }
  736. if(rc == SSH_AUTH_SUCCESS) {
  737. rc = SSH_OK;
  738. sshc->authed = TRUE;
  739. infof(data, "Completed public key authentication");
  740. state(data, SSH_AUTH_DONE);
  741. break;
  742. }
  743. MOVE_TO_SECONDARY_AUTH;
  744. }
  745. break;
  746. case SSH_AUTH_PKEY:
  747. rc = ssh_userauth_publickey(sshc->ssh_session, NULL, sshc->privkey);
  748. if(rc == SSH_AUTH_AGAIN) {
  749. rc = SSH_AGAIN;
  750. break;
  751. }
  752. if(rc == SSH_AUTH_SUCCESS) {
  753. sshc->authed = TRUE;
  754. infof(data, "Completed public key authentication");
  755. state(data, SSH_AUTH_DONE);
  756. break;
  757. }
  758. else {
  759. infof(data, "Failed public key authentication (rc: %d)", rc);
  760. MOVE_TO_SECONDARY_AUTH;
  761. }
  762. break;
  763. case SSH_AUTH_GSSAPI:
  764. if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) {
  765. MOVE_TO_TERTIARY_AUTH;
  766. break;
  767. }
  768. rc = ssh_userauth_gssapi(sshc->ssh_session);
  769. if(rc == SSH_AUTH_AGAIN) {
  770. rc = SSH_AGAIN;
  771. break;
  772. }
  773. if(rc == SSH_AUTH_SUCCESS) {
  774. rc = SSH_OK;
  775. sshc->authed = TRUE;
  776. infof(data, "Completed gssapi authentication");
  777. state(data, SSH_AUTH_DONE);
  778. break;
  779. }
  780. MOVE_TO_TERTIARY_AUTH;
  781. break;
  782. case SSH_AUTH_KEY_INIT:
  783. if(data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) {
  784. state(data, SSH_AUTH_KEY);
  785. }
  786. else {
  787. MOVE_TO_LAST_AUTH;
  788. }
  789. break;
  790. case SSH_AUTH_KEY:
  791. /* Authentication failed. Continue with keyboard-interactive now. */
  792. rc = myssh_auth_interactive(conn);
  793. if(rc == SSH_AGAIN) {
  794. break;
  795. }
  796. if(rc == SSH_OK) {
  797. sshc->authed = TRUE;
  798. infof(data, "completed keyboard interactive authentication");
  799. }
  800. state(data, SSH_AUTH_DONE);
  801. break;
  802. case SSH_AUTH_PASS_INIT:
  803. if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) {
  804. /* Host key authentication is intentionally not implemented */
  805. MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
  806. break;
  807. }
  808. state(data, SSH_AUTH_PASS);
  809. /* FALLTHROUGH */
  810. case SSH_AUTH_PASS:
  811. rc = ssh_userauth_password(sshc->ssh_session, NULL, conn->passwd);
  812. if(rc == SSH_AUTH_AGAIN) {
  813. rc = SSH_AGAIN;
  814. break;
  815. }
  816. if(rc == SSH_AUTH_SUCCESS) {
  817. sshc->authed = TRUE;
  818. infof(data, "Completed password authentication");
  819. state(data, SSH_AUTH_DONE);
  820. }
  821. else {
  822. MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
  823. }
  824. break;
  825. case SSH_AUTH_DONE:
  826. if(!sshc->authed) {
  827. failf(data, "Authentication failure");
  828. MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED);
  829. break;
  830. }
  831. /*
  832. * At this point we have an authenticated ssh session.
  833. */
  834. infof(data, "Authentication complete");
  835. Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
  836. conn->sockfd = sock;
  837. conn->writesockfd = CURL_SOCKET_BAD;
  838. if(conn->handler->protocol == CURLPROTO_SFTP) {
  839. state(data, SSH_SFTP_INIT);
  840. break;
  841. }
  842. infof(data, "SSH CONNECT phase done");
  843. state(data, SSH_STOP);
  844. break;
  845. case SSH_SFTP_INIT:
  846. ssh_set_blocking(sshc->ssh_session, 1);
  847. sshc->sftp_session = sftp_new(sshc->ssh_session);
  848. if(!sshc->sftp_session) {
  849. failf(data, "Failure initializing sftp session: %s",
  850. ssh_get_error(sshc->ssh_session));
  851. MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
  852. break;
  853. }
  854. rc = sftp_init(sshc->sftp_session);
  855. if(rc != SSH_OK) {
  856. rc = sftp_get_error(sshc->sftp_session);
  857. failf(data, "Failure initializing sftp session: %s",
  858. ssh_get_error(sshc->ssh_session));
  859. MOVE_TO_ERROR_STATE(sftp_error_to_CURLE(rc));
  860. break;
  861. }
  862. state(data, SSH_SFTP_REALPATH);
  863. /* FALLTHROUGH */
  864. case SSH_SFTP_REALPATH:
  865. /*
  866. * Get the "home" directory
  867. */
  868. sshc->homedir = sftp_canonicalize_path(sshc->sftp_session, ".");
  869. if(!sshc->homedir) {
  870. MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
  871. break;
  872. }
  873. data->state.most_recent_ftp_entrypath = sshc->homedir;
  874. /* This is the last step in the SFTP connect phase. Do note that while
  875. we get the homedir here, we get the "workingpath" in the DO action
  876. since the homedir will remain the same between request but the
  877. working path will not. */
  878. DEBUGF(infof(data, "SSH CONNECT phase done"));
  879. state(data, SSH_STOP);
  880. break;
  881. case SSH_SFTP_QUOTE_INIT:
  882. result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
  883. if(result) {
  884. sshc->actualcode = result;
  885. state(data, SSH_STOP);
  886. break;
  887. }
  888. if(data->set.quote) {
  889. infof(data, "Sending quote commands");
  890. sshc->quote_item = data->set.quote;
  891. state(data, SSH_SFTP_QUOTE);
  892. }
  893. else {
  894. state(data, SSH_SFTP_GETINFO);
  895. }
  896. break;
  897. case SSH_SFTP_POSTQUOTE_INIT:
  898. if(data->set.postquote) {
  899. infof(data, "Sending quote commands");
  900. sshc->quote_item = data->set.postquote;
  901. state(data, SSH_SFTP_QUOTE);
  902. }
  903. else {
  904. state(data, SSH_STOP);
  905. }
  906. break;
  907. case SSH_SFTP_QUOTE:
  908. /* Send any quote commands */
  909. sftp_quote(data);
  910. break;
  911. case SSH_SFTP_NEXT_QUOTE:
  912. Curl_safefree(sshc->quote_path1);
  913. Curl_safefree(sshc->quote_path2);
  914. sshc->quote_item = sshc->quote_item->next;
  915. if(sshc->quote_item) {
  916. state(data, SSH_SFTP_QUOTE);
  917. }
  918. else {
  919. if(sshc->nextstate != SSH_NO_STATE) {
  920. state(data, sshc->nextstate);
  921. sshc->nextstate = SSH_NO_STATE;
  922. }
  923. else {
  924. state(data, SSH_SFTP_GETINFO);
  925. }
  926. }
  927. break;
  928. case SSH_SFTP_QUOTE_STAT:
  929. sftp_quote_stat(data);
  930. break;
  931. case SSH_SFTP_QUOTE_SETSTAT:
  932. rc = sftp_setstat(sshc->sftp_session, sshc->quote_path2,
  933. sshc->quote_attrs);
  934. if(rc && !sshc->acceptfail) {
  935. Curl_safefree(sshc->quote_path1);
  936. Curl_safefree(sshc->quote_path2);
  937. failf(data, "Attempt to set SFTP stats failed: %s",
  938. ssh_get_error(sshc->ssh_session));
  939. state(data, SSH_SFTP_CLOSE);
  940. sshc->nextstate = SSH_NO_STATE;
  941. sshc->actualcode = CURLE_QUOTE_ERROR;
  942. /* sshc->actualcode = sftp_error_to_CURLE(err);
  943. * we do not send the actual error; we return
  944. * the error the libssh2 backend is returning */
  945. break;
  946. }
  947. state(data, SSH_SFTP_NEXT_QUOTE);
  948. break;
  949. case SSH_SFTP_QUOTE_SYMLINK:
  950. rc = sftp_symlink(sshc->sftp_session, sshc->quote_path2,
  951. sshc->quote_path1);
  952. if(rc && !sshc->acceptfail) {
  953. Curl_safefree(sshc->quote_path1);
  954. Curl_safefree(sshc->quote_path2);
  955. failf(data, "symlink command failed: %s",
  956. ssh_get_error(sshc->ssh_session));
  957. state(data, SSH_SFTP_CLOSE);
  958. sshc->nextstate = SSH_NO_STATE;
  959. sshc->actualcode = CURLE_QUOTE_ERROR;
  960. break;
  961. }
  962. state(data, SSH_SFTP_NEXT_QUOTE);
  963. break;
  964. case SSH_SFTP_QUOTE_MKDIR:
  965. rc = sftp_mkdir(sshc->sftp_session, sshc->quote_path1,
  966. (mode_t)data->set.new_directory_perms);
  967. if(rc && !sshc->acceptfail) {
  968. Curl_safefree(sshc->quote_path1);
  969. failf(data, "mkdir command failed: %s",
  970. ssh_get_error(sshc->ssh_session));
  971. state(data, SSH_SFTP_CLOSE);
  972. sshc->nextstate = SSH_NO_STATE;
  973. sshc->actualcode = CURLE_QUOTE_ERROR;
  974. break;
  975. }
  976. state(data, SSH_SFTP_NEXT_QUOTE);
  977. break;
  978. case SSH_SFTP_QUOTE_RENAME:
  979. rc = sftp_rename(sshc->sftp_session, sshc->quote_path1,
  980. sshc->quote_path2);
  981. if(rc && !sshc->acceptfail) {
  982. Curl_safefree(sshc->quote_path1);
  983. Curl_safefree(sshc->quote_path2);
  984. failf(data, "rename command failed: %s",
  985. ssh_get_error(sshc->ssh_session));
  986. state(data, SSH_SFTP_CLOSE);
  987. sshc->nextstate = SSH_NO_STATE;
  988. sshc->actualcode = CURLE_QUOTE_ERROR;
  989. break;
  990. }
  991. state(data, SSH_SFTP_NEXT_QUOTE);
  992. break;
  993. case SSH_SFTP_QUOTE_RMDIR:
  994. rc = sftp_rmdir(sshc->sftp_session, sshc->quote_path1);
  995. if(rc && !sshc->acceptfail) {
  996. Curl_safefree(sshc->quote_path1);
  997. failf(data, "rmdir command failed: %s",
  998. ssh_get_error(sshc->ssh_session));
  999. state(data, SSH_SFTP_CLOSE);
  1000. sshc->nextstate = SSH_NO_STATE;
  1001. sshc->actualcode = CURLE_QUOTE_ERROR;
  1002. break;
  1003. }
  1004. state(data, SSH_SFTP_NEXT_QUOTE);
  1005. break;
  1006. case SSH_SFTP_QUOTE_UNLINK:
  1007. rc = sftp_unlink(sshc->sftp_session, sshc->quote_path1);
  1008. if(rc && !sshc->acceptfail) {
  1009. Curl_safefree(sshc->quote_path1);
  1010. failf(data, "rm command failed: %s",
  1011. ssh_get_error(sshc->ssh_session));
  1012. state(data, SSH_SFTP_CLOSE);
  1013. sshc->nextstate = SSH_NO_STATE;
  1014. sshc->actualcode = CURLE_QUOTE_ERROR;
  1015. break;
  1016. }
  1017. state(data, SSH_SFTP_NEXT_QUOTE);
  1018. break;
  1019. case SSH_SFTP_QUOTE_STATVFS:
  1020. {
  1021. sftp_statvfs_t statvfs;
  1022. statvfs = sftp_statvfs(sshc->sftp_session, sshc->quote_path1);
  1023. if(!statvfs && !sshc->acceptfail) {
  1024. Curl_safefree(sshc->quote_path1);
  1025. failf(data, "statvfs command failed: %s",
  1026. ssh_get_error(sshc->ssh_session));
  1027. state(data, SSH_SFTP_CLOSE);
  1028. sshc->nextstate = SSH_NO_STATE;
  1029. sshc->actualcode = CURLE_QUOTE_ERROR;
  1030. break;
  1031. }
  1032. else if(statvfs) {
  1033. char *tmp = aprintf("statvfs:\n"
  1034. "f_bsize: %llu\n" "f_frsize: %llu\n"
  1035. "f_blocks: %llu\n" "f_bfree: %llu\n"
  1036. "f_bavail: %llu\n" "f_files: %llu\n"
  1037. "f_ffree: %llu\n" "f_favail: %llu\n"
  1038. "f_fsid: %llu\n" "f_flag: %llu\n"
  1039. "f_namemax: %llu\n",
  1040. statvfs->f_bsize, statvfs->f_frsize,
  1041. statvfs->f_blocks, statvfs->f_bfree,
  1042. statvfs->f_bavail, statvfs->f_files,
  1043. statvfs->f_ffree, statvfs->f_favail,
  1044. statvfs->f_fsid, statvfs->f_flag,
  1045. statvfs->f_namemax);
  1046. sftp_statvfs_free(statvfs);
  1047. if(!tmp) {
  1048. result = CURLE_OUT_OF_MEMORY;
  1049. state(data, SSH_SFTP_CLOSE);
  1050. sshc->nextstate = SSH_NO_STATE;
  1051. break;
  1052. }
  1053. result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
  1054. free(tmp);
  1055. if(result) {
  1056. state(data, SSH_SFTP_CLOSE);
  1057. sshc->nextstate = SSH_NO_STATE;
  1058. sshc->actualcode = result;
  1059. }
  1060. }
  1061. state(data, SSH_SFTP_NEXT_QUOTE);
  1062. break;
  1063. }
  1064. case SSH_SFTP_GETINFO:
  1065. if(data->set.get_filetime) {
  1066. state(data, SSH_SFTP_FILETIME);
  1067. }
  1068. else {
  1069. state(data, SSH_SFTP_TRANS_INIT);
  1070. }
  1071. break;
  1072. case SSH_SFTP_FILETIME:
  1073. {
  1074. sftp_attributes attrs;
  1075. attrs = sftp_stat(sshc->sftp_session, protop->path);
  1076. if(attrs) {
  1077. data->info.filetime = attrs->mtime;
  1078. sftp_attributes_free(attrs);
  1079. }
  1080. state(data, SSH_SFTP_TRANS_INIT);
  1081. break;
  1082. }
  1083. case SSH_SFTP_TRANS_INIT:
  1084. if(data->set.upload)
  1085. state(data, SSH_SFTP_UPLOAD_INIT);
  1086. else {
  1087. if(protop->path[strlen(protop->path)-1] == '/')
  1088. state(data, SSH_SFTP_READDIR_INIT);
  1089. else
  1090. state(data, SSH_SFTP_DOWNLOAD_INIT);
  1091. }
  1092. break;
  1093. case SSH_SFTP_UPLOAD_INIT:
  1094. {
  1095. int flags;
  1096. if(data->state.resume_from) {
  1097. sftp_attributes attrs;
  1098. if(data->state.resume_from < 0) {
  1099. attrs = sftp_stat(sshc->sftp_session, protop->path);
  1100. if(attrs) {
  1101. curl_off_t size = attrs->size;
  1102. if(size < 0) {
  1103. failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
  1104. MOVE_TO_ERROR_STATE(CURLE_BAD_DOWNLOAD_RESUME);
  1105. break;
  1106. }
  1107. data->state.resume_from = attrs->size;
  1108. sftp_attributes_free(attrs);
  1109. }
  1110. else {
  1111. data->state.resume_from = 0;
  1112. }
  1113. }
  1114. }
  1115. if(data->set.remote_append)
  1116. /* Try to open for append, but create if nonexisting */
  1117. flags = O_WRONLY|O_CREAT|O_APPEND;
  1118. else if(data->state.resume_from > 0)
  1119. /* If we have restart position then open for append */
  1120. flags = O_WRONLY|O_APPEND;
  1121. else
  1122. /* Clear file before writing (normal behavior) */
  1123. flags = O_WRONLY|O_CREAT|O_TRUNC;
  1124. if(sshc->sftp_file)
  1125. sftp_close(sshc->sftp_file);
  1126. sshc->sftp_file =
  1127. sftp_open(sshc->sftp_session, protop->path,
  1128. flags, (mode_t)data->set.new_file_perms);
  1129. if(!sshc->sftp_file) {
  1130. err = sftp_get_error(sshc->sftp_session);
  1131. if(((err == SSH_FX_NO_SUCH_FILE || err == SSH_FX_FAILURE ||
  1132. err == SSH_FX_NO_SUCH_PATH)) &&
  1133. (data->set.ftp_create_missing_dirs &&
  1134. (strlen(protop->path) > 1))) {
  1135. /* try to create the path remotely */
  1136. rc = 0;
  1137. sshc->secondCreateDirs = 1;
  1138. state(data, SSH_SFTP_CREATE_DIRS_INIT);
  1139. break;
  1140. }
  1141. else {
  1142. MOVE_TO_SFTP_CLOSE_STATE();
  1143. break;
  1144. }
  1145. }
  1146. /* If we have a restart point then we need to seek to the correct
  1147. position. */
  1148. if(data->state.resume_from > 0) {
  1149. /* Let's read off the proper amount of bytes from the input. */
  1150. if(conn->seek_func) {
  1151. Curl_set_in_callback(data, true);
  1152. seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
  1153. SEEK_SET);
  1154. Curl_set_in_callback(data, false);
  1155. }
  1156. if(seekerr != CURL_SEEKFUNC_OK) {
  1157. curl_off_t passed = 0;
  1158. if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
  1159. failf(data, "Could not seek stream");
  1160. return CURLE_FTP_COULDNT_USE_REST;
  1161. }
  1162. /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
  1163. do {
  1164. size_t readthisamountnow =
  1165. (data->state.resume_from - passed > data->set.buffer_size) ?
  1166. (size_t)data->set.buffer_size :
  1167. curlx_sotouz(data->state.resume_from - passed);
  1168. size_t actuallyread =
  1169. data->state.fread_func(data->state.buffer, 1,
  1170. readthisamountnow, data->state.in);
  1171. passed += actuallyread;
  1172. if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
  1173. /* this checks for greater-than only to make sure that the
  1174. CURL_READFUNC_ABORT return code still aborts */
  1175. failf(data, "Failed to read data");
  1176. MOVE_TO_ERROR_STATE(CURLE_FTP_COULDNT_USE_REST);
  1177. break;
  1178. }
  1179. } while(passed < data->state.resume_from);
  1180. if(rc)
  1181. break;
  1182. }
  1183. /* now, decrease the size of the read */
  1184. if(data->state.infilesize > 0) {
  1185. data->state.infilesize -= data->state.resume_from;
  1186. data->req.size = data->state.infilesize;
  1187. Curl_pgrsSetUploadSize(data, data->state.infilesize);
  1188. }
  1189. rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
  1190. if(rc) {
  1191. MOVE_TO_SFTP_CLOSE_STATE();
  1192. break;
  1193. }
  1194. }
  1195. if(data->state.infilesize > 0) {
  1196. data->req.size = data->state.infilesize;
  1197. Curl_pgrsSetUploadSize(data, data->state.infilesize);
  1198. }
  1199. /* upload data */
  1200. Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
  1201. /* not set by Curl_setup_transfer to preserve keepon bits */
  1202. conn->sockfd = conn->writesockfd;
  1203. /* store this original bitmask setup to use later on if we can't
  1204. figure out a "real" bitmask */
  1205. sshc->orig_waitfor = data->req.keepon;
  1206. /* we want to use the _sending_ function even when the socket turns
  1207. out readable as the underlying libssh sftp send function will deal
  1208. with both accordingly */
  1209. conn->cselect_bits = CURL_CSELECT_OUT;
  1210. /* since we don't really wait for anything at this point, we want the
  1211. state machine to move on as soon as possible so we set a very short
  1212. timeout here */
  1213. Curl_expire(data, 0, EXPIRE_RUN_NOW);
  1214. state(data, SSH_STOP);
  1215. break;
  1216. }
  1217. case SSH_SFTP_CREATE_DIRS_INIT:
  1218. if(strlen(protop->path) > 1) {
  1219. sshc->slash_pos = protop->path + 1; /* ignore the leading '/' */
  1220. state(data, SSH_SFTP_CREATE_DIRS);
  1221. }
  1222. else {
  1223. state(data, SSH_SFTP_UPLOAD_INIT);
  1224. }
  1225. break;
  1226. case SSH_SFTP_CREATE_DIRS:
  1227. sshc->slash_pos = strchr(sshc->slash_pos, '/');
  1228. if(sshc->slash_pos) {
  1229. *sshc->slash_pos = 0;
  1230. infof(data, "Creating directory '%s'", protop->path);
  1231. state(data, SSH_SFTP_CREATE_DIRS_MKDIR);
  1232. break;
  1233. }
  1234. state(data, SSH_SFTP_UPLOAD_INIT);
  1235. break;
  1236. case SSH_SFTP_CREATE_DIRS_MKDIR:
  1237. /* 'mode' - parameter is preliminary - default to 0644 */
  1238. rc = sftp_mkdir(sshc->sftp_session, protop->path,
  1239. (mode_t)data->set.new_directory_perms);
  1240. *sshc->slash_pos = '/';
  1241. ++sshc->slash_pos;
  1242. if(rc < 0) {
  1243. /*
  1244. * Abort if failure wasn't that the dir already exists or the
  1245. * permission was denied (creation might succeed further down the
  1246. * path) - retry on unspecific FAILURE also
  1247. */
  1248. err = sftp_get_error(sshc->sftp_session);
  1249. if((err != SSH_FX_FILE_ALREADY_EXISTS) &&
  1250. (err != SSH_FX_FAILURE) &&
  1251. (err != SSH_FX_PERMISSION_DENIED)) {
  1252. MOVE_TO_SFTP_CLOSE_STATE();
  1253. break;
  1254. }
  1255. rc = 0; /* clear rc and continue */
  1256. }
  1257. state(data, SSH_SFTP_CREATE_DIRS);
  1258. break;
  1259. case SSH_SFTP_READDIR_INIT:
  1260. Curl_pgrsSetDownloadSize(data, -1);
  1261. if(data->set.opt_no_body) {
  1262. state(data, SSH_STOP);
  1263. break;
  1264. }
  1265. /*
  1266. * This is a directory that we are trying to get, so produce a directory
  1267. * listing
  1268. */
  1269. sshc->sftp_dir = sftp_opendir(sshc->sftp_session,
  1270. protop->path);
  1271. if(!sshc->sftp_dir) {
  1272. failf(data, "Could not open directory for reading: %s",
  1273. ssh_get_error(sshc->ssh_session));
  1274. MOVE_TO_SFTP_CLOSE_STATE();
  1275. break;
  1276. }
  1277. state(data, SSH_SFTP_READDIR);
  1278. break;
  1279. case SSH_SFTP_READDIR:
  1280. if(sshc->readdir_attrs)
  1281. sftp_attributes_free(sshc->readdir_attrs);
  1282. sshc->readdir_attrs = sftp_readdir(sshc->sftp_session, sshc->sftp_dir);
  1283. if(sshc->readdir_attrs) {
  1284. sshc->readdir_filename = sshc->readdir_attrs->name;
  1285. sshc->readdir_longentry = sshc->readdir_attrs->longname;
  1286. sshc->readdir_len = strlen(sshc->readdir_filename);
  1287. if(data->set.list_only) {
  1288. char *tmpLine;
  1289. tmpLine = aprintf("%s\n", sshc->readdir_filename);
  1290. if(!tmpLine) {
  1291. state(data, SSH_SFTP_CLOSE);
  1292. sshc->actualcode = CURLE_OUT_OF_MEMORY;
  1293. break;
  1294. }
  1295. result = Curl_client_write(data, CLIENTWRITE_BODY,
  1296. tmpLine, sshc->readdir_len + 1);
  1297. free(tmpLine);
  1298. if(result) {
  1299. state(data, SSH_STOP);
  1300. break;
  1301. }
  1302. /* since this counts what we send to the client, we include the
  1303. newline in this counter */
  1304. data->req.bytecount += sshc->readdir_len + 1;
  1305. /* output debug output if that is requested */
  1306. Curl_debug(data, CURLINFO_DATA_OUT, (char *)sshc->readdir_filename,
  1307. sshc->readdir_len);
  1308. }
  1309. else {
  1310. sshc->readdir_currLen = strlen(sshc->readdir_longentry);
  1311. sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
  1312. sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
  1313. if(!sshc->readdir_line) {
  1314. state(data, SSH_SFTP_CLOSE);
  1315. sshc->actualcode = CURLE_OUT_OF_MEMORY;
  1316. break;
  1317. }
  1318. memcpy(sshc->readdir_line, sshc->readdir_longentry,
  1319. sshc->readdir_currLen);
  1320. if((sshc->readdir_attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS) &&
  1321. ((sshc->readdir_attrs->permissions & SSH_S_IFMT) ==
  1322. SSH_S_IFLNK)) {
  1323. sshc->readdir_linkPath = aprintf("%s%s", protop->path,
  1324. sshc->readdir_filename);
  1325. if(!sshc->readdir_linkPath) {
  1326. state(data, SSH_SFTP_CLOSE);
  1327. sshc->actualcode = CURLE_OUT_OF_MEMORY;
  1328. break;
  1329. }
  1330. state(data, SSH_SFTP_READDIR_LINK);
  1331. break;
  1332. }
  1333. state(data, SSH_SFTP_READDIR_BOTTOM);
  1334. break;
  1335. }
  1336. }
  1337. else if(sftp_dir_eof(sshc->sftp_dir)) {
  1338. state(data, SSH_SFTP_READDIR_DONE);
  1339. break;
  1340. }
  1341. else {
  1342. failf(data, "Could not open remote file for reading: %s",
  1343. ssh_get_error(sshc->ssh_session));
  1344. MOVE_TO_SFTP_CLOSE_STATE();
  1345. break;
  1346. }
  1347. break;
  1348. case SSH_SFTP_READDIR_LINK:
  1349. if(sshc->readdir_link_attrs)
  1350. sftp_attributes_free(sshc->readdir_link_attrs);
  1351. sshc->readdir_link_attrs = sftp_lstat(sshc->sftp_session,
  1352. sshc->readdir_linkPath);
  1353. if(sshc->readdir_link_attrs == 0) {
  1354. failf(data, "Could not read symlink for reading: %s",
  1355. ssh_get_error(sshc->ssh_session));
  1356. MOVE_TO_SFTP_CLOSE_STATE();
  1357. break;
  1358. }
  1359. if(!sshc->readdir_link_attrs->name) {
  1360. sshc->readdir_tmp = sftp_readlink(sshc->sftp_session,
  1361. sshc->readdir_linkPath);
  1362. if(!sshc->readdir_filename)
  1363. sshc->readdir_len = 0;
  1364. else
  1365. sshc->readdir_len = strlen(sshc->readdir_tmp);
  1366. sshc->readdir_longentry = NULL;
  1367. sshc->readdir_filename = sshc->readdir_tmp;
  1368. }
  1369. else {
  1370. sshc->readdir_len = strlen(sshc->readdir_link_attrs->name);
  1371. sshc->readdir_filename = sshc->readdir_link_attrs->name;
  1372. sshc->readdir_longentry = sshc->readdir_link_attrs->longname;
  1373. }
  1374. Curl_safefree(sshc->readdir_linkPath);
  1375. /* get room for the filename and extra output */
  1376. sshc->readdir_totalLen += 4 + sshc->readdir_len;
  1377. new_readdir_line = Curl_saferealloc(sshc->readdir_line,
  1378. sshc->readdir_totalLen);
  1379. if(!new_readdir_line) {
  1380. sshc->readdir_line = NULL;
  1381. state(data, SSH_SFTP_CLOSE);
  1382. sshc->actualcode = CURLE_OUT_OF_MEMORY;
  1383. break;
  1384. }
  1385. sshc->readdir_line = new_readdir_line;
  1386. sshc->readdir_currLen += msnprintf(sshc->readdir_line +
  1387. sshc->readdir_currLen,
  1388. sshc->readdir_totalLen -
  1389. sshc->readdir_currLen,
  1390. " -> %s",
  1391. sshc->readdir_filename);
  1392. sftp_attributes_free(sshc->readdir_link_attrs);
  1393. sshc->readdir_link_attrs = NULL;
  1394. sshc->readdir_filename = NULL;
  1395. sshc->readdir_longentry = NULL;
  1396. state(data, SSH_SFTP_READDIR_BOTTOM);
  1397. /* FALLTHROUGH */
  1398. case SSH_SFTP_READDIR_BOTTOM:
  1399. sshc->readdir_currLen += msnprintf(sshc->readdir_line +
  1400. sshc->readdir_currLen,
  1401. sshc->readdir_totalLen -
  1402. sshc->readdir_currLen, "\n");
  1403. result = Curl_client_write(data, CLIENTWRITE_BODY,
  1404. sshc->readdir_line,
  1405. sshc->readdir_currLen);
  1406. if(!result) {
  1407. /* output debug output if that is requested */
  1408. Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
  1409. sshc->readdir_currLen);
  1410. data->req.bytecount += sshc->readdir_currLen;
  1411. }
  1412. Curl_safefree(sshc->readdir_line);
  1413. ssh_string_free_char(sshc->readdir_tmp);
  1414. sshc->readdir_tmp = NULL;
  1415. if(result) {
  1416. state(data, SSH_STOP);
  1417. }
  1418. else
  1419. state(data, SSH_SFTP_READDIR);
  1420. break;
  1421. case SSH_SFTP_READDIR_DONE:
  1422. sftp_closedir(sshc->sftp_dir);
  1423. sshc->sftp_dir = NULL;
  1424. /* no data to transfer */
  1425. Curl_setup_transfer(data, -1, -1, FALSE, -1);
  1426. state(data, SSH_STOP);
  1427. break;
  1428. case SSH_SFTP_DOWNLOAD_INIT:
  1429. /*
  1430. * Work on getting the specified file
  1431. */
  1432. if(sshc->sftp_file)
  1433. sftp_close(sshc->sftp_file);
  1434. sshc->sftp_file = sftp_open(sshc->sftp_session, protop->path,
  1435. O_RDONLY, (mode_t)data->set.new_file_perms);
  1436. if(!sshc->sftp_file) {
  1437. failf(data, "Could not open remote file for reading: %s",
  1438. ssh_get_error(sshc->ssh_session));
  1439. MOVE_TO_SFTP_CLOSE_STATE();
  1440. break;
  1441. }
  1442. state(data, SSH_SFTP_DOWNLOAD_STAT);
  1443. break;
  1444. case SSH_SFTP_DOWNLOAD_STAT:
  1445. {
  1446. sftp_attributes attrs;
  1447. curl_off_t size;
  1448. attrs = sftp_fstat(sshc->sftp_file);
  1449. if(!attrs ||
  1450. !(attrs->flags & SSH_FILEXFER_ATTR_SIZE) ||
  1451. (attrs->size == 0)) {
  1452. /*
  1453. * sftp_fstat didn't return an error, so maybe the server
  1454. * just doesn't support stat()
  1455. * OR the server doesn't return a file size with a stat()
  1456. * OR file size is 0
  1457. */
  1458. data->req.size = -1;
  1459. data->req.maxdownload = -1;
  1460. Curl_pgrsSetDownloadSize(data, -1);
  1461. size = 0;
  1462. }
  1463. else {
  1464. size = attrs->size;
  1465. sftp_attributes_free(attrs);
  1466. if(size < 0) {
  1467. failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
  1468. return CURLE_BAD_DOWNLOAD_RESUME;
  1469. }
  1470. if(data->state.use_range) {
  1471. curl_off_t from, to;
  1472. char *ptr;
  1473. char *ptr2;
  1474. CURLofft to_t;
  1475. CURLofft from_t;
  1476. from_t = curlx_strtoofft(data->state.range, &ptr, 0, &from);
  1477. if(from_t == CURL_OFFT_FLOW) {
  1478. return CURLE_RANGE_ERROR;
  1479. }
  1480. while(*ptr && (ISBLANK(*ptr) || (*ptr == '-')))
  1481. ptr++;
  1482. to_t = curlx_strtoofft(ptr, &ptr2, 0, &to);
  1483. if(to_t == CURL_OFFT_FLOW) {
  1484. return CURLE_RANGE_ERROR;
  1485. }
  1486. if((to_t == CURL_OFFT_INVAL) /* no "to" value given */
  1487. || (to >= size)) {
  1488. to = size - 1;
  1489. }
  1490. if(from_t) {
  1491. /* from is relative to end of file */
  1492. from = size - to;
  1493. to = size - 1;
  1494. }
  1495. if(from > size) {
  1496. failf(data, "Offset (%"
  1497. CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
  1498. CURL_FORMAT_CURL_OFF_T ")", from, size);
  1499. return CURLE_BAD_DOWNLOAD_RESUME;
  1500. }
  1501. if(from > to) {
  1502. from = to;
  1503. size = 0;
  1504. }
  1505. else {
  1506. size = to - from + 1;
  1507. }
  1508. rc = sftp_seek64(sshc->sftp_file, from);
  1509. if(rc) {
  1510. MOVE_TO_SFTP_CLOSE_STATE();
  1511. break;
  1512. }
  1513. }
  1514. data->req.size = size;
  1515. data->req.maxdownload = size;
  1516. Curl_pgrsSetDownloadSize(data, size);
  1517. }
  1518. /* We can resume if we can seek to the resume position */
  1519. if(data->state.resume_from) {
  1520. if(data->state.resume_from < 0) {
  1521. /* We're supposed to download the last abs(from) bytes */
  1522. if((curl_off_t)size < -data->state.resume_from) {
  1523. failf(data, "Offset (%"
  1524. CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
  1525. CURL_FORMAT_CURL_OFF_T ")",
  1526. data->state.resume_from, size);
  1527. return CURLE_BAD_DOWNLOAD_RESUME;
  1528. }
  1529. /* download from where? */
  1530. data->state.resume_from += size;
  1531. }
  1532. else {
  1533. if((curl_off_t)size < data->state.resume_from) {
  1534. failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
  1535. ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
  1536. data->state.resume_from, size);
  1537. return CURLE_BAD_DOWNLOAD_RESUME;
  1538. }
  1539. }
  1540. /* Now store the number of bytes we are expected to download */
  1541. data->req.size = size - data->state.resume_from;
  1542. data->req.maxdownload = size - data->state.resume_from;
  1543. Curl_pgrsSetDownloadSize(data,
  1544. size - data->state.resume_from);
  1545. rc = sftp_seek64(sshc->sftp_file, data->state.resume_from);
  1546. if(rc) {
  1547. MOVE_TO_SFTP_CLOSE_STATE();
  1548. break;
  1549. }
  1550. }
  1551. }
  1552. /* Setup the actual download */
  1553. if(data->req.size == 0) {
  1554. /* no data to transfer */
  1555. Curl_setup_transfer(data, -1, -1, FALSE, -1);
  1556. infof(data, "File already completely downloaded");
  1557. state(data, SSH_STOP);
  1558. break;
  1559. }
  1560. Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
  1561. /* not set by Curl_setup_transfer to preserve keepon bits */
  1562. conn->writesockfd = conn->sockfd;
  1563. /* we want to use the _receiving_ function even when the socket turns
  1564. out writableable as the underlying libssh recv function will deal
  1565. with both accordingly */
  1566. conn->cselect_bits = CURL_CSELECT_IN;
  1567. if(result) {
  1568. /* this should never occur; the close state should be entered
  1569. at the time the error occurs */
  1570. state(data, SSH_SFTP_CLOSE);
  1571. sshc->actualcode = result;
  1572. }
  1573. else {
  1574. sshc->sftp_recv_state = 0;
  1575. state(data, SSH_STOP);
  1576. }
  1577. break;
  1578. case SSH_SFTP_CLOSE:
  1579. if(sshc->sftp_file) {
  1580. sftp_close(sshc->sftp_file);
  1581. sshc->sftp_file = NULL;
  1582. }
  1583. Curl_safefree(protop->path);
  1584. DEBUGF(infof(data, "SFTP DONE done"));
  1585. /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
  1586. After nextstate is executed, the control should come back to
  1587. SSH_SFTP_CLOSE to pass the correct result back */
  1588. if(sshc->nextstate != SSH_NO_STATE &&
  1589. sshc->nextstate != SSH_SFTP_CLOSE) {
  1590. state(data, sshc->nextstate);
  1591. sshc->nextstate = SSH_SFTP_CLOSE;
  1592. }
  1593. else {
  1594. state(data, SSH_STOP);
  1595. result = sshc->actualcode;
  1596. }
  1597. break;
  1598. case SSH_SFTP_SHUTDOWN:
  1599. /* during times we get here due to a broken transfer and then the
  1600. sftp_handle might not have been taken down so make sure that is done
  1601. before we proceed */
  1602. if(sshc->sftp_file) {
  1603. sftp_close(sshc->sftp_file);
  1604. sshc->sftp_file = NULL;
  1605. }
  1606. if(sshc->sftp_session) {
  1607. sftp_free(sshc->sftp_session);
  1608. sshc->sftp_session = NULL;
  1609. }
  1610. SSH_STRING_FREE_CHAR(sshc->homedir);
  1611. data->state.most_recent_ftp_entrypath = NULL;
  1612. state(data, SSH_SESSION_DISCONNECT);
  1613. break;
  1614. case SSH_SCP_TRANS_INIT:
  1615. result = Curl_getworkingpath(data, sshc->homedir, &protop->path);
  1616. if(result) {
  1617. sshc->actualcode = result;
  1618. state(data, SSH_STOP);
  1619. break;
  1620. }
  1621. /* Functions from the SCP subsystem cannot handle/return SSH_AGAIN */
  1622. ssh_set_blocking(sshc->ssh_session, 1);
  1623. if(data->set.upload) {
  1624. if(data->state.infilesize < 0) {
  1625. failf(data, "SCP requires a known file size for upload");
  1626. sshc->actualcode = CURLE_UPLOAD_FAILED;
  1627. MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
  1628. break;
  1629. }
  1630. sshc->scp_session =
  1631. ssh_scp_new(sshc->ssh_session, SSH_SCP_WRITE, protop->path);
  1632. state(data, SSH_SCP_UPLOAD_INIT);
  1633. }
  1634. else {
  1635. sshc->scp_session =
  1636. ssh_scp_new(sshc->ssh_session, SSH_SCP_READ, protop->path);
  1637. state(data, SSH_SCP_DOWNLOAD_INIT);
  1638. }
  1639. if(!sshc->scp_session) {
  1640. err_msg = ssh_get_error(sshc->ssh_session);
  1641. failf(data, "%s", err_msg);
  1642. MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
  1643. }
  1644. break;
  1645. case SSH_SCP_UPLOAD_INIT:
  1646. rc = ssh_scp_init(sshc->scp_session);
  1647. if(rc != SSH_OK) {
  1648. err_msg = ssh_get_error(sshc->ssh_session);
  1649. failf(data, "%s", err_msg);
  1650. MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
  1651. break;
  1652. }
  1653. rc = ssh_scp_push_file(sshc->scp_session, protop->path,
  1654. data->state.infilesize,
  1655. (int)data->set.new_file_perms);
  1656. if(rc != SSH_OK) {
  1657. err_msg = ssh_get_error(sshc->ssh_session);
  1658. failf(data, "%s", err_msg);
  1659. MOVE_TO_ERROR_STATE(CURLE_UPLOAD_FAILED);
  1660. break;
  1661. }
  1662. /* upload data */
  1663. Curl_setup_transfer(data, -1, data->req.size, FALSE, FIRSTSOCKET);
  1664. /* not set by Curl_setup_transfer to preserve keepon bits */
  1665. conn->sockfd = conn->writesockfd;
  1666. /* store this original bitmask setup to use later on if we can't
  1667. figure out a "real" bitmask */
  1668. sshc->orig_waitfor = data->req.keepon;
  1669. /* we want to use the _sending_ function even when the socket turns
  1670. out readable as the underlying libssh scp send function will deal
  1671. with both accordingly */
  1672. conn->cselect_bits = CURL_CSELECT_OUT;
  1673. state(data, SSH_STOP);
  1674. break;
  1675. case SSH_SCP_DOWNLOAD_INIT:
  1676. rc = ssh_scp_init(sshc->scp_session);
  1677. if(rc != SSH_OK) {
  1678. err_msg = ssh_get_error(sshc->ssh_session);
  1679. failf(data, "%s", err_msg);
  1680. MOVE_TO_ERROR_STATE(CURLE_COULDNT_CONNECT);
  1681. break;
  1682. }
  1683. state(data, SSH_SCP_DOWNLOAD);
  1684. /* FALLTHROUGH */
  1685. case SSH_SCP_DOWNLOAD:{
  1686. curl_off_t bytecount;
  1687. rc = ssh_scp_pull_request(sshc->scp_session);
  1688. if(rc != SSH_SCP_REQUEST_NEWFILE) {
  1689. err_msg = ssh_get_error(sshc->ssh_session);
  1690. failf(data, "%s", err_msg);
  1691. MOVE_TO_ERROR_STATE(CURLE_REMOTE_FILE_NOT_FOUND);
  1692. break;
  1693. }
  1694. /* download data */
  1695. bytecount = ssh_scp_request_get_size(sshc->scp_session);
  1696. data->req.maxdownload = (curl_off_t) bytecount;
  1697. Curl_setup_transfer(data, FIRSTSOCKET, bytecount, FALSE, -1);
  1698. /* not set by Curl_setup_transfer to preserve keepon bits */
  1699. conn->writesockfd = conn->sockfd;
  1700. /* we want to use the _receiving_ function even when the socket turns
  1701. out writableable as the underlying libssh recv function will deal
  1702. with both accordingly */
  1703. conn->cselect_bits = CURL_CSELECT_IN;
  1704. state(data, SSH_STOP);
  1705. break;
  1706. }
  1707. case SSH_SCP_DONE:
  1708. if(data->set.upload)
  1709. state(data, SSH_SCP_SEND_EOF);
  1710. else
  1711. state(data, SSH_SCP_CHANNEL_FREE);
  1712. break;
  1713. case SSH_SCP_SEND_EOF:
  1714. if(sshc->scp_session) {
  1715. rc = ssh_scp_close(sshc->scp_session);
  1716. if(rc == SSH_AGAIN) {
  1717. /* Currently the ssh_scp_close handles waiting for EOF in
  1718. * blocking way.
  1719. */
  1720. break;
  1721. }
  1722. if(rc != SSH_OK) {
  1723. infof(data, "Failed to close libssh scp channel: %s",
  1724. ssh_get_error(sshc->ssh_session));
  1725. }
  1726. }
  1727. state(data, SSH_SCP_CHANNEL_FREE);
  1728. break;
  1729. case SSH_SCP_CHANNEL_FREE:
  1730. if(sshc->scp_session) {
  1731. ssh_scp_free(sshc->scp_session);
  1732. sshc->scp_session = NULL;
  1733. }
  1734. DEBUGF(infof(data, "SCP DONE phase complete"));
  1735. ssh_set_blocking(sshc->ssh_session, 0);
  1736. state(data, SSH_SESSION_DISCONNECT);
  1737. /* FALLTHROUGH */
  1738. case SSH_SESSION_DISCONNECT:
  1739. /* during weird times when we've been prematurely aborted, the channel
  1740. is still alive when we reach this state and we MUST kill the channel
  1741. properly first */
  1742. if(sshc->scp_session) {
  1743. ssh_scp_free(sshc->scp_session);
  1744. sshc->scp_session = NULL;
  1745. }
  1746. ssh_disconnect(sshc->ssh_session);
  1747. if(!ssh_version(SSH_VERSION_INT(0, 10, 0))) {
  1748. /* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back,
  1749. explicitly mark it as closed with the memdebug macro. This libssh
  1750. bug is fixed in 0.10.0. */
  1751. fake_sclose(conn->sock[FIRSTSOCKET]);
  1752. conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;
  1753. }
  1754. SSH_STRING_FREE_CHAR(sshc->homedir);
  1755. data->state.most_recent_ftp_entrypath = NULL;
  1756. state(data, SSH_SESSION_FREE);
  1757. /* FALLTHROUGH */
  1758. case SSH_SESSION_FREE:
  1759. if(sshc->ssh_session) {
  1760. ssh_free(sshc->ssh_session);
  1761. sshc->ssh_session = NULL;
  1762. }
  1763. /* worst-case scenario cleanup */
  1764. DEBUGASSERT(sshc->ssh_session == NULL);
  1765. DEBUGASSERT(sshc->scp_session == NULL);
  1766. if(sshc->readdir_tmp) {
  1767. ssh_string_free_char(sshc->readdir_tmp);
  1768. sshc->readdir_tmp = NULL;
  1769. }
  1770. if(sshc->quote_attrs)
  1771. sftp_attributes_free(sshc->quote_attrs);
  1772. if(sshc->readdir_attrs)
  1773. sftp_attributes_free(sshc->readdir_attrs);
  1774. if(sshc->readdir_link_attrs)
  1775. sftp_attributes_free(sshc->readdir_link_attrs);
  1776. if(sshc->privkey)
  1777. ssh_key_free(sshc->privkey);
  1778. if(sshc->pubkey)
  1779. ssh_key_free(sshc->pubkey);
  1780. Curl_safefree(sshc->rsa_pub);
  1781. Curl_safefree(sshc->rsa);
  1782. Curl_safefree(sshc->quote_path1);
  1783. Curl_safefree(sshc->quote_path2);
  1784. Curl_safefree(sshc->readdir_line);
  1785. Curl_safefree(sshc->readdir_linkPath);
  1786. SSH_STRING_FREE_CHAR(sshc->homedir);
  1787. /* the code we are about to return */
  1788. result = sshc->actualcode;
  1789. memset(sshc, 0, sizeof(struct ssh_conn));
  1790. connclose(conn, "SSH session free");
  1791. sshc->state = SSH_SESSION_FREE; /* current */
  1792. sshc->nextstate = SSH_NO_STATE;
  1793. state(data, SSH_STOP);
  1794. break;
  1795. case SSH_QUIT:
  1796. /* fallthrough, just stop! */
  1797. default:
  1798. /* internal error */
  1799. sshc->nextstate = SSH_NO_STATE;
  1800. state(data, SSH_STOP);
  1801. break;
  1802. }
  1803. } while(!rc && (sshc->state != SSH_STOP));
  1804. if(rc == SSH_AGAIN) {
  1805. /* we would block, we need to wait for the socket to be ready (in the
  1806. right direction too)! */
  1807. *block = TRUE;
  1808. }
  1809. return result;
  1810. }
  1811. /* called by the multi interface to figure out what socket(s) to wait for and
  1812. for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
  1813. static int myssh_getsock(struct Curl_easy *data,
  1814. struct connectdata *conn,
  1815. curl_socket_t *sock)
  1816. {
  1817. int bitmap = GETSOCK_BLANK;
  1818. (void)data;
  1819. sock[0] = conn->sock[FIRSTSOCKET];
  1820. if(conn->waitfor & KEEP_RECV)
  1821. bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
  1822. if(conn->waitfor & KEEP_SEND)
  1823. bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
  1824. if(!conn->waitfor)
  1825. bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
  1826. return bitmap;
  1827. }
  1828. static void myssh_block2waitfor(struct connectdata *conn, bool block)
  1829. {
  1830. struct ssh_conn *sshc = &conn->proto.sshc;
  1831. /* If it didn't block, or nothing was returned by ssh_get_poll_flags
  1832. * have the original set */
  1833. conn->waitfor = sshc->orig_waitfor;
  1834. if(block) {
  1835. int dir = ssh_get_poll_flags(sshc->ssh_session);
  1836. if(dir & SSH_READ_PENDING) {
  1837. /* translate the libssh define bits into our own bit defines */
  1838. conn->waitfor = KEEP_RECV;
  1839. }
  1840. else if(dir & SSH_WRITE_PENDING) {
  1841. conn->waitfor = KEEP_SEND;
  1842. }
  1843. }
  1844. }
  1845. /* called repeatedly until done from multi.c */
  1846. static CURLcode myssh_multi_statemach(struct Curl_easy *data,
  1847. bool *done)
  1848. {
  1849. struct connectdata *conn = data->conn;
  1850. struct ssh_conn *sshc = &conn->proto.sshc;
  1851. bool block; /* we store the status and use that to provide a ssh_getsock()
  1852. implementation */
  1853. CURLcode result = myssh_statemach_act(data, &block);
  1854. *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
  1855. myssh_block2waitfor(conn, block);
  1856. return result;
  1857. }
  1858. static CURLcode myssh_block_statemach(struct Curl_easy *data,
  1859. bool disconnect)
  1860. {
  1861. struct connectdata *conn = data->conn;
  1862. struct ssh_conn *sshc = &conn->proto.sshc;
  1863. CURLcode result = CURLE_OK;
  1864. while((sshc->state != SSH_STOP) && !result) {
  1865. bool block;
  1866. timediff_t left = 1000;
  1867. struct curltime now = Curl_now();
  1868. result = myssh_statemach_act(data, &block);
  1869. if(result)
  1870. break;
  1871. if(!disconnect) {
  1872. if(Curl_pgrsUpdate(data))
  1873. return CURLE_ABORTED_BY_CALLBACK;
  1874. result = Curl_speedcheck(data, now);
  1875. if(result)
  1876. break;
  1877. left = Curl_timeleft(data, NULL, FALSE);
  1878. if(left < 0) {
  1879. failf(data, "Operation timed out");
  1880. return CURLE_OPERATION_TIMEDOUT;
  1881. }
  1882. }
  1883. if(block) {
  1884. curl_socket_t fd_read = conn->sock[FIRSTSOCKET];
  1885. /* wait for the socket to become ready */
  1886. (void) Curl_socket_check(fd_read, CURL_SOCKET_BAD,
  1887. CURL_SOCKET_BAD, left > 1000 ? 1000 : left);
  1888. }
  1889. }
  1890. return result;
  1891. }
  1892. /*
  1893. * SSH setup connection
  1894. */
  1895. static CURLcode myssh_setup_connection(struct Curl_easy *data,
  1896. struct connectdata *conn)
  1897. {
  1898. struct SSHPROTO *ssh;
  1899. (void)conn;
  1900. data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO));
  1901. if(!ssh)
  1902. return CURLE_OUT_OF_MEMORY;
  1903. return CURLE_OK;
  1904. }
  1905. static Curl_recv scp_recv, sftp_recv;
  1906. static Curl_send scp_send, sftp_send;
  1907. /*
  1908. * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
  1909. * do protocol-specific actions at connect-time.
  1910. */
  1911. static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
  1912. {
  1913. struct ssh_conn *ssh;
  1914. CURLcode result;
  1915. struct connectdata *conn = data->conn;
  1916. curl_socket_t sock = conn->sock[FIRSTSOCKET];
  1917. int rc;
  1918. /* initialize per-handle data if not already */
  1919. if(!data->req.p.ssh)
  1920. myssh_setup_connection(data, conn);
  1921. /* We default to persistent connections. We set this already in this connect
  1922. function to make the re-use checks properly be able to check this bit. */
  1923. connkeep(conn, "SSH default");
  1924. if(conn->handler->protocol & CURLPROTO_SCP) {
  1925. conn->recv[FIRSTSOCKET] = scp_recv;
  1926. conn->send[FIRSTSOCKET] = scp_send;
  1927. }
  1928. else {
  1929. conn->recv[FIRSTSOCKET] = sftp_recv;
  1930. conn->send[FIRSTSOCKET] = sftp_send;
  1931. }
  1932. ssh = &conn->proto.sshc;
  1933. ssh->ssh_session = ssh_new();
  1934. if(!ssh->ssh_session) {
  1935. failf(data, "Failure initialising ssh session");
  1936. return CURLE_FAILED_INIT;
  1937. }
  1938. rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_HOST, conn->host.name);
  1939. if(rc != SSH_OK) {
  1940. failf(data, "Could not set remote host");
  1941. return CURLE_FAILED_INIT;
  1942. }
  1943. rc = ssh_options_parse_config(ssh->ssh_session, NULL);
  1944. if(rc != SSH_OK) {
  1945. infof(data, "Could not parse SSH configuration files");
  1946. /* ignore */
  1947. }
  1948. rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_FD, &sock);
  1949. if(rc != SSH_OK) {
  1950. failf(data, "Could not set socket");
  1951. return CURLE_FAILED_INIT;
  1952. }
  1953. if(conn->user && conn->user[0] != '\0') {
  1954. infof(data, "User: %s", conn->user);
  1955. rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_USER, conn->user);
  1956. if(rc != SSH_OK) {
  1957. failf(data, "Could not set user");
  1958. return CURLE_FAILED_INIT;
  1959. }
  1960. }
  1961. if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
  1962. infof(data, "Known hosts: %s", data->set.str[STRING_SSH_KNOWNHOSTS]);
  1963. rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
  1964. data->set.str[STRING_SSH_KNOWNHOSTS]);
  1965. if(rc != SSH_OK) {
  1966. failf(data, "Could not set known hosts file path");
  1967. return CURLE_FAILED_INIT;
  1968. }
  1969. }
  1970. if(conn->remote_port) {
  1971. rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_PORT,
  1972. &conn->remote_port);
  1973. if(rc != SSH_OK) {
  1974. failf(data, "Could not set remote port");
  1975. return CURLE_FAILED_INIT;
  1976. }
  1977. }
  1978. if(data->set.ssh_compression) {
  1979. rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_COMPRESSION,
  1980. "zlib,zlib@openssh.com,none");
  1981. if(rc != SSH_OK) {
  1982. failf(data, "Could not set compression");
  1983. return CURLE_FAILED_INIT;
  1984. }
  1985. }
  1986. ssh->privkey = NULL;
  1987. ssh->pubkey = NULL;
  1988. if(data->set.str[STRING_SSH_PUBLIC_KEY]) {
  1989. rc = ssh_pki_import_pubkey_file(data->set.str[STRING_SSH_PUBLIC_KEY],
  1990. &ssh->pubkey);
  1991. if(rc != SSH_OK) {
  1992. failf(data, "Could not load public key file");
  1993. return CURLE_FAILED_INIT;
  1994. }
  1995. }
  1996. /* we do not verify here, we do it at the state machine,
  1997. * after connection */
  1998. state(data, SSH_INIT);
  1999. result = myssh_multi_statemach(data, done);
  2000. return result;
  2001. }
  2002. /* called from multi.c while DOing */
  2003. static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done)
  2004. {
  2005. CURLcode result;
  2006. result = myssh_multi_statemach(data, dophase_done);
  2007. if(*dophase_done) {
  2008. DEBUGF(infof(data, "DO phase is complete"));
  2009. }
  2010. return result;
  2011. }
  2012. /*
  2013. ***********************************************************************
  2014. *
  2015. * scp_perform()
  2016. *
  2017. * This is the actual DO function for SCP. Get a file according to
  2018. * the options previously setup.
  2019. */
  2020. static
  2021. CURLcode scp_perform(struct Curl_easy *data,
  2022. bool *connected, bool *dophase_done)
  2023. {
  2024. CURLcode result = CURLE_OK;
  2025. struct connectdata *conn = data->conn;
  2026. DEBUGF(infof(data, "DO phase starts"));
  2027. *dophase_done = FALSE; /* not done yet */
  2028. /* start the first command in the DO phase */
  2029. state(data, SSH_SCP_TRANS_INIT);
  2030. result = myssh_multi_statemach(data, dophase_done);
  2031. *connected = conn->bits.tcpconnect[FIRSTSOCKET];
  2032. if(*dophase_done) {
  2033. DEBUGF(infof(data, "DO phase is complete"));
  2034. }
  2035. return result;
  2036. }
  2037. static CURLcode myssh_do_it(struct Curl_easy *data, bool *done)
  2038. {
  2039. CURLcode result;
  2040. bool connected = 0;
  2041. struct connectdata *conn = data->conn;
  2042. struct ssh_conn *sshc = &conn->proto.sshc;
  2043. *done = FALSE; /* default to false */
  2044. data->req.size = -1; /* make sure this is unknown at this point */
  2045. sshc->actualcode = CURLE_OK; /* reset error code */
  2046. sshc->secondCreateDirs = 0; /* reset the create dir attempt state
  2047. variable */
  2048. Curl_pgrsSetUploadCounter(data, 0);
  2049. Curl_pgrsSetDownloadCounter(data, 0);
  2050. Curl_pgrsSetUploadSize(data, -1);
  2051. Curl_pgrsSetDownloadSize(data, -1);
  2052. if(conn->handler->protocol & CURLPROTO_SCP)
  2053. result = scp_perform(data, &connected, done);
  2054. else
  2055. result = sftp_perform(data, &connected, done);
  2056. return result;
  2057. }
  2058. /* BLOCKING, but the function is using the state machine so the only reason
  2059. this is still blocking is that the multi interface code has no support for
  2060. disconnecting operations that takes a while */
  2061. static CURLcode scp_disconnect(struct Curl_easy *data,
  2062. struct connectdata *conn,
  2063. bool dead_connection)
  2064. {
  2065. CURLcode result = CURLE_OK;
  2066. struct ssh_conn *ssh = &conn->proto.sshc;
  2067. (void) dead_connection;
  2068. if(ssh->ssh_session) {
  2069. /* only if there's a session still around to use! */
  2070. state(data, SSH_SESSION_DISCONNECT);
  2071. result = myssh_block_statemach(data, TRUE);
  2072. }
  2073. return result;
  2074. }
  2075. /* generic done function for both SCP and SFTP called from their specific
  2076. done functions */
  2077. static CURLcode myssh_done(struct Curl_easy *data, CURLcode status)
  2078. {
  2079. CURLcode result = CURLE_OK;
  2080. struct SSHPROTO *protop = data->req.p.ssh;
  2081. if(!status) {
  2082. /* run the state-machine */
  2083. result = myssh_block_statemach(data, FALSE);
  2084. }
  2085. else
  2086. result = status;
  2087. if(protop)
  2088. Curl_safefree(protop->path);
  2089. if(Curl_pgrsDone(data))
  2090. return CURLE_ABORTED_BY_CALLBACK;
  2091. data->req.keepon = 0; /* clear all bits */
  2092. return result;
  2093. }
  2094. static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
  2095. bool premature)
  2096. {
  2097. (void) premature; /* not used */
  2098. if(!status)
  2099. state(data, SSH_SCP_DONE);
  2100. return myssh_done(data, status);
  2101. }
  2102. static ssize_t scp_send(struct Curl_easy *data, int sockindex,
  2103. const void *mem, size_t len, CURLcode *err)
  2104. {
  2105. int rc;
  2106. struct connectdata *conn = data->conn;
  2107. (void) sockindex; /* we only support SCP on the fixed known primary socket */
  2108. (void) err;
  2109. rc = ssh_scp_write(conn->proto.sshc.scp_session, mem, len);
  2110. #if 0
  2111. /* The following code is misleading, mostly added as wishful thinking
  2112. * that libssh at some point will implement non-blocking ssh_scp_write/read.
  2113. * Currently rc can only be number of bytes read or SSH_ERROR. */
  2114. myssh_block2waitfor(conn, (rc == SSH_AGAIN) ? TRUE : FALSE);
  2115. if(rc == SSH_AGAIN) {
  2116. *err = CURLE_AGAIN;
  2117. return 0;
  2118. }
  2119. else
  2120. #endif
  2121. if(rc != SSH_OK) {
  2122. *err = CURLE_SSH;
  2123. return -1;
  2124. }
  2125. return len;
  2126. }
  2127. static ssize_t scp_recv(struct Curl_easy *data, int sockindex,
  2128. char *mem, size_t len, CURLcode *err)
  2129. {
  2130. ssize_t nread;
  2131. struct connectdata *conn = data->conn;
  2132. (void) err;
  2133. (void) sockindex; /* we only support SCP on the fixed known primary socket */
  2134. /* libssh returns int */
  2135. nread = ssh_scp_read(conn->proto.sshc.scp_session, mem, len);
  2136. #if 0
  2137. /* The following code is misleading, mostly added as wishful thinking
  2138. * that libssh at some point will implement non-blocking ssh_scp_write/read.
  2139. * Currently rc can only be SSH_OK or SSH_ERROR. */
  2140. myssh_block2waitfor(conn, (nread == SSH_AGAIN) ? TRUE : FALSE);
  2141. if(nread == SSH_AGAIN) {
  2142. *err = CURLE_AGAIN;
  2143. nread = -1;
  2144. }
  2145. #endif
  2146. return nread;
  2147. }
  2148. /*
  2149. * =============== SFTP ===============
  2150. */
  2151. /*
  2152. ***********************************************************************
  2153. *
  2154. * sftp_perform()
  2155. *
  2156. * This is the actual DO function for SFTP. Get a file/directory according to
  2157. * the options previously setup.
  2158. */
  2159. static
  2160. CURLcode sftp_perform(struct Curl_easy *data,
  2161. bool *connected,
  2162. bool *dophase_done)
  2163. {
  2164. CURLcode result = CURLE_OK;
  2165. struct connectdata *conn = data->conn;
  2166. DEBUGF(infof(data, "DO phase starts"));
  2167. *dophase_done = FALSE; /* not done yet */
  2168. /* start the first command in the DO phase */
  2169. state(data, SSH_SFTP_QUOTE_INIT);
  2170. /* run the state-machine */
  2171. result = myssh_multi_statemach(data, dophase_done);
  2172. *connected = conn->bits.tcpconnect[FIRSTSOCKET];
  2173. if(*dophase_done) {
  2174. DEBUGF(infof(data, "DO phase is complete"));
  2175. }
  2176. return result;
  2177. }
  2178. /* called from multi.c while DOing */
  2179. static CURLcode sftp_doing(struct Curl_easy *data,
  2180. bool *dophase_done)
  2181. {
  2182. CURLcode result = myssh_multi_statemach(data, dophase_done);
  2183. if(*dophase_done) {
  2184. DEBUGF(infof(data, "DO phase is complete"));
  2185. }
  2186. return result;
  2187. }
  2188. /* BLOCKING, but the function is using the state machine so the only reason
  2189. this is still blocking is that the multi interface code has no support for
  2190. disconnecting operations that takes a while */
  2191. static CURLcode sftp_disconnect(struct Curl_easy *data,
  2192. struct connectdata *conn,
  2193. bool dead_connection)
  2194. {
  2195. CURLcode result = CURLE_OK;
  2196. (void) dead_connection;
  2197. DEBUGF(infof(data, "SSH DISCONNECT starts now"));
  2198. if(conn->proto.sshc.ssh_session) {
  2199. /* only if there's a session still around to use! */
  2200. state(data, SSH_SFTP_SHUTDOWN);
  2201. result = myssh_block_statemach(data, TRUE);
  2202. }
  2203. DEBUGF(infof(data, "SSH DISCONNECT is done"));
  2204. return result;
  2205. }
  2206. static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
  2207. bool premature)
  2208. {
  2209. struct connectdata *conn = data->conn;
  2210. struct ssh_conn *sshc = &conn->proto.sshc;
  2211. if(!status) {
  2212. /* Post quote commands are executed after the SFTP_CLOSE state to avoid
  2213. errors that could happen due to open file handles during POSTQUOTE
  2214. operation */
  2215. if(!premature && data->set.postquote && !conn->bits.retry)
  2216. sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
  2217. state(data, SSH_SFTP_CLOSE);
  2218. }
  2219. return myssh_done(data, status);
  2220. }
  2221. /* return number of sent bytes */
  2222. static ssize_t sftp_send(struct Curl_easy *data, int sockindex,
  2223. const void *mem, size_t len, CURLcode *err)
  2224. {
  2225. ssize_t nwrite;
  2226. struct connectdata *conn = data->conn;
  2227. (void)sockindex;
  2228. nwrite = sftp_write(conn->proto.sshc.sftp_file, mem, len);
  2229. myssh_block2waitfor(conn, FALSE);
  2230. #if 0 /* not returned by libssh on write */
  2231. if(nwrite == SSH_AGAIN) {
  2232. *err = CURLE_AGAIN;
  2233. nwrite = 0;
  2234. }
  2235. else
  2236. #endif
  2237. if(nwrite < 0) {
  2238. *err = CURLE_SSH;
  2239. nwrite = -1;
  2240. }
  2241. return nwrite;
  2242. }
  2243. /*
  2244. * Return number of received (decrypted) bytes
  2245. * or <0 on error
  2246. */
  2247. static ssize_t sftp_recv(struct Curl_easy *data, int sockindex,
  2248. char *mem, size_t len, CURLcode *err)
  2249. {
  2250. ssize_t nread;
  2251. struct connectdata *conn = data->conn;
  2252. (void)sockindex;
  2253. DEBUGASSERT(len < CURL_MAX_READ_SIZE);
  2254. switch(conn->proto.sshc.sftp_recv_state) {
  2255. case 0:
  2256. conn->proto.sshc.sftp_file_index =
  2257. sftp_async_read_begin(conn->proto.sshc.sftp_file,
  2258. (uint32_t)len);
  2259. if(conn->proto.sshc.sftp_file_index < 0) {
  2260. *err = CURLE_RECV_ERROR;
  2261. return -1;
  2262. }
  2263. /* FALLTHROUGH */
  2264. case 1:
  2265. conn->proto.sshc.sftp_recv_state = 1;
  2266. nread = sftp_async_read(conn->proto.sshc.sftp_file,
  2267. mem, (uint32_t)len,
  2268. conn->proto.sshc.sftp_file_index);
  2269. myssh_block2waitfor(conn, (nread == SSH_AGAIN)?TRUE:FALSE);
  2270. if(nread == SSH_AGAIN) {
  2271. *err = CURLE_AGAIN;
  2272. return -1;
  2273. }
  2274. else if(nread < 0) {
  2275. *err = CURLE_RECV_ERROR;
  2276. return -1;
  2277. }
  2278. conn->proto.sshc.sftp_recv_state = 0;
  2279. return nread;
  2280. default:
  2281. /* we never reach here */
  2282. return -1;
  2283. }
  2284. }
  2285. static void sftp_quote(struct Curl_easy *data)
  2286. {
  2287. const char *cp;
  2288. struct connectdata *conn = data->conn;
  2289. struct SSHPROTO *protop = data->req.p.ssh;
  2290. struct ssh_conn *sshc = &conn->proto.sshc;
  2291. CURLcode result;
  2292. /*
  2293. * Support some of the "FTP" commands
  2294. */
  2295. char *cmd = sshc->quote_item->data;
  2296. sshc->acceptfail = FALSE;
  2297. /* if a command starts with an asterisk, which a legal SFTP command never
  2298. can, the command will be allowed to fail without it causing any
  2299. aborts or cancels etc. It will cause libcurl to act as if the command
  2300. is successful, whatever the server reponds. */
  2301. if(cmd[0] == '*') {
  2302. cmd++;
  2303. sshc->acceptfail = TRUE;
  2304. }
  2305. if(strcasecompare("pwd", cmd)) {
  2306. /* output debug output if that is requested */
  2307. char *tmp = aprintf("257 \"%s\" is current directory.\n",
  2308. protop->path);
  2309. if(!tmp) {
  2310. sshc->actualcode = CURLE_OUT_OF_MEMORY;
  2311. state(data, SSH_SFTP_CLOSE);
  2312. sshc->nextstate = SSH_NO_STATE;
  2313. return;
  2314. }
  2315. Curl_debug(data, CURLINFO_HEADER_OUT, (char *) "PWD\n", 4);
  2316. Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
  2317. /* this sends an FTP-like "header" to the header callback so that the
  2318. current directory can be read very similar to how it is read when
  2319. using ordinary FTP. */
  2320. result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
  2321. free(tmp);
  2322. if(result) {
  2323. state(data, SSH_SFTP_CLOSE);
  2324. sshc->nextstate = SSH_NO_STATE;
  2325. sshc->actualcode = result;
  2326. }
  2327. else
  2328. state(data, SSH_SFTP_NEXT_QUOTE);
  2329. return;
  2330. }
  2331. /*
  2332. * the arguments following the command must be separated from the
  2333. * command with a space so we can check for it unconditionally
  2334. */
  2335. cp = strchr(cmd, ' ');
  2336. if(!cp) {
  2337. failf(data, "Syntax error in SFTP command. Supply parameter(s)");
  2338. state(data, SSH_SFTP_CLOSE);
  2339. sshc->nextstate = SSH_NO_STATE;
  2340. sshc->actualcode = CURLE_QUOTE_ERROR;
  2341. return;
  2342. }
  2343. /*
  2344. * also, every command takes at least one argument so we get that
  2345. * first argument right now
  2346. */
  2347. result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
  2348. if(result) {
  2349. if(result == CURLE_OUT_OF_MEMORY)
  2350. failf(data, "Out of memory");
  2351. else
  2352. failf(data, "Syntax error: Bad first parameter");
  2353. state(data, SSH_SFTP_CLOSE);
  2354. sshc->nextstate = SSH_NO_STATE;
  2355. sshc->actualcode = result;
  2356. return;
  2357. }
  2358. /*
  2359. * SFTP is a binary protocol, so we don't send text commands
  2360. * to the server. Instead, we scan for commands used by
  2361. * OpenSSH's sftp program and call the appropriate libssh
  2362. * functions.
  2363. */
  2364. if(strncasecompare(cmd, "chgrp ", 6) ||
  2365. strncasecompare(cmd, "chmod ", 6) ||
  2366. strncasecompare(cmd, "chown ", 6) ||
  2367. strncasecompare(cmd, "atime ", 6) ||
  2368. strncasecompare(cmd, "mtime ", 6)) {
  2369. /* attribute change */
  2370. /* sshc->quote_path1 contains the mode to set */
  2371. /* get the destination */
  2372. result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
  2373. if(result) {
  2374. if(result == CURLE_OUT_OF_MEMORY)
  2375. failf(data, "Out of memory");
  2376. else
  2377. failf(data, "Syntax error in chgrp/chmod/chown/atime/mtime: "
  2378. "Bad second parameter");
  2379. Curl_safefree(sshc->quote_path1);
  2380. state(data, SSH_SFTP_CLOSE);
  2381. sshc->nextstate = SSH_NO_STATE;
  2382. sshc->actualcode = result;
  2383. return;
  2384. }
  2385. sshc->quote_attrs = NULL;
  2386. state(data, SSH_SFTP_QUOTE_STAT);
  2387. return;
  2388. }
  2389. if(strncasecompare(cmd, "ln ", 3) ||
  2390. strncasecompare(cmd, "symlink ", 8)) {
  2391. /* symbolic linking */
  2392. /* sshc->quote_path1 is the source */
  2393. /* get the destination */
  2394. result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
  2395. if(result) {
  2396. if(result == CURLE_OUT_OF_MEMORY)
  2397. failf(data, "Out of memory");
  2398. else
  2399. failf(data, "Syntax error in ln/symlink: Bad second parameter");
  2400. Curl_safefree(sshc->quote_path1);
  2401. state(data, SSH_SFTP_CLOSE);
  2402. sshc->nextstate = SSH_NO_STATE;
  2403. sshc->actualcode = result;
  2404. return;
  2405. }
  2406. state(data, SSH_SFTP_QUOTE_SYMLINK);
  2407. return;
  2408. }
  2409. else if(strncasecompare(cmd, "mkdir ", 6)) {
  2410. /* create dir */
  2411. state(data, SSH_SFTP_QUOTE_MKDIR);
  2412. return;
  2413. }
  2414. else if(strncasecompare(cmd, "rename ", 7)) {
  2415. /* rename file */
  2416. /* first param is the source path */
  2417. /* second param is the dest. path */
  2418. result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
  2419. if(result) {
  2420. if(result == CURLE_OUT_OF_MEMORY)
  2421. failf(data, "Out of memory");
  2422. else
  2423. failf(data, "Syntax error in rename: Bad second parameter");
  2424. Curl_safefree(sshc->quote_path1);
  2425. state(data, SSH_SFTP_CLOSE);
  2426. sshc->nextstate = SSH_NO_STATE;
  2427. sshc->actualcode = result;
  2428. return;
  2429. }
  2430. state(data, SSH_SFTP_QUOTE_RENAME);
  2431. return;
  2432. }
  2433. else if(strncasecompare(cmd, "rmdir ", 6)) {
  2434. /* delete dir */
  2435. state(data, SSH_SFTP_QUOTE_RMDIR);
  2436. return;
  2437. }
  2438. else if(strncasecompare(cmd, "rm ", 3)) {
  2439. state(data, SSH_SFTP_QUOTE_UNLINK);
  2440. return;
  2441. }
  2442. #ifdef HAS_STATVFS_SUPPORT
  2443. else if(strncasecompare(cmd, "statvfs ", 8)) {
  2444. state(data, SSH_SFTP_QUOTE_STATVFS);
  2445. return;
  2446. }
  2447. #endif
  2448. failf(data, "Unknown SFTP command");
  2449. Curl_safefree(sshc->quote_path1);
  2450. Curl_safefree(sshc->quote_path2);
  2451. state(data, SSH_SFTP_CLOSE);
  2452. sshc->nextstate = SSH_NO_STATE;
  2453. sshc->actualcode = CURLE_QUOTE_ERROR;
  2454. }
  2455. static void sftp_quote_stat(struct Curl_easy *data)
  2456. {
  2457. struct connectdata *conn = data->conn;
  2458. struct ssh_conn *sshc = &conn->proto.sshc;
  2459. char *cmd = sshc->quote_item->data;
  2460. sshc->acceptfail = FALSE;
  2461. /* if a command starts with an asterisk, which a legal SFTP command never
  2462. can, the command will be allowed to fail without it causing any
  2463. aborts or cancels etc. It will cause libcurl to act as if the command
  2464. is successful, whatever the server reponds. */
  2465. if(cmd[0] == '*') {
  2466. cmd++;
  2467. sshc->acceptfail = TRUE;
  2468. }
  2469. /* We read the file attributes, store them in sshc->quote_attrs
  2470. * and modify them accordingly to command. Then we switch to
  2471. * QUOTE_SETSTAT state to write new ones.
  2472. */
  2473. if(sshc->quote_attrs)
  2474. sftp_attributes_free(sshc->quote_attrs);
  2475. sshc->quote_attrs = sftp_stat(sshc->sftp_session, sshc->quote_path2);
  2476. if(!sshc->quote_attrs) {
  2477. Curl_safefree(sshc->quote_path1);
  2478. Curl_safefree(sshc->quote_path2);
  2479. failf(data, "Attempt to get SFTP stats failed: %d",
  2480. sftp_get_error(sshc->sftp_session));
  2481. state(data, SSH_SFTP_CLOSE);
  2482. sshc->nextstate = SSH_NO_STATE;
  2483. sshc->actualcode = CURLE_QUOTE_ERROR;
  2484. return;
  2485. }
  2486. /* Now set the new attributes... */
  2487. if(strncasecompare(cmd, "chgrp", 5)) {
  2488. sshc->quote_attrs->gid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
  2489. if(sshc->quote_attrs->gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
  2490. !sshc->acceptfail) {
  2491. Curl_safefree(sshc->quote_path1);
  2492. Curl_safefree(sshc->quote_path2);
  2493. failf(data, "Syntax error: chgrp gid not a number");
  2494. state(data, SSH_SFTP_CLOSE);
  2495. sshc->nextstate = SSH_NO_STATE;
  2496. sshc->actualcode = CURLE_QUOTE_ERROR;
  2497. return;
  2498. }
  2499. sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
  2500. }
  2501. else if(strncasecompare(cmd, "chmod", 5)) {
  2502. mode_t perms;
  2503. perms = (mode_t)strtoul(sshc->quote_path1, NULL, 8);
  2504. /* permissions are octal */
  2505. if(perms == 0 && !ISDIGIT(sshc->quote_path1[0])) {
  2506. Curl_safefree(sshc->quote_path1);
  2507. Curl_safefree(sshc->quote_path2);
  2508. failf(data, "Syntax error: chmod permissions not a number");
  2509. state(data, SSH_SFTP_CLOSE);
  2510. sshc->nextstate = SSH_NO_STATE;
  2511. sshc->actualcode = CURLE_QUOTE_ERROR;
  2512. return;
  2513. }
  2514. sshc->quote_attrs->permissions = perms;
  2515. sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_PERMISSIONS;
  2516. }
  2517. else if(strncasecompare(cmd, "chown", 5)) {
  2518. sshc->quote_attrs->uid = (uint32_t)strtoul(sshc->quote_path1, NULL, 10);
  2519. if(sshc->quote_attrs->uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
  2520. !sshc->acceptfail) {
  2521. Curl_safefree(sshc->quote_path1);
  2522. Curl_safefree(sshc->quote_path2);
  2523. failf(data, "Syntax error: chown uid not a number");
  2524. state(data, SSH_SFTP_CLOSE);
  2525. sshc->nextstate = SSH_NO_STATE;
  2526. sshc->actualcode = CURLE_QUOTE_ERROR;
  2527. return;
  2528. }
  2529. sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_UIDGID;
  2530. }
  2531. else if(strncasecompare(cmd, "atime", 5) ||
  2532. strncasecompare(cmd, "mtime", 5)) {
  2533. time_t date = Curl_getdate_capped(sshc->quote_path1);
  2534. bool fail = FALSE;
  2535. if(date == -1) {
  2536. failf(data, "incorrect date format for %.*s", 5, cmd);
  2537. fail = TRUE;
  2538. }
  2539. #if SIZEOF_TIME_T > 4
  2540. else if(date > 0xffffffff) {
  2541. failf(data, "date overflow");
  2542. fail = TRUE; /* avoid setting a capped time */
  2543. }
  2544. #endif
  2545. if(fail) {
  2546. Curl_safefree(sshc->quote_path1);
  2547. Curl_safefree(sshc->quote_path2);
  2548. state(data, SSH_SFTP_CLOSE);
  2549. sshc->nextstate = SSH_NO_STATE;
  2550. sshc->actualcode = CURLE_QUOTE_ERROR;
  2551. return;
  2552. }
  2553. if(strncasecompare(cmd, "atime", 5))
  2554. sshc->quote_attrs->atime = (uint32_t)date;
  2555. else /* mtime */
  2556. sshc->quote_attrs->mtime = (uint32_t)date;
  2557. sshc->quote_attrs->flags |= SSH_FILEXFER_ATTR_ACMODTIME;
  2558. }
  2559. /* Now send the completed structure... */
  2560. state(data, SSH_SFTP_QUOTE_SETSTAT);
  2561. return;
  2562. }
  2563. CURLcode Curl_ssh_init(void)
  2564. {
  2565. if(ssh_init()) {
  2566. DEBUGF(fprintf(stderr, "Error: libssh_init failed\n"));
  2567. return CURLE_FAILED_INIT;
  2568. }
  2569. return CURLE_OK;
  2570. }
  2571. void Curl_ssh_cleanup(void)
  2572. {
  2573. (void)ssh_finalize();
  2574. }
  2575. void Curl_ssh_version(char *buffer, size_t buflen)
  2576. {
  2577. (void)msnprintf(buffer, buflen, "libssh/%s", ssh_version(0));
  2578. }
  2579. #endif /* USE_LIBSSH */