Annotation of embedaddon/curl/lib/vssh/wolfssh.c, revision 1.1

1.1     ! misho       1: /***************************************************************************
        !             2:  *                                  _   _ ____  _
        !             3:  *  Project                     ___| | | |  _ \| |
        !             4:  *                             / __| | | | |_) | |
        !             5:  *                            | (__| |_| |  _ <| |___
        !             6:  *                             \___|\___/|_| \_\_____|
        !             7:  *
        !             8:  * Copyright (C) 2019 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
        !             9:  *
        !            10:  * This software is licensed as described in the file COPYING, which
        !            11:  * you should have received as part of this distribution. The terms
        !            12:  * are also available at https://curl.haxx.se/docs/copyright.html.
        !            13:  *
        !            14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
        !            15:  * copies of the Software, and permit persons to whom the Software is
        !            16:  * furnished to do so, under the terms of the COPYING file.
        !            17:  *
        !            18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
        !            19:  * KIND, either express or implied.
        !            20:  *
        !            21:  ***************************************************************************/
        !            22: 
        !            23: #include "curl_setup.h"
        !            24: 
        !            25: #ifdef USE_WOLFSSH
        !            26: 
        !            27: #include <limits.h>
        !            28: 
        !            29: #include <wolfssh/ssh.h>
        !            30: #include <wolfssh/wolfsftp.h>
        !            31: #include "urldata.h"
        !            32: #include "connect.h"
        !            33: #include "sendf.h"
        !            34: #include "progress.h"
        !            35: #include "curl_path.h"
        !            36: #include "strtoofft.h"
        !            37: #include "transfer.h"
        !            38: #include "speedcheck.h"
        !            39: #include "select.h"
        !            40: #include "multiif.h"
        !            41: #include "warnless.h"
        !            42: 
        !            43: /* The last 3 #include files should be in this order */
        !            44: #include "curl_printf.h"
        !            45: #include "curl_memory.h"
        !            46: #include "memdebug.h"
        !            47: 
        !            48: static CURLcode wssh_connect(struct connectdata *conn, bool *done);
        !            49: static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done);
        !            50: static CURLcode wssh_do(struct connectdata *conn, bool *done);
        !            51: #if 0
        !            52: static CURLcode wscp_done(struct connectdata *conn,
        !            53:                           CURLcode, bool premature);
        !            54: static CURLcode wscp_doing(struct connectdata *conn,
        !            55:                            bool *dophase_done);
        !            56: static CURLcode wscp_disconnect(struct connectdata *conn,
        !            57:                                 bool dead_connection);
        !            58: #endif
        !            59: static CURLcode wsftp_done(struct connectdata *conn,
        !            60:                            CURLcode, bool premature);
        !            61: static CURLcode wsftp_doing(struct connectdata *conn,
        !            62:                             bool *dophase_done);
        !            63: static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead);
        !            64: static int wssh_getsock(struct connectdata *conn,
        !            65:                         curl_socket_t *sock);
        !            66: static int wssh_perform_getsock(const struct connectdata *conn,
        !            67:                                 curl_socket_t *sock);
        !            68: static CURLcode wssh_setup_connection(struct connectdata *conn);
        !            69: 
        !            70: #if 0
        !            71: /*
        !            72:  * SCP protocol handler.
        !            73:  */
        !            74: 
        !            75: const struct Curl_handler Curl_handler_scp = {
        !            76:   "SCP",                                /* scheme */
        !            77:   wssh_setup_connection,                /* setup_connection */
        !            78:   wssh_do,                              /* do_it */
        !            79:   wscp_done,                            /* done */
        !            80:   ZERO_NULL,                            /* do_more */
        !            81:   wssh_connect,                         /* connect_it */
        !            82:   wssh_multi_statemach,                 /* connecting */
        !            83:   wscp_doing,                           /* doing */
        !            84:   wssh_getsock,                         /* proto_getsock */
        !            85:   wssh_getsock,                         /* doing_getsock */
        !            86:   ZERO_NULL,                            /* domore_getsock */
        !            87:   wssh_perform_getsock,                 /* perform_getsock */
        !            88:   wscp_disconnect,                      /* disconnect */
        !            89:   ZERO_NULL,                            /* readwrite */
        !            90:   ZERO_NULL,                            /* connection_check */
        !            91:   PORT_SSH,                             /* defport */
        !            92:   CURLPROTO_SCP,                        /* protocol */
        !            93:   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
        !            94:   | PROTOPT_NOURLQUERY                  /* flags */
        !            95: };
        !            96: 
        !            97: #endif
        !            98: 
        !            99: /*
        !           100:  * SFTP protocol handler.
        !           101:  */
        !           102: 
        !           103: const struct Curl_handler Curl_handler_sftp = {
        !           104:   "SFTP",                               /* scheme */
        !           105:   wssh_setup_connection,                /* setup_connection */
        !           106:   wssh_do,                              /* do_it */
        !           107:   wsftp_done,                           /* done */
        !           108:   ZERO_NULL,                            /* do_more */
        !           109:   wssh_connect,                         /* connect_it */
        !           110:   wssh_multi_statemach,                 /* connecting */
        !           111:   wsftp_doing,                          /* doing */
        !           112:   wssh_getsock,                         /* proto_getsock */
        !           113:   wssh_getsock,                         /* doing_getsock */
        !           114:   ZERO_NULL,                            /* domore_getsock */
        !           115:   wssh_perform_getsock,                 /* perform_getsock */
        !           116:   wsftp_disconnect,                     /* disconnect */
        !           117:   ZERO_NULL,                            /* readwrite */
        !           118:   ZERO_NULL,                            /* connection_check */
        !           119:   PORT_SSH,                             /* defport */
        !           120:   CURLPROTO_SFTP,                       /* protocol */
        !           121:   PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION
        !           122:   | PROTOPT_NOURLQUERY                  /* flags */
        !           123: };
        !           124: 
        !           125: /*
        !           126:  * SSH State machine related code
        !           127:  */
        !           128: /* This is the ONLY way to change SSH state! */
        !           129: static void state(struct connectdata *conn, sshstate nowstate)
        !           130: {
        !           131:   struct ssh_conn *sshc = &conn->proto.sshc;
        !           132: #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
        !           133:   /* for debug purposes */
        !           134:   static const char * const names[] = {
        !           135:     "SSH_STOP",
        !           136:     "SSH_INIT",
        !           137:     "SSH_S_STARTUP",
        !           138:     "SSH_HOSTKEY",
        !           139:     "SSH_AUTHLIST",
        !           140:     "SSH_AUTH_PKEY_INIT",
        !           141:     "SSH_AUTH_PKEY",
        !           142:     "SSH_AUTH_PASS_INIT",
        !           143:     "SSH_AUTH_PASS",
        !           144:     "SSH_AUTH_AGENT_INIT",
        !           145:     "SSH_AUTH_AGENT_LIST",
        !           146:     "SSH_AUTH_AGENT",
        !           147:     "SSH_AUTH_HOST_INIT",
        !           148:     "SSH_AUTH_HOST",
        !           149:     "SSH_AUTH_KEY_INIT",
        !           150:     "SSH_AUTH_KEY",
        !           151:     "SSH_AUTH_GSSAPI",
        !           152:     "SSH_AUTH_DONE",
        !           153:     "SSH_SFTP_INIT",
        !           154:     "SSH_SFTP_REALPATH",
        !           155:     "SSH_SFTP_QUOTE_INIT",
        !           156:     "SSH_SFTP_POSTQUOTE_INIT",
        !           157:     "SSH_SFTP_QUOTE",
        !           158:     "SSH_SFTP_NEXT_QUOTE",
        !           159:     "SSH_SFTP_QUOTE_STAT",
        !           160:     "SSH_SFTP_QUOTE_SETSTAT",
        !           161:     "SSH_SFTP_QUOTE_SYMLINK",
        !           162:     "SSH_SFTP_QUOTE_MKDIR",
        !           163:     "SSH_SFTP_QUOTE_RENAME",
        !           164:     "SSH_SFTP_QUOTE_RMDIR",
        !           165:     "SSH_SFTP_QUOTE_UNLINK",
        !           166:     "SSH_SFTP_QUOTE_STATVFS",
        !           167:     "SSH_SFTP_GETINFO",
        !           168:     "SSH_SFTP_FILETIME",
        !           169:     "SSH_SFTP_TRANS_INIT",
        !           170:     "SSH_SFTP_UPLOAD_INIT",
        !           171:     "SSH_SFTP_CREATE_DIRS_INIT",
        !           172:     "SSH_SFTP_CREATE_DIRS",
        !           173:     "SSH_SFTP_CREATE_DIRS_MKDIR",
        !           174:     "SSH_SFTP_READDIR_INIT",
        !           175:     "SSH_SFTP_READDIR",
        !           176:     "SSH_SFTP_READDIR_LINK",
        !           177:     "SSH_SFTP_READDIR_BOTTOM",
        !           178:     "SSH_SFTP_READDIR_DONE",
        !           179:     "SSH_SFTP_DOWNLOAD_INIT",
        !           180:     "SSH_SFTP_DOWNLOAD_STAT",
        !           181:     "SSH_SFTP_CLOSE",
        !           182:     "SSH_SFTP_SHUTDOWN",
        !           183:     "SSH_SCP_TRANS_INIT",
        !           184:     "SSH_SCP_UPLOAD_INIT",
        !           185:     "SSH_SCP_DOWNLOAD_INIT",
        !           186:     "SSH_SCP_DOWNLOAD",
        !           187:     "SSH_SCP_DONE",
        !           188:     "SSH_SCP_SEND_EOF",
        !           189:     "SSH_SCP_WAIT_EOF",
        !           190:     "SSH_SCP_WAIT_CLOSE",
        !           191:     "SSH_SCP_CHANNEL_FREE",
        !           192:     "SSH_SESSION_DISCONNECT",
        !           193:     "SSH_SESSION_FREE",
        !           194:     "QUIT"
        !           195:   };
        !           196: 
        !           197:   /* a precaution to make sure the lists are in sync */
        !           198:   DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST);
        !           199: 
        !           200:   if(sshc->state != nowstate) {
        !           201:     infof(conn->data, "wolfssh %p state change from %s to %s\n",
        !           202:           (void *)sshc, names[sshc->state], names[nowstate]);
        !           203:   }
        !           204: #endif
        !           205: 
        !           206:   sshc->state = nowstate;
        !           207: }
        !           208: 
        !           209: static ssize_t wscp_send(struct connectdata *conn, int sockindex,
        !           210:                          const void *mem, size_t len, CURLcode *err)
        !           211: {
        !           212:   ssize_t nwrite = 0;
        !           213:   (void)conn;
        !           214:   (void)sockindex; /* we only support SCP on the fixed known primary socket */
        !           215:   (void)mem;
        !           216:   (void)len;
        !           217:   (void)err;
        !           218: 
        !           219:   return nwrite;
        !           220: }
        !           221: 
        !           222: static ssize_t wscp_recv(struct connectdata *conn, int sockindex,
        !           223:                          char *mem, size_t len, CURLcode *err)
        !           224: {
        !           225:   ssize_t nread = 0;
        !           226:   (void)conn;
        !           227:   (void)sockindex; /* we only support SCP on the fixed known primary socket */
        !           228:   (void)mem;
        !           229:   (void)len;
        !           230:   (void)err;
        !           231: 
        !           232:   return nread;
        !           233: }
        !           234: 
        !           235: /* return number of sent bytes */
        !           236: static ssize_t wsftp_send(struct connectdata *conn, int sockindex,
        !           237:                           const void *mem, size_t len, CURLcode *err)
        !           238: {
        !           239:   struct ssh_conn *sshc = &conn->proto.sshc;
        !           240:   word32 offset[2];
        !           241:   int rc;
        !           242:   (void)sockindex;
        !           243: 
        !           244:   offset[0] =  (word32)sshc->offset&0xFFFFFFFF;
        !           245:   offset[1] =  (word32)(sshc->offset>>32)&0xFFFFFFFF;
        !           246: 
        !           247:   rc = wolfSSH_SFTP_SendWritePacket(sshc->ssh_session, sshc->handle,
        !           248:                                     sshc->handleSz,
        !           249:                                     &offset[0],
        !           250:                                     (byte *)mem, (word32)len);
        !           251: 
        !           252:   if(rc == WS_FATAL_ERROR)
        !           253:     rc = wolfSSH_get_error(sshc->ssh_session);
        !           254:   if(rc == WS_WANT_READ) {
        !           255:     conn->waitfor = KEEP_RECV;
        !           256:     *err = CURLE_AGAIN;
        !           257:     return -1;
        !           258:   }
        !           259:   else if(rc == WS_WANT_WRITE) {
        !           260:     conn->waitfor = KEEP_SEND;
        !           261:     *err = CURLE_AGAIN;
        !           262:     return -1;
        !           263:   }
        !           264:   if(rc < 0) {
        !           265:     failf(conn->data, "wolfSSH_SFTP_SendWritePacket returned %d\n", rc);
        !           266:     return -1;
        !           267:   }
        !           268:   DEBUGASSERT(rc == (int)len);
        !           269:   infof(conn->data, "sent %zd bytes SFTP from offset %zd\n",
        !           270:         len, sshc->offset);
        !           271:   sshc->offset += len;
        !           272:   return (ssize_t)rc;
        !           273: }
        !           274: 
        !           275: /*
        !           276:  * Return number of received (decrypted) bytes
        !           277:  * or <0 on error
        !           278:  */
        !           279: static ssize_t wsftp_recv(struct connectdata *conn, int sockindex,
        !           280:                           char *mem, size_t len, CURLcode *err)
        !           281: {
        !           282:   int rc;
        !           283:   struct ssh_conn *sshc = &conn->proto.sshc;
        !           284:   word32 offset[2];
        !           285:   (void)sockindex;
        !           286: 
        !           287:   offset[0] =  (word32)sshc->offset&0xFFFFFFFF;
        !           288:   offset[1] =  (word32)(sshc->offset>>32)&0xFFFFFFFF;
        !           289: 
        !           290:   rc = wolfSSH_SFTP_SendReadPacket(sshc->ssh_session, sshc->handle,
        !           291:                                    sshc->handleSz,
        !           292:                                    &offset[0],
        !           293:                                    (byte *)mem, (word32)len);
        !           294:   if(rc == WS_FATAL_ERROR)
        !           295:     rc = wolfSSH_get_error(sshc->ssh_session);
        !           296:   if(rc == WS_WANT_READ) {
        !           297:     conn->waitfor = KEEP_RECV;
        !           298:     *err = CURLE_AGAIN;
        !           299:     return -1;
        !           300:   }
        !           301:   else if(rc == WS_WANT_WRITE) {
        !           302:     conn->waitfor = KEEP_SEND;
        !           303:     *err = CURLE_AGAIN;
        !           304:     return -1;
        !           305:   }
        !           306: 
        !           307:   DEBUGASSERT(rc <= (int)len);
        !           308: 
        !           309:   if(rc < 0) {
        !           310:     failf(conn->data, "wolfSSH_SFTP_SendReadPacket returned %d\n", rc);
        !           311:     return -1;
        !           312:   }
        !           313:   sshc->offset += len;
        !           314: 
        !           315:   return (ssize_t)rc;
        !           316: }
        !           317: 
        !           318: /*
        !           319:  * SSH setup and connection
        !           320:  */
        !           321: static CURLcode wssh_setup_connection(struct connectdata *conn)
        !           322: {
        !           323:   struct SSHPROTO *ssh;
        !           324: 
        !           325:   conn->data->req.protop = ssh = calloc(1, sizeof(struct SSHPROTO));
        !           326:   if(!ssh)
        !           327:     return CURLE_OUT_OF_MEMORY;
        !           328: 
        !           329:   return CURLE_OK;
        !           330: }
        !           331: 
        !           332: static Curl_recv wscp_recv, wsftp_recv;
        !           333: static Curl_send wscp_send, wsftp_send;
        !           334: 
        !           335: static int userauth(byte authtype,
        !           336:                     WS_UserAuthData* authdata,
        !           337:                     void *ctx)
        !           338: {
        !           339:   struct connectdata *conn = ctx;
        !           340:   DEBUGF(infof(conn->data, "wolfssh callback: type %s\n",
        !           341:                authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" :
        !           342:                "PUBLICCKEY"));
        !           343:   if(authtype == WOLFSSH_USERAUTH_PASSWORD) {
        !           344:     authdata->sf.password.password = (byte *)conn->passwd;
        !           345:     authdata->sf.password.passwordSz = (word32) strlen(conn->passwd);
        !           346:   }
        !           347: 
        !           348:   return 0;
        !           349: }
        !           350: 
        !           351: static CURLcode wssh_connect(struct connectdata *conn, bool *done)
        !           352: {
        !           353:   struct Curl_easy *data = conn->data;
        !           354:   struct ssh_conn *sshc;
        !           355:   curl_socket_t sock = conn->sock[FIRSTSOCKET];
        !           356:   int rc;
        !           357: 
        !           358:   /* initialize per-handle data if not already */
        !           359:   if(!data->req.protop)
        !           360:     wssh_setup_connection(conn);
        !           361: 
        !           362:   /* We default to persistent connections. We set this already in this connect
        !           363:      function to make the re-use checks properly be able to check this bit. */
        !           364:   connkeep(conn, "SSH default");
        !           365: 
        !           366:   if(conn->handler->protocol & CURLPROTO_SCP) {
        !           367:     conn->recv[FIRSTSOCKET] = wscp_recv;
        !           368:     conn->send[FIRSTSOCKET] = wscp_send;
        !           369:   }
        !           370:   else {
        !           371:     conn->recv[FIRSTSOCKET] = wsftp_recv;
        !           372:     conn->send[FIRSTSOCKET] = wsftp_send;
        !           373:   }
        !           374:   sshc = &conn->proto.sshc;
        !           375:   sshc->ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
        !           376:   if(!sshc->ctx) {
        !           377:     failf(data, "No wolfSSH context");
        !           378:     goto error;
        !           379:   }
        !           380: 
        !           381:   sshc->ssh_session = wolfSSH_new(sshc->ctx);
        !           382:   if(sshc->ssh_session == NULL) {
        !           383:     failf(data, "No wolfSSH session");
        !           384:     goto error;
        !           385:   }
        !           386: 
        !           387:   rc = wolfSSH_SetUsername(sshc->ssh_session, conn->user);
        !           388:   if(rc != WS_SUCCESS) {
        !           389:     failf(data, "wolfSSH failed to set user name");
        !           390:     goto error;
        !           391:   }
        !           392: 
        !           393:   /* set callback for authentication */
        !           394:   wolfSSH_SetUserAuth(sshc->ctx, userauth);
        !           395:   wolfSSH_SetUserAuthCtx(sshc->ssh_session, conn);
        !           396: 
        !           397:   rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock);
        !           398:   if(rc) {
        !           399:     failf(data, "wolfSSH failed to set socket");
        !           400:     goto error;
        !           401:   }
        !           402: 
        !           403: #if 0
        !           404:   wolfSSH_Debugging_ON();
        !           405: #endif
        !           406: 
        !           407:   *done = TRUE;
        !           408:   if(conn->handler->protocol & CURLPROTO_SCP)
        !           409:     state(conn, SSH_INIT);
        !           410:   else
        !           411:     state(conn, SSH_SFTP_INIT);
        !           412: 
        !           413:   return wssh_multi_statemach(conn, done);
        !           414:   error:
        !           415:   wolfSSH_free(sshc->ssh_session);
        !           416:   wolfSSH_CTX_free(sshc->ctx);
        !           417:   return CURLE_FAILED_INIT;
        !           418: }
        !           419: 
        !           420: /*
        !           421:  * wssh_statemach_act() runs the SSH state machine as far as it can without
        !           422:  * blocking and without reaching the end.  The data the pointer 'block' points
        !           423:  * to will be set to TRUE if the wolfssh function returns EAGAIN meaning it
        !           424:  * wants to be called again when the socket is ready
        !           425:  */
        !           426: 
        !           427: static CURLcode wssh_statemach_act(struct connectdata *conn, bool *block)
        !           428: {
        !           429:   CURLcode result = CURLE_OK;
        !           430:   struct ssh_conn *sshc = &conn->proto.sshc;
        !           431:   struct Curl_easy *data = conn->data;
        !           432:   struct SSHPROTO *sftp_scp = data->req.protop;
        !           433:   WS_SFTPNAME *name;
        !           434:   int rc = 0;
        !           435:   *block = FALSE; /* we're not blocking by default */
        !           436: 
        !           437:   do {
        !           438:     switch(sshc->state) {
        !           439:     case SSH_INIT:
        !           440:       state(conn, SSH_S_STARTUP);
        !           441:       /* FALLTHROUGH */
        !           442:     case SSH_S_STARTUP:
        !           443:       rc = wolfSSH_connect(sshc->ssh_session);
        !           444:       if(rc != WS_SUCCESS)
        !           445:         rc = wolfSSH_get_error(sshc->ssh_session);
        !           446:       if(rc == WS_WANT_READ) {
        !           447:         *block = TRUE;
        !           448:         conn->waitfor = KEEP_RECV;
        !           449:         return CURLE_OK;
        !           450:       }
        !           451:       else if(rc == WS_WANT_WRITE) {
        !           452:         *block = TRUE;
        !           453:         conn->waitfor = KEEP_SEND;
        !           454:         return CURLE_OK;
        !           455:       }
        !           456:       else if(rc != WS_SUCCESS) {
        !           457:         state(conn, SSH_STOP);
        !           458:         return CURLE_SSH;
        !           459:       }
        !           460:       infof(data, "wolfssh connected!\n");
        !           461:       state(conn, SSH_STOP);
        !           462:       break;
        !           463:     case SSH_STOP:
        !           464:       break;
        !           465: 
        !           466:     case SSH_SFTP_INIT:
        !           467:       rc = wolfSSH_SFTP_connect(sshc->ssh_session);
        !           468:       if(rc != WS_SUCCESS)
        !           469:         rc = wolfSSH_get_error(sshc->ssh_session);
        !           470:       if(rc == WS_WANT_READ) {
        !           471:         *block = TRUE;
        !           472:         conn->waitfor = KEEP_RECV;
        !           473:         return CURLE_OK;
        !           474:       }
        !           475:       else if(rc == WS_WANT_WRITE) {
        !           476:         *block = TRUE;
        !           477:         conn->waitfor = KEEP_SEND;
        !           478:         return CURLE_OK;
        !           479:       }
        !           480:       else if(rc == WS_SUCCESS) {
        !           481:         infof(data, "wolfssh SFTP connected!\n");
        !           482:         state(conn, SSH_SFTP_REALPATH);
        !           483:       }
        !           484:       else {
        !           485:         failf(data, "wolfssh SFTP connect error %d", rc);
        !           486:         return CURLE_SSH;
        !           487:       }
        !           488:       break;
        !           489:     case SSH_SFTP_REALPATH:
        !           490:       name = wolfSSH_SFTP_RealPath(sshc->ssh_session, (char *)".");
        !           491:       rc = wolfSSH_get_error(sshc->ssh_session);
        !           492:       if(rc == WS_WANT_READ) {
        !           493:         *block = TRUE;
        !           494:         conn->waitfor = KEEP_RECV;
        !           495:         return CURLE_OK;
        !           496:       }
        !           497:       else if(rc == WS_WANT_WRITE) {
        !           498:         *block = TRUE;
        !           499:         conn->waitfor = KEEP_SEND;
        !           500:         return CURLE_OK;
        !           501:       }
        !           502:       else if(name && (rc == WS_SUCCESS)) {
        !           503:         sshc->homedir = malloc(name->fSz + 1);
        !           504:         if(!sshc->homedir) {
        !           505:           sshc->actualcode = CURLE_OUT_OF_MEMORY;
        !           506:         }
        !           507:         else {
        !           508:           memcpy(sshc->homedir, name->fName, name->fSz);
        !           509:           sshc->homedir[name->fSz] = 0;
        !           510:           infof(data, "wolfssh SFTP realpath succeeded!\n");
        !           511:         }
        !           512:         wolfSSH_SFTPNAME_list_free(name);
        !           513:         state(conn, SSH_STOP);
        !           514:         return CURLE_OK;
        !           515:       }
        !           516:       failf(data, "wolfssh SFTP realpath %d", rc);
        !           517:       return CURLE_SSH;
        !           518: 
        !           519:     case SSH_SFTP_QUOTE_INIT:
        !           520:       result = Curl_getworkingpath(conn, sshc->homedir, &sftp_scp->path);
        !           521:       if(result) {
        !           522:         sshc->actualcode = result;
        !           523:         state(conn, SSH_STOP);
        !           524:         break;
        !           525:       }
        !           526: 
        !           527:       if(data->set.quote) {
        !           528:         infof(data, "Sending quote commands\n");
        !           529:         sshc->quote_item = data->set.quote;
        !           530:         state(conn, SSH_SFTP_QUOTE);
        !           531:       }
        !           532:       else {
        !           533:         state(conn, SSH_SFTP_GETINFO);
        !           534:       }
        !           535:       break;
        !           536:     case SSH_SFTP_GETINFO:
        !           537:       if(data->set.get_filetime) {
        !           538:         state(conn, SSH_SFTP_FILETIME);
        !           539:       }
        !           540:       else {
        !           541:         state(conn, SSH_SFTP_TRANS_INIT);
        !           542:       }
        !           543:       break;
        !           544:     case SSH_SFTP_TRANS_INIT:
        !           545:       if(data->set.upload)
        !           546:         state(conn, SSH_SFTP_UPLOAD_INIT);
        !           547:       else {
        !           548:         if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/')
        !           549:           state(conn, SSH_SFTP_READDIR_INIT);
        !           550:         else
        !           551:           state(conn, SSH_SFTP_DOWNLOAD_INIT);
        !           552:       }
        !           553:       break;
        !           554:     case SSH_SFTP_UPLOAD_INIT: {
        !           555:       word32 flags;
        !           556:       WS_SFTP_FILEATRB createattrs;
        !           557:       if(data->state.resume_from) {
        !           558:         WS_SFTP_FILEATRB attrs;
        !           559:         if(data->state.resume_from < 0) {
        !           560:           rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path,
        !           561:                                  &attrs);
        !           562:           if(rc != WS_SUCCESS)
        !           563:             break;
        !           564: 
        !           565:           if(rc) {
        !           566:             data->state.resume_from = 0;
        !           567:           }
        !           568:           else {
        !           569:             curl_off_t size = ((curl_off_t)attrs.sz[1] << 32) | attrs.sz[0];
        !           570:             if(size < 0) {
        !           571:               failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size);
        !           572:               return CURLE_BAD_DOWNLOAD_RESUME;
        !           573:             }
        !           574:             data->state.resume_from = size;
        !           575:           }
        !           576:         }
        !           577:       }
        !           578: 
        !           579:       if(data->set.ftp_append)
        !           580:         /* Try to open for append, but create if nonexisting */
        !           581:         flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND;
        !           582:       else if(data->state.resume_from > 0)
        !           583:         /* If we have restart position then open for append */
        !           584:         flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND;
        !           585:       else
        !           586:         /* Clear file before writing (normal behaviour) */
        !           587:         flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC;
        !           588: 
        !           589:       memset(&createattrs, 0, sizeof(createattrs));
        !           590:       createattrs.per = (word32)data->set.new_file_perms;
        !           591:       sshc->handleSz = sizeof(sshc->handle);
        !           592:       rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
        !           593:                              flags, &createattrs,
        !           594:                              sshc->handle, &sshc->handleSz);
        !           595:       if(rc == WS_FATAL_ERROR)
        !           596:         rc = wolfSSH_get_error(sshc->ssh_session);
        !           597:       if(rc == WS_WANT_READ) {
        !           598:         *block = TRUE;
        !           599:         conn->waitfor = KEEP_RECV;
        !           600:         return CURLE_OK;
        !           601:       }
        !           602:       else if(rc == WS_WANT_WRITE) {
        !           603:         *block = TRUE;
        !           604:         conn->waitfor = KEEP_SEND;
        !           605:         return CURLE_OK;
        !           606:       }
        !           607:       else if(rc == WS_SUCCESS) {
        !           608:         infof(data, "wolfssh SFTP open succeeded!\n");
        !           609:       }
        !           610:       else {
        !           611:         failf(data, "wolfssh SFTP upload open failed: %d", rc);
        !           612:         return CURLE_SSH;
        !           613:       }
        !           614:       state(conn, SSH_SFTP_DOWNLOAD_STAT);
        !           615: 
        !           616:       /* If we have a restart point then we need to seek to the correct
        !           617:          position. */
        !           618:       if(data->state.resume_from > 0) {
        !           619:         /* Let's read off the proper amount of bytes from the input. */
        !           620:         int seekerr = CURL_SEEKFUNC_OK;
        !           621:         if(conn->seek_func) {
        !           622:           Curl_set_in_callback(data, true);
        !           623:           seekerr = conn->seek_func(conn->seek_client, data->state.resume_from,
        !           624:                                     SEEK_SET);
        !           625:           Curl_set_in_callback(data, false);
        !           626:         }
        !           627: 
        !           628:         if(seekerr != CURL_SEEKFUNC_OK) {
        !           629:           curl_off_t passed = 0;
        !           630: 
        !           631:           if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
        !           632:             failf(data, "Could not seek stream");
        !           633:             return CURLE_FTP_COULDNT_USE_REST;
        !           634:           }
        !           635:           /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
        !           636:           do {
        !           637:             size_t readthisamountnow =
        !           638:               (data->state.resume_from - passed > data->set.buffer_size) ?
        !           639:               (size_t)data->set.buffer_size :
        !           640:               curlx_sotouz(data->state.resume_from - passed);
        !           641: 
        !           642:             size_t actuallyread;
        !           643:             Curl_set_in_callback(data, true);
        !           644:             actuallyread = data->state.fread_func(data->state.buffer, 1,
        !           645:                                                   readthisamountnow,
        !           646:                                                   data->state.in);
        !           647:             Curl_set_in_callback(data, false);
        !           648: 
        !           649:             passed += actuallyread;
        !           650:             if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
        !           651:               /* this checks for greater-than only to make sure that the
        !           652:                  CURL_READFUNC_ABORT return code still aborts */
        !           653:               failf(data, "Failed to read data");
        !           654:               return CURLE_FTP_COULDNT_USE_REST;
        !           655:             }
        !           656:           } while(passed < data->state.resume_from);
        !           657:         }
        !           658: 
        !           659:         /* now, decrease the size of the read */
        !           660:         if(data->state.infilesize > 0) {
        !           661:           data->state.infilesize -= data->state.resume_from;
        !           662:           data->req.size = data->state.infilesize;
        !           663:           Curl_pgrsSetUploadSize(data, data->state.infilesize);
        !           664:         }
        !           665: 
        !           666:         sshc->offset += data->state.resume_from;
        !           667:       }
        !           668:       if(data->state.infilesize > 0) {
        !           669:         data->req.size = data->state.infilesize;
        !           670:         Curl_pgrsSetUploadSize(data, data->state.infilesize);
        !           671:       }
        !           672:       /* upload data */
        !           673:       Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET);
        !           674: 
        !           675:       /* not set by Curl_setup_transfer to preserve keepon bits */
        !           676:       conn->sockfd = conn->writesockfd;
        !           677: 
        !           678:       if(result) {
        !           679:         state(conn, SSH_SFTP_CLOSE);
        !           680:         sshc->actualcode = result;
        !           681:       }
        !           682:       else {
        !           683:         /* store this original bitmask setup to use later on if we can't
        !           684:            figure out a "real" bitmask */
        !           685:         sshc->orig_waitfor = data->req.keepon;
        !           686: 
        !           687:         /* we want to use the _sending_ function even when the socket turns
        !           688:            out readable as the underlying libssh2 sftp send function will deal
        !           689:            with both accordingly */
        !           690:         conn->cselect_bits = CURL_CSELECT_OUT;
        !           691: 
        !           692:         /* since we don't really wait for anything at this point, we want the
        !           693:            state machine to move on as soon as possible so we set a very short
        !           694:            timeout here */
        !           695:         Curl_expire(data, 0, EXPIRE_RUN_NOW);
        !           696: 
        !           697:         state(conn, SSH_STOP);
        !           698:       }
        !           699:       break;
        !           700:     }
        !           701:     case SSH_SFTP_DOWNLOAD_INIT:
        !           702:       sshc->handleSz = sizeof(sshc->handle);
        !           703:       rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path,
        !           704:                              WOLFSSH_FXF_READ, NULL,
        !           705:                              sshc->handle, &sshc->handleSz);
        !           706:       if(rc == WS_FATAL_ERROR)
        !           707:         rc = wolfSSH_get_error(sshc->ssh_session);
        !           708:       if(rc == WS_WANT_READ) {
        !           709:         *block = TRUE;
        !           710:         conn->waitfor = KEEP_RECV;
        !           711:         return CURLE_OK;
        !           712:       }
        !           713:       else if(rc == WS_WANT_WRITE) {
        !           714:         *block = TRUE;
        !           715:         conn->waitfor = KEEP_SEND;
        !           716:         return CURLE_OK;
        !           717:       }
        !           718:       else if(rc == WS_SUCCESS) {
        !           719:         infof(data, "wolfssh SFTP open succeeded!\n");
        !           720:         state(conn, SSH_SFTP_DOWNLOAD_STAT);
        !           721:         return CURLE_OK;
        !           722:       }
        !           723: 
        !           724:       failf(data, "wolfssh SFTP open failed: %d", rc);
        !           725:       return CURLE_SSH;
        !           726: 
        !           727:     case SSH_SFTP_DOWNLOAD_STAT: {
        !           728:       WS_SFTP_FILEATRB attrs;
        !           729:       curl_off_t size;
        !           730: 
        !           731:       rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path, &attrs);
        !           732:       if(rc == WS_FATAL_ERROR)
        !           733:         rc = wolfSSH_get_error(sshc->ssh_session);
        !           734:       if(rc == WS_WANT_READ) {
        !           735:         *block = TRUE;
        !           736:         conn->waitfor = KEEP_RECV;
        !           737:         return CURLE_OK;
        !           738:       }
        !           739:       else if(rc == WS_WANT_WRITE) {
        !           740:         *block = TRUE;
        !           741:         conn->waitfor = KEEP_SEND;
        !           742:         return CURLE_OK;
        !           743:       }
        !           744:       else if(rc == WS_SUCCESS) {
        !           745:         infof(data, "wolfssh STAT succeeded!\n");
        !           746:       }
        !           747:       else {
        !           748:         failf(data, "wolfssh SFTP open failed: %d", rc);
        !           749:         data->req.size = -1;
        !           750:         data->req.maxdownload = -1;
        !           751:         Curl_pgrsSetDownloadSize(data, -1);
        !           752:         return CURLE_SSH;
        !           753:       }
        !           754: 
        !           755:       size = ((curl_off_t)attrs.sz[1] <<32) | attrs.sz[0];
        !           756: 
        !           757:       data->req.size = size;
        !           758:       data->req.maxdownload = size;
        !           759:       Curl_pgrsSetDownloadSize(data, size);
        !           760: 
        !           761:       infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes\n", size);
        !           762: 
        !           763:       /* We cannot seek with wolfSSH so resuming and range requests are not
        !           764:          possible */
        !           765:       if(conn->data->state.use_range || data->state.resume_from) {
        !           766:         infof(data, "wolfSSH cannot do range/seek on SFTP\n");
        !           767:         return CURLE_BAD_DOWNLOAD_RESUME;
        !           768:       }
        !           769: 
        !           770:       /* Setup the actual download */
        !           771:       if(data->req.size == 0) {
        !           772:         /* no data to transfer */
        !           773:         Curl_setup_transfer(data, -1, -1, FALSE, -1);
        !           774:         infof(data, "File already completely downloaded\n");
        !           775:         state(conn, SSH_STOP);
        !           776:         break;
        !           777:       }
        !           778:       Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1);
        !           779: 
        !           780:       /* not set by Curl_setup_transfer to preserve keepon bits */
        !           781:       conn->writesockfd = conn->sockfd;
        !           782: 
        !           783:       /* we want to use the _receiving_ function even when the socket turns
        !           784:          out writableable as the underlying libssh2 recv function will deal
        !           785:          with both accordingly */
        !           786:       conn->cselect_bits = CURL_CSELECT_IN;
        !           787: 
        !           788:       if(result) {
        !           789:         /* this should never occur; the close state should be entered
        !           790:            at the time the error occurs */
        !           791:         state(conn, SSH_SFTP_CLOSE);
        !           792:         sshc->actualcode = result;
        !           793:       }
        !           794:       else {
        !           795:         state(conn, SSH_STOP);
        !           796:       }
        !           797:       break;
        !           798:     }
        !           799:     case SSH_SFTP_CLOSE:
        !           800:       if(sshc->handleSz)
        !           801:         rc = wolfSSH_SFTP_Close(sshc->ssh_session, sshc->handle,
        !           802:                                 sshc->handleSz);
        !           803:       else
        !           804:         rc = WS_SUCCESS; /* directory listing */
        !           805:       if(rc == WS_WANT_READ) {
        !           806:         *block = TRUE;
        !           807:         conn->waitfor = KEEP_RECV;
        !           808:         return CURLE_OK;
        !           809:       }
        !           810:       else if(rc == WS_WANT_WRITE) {
        !           811:         *block = TRUE;
        !           812:         conn->waitfor = KEEP_SEND;
        !           813:         return CURLE_OK;
        !           814:       }
        !           815:       else if(rc == WS_SUCCESS) {
        !           816:         state(conn, SSH_STOP);
        !           817:         return CURLE_OK;
        !           818:       }
        !           819: 
        !           820:       failf(data, "wolfssh SFTP CLOSE failed: %d", rc);
        !           821:       return CURLE_SSH;
        !           822: 
        !           823:     case SSH_SFTP_READDIR_INIT:
        !           824:       Curl_pgrsSetDownloadSize(data, -1);
        !           825:       if(data->set.opt_no_body) {
        !           826:         state(conn, SSH_STOP);
        !           827:         break;
        !           828:       }
        !           829:       state(conn, SSH_SFTP_READDIR);
        !           830:       /* FALLTHROUGH */
        !           831:     case SSH_SFTP_READDIR:
        !           832:       name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path);
        !           833:       if(!name)
        !           834:         rc = wolfSSH_get_error(sshc->ssh_session);
        !           835:       else
        !           836:         rc = WS_SUCCESS;
        !           837: 
        !           838:       if(rc == WS_WANT_READ) {
        !           839:         *block = TRUE;
        !           840:         conn->waitfor = KEEP_RECV;
        !           841:         return CURLE_OK;
        !           842:       }
        !           843:       else if(rc == WS_WANT_WRITE) {
        !           844:         *block = TRUE;
        !           845:         conn->waitfor = KEEP_SEND;
        !           846:         return CURLE_OK;
        !           847:       }
        !           848:       else if(name && (rc == WS_SUCCESS)) {
        !           849:         WS_SFTPNAME *origname = name;
        !           850:         result = CURLE_OK;
        !           851:         while(name) {
        !           852:           char *line = aprintf("%s\n",
        !           853:                                data->set.ftp_list_only ?
        !           854:                                name->fName : name->lName);
        !           855:           if(line == NULL) {
        !           856:             state(conn, SSH_SFTP_CLOSE);
        !           857:             sshc->actualcode = CURLE_OUT_OF_MEMORY;
        !           858:             break;
        !           859:           }
        !           860:           result = Curl_client_write(conn, CLIENTWRITE_BODY,
        !           861:                                      line, strlen(line));
        !           862:           free(line);
        !           863:           if(result) {
        !           864:             sshc->actualcode = result;
        !           865:             break;
        !           866:           }
        !           867:           name = name->next;
        !           868:         }
        !           869:         wolfSSH_SFTPNAME_list_free(origname);
        !           870:         state(conn, SSH_STOP);
        !           871:         return result;
        !           872:       }
        !           873:       failf(data, "wolfssh SFTP ls failed: %d", rc);
        !           874:       return CURLE_SSH;
        !           875: 
        !           876:     case SSH_SFTP_SHUTDOWN:
        !           877:       Curl_safefree(sshc->homedir);
        !           878:       wolfSSH_free(sshc->ssh_session);
        !           879:       wolfSSH_CTX_free(sshc->ctx);
        !           880:       state(conn, SSH_STOP);
        !           881:       return CURLE_OK;
        !           882:     default:
        !           883:       break;
        !           884:     }
        !           885:   } while(!rc && (sshc->state != SSH_STOP));
        !           886:   return result;
        !           887: }
        !           888: 
        !           889: /* called repeatedly until done from multi.c */
        !           890: static CURLcode wssh_multi_statemach(struct connectdata *conn, bool *done)
        !           891: {
        !           892:   struct ssh_conn *sshc = &conn->proto.sshc;
        !           893:   CURLcode result = CURLE_OK;
        !           894:   bool block; /* we store the status and use that to provide a ssh_getsock()
        !           895:                  implementation */
        !           896:   do {
        !           897:     result = wssh_statemach_act(conn, &block);
        !           898:     *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
        !           899:     /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
        !           900:        try again */
        !           901:     if(*done) {
        !           902:       DEBUGF(infof(conn->data, "wssh_statemach_act says DONE\n"));
        !           903:     }
        !           904:   } while(!result && !*done && !block);
        !           905: 
        !           906:   return result;
        !           907: }
        !           908: 
        !           909: static
        !           910: CURLcode wscp_perform(struct connectdata *conn,
        !           911:                       bool *connected,
        !           912:                       bool *dophase_done)
        !           913: {
        !           914:   (void)conn;
        !           915:   (void)connected;
        !           916:   (void)dophase_done;
        !           917:   return CURLE_OK;
        !           918: }
        !           919: 
        !           920: static
        !           921: CURLcode wsftp_perform(struct connectdata *conn,
        !           922:                        bool *connected,
        !           923:                        bool *dophase_done)
        !           924: {
        !           925:   CURLcode result = CURLE_OK;
        !           926: 
        !           927:   DEBUGF(infof(conn->data, "DO phase starts\n"));
        !           928: 
        !           929:   *dophase_done = FALSE; /* not done yet */
        !           930: 
        !           931:   /* start the first command in the DO phase */
        !           932:   state(conn, SSH_SFTP_QUOTE_INIT);
        !           933: 
        !           934:   /* run the state-machine */
        !           935:   result = wssh_multi_statemach(conn, dophase_done);
        !           936: 
        !           937:   *connected = conn->bits.tcpconnect[FIRSTSOCKET];
        !           938: 
        !           939:   if(*dophase_done) {
        !           940:     DEBUGF(infof(conn->data, "DO phase is complete\n"));
        !           941:   }
        !           942: 
        !           943:   return result;
        !           944: }
        !           945: 
        !           946: /*
        !           947:  * The DO function is generic for both protocols.
        !           948:  */
        !           949: static CURLcode wssh_do(struct connectdata *conn, bool *done)
        !           950: {
        !           951:   CURLcode result;
        !           952:   bool connected = 0;
        !           953:   struct Curl_easy *data = conn->data;
        !           954:   struct ssh_conn *sshc = &conn->proto.sshc;
        !           955: 
        !           956:   *done = FALSE; /* default to false */
        !           957:   data->req.size = -1; /* make sure this is unknown at this point */
        !           958:   sshc->actualcode = CURLE_OK; /* reset error code */
        !           959:   sshc->secondCreateDirs = 0;   /* reset the create dir attempt state
        !           960:                                    variable */
        !           961: 
        !           962:   Curl_pgrsSetUploadCounter(data, 0);
        !           963:   Curl_pgrsSetDownloadCounter(data, 0);
        !           964:   Curl_pgrsSetUploadSize(data, -1);
        !           965:   Curl_pgrsSetDownloadSize(data, -1);
        !           966: 
        !           967:   if(conn->handler->protocol & CURLPROTO_SCP)
        !           968:     result = wscp_perform(conn, &connected,  done);
        !           969:   else
        !           970:     result = wsftp_perform(conn, &connected,  done);
        !           971: 
        !           972:   return result;
        !           973: }
        !           974: 
        !           975: static CURLcode wssh_block_statemach(struct connectdata *conn,
        !           976:                                     bool disconnect)
        !           977: {
        !           978:   struct ssh_conn *sshc = &conn->proto.sshc;
        !           979:   CURLcode result = CURLE_OK;
        !           980:   struct Curl_easy *data = conn->data;
        !           981: 
        !           982:   while((sshc->state != SSH_STOP) && !result) {
        !           983:     bool block;
        !           984:     timediff_t left = 1000;
        !           985:     struct curltime now = Curl_now();
        !           986: 
        !           987:     result = wssh_statemach_act(conn, &block);
        !           988:     if(result)
        !           989:       break;
        !           990: 
        !           991:     if(!disconnect) {
        !           992:       if(Curl_pgrsUpdate(conn))
        !           993:         return CURLE_ABORTED_BY_CALLBACK;
        !           994: 
        !           995:       result = Curl_speedcheck(data, now);
        !           996:       if(result)
        !           997:         break;
        !           998: 
        !           999:       left = Curl_timeleft(data, NULL, FALSE);
        !          1000:       if(left < 0) {
        !          1001:         failf(data, "Operation timed out");
        !          1002:         return CURLE_OPERATION_TIMEDOUT;
        !          1003:       }
        !          1004:     }
        !          1005: 
        !          1006:     if(!result) {
        !          1007:       int dir = conn->waitfor;
        !          1008:       curl_socket_t sock = conn->sock[FIRSTSOCKET];
        !          1009:       curl_socket_t fd_read = CURL_SOCKET_BAD;
        !          1010:       curl_socket_t fd_write = CURL_SOCKET_BAD;
        !          1011:       if(dir == KEEP_RECV)
        !          1012:         fd_read = sock;
        !          1013:       else if(dir == KEEP_SEND)
        !          1014:         fd_write = sock;
        !          1015: 
        !          1016:       /* wait for the socket to become ready */
        !          1017:       (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
        !          1018:                               left>1000?1000:left); /* ignore result */
        !          1019:     }
        !          1020:   }
        !          1021: 
        !          1022:   return result;
        !          1023: }
        !          1024: 
        !          1025: /* generic done function for both SCP and SFTP called from their specific
        !          1026:    done functions */
        !          1027: static CURLcode wssh_done(struct connectdata *conn, CURLcode status)
        !          1028: {
        !          1029:   CURLcode result = CURLE_OK;
        !          1030:   struct SSHPROTO *sftp_scp = conn->data->req.protop;
        !          1031: 
        !          1032:   if(!status) {
        !          1033:     /* run the state-machine */
        !          1034:     result = wssh_block_statemach(conn, FALSE);
        !          1035:   }
        !          1036:   else
        !          1037:     result = status;
        !          1038: 
        !          1039:   if(sftp_scp)
        !          1040:     Curl_safefree(sftp_scp->path);
        !          1041:   if(Curl_pgrsDone(conn))
        !          1042:     return CURLE_ABORTED_BY_CALLBACK;
        !          1043: 
        !          1044:   conn->data->req.keepon = 0; /* clear all bits */
        !          1045:   return result;
        !          1046: }
        !          1047: 
        !          1048: #if 0
        !          1049: static CURLcode wscp_done(struct connectdata *conn,
        !          1050:                          CURLcode code, bool premature)
        !          1051: {
        !          1052:   CURLcode result = CURLE_OK;
        !          1053:   (void)conn;
        !          1054:   (void)code;
        !          1055:   (void)premature;
        !          1056: 
        !          1057:   return result;
        !          1058: }
        !          1059: 
        !          1060: static CURLcode wscp_doing(struct connectdata *conn,
        !          1061:                           bool *dophase_done)
        !          1062: {
        !          1063:   CURLcode result = CURLE_OK;
        !          1064:   (void)conn;
        !          1065:   (void)dophase_done;
        !          1066: 
        !          1067:   return result;
        !          1068: }
        !          1069: 
        !          1070: static CURLcode wscp_disconnect(struct connectdata *conn, bool dead_connection)
        !          1071: {
        !          1072:   CURLcode result = CURLE_OK;
        !          1073:   (void)conn;
        !          1074:   (void)dead_connection;
        !          1075: 
        !          1076:   return result;
        !          1077: }
        !          1078: #endif
        !          1079: 
        !          1080: static CURLcode wsftp_done(struct connectdata *conn,
        !          1081:                           CURLcode code, bool premature)
        !          1082: {
        !          1083:   (void)premature;
        !          1084:   state(conn, SSH_SFTP_CLOSE);
        !          1085: 
        !          1086:   return wssh_done(conn, code);
        !          1087: }
        !          1088: 
        !          1089: static CURLcode wsftp_doing(struct connectdata *conn,
        !          1090:                            bool *dophase_done)
        !          1091: {
        !          1092:   CURLcode result = wssh_multi_statemach(conn, dophase_done);
        !          1093: 
        !          1094:   if(*dophase_done) {
        !          1095:     DEBUGF(infof(conn->data, "DO phase is complete\n"));
        !          1096:   }
        !          1097:   return result;
        !          1098: }
        !          1099: 
        !          1100: static CURLcode wsftp_disconnect(struct connectdata *conn, bool dead)
        !          1101: {
        !          1102:   CURLcode result = CURLE_OK;
        !          1103:   (void)dead;
        !          1104: 
        !          1105:   DEBUGF(infof(conn->data, "SSH DISCONNECT starts now\n"));
        !          1106: 
        !          1107:   if(conn->proto.sshc.ssh_session) {
        !          1108:     /* only if there's a session still around to use! */
        !          1109:     state(conn, SSH_SFTP_SHUTDOWN);
        !          1110:     result = wssh_block_statemach(conn, TRUE);
        !          1111:   }
        !          1112: 
        !          1113:   DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
        !          1114:   return result;
        !          1115: }
        !          1116: 
        !          1117: static int wssh_getsock(struct connectdata *conn,
        !          1118:                         curl_socket_t *sock)
        !          1119: {
        !          1120:   return wssh_perform_getsock(conn, sock);
        !          1121: }
        !          1122: 
        !          1123: static int wssh_perform_getsock(const struct connectdata *conn,
        !          1124:                                 curl_socket_t *sock)
        !          1125: {
        !          1126:   int bitmap = GETSOCK_BLANK;
        !          1127:   int dir = conn->waitfor;
        !          1128:   sock[0] = conn->sock[FIRSTSOCKET];
        !          1129: 
        !          1130:   if(dir == KEEP_RECV)
        !          1131:     bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
        !          1132:   else if(dir == KEEP_SEND)
        !          1133:     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
        !          1134: 
        !          1135:   return bitmap;
        !          1136: }
        !          1137: 
        !          1138: size_t Curl_ssh_version(char *buffer, size_t buflen)
        !          1139: {
        !          1140:   return msnprintf(buffer, buflen, "wolfssh/%s", LIBWOLFSSH_VERSION_STRING);
        !          1141: }
        !          1142: 
        !          1143: CURLcode Curl_ssh_init(void)
        !          1144: {
        !          1145:   if(WS_SUCCESS != wolfSSH_Init()) {
        !          1146:     DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n"));
        !          1147:     return CURLE_FAILED_INIT;
        !          1148:   }
        !          1149: 
        !          1150:   return CURLE_OK;
        !          1151: }
        !          1152: void Curl_ssh_cleanup(void)
        !          1153: {
        !          1154: }
        !          1155: 
        !          1156: #endif /* USE_WOLFSSH */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>