00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "curl_setup.h"
00026
00027 #ifdef USE_LIBSSH2
00028
00029 #ifdef HAVE_LIMITS_H
00030 # include <limits.h>
00031 #endif
00032
00033 #include <libssh2.h>
00034 #include <libssh2_sftp.h>
00035
00036 #ifdef HAVE_FCNTL_H
00037 #include <fcntl.h>
00038 #endif
00039
00040 #ifdef HAVE_NETINET_IN_H
00041 #include <netinet/in.h>
00042 #endif
00043 #ifdef HAVE_ARPA_INET_H
00044 #include <arpa/inet.h>
00045 #endif
00046 #ifdef HAVE_UTSNAME_H
00047 #include <sys/utsname.h>
00048 #endif
00049 #ifdef HAVE_NETDB_H
00050 #include <netdb.h>
00051 #endif
00052 #ifdef __VMS
00053 #include <in.h>
00054 #include <inet.h>
00055 #endif
00056
00057 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
00058 #undef in_addr_t
00059 #define in_addr_t unsigned long
00060 #endif
00061
00062 #include <curl/curl.h>
00063 #include "urldata.h"
00064 #include "sendf.h"
00065 #include "hostip.h"
00066 #include "progress.h"
00067 #include "transfer.h"
00068 #include "escape.h"
00069 #include "http.h"
00070 #include "ssh.h"
00071 #include "url.h"
00072 #include "speedcheck.h"
00073 #include "getinfo.h"
00074 #include "strdup.h"
00075 #include "strcase.h"
00076 #include "vtls/vtls.h"
00077 #include "connect.h"
00078 #include "strerror.h"
00079 #include "inet_ntop.h"
00080 #include "parsedate.h"
00081 #include "sockaddr.h"
00082 #include "strtoofft.h"
00083 #include "multiif.h"
00084 #include "select.h"
00085 #include "warnless.h"
00086
00087
00088 #include "curl_printf.h"
00089 #include "curl_memory.h"
00090 #include "memdebug.h"
00091
00092 #ifdef WIN32
00093 # undef PATH_MAX
00094 # define PATH_MAX MAX_PATH
00095 # ifndef R_OK
00096 # define R_OK 4
00097 # endif
00098 #endif
00099
00100 #ifndef PATH_MAX
00101 #define PATH_MAX 1024
00102
00103 #endif
00104
00105 #if LIBSSH2_VERSION_NUM >= 0x010206
00106
00107 #define HAS_STATVFS_SUPPORT 1
00108 #endif
00109
00110 #define sftp_libssh2_last_error(s) curlx_ultosi(libssh2_sftp_last_error(s))
00111
00112 #define sftp_libssh2_realpath(s,p,t,m) \
00113 libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
00114 (t), (m), LIBSSH2_SFTP_REALPATH)
00115
00116
00117 static const char *sftp_libssh2_strerror(int err);
00118 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
00119 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc);
00120 static LIBSSH2_FREE_FUNC(my_libssh2_free);
00121
00122 static CURLcode get_pathname(const char **cpp, char **path);
00123
00124 static CURLcode ssh_connect(struct connectdata *conn, bool *done);
00125 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done);
00126 static CURLcode ssh_do(struct connectdata *conn, bool *done);
00127
00128 static CURLcode ssh_getworkingpath(struct connectdata *conn,
00129 char *homedir,
00130 char **path);
00131
00132 static CURLcode scp_done(struct connectdata *conn,
00133 CURLcode, bool premature);
00134 static CURLcode scp_doing(struct connectdata *conn,
00135 bool *dophase_done);
00136 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection);
00137
00138 static CURLcode sftp_done(struct connectdata *conn,
00139 CURLcode, bool premature);
00140 static CURLcode sftp_doing(struct connectdata *conn,
00141 bool *dophase_done);
00142 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead);
00143 static
00144 CURLcode sftp_perform(struct connectdata *conn,
00145 bool *connected,
00146 bool *dophase_done);
00147
00148 static int ssh_getsock(struct connectdata *conn,
00149 curl_socket_t *sock,
00150
00151 int numsocks);
00152
00153 static int ssh_perform_getsock(const struct connectdata *conn,
00154 curl_socket_t *sock,
00155
00156 int numsocks);
00157
00158 static CURLcode ssh_setup_connection(struct connectdata *conn);
00159
00160
00161
00162
00163
00164 const struct Curl_handler Curl_handler_scp = {
00165 "SCP",
00166 ssh_setup_connection,
00167 ssh_do,
00168 scp_done,
00169 ZERO_NULL,
00170 ssh_connect,
00171 ssh_multi_statemach,
00172 scp_doing,
00173 ssh_getsock,
00174 ssh_getsock,
00175 ZERO_NULL,
00176 ssh_perform_getsock,
00177 scp_disconnect,
00178 ZERO_NULL,
00179 PORT_SSH,
00180 CURLPROTO_SCP,
00181 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
00182 | PROTOPT_NOURLQUERY
00183 };
00184
00185
00186
00187
00188
00189
00190 const struct Curl_handler Curl_handler_sftp = {
00191 "SFTP",
00192 ssh_setup_connection,
00193 ssh_do,
00194 sftp_done,
00195 ZERO_NULL,
00196 ssh_connect,
00197 ssh_multi_statemach,
00198 sftp_doing,
00199 ssh_getsock,
00200 ssh_getsock,
00201 ZERO_NULL,
00202 ssh_perform_getsock,
00203 sftp_disconnect,
00204 ZERO_NULL,
00205 PORT_SSH,
00206 CURLPROTO_SFTP,
00207 PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
00208 | PROTOPT_NOURLQUERY
00209 };
00210
00211 static void
00212 kbd_callback(const char *name, int name_len, const char *instruction,
00213 int instruction_len, int num_prompts,
00214 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
00215 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
00216 void **abstract)
00217 {
00218 struct connectdata *conn = (struct connectdata *)*abstract;
00219
00220 #ifdef CURL_LIBSSH2_DEBUG
00221 fprintf(stderr, "name=%s\n", name);
00222 fprintf(stderr, "name_len=%d\n", name_len);
00223 fprintf(stderr, "instruction=%s\n", instruction);
00224 fprintf(stderr, "instruction_len=%d\n", instruction_len);
00225 fprintf(stderr, "num_prompts=%d\n", num_prompts);
00226 #else
00227 (void)name;
00228 (void)name_len;
00229 (void)instruction;
00230 (void)instruction_len;
00231 #endif
00232 if(num_prompts == 1) {
00233 responses[0].text = strdup(conn->passwd);
00234 responses[0].length = curlx_uztoui(strlen(conn->passwd));
00235 }
00236 (void)prompts;
00237 (void)abstract;
00238 }
00239
00240 static CURLcode sftp_libssh2_error_to_CURLE(int err)
00241 {
00242 switch(err) {
00243 case LIBSSH2_FX_OK:
00244 return CURLE_OK;
00245
00246 case LIBSSH2_FX_NO_SUCH_FILE:
00247 case LIBSSH2_FX_NO_SUCH_PATH:
00248 return CURLE_REMOTE_FILE_NOT_FOUND;
00249
00250 case LIBSSH2_FX_PERMISSION_DENIED:
00251 case LIBSSH2_FX_WRITE_PROTECT:
00252 case LIBSSH2_FX_LOCK_CONFlICT:
00253 return CURLE_REMOTE_ACCESS_DENIED;
00254
00255 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
00256 case LIBSSH2_FX_QUOTA_EXCEEDED:
00257 return CURLE_REMOTE_DISK_FULL;
00258
00259 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
00260 return CURLE_REMOTE_FILE_EXISTS;
00261
00262 case LIBSSH2_FX_DIR_NOT_EMPTY:
00263 return CURLE_QUOTE_ERROR;
00264
00265 default:
00266 break;
00267 }
00268
00269 return CURLE_SSH;
00270 }
00271
00272 static CURLcode libssh2_session_error_to_CURLE(int err)
00273 {
00274 switch(err) {
00275
00276 case LIBSSH2_ERROR_NONE:
00277 return CURLE_OK;
00278
00279 case LIBSSH2_ERROR_SOCKET_NONE:
00280 return CURLE_COULDNT_CONNECT;
00281
00282 case LIBSSH2_ERROR_ALLOC:
00283 return CURLE_OUT_OF_MEMORY;
00284
00285 case LIBSSH2_ERROR_SOCKET_SEND:
00286 return CURLE_SEND_ERROR;
00287
00288 case LIBSSH2_ERROR_HOSTKEY_INIT:
00289 case LIBSSH2_ERROR_HOSTKEY_SIGN:
00290 case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
00291 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
00292 return CURLE_PEER_FAILED_VERIFICATION;
00293
00294 case LIBSSH2_ERROR_PASSWORD_EXPIRED:
00295 return CURLE_LOGIN_DENIED;
00296
00297 case LIBSSH2_ERROR_SOCKET_TIMEOUT:
00298 case LIBSSH2_ERROR_TIMEOUT:
00299 return CURLE_OPERATION_TIMEDOUT;
00300
00301 case LIBSSH2_ERROR_EAGAIN:
00302 return CURLE_AGAIN;
00303 }
00304
00305
00306
00307
00308
00309 return CURLE_SSH;
00310 }
00311
00312 static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
00313 {
00314 (void)abstract;
00315 return malloc(count);
00316 }
00317
00318 static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
00319 {
00320 (void)abstract;
00321 return realloc(ptr, count);
00322 }
00323
00324 static LIBSSH2_FREE_FUNC(my_libssh2_free)
00325 {
00326 (void)abstract;
00327 if(ptr)
00328 free(ptr);
00329 }
00330
00331
00332
00333
00334
00335 static void state(struct connectdata *conn, sshstate nowstate)
00336 {
00337 struct ssh_conn *sshc = &conn->proto.sshc;
00338 #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
00339
00340 static const char * const names[] = {
00341 "SSH_STOP",
00342 "SSH_INIT",
00343 "SSH_S_STARTUP",
00344 "SSH_HOSTKEY",
00345 "SSH_AUTHLIST",
00346 "SSH_AUTH_PKEY_INIT",
00347 "SSH_AUTH_PKEY",
00348 "SSH_AUTH_PASS_INIT",
00349 "SSH_AUTH_PASS",
00350 "SSH_AUTH_AGENT_INIT",
00351 "SSH_AUTH_AGENT_LIST",
00352 "SSH_AUTH_AGENT",
00353 "SSH_AUTH_HOST_INIT",
00354 "SSH_AUTH_HOST",
00355 "SSH_AUTH_KEY_INIT",
00356 "SSH_AUTH_KEY",
00357 "SSH_AUTH_DONE",
00358 "SSH_SFTP_INIT",
00359 "SSH_SFTP_REALPATH",
00360 "SSH_SFTP_QUOTE_INIT",
00361 "SSH_SFTP_POSTQUOTE_INIT",
00362 "SSH_SFTP_QUOTE",
00363 "SSH_SFTP_NEXT_QUOTE",
00364 "SSH_SFTP_QUOTE_STAT",
00365 "SSH_SFTP_QUOTE_SETSTAT",
00366 "SSH_SFTP_QUOTE_SYMLINK",
00367 "SSH_SFTP_QUOTE_MKDIR",
00368 "SSH_SFTP_QUOTE_RENAME",
00369 "SSH_SFTP_QUOTE_RMDIR",
00370 "SSH_SFTP_QUOTE_UNLINK",
00371 "SSH_SFTP_QUOTE_STATVFS",
00372 "SSH_SFTP_GETINFO",
00373 "SSH_SFTP_FILETIME",
00374 "SSH_SFTP_TRANS_INIT",
00375 "SSH_SFTP_UPLOAD_INIT",
00376 "SSH_SFTP_CREATE_DIRS_INIT",
00377 "SSH_SFTP_CREATE_DIRS",
00378 "SSH_SFTP_CREATE_DIRS_MKDIR",
00379 "SSH_SFTP_READDIR_INIT",
00380 "SSH_SFTP_READDIR",
00381 "SSH_SFTP_READDIR_LINK",
00382 "SSH_SFTP_READDIR_BOTTOM",
00383 "SSH_SFTP_READDIR_DONE",
00384 "SSH_SFTP_DOWNLOAD_INIT",
00385 "SSH_SFTP_DOWNLOAD_STAT",
00386 "SSH_SFTP_CLOSE",
00387 "SSH_SFTP_SHUTDOWN",
00388 "SSH_SCP_TRANS_INIT",
00389 "SSH_SCP_UPLOAD_INIT",
00390 "SSH_SCP_DOWNLOAD_INIT",
00391 "SSH_SCP_DONE",
00392 "SSH_SCP_SEND_EOF",
00393 "SSH_SCP_WAIT_EOF",
00394 "SSH_SCP_WAIT_CLOSE",
00395 "SSH_SCP_CHANNEL_FREE",
00396 "SSH_SESSION_DISCONNECT",
00397 "SSH_SESSION_FREE",
00398 "QUIT"
00399 };
00400
00401 if(sshc->state != nowstate) {
00402 infof(conn->data, "SFTP %p state change from %s to %s\n",
00403 (void *)sshc, names[sshc->state], names[nowstate]);
00404 }
00405 #endif
00406
00407 sshc->state = nowstate;
00408 }
00409
00410
00411 static CURLcode ssh_getworkingpath(struct connectdata *conn,
00412 char *homedir,
00413 char **path)
00414
00415 {
00416 struct Curl_easy *data = conn->data;
00417 char *real_path = NULL;
00418 char *working_path;
00419 size_t working_path_len;
00420 CURLcode result =
00421 Curl_urldecode(data, data->state.path, 0, &working_path,
00422 &working_path_len, FALSE);
00423 if(result)
00424 return result;
00425
00426
00427 if(conn->handler->protocol & CURLPROTO_SCP) {
00428 real_path = malloc(working_path_len+1);
00429 if(real_path == NULL) {
00430 free(working_path);
00431 return CURLE_OUT_OF_MEMORY;
00432 }
00433 if((working_path_len > 3) && (!memcmp(working_path, "/~/", 3)))
00434
00435 memcpy(real_path, working_path+3, 4 + working_path_len-3);
00436 else
00437 memcpy(real_path, working_path, 1 + working_path_len);
00438 }
00439 else if(conn->handler->protocol & CURLPROTO_SFTP) {
00440 if((working_path_len > 1) && (working_path[1] == '~')) {
00441 size_t homelen = strlen(homedir);
00442 real_path = malloc(homelen + working_path_len + 1);
00443 if(real_path == NULL) {
00444 free(working_path);
00445 return CURLE_OUT_OF_MEMORY;
00446 }
00447
00448
00449 memcpy(real_path, homedir, homelen);
00450 real_path[homelen] = '/';
00451 real_path[homelen+1] = '\0';
00452 if(working_path_len > 3) {
00453 memcpy(real_path+homelen+1, working_path + 3,
00454 1 + working_path_len -3);
00455 }
00456 }
00457 else {
00458 real_path = malloc(working_path_len+1);
00459 if(real_path == NULL) {
00460 free(working_path);
00461 return CURLE_OUT_OF_MEMORY;
00462 }
00463 memcpy(real_path, working_path, 1+working_path_len);
00464 }
00465 }
00466
00467 free(working_path);
00468
00469
00470 *path = real_path;
00471
00472 return CURLE_OK;
00473 }
00474
00475 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
00476 static int sshkeycallback(struct Curl_easy *easy,
00477 const struct curl_khkey *knownkey,
00478 const struct curl_khkey *foundkey,
00479 enum curl_khmatch match,
00480 void *clientp)
00481 {
00482 (void)easy;
00483 (void)knownkey;
00484 (void)foundkey;
00485 (void)clientp;
00486
00487
00488 return (match != CURLKHMATCH_OK)?CURLKHSTAT_REJECT:CURLKHSTAT_FINE;
00489 }
00490 #endif
00491
00492
00493
00494
00495
00496 #ifdef HAVE_LIBSSH2_SFTP_SEEK64
00497 #define SFTP_SEEK(x,y) libssh2_sftp_seek64(x, (libssh2_uint64_t)y)
00498 #else
00499 #define SFTP_SEEK(x,y) libssh2_sftp_seek(x, (size_t)y)
00500 #endif
00501
00502
00503
00504
00505
00506 #ifndef HAVE_LIBSSH2_SCP_SEND64
00507 #define SCP_SEND(a,b,c,d) libssh2_scp_send_ex(a, b, (int)(c), (size_t)d, 0, 0)
00508 #else
00509 #define SCP_SEND(a,b,c,d) libssh2_scp_send64(a, b, (int)(c), \
00510 (libssh2_uint64_t)d, 0, 0)
00511 #endif
00512
00513
00514
00515
00516 #ifdef HAVE_LIBSSH2_SESSION_HANDSHAKE
00517 #define libssh2_session_startup(x,y) libssh2_session_handshake(x,y)
00518 #endif
00519
00520 static CURLcode ssh_knownhost(struct connectdata *conn)
00521 {
00522 CURLcode result = CURLE_OK;
00523
00524 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
00525 struct Curl_easy *data = conn->data;
00526
00527 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
00528
00529 struct ssh_conn *sshc = &conn->proto.sshc;
00530 int rc;
00531 int keytype;
00532 size_t keylen;
00533 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
00534 &keylen, &keytype);
00535 int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
00536 int keybit = 0;
00537
00538 if(remotekey) {
00539
00540
00541
00542
00543
00544 struct libssh2_knownhost *host;
00545 enum curl_khmatch keymatch;
00546 curl_sshkeycallback func =
00547 data->set.ssh_keyfunc?data->set.ssh_keyfunc:sshkeycallback;
00548 struct curl_khkey knownkey;
00549 struct curl_khkey *knownkeyp = NULL;
00550 struct curl_khkey foundkey;
00551
00552 keybit = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
00553 LIBSSH2_KNOWNHOST_KEY_SSHRSA:LIBSSH2_KNOWNHOST_KEY_SSHDSS;
00554
00555 #ifdef HAVE_LIBSSH2_KNOWNHOST_CHECKP
00556 keycheck = libssh2_knownhost_checkp(sshc->kh,
00557 conn->host.name,
00558 (conn->remote_port != PORT_SSH)?
00559 conn->remote_port:-1,
00560 remotekey, keylen,
00561 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
00562 LIBSSH2_KNOWNHOST_KEYENC_RAW|
00563 keybit,
00564 &host);
00565 #else
00566 keycheck = libssh2_knownhost_check(sshc->kh,
00567 conn->host.name,
00568 remotekey, keylen,
00569 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
00570 LIBSSH2_KNOWNHOST_KEYENC_RAW|
00571 keybit,
00572 &host);
00573 #endif
00574
00575 infof(data, "SSH host check: %d, key: %s\n", keycheck,
00576 (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
00577 host->key:"<none>");
00578
00579
00580 if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
00581 knownkey.key = host->key;
00582 knownkey.len = 0;
00583 knownkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
00584 CURLKHTYPE_RSA : CURLKHTYPE_DSS;
00585 knownkeyp = &knownkey;
00586 }
00587
00588
00589 foundkey.key = remotekey;
00590 foundkey.len = keylen;
00591 foundkey.keytype = (keytype == LIBSSH2_HOSTKEY_TYPE_RSA)?
00592 CURLKHTYPE_RSA : CURLKHTYPE_DSS;
00593
00594
00595
00596
00597
00598
00599 keymatch = (enum curl_khmatch)keycheck;
00600
00601
00602 rc = func(data, knownkeyp,
00603 &foundkey,
00604 keymatch, data->set.ssh_keyfunc_userp);
00605 }
00606 else
00607
00608 rc = CURLKHSTAT_REJECT;
00609
00610 switch(rc) {
00611 default:
00612
00613 case CURLKHSTAT_REJECT:
00614 state(conn, SSH_SESSION_FREE);
00615
00616 case CURLKHSTAT_DEFER:
00617
00618 result = sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
00619 break;
00620 case CURLKHSTAT_FINE:
00621 case CURLKHSTAT_FINE_ADD_TO_FILE:
00622
00623 if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
00624
00625
00626 int addrc = libssh2_knownhost_add(sshc->kh,
00627 conn->host.name, NULL,
00628 remotekey, keylen,
00629 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
00630 LIBSSH2_KNOWNHOST_KEYENC_RAW|
00631 keybit, NULL);
00632 if(addrc)
00633 infof(data, "Warning adding the known host %s failed!\n",
00634 conn->host.name);
00635 else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE) {
00636
00637
00638 int wrc =
00639 libssh2_knownhost_writefile(sshc->kh,
00640 data->set.str[STRING_SSH_KNOWNHOSTS],
00641 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
00642 if(wrc) {
00643 infof(data, "Warning, writing %s failed!\n",
00644 data->set.str[STRING_SSH_KNOWNHOSTS]);
00645 }
00646 }
00647 }
00648 break;
00649 }
00650 }
00651 #else
00652 (void)conn;
00653 #endif
00654 return result;
00655 }
00656
00657 static CURLcode ssh_check_fingerprint(struct connectdata *conn)
00658 {
00659 struct ssh_conn *sshc = &conn->proto.sshc;
00660 struct Curl_easy *data = conn->data;
00661 const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
00662 char md5buffer[33];
00663 int i;
00664
00665 const char *fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
00666 LIBSSH2_HOSTKEY_HASH_MD5);
00667
00668 if(fingerprint) {
00669
00670 for(i = 0; i < 16; i++)
00671 snprintf(&md5buffer[i*2], 3, "%02x", (unsigned char) fingerprint[i]);
00672 infof(data, "SSH MD5 fingerprint: %s\n", md5buffer);
00673 }
00674
00675
00676
00677
00678 if(pubkey_md5 && strlen(pubkey_md5) == 32) {
00679 if(!fingerprint || !strcasecompare(md5buffer, pubkey_md5)) {
00680 if(fingerprint)
00681 failf(data,
00682 "Denied establishing ssh session: mismatch md5 fingerprint. "
00683 "Remote %s is not equal to %s", md5buffer, pubkey_md5);
00684 else
00685 failf(data,
00686 "Denied establishing ssh session: md5 fingerprint not available");
00687 state(conn, SSH_SESSION_FREE);
00688 sshc->actualcode = CURLE_PEER_FAILED_VERIFICATION;
00689 return sshc->actualcode;
00690 }
00691 else {
00692 infof(data, "MD5 checksum match!\n");
00693
00694 return CURLE_OK;
00695 }
00696 }
00697 else
00698 return ssh_knownhost(conn);
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708 static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
00709 {
00710 CURLcode result = CURLE_OK;
00711 struct Curl_easy *data = conn->data;
00712 struct SSHPROTO *sftp_scp = data->req.protop;
00713 struct ssh_conn *sshc = &conn->proto.sshc;
00714 curl_socket_t sock = conn->sock[FIRSTSOCKET];
00715 char *new_readdir_line;
00716 int rc = LIBSSH2_ERROR_NONE;
00717 int err;
00718 int seekerr = CURL_SEEKFUNC_OK;
00719 *block = 0;
00720
00721 do {
00722
00723 switch(sshc->state) {
00724 case SSH_INIT:
00725 sshc->secondCreateDirs = 0;
00726 sshc->nextstate = SSH_NO_STATE;
00727 sshc->actualcode = CURLE_OK;
00728
00729
00730
00731 libssh2_session_set_blocking(sshc->ssh_session, 0);
00732
00733 state(conn, SSH_S_STARTUP);
00734
00735
00736 case SSH_S_STARTUP:
00737 rc = libssh2_session_startup(sshc->ssh_session, (int)sock);
00738 if(rc == LIBSSH2_ERROR_EAGAIN) {
00739 break;
00740 }
00741 else if(rc) {
00742 failf(data, "Failure establishing ssh session");
00743 state(conn, SSH_SESSION_FREE);
00744 sshc->actualcode = CURLE_FAILED_INIT;
00745 break;
00746 }
00747
00748 state(conn, SSH_HOSTKEY);
00749
00750
00751 case SSH_HOSTKEY:
00752
00753
00754
00755
00756
00757 result = ssh_check_fingerprint(conn);
00758 if(!result)
00759 state(conn, SSH_AUTHLIST);
00760
00761 break;
00762
00763 case SSH_AUTHLIST:
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
00775 conn->user,
00776 curlx_uztoui(strlen(conn->user)));
00777
00778 if(!sshc->authlist) {
00779 if(libssh2_userauth_authenticated(sshc->ssh_session)) {
00780 sshc->authed = TRUE;
00781 infof(data, "SSH user accepted with no authentication\n");
00782 state(conn, SSH_AUTH_DONE);
00783 break;
00784 }
00785 else {
00786 err = libssh2_session_last_errno(sshc->ssh_session);
00787 if(err == LIBSSH2_ERROR_EAGAIN)
00788 rc = LIBSSH2_ERROR_EAGAIN;
00789 else {
00790 state(conn, SSH_SESSION_FREE);
00791 sshc->actualcode = libssh2_session_error_to_CURLE(err);
00792 }
00793 break;
00794 }
00795 }
00796 infof(data, "SSH authentication methods available: %s\n",
00797 sshc->authlist);
00798
00799 state(conn, SSH_AUTH_PKEY_INIT);
00800 break;
00801
00802 case SSH_AUTH_PKEY_INIT:
00803
00804
00805
00806
00807 sshc->authed = FALSE;
00808
00809 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
00810 (strstr(sshc->authlist, "publickey") != NULL)) {
00811 char *home = NULL;
00812 bool out_of_memory = FALSE;
00813
00814 sshc->rsa_pub = sshc->rsa = NULL;
00815
00816
00817
00818 home = curl_getenv("HOME");
00819
00820 if(data->set.str[STRING_SSH_PRIVATE_KEY])
00821 sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
00822 else {
00823
00824 if(home) {
00825
00826 sshc->rsa = aprintf("%s/.ssh/id_rsa", home);
00827 if(!sshc->rsa)
00828 out_of_memory = TRUE;
00829 else if(access(sshc->rsa, R_OK) != 0) {
00830 Curl_safefree(sshc->rsa);
00831 sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
00832 if(!sshc->rsa)
00833 out_of_memory = TRUE;
00834 else if(access(sshc->rsa, R_OK) != 0) {
00835 Curl_safefree(sshc->rsa);
00836 }
00837 }
00838 }
00839 if(!out_of_memory && !sshc->rsa) {
00840
00841 sshc->rsa = strdup("id_rsa");
00842 if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
00843 Curl_safefree(sshc->rsa);
00844 sshc->rsa = strdup("id_dsa");
00845 if(sshc->rsa && access(sshc->rsa, R_OK) != 0) {
00846 Curl_safefree(sshc->rsa);
00847
00848
00849 sshc->rsa = strdup("");
00850 }
00851 }
00852 }
00853 }
00854
00855
00856
00857
00858
00859
00860 if(data->set.str[STRING_SSH_PUBLIC_KEY]
00861
00862 && data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
00863 sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
00864 if(!sshc->rsa_pub)
00865 out_of_memory = TRUE;
00866 }
00867
00868 if(out_of_memory || sshc->rsa == NULL) {
00869 free(home);
00870 Curl_safefree(sshc->rsa);
00871 Curl_safefree(sshc->rsa_pub);
00872 state(conn, SSH_SESSION_FREE);
00873 sshc->actualcode = CURLE_OUT_OF_MEMORY;
00874 break;
00875 }
00876
00877 sshc->passphrase = data->set.ssl.key_passwd;
00878 if(!sshc->passphrase)
00879 sshc->passphrase = "";
00880
00881 free(home);
00882
00883 if(sshc->rsa_pub)
00884 infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub);
00885 infof(data, "Using SSH private key file '%s'\n", sshc->rsa);
00886
00887 state(conn, SSH_AUTH_PKEY);
00888 }
00889 else {
00890 state(conn, SSH_AUTH_PASS_INIT);
00891 }
00892 break;
00893
00894 case SSH_AUTH_PKEY:
00895
00896
00897 rc = libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
00898 conn->user,
00899 curlx_uztoui(
00900 strlen(conn->user)),
00901 sshc->rsa_pub,
00902 sshc->rsa, sshc->passphrase);
00903 if(rc == LIBSSH2_ERROR_EAGAIN) {
00904 break;
00905 }
00906
00907 Curl_safefree(sshc->rsa_pub);
00908 Curl_safefree(sshc->rsa);
00909
00910 if(rc == 0) {
00911 sshc->authed = TRUE;
00912 infof(data, "Initialized SSH public key authentication\n");
00913 state(conn, SSH_AUTH_DONE);
00914 }
00915 else {
00916 char *err_msg;
00917 (void)libssh2_session_last_error(sshc->ssh_session,
00918 &err_msg, NULL, 0);
00919 infof(data, "SSH public key authentication failed: %s\n", err_msg);
00920 state(conn, SSH_AUTH_PASS_INIT);
00921 }
00922 break;
00923
00924 case SSH_AUTH_PASS_INIT:
00925 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
00926 (strstr(sshc->authlist, "password") != NULL)) {
00927 state(conn, SSH_AUTH_PASS);
00928 }
00929 else {
00930 state(conn, SSH_AUTH_HOST_INIT);
00931 }
00932 break;
00933
00934 case SSH_AUTH_PASS:
00935 rc = libssh2_userauth_password_ex(sshc->ssh_session, conn->user,
00936 curlx_uztoui(strlen(conn->user)),
00937 conn->passwd,
00938 curlx_uztoui(strlen(conn->passwd)),
00939 NULL);
00940 if(rc == LIBSSH2_ERROR_EAGAIN) {
00941 break;
00942 }
00943 else if(rc == 0) {
00944 sshc->authed = TRUE;
00945 infof(data, "Initialized password authentication\n");
00946 state(conn, SSH_AUTH_DONE);
00947 }
00948 else {
00949 state(conn, SSH_AUTH_HOST_INIT);
00950 rc = 0;
00951 }
00952 break;
00953
00954 case SSH_AUTH_HOST_INIT:
00955 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
00956 (strstr(sshc->authlist, "hostbased") != NULL)) {
00957 state(conn, SSH_AUTH_HOST);
00958 }
00959 else {
00960 state(conn, SSH_AUTH_AGENT_INIT);
00961 }
00962 break;
00963
00964 case SSH_AUTH_HOST:
00965 state(conn, SSH_AUTH_AGENT_INIT);
00966 break;
00967
00968 case SSH_AUTH_AGENT_INIT:
00969 #ifdef HAVE_LIBSSH2_AGENT_API
00970 if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT)
00971 && (strstr(sshc->authlist, "publickey") != NULL)) {
00972
00973
00974
00975
00976 if(!sshc->ssh_agent) {
00977 sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
00978 if(!sshc->ssh_agent) {
00979 infof(data, "Could not create agent object\n");
00980
00981 state(conn, SSH_AUTH_KEY_INIT);
00982 break;
00983 }
00984 }
00985
00986 rc = libssh2_agent_connect(sshc->ssh_agent);
00987 if(rc == LIBSSH2_ERROR_EAGAIN)
00988 break;
00989 if(rc < 0) {
00990 infof(data, "Failure connecting to agent\n");
00991 state(conn, SSH_AUTH_KEY_INIT);
00992 }
00993 else {
00994 state(conn, SSH_AUTH_AGENT_LIST);
00995 }
00996 }
00997 else
00998 #endif
00999 state(conn, SSH_AUTH_KEY_INIT);
01000 break;
01001
01002 case SSH_AUTH_AGENT_LIST:
01003 #ifdef HAVE_LIBSSH2_AGENT_API
01004 rc = libssh2_agent_list_identities(sshc->ssh_agent);
01005
01006 if(rc == LIBSSH2_ERROR_EAGAIN)
01007 break;
01008 if(rc < 0) {
01009 infof(data, "Failure requesting identities to agent\n");
01010 state(conn, SSH_AUTH_KEY_INIT);
01011 }
01012 else {
01013 state(conn, SSH_AUTH_AGENT);
01014 sshc->sshagent_prev_identity = NULL;
01015 }
01016 #endif
01017 break;
01018
01019 case SSH_AUTH_AGENT:
01020 #ifdef HAVE_LIBSSH2_AGENT_API
01021
01022
01023
01024 rc = libssh2_agent_get_identity(sshc->ssh_agent,
01025 &sshc->sshagent_identity,
01026 sshc->sshagent_prev_identity);
01027 if(rc == LIBSSH2_ERROR_EAGAIN)
01028 break;
01029
01030 if(rc == 0) {
01031 rc = libssh2_agent_userauth(sshc->ssh_agent, conn->user,
01032 sshc->sshagent_identity);
01033
01034 if(rc < 0) {
01035 if(rc != LIBSSH2_ERROR_EAGAIN)
01036
01037 sshc->sshagent_prev_identity = sshc->sshagent_identity;
01038 else
01039 break;
01040 }
01041 }
01042
01043 if(rc < 0)
01044 infof(data, "Failure requesting identities to agent\n");
01045 else if(rc == 1)
01046 infof(data, "No identity would match\n");
01047
01048 if(rc == LIBSSH2_ERROR_NONE) {
01049 sshc->authed = TRUE;
01050 infof(data, "Agent based authentication successful\n");
01051 state(conn, SSH_AUTH_DONE);
01052 }
01053 else {
01054 state(conn, SSH_AUTH_KEY_INIT);
01055 rc = 0;
01056 }
01057 #endif
01058 break;
01059
01060 case SSH_AUTH_KEY_INIT:
01061 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
01062 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
01063 state(conn, SSH_AUTH_KEY);
01064 }
01065 else {
01066 state(conn, SSH_AUTH_DONE);
01067 }
01068 break;
01069
01070 case SSH_AUTH_KEY:
01071
01072 rc = libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
01073 conn->user,
01074 curlx_uztoui(
01075 strlen(conn->user)),
01076 &kbd_callback);
01077 if(rc == LIBSSH2_ERROR_EAGAIN) {
01078 break;
01079 }
01080 else if(rc == 0) {
01081 sshc->authed = TRUE;
01082 infof(data, "Initialized keyboard interactive authentication\n");
01083 }
01084 state(conn, SSH_AUTH_DONE);
01085 break;
01086
01087 case SSH_AUTH_DONE:
01088 if(!sshc->authed) {
01089 failf(data, "Authentication failure");
01090 state(conn, SSH_SESSION_FREE);
01091 sshc->actualcode = CURLE_LOGIN_DENIED;
01092 break;
01093 }
01094
01095
01096
01097
01098 infof(data, "Authentication complete\n");
01099
01100 Curl_pgrsTime(conn->data, TIMER_APPCONNECT);
01101
01102 conn->sockfd = sock;
01103 conn->writesockfd = CURL_SOCKET_BAD;
01104
01105 if(conn->handler->protocol == CURLPROTO_SFTP) {
01106 state(conn, SSH_SFTP_INIT);
01107 break;
01108 }
01109 infof(data, "SSH CONNECT phase done\n");
01110 state(conn, SSH_STOP);
01111 break;
01112
01113 case SSH_SFTP_INIT:
01114
01115
01116
01117 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
01118 if(!sshc->sftp_session) {
01119 if(libssh2_session_last_errno(sshc->ssh_session) ==
01120 LIBSSH2_ERROR_EAGAIN) {
01121 rc = LIBSSH2_ERROR_EAGAIN;
01122 break;
01123 }
01124 else {
01125 char *err_msg;
01126
01127 (void)libssh2_session_last_error(sshc->ssh_session,
01128 &err_msg, NULL, 0);
01129 failf(data, "Failure initializing sftp session: %s", err_msg);
01130 state(conn, SSH_SESSION_FREE);
01131 sshc->actualcode = CURLE_FAILED_INIT;
01132 break;
01133 }
01134 }
01135 state(conn, SSH_SFTP_REALPATH);
01136 break;
01137
01138 case SSH_SFTP_REALPATH:
01139 {
01140 char tempHome[PATH_MAX];
01141
01142
01143
01144
01145 rc = sftp_libssh2_realpath(sshc->sftp_session, ".",
01146 tempHome, PATH_MAX-1);
01147 if(rc == LIBSSH2_ERROR_EAGAIN) {
01148 break;
01149 }
01150 else if(rc > 0) {
01151
01152 tempHome[rc] = '\0';
01153 sshc->homedir = strdup(tempHome);
01154 if(!sshc->homedir) {
01155 state(conn, SSH_SFTP_CLOSE);
01156 sshc->actualcode = CURLE_OUT_OF_MEMORY;
01157 break;
01158 }
01159 conn->data->state.most_recent_ftp_entrypath = sshc->homedir;
01160 }
01161 else {
01162
01163 err = sftp_libssh2_last_error(sshc->sftp_session);
01164 if(err)
01165 result = sftp_libssh2_error_to_CURLE(err);
01166 else
01167
01168
01169 result = CURLE_SSH;
01170 sshc->actualcode = result;
01171 DEBUGF(infof(data, "error = %d makes libcurl = %d\n",
01172 err, (int)result));
01173 state(conn, SSH_STOP);
01174 break;
01175 }
01176 }
01177
01178
01179
01180
01181 DEBUGF(infof(data, "SSH CONNECT phase done\n"));
01182 state(conn, SSH_STOP);
01183 break;
01184
01185 case SSH_SFTP_QUOTE_INIT:
01186
01187 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
01188 if(result) {
01189 sshc->actualcode = result;
01190 state(conn, SSH_STOP);
01191 break;
01192 }
01193
01194 if(data->set.quote) {
01195 infof(data, "Sending quote commands\n");
01196 sshc->quote_item = data->set.quote;
01197 state(conn, SSH_SFTP_QUOTE);
01198 }
01199 else {
01200 state(conn, SSH_SFTP_GETINFO);
01201 }
01202 break;
01203
01204 case SSH_SFTP_POSTQUOTE_INIT:
01205 if(data->set.postquote) {
01206 infof(data, "Sending quote commands\n");
01207 sshc->quote_item = data->set.postquote;
01208 state(conn, SSH_SFTP_QUOTE);
01209 }
01210 else {
01211 state(conn, SSH_STOP);
01212 }
01213 break;
01214
01215 case SSH_SFTP_QUOTE:
01216
01217 {
01218 const char *cp;
01219
01220
01221
01222
01223 char *cmd = sshc->quote_item->data;
01224 sshc->acceptfail = FALSE;
01225
01226
01227
01228
01229
01230
01231 if(cmd[0] == '*') {
01232 cmd++;
01233 sshc->acceptfail = TRUE;
01234 }
01235
01236 if(strcasecompare("pwd", cmd)) {
01237
01238 char *tmp = aprintf("257 \"%s\" is current directory.\n",
01239 sftp_scp->path);
01240 if(!tmp) {
01241 result = CURLE_OUT_OF_MEMORY;
01242 state(conn, SSH_SFTP_CLOSE);
01243 sshc->nextstate = SSH_NO_STATE;
01244 break;
01245 }
01246 if(data->set.verbose) {
01247 Curl_debug(data, CURLINFO_HEADER_OUT, (char *)"PWD\n", 4, conn);
01248 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp), conn);
01249 }
01250
01251
01252
01253 result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
01254 free(tmp);
01255 if(result) {
01256 state(conn, SSH_SFTP_CLOSE);
01257 sshc->nextstate = SSH_NO_STATE;
01258 sshc->actualcode = result;
01259 }
01260 else
01261 state(conn, SSH_SFTP_NEXT_QUOTE);
01262 break;
01263 }
01264 else if(cmd) {
01265
01266
01267
01268
01269 cp = strchr(cmd, ' ');
01270 if(cp == NULL) {
01271 failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
01272 state(conn, SSH_SFTP_CLOSE);
01273 sshc->nextstate = SSH_NO_STATE;
01274 sshc->actualcode = CURLE_QUOTE_ERROR;
01275 break;
01276 }
01277
01278
01279
01280
01281
01282 result = get_pathname(&cp, &sshc->quote_path1);
01283 if(result) {
01284 if(result == CURLE_OUT_OF_MEMORY)
01285 failf(data, "Out of memory");
01286 else
01287 failf(data, "Syntax error: Bad first parameter");
01288 state(conn, SSH_SFTP_CLOSE);
01289 sshc->nextstate = SSH_NO_STATE;
01290 sshc->actualcode = result;
01291 break;
01292 }
01293
01294
01295
01296
01297
01298
01299
01300 if(strncasecompare(cmd, "chgrp ", 6) ||
01301 strncasecompare(cmd, "chmod ", 6) ||
01302 strncasecompare(cmd, "chown ", 6) ) {
01303
01304
01305
01306
01307 result = get_pathname(&cp, &sshc->quote_path2);
01308 if(result) {
01309 if(result == CURLE_OUT_OF_MEMORY)
01310 failf(data, "Out of memory");
01311 else
01312 failf(data, "Syntax error in chgrp/chmod/chown: "
01313 "Bad second parameter");
01314 Curl_safefree(sshc->quote_path1);
01315 state(conn, SSH_SFTP_CLOSE);
01316 sshc->nextstate = SSH_NO_STATE;
01317 sshc->actualcode = result;
01318 break;
01319 }
01320 memset(&sshc->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
01321 state(conn, SSH_SFTP_QUOTE_STAT);
01322 break;
01323 }
01324 else if(strncasecompare(cmd, "ln ", 3) ||
01325 strncasecompare(cmd, "symlink ", 8)) {
01326
01327
01328
01329 result = get_pathname(&cp, &sshc->quote_path2);
01330 if(result) {
01331 if(result == CURLE_OUT_OF_MEMORY)
01332 failf(data, "Out of memory");
01333 else
01334 failf(data,
01335 "Syntax error in ln/symlink: Bad second parameter");
01336 Curl_safefree(sshc->quote_path1);
01337 state(conn, SSH_SFTP_CLOSE);
01338 sshc->nextstate = SSH_NO_STATE;
01339 sshc->actualcode = result;
01340 break;
01341 }
01342 state(conn, SSH_SFTP_QUOTE_SYMLINK);
01343 break;
01344 }
01345 else if(strncasecompare(cmd, "mkdir ", 6)) {
01346
01347 state(conn, SSH_SFTP_QUOTE_MKDIR);
01348 break;
01349 }
01350 else if(strncasecompare(cmd, "rename ", 7)) {
01351
01352
01353
01354 result = get_pathname(&cp, &sshc->quote_path2);
01355 if(result) {
01356 if(result == CURLE_OUT_OF_MEMORY)
01357 failf(data, "Out of memory");
01358 else
01359 failf(data, "Syntax error in rename: Bad second parameter");
01360 Curl_safefree(sshc->quote_path1);
01361 state(conn, SSH_SFTP_CLOSE);
01362 sshc->nextstate = SSH_NO_STATE;
01363 sshc->actualcode = result;
01364 break;
01365 }
01366 state(conn, SSH_SFTP_QUOTE_RENAME);
01367 break;
01368 }
01369 else if(strncasecompare(cmd, "rmdir ", 6)) {
01370
01371 state(conn, SSH_SFTP_QUOTE_RMDIR);
01372 break;
01373 }
01374 else if(strncasecompare(cmd, "rm ", 3)) {
01375 state(conn, SSH_SFTP_QUOTE_UNLINK);
01376 break;
01377 }
01378 #ifdef HAS_STATVFS_SUPPORT
01379 else if(strncasecompare(cmd, "statvfs ", 8)) {
01380 state(conn, SSH_SFTP_QUOTE_STATVFS);
01381 break;
01382 }
01383 #endif
01384
01385 failf(data, "Unknown SFTP command");
01386 Curl_safefree(sshc->quote_path1);
01387 Curl_safefree(sshc->quote_path2);
01388 state(conn, SSH_SFTP_CLOSE);
01389 sshc->nextstate = SSH_NO_STATE;
01390 sshc->actualcode = CURLE_QUOTE_ERROR;
01391 break;
01392 }
01393 }
01394 if(!sshc->quote_item) {
01395 state(conn, SSH_SFTP_GETINFO);
01396 }
01397 break;
01398
01399 case SSH_SFTP_NEXT_QUOTE:
01400 Curl_safefree(sshc->quote_path1);
01401 Curl_safefree(sshc->quote_path2);
01402
01403 sshc->quote_item = sshc->quote_item->next;
01404
01405 if(sshc->quote_item) {
01406 state(conn, SSH_SFTP_QUOTE);
01407 }
01408 else {
01409 if(sshc->nextstate != SSH_NO_STATE) {
01410 state(conn, sshc->nextstate);
01411 sshc->nextstate = SSH_NO_STATE;
01412 }
01413 else {
01414 state(conn, SSH_SFTP_GETINFO);
01415 }
01416 }
01417 break;
01418
01419 case SSH_SFTP_QUOTE_STAT:
01420 {
01421 char *cmd = sshc->quote_item->data;
01422 sshc->acceptfail = FALSE;
01423
01424
01425
01426
01427
01428
01429 if(cmd[0] == '*') {
01430 cmd++;
01431 sshc->acceptfail = TRUE;
01432 }
01433
01434 if(!strncasecompare(cmd, "chmod", 5)) {
01435
01436
01437
01438
01439 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
01440 curlx_uztoui(strlen(sshc->quote_path2)),
01441 LIBSSH2_SFTP_STAT,
01442 &sshc->quote_attrs);
01443 if(rc == LIBSSH2_ERROR_EAGAIN) {
01444 break;
01445 }
01446 else if(rc != 0 && !sshc->acceptfail) {
01447 err = sftp_libssh2_last_error(sshc->sftp_session);
01448 Curl_safefree(sshc->quote_path1);
01449 Curl_safefree(sshc->quote_path2);
01450 failf(data, "Attempt to get SFTP stats failed: %s",
01451 sftp_libssh2_strerror(err));
01452 state(conn, SSH_SFTP_CLOSE);
01453 sshc->nextstate = SSH_NO_STATE;
01454 sshc->actualcode = CURLE_QUOTE_ERROR;
01455 break;
01456 }
01457 }
01458
01459
01460 if(strncasecompare(cmd, "chgrp", 5)) {
01461 sshc->quote_attrs.gid = strtoul(sshc->quote_path1, NULL, 10);
01462 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
01463 if(sshc->quote_attrs.gid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
01464 !sshc->acceptfail) {
01465 Curl_safefree(sshc->quote_path1);
01466 Curl_safefree(sshc->quote_path2);
01467 failf(data, "Syntax error: chgrp gid not a number");
01468 state(conn, SSH_SFTP_CLOSE);
01469 sshc->nextstate = SSH_NO_STATE;
01470 sshc->actualcode = CURLE_QUOTE_ERROR;
01471 break;
01472 }
01473 }
01474 else if(strncasecompare(cmd, "chmod", 5)) {
01475 sshc->quote_attrs.permissions = strtoul(sshc->quote_path1, NULL, 8);
01476 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
01477
01478 if(sshc->quote_attrs.permissions == 0 &&
01479 !ISDIGIT(sshc->quote_path1[0])) {
01480 Curl_safefree(sshc->quote_path1);
01481 Curl_safefree(sshc->quote_path2);
01482 failf(data, "Syntax error: chmod permissions not a number");
01483 state(conn, SSH_SFTP_CLOSE);
01484 sshc->nextstate = SSH_NO_STATE;
01485 sshc->actualcode = CURLE_QUOTE_ERROR;
01486 break;
01487 }
01488 }
01489 else if(strncasecompare(cmd, "chown", 5)) {
01490 sshc->quote_attrs.uid = strtoul(sshc->quote_path1, NULL, 10);
01491 sshc->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
01492 if(sshc->quote_attrs.uid == 0 && !ISDIGIT(sshc->quote_path1[0]) &&
01493 !sshc->acceptfail) {
01494 Curl_safefree(sshc->quote_path1);
01495 Curl_safefree(sshc->quote_path2);
01496 failf(data, "Syntax error: chown uid not a number");
01497 state(conn, SSH_SFTP_CLOSE);
01498 sshc->nextstate = SSH_NO_STATE;
01499 sshc->actualcode = CURLE_QUOTE_ERROR;
01500 break;
01501 }
01502 }
01503
01504
01505 state(conn, SSH_SFTP_QUOTE_SETSTAT);
01506 break;
01507 }
01508
01509 case SSH_SFTP_QUOTE_SETSTAT:
01510 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
01511 curlx_uztoui(strlen(sshc->quote_path2)),
01512 LIBSSH2_SFTP_SETSTAT,
01513 &sshc->quote_attrs);
01514 if(rc == LIBSSH2_ERROR_EAGAIN) {
01515 break;
01516 }
01517 else if(rc != 0 && !sshc->acceptfail) {
01518 err = sftp_libssh2_last_error(sshc->sftp_session);
01519 Curl_safefree(sshc->quote_path1);
01520 Curl_safefree(sshc->quote_path2);
01521 failf(data, "Attempt to set SFTP stats failed: %s",
01522 sftp_libssh2_strerror(err));
01523 state(conn, SSH_SFTP_CLOSE);
01524 sshc->nextstate = SSH_NO_STATE;
01525 sshc->actualcode = CURLE_QUOTE_ERROR;
01526 break;
01527 }
01528 state(conn, SSH_SFTP_NEXT_QUOTE);
01529 break;
01530
01531 case SSH_SFTP_QUOTE_SYMLINK:
01532 rc = libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
01533 curlx_uztoui(strlen(sshc->quote_path1)),
01534 sshc->quote_path2,
01535 curlx_uztoui(strlen(sshc->quote_path2)),
01536 LIBSSH2_SFTP_SYMLINK);
01537 if(rc == LIBSSH2_ERROR_EAGAIN) {
01538 break;
01539 }
01540 else if(rc != 0 && !sshc->acceptfail) {
01541 err = sftp_libssh2_last_error(sshc->sftp_session);
01542 Curl_safefree(sshc->quote_path1);
01543 Curl_safefree(sshc->quote_path2);
01544 failf(data, "symlink command failed: %s",
01545 sftp_libssh2_strerror(err));
01546 state(conn, SSH_SFTP_CLOSE);
01547 sshc->nextstate = SSH_NO_STATE;
01548 sshc->actualcode = CURLE_QUOTE_ERROR;
01549 break;
01550 }
01551 state(conn, SSH_SFTP_NEXT_QUOTE);
01552 break;
01553
01554 case SSH_SFTP_QUOTE_MKDIR:
01555 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
01556 curlx_uztoui(strlen(sshc->quote_path1)),
01557 data->set.new_directory_perms);
01558 if(rc == LIBSSH2_ERROR_EAGAIN) {
01559 break;
01560 }
01561 else if(rc != 0 && !sshc->acceptfail) {
01562 err = sftp_libssh2_last_error(sshc->sftp_session);
01563 Curl_safefree(sshc->quote_path1);
01564 failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
01565 state(conn, SSH_SFTP_CLOSE);
01566 sshc->nextstate = SSH_NO_STATE;
01567 sshc->actualcode = CURLE_QUOTE_ERROR;
01568 break;
01569 }
01570 state(conn, SSH_SFTP_NEXT_QUOTE);
01571 break;
01572
01573 case SSH_SFTP_QUOTE_RENAME:
01574 rc = libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
01575 curlx_uztoui(strlen(sshc->quote_path1)),
01576 sshc->quote_path2,
01577 curlx_uztoui(strlen(sshc->quote_path2)),
01578 LIBSSH2_SFTP_RENAME_OVERWRITE |
01579 LIBSSH2_SFTP_RENAME_ATOMIC |
01580 LIBSSH2_SFTP_RENAME_NATIVE);
01581
01582 if(rc == LIBSSH2_ERROR_EAGAIN) {
01583 break;
01584 }
01585 else if(rc != 0 && !sshc->acceptfail) {
01586 err = sftp_libssh2_last_error(sshc->sftp_session);
01587 Curl_safefree(sshc->quote_path1);
01588 Curl_safefree(sshc->quote_path2);
01589 failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
01590 state(conn, SSH_SFTP_CLOSE);
01591 sshc->nextstate = SSH_NO_STATE;
01592 sshc->actualcode = CURLE_QUOTE_ERROR;
01593 break;
01594 }
01595 state(conn, SSH_SFTP_NEXT_QUOTE);
01596 break;
01597
01598 case SSH_SFTP_QUOTE_RMDIR:
01599 rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
01600 curlx_uztoui(strlen(sshc->quote_path1)));
01601 if(rc == LIBSSH2_ERROR_EAGAIN) {
01602 break;
01603 }
01604 else if(rc != 0 && !sshc->acceptfail) {
01605 err = sftp_libssh2_last_error(sshc->sftp_session);
01606 Curl_safefree(sshc->quote_path1);
01607 failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
01608 state(conn, SSH_SFTP_CLOSE);
01609 sshc->nextstate = SSH_NO_STATE;
01610 sshc->actualcode = CURLE_QUOTE_ERROR;
01611 break;
01612 }
01613 state(conn, SSH_SFTP_NEXT_QUOTE);
01614 break;
01615
01616 case SSH_SFTP_QUOTE_UNLINK:
01617 rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
01618 curlx_uztoui(strlen(sshc->quote_path1)));
01619 if(rc == LIBSSH2_ERROR_EAGAIN) {
01620 break;
01621 }
01622 else if(rc != 0 && !sshc->acceptfail) {
01623 err = sftp_libssh2_last_error(sshc->sftp_session);
01624 Curl_safefree(sshc->quote_path1);
01625 failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
01626 state(conn, SSH_SFTP_CLOSE);
01627 sshc->nextstate = SSH_NO_STATE;
01628 sshc->actualcode = CURLE_QUOTE_ERROR;
01629 break;
01630 }
01631 state(conn, SSH_SFTP_NEXT_QUOTE);
01632 break;
01633
01634 #ifdef HAS_STATVFS_SUPPORT
01635 case SSH_SFTP_QUOTE_STATVFS:
01636 {
01637 LIBSSH2_SFTP_STATVFS statvfs;
01638 rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
01639 curlx_uztoui(strlen(sshc->quote_path1)),
01640 &statvfs);
01641
01642 if(rc == LIBSSH2_ERROR_EAGAIN) {
01643 break;
01644 }
01645 else if(rc != 0 && !sshc->acceptfail) {
01646 err = sftp_libssh2_last_error(sshc->sftp_session);
01647 Curl_safefree(sshc->quote_path1);
01648 failf(data, "statvfs command failed: %s", sftp_libssh2_strerror(err));
01649 state(conn, SSH_SFTP_CLOSE);
01650 sshc->nextstate = SSH_NO_STATE;
01651 sshc->actualcode = CURLE_QUOTE_ERROR;
01652 break;
01653 }
01654 else if(rc == 0) {
01655 char *tmp = aprintf("statvfs:\n"
01656 "f_bsize: %llu\n" "f_frsize: %llu\n"
01657 "f_blocks: %llu\n" "f_bfree: %llu\n"
01658 "f_bavail: %llu\n" "f_files: %llu\n"
01659 "f_ffree: %llu\n" "f_favail: %llu\n"
01660 "f_fsid: %llu\n" "f_flag: %llu\n"
01661 "f_namemax: %llu\n",
01662 statvfs.f_bsize, statvfs.f_frsize,
01663 statvfs.f_blocks, statvfs.f_bfree,
01664 statvfs.f_bavail, statvfs.f_files,
01665 statvfs.f_ffree, statvfs.f_favail,
01666 statvfs.f_fsid, statvfs.f_flag,
01667 statvfs.f_namemax);
01668 if(!tmp) {
01669 result = CURLE_OUT_OF_MEMORY;
01670 state(conn, SSH_SFTP_CLOSE);
01671 sshc->nextstate = SSH_NO_STATE;
01672 break;
01673 }
01674
01675 result = Curl_client_write(conn, CLIENTWRITE_HEADER, tmp, strlen(tmp));
01676 free(tmp);
01677 if(result) {
01678 state(conn, SSH_SFTP_CLOSE);
01679 sshc->nextstate = SSH_NO_STATE;
01680 sshc->actualcode = result;
01681 }
01682 }
01683 state(conn, SSH_SFTP_NEXT_QUOTE);
01684 break;
01685 }
01686 #endif
01687 case SSH_SFTP_GETINFO:
01688 {
01689 if(data->set.get_filetime) {
01690 state(conn, SSH_SFTP_FILETIME);
01691 }
01692 else {
01693 state(conn, SSH_SFTP_TRANS_INIT);
01694 }
01695 break;
01696 }
01697
01698 case SSH_SFTP_FILETIME:
01699 {
01700 LIBSSH2_SFTP_ATTRIBUTES attrs;
01701
01702 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
01703 curlx_uztoui(strlen(sftp_scp->path)),
01704 LIBSSH2_SFTP_STAT, &attrs);
01705 if(rc == LIBSSH2_ERROR_EAGAIN) {
01706 break;
01707 }
01708 else if(rc == 0) {
01709 data->info.filetime = (long)attrs.mtime;
01710 }
01711
01712 state(conn, SSH_SFTP_TRANS_INIT);
01713 break;
01714 }
01715
01716 case SSH_SFTP_TRANS_INIT:
01717 if(data->set.upload)
01718 state(conn, SSH_SFTP_UPLOAD_INIT);
01719 else {
01720 if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
01721 state(conn, SSH_SFTP_READDIR_INIT);
01722 else
01723 state(conn, SSH_SFTP_DOWNLOAD_INIT);
01724 }
01725 break;
01726
01727 case SSH_SFTP_UPLOAD_INIT:
01728 {
01729 unsigned long flags;
01730
01731
01732
01733
01734
01735
01736
01737 if(data->state.resume_from != 0) {
01738 LIBSSH2_SFTP_ATTRIBUTES attrs;
01739 if(data->state.resume_from < 0) {
01740 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
01741 curlx_uztoui(strlen(sftp_scp->path)),
01742 LIBSSH2_SFTP_STAT, &attrs);
01743 if(rc == LIBSSH2_ERROR_EAGAIN) {
01744 break;
01745 }
01746 else if(rc) {
01747 data->state.resume_from = 0;
01748 }
01749 else {
01750 curl_off_t size = attrs.filesize;
01751 if(size < 0) {
01752 failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
01753 return CURLE_BAD_DOWNLOAD_RESUME;
01754 }
01755 data->state.resume_from = attrs.filesize;
01756 }
01757 }
01758 }
01759
01760 if(data->set.ftp_append)
01761
01762 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_APPEND;
01763 else if(data->state.resume_from > 0)
01764
01765 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_APPEND;
01766 else
01767
01768 flags = LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC;
01769
01770 sshc->sftp_handle =
01771 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
01772 curlx_uztoui(strlen(sftp_scp->path)),
01773 flags, data->set.new_file_perms,
01774 LIBSSH2_SFTP_OPENFILE);
01775
01776 if(!sshc->sftp_handle) {
01777 rc = libssh2_session_last_errno(sshc->ssh_session);
01778
01779 if(LIBSSH2_ERROR_EAGAIN == rc)
01780 break;
01781 else {
01782 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
01783
01784
01785 err = sftp_libssh2_last_error(sshc->sftp_session);
01786 else
01787 err = -1;
01788
01789 if(sshc->secondCreateDirs) {
01790 state(conn, SSH_SFTP_CLOSE);
01791 sshc->actualcode = err>= LIBSSH2_FX_OK?
01792 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
01793 failf(data, "Creating the dir/file failed: %s",
01794 sftp_libssh2_strerror(err));
01795 break;
01796 }
01797 else if(((err == LIBSSH2_FX_NO_SUCH_FILE) ||
01798 (err == LIBSSH2_FX_FAILURE) ||
01799 (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
01800 (data->set.ftp_create_missing_dirs &&
01801 (strlen(sftp_scp->path) > 1))) {
01802
01803 sshc->secondCreateDirs = 1;
01804 state(conn, SSH_SFTP_CREATE_DIRS_INIT);
01805 break;
01806 }
01807 state(conn, SSH_SFTP_CLOSE);
01808 sshc->actualcode = err>= LIBSSH2_FX_OK?
01809 sftp_libssh2_error_to_CURLE(err):CURLE_SSH;
01810 if(!sshc->actualcode) {
01811
01812
01813
01814 sshc->actualcode = CURLE_SSH;
01815 err=-1;
01816 }
01817 failf(data, "Upload failed: %s (%d/%d)",
01818 err>= LIBSSH2_FX_OK?sftp_libssh2_strerror(err):"ssh error",
01819 err, rc);
01820 break;
01821 }
01822 }
01823
01824
01825
01826 if(data->state.resume_from > 0) {
01827
01828 if(conn->seek_func) {
01829 seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
01830 SEEK_SET);
01831 }
01832
01833 if(seekerr != CURL_SEEKFUNC_OK) {
01834
01835 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
01836 failf(data, "Could not seek stream");
01837 return CURLE_FTP_COULDNT_USE_REST;
01838 }
01839
01840 else {
01841 curl_off_t passed=0;
01842 do {
01843 size_t readthisamountnow =
01844 (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
01845 BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
01846
01847 size_t actuallyread =
01848 data->state.fread_func(data->state.buffer, 1,
01849 readthisamountnow, data->state.in);
01850
01851 passed += actuallyread;
01852 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
01853
01854
01855 failf(data, "Failed to read data");
01856 return CURLE_FTP_COULDNT_USE_REST;
01857 }
01858 } while(passed < data->state.resume_from);
01859 }
01860 }
01861
01862
01863 if(data->state.infilesize > 0) {
01864 data->state.infilesize -= data->state.resume_from;
01865 data->req.size = data->state.infilesize;
01866 Curl_pgrsSetUploadSize(data, data->state.infilesize);
01867 }
01868
01869 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
01870 }
01871 if(data->state.infilesize > 0) {
01872 data->req.size = data->state.infilesize;
01873 Curl_pgrsSetUploadSize(data, data->state.infilesize);
01874 }
01875
01876 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
01877
01878
01879 conn->sockfd = conn->writesockfd;
01880
01881 if(result) {
01882 state(conn, SSH_SFTP_CLOSE);
01883 sshc->actualcode = result;
01884 }
01885 else {
01886
01887
01888 sshc->orig_waitfor = data->req.keepon;
01889
01890
01891
01892
01893 conn->cselect_bits = CURL_CSELECT_OUT;
01894
01895
01896
01897
01898 Curl_expire(data, 0);
01899
01900 state(conn, SSH_STOP);
01901 }
01902 break;
01903 }
01904
01905 case SSH_SFTP_CREATE_DIRS_INIT:
01906 if(strlen(sftp_scp->path) > 1) {
01907 sshc->slash_pos = sftp_scp->path + 1;
01908 state(conn, SSH_SFTP_CREATE_DIRS);
01909 }
01910 else {
01911 state(conn, SSH_SFTP_UPLOAD_INIT);
01912 }
01913 break;
01914
01915 case SSH_SFTP_CREATE_DIRS:
01916 sshc->slash_pos = strchr(sshc->slash_pos, '/');
01917 if(sshc->slash_pos) {
01918 *sshc->slash_pos = 0;
01919
01920 infof(data, "Creating directory '%s'\n", sftp_scp->path);
01921 state(conn, SSH_SFTP_CREATE_DIRS_MKDIR);
01922 break;
01923 }
01924 else {
01925 state(conn, SSH_SFTP_UPLOAD_INIT);
01926 }
01927 break;
01928
01929 case SSH_SFTP_CREATE_DIRS_MKDIR:
01930
01931 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sftp_scp->path,
01932 curlx_uztoui(strlen(sftp_scp->path)),
01933 data->set.new_directory_perms);
01934 if(rc == LIBSSH2_ERROR_EAGAIN) {
01935 break;
01936 }
01937 *sshc->slash_pos = '/';
01938 ++sshc->slash_pos;
01939 if(rc == -1) {
01940
01941
01942
01943
01944
01945 err = sftp_libssh2_last_error(sshc->sftp_session);
01946 if((err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
01947 (err != LIBSSH2_FX_FAILURE) &&
01948 (err != LIBSSH2_FX_PERMISSION_DENIED)) {
01949 result = sftp_libssh2_error_to_CURLE(err);
01950 state(conn, SSH_SFTP_CLOSE);
01951 sshc->actualcode = result?result:CURLE_SSH;
01952 break;
01953 }
01954 }
01955 state(conn, SSH_SFTP_CREATE_DIRS);
01956 break;
01957
01958 case SSH_SFTP_READDIR_INIT:
01959 Curl_pgrsSetDownloadSize(data, -1);
01960 if(data->set.opt_no_body) {
01961 state(conn, SSH_STOP);
01962 break;
01963 }
01964
01965
01966
01967
01968
01969 sshc->sftp_handle = libssh2_sftp_open_ex(sshc->sftp_session,
01970 sftp_scp->path,
01971 curlx_uztoui(
01972 strlen(sftp_scp->path)),
01973 0, 0, LIBSSH2_SFTP_OPENDIR);
01974 if(!sshc->sftp_handle) {
01975 if(libssh2_session_last_errno(sshc->ssh_session) ==
01976 LIBSSH2_ERROR_EAGAIN) {
01977 rc = LIBSSH2_ERROR_EAGAIN;
01978 break;
01979 }
01980 else {
01981 err = sftp_libssh2_last_error(sshc->sftp_session);
01982 failf(data, "Could not open directory for reading: %s",
01983 sftp_libssh2_strerror(err));
01984 state(conn, SSH_SFTP_CLOSE);
01985 result = sftp_libssh2_error_to_CURLE(err);
01986 sshc->actualcode = result?result:CURLE_SSH;
01987 break;
01988 }
01989 }
01990 sshc->readdir_filename = malloc(PATH_MAX+1);
01991 if(!sshc->readdir_filename) {
01992 state(conn, SSH_SFTP_CLOSE);
01993 sshc->actualcode = CURLE_OUT_OF_MEMORY;
01994 break;
01995 }
01996 sshc->readdir_longentry = malloc(PATH_MAX+1);
01997 if(!sshc->readdir_longentry) {
01998 Curl_safefree(sshc->readdir_filename);
01999 state(conn, SSH_SFTP_CLOSE);
02000 sshc->actualcode = CURLE_OUT_OF_MEMORY;
02001 break;
02002 }
02003 state(conn, SSH_SFTP_READDIR);
02004 break;
02005
02006 case SSH_SFTP_READDIR:
02007 sshc->readdir_len = libssh2_sftp_readdir_ex(sshc->sftp_handle,
02008 sshc->readdir_filename,
02009 PATH_MAX,
02010 sshc->readdir_longentry,
02011 PATH_MAX,
02012 &sshc->readdir_attrs);
02013 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
02014 rc = LIBSSH2_ERROR_EAGAIN;
02015 break;
02016 }
02017 if(sshc->readdir_len > 0) {
02018 sshc->readdir_filename[sshc->readdir_len] = '\0';
02019
02020 if(data->set.ftp_list_only) {
02021 char *tmpLine;
02022
02023 tmpLine = aprintf("%s\n", sshc->readdir_filename);
02024 if(tmpLine == NULL) {
02025 state(conn, SSH_SFTP_CLOSE);
02026 sshc->actualcode = CURLE_OUT_OF_MEMORY;
02027 break;
02028 }
02029 result = Curl_client_write(conn, CLIENTWRITE_BODY,
02030 tmpLine, sshc->readdir_len+1);
02031 free(tmpLine);
02032
02033 if(result) {
02034 state(conn, SSH_STOP);
02035 break;
02036 }
02037
02038
02039 data->req.bytecount += sshc->readdir_len+1;
02040
02041
02042 if(data->set.verbose) {
02043 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_filename,
02044 sshc->readdir_len, conn);
02045 }
02046 }
02047 else {
02048 sshc->readdir_currLen = (int)strlen(sshc->readdir_longentry);
02049 sshc->readdir_totalLen = 80 + sshc->readdir_currLen;
02050 sshc->readdir_line = calloc(sshc->readdir_totalLen, 1);
02051 if(!sshc->readdir_line) {
02052 Curl_safefree(sshc->readdir_filename);
02053 Curl_safefree(sshc->readdir_longentry);
02054 state(conn, SSH_SFTP_CLOSE);
02055 sshc->actualcode = CURLE_OUT_OF_MEMORY;
02056 break;
02057 }
02058
02059 memcpy(sshc->readdir_line, sshc->readdir_longentry,
02060 sshc->readdir_currLen);
02061 if((sshc->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
02062 ((sshc->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
02063 LIBSSH2_SFTP_S_IFLNK)) {
02064 sshc->readdir_linkPath = malloc(PATH_MAX + 1);
02065 if(sshc->readdir_linkPath == NULL) {
02066 Curl_safefree(sshc->readdir_filename);
02067 Curl_safefree(sshc->readdir_longentry);
02068 state(conn, SSH_SFTP_CLOSE);
02069 sshc->actualcode = CURLE_OUT_OF_MEMORY;
02070 break;
02071 }
02072
02073 snprintf(sshc->readdir_linkPath, PATH_MAX, "%s%s", sftp_scp->path,
02074 sshc->readdir_filename);
02075 state(conn, SSH_SFTP_READDIR_LINK);
02076 break;
02077 }
02078 state(conn, SSH_SFTP_READDIR_BOTTOM);
02079 break;
02080 }
02081 }
02082 else if(sshc->readdir_len == 0) {
02083 Curl_safefree(sshc->readdir_filename);
02084 Curl_safefree(sshc->readdir_longentry);
02085 state(conn, SSH_SFTP_READDIR_DONE);
02086 break;
02087 }
02088 else if(sshc->readdir_len <= 0) {
02089 err = sftp_libssh2_last_error(sshc->sftp_session);
02090 result = sftp_libssh2_error_to_CURLE(err);
02091 sshc->actualcode = result?result:CURLE_SSH;
02092 failf(data, "Could not open remote file for reading: %s :: %d",
02093 sftp_libssh2_strerror(err),
02094 libssh2_session_last_errno(sshc->ssh_session));
02095 Curl_safefree(sshc->readdir_filename);
02096 Curl_safefree(sshc->readdir_longentry);
02097 state(conn, SSH_SFTP_CLOSE);
02098 break;
02099 }
02100 break;
02101
02102 case SSH_SFTP_READDIR_LINK:
02103 sshc->readdir_len =
02104 libssh2_sftp_symlink_ex(sshc->sftp_session,
02105 sshc->readdir_linkPath,
02106 curlx_uztoui(strlen(sshc->readdir_linkPath)),
02107 sshc->readdir_filename,
02108 PATH_MAX, LIBSSH2_SFTP_READLINK);
02109 if(sshc->readdir_len == LIBSSH2_ERROR_EAGAIN) {
02110 rc = LIBSSH2_ERROR_EAGAIN;
02111 break;
02112 }
02113 Curl_safefree(sshc->readdir_linkPath);
02114
02115
02116 sshc->readdir_totalLen += 4 + sshc->readdir_len;
02117 new_readdir_line = Curl_saferealloc(sshc->readdir_line,
02118 sshc->readdir_totalLen);
02119 if(!new_readdir_line) {
02120 sshc->readdir_line = NULL;
02121 Curl_safefree(sshc->readdir_filename);
02122 Curl_safefree(sshc->readdir_longentry);
02123 state(conn, SSH_SFTP_CLOSE);
02124 sshc->actualcode = CURLE_OUT_OF_MEMORY;
02125 break;
02126 }
02127 sshc->readdir_line = new_readdir_line;
02128
02129 sshc->readdir_currLen += snprintf(sshc->readdir_line +
02130 sshc->readdir_currLen,
02131 sshc->readdir_totalLen -
02132 sshc->readdir_currLen,
02133 " -> %s",
02134 sshc->readdir_filename);
02135
02136 state(conn, SSH_SFTP_READDIR_BOTTOM);
02137 break;
02138
02139 case SSH_SFTP_READDIR_BOTTOM:
02140 sshc->readdir_currLen += snprintf(sshc->readdir_line +
02141 sshc->readdir_currLen,
02142 sshc->readdir_totalLen -
02143 sshc->readdir_currLen, "\n");
02144 result = Curl_client_write(conn, CLIENTWRITE_BODY,
02145 sshc->readdir_line,
02146 sshc->readdir_currLen);
02147
02148 if(!result) {
02149
02150
02151 if(data->set.verbose) {
02152 Curl_debug(data, CURLINFO_DATA_OUT, sshc->readdir_line,
02153 sshc->readdir_currLen, conn);
02154 }
02155 data->req.bytecount += sshc->readdir_currLen;
02156 }
02157 Curl_safefree(sshc->readdir_line);
02158 if(result) {
02159 state(conn, SSH_STOP);
02160 }
02161 else
02162 state(conn, SSH_SFTP_READDIR);
02163 break;
02164
02165 case SSH_SFTP_READDIR_DONE:
02166 if(libssh2_sftp_closedir(sshc->sftp_handle) ==
02167 LIBSSH2_ERROR_EAGAIN) {
02168 rc = LIBSSH2_ERROR_EAGAIN;
02169 break;
02170 }
02171 sshc->sftp_handle = NULL;
02172 Curl_safefree(sshc->readdir_filename);
02173 Curl_safefree(sshc->readdir_longentry);
02174
02175
02176 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
02177 state(conn, SSH_STOP);
02178 break;
02179
02180 case SSH_SFTP_DOWNLOAD_INIT:
02181
02182
02183
02184 sshc->sftp_handle =
02185 libssh2_sftp_open_ex(sshc->sftp_session, sftp_scp->path,
02186 curlx_uztoui(strlen(sftp_scp->path)),
02187 LIBSSH2_FXF_READ, data->set.new_file_perms,
02188 LIBSSH2_SFTP_OPENFILE);
02189 if(!sshc->sftp_handle) {
02190 if(libssh2_session_last_errno(sshc->ssh_session) ==
02191 LIBSSH2_ERROR_EAGAIN) {
02192 rc = LIBSSH2_ERROR_EAGAIN;
02193 break;
02194 }
02195 else {
02196 err = sftp_libssh2_last_error(sshc->sftp_session);
02197 failf(data, "Could not open remote file for reading: %s",
02198 sftp_libssh2_strerror(err));
02199 state(conn, SSH_SFTP_CLOSE);
02200 result = sftp_libssh2_error_to_CURLE(err);
02201 sshc->actualcode = result?result:CURLE_SSH;
02202 break;
02203 }
02204 }
02205 state(conn, SSH_SFTP_DOWNLOAD_STAT);
02206 break;
02207
02208 case SSH_SFTP_DOWNLOAD_STAT:
02209 {
02210 LIBSSH2_SFTP_ATTRIBUTES attrs;
02211
02212 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sftp_scp->path,
02213 curlx_uztoui(strlen(sftp_scp->path)),
02214 LIBSSH2_SFTP_STAT, &attrs);
02215 if(rc == LIBSSH2_ERROR_EAGAIN) {
02216 break;
02217 }
02218 else if(rc ||
02219 !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
02220 (attrs.filesize == 0)) {
02221
02222
02223
02224
02225
02226
02227 data->req.size = -1;
02228 data->req.maxdownload = -1;
02229 Curl_pgrsSetDownloadSize(data, -1);
02230 }
02231 else {
02232 curl_off_t size = attrs.filesize;
02233
02234 if(size < 0) {
02235 failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
02236 return CURLE_BAD_DOWNLOAD_RESUME;
02237 }
02238 if(conn->data->state.use_range) {
02239 curl_off_t from, to;
02240 char *ptr;
02241 char *ptr2;
02242
02243 from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
02244 while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
02245 ptr++;
02246 to=curlx_strtoofft(ptr, &ptr2, 0);
02247 if((ptr == ptr2)
02248 || (to >= size)) {
02249 to = size - 1;
02250 }
02251 if(from < 0) {
02252
02253 from += size;
02254 }
02255 if(from > size) {
02256 failf(data, "Offset (%"
02257 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
02258 CURL_FORMAT_CURL_OFF_T ")", from, attrs.filesize);
02259 return CURLE_BAD_DOWNLOAD_RESUME;
02260 }
02261 if(from > to) {
02262 from = to;
02263 size = 0;
02264 }
02265 else {
02266 size = to - from + 1;
02267 }
02268
02269 SFTP_SEEK(conn->proto.sshc.sftp_handle, from);
02270 }
02271 data->req.size = size;
02272 data->req.maxdownload = size;
02273 Curl_pgrsSetDownloadSize(data, size);
02274 }
02275
02276
02277 if(data->state.resume_from) {
02278 if(data->state.resume_from < 0) {
02279
02280 if((curl_off_t)attrs.filesize < -data->state.resume_from) {
02281 failf(data, "Offset (%"
02282 CURL_FORMAT_CURL_OFF_T ") was beyond file size (%"
02283 CURL_FORMAT_CURL_OFF_T ")",
02284 data->state.resume_from, attrs.filesize);
02285 return CURLE_BAD_DOWNLOAD_RESUME;
02286 }
02287
02288 data->state.resume_from += attrs.filesize;
02289 }
02290 else {
02291 if((curl_off_t)attrs.filesize < data->state.resume_from) {
02292 failf(data, "Offset (%" CURL_FORMAT_CURL_OFF_T
02293 ") was beyond file size (%" CURL_FORMAT_CURL_OFF_T ")",
02294 data->state.resume_from, attrs.filesize);
02295 return CURLE_BAD_DOWNLOAD_RESUME;
02296 }
02297 }
02298
02299
02300 data->req.size = attrs.filesize - data->state.resume_from;
02301 data->req.maxdownload = attrs.filesize - data->state.resume_from;
02302 Curl_pgrsSetDownloadSize(data,
02303 attrs.filesize - data->state.resume_from);
02304 SFTP_SEEK(sshc->sftp_handle, data->state.resume_from);
02305 }
02306 }
02307
02308
02309 if(data->req.size == 0) {
02310
02311 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
02312 infof(data, "File already completely downloaded\n");
02313 state(conn, SSH_STOP);
02314 break;
02315 }
02316 else {
02317 Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
02318 FALSE, NULL, -1, NULL);
02319
02320
02321 conn->writesockfd = conn->sockfd;
02322
02323
02324
02325
02326 conn->cselect_bits = CURL_CSELECT_IN;
02327 }
02328 if(result) {
02329
02330
02331 state(conn, SSH_SFTP_CLOSE);
02332 sshc->actualcode = result;
02333 }
02334 else {
02335 state(conn, SSH_STOP);
02336 }
02337 break;
02338
02339 case SSH_SFTP_CLOSE:
02340 if(sshc->sftp_handle) {
02341 rc = libssh2_sftp_close(sshc->sftp_handle);
02342 if(rc == LIBSSH2_ERROR_EAGAIN) {
02343 break;
02344 }
02345 else if(rc < 0) {
02346 infof(data, "Failed to close libssh2 file\n");
02347 }
02348 sshc->sftp_handle = NULL;
02349 }
02350 if(sftp_scp)
02351 Curl_safefree(sftp_scp->path);
02352
02353 DEBUGF(infof(data, "SFTP DONE done\n"));
02354
02355
02356
02357
02358 if(sshc->nextstate != SSH_NO_STATE &&
02359 sshc->nextstate != SSH_SFTP_CLOSE) {
02360 state(conn, sshc->nextstate);
02361 sshc->nextstate = SSH_SFTP_CLOSE;
02362 }
02363 else {
02364 state(conn, SSH_STOP);
02365 result = sshc->actualcode;
02366 }
02367 break;
02368
02369 case SSH_SFTP_SHUTDOWN:
02370
02371
02372
02373
02374 if(sshc->sftp_handle) {
02375 rc = libssh2_sftp_close(sshc->sftp_handle);
02376 if(rc == LIBSSH2_ERROR_EAGAIN) {
02377 break;
02378 }
02379 else if(rc < 0) {
02380 infof(data, "Failed to close libssh2 file\n");
02381 }
02382 sshc->sftp_handle = NULL;
02383 }
02384 if(sshc->sftp_session) {
02385 rc = libssh2_sftp_shutdown(sshc->sftp_session);
02386 if(rc == LIBSSH2_ERROR_EAGAIN) {
02387 break;
02388 }
02389 else if(rc < 0) {
02390 infof(data, "Failed to stop libssh2 sftp subsystem\n");
02391 }
02392 sshc->sftp_session = NULL;
02393 }
02394
02395 Curl_safefree(sshc->homedir);
02396 conn->data->state.most_recent_ftp_entrypath = NULL;
02397
02398 state(conn, SSH_SESSION_DISCONNECT);
02399 break;
02400
02401 case SSH_SCP_TRANS_INIT:
02402 result = ssh_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
02403 if(result) {
02404 sshc->actualcode = result;
02405 state(conn, SSH_STOP);
02406 break;
02407 }
02408
02409 if(data->set.upload) {
02410 if(data->state.infilesize < 0) {
02411 failf(data, "SCP requires a known file size for upload");
02412 sshc->actualcode = CURLE_UPLOAD_FAILED;
02413 state(conn, SSH_SCP_CHANNEL_FREE);
02414 break;
02415 }
02416 state(conn, SSH_SCP_UPLOAD_INIT);
02417 }
02418 else {
02419 state(conn, SSH_SCP_DOWNLOAD_INIT);
02420 }
02421 break;
02422
02423 case SSH_SCP_UPLOAD_INIT:
02424
02425
02426
02427
02428
02429
02430 sshc->ssh_channel =
02431 SCP_SEND(sshc->ssh_session, sftp_scp->path, data->set.new_file_perms,
02432 data->state.infilesize);
02433 if(!sshc->ssh_channel) {
02434 if(libssh2_session_last_errno(sshc->ssh_session) ==
02435 LIBSSH2_ERROR_EAGAIN) {
02436 rc = LIBSSH2_ERROR_EAGAIN;
02437 break;
02438 }
02439 else {
02440 int ssh_err;
02441 char *err_msg;
02442
02443 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
02444 &err_msg, NULL, 0));
02445 failf(conn->data, "%s", err_msg);
02446 state(conn, SSH_SCP_CHANNEL_FREE);
02447 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
02448 break;
02449 }
02450 }
02451
02452
02453 Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
02454 FIRSTSOCKET, NULL);
02455
02456
02457 conn->sockfd = conn->writesockfd;
02458
02459 if(result) {
02460 state(conn, SSH_SCP_CHANNEL_FREE);
02461 sshc->actualcode = result;
02462 }
02463 else {
02464
02465
02466 sshc->orig_waitfor = data->req.keepon;
02467
02468
02469
02470
02471 conn->cselect_bits = CURL_CSELECT_OUT;
02472
02473 state(conn, SSH_STOP);
02474 }
02475 break;
02476
02477 case SSH_SCP_DOWNLOAD_INIT:
02478 {
02479 curl_off_t bytecount;
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491 #if LIBSSH2_VERSION_NUM < 0x010700
02492 struct stat sb;
02493 memset(&sb, 0, sizeof(struct stat));
02494 sshc->ssh_channel = libssh2_scp_recv(sshc->ssh_session,
02495 sftp_scp->path, &sb);
02496 #else
02497 libssh2_struct_stat sb;
02498 memset(&sb, 0, sizeof(libssh2_struct_stat));
02499 sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session,
02500 sftp_scp->path, &sb);
02501 #endif
02502
02503 if(!sshc->ssh_channel) {
02504 if(libssh2_session_last_errno(sshc->ssh_session) ==
02505 LIBSSH2_ERROR_EAGAIN) {
02506 rc = LIBSSH2_ERROR_EAGAIN;
02507 break;
02508 }
02509 else {
02510 int ssh_err;
02511 char *err_msg;
02512
02513 ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session,
02514 &err_msg, NULL, 0));
02515 failf(conn->data, "%s", err_msg);
02516 state(conn, SSH_SCP_CHANNEL_FREE);
02517 sshc->actualcode = libssh2_session_error_to_CURLE(ssh_err);
02518 break;
02519 }
02520 }
02521
02522
02523 bytecount = (curl_off_t)sb.st_size;
02524 data->req.maxdownload = (curl_off_t)sb.st_size;
02525 Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL);
02526
02527
02528 conn->writesockfd = conn->sockfd;
02529
02530
02531
02532
02533 conn->cselect_bits = CURL_CSELECT_IN;
02534
02535 if(result) {
02536 state(conn, SSH_SCP_CHANNEL_FREE);
02537 sshc->actualcode = result;
02538 }
02539 else
02540 state(conn, SSH_STOP);
02541 }
02542 break;
02543
02544 case SSH_SCP_DONE:
02545 if(data->set.upload)
02546 state(conn, SSH_SCP_SEND_EOF);
02547 else
02548 state(conn, SSH_SCP_CHANNEL_FREE);
02549 break;
02550
02551 case SSH_SCP_SEND_EOF:
02552 if(sshc->ssh_channel) {
02553 rc = libssh2_channel_send_eof(sshc->ssh_channel);
02554 if(rc == LIBSSH2_ERROR_EAGAIN) {
02555 break;
02556 }
02557 else if(rc) {
02558 infof(data, "Failed to send libssh2 channel EOF\n");
02559 }
02560 }
02561 state(conn, SSH_SCP_WAIT_EOF);
02562 break;
02563
02564 case SSH_SCP_WAIT_EOF:
02565 if(sshc->ssh_channel) {
02566 rc = libssh2_channel_wait_eof(sshc->ssh_channel);
02567 if(rc == LIBSSH2_ERROR_EAGAIN) {
02568 break;
02569 }
02570 else if(rc) {
02571 infof(data, "Failed to get channel EOF: %d\n", rc);
02572 }
02573 }
02574 state(conn, SSH_SCP_WAIT_CLOSE);
02575 break;
02576
02577 case SSH_SCP_WAIT_CLOSE:
02578 if(sshc->ssh_channel) {
02579 rc = libssh2_channel_wait_closed(sshc->ssh_channel);
02580 if(rc == LIBSSH2_ERROR_EAGAIN) {
02581 break;
02582 }
02583 else if(rc) {
02584 infof(data, "Channel failed to close: %d\n", rc);
02585 }
02586 }
02587 state(conn, SSH_SCP_CHANNEL_FREE);
02588 break;
02589
02590 case SSH_SCP_CHANNEL_FREE:
02591 if(sshc->ssh_channel) {
02592 rc = libssh2_channel_free(sshc->ssh_channel);
02593 if(rc == LIBSSH2_ERROR_EAGAIN) {
02594 break;
02595 }
02596 else if(rc < 0) {
02597 infof(data, "Failed to free libssh2 scp subsystem\n");
02598 }
02599 sshc->ssh_channel = NULL;
02600 }
02601 DEBUGF(infof(data, "SCP DONE phase complete\n"));
02602 #if 0
02603 state(conn, SSH_SESSION_DISCONNECT);
02604 #endif
02605 state(conn, SSH_STOP);
02606 result = sshc->actualcode;
02607 break;
02608
02609 case SSH_SESSION_DISCONNECT:
02610
02611
02612
02613 if(sshc->ssh_channel) {
02614 rc = libssh2_channel_free(sshc->ssh_channel);
02615 if(rc == LIBSSH2_ERROR_EAGAIN) {
02616 break;
02617 }
02618 else if(rc < 0) {
02619 infof(data, "Failed to free libssh2 scp subsystem\n");
02620 }
02621 sshc->ssh_channel = NULL;
02622 }
02623
02624 if(sshc->ssh_session) {
02625 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
02626 if(rc == LIBSSH2_ERROR_EAGAIN) {
02627 break;
02628 }
02629 else if(rc < 0) {
02630 infof(data, "Failed to disconnect libssh2 session\n");
02631 }
02632 }
02633
02634 Curl_safefree(sshc->homedir);
02635 conn->data->state.most_recent_ftp_entrypath = NULL;
02636
02637 state(conn, SSH_SESSION_FREE);
02638 break;
02639
02640 case SSH_SESSION_FREE:
02641 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
02642 if(sshc->kh) {
02643 libssh2_knownhost_free(sshc->kh);
02644 sshc->kh = NULL;
02645 }
02646 #endif
02647
02648 #ifdef HAVE_LIBSSH2_AGENT_API
02649 if(sshc->ssh_agent) {
02650 rc = libssh2_agent_disconnect(sshc->ssh_agent);
02651 if(rc == LIBSSH2_ERROR_EAGAIN) {
02652 break;
02653 }
02654 else if(rc < 0) {
02655 infof(data, "Failed to disconnect from libssh2 agent\n");
02656 }
02657 libssh2_agent_free(sshc->ssh_agent);
02658 sshc->ssh_agent = NULL;
02659
02660
02661
02662 sshc->sshagent_identity = NULL;
02663 sshc->sshagent_prev_identity = NULL;
02664 }
02665 #endif
02666
02667 if(sshc->ssh_session) {
02668 rc = libssh2_session_free(sshc->ssh_session);
02669 if(rc == LIBSSH2_ERROR_EAGAIN) {
02670 break;
02671 }
02672 else if(rc < 0) {
02673 infof(data, "Failed to free libssh2 session\n");
02674 }
02675 sshc->ssh_session = NULL;
02676 }
02677
02678
02679
02680 DEBUGASSERT(sshc->ssh_session == NULL);
02681 DEBUGASSERT(sshc->ssh_channel == NULL);
02682 DEBUGASSERT(sshc->sftp_session == NULL);
02683 DEBUGASSERT(sshc->sftp_handle == NULL);
02684 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
02685 DEBUGASSERT(sshc->kh == NULL);
02686 #endif
02687 #ifdef HAVE_LIBSSH2_AGENT_API
02688 DEBUGASSERT(sshc->ssh_agent == NULL);
02689 #endif
02690
02691 Curl_safefree(sshc->rsa_pub);
02692 Curl_safefree(sshc->rsa);
02693
02694 Curl_safefree(sshc->quote_path1);
02695 Curl_safefree(sshc->quote_path2);
02696
02697 Curl_safefree(sshc->homedir);
02698
02699 Curl_safefree(sshc->readdir_filename);
02700 Curl_safefree(sshc->readdir_longentry);
02701 Curl_safefree(sshc->readdir_line);
02702 Curl_safefree(sshc->readdir_linkPath);
02703
02704
02705 result = sshc->actualcode;
02706
02707 memset(sshc, 0, sizeof(struct ssh_conn));
02708
02709 connclose(conn, "SSH session free");
02710 sshc->state = SSH_SESSION_FREE;
02711 sshc->nextstate = SSH_NO_STATE;
02712 state(conn, SSH_STOP);
02713 break;
02714
02715 case SSH_QUIT:
02716
02717 default:
02718
02719 sshc->nextstate = SSH_NO_STATE;
02720 state(conn, SSH_STOP);
02721 break;
02722 }
02723
02724 } while(!rc && (sshc->state != SSH_STOP));
02725
02726 if(rc == LIBSSH2_ERROR_EAGAIN) {
02727
02728
02729 *block = TRUE;
02730 }
02731
02732 return result;
02733 }
02734
02735
02736
02737 static int ssh_perform_getsock(const struct connectdata *conn,
02738 curl_socket_t *sock,
02739
02740 int numsocks)
02741 {
02742 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
02743 int bitmap = GETSOCK_BLANK;
02744 (void)numsocks;
02745
02746 sock[0] = conn->sock[FIRSTSOCKET];
02747
02748 if(conn->waitfor & KEEP_RECV)
02749 bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
02750
02751 if(conn->waitfor & KEEP_SEND)
02752 bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
02753
02754 return bitmap;
02755 #else
02756
02757
02758 return Curl_single_getsock(conn, sock, numsocks);
02759 #endif
02760 }
02761
02762
02763
02764 static int ssh_getsock(struct connectdata *conn,
02765 curl_socket_t *sock,
02766
02767 int numsocks)
02768 {
02769 #ifndef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
02770 (void)conn;
02771 (void)sock;
02772 (void)numsocks;
02773
02774
02775 return GETSOCK_BLANK;
02776 #else
02777
02778
02779 return ssh_perform_getsock(conn, sock, numsocks);
02780 #endif
02781 }
02782
02783 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
02784
02785
02786
02787
02788
02789
02790
02791 static void ssh_block2waitfor(struct connectdata *conn, bool block)
02792 {
02793 struct ssh_conn *sshc = &conn->proto.sshc;
02794 int dir = 0;
02795 if(block) {
02796 dir = libssh2_session_block_directions(sshc->ssh_session);
02797 if(dir) {
02798
02799 conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) |
02800 ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0);
02801 }
02802 }
02803 if(!dir)
02804
02805
02806 conn->waitfor = sshc->orig_waitfor;
02807 }
02808 #else
02809
02810 #define ssh_block2waitfor(x,y) Curl_nop_stmt
02811 #endif
02812
02813
02814 static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
02815 {
02816 struct ssh_conn *sshc = &conn->proto.sshc;
02817 CURLcode result = CURLE_OK;
02818 bool block;
02819
02820
02821 result = ssh_statemach_act(conn, &block);
02822 *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
02823 ssh_block2waitfor(conn, block);
02824
02825 return result;
02826 }
02827
02828 static CURLcode ssh_block_statemach(struct connectdata *conn,
02829 bool duringconnect)
02830 {
02831 struct ssh_conn *sshc = &conn->proto.sshc;
02832 CURLcode result = CURLE_OK;
02833 struct Curl_easy *data = conn->data;
02834
02835 while((sshc->state != SSH_STOP) && !result) {
02836 bool block;
02837 long left;
02838
02839 result = ssh_statemach_act(conn, &block);
02840 if(result)
02841 break;
02842
02843 if(Curl_pgrsUpdate(conn))
02844 return CURLE_ABORTED_BY_CALLBACK;
02845 else {
02846 struct timeval now = Curl_tvnow();
02847 result = Curl_speedcheck(data, now);
02848 if(result)
02849 break;
02850 }
02851
02852 left = Curl_timeleft(data, NULL, duringconnect);
02853 if(left < 0) {
02854 failf(data, "Operation timed out");
02855 return CURLE_OPERATION_TIMEDOUT;
02856 }
02857
02858 #ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
02859 if(!result && block) {
02860 int dir = libssh2_session_block_directions(sshc->ssh_session);
02861 curl_socket_t sock = conn->sock[FIRSTSOCKET];
02862 curl_socket_t fd_read = CURL_SOCKET_BAD;
02863 curl_socket_t fd_write = CURL_SOCKET_BAD;
02864 if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
02865 fd_read = sock;
02866 if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
02867 fd_write = sock;
02868
02869 (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
02870 left>1000?1000:left);
02871 }
02872 #endif
02873
02874 }
02875
02876 return result;
02877 }
02878
02879
02880
02881
02882 static CURLcode ssh_setup_connection(struct connectdata *conn)
02883 {
02884 struct SSHPROTO *ssh;
02885
02886 conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
02887 if(!ssh)
02888 return CURLE_OUT_OF_MEMORY;
02889
02890 return CURLE_OK;
02891 }
02892
02893 static Curl_recv scp_recv, sftp_recv;
02894 static Curl_send scp_send, sftp_send;
02895
02896
02897
02898
02899
02900 static CURLcode ssh_connect(struct connectdata *conn, bool *done)
02901 {
02902 #ifdef CURL_LIBSSH2_DEBUG
02903 curl_socket_t sock;
02904 #endif
02905 struct ssh_conn *ssh;
02906 CURLcode result;
02907 struct Curl_easy *data = conn->data;
02908
02909
02910 if(!data->req.protop)
02911 ssh_setup_connection(conn);
02912
02913
02914
02915 connkeep(conn, "SSH default");
02916
02917 if(conn->handler->protocol & CURLPROTO_SCP) {
02918 conn->recv[FIRSTSOCKET] = scp_recv;
02919 conn->send[FIRSTSOCKET] = scp_send;
02920 }
02921 else {
02922 conn->recv[FIRSTSOCKET] = sftp_recv;
02923 conn->send[FIRSTSOCKET] = sftp_send;
02924 }
02925 ssh = &conn->proto.sshc;
02926
02927 #ifdef CURL_LIBSSH2_DEBUG
02928 if(conn->user) {
02929 infof(data, "User: %s\n", conn->user);
02930 }
02931 if(conn->passwd) {
02932 infof(data, "Password: %s\n", conn->passwd);
02933 }
02934 sock = conn->sock[FIRSTSOCKET];
02935 #endif
02936
02937 ssh->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
02938 my_libssh2_free,
02939 my_libssh2_realloc, conn);
02940 if(ssh->ssh_session == NULL) {
02941 failf(data, "Failure initialising ssh session");
02942 return CURLE_FAILED_INIT;
02943 }
02944
02945 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
02946 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
02947 int rc;
02948 ssh->kh = libssh2_knownhost_init(ssh->ssh_session);
02949 if(!ssh->kh) {
02950
02951 return CURLE_FAILED_INIT;
02952 }
02953
02954
02955 rc = libssh2_knownhost_readfile(ssh->kh,
02956 data->set.str[STRING_SSH_KNOWNHOSTS],
02957 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
02958 if(rc < 0)
02959 infof(data, "Failed to read known hosts from %s\n",
02960 data->set.str[STRING_SSH_KNOWNHOSTS]);
02961 }
02962 #endif
02963
02964 #ifdef CURL_LIBSSH2_DEBUG
02965 libssh2_trace(ssh->ssh_session, ~0);
02966 infof(data, "SSH socket: %d\n", (int)sock);
02967 #endif
02968
02969 state(conn, SSH_INIT);
02970
02971 result = ssh_multi_statemach(conn, done);
02972
02973 return result;
02974 }
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985 static
02986 CURLcode scp_perform(struct connectdata *conn,
02987 bool *connected,
02988 bool *dophase_done)
02989 {
02990 CURLcode result = CURLE_OK;
02991
02992 DEBUGF(infof(conn->data, "DO phase starts\n"));
02993
02994 *dophase_done = FALSE;
02995
02996
02997 state(conn, SSH_SCP_TRANS_INIT);
02998
02999
03000 result = ssh_multi_statemach(conn, dophase_done);
03001
03002 *connected = conn->bits.tcpconnect[FIRSTSOCKET];
03003
03004 if(*dophase_done) {
03005 DEBUGF(infof(conn->data, "DO phase is complete\n"));
03006 }
03007
03008 return result;
03009 }
03010
03011
03012 static CURLcode scp_doing(struct connectdata *conn,
03013 bool *dophase_done)
03014 {
03015 CURLcode result;
03016 result = ssh_multi_statemach(conn, dophase_done);
03017
03018 if(*dophase_done) {
03019 DEBUGF(infof(conn->data, "DO phase is complete\n"));
03020 }
03021 return result;
03022 }
03023
03024
03025
03026
03027
03028
03029 static CURLcode ssh_do(struct connectdata *conn, bool *done)
03030 {
03031 CURLcode result;
03032 bool connected = 0;
03033 struct Curl_easy *data = conn->data;
03034 struct ssh_conn *sshc = &conn->proto.sshc;
03035
03036 *done = FALSE;
03037
03038 data->req.size = -1;
03039
03040 sshc->actualcode = CURLE_OK;
03041 sshc->secondCreateDirs =0;
03042
03043
03044 Curl_pgrsSetUploadCounter(data, 0);
03045 Curl_pgrsSetDownloadCounter(data, 0);
03046 Curl_pgrsSetUploadSize(data, -1);
03047 Curl_pgrsSetDownloadSize(data, -1);
03048
03049 if(conn->handler->protocol & CURLPROTO_SCP)
03050 result = scp_perform(conn, &connected, done);
03051 else
03052 result = sftp_perform(conn, &connected, done);
03053
03054 return result;
03055 }
03056
03057
03058
03059
03060 static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
03061 {
03062 CURLcode result = CURLE_OK;
03063 struct ssh_conn *ssh = &conn->proto.sshc;
03064 (void) dead_connection;
03065
03066 if(ssh->ssh_session) {
03067
03068
03069 state(conn, SSH_SESSION_DISCONNECT);
03070
03071 result = ssh_block_statemach(conn, FALSE);
03072 }
03073
03074 return result;
03075 }
03076
03077
03078
03079 static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
03080 {
03081 CURLcode result = CURLE_OK;
03082 struct SSHPROTO *sftp_scp = conn->data->req.protop;
03083
03084 if(!status) {
03085
03086
03087
03088
03089
03090
03091 result = ssh_block_statemach(conn, FALSE);
03092 }
03093 else
03094 result = status;
03095
03096 if(sftp_scp)
03097 Curl_safefree(sftp_scp->path);
03098 if(Curl_pgrsDone(conn))
03099 return CURLE_ABORTED_BY_CALLBACK;
03100
03101 conn->data->req.keepon = 0;
03102 return result;
03103 }
03104
03105
03106 static CURLcode scp_done(struct connectdata *conn, CURLcode status,
03107 bool premature)
03108 {
03109 (void)premature;
03110
03111 if(!status)
03112 state(conn, SSH_SCP_DONE);
03113
03114 return ssh_done(conn, status);
03115
03116 }
03117
03118 static ssize_t scp_send(struct connectdata *conn, int sockindex,
03119 const void *mem, size_t len, CURLcode *err)
03120 {
03121 ssize_t nwrite;
03122 (void)sockindex;
03123
03124
03125 nwrite = (ssize_t)
03126 libssh2_channel_write(conn->proto.sshc.ssh_channel, mem, len);
03127
03128 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
03129
03130 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
03131 *err = CURLE_AGAIN;
03132 nwrite = 0;
03133 }
03134 else if(nwrite < LIBSSH2_ERROR_NONE) {
03135 *err = libssh2_session_error_to_CURLE((int)nwrite);
03136 nwrite = -1;
03137 }
03138
03139 return nwrite;
03140 }
03141
03142 static ssize_t scp_recv(struct connectdata *conn, int sockindex,
03143 char *mem, size_t len, CURLcode *err)
03144 {
03145 ssize_t nread;
03146 (void)sockindex;
03147
03148
03149 nread = (ssize_t)
03150 libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
03151
03152 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
03153 if(nread == LIBSSH2_ERROR_EAGAIN) {
03154 *err = CURLE_AGAIN;
03155 nread = -1;
03156 }
03157
03158 return nread;
03159 }
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174 static
03175 CURLcode sftp_perform(struct connectdata *conn,
03176 bool *connected,
03177 bool *dophase_done)
03178 {
03179 CURLcode result = CURLE_OK;
03180
03181 DEBUGF(infof(conn->data, "DO phase starts\n"));
03182
03183 *dophase_done = FALSE;
03184
03185
03186 state(conn, SSH_SFTP_QUOTE_INIT);
03187
03188
03189 result = ssh_multi_statemach(conn, dophase_done);
03190
03191 *connected = conn->bits.tcpconnect[FIRSTSOCKET];
03192
03193 if(*dophase_done) {
03194 DEBUGF(infof(conn->data, "DO phase is complete\n"));
03195 }
03196
03197 return result;
03198 }
03199
03200
03201 static CURLcode sftp_doing(struct connectdata *conn,
03202 bool *dophase_done)
03203 {
03204 CURLcode result = ssh_multi_statemach(conn, dophase_done);
03205
03206 if(*dophase_done) {
03207 DEBUGF(infof(conn->data, "DO phase is complete\n"));
03208 }
03209 return result;
03210 }
03211
03212
03213
03214
03215 static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
03216 {
03217 CURLcode result = CURLE_OK;
03218 (void) dead_connection;
03219
03220 DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
03221
03222 if(conn->proto.sshc.ssh_session) {
03223
03224 state(conn, SSH_SFTP_SHUTDOWN);
03225 result = ssh_block_statemach(conn, FALSE);
03226 }
03227
03228 DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
03229
03230 return result;
03231
03232 }
03233
03234 static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
03235 bool premature)
03236 {
03237 struct ssh_conn *sshc = &conn->proto.sshc;
03238
03239 if(!status) {
03240
03241
03242
03243 if(!status && !premature && conn->data->set.postquote) {
03244 sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
03245 state(conn, SSH_SFTP_CLOSE);
03246 }
03247 else
03248 state(conn, SSH_SFTP_CLOSE);
03249 }
03250 return ssh_done(conn, status);
03251 }
03252
03253
03254 static ssize_t sftp_send(struct connectdata *conn, int sockindex,
03255 const void *mem, size_t len, CURLcode *err)
03256 {
03257 ssize_t nwrite;
03258
03259
03260 (void)sockindex;
03261
03262 nwrite = libssh2_sftp_write(conn->proto.sshc.sftp_handle, mem, len);
03263
03264 ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
03265
03266 if(nwrite == LIBSSH2_ERROR_EAGAIN) {
03267 *err = CURLE_AGAIN;
03268 nwrite = 0;
03269 }
03270 else if(nwrite < LIBSSH2_ERROR_NONE) {
03271 *err = libssh2_session_error_to_CURLE((int)nwrite);
03272 nwrite = -1;
03273 }
03274
03275 return nwrite;
03276 }
03277
03278
03279
03280
03281
03282 static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
03283 char *mem, size_t len, CURLcode *err)
03284 {
03285 ssize_t nread;
03286 (void)sockindex;
03287
03288 nread = libssh2_sftp_read(conn->proto.sshc.sftp_handle, mem, len);
03289
03290 ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
03291
03292 if(nread == LIBSSH2_ERROR_EAGAIN) {
03293 *err = CURLE_AGAIN;
03294 nread = -1;
03295
03296 }
03297 else if(nread < 0) {
03298 *err = libssh2_session_error_to_CURLE((int)nread);
03299 }
03300 return nread;
03301 }
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320 static CURLcode
03321 get_pathname(const char **cpp, char **path)
03322 {
03323 const char *cp = *cpp, *end;
03324 char quot;
03325 unsigned int i, j;
03326 static const char WHITESPACE[] = " \t\r\n";
03327
03328 cp += strspn(cp, WHITESPACE);
03329 if(!*cp) {
03330 *cpp = cp;
03331 *path = NULL;
03332 return CURLE_QUOTE_ERROR;
03333 }
03334
03335 *path = malloc(strlen(cp) + 1);
03336 if(*path == NULL)
03337 return CURLE_OUT_OF_MEMORY;
03338
03339
03340 if(*cp == '\"' || *cp == '\'') {
03341 quot = *cp++;
03342
03343
03344 for(i = j = 0; i <= strlen(cp); i++) {
03345 if(cp[i] == quot) {
03346 i++;
03347 (*path)[j] = '\0';
03348 break;
03349 }
03350 if(cp[i] == '\0') {
03351
03352 goto fail;
03353 }
03354 if(cp[i] == '\\') {
03355 i++;
03356 if(cp[i] != '\'' && cp[i] != '\"' &&
03357 cp[i] != '\\') {
03358
03359
03360 goto fail;
03361 }
03362 }
03363 (*path)[j++] = cp[i];
03364 }
03365
03366 if(j == 0) {
03367
03368 goto fail;
03369 }
03370 *cpp = cp + i + strspn(cp + i, WHITESPACE);
03371 }
03372 else {
03373
03374 end = strpbrk(cp, WHITESPACE);
03375 if(end == NULL)
03376 end = strchr(cp, '\0');
03377 *cpp = end + strspn(end, WHITESPACE);
03378
03379 memcpy(*path, cp, end - cp);
03380 (*path)[end - cp] = '\0';
03381 }
03382 return CURLE_OK;
03383
03384 fail:
03385 Curl_safefree(*path);
03386 return CURLE_QUOTE_ERROR;
03387 }
03388
03389
03390 static const char *sftp_libssh2_strerror(int err)
03391 {
03392 switch(err) {
03393 case LIBSSH2_FX_NO_SUCH_FILE:
03394 return "No such file or directory";
03395
03396 case LIBSSH2_FX_PERMISSION_DENIED:
03397 return "Permission denied";
03398
03399 case LIBSSH2_FX_FAILURE:
03400 return "Operation failed";
03401
03402 case LIBSSH2_FX_BAD_MESSAGE:
03403 return "Bad message from SFTP server";
03404
03405 case LIBSSH2_FX_NO_CONNECTION:
03406 return "Not connected to SFTP server";
03407
03408 case LIBSSH2_FX_CONNECTION_LOST:
03409 return "Connection to SFTP server lost";
03410
03411 case LIBSSH2_FX_OP_UNSUPPORTED:
03412 return "Operation not supported by SFTP server";
03413
03414 case LIBSSH2_FX_INVALID_HANDLE:
03415 return "Invalid handle";
03416
03417 case LIBSSH2_FX_NO_SUCH_PATH:
03418 return "No such file or directory";
03419
03420 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
03421 return "File already exists";
03422
03423 case LIBSSH2_FX_WRITE_PROTECT:
03424 return "File is write protected";
03425
03426 case LIBSSH2_FX_NO_MEDIA:
03427 return "No media";
03428
03429 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
03430 return "Disk full";
03431
03432 case LIBSSH2_FX_QUOTA_EXCEEDED:
03433 return "User quota exceeded";
03434
03435 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
03436 return "Unknown principle";
03437
03438 case LIBSSH2_FX_LOCK_CONFlICT:
03439 return "File lock conflict";
03440
03441 case LIBSSH2_FX_DIR_NOT_EMPTY:
03442 return "Directory not empty";
03443
03444 case LIBSSH2_FX_NOT_A_DIRECTORY:
03445 return "Not a directory";
03446
03447 case LIBSSH2_FX_INVALID_FILENAME:
03448 return "Invalid filename";
03449
03450 case LIBSSH2_FX_LINK_LOOP:
03451 return "Link points to itself";
03452 }
03453 return "Unknown error in libssh2";
03454 }
03455
03456 #endif