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
00026 #include "setup.h"
00027
00028 #ifdef USE_LIBSSH2
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032 #include <stdarg.h>
00033 #include <ctype.h>
00034 #include <limits.h>
00035
00036 #include <libssh2.h>
00037 #include <libssh2_sftp.h>
00038
00039 #ifdef HAVE_UNISTD_H
00040 #include <unistd.h>
00041 #endif
00042
00043 #ifdef HAVE_FCNTL_H
00044 #include <fcntl.h>
00045 #endif
00046
00047 #ifdef HAVE_TIME_H
00048 #include <time.h>
00049 #endif
00050
00051 #ifndef WIN32
00052 #ifdef HAVE_SYS_SOCKET_H
00053 #include <sys/socket.h>
00054 #endif
00055 #ifdef HAVE_NETINET_IN_H
00056 #include <netinet/in.h>
00057 #endif
00058 #ifdef HAVE_ARPA_INET_H
00059 #include <arpa/inet.h>
00060 #endif
00061 #ifdef HAVE_UTSNAME_H
00062 #include <sys/utsname.h>
00063 #endif
00064 #ifdef HAVE_NETDB_H
00065 #include <netdb.h>
00066 #endif
00067 #ifdef VMS
00068 #include <in.h>
00069 #include <inet.h>
00070 #endif
00071 #endif
00072
00073 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
00074 #undef in_addr_t
00075 #define in_addr_t unsigned long
00076 #endif
00077
00078 #include <curl/curl.h>
00079 #include "urldata.h"
00080 #include "sendf.h"
00081 #include "easyif.h"
00082
00083 #include "if2ip.h"
00084 #include "hostip.h"
00085 #include "progress.h"
00086 #include "transfer.h"
00087 #include "escape.h"
00088 #include "http.h"
00089 #include "ssh.h"
00090 #include "url.h"
00091 #include "speedcheck.h"
00092 #include "getinfo.h"
00093
00094 #include "strtoofft.h"
00095 #include "strequal.h"
00096 #include "sslgen.h"
00097 #include "connect.h"
00098 #include "strerror.h"
00099 #include "memory.h"
00100 #include "inet_ntop.h"
00101 #include "select.h"
00102 #include "parsedate.h"
00103 #include "sockaddr.h"
00104 #include "multiif.h"
00105
00106 #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
00107 #include "inet_ntoa_r.h"
00108 #endif
00109
00110 #define _MPRINTF_REPLACE
00111 #include <curl/mprintf.h>
00112
00113 #define _MPRINTF_REPLACE
00114 #include <curl/mprintf.h>
00115
00116
00117 #ifdef CURLDEBUG
00118 #include "memdebug.h"
00119 #endif
00120
00121 #ifndef PATH_MAX
00122 #define PATH_MAX 1024
00123
00124 #endif
00125
00126 #ifndef LIBSSH2_SFTP_S_IRUSR
00127
00128
00129
00130 #ifndef S_IRGRP
00131 #define S_IRGRP 0
00132 #endif
00133
00134 #ifndef S_IROTH
00135 #define S_IROTH 0
00136 #endif
00137
00138
00139
00140 #define LIBSSH2_SFTP_S_IRWXU S_IRWXU
00141 #define LIBSSH2_SFTP_S_IRUSR S_IRUSR
00142 #define LIBSSH2_SFTP_S_IWUSR S_IWUSR
00143 #define LIBSSH2_SFTP_S_IXUSR S_IXUSR
00144
00145 #define LIBSSH2_SFTP_S_IRWXG S_IRWXG
00146 #define LIBSSH2_SFTP_S_IRGRP S_IRGRP
00147 #define LIBSSH2_SFTP_S_IWGRP S_IWGRP
00148 #define LIBSSH2_SFTP_S_IXGRP S_IXGRP
00149
00150 #define LIBSSH2_SFTP_S_IRWXO S_IRWXO
00151 #define LIBSSH2_SFTP_S_IROTH S_IROTH
00152 #define LIBSSH2_SFTP_S_IWOTH S_IWOTH
00153 #define LIBSSH2_SFTP_S_IXOTH S_IXOTH
00154
00155
00156 #define LIBSSH2_SFTP_S_IFMT S_IFMT
00157 #define LIBSSH2_SFTP_S_IFDIR S_IFDIR
00158 #define LIBSSH2_SFTP_S_IFLNK S_IFLNK
00159 #define LIBSSH2_SFTP_S_IFSOCK S_IFSOCK
00160 #define LIBSSH2_SFTP_S_IFCHR S_IFCHR
00161 #define LIBSSH2_SFTP_S_IFBLK S_IFBLK
00162 #endif
00163
00164
00165 static const char *sftp_libssh2_strerror(unsigned long err);
00166 static CURLcode sftp_sendquote(struct connectdata *conn,
00167 struct curl_slist *quote);
00168 static CURLcode sftp_create_dirs(struct connectdata *conn);
00169
00170 static LIBSSH2_ALLOC_FUNC(libssh2_malloc);
00171 static LIBSSH2_REALLOC_FUNC(libssh2_realloc);
00172 static LIBSSH2_FREE_FUNC(libssh2_free);
00173
00174 static void
00175 kbd_callback(const char *name, int name_len, const char *instruction,
00176 int instruction_len, int num_prompts,
00177 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
00178 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
00179 void **abstract)
00180 {
00181 struct SSHPROTO *ssh = (struct SSHPROTO *)*abstract;
00182
00183 #ifdef CURL_LIBSSH2_DEBUG
00184 fprintf(stderr, "name=%s\n", name);
00185 fprintf(stderr, "name_len=%d\n", name_len);
00186 fprintf(stderr, "instruction=%s\n", instruction);
00187 fprintf(stderr, "instruction_len=%d\n", instruction_len);
00188 fprintf(stderr, "num_prompts=%d\n", num_prompts);
00189 #else
00190 (void)name;
00191 (void)name_len;
00192 (void)instruction;
00193 (void)instruction_len;
00194 #endif
00195 if (num_prompts == 1) {
00196 responses[0].text = strdup(ssh->passwd);
00197 responses[0].length = strlen(ssh->passwd);
00198 }
00199 (void)prompts;
00200 (void)abstract;
00201 }
00202
00203 static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err)
00204 {
00205 if (err == LIBSSH2_FX_OK)
00206 return CURLE_OK;
00207
00208
00209
00210
00211
00212 if (err == LIBSSH2_FX_NO_SUCH_FILE)
00213 return CURLE_REMOTE_FILE_NOT_FOUND;
00214
00215 return CURLE_SSH;
00216 }
00217
00218 static CURLcode libssh2_session_error_to_CURLE(int err)
00219 {
00220 (void)err;
00221 return CURLE_SSH;
00222 }
00223
00224 static LIBSSH2_ALLOC_FUNC(libssh2_malloc)
00225 {
00226 return malloc(count);
00227 (void)abstract;
00228 }
00229
00230 static LIBSSH2_REALLOC_FUNC(libssh2_realloc)
00231 {
00232 return realloc(ptr, count);
00233 (void)abstract;
00234 }
00235
00236 static LIBSSH2_FREE_FUNC(libssh2_free)
00237 {
00238 free(ptr);
00239 (void)abstract;
00240 }
00241
00242 #if (LIBSSH2_APINO >= 200706012030)
00243
00244
00245
00246
00247 static void state(struct connectdata *conn, ftpstate state)
00248 {
00249 #if defined(CURLDEBUG) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
00250
00251 const char *names[]={
00252 "STOP",
00253 "SSH_S_STARTUP",
00254 "SSH_AUTHLIST",
00255 "SSH_AUTH_PKEY_INIT",
00256 "SSH_AUTH_PKEY",
00257 "SSH_AUTH_PASS_INIT",
00258 "SSH_AUTH_PASS",
00259 "SSH_AUTH_HOST_INIT",
00260 "SSH_AUTH_HOST",
00261 "SSH_AUTH_KEY_INIT",
00262 "SSH_AUTH_KEY",
00263 "SSH_AUTH_DONE",
00264 "SSH_SFTP_INIT",
00265 "SSH_SFTP_REALPATH",
00266 "SSH_GET_WORKINGPATH",
00267 "SSH_SFTP_SHUTDOWN",
00268 "SSH_SESSION_FREE",
00269 "QUIT"
00270 };
00271 #endif
00272 struct ssh_conn *sshc = &conn->proto.sshc;
00273
00274 #if defined(CURLDEBUG) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
00275 if (sshc->state != state) {
00276 infof(conn->data, "FTP %p state change from %s to %s\n",
00277 sshc, names[sshc->state], names[state]);
00278 }
00279 #endif
00280
00281 sshc->state = state;
00282 }
00283
00284 static CURLcode ssh_statemach_act(struct connectdata *conn)
00285 {
00286 CURLcode result = CURLE_OK;
00287 struct SessionHandle *data=conn->data;
00288 struct ssh_conn *sshc = &conn->proto.sshc;
00289 curl_socket_t sock = conn->sock[FIRSTSOCKET];
00290 struct SSHPROTO *ssh;
00291 #ifdef CURL_LIBSSH2_DEBUG
00292 const char *fingerprint;
00293 #endif
00294 int rc;
00295
00296 ssh = data->reqdata.proto.ssh;
00297
00298 switch(sshc->state) {
00299 case SSH_S_STARTUP:
00300 rc = libssh2_session_startup(ssh->ssh_session, sock);
00301 if (rc == LIBSSH2_ERROR_EAGAIN) {
00302 break;
00303 }
00304 else if (rc) {
00305 failf(data, "Failure establishing ssh session");
00306 state(conn, SSH_SESSION_FREE);
00307 sshc->actualCode = CURLE_FAILED_INIT;
00308 break;
00309 }
00310
00311
00312 libssh2_session_set_blocking(ssh->ssh_session, 0);
00313
00314 #ifdef CURL_LIBSSH2_DEBUG
00315
00316
00317
00318
00319
00320
00321 fingerprint = libssh2_hostkey_hash(ssh->ssh_session,
00322 LIBSSH2_HOSTKEY_HASH_MD5);
00323
00324
00325 infof(data, "Fingerprint: ");
00326 for (rc = 0; rc < 16; rc++) {
00327 infof(data, "%02X ", (unsigned char) fingerprint[rc]);
00328 }
00329 infof(data, "\n");
00330 #endif
00331
00332 state(conn, SSH_AUTHLIST);
00333 break;
00334
00335 case SSH_AUTHLIST:
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 sshc->authlist = libssh2_userauth_list(ssh->ssh_session, ssh->user,
00349 strlen(ssh->user));
00350
00351 if (!sshc->authlist) {
00352 if (libssh2_session_last_errno(ssh->ssh_session) ==
00353 LIBSSH2_ERROR_EAGAIN) {
00354 break;
00355 } else {
00356 state(conn, SSH_SESSION_FREE);
00357 sshc->actualCode = CURLE_OUT_OF_MEMORY;
00358 break;
00359 }
00360 }
00361 infof(data, "SSH authentication methods available: %s\n", sshc->authlist);
00362
00363 state(conn, SSH_AUTH_PKEY_INIT);
00364 break;
00365
00366 case SSH_AUTH_PKEY_INIT:
00367
00368
00369
00370
00371 sshc->authed = FALSE;
00372
00373 if ((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
00374 (strstr(sshc->authlist, "publickey") != NULL)) {
00375 char *home;
00376
00377 sshc->rsa_pub = sshc->rsa = NULL;
00378
00379
00380
00381 home = curl_getenv("HOME");
00382
00383 if (data->set.ssh_public_key)
00384 sshc->rsa_pub = aprintf("%s", data->set.ssh_public_key);
00385 else if (home)
00386 sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home);
00387
00388 if (sshc->rsa_pub == NULL) {
00389 curl_free(home);
00390 state(conn, SSH_SESSION_FREE);
00391 sshc->actualCode = CURLE_OUT_OF_MEMORY;
00392 break;
00393 }
00394
00395 if (data->set.ssh_private_key)
00396 sshc->rsa = aprintf("%s", data->set.ssh_private_key);
00397 else if (home)
00398 sshc->rsa = aprintf("%s/.ssh/id_dsa", home);
00399
00400 if (sshc->rsa == NULL) {
00401 curl_free(home);
00402 curl_free(sshc->rsa_pub);
00403 state(conn, SSH_SESSION_FREE);
00404 sshc->actualCode = CURLE_OUT_OF_MEMORY;
00405 break;
00406 }
00407
00408 sshc->passphrase = data->set.key_passwd;
00409 if (!sshc->passphrase)
00410 sshc->passphrase = "";
00411
00412 curl_free(home);
00413
00414 infof(conn->data, "Using ssh public key file %s\n", sshc->rsa_pub);
00415 infof(conn->data, "Using ssh private key file %s\n", sshc->rsa);
00416
00417 state(conn, SSH_AUTH_PKEY);
00418 } else {
00419 state(conn, SSH_AUTH_PASS_INIT);
00420 }
00421 break;
00422
00423 case SSH_AUTH_PKEY:
00424
00425
00426 rc = libssh2_userauth_publickey_fromfile(ssh->ssh_session, ssh->user,
00427 sshc->rsa_pub, sshc->rsa,
00428 sshc->passphrase);
00429 if (rc == LIBSSH2_ERROR_EAGAIN) {
00430 break;
00431 }
00432
00433 curl_free(sshc->rsa_pub);
00434 curl_free(sshc->rsa);
00435
00436 if (rc == 0) {
00437 sshc->authed = TRUE;
00438 infof(conn->data, "Initialized SSH public key authentication\n");
00439 state(conn, SSH_AUTH_DONE);
00440 } else {
00441 state(conn, SSH_AUTH_PASS_INIT);
00442 }
00443 break;
00444
00445 case SSH_AUTH_PASS_INIT:
00446 if ((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
00447 (strstr(sshc->authlist, "password") != NULL)) {
00448 state(conn, SSH_AUTH_PASS);
00449 } else {
00450 state(conn, SSH_AUTH_HOST_INIT);
00451 }
00452 break;
00453
00454 case SSH_AUTH_PASS:
00455 rc = libssh2_userauth_password(ssh->ssh_session, ssh->user,
00456 ssh->passwd);
00457 if (rc == LIBSSH2_ERROR_EAGAIN) {
00458 break;
00459 }
00460 else if (rc == 0) {
00461 sshc->authed = TRUE;
00462 infof(conn->data, "Initialized password authentication\n");
00463 state(conn, SSH_AUTH_DONE);
00464 } else {
00465 state(conn, SSH_AUTH_HOST_INIT);
00466 }
00467 break;
00468
00469 case SSH_AUTH_HOST_INIT:
00470 if ((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
00471 (strstr(sshc->authlist, "hostbased") != NULL)) {
00472 state(conn, SSH_AUTH_HOST);
00473 } else {
00474 state(conn, SSH_AUTH_KEY_INIT);
00475 }
00476 break;
00477
00478 case SSH_AUTH_HOST:
00479 state(conn, SSH_AUTH_KEY_INIT);
00480 break;
00481
00482 case SSH_AUTH_KEY_INIT:
00483 if ((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
00484 && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
00485 state(conn, SSH_AUTH_KEY);
00486 } else {
00487 state(conn, SSH_AUTH_DONE);
00488 }
00489 break;
00490
00491 case SSH_AUTH_KEY:
00492
00493 rc = libssh2_userauth_keyboard_interactive_ex(ssh->ssh_session,
00494 ssh->user,
00495 strlen(ssh->user),
00496 &kbd_callback);
00497 if (rc == LIBSSH2_ERROR_EAGAIN) {
00498 break;
00499 }
00500 else if (rc == 0) {
00501 sshc->authed = TRUE;
00502 infof(conn->data, "Initialized keyboard interactive authentication\n");
00503 }
00504 state(conn, SSH_AUTH_DONE);
00505 break;
00506
00507 case SSH_AUTH_DONE:
00508 if (!sshc->authed) {
00509 failf(data, "Authentication failure");
00510 state(conn, SSH_SESSION_FREE);
00511 sshc->actualCode = CURLE_LOGIN_DENIED;
00512 break;
00513 }
00514
00515
00516
00517
00518 infof(conn->data, "Authentication complete\n");
00519
00520 conn->sockfd = sock;
00521 conn->writesockfd = CURL_SOCKET_BAD;
00522
00523 if (conn->protocol == PROT_SFTP) {
00524 state(conn, SSH_SFTP_INIT);
00525 break;
00526 }
00527 state(conn, SSH_GET_WORKINGPATH);
00528 break;
00529
00530 case SSH_SFTP_INIT:
00531
00532
00533
00534 ssh->sftp_session = libssh2_sftp_init(ssh->ssh_session);
00535 if (!ssh->sftp_session) {
00536 if (libssh2_session_last_errno(ssh->ssh_session) ==
00537 LIBSSH2_ERROR_EAGAIN) {
00538 break;
00539 } else {
00540 failf(data, "Failure initialising sftp session\n");
00541 state(conn, SSH_SESSION_FREE);
00542 sshc->actualCode = CURLE_FAILED_INIT;
00543 break;
00544 }
00545 }
00546 state(conn, SSH_SFTP_REALPATH);
00547 break;
00548
00549 case SSH_SFTP_REALPATH:
00550 {
00551 char tempHome[PATH_MAX];
00552
00553
00554
00555
00556 rc = libssh2_sftp_realpath(ssh->sftp_session, ".",
00557 tempHome, PATH_MAX-1);
00558 if (rc == LIBSSH2_ERROR_EAGAIN) {
00559 break;
00560 }
00561 else if (rc > 0) {
00562
00563 tempHome[rc] = '\0';
00564 ssh->homedir = (char *)strdup(tempHome);
00565 if (!ssh->homedir) {
00566 state(conn, SSH_SFTP_SHUTDOWN);
00567 sshc->actualCode = CURLE_OUT_OF_MEMORY;
00568 break;
00569 }
00570 } else {
00571
00572 result = libssh2_sftp_last_error(ssh->sftp_session);
00573 DEBUGF(infof(data, "error = %d\n", result));
00574 state(conn, SSH_STOP);
00575 break;
00576 }
00577 state(conn, SSH_GET_WORKINGPATH);
00578 }
00579 break;
00580
00581 case SSH_GET_WORKINGPATH:
00582 {
00583 char *real_path;
00584 char *working_path;
00585 int working_path_len;
00586
00587 working_path = curl_easy_unescape(data, data->reqdata.path, 0,
00588 &working_path_len);
00589 if (!working_path) {
00590 state(conn, SSH_STOP);
00591 result = CURLE_OUT_OF_MEMORY;
00592 break;
00593 }
00594
00595
00596 if (conn->protocol == PROT_SCP) {
00597 real_path = (char *)malloc(working_path_len+1);
00598 if (real_path == NULL) {
00599 Curl_safefree(working_path);
00600 state(conn, SSH_SESSION_FREE);
00601 sshc->actualCode = CURLE_OUT_OF_MEMORY;
00602 break;
00603 }
00604 if (working_path[1] == '~')
00605
00606
00607 memcpy(real_path, working_path+1, 1 + working_path_len-1);
00608 else
00609 memcpy(real_path, working_path, 1 + working_path_len);
00610 }
00611 else if (conn->protocol == PROT_SFTP) {
00612 if (working_path[1] == '~') {
00613 real_path = (char *)malloc(strlen(ssh->homedir) +
00614 working_path_len + 1);
00615 if (real_path == NULL) {
00616 Curl_safefree(ssh->homedir);
00617 ssh->homedir = NULL;
00618 Curl_safefree(working_path);
00619 state(conn, SSH_SFTP_SHUTDOWN);
00620 sshc->actualCode = CURLE_OUT_OF_MEMORY;
00621 break;
00622 }
00623
00624
00625 memcpy(real_path, ssh->homedir, strlen(ssh->homedir));
00626 real_path[strlen(ssh->homedir)] = '/';
00627 real_path[strlen(ssh->homedir)+1] = '\0';
00628 if (working_path_len > 3) {
00629 memcpy(real_path+strlen(ssh->homedir)+1, working_path + 3,
00630 1 + working_path_len -3);
00631 }
00632 }
00633 else {
00634 real_path = (char *)malloc(working_path_len+1);
00635 if (real_path == NULL) {
00636 Curl_safefree(ssh->homedir);
00637 ssh->homedir = NULL;
00638 Curl_safefree(working_path);
00639 state(conn, SSH_SFTP_SHUTDOWN);
00640 sshc->actualCode = CURLE_OUT_OF_MEMORY;
00641 break;
00642 }
00643 memcpy(real_path, working_path, 1+working_path_len);
00644 }
00645 }
00646 else {
00647 Curl_safefree(working_path);
00648 state(conn, SSH_SESSION_FREE);
00649 sshc->actualCode = CURLE_FAILED_INIT;
00650 break;
00651 }
00652
00653 Curl_safefree(working_path);
00654 ssh->path = real_path;
00655
00656
00657 state(conn, SSH_STOP);
00658 }
00659 break;
00660
00661 case SSH_SFTP_SHUTDOWN:
00662 rc = libssh2_sftp_shutdown(ssh->sftp_session);
00663 if (rc == LIBSSH2_ERROR_EAGAIN) {
00664 break;
00665 }
00666 ssh->sftp_session = NULL;
00667 state(conn, SSH_SESSION_FREE);
00668 break;
00669
00670 case SSH_SESSION_FREE:
00671 rc = libssh2_session_free(ssh->ssh_session);
00672 if (rc == LIBSSH2_ERROR_EAGAIN) {
00673 break;
00674 }
00675 ssh->ssh_session = NULL;
00676 state(conn, SSH_STOP);
00677 result = sshc->actualCode;
00678 break;
00679
00680 case SSH_QUIT:
00681
00682 default:
00683
00684 state(conn, SSH_STOP);
00685 break;
00686 }
00687
00688 return result;
00689 }
00690
00691
00692 CURLcode Curl_ssh_multi_statemach(struct connectdata *conn,
00693 bool *done)
00694 {
00695 #if 0
00696 curl_socket_t sock = conn->sock[FIRSTSOCKET];
00697 #endif
00698 int rc = 1;
00699 struct SessionHandle *data=conn->data;
00700 struct ssh_conn *sshc = &conn->proto.sshc;
00701 CURLcode result = CURLE_OK;
00702 #if 0
00703 long timeout_ms = ssh_state_timeout(conn);
00704 #endif
00705
00706 *done = FALSE;
00707
00708 #if 0
00709 if (timeout_ms <= 0) {
00710 failf(data, "SSH response timeout");
00711 return CURLE_OPERATION_TIMEDOUT;
00712 }
00713
00714 rc = Curl_socket_ready(sshc->sendleft?CURL_SOCKET_BAD:sock,
00715 sshc->sendleft?sock:CURL_SOCKET_BAD,
00716 0);
00717 #endif
00718
00719 if (rc == -1) {
00720 failf(data, "select/poll error");
00721 return CURLE_OUT_OF_MEMORY;
00722 }
00723 else if (rc != 0) {
00724 result = ssh_statemach_act(conn);
00725 *done = (bool)(sshc->state == SSH_STOP);
00726 }
00727
00728
00729 return result;
00730 }
00731
00732 static CURLcode ssh_easy_statemach(struct connectdata *conn)
00733 {
00734 #if 0
00735 curl_socket_t sock = conn->sock[FIRSTSOCKET];
00736 #endif
00737 int rc = 1;
00738 struct SessionHandle *data=conn->data;
00739 struct ssh_conn *sshc = &conn->proto.sshc;
00740 CURLcode result = CURLE_OK;
00741
00742 while(sshc->state != SSH_STOP) {
00743 #if 0
00744 long timeout_ms = ssh_state_timeout(conn);
00745
00746 if (timeout_ms <=0 ) {
00747 failf(data, "SSH response timeout");
00748 return CURLE_OPERATION_TIMEDOUT;
00749 }
00750
00751 rc = Curl_socket_ready(sshc->sendleft?CURL_SOCKET_BAD:sock,
00752 sshc->sendleft?sock:CURL_SOCKET_BAD,
00753 (int)timeout_ms);
00754 #endif
00755
00756 if (rc == -1) {
00757 failf(data, "select/poll error");
00758 return CURLE_OUT_OF_MEMORY;
00759 }
00760 else if (rc == 0) {
00761 result = CURLE_OPERATION_TIMEDOUT;
00762 break;
00763 }
00764 else {
00765 result = ssh_statemach_act(conn);
00766 if (result)
00767 break;
00768 }
00769 }
00770
00771 return result;
00772 }
00773 #endif
00774
00775
00776
00777
00778 static CURLcode ssh_init(struct connectdata *conn)
00779 {
00780 struct SessionHandle *data = conn->data;
00781 struct SSHPROTO *ssh;
00782 if (data->reqdata.proto.ssh)
00783 return CURLE_OK;
00784
00785 ssh = (struct SSHPROTO *)calloc(sizeof(struct SSHPROTO), 1);
00786 if (!ssh)
00787 return CURLE_OUT_OF_MEMORY;
00788
00789 data->reqdata.proto.ssh = ssh;
00790
00791
00792 ssh->bytecountp = &data->reqdata.keep.bytecount;
00793
00794
00795 ssh->user = conn->user;
00796 ssh->passwd = conn->passwd;
00797
00798 ssh->errorstr = NULL;
00799
00800 ssh->ssh_session = NULL;
00801 ssh->ssh_channel = NULL;
00802 ssh->sftp_session = NULL;
00803 ssh->sftp_handle = NULL;
00804
00805 return CURLE_OK;
00806 }
00807
00808
00809
00810
00811
00812 CURLcode Curl_ssh_connect(struct connectdata *conn, bool *done)
00813 {
00814 int i;
00815 struct SSHPROTO *ssh;
00816 const char *fingerprint;
00817 const char *authlist;
00818 char tempHome[PATH_MAX];
00819 curl_socket_t sock;
00820 char *real_path;
00821 char *working_path;
00822 int working_path_len;
00823 bool authed = FALSE;
00824 CURLcode result;
00825 struct SessionHandle *data = conn->data;
00826
00827 result = ssh_init(conn);
00828 if (result)
00829 return result;
00830
00831 ssh = data->reqdata.proto.ssh;
00832
00833 #ifdef CURL_LIBSSH2_DEBUG
00834 if (ssh->user) {
00835 infof(data, "User: %s\n", ssh->user);
00836 }
00837 if (ssh->passwd) {
00838 infof(data, "Password: %s\n", ssh->passwd);
00839 }
00840 #endif
00841 sock = conn->sock[FIRSTSOCKET];
00842 ssh->ssh_session = libssh2_session_init_ex(libssh2_malloc, libssh2_free,
00843 libssh2_realloc, ssh);
00844 if (ssh->ssh_session == NULL) {
00845 failf(data, "Failure initialising ssh session");
00846 return CURLE_FAILED_INIT;
00847 }
00848
00849 #ifdef CURL_LIBSSH2_DEBUG
00850 libssh2_trace(ssh->ssh_session, LIBSSH2_TRACE_CONN|LIBSSH2_TRACE_TRANS|
00851 LIBSSH2_TRACE_KEX|LIBSSH2_TRACE_AUTH|LIBSSH2_TRACE_SCP|
00852 LIBSSH2_TRACE_SFTP|LIBSSH2_TRACE_ERROR|
00853 LIBSSH2_TRACE_PUBLICKEY);
00854 infof(data, "SSH socket: %d\n", sock);
00855 #endif
00856
00857 #if (LIBSSH2_APINO >= 200706012030)
00858 state(conn, SSH_S_STARTUP);
00859
00860 if (data->state.used_interface == Curl_if_multi)
00861 result = Curl_ssh_multi_statemach(conn, done);
00862 else {
00863 result = ssh_easy_statemach(conn);
00864 if (!result)
00865 *done = TRUE;
00866 }
00867
00868 return result;
00869 (void)authed;
00870 (void)working_path;
00871 (void)working_path_len;
00872 (void)real_path;
00873 (void)tempHome;
00874 (void)authlist;
00875 (void)fingerprint;
00876 (void)i;
00877
00878 #else
00879
00880 if (libssh2_session_startup(ssh->ssh_session, sock)) {
00881 failf(data, "Failure establishing ssh session");
00882 libssh2_session_free(ssh->ssh_session);
00883 ssh->ssh_session = NULL;
00884 return CURLE_FAILED_INIT;
00885 }
00886
00887
00888
00889
00890
00891
00892
00893 fingerprint = libssh2_hostkey_hash(ssh->ssh_session,
00894 LIBSSH2_HOSTKEY_HASH_MD5);
00895
00896 #ifdef CURL_LIBSSH2_DEBUG
00897
00898 infof(data, "Fingerprint: ");
00899 for (i = 0; i < 16; i++) {
00900 infof(data, "%02X ", (unsigned char) fingerprint[i]);
00901 }
00902 infof(data, "\n");
00903 #endif
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916 authlist = libssh2_userauth_list(ssh->ssh_session, ssh->user,
00917 strlen(ssh->user));
00918 if (!authlist) {
00919 libssh2_session_free(ssh->ssh_session);
00920 ssh->ssh_session = NULL;
00921 return CURLE_OUT_OF_MEMORY;
00922 }
00923 infof(data, "SSH authentication methods available: %s\n", authlist);
00924
00925
00926
00927
00928
00929 if ((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
00930 (strstr(authlist, "publickey") != NULL)) {
00931 char *home;
00932 const char *passphrase;
00933 char rsa_pub[PATH_MAX];
00934 char rsa[PATH_MAX];
00935
00936 rsa_pub[0] = rsa[0] = '\0';
00937
00938
00939
00940 home = curl_getenv("HOME");
00941
00942 if (data->set.ssh_public_key)
00943 snprintf(rsa_pub, sizeof(rsa_pub), "%s", data->set.ssh_public_key);
00944 else if (home)
00945 snprintf(rsa_pub, sizeof(rsa_pub), "%s/.ssh/id_dsa.pub", home);
00946
00947 if (data->set.ssh_private_key)
00948 snprintf(rsa, sizeof(rsa), "%s", data->set.ssh_private_key);
00949 else if (home)
00950 snprintf(rsa, sizeof(rsa), "%s/.ssh/id_dsa", home);
00951
00952 passphrase = data->set.key_passwd;
00953 if (!passphrase)
00954 passphrase = "";
00955
00956 curl_free(home);
00957
00958 infof(conn->data, "Using ssh public key file %s\n", rsa_pub);
00959 infof(conn->data, "Using ssh private key file %s\n", rsa);
00960
00961 if (rsa_pub[0]) {
00962
00963
00964 if (libssh2_userauth_publickey_fromfile(ssh->ssh_session, ssh->user,
00965 rsa_pub, rsa, passphrase) == 0) {
00966 authed = TRUE;
00967 infof(conn->data, "Initialized SSH public key authentication\n");
00968 }
00969 }
00970 }
00971 if (!authed &&
00972 (data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
00973 (strstr(authlist, "password") != NULL)) {
00974 if (!libssh2_userauth_password(ssh->ssh_session, ssh->user, ssh->passwd)) {
00975 authed = TRUE;
00976 infof(conn->data, "Initialized password authentication\n");
00977 }
00978 }
00979 if (!authed && (data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
00980 (strstr(authlist, "hostbased") != NULL)) {
00981 }
00982 if (!authed && (data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD)
00983 && (strstr(authlist, "keyboard-interactive") != NULL)) {
00984
00985 if (!libssh2_userauth_keyboard_interactive_ex(ssh->ssh_session, ssh->user,
00986 strlen(ssh->user),
00987 &kbd_callback)) {
00988 authed = TRUE;
00989 infof(conn->data, "Initialized keyboard interactive authentication\n");
00990 }
00991 }
00992 Curl_safefree((void *)authlist);
00993 authlist = NULL;
00994
00995 if (!authed) {
00996 failf(data, "Authentication failure");
00997 libssh2_session_free(ssh->ssh_session);
00998 ssh->ssh_session = NULL;
00999 return CURLE_LOGIN_DENIED;
01000 }
01001
01002
01003
01004
01005 infof(conn->data, "Authentication complete\n");
01006
01007 conn->sockfd = sock;
01008 conn->writesockfd = CURL_SOCKET_BAD;
01009
01010 if (conn->protocol == PROT_SFTP) {
01011
01012
01013
01014 ssh->sftp_session = libssh2_sftp_init(ssh->ssh_session);
01015 if (ssh->sftp_session == NULL) {
01016 failf(data, "Failure initialising sftp session\n");
01017 libssh2_session_free(ssh->ssh_session);
01018 ssh->ssh_session = NULL;
01019 return CURLE_FAILED_INIT;
01020 }
01021
01022
01023
01024
01025 i = libssh2_sftp_realpath(ssh->sftp_session, ".", tempHome, PATH_MAX-1);
01026 if (i > 0) {
01027
01028 tempHome[i] = '\0';
01029 ssh->homedir = (char *)strdup(tempHome);
01030 if (!ssh->homedir) {
01031 libssh2_sftp_shutdown(ssh->sftp_session);
01032 ssh->sftp_session = NULL;
01033 libssh2_session_free(ssh->ssh_session);
01034 ssh->ssh_session = NULL;
01035 return CURLE_OUT_OF_MEMORY;
01036 }
01037 }
01038 else {
01039
01040 i = libssh2_sftp_last_error(ssh->sftp_session);
01041 DEBUGF(infof(data, "error = %d\n", i));
01042 }
01043 }
01044
01045 working_path = curl_easy_unescape(data, data->reqdata.path, 0,
01046 &working_path_len);
01047 if (!working_path)
01048 return CURLE_OUT_OF_MEMORY;
01049
01050
01051 if (conn->protocol == PROT_SCP) {
01052 real_path = (char *)malloc(working_path_len+1);
01053 if (real_path == NULL) {
01054 libssh2_session_free(ssh->ssh_session);
01055 ssh->ssh_session = NULL;
01056 Curl_safefree(working_path);
01057 return CURLE_OUT_OF_MEMORY;
01058 }
01059 if (working_path[1] == '~')
01060
01061 memcpy(real_path, working_path+1, 1 + working_path_len-1);
01062 else
01063 memcpy(real_path, working_path, 1 + working_path_len);
01064 }
01065 else if (conn->protocol == PROT_SFTP) {
01066 if (working_path[1] == '~') {
01067 real_path = (char *)malloc(strlen(ssh->homedir) +
01068 working_path_len + 1);
01069 if (real_path == NULL) {
01070 libssh2_sftp_shutdown(ssh->sftp_session);
01071 ssh->sftp_session = NULL;
01072 libssh2_session_free(ssh->ssh_session);
01073 ssh->ssh_session = NULL;
01074 Curl_safefree(ssh->homedir);
01075 ssh->homedir = NULL;
01076 Curl_safefree(working_path);
01077 return CURLE_OUT_OF_MEMORY;
01078 }
01079
01080 memcpy(real_path, ssh->homedir, strlen(ssh->homedir));
01081 real_path[strlen(ssh->homedir)] = '/';
01082 real_path[strlen(ssh->homedir)+1] = '\0';
01083 if (working_path_len > 3) {
01084 memcpy(real_path+strlen(ssh->homedir)+1, working_path + 3,
01085 1 + working_path_len -3);
01086 }
01087 }
01088 else {
01089 real_path = (char *)malloc(working_path_len+1);
01090 if (real_path == NULL) {
01091 libssh2_sftp_shutdown(ssh->sftp_session);
01092 ssh->sftp_session = NULL;
01093 libssh2_session_free(ssh->ssh_session);
01094 ssh->ssh_session = NULL;
01095 Curl_safefree(ssh->homedir);
01096 ssh->homedir = NULL;
01097 Curl_safefree(working_path);
01098 return CURLE_OUT_OF_MEMORY;
01099 }
01100 memcpy(real_path, working_path, 1+working_path_len);
01101 }
01102 }
01103 else {
01104 libssh2_session_free(ssh->ssh_session);
01105 ssh->ssh_session = NULL;
01106 Curl_safefree(working_path);
01107 return CURLE_FAILED_INIT;
01108 }
01109
01110 Curl_safefree(working_path);
01111 ssh->path = real_path;
01112
01113 *done = TRUE;
01114 return CURLE_OK;
01115 #endif
01116 }
01117
01118 CURLcode Curl_scp_do(struct connectdata *conn, bool *done)
01119 {
01120 struct stat sb;
01121 struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
01122 CURLcode res = CURLE_OK;
01123
01124 *done = TRUE;
01125
01126 if (conn->data->set.upload) {
01127 if(conn->data->set.infilesize < 0) {
01128 failf(conn->data, "SCP requires a known file size for upload");
01129 return CURLE_UPLOAD_FAILED;
01130 }
01131
01132
01133
01134
01135
01136
01137 #if (LIBSSH2_APINO >= 200706012030)
01138 do {
01139 scp->ssh_channel = libssh2_scp_send_ex(scp->ssh_session, scp->path,
01140 conn->data->set.new_file_perms,
01141 conn->data->set.infilesize, 0, 0);
01142 if (!scp->ssh_channel &&
01143 (libssh2_session_last_errno(scp->ssh_session) !=
01144 LIBSSH2_ERROR_EAGAIN)) {
01145 int err;
01146 char *err_msg;
01147
01148 err = libssh2_session_error_to_CURLE(
01149 libssh2_session_last_error(scp->ssh_session, &err_msg, NULL, 0));
01150 failf(conn->data, "%s", err_msg);
01151 return err;
01152 }
01153 } while (!scp->ssh_channel);
01154 #else
01155 scp->ssh_channel = libssh2_scp_send_ex(scp->ssh_session, scp->path,
01156 conn->data->set.new_file_perms,
01157 conn->data->set.infilesize, 0, 0);
01158 if (!scp->ssh_channel)
01159 return CURLE_FAILED_INIT;
01160 #endif
01161
01162
01163 res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
01164 }
01165 else {
01166
01167
01168
01169
01170 curl_off_t bytecount;
01171 memset(&sb, 0, sizeof(struct stat));
01172 #if (LIBSSH2_APINO >= 200706012030)
01173 do {
01174 scp->ssh_channel = libssh2_scp_recv(scp->ssh_session, scp->path, &sb);
01175 if (!scp->ssh_channel &&
01176 (libssh2_session_last_errno(scp->ssh_session) !=
01177 LIBSSH2_ERROR_EAGAIN)) {
01178 if ((sb.st_mode == 0) && (sb.st_atime == 0) && (sb.st_mtime == 0) &&
01179 (sb.st_size == 0)) {
01180
01181 return CURLE_REMOTE_FILE_NOT_FOUND;
01182 }
01183 return libssh2_session_error_to_CURLE(
01184 libssh2_session_last_error(scp->ssh_session, NULL, NULL, 0));
01185 }
01186 } while (!scp->ssh_channel);
01187 #else
01188 scp->ssh_channel = libssh2_scp_recv(scp->ssh_session, scp->path, &sb);
01189 if (!scp->ssh_channel) {
01190 if ((sb.st_mode == 0) && (sb.st_atime == 0) && (sb.st_mtime == 0) &&
01191 (sb.st_size == 0)) {
01192
01193 return CURLE_REMOTE_FILE_NOT_FOUND;
01194 }
01195 return libssh2_session_error_to_CURLE(
01196 libssh2_session_last_error(scp->ssh_session, NULL, NULL, 0));
01197 }
01198 #endif
01199
01200 bytecount = (curl_off_t) sb.st_size;
01201 conn->data->reqdata.maxdownload = (curl_off_t) sb.st_size;
01202 res = Curl_setup_transfer(conn, FIRSTSOCKET,
01203 bytecount, FALSE, NULL, -1, NULL);
01204 }
01205
01206 return res;
01207 }
01208
01209 CURLcode Curl_scp_done(struct connectdata *conn, CURLcode status,
01210 bool premature)
01211 {
01212 int rc;
01213 struct SSHPROTO *scp = conn->data->reqdata.proto.ssh;
01214 (void)premature;
01215
01216 Curl_safefree(scp->path);
01217 scp->path = NULL;
01218
01219 if (scp->ssh_channel) {
01220 #if (LIBSSH2_APINO >= 200706012030)
01221 if (conn->data->set.upload) {
01222 while ((rc = libssh2_channel_send_eof(scp->ssh_channel)) ==
01223 LIBSSH2_ERROR_EAGAIN);
01224 if (rc) {
01225 infof(conn->data, "Failed to send libssh2 channel EOF\n");
01226 }
01227 while ((rc = libssh2_channel_wait_eof(scp->ssh_channel)) ==
01228 LIBSSH2_ERROR_EAGAIN);
01229 if (rc) {
01230 infof(conn->data, "Failed to get channel EOF\n");
01231 }
01232 while ((rc = libssh2_channel_wait_closed(scp->ssh_channel)) ==
01233 LIBSSH2_ERROR_EAGAIN);
01234 if (rc) {
01235 infof(conn->data, "Channel failed to close\n");
01236 }
01237 }
01238 #else
01239 if (conn->data->set.upload &&
01240 libssh2_channel_send_eof(scp->ssh_channel) < 0) {
01241 infof(conn->data, "Failed to send libssh2 channel EOF\n");
01242 }
01243 if (libssh2_channel_close(scp->ssh_channel) < 0) {
01244 infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
01245 }
01246 #endif
01247 libssh2_channel_free(scp->ssh_channel);
01248 }
01249
01250 if (scp->ssh_session) {
01251 #if (LIBSSH2_APINO >= 200706012030)
01252 while (libssh2_session_disconnect(scp->ssh_session, "Shutdown") ==
01253 LIBSSH2_ERROR_EAGAIN);
01254 #else
01255 libssh2_session_disconnect(scp->ssh_session, "Shutdown");
01256 #endif
01257 libssh2_session_free(scp->ssh_session);
01258 scp->ssh_session = NULL;
01259 }
01260
01261 free(conn->data->reqdata.proto.ssh);
01262 conn->data->reqdata.proto.ssh = NULL;
01263 Curl_pgrsDone(conn);
01264
01265 (void)status;
01266 (void) rc;
01267
01268 return CURLE_OK;
01269 }
01270
01271
01272 ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
01273 void *mem, size_t len)
01274 {
01275 ssize_t nwrite;
01276
01277
01278
01279
01280
01281
01282 #if defined(LIBSSH2CHANNEL_EAGAIN) && (LIBSSH2_APINO < 200706012030)
01283 nwrite = (ssize_t)
01284 libssh2_channel_writenb(conn->data->reqdata.proto.ssh->ssh_channel,
01285 mem, len);
01286 #else
01287 nwrite = (ssize_t)
01288 libssh2_channel_write(conn->data->reqdata.proto.ssh->ssh_channel,
01289 mem, len);
01290 #if (LIBSSH2_APINO >= 200706012030)
01291 if (nwrite == LIBSSH2_ERROR_EAGAIN) {
01292 return 0;
01293 }
01294 #endif
01295 #endif
01296 (void)sockindex;
01297 return nwrite;
01298 }
01299
01300
01301
01302
01303
01304 ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
01305 char *mem, size_t len)
01306 {
01307 ssize_t nread;
01308 (void)sockindex;
01309
01310
01311
01312
01313
01314
01315
01316 #if defined(LIBSSH2CHANNEL_EAGAIN) && (LIBSSH2_APINO < 200706012030)
01317
01318 nread = (ssize_t)
01319 libssh2_channel_readnb(conn->data->reqdata.proto.ssh->ssh_channel,
01320 mem, len);
01321 #else
01322 nread = (ssize_t)
01323 libssh2_channel_read(conn->data->reqdata.proto.ssh->ssh_channel,
01324 mem, len);
01325 #endif
01326 return nread;
01327 }
01328
01329
01330
01331
01332
01333 CURLcode Curl_sftp_do(struct connectdata *conn, bool *done)
01334 {
01335 LIBSSH2_SFTP_ATTRIBUTES attrs;
01336 struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
01337 CURLcode res = CURLE_OK;
01338 struct SessionHandle *data = conn->data;
01339 curl_off_t bytecount = 0;
01340 char *buf = data->state.buffer;
01341 unsigned long err = 0;
01342 int rc;
01343
01344 *done = TRUE;
01345
01346
01347 if(conn->data->set.quote) {
01348 infof(conn->data, "Sending quote commands\n");
01349 res = sftp_sendquote(conn, conn->data->set.quote);
01350 if (res != CURLE_OK)
01351 return res;
01352 }
01353
01354 if (data->set.upload) {
01355
01356
01357
01358
01359
01360
01361 #if (LIBSSH2_APINO >= 200706012030)
01362 do {
01363 sftp->sftp_handle =
01364 libssh2_sftp_open(sftp->sftp_session, sftp->path,
01365 LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
01366 data->set.new_file_perms);
01367 if (!sftp->sftp_handle &&
01368 (libssh2_session_last_errno(sftp->ssh_session) !=
01369 LIBSSH2_ERROR_EAGAIN)) {
01370 err = libssh2_sftp_last_error(sftp->sftp_session);
01371 if (((err == LIBSSH2_FX_NO_SUCH_FILE) ||
01372 (err == LIBSSH2_FX_FAILURE) ||
01373 (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
01374 (conn->data->set.ftp_create_missing_dirs &&
01375 (strlen(sftp->path) > 1))) {
01376
01377 res = sftp_create_dirs(conn);
01378 if (res == 0) {
01379 do {
01380 sftp->sftp_handle = libssh2_sftp_open(sftp->sftp_session,
01381 sftp->path,
01382 LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
01383 data->set.new_file_perms);
01384 if (!sftp->sftp_handle &&
01385 (libssh2_session_last_errno(sftp->ssh_session) !=
01386 LIBSSH2_ERROR_EAGAIN)) {
01387 err = libssh2_sftp_last_error(sftp->sftp_session);
01388 failf(conn->data, "Could not open remote file for writing: %s",
01389 sftp_libssh2_strerror(err));
01390 return sftp_libssh2_error_to_CURLE(err);
01391 }
01392 } while (!sftp->sftp_handle);
01393 }
01394 }
01395 if (!sftp->sftp_handle) {
01396 err = libssh2_sftp_last_error(sftp->sftp_session);
01397 failf(conn->data, "Could not open remote file for writing: %s",
01398 sftp_libssh2_strerror(err));
01399 return sftp_libssh2_error_to_CURLE(err);
01400 }
01401 }
01402 } while (!sftp->sftp_handle);
01403 #else
01404 sftp->sftp_handle =
01405 libssh2_sftp_open(sftp->sftp_session, sftp->path,
01406 LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
01407 data->set.new_file_perms);
01408 if (!sftp->sftp_handle) {
01409 err = libssh2_sftp_last_error(sftp->sftp_session);
01410 if (((err == LIBSSH2_FX_NO_SUCH_FILE) ||
01411 (err == LIBSSH2_FX_FAILURE) ||
01412 (err == LIBSSH2_FX_NO_SUCH_PATH)) &&
01413 (conn->data->set.ftp_create_missing_dirs &&
01414 (strlen(sftp->path) > 1))) {
01415
01416 res = sftp_create_dirs(conn);
01417 if (res == 0) {
01418 sftp->sftp_handle = libssh2_sftp_open(sftp->sftp_session, sftp->path,
01419 LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC,
01420 data->set.new_file_perms);
01421 }
01422 }
01423 if (!sftp->sftp_handle) {
01424 err = libssh2_sftp_last_error(sftp->sftp_session);
01425 failf(conn->data, "Could not open remote file for writing: %s",
01426 sftp_libssh2_strerror(err));
01427 return sftp_libssh2_error_to_CURLE(err);
01428 }
01429 }
01430 #endif
01431
01432
01433 res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
01434 }
01435 else {
01436 if (sftp->path[strlen(sftp->path)-1] == '/') {
01437
01438
01439
01440
01441
01442
01443
01444
01445 char filename[PATH_MAX+1];
01446 int len, totalLen, currLen;
01447 char *line;
01448
01449 #if (LIBSSH2_APINO >= 200706012030)
01450 do {
01451 sftp->sftp_handle =
01452 libssh2_sftp_opendir(sftp->sftp_session, sftp->path);
01453 if (!sftp->sftp_handle &&
01454 (libssh2_session_last_errno(sftp->ssh_session) !=
01455 LIBSSH2_ERROR_EAGAIN)) {
01456 err = libssh2_sftp_last_error(sftp->sftp_session);
01457 failf(conn->data, "Could not open directory for reading: %s",
01458 sftp_libssh2_strerror(err));
01459 return sftp_libssh2_error_to_CURLE(err);
01460 }
01461 } while (!sftp->sftp_handle);
01462 #else
01463 sftp->sftp_handle =
01464 libssh2_sftp_opendir(sftp->sftp_session, sftp->path);
01465 if (!sftp->sftp_handle) {
01466 err = libssh2_sftp_last_error(sftp->sftp_session);
01467 failf(conn->data, "Could not open directory for reading: %s",
01468 sftp_libssh2_strerror(err));
01469 return sftp_libssh2_error_to_CURLE(err);
01470 }
01471 #endif
01472
01473 do {
01474 #if (LIBSSH2_APINO >= 200706012030)
01475 while ((len = libssh2_sftp_readdir(sftp->sftp_handle, filename,
01476 PATH_MAX, &attrs)) ==
01477 LIBSSH2_ERROR_EAGAIN);
01478 #else
01479 len = libssh2_sftp_readdir(sftp->sftp_handle, filename,
01480 PATH_MAX, &attrs);
01481 #endif
01482 if (len > 0) {
01483 filename[len] = '\0';
01484
01485 if (data->set.ftp_list_only) {
01486 char *tmpLine;
01487
01488 tmpLine = aprintf("%s\n", filename);
01489 if (tmpLine == NULL) {
01490 return CURLE_OUT_OF_MEMORY;
01491 }
01492 res = Curl_client_write(conn, CLIENTWRITE_BODY, tmpLine, 0);
01493 Curl_safefree(tmpLine);
01494 }
01495 else {
01496 totalLen = 80 + len;
01497 line = (char *)malloc(totalLen);
01498 if (!line)
01499 return CURLE_OUT_OF_MEMORY;
01500
01501 if (!(attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID))
01502 attrs.uid = attrs.gid =0;
01503
01504 currLen = snprintf(line, totalLen, "---------- 1 %5d %5d",
01505 attrs.uid, attrs.gid);
01506
01507 if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) {
01508 if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
01509 LIBSSH2_SFTP_S_IFDIR) {
01510 line[0] = 'd';
01511 }
01512 else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
01513 LIBSSH2_SFTP_S_IFLNK) {
01514 line[0] = 'l';
01515 }
01516 else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
01517 LIBSSH2_SFTP_S_IFSOCK) {
01518 line[0] = 's';
01519 }
01520 else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
01521 LIBSSH2_SFTP_S_IFCHR) {
01522 line[0] = 'c';
01523 }
01524 else if ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
01525 LIBSSH2_SFTP_S_IFBLK) {
01526 line[0] = 'b';
01527 }
01528 if (attrs.permissions & LIBSSH2_SFTP_S_IRUSR) {
01529 line[1] = 'r';
01530 }
01531 if (attrs.permissions & LIBSSH2_SFTP_S_IWUSR) {
01532 line[2] = 'w';
01533 }
01534 if (attrs.permissions & LIBSSH2_SFTP_S_IXUSR) {
01535 line[3] = 'x';
01536 }
01537 if (attrs.permissions & LIBSSH2_SFTP_S_IRGRP) {
01538 line[4] = 'r';
01539 }
01540 if (attrs.permissions & LIBSSH2_SFTP_S_IWGRP) {
01541 line[5] = 'w';
01542 }
01543 if (attrs.permissions & LIBSSH2_SFTP_S_IXGRP) {
01544 line[6] = 'x';
01545 }
01546 if (attrs.permissions & LIBSSH2_SFTP_S_IROTH) {
01547 line[7] = 'r';
01548 }
01549 if (attrs.permissions & LIBSSH2_SFTP_S_IWOTH) {
01550 line[8] = 'w';
01551 }
01552 if (attrs.permissions & LIBSSH2_SFTP_S_IXOTH) {
01553 line[9] = 'x';
01554 }
01555 }
01556 if (attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) {
01557 currLen += snprintf(line+currLen, totalLen-currLen, "%11lld",
01558 attrs.filesize);
01559 }
01560 if (attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) {
01561 static const char * const months[12] = {
01562 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
01563 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
01564 struct tm *nowParts;
01565 time_t now, remoteTime;
01566
01567 now = time(NULL);
01568 remoteTime = (time_t)attrs.mtime;
01569 nowParts = localtime(&remoteTime);
01570
01571 if ((time_t)attrs.mtime > (now - (3600 * 24 * 180))) {
01572 currLen += snprintf(line+currLen, totalLen-currLen,
01573 " %s %2d %2d:%02d",
01574 months[nowParts->tm_mon],
01575 nowParts->tm_mday, nowParts->tm_hour,
01576 nowParts->tm_min);
01577 }
01578 else {
01579 currLen += snprintf(line+currLen, totalLen-currLen,
01580 " %s %2d %5d", months[nowParts->tm_mon],
01581 nowParts->tm_mday, 1900+nowParts->tm_year);
01582 }
01583 }
01584 currLen += snprintf(line+currLen, totalLen-currLen, " %s",
01585 filename);
01586 if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
01587 ((attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
01588 LIBSSH2_SFTP_S_IFLNK)) {
01589 char linkPath[PATH_MAX + 1];
01590
01591 snprintf(linkPath, PATH_MAX, "%s%s", sftp->path, filename);
01592 #if (LIBSSH2_APINO >= 200706012030)
01593 while ((len = libssh2_sftp_readlink(sftp->sftp_session, linkPath,
01594 filename, PATH_MAX)) ==
01595 LIBSSH2_ERROR_EAGAIN);
01596 #else
01597 len = libssh2_sftp_readlink(sftp->sftp_session, linkPath,
01598 filename, PATH_MAX);
01599 #endif
01600 line = realloc(line, totalLen + 4 + len);
01601 if (!line)
01602 return CURLE_OUT_OF_MEMORY;
01603
01604 currLen += snprintf(line+currLen, totalLen-currLen, " -> %s",
01605 filename);
01606 }
01607
01608 currLen += snprintf(line+currLen, totalLen-currLen, "\n");
01609 res = Curl_client_write(conn, CLIENTWRITE_BODY, line, 0);
01610 free(line);
01611 }
01612 }
01613 else if (len <= 0) {
01614 break;
01615 }
01616 } while (1);
01617 #if (LIBSSH2_APINO >= 200706012030)
01618 while (libssh2_sftp_closedir(sftp->sftp_handle) == LIBSSH2_ERROR_EAGAIN);
01619 #else
01620 libssh2_sftp_closedir(sftp->sftp_handle);
01621 #endif
01622 sftp->sftp_handle = NULL;
01623
01624
01625 res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
01626 }
01627 else {
01628
01629
01630
01631 #if (LIBSSH2_APINO >= 200706012030)
01632 do {
01633 sftp->sftp_handle =
01634 libssh2_sftp_open(sftp->sftp_session, sftp->path, LIBSSH2_FXF_READ,
01635 data->set.new_file_perms);
01636 if (!sftp->sftp_handle &&
01637 (libssh2_session_last_errno(sftp->ssh_session) !=
01638 LIBSSH2_ERROR_EAGAIN)) {
01639 err = libssh2_sftp_last_error(sftp->sftp_session);
01640 failf(conn->data, "Could not open remote file for reading: %s",
01641 sftp_libssh2_strerror(err));
01642 return sftp_libssh2_error_to_CURLE(err);
01643 }
01644 } while (!sftp->sftp_handle);
01645 #else
01646 sftp->sftp_handle =
01647 libssh2_sftp_open(sftp->sftp_session, sftp->path, LIBSSH2_FXF_READ,
01648 data->set.new_file_perms);
01649 if (!sftp->sftp_handle) {
01650 err = libssh2_sftp_last_error(sftp->sftp_session);
01651 failf(conn->data, "Could not open remote file for reading: %s",
01652 sftp_libssh2_strerror(err));
01653 return sftp_libssh2_error_to_CURLE(err);
01654 }
01655 #endif
01656
01657 #if (LIBSSH2_APINO >= 200706012030)
01658 while ((rc = libssh2_sftp_stat(sftp->sftp_session, sftp->path, &attrs))
01659 == LIBSSH2_ERROR_EAGAIN);
01660 #else
01661 rc = libssh2_sftp_stat(sftp->sftp_session, sftp->path, &attrs);
01662 #endif
01663 if (rc) {
01664
01665
01666
01667
01668 data->reqdata.size = -1;
01669 data->reqdata.maxdownload = -1;
01670 }
01671 else {
01672 data->reqdata.size = attrs.filesize;
01673 data->reqdata.maxdownload = attrs.filesize;
01674 Curl_pgrsSetDownloadSize(data, attrs.filesize);
01675 }
01676
01677 Curl_pgrsTime(data, TIMER_STARTTRANSFER);
01678
01679
01680
01681
01682 #if 0
01683
01684
01685 res = Curl_setup_transfer(conn, FIRSTSOCKET,
01686 bytecount, FALSE, NULL, -1, NULL);
01687 #endif
01688 while (res == CURLE_OK) {
01689 #if (LIBSSH2_APINO >= 200706012030)
01690 ssize_t nread;
01691
01692 while ((nread = libssh2_sftp_read(data->reqdata.proto.ssh->sftp_handle,
01693 buf, BUFSIZE-1)) == LIBSSH2_ERROR_EAGAIN);
01694 #else
01695 size_t nread;
01696
01697
01698 nread = libssh2_sftp_read(data->reqdata.proto.ssh->sftp_handle,
01699 buf, BUFSIZE-1);
01700 #endif
01701
01702 if (nread > 0)
01703 buf[nread] = 0;
01704
01705 #if (LIBSSH2_APINO >= 200706012030)
01706 if (nread <= 0)
01707 break;
01708 #else
01709
01710
01711 if ((nread == 0) || (nread == (size_t)~0))
01712 break;
01713 #endif
01714
01715 bytecount += nread;
01716
01717 res = Curl_client_write(conn, CLIENTWRITE_BODY, buf, nread);
01718 if(res)
01719 return res;
01720
01721 Curl_pgrsSetDownloadCounter(data, bytecount);
01722
01723 if(Curl_pgrsUpdate(conn))
01724 res = CURLE_ABORTED_BY_CALLBACK;
01725 else {
01726 struct timeval now = Curl_tvnow();
01727 res = Curl_speedcheck(data, now);
01728 }
01729 }
01730 if(Curl_pgrsUpdate(conn))
01731 res = CURLE_ABORTED_BY_CALLBACK;
01732
01733
01734 res = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
01735 }
01736 }
01737
01738 return res;
01739 }
01740
01741 CURLcode Curl_sftp_done(struct connectdata *conn, CURLcode status,
01742 bool premature)
01743 {
01744 struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
01745 CURLcode rc = CURLE_OK;
01746 int ret;
01747 (void)premature;
01748
01749 Curl_safefree(sftp->path);
01750 sftp->path = NULL;
01751
01752 Curl_safefree(sftp->homedir);
01753 sftp->homedir = NULL;
01754
01755 if (sftp->sftp_handle) {
01756 #if (LIBSSH2_APINO >= 200706012030)
01757 while ((ret = libssh2_sftp_close(sftp->sftp_handle)) ==
01758 LIBSSH2_ERROR_EAGAIN);
01759 if (ret < 0) {
01760 infof(conn->data, "Failed to close libssh2 file\n");
01761 }
01762 #else
01763 if (libssh2_sftp_close(sftp->sftp_handle) < 0) {
01764 infof(conn->data, "Failed to close libssh2 file\n");
01765 }
01766 #endif
01767 }
01768
01769
01770 if(!status && !premature && conn->data->set.postquote) {
01771 infof(conn->data, "Sending postquote commands\n");
01772 rc = sftp_sendquote(conn, conn->data->set.postquote);
01773 }
01774
01775 if (sftp->sftp_session) {
01776 #if (LIBSSH2_APINO >= 200706012030)
01777 while ((ret = libssh2_sftp_shutdown(sftp->sftp_session)) ==
01778 LIBSSH2_ERROR_EAGAIN);
01779 if (ret < 0) {
01780 infof(conn->data, "Failed to stop libssh2 sftp subsystem\n");
01781 }
01782 #else
01783 if (libssh2_sftp_shutdown(sftp->sftp_session) < 0) {
01784 infof(conn->data, "Failed to stop libssh2 sftp subsystem\n");
01785 }
01786 #endif
01787 }
01788
01789 if (sftp->ssh_channel) {
01790 #if (LIBSSH2_APINO >= 200706012030)
01791 while ((ret = libssh2_channel_close(sftp->ssh_channel)) ==
01792 LIBSSH2_ERROR_EAGAIN);
01793 if (ret < 0) {
01794 infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
01795 }
01796 #else
01797 if (libssh2_channel_close(sftp->ssh_channel) < 0) {
01798 infof(conn->data, "Failed to stop libssh2 channel subsystem\n");
01799 }
01800 #endif
01801 }
01802
01803 if (sftp->ssh_session) {
01804 #if (LIBSSH2_APINO >= 200706012030)
01805 while (libssh2_session_disconnect(sftp->ssh_session, "Shutdown") ==
01806 LIBSSH2_ERROR_EAGAIN);
01807 #else
01808 libssh2_session_disconnect(sftp->ssh_session, "Shutdown");
01809 #endif
01810 libssh2_session_free(sftp->ssh_session);
01811 sftp->ssh_session = NULL;
01812 }
01813
01814 free(conn->data->reqdata.proto.ssh);
01815 conn->data->reqdata.proto.ssh = NULL;
01816 Curl_pgrsDone(conn);
01817
01818 (void)status;
01819 (void)ret;
01820
01821 return rc;
01822 }
01823
01824
01825 ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
01826 void *mem, size_t len)
01827 {
01828 ssize_t nwrite;
01829
01830
01831 #if defined(LIBSSH2SFTP_EAGAIN) && (LIBSSH2_APINO < 200706012030)
01832
01833 nwrite = (ssize_t)
01834 libssh2_sftp_writenb(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
01835 #else
01836 nwrite = (ssize_t)
01837 libssh2_sftp_write(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
01838 #if (LIBSSH2_APINO >= 200706012030)
01839 if (nwrite == LIBSSH2_ERROR_EAGAIN) {
01840 return 0;
01841 }
01842 #endif
01843 #endif
01844 (void)sockindex;
01845 return nwrite;
01846 }
01847
01848
01849
01850
01851
01852 ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
01853 char *mem, size_t len)
01854 {
01855 ssize_t nread;
01856 (void)sockindex;
01857
01858
01859
01860 #if defined(LIBSSH2SFTP_EAGAIN) && (LIBSSH2_APINO < 200706012030)
01861
01862 nread = (ssize_t)
01863 libssh2_sftp_readnb(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
01864 #else
01865 nread = (ssize_t)
01866 libssh2_sftp_read(conn->data->reqdata.proto.ssh->sftp_handle, mem, len);
01867 #endif
01868 return nread;
01869 }
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888 static int
01889 get_pathname(const char **cpp, char **path)
01890 {
01891 const char *cp = *cpp, *end;
01892 char quot;
01893 u_int i, j;
01894 static const char * const WHITESPACE = " \t\r\n";
01895
01896 cp += strspn(cp, WHITESPACE);
01897 if (!*cp) {
01898 *cpp = cp;
01899 *path = NULL;
01900 return CURLE_FTP_QUOTE_ERROR;
01901 }
01902
01903 *path = malloc(strlen(cp) + 1);
01904 if (*path == NULL)
01905 return CURLE_OUT_OF_MEMORY;
01906
01907
01908 if (*cp == '\"' || *cp == '\'') {
01909 quot = *cp++;
01910
01911
01912 for (i = j = 0; i <= strlen(cp); i++) {
01913 if (cp[i] == quot) {
01914 i++;
01915 (*path)[j] = '\0';
01916 break;
01917 }
01918 if (cp[i] == '\0') {
01919
01920 goto fail;
01921 }
01922 if (cp[i] == '\\') {
01923 i++;
01924 if (cp[i] != '\'' && cp[i] != '\"' &&
01925 cp[i] != '\\') {
01926
01927
01928 goto fail;
01929 }
01930 }
01931 (*path)[j++] = cp[i];
01932 }
01933
01934 if (j == 0) {
01935
01936 goto fail;
01937 }
01938 *cpp = cp + i + strspn(cp + i, WHITESPACE);
01939 }
01940 else {
01941
01942 end = strpbrk(cp, WHITESPACE);
01943 if (end == NULL)
01944 end = strchr(cp, '\0');
01945 *cpp = end + strspn(end, WHITESPACE);
01946
01947 memcpy(*path, cp, end - cp);
01948 (*path)[end - cp] = '\0';
01949 }
01950 return (0);
01951
01952 fail:
01953 free(*path);
01954 *path = NULL;
01955 return CURLE_FTP_QUOTE_ERROR;
01956 }
01957
01958
01959 static const char *sftp_libssh2_strerror(unsigned long err)
01960 {
01961 switch (err) {
01962 case LIBSSH2_FX_NO_SUCH_FILE:
01963 return "No such file or directory";
01964 case LIBSSH2_FX_PERMISSION_DENIED:
01965 return "Permission denied";
01966 case LIBSSH2_FX_FAILURE:
01967 return "Operation failed";
01968 case LIBSSH2_FX_BAD_MESSAGE:
01969 return "Bad message from SFTP server";
01970 case LIBSSH2_FX_NO_CONNECTION:
01971 return "Not connected to SFTP server";
01972 case LIBSSH2_FX_CONNECTION_LOST:
01973 return "Connection to SFTP server lost";
01974 case LIBSSH2_FX_OP_UNSUPPORTED:
01975 return "Operation not supported by SFTP server";
01976 case LIBSSH2_FX_INVALID_HANDLE:
01977 return "Invalid handle";
01978 case LIBSSH2_FX_NO_SUCH_PATH:
01979 return "No such file or directory";
01980 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
01981 return "File already exists";
01982 case LIBSSH2_FX_WRITE_PROTECT:
01983 return "File is write protected";
01984 case LIBSSH2_FX_NO_MEDIA:
01985 return "No media";
01986 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
01987 return "Disk full";
01988 case LIBSSH2_FX_QUOTA_EXCEEDED:
01989 return "User quota exceeded";
01990 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
01991 return "Unknown principle";
01992 case LIBSSH2_FX_LOCK_CONFlICT:
01993 return "File lock conflict";
01994 case LIBSSH2_FX_DIR_NOT_EMPTY:
01995 return "Directory not empty";
01996 case LIBSSH2_FX_NOT_A_DIRECTORY:
01997 return "Not a directory";
01998 case LIBSSH2_FX_INVALID_FILENAME:
01999 return "Invalid filename";
02000 case LIBSSH2_FX_LINK_LOOP:
02001 return "Link points to itself";
02002 }
02003 return "Unknown error in libssh2";
02004 }
02005
02006
02007 static CURLcode sftp_sendquote(struct connectdata *conn,
02008 struct curl_slist *quote)
02009 {
02010 struct curl_slist *item=quote;
02011 const char *cp;
02012 long err;
02013 struct SessionHandle *data = conn->data;
02014 LIBSSH2_SFTP *sftp_session = data->reqdata.proto.ssh->sftp_session;
02015 int ret;
02016
02017 while (item) {
02018 if (item->data) {
02019 char *path1 = NULL;
02020 char *path2 = NULL;
02021
02022
02023
02024 cp = strchr(item->data, ' ');
02025 if (cp == NULL) {
02026 failf(data, "Syntax error in SFTP command. Supply parameter(s)!");
02027 return CURLE_FTP_QUOTE_ERROR;
02028 }
02029
02030
02031
02032 err = get_pathname(&cp, &path1);
02033 if (err) {
02034 if (err == CURLE_OUT_OF_MEMORY)
02035 failf(data, "Out of memory");
02036 else
02037 failf(data, "Syntax error: Bad first parameter");
02038 return err;
02039 }
02040
02041
02042
02043
02044 if (curl_strnequal(item->data, "chgrp ", 6) ||
02045 curl_strnequal(item->data, "chmod ", 6) ||
02046 curl_strnequal(item->data, "chown ", 6) ) {
02047 LIBSSH2_SFTP_ATTRIBUTES attrs;
02048
02049
02050 err = get_pathname(&cp, &path2);
02051 if (err) {
02052 if (err == CURLE_OUT_OF_MEMORY)
02053 failf(data, "Out of memory");
02054 else
02055 failf(data,
02056 "Syntax error in chgrp/chmod/chown: Bad second parameter");
02057 free(path1);
02058 return err;
02059 }
02060 memset(&attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
02061 #if (LIBSSH2_APINO >= 200706012030)
02062 while ((ret = libssh2_sftp_stat(sftp_session,
02063 path2, &attrs)) ==
02064 LIBSSH2_ERROR_EAGAIN);
02065 if (ret != 0) {
02066 err = libssh2_sftp_last_error(sftp_session);
02067 free(path1);
02068 free(path2);
02069 failf(data, "Attempt to get SFTP stats failed: %s",
02070 sftp_libssh2_strerror(err));
02071 return CURLE_FTP_QUOTE_ERROR;
02072 }
02073 #else
02074 if (libssh2_sftp_stat(sftp_session,
02075 path2, &attrs) != 0) {
02076 err = libssh2_sftp_last_error(sftp_session);
02077 free(path1);
02078 free(path2);
02079 failf(data, "Attempt to get SFTP stats failed: %s",
02080 sftp_libssh2_strerror(err));
02081 return CURLE_FTP_QUOTE_ERROR;
02082 }
02083 #endif
02084
02085
02086 if (curl_strnequal(item->data, "chgrp", 5)) {
02087 attrs.gid = strtol(path1, NULL, 10);
02088 if (attrs.gid == 0 && !ISDIGIT(path1[0])) {
02089 free(path1);
02090 free(path2);
02091 failf(data, "Syntax error: chgrp gid not a number");
02092 return CURLE_FTP_QUOTE_ERROR;
02093 }
02094 }
02095 else if (curl_strnequal(item->data, "chmod", 5)) {
02096 attrs.permissions = strtol(path1, NULL, 8);
02097 if (attrs.permissions == 0 && !ISDIGIT(path1[0])) {
02098 free(path1);
02099 free(path2);
02100 failf(data, "Syntax error: chmod permissions not a number");
02101 return CURLE_FTP_QUOTE_ERROR;
02102 }
02103 }
02104 else if (curl_strnequal(item->data, "chown", 5)) {
02105 attrs.uid = strtol(path1, NULL, 10);
02106 if (attrs.uid == 0 && !ISDIGIT(path1[0])) {
02107 free(path1);
02108 free(path2);
02109 failf(data, "Syntax error: chown uid not a number");
02110 return CURLE_FTP_QUOTE_ERROR;
02111 }
02112 }
02113
02114
02115 #if (LIBSSH2_APINO >= 200706012030)
02116 while ((ret = libssh2_sftp_setstat(sftp_session, path2, &attrs)) ==
02117 LIBSSH2_ERROR_EAGAIN);
02118 if (ret != 0) {
02119 err = libssh2_sftp_last_error(sftp_session);
02120 free(path1);
02121 free(path2);
02122 failf(data, "Attempt to set SFTP stats failed: %s",
02123 sftp_libssh2_strerror(err));
02124 return CURLE_FTP_QUOTE_ERROR;
02125 }
02126 #else
02127 if (libssh2_sftp_setstat(sftp_session, path2, &attrs) != 0) {
02128 err = libssh2_sftp_last_error(sftp_session);
02129 free(path1);
02130 free(path2);
02131 failf(data, "Attempt to set SFTP stats failed: %s",
02132 sftp_libssh2_strerror(err));
02133 return CURLE_FTP_QUOTE_ERROR;
02134 }
02135 #endif
02136 }
02137 else if (curl_strnequal(item->data, "ln ", 3) ||
02138 curl_strnequal(item->data, "symlink ", 8)) {
02139
02140
02141 err = get_pathname(&cp, &path2);
02142 if (err) {
02143 if (err == CURLE_OUT_OF_MEMORY)
02144 failf(data, "Out of memory");
02145 else
02146 failf(data,
02147 "Syntax error in ln/symlink: Bad second parameter");
02148 free(path1);
02149 return err;
02150 }
02151 #if (LIBSSH2_APINO >= 200706012030)
02152 while ((ret = libssh2_sftp_symlink(sftp_session, path1, path2)) ==
02153 LIBSSH2_ERROR_EAGAIN);
02154 if (ret != 0) {
02155 err = libssh2_sftp_last_error(sftp_session);
02156 free(path1);
02157 free(path2);
02158 failf(data, "symlink command failed: %s",
02159 sftp_libssh2_strerror(err));
02160 return CURLE_FTP_QUOTE_ERROR;
02161 }
02162 #else
02163 if (libssh2_sftp_symlink(sftp_session, path1, path2) != 0) {
02164 err = libssh2_sftp_last_error(sftp_session);
02165 free(path1);
02166 free(path2);
02167 failf(data, "symlink command failed: %s",
02168 sftp_libssh2_strerror(err));
02169 return CURLE_FTP_QUOTE_ERROR;
02170 }
02171 #endif
02172 }
02173 else if (curl_strnequal(item->data, "mkdir ", 6)) {
02174 #if (LIBSSH2_APINO >= 200706012030)
02175 while ((ret = libssh2_sftp_mkdir(sftp_session, path1, 0744)) ==
02176 LIBSSH2_ERROR_EAGAIN);
02177 if (ret != 0) {
02178 err = libssh2_sftp_last_error(sftp_session);
02179 free(path1);
02180 failf(data, "mkdir command failed: %s", sftp_libssh2_strerror(err));
02181 return CURLE_FTP_QUOTE_ERROR;
02182 }
02183 #else
02184 if (libssh2_sftp_mkdir(sftp_session, path1, 0744) != 0) {
02185 err = libssh2_sftp_last_error(sftp_session);
02186 free(path1);
02187 failf(data, "mkdir command failed: %s",
02188 sftp_libssh2_strerror(err));
02189 return CURLE_FTP_QUOTE_ERROR;
02190 }
02191 #endif
02192 }
02193 else if (curl_strnequal(item->data, "rename ", 7)) {
02194
02195 err = get_pathname(&cp, &path2);
02196 if (err) {
02197 if (err == CURLE_OUT_OF_MEMORY)
02198 failf(data, "Out of memory");
02199 else
02200 failf(data,
02201 "Syntax error in rename: Bad second parameter");
02202 free(path1);
02203 return err;
02204 }
02205 #if (LIBSSH2_APINO >= 200706012030)
02206 while ((ret = libssh2_sftp_rename(sftp_session, path1, path2)) ==
02207 LIBSSH2_ERROR_EAGAIN);
02208 if (ret != 0) {
02209 err = libssh2_sftp_last_error(sftp_session);
02210 free(path1);
02211 free(path2);
02212 failf(data, "rename command failed: %s", sftp_libssh2_strerror(err));
02213 return CURLE_FTP_QUOTE_ERROR;
02214 }
02215 #else
02216 if (libssh2_sftp_rename(sftp_session,
02217 path1, path2) != 0) {
02218 err = libssh2_sftp_last_error(sftp_session);
02219 free(path1);
02220 free(path2);
02221 failf(data, "rename command failed: %s",
02222 sftp_libssh2_strerror(err));
02223 return CURLE_FTP_QUOTE_ERROR;
02224 }
02225 #endif
02226 }
02227 else if (curl_strnequal(item->data, "rmdir ", 6)) {
02228 #if (LIBSSH2_APINO >= 200706012030)
02229 while ((ret = libssh2_sftp_rmdir(sftp_session, path1)) ==
02230 LIBSSH2_ERROR_EAGAIN);
02231 if (ret != 0) {
02232 err = libssh2_sftp_last_error(sftp_session);
02233 free(path1);
02234 failf(data, "rmdir command failed: %s", sftp_libssh2_strerror(err));
02235 return CURLE_FTP_QUOTE_ERROR;
02236 }
02237 #else
02238 if (libssh2_sftp_rmdir(sftp_session,
02239 path1) != 0) {
02240 err = libssh2_sftp_last_error(sftp_session);
02241 free(path1);
02242 failf(data, "rmdir command failed: %s",
02243 sftp_libssh2_strerror(err));
02244 return CURLE_FTP_QUOTE_ERROR;
02245 }
02246 #endif
02247 }
02248 else if (curl_strnequal(item->data, "rm ", 3)) {
02249 #if (LIBSSH2_APINO >= 200706012030)
02250 while ((ret = libssh2_sftp_unlink(sftp_session, path1)) ==
02251 LIBSSH2_ERROR_EAGAIN);
02252 if (ret != 0) {
02253 err = libssh2_sftp_last_error(sftp_session);
02254 free(path1);
02255 failf(data, "rm command failed: %s", sftp_libssh2_strerror(err));
02256 return CURLE_FTP_QUOTE_ERROR;
02257 }
02258 #else
02259 if (libssh2_sftp_unlink(sftp_session, path1) != 0) {
02260 err = libssh2_sftp_last_error(sftp_session);
02261 free(path1);
02262 failf(data, "rm command failed: %s",
02263 sftp_libssh2_strerror(err));
02264 return CURLE_FTP_QUOTE_ERROR;
02265 }
02266 #endif
02267 }
02268
02269 if (path1)
02270 free(path1);
02271 if (path2)
02272 free(path2);
02273 }
02274 item = item->next;
02275 }
02276 (void)ret;
02277
02278 return CURLE_OK;
02279 }
02280
02281
02282
02283
02284
02285 static CURLcode sftp_create_dirs(struct connectdata *conn) {
02286 CURLcode result = CURLE_OK;
02287 unsigned int sftp_err = 0;
02288 int rc;
02289 struct SSHPROTO *sftp = conn->data->reqdata.proto.ssh;
02290
02291 if (strlen(sftp->path) > 1) {
02292 char *slash_pos = sftp->path + 1;
02293
02294 while ((slash_pos = strchr(slash_pos, '/')) != NULL) {
02295 *slash_pos = 0;
02296
02297 infof(conn->data, "Creating directory '%s'\n", sftp->path);
02298
02299 #if (LIBSSH2_APINO >= 200706012030)
02300 while ((rc = libssh2_sftp_mkdir(sftp->sftp_session, sftp->path,
02301 conn->data->set.new_directory_perms)) ==
02302 LIBSSH2_ERROR_EAGAIN);
02303 #else
02304 rc = libssh2_sftp_mkdir(sftp->sftp_session, sftp->path,
02305 conn->data->set.new_directory_perms);
02306 #endif
02307 *slash_pos = '/';
02308 ++slash_pos;
02309 if (rc == -1) {
02310
02311
02312
02313
02314 sftp_err = libssh2_sftp_last_error(sftp->sftp_session);
02315 if ((sftp_err != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
02316 (sftp_err != LIBSSH2_FX_FAILURE) &&
02317 (sftp_err != LIBSSH2_FX_PERMISSION_DENIED)) {
02318 result = -1;
02319 break;
02320 }
02321 }
02322 }
02323 }
02324 return result;
02325 }
02326
02327 #endif