113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci#include "curl_setup.h" 2613498266Sopenharmony_ci 2713498266Sopenharmony_ci#ifdef USE_WOLFSSH 2813498266Sopenharmony_ci 2913498266Sopenharmony_ci#include <limits.h> 3013498266Sopenharmony_ci 3113498266Sopenharmony_ci#include <wolfssh/ssh.h> 3213498266Sopenharmony_ci#include <wolfssh/wolfsftp.h> 3313498266Sopenharmony_ci#include "urldata.h" 3413498266Sopenharmony_ci#include "cfilters.h" 3513498266Sopenharmony_ci#include "connect.h" 3613498266Sopenharmony_ci#include "sendf.h" 3713498266Sopenharmony_ci#include "progress.h" 3813498266Sopenharmony_ci#include "curl_path.h" 3913498266Sopenharmony_ci#include "strtoofft.h" 4013498266Sopenharmony_ci#include "transfer.h" 4113498266Sopenharmony_ci#include "speedcheck.h" 4213498266Sopenharmony_ci#include "select.h" 4313498266Sopenharmony_ci#include "multiif.h" 4413498266Sopenharmony_ci#include "warnless.h" 4513498266Sopenharmony_ci#include "strdup.h" 4613498266Sopenharmony_ci 4713498266Sopenharmony_ci/* The last 3 #include files should be in this order */ 4813498266Sopenharmony_ci#include "curl_printf.h" 4913498266Sopenharmony_ci#include "curl_memory.h" 5013498266Sopenharmony_ci#include "memdebug.h" 5113498266Sopenharmony_ci 5213498266Sopenharmony_cistatic CURLcode wssh_connect(struct Curl_easy *data, bool *done); 5313498266Sopenharmony_cistatic CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done); 5413498266Sopenharmony_cistatic CURLcode wssh_do(struct Curl_easy *data, bool *done); 5513498266Sopenharmony_ci#if 0 5613498266Sopenharmony_cistatic CURLcode wscp_done(struct Curl_easy *data, 5713498266Sopenharmony_ci CURLcode, bool premature); 5813498266Sopenharmony_cistatic CURLcode wscp_doing(struct Curl_easy *data, 5913498266Sopenharmony_ci bool *dophase_done); 6013498266Sopenharmony_cistatic CURLcode wscp_disconnect(struct Curl_easy *data, 6113498266Sopenharmony_ci struct connectdata *conn, 6213498266Sopenharmony_ci bool dead_connection); 6313498266Sopenharmony_ci#endif 6413498266Sopenharmony_cistatic CURLcode wsftp_done(struct Curl_easy *data, 6513498266Sopenharmony_ci CURLcode, bool premature); 6613498266Sopenharmony_cistatic CURLcode wsftp_doing(struct Curl_easy *data, 6713498266Sopenharmony_ci bool *dophase_done); 6813498266Sopenharmony_cistatic CURLcode wsftp_disconnect(struct Curl_easy *data, 6913498266Sopenharmony_ci struct connectdata *conn, 7013498266Sopenharmony_ci bool dead); 7113498266Sopenharmony_cistatic int wssh_getsock(struct Curl_easy *data, 7213498266Sopenharmony_ci struct connectdata *conn, 7313498266Sopenharmony_ci curl_socket_t *sock); 7413498266Sopenharmony_cistatic CURLcode wssh_setup_connection(struct Curl_easy *data, 7513498266Sopenharmony_ci struct connectdata *conn); 7613498266Sopenharmony_ci 7713498266Sopenharmony_ci#if 0 7813498266Sopenharmony_ci/* 7913498266Sopenharmony_ci * SCP protocol handler. 8013498266Sopenharmony_ci */ 8113498266Sopenharmony_ci 8213498266Sopenharmony_ciconst struct Curl_handler Curl_handler_scp = { 8313498266Sopenharmony_ci "SCP", /* scheme */ 8413498266Sopenharmony_ci wssh_setup_connection, /* setup_connection */ 8513498266Sopenharmony_ci wssh_do, /* do_it */ 8613498266Sopenharmony_ci wscp_done, /* done */ 8713498266Sopenharmony_ci ZERO_NULL, /* do_more */ 8813498266Sopenharmony_ci wssh_connect, /* connect_it */ 8913498266Sopenharmony_ci wssh_multi_statemach, /* connecting */ 9013498266Sopenharmony_ci wscp_doing, /* doing */ 9113498266Sopenharmony_ci wssh_getsock, /* proto_getsock */ 9213498266Sopenharmony_ci wssh_getsock, /* doing_getsock */ 9313498266Sopenharmony_ci ZERO_NULL, /* domore_getsock */ 9413498266Sopenharmony_ci wssh_getsock, /* perform_getsock */ 9513498266Sopenharmony_ci wscp_disconnect, /* disconnect */ 9613498266Sopenharmony_ci ZERO_NULL, /* write_resp */ 9713498266Sopenharmony_ci ZERO_NULL, /* connection_check */ 9813498266Sopenharmony_ci ZERO_NULL, /* attach connection */ 9913498266Sopenharmony_ci PORT_SSH, /* defport */ 10013498266Sopenharmony_ci CURLPROTO_SCP, /* protocol */ 10113498266Sopenharmony_ci PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION 10213498266Sopenharmony_ci | PROTOPT_NOURLQUERY /* flags */ 10313498266Sopenharmony_ci}; 10413498266Sopenharmony_ci 10513498266Sopenharmony_ci#endif 10613498266Sopenharmony_ci 10713498266Sopenharmony_ci/* 10813498266Sopenharmony_ci * SFTP protocol handler. 10913498266Sopenharmony_ci */ 11013498266Sopenharmony_ci 11113498266Sopenharmony_ciconst struct Curl_handler Curl_handler_sftp = { 11213498266Sopenharmony_ci "SFTP", /* scheme */ 11313498266Sopenharmony_ci wssh_setup_connection, /* setup_connection */ 11413498266Sopenharmony_ci wssh_do, /* do_it */ 11513498266Sopenharmony_ci wsftp_done, /* done */ 11613498266Sopenharmony_ci ZERO_NULL, /* do_more */ 11713498266Sopenharmony_ci wssh_connect, /* connect_it */ 11813498266Sopenharmony_ci wssh_multi_statemach, /* connecting */ 11913498266Sopenharmony_ci wsftp_doing, /* doing */ 12013498266Sopenharmony_ci wssh_getsock, /* proto_getsock */ 12113498266Sopenharmony_ci wssh_getsock, /* doing_getsock */ 12213498266Sopenharmony_ci ZERO_NULL, /* domore_getsock */ 12313498266Sopenharmony_ci wssh_getsock, /* perform_getsock */ 12413498266Sopenharmony_ci wsftp_disconnect, /* disconnect */ 12513498266Sopenharmony_ci ZERO_NULL, /* write_resp */ 12613498266Sopenharmony_ci ZERO_NULL, /* connection_check */ 12713498266Sopenharmony_ci ZERO_NULL, /* attach connection */ 12813498266Sopenharmony_ci PORT_SSH, /* defport */ 12913498266Sopenharmony_ci CURLPROTO_SFTP, /* protocol */ 13013498266Sopenharmony_ci CURLPROTO_SFTP, /* family */ 13113498266Sopenharmony_ci PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION 13213498266Sopenharmony_ci | PROTOPT_NOURLQUERY /* flags */ 13313498266Sopenharmony_ci}; 13413498266Sopenharmony_ci 13513498266Sopenharmony_ci/* 13613498266Sopenharmony_ci * SSH State machine related code 13713498266Sopenharmony_ci */ 13813498266Sopenharmony_ci/* This is the ONLY way to change SSH state! */ 13913498266Sopenharmony_cistatic void state(struct Curl_easy *data, sshstate nowstate) 14013498266Sopenharmony_ci{ 14113498266Sopenharmony_ci struct connectdata *conn = data->conn; 14213498266Sopenharmony_ci struct ssh_conn *sshc = &conn->proto.sshc; 14313498266Sopenharmony_ci#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 14413498266Sopenharmony_ci /* for debug purposes */ 14513498266Sopenharmony_ci static const char * const names[] = { 14613498266Sopenharmony_ci "SSH_STOP", 14713498266Sopenharmony_ci "SSH_INIT", 14813498266Sopenharmony_ci "SSH_S_STARTUP", 14913498266Sopenharmony_ci "SSH_HOSTKEY", 15013498266Sopenharmony_ci "SSH_AUTHLIST", 15113498266Sopenharmony_ci "SSH_AUTH_PKEY_INIT", 15213498266Sopenharmony_ci "SSH_AUTH_PKEY", 15313498266Sopenharmony_ci "SSH_AUTH_PASS_INIT", 15413498266Sopenharmony_ci "SSH_AUTH_PASS", 15513498266Sopenharmony_ci "SSH_AUTH_AGENT_INIT", 15613498266Sopenharmony_ci "SSH_AUTH_AGENT_LIST", 15713498266Sopenharmony_ci "SSH_AUTH_AGENT", 15813498266Sopenharmony_ci "SSH_AUTH_HOST_INIT", 15913498266Sopenharmony_ci "SSH_AUTH_HOST", 16013498266Sopenharmony_ci "SSH_AUTH_KEY_INIT", 16113498266Sopenharmony_ci "SSH_AUTH_KEY", 16213498266Sopenharmony_ci "SSH_AUTH_GSSAPI", 16313498266Sopenharmony_ci "SSH_AUTH_DONE", 16413498266Sopenharmony_ci "SSH_SFTP_INIT", 16513498266Sopenharmony_ci "SSH_SFTP_REALPATH", 16613498266Sopenharmony_ci "SSH_SFTP_QUOTE_INIT", 16713498266Sopenharmony_ci "SSH_SFTP_POSTQUOTE_INIT", 16813498266Sopenharmony_ci "SSH_SFTP_QUOTE", 16913498266Sopenharmony_ci "SSH_SFTP_NEXT_QUOTE", 17013498266Sopenharmony_ci "SSH_SFTP_QUOTE_STAT", 17113498266Sopenharmony_ci "SSH_SFTP_QUOTE_SETSTAT", 17213498266Sopenharmony_ci "SSH_SFTP_QUOTE_SYMLINK", 17313498266Sopenharmony_ci "SSH_SFTP_QUOTE_MKDIR", 17413498266Sopenharmony_ci "SSH_SFTP_QUOTE_RENAME", 17513498266Sopenharmony_ci "SSH_SFTP_QUOTE_RMDIR", 17613498266Sopenharmony_ci "SSH_SFTP_QUOTE_UNLINK", 17713498266Sopenharmony_ci "SSH_SFTP_QUOTE_STATVFS", 17813498266Sopenharmony_ci "SSH_SFTP_GETINFO", 17913498266Sopenharmony_ci "SSH_SFTP_FILETIME", 18013498266Sopenharmony_ci "SSH_SFTP_TRANS_INIT", 18113498266Sopenharmony_ci "SSH_SFTP_UPLOAD_INIT", 18213498266Sopenharmony_ci "SSH_SFTP_CREATE_DIRS_INIT", 18313498266Sopenharmony_ci "SSH_SFTP_CREATE_DIRS", 18413498266Sopenharmony_ci "SSH_SFTP_CREATE_DIRS_MKDIR", 18513498266Sopenharmony_ci "SSH_SFTP_READDIR_INIT", 18613498266Sopenharmony_ci "SSH_SFTP_READDIR", 18713498266Sopenharmony_ci "SSH_SFTP_READDIR_LINK", 18813498266Sopenharmony_ci "SSH_SFTP_READDIR_BOTTOM", 18913498266Sopenharmony_ci "SSH_SFTP_READDIR_DONE", 19013498266Sopenharmony_ci "SSH_SFTP_DOWNLOAD_INIT", 19113498266Sopenharmony_ci "SSH_SFTP_DOWNLOAD_STAT", 19213498266Sopenharmony_ci "SSH_SFTP_CLOSE", 19313498266Sopenharmony_ci "SSH_SFTP_SHUTDOWN", 19413498266Sopenharmony_ci "SSH_SCP_TRANS_INIT", 19513498266Sopenharmony_ci "SSH_SCP_UPLOAD_INIT", 19613498266Sopenharmony_ci "SSH_SCP_DOWNLOAD_INIT", 19713498266Sopenharmony_ci "SSH_SCP_DOWNLOAD", 19813498266Sopenharmony_ci "SSH_SCP_DONE", 19913498266Sopenharmony_ci "SSH_SCP_SEND_EOF", 20013498266Sopenharmony_ci "SSH_SCP_WAIT_EOF", 20113498266Sopenharmony_ci "SSH_SCP_WAIT_CLOSE", 20213498266Sopenharmony_ci "SSH_SCP_CHANNEL_FREE", 20313498266Sopenharmony_ci "SSH_SESSION_DISCONNECT", 20413498266Sopenharmony_ci "SSH_SESSION_FREE", 20513498266Sopenharmony_ci "QUIT" 20613498266Sopenharmony_ci }; 20713498266Sopenharmony_ci 20813498266Sopenharmony_ci /* a precaution to make sure the lists are in sync */ 20913498266Sopenharmony_ci DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); 21013498266Sopenharmony_ci 21113498266Sopenharmony_ci if(sshc->state != nowstate) { 21213498266Sopenharmony_ci infof(data, "wolfssh %p state change from %s to %s", 21313498266Sopenharmony_ci (void *)sshc, names[sshc->state], names[nowstate]); 21413498266Sopenharmony_ci } 21513498266Sopenharmony_ci#endif 21613498266Sopenharmony_ci 21713498266Sopenharmony_ci sshc->state = nowstate; 21813498266Sopenharmony_ci} 21913498266Sopenharmony_ci 22013498266Sopenharmony_cistatic ssize_t wscp_send(struct Curl_easy *data, int sockindex, 22113498266Sopenharmony_ci const void *mem, size_t len, CURLcode *err) 22213498266Sopenharmony_ci{ 22313498266Sopenharmony_ci ssize_t nwrite = 0; 22413498266Sopenharmony_ci (void)data; 22513498266Sopenharmony_ci (void)sockindex; /* we only support SCP on the fixed known primary socket */ 22613498266Sopenharmony_ci (void)mem; 22713498266Sopenharmony_ci (void)len; 22813498266Sopenharmony_ci (void)err; 22913498266Sopenharmony_ci 23013498266Sopenharmony_ci return nwrite; 23113498266Sopenharmony_ci} 23213498266Sopenharmony_ci 23313498266Sopenharmony_cistatic ssize_t wscp_recv(struct Curl_easy *data, int sockindex, 23413498266Sopenharmony_ci char *mem, size_t len, CURLcode *err) 23513498266Sopenharmony_ci{ 23613498266Sopenharmony_ci ssize_t nread = 0; 23713498266Sopenharmony_ci (void)data; 23813498266Sopenharmony_ci (void)sockindex; /* we only support SCP on the fixed known primary socket */ 23913498266Sopenharmony_ci (void)mem; 24013498266Sopenharmony_ci (void)len; 24113498266Sopenharmony_ci (void)err; 24213498266Sopenharmony_ci 24313498266Sopenharmony_ci return nread; 24413498266Sopenharmony_ci} 24513498266Sopenharmony_ci 24613498266Sopenharmony_ci/* return number of sent bytes */ 24713498266Sopenharmony_cistatic ssize_t wsftp_send(struct Curl_easy *data, int sockindex, 24813498266Sopenharmony_ci const void *mem, size_t len, CURLcode *err) 24913498266Sopenharmony_ci{ 25013498266Sopenharmony_ci struct connectdata *conn = data->conn; 25113498266Sopenharmony_ci struct ssh_conn *sshc = &conn->proto.sshc; 25213498266Sopenharmony_ci word32 offset[2]; 25313498266Sopenharmony_ci int rc; 25413498266Sopenharmony_ci (void)sockindex; 25513498266Sopenharmony_ci 25613498266Sopenharmony_ci offset[0] = (word32)sshc->offset&0xFFFFFFFF; 25713498266Sopenharmony_ci offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF; 25813498266Sopenharmony_ci 25913498266Sopenharmony_ci rc = wolfSSH_SFTP_SendWritePacket(sshc->ssh_session, sshc->handle, 26013498266Sopenharmony_ci sshc->handleSz, 26113498266Sopenharmony_ci &offset[0], 26213498266Sopenharmony_ci (byte *)mem, (word32)len); 26313498266Sopenharmony_ci 26413498266Sopenharmony_ci if(rc == WS_FATAL_ERROR) 26513498266Sopenharmony_ci rc = wolfSSH_get_error(sshc->ssh_session); 26613498266Sopenharmony_ci if(rc == WS_WANT_READ) { 26713498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 26813498266Sopenharmony_ci *err = CURLE_AGAIN; 26913498266Sopenharmony_ci return -1; 27013498266Sopenharmony_ci } 27113498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 27213498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 27313498266Sopenharmony_ci *err = CURLE_AGAIN; 27413498266Sopenharmony_ci return -1; 27513498266Sopenharmony_ci } 27613498266Sopenharmony_ci if(rc < 0) { 27713498266Sopenharmony_ci failf(data, "wolfSSH_SFTP_SendWritePacket returned %d", rc); 27813498266Sopenharmony_ci return -1; 27913498266Sopenharmony_ci } 28013498266Sopenharmony_ci DEBUGASSERT(rc == (int)len); 28113498266Sopenharmony_ci infof(data, "sent %zu bytes SFTP from offset %" CURL_FORMAT_CURL_OFF_T, 28213498266Sopenharmony_ci len, sshc->offset); 28313498266Sopenharmony_ci sshc->offset += len; 28413498266Sopenharmony_ci return (ssize_t)rc; 28513498266Sopenharmony_ci} 28613498266Sopenharmony_ci 28713498266Sopenharmony_ci/* 28813498266Sopenharmony_ci * Return number of received (decrypted) bytes 28913498266Sopenharmony_ci * or <0 on error 29013498266Sopenharmony_ci */ 29113498266Sopenharmony_cistatic ssize_t wsftp_recv(struct Curl_easy *data, int sockindex, 29213498266Sopenharmony_ci char *mem, size_t len, CURLcode *err) 29313498266Sopenharmony_ci{ 29413498266Sopenharmony_ci int rc; 29513498266Sopenharmony_ci struct connectdata *conn = data->conn; 29613498266Sopenharmony_ci struct ssh_conn *sshc = &conn->proto.sshc; 29713498266Sopenharmony_ci word32 offset[2]; 29813498266Sopenharmony_ci (void)sockindex; 29913498266Sopenharmony_ci 30013498266Sopenharmony_ci offset[0] = (word32)sshc->offset&0xFFFFFFFF; 30113498266Sopenharmony_ci offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF; 30213498266Sopenharmony_ci 30313498266Sopenharmony_ci rc = wolfSSH_SFTP_SendReadPacket(sshc->ssh_session, sshc->handle, 30413498266Sopenharmony_ci sshc->handleSz, 30513498266Sopenharmony_ci &offset[0], 30613498266Sopenharmony_ci (byte *)mem, (word32)len); 30713498266Sopenharmony_ci if(rc == WS_FATAL_ERROR) 30813498266Sopenharmony_ci rc = wolfSSH_get_error(sshc->ssh_session); 30913498266Sopenharmony_ci if(rc == WS_WANT_READ) { 31013498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 31113498266Sopenharmony_ci *err = CURLE_AGAIN; 31213498266Sopenharmony_ci return -1; 31313498266Sopenharmony_ci } 31413498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 31513498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 31613498266Sopenharmony_ci *err = CURLE_AGAIN; 31713498266Sopenharmony_ci return -1; 31813498266Sopenharmony_ci } 31913498266Sopenharmony_ci 32013498266Sopenharmony_ci DEBUGASSERT(rc <= (int)len); 32113498266Sopenharmony_ci 32213498266Sopenharmony_ci if(rc < 0) { 32313498266Sopenharmony_ci failf(data, "wolfSSH_SFTP_SendReadPacket returned %d", rc); 32413498266Sopenharmony_ci return -1; 32513498266Sopenharmony_ci } 32613498266Sopenharmony_ci sshc->offset += len; 32713498266Sopenharmony_ci 32813498266Sopenharmony_ci return (ssize_t)rc; 32913498266Sopenharmony_ci} 33013498266Sopenharmony_ci 33113498266Sopenharmony_ci/* 33213498266Sopenharmony_ci * SSH setup and connection 33313498266Sopenharmony_ci */ 33413498266Sopenharmony_cistatic CURLcode wssh_setup_connection(struct Curl_easy *data, 33513498266Sopenharmony_ci struct connectdata *conn) 33613498266Sopenharmony_ci{ 33713498266Sopenharmony_ci struct SSHPROTO *ssh; 33813498266Sopenharmony_ci (void)conn; 33913498266Sopenharmony_ci 34013498266Sopenharmony_ci data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); 34113498266Sopenharmony_ci if(!ssh) 34213498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 34313498266Sopenharmony_ci 34413498266Sopenharmony_ci return CURLE_OK; 34513498266Sopenharmony_ci} 34613498266Sopenharmony_ci 34713498266Sopenharmony_cistatic int userauth(byte authtype, 34813498266Sopenharmony_ci WS_UserAuthData* authdata, 34913498266Sopenharmony_ci void *ctx) 35013498266Sopenharmony_ci{ 35113498266Sopenharmony_ci struct Curl_easy *data = ctx; 35213498266Sopenharmony_ci DEBUGF(infof(data, "wolfssh callback: type %s", 35313498266Sopenharmony_ci authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" : 35413498266Sopenharmony_ci "PUBLICCKEY")); 35513498266Sopenharmony_ci if(authtype == WOLFSSH_USERAUTH_PASSWORD) { 35613498266Sopenharmony_ci authdata->sf.password.password = (byte *)data->conn->passwd; 35713498266Sopenharmony_ci authdata->sf.password.passwordSz = (word32) strlen(data->conn->passwd); 35813498266Sopenharmony_ci } 35913498266Sopenharmony_ci 36013498266Sopenharmony_ci return 0; 36113498266Sopenharmony_ci} 36213498266Sopenharmony_ci 36313498266Sopenharmony_cistatic CURLcode wssh_connect(struct Curl_easy *data, bool *done) 36413498266Sopenharmony_ci{ 36513498266Sopenharmony_ci struct connectdata *conn = data->conn; 36613498266Sopenharmony_ci struct ssh_conn *sshc; 36713498266Sopenharmony_ci curl_socket_t sock = conn->sock[FIRSTSOCKET]; 36813498266Sopenharmony_ci int rc; 36913498266Sopenharmony_ci 37013498266Sopenharmony_ci /* initialize per-handle data if not already */ 37113498266Sopenharmony_ci if(!data->req.p.ssh) 37213498266Sopenharmony_ci wssh_setup_connection(data, conn); 37313498266Sopenharmony_ci 37413498266Sopenharmony_ci /* We default to persistent connections. We set this already in this connect 37513498266Sopenharmony_ci function to make the reuse checks properly be able to check this bit. */ 37613498266Sopenharmony_ci connkeep(conn, "SSH default"); 37713498266Sopenharmony_ci 37813498266Sopenharmony_ci if(conn->handler->protocol & CURLPROTO_SCP) { 37913498266Sopenharmony_ci conn->recv[FIRSTSOCKET] = wscp_recv; 38013498266Sopenharmony_ci conn->send[FIRSTSOCKET] = wscp_send; 38113498266Sopenharmony_ci } 38213498266Sopenharmony_ci else { 38313498266Sopenharmony_ci conn->recv[FIRSTSOCKET] = wsftp_recv; 38413498266Sopenharmony_ci conn->send[FIRSTSOCKET] = wsftp_send; 38513498266Sopenharmony_ci } 38613498266Sopenharmony_ci sshc = &conn->proto.sshc; 38713498266Sopenharmony_ci sshc->ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL); 38813498266Sopenharmony_ci if(!sshc->ctx) { 38913498266Sopenharmony_ci failf(data, "No wolfSSH context"); 39013498266Sopenharmony_ci goto error; 39113498266Sopenharmony_ci } 39213498266Sopenharmony_ci 39313498266Sopenharmony_ci sshc->ssh_session = wolfSSH_new(sshc->ctx); 39413498266Sopenharmony_ci if(!sshc->ssh_session) { 39513498266Sopenharmony_ci failf(data, "No wolfSSH session"); 39613498266Sopenharmony_ci goto error; 39713498266Sopenharmony_ci } 39813498266Sopenharmony_ci 39913498266Sopenharmony_ci rc = wolfSSH_SetUsername(sshc->ssh_session, conn->user); 40013498266Sopenharmony_ci if(rc != WS_SUCCESS) { 40113498266Sopenharmony_ci failf(data, "wolfSSH failed to set user name"); 40213498266Sopenharmony_ci goto error; 40313498266Sopenharmony_ci } 40413498266Sopenharmony_ci 40513498266Sopenharmony_ci /* set callback for authentication */ 40613498266Sopenharmony_ci wolfSSH_SetUserAuth(sshc->ctx, userauth); 40713498266Sopenharmony_ci wolfSSH_SetUserAuthCtx(sshc->ssh_session, data); 40813498266Sopenharmony_ci 40913498266Sopenharmony_ci rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock); 41013498266Sopenharmony_ci if(rc) { 41113498266Sopenharmony_ci failf(data, "wolfSSH failed to set socket"); 41213498266Sopenharmony_ci goto error; 41313498266Sopenharmony_ci } 41413498266Sopenharmony_ci 41513498266Sopenharmony_ci#if 0 41613498266Sopenharmony_ci wolfSSH_Debugging_ON(); 41713498266Sopenharmony_ci#endif 41813498266Sopenharmony_ci 41913498266Sopenharmony_ci *done = TRUE; 42013498266Sopenharmony_ci if(conn->handler->protocol & CURLPROTO_SCP) 42113498266Sopenharmony_ci state(data, SSH_INIT); 42213498266Sopenharmony_ci else 42313498266Sopenharmony_ci state(data, SSH_SFTP_INIT); 42413498266Sopenharmony_ci 42513498266Sopenharmony_ci return wssh_multi_statemach(data, done); 42613498266Sopenharmony_cierror: 42713498266Sopenharmony_ci wolfSSH_free(sshc->ssh_session); 42813498266Sopenharmony_ci wolfSSH_CTX_free(sshc->ctx); 42913498266Sopenharmony_ci return CURLE_FAILED_INIT; 43013498266Sopenharmony_ci} 43113498266Sopenharmony_ci 43213498266Sopenharmony_ci/* 43313498266Sopenharmony_ci * wssh_statemach_act() runs the SSH state machine as far as it can without 43413498266Sopenharmony_ci * blocking and without reaching the end. The data the pointer 'block' points 43513498266Sopenharmony_ci * to will be set to TRUE if the wolfssh function returns EAGAIN meaning it 43613498266Sopenharmony_ci * wants to be called again when the socket is ready 43713498266Sopenharmony_ci */ 43813498266Sopenharmony_ci 43913498266Sopenharmony_cistatic CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) 44013498266Sopenharmony_ci{ 44113498266Sopenharmony_ci CURLcode result = CURLE_OK; 44213498266Sopenharmony_ci struct connectdata *conn = data->conn; 44313498266Sopenharmony_ci struct ssh_conn *sshc = &conn->proto.sshc; 44413498266Sopenharmony_ci struct SSHPROTO *sftp_scp = data->req.p.ssh; 44513498266Sopenharmony_ci WS_SFTPNAME *name; 44613498266Sopenharmony_ci int rc = 0; 44713498266Sopenharmony_ci *block = FALSE; /* we're not blocking by default */ 44813498266Sopenharmony_ci 44913498266Sopenharmony_ci do { 45013498266Sopenharmony_ci switch(sshc->state) { 45113498266Sopenharmony_ci case SSH_INIT: 45213498266Sopenharmony_ci state(data, SSH_S_STARTUP); 45313498266Sopenharmony_ci break; 45413498266Sopenharmony_ci 45513498266Sopenharmony_ci case SSH_S_STARTUP: 45613498266Sopenharmony_ci rc = wolfSSH_connect(sshc->ssh_session); 45713498266Sopenharmony_ci if(rc != WS_SUCCESS) 45813498266Sopenharmony_ci rc = wolfSSH_get_error(sshc->ssh_session); 45913498266Sopenharmony_ci if(rc == WS_WANT_READ) { 46013498266Sopenharmony_ci *block = TRUE; 46113498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 46213498266Sopenharmony_ci return CURLE_OK; 46313498266Sopenharmony_ci } 46413498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 46513498266Sopenharmony_ci *block = TRUE; 46613498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 46713498266Sopenharmony_ci return CURLE_OK; 46813498266Sopenharmony_ci } 46913498266Sopenharmony_ci else if(rc != WS_SUCCESS) { 47013498266Sopenharmony_ci state(data, SSH_STOP); 47113498266Sopenharmony_ci return CURLE_SSH; 47213498266Sopenharmony_ci } 47313498266Sopenharmony_ci infof(data, "wolfssh connected"); 47413498266Sopenharmony_ci state(data, SSH_STOP); 47513498266Sopenharmony_ci break; 47613498266Sopenharmony_ci case SSH_STOP: 47713498266Sopenharmony_ci break; 47813498266Sopenharmony_ci 47913498266Sopenharmony_ci case SSH_SFTP_INIT: 48013498266Sopenharmony_ci rc = wolfSSH_SFTP_connect(sshc->ssh_session); 48113498266Sopenharmony_ci if(rc != WS_SUCCESS) 48213498266Sopenharmony_ci rc = wolfSSH_get_error(sshc->ssh_session); 48313498266Sopenharmony_ci if(rc == WS_WANT_READ) { 48413498266Sopenharmony_ci *block = TRUE; 48513498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 48613498266Sopenharmony_ci return CURLE_OK; 48713498266Sopenharmony_ci } 48813498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 48913498266Sopenharmony_ci *block = TRUE; 49013498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 49113498266Sopenharmony_ci return CURLE_OK; 49213498266Sopenharmony_ci } 49313498266Sopenharmony_ci else if(rc == WS_SUCCESS) { 49413498266Sopenharmony_ci infof(data, "wolfssh SFTP connected"); 49513498266Sopenharmony_ci state(data, SSH_SFTP_REALPATH); 49613498266Sopenharmony_ci } 49713498266Sopenharmony_ci else { 49813498266Sopenharmony_ci failf(data, "wolfssh SFTP connect error %d", rc); 49913498266Sopenharmony_ci return CURLE_SSH; 50013498266Sopenharmony_ci } 50113498266Sopenharmony_ci break; 50213498266Sopenharmony_ci case SSH_SFTP_REALPATH: 50313498266Sopenharmony_ci name = wolfSSH_SFTP_RealPath(sshc->ssh_session, (char *)"."); 50413498266Sopenharmony_ci rc = wolfSSH_get_error(sshc->ssh_session); 50513498266Sopenharmony_ci if(rc == WS_WANT_READ) { 50613498266Sopenharmony_ci *block = TRUE; 50713498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 50813498266Sopenharmony_ci return CURLE_OK; 50913498266Sopenharmony_ci } 51013498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 51113498266Sopenharmony_ci *block = TRUE; 51213498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 51313498266Sopenharmony_ci return CURLE_OK; 51413498266Sopenharmony_ci } 51513498266Sopenharmony_ci else if(name && (rc == WS_SUCCESS)) { 51613498266Sopenharmony_ci sshc->homedir = Curl_memdup0(name->fName, name->fSz); 51713498266Sopenharmony_ci if(!sshc->homedir) 51813498266Sopenharmony_ci sshc->actualcode = CURLE_OUT_OF_MEMORY; 51913498266Sopenharmony_ci wolfSSH_SFTPNAME_list_free(name); 52013498266Sopenharmony_ci state(data, SSH_STOP); 52113498266Sopenharmony_ci return CURLE_OK; 52213498266Sopenharmony_ci } 52313498266Sopenharmony_ci failf(data, "wolfssh SFTP realpath %d", rc); 52413498266Sopenharmony_ci return CURLE_SSH; 52513498266Sopenharmony_ci 52613498266Sopenharmony_ci case SSH_SFTP_QUOTE_INIT: 52713498266Sopenharmony_ci result = Curl_getworkingpath(data, sshc->homedir, &sftp_scp->path); 52813498266Sopenharmony_ci if(result) { 52913498266Sopenharmony_ci sshc->actualcode = result; 53013498266Sopenharmony_ci state(data, SSH_STOP); 53113498266Sopenharmony_ci break; 53213498266Sopenharmony_ci } 53313498266Sopenharmony_ci 53413498266Sopenharmony_ci if(data->set.quote) { 53513498266Sopenharmony_ci infof(data, "Sending quote commands"); 53613498266Sopenharmony_ci sshc->quote_item = data->set.quote; 53713498266Sopenharmony_ci state(data, SSH_SFTP_QUOTE); 53813498266Sopenharmony_ci } 53913498266Sopenharmony_ci else { 54013498266Sopenharmony_ci state(data, SSH_SFTP_GETINFO); 54113498266Sopenharmony_ci } 54213498266Sopenharmony_ci break; 54313498266Sopenharmony_ci case SSH_SFTP_GETINFO: 54413498266Sopenharmony_ci if(data->set.get_filetime) { 54513498266Sopenharmony_ci state(data, SSH_SFTP_FILETIME); 54613498266Sopenharmony_ci } 54713498266Sopenharmony_ci else { 54813498266Sopenharmony_ci state(data, SSH_SFTP_TRANS_INIT); 54913498266Sopenharmony_ci } 55013498266Sopenharmony_ci break; 55113498266Sopenharmony_ci case SSH_SFTP_TRANS_INIT: 55213498266Sopenharmony_ci if(data->state.upload) 55313498266Sopenharmony_ci state(data, SSH_SFTP_UPLOAD_INIT); 55413498266Sopenharmony_ci else { 55513498266Sopenharmony_ci if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') 55613498266Sopenharmony_ci state(data, SSH_SFTP_READDIR_INIT); 55713498266Sopenharmony_ci else 55813498266Sopenharmony_ci state(data, SSH_SFTP_DOWNLOAD_INIT); 55913498266Sopenharmony_ci } 56013498266Sopenharmony_ci break; 56113498266Sopenharmony_ci case SSH_SFTP_UPLOAD_INIT: { 56213498266Sopenharmony_ci word32 flags; 56313498266Sopenharmony_ci WS_SFTP_FILEATRB createattrs; 56413498266Sopenharmony_ci if(data->state.resume_from) { 56513498266Sopenharmony_ci WS_SFTP_FILEATRB attrs; 56613498266Sopenharmony_ci if(data->state.resume_from < 0) { 56713498266Sopenharmony_ci rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path, 56813498266Sopenharmony_ci &attrs); 56913498266Sopenharmony_ci if(rc != WS_SUCCESS) 57013498266Sopenharmony_ci break; 57113498266Sopenharmony_ci 57213498266Sopenharmony_ci if(rc) { 57313498266Sopenharmony_ci data->state.resume_from = 0; 57413498266Sopenharmony_ci } 57513498266Sopenharmony_ci else { 57613498266Sopenharmony_ci curl_off_t size = ((curl_off_t)attrs.sz[1] << 32) | attrs.sz[0]; 57713498266Sopenharmony_ci if(size < 0) { 57813498266Sopenharmony_ci failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); 57913498266Sopenharmony_ci return CURLE_BAD_DOWNLOAD_RESUME; 58013498266Sopenharmony_ci } 58113498266Sopenharmony_ci data->state.resume_from = size; 58213498266Sopenharmony_ci } 58313498266Sopenharmony_ci } 58413498266Sopenharmony_ci } 58513498266Sopenharmony_ci 58613498266Sopenharmony_ci if(data->set.remote_append) 58713498266Sopenharmony_ci /* Try to open for append, but create if nonexisting */ 58813498266Sopenharmony_ci flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND; 58913498266Sopenharmony_ci else if(data->state.resume_from > 0) 59013498266Sopenharmony_ci /* If we have restart position then open for append */ 59113498266Sopenharmony_ci flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND; 59213498266Sopenharmony_ci else 59313498266Sopenharmony_ci /* Clear file before writing (normal behavior) */ 59413498266Sopenharmony_ci flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC; 59513498266Sopenharmony_ci 59613498266Sopenharmony_ci memset(&createattrs, 0, sizeof(createattrs)); 59713498266Sopenharmony_ci createattrs.per = (word32)data->set.new_file_perms; 59813498266Sopenharmony_ci sshc->handleSz = sizeof(sshc->handle); 59913498266Sopenharmony_ci rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path, 60013498266Sopenharmony_ci flags, &createattrs, 60113498266Sopenharmony_ci sshc->handle, &sshc->handleSz); 60213498266Sopenharmony_ci if(rc == WS_FATAL_ERROR) 60313498266Sopenharmony_ci rc = wolfSSH_get_error(sshc->ssh_session); 60413498266Sopenharmony_ci if(rc == WS_WANT_READ) { 60513498266Sopenharmony_ci *block = TRUE; 60613498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 60713498266Sopenharmony_ci return CURLE_OK; 60813498266Sopenharmony_ci } 60913498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 61013498266Sopenharmony_ci *block = TRUE; 61113498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 61213498266Sopenharmony_ci return CURLE_OK; 61313498266Sopenharmony_ci } 61413498266Sopenharmony_ci else if(rc == WS_SUCCESS) { 61513498266Sopenharmony_ci infof(data, "wolfssh SFTP open succeeded"); 61613498266Sopenharmony_ci } 61713498266Sopenharmony_ci else { 61813498266Sopenharmony_ci failf(data, "wolfssh SFTP upload open failed: %d", rc); 61913498266Sopenharmony_ci return CURLE_SSH; 62013498266Sopenharmony_ci } 62113498266Sopenharmony_ci state(data, SSH_SFTP_DOWNLOAD_STAT); 62213498266Sopenharmony_ci 62313498266Sopenharmony_ci /* If we have a restart point then we need to seek to the correct 62413498266Sopenharmony_ci position. */ 62513498266Sopenharmony_ci if(data->state.resume_from > 0) { 62613498266Sopenharmony_ci /* Let's read off the proper amount of bytes from the input. */ 62713498266Sopenharmony_ci int seekerr = CURL_SEEKFUNC_OK; 62813498266Sopenharmony_ci if(conn->seek_func) { 62913498266Sopenharmony_ci Curl_set_in_callback(data, true); 63013498266Sopenharmony_ci seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, 63113498266Sopenharmony_ci SEEK_SET); 63213498266Sopenharmony_ci Curl_set_in_callback(data, false); 63313498266Sopenharmony_ci } 63413498266Sopenharmony_ci 63513498266Sopenharmony_ci if(seekerr != CURL_SEEKFUNC_OK) { 63613498266Sopenharmony_ci curl_off_t passed = 0; 63713498266Sopenharmony_ci 63813498266Sopenharmony_ci if(seekerr != CURL_SEEKFUNC_CANTSEEK) { 63913498266Sopenharmony_ci failf(data, "Could not seek stream"); 64013498266Sopenharmony_ci return CURLE_FTP_COULDNT_USE_REST; 64113498266Sopenharmony_ci } 64213498266Sopenharmony_ci /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ 64313498266Sopenharmony_ci do { 64413498266Sopenharmony_ci char scratch[4*1024]; 64513498266Sopenharmony_ci size_t readthisamountnow = 64613498266Sopenharmony_ci (data->state.resume_from - passed > 64713498266Sopenharmony_ci (curl_off_t)sizeof(scratch)) ? 64813498266Sopenharmony_ci sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed); 64913498266Sopenharmony_ci 65013498266Sopenharmony_ci size_t actuallyread; 65113498266Sopenharmony_ci Curl_set_in_callback(data, true); 65213498266Sopenharmony_ci actuallyread = data->state.fread_func(scratch, 1, 65313498266Sopenharmony_ci readthisamountnow, 65413498266Sopenharmony_ci data->state.in); 65513498266Sopenharmony_ci Curl_set_in_callback(data, false); 65613498266Sopenharmony_ci 65713498266Sopenharmony_ci passed += actuallyread; 65813498266Sopenharmony_ci if((actuallyread == 0) || (actuallyread > readthisamountnow)) { 65913498266Sopenharmony_ci /* this checks for greater-than only to make sure that the 66013498266Sopenharmony_ci CURL_READFUNC_ABORT return code still aborts */ 66113498266Sopenharmony_ci failf(data, "Failed to read data"); 66213498266Sopenharmony_ci return CURLE_FTP_COULDNT_USE_REST; 66313498266Sopenharmony_ci } 66413498266Sopenharmony_ci } while(passed < data->state.resume_from); 66513498266Sopenharmony_ci } 66613498266Sopenharmony_ci 66713498266Sopenharmony_ci /* now, decrease the size of the read */ 66813498266Sopenharmony_ci if(data->state.infilesize > 0) { 66913498266Sopenharmony_ci data->state.infilesize -= data->state.resume_from; 67013498266Sopenharmony_ci data->req.size = data->state.infilesize; 67113498266Sopenharmony_ci Curl_pgrsSetUploadSize(data, data->state.infilesize); 67213498266Sopenharmony_ci } 67313498266Sopenharmony_ci 67413498266Sopenharmony_ci sshc->offset += data->state.resume_from; 67513498266Sopenharmony_ci } 67613498266Sopenharmony_ci if(data->state.infilesize > 0) { 67713498266Sopenharmony_ci data->req.size = data->state.infilesize; 67813498266Sopenharmony_ci Curl_pgrsSetUploadSize(data, data->state.infilesize); 67913498266Sopenharmony_ci } 68013498266Sopenharmony_ci /* upload data */ 68113498266Sopenharmony_ci Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); 68213498266Sopenharmony_ci 68313498266Sopenharmony_ci /* not set by Curl_setup_transfer to preserve keepon bits */ 68413498266Sopenharmony_ci conn->sockfd = conn->writesockfd; 68513498266Sopenharmony_ci 68613498266Sopenharmony_ci if(result) { 68713498266Sopenharmony_ci state(data, SSH_SFTP_CLOSE); 68813498266Sopenharmony_ci sshc->actualcode = result; 68913498266Sopenharmony_ci } 69013498266Sopenharmony_ci else { 69113498266Sopenharmony_ci /* store this original bitmask setup to use later on if we can't 69213498266Sopenharmony_ci figure out a "real" bitmask */ 69313498266Sopenharmony_ci sshc->orig_waitfor = data->req.keepon; 69413498266Sopenharmony_ci 69513498266Sopenharmony_ci /* we want to use the _sending_ function even when the socket turns 69613498266Sopenharmony_ci out readable as the underlying libssh2 sftp send function will deal 69713498266Sopenharmony_ci with both accordingly */ 69813498266Sopenharmony_ci data->state.select_bits = CURL_CSELECT_OUT; 69913498266Sopenharmony_ci 70013498266Sopenharmony_ci /* since we don't really wait for anything at this point, we want the 70113498266Sopenharmony_ci state machine to move on as soon as possible so we set a very short 70213498266Sopenharmony_ci timeout here */ 70313498266Sopenharmony_ci Curl_expire(data, 0, EXPIRE_RUN_NOW); 70413498266Sopenharmony_ci 70513498266Sopenharmony_ci state(data, SSH_STOP); 70613498266Sopenharmony_ci } 70713498266Sopenharmony_ci break; 70813498266Sopenharmony_ci } 70913498266Sopenharmony_ci case SSH_SFTP_DOWNLOAD_INIT: 71013498266Sopenharmony_ci sshc->handleSz = sizeof(sshc->handle); 71113498266Sopenharmony_ci rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path, 71213498266Sopenharmony_ci WOLFSSH_FXF_READ, NULL, 71313498266Sopenharmony_ci sshc->handle, &sshc->handleSz); 71413498266Sopenharmony_ci if(rc == WS_FATAL_ERROR) 71513498266Sopenharmony_ci rc = wolfSSH_get_error(sshc->ssh_session); 71613498266Sopenharmony_ci if(rc == WS_WANT_READ) { 71713498266Sopenharmony_ci *block = TRUE; 71813498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 71913498266Sopenharmony_ci return CURLE_OK; 72013498266Sopenharmony_ci } 72113498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 72213498266Sopenharmony_ci *block = TRUE; 72313498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 72413498266Sopenharmony_ci return CURLE_OK; 72513498266Sopenharmony_ci } 72613498266Sopenharmony_ci else if(rc == WS_SUCCESS) { 72713498266Sopenharmony_ci infof(data, "wolfssh SFTP open succeeded"); 72813498266Sopenharmony_ci state(data, SSH_SFTP_DOWNLOAD_STAT); 72913498266Sopenharmony_ci return CURLE_OK; 73013498266Sopenharmony_ci } 73113498266Sopenharmony_ci 73213498266Sopenharmony_ci failf(data, "wolfssh SFTP open failed: %d", rc); 73313498266Sopenharmony_ci return CURLE_SSH; 73413498266Sopenharmony_ci 73513498266Sopenharmony_ci case SSH_SFTP_DOWNLOAD_STAT: { 73613498266Sopenharmony_ci WS_SFTP_FILEATRB attrs; 73713498266Sopenharmony_ci curl_off_t size; 73813498266Sopenharmony_ci 73913498266Sopenharmony_ci rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path, &attrs); 74013498266Sopenharmony_ci if(rc == WS_FATAL_ERROR) 74113498266Sopenharmony_ci rc = wolfSSH_get_error(sshc->ssh_session); 74213498266Sopenharmony_ci if(rc == WS_WANT_READ) { 74313498266Sopenharmony_ci *block = TRUE; 74413498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 74513498266Sopenharmony_ci return CURLE_OK; 74613498266Sopenharmony_ci } 74713498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 74813498266Sopenharmony_ci *block = TRUE; 74913498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 75013498266Sopenharmony_ci return CURLE_OK; 75113498266Sopenharmony_ci } 75213498266Sopenharmony_ci else if(rc == WS_SUCCESS) { 75313498266Sopenharmony_ci infof(data, "wolfssh STAT succeeded"); 75413498266Sopenharmony_ci } 75513498266Sopenharmony_ci else { 75613498266Sopenharmony_ci failf(data, "wolfssh SFTP open failed: %d", rc); 75713498266Sopenharmony_ci data->req.size = -1; 75813498266Sopenharmony_ci data->req.maxdownload = -1; 75913498266Sopenharmony_ci Curl_pgrsSetDownloadSize(data, -1); 76013498266Sopenharmony_ci return CURLE_SSH; 76113498266Sopenharmony_ci } 76213498266Sopenharmony_ci 76313498266Sopenharmony_ci size = ((curl_off_t)attrs.sz[1] <<32) | attrs.sz[0]; 76413498266Sopenharmony_ci 76513498266Sopenharmony_ci data->req.size = size; 76613498266Sopenharmony_ci data->req.maxdownload = size; 76713498266Sopenharmony_ci Curl_pgrsSetDownloadSize(data, size); 76813498266Sopenharmony_ci 76913498266Sopenharmony_ci infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes", size); 77013498266Sopenharmony_ci 77113498266Sopenharmony_ci /* We cannot seek with wolfSSH so resuming and range requests are not 77213498266Sopenharmony_ci possible */ 77313498266Sopenharmony_ci if(data->state.use_range || data->state.resume_from) { 77413498266Sopenharmony_ci infof(data, "wolfSSH cannot do range/seek on SFTP"); 77513498266Sopenharmony_ci return CURLE_BAD_DOWNLOAD_RESUME; 77613498266Sopenharmony_ci } 77713498266Sopenharmony_ci 77813498266Sopenharmony_ci /* Setup the actual download */ 77913498266Sopenharmony_ci if(data->req.size == 0) { 78013498266Sopenharmony_ci /* no data to transfer */ 78113498266Sopenharmony_ci Curl_setup_transfer(data, -1, -1, FALSE, -1); 78213498266Sopenharmony_ci infof(data, "File already completely downloaded"); 78313498266Sopenharmony_ci state(data, SSH_STOP); 78413498266Sopenharmony_ci break; 78513498266Sopenharmony_ci } 78613498266Sopenharmony_ci Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); 78713498266Sopenharmony_ci 78813498266Sopenharmony_ci /* not set by Curl_setup_transfer to preserve keepon bits */ 78913498266Sopenharmony_ci conn->writesockfd = conn->sockfd; 79013498266Sopenharmony_ci 79113498266Sopenharmony_ci /* we want to use the _receiving_ function even when the socket turns 79213498266Sopenharmony_ci out writableable as the underlying libssh2 recv function will deal 79313498266Sopenharmony_ci with both accordingly */ 79413498266Sopenharmony_ci data->state.select_bits = CURL_CSELECT_IN; 79513498266Sopenharmony_ci 79613498266Sopenharmony_ci if(result) { 79713498266Sopenharmony_ci /* this should never occur; the close state should be entered 79813498266Sopenharmony_ci at the time the error occurs */ 79913498266Sopenharmony_ci state(data, SSH_SFTP_CLOSE); 80013498266Sopenharmony_ci sshc->actualcode = result; 80113498266Sopenharmony_ci } 80213498266Sopenharmony_ci else { 80313498266Sopenharmony_ci state(data, SSH_STOP); 80413498266Sopenharmony_ci } 80513498266Sopenharmony_ci break; 80613498266Sopenharmony_ci } 80713498266Sopenharmony_ci case SSH_SFTP_CLOSE: 80813498266Sopenharmony_ci if(sshc->handleSz) 80913498266Sopenharmony_ci rc = wolfSSH_SFTP_Close(sshc->ssh_session, sshc->handle, 81013498266Sopenharmony_ci sshc->handleSz); 81113498266Sopenharmony_ci else 81213498266Sopenharmony_ci rc = WS_SUCCESS; /* directory listing */ 81313498266Sopenharmony_ci if(rc == WS_WANT_READ) { 81413498266Sopenharmony_ci *block = TRUE; 81513498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 81613498266Sopenharmony_ci return CURLE_OK; 81713498266Sopenharmony_ci } 81813498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 81913498266Sopenharmony_ci *block = TRUE; 82013498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 82113498266Sopenharmony_ci return CURLE_OK; 82213498266Sopenharmony_ci } 82313498266Sopenharmony_ci else if(rc == WS_SUCCESS) { 82413498266Sopenharmony_ci state(data, SSH_STOP); 82513498266Sopenharmony_ci return CURLE_OK; 82613498266Sopenharmony_ci } 82713498266Sopenharmony_ci 82813498266Sopenharmony_ci failf(data, "wolfssh SFTP CLOSE failed: %d", rc); 82913498266Sopenharmony_ci return CURLE_SSH; 83013498266Sopenharmony_ci 83113498266Sopenharmony_ci case SSH_SFTP_READDIR_INIT: 83213498266Sopenharmony_ci Curl_pgrsSetDownloadSize(data, -1); 83313498266Sopenharmony_ci if(data->req.no_body) { 83413498266Sopenharmony_ci state(data, SSH_STOP); 83513498266Sopenharmony_ci break; 83613498266Sopenharmony_ci } 83713498266Sopenharmony_ci state(data, SSH_SFTP_READDIR); 83813498266Sopenharmony_ci break; 83913498266Sopenharmony_ci 84013498266Sopenharmony_ci case SSH_SFTP_READDIR: 84113498266Sopenharmony_ci name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path); 84213498266Sopenharmony_ci if(!name) 84313498266Sopenharmony_ci rc = wolfSSH_get_error(sshc->ssh_session); 84413498266Sopenharmony_ci else 84513498266Sopenharmony_ci rc = WS_SUCCESS; 84613498266Sopenharmony_ci 84713498266Sopenharmony_ci if(rc == WS_WANT_READ) { 84813498266Sopenharmony_ci *block = TRUE; 84913498266Sopenharmony_ci conn->waitfor = KEEP_RECV; 85013498266Sopenharmony_ci return CURLE_OK; 85113498266Sopenharmony_ci } 85213498266Sopenharmony_ci else if(rc == WS_WANT_WRITE) { 85313498266Sopenharmony_ci *block = TRUE; 85413498266Sopenharmony_ci conn->waitfor = KEEP_SEND; 85513498266Sopenharmony_ci return CURLE_OK; 85613498266Sopenharmony_ci } 85713498266Sopenharmony_ci else if(name && (rc == WS_SUCCESS)) { 85813498266Sopenharmony_ci WS_SFTPNAME *origname = name; 85913498266Sopenharmony_ci result = CURLE_OK; 86013498266Sopenharmony_ci while(name) { 86113498266Sopenharmony_ci char *line = aprintf("%s\n", 86213498266Sopenharmony_ci data->set.list_only ? 86313498266Sopenharmony_ci name->fName : name->lName); 86413498266Sopenharmony_ci if(!line) { 86513498266Sopenharmony_ci state(data, SSH_SFTP_CLOSE); 86613498266Sopenharmony_ci sshc->actualcode = CURLE_OUT_OF_MEMORY; 86713498266Sopenharmony_ci break; 86813498266Sopenharmony_ci } 86913498266Sopenharmony_ci result = Curl_client_write(data, CLIENTWRITE_BODY, 87013498266Sopenharmony_ci line, strlen(line)); 87113498266Sopenharmony_ci free(line); 87213498266Sopenharmony_ci if(result) { 87313498266Sopenharmony_ci sshc->actualcode = result; 87413498266Sopenharmony_ci break; 87513498266Sopenharmony_ci } 87613498266Sopenharmony_ci name = name->next; 87713498266Sopenharmony_ci } 87813498266Sopenharmony_ci wolfSSH_SFTPNAME_list_free(origname); 87913498266Sopenharmony_ci state(data, SSH_STOP); 88013498266Sopenharmony_ci return result; 88113498266Sopenharmony_ci } 88213498266Sopenharmony_ci failf(data, "wolfssh SFTP ls failed: %d", rc); 88313498266Sopenharmony_ci return CURLE_SSH; 88413498266Sopenharmony_ci 88513498266Sopenharmony_ci case SSH_SFTP_SHUTDOWN: 88613498266Sopenharmony_ci Curl_safefree(sshc->homedir); 88713498266Sopenharmony_ci wolfSSH_free(sshc->ssh_session); 88813498266Sopenharmony_ci wolfSSH_CTX_free(sshc->ctx); 88913498266Sopenharmony_ci state(data, SSH_STOP); 89013498266Sopenharmony_ci return CURLE_OK; 89113498266Sopenharmony_ci default: 89213498266Sopenharmony_ci break; 89313498266Sopenharmony_ci } 89413498266Sopenharmony_ci } while(!rc && (sshc->state != SSH_STOP)); 89513498266Sopenharmony_ci return result; 89613498266Sopenharmony_ci} 89713498266Sopenharmony_ci 89813498266Sopenharmony_ci/* called repeatedly until done from multi.c */ 89913498266Sopenharmony_cistatic CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done) 90013498266Sopenharmony_ci{ 90113498266Sopenharmony_ci struct connectdata *conn = data->conn; 90213498266Sopenharmony_ci struct ssh_conn *sshc = &conn->proto.sshc; 90313498266Sopenharmony_ci CURLcode result = CURLE_OK; 90413498266Sopenharmony_ci bool block; /* we store the status and use that to provide a ssh_getsock() 90513498266Sopenharmony_ci implementation */ 90613498266Sopenharmony_ci do { 90713498266Sopenharmony_ci result = wssh_statemach_act(data, &block); 90813498266Sopenharmony_ci *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; 90913498266Sopenharmony_ci /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then 91013498266Sopenharmony_ci try again */ 91113498266Sopenharmony_ci if(*done) { 91213498266Sopenharmony_ci DEBUGF(infof(data, "wssh_statemach_act says DONE")); 91313498266Sopenharmony_ci } 91413498266Sopenharmony_ci } while(!result && !*done && !block); 91513498266Sopenharmony_ci 91613498266Sopenharmony_ci return result; 91713498266Sopenharmony_ci} 91813498266Sopenharmony_ci 91913498266Sopenharmony_cistatic 92013498266Sopenharmony_ciCURLcode wscp_perform(struct Curl_easy *data, 92113498266Sopenharmony_ci bool *connected, 92213498266Sopenharmony_ci bool *dophase_done) 92313498266Sopenharmony_ci{ 92413498266Sopenharmony_ci (void)data; 92513498266Sopenharmony_ci (void)connected; 92613498266Sopenharmony_ci (void)dophase_done; 92713498266Sopenharmony_ci return CURLE_OK; 92813498266Sopenharmony_ci} 92913498266Sopenharmony_ci 93013498266Sopenharmony_cistatic 93113498266Sopenharmony_ciCURLcode wsftp_perform(struct Curl_easy *data, 93213498266Sopenharmony_ci bool *connected, 93313498266Sopenharmony_ci bool *dophase_done) 93413498266Sopenharmony_ci{ 93513498266Sopenharmony_ci CURLcode result = CURLE_OK; 93613498266Sopenharmony_ci 93713498266Sopenharmony_ci DEBUGF(infof(data, "DO phase starts")); 93813498266Sopenharmony_ci 93913498266Sopenharmony_ci *dophase_done = FALSE; /* not done yet */ 94013498266Sopenharmony_ci 94113498266Sopenharmony_ci /* start the first command in the DO phase */ 94213498266Sopenharmony_ci state(data, SSH_SFTP_QUOTE_INIT); 94313498266Sopenharmony_ci 94413498266Sopenharmony_ci /* run the state-machine */ 94513498266Sopenharmony_ci result = wssh_multi_statemach(data, dophase_done); 94613498266Sopenharmony_ci 94713498266Sopenharmony_ci *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET); 94813498266Sopenharmony_ci 94913498266Sopenharmony_ci if(*dophase_done) { 95013498266Sopenharmony_ci DEBUGF(infof(data, "DO phase is complete")); 95113498266Sopenharmony_ci } 95213498266Sopenharmony_ci 95313498266Sopenharmony_ci return result; 95413498266Sopenharmony_ci} 95513498266Sopenharmony_ci 95613498266Sopenharmony_ci/* 95713498266Sopenharmony_ci * The DO function is generic for both protocols. 95813498266Sopenharmony_ci */ 95913498266Sopenharmony_cistatic CURLcode wssh_do(struct Curl_easy *data, bool *done) 96013498266Sopenharmony_ci{ 96113498266Sopenharmony_ci CURLcode result; 96213498266Sopenharmony_ci bool connected = 0; 96313498266Sopenharmony_ci struct connectdata *conn = data->conn; 96413498266Sopenharmony_ci struct ssh_conn *sshc = &conn->proto.sshc; 96513498266Sopenharmony_ci 96613498266Sopenharmony_ci *done = FALSE; /* default to false */ 96713498266Sopenharmony_ci data->req.size = -1; /* make sure this is unknown at this point */ 96813498266Sopenharmony_ci sshc->actualcode = CURLE_OK; /* reset error code */ 96913498266Sopenharmony_ci sshc->secondCreateDirs = 0; /* reset the create dir attempt state 97013498266Sopenharmony_ci variable */ 97113498266Sopenharmony_ci 97213498266Sopenharmony_ci Curl_pgrsSetUploadCounter(data, 0); 97313498266Sopenharmony_ci Curl_pgrsSetDownloadCounter(data, 0); 97413498266Sopenharmony_ci Curl_pgrsSetUploadSize(data, -1); 97513498266Sopenharmony_ci Curl_pgrsSetDownloadSize(data, -1); 97613498266Sopenharmony_ci 97713498266Sopenharmony_ci if(conn->handler->protocol & CURLPROTO_SCP) 97813498266Sopenharmony_ci result = wscp_perform(data, &connected, done); 97913498266Sopenharmony_ci else 98013498266Sopenharmony_ci result = wsftp_perform(data, &connected, done); 98113498266Sopenharmony_ci 98213498266Sopenharmony_ci return result; 98313498266Sopenharmony_ci} 98413498266Sopenharmony_ci 98513498266Sopenharmony_cistatic CURLcode wssh_block_statemach(struct Curl_easy *data, 98613498266Sopenharmony_ci bool disconnect) 98713498266Sopenharmony_ci{ 98813498266Sopenharmony_ci struct connectdata *conn = data->conn; 98913498266Sopenharmony_ci struct ssh_conn *sshc = &conn->proto.sshc; 99013498266Sopenharmony_ci CURLcode result = CURLE_OK; 99113498266Sopenharmony_ci 99213498266Sopenharmony_ci while((sshc->state != SSH_STOP) && !result) { 99313498266Sopenharmony_ci bool block; 99413498266Sopenharmony_ci timediff_t left = 1000; 99513498266Sopenharmony_ci struct curltime now = Curl_now(); 99613498266Sopenharmony_ci 99713498266Sopenharmony_ci result = wssh_statemach_act(data, &block); 99813498266Sopenharmony_ci if(result) 99913498266Sopenharmony_ci break; 100013498266Sopenharmony_ci 100113498266Sopenharmony_ci if(!disconnect) { 100213498266Sopenharmony_ci if(Curl_pgrsUpdate(data)) 100313498266Sopenharmony_ci return CURLE_ABORTED_BY_CALLBACK; 100413498266Sopenharmony_ci 100513498266Sopenharmony_ci result = Curl_speedcheck(data, now); 100613498266Sopenharmony_ci if(result) 100713498266Sopenharmony_ci break; 100813498266Sopenharmony_ci 100913498266Sopenharmony_ci left = Curl_timeleft(data, NULL, FALSE); 101013498266Sopenharmony_ci if(left < 0) { 101113498266Sopenharmony_ci failf(data, "Operation timed out"); 101213498266Sopenharmony_ci return CURLE_OPERATION_TIMEDOUT; 101313498266Sopenharmony_ci } 101413498266Sopenharmony_ci } 101513498266Sopenharmony_ci 101613498266Sopenharmony_ci if(!result) { 101713498266Sopenharmony_ci int dir = conn->waitfor; 101813498266Sopenharmony_ci curl_socket_t sock = conn->sock[FIRSTSOCKET]; 101913498266Sopenharmony_ci curl_socket_t fd_read = CURL_SOCKET_BAD; 102013498266Sopenharmony_ci curl_socket_t fd_write = CURL_SOCKET_BAD; 102113498266Sopenharmony_ci if(dir == KEEP_RECV) 102213498266Sopenharmony_ci fd_read = sock; 102313498266Sopenharmony_ci else if(dir == KEEP_SEND) 102413498266Sopenharmony_ci fd_write = sock; 102513498266Sopenharmony_ci 102613498266Sopenharmony_ci /* wait for the socket to become ready */ 102713498266Sopenharmony_ci (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, 102813498266Sopenharmony_ci left>1000?1000:left); /* ignore result */ 102913498266Sopenharmony_ci } 103013498266Sopenharmony_ci } 103113498266Sopenharmony_ci 103213498266Sopenharmony_ci return result; 103313498266Sopenharmony_ci} 103413498266Sopenharmony_ci 103513498266Sopenharmony_ci/* generic done function for both SCP and SFTP called from their specific 103613498266Sopenharmony_ci done functions */ 103713498266Sopenharmony_cistatic CURLcode wssh_done(struct Curl_easy *data, CURLcode status) 103813498266Sopenharmony_ci{ 103913498266Sopenharmony_ci CURLcode result = CURLE_OK; 104013498266Sopenharmony_ci struct SSHPROTO *sftp_scp = data->req.p.ssh; 104113498266Sopenharmony_ci 104213498266Sopenharmony_ci if(!status) { 104313498266Sopenharmony_ci /* run the state-machine */ 104413498266Sopenharmony_ci result = wssh_block_statemach(data, FALSE); 104513498266Sopenharmony_ci } 104613498266Sopenharmony_ci else 104713498266Sopenharmony_ci result = status; 104813498266Sopenharmony_ci 104913498266Sopenharmony_ci if(sftp_scp) 105013498266Sopenharmony_ci Curl_safefree(sftp_scp->path); 105113498266Sopenharmony_ci if(Curl_pgrsDone(data)) 105213498266Sopenharmony_ci return CURLE_ABORTED_BY_CALLBACK; 105313498266Sopenharmony_ci 105413498266Sopenharmony_ci data->req.keepon = 0; /* clear all bits */ 105513498266Sopenharmony_ci return result; 105613498266Sopenharmony_ci} 105713498266Sopenharmony_ci 105813498266Sopenharmony_ci#if 0 105913498266Sopenharmony_cistatic CURLcode wscp_done(struct Curl_easy *data, 106013498266Sopenharmony_ci CURLcode code, bool premature) 106113498266Sopenharmony_ci{ 106213498266Sopenharmony_ci CURLcode result = CURLE_OK; 106313498266Sopenharmony_ci (void)conn; 106413498266Sopenharmony_ci (void)code; 106513498266Sopenharmony_ci (void)premature; 106613498266Sopenharmony_ci 106713498266Sopenharmony_ci return result; 106813498266Sopenharmony_ci} 106913498266Sopenharmony_ci 107013498266Sopenharmony_cistatic CURLcode wscp_doing(struct Curl_easy *data, 107113498266Sopenharmony_ci bool *dophase_done) 107213498266Sopenharmony_ci{ 107313498266Sopenharmony_ci CURLcode result = CURLE_OK; 107413498266Sopenharmony_ci (void)conn; 107513498266Sopenharmony_ci (void)dophase_done; 107613498266Sopenharmony_ci 107713498266Sopenharmony_ci return result; 107813498266Sopenharmony_ci} 107913498266Sopenharmony_ci 108013498266Sopenharmony_cistatic CURLcode wscp_disconnect(struct Curl_easy *data, 108113498266Sopenharmony_ci struct connectdata *conn, bool dead_connection) 108213498266Sopenharmony_ci{ 108313498266Sopenharmony_ci CURLcode result = CURLE_OK; 108413498266Sopenharmony_ci (void)data; 108513498266Sopenharmony_ci (void)conn; 108613498266Sopenharmony_ci (void)dead_connection; 108713498266Sopenharmony_ci 108813498266Sopenharmony_ci return result; 108913498266Sopenharmony_ci} 109013498266Sopenharmony_ci#endif 109113498266Sopenharmony_ci 109213498266Sopenharmony_cistatic CURLcode wsftp_done(struct Curl_easy *data, 109313498266Sopenharmony_ci CURLcode code, bool premature) 109413498266Sopenharmony_ci{ 109513498266Sopenharmony_ci (void)premature; 109613498266Sopenharmony_ci state(data, SSH_SFTP_CLOSE); 109713498266Sopenharmony_ci 109813498266Sopenharmony_ci return wssh_done(data, code); 109913498266Sopenharmony_ci} 110013498266Sopenharmony_ci 110113498266Sopenharmony_cistatic CURLcode wsftp_doing(struct Curl_easy *data, 110213498266Sopenharmony_ci bool *dophase_done) 110313498266Sopenharmony_ci{ 110413498266Sopenharmony_ci CURLcode result = wssh_multi_statemach(data, dophase_done); 110513498266Sopenharmony_ci 110613498266Sopenharmony_ci if(*dophase_done) { 110713498266Sopenharmony_ci DEBUGF(infof(data, "DO phase is complete")); 110813498266Sopenharmony_ci } 110913498266Sopenharmony_ci return result; 111013498266Sopenharmony_ci} 111113498266Sopenharmony_ci 111213498266Sopenharmony_cistatic CURLcode wsftp_disconnect(struct Curl_easy *data, 111313498266Sopenharmony_ci struct connectdata *conn, 111413498266Sopenharmony_ci bool dead) 111513498266Sopenharmony_ci{ 111613498266Sopenharmony_ci CURLcode result = CURLE_OK; 111713498266Sopenharmony_ci (void)dead; 111813498266Sopenharmony_ci 111913498266Sopenharmony_ci DEBUGF(infof(data, "SSH DISCONNECT starts now")); 112013498266Sopenharmony_ci 112113498266Sopenharmony_ci if(conn->proto.sshc.ssh_session) { 112213498266Sopenharmony_ci /* only if there's a session still around to use! */ 112313498266Sopenharmony_ci state(data, SSH_SFTP_SHUTDOWN); 112413498266Sopenharmony_ci result = wssh_block_statemach(data, TRUE); 112513498266Sopenharmony_ci } 112613498266Sopenharmony_ci 112713498266Sopenharmony_ci DEBUGF(infof(data, "SSH DISCONNECT is done")); 112813498266Sopenharmony_ci return result; 112913498266Sopenharmony_ci} 113013498266Sopenharmony_ci 113113498266Sopenharmony_cistatic int wssh_getsock(struct Curl_easy *data, 113213498266Sopenharmony_ci struct connectdata *conn, 113313498266Sopenharmony_ci curl_socket_t *sock) 113413498266Sopenharmony_ci{ 113513498266Sopenharmony_ci int bitmap = GETSOCK_BLANK; 113613498266Sopenharmony_ci int dir = conn->waitfor; 113713498266Sopenharmony_ci (void)data; 113813498266Sopenharmony_ci sock[0] = conn->sock[FIRSTSOCKET]; 113913498266Sopenharmony_ci 114013498266Sopenharmony_ci if(dir == KEEP_RECV) 114113498266Sopenharmony_ci bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); 114213498266Sopenharmony_ci else if(dir == KEEP_SEND) 114313498266Sopenharmony_ci bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); 114413498266Sopenharmony_ci 114513498266Sopenharmony_ci return bitmap; 114613498266Sopenharmony_ci} 114713498266Sopenharmony_ci 114813498266Sopenharmony_civoid Curl_ssh_version(char *buffer, size_t buflen) 114913498266Sopenharmony_ci{ 115013498266Sopenharmony_ci (void)msnprintf(buffer, buflen, "wolfssh/%s", LIBWOLFSSH_VERSION_STRING); 115113498266Sopenharmony_ci} 115213498266Sopenharmony_ci 115313498266Sopenharmony_ciCURLcode Curl_ssh_init(void) 115413498266Sopenharmony_ci{ 115513498266Sopenharmony_ci if(WS_SUCCESS != wolfSSH_Init()) { 115613498266Sopenharmony_ci DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n")); 115713498266Sopenharmony_ci return CURLE_FAILED_INIT; 115813498266Sopenharmony_ci } 115913498266Sopenharmony_ci 116013498266Sopenharmony_ci return CURLE_OK; 116113498266Sopenharmony_ci} 116213498266Sopenharmony_civoid Curl_ssh_cleanup(void) 116313498266Sopenharmony_ci{ 116413498266Sopenharmony_ci (void)wolfSSH_Cleanup(); 116513498266Sopenharmony_ci} 116613498266Sopenharmony_ci 116713498266Sopenharmony_ci#endif /* USE_WOLFSSH */ 1168