libssh.c 94 KB

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