Annotation of embedaddon/curl/lib/vssh/wolfssh.c, revision 1.1.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>