From e1a87a86056213c4e2ba797e75f6b57e35f2fdd6 Mon Sep 17 00:00:00 2001 From: sherlock2010 <15151851377@163.com> Date: Fri, 14 Nov 2025 17:19:50 +0800 Subject: [PATCH] fix CVE-2025-10966 (cherry picked from commit e4fe7a9bca1f99730493bf202e2b4257f476a1ba) --- backport-CVE-2025-10966.patch | 1404 +++++++++++++++++++++++++++++++++ curl.spec | 9 +- 2 files changed, 1412 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2025-10966.patch diff --git a/backport-CVE-2025-10966.patch b/backport-CVE-2025-10966.patch new file mode 100644 index 0000000..4e15aa1 --- /dev/null +++ b/backport-CVE-2025-10966.patch @@ -0,0 +1,1404 @@ +From b011e3fcfb06d6c0278595ee2ee297036fbe9793 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 24 Sep 2025 06:52:52 +0200 +Subject: [PATCH] vssh: drop support for wolfSSH + +The implementation was incomplete and lesser than the other backends. No +one ever reported a bug or requested enhancements for this, indicating +that this backend was never used. + +Closes #18700 + +Conflict:remove file not exist +context adapt +Reference:https://github.com/curl/curl/commit/b011e3fcfb06d6c027859 +--- + configure.ac | 31 - + docs/KNOWN_BUGS | 9 - + lib/Makefile.inc | 3 +- + lib/curl_setup.h | 2 +- + lib/url.c | 2 +- + lib/version.c | 4 +- + lib/vssh/ssh.h | 9 - + lib/vssh/wolfssh.c | 1174 --------------------------------- + packages/OS400/ccsidcurl.c | 2 +- + tests/runtests.pl | 3 - + 10 files changed, 5 insertions(+), 1233 deletions(-) + delete mode 100644 lib/vssh/wolfssh.c + +diff --git a/configure.ac b/configure.ac +index 922978bfc..56ac66de2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2290,12 +2290,6 @@ AS_HELP_STRING([--with-libssh=PATH],[Where to look for libssh, PATH points to th + AS_HELP_STRING([--with-libssh], [enable libssh]), + OPT_LIBSSH=$withval, OPT_LIBSSH=no) + +-OPT_WOLFSSH=off +-AC_ARG_WITH(wolfssh,dnl +-AS_HELP_STRING([--with-wolfssh=PATH],[Where to look for wolfssh, PATH points to the wolfSSH installation; when possible, set the PKG_CONFIG_PATH environment variable instead of using this option]) +-AS_HELP_STRING([--with-wolfssh], [enable wolfssh]), +- OPT_WOLFSSH=$withval, OPT_WOLFSSH=no) +- + if test X"$OPT_LIBSSH2" != Xno; then + dnl backup the pre-libssh2 variables + CLEANLDFLAGS="$LDFLAGS" +@@ -2453,28 +2447,6 @@ elif test X"$OPT_LIBSSH" != Xno; then + CPPFLAGS=$CLEANCPPFLAGS + LIBS=$CLEANLIBS + fi +-elif test X"$OPT_WOLFSSH" != Xno; then +- dnl backup the pre-wolfssh variables +- CLEANLDFLAGS="$LDFLAGS" +- CLEANCPPFLAGS="$CPPFLAGS" +- CLEANLIBS="$LIBS" +- +- +- if test "$OPT_WOLFSSH" != yes; then +- WOLFCONFIG="$OPT_WOLFSSH/bin/wolfssh-config" +- LDFLAGS="$LDFLAGS `$WOLFCONFIG --libs`" +- CPPFLAGS="$CPPFLAGS `$WOLFCONFIG --cflags`" +- fi +- +- AC_CHECK_LIB(wolfssh, wolfSSH_Init) +- +- AC_CHECK_HEADERS(wolfssh/ssh.h, +- curl_ssh_msg="enabled (wolfSSH)" +- WOLFSSH_ENABLED=1 +- AC_DEFINE(USE_WOLFSSH, 1, [if wolfSSH is in use]) +- AC_SUBST(USE_WOLFSSH, [1]) +- ) +- + fi + + dnl ********************************************************************** +@@ -5501,9 +5473,6 @@ if test "x$USE_LIBSSH" = "x1"; then + SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SCP" + SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SFTP" + fi +-if test "x$USE_WOLFSSH" = "x1"; then +- SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SFTP" +-fi + if test "x$CURL_DISABLE_RTSP" != "x1"; then + SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS RTSP" + fi +diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS +index 170132f50..1eb5716f8 100644 +--- a/docs/KNOWN_BUGS ++++ b/docs/KNOWN_BUGS +@@ -60,7 +60,6 @@ problems may have been fixed or changed somewhat since this was written. + + 9. SFTP and SCP + 9.1 SFTP does not do CURLOPT_POSTQUOTE correct +- 9.2 wolfssh: publickey auth does not work + 9.3 Remote recursive folder creation with SFTP + 9.4 libssh blocking and infinite loop problem + 9.5 cygwin: "WARNING: UNPROTECTED PRIVATE KEY FILE!" +@@ -400,14 +398,6 @@ problems may have been fixed or changed somewhat since this was written. + report but it cannot be accepted as-is. See + https://curl.se/bug/view.cgi?id=748 + +-9.2 wolfssh: publickey auth does not work +- +- When building curl to use the wolfSSH backend for SFTP, the publickey +- authentication does not work. This is simply functionality not written for curl +- yet, the necessary API for make this work is provided by wolfSSH. +- +- See https://github.com/curl/curl/issues/4820 +- + 9.3 Remote recursive folder creation with SFTP + + On this servers, the curl fails to create directories on the remote server +diff --git a/lib/Makefile.inc b/lib/Makefile.inc +index c17a8d9c3..6391eb2c4 100644 +--- a/lib/Makefile.inc ++++ b/lib/Makefile.inc +@@ -127,8 +127,7 @@ LIB_VQUIC_HFILES = \ + + LIB_VSSH_CFILES = \ + vssh/libssh.c \ +- vssh/libssh2.c \ +- vssh/wolfssh.c ++ vssh/libssh2.c + + LIB_VSSH_HFILES = \ + vssh/ssh.h +diff --git a/lib/curl_setup.h b/lib/curl_setup.h +index e49c57231..55c65c99f 100644 +--- a/lib/curl_setup.h ++++ b/lib/curl_setup.h +@@ -776,7 +776,7 @@ + #error "No longer supported. Set CURLOPT_CAINFO at runtime instead." + #endif + +-#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) || defined(USE_WOLFSSH) ++#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) + #define USE_SSH + #endif + +diff --git a/lib/url.c b/lib/url.c +index a03a11199..6af2b7fb8 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1611,7 +1611,7 @@ const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, + &Curl_handler_file, + #endif + +-#if defined(USE_SSH) && !defined(USE_WOLFSSH) ++#if defined(USE_SSH) + &Curl_handler_scp, + #endif + +diff --git a/lib/version.c b/lib/version.c +index a2d486720..8158f26e7 100644 +--- a/lib/version.c ++++ b/lib/version.c +@@ -368,10 +368,8 @@ static const char * const supported_protocols[] = { + #ifndef CURL_DISABLE_RTSP + "rtsp", + #endif +-#if defined(USE_SSH) && !defined(USE_WOLFSSH) +- "scp", +-#endif + #ifdef USE_SSH ++ "scp", + "sftp", + #endif + #if !defined(CURL_DISABLE_SMB) && defined(USE_CURL_NTLM_CORE) +diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h +index 75b31bd93..9a5f1b7e3 100644 +--- a/lib/vssh/ssh.h ++++ b/lib/vssh/ssh.h +@@ -34,9 +34,6 @@ + #elif defined(USE_LIBSSH) + #include + #include +-#elif defined(USE_WOLFSSH) +-#include +-#include + #endif + + /**************************************************************************** +@@ -211,12 +208,6 @@ struct ssh_conn { + #ifdef HAVE_LIBSSH2_KNOWNHOST_API + LIBSSH2_KNOWNHOSTS *kh; + #endif +-#elif defined(USE_WOLFSSH) +- WOLFSSH *ssh_session; +- WOLFSSH_CTX *ctx; +- word32 handleSz; +- byte handle[WOLFSSH_MAX_HANDLE]; +- curl_off_t offset; + #endif /* USE_LIBSSH */ + }; + +diff --git a/lib/vssh/wolfssh.c b/lib/vssh/wolfssh.c +deleted file mode 100644 +index 7cd0402a9..000000000 +--- a/lib/vssh/wolfssh.c ++++ /dev/null +@@ -1,1174 +0,0 @@ +-/*************************************************************************** +- * _ _ ____ _ +- * Project ___| | | | _ \| | +- * / __| | | | |_) | | +- * | (__| |_| | _ <| |___ +- * \___|\___/|_| \_\_____| +- * +- * Copyright (C) Daniel Stenberg, , et al. +- * +- * This software is licensed as described in the file COPYING, which +- * you should have received as part of this distribution. The terms +- * are also available at https://curl.se/docs/copyright.html. +- * +- * You may opt to use, copy, modify, merge, publish, distribute and/or sell +- * copies of the Software, and permit persons to whom the Software is +- * furnished to do so, under the terms of the COPYING file. +- * +- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +- * KIND, either express or implied. +- * +- * SPDX-License-Identifier: curl +- * +- ***************************************************************************/ +- +-#include "curl_setup.h" +- +-#ifdef USE_WOLFSSH +- +-#include +- +-#include +-#include +-#include "urldata.h" +-#include "cfilters.h" +-#include "connect.h" +-#include "sendf.h" +-#include "progress.h" +-#include "curl_path.h" +-#include "strtoofft.h" +-#include "transfer.h" +-#include "speedcheck.h" +-#include "select.h" +-#include "multiif.h" +-#include "warnless.h" +- +-/* The last 3 #include files should be in this order */ +-#include "curl_printf.h" +-#include "curl_memory.h" +-#include "memdebug.h" +- +-static CURLcode wssh_connect(struct Curl_easy *data, bool *done); +-static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done); +-static CURLcode wssh_do(struct Curl_easy *data, bool *done); +-#if 0 +-static CURLcode wscp_done(struct Curl_easy *data, +- CURLcode, bool premature); +-static CURLcode wscp_doing(struct Curl_easy *data, +- bool *dophase_done); +-static CURLcode wscp_disconnect(struct Curl_easy *data, +- struct connectdata *conn, +- bool dead_connection); +-#endif +-static CURLcode wsftp_done(struct Curl_easy *data, +- CURLcode, bool premature); +-static CURLcode wsftp_doing(struct Curl_easy *data, +- bool *dophase_done); +-static CURLcode wsftp_disconnect(struct Curl_easy *data, +- struct connectdata *conn, +- bool dead); +-static int wssh_getsock(struct Curl_easy *data, +- struct connectdata *conn, +- curl_socket_t *sock); +-static CURLcode wssh_setup_connection(struct Curl_easy *data, +- struct connectdata *conn); +- +-#if 0 +-/* +- * SCP protocol handler. +- */ +- +-const struct Curl_handler Curl_handler_scp = { +- "SCP", /* scheme */ +- wssh_setup_connection, /* setup_connection */ +- wssh_do, /* do_it */ +- wscp_done, /* done */ +- ZERO_NULL, /* do_more */ +- wssh_connect, /* connect_it */ +- wssh_multi_statemach, /* connecting */ +- wscp_doing, /* doing */ +- wssh_getsock, /* proto_getsock */ +- wssh_getsock, /* doing_getsock */ +- ZERO_NULL, /* domore_getsock */ +- wssh_getsock, /* perform_getsock */ +- wscp_disconnect, /* disconnect */ +- ZERO_NULL, /* readwrite */ +- ZERO_NULL, /* connection_check */ +- ZERO_NULL, /* attach connection */ +- PORT_SSH, /* defport */ +- CURLPROTO_SCP, /* protocol */ +- PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION +- | PROTOPT_NOURLQUERY /* flags */ +-}; +- +-#endif +- +-/* +- * SFTP protocol handler. +- */ +- +-const struct Curl_handler Curl_handler_sftp = { +- "SFTP", /* scheme */ +- wssh_setup_connection, /* setup_connection */ +- wssh_do, /* do_it */ +- wsftp_done, /* done */ +- ZERO_NULL, /* do_more */ +- wssh_connect, /* connect_it */ +- wssh_multi_statemach, /* connecting */ +- wsftp_doing, /* doing */ +- wssh_getsock, /* proto_getsock */ +- wssh_getsock, /* doing_getsock */ +- ZERO_NULL, /* domore_getsock */ +- wssh_getsock, /* perform_getsock */ +- wsftp_disconnect, /* disconnect */ +- ZERO_NULL, /* readwrite */ +- ZERO_NULL, /* connection_check */ +- ZERO_NULL, /* attach connection */ +- PORT_SSH, /* defport */ +- CURLPROTO_SFTP, /* protocol */ +- CURLPROTO_SFTP, /* family */ +- PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION +- | PROTOPT_NOURLQUERY /* flags */ +-}; +- +-/* +- * SSH State machine related code +- */ +-/* This is the ONLY way to change SSH state! */ +-static void state(struct Curl_easy *data, sshstate nowstate) +-{ +- struct connectdata *conn = data->conn; +- struct ssh_conn *sshc = &conn->proto.sshc; +-#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +- /* for debug purposes */ +- static const char * const names[] = { +- "SSH_STOP", +- "SSH_INIT", +- "SSH_S_STARTUP", +- "SSH_HOSTKEY", +- "SSH_AUTHLIST", +- "SSH_AUTH_PKEY_INIT", +- "SSH_AUTH_PKEY", +- "SSH_AUTH_PASS_INIT", +- "SSH_AUTH_PASS", +- "SSH_AUTH_AGENT_INIT", +- "SSH_AUTH_AGENT_LIST", +- "SSH_AUTH_AGENT", +- "SSH_AUTH_HOST_INIT", +- "SSH_AUTH_HOST", +- "SSH_AUTH_KEY_INIT", +- "SSH_AUTH_KEY", +- "SSH_AUTH_GSSAPI", +- "SSH_AUTH_DONE", +- "SSH_SFTP_INIT", +- "SSH_SFTP_REALPATH", +- "SSH_SFTP_QUOTE_INIT", +- "SSH_SFTP_POSTQUOTE_INIT", +- "SSH_SFTP_QUOTE", +- "SSH_SFTP_NEXT_QUOTE", +- "SSH_SFTP_QUOTE_STAT", +- "SSH_SFTP_QUOTE_SETSTAT", +- "SSH_SFTP_QUOTE_SYMLINK", +- "SSH_SFTP_QUOTE_MKDIR", +- "SSH_SFTP_QUOTE_RENAME", +- "SSH_SFTP_QUOTE_RMDIR", +- "SSH_SFTP_QUOTE_UNLINK", +- "SSH_SFTP_QUOTE_STATVFS", +- "SSH_SFTP_GETINFO", +- "SSH_SFTP_FILETIME", +- "SSH_SFTP_TRANS_INIT", +- "SSH_SFTP_UPLOAD_INIT", +- "SSH_SFTP_CREATE_DIRS_INIT", +- "SSH_SFTP_CREATE_DIRS", +- "SSH_SFTP_CREATE_DIRS_MKDIR", +- "SSH_SFTP_READDIR_INIT", +- "SSH_SFTP_READDIR", +- "SSH_SFTP_READDIR_LINK", +- "SSH_SFTP_READDIR_BOTTOM", +- "SSH_SFTP_READDIR_DONE", +- "SSH_SFTP_DOWNLOAD_INIT", +- "SSH_SFTP_DOWNLOAD_STAT", +- "SSH_SFTP_CLOSE", +- "SSH_SFTP_SHUTDOWN", +- "SSH_SCP_TRANS_INIT", +- "SSH_SCP_UPLOAD_INIT", +- "SSH_SCP_DOWNLOAD_INIT", +- "SSH_SCP_DOWNLOAD", +- "SSH_SCP_DONE", +- "SSH_SCP_SEND_EOF", +- "SSH_SCP_WAIT_EOF", +- "SSH_SCP_WAIT_CLOSE", +- "SSH_SCP_CHANNEL_FREE", +- "SSH_SESSION_DISCONNECT", +- "SSH_SESSION_FREE", +- "QUIT" +- }; +- +- /* a precaution to make sure the lists are in sync */ +- DEBUGASSERT(sizeof(names)/sizeof(names[0]) == SSH_LAST); +- +- if(sshc->state != nowstate) { +- infof(data, "wolfssh %p state change from %s to %s", +- (void *)sshc, names[sshc->state], names[nowstate]); +- } +-#endif +- +- sshc->state = nowstate; +-} +- +-static ssize_t wscp_send(struct Curl_easy *data, int sockindex, +- const void *mem, size_t len, CURLcode *err) +-{ +- ssize_t nwrite = 0; +- (void)data; +- (void)sockindex; /* we only support SCP on the fixed known primary socket */ +- (void)mem; +- (void)len; +- (void)err; +- +- return nwrite; +-} +- +-static ssize_t wscp_recv(struct Curl_easy *data, int sockindex, +- char *mem, size_t len, CURLcode *err) +-{ +- ssize_t nread = 0; +- (void)data; +- (void)sockindex; /* we only support SCP on the fixed known primary socket */ +- (void)mem; +- (void)len; +- (void)err; +- +- return nread; +-} +- +-/* return number of sent bytes */ +-static ssize_t wsftp_send(struct Curl_easy *data, int sockindex, +- const void *mem, size_t len, CURLcode *err) +-{ +- struct connectdata *conn = data->conn; +- struct ssh_conn *sshc = &conn->proto.sshc; +- word32 offset[2]; +- int rc; +- (void)sockindex; +- +- offset[0] = (word32)sshc->offset&0xFFFFFFFF; +- offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF; +- +- rc = wolfSSH_SFTP_SendWritePacket(sshc->ssh_session, sshc->handle, +- sshc->handleSz, +- &offset[0], +- (byte *)mem, (word32)len); +- +- if(rc == WS_FATAL_ERROR) +- rc = wolfSSH_get_error(sshc->ssh_session); +- if(rc == WS_WANT_READ) { +- conn->waitfor = KEEP_RECV; +- *err = CURLE_AGAIN; +- return -1; +- } +- else if(rc == WS_WANT_WRITE) { +- conn->waitfor = KEEP_SEND; +- *err = CURLE_AGAIN; +- return -1; +- } +- if(rc < 0) { +- failf(data, "wolfSSH_SFTP_SendWritePacket returned %d", rc); +- return -1; +- } +- DEBUGASSERT(rc == (int)len); +- infof(data, "sent %zu bytes SFTP from offset %" CURL_FORMAT_CURL_OFF_T, +- len, sshc->offset); +- sshc->offset += len; +- return (ssize_t)rc; +-} +- +-/* +- * Return number of received (decrypted) bytes +- * or <0 on error +- */ +-static ssize_t wsftp_recv(struct Curl_easy *data, int sockindex, +- char *mem, size_t len, CURLcode *err) +-{ +- int rc; +- struct connectdata *conn = data->conn; +- struct ssh_conn *sshc = &conn->proto.sshc; +- word32 offset[2]; +- (void)sockindex; +- +- offset[0] = (word32)sshc->offset&0xFFFFFFFF; +- offset[1] = (word32)(sshc->offset>>32)&0xFFFFFFFF; +- +- rc = wolfSSH_SFTP_SendReadPacket(sshc->ssh_session, sshc->handle, +- sshc->handleSz, +- &offset[0], +- (byte *)mem, (word32)len); +- if(rc == WS_FATAL_ERROR) +- rc = wolfSSH_get_error(sshc->ssh_session); +- if(rc == WS_WANT_READ) { +- conn->waitfor = KEEP_RECV; +- *err = CURLE_AGAIN; +- return -1; +- } +- else if(rc == WS_WANT_WRITE) { +- conn->waitfor = KEEP_SEND; +- *err = CURLE_AGAIN; +- return -1; +- } +- +- DEBUGASSERT(rc <= (int)len); +- +- if(rc < 0) { +- failf(data, "wolfSSH_SFTP_SendReadPacket returned %d", rc); +- return -1; +- } +- sshc->offset += len; +- +- return (ssize_t)rc; +-} +- +-/* +- * SSH setup and connection +- */ +-static CURLcode wssh_setup_connection(struct Curl_easy *data, +- struct connectdata *conn) +-{ +- struct SSHPROTO *ssh; +- (void)conn; +- +- data->req.p.ssh = ssh = calloc(1, sizeof(struct SSHPROTO)); +- if(!ssh) +- return CURLE_OUT_OF_MEMORY; +- +- return CURLE_OK; +-} +- +-static Curl_recv wscp_recv, wsftp_recv; +-static Curl_send wscp_send, wsftp_send; +- +-static int userauth(byte authtype, +- WS_UserAuthData* authdata, +- void *ctx) +-{ +- struct Curl_easy *data = ctx; +- DEBUGF(infof(data, "wolfssh callback: type %s", +- authtype == WOLFSSH_USERAUTH_PASSWORD ? "PASSWORD" : +- "PUBLICCKEY")); +- if(authtype == WOLFSSH_USERAUTH_PASSWORD) { +- authdata->sf.password.password = (byte *)data->conn->passwd; +- authdata->sf.password.passwordSz = (word32) strlen(data->conn->passwd); +- } +- +- return 0; +-} +- +-static CURLcode wssh_connect(struct Curl_easy *data, bool *done) +-{ +- struct connectdata *conn = data->conn; +- struct ssh_conn *sshc; +- curl_socket_t sock = conn->sock[FIRSTSOCKET]; +- int rc; +- +- /* initialize per-handle data if not already */ +- if(!data->req.p.ssh) +- wssh_setup_connection(data, conn); +- +- /* We default to persistent connections. We set this already in this connect +- function to make the reuse checks properly be able to check this bit. */ +- connkeep(conn, "SSH default"); +- +- if(conn->handler->protocol & CURLPROTO_SCP) { +- conn->recv[FIRSTSOCKET] = wscp_recv; +- conn->send[FIRSTSOCKET] = wscp_send; +- } +- else { +- conn->recv[FIRSTSOCKET] = wsftp_recv; +- conn->send[FIRSTSOCKET] = wsftp_send; +- } +- sshc = &conn->proto.sshc; +- sshc->ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL); +- if(!sshc->ctx) { +- failf(data, "No wolfSSH context"); +- goto error; +- } +- +- sshc->ssh_session = wolfSSH_new(sshc->ctx); +- if(!sshc->ssh_session) { +- failf(data, "No wolfSSH session"); +- goto error; +- } +- +- rc = wolfSSH_SetUsername(sshc->ssh_session, conn->user); +- if(rc != WS_SUCCESS) { +- failf(data, "wolfSSH failed to set user name"); +- goto error; +- } +- +- /* set callback for authentication */ +- wolfSSH_SetUserAuth(sshc->ctx, userauth); +- wolfSSH_SetUserAuthCtx(sshc->ssh_session, data); +- +- rc = wolfSSH_set_fd(sshc->ssh_session, (int)sock); +- if(rc) { +- failf(data, "wolfSSH failed to set socket"); +- goto error; +- } +- +-#if 0 +- wolfSSH_Debugging_ON(); +-#endif +- +- *done = TRUE; +- if(conn->handler->protocol & CURLPROTO_SCP) +- state(data, SSH_INIT); +- else +- state(data, SSH_SFTP_INIT); +- +- return wssh_multi_statemach(data, done); +-error: +- wolfSSH_free(sshc->ssh_session); +- wolfSSH_CTX_free(sshc->ctx); +- return CURLE_FAILED_INIT; +-} +- +-/* +- * wssh_statemach_act() runs the SSH state machine as far as it can without +- * blocking and without reaching the end. The data the pointer 'block' points +- * to will be set to TRUE if the wolfssh function returns EAGAIN meaning it +- * wants to be called again when the socket is ready +- */ +- +-static CURLcode wssh_statemach_act(struct Curl_easy *data, bool *block) +-{ +- CURLcode result = CURLE_OK; +- struct connectdata *conn = data->conn; +- struct ssh_conn *sshc = &conn->proto.sshc; +- struct SSHPROTO *sftp_scp = data->req.p.ssh; +- WS_SFTPNAME *name; +- int rc = 0; +- *block = FALSE; /* we're not blocking by default */ +- +- do { +- switch(sshc->state) { +- case SSH_INIT: +- state(data, SSH_S_STARTUP); +- break; +- +- case SSH_S_STARTUP: +- rc = wolfSSH_connect(sshc->ssh_session); +- if(rc != WS_SUCCESS) +- rc = wolfSSH_get_error(sshc->ssh_session); +- if(rc == WS_WANT_READ) { +- *block = TRUE; +- conn->waitfor = KEEP_RECV; +- return CURLE_OK; +- } +- else if(rc == WS_WANT_WRITE) { +- *block = TRUE; +- conn->waitfor = KEEP_SEND; +- return CURLE_OK; +- } +- else if(rc != WS_SUCCESS) { +- state(data, SSH_STOP); +- return CURLE_SSH; +- } +- infof(data, "wolfssh connected"); +- state(data, SSH_STOP); +- break; +- case SSH_STOP: +- break; +- +- case SSH_SFTP_INIT: +- rc = wolfSSH_SFTP_connect(sshc->ssh_session); +- if(rc != WS_SUCCESS) +- rc = wolfSSH_get_error(sshc->ssh_session); +- if(rc == WS_WANT_READ) { +- *block = TRUE; +- conn->waitfor = KEEP_RECV; +- return CURLE_OK; +- } +- else if(rc == WS_WANT_WRITE) { +- *block = TRUE; +- conn->waitfor = KEEP_SEND; +- return CURLE_OK; +- } +- else if(rc == WS_SUCCESS) { +- infof(data, "wolfssh SFTP connected"); +- state(data, SSH_SFTP_REALPATH); +- } +- else { +- failf(data, "wolfssh SFTP connect error %d", rc); +- return CURLE_SSH; +- } +- break; +- case SSH_SFTP_REALPATH: +- name = wolfSSH_SFTP_RealPath(sshc->ssh_session, (char *)"."); +- rc = wolfSSH_get_error(sshc->ssh_session); +- if(rc == WS_WANT_READ) { +- *block = TRUE; +- conn->waitfor = KEEP_RECV; +- return CURLE_OK; +- } +- else if(rc == WS_WANT_WRITE) { +- *block = TRUE; +- conn->waitfor = KEEP_SEND; +- return CURLE_OK; +- } +- else if(name && (rc == WS_SUCCESS)) { +- sshc->homedir = malloc(name->fSz + 1); +- if(!sshc->homedir) { +- sshc->actualcode = CURLE_OUT_OF_MEMORY; +- } +- else { +- memcpy(sshc->homedir, name->fName, name->fSz); +- sshc->homedir[name->fSz] = 0; +- infof(data, "wolfssh SFTP realpath succeeded"); +- } +- wolfSSH_SFTPNAME_list_free(name); +- state(data, SSH_STOP); +- return CURLE_OK; +- } +- failf(data, "wolfssh SFTP realpath %d", rc); +- return CURLE_SSH; +- +- case SSH_SFTP_QUOTE_INIT: +- result = Curl_getworkingpath(data, sshc->homedir, &sftp_scp->path); +- if(result) { +- sshc->actualcode = result; +- state(data, SSH_STOP); +- break; +- } +- +- if(data->set.quote) { +- infof(data, "Sending quote commands"); +- sshc->quote_item = data->set.quote; +- state(data, SSH_SFTP_QUOTE); +- } +- else { +- state(data, SSH_SFTP_GETINFO); +- } +- break; +- case SSH_SFTP_GETINFO: +- if(data->set.get_filetime) { +- state(data, SSH_SFTP_FILETIME); +- } +- else { +- state(data, SSH_SFTP_TRANS_INIT); +- } +- break; +- case SSH_SFTP_TRANS_INIT: +- if(data->state.upload) +- state(data, SSH_SFTP_UPLOAD_INIT); +- else { +- if(sftp_scp->path[strlen(sftp_scp->path)-1] == '/') +- state(data, SSH_SFTP_READDIR_INIT); +- else +- state(data, SSH_SFTP_DOWNLOAD_INIT); +- } +- break; +- case SSH_SFTP_UPLOAD_INIT: { +- word32 flags; +- WS_SFTP_FILEATRB createattrs; +- if(data->state.resume_from) { +- WS_SFTP_FILEATRB attrs; +- if(data->state.resume_from < 0) { +- rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path, +- &attrs); +- if(rc != WS_SUCCESS) +- break; +- +- if(rc) { +- data->state.resume_from = 0; +- } +- else { +- curl_off_t size = ((curl_off_t)attrs.sz[1] << 32) | attrs.sz[0]; +- if(size < 0) { +- failf(data, "Bad file size (%" CURL_FORMAT_CURL_OFF_T ")", size); +- return CURLE_BAD_DOWNLOAD_RESUME; +- } +- data->state.resume_from = size; +- } +- } +- } +- +- if(data->set.remote_append) +- /* Try to open for append, but create if nonexisting */ +- flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_APPEND; +- else if(data->state.resume_from > 0) +- /* If we have restart position then open for append */ +- flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_APPEND; +- else +- /* Clear file before writing (normal behavior) */ +- flags = WOLFSSH_FXF_WRITE|WOLFSSH_FXF_CREAT|WOLFSSH_FXF_TRUNC; +- +- memset(&createattrs, 0, sizeof(createattrs)); +- createattrs.per = (word32)data->set.new_file_perms; +- sshc->handleSz = sizeof(sshc->handle); +- rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path, +- flags, &createattrs, +- sshc->handle, &sshc->handleSz); +- if(rc == WS_FATAL_ERROR) +- rc = wolfSSH_get_error(sshc->ssh_session); +- if(rc == WS_WANT_READ) { +- *block = TRUE; +- conn->waitfor = KEEP_RECV; +- return CURLE_OK; +- } +- else if(rc == WS_WANT_WRITE) { +- *block = TRUE; +- conn->waitfor = KEEP_SEND; +- return CURLE_OK; +- } +- else if(rc == WS_SUCCESS) { +- infof(data, "wolfssh SFTP open succeeded"); +- } +- else { +- failf(data, "wolfssh SFTP upload open failed: %d", rc); +- return CURLE_SSH; +- } +- state(data, SSH_SFTP_DOWNLOAD_STAT); +- +- /* If we have a restart point then we need to seek to the correct +- position. */ +- if(data->state.resume_from > 0) { +- /* Let's read off the proper amount of bytes from the input. */ +- int seekerr = CURL_SEEKFUNC_OK; +- if(conn->seek_func) { +- Curl_set_in_callback(data, true); +- seekerr = conn->seek_func(conn->seek_client, data->state.resume_from, +- SEEK_SET); +- Curl_set_in_callback(data, false); +- } +- +- if(seekerr != CURL_SEEKFUNC_OK) { +- curl_off_t passed = 0; +- +- if(seekerr != CURL_SEEKFUNC_CANTSEEK) { +- failf(data, "Could not seek stream"); +- return CURLE_FTP_COULDNT_USE_REST; +- } +- /* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */ +- do { +- size_t readthisamountnow = +- (data->state.resume_from - passed > data->set.buffer_size) ? +- (size_t)data->set.buffer_size : +- curlx_sotouz(data->state.resume_from - passed); +- +- size_t actuallyread; +- Curl_set_in_callback(data, true); +- actuallyread = data->state.fread_func(data->state.buffer, 1, +- readthisamountnow, +- data->state.in); +- Curl_set_in_callback(data, false); +- +- passed += actuallyread; +- if((actuallyread == 0) || (actuallyread > readthisamountnow)) { +- /* this checks for greater-than only to make sure that the +- CURL_READFUNC_ABORT return code still aborts */ +- failf(data, "Failed to read data"); +- return CURLE_FTP_COULDNT_USE_REST; +- } +- } while(passed < data->state.resume_from); +- } +- +- /* now, decrease the size of the read */ +- if(data->state.infilesize > 0) { +- data->state.infilesize -= data->state.resume_from; +- data->req.size = data->state.infilesize; +- Curl_pgrsSetUploadSize(data, data->state.infilesize); +- } +- +- sshc->offset += data->state.resume_from; +- } +- if(data->state.infilesize > 0) { +- data->req.size = data->state.infilesize; +- Curl_pgrsSetUploadSize(data, data->state.infilesize); +- } +- /* upload data */ +- Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); +- +- /* not set by Curl_setup_transfer to preserve keepon bits */ +- conn->sockfd = conn->writesockfd; +- +- if(result) { +- state(data, SSH_SFTP_CLOSE); +- sshc->actualcode = result; +- } +- else { +- /* store this original bitmask setup to use later on if we can't +- figure out a "real" bitmask */ +- sshc->orig_waitfor = data->req.keepon; +- +- /* we want to use the _sending_ function even when the socket turns +- out readable as the underlying libssh2 sftp send function will deal +- with both accordingly */ +- conn->cselect_bits = CURL_CSELECT_OUT; +- +- /* since we don't really wait for anything at this point, we want the +- state machine to move on as soon as possible so we set a very short +- timeout here */ +- Curl_expire(data, 0, EXPIRE_RUN_NOW); +- +- state(data, SSH_STOP); +- } +- break; +- } +- case SSH_SFTP_DOWNLOAD_INIT: +- sshc->handleSz = sizeof(sshc->handle); +- rc = wolfSSH_SFTP_Open(sshc->ssh_session, sftp_scp->path, +- WOLFSSH_FXF_READ, NULL, +- sshc->handle, &sshc->handleSz); +- if(rc == WS_FATAL_ERROR) +- rc = wolfSSH_get_error(sshc->ssh_session); +- if(rc == WS_WANT_READ) { +- *block = TRUE; +- conn->waitfor = KEEP_RECV; +- return CURLE_OK; +- } +- else if(rc == WS_WANT_WRITE) { +- *block = TRUE; +- conn->waitfor = KEEP_SEND; +- return CURLE_OK; +- } +- else if(rc == WS_SUCCESS) { +- infof(data, "wolfssh SFTP open succeeded"); +- state(data, SSH_SFTP_DOWNLOAD_STAT); +- return CURLE_OK; +- } +- +- failf(data, "wolfssh SFTP open failed: %d", rc); +- return CURLE_SSH; +- +- case SSH_SFTP_DOWNLOAD_STAT: { +- WS_SFTP_FILEATRB attrs; +- curl_off_t size; +- +- rc = wolfSSH_SFTP_STAT(sshc->ssh_session, sftp_scp->path, &attrs); +- if(rc == WS_FATAL_ERROR) +- rc = wolfSSH_get_error(sshc->ssh_session); +- if(rc == WS_WANT_READ) { +- *block = TRUE; +- conn->waitfor = KEEP_RECV; +- return CURLE_OK; +- } +- else if(rc == WS_WANT_WRITE) { +- *block = TRUE; +- conn->waitfor = KEEP_SEND; +- return CURLE_OK; +- } +- else if(rc == WS_SUCCESS) { +- infof(data, "wolfssh STAT succeeded"); +- } +- else { +- failf(data, "wolfssh SFTP open failed: %d", rc); +- data->req.size = -1; +- data->req.maxdownload = -1; +- Curl_pgrsSetDownloadSize(data, -1); +- return CURLE_SSH; +- } +- +- size = ((curl_off_t)attrs.sz[1] <<32) | attrs.sz[0]; +- +- data->req.size = size; +- data->req.maxdownload = size; +- Curl_pgrsSetDownloadSize(data, size); +- +- infof(data, "SFTP download %" CURL_FORMAT_CURL_OFF_T " bytes", size); +- +- /* We cannot seek with wolfSSH so resuming and range requests are not +- possible */ +- if(data->state.use_range || data->state.resume_from) { +- infof(data, "wolfSSH cannot do range/seek on SFTP"); +- return CURLE_BAD_DOWNLOAD_RESUME; +- } +- +- /* Setup the actual download */ +- if(data->req.size == 0) { +- /* no data to transfer */ +- Curl_setup_transfer(data, -1, -1, FALSE, -1); +- infof(data, "File already completely downloaded"); +- state(data, SSH_STOP); +- break; +- } +- Curl_setup_transfer(data, FIRSTSOCKET, data->req.size, FALSE, -1); +- +- /* not set by Curl_setup_transfer to preserve keepon bits */ +- conn->writesockfd = conn->sockfd; +- +- /* we want to use the _receiving_ function even when the socket turns +- out writableable as the underlying libssh2 recv function will deal +- with both accordingly */ +- conn->cselect_bits = CURL_CSELECT_IN; +- +- if(result) { +- /* this should never occur; the close state should be entered +- at the time the error occurs */ +- state(data, SSH_SFTP_CLOSE); +- sshc->actualcode = result; +- } +- else { +- state(data, SSH_STOP); +- } +- break; +- } +- case SSH_SFTP_CLOSE: +- if(sshc->handleSz) +- rc = wolfSSH_SFTP_Close(sshc->ssh_session, sshc->handle, +- sshc->handleSz); +- else +- rc = WS_SUCCESS; /* directory listing */ +- if(rc == WS_WANT_READ) { +- *block = TRUE; +- conn->waitfor = KEEP_RECV; +- return CURLE_OK; +- } +- else if(rc == WS_WANT_WRITE) { +- *block = TRUE; +- conn->waitfor = KEEP_SEND; +- return CURLE_OK; +- } +- else if(rc == WS_SUCCESS) { +- state(data, SSH_STOP); +- return CURLE_OK; +- } +- +- failf(data, "wolfssh SFTP CLOSE failed: %d", rc); +- return CURLE_SSH; +- +- case SSH_SFTP_READDIR_INIT: +- Curl_pgrsSetDownloadSize(data, -1); +- if(data->req.no_body) { +- state(data, SSH_STOP); +- break; +- } +- state(data, SSH_SFTP_READDIR); +- break; +- +- case SSH_SFTP_READDIR: +- name = wolfSSH_SFTP_LS(sshc->ssh_session, sftp_scp->path); +- if(!name) +- rc = wolfSSH_get_error(sshc->ssh_session); +- else +- rc = WS_SUCCESS; +- +- if(rc == WS_WANT_READ) { +- *block = TRUE; +- conn->waitfor = KEEP_RECV; +- return CURLE_OK; +- } +- else if(rc == WS_WANT_WRITE) { +- *block = TRUE; +- conn->waitfor = KEEP_SEND; +- return CURLE_OK; +- } +- else if(name && (rc == WS_SUCCESS)) { +- WS_SFTPNAME *origname = name; +- result = CURLE_OK; +- while(name) { +- char *line = aprintf("%s\n", +- data->set.list_only ? +- name->fName : name->lName); +- if(!line) { +- state(data, SSH_SFTP_CLOSE); +- sshc->actualcode = CURLE_OUT_OF_MEMORY; +- break; +- } +- result = Curl_client_write(data, CLIENTWRITE_BODY, +- line, strlen(line)); +- free(line); +- if(result) { +- sshc->actualcode = result; +- break; +- } +- name = name->next; +- } +- wolfSSH_SFTPNAME_list_free(origname); +- state(data, SSH_STOP); +- return result; +- } +- failf(data, "wolfssh SFTP ls failed: %d", rc); +- return CURLE_SSH; +- +- case SSH_SFTP_SHUTDOWN: +- Curl_safefree(sshc->homedir); +- wolfSSH_free(sshc->ssh_session); +- wolfSSH_CTX_free(sshc->ctx); +- state(data, SSH_STOP); +- return CURLE_OK; +- default: +- break; +- } +- } while(!rc && (sshc->state != SSH_STOP)); +- return result; +-} +- +-/* called repeatedly until done from multi.c */ +-static CURLcode wssh_multi_statemach(struct Curl_easy *data, bool *done) +-{ +- struct connectdata *conn = data->conn; +- struct ssh_conn *sshc = &conn->proto.sshc; +- CURLcode result = CURLE_OK; +- bool block; /* we store the status and use that to provide a ssh_getsock() +- implementation */ +- do { +- result = wssh_statemach_act(data, &block); +- *done = (sshc->state == SSH_STOP) ? TRUE : FALSE; +- /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then +- try again */ +- if(*done) { +- DEBUGF(infof(data, "wssh_statemach_act says DONE")); +- } +- } while(!result && !*done && !block); +- +- return result; +-} +- +-static +-CURLcode wscp_perform(struct Curl_easy *data, +- bool *connected, +- bool *dophase_done) +-{ +- (void)data; +- (void)connected; +- (void)dophase_done; +- return CURLE_OK; +-} +- +-static +-CURLcode wsftp_perform(struct Curl_easy *data, +- bool *connected, +- bool *dophase_done) +-{ +- CURLcode result = CURLE_OK; +- +- DEBUGF(infof(data, "DO phase starts")); +- +- *dophase_done = FALSE; /* not done yet */ +- +- /* start the first command in the DO phase */ +- state(data, SSH_SFTP_QUOTE_INIT); +- +- /* run the state-machine */ +- result = wssh_multi_statemach(data, dophase_done); +- +- *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET); +- +- if(*dophase_done) { +- DEBUGF(infof(data, "DO phase is complete")); +- } +- +- return result; +-} +- +-/* +- * The DO function is generic for both protocols. +- */ +-static CURLcode wssh_do(struct Curl_easy *data, bool *done) +-{ +- CURLcode result; +- bool connected = 0; +- struct connectdata *conn = data->conn; +- struct ssh_conn *sshc = &conn->proto.sshc; +- +- *done = FALSE; /* default to false */ +- data->req.size = -1; /* make sure this is unknown at this point */ +- sshc->actualcode = CURLE_OK; /* reset error code */ +- sshc->secondCreateDirs = 0; /* reset the create dir attempt state +- variable */ +- +- Curl_pgrsSetUploadCounter(data, 0); +- Curl_pgrsSetDownloadCounter(data, 0); +- Curl_pgrsSetUploadSize(data, -1); +- Curl_pgrsSetDownloadSize(data, -1); +- +- if(conn->handler->protocol & CURLPROTO_SCP) +- result = wscp_perform(data, &connected, done); +- else +- result = wsftp_perform(data, &connected, done); +- +- return result; +-} +- +-static CURLcode wssh_block_statemach(struct Curl_easy *data, +- bool disconnect) +-{ +- struct connectdata *conn = data->conn; +- struct ssh_conn *sshc = &conn->proto.sshc; +- CURLcode result = CURLE_OK; +- +- while((sshc->state != SSH_STOP) && !result) { +- bool block; +- timediff_t left = 1000; +- struct curltime now = Curl_now(); +- +- result = wssh_statemach_act(data, &block); +- if(result) +- break; +- +- if(!disconnect) { +- if(Curl_pgrsUpdate(data)) +- return CURLE_ABORTED_BY_CALLBACK; +- +- result = Curl_speedcheck(data, now); +- if(result) +- break; +- +- left = Curl_timeleft(data, NULL, FALSE); +- if(left < 0) { +- failf(data, "Operation timed out"); +- return CURLE_OPERATION_TIMEDOUT; +- } +- } +- +- if(!result) { +- int dir = conn->waitfor; +- curl_socket_t sock = conn->sock[FIRSTSOCKET]; +- curl_socket_t fd_read = CURL_SOCKET_BAD; +- curl_socket_t fd_write = CURL_SOCKET_BAD; +- if(dir == KEEP_RECV) +- fd_read = sock; +- else if(dir == KEEP_SEND) +- fd_write = sock; +- +- /* wait for the socket to become ready */ +- (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, +- left>1000?1000:left); /* ignore result */ +- } +- } +- +- return result; +-} +- +-/* generic done function for both SCP and SFTP called from their specific +- done functions */ +-static CURLcode wssh_done(struct Curl_easy *data, CURLcode status) +-{ +- CURLcode result = CURLE_OK; +- struct SSHPROTO *sftp_scp = data->req.p.ssh; +- +- if(!status) { +- /* run the state-machine */ +- result = wssh_block_statemach(data, FALSE); +- } +- else +- result = status; +- +- if(sftp_scp) +- Curl_safefree(sftp_scp->path); +- if(Curl_pgrsDone(data)) +- return CURLE_ABORTED_BY_CALLBACK; +- +- data->req.keepon = 0; /* clear all bits */ +- return result; +-} +- +-#if 0 +-static CURLcode wscp_done(struct Curl_easy *data, +- CURLcode code, bool premature) +-{ +- CURLcode result = CURLE_OK; +- (void)conn; +- (void)code; +- (void)premature; +- +- return result; +-} +- +-static CURLcode wscp_doing(struct Curl_easy *data, +- bool *dophase_done) +-{ +- CURLcode result = CURLE_OK; +- (void)conn; +- (void)dophase_done; +- +- return result; +-} +- +-static CURLcode wscp_disconnect(struct Curl_easy *data, +- struct connectdata *conn, bool dead_connection) +-{ +- CURLcode result = CURLE_OK; +- (void)data; +- (void)conn; +- (void)dead_connection; +- +- return result; +-} +-#endif +- +-static CURLcode wsftp_done(struct Curl_easy *data, +- CURLcode code, bool premature) +-{ +- (void)premature; +- state(data, SSH_SFTP_CLOSE); +- +- return wssh_done(data, code); +-} +- +-static CURLcode wsftp_doing(struct Curl_easy *data, +- bool *dophase_done) +-{ +- CURLcode result = wssh_multi_statemach(data, dophase_done); +- +- if(*dophase_done) { +- DEBUGF(infof(data, "DO phase is complete")); +- } +- return result; +-} +- +-static CURLcode wsftp_disconnect(struct Curl_easy *data, +- struct connectdata *conn, +- bool dead) +-{ +- CURLcode result = CURLE_OK; +- (void)dead; +- +- DEBUGF(infof(data, "SSH DISCONNECT starts now")); +- +- if(conn->proto.sshc.ssh_session) { +- /* only if there's a session still around to use! */ +- state(data, SSH_SFTP_SHUTDOWN); +- result = wssh_block_statemach(data, TRUE); +- } +- +- DEBUGF(infof(data, "SSH DISCONNECT is done")); +- return result; +-} +- +-static int wssh_getsock(struct Curl_easy *data, +- struct connectdata *conn, +- curl_socket_t *sock) +-{ +- int bitmap = GETSOCK_BLANK; +- int dir = conn->waitfor; +- (void)data; +- sock[0] = conn->sock[FIRSTSOCKET]; +- +- if(dir == KEEP_RECV) +- bitmap |= GETSOCK_READSOCK(FIRSTSOCKET); +- else if(dir == KEEP_SEND) +- bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET); +- +- return bitmap; +-} +- +-void Curl_ssh_version(char *buffer, size_t buflen) +-{ +- (void)msnprintf(buffer, buflen, "wolfssh/%s", LIBWOLFSSH_VERSION_STRING); +-} +- +-CURLcode Curl_ssh_init(void) +-{ +- if(WS_SUCCESS != wolfSSH_Init()) { +- DEBUGF(fprintf(stderr, "Error: wolfSSH_Init failed\n")); +- return CURLE_FAILED_INIT; +- } +- +- return CURLE_OK; +-} +-void Curl_ssh_cleanup(void) +-{ +- (void)wolfSSH_Cleanup(); +-} +- +-#endif /* USE_WOLFSSH */ +diff --git a/packages/OS400/ccsidcurl.c b/packages/OS400/ccsidcurl.c +index a9c04d5a4..101cf9024 100644 +--- a/packages/OS400/ccsidcurl.c ++++ b/packages/OS400/ccsidcurl.c +@@ -1213,8 +1213,8 @@ curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) + if(!s) { + result = CURLE_OUT_OF_MEMORY; + break; +- } + } ++ } + else { + /* Data length specified. */ + size_t len; +diff --git a/tests/runtests.pl b/tests/runtests.pl +index 4945e94cd..6b6e5b076 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -639,9 +639,6 @@ sub checksystemfeatures { + } + } + } +- if ($libcurl =~ /wolfssh/i) { +- $feature{"wolfssh"} = 1; +- } + } + elsif($_ =~ /^Protocols: (.*)/i) { + # these are the protocols compiled in to this libcurl +-- +2.43.0 diff --git a/curl.spec b/curl.spec index eb28e30..731bbe2 100644 --- a/curl.spec +++ b/curl.spec @@ -7,7 +7,7 @@ Name: curl Version: 8.4.0 -Release: 22 +Release: 23 Summary: Curl is used in command lines or scripts to transfer data License: curl URL: https://curl.se/ @@ -57,6 +57,7 @@ Patch48: backport-curl_path-make-SFTP-handle-a-path-like-properly.patch Patch49: backport-tool_getparam-clear-argument-only-when-needed.patch Patch50: backport-CVE-2025-9086.patch Patch51: backport-CVE-2025-10148.patch +Patch52: backport-CVE-2025-10966.patch BuildRequires: automake brotli-devel coreutils gcc groff krb5-devel BuildRequires: libidn2-devel libnghttp2-devel libpsl-devel @@ -244,6 +245,12 @@ rm -rf ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_mandir}/man3/* %changelog +* Fri Nov 14 2025 zhouyihang - 8.4.0-23 +- Type:CVE +- CVE:CVE-2025-10966 +- SUG:NA +- DESC:fix CVE-2025-10966 + * Fri Sep 12 2025 zhouyihang - 8.4.0-22 - Type:CVE - CVE:CVE-2025-9086 CVE-2025-10148 -- Gitee